shithub: pokecrystal

Download patch

ref: d626a0dc3b0ba5d3c4f9984321a5a26941e8ec61
parent: 4fb008844030283ad34cb0802b088b4dd7c9891c
parent: 7580f1119b2409aeeea1e3ce2f26c0a2c1663756
author: Rangi <35663410+Rangi42@users.noreply.github.com>
date: Mon Jul 13 12:16:28 EDT 2020

Merge pull request #743 from Rangi42/master

Disassemble the final English debug ROMs

diff: cannot open b/engine/debug//null: file does not exist: 'b/engine/debug//null'
--- a/FAQ.md
+++ b/FAQ.md
@@ -4,7 +4,7 @@
 ## Questions
 
 - [What is pokecrystal11.gbc?](#what-is-pokecrystal11gbc)
-- [What is pokecrystal-au.gbc?](#what-is-pokecrystal-augbc)
+- [What is pokecrystal_au.gbc?](#what-is-pokecrystal_augbc)
 - [I can't build the ROM, `make` just prints an error!](#i-cant-build-the-rom-make-just-prints-an-error)
   - [`gcc`: command not found](#gcc-command-not-found)
   - ["ERROR: `UNION` already defined"](#error-union-already-defined)
@@ -25,9 +25,10 @@
 
 Version 1.1 of Pokémon Crystal, which fixed some issues with the initial international release. `make crystal11` defines `_CRYSTAL11` so the assembly builds the changed version.
 
-## What is pokecrystal-au.gbc?
 
-The Australian release of Pokémon Crystal, which is based on the international 1.1 release but censors gambling references from the Game Corners. `make crystal-au` defines `_CRYSTAL11` and `_CRYSTAL_AU` so the assembly builds the changed version.
+## What is pokecrystal_au.gbc?
+
+The Australian release of Pokémon Crystal, which is based on the international 1.1 release but censors gambling references from the Game Corners. `make crystal_au` defines `_CRYSTAL11` and `_CRYSTAL_AU` so the assembly builds the changed version.
 
 
 ## I can't build the ROM, `make` just prints an error!
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
-roms := pokecrystal.gbc pokecrystal11.gbc pokecrystal-au.gbc
+roms := pokecrystal.gbc pokecrystal11.gbc pokecrystal_au.gbc pokecrystal_debug.gbc pokecrystal11_debug.gbc
 
-crystal_obj := \
+rom_obj := \
 audio.o \
 home.o \
 main.o \
@@ -17,8 +17,11 @@
 gfx/tilesets.o \
 lib/mobile/main.o
 
-crystal11_obj := $(crystal_obj:.o=11.o)
-crystal_au_obj := $(crystal_obj:.o=_au.o)
+pokecrystal_obj         := $(rom_obj:.o=.o)
+pokecrystal11_obj       := $(rom_obj:.o=11.o)
+pokecrystal_au_obj      := $(rom_obj:.o=_au.o)
+pokecrystal_debug_obj   := $(rom_obj:.o=_debug.o)
+pokecrystal11_debug_obj := $(rom_obj:.o=11_debug.o)
 
 
 ### Build tools
@@ -39,24 +42,26 @@
 ### Build targets
 
 .SUFFIXES:
-.PHONY: all crystal crystal11 crystal_au clean tidy compare tools
+.PHONY: all crystal crystal11 crystal_au crystal_debug crystal11_debug clean tidy compare tools
 .SECONDEXPANSION:
 .PRECIOUS:
 .SECONDARY:
 
 all: crystal
-crystal:    pokecrystal.gbc
-crystal11:  pokecrystal11.gbc
-crystal-au: pokecrystal-au.gbc
+crystal:         pokecrystal.gbc
+crystal11:       pokecrystal11.gbc
+crystal_au:      pokecrystal_au.gbc
+crystal_debug:   pokecrystal_debug.gbc
+crystal11_debug: pokecrystal11_debug.gbc
 
 clean:
-	rm -f $(roms) $(crystal_obj) $(crystal11_obj) $(crystal_au_obj) $(roms:.gbc=.map) $(roms:.gbc=.sym) rgbdscheck.o
+	rm -f $(roms) $(pokecrystal_obj) $(pokecrystal11_obj) $(pokecrystal_au_obj) $(pokecrystal_debug_obj) $(pokecrystal11_debug_obj) $(roms:.gbc=.map) $(roms:.gbc=.sym) rgbdscheck.o
 	find gfx \( -name "*.[12]bpp" -o -name "*.lz" -o -name "*.gbcpal" -o -name "*.sgb.tilemap" \) -delete
 	find gfx/pokemon -mindepth 1 ! -path "gfx/pokemon/unown/*" \( -name "bitmask.asm" -o -name "frames.asm" -o -name "front.animated.tilemap" -o -name "front.dimensions" \) -delete
 	$(MAKE) clean -C tools/
 
 tidy:
-	rm -f $(roms) $(crystal_obj) $(crystal11_obj) $(crystal_au_obj) $(roms:.gbc=.map) $(roms:.gbc=.sym) rgbdscheck.o
+	rm -f $(roms) $(pokecrystal_obj) $(pokecrystal11_obj) $(pokecrystal_au_obj) $(pokecrystal_debug_obj) $(pokecrystal11_debug_obj) $(roms:.gbc=.map) $(roms:.gbc=.sym) rgbdscheck.o
 	$(MAKE) clean -C tools/
 
 compare: $(roms)
@@ -72,9 +77,11 @@
 RGBASMFLAGS += -E
 endif
 
-$(crystal_obj):    RGBASMFLAGS +=
-$(crystal11_obj):  RGBASMFLAGS += -D _CRYSTAL11
-$(crystal_au_obj): RGBASMFLAGS += -D _CRYSTAL11 -D _CRYSTAL_AU
+$(pokecrystal_obj):         RGBASMFLAGS +=
+$(pokecrystal11_obj):       RGBASMFLAGS += -D _CRYSTAL11
+$(pokecrystal_au_obj):      RGBASMFLAGS += -D _CRYSTAL11 -D _CRYSTAL_AU
+$(pokecrystal_debug_obj):   RGBASMFLAGS += -D _DEBUG
+$(pokecrystal11_debug_obj): RGBASMFLAGS += -D _CRYSTAL11 -D _DEBUG
 
 rgbdscheck.o: rgbdscheck.asm
 	$(RGBASM) -o $@ $<
@@ -93,24 +100,25 @@
 
 $(info $(shell $(MAKE) -C tools))
 
-$(foreach obj, $(crystal_au_obj), $(eval $(call DEP,$(obj),$(obj:_au.o=.asm))))
-$(foreach obj, $(crystal11_obj), $(eval $(call DEP,$(obj),$(obj:11.o=.asm))))
-$(foreach obj, $(crystal_obj), $(eval $(call DEP,$(obj),$(obj:.o=.asm))))
+# Dependencies for shared objects objects
+$(foreach obj, $(pokecrystal_obj), $(eval $(call DEP,$(obj),$(obj:.o=.asm))))
+$(foreach obj, $(pokecrystal11_obj), $(eval $(call DEP,$(obj),$(obj:11.o=.asm))))
+$(foreach obj, $(pokecrystal_au_obj), $(eval $(call DEP,$(obj),$(obj:_au.o=.asm))))
+$(foreach obj, $(pokecrystal_debug_obj), $(eval $(call DEP,$(obj),$(obj:_debug.o=.asm))))
+$(foreach obj, $(pokecrystal11_debug_obj), $(eval $(call DEP,$(obj),$(obj:11_debug.o=.asm))))
 
 endif
 
 
-pokecrystal.gbc: $(crystal_obj) layout.link
-	$(RGBLINK) -n pokecrystal.sym -m pokecrystal.map -l layout.link -p 0 -o $@ $(crystal_obj)
-	$(RGBFIX) -Cjv -t PM_CRYSTAL -i BYTE -k 01 -l 0x33 -m 0x10 -r 3 -p 0 $@
+pokecrystal_opt         = -Cjv -t PM_CRYSTAL -i BYTE -n 0 -k 01 -l 0x33 -m 0x10 -r 3 -p 0
+pokecrystal11_opt       = -Cjv -t PM_CRYSTAL -i BYTE -n 1 -k 01 -l 0x33 -m 0x10 -r 3 -p 0
+pokecrystal_au_opt      = -Cjv -t PM_CRYSTAL -i BYTU -n 0 -k 01 -l 0x33 -m 0x10 -r 3 -p 0
+pokecrystal_debug_opt   = -Cjv -t PM_CRYSTAL -i BYTE -n 0 -k 01 -l 0x33 -m 0x10 -r 3 -p 0
+pokecrystal11_debug_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 1 -k 01 -l 0x33 -m 0x10 -r 3 -p 0
 
-pokecrystal11.gbc: $(crystal11_obj) layout.link
-	$(RGBLINK) -n pokecrystal11.sym -m pokecrystal11.map -l layout.link -p 0 -o $@ $(crystal11_obj)
-	$(RGBFIX) -Cjv -t PM_CRYSTAL -i BYTE -n 1 -k 01 -l 0x33 -m 0x10 -r 3 -p 0 $@
-
-pokecrystal-au.gbc: $(crystal_au_obj) layout.link
-	$(RGBLINK) -n pokecrystal-au.sym -m pokecrystal-au.map -l layout.link -p 0 -o $@ $(crystal_au_obj)
-	$(RGBFIX) -Cjv -t PM_CRYSTAL -i BYTU -k 01 -l 0x33 -m 0x10 -r 3 -p 0 $@
+%.gbc: $$(%_obj) layout.link
+	$(RGBLINK) -n $*.sym -m $*.map -l layout.link -o $@ $(filter %.o,$^)
+	$(RGBFIX) $($*_opt) $@
 
 
 ### LZ compression rules
--- a/README.md
+++ b/README.md
@@ -7,6 +7,8 @@
 - Pokemon - Crystal Version (UE) (V1.0) [C][!].gbc `sha1: f4cd194bdee0d04ca4eac29e09b8e4e9d818c133`
 - Pokemon - Crystal Version (UE) (V1.1) [C][!].gbc `sha1: f2f52230b536214ef7c9924f483392993e226cfb`
 - Pokemon - Crystal Version (A) [C][!].gbc `sha1: a0fc810f1d4e124434f7be2c989ab5b5892ddf36`
+- CRYSTAL_ps3_010328d.bin `sha1: c60d57a24bbe8ecf7cba54ab3f90669f97bd330d`
+- CRYSTAL_ps3_us_revise_010710d.bin `sha1: 391ae86b1d5a26db712ffe6c28bbf2a1f804c3c4`
 
 To set up the repository, see [INSTALL.md](INSTALL.md).
 
--- a/constants/item_data_constants.asm
+++ b/constants/item_data_constants.asm
@@ -47,6 +47,8 @@
 MAX_KEY_ITEMS EQU 25
 MAX_PC_ITEMS  EQU 50
 
+MAX_ITEM_STACK EQU 99
+
 ; mail
 MAIL_LINE_LENGTH   EQU $10
 MAIL_MSG_LENGTH    EQU $20
--- a/constants/misc_constants.asm
+++ b/constants/misc_constants.asm
@@ -19,6 +19,9 @@
 SAVE_CHECK_VALUE_1 EQU 99
 SAVE_CHECK_VALUE_2 EQU 127
 
+; RTC halted check value
+RTC_HALT_VALUE EQU $1234
+
 ; time of day boundaries
 MORN_HOUR EQU 4  ; 4 AM
 DAY_HOUR  EQU 10 ; 10 AM
--- a/engine/battle/effect_commands.asm
+++ b/engine/battle/effect_commands.asm
@@ -3432,7 +3432,24 @@
 	ld [wBuffer4], a
 	sbc b
 	ld [wEnemyMonHP], a
+if DEF(_DEBUG)
+	push af
+	ld a, BANK(sSkipBattle)
+	call OpenSRAM
+	ld a, [sSkipBattle]
+	call CloseSRAM
+	or a
+	; If [sSkipBattle] is nonzero, skip the "jr nc, .no_underflow" check,
+	; so any attack deals maximum damage to the enemy.
+	jr nz, .debug_skip
+	pop af
 	jr nc, .no_underflow
+	push af
+.debug_skip
+	pop af
+else
+	jr nc, .no_underflow
+endc
 
 	ld a, [wBuffer4]
 	ld [hli], a
--- /dev/null
+++ b/engine/debug/color_picker.asm
@@ -1,0 +1,1391 @@
+	const_def $6a
+	const DEBUGTEST_TICKS_1 ; $6a
+	const DEBUGTEST_TICKS_2 ; $6b
+	const DEBUGTEST_WHITE   ; $6c
+	const DEBUGTEST_LIGHT   ; $6d
+	const DEBUGTEST_DARK    ; $6e
+	const DEBUGTEST_BLACK   ; $6f
+	const DEBUGTEST_0       ; $70
+	const DEBUGTEST_1       ; $71
+	const DEBUGTEST_2       ; $72
+	const DEBUGTEST_3       ; $73
+	const DEBUGTEST_4       ; $74
+	const DEBUGTEST_5       ; $75
+	const DEBUGTEST_6       ; $76
+	const DEBUGTEST_7       ; $77
+	const DEBUGTEST_8       ; $78
+	const DEBUGTEST_9       ; $79
+	const DEBUGTEST_A       ; $7a
+	const DEBUGTEST_B       ; $7b
+	const DEBUGTEST_C       ; $7c
+	const DEBUGTEST_D       ; $7d
+	const DEBUGTEST_E       ; $7e
+	const DEBUGTEST_F       ; $7f
+
+ColorTest:
+; A debug menu to test monster and trainer palettes at runtime.
+
+	ldh a, [hCGB]
+	and a
+	jr nz, .asm_818b5
+	ldh a, [hSGB]
+	and a
+	ret z
+
+.asm_818b5
+	ldh a, [hInMenu]
+	push af
+	ld a, $1
+	ldh [hInMenu], a
+	call DisableLCD
+	call Function81948
+	call Function8197c
+	call Function819a7
+	call Function818f4
+	call EnableLCD
+	ld de, MUSIC_NONE
+	call PlayMusic
+	xor a
+	ld [wJumptableIndex], a
+	ld [wcf66], a
+	ld [wd003], a
+.asm_818de
+	ld a, [wJumptableIndex]
+	bit 7, a
+	jr nz, .asm_818f0
+	call Function81a74
+	call Function81f5e
+	call DelayFrame
+	jr .asm_818de
+
+.asm_818f0
+	pop af
+	ldh [hInMenu], a
+	ret
+
+Function818f4:
+	ld a, [wd002]
+	and a
+	jr nz, Function81911
+	ld hl, PokemonPalettes
+
+Function818fd:
+	ld de, wOverworldMapBlocks
+	ld c, NUM_POKEMON + 1
+.asm_81902
+	push bc
+	push hl
+	call Function81928
+	pop hl
+	ld bc, 8
+	add hl, bc
+	pop bc
+	dec c
+	jr nz, .asm_81902
+	ret
+
+Function81911:
+	ld hl, TrainerPalettes
+	ld de, wOverworldMapBlocks
+	ld c, NUM_TRAINER_CLASSES
+.asm_81919
+	push bc
+	push hl
+	call Function81928
+	pop hl
+	ld bc, 4
+	add hl, bc
+	pop bc
+	dec c
+	jr nz, .asm_81919
+	ret
+
+Function81928:
+	ld a, BANK(PokemonPalettes) ; aka BANK(TrainerPalettes)
+	call GetFarByte
+	ld [de], a
+	inc de
+	inc hl
+	ld a, BANK(PokemonPalettes) ; aka BANK(TrainerPalettes)
+	call GetFarByte
+	ld [de], a
+	inc de
+	inc hl
+	ld a, BANK(PokemonPalettes) ; aka BANK(TrainerPalettes)
+	call GetFarByte
+	ld [de], a
+	inc de
+	inc hl
+	ld a, BANK(PokemonPalettes) ; aka BANK(TrainerPalettes)
+	call GetFarByte
+	ld [de], a
+	inc de
+	ret
+
+Function81948:
+	ld a, $1
+	ldh [rVBK], a
+	ld hl, vTiles0
+	ld bc, sScratch - vTiles0
+	xor a
+	call ByteFill
+	ld a, $0
+	ldh [rVBK], a
+	ld hl, vTiles0
+	ld bc, sScratch - vTiles0
+	xor a
+	call ByteFill
+	hlcoord 0, 0, wAttrmap
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	xor a
+	call ByteFill
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	xor a
+	call ByteFill
+	call ClearSprites
+	ret
+
+Function8197c:
+	ld hl, DebugColorTestGFX
+	ld de, vTiles2 tile DEBUGTEST_TICKS_1
+	ld bc, 22 tiles
+	call CopyBytes
+	ld hl, DebugUpArrowGFX
+	ld de, vTiles0
+	ld bc, 1 tiles
+	call CopyBytes
+	call LoadStandardFont
+	ld hl, vTiles1
+	lb bc, 8, 0
+.asm_8199d
+	ld a, [hl]
+	xor $ff
+	ld [hli], a
+	dec bc
+	ld a, c
+	or b
+	jr nz, .asm_8199d
+	ret
+
+Function819a7:
+	ldh a, [hCGB]
+	and a
+	ret z
+	ldh a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals2)
+	ldh [rSVBK], a
+	ld hl, Palette_DebugBG
+	ld de, wBGPals2
+	ld bc, 16 palettes
+	call CopyBytes
+	ld a, 1 << rBGPI_AUTO_INCREMENT
+	ldh [rBGPI], a
+	ld hl, Palette_DebugBG
+	ld c, 8 palettes
+	xor a
+.asm_819c8
+	ldh [rBGPD], a
+	dec c
+	jr nz, .asm_819c8
+	ld a, 1 << rOBPI_AUTO_INCREMENT
+	ldh [rOBPI], a
+	ld hl, Palette_DebugOB
+	ld c, 8 palettes
+.asm_819d6
+	ld a, [hli]
+	ldh [rOBPD], a
+	dec c
+	jr nz, .asm_819d6
+	ld a, $94
+	ld [wc608], a
+	ld a, $52
+	ld [wc608 + 1], a
+	ld a, $4a
+	ld [wc608 + 2], a
+	ld a, $29
+	ld [wc608 + 3], a
+	pop af
+	ldh [rSVBK], a
+	ret
+
+Palette_DebugBG:
+INCLUDE "gfx/debug/bg.pal"
+
+Palette_DebugOB:
+INCLUDE "gfx/debug/ob.pal"
+
+Function81a74:
+	call JoyTextDelay
+	ld a, [wJumptableIndex]
+	cp $4
+	jr nc, .asm_81a8b
+	ld hl, hJoyLast
+	ld a, [hl]
+	and SELECT
+	jr nz, .asm_81a9a
+	ld a, [hl]
+	and START
+	jr nz, .asm_81aab
+
+.asm_81a8b
+	jumptable Jumptable_81acf, wJumptableIndex
+
+.asm_81a9a
+	call Function81eca
+	call Function81ac3
+	ld e, a
+	ld a, [wcf66]
+	inc a
+	cp e
+	jr c, .asm_81aba
+	xor a
+	jr .asm_81aba
+
+.asm_81aab
+	call Function81eca
+	ld a, [wcf66]
+	dec a
+	cp $ff
+	jr nz, .asm_81aba
+	call Function81ac3
+	dec a
+
+.asm_81aba
+	ld [wcf66], a
+	ld a, $0
+	ld [wJumptableIndex], a
+	ret
+
+Function81ac3:
+; Looping back around the pic set.
+	ld a, [wd002]
+	and a
+	jr nz, .asm_81acc
+	ld a, NUM_POKEMON ; CELEBI
+	ret
+
+.asm_81acc
+	ld a, NUM_TRAINER_CLASSES - 1 ; MYSTICALMAN
+	ret
+
+Jumptable_81acf:
+	dw Function81adb
+	dw Function81c18
+	dw Function81c33
+	dw Function81cc2
+	dw Function81d8e
+	dw Function81daf
+
+Function81adb:
+	xor a
+	ldh [hBGMapMode], a
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, DEBUGTEST_BLACK
+	call ByteFill
+	hlcoord 1, 3
+	lb bc, 7, 18
+	ld a, DEBUGTEST_WHITE
+	call DebugColor_FillBoxWithByte
+	hlcoord 11, 0
+	lb bc, 2, 3
+	ld a, DEBUGTEST_LIGHT
+	call DebugColor_FillBoxWithByte
+	hlcoord 16, 0
+	lb bc, 2, 3
+	ld a, DEBUGTEST_DARK
+	call DebugColor_FillBoxWithByte
+	call Function81bc0
+	call Function81bf4
+	ld a, [wcf66]
+	inc a
+	ld [wCurPartySpecies], a
+	ld [wDeciramBuffer], a
+	hlcoord 0, 1
+	ld de, wDeciramBuffer
+	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
+	call PrintNum
+	ld a, [wd002]
+	and a
+	jr nz, .asm_81b7a
+	ld a, $1
+	ld [wUnownLetter], a
+	call GetPokemonName
+	hlcoord 4, 1
+	call PlaceString
+	xor a
+	ld [wBoxAlignment], a
+	hlcoord 12, 3
+	call _PrepMonFrontpic
+	ld de, vTiles2 tile $31
+	predef GetMonBackpic
+	ld a, $31
+	ldh [hGraphicStartTile], a
+	hlcoord 2, 4
+	lb bc, 6, 6
+	predef PlaceGraphic
+	ld a, [wd003]
+	and a
+	jr z, .asm_81b66
+	ld de, String_81baf
+	jr .asm_81b69
+
+.asm_81b66
+	ld de, String_81bb4
+
+.asm_81b69
+	hlcoord 7, 17
+	call PlaceString
+	hlcoord 0, 17
+	ld de, String_81bb9
+	call PlaceString
+	jr .asm_81ba9
+
+.asm_81b7a
+	ld a, [wDeciramBuffer]
+	ld [wTrainerClass], a
+	callfar GetTrainerAttributes
+	ld de, wStringBuffer1
+	hlcoord 4, 1
+	call PlaceString
+	ld de, vTiles2
+	callfar GetTrainerPic
+	xor a
+	ld [wTempEnemyMonSpecies], a
+	ldh [hGraphicStartTile], a
+	hlcoord 2, 3
+	lb bc, 7, 7
+	predef PlaceGraphic
+
+.asm_81ba9
+	ld a, $1
+	ld [wJumptableIndex], a
+	ret
+
+String_81baf: db "レア", DEBUGTEST_BLACK, DEBUGTEST_BLACK, "@" ; rare (shiny)
+String_81bb4: db "ノーマル@" ; normal
+String_81bb9: db DEBUGTEST_A, "きりかえ▶@" ; (A) switches
+
+Function81bc0:
+	decoord 0, 11, wAttrmap
+	hlcoord 2, 11
+	ld a, $1
+	call Function81bde
+	decoord 0, 13, wAttrmap
+	hlcoord 2, 13
+	ld a, $2
+	call Function81bde
+	decoord 0, 15, wAttrmap
+	hlcoord 2, 15
+	ld a, $3
+
+Function81bde:
+	push af
+	ld a, DEBUGTEST_TICKS_1
+	ld [hli], a
+	ld bc, $f
+	ld a, DEBUGTEST_TICKS_2
+	call ByteFill
+	ld l, e
+	ld h, d
+	pop af
+	ld bc, $28
+	call ByteFill
+	ret
+
+Function81bf4:
+	ld a, [wcf66]
+	inc a
+	ld l, a
+	ld h, $0
+	add hl, hl
+	add hl, hl
+	ld de, wOverworldMapBlocks
+	add hl, de
+	ld de, wc608
+	ld bc, 4
+	call CopyBytes
+	xor a
+	ld [wcf64], a
+	ld [wcf65], a
+	ld de, wc608
+	call Function81ea5
+	ret
+
+Function81c18:
+	ldh a, [hCGB]
+	and a
+	jr z, .asm_81c2a
+	ld a, $2
+	ldh [hBGMapMode], a
+	call DelayFrame
+	call DelayFrame
+	call DelayFrame
+
+.asm_81c2a
+	call WaitBGMap
+	ld a, $2
+	ld [wJumptableIndex], a
+	ret
+
+Function81c33:
+	ldh a, [hCGB]
+	and a
+	jr z, .asm_81c69
+	ldh a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals2)
+	ldh [rSVBK], a
+	ld hl, wBGPals2
+	ld de, wc608
+	ld c, $1
+	call Function81ee3
+	hlcoord 10, 2
+	ld de, wc608
+	call Function81ca7
+	hlcoord 15, 2
+	ld de, wc608 + 2
+	call Function81ca7
+	ld a, $1
+	ldh [hCGBPalUpdate], a
+	ld a, $3
+	ld [wJumptableIndex], a
+	pop af
+	ldh [rSVBK], a
+	ret
+
+.asm_81c69
+	ld hl, wSGBPals
+	ld a, 1
+	ld [hli], a
+	ld a, LOW(PALRGB_WHITE)
+	ld [hli], a
+	ld a, HIGH(PALRGB_WHITE)
+	ld [hli], a
+	ld a, [wc608]
+	ld [hli], a
+	ld a, [wc608 + 1]
+	ld [hli], a
+	ld a, [wc608 + 2]
+	ld [hli], a
+	ld a, [wc608 + 3]
+	ld [hli], a
+	xor a
+	ld [hli], a
+	ld [hli], a
+	ld [hl], a
+	ld hl, wSGBPals
+	call Function81f0c
+	hlcoord 10, 2
+	ld de, wc608
+	call Function81ca7
+	hlcoord 15, 2
+	ld de, wc608 + 2
+	call Function81ca7
+	ld a, $3
+	ld [wJumptableIndex], a
+	ret
+
+Function81ca7:
+	inc hl
+	inc hl
+	inc hl
+	ld a, [de]
+	call Function81cbc
+	ld a, [de]
+	swap a
+	call Function81cbc
+	inc de
+	ld a, [de]
+	call Function81cbc
+	ld a, [de]
+	swap a
+
+Function81cbc:
+	and $f
+	add DEBUGTEST_0
+	ld [hld], a
+	ret
+
+Function81cc2:
+	ldh a, [hJoyLast]
+	and B_BUTTON
+	jr nz, .asm_81cdf
+	ldh a, [hJoyLast]
+	and A_BUTTON
+	jr nz, .asm_81ce5
+	ld a, [wcf64]
+	and $3
+	ld e, a
+	ld d, 0
+	ld hl, Jumptable_81d02
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+.asm_81cdf
+	ld a, $4
+	ld [wJumptableIndex], a
+	ret
+
+.asm_81ce5
+	ld a, [wd002]
+	and a
+	ret nz
+	ld a, [wd003]
+	xor $4
+	ld [wd003], a
+	ld c, a
+	ld b, 0
+	ld hl, PokemonPalettes
+	add hl, bc
+	call Function818fd
+	ld a, $0
+	ld [wJumptableIndex], a
+	ret
+
+Jumptable_81d02:
+	dw Function81d0a
+	dw Function81d34
+	dw Function81d46
+	dw Function81d58
+
+Function81d0a:
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_DOWN
+	jr nz, Function81d89
+	ld a, [hl]
+	and D_LEFT
+	jr nz, .asm_81d1d
+	ld a, [hl]
+	and D_RIGHT
+	jr nz, .asm_81d28
+	ret
+
+.asm_81d1d
+	xor a
+	ld [wcf65], a
+	ld de, wc608
+	call Function81ea5
+	ret
+
+.asm_81d28
+	ld a, $1
+	ld [wcf65], a
+	ld de, wc608 + 2
+	call Function81ea5
+	ret
+
+Function81d34:
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_DOWN
+	jr nz, Function81d89
+	ld a, [hl]
+	and D_UP
+	jr nz, Function81d84
+	ld hl, wc608 + 10
+	jr Function81d63
+
+Function81d46:
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_DOWN
+	jr nz, Function81d89
+	ld a, [hl]
+	and D_UP
+	jr nz, Function81d84
+	ld hl, wc608 + 11
+	jr Function81d63
+
+Function81d58:
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_UP
+	jr nz, Function81d84
+	ld hl, wc608 + 12
+
+Function81d63:
+	ldh a, [hJoyLast]
+	and D_RIGHT
+	jr nz, Function81d70
+	ldh a, [hJoyLast]
+	and D_LEFT
+	jr nz, Function81d77
+	ret
+
+Function81d70:
+	ld a, [hl]
+	cp $1f
+	ret nc
+	inc [hl]
+	jr Function81d7b
+
+Function81d77:
+	ld a, [hl]
+	and a
+	ret z
+	dec [hl]
+
+Function81d7b:
+	call Function81e67
+	ld a, $2
+	ld [wJumptableIndex], a
+	ret
+
+Function81d84:
+	ld hl, wcf64
+	dec [hl]
+	ret
+
+Function81d89:
+	ld hl, wcf64
+	inc [hl]
+	ret
+
+Function81d8e:
+	hlcoord 0, 10
+	ld bc, $a0
+	ld a, DEBUGTEST_BLACK
+	call ByteFill
+	hlcoord 2, 12
+	ld de, String_81fcd
+	call PlaceString
+	xor a
+	ld [wd004], a
+	call Function81df4
+	ld a, $5
+	ld [wJumptableIndex], a
+	ret
+
+Function81daf:
+	ld hl, hJoyPressed
+	ld a, [hl]
+	and B_BUTTON
+	jr nz, .asm_81dbb
+	call Function81dc7
+	ret
+
+.asm_81dbb
+	ld a, $0
+	ld [wJumptableIndex], a
+	ret
+
+Function81dc1:
+	ld hl, wJumptableIndex
+	set 7, [hl]
+	ret
+
+Function81dc7:
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_UP
+	jr nz, .asm_81dd5
+	ld a, [hl]
+	and D_DOWN
+	jr nz, .asm_81de2
+	ret
+
+.asm_81dd5
+	ld a, [wd004]
+	cp $3b
+	jr z, .asm_81ddf
+	inc a
+	jr .asm_81ded
+
+.asm_81ddf
+	xor a
+	jr .asm_81ded
+
+.asm_81de2
+	ld a, [wd004]
+	and a
+	jr z, .asm_81deb
+	dec a
+	jr .asm_81ded
+
+.asm_81deb
+	ld a, $3b
+
+.asm_81ded
+	ld [wd004], a
+	call Function81df4
+	ret
+
+Function81df4:
+	hlcoord 10, 11
+	call Function81e5e
+	hlcoord 10, 12
+	call Function81e5e
+	hlcoord 10, 13
+	call Function81e5e
+	hlcoord 10, 14
+	call Function81e5e
+	ld a, [wd004]
+	inc a
+	ld [wTempTMHM], a
+	predef GetTMHMMove
+	ld a, [wTempTMHM]
+	ld [wPutativeTMHMMove], a
+	call GetMoveName
+	hlcoord 10, 12
+	call PlaceString
+	ld a, [wd004]
+	call Function81e55
+	ld [wCurItem], a
+	predef CanLearnTMHMMove
+	ld a, c
+	and a
+	ld de, String_81e46
+	jr nz, .asm_81e3f
+	ld de, String_81e4d
+
+.asm_81e3f
+	hlcoord 10, 14
+	call PlaceString
+	ret
+
+String_81e46: db "おぼえられる@" ; can be taught
+String_81e4d: db "おぼえられない@" ; cannot be taught
+
+Function81e55:
+	cp $32
+	jr c, .asm_81e5b
+	inc a
+	inc a
+
+.asm_81e5b
+	add $bf
+	ret
+
+Function81e5e:
+	ld bc, 10
+	ld a, DEBUGTEST_BLACK
+	call ByteFill
+	ret
+
+Function81e67:
+	ld a, [wc608 + 10]
+	and $1f
+	ld e, a
+	ld a, [wc608 + 11]
+	and $7
+	sla a
+	swap a
+	or e
+	ld e, a
+	ld a, [wc608 + 11]
+	and $18
+	sla a
+	swap a
+	ld d, a
+	ld a, [wc608 + 12]
+	and $1f
+	sla a
+	sla a
+	or d
+	ld d, a
+	ld a, [wcf65]
+	and a
+	jr z, .asm_81e9c
+	ld a, e
+	ld [wc608 + 2], a
+	ld a, d
+	ld [wc608 + 3], a
+	ret
+
+.asm_81e9c
+	ld a, e
+	ld [wc608], a
+	ld a, d
+	ld [wc608 + 1], a
+	ret
+
+Function81ea5:
+	ld a, [de]
+	and $1f
+	ld [wc608 + 10], a
+	ld a, [de]
+	and $e0
+	swap a
+	srl a
+	ld b, a
+	inc de
+	ld a, [de]
+	and $3
+	swap a
+	srl a
+	or b
+	ld [wc608 + 11], a
+	ld a, [de]
+	and $7c
+	srl a
+	srl a
+	ld [wc608 + 12], a
+	ret
+
+Function81eca:
+	ld a, [wcf66]
+	inc a
+	ld l, a
+	ld h, $0
+	add hl, hl
+	add hl, hl
+	ld de, wOverworldMapBlocks
+	add hl, de
+	ld e, l
+	ld d, h
+	ld hl, wc608
+	ld bc, 4
+	call CopyBytes
+	ret
+
+Function81ee3:
+.asm_81ee3
+	ld a, LOW(PALRGB_WHITE)
+	ld [hli], a
+	ld a, HIGH(PALRGB_WHITE)
+	ld [hli], a
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	inc de
+	ld [hli], a
+	ld a, [de]
+	inc de
+	ld [hli], a
+	xor a
+	ld [hli], a
+	ld [hli], a
+	dec c
+	jr nz, .asm_81ee3
+	ret
+
+DebugColor_FillBoxWithByte:
+; For some reason, we have another copy of FillBoxWithByte here
+.row
+	push bc
+	push hl
+.col
+	ld [hli], a
+	dec c
+	jr nz, .col
+	pop hl
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	pop bc
+	dec b
+	jr nz, .row
+	ret
+
+Function81f0c:
+	ld a, [wcfbe]
+	push af
+	set 7, a
+	ld [wcfbe], a
+	call Function81f1d
+	pop af
+	ld [wcfbe], a
+	ret
+
+Function81f1d:
+	ld a, [hl]
+	and $7
+	ret z
+	ld b, a
+.asm_81f22
+	push bc
+	xor a
+	ldh [rJOYP], a
+	ld a, $30
+	ldh [rJOYP], a
+	ld b, $10
+.asm_81f2c
+	ld e, $8
+	ld a, [hli]
+	ld d, a
+.asm_81f30
+	bit 0, d
+	ld a, $10
+	jr nz, .asm_81f38
+	ld a, $20
+
+.asm_81f38
+	ldh [rJOYP], a
+	ld a, $30
+	ldh [rJOYP], a
+	rr d
+	dec e
+	jr nz, .asm_81f30
+	dec b
+	jr nz, .asm_81f2c
+	ld a, $20
+	ldh [rJOYP], a
+	ld a, $30
+	ldh [rJOYP], a
+	ld de, 7000
+.asm_81f51
+	nop
+	nop
+	nop
+	dec de
+	ld a, d
+	or e
+	jr nz, .asm_81f51
+	pop bc
+	dec b
+	jr nz, .asm_81f22
+	ret
+
+Function81f5e:
+	ld a, DEBUGTEST_BLACK
+	hlcoord 10, 0
+	ld [hl], a
+	hlcoord 15, 0
+	ld [hl], a
+	hlcoord 1, 11
+	ld [hl], a
+	hlcoord 1, 13
+	ld [hl], a
+	hlcoord 1, 15
+	ld [hl], a
+	ld a, [wJumptableIndex]
+	cp $3
+	jr nz, .asm_81fc9
+	ld a, [wcf64]
+	and a
+	jr z, .asm_81f8d
+	dec a
+	hlcoord 1, 11
+	ld bc, 2 * SCREEN_WIDTH
+	call AddNTimes
+	ld [hl], $ed
+
+.asm_81f8d
+	ld a, [wcf65]
+	and a
+	jr z, .asm_81f98
+	hlcoord 15, 0
+	jr .asm_81f9b
+
+.asm_81f98
+	hlcoord 10, 0
+
+.asm_81f9b
+	ld [hl], $ed
+	ld b, $70
+	ld c, $5
+	ld hl, wVirtualOAM
+	ld de, wc608 + 10
+	call .asm_81fb7
+	ld de, wc608 + 11
+	call .asm_81fb7
+	ld de, wc608 + 12
+	call .asm_81fb7
+	ret
+
+.asm_81fb7
+	ld a, b
+	ld [hli], a ; y
+	ld a, [de]
+	add a
+	add a
+	add 3 * TILE_WIDTH
+	ld [hli], a ; x
+	xor a
+	ld [hli], a ; tile id
+	ld a, c
+	ld [hli], a ; attributes
+	ld a, 2 * TILE_WIDTH
+	add b
+	ld b, a
+	inc c
+	ret
+
+.asm_81fc9
+	call ClearSprites
+	ret
+
+String_81fcd:
+	db   "おわりますか?" ; Are you finished?
+	next "はい<DOT><DOT><DOT>", DEBUGTEST_A ; YES...(A)
+	next "いいえ<DOT><DOT>", DEBUGTEST_B ; NO..(B)
+	db   "@"
+
+DebugUpArrowGFX:
+INCBIN "gfx/debug/up_arrow.2bpp"
+
+DebugColorTestGFX:
+INCBIN "gfx/debug/color_test.2bpp"
+
+TilesetColorTest:
+	ret
+	xor a
+	ld [wJumptableIndex], a
+	ld [wcf64], a
+	ld [wcf65], a
+	ld [wcf66], a
+	ldh [hMapAnims], a
+	call ClearSprites
+	call OverworldTextModeSwitch
+	call WaitBGMap2
+	xor a
+	ldh [hBGMapMode], a
+	ld de, DebugColorTestGFX
+	ld hl, vTiles2 tile DEBUGTEST_TICKS_1
+	lb bc, BANK(DebugColorTestGFX), 22
+	call Request2bpp
+	ld de, DebugUpArrowGFX
+	ld hl, vTiles1
+	lb bc, BANK(DebugUpArrowGFX), 1
+	call Request2bpp
+	ld a, HIGH(vBGMap1)
+	ldh [hBGMapAddress + 1], a
+	hlcoord 0, 0
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, DEBUGTEST_BLACK
+	call ByteFill
+	hlcoord 0, 0, wAttrmap
+	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+	ld a, $7
+	call ByteFill
+	ld de, $15
+	ld a, DEBUGTEST_WHITE
+	call Function821d2
+	ld de, $1a
+	ld a, DEBUGTEST_LIGHT
+	call Function821d2
+	ld de, $1f
+	ld a, DEBUGTEST_DARK
+	call Function821d2
+	ld de, $24
+	ld a, DEBUGTEST_BLACK
+	call Function821d2
+	call Function821f4
+	call Function8220f
+	call WaitBGMap2
+	ld [wJumptableIndex], a
+	ld a, $40
+	ldh [hWY], a
+	ret
+
+Function821d2:
+	hlcoord 0, 0
+	call Function821de
+
+Function821d8:
+	ld a, [wcf64]
+	hlcoord 0, 0, wAttrmap
+
+Function821de:
+	add hl, de
+rept 4
+	ld [hli], a
+endr
+	ld bc, $10
+	add hl, bc
+rept 4
+	ld [hli], a
+endr
+	ld bc, $10
+	add hl, bc
+rept 4
+	ld [hli], a
+endr
+	ret
+
+Function821f4:
+	hlcoord 2, 4
+	call Function82203
+	hlcoord 2, 6
+	call Function82203
+	hlcoord 2, 8
+
+Function82203:
+	ld a, DEBUGTEST_TICKS_1
+	ld [hli], a
+	ld bc, $10 - 1
+	ld a, DEBUGTEST_TICKS_2
+	call ByteFill
+	ret
+
+Function8220f:
+	ldh a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals1)
+	ldh [rSVBK], a
+	ld a, [wcf64]
+	ld l, a
+	ld h, $0
+	add hl, hl
+	add hl, hl
+	add hl, hl
+	ld de, wBGPals1
+	add hl, de
+	ld de, wc608
+	ld bc, 8
+	call CopyBytes
+	ld de, wc608
+	call Function81ea5
+	pop af
+	ldh [rSVBK], a
+	ret
+
+Function82236:
+	ld hl, hJoyLast
+	ld a, [hl]
+	and SELECT
+	jr nz, .loop7
+	ld a, [hl]
+	and B_BUTTON
+	jr nz, .asm_82299
+	call Function822f0
+	ret
+
+.loop7
+	ld hl, wcf64
+	ld a, [hl]
+	inc a
+	and $7
+	cp $7
+	jr nz, .asm_82253
+	xor a
+
+.asm_82253
+	ld [hl], a
+	ld de, $15
+	call Function821d8
+	ld de, $1a
+	call Function821d8
+	ld de, $1f
+	call Function821d8
+	ld de, $24
+	call Function821d8
+	ldh a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals2)
+	ldh [rSVBK], a
+	ld hl, wBGPals2
+	ld a, [wcf64]
+	ld bc, 1 palettes
+	call AddNTimes
+	ld de, wc608
+	ld bc, 1 palettes
+	call CopyBytes
+	pop af
+	ldh [rSVBK], a
+	ld a, $2
+	ldh [hBGMapMode], a
+	ld c, 3
+	call DelayFrames
+	ld a, $1
+	ldh [hBGMapMode], a
+	ret
+
+.asm_82299
+	call ClearSprites
+	ldh a, [hWY]
+	xor $d0
+	ldh [hWY], a
+	ret
+
+Function822a3:
+	ldh a, [rSVBK]
+	push af
+	ld a, BANK(wBGPals2)
+	ldh [rSVBK], a
+	ld hl, wBGPals2
+	ld a, [wcf64]
+	ld bc, 1 palettes
+	call AddNTimes
+	ld e, l
+	ld d, h
+	ld hl, wc608
+	ld bc, 1 palettes
+	call CopyBytes
+	hlcoord 1, 0
+	ld de, wc608
+	call Function81ca7
+	hlcoord 6, 0
+	ld de, wc608 + 2
+	call Function81ca7
+	hlcoord 11, 0
+	ld de, wc608 + 4
+	call Function81ca7
+	hlcoord 16, 0
+	ld de, wc608 + 6
+	call Function81ca7
+	pop af
+	ldh [rSVBK], a
+	ld a, $1
+	ldh [hCGBPalUpdate], a
+	call DelayFrame
+	ret
+
+Function822f0:
+	ld a, [wcf65]
+	and 3
+	ld e, a
+	ld d, 0
+	ld hl, .dw
+	add hl, de
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp hl
+
+.dw
+	dw Function82309
+	dw Function82339
+	dw Function8234b
+	dw Function8235d
+
+Function82309:
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_DOWN
+	jr nz, Function8238c
+	ld a, [hl]
+	and D_LEFT
+	jr nz, .asm_8231c
+	ld a, [hl]
+	and D_RIGHT
+	jr nz, .asm_82322
+	ret
+
+.asm_8231c
+	ld a, [wcf66]
+	dec a
+	jr .asm_82326
+
+.asm_82322
+	ld a, [wcf66]
+	inc a
+
+.asm_82326
+	and $3
+	ld [wcf66], a
+	ld e, a
+	ld d, $0
+	ld hl, wc608
+	add hl, de
+	add hl, de
+	ld e, l
+	ld d, h
+	call Function81ea5
+	ret
+
+Function82339:
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_DOWN
+	jr nz, Function8238c
+	ld a, [hl]
+	and D_UP
+	jr nz, Function82387
+	ld hl, wc608 + 10
+	jr Function82368
+
+Function8234b:
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_DOWN
+	jr nz, Function8238c
+	ld a, [hl]
+	and D_UP
+	jr nz, Function82387
+	ld hl, wc608 + 11
+	jr Function82368
+
+Function8235d:
+	ld hl, hJoyLast
+	ld a, [hl]
+	and D_UP
+	jr nz, Function82387
+	ld hl, wc608 + 12
+
+Function82368:
+	ldh a, [hJoyLast]
+	and D_RIGHT
+	jr nz, .asm_82375
+	ldh a, [hJoyLast]
+	and D_LEFT
+	jr nz, .asm_8237c
+	ret
+
+.asm_82375
+	ld a, [hl]
+	cp $1f
+	ret nc
+	inc [hl]
+	jr .asm_82380
+
+.asm_8237c
+	ld a, [hl]
+	and a
+	ret z
+	dec [hl]
+
+.asm_82380
+	call Function82391
+	call Function822a3
+	ret
+
+Function82387:
+	ld hl, wcf65
+	dec [hl]
+	ret
+
+Function8238c:
+	ld hl, wcf65
+	inc [hl]
+	ret
+
+Function82391:
+	ld a, [wc608 + 10]
+	and $1f
+	ld e, a
+	ld a, [wc608 + 11]
+	and $7
+	sla a
+	swap a
+	or e
+	ld e, a
+	ld a, [wc608 + 11]
+	and $18
+	sla a
+	swap a
+	ld d, a
+	ld a, [wc608 + 12]
+	and $1f
+	sla a
+	sla a
+	or d
+	ld d, a
+	ld a, [wcf66]
+	ld c, a
+	ld b, $0
+	ld hl, wc608
+	add hl, bc
+	add hl, bc
+	ld a, e
+	ld [hli], a
+	ld [hl], d
+	ret
+
+Function823c6:
+	ret
+
+Function823c7:
+	ret
--- /dev/null
+++ b/engine/debug/debug_room.asm
@@ -1,0 +1,1762 @@
+	; _DebugRoom.MenuItems indexes
+	const_def
+	const DEBUGROOMMENU_PAGE_1 ; 0
+	const DEBUGROOMMENU_PAGE_2 ; 1
+	const DEBUGROOMMENU_PAGE_3 ; 2
+DEBUGROOMMENU_NUM_PAGES EQU const_value
+
+	; _DebugRoom.Strings and _DebugRoom.Jumptable indexes
+	const_def
+	const DEBUGROOMMENUITEM_SP_CLEAR     ; 00
+	const DEBUGROOMMENUITEM_WIN_WORK_CLR ; 01
+	const DEBUGROOMMENUITEM_POKEMON_GET  ; 02
+	const DEBUGROOMMENUITEM_POKEDEX_COMP ; 03
+	const DEBUGROOMMENUITEM_TIMER_RESET  ; 04
+	const DEBUGROOMMENUITEM_DECORATE_ALL ; 05
+	const DEBUGROOMMENUITEM_ITEM_GET     ; 06
+	const DEBUGROOMMENUITEM_RTC_EDIT     ; 07
+	const DEBUGROOMMENUITEM_NEXT         ; 08
+	const DEBUGROOMMENUITEM_GB_ID_SET    ; 09
+	const DEBUGROOMMENUITEM_BTL_REC_CLR  ; 0a
+	const DEBUGROOMMENUITEM_POKEDEX_CLR  ; 0b
+	const DEBUGROOMMENUITEM_HALT_CHK_CLR ; 0c
+	const DEBUGROOMMENUITEM_BATTLE_SKIP  ; 0d
+	const DEBUGROOMMENUITEM_HOF_CLEAR    ; 0e
+	const DEBUGROOMMENUITEM_ROM_CHECKSUM ; 0f
+	const DEBUGROOMMENUITEM_TEL_DEBUG    ; 10
+	const DEBUGROOMMENUITEM_SUM_RECALC   ; 11
+	const DEBUGROOMMENUITEM_RAM_FLAG_CLR ; 12
+	const DEBUGROOMMENUITEM_CHANGE_SEX   ; 13
+	const DEBUGROOMMENUITEM_BT_BUG_POKE  ; 14
+
+_DebugRoom:
+	ldh a, [hJoyDown]
+	and SELECT | START
+	cp SELECT | START
+	ret nz
+	ldh a, [hDebugRoomMenuPage]
+	push af
+	xor a
+	ldh [hDebugRoomMenuPage], a
+.loop
+	ld hl, wTilemap
+	ld bc, wTilemapEnd - wTilemap
+	ld a, " "
+	call ByteFill
+	call DebugRoom_PrintStackBottomTop
+	call DebugRoom_PrintWindowStackBottomTop
+	call DebugRoom_PrintRTCHaltChk
+	call DebugRoom_PrintBattleSkip
+	call DebugRoom_PrintTelDebug
+	call DebugRoom_PrintRAMFlag
+	call DebugRoom_PrintGender
+	ldh a, [hDebugRoomMenuPage]
+	ld [wWhichIndexSet], a
+	ld hl, .MenuHeader
+	call LoadMenuHeader
+	call SetUpMenu
+.wait
+	call GetScrollingMenuJoypad
+	ld a, [wMenuJoypad]
+	and A_BUTTON | B_BUTTON
+	jr z, .wait
+	call CloseWindow
+	cp B_BUTTON
+	jr z, .done
+	ld a, [wMenuSelection]
+	ld hl, .Jumptable
+	rst JumpTable
+	jr .loop
+.done
+	pop af
+	ldh [hDebugRoomMenuPage], a
+	ret
+
+.MenuHeader:
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 0, 0, 15, SCREEN_HEIGHT - 1
+	dw .MenuData
+	db 1 ; default option
+
+.MenuData:
+	db STATICMENU_CURSOR ; flags
+	db 0 ; items
+	dw .MenuItems
+	dw PlaceMenuStrings
+	dw .Strings
+
+.Strings:
+; entries correspond to DEBUGROOMMENUITEM_* constants
+	db "SP CLEAR@"
+	db "WIN WORK CLR@"
+	db "#MON GET!@"
+	db "#DEX COMP@"
+	db "TIMER RESET@"
+	db "DECORATE ALL@"
+	db "ITEM GET!@"
+	db "RTC EDIT@"
+	db "NEXT@"
+	db "GB ID SET@"
+	db "BTL REC CLR@"
+	db "#DEX CLR@"
+	db "HALT CHK CLR@"
+	db "BATTLE SKIP@"
+	db "HOF CLEAR@"
+	db "ROM CHECKSUM@"
+	db "TEL DEBUG@"
+	db "SUM RECALC@"
+	db "RAM FLAG CLR@"
+	db "CHANGE SEX@"
+	db "BT BUG POKE@"
+
+.Jumptable:
+; entries correspond to DEBUGROOMMENUITEM_* constants
+	dw DebugRoomMenu_SpClear
+	dw DebugRoomMenu_WinWorkClr
+	dw DebugRoomMenu_PokemonGet
+	dw DebugRoomMenu_PokedexComp
+	dw DebugRoomMenu_TimerReset
+	dw DebugRoomMenu_DecorateAll
+	dw DebugRoomMenu_ItemGet
+	dw DebugRoomMenu_RTCEdit
+	dw DebugRoomMenu_Next
+	dw DebugRoomMenu_GBIDSet
+	dw DebugRoomMenu_BtlRecClr
+	dw DebugRoomMenu_PokedexClr
+	dw DebugRoomMenu_HaltChkClr
+	dw DebugRoomMenu_BattleSkip
+	dw DebugRoomMenu_HOFClear
+	dw DebugRoomMenu_ROMChecksum
+	dw DebugRoomMenu_TelDebug
+	dw DebugRoomMenu_SumRecalc
+	dw DebugRoomMenu_RAMFlagClr
+	dw DebugRoomMenu_ChangeSex
+	dw DebugRoomMenu_BTBugPoke
+
+.MenuItems:
+; entries correspond to DEBUGROOMMENU_* constants
+
+	; DEBUGROOMMENU_PAGE_1
+	db 8
+	db DEBUGROOMMENUITEM_SP_CLEAR
+	db DEBUGROOMMENUITEM_BATTLE_SKIP
+	db DEBUGROOMMENUITEM_RTC_EDIT
+	db DEBUGROOMMENUITEM_TIMER_RESET
+	db DEBUGROOMMENUITEM_HALT_CHK_CLR
+	db DEBUGROOMMENUITEM_GB_ID_SET
+	db DEBUGROOMMENUITEM_BTL_REC_CLR
+	db DEBUGROOMMENUITEM_NEXT
+	db -1
+
+	; DEBUGROOMMENU_PAGE_2
+	db 8
+	db DEBUGROOMMENUITEM_POKEMON_GET
+	db DEBUGROOMMENUITEM_ITEM_GET
+	db DEBUGROOMMENUITEM_POKEDEX_COMP
+	db DEBUGROOMMENUITEM_POKEDEX_CLR
+	db DEBUGROOMMENUITEM_DECORATE_ALL
+	db DEBUGROOMMENUITEM_HOF_CLEAR
+	db DEBUGROOMMENUITEM_ROM_CHECKSUM
+	db DEBUGROOMMENUITEM_NEXT
+	db -1
+
+	; DEBUGROOMMENU_PAGE_3
+	db 6
+	db DEBUGROOMMENUITEM_TEL_DEBUG
+	db DEBUGROOMMENUITEM_SUM_RECALC
+	db DEBUGROOMMENUITEM_RAM_FLAG_CLR
+	db DEBUGROOMMENUITEM_CHANGE_SEX
+	db DEBUGROOMMENUITEM_BT_BUG_POKE
+	db DEBUGROOMMENUITEM_NEXT
+	db -1
+
+DebugRoomMenu_Next:
+	ldh a, [hDebugRoomMenuPage]
+	inc a
+	cp DEBUGROOMMENU_NUM_PAGES
+	jr c, .got_page
+	xor a ; DEBUGROOMMENU_PAGE_1
+.got_page
+	ldh [hDebugRoomMenuPage], a
+	ret
+
+DebugRoom_SaveChecksum:
+	ld a, BANK(sGameData)
+	call OpenSRAM
+	ld bc, sGameDataEnd - sGameData
+	ld de, 0
+	ld hl, sGameData
+.loop
+	ld a, [hli]
+	add e
+	ld e, a
+	ld a, d
+	adc 0
+	ld d, a
+	dec bc
+	ld a, b
+	or c
+	jr nz, .loop
+	ld a, e
+	ld [sChecksum + 0], a
+	ld a, d
+	ld [sChecksum + 1], a
+	call CloseSRAM
+	ret
+
+DebugRoomMenu_SpClear:
+	call YesNoBox
+	ret c
+	ld a, BANK(sStackTop)
+	call OpenSRAM
+	xor a
+	ld hl, sStackTop
+	ld [hli], a
+	ld [hl], a
+	call CloseSRAM
+	call DebugRoom_PrintStackBottomTop
+	ret
+
+DebugRoom_PrintStackBottomTop:
+	ld a, BANK(sStackTop)
+	call OpenSRAM
+	hlcoord 16, 14
+	ld de, sStackTop + 1
+	ld c, 1
+	call PrintHexNumber
+	ld de, sStackTop + 0
+	ld c, 1
+	call PrintHexNumber
+	call CloseSRAM
+	hlcoord 16, 12
+	ld de, .SPString
+	call PlaceString
+	ld d, LOW(wStackBottom)
+	ld e, HIGH(wStackBottom)
+	push de
+	ld hl, sp+0
+	ld d, h
+	ld e, l
+	hlcoord 16, 13
+	ld c, 2
+	call PrintHexNumber
+	pop de
+	ret
+
+.SPString:
+	db "SP:@"
+
+DebugRoomMenu_WinWorkClr:
+	call YesNoBox
+	ret c
+	ld a, [wWindowStackPointer]
+	ld l, a
+	ld a, [wWindowStackPointer + 1]
+	ld h, a
+	inc hl
+	ld a, l
+	sub LOW(wWindowStack)
+	ld a, h
+	sbc HIGH(wWindowStack)
+	ret c
+	ld a, $00
+	call OpenSRAM
+	ld bc, -wWindowStack + $10000
+	add hl, bc
+	ld b, h
+	ld c, l
+	ld hl, wWindowStack
+	xor a
+	call ByteFill
+	call CloseSRAM
+	ret
+
+DebugRoom_PrintWindowStackBottomTop:
+	ret ; stubbed out
+
+	ld a, $00
+	call OpenSRAM
+	ld hl, wWindowStack
+.loop
+	ld a, h
+	cp $c0
+	jr z, .ok
+	ld a, [hl]
+	or a
+	jr nz, .ok
+	inc hl
+	jr .loop
+.ok
+	call CloseSRAM
+	ld a, h
+	ld h, l
+	ld l, a
+	push hl
+	ld hl, sp+0
+	ld d, h
+	ld e, l
+	hlcoord 16, 17
+	ld c, 2
+	call PrintHexNumber
+	pop hl
+	ld d, LOW(wWindowStack)
+	ld e, HIGH(wWindowStack)
+	push de
+	ld hl, sp+0
+	ld d, h
+	ld e, l
+	hlcoord 16, 16
+	ld c, 2
+	call PrintHexNumber
+	pop de
+	hlcoord 16, 15
+	ld de, .WSPString
+	call PlaceString
+	ret
+
+.WSPString:
+	db "WSP:@"
+
+DebugRoomMenu_PokedexComp:
+	call YesNoBox
+	ret c
+	ld a, BANK(sGameData) ; aka BANK(sPlayerData)
+	call OpenSRAM
+	ld hl, sPlayerData + (wPokedexCaught - wPlayerData)
+	ld b, wEndPokedexSeen - wPokedexCaught
+	ld a, %11111111
+.loop1
+	ld [hli], a
+	dec b
+	jr nz, .loop1
+	ld a, (1 << (NUM_POKEMON % 8)) - 1 ; %00000111
+	ld [sPlayerData + (wEndPokedexCaught - 1 - wPlayerData)], a
+	ld [sPlayerData + (wEndPokedexSeen - 1 - wPlayerData)], a
+	ld hl, sPlayerData + (wStatusFlags - wPlayerData)
+	set STATUSFLAGS_UNOWN_DEX_F, [hl]
+	ld a, UNOWN_A
+	ld [sGameData + (wFirstUnownSeen - wGameData)], a
+	ld hl, sGameData + (wUnownDex - wGameData)
+	ld b, NUM_UNOWN
+.loop2
+	ld [hli], a
+	inc a
+	dec b
+	jr nz, .loop2
+	call CloseSRAM
+	call DebugRoom_SaveChecksum
+	ret
+
+DebugRoomMenu_PokedexClr:
+	call YesNoBox
+	ret c
+	ld a, BANK(sPlayerData)
+	call OpenSRAM
+	ld hl, sPlayerData + (wStatusFlags - wPlayerData)
+	res STATUSFLAGS_UNOWN_DEX_F, [hl]
+	ld hl, sPlayerData + (wPokedexCaught - wPlayerData)
+	ld bc, wEndPokedexSeen - wPokedexCaught
+	xor a
+	call ByteFill
+	ld hl, sGameData + (wUnownDex - wGameData)
+	ld bc, NUM_UNOWN
+	xor a
+	call ByteFill
+	call CloseSRAM
+	call DebugRoom_SaveChecksum
+	ret
+
+DebugRoomMenu_TimerReset:
+	call YesNoBox
+	ret c
+	ld a, BANK(sRTCStatusFlags)
+	call OpenSRAM
+	ld hl, sRTCStatusFlags
+	set 7, [hl]
+	call CloseSRAM
+	ret
+
+DebugRoomMenu_BattleSkip:
+	ld a, BANK(sSkipBattle)
+	call OpenSRAM
+	ld a, [sSkipBattle]
+	inc a
+	and 1
+	ld [sSkipBattle], a
+	call CloseSRAM
+	ret
+
+DebugRoom_PrintBattleSkip:
+	hlcoord 16, 6
+	ld de, .BTLString
+	call PlaceString
+	ld a, BANK(sSkipBattle)
+	call OpenSRAM
+	ld a, [sSkipBattle]
+	call CloseSRAM
+	hlcoord 16, 7
+	ld de, .DoString
+	or a
+	jr z, .ok
+	ld de, .SkipString
+.ok
+	call PlaceString
+	ret
+
+.BTLString:
+	db "BTL:@"
+.DoString:
+	db "  DO@"
+.SkipString:
+	db "SKIP@"
+
+DebugRoomMenu_ChangeSex:
+	ld a, BANK(sCrystalData)
+	call OpenSRAM
+	ld a, [sCrystalData + (wPlayerGender - wCrystalData)]
+	inc a
+	and 1
+	ld [sCrystalData + (wPlayerGender - wCrystalData)], a
+	call CloseSRAM
+	ret
+
+DebugRoom_PrintGender:
+	hlcoord 16, 0
+	ld de, .SexString
+	call PlaceString
+	ld a, BANK(sCrystalData)
+	call OpenSRAM
+	ld a, [sCrystalData + (wPlayerGender - wCrystalData)]
+	call CloseSRAM
+	or a
+	ld a, "♂"
+	jr z, .ok
+	ld a, "♀"
+.ok
+	hlcoord 19, 1
+	ld [hl], a
+	ret
+
+.SexString:
+	db "SEX:@"
+
+DebugRoomMenu_TelDebug:
+	ld a, BANK(sDebugTimeCyclesSinceLastCall)
+	call OpenSRAM
+	ld a, [sDebugTimeCyclesSinceLastCall]
+	inc a
+	cp 3
+	jr c, .ok
+	xor a
+.ok
+	ld [sDebugTimeCyclesSinceLastCall], a
+	call CloseSRAM
+	ret
+
+DebugRoom_PrintTelDebug:
+	hlcoord 16, 16
+	ld de, .TelString
+	call PlaceString
+	ld a, BANK(sDebugTimeCyclesSinceLastCall)
+	call OpenSRAM
+	ld a, [sDebugTimeCyclesSinceLastCall]
+	call CloseSRAM
+	hlcoord 16, 17
+	ld de, .BusyString
+	dec a
+	jr z, .ok
+	ld de, .HardString
+	dec a
+	jr z, .ok
+	ld de, .OffString
+.ok
+	call PlaceString
+	ret
+
+.TelString:
+	db "TEL:@"
+.OffString:
+	db " OFF@"
+.BusyString:
+	db "BUSY@"
+.HardString:
+	db "HARD@"
+
+DebugRoomMenu_RAMFlagClr:
+	call YesNoBox
+	ret c
+	ld a, BANK(sOpenedInvalidSRAM)
+	call OpenSRAM
+	xor a
+	ld [sOpenedInvalidSRAM], a
+	call CloseSRAM
+	ret
+
+DebugRoom_PrintRAMFlag:
+	ld a, BANK(sOpenedInvalidSRAM)
+	call OpenSRAM
+	ld de, sOpenedInvalidSRAM
+	hlcoord 18, 4
+	ld c, 1
+	call PrintHexNumber
+	call CloseSRAM
+	hlcoord 16, 3
+	ld de, .RamString
+	call PlaceString
+	ret
+
+.RamString:
+	db "RAM:@"
+
+DebugRoomMenu_SumRecalc:
+	call YesNoBox
+	ret c
+	call DebugRoom_SaveChecksum
+	ret
+
+DebugRoomMenu_DecorateAll:
+	call YesNoBox
+	ret c
+	ld a, BANK(sPlayerData)
+	call OpenSRAM
+	ld hl, sPlayerData + (wEventFlags - wPlayerData)
+	ld de, EVENT_DECO_BED_1 ; the first EVENT_DECO_* constant
+	ld b, SET_FLAG
+	ld c, EVENT_DECO_BIG_LAPRAS_DOLL - EVENT_DECO_BED_1 + 1
+.loop
+	push bc
+	push de
+	push hl
+	call FlagAction
+	pop hl
+	pop de
+	pop bc
+	inc de
+	dec c
+	jr nz, .loop
+	call CloseSRAM
+	call DebugRoom_SaveChecksum
+	ret
+
+paged_value: MACRO
+	dw \1 ; value address
+	db \2 ; min value
+	db \3 ; max value
+	db \4 ; initial value
+	dw \5 ; label string
+	dw \6 ; value name function
+	db \7 ; is hex value?
+ENDM
+
+PAGED_VALUE_SIZE EQU 10
+
+DebugRoom_EditPagedValues:
+	xor a
+	ld [wDebugRoomCurPage], a
+	ld [wDebugRoomCurValue], a
+	ld a, [hli]
+	ld [wDebugRoomAFunction], a
+	ld a, [hli]
+	ld [wDebugRoomAFunction+1], a
+	ld a, [hli]
+	ld [wDebugRoomSelectFunction], a
+	ld a, [hli]
+	ld [wDebugRoomSelectFunction+1], a
+	ld a, [hli]
+	ld [wDebugRoomStartFunction], a
+	ld a, [hli]
+	ld [wDebugRoomStartFunction+1], a
+	ld a, [hli]
+	ld [wDebugRoomAutoFunction], a
+	ld a, [hli]
+	ld [wDebugRoomAutoFunction+1], a
+	ld a, [hli]
+	ld [wDebugRoomPageCount], a
+	ld a, l
+	ld [wDebugRoomPagedValuesPtr], a
+	ld a, h
+	ld [wDebugRoomPagedValuesPtr+1], a
+	ld hl, hInMenu
+	ld a, [hl]
+	push af
+	ld [hl], TRUE
+	call ClearBGPalettes
+	hlcoord 0, 0
+	ld b, SCREEN_HEIGHT - 2
+	ld c, SCREEN_WIDTH - 2
+	call Textbox
+	hlcoord 8, 17
+	ld de, DebugRoom_PageString
+	call PlaceString
+	call DebugRoom_InitializePagedValues
+	xor a
+	call DebugRoom_PrintPage
+	ld a, "▶"
+	call DebugRoom_ShowHideCursor
+	xor a
+	ldh [hJoyLast], a
+	xor a
+	ld [wDebugRoomCurPage], a
+	inc a
+	ldh [hBGMapMode], a
+	call WaitBGMap
+	ld b, SCGB_DIPLOMA
+	call GetSGBLayout
+	call SetPalettes
+.resume
+	call DelayFrame
+	call JoyTextDelay
+	ldh a, [hJoyLast]
+	bit 1, a
+	jr nz, .done
+	ld hl, .continue
+	push hl
+	rra ; A_BUTTON_F?
+	jr c, DebugRoom_PagedValuePressedA
+	rra ; skip B_BUTTON_F
+	rra ; SELECT_F?
+	jr c, DebugRoom_PagedValuePressedSelect
+	rra ; START_F?
+	jr c, DebugRoom_PagedValuePressedStart
+	rra ; D_RIGHT_F?
+	jp c, DebugRoom_IncrementPagedValue
+	rra ; D_LEFT_F?
+	jp c, DebugRoom_DecrementPagedValue
+	rra ; D_UP_F?
+	jp c, DebugRoom_PrevPagedValue
+	rra ; D_DOWN_F?
+	jp c, DebugRoom_NextPagedValue
+	pop hl
+.continue
+; call wDebugRoomAutoFunction if it's not null, then jump to .resume
+	ld hl, .resume
+	push hl
+	ld a, [wDebugRoomAutoFunction]
+	ld l, a
+	ld a, [wDebugRoomAutoFunction+1]
+	ld h, a
+	or l
+	ret z
+	jp hl
+
+.done
+	pop af
+	ldh [hInMenu], a
+	scf
+	ret
+
+DebugRoom_PagedValuePressedA:
+	ld hl, wDebugRoomAFunction
+	jr _CallNonNullPointer
+
+DebugRoom_PagedValuePressedSelect:
+	ld hl, wDebugRoomSelectFunction
+	jr _CallNonNullPointer
+
+DebugRoom_PagedValuePressedStart:
+	ld hl, wDebugRoomStartFunction
+	; fallthrough
+
+_CallNonNullPointer:
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	or h
+	ret z
+	jp hl
+
+DebugRoom_PageString:
+	db " P  @"
+
+DebugRoom_IncrementPagedValue:
+	call DebugRoom_GetCurPagedValuePtr
+	ld e, [hl] ; de = value address
+	inc hl
+	ld d, [hl]
+	inc hl
+	inc hl
+	ld a, [de] ; a = max value
+	cp [hl]
+	ret z
+	inc a
+	ld [de], a
+	call DebugRoom_PrintPageBValueC
+	ret
+
+DebugRoom_DecrementPagedValue:
+	call DebugRoom_GetCurPagedValuePtr
+	ld e, [hl] ; de = value address
+	inc hl
+	ld d, [hl]
+	inc hl
+	ld a, [de] ; a = min value
+	cp [hl]
+	ret z
+	dec a
+	ld [de], a
+	call DebugRoom_PrintPageBValueC
+	ret
+
+DebugRoom_NextPage:
+	ld a, [wDebugRoomPageCount]
+	ld c, a
+	ld a, [wDebugRoomCurPage]
+	inc a
+	cp c
+	jr c, .ok
+	xor a
+.ok
+	ld [wDebugRoomCurPage], a
+	call DebugRoom_PrintPage
+	ld a, [wDebugRoomCurPage]
+	call DebugRoom_GetNthPagePtr
+	ld a, [wDebugRoomCurValue]
+	cp [hl]
+	jr c, .skip
+	ld a, [hl]
+	dec a
+	ld [wDebugRoomCurValue], a
+.skip
+	ld a, "▶"
+	call DebugRoom_ShowHideCursor
+	ret
+
+DebugRoom_PrevPage:
+	ld a, [wDebugRoomCurPage]
+	or a
+	jr nz, .ok
+	ld a, [wDebugRoomPageCount]
+.ok
+	dec a
+	ld [wDebugRoomCurPage], a
+	call DebugRoom_PrintPage
+	ld a, [wDebugRoomCurPage]
+	call DebugRoom_GetNthPagePtr
+	ld a, [wDebugRoomCurValue]
+	cp [hl]
+	jr c, .skip
+	ld a, [hl]
+	dec a
+	ld [wDebugRoomCurValue], a
+.skip
+	ld a, "▶"
+	call DebugRoom_ShowHideCursor
+	ret
+
+DebugRoom_NextPagedValue:
+	ld a, " "
+	call DebugRoom_ShowHideCursor
+	ld a, [wDebugRoomCurPage]
+	call DebugRoom_GetNthPagePtr
+	ld a, [wDebugRoomCurValue]
+	inc a
+	cp [hl] ; incremented value < paged_value count?
+	jr c, DebugRoom_UpdateValueCursor
+	xor a
+	ld [wDebugRoomCurValue], a
+	jr DebugRoom_NextPage
+
+DebugRoom_UpdateValueCursor:
+	ld [wDebugRoomCurValue], a
+	ld a, "▶"
+	call DebugRoom_ShowHideCursor
+	ret
+
+DebugRoom_PrevPagedValue:
+	ld a, " "
+	call DebugRoom_ShowHideCursor
+	ld a, [wDebugRoomCurValue]
+	or a ; pre-decremented value > 0?
+	jr nz, .decrement
+	ld a, -1
+	ld [wDebugRoomCurValue], a
+	jr DebugRoom_PrevPage
+
+.decrement:
+	dec a
+	jr DebugRoom_UpdateValueCursor
+
+DebugRoom_GetNthPagePtr:
+; Input: a = page index
+; Output: hl = pointer to paged_data list
+	ld h, 0
+	ld l, a
+	add hl, hl
+	ld a, [wDebugRoomPagedValuesPtr]
+	ld e, a
+	ld a, [wDebugRoomPagedValuesPtr+1]
+	ld d, a
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ret
+
+_DebugRoom_GetPageBValueCPtr:
+	push bc
+	ld a, b
+	call DebugRoom_GetNthPagePtr
+	pop bc
+	inc hl
+	ld a, c
+	ld bc, PAGED_VALUE_SIZE
+	call AddNTimes
+	ret
+
+DebugRoom_GetCurPagedValuePtr:
+	ld a, [wDebugRoomCurPage]
+	ld b, a
+	ld a, [wDebugRoomCurValue]
+	ld c, a
+	jr _DebugRoom_GetPageBValueCPtr
+
+DebugRoom_ShowHideCursor:
+	push af
+	hlcoord 1, 1
+	ld bc, SCREEN_WIDTH * 2
+	ld a, [wDebugRoomCurValue]
+	call AddNTimes
+	pop af
+	ld [hl], a
+	ret
+
+DebugRoom_InitializePagedValues:
+; Load the initial values for all pages of the current paged value header
+	ld a, [wDebugRoomPageCount]
+.page_loop
+	dec a
+	push af
+	call .InitializePage
+	pop af
+	jr nz, .page_loop
+	ret
+
+.InitializePage:
+; Load the initial values for page a
+	ld b, a
+	ld h, 0
+	ld l, a
+	add hl, hl
+	ld a, [wDebugRoomPagedValuesPtr]
+	ld e, a
+	ld a, [wDebugRoomPagedValuesPtr+1]
+	ld d, a
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld c, [hl] ; c = paged_value count
+.value_loop
+	push bc
+	dec c
+	call .InitializeValue
+	pop bc
+	dec c
+	jr nz, .value_loop
+	ret
+
+.InitializeValue:
+; Load the initial value for page b, value c
+	ld h, 0
+	ld l, b
+	add hl, hl
+	ld a, [wDebugRoomPagedValuesPtr]
+	ld e, a
+	ld a, [wDebugRoomPagedValuesPtr+1]
+	ld d, a
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	inc hl ; skip the paged_value count
+	ld a, c
+	push bc
+	ld bc, PAGED_VALUE_SIZE
+	call AddNTimes
+	pop bc
+	ld e, [hl] ; de = value address
+	inc hl
+	ld d, [hl]
+	inc hl
+	inc hl
+	inc hl
+	ld a, [hl] ; a = initial value
+	ld [de], a
+	ret
+
+DebugRoom_PrintPage:
+	push af
+	hlcoord 10, 17
+	add "1"
+	ld [hl], a
+	hlcoord 1, 1
+	lb bc, SCREEN_HEIGHT - 2, SCREEN_WIDTH - 2
+	call ClearBox
+	pop af
+	ld b, a
+	ld h, 0
+	ld l, a
+	add hl, hl
+	ld a, [wDebugRoomPagedValuesPtr]
+	ld e, a
+	ld a, [wDebugRoomPagedValuesPtr+1]
+	ld d, a
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld c, [hl] ; c = paged_value count
+.loop
+	push bc
+	dec c
+	call DebugRoom_PrintPagedValue
+	pop bc
+	dec c
+	jr nz, .loop
+	ret
+
+DebugRoom_PrintPageBValueC:
+	ld a, [wDebugRoomCurPage]
+	ld b, a
+	ld a, [wDebugRoomCurValue]
+	ld c, a
+	jr DebugRoom_PrintPagedValue
+
+DebugRoom_PrintPagedValue:
+; Print the value for page b, value c
+	ld h, 0
+	ld l, b
+	add hl, hl
+	ld a, [wDebugRoomPagedValuesPtr]
+	ld e, a
+	ld a, [wDebugRoomPagedValuesPtr+1]
+	ld d, a
+	add hl, de
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	inc hl ; skip the paged_value count
+	ld a, c
+	push bc
+	ld bc, PAGED_VALUE_SIZE
+	call AddNTimes
+	pop bc
+	ld e, [hl] ; de = value address
+	inc hl
+	ld d, [hl]
+	inc hl
+	push de
+	inc hl
+	inc hl
+	inc hl
+	ld e, [hl] ; de = label string
+	inc hl
+	ld d, [hl]
+	inc hl
+	push hl
+	hlcoord 2, 1
+	ld a, c
+	ld bc, SCREEN_WIDTH * 2
+	call AddNTimes
+	push hl
+	call PlaceString
+	pop hl
+	ld bc, SCREEN_WIDTH - 7
+	add hl, bc
+	pop bc ; pushed hl
+	pop de
+	push de
+	push bc
+	inc bc
+	inc bc
+	ld a, [bc] ; a = is hex value?
+	or a
+	jr nz, .hex
+	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
+	call PrintNum
+	jr .printed
+.hex
+	ld c, 1
+	call PrintHexNumber
+	ld [hl], "H"
+	inc hl
+.printed
+	ld bc, 6
+	add hl, bc
+	ld b, h
+	ld c, l
+	pop hl
+	pop de
+	ld a, [hli] ; hl = value name function
+	ld h, [hl]
+	ld l, a
+	or h
+	ret z
+	ld a, [de]
+	jp hl
+
+DebugRoom_JoyWaitABSelect:
+.loop
+	call GetJoypad
+	ldh a, [hJoyPressed]
+	and A_BUTTON | B_BUTTON | SELECT
+	jr z, .loop
+	ret
+
+DebugRoomMenu_ItemGet:
+	ld hl, .PagedValuesHeader
+	call DebugRoom_EditPagedValues
+	ret
+
+.PagedValuesHeader:
+	dw NULL ; A function
+	dw NULL ; Select function
+	dw DebugRoom_SaveItem ; Start function
+	dw NULL ; Auto function
+	db 1 ; # pages
+	dw DebugRoomMenu_ItemGet_Page1Values
+
+DebugRoom_SaveItem:
+	call YesNoBox
+	ret c
+	ld a, BANK(sPlayerData)
+	call OpenSRAM
+	ld hl, sPlayerData + (wPCItems - wPlayerData)
+	ld a, [wDebugRoomItemID]
+	ld c, a
+.loop1
+	ld a, [hl]
+	cp c
+	jr z, .found
+	cp -1
+	jr z, .not_found
+	inc hl
+	inc hl
+	jr .loop1
+
+.found
+	inc hl
+	ld a, [wDebugRoomItemQuantity]
+	add [hl]
+	cp MAX_ITEM_STACK + 1
+	jr c, .max
+	ld a, MAX_ITEM_STACK
+.max
+	ld [hl], a
+	ld hl, .ItemNumberAddedText
+	jr .done
+
+.not_found
+	ld a, [sPlayerData + (wNumPCItems - wPlayerData)]
+	cp MAX_PC_ITEMS
+	jr nc, .full
+	inc a
+	ld [sPlayerData + (wNumPCItems - wPlayerData)], a
+	ld a, [wDebugRoomItemID]
+	ld [hli], a
+	ld a, [wDebugRoomItemQuantity]
+	ld [hli], a
+	ld [hl], -1 ; terminator
+	ld hl, .CreatedNewItemText
+	jr .done
+
+.full
+	ld hl, .StockFullText
+.done
+	call CloseSRAM
+	call MenuTextbox
+	call DebugRoom_JoyWaitABSelect
+	call CloseWindow
+	call DebugRoom_SaveChecksum
+	ret
+
+.ItemNumberAddedText:
+	text "Item number added!"
+	done
+
+.CreatedNewItemText:
+	text "Created new item!"
+	done
+
+.StockFullText:
+	text "Stock full!!"
+	done
+
+DebugRoom_PrintItemName:
+	ld [wNamedObjectIndexBuffer], a
+	push bc
+	call GetItemName
+	pop hl
+	push hl
+	lb bc, 1, 12
+	call ClearBox
+	pop hl
+	ld de, wStringBuffer1
+	call PlaceString
+	ret
+
+DebugRoomMenu_ItemGet_Page1Values:
+	db 2
+	paged_value wDebugRoomItemID,       1, NUM_POKEMON, MASTER_BALL, .ItemNameString, DebugRoom_PrintItemName, FALSE
+	paged_value wDebugRoomItemQuantity, 1, 99,          1,           .NumberString,   NULL,                    FALSE
+
+.ItemNameString: db "ITEM NAME@"
+.NumberString:   db "NUMBER@"
+
+DebugRoomMenu_PokemonGet:
+	ld hl, .PagedValuesHeader
+	call DebugRoom_EditPagedValues
+	ret
+
+.PagedValuesHeader:
+	dw NULL ; A function
+	dw NULL ; Select function
+	dw DebugRoom_SavePokemon ; Start function
+	dw NULL ; Auto function
+	db 4 ; # pages
+	dw DebugRoomMenu_PokemonGet_Page1Values
+	dw DebugRoomMenu_PokemonGet_Page2Values
+	dw DebugRoomMenu_PokemonGet_Page3Values
+	dw DebugRoomMenu_PokemonGet_Page4Values
+
+DebugRoom_SavePokemon:
+	call YesNoBox
+	ret c
+	call DebugRoom_UpdateExpForLevel
+	ld a, [wDebugRoomMonBox]
+	dec a
+	ld b, a
+	add a
+	add b
+	ld h, 0
+	ld l, a
+	ld de, DebugRoom_BoxAddresses
+	add hl, de
+	ld a, [hli]
+	call OpenSRAM
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	ld a, [hl]
+	cp MONS_PER_BOX
+	jr nc, .full
+	; update count and species list
+	push hl
+	inc [hl]
+	inc hl
+	ld d, 0
+	ld e, a
+	add hl, de
+	ld a, [wDebugRoomMonSpecies]
+	ld [hli], a
+	ld [hl], -1
+	pop hl
+	; skip count and species list
+	ld bc, 2 + MONS_PER_BOX
+	add hl, bc
+	; update Nth box mon
+	push de
+	push hl
+	ld a, e
+	ld bc, BOXMON_STRUCT_LENGTH
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ld hl, wDebugRoomMon
+	ld bc, BOXMON_STRUCT_LENGTH
+	call CopyBytes
+	pop hl
+	pop de
+	; skip box mons
+	ld bc, BOXMON_STRUCT_LENGTH * MONS_PER_BOX
+	add hl, bc
+	; update Nth OT name
+	push de
+	push hl
+	ld a, e
+	ld bc, NAME_LENGTH
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ld hl, .OTString
+	ld bc, NAME_LENGTH
+	call CopyBytes
+	pop hl
+	pop de
+	; skip OT names
+	ld bc, NAME_LENGTH * MONS_PER_BOX
+	add hl, bc
+	; update Nth nickname
+	push de
+	push hl
+	ld a, e
+	ld bc, MON_NAME_LENGTH
+	call AddNTimes
+	ld d, h
+	ld e, l
+	ld hl, .NicknameString
+	ld bc, MON_NAME_LENGTH
+	call CopyBytes
+	pop hl
+	pop de
+	call CloseSRAM
+	ld hl, .CompletedText
+	call MenuTextbox
+	call DebugRoom_JoyWaitABSelect
+	call CloseWindow
+	ret
+
+.full
+	call CloseSRAM
+	ld hl, .BoxIsFullText
+	call MenuTextbox
+	call DebugRoom_JoyWaitABSelect
+	call CloseWindow
+	ret
+
+.OTString:
+	db "DEBUG▶OT@"
+
+.NicknameString:
+	db "DEBUG▶<PK><MN>@"
+
+.CompletedText:
+	text "COMPLETED!"
+	done
+
+.BoxIsFullText:
+	text "BOX IS FULL!"
+	done
+
+DebugRoom_PrintPokemonName:
+	ld [wNamedObjectIndexBuffer], a
+	push bc
+	call GetPokemonName
+	jr _DebugRoom_FinishGetName
+
+DebugRoom_PrintItemName2:
+	ld [wNamedObjectIndexBuffer], a
+	push bc
+	call GetItemName
+	jr _DebugRoom_FinishGetName
+
+DebugRoom_PrintMoveName:
+	ld [wNamedObjectIndexBuffer], a
+	push bc
+	call GetMoveName
+	jr _DebugRoom_FinishGetName
+
+_DebugRoom_FinishGetName:
+	pop hl
+	push hl
+	lb bc, 1, 12
+	call ClearBox
+	pop hl
+	ld de, wStringBuffer1
+	call PlaceString
+	ret
+
+DebugRoom_UpdateExpForLevel:
+	ld hl, BaseData + BASE_GROWTH_RATE
+	ld bc, BASE_DATA_SIZE
+	ld a, [wDebugRoomMonSpecies]
+	dec a
+	call AddNTimes
+	ld a, BANK(BaseData)
+	call GetFarByte
+	ld [wBaseGrowthRate], a
+	ld a, [wDebugRoomMonLevel]
+	ld d, a
+	farcall CalcExpAtLevel
+	ld hl, wDebugRoomMonExp
+	ldh a, [hProduct + 1]
+	ld [hli], a
+	ldh a, [hProduct + 2]
+	ld [hli], a
+	ldh a, [hProduct + 3]
+	ld [hl], a
+	ret
+
+DebugRoomMenu_PokemonGet_Page1Values:
+	db 8
+	paged_value wDebugRoomMonSpecies,       1,   NUM_POKEMON, BULBASAUR,      DebugRoom_BoxStructStrings.Pokemon,   DebugRoom_PrintPokemonName, FALSE
+	paged_value wDebugRoomMonItem,          1,   $ff,         MASTER_BALL,    DebugRoom_BoxStructStrings.Item,      DebugRoom_PrintItemName2,   FALSE
+	paged_value wDebugRoomMonMoves+0,       1,   NUM_ATTACKS, POUND,          DebugRoom_BoxStructStrings.Move1,     DebugRoom_PrintMoveName,    FALSE
+	paged_value wDebugRoomMonMoves+1,       1,   NUM_ATTACKS, POUND,          DebugRoom_BoxStructStrings.Move2,     DebugRoom_PrintMoveName,    FALSE
+	paged_value wDebugRoomMonMoves+2,       1,   NUM_ATTACKS, POUND,          DebugRoom_BoxStructStrings.Move3,     DebugRoom_PrintMoveName,    FALSE
+	paged_value wDebugRoomMonMoves+3,       1,   NUM_ATTACKS, POUND,          DebugRoom_BoxStructStrings.Move4,     DebugRoom_PrintMoveName,    FALSE
+	paged_value wDebugRoomMonID+0,          $00, $ff,         HIGH(1234),     DebugRoom_BoxStructStrings.ID0,       NULL,                       FALSE
+	paged_value wDebugRoomMonID+1,          $00, $ff,         LOW(1234),      DebugRoom_BoxStructStrings.ID1,       NULL,                       FALSE
+
+DebugRoomMenu_PokemonGet_Page2Values:
+	db 8
+	paged_value wDebugRoomMonHPExp+0,       $00, $ff,         $00,            DebugRoom_BoxStructStrings.HPExp0,    NULL,                       FALSE
+	paged_value wDebugRoomMonHPExp+1,       $00, $ff,         $00,            DebugRoom_BoxStructStrings.HPExp1,    NULL,                       FALSE
+	paged_value wDebugRoomMonAtkExp+0,      $00, $ff,         $00,            DebugRoom_BoxStructStrings.AttkExp0,  NULL,                       FALSE
+	paged_value wDebugRoomMonAtkExp+1,      $00, $ff,         $00,            DebugRoom_BoxStructStrings.AttkExp1,  NULL,                       FALSE
+	paged_value wDebugRoomMonDefExp+0,      $00, $ff,         $00,            DebugRoom_BoxStructStrings.DfnsExp0,  NULL,                       FALSE
+	paged_value wDebugRoomMonDefExp+1,      $00, $ff,         $00,            DebugRoom_BoxStructStrings.DfnsExp1,  NULL,                       FALSE
+	paged_value wDebugRoomMonSpdExp+0,      $00, $ff,         $00,            DebugRoom_BoxStructStrings.SpeedExp0, NULL,                       FALSE
+	paged_value wDebugRoomMonSpdExp+1,      $00, $ff,         $00,            DebugRoom_BoxStructStrings.SpeedExp1, NULL,                       FALSE
+
+DebugRoomMenu_PokemonGet_Page3Values:
+	db 8
+	paged_value wDebugRoomMonSpcExp+0,      $00, $ff,         $00,            DebugRoom_BoxStructStrings.SpclExp0,  NULL,                       FALSE
+	paged_value wDebugRoomMonSpcExp+1,      $00, $ff,         $00,            DebugRoom_BoxStructStrings.SpclExp1,  NULL,                       FALSE
+	paged_value wDebugRoomMonDVs+0,         $00, $ff,         $00,            DebugRoom_BoxStructStrings.PowerRnd0, NULL,                       TRUE
+	paged_value wDebugRoomMonDVs+1,         $00, $ff,         $00,            DebugRoom_BoxStructStrings.PowerRnd1, NULL,                       TRUE
+	paged_value wDebugRoomMonPP+0,          $00, $ff,         $00,            DebugRoom_BoxStructStrings.PP1,       NULL,                       FALSE
+	paged_value wDebugRoomMonPP+1,          $00, $ff,         $00,            DebugRoom_BoxStructStrings.PP2,       NULL,                       FALSE
+	paged_value wDebugRoomMonPP+2,          $00, $ff,         $00,            DebugRoom_BoxStructStrings.PP3,       NULL,                       FALSE
+	paged_value wDebugRoomMonPP+3,          $00, $ff,         $00,            DebugRoom_BoxStructStrings.PP4,       NULL,                       FALSE
+
+DebugRoomMenu_PokemonGet_Page4Values:
+	db 6
+	paged_value wDebugRoomMonHappiness,     $00, $ff,         BASE_HAPPINESS, DebugRoom_BoxStructStrings.Friend,    NULL,                       FALSE
+	paged_value wDebugRoomMonPokerusStatus, $00, $ff,         $00,            DebugRoom_BoxStructStrings.Pokerus,   NULL,                       TRUE
+	paged_value wDebugRoomMonCaughtData+0,  $00, $ff,         $00,            DebugRoom_BoxStructStrings.NoUse0,    NULL,                       FALSE
+	paged_value wDebugRoomMonCaughtData+1,  $00, $ff,         $00,            DebugRoom_BoxStructStrings.NoUse1,    NULL,                       FALSE
+	paged_value wDebugRoomMonLevel,         1,   MAX_LEVEL,   $05,            DebugRoom_BoxStructStrings.Level,     NULL,                       FALSE
+	paged_value wDebugRoomMonBox,           1,   NUM_BOXES,   $0e,            DebugRoom_BoxStructStrings.SendBox,   NULL,                       FALSE
+
+DebugRoom_BoxStructStrings:
+.Pokemon:   db "#MON@"
+.Item:      db "ITEM@"
+.Move1:     db "MOVE 1@"
+.Move2:     db "MOVE 2@"
+.Move3:     db "MOVE 3@"
+.Move4:     db "MOVE 4@"
+.ID0:       db "ID[0]@"
+.ID1:       db "ID[1]@"
+.BaseExp0:  db "BASE EXP[0]@"
+.BaseExp1:  db "BASE EXP[1]@"
+.BaseExp2:  db "BASE EXP[2]@"
+.HPExp0:    db "HP EXP[0]@"
+.HPExp1:    db "HP EXP[1]@"
+.AttkExp0:  db "ATTK EXP[0]@"
+.AttkExp1:  db "ATTK EXP[1]@"
+.DfnsExp0:  db "DFNS EXP[0]@"
+.DfnsExp1:  db "DFNS EXP[1]@"
+.SpeedExp0: db "SPEED EXP[0]@"
+.SpeedExp1: db "SPEED EXP[1]@"
+.SpclExp0:  db "SPCL EXP[0]@"
+.SpclExp1:  db "SPCL EXP[1]@"
+.PowerRnd0: db "POWER RND[0]<LF>  RARE:--1-1010@"
+.PowerRnd1: db "POWER RND[1]<LF>  RARE:10101010@"
+.PP1:       db "PP 1@"
+.PP2:       db "PP 2@"
+.PP3:       db "PP 3@"
+.PP4:       db "PP 4@"
+.Friend:    db "FRIEND@"
+.Pokerus:   db "#RUS@"
+.NoUse0:    db "NO USE[0]@"
+.NoUse1:    db "NO USE[1]@"
+.Level:     db "LEVEL@"
+.SendBox:   db "SEND BOX@"
+
+DebugRoom_BoxAddresses:
+	dba sBox1
+	dba sBox2
+	dba sBox3
+	dba sBox4
+	dba sBox5
+	dba sBox6
+	dba sBox7
+	dba sBox8
+	dba sBox9
+	dba sBox10
+	dba sBox11
+	dba sBox12
+	dba sBox13
+	dba sBox14
+
+DebugRoomMenu_RTCEdit:
+	ld hl, .PagedValuesHeader
+	call DebugRoom_EditPagedValues
+	ret
+
+.PagedValuesHeader:
+	dw NULL ; A function
+	dw NULL ; Select function
+	dw DebugRoom_SaveRTC ; Start function
+	dw DebugRoomMenu_RTCEdit_UpdateClock ; Auto function
+	db 1 ; # pages
+	dw DebugRoomMenu_RTCEdit_Page1Values
+
+DebugRoom_SaveRTC:
+	call YesNoBox
+	ret c
+	ld hl, wDebugRoomRTCSec
+	call DebugRoom_SetClock
+	ret
+
+DebugRoomMenu_RTCEdit_UpdateClock:
+	ld hl, wDebugRoomRTCCurSec
+	call DebugRoom_GetClock
+	ld de, DebugRoom_DayHTimeString
+	hlcoord 3, 14
+	call PlaceString
+	ld a, [wDebugRoomRTCCurDay + 0]
+	ld h, a
+	ld a, [wDebugRoomRTCCurDay + 1]
+	ld l, a
+	push hl
+	ld hl, sp+0
+	ld d, h
+	ld e, l
+	hlcoord 7, 14
+	ld c, 2
+	call PrintHexNumber
+	pop hl
+	hlcoord 8, 15
+	ld de, wDebugRoomRTCCurHour
+	lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+	call PrintNum
+	ld [hl], ":"
+	inc hl
+	ld de, wDebugRoomRTCCurMin
+	lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+	call PrintNum
+	ld [hl], ":"
+	inc hl
+	ld de, wDebugRoomRTCCurSec
+	lb bc, PRINTNUM_LEADINGZEROS | 1, 2
+	call PrintNum
+	ret
+
+DebugRoom_DayHTimeString:
+	db "DAY     H<LF>TIME@"
+
+DebugRoom_GetClock:
+	ld a, SRAM_ENABLE
+	ld [MBC3SRamEnable], a
+	xor a
+	ld [MBC3LatchClock], a
+	inc a
+	ld [MBC3LatchClock], a
+	ld b, RTC_DH - RTC_S + 1
+	ld c, RTC_S
+.loop
+	ld a, c
+	ld [MBC3SRamBank], a
+	ld a, [MBC3RTC]
+	ld [hli], a
+	inc c
+	dec b
+	jr nz, .loop
+	call CloseSRAM
+	ret
+
+DebugRoom_SetClock:
+	ld a, SRAM_ENABLE
+	ld [MBC3SRamEnable], a
+	ld b, RTC_DH - RTC_S + 1
+	ld c, RTC_S
+.loop
+	ld a, c
+	ld [MBC3SRamBank], a
+	ld a, [hli]
+	ld [MBC3RTC], a
+	inc c
+	dec b
+	jr nz, .loop
+	call CloseSRAM
+	ret
+
+DebugRoomMenu_RTCEdit_Page1Values:
+	db 5
+	paged_value wDebugRoomRTCSec,   0,   60 - 1, 0, .SecondString, NULL, FALSE
+	paged_value wDebugRoomRTCMin,   0,   60 - 1, 0, .MinuteString, NULL, FALSE
+	paged_value wDebugRoomRTCHour,  0,   24 - 1, 0, .HourString,   NULL, FALSE
+	paged_value wDebugRoomRTCDay+0, $00, $ff,    0, .DayLString,   NULL, TRUE
+	paged_value wDebugRoomRTCDay+1, $00, $ff,    0, .DayHString,   NULL, TRUE
+
+.SecondString: db "SECOND@"
+.MinuteString: db "MINUTE@"
+.HourString:   db "HOUR@"
+.DayLString:   db "DAY L@"
+.DayHString:   db "DAY H<LF> BIT0:DAY MSB<LF> BIT6:HALT<LF> BIT7:DAY CARRY@"
+
+DebugRoomMenu_HaltChkClr:
+	call YesNoBox
+	ret c
+	ld a, BANK(sRTCHaltCheckValue)
+	call OpenSRAM
+	xor a
+	ld hl, sRTCHaltCheckValue
+	ld [hli], a
+	ld [hl], a
+	call CloseSRAM
+	call DebugRoom_PrintRTCHaltChk
+	ret
+
+DebugRoom_PrintRTCHaltChk:
+	hlcoord 16, 9
+	ld de, .RTCString
+	call PlaceString
+	ld a, BANK(sRTCHaltCheckValue)
+	ld hl, sRTCHaltCheckValue
+	call OpenSRAM
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	call CloseSRAM
+	ld de, .HaltString
+	ld a, h
+	cp HIGH(RTC_HALT_VALUE)
+	jr nz, .ok
+	ld a, l
+	cp LOW(RTC_HALT_VALUE)
+	jr z, .done
+.ok
+	ld de, .OKString
+.done
+	hlcoord 16, 10
+	call PlaceString
+	ret
+
+.RTCString:
+	db "RTC:@"
+
+.OKString:
+	db "  OK@"
+
+.HaltString:
+	db "HALT@"
+
+DebugRoomMenu_GBIDSet:
+	ld hl, .PagedValuesHeader
+	call DebugRoom_EditPagedValues
+	ret
+
+.PagedValuesHeader:
+	dw NULL ; A function
+	dw NULL ; Select function
+	dw DebugRoom_SaveGBID ; Start function
+	dw NULL ; Auto function
+	db 1 ; # pages
+	dw DebugRoomMenu_GBIDSet_Page1Values
+
+DebugRoom_SaveGBID:
+	call YesNoBox
+	ret c
+	ld a, BANK(sPlayerData)
+	call OpenSRAM
+	ld hl, sPlayerData + (wPlayerID - wPlayerData)
+	ld a, [wDebugRoomGBID + 0]
+	ld [hli], a
+	ld a, [wDebugRoomGBID + 1]
+	ld [hli], a
+	call CloseSRAM
+	call DebugRoom_SaveChecksum
+	ret
+
+DebugRoomMenu_GBIDSet_Page1Values:
+	db 2
+	paged_value wDebugRoomGBID+0, $00, $ff, $00, .GBID0String, NULL, TRUE
+	paged_value wDebugRoomGBID+1, $00, $ff, $00, .GBID1String, NULL, TRUE
+
+.GBID0String: db "GB ID [0]@"
+.GBID1String: db "GB ID [1]@"
+
+DebugRoomMenu_BtlRecClr:
+	call YesNoBox
+	ret c
+	ld a, BANK(sLinkBattleStats)
+	call OpenSRAM
+	xor a
+	ld hl, sLinkBattleStats
+	ld bc, sLinkBattleStatsEnd - sLinkBattleStats
+	call ByteFill
+	call CloseSRAM
+	ret
+
+DebugRoomMenu_HOFClear:
+	call YesNoBox
+	ret c
+	ld a, BANK(sPlayerData)
+	call OpenSRAM
+	ld hl, sPlayerData + (wHallOfFameCount - wPlayerData)
+	ld [hl], 0
+	xor a
+	ld hl, sHallOfFame
+	ld bc, sHallOfFameEnd - sHallOfFame
+	call ByteFill
+	call CloseSRAM
+	call DebugRoom_SaveChecksum
+	ret
+
+ComputeROMChecksum:
+	ld de, 0
+	call .ComputeROM0Checksum
+	ld c, $01 ; first bank
+.loop:
+	push bc
+	push de
+	ld a, c
+	cpl
+	inc a
+	add $80
+	ld de, wDebugRoomCurChecksumBank
+	ld [de], a
+	hlcoord 16, 16
+	ld c, 1
+	call PrintHexNumber
+	ld [hl], "h"
+	pop de
+	pop bc
+	call ComputeROMXChecksum
+	inc c
+	ld a, c
+	cp $80 ; number of banks
+	jr c, .loop
+	ld a, d
+	ld [wDebugRoomROMChecksum + 0], a
+	ld a, e
+	ld [wDebugRoomROMChecksum + 1], a
+	ret
+
+.AddAtoDE:
+	add e
+	ld e, a
+	ld a, d
+	adc 0
+	ld d, a
+	ret
+
+.ComputeROM0Checksum:
+	ld hl, $0000 ; ROM0 start
+.rom0_loop
+	ld a, [hli]
+	call .AddAtoDE
+	ld a, h
+	cp $40 ; HIGH(ROM0 end)
+	jr c, .rom0_loop
+	ret
+
+.ComputeROMXChecksum: ; unreferenced
+	ld hl, $4000 ; ROMX start
+.romx_loop
+	ld a, c
+	call GetFarByte
+	inc hl
+	call .AddAtoDE
+	ld a, h
+	cp $80 ; HIGH(ROMX end)
+	jr c, .romx_loop
+	ret
+
+DebugRoom_PrintROMChecksum: ; unreferenced
+	hlcoord 16, 0
+	ld de, .SumString
+	call PlaceString
+	hlcoord 16, 1
+	ld de, wDebugRoomROMChecksum
+	ld c, 2
+	call PrintHexNumber
+	ret
+
+.SumString:
+	db "SUM:@"
+
+DebugRoomMenu_ROMChecksum:
+	ld hl, .WaitText
+	call MenuTextbox
+	call ComputeROMChecksum
+	call CloseWindow
+	ld hl, .ROMChecksumText
+	call MenuTextbox
+	hlcoord 14, 14
+	ld de, wDebugRoomROMChecksum
+	ld c, 2
+	call PrintHexNumber
+	ld [hl], "h"
+	call DebugRoom_JoyWaitABSelect
+	call CloseWindow
+	ret
+
+.WaitText:
+	text "Wait..."
+	done
+
+.ROMChecksumText:
+	text "ROM CHECKSUM:"
+	next ""
+	done
+
+DebugRoomMenu_BTBugPoke:
+	ld a, BANK(sIsBugMon)
+	call OpenSRAM
+	ld a, [sIsBugMon]
+	call CloseSRAM
+	or a
+	jr nz, .bug_mon
+	ld hl, .NoBugMonText
+	call MenuTextbox
+	call DebugRoom_JoyWaitABSelect
+	call CloseWindow
+	ret
+
+.NoBugMonText:
+	text "No bug #MON."
+	done
+
+.bug_mon:
+	ld hl, .ItsBugMonText
+	call MenuTextbox
+	ld a, BANK(sIsBugMon)
+	call OpenSRAM
+	hlcoord 4, 16
+	ld de, sIsBugMon
+	ld c, 1
+	call PrintHexNumber
+	ld [hl], "h"
+	call YesNoBox
+	jr c, .done
+	xor a
+	ld [sIsBugMon], a
+.done
+	call CloseSRAM
+	call CloseWindow
+	ret
+
+.ItsBugMonText:
+	text "It'", "s bug #MON!"
+	next "No.    Clear flag?"
+	done
+
+PrintHexNumber:
+; Print the c-byte value from de to hl as hexadecimal digits.
+.loop
+	push bc
+	call .HandleByte
+	pop bc
+	dec c
+	jr nz, .loop
+	ret
+
+.HandleByte:
+	ld a, [de]
+	swap a
+	and $f
+	call .PrintDigit
+	ld [hli], a
+	ld a, [de]
+	and $f
+	call .PrintDigit
+	ld [hli], a
+	inc de
+	ret
+
+.PrintDigit:
+	ld bc, .HexDigits
+	add c
+	ld c, a
+	ld a, 0
+	adc b
+	ld b, a
+	ld a, [bc]
+	ret
+
+.HexDigits:
+	db "0123456789ABCDEF"
--- a/engine/items/items.asm
+++ b/engine/items/items.asm
@@ -168,7 +168,7 @@
 	jr z, .terminator
 	cp c
 	jr nz, .next
-	ld a, 99
+	ld a, MAX_ITEM_STACK
 	sub [hl]
 	add b
 	ld b, a
@@ -205,14 +205,14 @@
 	jr nz, .loop2
 	ld a, [wItemQuantityBuffer]
 	add [hl]
-	cp 100
+	cp MAX_ITEM_STACK + 1
 	jr nc, .newstack
 	ld [hl], a
 	jr .done
 
 .newstack
-	ld [hl], 99
-	sub 99
+	ld [hl], MAX_ITEM_STACK
+	sub MAX_ITEM_STACK
 	ld [wItemQuantityBuffer], a
 	jr .loop2
 
@@ -408,7 +408,7 @@
 	add hl, bc
 	ld a, [wItemQuantityChangeBuffer]
 	add [hl]
-	cp 100
+	cp MAX_ITEM_STACK + 1
 	jr nc, .toomany
 	ld [hl], a
 	scf
--- a/engine/items/mart.asm
+++ b/engine/items/mart.asm
@@ -498,7 +498,7 @@
 	ret
 
 StandardMartAskPurchaseQuantity:
-	ld a, 99
+	ld a, MAX_ITEM_STACK
 	ld [wItemQuantityBuffer], a
 	ld a, MARTTEXT_HOW_MANY
 	call LoadBuyMenuText
@@ -557,7 +557,7 @@
 	ld a, MARTTEXT_HOW_MANY
 	call LoadBuyMenuText
 	call .GetSalePrice
-	ld a, 99
+	ld a, MAX_ITEM_STACK
 	ld [wItemQuantityBuffer], a
 	farcall RooftopSale_SelectQuantityToBuy
 	call ExitMenu
--- a/engine/items/switch_items.asm
+++ b/engine/items/switch_items.asm
@@ -96,11 +96,11 @@
 	jr nz, .asm_249cd
 	ld a, [wScrollingMenuCursorPosition]
 	call Function24a97
-	cp 99
+	cp MAX_ITEM_STACK
 	jr z, .asm_249cd
 	ld a, [wSwitchItem]
 	call Function24a97
-	cp 99
+	cp MAX_ITEM_STACK
 	jr nz, .asm_249cf
 .asm_249cd
 	and a
@@ -121,14 +121,14 @@
 	ld a, [hl]
 	pop hl
 	add [hl]
-	cp 100
+	cp MAX_ITEM_STACK + 1
 	jr c, .asm_24a01
-	sub 99
+	sub MAX_ITEM_STACK
 	push af
 	ld a, [wScrollingMenuCursorPosition]
 	call ItemSwitch_GetNthItem
 	inc hl
-	ld [hl], 99
+	ld [hl], MAX_ITEM_STACK
 	ld a, [wSwitchItem]
 	call ItemSwitch_GetNthItem
 	inc hl
--- a/engine/menus/debug.asm
+++ /dev/null
@@ -1,1391 +1,0 @@
-	const_def $6a
-	const DEBUGTEST_TICKS_1 ; $6a
-	const DEBUGTEST_TICKS_2 ; $6b
-	const DEBUGTEST_WHITE   ; $6c
-	const DEBUGTEST_LIGHT   ; $6d
-	const DEBUGTEST_DARK    ; $6e
-	const DEBUGTEST_BLACK   ; $6f
-	const DEBUGTEST_0       ; $70
-	const DEBUGTEST_1       ; $71
-	const DEBUGTEST_2       ; $72
-	const DEBUGTEST_3       ; $73
-	const DEBUGTEST_4       ; $74
-	const DEBUGTEST_5       ; $75
-	const DEBUGTEST_6       ; $76
-	const DEBUGTEST_7       ; $77
-	const DEBUGTEST_8       ; $78
-	const DEBUGTEST_9       ; $79
-	const DEBUGTEST_A       ; $7a
-	const DEBUGTEST_B       ; $7b
-	const DEBUGTEST_C       ; $7c
-	const DEBUGTEST_D       ; $7d
-	const DEBUGTEST_E       ; $7e
-	const DEBUGTEST_F       ; $7f
-
-ColorTest:
-; A debug menu to test monster and trainer palettes at runtime.
-
-	ldh a, [hCGB]
-	and a
-	jr nz, .asm_818b5
-	ldh a, [hSGB]
-	and a
-	ret z
-
-.asm_818b5
-	ldh a, [hInMenu]
-	push af
-	ld a, $1
-	ldh [hInMenu], a
-	call DisableLCD
-	call Function81948
-	call Function8197c
-	call Function819a7
-	call Function818f4
-	call EnableLCD
-	ld de, MUSIC_NONE
-	call PlayMusic
-	xor a
-	ld [wJumptableIndex], a
-	ld [wcf66], a
-	ld [wd003], a
-.asm_818de
-	ld a, [wJumptableIndex]
-	bit 7, a
-	jr nz, .asm_818f0
-	call Function81a74
-	call Function81f5e
-	call DelayFrame
-	jr .asm_818de
-
-.asm_818f0
-	pop af
-	ldh [hInMenu], a
-	ret
-
-Function818f4:
-	ld a, [wd002]
-	and a
-	jr nz, Function81911
-	ld hl, PokemonPalettes
-
-Function818fd:
-	ld de, wOverworldMapBlocks
-	ld c, NUM_POKEMON + 1
-.asm_81902
-	push bc
-	push hl
-	call Function81928
-	pop hl
-	ld bc, 8
-	add hl, bc
-	pop bc
-	dec c
-	jr nz, .asm_81902
-	ret
-
-Function81911:
-	ld hl, TrainerPalettes
-	ld de, wOverworldMapBlocks
-	ld c, NUM_TRAINER_CLASSES
-.asm_81919
-	push bc
-	push hl
-	call Function81928
-	pop hl
-	ld bc, 4
-	add hl, bc
-	pop bc
-	dec c
-	jr nz, .asm_81919
-	ret
-
-Function81928:
-	ld a, BANK(PokemonPalettes) ; aka BANK(TrainerPalettes)
-	call GetFarByte
-	ld [de], a
-	inc de
-	inc hl
-	ld a, BANK(PokemonPalettes) ; aka BANK(TrainerPalettes)
-	call GetFarByte
-	ld [de], a
-	inc de
-	inc hl
-	ld a, BANK(PokemonPalettes) ; aka BANK(TrainerPalettes)
-	call GetFarByte
-	ld [de], a
-	inc de
-	inc hl
-	ld a, BANK(PokemonPalettes) ; aka BANK(TrainerPalettes)
-	call GetFarByte
-	ld [de], a
-	inc de
-	ret
-
-Function81948:
-	ld a, $1
-	ldh [rVBK], a
-	ld hl, vTiles0
-	ld bc, sScratch - vTiles0
-	xor a
-	call ByteFill
-	ld a, $0
-	ldh [rVBK], a
-	ld hl, vTiles0
-	ld bc, sScratch - vTiles0
-	xor a
-	call ByteFill
-	hlcoord 0, 0, wAttrmap
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	xor a
-	call ByteFill
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	xor a
-	call ByteFill
-	call ClearSprites
-	ret
-
-Function8197c:
-	ld hl, DebugColorTestGFX
-	ld de, vTiles2 tile DEBUGTEST_TICKS_1
-	ld bc, 22 tiles
-	call CopyBytes
-	ld hl, DebugUpArrowGFX
-	ld de, vTiles0
-	ld bc, 1 tiles
-	call CopyBytes
-	call LoadStandardFont
-	ld hl, vTiles1
-	lb bc, 8, 0
-.asm_8199d
-	ld a, [hl]
-	xor $ff
-	ld [hli], a
-	dec bc
-	ld a, c
-	or b
-	jr nz, .asm_8199d
-	ret
-
-Function819a7:
-	ldh a, [hCGB]
-	and a
-	ret z
-	ldh a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals2)
-	ldh [rSVBK], a
-	ld hl, Palette_DebugBG
-	ld de, wBGPals2
-	ld bc, 16 palettes
-	call CopyBytes
-	ld a, 1 << rBGPI_AUTO_INCREMENT
-	ldh [rBGPI], a
-	ld hl, Palette_DebugBG
-	ld c, 8 palettes
-	xor a
-.asm_819c8
-	ldh [rBGPD], a
-	dec c
-	jr nz, .asm_819c8
-	ld a, 1 << rOBPI_AUTO_INCREMENT
-	ldh [rOBPI], a
-	ld hl, Palette_DebugOB
-	ld c, 8 palettes
-.asm_819d6
-	ld a, [hli]
-	ldh [rOBPD], a
-	dec c
-	jr nz, .asm_819d6
-	ld a, $94
-	ld [wc608], a
-	ld a, $52
-	ld [wc608 + 1], a
-	ld a, $4a
-	ld [wc608 + 2], a
-	ld a, $29
-	ld [wc608 + 3], a
-	pop af
-	ldh [rSVBK], a
-	ret
-
-Palette_DebugBG:
-INCLUDE "gfx/debug/bg.pal"
-
-Palette_DebugOB:
-INCLUDE "gfx/debug/ob.pal"
-
-Function81a74:
-	call JoyTextDelay
-	ld a, [wJumptableIndex]
-	cp $4
-	jr nc, .asm_81a8b
-	ld hl, hJoyLast
-	ld a, [hl]
-	and SELECT
-	jr nz, .asm_81a9a
-	ld a, [hl]
-	and START
-	jr nz, .asm_81aab
-
-.asm_81a8b
-	jumptable Jumptable_81acf, wJumptableIndex
-
-.asm_81a9a
-	call Function81eca
-	call Function81ac3
-	ld e, a
-	ld a, [wcf66]
-	inc a
-	cp e
-	jr c, .asm_81aba
-	xor a
-	jr .asm_81aba
-
-.asm_81aab
-	call Function81eca
-	ld a, [wcf66]
-	dec a
-	cp $ff
-	jr nz, .asm_81aba
-	call Function81ac3
-	dec a
-
-.asm_81aba
-	ld [wcf66], a
-	ld a, $0
-	ld [wJumptableIndex], a
-	ret
-
-Function81ac3:
-; Looping back around the pic set.
-	ld a, [wd002]
-	and a
-	jr nz, .asm_81acc
-	ld a, NUM_POKEMON ; CELEBI
-	ret
-
-.asm_81acc
-	ld a, NUM_TRAINER_CLASSES - 1 ; MYSTICALMAN
-	ret
-
-Jumptable_81acf:
-	dw Function81adb
-	dw Function81c18
-	dw Function81c33
-	dw Function81cc2
-	dw Function81d8e
-	dw Function81daf
-
-Function81adb:
-	xor a
-	ldh [hBGMapMode], a
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, DEBUGTEST_BLACK
-	call ByteFill
-	hlcoord 1, 3
-	lb bc, 7, 18
-	ld a, DEBUGTEST_WHITE
-	call DebugColor_FillBoxWithByte
-	hlcoord 11, 0
-	lb bc, 2, 3
-	ld a, DEBUGTEST_LIGHT
-	call DebugColor_FillBoxWithByte
-	hlcoord 16, 0
-	lb bc, 2, 3
-	ld a, DEBUGTEST_DARK
-	call DebugColor_FillBoxWithByte
-	call Function81bc0
-	call Function81bf4
-	ld a, [wcf66]
-	inc a
-	ld [wCurPartySpecies], a
-	ld [wDeciramBuffer], a
-	hlcoord 0, 1
-	ld de, wDeciramBuffer
-	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
-	call PrintNum
-	ld a, [wd002]
-	and a
-	jr nz, .asm_81b7a
-	ld a, $1
-	ld [wUnownLetter], a
-	call GetPokemonName
-	hlcoord 4, 1
-	call PlaceString
-	xor a
-	ld [wBoxAlignment], a
-	hlcoord 12, 3
-	call _PrepMonFrontpic
-	ld de, vTiles2 tile $31
-	predef GetMonBackpic
-	ld a, $31
-	ldh [hGraphicStartTile], a
-	hlcoord 2, 4
-	lb bc, 6, 6
-	predef PlaceGraphic
-	ld a, [wd003]
-	and a
-	jr z, .asm_81b66
-	ld de, String_81baf
-	jr .asm_81b69
-
-.asm_81b66
-	ld de, String_81bb4
-
-.asm_81b69
-	hlcoord 7, 17
-	call PlaceString
-	hlcoord 0, 17
-	ld de, String_81bb9
-	call PlaceString
-	jr .asm_81ba9
-
-.asm_81b7a
-	ld a, [wDeciramBuffer]
-	ld [wTrainerClass], a
-	callfar GetTrainerAttributes
-	ld de, wStringBuffer1
-	hlcoord 4, 1
-	call PlaceString
-	ld de, vTiles2
-	callfar GetTrainerPic
-	xor a
-	ld [wTempEnemyMonSpecies], a
-	ldh [hGraphicStartTile], a
-	hlcoord 2, 3
-	lb bc, 7, 7
-	predef PlaceGraphic
-
-.asm_81ba9
-	ld a, $1
-	ld [wJumptableIndex], a
-	ret
-
-String_81baf: db "レア", DEBUGTEST_BLACK, DEBUGTEST_BLACK, "@" ; rare (shiny)
-String_81bb4: db "ノーマル@" ; normal
-String_81bb9: db DEBUGTEST_A, "きりかえ▶@" ; (A) switches
-
-Function81bc0:
-	decoord 0, 11, wAttrmap
-	hlcoord 2, 11
-	ld a, $1
-	call Function81bde
-	decoord 0, 13, wAttrmap
-	hlcoord 2, 13
-	ld a, $2
-	call Function81bde
-	decoord 0, 15, wAttrmap
-	hlcoord 2, 15
-	ld a, $3
-
-Function81bde:
-	push af
-	ld a, DEBUGTEST_TICKS_1
-	ld [hli], a
-	ld bc, $f
-	ld a, DEBUGTEST_TICKS_2
-	call ByteFill
-	ld l, e
-	ld h, d
-	pop af
-	ld bc, $28
-	call ByteFill
-	ret
-
-Function81bf4:
-	ld a, [wcf66]
-	inc a
-	ld l, a
-	ld h, $0
-	add hl, hl
-	add hl, hl
-	ld de, wOverworldMapBlocks
-	add hl, de
-	ld de, wc608
-	ld bc, 4
-	call CopyBytes
-	xor a
-	ld [wcf64], a
-	ld [wcf65], a
-	ld de, wc608
-	call Function81ea5
-	ret
-
-Function81c18:
-	ldh a, [hCGB]
-	and a
-	jr z, .asm_81c2a
-	ld a, $2
-	ldh [hBGMapMode], a
-	call DelayFrame
-	call DelayFrame
-	call DelayFrame
-
-.asm_81c2a
-	call WaitBGMap
-	ld a, $2
-	ld [wJumptableIndex], a
-	ret
-
-Function81c33:
-	ldh a, [hCGB]
-	and a
-	jr z, .asm_81c69
-	ldh a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals2)
-	ldh [rSVBK], a
-	ld hl, wBGPals2
-	ld de, wc608
-	ld c, $1
-	call Function81ee3
-	hlcoord 10, 2
-	ld de, wc608
-	call Function81ca7
-	hlcoord 15, 2
-	ld de, wc608 + 2
-	call Function81ca7
-	ld a, $1
-	ldh [hCGBPalUpdate], a
-	ld a, $3
-	ld [wJumptableIndex], a
-	pop af
-	ldh [rSVBK], a
-	ret
-
-.asm_81c69
-	ld hl, wSGBPals
-	ld a, 1
-	ld [hli], a
-	ld a, LOW(PALRGB_WHITE)
-	ld [hli], a
-	ld a, HIGH(PALRGB_WHITE)
-	ld [hli], a
-	ld a, [wc608]
-	ld [hli], a
-	ld a, [wc608 + 1]
-	ld [hli], a
-	ld a, [wc608 + 2]
-	ld [hli], a
-	ld a, [wc608 + 3]
-	ld [hli], a
-	xor a
-	ld [hli], a
-	ld [hli], a
-	ld [hl], a
-	ld hl, wSGBPals
-	call Function81f0c
-	hlcoord 10, 2
-	ld de, wc608
-	call Function81ca7
-	hlcoord 15, 2
-	ld de, wc608 + 2
-	call Function81ca7
-	ld a, $3
-	ld [wJumptableIndex], a
-	ret
-
-Function81ca7:
-	inc hl
-	inc hl
-	inc hl
-	ld a, [de]
-	call Function81cbc
-	ld a, [de]
-	swap a
-	call Function81cbc
-	inc de
-	ld a, [de]
-	call Function81cbc
-	ld a, [de]
-	swap a
-
-Function81cbc:
-	and $f
-	add DEBUGTEST_0
-	ld [hld], a
-	ret
-
-Function81cc2:
-	ldh a, [hJoyLast]
-	and B_BUTTON
-	jr nz, .asm_81cdf
-	ldh a, [hJoyLast]
-	and A_BUTTON
-	jr nz, .asm_81ce5
-	ld a, [wcf64]
-	and $3
-	ld e, a
-	ld d, 0
-	ld hl, Jumptable_81d02
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-
-.asm_81cdf
-	ld a, $4
-	ld [wJumptableIndex], a
-	ret
-
-.asm_81ce5
-	ld a, [wd002]
-	and a
-	ret nz
-	ld a, [wd003]
-	xor $4
-	ld [wd003], a
-	ld c, a
-	ld b, 0
-	ld hl, PokemonPalettes
-	add hl, bc
-	call Function818fd
-	ld a, $0
-	ld [wJumptableIndex], a
-	ret
-
-Jumptable_81d02:
-	dw Function81d0a
-	dw Function81d34
-	dw Function81d46
-	dw Function81d58
-
-Function81d0a:
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_DOWN
-	jr nz, Function81d89
-	ld a, [hl]
-	and D_LEFT
-	jr nz, .asm_81d1d
-	ld a, [hl]
-	and D_RIGHT
-	jr nz, .asm_81d28
-	ret
-
-.asm_81d1d
-	xor a
-	ld [wcf65], a
-	ld de, wc608
-	call Function81ea5
-	ret
-
-.asm_81d28
-	ld a, $1
-	ld [wcf65], a
-	ld de, wc608 + 2
-	call Function81ea5
-	ret
-
-Function81d34:
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_DOWN
-	jr nz, Function81d89
-	ld a, [hl]
-	and D_UP
-	jr nz, Function81d84
-	ld hl, wc608 + 10
-	jr Function81d63
-
-Function81d46:
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_DOWN
-	jr nz, Function81d89
-	ld a, [hl]
-	and D_UP
-	jr nz, Function81d84
-	ld hl, wc608 + 11
-	jr Function81d63
-
-Function81d58:
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_UP
-	jr nz, Function81d84
-	ld hl, wc608 + 12
-
-Function81d63:
-	ldh a, [hJoyLast]
-	and D_RIGHT
-	jr nz, Function81d70
-	ldh a, [hJoyLast]
-	and D_LEFT
-	jr nz, Function81d77
-	ret
-
-Function81d70:
-	ld a, [hl]
-	cp $1f
-	ret nc
-	inc [hl]
-	jr Function81d7b
-
-Function81d77:
-	ld a, [hl]
-	and a
-	ret z
-	dec [hl]
-
-Function81d7b:
-	call Function81e67
-	ld a, $2
-	ld [wJumptableIndex], a
-	ret
-
-Function81d84:
-	ld hl, wcf64
-	dec [hl]
-	ret
-
-Function81d89:
-	ld hl, wcf64
-	inc [hl]
-	ret
-
-Function81d8e:
-	hlcoord 0, 10
-	ld bc, $a0
-	ld a, DEBUGTEST_BLACK
-	call ByteFill
-	hlcoord 2, 12
-	ld de, String_81fcd
-	call PlaceString
-	xor a
-	ld [wd004], a
-	call Function81df4
-	ld a, $5
-	ld [wJumptableIndex], a
-	ret
-
-Function81daf:
-	ld hl, hJoyPressed
-	ld a, [hl]
-	and B_BUTTON
-	jr nz, .asm_81dbb
-	call Function81dc7
-	ret
-
-.asm_81dbb
-	ld a, $0
-	ld [wJumptableIndex], a
-	ret
-
-Function81dc1:
-	ld hl, wJumptableIndex
-	set 7, [hl]
-	ret
-
-Function81dc7:
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_UP
-	jr nz, .asm_81dd5
-	ld a, [hl]
-	and D_DOWN
-	jr nz, .asm_81de2
-	ret
-
-.asm_81dd5
-	ld a, [wd004]
-	cp $3b
-	jr z, .asm_81ddf
-	inc a
-	jr .asm_81ded
-
-.asm_81ddf
-	xor a
-	jr .asm_81ded
-
-.asm_81de2
-	ld a, [wd004]
-	and a
-	jr z, .asm_81deb
-	dec a
-	jr .asm_81ded
-
-.asm_81deb
-	ld a, $3b
-
-.asm_81ded
-	ld [wd004], a
-	call Function81df4
-	ret
-
-Function81df4:
-	hlcoord 10, 11
-	call Function81e5e
-	hlcoord 10, 12
-	call Function81e5e
-	hlcoord 10, 13
-	call Function81e5e
-	hlcoord 10, 14
-	call Function81e5e
-	ld a, [wd004]
-	inc a
-	ld [wTempTMHM], a
-	predef GetTMHMMove
-	ld a, [wTempTMHM]
-	ld [wPutativeTMHMMove], a
-	call GetMoveName
-	hlcoord 10, 12
-	call PlaceString
-	ld a, [wd004]
-	call Function81e55
-	ld [wCurItem], a
-	predef CanLearnTMHMMove
-	ld a, c
-	and a
-	ld de, String_81e46
-	jr nz, .asm_81e3f
-	ld de, String_81e4d
-
-.asm_81e3f
-	hlcoord 10, 14
-	call PlaceString
-	ret
-
-String_81e46: db "おぼえられる@" ; can be taught
-String_81e4d: db "おぼえられない@" ; cannot be taught
-
-Function81e55:
-	cp $32
-	jr c, .asm_81e5b
-	inc a
-	inc a
-
-.asm_81e5b
-	add $bf
-	ret
-
-Function81e5e:
-	ld bc, 10
-	ld a, DEBUGTEST_BLACK
-	call ByteFill
-	ret
-
-Function81e67:
-	ld a, [wc608 + 10]
-	and $1f
-	ld e, a
-	ld a, [wc608 + 11]
-	and $7
-	sla a
-	swap a
-	or e
-	ld e, a
-	ld a, [wc608 + 11]
-	and $18
-	sla a
-	swap a
-	ld d, a
-	ld a, [wc608 + 12]
-	and $1f
-	sla a
-	sla a
-	or d
-	ld d, a
-	ld a, [wcf65]
-	and a
-	jr z, .asm_81e9c
-	ld a, e
-	ld [wc608 + 2], a
-	ld a, d
-	ld [wc608 + 3], a
-	ret
-
-.asm_81e9c
-	ld a, e
-	ld [wc608], a
-	ld a, d
-	ld [wc608 + 1], a
-	ret
-
-Function81ea5:
-	ld a, [de]
-	and $1f
-	ld [wc608 + 10], a
-	ld a, [de]
-	and $e0
-	swap a
-	srl a
-	ld b, a
-	inc de
-	ld a, [de]
-	and $3
-	swap a
-	srl a
-	or b
-	ld [wc608 + 11], a
-	ld a, [de]
-	and $7c
-	srl a
-	srl a
-	ld [wc608 + 12], a
-	ret
-
-Function81eca:
-	ld a, [wcf66]
-	inc a
-	ld l, a
-	ld h, $0
-	add hl, hl
-	add hl, hl
-	ld de, wOverworldMapBlocks
-	add hl, de
-	ld e, l
-	ld d, h
-	ld hl, wc608
-	ld bc, 4
-	call CopyBytes
-	ret
-
-Function81ee3:
-.asm_81ee3
-	ld a, LOW(PALRGB_WHITE)
-	ld [hli], a
-	ld a, HIGH(PALRGB_WHITE)
-	ld [hli], a
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	inc de
-	ld [hli], a
-	ld a, [de]
-	inc de
-	ld [hli], a
-	xor a
-	ld [hli], a
-	ld [hli], a
-	dec c
-	jr nz, .asm_81ee3
-	ret
-
-DebugColor_FillBoxWithByte:
-; For some reason, we have another copy of FillBoxWithByte here
-.row
-	push bc
-	push hl
-.col
-	ld [hli], a
-	dec c
-	jr nz, .col
-	pop hl
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	pop bc
-	dec b
-	jr nz, .row
-	ret
-
-Function81f0c:
-	ld a, [wcfbe]
-	push af
-	set 7, a
-	ld [wcfbe], a
-	call Function81f1d
-	pop af
-	ld [wcfbe], a
-	ret
-
-Function81f1d:
-	ld a, [hl]
-	and $7
-	ret z
-	ld b, a
-.asm_81f22
-	push bc
-	xor a
-	ldh [rJOYP], a
-	ld a, $30
-	ldh [rJOYP], a
-	ld b, $10
-.asm_81f2c
-	ld e, $8
-	ld a, [hli]
-	ld d, a
-.asm_81f30
-	bit 0, d
-	ld a, $10
-	jr nz, .asm_81f38
-	ld a, $20
-
-.asm_81f38
-	ldh [rJOYP], a
-	ld a, $30
-	ldh [rJOYP], a
-	rr d
-	dec e
-	jr nz, .asm_81f30
-	dec b
-	jr nz, .asm_81f2c
-	ld a, $20
-	ldh [rJOYP], a
-	ld a, $30
-	ldh [rJOYP], a
-	ld de, 7000
-.asm_81f51
-	nop
-	nop
-	nop
-	dec de
-	ld a, d
-	or e
-	jr nz, .asm_81f51
-	pop bc
-	dec b
-	jr nz, .asm_81f22
-	ret
-
-Function81f5e:
-	ld a, DEBUGTEST_BLACK
-	hlcoord 10, 0
-	ld [hl], a
-	hlcoord 15, 0
-	ld [hl], a
-	hlcoord 1, 11
-	ld [hl], a
-	hlcoord 1, 13
-	ld [hl], a
-	hlcoord 1, 15
-	ld [hl], a
-	ld a, [wJumptableIndex]
-	cp $3
-	jr nz, .asm_81fc9
-	ld a, [wcf64]
-	and a
-	jr z, .asm_81f8d
-	dec a
-	hlcoord 1, 11
-	ld bc, 2 * SCREEN_WIDTH
-	call AddNTimes
-	ld [hl], $ed
-
-.asm_81f8d
-	ld a, [wcf65]
-	and a
-	jr z, .asm_81f98
-	hlcoord 15, 0
-	jr .asm_81f9b
-
-.asm_81f98
-	hlcoord 10, 0
-
-.asm_81f9b
-	ld [hl], $ed
-	ld b, $70
-	ld c, $5
-	ld hl, wVirtualOAM
-	ld de, wc608 + 10
-	call .asm_81fb7
-	ld de, wc608 + 11
-	call .asm_81fb7
-	ld de, wc608 + 12
-	call .asm_81fb7
-	ret
-
-.asm_81fb7
-	ld a, b
-	ld [hli], a ; y
-	ld a, [de]
-	add a
-	add a
-	add 3 * TILE_WIDTH
-	ld [hli], a ; x
-	xor a
-	ld [hli], a ; tile id
-	ld a, c
-	ld [hli], a ; attributes
-	ld a, 2 * TILE_WIDTH
-	add b
-	ld b, a
-	inc c
-	ret
-
-.asm_81fc9
-	call ClearSprites
-	ret
-
-String_81fcd:
-	db   "おわりますか?" ; Are you finished?
-	next "はい<DOT><DOT><DOT>", DEBUGTEST_A ; YES...(A)
-	next "いいえ<DOT><DOT>", DEBUGTEST_B ; NO..(B)
-	db   "@"
-
-DebugUpArrowGFX:
-INCBIN "gfx/debug/up_arrow.2bpp"
-
-DebugColorTestGFX:
-INCBIN "gfx/debug/color_test.2bpp"
-
-TilesetColorTest:
-	ret
-	xor a
-	ld [wJumptableIndex], a
-	ld [wcf64], a
-	ld [wcf65], a
-	ld [wcf66], a
-	ldh [hMapAnims], a
-	call ClearSprites
-	call OverworldTextModeSwitch
-	call WaitBGMap2
-	xor a
-	ldh [hBGMapMode], a
-	ld de, DebugColorTestGFX
-	ld hl, vTiles2 tile DEBUGTEST_TICKS_1
-	lb bc, BANK(DebugColorTestGFX), 22
-	call Request2bpp
-	ld de, DebugUpArrowGFX
-	ld hl, vTiles1
-	lb bc, BANK(DebugUpArrowGFX), 1
-	call Request2bpp
-	ld a, HIGH(vBGMap1)
-	ldh [hBGMapAddress + 1], a
-	hlcoord 0, 0
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, DEBUGTEST_BLACK
-	call ByteFill
-	hlcoord 0, 0, wAttrmap
-	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
-	ld a, $7
-	call ByteFill
-	ld de, $15
-	ld a, DEBUGTEST_WHITE
-	call Function821d2
-	ld de, $1a
-	ld a, DEBUGTEST_LIGHT
-	call Function821d2
-	ld de, $1f
-	ld a, DEBUGTEST_DARK
-	call Function821d2
-	ld de, $24
-	ld a, DEBUGTEST_BLACK
-	call Function821d2
-	call Function821f4
-	call Function8220f
-	call WaitBGMap2
-	ld [wJumptableIndex], a
-	ld a, $40
-	ldh [hWY], a
-	ret
-
-Function821d2:
-	hlcoord 0, 0
-	call Function821de
-
-Function821d8:
-	ld a, [wcf64]
-	hlcoord 0, 0, wAttrmap
-
-Function821de:
-	add hl, de
-rept 4
-	ld [hli], a
-endr
-	ld bc, $10
-	add hl, bc
-rept 4
-	ld [hli], a
-endr
-	ld bc, $10
-	add hl, bc
-rept 4
-	ld [hli], a
-endr
-	ret
-
-Function821f4:
-	hlcoord 2, 4
-	call Function82203
-	hlcoord 2, 6
-	call Function82203
-	hlcoord 2, 8
-
-Function82203:
-	ld a, DEBUGTEST_TICKS_1
-	ld [hli], a
-	ld bc, $10 - 1
-	ld a, DEBUGTEST_TICKS_2
-	call ByteFill
-	ret
-
-Function8220f:
-	ldh a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals1)
-	ldh [rSVBK], a
-	ld a, [wcf64]
-	ld l, a
-	ld h, $0
-	add hl, hl
-	add hl, hl
-	add hl, hl
-	ld de, wBGPals1
-	add hl, de
-	ld de, wc608
-	ld bc, 8
-	call CopyBytes
-	ld de, wc608
-	call Function81ea5
-	pop af
-	ldh [rSVBK], a
-	ret
-
-Function82236:
-	ld hl, hJoyLast
-	ld a, [hl]
-	and SELECT
-	jr nz, .loop7
-	ld a, [hl]
-	and B_BUTTON
-	jr nz, .asm_82299
-	call Function822f0
-	ret
-
-.loop7
-	ld hl, wcf64
-	ld a, [hl]
-	inc a
-	and $7
-	cp $7
-	jr nz, .asm_82253
-	xor a
-
-.asm_82253
-	ld [hl], a
-	ld de, $15
-	call Function821d8
-	ld de, $1a
-	call Function821d8
-	ld de, $1f
-	call Function821d8
-	ld de, $24
-	call Function821d8
-	ldh a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals2)
-	ldh [rSVBK], a
-	ld hl, wBGPals2
-	ld a, [wcf64]
-	ld bc, 1 palettes
-	call AddNTimes
-	ld de, wc608
-	ld bc, 1 palettes
-	call CopyBytes
-	pop af
-	ldh [rSVBK], a
-	ld a, $2
-	ldh [hBGMapMode], a
-	ld c, 3
-	call DelayFrames
-	ld a, $1
-	ldh [hBGMapMode], a
-	ret
-
-.asm_82299
-	call ClearSprites
-	ldh a, [hWY]
-	xor $d0
-	ldh [hWY], a
-	ret
-
-Function822a3:
-	ldh a, [rSVBK]
-	push af
-	ld a, BANK(wBGPals2)
-	ldh [rSVBK], a
-	ld hl, wBGPals2
-	ld a, [wcf64]
-	ld bc, 1 palettes
-	call AddNTimes
-	ld e, l
-	ld d, h
-	ld hl, wc608
-	ld bc, 1 palettes
-	call CopyBytes
-	hlcoord 1, 0
-	ld de, wc608
-	call Function81ca7
-	hlcoord 6, 0
-	ld de, wc608 + 2
-	call Function81ca7
-	hlcoord 11, 0
-	ld de, wc608 + 4
-	call Function81ca7
-	hlcoord 16, 0
-	ld de, wc608 + 6
-	call Function81ca7
-	pop af
-	ldh [rSVBK], a
-	ld a, $1
-	ldh [hCGBPalUpdate], a
-	call DelayFrame
-	ret
-
-Function822f0:
-	ld a, [wcf65]
-	and 3
-	ld e, a
-	ld d, 0
-	ld hl, .dw
-	add hl, de
-	add hl, de
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp hl
-
-.dw
-	dw Function82309
-	dw Function82339
-	dw Function8234b
-	dw Function8235d
-
-Function82309:
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_DOWN
-	jr nz, Function8238c
-	ld a, [hl]
-	and D_LEFT
-	jr nz, .asm_8231c
-	ld a, [hl]
-	and D_RIGHT
-	jr nz, .asm_82322
-	ret
-
-.asm_8231c
-	ld a, [wcf66]
-	dec a
-	jr .asm_82326
-
-.asm_82322
-	ld a, [wcf66]
-	inc a
-
-.asm_82326
-	and $3
-	ld [wcf66], a
-	ld e, a
-	ld d, $0
-	ld hl, wc608
-	add hl, de
-	add hl, de
-	ld e, l
-	ld d, h
-	call Function81ea5
-	ret
-
-Function82339:
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_DOWN
-	jr nz, Function8238c
-	ld a, [hl]
-	and D_UP
-	jr nz, Function82387
-	ld hl, wc608 + 10
-	jr Function82368
-
-Function8234b:
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_DOWN
-	jr nz, Function8238c
-	ld a, [hl]
-	and D_UP
-	jr nz, Function82387
-	ld hl, wc608 + 11
-	jr Function82368
-
-Function8235d:
-	ld hl, hJoyLast
-	ld a, [hl]
-	and D_UP
-	jr nz, Function82387
-	ld hl, wc608 + 12
-
-Function82368:
-	ldh a, [hJoyLast]
-	and D_RIGHT
-	jr nz, .asm_82375
-	ldh a, [hJoyLast]
-	and D_LEFT
-	jr nz, .asm_8237c
-	ret
-
-.asm_82375
-	ld a, [hl]
-	cp $1f
-	ret nc
-	inc [hl]
-	jr .asm_82380
-
-.asm_8237c
-	ld a, [hl]
-	and a
-	ret z
-	dec [hl]
-
-.asm_82380
-	call Function82391
-	call Function822a3
-	ret
-
-Function82387:
-	ld hl, wcf65
-	dec [hl]
-	ret
-
-Function8238c:
-	ld hl, wcf65
-	inc [hl]
-	ret
-
-Function82391:
-	ld a, [wc608 + 10]
-	and $1f
-	ld e, a
-	ld a, [wc608 + 11]
-	and $7
-	sla a
-	swap a
-	or e
-	ld e, a
-	ld a, [wc608 + 11]
-	and $18
-	sla a
-	swap a
-	ld d, a
-	ld a, [wc608 + 12]
-	and $1f
-	sla a
-	sla a
-	or d
-	ld d, a
-	ld a, [wcf66]
-	ld c, a
-	ld b, $0
-	ld hl, wc608
-	add hl, bc
-	add hl, bc
-	ld a, e
-	ld [hli], a
-	ld [hl], d
-	ret
-
-Function823c6:
-	ret
-
-Function823c7:
-	ret
--- a/engine/menus/intro_menu.asm
+++ b/engine/menus/intro_menu.asm
@@ -88,6 +88,12 @@
 	farcall InitMobileProfile ; mobile
 	ret
 
+if DEF(_DEBUG)
+DebugRoom: ; unreferenced
+	farcall _DebugRoom
+	ret
+endc
+
 ResetWRAM:
 	xor a
 	ldh [hBGMapMode], a
--- a/engine/menus/main_menu.asm
+++ b/engine/menus/main_menu.asm
@@ -18,6 +18,7 @@
 	const MAINMENUITEM_MYSTERY_GIFT   ; 3
 	const MAINMENUITEM_MOBILE         ; 4
 	const MAINMENUITEM_MOBILE_STUDIUM ; 5
+	const MAINMENUITEM_DEBUG_ROOM     ; 6
 
 MobileMenuGFX:
 INCBIN "gfx/mobile/mobile_menu.2bpp"
@@ -70,6 +71,9 @@
 	db "MYSTERY GIFT@"
 	db "MOBILE@"
 	db "MOBILE STUDIUM@"
+if DEF(_DEBUG)
+	db "DEBUG ROOM@"
+endc
 
 .Jumptable:
 ; entries correspond to MAINMENUITEM_* constants
@@ -79,6 +83,9 @@
 	dw MainMenu_MysteryGift
 	dw MainMenu_Mobile
 	dw MainMenu_MobileStudium
+if DEF(_DEBUG)
+	dw MainMenu_DebugRoom
+endc
 
 MainMenuItems:
 ; entries correspond to MAINMENU_* constants
@@ -90,40 +97,52 @@
 	db -1
 
 	; MAINMENU_CONTINUE
-	db 3
+	db 3 + DEF(_DEBUG)
 	db MAINMENUITEM_CONTINUE
 	db MAINMENUITEM_NEW_GAME
 	db MAINMENUITEM_OPTION
+if DEF(_DEBUG)
+	db MAINMENUITEM_DEBUG_ROOM
+endc
 	db -1
 
 	; MAINMENU_MOBILE_MYSTERY
-	db 5
+	db 5 + DEF(_DEBUG)
 	db MAINMENUITEM_CONTINUE
 	db MAINMENUITEM_NEW_GAME
 	db MAINMENUITEM_OPTION
 	db MAINMENUITEM_MYSTERY_GIFT
 	db MAINMENUITEM_MOBILE
+if DEF(_DEBUG)
+	db MAINMENUITEM_DEBUG_ROOM
+endc
 	db -1
 
 	; MAINMENU_MOBILE
-	db 4
+	db 4 + DEF(_DEBUG)
 	db MAINMENUITEM_CONTINUE
 	db MAINMENUITEM_NEW_GAME
 	db MAINMENUITEM_OPTION
 	db MAINMENUITEM_MOBILE
+if DEF(_DEBUG)
+	db MAINMENUITEM_DEBUG_ROOM
+endc
 	db -1
 
 	; MAINMENU_MOBILE_STUDIUM
-	db 5
+	db 5 + DEF(_DEBUG)
 	db MAINMENUITEM_CONTINUE
 	db MAINMENUITEM_NEW_GAME
 	db MAINMENUITEM_OPTION
 	db MAINMENUITEM_MOBILE
 	db MAINMENUITEM_MOBILE_STUDIUM
+if DEF(_DEBUG)
+	db MAINMENUITEM_DEBUG_ROOM
+endc
 	db -1
 
 	; MAINMENU_MYSTERY_MOBILE_STUDIUM
-	db 6
+	db 6 + DEF(_DEBUG)
 	db MAINMENUITEM_CONTINUE
 	db MAINMENUITEM_NEW_GAME
 	db MAINMENUITEM_OPTION
@@ -130,31 +149,43 @@
 	db MAINMENUITEM_MYSTERY_GIFT
 	db MAINMENUITEM_MOBILE
 	db MAINMENUITEM_MOBILE_STUDIUM
+if DEF(_DEBUG)
+	db MAINMENUITEM_DEBUG_ROOM
+endc
 	db -1
 
 	; MAINMENU_MYSTERY
-	db 4
+	db 4 + DEF(_DEBUG)
 	db MAINMENUITEM_CONTINUE
 	db MAINMENUITEM_NEW_GAME
 	db MAINMENUITEM_OPTION
 	db MAINMENUITEM_MYSTERY_GIFT
+if DEF(_DEBUG)
+	db MAINMENUITEM_DEBUG_ROOM
+endc
 	db -1
 
 	; MAINMENU_MYSTERY_STUDIUM
-	db 5
+	db 5 + DEF(_DEBUG)
 	db MAINMENUITEM_CONTINUE
 	db MAINMENUITEM_NEW_GAME
 	db MAINMENUITEM_OPTION
 	db MAINMENUITEM_MYSTERY_GIFT
 	db MAINMENUITEM_MOBILE_STUDIUM
+if DEF(_DEBUG)
+	db MAINMENUITEM_DEBUG_ROOM
+endc
 	db -1
 
 	; MAINMENU_STUDIUM
-	db 4
+	db 4 + DEF(_DEBUG)
 	db MAINMENUITEM_CONTINUE
 	db MAINMENUITEM_NEW_GAME
 	db MAINMENUITEM_OPTION
 	db MAINMENUITEM_MOBILE_STUDIUM
+if DEF(_DEBUG)
+	db MAINMENUITEM_DEBUG_ROOM
+endc
 	db -1
 
 MainMenu_GetWhichMenu:
--- a/engine/overworld/time.asm
+++ b/engine/overworld/time.asm
@@ -25,6 +25,20 @@
 	ld hl, .ReceiveCallDelays
 	add hl, de
 	ld a, [hl]
+if DEF(_DEBUG)
+	ld h, a
+	ld a, BANK(sDebugTimeCyclesSinceLastCall)
+	call OpenSRAM
+	ld a, [sDebugTimeCyclesSinceLastCall]
+	call CloseSRAM
+	dec a
+	cp 2
+	jr nc, .debug_ok
+	xor 1
+	ld h, a
+.debug_ok
+	ld a, h
+endc
 	jp RestartReceiveCallDelay
 
 .ReceiveCallDelays:
--- a/engine/pokemon/stats_screen.asm
+++ b/engine/pokemon/stats_screen.asm
@@ -185,6 +185,10 @@
 .check
 	bit A_BUTTON_F, a
 	jr nz, .quit
+if DEF(_DEBUG)
+	cp START
+	jr z, .hatch
+endc
 	and D_DOWN | D_UP | A_BUTTON | B_BUTTON
 	jp StatsScreen_JoypadAction
 
@@ -193,6 +197,39 @@
 	call StatsScreen_SetJumptableIndex
 	ret
 
+if DEF(_DEBUG)
+.hatch
+	ld a, [wMonType]
+	or a
+	jr nz, .skip
+	push bc
+	push de
+	push hl
+	ld a, [wCurPartyMon]
+	ld bc, PARTYMON_STRUCT_LENGTH
+	ld hl, wPartyMon1Happiness
+	call AddNTimes
+	ld [hl], 1
+	ld a, 1
+	ld [wTempMonHappiness], a
+	ld a, 127
+	ld [wStepCount], a
+	ld de, .HatchSoonString
+	hlcoord 8, 17
+	call PlaceString
+	ld hl, wcf64
+	set 5, [hl]
+	pop hl
+	pop de
+	pop bc
+.skip
+	xor a
+	jp StatsScreen_JoypadAction
+
+.HatchSoonString:
+	db "▶HATCH SOON!@"
+endc
+
 StatsScreen_LoadPage:
 	call StatsScreen_LoadGFX
 	ld hl, wcf64
@@ -970,6 +1007,17 @@
 	ld de, FiveQMarkString
 	hlcoord 11, 5
 	call PlaceString
+if DEF(_DEBUG)
+	ld de, .PushStartString
+	hlcoord 8, 17
+	call PlaceString
+	jr .placed_push_start
+
+.PushStartString:
+	db "▶PUSH START.@"
+
+.placed_push_start
+endc
 	ld a, [wTempMonHappiness] ; egg status
 	ld de, EggSoonString
 	cp $6
--- a/home/map.asm
+++ b/home/map.asm
@@ -1138,7 +1138,7 @@
 	ld d, $0
 	ld hl, wObjectMasks
 	add hl, de
-	ld [hl], -1 ; , masked
+	ld [hl], -1 ; masked
 	ret
 
 UnmaskObject::
@@ -1149,6 +1149,28 @@
 	add hl, de
 	ld [hl], 0 ; unmasked
 	ret
+
+if DEF(_DEBUG)
+ComputeROMXChecksum::
+	ldh a, [hROMBank]
+	push af
+	ld a, c
+	rst Bankswitch
+	ld hl, $4000 ; ROMX start
+.loop
+	ld a, [hli]
+	add e
+	ld e, a
+	ld a, d
+	adc 0
+	ld d, a
+	ld a, h
+	cp $80 ; HIGH(ROMX end)
+	jr c, .loop
+	pop af
+	rst Bankswitch
+	ret
+endc
 
 ScrollMapUp::
 	hlcoord 0, 0
--- a/home/sram.asm
+++ b/home/sram.asm
@@ -2,6 +2,22 @@
 ; if invalid bank, sram is disabled
 	cp NUM_SRAM_BANKS
 	jr c, .valid
+if DEF(_DEBUG)
+	push af
+	push bc
+	ld b, 1
+.loop
+	sla b
+	dec a
+	jr nz, .loop
+	ld a, BANK(sOpenedInvalidSRAM)
+	call OpenSRAM
+	ld a, [sOpenedInvalidSRAM]
+	or b
+	ld [sOpenedInvalidSRAM], a
+	pop bc
+	pop af
+endc
 	jr CloseSRAM
 
 .valid:
--- a/hram.asm
+++ b/hram.asm
@@ -165,6 +165,10 @@
 hDMATransfer:: db
 hMobile:: db
 hSystemBooted:: db
+
+if DEF(_DEBUG)
+hDebugRoomMenuPage::
+endc
 hClockResetTrigger:: db
 
 	ds 19
--- a/layout.link
+++ b/layout.link
@@ -294,6 +294,7 @@
 	"Tileset Data 7"
 	"bank77_2"
 ROMX $78
+	"Debug Room"
 	"Tileset Data 8"
 ROMX $7b
 	"Battle Tower Text"
--- a/main.asm
+++ b/main.asm
@@ -290,7 +290,7 @@
 INCLUDE "engine/events/engine_flags.asm"
 INCLUDE "engine/overworld/variables.asm"
 INCLUDE "data/text/battle.asm"
-INCLUDE "engine/menus/debug.asm"
+INCLUDE "engine/debug/color_picker.asm"
 
 
 SECTION "bank21", ROMX
@@ -696,6 +696,13 @@
 INCLUDE "engine/pokemon/european_mail.asm"
 
 
+SECTION "Debug Room", ROMX
+
+if DEF(_DEBUG)
+INCLUDE "engine/debug/debug_room.asm"
+endc
+
+
 SECTION "Battle Tower Text", ROMX
 
 INCLUDE "data/battle_tower/trainer_text.asm"
@@ -722,7 +729,15 @@
 if DEF(_CRYSTAL_AU)
 INCBIN "mobile/stadium/stadium2_au.bin"
 elif DEF(_CRYSTAL11)
+if DEF(_DEBUG)
+INCBIN "mobile/stadium/stadium2_11_debug.bin"
+else
 INCBIN "mobile/stadium/stadium2_11.bin"
+endc
 else
+if DEF(_DEBUG)
+INCBIN "mobile/stadium/stadium2_debug.bin"
+else
 INCBIN "mobile/stadium/stadium2.bin"
+endc
 endc
--- a/mobile/mobile_menu.asm
+++ b/mobile/mobile_menu.asm
@@ -844,3 +844,9 @@
 	dec b
 	jr nz, Function4a6d8
 	ret
+
+if DEF(_DEBUG)
+MainMenu_DebugRoom:
+	farcall _DebugRoom
+	ret
+endc
binary files /dev/null b/mobile/stadium/stadium2_11_debug.bin differ
binary files /dev/null b/mobile/stadium/stadium2_debug.bin differ
--- a/roms.sha1
+++ b/roms.sha1
@@ -1,3 +1,5 @@
 f4cd194bdee0d04ca4eac29e09b8e4e9d818c133 *pokecrystal.gbc
 f2f52230b536214ef7c9924f483392993e226cfb *pokecrystal11.gbc
-a0fc810f1d4e124434f7be2c989ab5b5892ddf36 *pokecrystal-au.gbc
+a0fc810f1d4e124434f7be2c989ab5b5892ddf36 *pokecrystal_au.gbc
+c60d57a24bbe8ecf7cba54ab3f90669f97bd330d *pokecrystal_debug.gbc
+391ae86b1d5a26db712ffe6c28bbf2a1f804c3c4 *pokecrystal11_debug.gbc
--- a/sram.asm
+++ b/sram.asm
@@ -90,6 +90,14 @@
 
 sStackTop:: dw
 
+if DEF(_DEBUG)
+sRTCHaltCheckValue:: dw
+sSkipBattle:: db
+sDebugTimeCyclesSinceLastCall:: db
+sOpenedInvalidSRAM:: db
+sIsBugMon:: db
+endc
+
 
 SECTION "Save", SRAM
 
--- a/wram.asm
+++ b/wram.asm
@@ -1177,6 +1177,49 @@
 wccb8:: ds 1
 wccb9:: ds 1
 wccba:: ds 102
+
+if DEF(_DEBUG)
+NEXTU
+; debug room
+
+; debug room RTC values
+wDebugRoomRTCSec::  db
+wDebugRoomRTCMin::  db
+wDebugRoomRTCHour:: db
+wDebugRoomRTCDay::  dw
+wDebugRoomRTCCurSec::  db
+wDebugRoomRTCCurMin::  db
+wDebugRoomRTCCurHour:: db
+wDebugRoomRTCCurDay::  dw
+
+; debug room paged values
+wDebugRoomCurPage::        db
+wDebugRoomCurValue::       db
+wDebugRoomAFunction::      dw
+wDebugRoomStartFunction::  dw
+wDebugRoomSelectFunction:: dw
+wDebugRoomAutoFunction::   dw
+wDebugRoomPageCount::      db
+wDebugRoomPagedValuesPtr:: dw
+
+wDebugRoomROMChecksum:: dw
+wDebugRoomCurChecksumBank:: db
+
+UNION
+; debug room new item values
+wDebugRoomItemID::       db
+wDebugRoomItemQuantity:: db
+NEXTU
+; debug room new pokemon values
+wDebugRoomMon::    box_struct wDebugRoomMon
+wDebugRoomMonBox:: db
+NEXTU
+; debug room GB ID values
+wDebugRoomGBID:: dw
+ENDU
+
+endc
+
 ENDU