JavaScriptを有効にすると、ここにメニューを表示します。
FM-7用レトロゲーム勝手にジョイスティック対応化プロジェクト - Delphis

ysflight.com

Delphis (Compac, I/O 1984年5月号掲載, 服部浩憲氏作)

Delphisは富士通FM-7/8用立てスクロールシューティングゲームでI/O 1985年2月号に掲載されたプログラムだった。当時はnamcoのXeviousが大ヒット中で、それと似たようなゲームが載ったので、「おお、これは是非打ち込んでやってみたい」と、思ったが載ってるコードの分量に圧倒されて結局打ち込めなくて、その後小遣いを貯めて青森県弘前市の電巧堂代官町店の二階のパソコンフロアでテープ版を買った。買った場所は記憶があいまいだけど多分電巧堂代官町店の二階のパソコンフロアで間違いない。

FM-7は当時としては画期的な2ピクセル単位のスクロールができた。Delphisはそれをうまく活用していた。さらに作者の頭が良かったのは、スクロールする背景は4ピクセルごとに描き、プレイヤーが操作するキャラクター、敵機などは背景の隙間の3ピクセルずつに描いていた。当時複数画面の重ね合わせをしようと思ったら少なくともうち1画面は単色に制限されてしまう問題があったのだが、Delphisはこの方法でフルカラー(ちなみにFM-7時代のフルカラーは8色)を実現していた。

時系列はよく覚えてないのだが、FM-7には電波新聞社から酷い移植レベルのXeviousが発売された。一応、買ってプレイしたけど、他機種の移植レベルと比べて苦々しく思っていた。PC6601用にTiny Xeviousという緑がかったXeviousが発売されていたのだが、FM-7用はTinyとついていないにもかかわらず緑ががっていた。いや、黄ばんでいたというべきか。そしてスクロールは8ピクセル単位で、テキストがスクロールするかのごとくガクンガクンと進んでいった。ゲーセンではあれほど苦労したブラグザカート(扇形に弾をばらまいていく)の弾も、処理が遅いもんだから余裕で回避できた。その後電波新聞社は「ドルアーガの塔」と「ドラゴンバスター」をありえない素晴らしいレベルでFM77AVに移植して汚名を返上した感じはあるけれど、Xeviousの移植によってFM-7ユーザの間の電波新聞社の評価は恒久的かつ不可逆的なダメージを負うことになった。そんな中でDelphisの存在はFM-7に縦スクロールシューティングができないわけではないという、ある意味救いだった。

ところが、そのDelphisやってみたらひどく操作性が悪い。FM-7シリーズPCは、キーリリースイベントが物理的に取得できない。だから、FMユーザはキャラクターの動きを止めるときテンキーの5を押す技術が身についていた。ところが、何を思ったかこの作者、テンキーの2468でなく、1235を使って自機を移動させることにした。だから5キーで止められない。止まらないなら割り切って操作もできるのだが、これもまた何を思ったかこの作者、0キーで爆撃(Xeviousのブラスターみたいなの)すると自機が止まる。弾を回避しながら爆撃するとその場で止まってやられるというあまりの操作性。

結局その後無敵モードか何か使って一応最後まで見たんだったかな?

Delphisはそのインパクトから、もしも今まだ動作するFM-7があるならばときどき走らせたいゲームの一本と言える。レトロPCのイベントとかでFM-7を展示する機会があったら是非走らせてあげてほしい。しかし、操作性の悪さから実際プレイしてもらうと最近のぬるいゲームに慣れた若者はすぐ投げ出してしまうと思う。そういうわけで、勝手にジョイスティックに対応させた。ついでに斜め移動も可能にした。ついでに2018年になって今更発覚したバグも取った。それから、当時よくあったパターンでCAPS Lockをオンにしてないと何も反応しなくて何で動かんのだろう?と思う問題もついでに直した。あと、ゲーム開始時にスペースキーを押してからゲームタイプA/Bを選ぶわけだがこれもジョイスティックのボタンで先に進めるようにした。

解析してたらゲームタイプA/Bを選ぶところで大文字の'O'を押すと違う挙動をするようなんだけど、これが無敵モードだったかな? (確認。大文字の'O'を押してから'A'または'B'で無敵モード。)

2018年になって今更発覚したバグ

ちなみに、2018年になって実機でプレイしようとしたとき数回に1回しか起動しなくてなぜだろう?と、思ってコードを見たらバグを発見。当時そんなだった記憶は無いんだけどI/Oに載ってるコードも確かにバグってた。Delphisは二段階LOAD(最初のF-BASICのローダーを数えると三段階ロードだけどそれを言い出すと市販ソフトの大半が二段階ロードになってしまう)で、最初のプログラムがデータを裏RAMやSubCPUに転送、次のプログラムが本体になっている。ところが、最初のプログラムでSubCPUをHALTさせるコードが間違ってた。修正するには、BASICのローダーを次のように書き換えるといい。

10 CLEAR ,&H14FF
20 LOADM"DATA"
30 POKE &H68B1,&HFD
40 POKE &H68B2,&H05
50 POKE &H68B3,&H2A
60 POKE &H68B4,&HFB
70 EXEC
80 LOADM"DELPH.M"
90 POKE &H560D,&HFD
100 POKE &H560E,&H05
110 POKE &H560F,&H2A
120 POKE &H5610,&HFB
130 EXEC

バグが残ったままでFM-7が動作するためにはメインCPUがサブCPUを止めるシグナルを出して ($FD05に$80を書き込み) 次のCPUクロックでサブCPUが止まっていなくてはならない。そんなことは当時も起らなかったはずなんだけど。なぜ当時このバグが発覚しなかったのか、まったく謎。本来であれば$FD05に$80を書き込むと、サブCPUにHALT信号が送られて、サブCPUが本当に停止すると$FD05の読み込みでBit 7が0になるので、それまで待つのが正しいんだけど、元のDelphisのコードは待たない。

勝手にジョイスティック対応

なお、対応してるのは富士通純正FM音源カードに接続するか、FM77L2, FM77AV以降なら本体のジョイスティックポートに接続するMSX用ジョイスティック。まだBeep秋葉原とか家電のケンちゃんとかKVCラボで売ってるからなんとかゲットする。富士通純正FM音源カードの回路図は現在リバースエンジニアリング中。FM77AV以前ユーザでFM音源カード持ってない人も自作できるような情報をysflight.comに出せるといいんだけど、それは現在進行中。

勝手にジョイスティックに対応するには、次のF-BASICプログラムとマシン語プログラムをタイプする。

SAVE "DELPHJS"

10 CLEAR 20,&H13FF
20 LOADM "DELPHJSM"
30 LOADM "DATA"
40 POKE &H68B1,&HFD
50 POKE &H68B2,&H05
60 POKE &H68B3,&H2A
70 POKE &H68B4,&HFB
80 EXEC
90 LOADM "DELPH.M"
100 POKE &H560D,&HFD
110 POKE &H560E,&H05
120 POKE &H560F,&H2A
130 POKE &H5610,&HFB
140 EXEC &H1400

SAVEM "DELPHJSM",&H1400,&H153E,&H1400

Add +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F Sum
1400 17 01 02 86 7E B7 52 C1 30 8C 2C BF 52 C2 86 BD :E6 |....~.R.0.,.R...
1410 30 8D 00 E3 B7 55 F7 BF 55 F8 30 8D 00 C0 B7 42 :25 |0....U..U.0....B
1420 2A BF 42 2B 30 8D 00 A1 B7 42 EF BF 42 F0 B7 42 :86 |*.B+0....B..B..B
1430 1B BF 42 1C 7E 33 00 34 7D 4F 17 00 D3 34 02 85 :8E |..B.~3.4}O...4..
1440 20 26 11 C6 58 7D 23 E6 27 07 7D 23 E7 26 05 C6 :A1 | &..X}#.'.}#.&..
1450 5A F7 22 09 85 10 26 0A FC 16 31 26 05 C6 30 F7 :9C |Z."...&...1&..0.
1460 22 09 4F C6 01 E4 E4 26 0F F6 16 2E 5A C1 0F 25 :C7 |".O....&....Z..%
1470 07 F7 16 2E 8A 01 20 13 C6 02 E4 E4 26 0D F6 16 :CF |...... .....&...
1480 2E 5C C1 2D 2C 05 F7 16 2E 8A 04 C6 04 E4 E4 26 :2A |.\.-,..........&
1490 0F F6 16 1A 5A C1 07 25 07 F7 16 1A 8A 10 20 13 :77 |....Z..%...... .
14A0 C6 08 E4 E4 26 13 F6 16 1A 5C C1 42 2C 0B F7 16 :98 |....&....\.B,...
14B0 1A 8A 08 85 07 26 02 8A 02 35 04 35 7D 4D 27 03 :4E |.....&...5.5}M'.
14C0 7E 53 1A B6 22 09 7E 52 C4 34 04 4F 8D 42 84 30 :6A |~S..".~R.4.O.B.0
14D0 81 30 27 05 86 20 B7 22 09 B6 22 09 35 84 BD 43 :FF |.0'.. ."..".5..C
14E0 E8 34 04 4F 8D 2A 84 30 81 30 27 05 86 42 B7 22 :58 |.4.O.*.0.0'..B."
14F0 09 35 04 B6 22 09 39 81 61 25 06 81 7A 2E 02 8B :1F |.5..".9.a%..z...
---------------------------------------------------------
     3C F9 2A E3 55 99 7E 7E B1 7B 3C 9B CC E2 4C 30

Add +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F Sum
1500 E0 B7 22 09 39 CC 0F 7F 8D 20 CC 07 BF 20 1B 39 :08 |..".9... ... .9
1510 C6 2F 84 01 27 02 C6 5F 86 0F 8D 0E 86 0E 8D 13 :2C |./..'.._........
1520 86 09 B7 FD 15 B6 FD 16 20 11 8D 07 F7 FD 16 86 :76 |........ .......
1530 02 20 05 B7 FD 16 86 03 B7 FD 15 7F FD 15 39    :0D |. ...........9.
---------------------------------------------------------
     2E 0F 62 BE 72 9A 58 F7 EA 3D FB 9B 39 40 F7 D2

プログラムは、DELPHJS, DELPHJSM, もともとのDelphisのファイル、の順にテープ(またはテープイメージ)に保存するか、あるいはディスクでもいいけど。

あるいは、Delphisのテープイメージdelphis.t77がある場合は、ここのt77save.exeを使って、このt77ファイル(delphjs.t77)とつなげる。

t77save.exe -new Delphis_JS.t77 -append delphjs.t77 -append delphis.t77

あとはテープ(テープイメージ)をセットして、FM-7で

RUN ""

で実行。

一応アセンブリコード

一応、ジョイスティック対応化パッチのアセンブリコードはこんな感じ。FM-7実機再稼働プロジェクト始めてからすごい分量書いたなあ。楽しいけど。

                        ORG     $1400

JS_FLAG_UP              EQU     1
JS_FLAG_DOWN            EQU     2
JS_FLAG_LEFT            EQU     4
JS_FLAG_RIGHT           EQU     8
JS_FLAG_ABUTTON         EQU     16
JS_FLAG_BBUTTON         EQU     32


KEY_CODE                EQU     $2209
X_COORD                 EQU     $161A
Y_COORD                 EQU     $162E
KEY_TO_GUN_FLAG1        EQU     $23E6
KEY_TO_GUN_FLAG2        EQU     $23E7
BOMB_READY_2BYTE        EQU     $1631
INKEY_FUNC              EQU     $43E8


INSTALL_AND_RUN         LBSR    JSInit

                        LDA     #$7E        ; JMP
                        STA     $52C1
                        LEAX    DELPHIS_JS,PCR
                        STX     $52C2       ; Make it JMP DELPHIS_JS

                        LDA     #$BD        ; JSR

                        LEAX    CAPITALIZE,PCR
                        STA     $55F7
                        STX     $55F8

                        ;   422A 17 01 BB       LBSR  $43E8
                        LEAX    GAME_TYPE_CHECK,PCR
                        STA     $422A
                        STX     $422B

                        ;   42EF B6 22 09       LDA   $2209
                        LEAX    DEMO_STOP_CHECK,PCR
                        STA     $42EF
                        STX     $42F0

                        ;   421B B6 22 09       LDA   $2209
                        STA     $421B
                        STX     $421C

                        JMP     $3300

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

DELPHIS_JS              PSHS    B,X,Y,U,CC,DP

                        CLRA
                        LBSR    JSRead
                        PSHS    A



                        BITA    #JS_FLAG_BBUTTON
                        BNE     NOT_GUN_BUTTON
                        LDB     #'X'
                        TST     KEY_TO_GUN_FLAG1
                        BEQ     GUN_BUTTON_SETKEY
                        TST     KEY_TO_GUN_FLAG2
                        BNE     NOT_GUN_BUTTON
                        LDB     #'Z'
GUN_BUTTON_SETKEY       STB     KEY_CODE
NOT_GUN_BUTTON



                        BITA    #JS_FLAG_ABUTTON
                        BNE     NOT_BOMB_BUTTON
                        LDD     BOMB_READY_2BYTE
                        BNE     NOT_BOMB_BUTTON     ; Must be zero.
                        LDB     #'0'
                        STB     KEY_CODE
NOT_BOMB_BUTTON



                        CLRA

                        LDB     #JS_FLAG_UP
                        ANDB    ,S
                        BNE     NOT_UP

                        LDB     Y_COORD
                        DECB
                        CMPB    #$0F
                        BCS     NOT_UP

                        STB     Y_COORD
                        ORA     #1
                        BRA     NOT_DOWN

NOT_UP                  LDB     #JS_FLAG_DOWN
                        ANDB    ,S
                        BNE     NOT_DOWN

                        LDB     Y_COORD
                        INCB
                        CMPB    #$2D
                        BGE     NOT_DOWN

                        STB     Y_COORD
                        ORA     #4


NOT_DOWN                LDB     #JS_FLAG_LEFT
                        ANDB    ,S
                        BNE     NOT_LEFT

                        LDB     X_COORD
                        DECB
                        CMPB    #7
                        BCS     NOT_LEFT

                        STB     X_COORD
                        ORA     #$10
                        BRA     LEFT_OR_RIGHT

NOT_LEFT                LDB     #JS_FLAG_RIGHT
                        ANDB    ,S
                        BNE     NOT_RIGHT

                        LDB     X_COORD
                        INCB
                        CMPB    #$42
                        BGE     NOT_RIGHT

                        STB     X_COORD
                        ORA     #$08

LEFT_OR_RIGHT           BITA    #7
                        BNE     NOT_RIGHT
                        ORA     #2
NOT_RIGHT

                        PULS    B
                        PULS    B,X,Y,U,CC,DP
                        TSTA
                        BEQ     DELPH_NOTMOVED
DELPH_MOVED
                        ; If moved
                        JMP     $531A

DELPH_NOTMOVED
                        ; If no move
                        LDA     $2209
                        JMP     $52C4


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

DEMO_STOP_CHECK         PSHS    B
                        CLRA
                        BSR     JSRead
                        ANDA    #JS_FLAG_ABUTTON+JS_FLAG_BBUTTON
                        CMPA    #JS_FLAG_ABUTTON+JS_FLAG_BBUTTON
                        BEQ     DEMO_STOP_CHECK_EXIT
                        LDA     #' '
                        STA     KEY_CODE
DEMO_STOP_CHECK_EXIT    LDA     KEY_CODE
                        PULS    B,PC

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

GAME_TYPE_CHECK         JSR     INKEY_FUNC
                        PSHS    B
                        CLRA
                        BSR     JSRead
                        ANDA    #JS_FLAG_ABUTTON+JS_FLAG_BBUTTON
                        CMPA    #JS_FLAG_ABUTTON+JS_FLAG_BBUTTON
                        BEQ     EXIT_GAME_TYPE_CHECK
                        LDA     #'B'
                        STA     KEY_CODE
EXIT_GAME_TYPE_CHECK    PULS    B
                        LDA     KEY_CODE
                        RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

CAPITALIZE              CMPA    #'a'
                        BLO     CAPITALIZE_SETKEY
                        CMPA    #'z'
                        BGT     CAPITALIZE_SETKEY
                        ADDA    #'A'-'a'
CAPITALIZE_SETKEY       STA     KEY_CODE
                        RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

IO_FM_CMD               EQU     $FD15
IO_FM_DATA              EQU     $FD16

FM_CMD_LATCH            EQU     3
FM_CMD_WRITE            EQU     2
FM_CMD_READ             EQU     9

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

JSInit                  LDD     #$0F7F  ; Reg 15 <- $7F
                        BSR     FMWrite
                        LDD     #$07BF  ; Reg 7 <- $BF
                        BRA     FMWrite
                        RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                        ; A 0->JS0  1->JS1
JSRead                  LDB     #$2F
                        ANDA    #1
                        BEQ     JSRead0
                        LDB     #$5F
JSRead0                 LDA     #$0F    ; Reg 15 < $2F or $5F
                        BSR     FMWrite

                        LDA     #14
                        BSR     FMLatchRegister
                        LDA     #9
                        STA     IO_FM_CMD
                        LDA     IO_FM_DATA
                        BRA     FMClearCommand

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                        ; A Register
                        ; B Data
FMWrite                 BSR     FMLatchRegister
                        STB     IO_FM_DATA
                        LDA     #FM_CMD_WRITE
                        BRA     FMWriteCommand

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                        ; A Register
FMLatchRegister         STA     IO_FM_DATA
                        LDA     #FM_CMD_LATCH

FMWriteCommand          STA     IO_FM_CMD
FMClearCommand          CLR     IO_FM_CMD
                        RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                        END     INSTALL_AND_RUN

 

Comments are welcome.  Send E-Mail to: 

Back to http://www.ysflight.com