Unirom8とwindows上で動作するのnops.exeを使って初代プレステで自作プログラムを動作する

## はじめに
　初代プレステ（以降、PS1）でリージョンフリーでゲームソフトを動かす際は、FreePSXBootとunirom8の組み合わせが便利です。FreePSXBootのサイトでは、ゲーム起動の情報のみが記載されています。
　自作ソフトを動作させるためには、何らかの方法で自作ソフトをPS1に読み込ませる必要があります。それに必要なツールはどこにあるかというと、unirom8のgithubレポジトリです。
　本稿では、unirom8と一緒に配布されているツール類のうち、nops.exeを紹介します。
## unirom8の配布ツール類

UNIROM_BOOTDISC_8.0.K.zipをダウンロードして展開すると、「UNIROM_BOOTDISC_8.0.K」フォルダの中に「stuff」フォルダがあります。

https://github.com/JonathanDotCel/unirom8_bootdisc_and_firmware_for_ps1/releases/tag/8.0.K

この中に、WindowsやMacOS、Linux（以降、母艦）側で使う各種ファイルが保存されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693019/6d112e6b-b77d-a254-bba5-603f67a971dd.png)
README.txtの中の、母艦に関係するものだけ紹介します。
nops.exe, ELFSharp.dll, nops
PS1と母艦との間でシリアルポート経由でファイルを転送するときに使うプログラムです。
Windowsでは、コマンドプロンプト上で「nops.exe」、MacやLinuxでは、monoをインストールした後、バッチファイルの「nops」を使って「nopx.exe」を起動します。

https://github.com/JonathanDotCel/NOTPSXSerial

schematic.png
PS1とArduino UNO R3との間の配線方法が書かれています。TX用の8 kオームのプルダウン抵抗は大事。

danhans_pong.psx
Danさんの作成したソフトで、PS1上で動きます。

exe2memcard
メモリカードから自作ソフトを作成する際に使用します。使い方は、「exe2memcard」フォルダ内の「README.txt」参照。
## nops.exe
　コマンドプロンプトから起動すると、使用法が表示されます。

　色々ありますが、PS1用実行ファイルの転送方法の
```
　NOPS.EXE /exe <FILE.EXE> COM8
```
が使えればいいかと思います。
　COM8の部分はwindowsだとデバイスマネージャーで、確認してください。

##　danhans_pong.psxを起動
　EXEファイルと想定して、以下のコマンドでファイルを転送します。 
```
 nops /exe  danhans_pong.psx COM19
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693019/158344df-5e97-22f2-f433-f7b51d9a57ec.png)
　ファイル転送が終了すると、PS1で転送したプログラムが起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693019/68ada69b-da84-e278-96dc-9a60a2ca6085.png)
　コントローラで遊びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693019/941a38fe-ac7d-3fcc-cc49-a34b7b9206e4.png)
## nops.exeでカートリッジのROMを書き換える
　PS1の背面のシリアルポートには、チートコードを保存するカートリッジ（以降、チートカート）を接続可能です。アリエクだと、例えば以下の商品を入手可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693019/79e4b5d9-7adc-57b7-c11a-c312ee9353e7.png)
このチートカートには、AM29F10というROMが搭載されています。128 kBのPS1で起動するプログラムを保存可能です。保存されたプログラムは、PS1の電源を入れると起動します。
　unirom8とnops.exeの組み合わせで、このROMの中身を書き換え可能です。
　PS1側でunirom8を起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693019/761a5c4a-3f46-1909-2a9a-3e8529f22b73.png)
 背面のパラレルポートにチートカートリッジを差し込みます。
　Windowsマシンから、unirom8のプログラムを転送します。
```
nops /rom unirom_standalone.rom COM19
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693019/c7bb6cb1-9642-3445-3285-54c794a693b6.png)
ROMの種類を確認し、容量の確認をします。保存可能だとわかるとファイルを転送します。
　一方、PS1の画面では、以下の表示となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693019/5dc985e9-1a47-5183-0e3a-7a77c9bf90ca.png)
　ROMの存在を確認し、そのIDを確認し、接続されているROMがどのようなものであるか判定します。
　次にDATAの転送を要求し、ファイルを受け取ります。ファイルが正しく転送されたことを確認したら、ROMの内容を消去します。
　その後、受け取ったファイルをROMに書き込みます。ここでは、20%書き込みが進んでいます。
 　以下には、書き込みが100%になった表示が出ています。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693019/e16a88cc-7302-5fad-ba70-b7d6f0a06a6a.png)
　100%の書き込みが終わると、PS1が再起動します。再起動中は、以下の画面が出ます。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693019/0643fd5b-0607-b137-2963-8a1dc3fc37fa.png)
　再起動後にunirom8が起動します。以下のunirom8はチートカートから起動しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693019/2701a78f-30f5-c683-446d-793e8b96efab.png)
　このチートカートをPS1のパラレルポートに接続しておくと、FreePSXBootを使わなくても、unirom8がすぐ起動します。
 
 https://psx0.wordpress.com/2022/04/05/cheap-playstation-cheat-carts/
## おわりに
　unirom8とnops.exeの組み合わせを使って、シリアルポート経由のファイル転送とチートカートのROMの書き換えが可能となりました。
 nops.exeには他の機能もありますので、以下の「おまけ」やnops.exeの説明を参考に、自作プログラム開発に活用してください。
## おまけ
オプションを付けずにnops.exeを実行した時のメッセージを記載します。

```
================================================================================
    Totally NOtPsxSerial v14 (8.0.J)
    Thanks: Jihad of HITMEN, Shendo, Type79, Dax,
            r0r0, Skitchin, danhans42, Schnappy,
            Nicolas Noble, T0fuZ & Arthur!

            Instructions :  http://unirom.github.io
            Discord      :  http://psx.dev
================================================================================

        Note: You may have to install mono and launch via 'mono nops.exe /args' if...
      - Windows cant put your serial device (FTDI, etc) into 115200baud
      - You are using a Sharklink/Net Yaroze cable
      - Any flavour of *nix/OSX


    Usage : NOPS.EXE [/args] [FILENAME] [COMPORT]
    Usage : NOPS.EXE [/args] [FILENAME] [IPADDRESS:PORT]

    Bridge: NOPS.EXE /bridge [LOCALIP:PORT] [COMPORT]
            bridges e.g. a local serial device and port, allowing remote connections


      Send an .EXE :  NOPS.EXE /exe <FILE.EXE> COM8

      Flash a .ROM :  NOPS.EXE /rom <FILE.ROM> COM8

      Send a  .BIN :  NOPS.EXE /bin 0xADDRESS0 <FILE.BIN> COM8

      Jump addr (jr) :  NOPS.EXE /jmp 0xADDRESS0 COM8
      Call addr (jal):  NOPS.EXE /jal 0xADDRESS0 COM8

    Dumpy Stuff:
                RAM  (  2m) :  NOPS.EXE /dump 0x80000000 0x200000 <DUMP.BIN> COM8
                ROM  (128k) :  NOPS.EXE /dump 0x1F000000 0x20000  <DUMP.BIN> COM8
                ROM  (384k) :  NOPS.EXE /dump 0x1F000000 0x60000  <DUMP.BIN> COM8
                ROM  (512k) :  NOPS.EXE /dump 0x1F000000 0x80000  <DUMP.BIN> COM8
                BIOS (512k) :  NOPS.EXE /dump 0xBFC00000 0x80000  <DUMP.BIN> COM8
                SPAD (  1k) :  NOPS.EXE /dump 0x1F800000 0x400    <DUMP.BIN> COM8

                WARNING! If named dump file already exist it will be overwritten!
                Also note that you can use * for <DUMP.BIN> to have automagically generated filename

    Memory Cards:
               MC0->File :  NOPS.EXE /mcdown 0 filename.mcr COM8
               MC1->File :  NOPS.EXE /mcdown 1 filename.mcr COM8
               File->MC0 :  NOPS.EXE /mcup 0 filename.mcr COM8

    Pokey Poke:
                 8 bits :  NOPS.exe /poke8 0x80100001 0x01 COM8
                16 bits :  NOPS.exe /poke16 0x80100002 0x0202 COM8
                32 bits :  NOPS.exe /poke32 0x80100004 0x04040404 COM8

    Continuous Hex Dump (to screen):
                CD REGS:   NOPS.EXE /watch 0x1F801800 0x4 COM8

    Extra switches:
                /m to open the Serial IO monitor (can be used /m COM8 alone)
                /fast to enable or continue using 500k baud
                /debug to enable experimental /bin & /dump during gameplay

    Examples:
                nops /fast /rom unirom_b.rom COM14
                nops /exe mything.exe /m COM14
                nops /fast /poke8 0x80100000 0x04 COM14

   Debug Functions:   (Must be in debug mode via L1+Square or nops /debug)
                Halt the PSX                       : nops /halt
                Continue from halt/exeception/hook : nops /cont
                Show registers from last interrupt : nops /regs
                Set a register while halted        : nops /setreg 0xADDR 0xVALUE
                Hook (halt) on memory read  *      : nops /hookread 0xADDR
                Hook (halt) on memory write *      : nops /hookwrite 0xADDR
                Hook (halt) on memory exec  *      : nops /hookex 0xADDR
                Unhook (read/write/exec)           : nops /unhook
                * = Resume with nops /cont

  STDIN Functions:
                Types a string into stdin  : nops /type "something"
                at about 1 char per frame  : nops /type 'something'
```