HOME
  Security
   Software
    Hardware
  
FPGA
  CPU
   Android
    Raspberry Pi
  
nLite
  Xcode
   etc.
    ALL
  
LINK
BACK
 

2018/09/20

ファミコンの市販ゲームソフトの書き換え改造 AC化 Arcade Conversionの IPSパッチプログラム ファミコンの市販ゲームソフトの書き換え改造 AC化 Arcade Conversionの IPSパッチプログラム

(.NET C#でバイト配列のバイナリファイルを読み書きする方法、Windowsと macOSの両方で動作)

Tags: [通信販売]




●任天堂のミニファミコンとスーファミミニが抱き合わせ販売で復活したので買ってみた

ニンテンドークラシックミニ ファミリーコンピュータ|任天堂

●クラシックミニのファミコン
クラシックミニのファミコン
 ※ HDMIケーブル、USBケーブルが付属

収録ゲームの一覧 全 30個

●クラシックミニのスーファミ
ニンテンドークラシックミニ スーパーファミコン | 任天堂
 ※ HDMIケーブル、USBケーブルが付属

収録タイトル一覧 全 21個

●週刊少年ジャンプ版 ミニファミコン

ニンテンドークラシックミニ ファミリーコンピュータ 週刊少年ジャンプ創刊50周年記念バージョン|任天堂
収録タイトル一覧 全 20個


●任天堂のミニファミコンとミニスーファミ、週刊少年ジャンプ版も販売価格が落ち着いた感じ

 一時期は品薄と転売屋でアホみたいなプレミア転売価格で販売されていましたが、任天堂のミニファミコンとミニスーファミは普通に新品が在庫品で流通する様になり、週刊少年ジャンプ版も再生産されて新品が定価よりも若干安く売られています。

種類税抜き定価(税込)製品型番本体型番
ミニファミコン(再生産)5980円(6458円)CLV-S-HVCCCLV-101
ミニスーファミ7980円(8618円)CLV-S-SHVFCLV-301
週刊少年ジャンプ版7980円(8618円)CLV-S-HVJJCLV-101
専用 USB対応 ACアダプター
+5V 1.5A出力 世界対応 LITEON製
1000円(1080円)CLV-A-ADLQCLV-003
海外版ミニファミコンCLV-001 Clover
海外版ミニファミコン コントローラパッドCLV-002 CloverCon
※ ACアダプタは +5V 1.0A出力で有れば市販品でも代用可能です。
※ 電源供給の USBとして「テレビやパソコンなどの USB端子」と箱に書いてありますが、一般的な USBの規格では最大供給可能電流は 500mAとなっています。動かない場合や不安定な場合は素直に専用の USB電源を用意しましょう。
※ Windowsパソコンの場合、USB 3.0コネクタの色は「青色」が一般的です。

ニンテンドークラシックミニ ダブルパック 【Amazon.co.jp限定】オリジナル版『スーパーマリオブラザーズ』"風"説明書+オリジナル版『F-ZERO』"風"説明書+オリジナル壁紙 配信
ASIN: B07GVBWNPF

バラで購入の場合購入価格の合計:
5980+7980+1000+税 = 16156円
ざっくり ACアダプターぶんお得。

ニンテンドークラシックミニ ファミリーコンピュータ+【Amazon.co.jp限定】オリジナル版『スーパーマリオブラザーズ』"風"説明書+オリジナル壁紙 配信
ASIN: B07DCGLP59

ニンテンドークラシックミニ スーパーファミコン+【Amazon.co.jp限定】オリジナル版『F-ZERO』"風"説明書+オリジナル壁紙 配信
ASIN: B07DCFDB1H

ニンテンドークラシックミニ ファミリーコンピュータ 週刊少年ジャンプ創刊50周年記念バージョン
ASIN: B07D2HMM6Q

※本商品の参考価格は8,618円(税込)です。

● NEOGEO miniも通常在庫になってますね。
NEOGEO mini - SNK

NEOGEO mini【Amazon.co.jp限定】「TWINKLE STAR SPRITES」STEAMコード 配信
ASIN: B07G341HR2

定価(税抜):11500円
税込み価格:12420円


●市販ゲームソフトの書き換え改造のパッチ方法として IPS形式のファイルが出回っています

IPSパッチについて
 IPSファイルの仕様

● IPS (binary patch format)

PATCHヘッダー(5バイト) 50 41 54 43 48
チャンク
...
チャンク
EOFフッター(3バイト) 45 4F 46
Truncate情報(3バイト)無い場合もある

チャンク
[1] AM(Absolute Mode)チャンク
 オフセットからデータをデータの長さぶんだけ書き込む
オフセット 3バイト
データの長さ 2バイト
データ {データの長さぶん}

[2] EM(Encoded Mode)チャンク
 オフセットから値を回数ぶんだけ書き込む(データの長さは常に 00 00)
オフセット 3バイト
データの長さ 2バイト(常に 00 00)
回数 2バイト
値 1バイト

Truncate情報
 オフセット以降を削除して切り捨てる
オフセット 3バイト


● IPSのパッチファイルを処理するプログラムを作りました

 パッチアプリとしては WinIPSが有名ですが、C#で簡単にできるので私も作ってみました。
SMB Laboratory - SMB UtilityやWinIPSの公式サイト

 C#で作ったので、Windowsと macOSの両方で動作します。

 Windowsは Visual Studio 2013でコンパイルして動作を確認しました。
 macOSは Visual Studio for Mac 7.6.7(build 49)でコンパイルして動作を確認しました。

 IPSファイルを読み込んで .nesファイルにパッチをあてます。
 IpsPatch.exe
 IpsPatch.exe [IPS file name] [ROM file name] <Write file name>
 第3引数で出力のファイル名を指定できます。
 第3引数を省略した場合の出力ファイル名は "filename_patched.ext"の様にファイル名部分に "_patched"が付いたファイル名になります。

 C#で byte[]のバイト配列でバイナリファイルを読み書きするサンプルにもなります。
 配列の動的拡張処理は Array.Resize(ref rbuff, (offset + length));が参考になります。

 著作権は放棄していません。
 ライセンスは
 ・商用利用の場合は GNU General Public License v3.0
GNU General Public License v3.0
 ・それ以外の場合は Apache License, Version 2.0
APACHE LICENSE, VERSION 2.0
 のデュアルライセンスとしておきます。

Program.cs
 // IPS Patch program
 // IpsPatch.exe
 // Copyright (c)2018 FREE WING, Y.Sakamoto

using System;
using System.IO;

namespace IpsPatch
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 2)
            {
                Console.WriteLine("Error");
                return;
            }

            string ipsFilePath = args[0];
            byte[] ipsBuff = ReadByteFile(ipsFilePath);

            string filePath = args[1];
            byte[] rbuff = ReadByteFile(filePath);

            string ext = Path.GetExtension(filePath);
            string wfilePath = filePath.Replace(ext, "_pached" + ext);
            if (args.Length >= 3)
            {
                wfilePath = args[2];
            }

            bool err = false;
            int ipsstate = 0;
            int ipspos = 0;
            while ((ipspos < ipsBuff.Length) && (!err))
            {
                switch (ipsstate)
                {
                    case 0:
                        // PATCH
                        byte[] patch = { 0x50, 0x41, 0x54, 0x43, 0x48 };
                        for (int pos = 0; pos < patch.Length; ++pos)
                        {
                            byte ib = ipsBuff[ipspos++];
                            if (ib != patch[pos])
                            {
                                err = true;
                                break;
                            }
                        }

                        if (err)
                        {
                            break;
                        }

                        ++ipsstate;
                        break;

                    case 1:
                        // Chunk
                        // EOF
                        int offset = ipsBuff[ipspos++];
                        offset <<= 8;
                        offset |= ipsBuff[ipspos++];
                        offset <<= 8;
                        offset |= ipsBuff[ipspos++];

                        // EOF ?
                        if (offset == 0x00454F46)
                        {
                            if ( (ipspos == ipsBuff.Length) || (ipspos == (ipsBuff.Length - 3)) )
                            {
                                ++ipsstate;
                                break;
                            }
                        }

                         int length = ipsBuff[ipspos++];
                        length <<= 8;
                        length |= ipsBuff[ipspos++];
                        if (length != 0x0000)
                        {
                            if (rbuff.Length < (offset + length))
                            {
                                Array.Resize(ref rbuff, (offset + length));
                            }

                            // AM
                            while (length-- > 0)
                            {
                                rbuff[offset++] = ipsBuff[ipspos++];
                            }
                        }
                        else
                        {
                            // EM
                            int count = ipsBuff[ipspos++];
                            count <<= 8;
                            count |= ipsBuff[ipspos++];

                            if (rbuff.Length < (offset + count))
                            {
                                Array.Resize(ref rbuff, (offset + count));
                            }

                            byte b = ipsBuff[ipspos++];

                            while (count-- > 0)
                            {
                                rbuff[offset++] = b;
                            }
                        }
                        break;

                    case 2:
                        // Truncate
                        int truncate = ipsBuff[ipspos++];
                        truncate <<= 8;
                        truncate |= ipsBuff[ipspos++];
                        truncate <<= 8;
                        truncate |= ipsBuff[ipspos++];

                        Array.Resize(ref rbuff, truncate);

                        break;

                    default:
                        err = true;
                        break;
                }
            }

            if (err)
            {
                Console.WriteLine("Error");
                return;
            }

            WriteByteFile(wfilePath, rbuff);
            Console.WriteLine("Size = 0x" + rbuff.Length.ToString("x08"));
        }

        static byte[] ReadByteFile(string filePath)
        {
            using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                var buffer = new byte[fs.Length];
                fs.Read(buffer, 0, buffer.Length);
                return buffer;
            }
        }

        static void WriteByteFile(string filePath, byte[] buff)
        {
            using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
            {
                fs.Write(buff, 0, buff.Length);
            }
        }
    }
}



Tags: [通信販売]

●関連するコンテンツ(この記事を読んだ人は、次の記事も読んでいます)

ニンテンドークラシックミニ ダブルパックを購入、ミニ ファミリーコンピュータとミニ スーパーファミコン
ニンテンドークラシックミニ ダブルパックを購入、ミニ ファミリーコンピュータとミニ スーパーファミコン

  品薄だったミニファミコンがミニスーファミとダブルパックで販売再開したので買ってみた

任天堂 クラシックミニ ミニファミコンとミニスーファミを改造して任意のゲームを追加する
任天堂 クラシックミニ ミニファミコンとミニスーファミを改造して任意のゲームを追加する

  ファミコンミニとスーファミミニをハックして任意のゲームを追加やゲームボーイや PCエンジンを動かす

任天堂 クラシックミニ ミニスーファミに hakchi2アプリを入れて任意のゲームを追加や他機種のゲームで遊ぶ
任天堂 クラシックミニ ミニスーファミに hakchi2アプリを入れて任意のゲームを追加や他機種のゲームで遊ぶ

  ファミコンミニとスーファミミニに hakchi2アプリを入れてゲーム追加や他のゲーム機のゲームで遊ぶ

任天堂 クラシックミニ ファミコンに隠されたハッカー宛てのメッセージをハッカーが発見する!
任天堂 クラシックミニ ファミコンに隠されたハッカー宛てのメッセージをハッカーが発見する!

  ファミコンミニ内の隠された場所に隠されたハッカー宛てウィットなメッセージ、キャプテン花札

インターネットから無料でダウンロードできるゲーム機用のゲームソフトのまとめ
インターネットから無料でダウンロードできるゲーム機用のゲームソフトのまとめ

  スーファミミニをハックしてネットからダウンロードできるゲームを追加してみるテスト

.QD形式のファイルを .FDS形式に変換してエミュで遊ぶ夢 QD to FDS converter Win macOS
.QD形式のファイルを .FDS形式に変換してエミュで遊ぶ夢 QD to FDS converter Win macOS

  .NET C#でバイト配列のバイナリファイルを読み書きする方法、Windowsと macOSの両方で動作

任天堂 クラシックミニ ミニスーファミを改造してスーファミの任意のゲームを追加する方法
任天堂 クラシックミニ ミニスーファミを改造してスーファミの任意のゲームを追加する方法

  スーファミミニをハックして好きなスーファミのゲームを追加してみるテスト

任天堂 クラシックミニ ミニスーファミを改造してファミコンの任意のゲームを追加する方法
任天堂 クラシックミニ ミニスーファミを改造してファミコンの任意のゲームを追加する方法

  スーファミミニをハックして好きなファミコンのゲームを追加してみるテスト

任天堂 クラシックミニ ミニスーファミを改造してゲーム ボーイ アドバンスの任意のゲームを追加する方法
任天堂 クラシックミニ ミニスーファミを改造してゲーム ボーイ アドバンスの任意のゲームを追加する方法

  スーファミミニをハックして好きな GBA ゲームボーイアドバンスのゲームを追加してみるテスト

「ふるさと納税」でファミコンの同人ゲーム「キラキラスターナイト ふるさと納税 ふじみ野版」
「ふるさと納税」でファミコンの同人ゲーム「キラキラスターナイト ふるさと納税 ふじみ野版」

  ふるさと納税の返礼品でファミコンの同人ゲームを実質 2000円でゲットする方法

SONY PlayStation Classicをハックして任意のゲームを追加する方法 BleemSync編
SONY PlayStation Classicをハックして任意のゲームを追加する方法 BleemSync編

  任意のゲームを復刻版プレイステーションミニ クラシック SCPH-1000RJに追加する方法

SONY PlayStation Classicを買ってみた。内箱の正しい開け方
SONY PlayStation Classicを買ってみた。内箱の正しい開け方

  初期型プレイステーションの復刻版プレイステーション クラシック SCPH-1000RJを買った




[HOME] | [BACK]
リンクフリー(連絡不要、ただしトップページ以外は Web構成の変更で移動する場合があります)
Copyright (c) 2018 FREE WING,Y.Sakamoto
Powered by 猫屋敷工房 & HTML Generator

http://www.neko.ne.jp/~freewing/hardware/nintendo_mini_nes_game_ac_modify_ips_patch/