summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--audio/engine.asm11
-rw-r--r--charmap.asm34
-rw-r--r--constants.asm4
-rw-r--r--constants/serial_constants.asm17
-rw-r--r--engine/link/place_waiting_text.asm11
-rw-r--r--home.asm64
-rw-r--r--home/audio.asm10
-rw-r--r--home/clear_sprites.asm2
-rw-r--r--home/copy.asm4
-rw-r--r--home/init.asm4
-rw-r--r--home/lcd.asm7
-rw-r--r--home/oam_dma.asm2
-rw-r--r--home/predef.asm28
-rw-r--r--home/serial.asm2
-rw-r--r--hram.asm10
-rw-r--r--macros.asm9
-rw-r--r--main.asm4
-rw-r--r--shim.sym81
-rw-r--r--wram.asm134
20 files changed, 288 insertions, 154 deletions
diff --git a/Makefile b/Makefile
index 93cfddb..8d0f2db 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@
ROMS := pokegold-spaceworld.gb
BASEROM := baserom.gb
-OBJS := home.o main.o wram.o hram.o shim.o
+OBJS := home.o main.o audio.o sram.o wram.o hram.o shim.o
# Link objects together to build a rom.
all: $(ROMS) compare
@@ -34,7 +34,7 @@ $(ROMS): $(OBJS)
rgbfix -f -v -k 01 -l 0x33 -m 0x03 -p 0 -r 3 -t "POKEMON2GOLD" $@
compare: $(ROMS) $(BASEROM)
- cmp $^
+ cmp -l $^
# Remove files generated by the build process.
clean:
diff --git a/audio/engine.asm b/audio/engine.asm
index e008e9d..779f7e0 100644
--- a/audio/engine.asm
+++ b/audio/engine.asm
@@ -30,8 +30,8 @@ _DisableAudio:: ; 3a:4000
xor a
ld [hli], a
dec de
- ld a, d
- or e
+ ld a, e
+ or d
jr nz, .clear
ld a, $77
@@ -124,7 +124,7 @@ SetLRTracks: ; 3a:4d51
maskbits NUM_MUSIC_CHANS
ld e, a
ld d, 0
- ld hl, 52B3 ; FIXME
+ ld hl, $52B3 ; FIXME
add hl, de
ld a, [hl]
ld hl, wChannel1Tracks - wChannel1
@@ -157,3 +157,8 @@ _PlayMusic:: ; 3a:4d66
push af
call LoadChannel
call StartChannel
+ pop af
+ dec a
+ jr nz, .loop
+ xor a
+ ; TODO
diff --git a/charmap.asm b/charmap.asm
index 1d25197..eef4f64 100644
--- a/charmap.asm
+++ b/charmap.asm
@@ -229,21 +229,29 @@
charmap "ァ", $e9
charmap "ゥ", $ea
charmap "ェ", $eb
+
+ charmap "▷", $ec
+ charmap "▶", $ed
+ charmap "▲", $ed
+ charmap "▼", $ee
+ charmap "♂", $ef
charmap "円", $f0
-
- charmap ".", $f2
- charmap "/", $f3
+ charmap "×", $f1
+ charmap ".", $f2
+ charmap "/", $f3
charmap "ォ", $f4
+
+ charmap "♀", $f5
- charmap "0", $f6
- charmap "1", $f7
- charmap "2", $f8
- charmap "3", $f9
- charmap "4", $fa
- charmap "5", $fb
- charmap "6", $fc
- charmap "7", $fd
- charmap "8", $fe
- charmap "9", $ff
+ charmap "0", $f6
+ charmap "1", $f7
+ charmap "2", $f8
+ charmap "3", $f9
+ charmap "4", $fa
+ charmap "5", $fb
+ charmap "6", $fc
+ charmap "7", $fd
+ charmap "8", $fe
+ charmap "9", $ff
diff --git a/constants.asm b/constants.asm
index e2ea93a..691e6c6 100644
--- a/constants.asm
+++ b/constants.asm
@@ -2,8 +2,9 @@ INCLUDE "charmap.asm"
INCLUDE "macros.asm"
-INCLUDE "constants/hardware_constants.asm"
+INCLUDE "constants/audio_constants.asm"
INCLUDE "constants/gfx_constants.asm"
+INCLUDE "constants/hardware_constants.asm"
INCLUDE "constants/text_constants.asm"
INCLUDE "constants/type_constants.asm"
@@ -11,3 +12,4 @@ INCLUDE "constants/pokedex_constants.asm"
INCLUDE "constants/pokemon_data_constants.asm"
INCLUDE "constants/move_constants.asm"
INCLUDE "constants/item_constants.asm"
+INCLUDE "constants/serial_constants.asm"
diff --git a/constants/serial_constants.asm b/constants/serial_constants.asm
new file mode 100644
index 0000000..e475798
--- /dev/null
+++ b/constants/serial_constants.asm
@@ -0,0 +1,17 @@
+; serial
+
+ESTABLISH_CONNECTION_WITH_INTERNAL_CLOCK EQU $01
+ESTABLISH_CONNECTION_WITH_EXTERNAL_CLOCK EQU $02
+
+USING_EXTERNAL_CLOCK EQU $01
+USING_INTERNAL_CLOCK EQU $02
+CONNECTION_NOT_ESTABLISHED EQU $ff
+
+; signals the start of an array of bytes transferred over the link cable
+SERIAL_PREAMBLE_BYTE EQU $FD
+
+; this byte is used when there is no data to send
+SERIAL_NO_DATA_BYTE EQU $FE
+
+; signals the end of one part of a patch list (there are two parts) for player/enemy party data
+SERIAL_PATCH_LIST_PART_TERMINATOR EQU $FF
diff --git a/engine/link/place_waiting_text.asm b/engine/link/place_waiting_text.asm
index 19d4a6a..96458f0 100644
--- a/engine/link/place_waiting_text.asm
+++ b/engine/link/place_waiting_text.asm
@@ -7,11 +7,14 @@ PlaceWaitingText:: ; 1:4000
ld a, [wBattleMode]
and a
jr z, .link_textbox
- call Textbox
+ call DrawTextBox
jr .textbox_done
.link_textbox
- predef Predef_LinkTextbox
+ ; TODO
+ ; predef Predef_LinkTextbox
+ ld a, $1C
+ call Predef
.textbox_done
hlcoord 4, 11
ld de, .Waiting
@@ -19,5 +22,5 @@ PlaceWaitingText:: ; 1:4000
ld c, 50
jp DelayFrames
-.Waiting:
- db "Waiting...!@" \ No newline at end of file
+.Waiting
+ db "つうしんたいきちゅう!@" \ No newline at end of file
diff --git a/home.asm b/home.asm
index 8d4fd91..53df26e 100644
--- a/home.asm
+++ b/home.asm
@@ -1,22 +1,54 @@
INCLUDE "constants.asm"
-SECTION "Entry point", ROM0[$100]
- nop
- jp Init
-
-SECTION "Global check value", ROM0[$14E]
-; The ROM has an incorrect global check, so set it here
-; It is not corrected by RGBFIX
- db $21, $C6
-
+INCLUDE "home/rst.asm"
+INCLUDE "home/interrupts.asm"
+INCLUDE "home/init.asm"
+INCLUDE "home/vblank.asm"
+INCLUDE "home/lcd.asm"
+INCLUDE "home/serial.asm"
-SECTION "VBlank handler", ROM0[$150]
- ; TODO
+SECTION "Empty function", ROM0[$2F97]
-
-SECTION "Init", ROM0[$52F]
-
-Init:
- di
+InexplicablyEmptyFunction:: ; 2f97
+REPT 16
+ nop
+ENDR
+ ret
+
+INCLUDE "home/farcall.asm"
+INCLUDE "home/predef.asm"
+INCLUDE "home/sram.asm"
+INCLUDE "home/bankswitch.asm"
+INCLUDE "home/clear_sprites.asm"
+INCLUDE "home/copy.asm"
+INCLUDE "home/copy_tilemap.asm"
+INCLUDE "home/audio.asm"
+INCLUDE "home/oam_dma.asm"
+
+
+; TODO:
+; 1. Figure out what these are. Might be related to RTC, like ClearRTCStatus and the ilk.
+; 2. Give them proper names.
+; 3. Move them to their own file(s).
+
+SECTION "Unknown functions", ROM0[$1FF4]
+
+_1FF4:: ; 1ff4
+ ld a, BANK(s0_a600)
+ call OpenSRAM
+ ld hl, s0_a600 ; TODO: label this.
+ ld bc, 7
xor a
+ call ByteFill
+ call CloseSRAM
+ ret
+
+_2007:: ; 2007
+ ld a, BANK(s0_a600)
+ call OpenSRAM
+ ld a, [s0_a600]
+ and 8
+ ld [wce5f], a
+ call CloseSRAM
+ ret
diff --git a/home/audio.asm b/home/audio.asm
index bb49d42..cc0c0f9 100644
--- a/home/audio.asm
+++ b/home/audio.asm
@@ -1,4 +1,4 @@
-SECTION "Audio", ROM0[$3CBF]
+SECTION "Audio interface", ROM0[$3CBF]
DisableAudio:: ; 3cbf
push hl
@@ -42,7 +42,7 @@ UpdateSound:: ; 3cdb
ret
-LoadMusicByte:: ; 3cf7
+_LoadMusicByte:: ; 3cf7
ld [MBC3RomBank], a ; Unsafe
ldh [hROMBank], a
ld a, [de]
@@ -127,10 +127,10 @@ PlaySFX:: ; 3d63
push af
ldh a, [hROMBank]
push af
- ld a, BANK(PlaySFX_)
+ ld a, BANK(_PlaySFX)
ld [MBC3RomBank], a ; Unsafe
ldh [hROMBank], a
- call PlaySFX_
+ call _PlaySFX
pop af
ld [MBC3RomBank], a ; Unsafe
ldh [hROMBank], a
@@ -140,4 +140,4 @@ PlaySFX:: ; 3d63
pop hl
ret
-
+WaitPlaySFX:: ; 3d7f
diff --git a/home/clear_sprites.asm b/home/clear_sprites.asm
index 9ce9a54..64f8706 100644
--- a/home/clear_sprites.asm
+++ b/home/clear_sprites.asm
@@ -16,7 +16,7 @@ HideSprites:: ; 32e7
ld b, NUM_SPRITE_OAM_STRUCTS
ld a, $A0
.loop
- ld [hli], a
+ ld [hl], a
add hl, de
dec b
jr nz, .loop
diff --git a/home/copy.asm b/home/copy.asm
index f89bd49..ce66daf 100644
--- a/home/copy.asm
+++ b/home/copy.asm
@@ -62,7 +62,7 @@ ByteFill:: ; 3339
.loop
ld [hli], a
dec c
- jr z, .loop
+ jr nz, .loop
dec b
- jr z, .loop
+ jr nz, .loop
ret
diff --git a/home/init.asm b/home/init.asm
index fcafa3c..2fc2105 100644
--- a/home/init.asm
+++ b/home/init.asm
@@ -31,6 +31,7 @@ Init: ; 052f
ld [rTAC], a
ld a, 1 << rLCDC_ENABLE
ld [rLCDC], a
+ call DisableLCD
ld sp, wStackBottom
call ClearVRAM
@@ -70,7 +71,7 @@ Init: ; 052f
ldh [hLinkPlayerNumber], a
ld h, HIGH($9800)
call BlankBGMap
- ld h, HIGH($9800)
+ ld h, HIGH($9C00)
call BlankBGMap
ld a, LCDC_DEFAULT
ld [rLCDC], a
@@ -107,6 +108,7 @@ Init: ; 052f
ClearVRAM: ; 05e6
ld hl, VRAM_Begin
ld bc, VRAM_End - VRAM_Begin
+ xor a
call ByteFill
ret
diff --git a/home/lcd.asm b/home/lcd.asm
index dcf6bfa..1b23545 100644
--- a/home/lcd.asm
+++ b/home/lcd.asm
@@ -44,11 +44,12 @@ LCD:: ; 03ae
; 0:3e1
- sine_table 16
+; TODO: can this be done using `sine_table`?
+ db 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, 3, 3, 2, 2, 1, 0, -1, -2, -2, -3, -3, -4, -4, -4, -4, -4, -3, -3, -2, -2, -1
DisableLCD:: ; 0401
- ld a, [rLY]
+ ld a, [rLCDC]
bit 7, a
ret z
xor a
@@ -59,7 +60,7 @@ DisableLCD:: ; 0401
ld [rIE], a
.wait
ld a, [rLY]
- cp LY_VBLANK
+ cp LY_VBLANK + 1
jr nz, .wait
ld a, [rLCDC]
and $7F ; Shut LCD down
diff --git a/home/oam_dma.asm b/home/oam_dma.asm
index 958e88c..1737456 100644
--- a/home/oam_dma.asm
+++ b/home/oam_dma.asm
@@ -15,8 +15,8 @@ WriteOAMDMACodeToHRAM:: ; 4153
.OAMDMA ; 4161
ld a, HIGH(wVirtualOAM)
ldh [rDMA], a
-.wait
ld a, $28
+.wait
dec a
jr nz, .wait
ret
diff --git a/home/predef.asm b/home/predef.asm
index 6c85236..53af045 100644
--- a/home/predef.asm
+++ b/home/predef.asm
@@ -11,7 +11,7 @@ Predef:: ; 2fde
ld hl, .return
push hl
push de
- jr .save_regs
+ jr .get_regs
.return
ld a, h
@@ -27,17 +27,17 @@ Predef:: ; 2fde
ld l, a
ret
-.save_regs
- ld a, h
- ld [wPredefHL], a
- ld a, l
- ld [wPredefHL + 1], a
- ld a, d
- ld [wPredefDE], a
- ld a, e
- ld [wPredefDE + 1], a
- ld a, b
- ld [wPredefBC], a
- ld a, c
- ld [wPredefBC + 1], a
+.get_regs
+ ld a, [wPredefHL]
+ ld h, a
+ ld a, [wPredefHL + 1]
+ ld l, a
+ ld a, [wPredefDE]
+ ld d, a
+ ld a, [wPredefDE + 1]
+ ld e, a
+ ld a, [wPredefBC]
+ ld b, a
+ ld a, [wPredefBC + 1]
+ ld c, a
ret
diff --git a/home/serial.asm b/home/serial.asm
index b474e5d..42bd643 100644
--- a/home/serial.asm
+++ b/home/serial.asm
@@ -39,7 +39,7 @@ Serial::
jr .done
.master
xor a
- ld [rSC], a
+ ld [rSB], a
.done
ld a, 1
diff --git a/hram.asm b/hram.asm
index c2b654d..6d33f66 100644
--- a/hram.asm
+++ b/hram.asm
@@ -15,13 +15,7 @@ hVBlank:: ; ff99
db
- ds 8 ; TODO
-
-
- ds 3 ; 3 joypad constants, TODO: investigate
-
-
- ds 47 ; TODO
+ ds 54 ; TODO
hLCDCPointer:: ; ffd0
@@ -52,6 +46,8 @@ hSCY:: db ; ffda
hWX:: db ; ffdb
hWY:: db ; ffdc
+ db ; TODO
+
hBGMapMode:: ; ffde
db
diff --git a/macros.asm b/macros.asm
index 25c1ed6..07e5b41 100644
--- a/macros.asm
+++ b/macros.asm
@@ -1,6 +1,7 @@
+INCLUDE "macros/code.asm"
+INCLUDE "macros/coords.asm"
+INCLUDE "macros/data.asm"
INCLUDE "macros/enum.asm"
-INCLUDE "macros/predef.asm"
INCLUDE "macros/farcall.asm"
-INCLUDE "macros/data.asm"
-INCLUDE "macros/code.asm"
-INCLUDE "macros/coords.asm" \ No newline at end of file
+INCLUDE "macros/predef.asm"
+INCLUDE "macros/wram.asm"
diff --git a/main.asm b/main.asm
index 74e2bdc..0bb0250 100644
--- a/main.asm
+++ b/main.asm
@@ -1,5 +1,9 @@
INCLUDE "constants.asm"
+; bank 1
+INCLUDE "engine/link/place_waiting_text.asm"
+INCLUDE "engine/title.asm"
+INCLUDE "engine/predef.asm"
; TODO
SECTION "Font Gfx", ROMX[$4362], BANK[$3e]
diff --git a/shim.sym b/shim.sym
index f62e47f..15d020b 100644
--- a/shim.sym
+++ b/shim.sym
@@ -1,14 +1,6 @@
; ROM0
00:0317 DelayFrame
00:0324 DelayFrames
-00:0401 DisableLCD
-00:0410 DisableLCD.wait
-00:0423 EnableLCD
-00:05E6 ClearVRAM
-00:05F1 BlankBGMap
-00:05F1 FillBGMap
-00:05F6 _FillBGMap
-00:05FA _FillBGMap.loop
00:0884 UpdateJoypad
00:0d1a LoadFontExtra
00:0d0a LoadFont
@@ -27,32 +19,12 @@
00:1e58 OpenMenu
00:1F9E ClearWindowData
00:1FCC ClearWindowData.bytefill
-00:2007 Unk_2007
00:20ff RunMapScript
00:232c LoadMapWarp
00:23e5 OverworldFadeIn
-00:2FA8 FarCall_hl
-00:2FC8 FarCall_hl.return
-00:2FDE Predef
-00:2FF6 Predef.return
-00:300C Predef.saveregs
00:3270 Random
-00:32A7 OpenSRAM
-00:32B7 CloseSRAM
-00:32C2 Bankswitch
-00:32DC ClearSprites
-00:32E2 ClearSprites.loop
-00:32F7 FarCopyBytes
-00:330A CopyBytes
-00:3313 CopyBytes.next
-00:331A CopyBytesSmall
-00:3321 GetFarByte
-00:3339 ByteFill
-00:3342 ByteFill.smallfill
-00:3343 ByteFill.startfilling
-00:3344 ByteFill.loop
00:3429 AddAMulBC
00:3621 WaitBGMap
00:362B SetPalettes
@@ -63,13 +35,6 @@
00:3655 SetHPPal.done
00:36C8 NamesPointers
00:36E0 GetName
-00:3CBF DisableAudio
-00:3CDB UpdateSound
-00:3CF7 LoadMusicByte_
-00:3D07 PlayMusic
-00:3D23 PlayCryHeader
-00:3D63 PlaySFX
-00:3D7F WaitPlaySFX
00:3D86 WaitSFX
00:3D87 WaitSFX.wait
00:3DA5 MaxVolume
@@ -86,19 +51,10 @@
00:3E1B GetMapMusic
00:3E2E GetMapMusic.unk_3E2E
00:3E32 Unk_3E32 ; What the f*** is this???
-; (edited)
-01:4153 LoadPushOAM
-01:415A LoadPushOAM.loop
-01:4161 PushOAM
-01:4167 PushOAM.wait
-01:416B PushOAMEnd
+
01:53cc MainMenu
-01:5D8C IntroSequence
01:5eb8 TitleFlameGfx
01:5f38 TitleNoteGfx
-01:62B0 GetPredefPointer
-01:62D3 PredefPointers
-01:62A5 GameInit
01:6FEC ItemNames
02:4856 DecompTownMapTilemap
@@ -142,13 +98,11 @@
30:4000 OverworldSpriteGfx
-3A:4000 DisableAudio_
-3A:4012 DisableAudio_.initchannel
-3A:4026 DisableAudio_.clearmusicmem
-3A:4037 UpdateSound_
-3A:4D66 PlayMusic_
-3A:4D9D PlayCryHeader_
-3A:4E22 PlaySFX_
+3A:4D9D _PlayCryHeader
+3A:4E22 _PlaySFX
+3A:4F11 LoadChannel
+3A:4F6C LoadMusicByte
+3A:52C7 Music
3e:4162 FontExtraGfx
3e:4762 FontBattleExtraGfx
@@ -161,23 +115,8 @@
3f:6750 PicTestMenu
3f:6755 PicTestMenu.loop
-3C:51CB CryHeaders
-
;00:BFFF sWindowStackTop
-00:C000 Music
-00:C0CB wChannel5Flags
-00:C0FD wChannel6Flags
-00:C12F wChannel7Flags
-00:C161 wChannel8Flags
-00:C199 wVolume
-00:C1AD wMapMusic
-00:C1AE wCryPitch
-00:C1B0 wCryLength
-00:C1BC wMusicEnd ; ? ; either wChannelsEnd or wMusicEnd, unsure
-00:C200 wOAMBuffer
-00:C2A0 wTileMap
-00:c40b wWhichPicTest ; Monster or Trainer test?
00:c5e8 wMapScriptNumber
00:ca22 wTrainerClass
00:cb5b wName
@@ -187,17 +126,9 @@
00:CC02 wMenuDataHeader
00:CC12 wMenuData2
00:CC22 wMenuData3
-00:CC38 wUnk_CC38 ; wceeb in pokegold
-00:cc39 wDebugWarpSelection
-00:CCCF wSGB
-00:CD4F wPredefID
-00:CD50 wPredefRegs
-00:CD54 wFarCallBCBuffer
00:cdbe wTargetMapUnk
00:cdbf wTargetMapGroup
00:cdc0 wTargetMapId
-00:CE3C wBuffer
-00:CE5F wUnk_CE5F
00:CE62 wTextBoxFlags
00:ce67 wPlayerName
diff --git a/wram.asm b/wram.asm
index 98ccd5d..4f57225 100644
--- a/wram.asm
+++ b/wram.asm
@@ -1,4 +1,136 @@
INCLUDE "constants.asm"
-; TODO
+SECTION "Music engine RAM", WRAM0[$C000]
+
+wMusic:: ; c000
+
+wChannels::
+wChannel1:: channel_struct wChannel1 ; c000
+wChannel2:: channel_struct wChannel2 ; c032
+wChannel3:: channel_struct wChannel3 ; c064
+wChannel4:: channel_struct wChannel4 ; c096
+
+wSFXChannels::
+wChannel5:: channel_struct wChannel5 ; c0c8
+wChannel6:: channel_struct wChannel6 ; c0fa
+wChannel7:: channel_struct wChannel7 ; c12c
+wChannel8:: channel_struct wChannel8 ; c15e
+
+ ds 8 ; TODO
+
+wCurChannel:: ; c198
+ db
+
+wVolume:: ; c199
+ db
+
+ ds 2 ; TODO
+
+wMusicID:: ; c19c
+ dw
+
+wMusicBank:: ; c19e
+ db
+
+ ds 14 ; TODO
+
+wMapMusic:: ; c1ad
+ db
+
+wCryPitch:: ; c1ae
+ dw
+
+wCryLength:: ; c1b0
+ dw
+
+ ds 10 ; TODO
+
+
+; either wChannelsEnd or wMusicEnd, unsure
+wMusicInitEnd:: ; c1bc
+
+
+SECTION "OAM buffer", WRAM0[$C200]
+
+wVirtualOAM:: ; c200
+ ds SPRITEOAMSTRUCT_LENGTH * NUM_SPRITE_OAM_STRUCTS
+wVirtualOAMEnd::
+
+wTileMap:: ; c2a0
+ ds SCREEN_HEIGHT * SCREEN_WIDTH
+
+UNION
+
+wTileMapBackup:: ; c408
+ ds SCREEN_HEIGHT * SCREEN_WIDTH
+
+NEXTU
+
+ ds 3
+
+; Monster or Trainer test?
+wWhichPicTest:: ; c40b
+ db
+
+ENDU
+
+
+SECTION "LY overrides buffer", WRAM0[$C600]
+
+wLYOverrides:: ; c600
+ ds SCREEN_HEIGHT_PX
+
+
+SECTION "CC38", WRAM0[$CC38] ; Please merge when more is disassembled
+
+wcc38:: ; cc38 ; TODO: wceeb in pokegold, what is this?
+ db
+
+wDebugWarpSelection:: ; cc39
+ db
+
+ ds 6
+
+wSGB:: ; cccf
+ db
+
+
+SECTION "CD4F", WRAM0[$CD4F]
+
+wPredefID:: ; cd4f
+ db
+
+wPredefHL:: ; cd50
+ dw
+wPredefDE:: ; cd52
+ dw
+wPredefBC:: ; cd54
+
+wFarCallBCBuffer:: ; cd54
+ dw
+
+
+SECTION "CE00", WRAM0[$CE00]
+
+wBattleMode:: ; ce00
+ db
+
+
+SECTION "CE3C", WRAM0[$CE3C]
+
+wBuffer:: ; ce3c
+ db
+
+
+SECTION "CE5F", WRAM0[$CE5F]
+
+wce5f:: ; ce5f ; TODO
+ db
+
+
+SECTION "Stack bottom", WRAM0[$DFFF]
+
+; Where SP is set at game init
+wStackBottom:: ; dfff
+; Due to the way the stack works (`push` first decrements, then writes), the byte at $DFFF is actually wasted