前回→ポケモン赤緑で今流れている曲を鍵盤に表示する - 理科
ポケモン赤緑のなかよしバッヂを使った任意コード実行で今流れている曲を鍵盤に表示しました。
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