diff options
36 files changed, 1974 insertions, 54 deletions
@@ -6,7 +6,7 @@ ROMS := pokegold-spaceworld.gb BASEROM := baserom.gb -OBJS := home.o main.o wram.o shim.o +OBJS := home.o main.o wram.o hram.o shim.o # Link objects together to build a rom. all: $(ROMS) compare @@ -27,10 +27,10 @@ $(foreach obj, $(OBJS), $(eval $(call DEP,$(obj),$(obj:.o=.asm)))) endif shim.asm: shim.sym - python3 tools/make_shim.py $^ > $@ + python3 tools/make_shim.py -w $^ > $@ $(ROMS): $(OBJS) - rgblink -n $(ROMS:.gb=.sym) -m $(ROMS:.gb=.map) -O $(BASEROM) -o $@ $^ + rgblink -d -n $(ROMS:.gb=.sym) -m $(ROMS:.gb=.map) -O $(BASEROM) -o $@ $^ rgbfix -f -v -k 01 -l 0x33 -m 0x03 -p 0 -r 3 -t "POKEMON2GOLD" $@ compare: $(ROMS) $(BASEROM) diff --git a/audio.asm b/audio.asm new file mode 100644 index 0000000..aec654c --- /dev/null +++ b/audio.asm @@ -0,0 +1,11 @@ +INCLUDE "constants.asm" + + +SECTION "Audio", ROMX[$4000],BANK[$3A] + +INCLUDE "audio/engine.asm" + + +SECTION "Cries", ROMX[$51CB],BANK[$3C] ; TODO: Temporary, please map 4000-51CA and move this section's base + +CryHeaders:: ; TODO: Rip the data, then INCBIN it diff --git a/audio/engine.asm b/audio/engine.asm new file mode 100644 index 0000000..e008e9d --- /dev/null +++ b/audio/engine.asm @@ -0,0 +1,159 @@ +_DisableAudio:: ; 3a:4000 + push hl + push de + push bc + push af + ld hl, rNR50 + xor a + ld [hli], a + ld [hli], a + ld a, $80 + ld [hli], a + ld hl, rNR10 + ld e, 4 +.init_channel + xor a + ld [hli], a + ld [hli], a + ld a, 8 + ld [hli], a + xor a + ld [hli], a + ld a, $80 + ld [hli], a + dec e + jr nz, .init_channel + + ld hl, wMusic + ld de, wMusicInitEnd - wMusic +.clear + xor a + ld [hli], a + dec de + ld a, d + or e + jr nz, .clear + + ld a, $77 + ld [wVolume], a + + pop af + pop bc + pop de + pop hl + ret + + +_UpdateSound:: ; 3a:4037 + xor a + ; So, I'm being told I need to disassemble this... + ; OH HELL NO + + ; ... TODO :/ + + + +SECTION "Audio engine, part 2", ROMX[$4CEE],BANK[$3A] ; TODO: disassemble what's above (gulp) and remove this + +SetGlobalTempo: ; 3a:4cee + push bc + ld a, [wCurChannel] + cp CHAN5 + jr nc, .sfxchannels + ld bc, wChannel1 + call Tempo + ld bc, wChannel2 + call Tempo + ld bc, wChannel3 + call Tempo + ld bc, wChannel4 + call Tempo + jr .end + +.sfxchannels + ld bc, wChannel5 + call Tempo + ld bc, wChannel6 + call Tempo + ld bc, wChannel7 + call Tempo + ld bc, wChannel8 + call Tempo + +.end + pop bc + ret + +Tempo: ; 3a:4d2a + ld hl, wChannel1Tempo - wChannel1 + add hl, bc + ld [hl], e + inc hl + ld [hl], d + xor a + ld hl, wChannel1Field16 - wChannel1 + add hl, bc + ld [hl], a + ret + + +StartChannel: ; 3a:4d38 + call SetLRTracks + ld hl, wChannel1Flags - wChannel1 + add hl, bc + set SOUND_CHANNEL_ON, [hl] + ret + + +StopChannel: ; 3a:4d42 + ld hl, wChannel1Flags - wChannel1 + add hl, bc + res SOUND_CHANNEL_ON, [hl] + ld hl, wChannel1MusicID - wChannel1 + add hl, bc + xor a + ld [hli], a + ld [hli], a + ld [hli], a + ret + + +SetLRTracks: ; 3a:4d51 + push de + ld a, [wCurChannel] + maskbits NUM_MUSIC_CHANS + ld e, a + ld d, 0 + ld hl, 52B3 ; FIXME + add hl, de + ld a, [hl] + ld hl, wChannel1Tracks - wChannel1 + add hl, bc + ld [hl], a + pop de + ret + + +_PlayMusic:: ; 3a:4d66 + ld hl, wMusicID + ld [hl], e + inc hl + ld [hl], d + ld hl, Music + add hl, de + add hl, de + add hl, de + ld a, [hli] + ld [wMusicBank], a + ld e, [hl] + inc hl + ld d, [hl] + call LoadMusicByte + rlca + rlca + maskbits NUM_MUSIC_CHANS + inc a +.loop + push af + call LoadChannel + call StartChannel diff --git a/constants/audio_constants.asm b/constants/audio_constants.asm new file mode 100644 index 0000000..c341e90 --- /dev/null +++ b/constants/audio_constants.asm @@ -0,0 +1,62 @@ + + +; pitch + const_def + const __ + const C_ + const C# + const D_ + const D# + const E_ + const F_ + const F# + const G_ + const G# + const A_ + const A# + const B_ + +; channel + const_def + const CHAN1 + const CHAN2 + const CHAN3 + const CHAN4 +NUM_MUSIC_CHANS EQU const_value +NUM_NOISE_CHANS EQU const_value + const CHAN5 + const CHAN6 + const CHAN7 + const CHAN8 +NUM_CHANNELS EQU const_value + +; Flags1 +SOUND_CHANNEL_ON EQU 0 +SOUND_SUBROUTINE EQU 1 +SOUND_LOOPING EQU 2 +SOUND_SFX EQU 3 +SOUND_NOISE EQU 4 +SOUND_REST EQU 5 + +; Flags2 + +SOUND_VIBRATO EQU 0 +SOUND_PITCH_WHEEL EQU 1 +SOUND_DUTY EQU 2 +SOUND_UNKN_0B EQU 3 +SOUND_CRY_PITCH EQU 4 +SOUND_UNKN_0D EQU 5 +SOUND_UNKN_0E EQU 6 +SOUND_UNKN_0F EQU 7 + +; Flags3 +SOUND_VIBRATO_DIR EQU 0 +SOUND_PITCH_WHEEL_DIR EQU 1 + +; NoteFlags +NOTE_UNKN_0 EQU 0 +NOTE_UNKN_1 EQU 1 +NOTE_UNKN_3 EQU 3 +NOTE_UNKN_4 EQU 4 +NOTE_REST EQU 5 +NOTE_UNKN_6 EQU 6 diff --git a/constants/hardware_constants.asm b/constants/hardware_constants.asm index d96672c..b47da72 100644 --- a/constants/hardware_constants.asm +++ b/constants/hardware_constants.asm @@ -124,6 +124,10 @@ rLCDC_SPRITE_SIZE EQU 2 ; 0=8x8, 1=8x16 rLCDC_WINDOW_TILEMAP EQU 6 ; 0=9800-9BFF, 1=9C00-9FFF rLCDC_ENABLE EQU 7 ; 0=Off, 1=On rSTAT EQU $ff41 ; LCDC Status (R/W) +rSTAT_HBLANK EQU 3 ; 0=Off, 1=On +rSTAT_VBLANK EQU 4 ; 0=Off, 1=On +rSTAT_MODE2 EQU 5 ; 0=Off, 1=On +rSTAT_LYC EQU 6 ; 0=Off, 1=On rSCY EQU $ff42 ; Scroll Y (R/W) rSCX EQU $ff43 ; Scroll X (R/W) rLY EQU $ff44 ; LCDC Y-Coordinate (R) diff --git a/constants/serial.asm b/constants/serial.asm new file mode 100644 index 0000000..e475798 --- /dev/null +++ b/constants/serial.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 new file mode 100644 index 0000000..19d4a6a --- /dev/null +++ b/engine/link/place_waiting_text.asm @@ -0,0 +1,23 @@ +SECTION "PlaceWaitingText", ROMX[$4000],BANK[1] + +PlaceWaitingText:: ; 1:4000 + hlcoord 3, 10 + ld b, 1 + ld c, 11 + ld a, [wBattleMode] + and a + jr z, .link_textbox + call Textbox + jr .textbox_done + +.link_textbox + predef Predef_LinkTextbox +.textbox_done + hlcoord 4, 11 + ld de, .Waiting + call PlaceString + ld c, 50 + jp DelayFrames + +.Waiting: + db "Waiting...!@"
\ No newline at end of file diff --git a/engine/predef.asm b/engine/predef.asm new file mode 100644 index 0000000..dca0283 --- /dev/null +++ b/engine/predef.asm @@ -0,0 +1,122 @@ +SECTION "Predef pointers", ROMX[$62B0],BANK[1] + +GetPredefPointer:: ; 1:62b0 + ld a, h + ld [wPredefHL], a + ld a, l + ld [wPredefHL + 1], a + ld hl, wPredefDE + ld a, d + ld [hli], a + ld a, e + ld [hli], a + ld a, b + ld [hli], a + ld [hl], c + + ld a, [wPredefID] + ld e, a + ld d, 0 + ld hl, PredefPointers + add hl, de + add hl, de + add hl, de + ld a, [hli] + ld e, [hl] + inc hl + ld d, [hl] + ret + +PredefPointers:: ; 1:62d3 + ; To YOU who is reading this: + ; Please be a peach and nuke the hell out of these: + ; WE NEED LABELS! + ; Thank youu~ + + dbw 1, $6445 ; 0 + dbw 1, $5D27 + dbw 1, $6713 + dbw 1, $66B1 + dbw 1, $4031 + dbw 3, $4E10 + dbw 3, $4D6F + dbw 3, $4DE3 + dbw 3, $4DE3 ; 8 + dbw 3, $4DE3 + dbw 3, $4DF9 + dbw 3, $4E10 + dbw 3, $4D33 + dbw 3, $366C + dbw 3, $4E3C + dbw 3, $5A28 + dbw 3, $5886 ; 10 + dbw 3, $5A4F + dbw 3, $5AC8 + dbw 3, $5CFC + dbw 3, $5C16 + dbw 3, $5D5C + dbw 3, $5E79 + dbw 3, $4E7C + dbw 3, $5F7D ; 18 + dbw 3, $5F91 + dbw 4, $528F + dbw 4, $52C1 + dbw 10, $4C98 + dbw 11, $5663 + dbw 15, $55CE + dbw 15, $7019 + dbw 15, $7068 ; 20 + dbw 15, $704A + dbw 15, $508C + dbw 15, $567C + dbw 15, $61A4 + dbw 15, $6F19 + dbw 15, $6874 + dbw 15, $691E + dbw 15, $6963 ; 28 + dbw 16, $61F8 + dbw 16, $6252 + dbw 16, $5FA1 + dbw 10, $4DA4 + dbw 10, $4D6E + dbw 16, $4AC7 + dbw 16, $4000 + dbw 16, $4B5C ; 30 + dbw 20, $4000 + dbw 20, $4BFE + dbw 20, $4BCD + dbw 20, $4B92 + dbw 20, $48C4 + dbw 20, $4771 + dbw 20, $4774 + dbw 20, $481F ; 38 + dbw 20, $46D4 + dbw 20, $469E + dbw 20, $42B5 + dbw 20, $4244 + dbw 20, $4248 + dbw 20, $40C6 + dbw 20, $40A0 + dbw 20, $4073 ; 40 + dbw 20, $4ED9 + dbw 50, $76FF + dbw 50, $7710 + dbw 50, $7733 + dbw 5, $45B8 + dbw 5, $46DC + dbw 5, $45DE + dbw 50, $4000 ; 48 + dbw 5, $457A + dbw 5, $43E0 + dbw 2, $5695 + dbw 2, $528B + dbw 2, $4786 + dbw 35, $44BE + dbw 35, $49C6 + dbw 35, $4940 ; 50 + dbw 51, $4001 + dbw 51, $4000 + dbw 51, $4000 + dbw 63, $5B66 + dbw 4, $640B + dbw $FF, InexplicablyEmptyFunction diff --git a/engine/title.asm b/engine/title.asm new file mode 100644 index 0000000..9df68ed --- /dev/null +++ b/engine/title.asm @@ -0,0 +1,14 @@ +SECTION "Title screen", ROMX[$5D8C],BANK[1] + +IntroSequence:: ; 5d8c + ; TODO + + +SECTION "Title screen TEMPORARY", ROMX[$62A5],BANK[1] ; TODO: merge this with the section above + +GameInit:: ; 62a5 + call ClearWindowData + ld a, $23 + ld [wce5f], a + jp IntroSequence + diff --git a/home/audio.asm b/home/audio.asm new file mode 100644 index 0000000..bb49d42 --- /dev/null +++ b/home/audio.asm @@ -0,0 +1,143 @@ +SECTION "Audio", ROM0[$3CBF] + +DisableAudio:: ; 3cbf + push hl + push de + push bc + push af + ldh a, [hROMBank] + push af + ld a, BANK(_DisableAudio) + ld [MBC3RomBank], a ; Unsafe + ldh [hROMBank], a + call _DisableAudio + pop af + ld [MBC3RomBank], a ; Unsafe + ldh [hROMBank], a + pop af + pop bc + pop de + pop hl + ret + + +UpdateSound:: ; 3cdb + push hl + push de + push bc + push af + ldh a, [hROMBank] + push af + ld a, BANK(_UpdateSound) + ld [MBC3RomBank], a ; Unsafe + ldh [hROMBank], a + call _UpdateSound + pop af + ld [MBC3RomBank], a ; Unsafe + ldh [hROMBank], a + pop af + pop bc + pop de + pop hl + ret + + +LoadMusicByte:: ; 3cf7 + ld [MBC3RomBank], a ; Unsafe + ldh [hROMBank], a + ld a, [de] + push af + ld a, BANK(_UpdateSound) + ld [MBC3RomBank], a ; Unsafe + ldh [hROMBank], a + pop af + ret + + +PlayMusic:: ; 3d07 + push hl + push de + push bc + push af + ldh a, [hROMBank] + push af + ld a, BANK(_PlayMusic) + ld [MBC3RomBank], a ; Unsafe + ldh [hROMBank], a + call _PlayMusic + pop af + ld [MBC3RomBank], a ; Unsafe + ldh [hROMBank], a + pop af + pop bc + pop de + pop hl + ret + + +PlayCryHeader:: ; 3d23 + push hl + push de + push bc + push af + ldh a, [hROMBank] + push af + + ld a, BANK(CryHeaders) + ld [MBC3RomBank], a ; Unsafe + ldh [hROMBank], a + ld hl, CryHeaders +REPT 6 + add hl, de +ENDR + ld e, [hl] + inc hl + ld d, [hl] + inc hl + ld a, [hli] + ld [wCryPitch], a + ld a, [hli] + ld [wCryPitch + 1], a + ld a, [hli] + ld [wCryLength], a + ld a, [hl] + ld [wCryLength + 1], a + + ld a, BANK(_PlayCryHeader) + ld [MBC3RomBank], a ; Unsafe + ldh [hROMBank], a + call _PlayCryHeader + + pop af + ld [MBC3RomBank], a ; Unsafe + ldh [hROMBank], a + pop af + pop bc + pop de + pop hl + ret + + + + +PlaySFX:: ; 3d63 + push hl + push de + push bc + push af + ldh a, [hROMBank] + push af + ld a, BANK(PlaySFX_) + ld [MBC3RomBank], a ; Unsafe + ldh [hROMBank], a + call PlaySFX_ + pop af + ld [MBC3RomBank], a ; Unsafe + ldh [hROMBank], a + pop af + pop bc + pop de + pop hl + ret + + diff --git a/home/bankswitch.asm b/home/bankswitch.asm new file mode 100644 index 0000000..67fae1a --- /dev/null +++ b/home/bankswitch.asm @@ -0,0 +1,8 @@ +SECTION "Bankswitch", ROM0[$32C2] + +; Moved to a rst vector in final US releases (not sure about JP) +; All rst vectors are unused at this point in development +Bankswitch:: ; 32c2 + ldh [hROMBank], a + ld [MBC3RomBank], a + ret diff --git a/home/clear_sprites.asm b/home/clear_sprites.asm new file mode 100644 index 0000000..9ce9a54 --- /dev/null +++ b/home/clear_sprites.asm @@ -0,0 +1,23 @@ +SECTION "Sprite clearing", ROM0[$32DC] + +ClearSprites:: ; 32dc + ld hl, wVirtualOAM + ld b, wVirtualOAMEnd - wVirtualOAM + xor a +.loop + ld [hli], a + dec b + jr nz, .loop + ret + +HideSprites:: ; 32e7 + ld hl, wVirtualOAM + ld de, SPRITEOAMSTRUCT_LENGTH + ld b, NUM_SPRITE_OAM_STRUCTS + ld a, $A0 +.loop + ld [hli], a + add hl, de + dec b + jr nz, .loop + ret diff --git a/home/copy.asm b/home/copy.asm new file mode 100644 index 0000000..f89bd49 --- /dev/null +++ b/home/copy.asm @@ -0,0 +1,68 @@ +SECTION "Copy functions", ROM0[$32F7] + +FarCopyBytes:: ; 32f7 + ld [wBuffer], a + ldh a, [hROMBank] + push af + ld a, [wBuffer] + call Bankswitch + call CopyBytes + pop af + jp Bankswitch + +CopyBytes:: ; 330a + ld a, b + and a + jr z, CopyBytesSmall + ld a, c + and a + jr z, .next + inc b +.next + call CopyBytesSmall + dec b + jr nz, .next + ret + +CopyBytesSmall:: ; 331a + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, CopyBytesSmall + ret + + +GetFarByte:: ; 3321 + ld [wBuffer], a + ldh a, [hROMBank] + push af + ld a, [wBuffer] + call Bankswitch + ld a, [hl] + ld [wBuffer], a + pop af + call Bankswitch + ld a, [wBuffer] + ret + + +ByteFill:: ; 3339 + push af + ld a, b + and a + jr z, .small_fill + ld a, c + and a + jr z, .start_filling +.small_fill + inc b +.start_filling + pop af +.loop + ld [hli], a + dec c + jr z, .loop + dec b + jr z, .loop + ret diff --git a/home/copy_tilemap.asm b/home/copy_tilemap.asm new file mode 100644 index 0000000..950bb24 --- /dev/null +++ b/home/copy_tilemap.asm @@ -0,0 +1,18 @@ +SECTION "Tilemap copy/restore funcs", ROM0[$3355] + +BackUpTilesToBuffer:: ; 3355 + hlcoord 0, 0 + decoord 0, 0, wTileMapBackup + ld bc, SCREEN_HEIGHT * SCREEN_WIDTH + jp CopyBytes + +ReloadTilesFromBuffer:: ; 3361 + xor a + ldh [hBGMapMode], a + hlcoord 0, 0, wTileMapBackup + decoord 0, 0 + ld bc, SCREEN_HEIGHT * SCREEN_WIDTH + call CopyBytes + ld a, 1 + ldh [hBGMapMode], a + ret diff --git a/home/farcall.asm b/home/farcall.asm new file mode 100644 index 0000000..68f8ab0 --- /dev/null +++ b/home/farcall.asm @@ -0,0 +1,36 @@ +SECTION "Farcall", ROM0[$2FA8] + +FarCall_hl:: ; 2fa8 + push af + ld a, b + ld [wFarCallBCBuffer], a + ld a, c + ld [wFarCallBCBuffer + 1], a + pop af + ld b, a + ldh a, [hROMBank] + push af + ld a, b + call Bankswitch + ld bc, .return + push bc + push hl + ld a, [wFarCallBCBuffer] + ld b, a + ld a, [wFarCallBCBuffer + 1] + ld c, a + ret + +.return + ld a, b + ld [wFarCallBCBuffer], a + ld a, c + ld [wFarCallBCBuffer + 1], a + pop bc + ld a, b + call Bankswitch + ld a, [wFarCallBCBuffer] + ld b, a + ld a, [wFarCallBCBuffer + 1] + ld c, a + ret diff --git a/home/init.asm b/home/init.asm new file mode 100644 index 0000000..fcafa3c --- /dev/null +++ b/home/init.asm @@ -0,0 +1,129 @@ +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 + + +SECTION "Init", ROM0[$52F] + +Init: ; 052f + di + xor a + ld [rIF], a + ld [rIE], a + ld [rSCX], a + ld [rSCY], a + ld [rSB], a + ld [rSC], a + ld [rWX], a + ld [rWY], a + ld [rBGP], a + ld [rOBP0], a + ld [rOBP1], a + ld [rTMA], a + ld [rTAC], a + ld [wcc38], a ; Useless, since WRAM gets cleared right after + ld a, 1 << rTAC_ON | rTAC_4096_HZ + ld [rTAC], a + ld a, 1 << rLCDC_ENABLE + ld [rLCDC], a + + ld sp, wStackBottom + call ClearVRAM + ld hl, WRAM0_Begin + ld bc, WRAM1_End - WRAM0_Begin +.ByteFill ; 0565 + ld [hl], 0 + inc hl + dec bc + ld a, b + or c + jr nz, .ByteFill + ld hl, HRAM_Begin + ld bc, HRAM_End - HRAM_Begin + call ByteFill + call ClearSprites + + ld a, BANK(WriteOAMDMACodeToHRAM) + call Bankswitch + call WriteOAMDMACodeToHRAM + + xor a + ldh [hMapAnims], a + ldh [hSCX], a + ldh [hSCY], a + ldh [rJOYP], a + ld a, 1 << rSTAT_HBLANK + ld [rSTAT], a + ld a, SCREEN_HEIGHT_PX + ldh [hWY], a + ld [rWY], a + ld a, 7 + ldh [hWX], a + ld [rWX], a + + ld a, $FF + ldh [hLinkPlayerNumber], a + ld h, HIGH($9800) + call BlankBGMap + ld h, HIGH($9800) + call BlankBGMap + ld a, LCDC_DEFAULT + ld [rLCDC], a + + call DisableAudio + call _2007 + ; predef ??? + ld a, $4B ; TODO: add predefs so the line above can be uncommented + call Predef + ld a, $1F + ld [rIE], a + ld a, HIGH($9C00) + ldh [hBGMapAddress + 1], a + xor a + ldh [hBGMapAddress], a + + call DisableLCD + call ClearVRAM + ld a, LCDC_DEFAULT + ld [rLCDC], a + ei + + ld a, SRAM_ENABLE + ld [MBC3SRamEnable], a + ld a, RTC_DH + ld [MBC3SRamBank], a + xor a + ld [SRAM_Begin], a + ld a, 0 ; Useless + ld [MBC3LatchClock], a + ld [MBC3SRamEnable], a + jp GameInit + +ClearVRAM: ; 05e6 + ld hl, VRAM_Begin + ld bc, VRAM_End - VRAM_Begin + call ByteFill + ret + +BlankBGMap: + ld a, $7F + jr _FillBGMap + +FillBGMap: + ld a, l + +_FillBGMap: + ld de, $400 + ld l, e +.loop + ld [hli], a + dec e + jr nz, .loop + dec d + jr nz, .loop + ret diff --git a/home/interrupts.asm b/home/interrupts.asm new file mode 100644 index 0000000..91610e0 --- /dev/null +++ b/home/interrupts.asm @@ -0,0 +1,26 @@ +SECTION "VBlank interrupt vector", ROM0[$040] + jp VBlank + +SECTION "LCD interrupt vector", ROM0[$048] + jp LCD + +SECTION "Timer interrupt vector", ROM0[$050] + jp TimerDummy + +SECTION "Serial interrupt vector", ROM0[$058] + jp Serial + +SECTION "Joypad interrupt vector", ROM0[$060] + jp JoypadDummy + + +SECTION "Timer dummy interrupt", ROM0[$42A] + +TimerDummy: ; 042a + reti + + +SECTION "Joypad dummy interrupt", ROM0[$7F7] + +JoypadDummy: ; 07f7 + reti
\ No newline at end of file diff --git a/home/lcd.asm b/home/lcd.asm new file mode 100644 index 0000000..dcf6bfa --- /dev/null +++ b/home/lcd.asm @@ -0,0 +1,77 @@ +SECTION "LCD functions", ROM0[$3AE] + +LCD:: ; 03ae + push af + ldh a, [hLCDCPointer] + and a + jr z, .done + push hl + rla + jr c, .try_hide_sprites + ld a, [rLY] + ld l, a + ld h, HIGH(wLYOverrides) + ld h, [hl] + ldh a, [hLCDCPointer] + ld l, a + ld a, h + ld h, $FF + ld [hl], a + pop hl + pop af + reti + +.try_hide_sprites + ld a, [rLY] + cp $80 + jr nz, .dont_hide + ld hl, rLCDC + res 1, [hl] +.dont_hide + pop hl + pop af + reti + + ; Seems unused? + ldh a, [hSCX] + ld [rSCX], a + ldh a, [hSCY] + ld [rSCY], a + pop hl +.done + pop af + reti + + +; 0:3e1 + sine_table 16 + + +DisableLCD:: ; 0401 + ld a, [rLY] + bit 7, a + ret z + xor a + ld [rIF], a + ld a, [rIE] + ld b, a + res 0, a + ld [rIE], a +.wait + ld a, [rLY] + cp LY_VBLANK + jr nz, .wait + ld a, [rLCDC] + and $7F ; Shut LCD down + ld [rLCDC], a + xor a + ld [rIF], a + ld a, b + ld [rIE], a + ret + +EnableLCD:: ; 0423 + ld a, [rLCDC] + set 7, a + ld [rLCDC], a + ret diff --git a/home/oam_dma.asm b/home/oam_dma.asm new file mode 100644 index 0000000..958e88c --- /dev/null +++ b/home/oam_dma.asm @@ -0,0 +1,23 @@ +SECTION "OAM DMA", ROMX[$4153],BANK[1] + +WriteOAMDMACodeToHRAM:: ; 4153 + ld c, LOW(hOAMDMA) + ld b, .OAMDMAEnd - .OAMDMA + ld hl, .OAMDMA +.loop + ld a, [hli] + ld [$ff00+c], a + inc c + dec b + jr nz, .loop + ret + +.OAMDMA ; 4161 + ld a, HIGH(wVirtualOAM) + ldh [rDMA], a +.wait + ld a, $28 + dec a + jr nz, .wait + ret +.OAMDMAEnd ; 416b diff --git a/home/predef.asm b/home/predef.asm new file mode 100644 index 0000000..6c85236 --- /dev/null +++ b/home/predef.asm @@ -0,0 +1,43 @@ +SECTION "Predef", ROM0[$2FDE] + +Predef:: ; 2fde + ld [wPredefID], a + ldh a, [hROMBank] + push af + ld a, BANK(GetPredefPointer) + call Bankswitch + call GetPredefPointer + call Bankswitch + ld hl, .return + push hl + push de + jr .save_regs + +.return + ld a, h + ld [wPredefHL], a + ld a, l + ld [wPredefHL + 1], a + pop hl + ld a, h ; Could have used `pop af` instead + call Bankswitch + ld a, [wPredefHL] + ld h, a + ld a, [wPredefHL + 1] + 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 + ret diff --git a/home/rst.asm b/home/rst.asm new file mode 100644 index 0000000..851775b --- /dev/null +++ b/home/rst.asm @@ -0,0 +1,25 @@ +; rst vectors + +SECTION "rst00", ROM0[$000] + rst $38 + +SECTION "rst08", ROM0[$008] + rst $38 + +SECTION "rst10", ROM0[$010] + rst $38 + +SECTION "rst18", ROM0[$018] + rst $38 + +SECTION "rst20", ROM0[$020] + rst $38 + +SECTION "rst28", ROM0[$028] + rst $38 + +SECTION "rst30", ROM0[$030] + rst $38 + +SECTION "rst38", ROM0[$038] + jp $F080 ; Jumps in the middle of unmapped memory. Probably used to trigger a breakpoint of sorts. diff --git a/home/serial.asm b/home/serial.asm new file mode 100644 index 0000000..b474e5d --- /dev/null +++ b/home/serial.asm @@ -0,0 +1,53 @@ +SECTION "Serial handler", ROM0[$602] + +Serial:: + push af + push bc + push de + push hl + ldh a, [hLinkPlayerNumber] + inc a + jr z, .init_player_number + + ld a, [rSB] + ldh [hSerialRecieve], a + ldh a, [hSerialSend] + ld [rSB], a + ldh a, [hLinkPlayerNumber] + cp 2 + jr z, .done + ld a, 1 << rSC_ON + ld [rSC], a + jr .done + +.init_player_number + ld a, [rSB] + ldh [hSerialRecieve], a + ldh [hLinkPlayerNumber], a + cp 2 + jr z, .master + xor a + ld [rSB], a + ld a, 3 + ld [rDIV], a +.wait + ld a, [rDIV] + bit 7, a + jr nz, .wait + ld a, 1 << rSC_ON + ld [rSC], a + jr .done +.master + xor a + ld [rSC], a + +.done + ld a, 1 + ldh [hSerialRecieved], a + ld a, SERIAL_NO_DATA_BYTE + ldh [hSerialSend], a + pop hl + pop de + pop bc + pop af + reti diff --git a/home/sram.asm b/home/sram.asm new file mode 100644 index 0000000..c204b9b --- /dev/null +++ b/home/sram.asm @@ -0,0 +1,19 @@ +SECTION "SRAM functions", ROM0[$32A7] + +OpenSRAM:: ; 32a7 + push af + ld a, 1 + ld [MBC3LatchClock], a + ld a, SRAM_ENABLE + ld [MBC3SRamEnable], a + pop af + ld [MBC3SRamBank], a + ret + +CloseSRAM:: ; 32b7 + push af + ld a, SRAM_DISABLE + ld [MBC3LatchClock], a + ld [MBC3SRamEnable], a + pop af + ret diff --git a/home/vblank.asm b/home/vblank.asm new file mode 100644 index 0000000..efa7196 --- /dev/null +++ b/home/vblank.asm @@ -0,0 +1,29 @@ +SECTION "VBlank handler", ROM0[$150] + +VBlank:: ; 0150 + push af + push bc + push de + push hl + ldh a, [hVBlank] + and 3 + ld e, a + ld d, 0 + ld hl, .blanks + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + ld de, .return + push de + jp hl +.return + pop hl + pop de + pop bc + pop af + reti + +.blanks + ; TODO diff --git a/hram.asm b/hram.asm new file mode 100644 index 0000000..c2b654d --- /dev/null +++ b/hram.asm @@ -0,0 +1,71 @@ +SECTION "HRAM", HRAM[$FF80] + +hOAMDMA:: ; ff80 + ds 10 + + + ds 14 ; TODO + + +hROMBank:: ; ff98 + db + + +hVBlank:: ; ff99 + db + + + ds 8 ; TODO + + + ds 3 ; 3 joypad constants, TODO: investigate + + + ds 47 ; TODO + + +hLCDCPointer:: ; ffd0 + db + + + ds 3 ; TODO + + +hSerialRecieved:: ; ffd4 + db + +hLinkPlayerNumber:: ; ffd5 + db + + + db ; TODO + + +hSerialSend:: ; ffd7 + db +hSerialRecieve:: ; ffd8 + db + + +hSCX:: db ; ffd9 +hSCY:: db ; ffda +hWX:: db ; ffdb +hWY:: db ; ffdc + +hBGMapMode:: ; ffde + db + + db ; TODO + +hBGMapAddress:: ; ffe0 + dw + + + ds 6 ; TODO + + +hMapAnims:: ; ffe8 + ; TODO: figure out size + + + ; TODO @@ -1 +1,6 @@ -INCLUDE "macros/enum.asm"
\ No newline at end of file +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 diff --git a/macros/code.asm b/macros/code.asm new file mode 100644 index 0000000..1fb651f --- /dev/null +++ b/macros/code.asm @@ -0,0 +1,101 @@ +; Syntactic sugar macros + +lb: MACRO ; r, hi, lo + ld \1, (((\2) & $ff) << 8) | (((\3) & $ff)) +ENDM + +ln: MACRO ; r, hi, lo + ld \1, (((\2) & $f) << 4) | (((\3) & $f)) +ENDM + +ldpixel: MACRO +if _NARG >= 5 + lb \1, \2 * 8 + \4, \3 * 8 + \5 +else + lb \1, \2 * 8, \3 * 8 +endc +ENDM + +depixel EQUS "ldpixel de," +bcpixel EQUS "ldpixel bc," + + +; Design patterns + +jumptable: MACRO + ld a, [\2] + ld e, a + ld d, 0 + ld hl, \1 + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl +ENDM + +maskbits: MACRO +; masks just enough bits to cover the argument +; e.g. "maskbits 26" becomes "and %00011111" (since 26 - 1 = %00011001) +; example usage in rejection sampling: +; .loop +; call Random +; maskbits 26 +; cp 26 +; jr nc, .loop +x = 1 +rept 8 +if x + 1 < (\1) +x = x << 1 | 1 +endc +endr + and x +ENDM + +calc_sine_wave: MACRO +; input: a = a signed 6-bit value +; output: a = d * sin(a * pi/32) + and %111111 + cp %100000 + jr nc, .negative\@ + call .apply\@ + ld a, h + ret +.negative\@ + and %011111 + call .apply\@ + ld a, h + xor $ff + inc a + ret +.apply\@ + ld e, a + ld a, d + ld d, 0 +if _NARG == 1 + ld hl, \1 +else + ld hl, .sinetable\@ +endc + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ld hl, 0 +.multiply\@ ; factor amplitude + srl a + jr nc, .even\@ + add hl, de +.even\@ + sla e + rl d + and a + jr nz, .multiply\@ + ret +if _NARG == 0 +.sinetable\@ + sine_table 32 +endc +ENDM diff --git a/macros/coords.asm b/macros/coords.asm new file mode 100644 index 0000000..0833c24 --- /dev/null +++ b/macros/coords.asm @@ -0,0 +1,52 @@ +hlcoord EQUS "coord hl," +bccoord EQUS "coord bc," +decoord EQUS "coord de," + +coord: MACRO +; register, x, y[, origin] + if _NARG < 4 + ld \1, (\3) * SCREEN_WIDTH + (\2) + wTileMap + else + ld \1, (\3) * SCREEN_WIDTH + (\2) + \4 + endc +ENDM + +hlbgcoord EQUS "bgcoord hl," +bcbgcoord EQUS "bgcoord bc," +debgcoord EQUS "bgcoord de," + +bgcoord: MACRO +; register, x, y[, origin] + if _NARG < 4 + ld \1, (\3) * BG_MAP_WIDTH + (\2) + vBGMap0 + else + ld \1, (\3) * BG_MAP_WIDTH + (\2) + \4 + endc +ENDM + +dwcoord: MACRO +; x, y +rept _NARG / 2 + dw (\2) * SCREEN_WIDTH + (\1) + wTileMap + shift + shift +endr +ENDM + +ldcoord_a: MACRO +; x, y[, origin] + if _NARG < 3 + ld [(\2) * SCREEN_WIDTH + (\1) + wTileMap], a + else + ld [(\2) * SCREEN_WIDTH + (\1) + \3], a + endc +ENDM + +lda_coord: MACRO +; x, y[, origin] + if _NARG < 3 + ld a, [(\2) * SCREEN_WIDTH + (\1) + wTileMap] + else + ld a, [(\2) * SCREEN_WIDTH + (\1) + \3] + endc +ENDM diff --git a/macros/data.asm b/macros/data.asm new file mode 100644 index 0000000..241e52a --- /dev/null +++ b/macros/data.asm @@ -0,0 +1,129 @@ +; Value macros + +percent EQUS "* $ff / 100" + + +; Constant data (db, dw, dl) macros + +dwb: MACRO + dw \1 + db \2 +ENDM + +dbw: MACRO + db \1 + dw \2 +ENDM + +dbbw: MACRO + db \1, \2 + dw \3 +ENDM + +dbww: MACRO + db \1 + dw \2, \3 +ENDM + +dbwww: MACRO + db \1 + dw \2, \3, \4 +ENDM + +dn: MACRO ; nybbles +rept _NARG / 2 + db ((\1) << 4) | (\2) + shift + shift +endr +ENDM + +dc: MACRO ; "crumbs" +rept _NARG / 4 + db ((\1) << 6) | ((\2) << 4) | ((\3) << 2) | (\4) + shift + shift + shift + shift +endr +ENDM + +dx: MACRO +x = 8 * ((\1) - 1) +rept \1 + db LOW((\2) >> x) +x = x + -8 +endr +ENDM + +dt: MACRO ; three-byte (big-endian) + dx 3, \1 +ENDM + +dd: MACRO ; four-byte (big-endian) + dx 4, \1 +ENDM + +bigdw: MACRO ; big-endian word + dx 2, \1 +ENDM + +dba: MACRO ; dbw bank, address +rept _NARG + dbw BANK(\1), \1 + shift +endr +ENDM + +dab: MACRO ; dwb address, bank +rept _NARG + dwb \1, BANK(\1) + shift +endr +ENDM + +dba_pic: MACRO ; dbw bank, address + db BANK(\1) - PICS_FIX + dw \1 +ENDM + + +dbpixel: MACRO +if _NARG >= 4 +; x tile, x pxl, y tile, y pxl + db \1 * 8 + \3, \2 * 8 + \4 +else +; x, y + db \1 * 8, \2 * 8 +endc +ENDM + +dsprite: MACRO +; y tile, y pxl, x tile, x pxl, vtile offset, flags, attributes + db LOW(\1 * 8) + \2, LOW(\3 * 8) + \4, \5, \6 +ENDM + + +menu_coords: MACRO +; x1, y1, x2, y2 + db \2, \1 ; start coords + db \4, \3 ; end coords +ENDM + + +bcd: MACRO +rept _NARG + dn LOW(\1) / 10, (\1) % 10 + shift +endr +ENDM + + +sine_table: MACRO +; \1 samples of sin(x) from x=0 to x<32768 (pi radians) +x = 0 +rept \1 + dw HIGH(sin(x) + LOW(sin(x))) ; round up +x = x + DIV(32768, \1) ; a circle has 65536 "degrees" +endr +ENDM diff --git a/macros/farcall.asm b/macros/farcall.asm new file mode 100644 index 0000000..e70cff8 --- /dev/null +++ b/macros/farcall.asm @@ -0,0 +1,22 @@ + +farcall: MACRO ; bank, address + ld a, BANK(\1) + ld hl, \1 + call FarCall +ENDM + +callfar: MACRO ; address, bank + ld hl, \1 + ld a, BANK(\1) + call FarCall +ENDM + +homecall: MACRO + ld a, [hROMBank] + push af + ld a, BANK(\1) + call Bankswitch + call \1 + pop af + call Bankswitch +ENDM diff --git a/macros/gfx.asm b/macros/gfx.asm new file mode 100644 index 0000000..16c7d9b --- /dev/null +++ b/macros/gfx.asm @@ -0,0 +1,2 @@ +tiles EQUS "* LEN_2BPP_TILE" +tile EQUS "+ LEN_2BPP_TILE *" diff --git a/macros/predef.asm b/macros/predef.asm new file mode 100644 index 0000000..7850350 --- /dev/null +++ b/macros/predef.asm @@ -0,0 +1,15 @@ +predef_id: MACRO +; Some functions load the predef id +; without immediately calling Predef. + ld a, (\1Predef - PredefPointers) / 3 +ENDM + +predef: MACRO + predef_id \1 + call Predef +ENDM + +predef_jump: MACRO + predef_id \1 + jp Predef +ENDM diff --git a/macros/wram.asm b/macros/wram.asm new file mode 100644 index 0000000..7e7505f --- /dev/null +++ b/macros/wram.asm @@ -0,0 +1,365 @@ + +flag_array: MACRO + ds ((\1) + 7) / 8 +ENDM + +box_struct: MACRO +\1Species:: db +\1Item:: db +\1Moves:: ds NUM_MOVES +\1ID:: dw +\1Exp:: ds 3 +\1StatExp:: +\1HPExp:: dw +\1AtkExp:: dw +\1DefExp:: dw +\1SpdExp:: dw +\1SpcExp:: dw +\1DVs:: ds 2 +\1PP:: ds NUM_MOVES +\1Happiness:: db +\1PokerusStatus:: db +\1CaughtData:: +\1CaughtTime:: +\1CaughtLevel:: db +\1CaughtGender:: +\1CaughtLocation:: db +\1Level:: db +\1End:: +ENDM + +party_struct: MACRO + box_struct \1 +\1Status:: db +\1Unused:: db +\1HP:: dw +\1MaxHP:: dw +\1Stats:: ; big endian +\1Attack:: dw +\1Defense:: dw +\1Speed:: dw +\1SpclAtk:: dw +\1SpclDef:: dw +\1StatsEnd:: +ENDM + +red_box_struct: MACRO +\1Species:: db +\1HP:: dw +\1BoxLevel:: db +\1Status:: db +\1Type:: +\1Type1:: db +\1Type2:: db +\1CatchRate:: db +\1Moves:: ds NUM_MOVES +\1OTID:: dw +\1Exp:: ds 3 +\1HPExp:: dw +\1AttackExp:: dw +\1DefenseExp:: dw +\1SpeedExp:: dw +\1SpecialExp:: dw +\1DVs:: ds 2 +\1PP:: ds NUM_MOVES +ENDM + +red_party_struct: MACRO + red_box_struct \1 +\1Level:: db +\1Stats:: +\1MaxHP:: dw +\1Attack:: dw +\1Defense:: dw +\1Speed:: dw +\1Special:: dw +ENDM + + +battle_struct: MACRO +\1Species:: db +\1Item:: db +\1Moves:: ds NUM_MOVES +\1MovesEnd:: +\1DVs:: ds 2 +\1PP:: ds NUM_MOVES +\1Happiness:: db +\1Level:: db +\1Status:: ds 2 +\1HP:: dw +\1MaxHP:: dw +\1Stats:: ; big endian +\1Attack:: dw +\1Defense:: dw +\1Speed:: dw +\1SpclAtk:: dw +\1SpclDef:: dw +\1StatsEnd:: +\1Type:: +\1Type1:: db +\1Type2:: db +\1StructEnd:: +ENDM + +box: MACRO +\1:: +\1Count:: ds 1 +\1Species:: ds MONS_PER_BOX + 1 +\1Mons:: +\1Mon1:: box_struct \1Mon1 +\1Mon2:: ds BOXMON_STRUCT_LENGTH * (MONS_PER_BOX +- 1) +\1MonOT:: ds NAME_LENGTH * MONS_PER_BOX +\1MonNicknames:: ds PKMN_NAME_LENGTH * MONS_PER_BOX +\1MonNicknamesEnd:: +\1End:: ds 2 ; padding +ENDM + + +channel_struct: MACRO +; TODO: CH1 isn't at C101, please rebase all of these +; Addreses are Channel1 (c101). +\1MusicID:: dw +\1MusicBank:: db +\1Flags:: db ; 0:on/off 1:subroutine 3:sfx 4:noise 5:rest +\1Flags2:: db ; 0:vibrato on/off 2:duty 4:cry pitch +\1Flags3:: db ; 0:vibrato up/down +\1MusicAddress:: dw +\1LastMusicAddress:: dw + dw +\1NoteFlags:: db ; 5:rest +\1Condition:: db ; conditional jumps +\1DutyCycle:: db ; bits 6-7 (0:12.5% 1:25% 2:50% 3:75%) +\1Intensity:: db ; hi:pressure lo:velocity +\1Frequency:: ; 11 bits +\1FrequencyLo:: db +\1FrequencyHi:: db +\1Pitch:: db ; 0:rest 1-c:note +\1Octave:: db ; 7-0 (0 is highest) +\1StartingOctave:: db ; raises existing octaves (to repeat phrases) +\1NoteDuration:: db ; frames remaining for the current note +\1Field16:: ds 1 ; c117 + ds 1 ; c118 +\1LoopCount:: db +\1Tempo:: dw +\1Tracks:: db ; hi:left lo:right +\1SFXDutyLoop:: ds 1 ; c11d +\1VibratoDelayCount:: db ; initialized by \1VibratoDelay +\1VibratoDelay:: db ; number of frames a note plays until vibrato starts +\1VibratoExtent:: db +\1VibratoRate:: db ; hi:frames for each alt lo:frames to the next alt +\1PitchWheelTarget:: dw ; frequency endpoint for pitch wheel +\1PitchWheelAmount:: db ; c124 +\1PitchWheelAmountFraction:: db ; c125 +\1Field25:: ds 1 ; c126 + ds 1 ; c127 +\1CryPitch:: dw +\1Field29:: ds 1 +\1Field2a:: ds 2 +\1Field2c:: ds 1 +\1NoteLength:: db ; frames per 16th note +\1Field2e:: ds 1 ; c12f +\1Field2f:: ds 1 ; c130 +\1Field30:: ds 1 ; c131 + ds 1 ; c132 +ENDM + +mailmsg: MACRO +\1Message:: ds MAIL_MSG_LENGTH +\1MessageEnd:: ds 1 +\1Author:: ds PLAYER_NAME_LENGTH +\1AuthorNationality:: ds 2 +\1AuthorID:: ds 2 +\1Species:: ds 1 +\1Type:: ds 1 +\1End:: +endm + +hof_mon: MACRO +\1Species:: ds 1 +\1ID:: ds 2 +\1DVs:: ds 2 +\1Level:: ds 1 +\1Nickname:: ds PKMN_NAME_LENGTH +- 1 +\1End:: +endm + +roam_struct: MACRO +\1Species:: db +\1Level:: db +\1MapGroup:: db +\1MapNumber:: db +\1HP:: ds 1 +\1DVs:: ds 2 +ENDM + +bugcontestwinner: macro +\1PersonID:: ds 1 +\1Mon:: ds 1 +\1Score:: ds 2 +endm + +hall_of_fame: MACRO +\1:: +\1WinCount:: ds 1 +\1Mon1:: hof_mon \1Mon1 +\1Mon2:: hof_mon \1Mon2 +\1Mon3:: hof_mon \1Mon3 +\1Mon4:: hof_mon \1Mon4 +\1Mon5:: hof_mon \1Mon5 +\1Mon6:: hof_mon \1Mon6 +\1End:: ds 1 +ENDM + +trademon: MACRO +\1Species:: ds 1 ; wc6d0 | wc702 +\1SpeciesName:: ds PKMN_NAME_LENGTH ; wc6d1 | wc703 +\1Nickname:: ds PKMN_NAME_LENGTH ; wc6dc | wc70e +\1SenderName:: ds NAME_LENGTH ; wc6e7 | wc719 +\1OTName:: ds NAME_LENGTH ; wc6f2 | wc724 +\1DVs:: ds 2 ; wc6fd | wc72f +\1ID:: ds 2 ; wc6ff | wc731 +\1CaughtData:: ds 1 ; wc701 | wc733 +\1End:: +ENDM + +move_struct: MACRO +\1Animation:: ds 1 +\1Effect:: ds 1 +\1Power:: ds 1 +\1Type:: ds 1 +\1Accuracy:: ds 1 +\1PP:: ds 1 +\1EffectChance:: ds 1 +endm + +slot_reel: MACRO +\1ReelAction:: db +\1TilemapAddr:: dw +\1Position:: db +\1SpinDistance:: db +\1SpinRate:: db +\1OAMAddr:: dw +\1XCoord:: db +\1Slot09:: ds 1 +\1Slot0a:: ds 1 +\1Slot0b:: ds 1 +\1Slot0c:: ds 1 +\1Slot0d:: ds 1 +\1Slot0e:: ds 1 +\1Slot0f:: ds 1 +endm + +object_struct: MACRO +\1Struct:: +\1Sprite:: ds 1 +\1MapObjectIndex:: ds 1 +\1SpriteTile:: ds 1 +\1MovementType:: ds 1 +\1Flags:: ds 2 +\1Palette:: ds 1 +\1Walking:: ds 1 +\1Direction:: ds 1 +\1StepType:: ds 1 +\1StepDuration:: ds 1 +\1Action:: ds 1 +\1ObjectStepFrame:: ds 1 +\1Facing:: ds 1 +\1StandingTile:: ds 1 ; collision +\1LastTile:: ds 1 ; collision +\1StandingMapX:: ds 1 +\1StandingMapY:: ds 1 +\1LastMapX:: ds 1 +\1LastMapY:: ds 1 +\1ObjectInitX:: ds 1 +\1ObjectInitY:: ds 1 +\1Radius:: ds 1 +\1SpriteX:: ds 1 +\1SpriteY:: ds 1 +\1SpriteXOffset:: ds 1 +\1SpriteYOffset:: ds 1 +\1MovementByteIndex:: ds 1 +\1Object28:: ds 1 +\1Object29:: ds 1 +\1Object30:: ds 1 +\1Object31:: ds 1 +\1Range:: ds 1 + ds 7 +\1StructEnd:: +ENDM + +map_object: MACRO +\1Object:: +\1ObjectStructID:: ds 1 +\1ObjectSprite:: ds 1 +\1ObjectYCoord:: ds 1 +\1ObjectXCoord:: ds 1 +\1ObjectMovement:: ds 1 +\1ObjectRadius:: ds 1 +\1ObjectHour:: ds 1 +\1ObjectTimeOfDay:: ds 1 +\1ObjectColor:: ds 1 +\1ObjectRange:: ds 1 +\1ObjectScript:: ds 2 +\1ObjectEventFlag:: ds 2 + ds 2 +endm + +sprite_anim_struct: MACRO +\1Index:: ds 1 ; 0 +\1FramesetID:: ds 1 ; 1 +\1AnimSeqID:: ds 1 ; 2 +\1TileID:: ds 1 ; 3 +\1XCoord:: ds 1 ; 4 +\1YCoord:: ds 1 ; 5 +\1XOffset:: ds 1 ; 6 +\1YOffset:: ds 1 ; 7 +\1Duration:: ds 1 ; 8 +\1DurationOffset:: ds 1 ; 9 +\1FrameIndex:: ds 1 ; a +\1Sprite0b:: ds 1 +\1Sprite0c:: ds 1 +\1Sprite0d:: ds 1 +\1Sprite0e:: ds 1 +\1Sprite0f:: ds 1 +ENDM + +battle_anim_struct: MACRO +; Placeholder until we can figure out what it all means +\1_Index:: ds 1 +\1_Anim01:: ds 1 +\1_Anim02:: ds 1 +\1_FramesetIndex:: ds 1 +\1_FunctionIndex:: ds 1 +\1_Anim05:: ds 1 +\1_TileID:: ds 1 +\1_XCoord:: ds 1 +\1_YCoord:: ds 1 +\1_XOffset:: ds 1 +\1_YOffset:: ds 1 +\1_Anim0b:: ds 1 +\1_Anim0c:: ds 1 +\1_Anim0d:: ds 1 +\1_AnonJumptableIndex:: ds 1 +\1_Anim0f:: ds 1 +\1_Anim10:: ds 1 +\1_Anim11:: ds 1 +\1_Anim12:: ds 1 +\1_Anim13:: ds 1 +\1_Anim14:: ds 1 +\1_Anim15:: ds 1 +\1_Anim16:: ds 1 +\1_Anim17:: ds 1 +endm + +battle_bg_effect: MACRO +\1_Function:: ds 1 +\1_01:: ds 1 +\1_02:: ds 1 +\1_03:: ds 1 +endm + +warp_struct: MACRO +\1WarpNumber:: ds 1 +\1MapGroup:: ds 1 +\1MapNumber:: ds 1 +ENDM @@ -28,7 +28,6 @@ 00:232c LoadMapWarp 00:23e5 OverworldFadeIn -00:2F97 InexplicablyEmptyFunction 00:2FA8 FarCall_hl 00:2FC8 FarCall_hl.return 00:2FDE Predef @@ -178,18 +177,3 @@ 01:d66a wMapScriptPtr 01:D7D2 wPartyMonOT 01:DA3B wUnk_DA3B ; In final, $DE7D in NamesPointers (6th entry) -01:DFFF wStackTop - -00:FF80 hPushOAM -00:FF98 hROMBank -00:FFA3 hUnk_FFA3 -00:FFA4 hUnk_Joypad ; ? -00:FFD5 hLinkPlayerNumber -00:FFD9 hSCX -00:FFDA hSCY -00:FFDB hWX -00:FFDC hWY -00:FFDE hBGMapMode -00:FFE0 hBGMapAddress -00:FFE8 hMapAnims - diff --git a/sram.asm b/sram.asm new file mode 100644 index 0000000..3ea96e7 --- /dev/null +++ b/sram.asm @@ -0,0 +1,4 @@ +SECTION "Unknown, bank 0", SRAM[$A600],BANK[0] + +s0_a600:: ; TODO: properly label this + ds 7 ; TODO: figure out exact size diff --git a/tools/make_shim.py b/tools/make_shim.py index 67b9f4e..7c60f4f 100644 --- a/tools/make_shim.py +++ b/tools/make_shim.py @@ -1,39 +1,77 @@ from sys import argv, stderr -for line in open(argv[1]): - line = line.split(";")[0] - line = line.strip() - if line and " " in line: - address, symbol = line.split() - bank, pointer = address.split(":") - bank = int(bank, 16) - pointer = int(pointer, 16) - section = None - if bank == 0 and pointer < 0x4000: - section = "ROM0" - bank = None - elif pointer < 0x8000: - section = "ROMX" - elif pointer < 0xa000: - section = "VRAM" - elif pointer < 0xc000: - section = "SRAM" - elif bank == 0 and pointer < 0xd000: - section = "WRAM0" - bank = None - elif pointer < 0xe000: - section = "WRAMX" - elif pointer > 0xff80 and pointer <= 0xffff: - section = "HRAM" - else: - stderr.write(f"Unknown section for {line}\n") - - if section: - if bank: - print(f"SECTION \"Shim for {symbol}\", {section}[${pointer:x}], BANK[${bank:x}]") - else: - print(f"SECTION \"Shim for {symbol}\", {section}[${pointer:x}]") - print(f"{symbol}::\n\n") + +section_list = [ + {'end': 0x4000, 'invalid': False, 'name': "ROM0", 'banked': False}, + {'end': 0x8000, 'invalid': False, 'name': "ROMX", 'banked': True}, + {'end': 0xA000, 'invalid': False, 'name': "VRAM", 'banked': True}, + {'end': 0xC000, 'invalid': False, 'name': "SRAM", 'banked': True}, + {'end': 0xD000, 'invalid': False, 'name': "WRAM0", 'banked': False}, + {'end': 0xE000, 'invalid': False, 'name': "WRAMX", 'banked': True}, + {'end': 0xFE00, 'invalid': True , 'name': "Echo RAM"}, + {'end': 0xFEA0, 'invalid': False, 'name': "OAM", 'banked': False}, + {'end': 0xFF80, 'invalid': True , 'name': "FEXX / IO"}, + {'end': 0xFFFF, 'invalid': False, 'name': "HRAM", 'banked': False} +] + + +argv_id = 1 +file_list = [] +options = [] +while argv_id < len(argv): + arg = argv[argv_id] + if arg[0] != '-': + file_list.append(arg) + elif arg[1] != '-': + for option in arg[1:]: + options.append(option) + else: + options.append(option[2:]) + argv_id += 1 + + +if 'w' in options or 'd' in options: + section_list[4]['end'] = 0xE000 + +if 't' in options: + section_list[0]['end'] = 0x8000 + + +for file_name in file_list: + with open(file_name, "rt") as f: + for line in f: + line = line.split(";")[0] + line = line.strip() + if line and " " in line: + address, symbol = line.split() + bank, pointer = address.split(":") + bank = int(bank, 16) + pointer = int(pointer, 16) + + section = None + for section_type in section_list: + if pointer < section_type['end']: + if section_type['invalid']: + stderr.write(f"Warning: cannot shim '{symbol}' in section type '{section_type['name']}'\n") + section = False + else: + section = section_type['name'] + if not section_type['banked']: + bank = None + break + + if section == False: # Found section, but cannot shim it + continue + + if section == None: # Didn't find a section at all + stderr.write(f"Unknown section for {line}\n") + + if section: + if bank: + print(f"SECTION \"Shim for {symbol}\", {section}[${pointer:x}], BANK[${bank:x}]") + else: + print(f"SECTION \"Shim for {symbol}\", {section}[${pointer:x}]") + print(f"{symbol}::\n\n") |