|
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:
|