カナダ滞在記 2/19〜2/25

最近だるくてほとんど何もできていない。そのため記事も短めです。

2月19日(日)

研究に進展がありそうな兆しが見えた。

mathlogに記事を書いた。

mathlog.info

2月20日(月)

今日は祝日 (Family Day)。散髪屋に行ったり、半袖のTシャツを買ったり、昼に点心を食べたりした。

CNタワーが虹色に光っていた。

2月21日(火)

2月22日(水)

将棋盤を買ったので、同じ部屋のJ氏と指した。負けた。

2月23日(木)

将棋をまたJ氏と指した。勝った。

かんたんなことだけど、新しいことを一つ示せた。

2月24日(金)

今度は将棋をT氏と指した。実力で負けた。

バナナなどを買った。

2月25日(土)

平面を3つの雲で覆う論文を読んだ。

Three clouds may cover the plane - ScienceDirect

カナダ滞在記 2/12〜2/18

疲れが溜まっていて、今週は授業もサボることが多かった。毎晩爆音で映画を流している隣人が悪い。

可測基数の勉強はそこそこ進んだ。

2/14(火)に学生トークをした。

お絵かきもした。

また、新しいプレプリントを公開した。

arxiv.org

2/17(金)のアンガーの授業は2^{aleph_0}<2^{aleph_1} implies weak diamond (Devlin-Shelahの定理)の話だった。かなりついていけた。

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

前回→ポケモン赤緑で今流れている曲を鍵盤に表示する - 理科

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

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

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

追記(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

カナダ滞在記 2/5〜2/11

2/5 (日)

ホステルをチェックアウトし、新しいホステルにチェックインした。ホステルというか、今回はマンションの1室をシェアハウスする感じのようだ。隣の隣人が映画を流していてうるさい。  コインランドリーにも行った。

2/6 (月)

「気絶して気付いた起きたら日本の家だった」という夢を見たがかなりリアルな夢だった。

アンガーの授業は、マーティンの公理の応用の話。

2/7 (火)

ソレツキの授業は、ハール測度の話。

昼、プーティンを食べたが、まずかった。

バナナとコーヒーとレポート用紙を買った。

本日の模写。

ブログに一つ記事を書いた。

「なかよしバッヂ」で任意コード実行ができるわけ - 理科

2/8 (水)

T氏の学生発表を聴いた。

2/9 (木)

ソレツキの授業はベールのカテゴリーのポーランド群への応用?よく聴いていなかった。

この記事やそのプログラムを書いた。

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

2/10 (金)

スペンサー・アンガーの代わりにジャスティン・ムーアが授業をした。 MA_{aleph_1}より弱い公理である「ccc posetはproperty K_nを持つものしかない」とか「cccの直積がccc」みたいなものからの帰結の話だった。興味深い。

この記事やそのプログラムを書いた。

ポケモン赤緑で今流れている曲を鍵盤に表示する その2 - 理科

現実逃避はそろそろ終わりにして数学に戻らねば。

2/11 (土)

template iterationの勉強会のあとみんなで寿司に行った。 夜、ジャスティン・ムーアやステヴォ・トドロチェヴィチと学生3人でカフェに行った。が、周りががやがやしているのでいつも以上に英語が聴き取れなかった。

「なかよしバッヂ」で任意コード実行ができるわけ

初代ポケモン赤緑 (後期版)のバグ解説記事です。 表題の通り「なかよしバッヂ」で任意コード実行ができる理由を解説します。

メモリバンク3のアドレス0x563d、つまり03:563dというアドレスを今後UseItem_と呼びます。

UseItem_にはアイテムを使うときの処理のルーチンが記述されています。

その中身は次の図の通りです。

つまり、UseItem_の先頭には「ジャンプベクトル」を使ってアイテムIDに応じたアドレスにジャンプする処理が格納されています。 その処理に続けてジャンプベクトルが格納されています。 その0バイト〜1バイト目はアイテム1を使ったときのジャンプ先、2バイト〜3バイト目はアイテム2を使ったときのジャンプ先、…ということですね。 さらにそこに続けて、ジャンプベクトルでジャンプ先として指定されている、個々のアイテムの処理が書かれています。

ところが、ジャンプベクトルは83個のジャンプ先 (166バイト)しかありません。 ポケモン赤緑はここで、ベクトルの境界チェックをしません。 つまり内部IDが84 (アイテムの内部IDは1から始まることに注意)以上なアイテムを使用すると変なところからアドレスを拾ってきて、そこにジャンプするわけですね。 なお、ひでんマシンとわざマシンは内部ID196 (=0xc4)以上ですが、これらについては最初の処理に分岐があり、ここで紹介したジャンプベクトルは使わないようになっています。

変なアドレスと言いましたが、具体的には84番目のアイテムでは「ボールを使うときの処理」 の先頭(UseItem_+0xc0)に書かれたバイナリを読み取り、それをアドレスとして読み取ってそこへジャンプするわけです。85番目のアイテムなら「ボールを使うときの処理」の2バイト目、86番目なら「ボールを使うときの処理」の4バイト目、…というわけです。

さて、なかよしバッヂは内部ID 103 (=0x67)ですから、「ボールを使うときの処理」 の38 (= (103 - 84) * 2)バイト目を見るわけですね。 そこには

83 d9

が書かれています。 したがって、なかよしバッヂを使うと0xd983へジャンプするわけです。 ここはサファリボールの残り個数が格納されているアドレスであり、その続きには育て屋にあずけているポケモンにニックネームが格納されているので、これを適当にいじることで任意コード実行ができます。

なお、サファリボールの残り個数のアドレスがボールの処理の中に書かれているのは何も不思議ではありません。 ボールの処理で「サファリボールの残り個数を1減らす」という処理をしないといけないからですね。

この記事を見て興味を持った方はぜひ、bgbというエミュレータでアドレス「03:563d」にブレークポイントを設定して遊んでみてください。

カナダ滞在記 1/29〜2/4

1/29 (日)

コインランドリーに行った。 「可測基数ノート」というPDFを生成し始めた。

スーパーでバナナと黄色いレポート用紙を買った。

1/30 (月)

アンガーの7回目の授業は反復強制法の話。

授業のあと、M氏の誕生日でケーキがふるまわれた。

午後、strong homologyのセミナーを聴いた。 内容は僕にとって「やや難しい」程度なんだけど、低い英語リスニング能力のせいでついていくのが大変だった。

昨日買ったレポート用紙でがりがり計算。これが数学だ!

しかし、かなり良いアイディアと思って試した証明はうまく行かなかった。

また人の誕生日で飲みに来た。

1/31 (火)

ソレツキの授業4回目。 コンパクトハウスドルフ空間に対してHomeo(X)がC(X, X)のG_δ部分集合であることの証明になるほどとなった。

寿司の店に行ってSUSHI BURRITOを食べた。かなーりおいしかった。

気分展開に模写などする。

夜にハリーポッターシャドーイングとラジオ体操もした。

2/1 (水)

指導教員とのzoomミーティングをした。文献を読んでいていろいろわかんなかったところを教えてもらった。

「共終数の初歩」というPDFを作った。

2/2 (木)

ソレツキの授業はウリソーン空間の話だった。

夜にハリーポッターシャドーイングと模写をした。

2/3 (金)

アンガーの授業はマーティンの公理の無矛盾性証明だった。

2/4 (土)

template iterationの勉強会を始めた。

Template iterations and maximal cofinitary groupsという論文を一緒に読んでいく。

最初の自由群に関する部分や因子となるべき強制法の話などを一緒に読んだ。