前回→ポケモン赤緑で今流れている曲を鍵盤に表示する - 理科
白鍵と黒鍵のある鍵盤に表示するバージョンを作成しました。また、昨日の動画は表示がデタラメだった (なにせ音楽のROMバンクに切り替えるのを忘れていた!)ので、そこも修正しています…。 pic.twitter.com/vCYhHgNdSM
— でぃぐ(ゲーム用垢) (@fujidig_game) 2023年2月11日
さっきの動画のプログラムはオクターブを正しく反映していませんでした。修正版です。 pic.twitter.com/jfDnEgVQuP
— でぃぐ(ゲーム用垢) (@fujidig_game) 2023年2月11日
ポケモン赤緑のなかよしバッヂを使った任意コード実行で今流れている曲を鍵盤に表示しました。
Aボタン入力で脱出できます。
白鍵と黒鍵のある鍵盤に表示するバージョンになっているほか、前回のは表示がデタラメだった (なにせ音楽のROMバンクに切り替えるのを忘れていた!)ので、そこも修正しています。
アイスさんの動画を超参考にしました:
【初代ポケモン】ポケモンで作曲をする方法 バグ・任意コード実行 - YouTube
バイナリ (0xda00からスタート; 488バイト)
cd 67 01 21 00 88 11 0c db 1a 47 13 1a 4f 13 cd 9b da 7b fe 44 c2 09 da 21 3d 88 3e a9 22 77 cd 81 01 cd 92 db cd 9e db cd aa db cd 67 38 fa b3 ff cb 47 c0 11 a0 c3 3e 00 cd 4f da 11 dc c3 3e 01 cd 4f da 11 18 c4 3e 02 cd 4f da c3 22 da cd a8 da 3e 00 c5 f5 81 fe 05 ca 61 da 3e 00 c3 6d da 78 fe 0c da 6c da 3e 00 c3 6d da 3c 06 00 4f 81 81 17 4f 21 44 db 09 cd 91 da d5 7b c6 11 5f 7a ce 00 57 cd 91 da d1 f1 c1 3c fe 06 c8 c3 54 da 2a 12 13 2a 12 13 2a 12 13 c9 d5 16 08 78 22 79 22 15 c2 9e da d1 c9 e5 d5 16 00 5f 21 e2 db 7c b5 ca d2 da 19 19 fa db d2 ea 00 20 2a 4f 7e 47 cd d9 da cb 37 e6 0f 47 21 d6 c0 19 7e 4f d1 e1 c9 06 0f 0e 00 d1 e1 c9 d5 60 69 2a 47 fe dc c2 e7 da 23 c3 dc da fe ed c2 f1 da 23 23 c3 dc da e6 f0 fe e0 c2 fb da c3 dc da 78 fe fe c2 0a db 23 2a 47 7e 67 68 c3 dc da d1 c9 99 99 a6 a6 66 66 89 89 22 22 44 44 99 f9 89 f9 81 99 99 9f 89 8f 98 99 26 a6 a6 e6 22 e2 a6 be 22 3e a0 a6 a6 a7 66 e6 22 23 44 c4 06 66 66 7e 44 7c 60 66 66 67 44 47 80 81 82 83 84 85 86 81 82 87 84 85 88 81 82 83 84 85 89 81 82 8a 84 85 8b 8c 82 83 84 85 80 8d 82 83 8e 85 80 8f 82 83 90 85 80 91 82 83 84 85 80 92 93 83 94 95 80 81 96 83 84 85 80 81 97 83 84 98 80 81 99 83 84 85 80 81 9a 83 84 9b 21 06 c0 11 dc db 01 e2 db c3 b3 db 21 08 c0 11 de db 01 e4 db c3 b3 db 21 0a c0 11 e0 db 01 e6 db e5 c5 d5 2a 4f 7e 47 62 6b 2a 5f 7e 57 78 aa 47 79 ab b0 d1 c1 ca d5 db 60 69 1a 47 22 13 1a 4f 77 1b e1 2a 12 13 7e 12 c9 00 00 00 00 00 00 00 00 00 00 00 00
ソースコード (https://github.com/ulrikdamm/Assemblerでアセンブルできるものです)
PlaySound = 0x0e33 wTileMap = 0xc3a0 wChannelCommandPointers = 0xc006 wChannelOctaves = 0xc0d6 DisableLCD = 0x0167 EnableLCD = 0x0181 JoypadLowSensitivity = 0x3867 hJoyPressed = 0xffb3 vFont = 0x8800 DelayFrame = 0x0b31 DelayFrames = 0x376F wMapMusicROMBank = 0xd2db BankSwitch = 0x360e SCREEN_WIDTH = 0x14 [org(0xda00)] start: call DisableLCD # タイルの作成 ld hl, vFont ld de, TileData maketiles_loop: ld a, [de] ld b, a inc de ld a, [de] ld c, a inc de call CreateTile ld a, e cp TileDataEnd & 0xff jp nz, maketiles_loop ld hl, vFont + (0x10 * 3) + 0xd ld a, 0xa9 ld [hl+], a ld [hl], a call EnableLCD loop: call loadPlayingAddress_0 call loadPlayingAddress_1 call loadPlayingAddress_2 call JoypadLowSensitivity ld a, [hJoyPressed] bit 0, a ret nz ld de, wTileMap ld a, 0 call do ld de, wTileMap + SCREEN_WIDTH * 3 ld a, 1 call do ld de, wTileMap + SCREEN_WIDTH * 6 ld a, 2 call do jp loop # 入力: a (チャンネル番号)、de (出力先アドレス) do: call calculate_position ld a, 0 do_loop: push bc push af # 5 - オクターブ = a なら音階に沿った番号、そうでなければ番号0を格納する add a, c cp 5 jp z, do_equal ld a, 0 jp do_join do_equal: ld a, b cp 0xc jp c, do_ok_note ld a, 0 jp do_join do_ok_note: inc a do_join: ld b, 0 # 6倍 ld c, a add a, c add a, c rla ld c, a ld hl, TileNumbers add hl, bc call copy_3_times # deにSCREEN_WIDTH-3を足す push de ld a, e add a, SCREEN_WIDTH - 3 ld e, a ld a, d adc a, 0 ld d, a call copy_3_times pop de pop af pop bc inc a cp 6 ret z jp do_loop copy_3_times: ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ld a, [hl+] ld [de], a inc de ret CreateTile: push de ld d, 8 CreateTile_loop: ld a, b ld [hl+], a ld a, c ld [hl+], a dec d jp nz, CreateTile_loop pop de ret # 入力: a (チャンネルの番号 0〜3) # 出力: b (音階)、c (オクターブ) calculate_position: push hl push de ld d, 0 ld e, a # ld hl, wChannelCommandPointers ld hl, PlayingAddress ld a, h or l jp z, ifnullptr add hl, de add hl, de # 音楽のバンクにスイッチ ld a, [wMapMusicROMBank] ld [0x2000], a #ld b, a #push de #push hl #call BankSwitch #pop hl #pop de ld a, [hl+] ld c, a ld a, [hl] ld b, a call ReadNotes swap a and 0xf ld b, a ld hl, wChannelOctaves add hl, de ld a, [hl] ld c, a pop de pop hl ret ifnullptr: ld b, 0xf ld c, 0x0 pop de pop hl ret # 入力: bc (アドレス) ReadNotes: push de ld h, b ld l, c ReadNotes_: ld a, [hl+] ld b, a cp 0xdc jp nz, non_dc inc hl jp ReadNotes_ non_dc: cp 0xed jp nz, non_ed inc hl inc hl jp ReadNotes_ non_ed: and 0xf0 cp 0xe0 jp nz, non_e jp ReadNotes_ non_e: ld a, b cp 0xfe jp nz, non_fe inc hl ld a, [hl+] ld b, a ld a, [hl] ld h, a ld l, b jp ReadNotes_ non_fe: pop de ret TileData: db 0x99, 0x99, 0xa6, 0xa6, 0x66, 0x66, 0x89, 0x89, 0x22, 0x22, 0x44, 0x44 db 0x99, 0xf9, 0x89, 0xf9, 0x81, 0x99, 0x99, 0x9f, 0x89, 0x8f, 0x98, 0x99 db 0x26, 0xa6, 0xa6, 0xe6, 0x22, 0xe2, 0xa6, 0xbe, 0x22, 0x3e, 0xa0, 0xa6 db 0xa6, 0xa7, 0x66, 0xe6, 0x22, 0x23, 0x44, 0xc4, 0x06, 0x66, 0x66, 0x7e db 0x44, 0x7c, 0x60, 0x66, 0x66, 0x67, 0x44, 0x47 TileDataEnd: TileNumbers: db 0x80, 0x81, 0x82, 0x83, 0x84, 0x85 # 0 db 0x86, 0x81, 0x82, 0x87, 0x84, 0x85 # 1 db 0x88, 0x81, 0x82, 0x83, 0x84, 0x85 # 2 db 0x89, 0x81, 0x82, 0x8a, 0x84, 0x85 # 3 db 0x8b, 0x8c, 0x82, 0x83, 0x84, 0x85 # 4 db 0x80, 0x8d, 0x82, 0x83, 0x8e, 0x85 # 5 db 0x80, 0x8f, 0x82, 0x83, 0x90, 0x85 # 6 db 0x80, 0x91, 0x82, 0x83, 0x84, 0x85 # 7 db 0x80, 0x92, 0x93, 0x83, 0x94, 0x95 # 8 db 0x80, 0x81, 0x96, 0x83, 0x84, 0x85 # 9 db 0x80, 0x81, 0x97, 0x83, 0x84, 0x98 # 10 db 0x80, 0x81, 0x99, 0x83, 0x84, 0x85 # 11 db 0x80, 0x81, 0x9a, 0x83, 0x84, 0x9b # 12 loadPlayingAddress_0: ld hl, wChannelCommandPointers ld de, PrevAddress ld bc, PlayingAddress jp loadPlayingAddressCommon loadPlayingAddress_1: ld hl, wChannelCommandPointers + 2 ld de, PrevAddress + 2 ld bc, PlayingAddress + 2 jp loadPlayingAddressCommon loadPlayingAddress_2: ld hl, wChannelCommandPointers + 4 ld de, PrevAddress + 4 ld bc, PlayingAddress + 4 loadPlayingAddressCommon: push hl push bc push de # bcにwChannelCommandPointersの中身を代入 ld a, [hl+] ld c, a ld a, [hl] ld b, a # deにPrevAddressの中身を代入 ld h, d ld l, e ld a, [hl+] ld e, a ld a, [hl] ld d, a ld a, b xor d ld b, a ld a, c xor e or b pop de pop bc jp z, nochange # 変更ありの場合、PrevAddressをPlayingAddressにコピー ld h, b ld l, c ld a, [de] ld b, a ld [hl+], a inc de ld a, [de] ld c, a ld [hl], a dec de nochange: # 変更あるなしに関わらず、wChannelCommandPointersをPrevAddressにコピー pop hl ld a, [hl+] ld [de], a inc de ld a, [hl] ld [de], a ret PrevAddress: nop nop nop nop nop nop PlayingAddress: nop nop nop nop nop nop