|
Emergency (ゲームタイトル画面では「The Emergency」と表示される) はI/O 1984年2月号掲載のFM-7用ゲームで、ワイヤーフレーム表示による3次元グラフィックで表示された地面の上を飛びながら地上目標に機銃掃射して破壊するのが目的というものだった。当時のレベルとしては信じられないような高速表示を実現していて、地面はただの格子とはいえ、上空を自由に飛び回ることができる感覚は新鮮だった。マイフレーム3次元描画しているのはたったの22本の直線なのだが、FM-7でここまでできるのかと衝撃を受けた一本だった。当時のFM-7ユーザなら誰もが記憶に残っているゲームだと思う。
また、FM-7のメインCPUとサブCPUでうまく並列処理をすることによって高速表示を実現していた。ジョイスティック対応するために解析してわかったけど機銃の発射を判定して弾丸のグラフィックを描画するところまでサブCPUで処理していて、メインCPUには弾丸の描画が終わった後で機銃が発射されたことを通知していた。(命中判定はメインCPU)ほとんどのFM-7用プログラムではサブCPUはグラフィックだけ担当で他の処理はメインCPUが担当するように役割分担しているが、これだとサブCPUのアイドルタイムが長くなってFM-7のふたつのCPUを必ずしも100%有効活用できない。EmergencyはサブCPUにより多くの処理をさせることでメイン・サブ両CPUが100%に近い効率で働くように工夫していた。
今でこそマルチコアのCPUによる並列処理は当たり前になったけど、当時はFM-7のサブCPUに意味があるのか疑問視する意見もあった。そのような疑念を実例を持って打ち砕いたのがEmergencyだった。富士通のパソコンはいつでも世の中の3歩ぐらい先を行っていたのに早すぎていまいちメジャーになれない。それはFM TOWNSまで続く富士通の伝統であった。
このEmergencyもFM-7の歴史を語る上で絶対はずせない一本と言えるので動態保存したいプログラムの一本なのだが、いかんせんジョイスティックに対応してない。最近の若いゲーマーだと操作性が悪くて投げ出してしまうかもしれない。そこで、勝手にジョイスティックに対応してみた。FM音源カードがあれば、あるいはFM77AV以降であればMSXジョイスティックをつなげて使用できる。なお、ジョイスティックではスピードのコントロールができないけど、スピードコントロールしなくてもほぼ問題なくプレイできるので支障ないと思う。
F-BASIC部分の書き換えが必要なので、対応パッチの当たった実行メディアを作るにはXM7か実機が必要。多分実機+テープBIOSリダイレクターまたは実機+ディスクBIOSリダイレクターでもできると思う。
(1) 空きテープまたは空きテープイメージを準備。F-BASICフォーマットのディスクでも可。
(2) 実機上で次のプログラムを入力して、SAVE "EMERGJS" としてテープにセーブ。
10 CLEAR ,&H3AFF
20 LOADM "EMERGJSM"
30 LOADM "emerg.m"
40 RUN
"EMER"
(3) 次のコマンドをタイプ。
CLEAR ,&H3AFF
(4) 次のダンプリストを入力して、SAVEM "EMERGJSM",&H3B00,&H3C20,&H3B00 でセーブ。
Add +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F Sum 3B00 20 1C 20 06 20 01 00 16 00 AF 34 06 6F 8C F7 4F :C3 | . . .....4.o..O 3B10 17 00 B1 84 30 81 30 27 03 6C 8C EA 35 86 17 00 :0B |....0.0'.l..5... 3B20 98 B6 FD 05 2B FB 86 80 B7 FD 05 B6 FD 05 2A FB :12 |....+.........*. 3B30 30 8D 00 C0 10 8E FC 80 C6 2D A6 80 A7 A0 5A 26 :77 |0........-....Z& 3B40 F9 7F FD 05 B6 FD 05 2B FB 86 BD B7 63 5E 8E C9 :6A |......+....c^.. 3B50 00 BF 63 5F 8E C8 FF BF 63 66 8E 12 12 BF 56 C5 :EA |..c_....cf....V. 3B60 86 BD B7 56 90 30 8C 06 BF 56 91 7E 53 00 34 7D :CA |...V.0...V.~S.4} 3B70 4F 8D 51 85 10 26 06 C6 80 DA 39 D7 39 1F 89 C4 :C3 |O.Q..&....9.9... 3B80 0F C1 0F 26 05 A1 8C 30 27 29 C6 30 85 04 26 04 :60 |...&...0').0..&. 3B90 C6 37 20 18 85 08 26 04 C6 39 20 10 85 01 26 04 :CB |.7 ...&..9 ...&. 3BA0 C6 38 20 08 85 02 26 04 C6 32 20 00 A7 8C 09 1F :4A |.8 ...&..2 ..... 3BB0 98 35 FD B6 FD 01 35 FD 00 CC 0F 7F 8D 20 CC 07 :8A |.5....5..... .. 3BC0 BF 20 1B 39 C6 2F 84 01 27 02 C6 5F 86 0F 8D 0E :2B |. .9./..'.._.... 3BD0 86 0E 8D 13 86 09 B7 FD 15 B6 FD 16 20 11 8D 07 :1A |............ ... 3BE0 F7 FD 16 86 02 20 05 B7 FD 16 86 03 B7 FD 15 7F :52 |..... ......... 3BF0 FD 15 39 00 00 00 3F 59 41 4D 41 55 43 48 49 91 :6C |..9...?YAMAUCHI. --------------------------------------------------------- 39 8C 79 5C C9 2A D4 36 4A DC 1F D0 27 09 CC 92 Add +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F Sum 3C00 D3 93 C9 00 00 1A 90 B6 D4 01 B7 C8 FF B6 D3 80 :EB |................ 3C10 2A 09 86 01 97 04 86 20 B7 C8 FF 96 04 7F D3 81 :E6 |*...... ....... 3C20 39 :39 |9............... --------------------------------------------------------- 36 9C 4F 01 97 1E 16 D6 8B C9 B6 5E 03 35 A6 01
(5) "Emergency"のテープなりディスクなりからマシン語部を読み込み。(COMPACのテープ版、ディスク版ではファイル名 "emerg.m" だった模様。僕は当時自分でI/Oから打ち込んだからそうだったのか実際のメディアで確認できなかった。)
(6) 手順1で用意したテープまたはテープイメージをセットして、 SAVEM "emerg.m",&H3D00,&H6FFF,&H5300 としてセーブ。
(7) "Emergency"のテープなりディスクなりからF-BASIC部を読み込んで、コードを以下のように修正。
1100 CLEAR 300,&H3AFF:SCREEN 7,7:DIM HIS(5):COLOR 5
1105 EXEC &H3B04
2350 EXEC &H3B00
1190 A$=INKEY$:EXEC &H3B02:IF A$<>" " AND PEEK(&H3B06)=0 THEN 1190
1900 A$=INKEY$:EXEC &H3B02:IF A$<>" " AND PEEK(&H3B06)=0 THEN 1900
2370 A$=INKEY$:EXEC &H3B02:IF A$<>" " AND PEEK(&H3B06)=0 THEN 2370
3210 A$=INKEY$:EXEC &H3B02:IF A$<>" " AND PEEK(&H3B06)=0 THEN 3210
3800 A$=INKEY$:EXEC &H3B02:IF A$<>" " AND PEEK(&H3B06)=0 THEN 3800
(8) 手順1で用意したテープまたはテープイメージをセットして、 SAVE "EMER"
あとは、テープをセットして、 RUN "CAS0:" あるいは、ディスクだったら RUN "EMERGJS" で起動。
一応ジョイスティック対応化パッチのアセンブリコード。苦労したのは、スペースキーの判定をサブCPUでやってたもんだから、メインCPUでボタン押下を検出したらサブにシグナルを送るコード、そしてサブCPUではメインからのシグナルを理解してスペースキーと同じ処理をするようにサブCPUにもパッチを送らなくてはならなかった。
ORG $3B00 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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INSTALL_AND_RUN BRA INSTALL_MAIN ; $3B00 BRA EMERGENCY_READ_JOYSTICK_BUTTON ; $3B02 BRA EMERGENCY_JSINIT BUTTONPRESS FCB 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EMERGENCY_JSINIT LBRA JSInit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EMERGENCY_READ_JOYSTICK_BUTTON ; For F-BASIC part PSHS A,B CLR BUTTONPRESS,PCR CLRA LBSR JSRead ANDA #JS_FLAG_ABUTTON+JS_FLAG_BBUTTON CMPA #JS_FLAG_ABUTTON+JS_FLAG_BBUTTON BEQ EXIT_EMERGENCY_READ_JOYSTICK_BUTTON INC BUTTONPRESS,PCR EXIT_EMERGENCY_READ_JOYSTICK_BUTTON PULS A,B,PC ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INSTALL_MAIN LBSR JSInit SUBSYS_READY_WAIT LDA $FD05 BMI SUBSYS_READY_WAIT LDA #$80 STA $FD05 SUBSYS_HALT_WAIT LDA $FD05 BPL SUBSYS_HALT_WAIT LEAX SUBSYS_CMD,PCR LDY #$FC80 LDB #SUBSYS_CMD_END-SUBSYS_CMD SUBSYS_TFR_LOOP LDA ,X+ STA ,Y+ DECB BNE SUBSYS_TFR_LOOP CLR $FD05 SUBSYS_UNHALT_WAIT LDA $FD05 BMI SUBSYS_UNHALT_WAIT ; 635E(C05E) CLR $D381 -> JSR $C900 LDA #$BD STA $635E LDX #$C900 STX $635F ; 6365(C065) LDA $D401 -> LDA $C8FF LDX #$C8FF STX $6366 ; Stop with '5' key LDX #$1212 STX $56C5 ; 5690 LDA $FD01 LDA #$BD STA $5690 LEAX EMERGENCY_JOYSCAN,PCR STX $5691 JMP $5300 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EMERGENCY_JOYSCAN PSHS B,X,Y,U,CC,DP CLRA BSR JSRead BITA #JS_FLAG_ABUTTON BNE JOYSCAN_NO_ABUTTON LDB #$80 ORB <$39 STB <$39 JOYSCAN_NO_ABUTTON TFR A,B ANDB #JS_FLAG_LEFT+JS_FLAG_RIGHT+JS_FLAG_UP+JS_FLAG_DOWN CMPB #JS_FLAG_LEFT+JS_FLAG_RIGHT+JS_FLAG_UP+JS_FLAG_DOWN BNE JOYSCAN_DIRECTION_INPUT CMPA EMERGENCY_PREV_JS_STATE,PCR BEQ EMERGENCY_JOYSCAN_NOJSINPUT JOYSCAN_DIRECTION_INPUT LDB #'0' ; Tentative. Stop BITA #JS_FLAG_LEFT BNE JOYSCAN_NOT_LEFT LDB #'7' BRA EMERGENCY_JOYSCAN_JSINPUT JOYSCAN_NOT_LEFT BITA #JS_FLAG_RIGHT BNE JOYSCAN_NOT_RIGHT LDB #'9' BRA EMERGENCY_JOYSCAN_JSINPUT JOYSCAN_NOT_RIGHT BITA #JS_FLAG_UP BNE JOYSCAN_NOT_UP LDB #'8' BRA EMERGENCY_JOYSCAN_JSINPUT JOYSCAN_NOT_UP BITA #JS_FLAG_DOWN BNE JOYSCAN_NOT_DOWN LDB #'2' BRA EMERGENCY_JOYSCAN_JSINPUT JOYSCAN_NOT_DOWN EMERGENCY_JOYSCAN_JSINPUT STA EMERGENCY_PREV_JS_STATE,PCR TFR B,A PULS B,X,Y,U,CC,DP,PC EMERGENCY_JOYSCAN_NOJSINPUT LDA $FD01 PULS B,X,Y,U,CC,DP,PC EMERGENCY_PREV_JS_STATE FCB 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LAST_JOYSTICK_STATUS FCB 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SUBSYS_CMD FCB 0,0 FCB $3F ; SubCPU Control FCB "YAMAUCHI" FCB $91 FDB $D380+(SUBCPU_HOOK_BEGIN-SUBSYS_CMD) FDB $C900 FDB #SUBCPU_HOOK_END-SUBCPU_HOOK_BEGIN FCB $90 SUBCPU_HOOK_BEGIN LDA $D401 STA $C8FF LDA $D380 BPL NO_MISSILE_FROM_MAINCPU LDA #1 STA <$04 LDA #$20 STA $C8FF NO_MISSILE_FROM_MAINCPU LDA <$04 CLR $D381 RTS SUBCPU_HOOK_END SUBSYS_CMD_END
Comments are welcome. Send E-Mail to: |