Zガンダムホットスクランブルの TAS を作ってしまった

indirect jmp (jmp ($xxxx)) がないかなーと思ったらものすごく都合のいい命令があって、ゲーム中の3Dシーンでは常に実行されていました。

B153: ldy  $4A ;enemy id number?
B155: jsr  $B16E
B16E: lda  $0300,y ;work index
B171: tax  ;assumed numbers are 0, 2, 4, 6, 8, 0xa and 0xc.
B172: lda  $B180,x ;jump table
B175: sta  $18
B177: lda  $B181,x
B17A: sta  $19
B17C: jmp  ($0018)

中身は10秒以内で作れるなと思ったので FCEUX を触ってみてあっさり作れたので投稿しました。*1

  • 動画の中で 360 frame って書いたけど、320 frame の間違いです。
  • youtube と nicovideo に上げました。2つとも内容は同じです。
  • 最速で入力しているだけで、人間でもゆっくりボタンをいれれば誰でも成功できます。

http://www.nicovideo.jp/watch/sm22828470

monitor on にするために

雑誌ではすごくわかりにくく書いていますが、プログラム自体はAボタンかBボタンを押したとき(OFF->ON)に入力成功かを判定しています。そのため方向キーはいつ放しても大丈夫です。曲者はAボタンとBボタンを同時に押す場面でして、全く同時にボタンを押すことができればコマンド入力は成功します。
それとこのプログラムは同じボタンを ON->OFF->ON とする場合に OFF の期間がが連続して 3frame 以上必要です。違うボタンであれば次の frame にいれられます。

判定条件を上から下へ順番に記載します。

01:   A
02:↑ A
03:  BA
04:↑B
05:  B
06:→B
07:  BA
08:→ A
09:→ A
10:← A
11:  BA
12:↓BA
13:↓B

AB同時押しが発生する前のボタンは放さずに別のボタンを押した方が入力の確実性があがります。ですので、下記の番号遷移の場合はボタンを放さない方がいいでしょう。

  • 2->3 の A
  • 6->7 の B
  • 10->12 の A

押した遷移を日本語の文で書くと結果として雑誌のような複雑怪奇な手順になってしまいますが、実際に入力するとそんなに難しくありませんでした。

fm2 file

たいした行数じゃないからここに記載します。

version 3
emuVersion 22020
rerecordCount 0
palFlag 0
romFilename HotScramble
romChecksum base64:cQ0iICWJ3s6uevapPBhulQ==
guid 1869630A-01F7-899E-D8B4-2DDBFC88CA46
fourscore 0
microphone 0
port0 1
port1 1
port2 0
FDS 0
NewPPU 0
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|1|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|.......A||
|0|........|...U....||
|0|........|...U....||
|0|........|...U....||
|0|........|...U...A||
|0|........|......BA||
|0|........|...U....||
|0|........|...U....||
|0|........|...U....||
|0|........|...U..B.||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|......B.||
|0|........|R.......||
|0|........|R.......||
|0|........|R.......||
|0|........|R.....B.||
|0|........|......BA||
|0|........|R.......||
|0|........|R.......||
|0|........|R.......||
|0|........|R......A||
|0|........|R.......||
|0|........|R.......||
|0|........|R.......||
|0|........|R......A||
|0|........|.L......||
|0|........|.L......||
|0|........|.L......||
|0|........|.L.....A||
|0|........|......BA||
|0|........|..D.....||
|0|........|..D.....||
|0|........|..D.....||
|0|........|..D...BA||
|0|........|..D.....||
|0|........|..D.....||
|0|........|..D.....||
|0|........|..D...B.||
|0|....T...|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|....T...|........||
|0|....T...|........||
|0|....T...|........||
|0|....T...|........||
|0|....T...|........||
|0|....T...|........||
|0|....T...|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|........||
|0|....T...|........||monitor start
|0|........|R.......||
|0|........|...U....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|...U....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|...U....||address = 0x0300
|0|........|R.......||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|R.......||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|R.......||
|0|........|...U....||data = 0x10
|0|........|........||
|0|........|........||
|0|........|R.......||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||data -= 2; data = 0xe
|0|........|R.......||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|R.......||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||address -= 0x100; address = 0x200
|0|........|R.......||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|R.......||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|R.......||
|0|........|...U....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|...U....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|...U....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|...U....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|...U....||data += 0x50; data = 0x50
|0|........|R.......||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||data -= 4; data = 0x4c
|0|........|.......A||address += 1; address = 0x201
|0|........|...U....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|...U....||data += 2; data = 0x02
|0|........|.L......||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|.......A||address += 1; 
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||
|0|........|........||
|0|........|........||
|0|........|........||
|0|........|..D.....||data += 0x80; jmp $8092 (staffroll sequence)
|0|....T...|........||

*1:Bizhowk は reset button の実装をしてないみたいで copyright を飛ばせなかった。這是無能。