ポケモン赤緑で今流れている曲を鍵盤に表示する

追記(2023/2/10):以下のプログラムは全然正しく音階を表示していませんでした。修正版はこちら→ポケモン赤緑で今流れている曲を鍵盤に表示する その2 - 理科

ポケモン赤緑のなかよしバッヂを使った任意コード実行で今流れている曲を鍵盤に表示しました。

2つのパルスチャンネルのみ出力しています。ウェーブチャンネルとノイズチャンネルの表示は未実装です。

合っているか確かめてません…。また、白鍵と黒鍵を分けずに一列に並べています。

Aボタン入力で脱出できます。

アイスさんの動画を超参考にしました:

【初代ポケモン】ポケモンで作曲をする方法 バグ・任意コード実行 - YouTube

白鍵と黒鍵のあるバージョンも作成してみたいかも。

0xda00からスタート

cd 67 01 21 00 90 06 88 0e 88 cd 36 da 0e f8 cd
36 da 0e 8f cd 36 da cd 81 01 cd 67 38 fa b3 ff
cb 47 c0 21 a0 c3 3e 00 cd 41 da 21 dc c3 3e 01
cd 41 da c3 1a da 16 08 78 22 79 22 15 c2 38 da
c9 cd 73 da 4f 06 00 78 87 b9 c2 52 da 3e 01 c3
60 da 78 87 3c b9 c2 5e da 3e 02 c3 60 da 3e 00
77 e5 c5 01 14 00 09 77 c1 e1 23 04 78 fe 14 c2
47 da c9 e5 16 00 5f 21 06 c0 19 19 7e 23 4f 7e
47 0a cb 37 e6 0f 4f 21 d6 c0 19 19 7e fe 04 da
a1 da fe 06 d2 a1 da d6 04 47 80 80 17 17 81 e1
c9 3e ff e1 c9

ソースコード (https://github.com/ulrikdamm/Assemblerアセンブルできるものです)

PlaySound = 0x0e33
wTileMap = 0xc3a0
wChannelCommandPointers = 0xc006
wChannelOctaves = 0xc0d6
DisableLCD = 0x0167
EnableLCD = 0x0181
JoypadLowSensitivity = 0x3867
hJoyPressed = 0xffb3
vTileset = 0x9000

SCREEN_WIDTH = 0x14

[org(0xda00)]
start:
    call DisableLCD
    ld hl, vTileset
    ld b, 0x88
    ld c, 0x88
    call CreateTile
    ld c, 0xf8
    call CreateTile
    ld c, 0x8f
    call CreateTile
    call EnableLCD

loop:
    call JoypadLowSensitivity
    ld a, [hJoyPressed]
    bit 0, a
    ret nz
    ld hl, wTileMap
    ld a, 0
    call do
    ld hl, wTileMap + SCREEN_WIDTH * 3
    ld a, 1
    call do
    # ld hl, wTileMap + SCREEN_WIDTH * 6
    # ld a, 2
    # call do
    jp loop

CreateTile:
    ld d, 8
CreateTile_loop:
    ld a, b
    ld [hl+], a
    ld a, c
    ld [hl+], a
    dec d
    jp nz, CreateTile_loop
    ret

do:
    call calculate_position
    ld c, a
    ld b, 0
lp:
    ld a, b
    add a, a
    cp c
    jp nz, nonhit1
    # b + b == cならタイルを1に
    ld a, 1
    jp join
nonhit1:
    ld a, b
    add a, a
    inc a
    cp c
    jp nz, nonhit2
    # b + b + 1 == cならタイルを2に
    ld a, 2
    jp join
nonhit2:
    ld a, 0
join:
    ld [hl], a
    push hl
    push bc
    ld bc, SCREEN_WIDTH
    add hl, bc
    ld [hl], a
    pop bc
    pop hl
    inc hl
    inc b
    ld a, b
    cp 20
    jp nz, lp
    ret

calculate_position:
    push hl
    ld d, 0
    ld e, a
    ld hl, wChannelCommandPointers
    add hl, de
    add hl, de
    ld a, [hl]
    inc hl
    ld c, a
    ld a, [hl]
    ld b, a
    ld a, [bc]
    swap a
    and 0xf
    ld c, a
    ld hl, wChannelOctaves
    add hl, de
    add hl, de
    ld a, [hl]
    cp 4
    jp c, outofrange
    cp 6
    jp nc, outofrange
    sub a, 4
    # 12倍
    ld b, a
    add a, b
    add a, b
    rla
    rla
    add a, c
    pop hl
    ret
outofrange:
    ld a, 0xff
    pop hl
    ret