JavaScriptを有効にすると、ここにメニューを表示します。
富士通FM-7用"Emergency" - 勝手にジョイスティック対応化パッチ

ysflight.com

Emergency (COMPAC, I/O 1984年2月号掲載, 松崎知式氏作)

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: 

Back to http://www.ysflight.com