pokepinball/home.asm
2017-06-19 13:26:28 -07:00

5714 lines
79 KiB
NASM
Executable File

SECTION "rst 00", ROM0 [$00]
di
jp Entry
SECTION "rst 10", ROM0 [$10]
jp DelayFrame
SECTION "rst 18", ROM0 [$18]
jp JumpToFuncInTable
SECTION "rst 20", ROM0 [$20]
jp Func_486
SECTION "VBlankInt", ROM0 [$40]
jp VBlank
SECTION "HBlankInt", ROM0 [$48]
jp LCD
SECTION "TimerInt", ROM0 [$50]
jp Timer
SECTION "SerialInt", ROM0 [$58]
jp Serial
SECTION "JoypadInt", ROM0 [$60]
jp Joypad
SECTION "Entry", ROM0 [$100]
Entry: ; 0x100
nop
jp Start
SECTION "Header", ROM0 [$104]
; The header is generated by rgbfix.
; The space here is allocated to prevent code from being overwritten.
ds $150 - $104
SECTION "Main", ROM0 [$150]
Start: ; 0x150
ld [hGameBoyColorFlag], a
ld sp, hGameBoyColorFlag
di
xor a
ld [rIF], a
ld a, [rLCDC] ; LCD Control
bit 7, a ; Check if LCD Display is enabled
jr nz, .LCDDisplayEnabled
set 7, a
ld [rLCDC], a
.LCDDisplayEnabled
ld bc, $0002
call SGBWait1750
.waitForVBlank
ld a, [rLY] ; LY register (LCDC Y-Coordinate)
cp 145 ; > 144 means V-Blank
jr c, .waitForVBlank
ld a, $81
ld [rLCDC], a ; Enable LCD Display
xor a
ld [rBGP], a ; Clear Palette Data
ld [rOBP0], a
ld [rOBP1], a
ld bc, $0002
call SGBWait1750
.waitForVBlank2
ld a, [rLY] ; LY register (LCDC Y-Coordinate)
cp 145 ; > 144 means V-Blank
jr c, .waitForVBlank2
xor a
ld [rLCDC], a ; Disable LCD Display
ld hl, wc000
ld bc, $2000
call ClearData ; Clear WRAM Bank 0
ld hl, vTilesOB
ld bc, $1000
call ClearData ; Clear First half of VRAM
ld a, SRAM_ENABLE
ld [MBC5SRamEnable], a ; Enable RAM
ld a, $1
ld [MBC5RomBank], a ; Load ROM Bank $1
ld a, $0
ld [MBC5RomBankOn], a ; Enable ROM Banking Mode
ld a, $0
ld [MBC5SRamBank], a ; Set bits 5 and 6 of ROM Bank Number
ld a, $1
ld [hLoadedROMBank], a
ld a, $1
ld [MBC5RomBankOn], a ; Enable RAM Banking Mode
ld a, $0
ld [MBC5SRamBank], a ; Load RAM Bank $0
ld sp, wStack ; Initialize stack pointer to the end of WRAM Bank $1
ld hl, hPushOAM
ld bc, $007e
call ClearData ; Clear High RAM (HRAM)
call WriteDMACodeToHRAM
call ClearOAMBuffer
xor a
ld [wd7fb], a
ld [wd7fc], a
ld [wd7fd], a
ld [hHBlankRoutine], a
ld [$ffb1], a
ld [wd8e1], a
ld [wd7fe], a
ld [hSGBInit], a
ld hl, hLCDC
xor a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ld a, $8f
ld [hli], a
ld a, $a6
ld [hli], a
ld a, $0
ld [wd849], a
ld [wd84a], a
ld a, Bank(PlaySong_BankF)
call SetSongBank
call Func_23b
ld a, [hGameBoyColorFlag]
and a
jr nz, .asm_222
call InitSGB
rl a
and $1
ld [hSGBFlag], a
call SendSGBBorder
ld a, [hSGBFlag]
and a
jr z, .asm_222
ld a, $1
ld [wd917], a
.asm_222
ld a, $1
ld [rIE], a ; Only enable LCD Status interrupt
ei
ld a, $ff
ld [wd810], a
call Func_97a
xor a
ld [wdaa3], a
ld a, BANK(Func_1ffc)
ld hl, Func_1ffc
call BankSwitchSimple
Func_23b: ; 0x23b
ld a, [hGameBoyColorFlag]
cp $11
jr nz, .asm_248
ld a, $1
ld [hGameBoyColorFlag], a
ld [$fffd], a
ret
.asm_248
xor a
ld [hGameBoyColorFlag], a
ld [$fffd], a
ret
SoftReset:
di
ld sp, hGameBoyColorFlag
xor a
ld [rIF], a
ld bc, $2
call SGBWait1750
ld hl, wc000
ld bc, $2000
call ClearData
ld hl, $8000
ld bc, $1000
call ClearData
ld a, SRAM_ENABLE
ld [MBC5SRamEnable], a
ld a, $1
ld [MBC5RomBank], a
ld a, $0
ld [MBC5RomBankOn], a
ld a, $0
ld [MBC5SRamBank], a
ld a, $1
ld [hLoadedROMBank], a
ld a, $1
ld [MBC5RomBankOn], a
ld a, $0
ld [MBC5SRamBank], a
ld sp, wStack
call WriteDMACodeToHRAM
call ClearOAMBuffer
xor a
ld [wd7fb], a
ld [wd7fc], a
ld [wd7fd], a
ld [hHBlankRoutine], a
ld [$ffb1], a
ld [wd8e1], a
ld [wd7fe], a
ld hl, hLCDC
xor a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ld a, $8f
ld [hli], a
ld a, $a6
ld [hli], a
ld a, $0
ld [wd849], a
ld [wd84a], a
ld a, BANK(Func_3c000)
call SetSongBank
ld a, [hSGBFlag]
and a
jr z, .asm_02d5
ld a, $1
ld [wd917], a
.asm_02d5
ld a, $1
ld [rIE], a
ei
ld a, $ff
ld [wd810], a
call Func_97a
ld a, [hGameBoyColorFlag]
ld [$fffd], a
xor a
ld [wdaa3], a
ld a, $0
ld hl, Func_1ffc
call BankSwitchSimple
; fallthrough
VBlank: ; 0x2f2
push af
push bc
push de
push hl
call hPushOAM ; OAM DMA transfer
ld a, [hLCDC]
ld [rLCDC], a
call Func_113a
ei
ld a, [rLY]
cp $90
jr c, .asm_328
ld hl, hSTAT
ld c, rSTAT - $ff00
ld a, [hli]
ld [$ff00+c], a
inc c
ld a, [hli]
ld [$ff00+c], a
inc c
ld a, [hli]
ld [$ff00+c], a
inc c
inc c
ld a, [hli]
ld [$ff00+c], a
inc c
inc c
ld a, [hli]
ld [$ff00+c], a
inc c
ld a, [hli]
ld [$ff00+c], a
inc c
ld a, [hli]
ld [$ff00+c], a
inc c
ld a, [hli]
ld [$ff00+c], a
inc c
ld a, [hli]
ld [$ff00+c], a
.asm_328
ld a, [hLYC]
ld [hLastLYC], a
ld a, [hNextLYCSub]
ld [hLYCSub], a
ld a, [hNextFrameHBlankSCX]
ld [hHBlankSCX], a
ld a, [hNextFrameHBlankSCY]
ld [hHBlankSCY], a
call ReadJoypad
ld a, [wdaa3]
and a
jr nz, .asm_359
ld a, [hJoypadState]
cp $f
jr nz, .asm_359
ld a, [hNewlyPressedButtons]
and $f
jr z, .asm_359
ld hl, [sp+$8]
ld [hl], $c3
inc hl
ld [hl], $3
ld a, $1
ld [wdaa3], a
.asm_359
ld hl, hNumFramesSinceLastVBlank
ld a, [hl]
inc [hl]
and a
jr nz, .asm_365
ld hl, hNumFramesDropped
inc [hl]
.asm_365
ld hl, hVBlankCount
inc [hl]
ld a, [wd8e1]
and a
call nz, Func_167b
ld a, [wd849]
and a
jr nz, .asm_37d
ld a, [wd85d]
and a
call nz, Func_504
.asm_37d
ld a, [wd84a]
and a
jr z, .asm_39d
xor a
ld [wd84a], a
ld a, $1
ld [wd849], a
ld a, $bc
ld [rTMA], a
ld a, $0
ld [rTAC], a
ld hl, rIE
set 2, [hl]
ld a, $4
ld [rTAC], a
.asm_39d
ld hl, MBC5SRamBank
ld a, [wd917]
and a
jr nz, .asm_3b5
ld a, [wd803]
rrca
ld [wd803], a
and $1
jr z, .asm_3b5
set 3, [hl]
jr .asm_3b7
.asm_3b5
res 3, [hl]
.asm_3b7
ld a, [wd4aa]
and a
call nz, Func_e69
pop hl
pop de
pop bc
pop af
reti
Func_3c3:
ld a, [rLCDC]
bit 7, a
jr z, .asm_03cf
call Func_cb5
call Func_576
.asm_03cf
ld hl, hSTAT
res 6, [hl]
ld hl, rIE
res 1, [hl]
xor a
ld [MBC5SRamEnable], a
ld [rSB], a
ld [rSC], a
ld [rIE], a
ld [rNR52], a
ld a, [$fffd]
ld [hGameBoyColorFlag], a
jp SoftReset
LCD: ; 0x3ec
push af
push bc
push de
push hl
ld a, [hHBlankRoutine]
sla a
ld c, a
ld b, $0
ld hl, PointerTable_408
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
jp [hl]
Func_3ff: ; 0x3ff
ld a, $1
ld [$ffb5], a
pop hl
pop de
pop bc
pop af
reti
PointerTable_408: ; 0x408
dw Func_fbc
dw Func_fbf
dw Func_fea
dw Func_105d
dw Func_109e
dw Func_10a1
dw Func_10a4
dw Func_10a7
Timer: ; 0x418
ei
push af
push bc
push de
push hl
ld a, [wd849]
and a
jr z, .asm_42a
ld a, [wd85d]
and a
call nz, Func_504
.asm_42a
ld a, [wd84a]
and a
jr z, .asm_440
xor a
ld [wd84a], a
ld [wd849], a
ld a, $0
ld [rTAC], a
ld hl, rIE
res 2, [hl]
.asm_440
pop hl
pop de
pop bc
pop af
reti
Serial: ; 0x445
push af
push bc
push de
push hl
ld hl, Data_45d
push hl
ld a, [$ffb1]
sla a
ld c, a
ld b, $0
ld hl, Data_462
add hl, bc
ld c, [hl]
inc hl
ld b, [hl]
push bc
ret
Data_45d:
db $e1, $d1, $c1, $f1, $d9
Data_462:
db $64, $16, $66, $04, $c9
Joypad: ; 0x467
reti
DelayFrame: ; 0x468
ld a, [rLCDC]
bit 7, a
ret z
ld hl, hNumFramesSinceLastVBlank
xor a
ld [hl], a
.asm_472
ld a, [hl]
and a
jr z, .asm_472
ret
JumpToFuncInTable: ; 0x477
; Jumps to a function in the pointer table immediately following
; a "rst JumpTable" call. Function must be in the same Bank as the pointer table.
; input: a = index of function in table
sla a
pop hl
push de
ld e, a
ld d, $0
add hl, de
ld e, [hl]
inc hl
ld d, [hl]
ld l, e
ld h, d
pop de
jp [hl]
Func_486: ; 0x486
rlca
add l
ld l, a
jr nc, .noCarry
inc h
.noCarry
ld a, [hli]
ld h, [hl]
ld l, a
ret
PlaySong: ; 0x490
ld a, [hLoadedROMBank]
push af
ld a, [wCurrentSongBank]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld a, e
ld [wStageSong], a
ld a, [wCurrentSongBank]
ld [wStageSongBank], a
call PlaySong_BankF ; this function is replicated in multiple banks.
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ret
PlaySoundEffect: ; 0x4af
; input: de = sound effect id? I think d specifies something special and e holds the id
ld a, [wdead]
and a
ret nz
ld a, [wSFXTimer]
and a
jr z, .asm_4bd
ld a, d
and a
ret z
.asm_4bd
ld a, d
ld [wSFXTimer], a
ld d, $0
ld a, [hLoadedROMBank]
push af
ld a, [wCurrentSongBank]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
call PlaySoundEffect_BankF ; this function is replicated in multiple banks
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ret
Func_4d8: ; 0x4d8
push bc
push de
push hl
ld a, [wChannel4 + 2]
ld hl, wChannel5 + 2
or [hl]
ld hl, wChannel6 + 2
or [hl]
and $1
call z, PlaySoundEffect
pop hl
pop de
pop bc
ret
PlayCry: ; 0x4ef
; Plays a Pokemon cry.
; Input: e = mon id
ld a, [hLoadedROMBank]
push af
ld a, [wCurrentSongBank]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
call PlayCry_BankF ; this function is replicated in multiple banks
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ret
Func_504: ; 0x504
ld a, [hLoadedROMBank]
push af
ld a, [wCurrentSongBank]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
call Func_3c180
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld a, [wd801]
inc a
ld [wd801], a
and $3
ret nz
ld a, [wSFXTimer]
and a
ret z
dec a
ld [wSFXTimer], a
ret
SetSongBank: ; 0x52c
di
ld [wCurrentSongBank], a
ei
ret
CallInFollowingTable: ; 0x532
; Calls a function in a table located immediately after a call to this function.
; Inputs: a = entry in the table
ld e, a
ld d, $0
sla e
rl d
sla e
rl d ; multiplied a by 4 because entries in the table are 4 bytes each
pop hl
add hl, de
ld e, [hl]
inc hl
ld d, [hl]
inc hl
ld a, [hl]
ld h, d
ld l, e
jp BankSwitch
BankSwitchSimple: ; 0x549
; Switches to Bank in register a and jumps to hl.
ld [hLoadedROMBank], a
ld [MBC5RomBank], a ; Load Bank
jp [hl]
BankSwitch: ; 0x54f
ld e, a
ld a, [hLoadedROMBank] ; currently-loaded Bank
cp e
jr z, .doJump
push af
ld a, e
call .loadNewBank
call .doJump
pop de
ld a, d
.loadNewBank
push hl
push de
ld hl, rIE
ld d, [hl]
ld [hl], $0
ld [MBC5RomBank], a
ld [hLoadedROMBank], a
ld [hl], d
pop de
pop hl
ret
.doJump
ld a, [hFarCallTempE]
ld e, a
ld a, [hFarCallTempA]
jp [hl]
Func_576: ; 0x576
ld a, [rLCDC]
bit 7, a
ret z
ld a, [hLCDC]
res 7, a
ld [hLCDC], a
.asm_581
ld a, [rLCDC]
bit 7, a
jr nz, .asm_581
ret
Func_588: ; 0x588
ld a, [hFFC4]
and a
call nz, Func_597
ld a, [hLCDC]
set 7, a
ld [rLCDC], a
ld [hLCDC], a
ret
Func_597: ; 0x597
ld de, rBGPI
ld a, $80
ld [de], a
inc de
ld b, $8
.asm_5a0
ld a, [wBGP]
call Func_5c2
dec b
jr nz, .asm_5a0
ld de, rOBPI
ld a, $80
ld [de], a
inc de
ld b, $4
.asm_5b2
ld a, [wOBP0]
call Func_5c2
ld a, [wOBP1]
call Func_5c2
dec b
jr nz, .asm_5b2
ret
Func_5c2: ; 0x5c2
push bc
ld b, $4
.asm_5c5
push af
push bc
and $3
sla a
ld c, a
ld b, $0
ld hl, GreyscalePalette
add hl, bc
ld a, [hli]
ld [de], a
ld a, [hli]
ld [de], a
pop bc
pop af
srl a
srl a
dec b
jr nz, .asm_5c5
pop bc
ret
GreyscalePalette:
RGB 31, 31, 31
RGB 21, 21, 21
RGB 11, 11, 11
RGB 0, 0, 0
Func_5e9:
ld a, [rIE]
res 0, a
ld [rIE], a
ret
Func_5f0:
ld a, [rIE]
set 0, a
ld [rIE], a
ret
WriteDMACodeToHRAM: ; 0x5f7
; Initializes registers hPushOAM - hFarCallTempA
ld c, $80
ld b, $a ; number of bytes to load
ld hl, DMARoutine
.loop
ld a, [hli]
ld [$ff00+c], a ; add register c to $ff00, and store register a into the resulting address
inc c
dec b
jr nz, .loop
ret
DMARoutine:
; This routine is initially loaded into hPushOAM - hFarCallTempA by WriteDMACodeToHRAM.
ld a, (wOAMBuffer >> 8)
ld [rDMA], a ; start DMA
ld a, $28
.waitLoop ; wait for DMA to finish
dec a
jr nz, .waitLoop
ret
WaitForLCD: ; 0x60f
; Wait for LCD controller to stop reading from both OAM and VRAM because
; CPU can't access OAM, VRAM, or palette data ($ff69, $ff6b) during this time.
ld a, [rSTAT] ; LCDC Status register
and $3
jr nz, WaitForLCD
ld a, $a
.delay10Cycles
dec a
jr nz, .delay10Cycles
ret
Func_61b: ; 0x61b
ld a, [rLY] ; LY register (LCDC Y-Coordinate)
cp $40
jr c, .asm_625
cp $80
jr c, .asm_63d
.asm_625
ld a, [rLY] ; LY register (LCDC Y-Coordinate)
cp $40
jr c, .asm_625
cp $80
jr nc, .asm_625
.asm_62f
ld a, [rSTAT]
and $3
jr nz, .asm_62f ; wait for lcd controller to finish transferring data
ld a, $15
.wait
dec a
jr nz, .wait
nop
nop
nop
.asm_63d
ret
Func_63e: ; 0xc3e
dec bc
.asm_63f
ld [hli], a
dec bc
bit 7, b
jr z, .asm_63f
ret
Func_646:
srl b
rr c
.asm_064a
ld a, e
ld [hli], a
ld a, d
ld [hli], a
dec bc
ld a, b
or c
jr nz, .asm_064a
ret
ClearData: ; 0x654
; Clears bc bytes starting at hl.
; bc can be a maximum of $7fff, since it checks bit 7 of b when looping.
xor a
dec bc
.clearLoop
ld [hli], a
dec bc
bit 7, b
jr z, .clearLoop
ret
LocalCopyData: ; 0x65d
ld a, [hli]
ld [de], a
inc de
dec bc
ld a, c
or b
jr nz, LocalCopyData
ret
FarCopyData: ; 0x666 spooky
; Copies data from any bank to either working RAM or video RAM
; Input: hl = address of data to copy
; a = bank of data to copy
; de = destination for data
; bc = number of bytes to copy
bit 7, h
jr nz, .copyFromSRAM
ld [hROMBankBuffer], a
ld a, [hLoadedROMBank]
push af
ld a, [hROMBankBuffer]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
scf
jr .copyData
.copyFromSRAM
ld [MBC5SRamBank], a
and a
.copyData
push af
.copyLoop
ld a, [hli]
ld [de], a
inc de
dec bc
ld a, c
or b
jr nz, .copyLoop
pop af
ret nc
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ret
ReadByteFromBank: ; 0x68f
; Input: a = bank
; hl = address of byte to read
; Output: a = byte at a:hl
push de
ld d, a
ld a, [hLoadedROMBank]
ld e, a
ld a, d
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld d, [hl]
ld a, e
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld a, d
pop de
ret
LoadVideoData: ; 0x6a4
; Input:
; hl = address of pointer table
; a = index of item to load in pointer table
; This needs more documentation. It loads things like graphics and palettes.
sla a
ld c, a
ld b, $0
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
.loadItem
ld a, [hli]
ld c, a
and [hl]
cp $ff ; two consecutive $ff bytes terminate the array
ret z
ld a, [hli]
ld b, a ; bc contains pointer to data to be loaded
push hl
push bc
ld a, [hli] ; a contains bank of data to be loaded
ld e, [hl]
inc hl
ld d, [hl] ; de contains destination address for data
inc hl
ld c, [hl]
inc hl
ld b, [hl] ; bc contains last word of data struct
inc hl ; this is a wasted instruction
pop hl
call Func_6cb
pop hl
ld bc, $0005
add hl, bc
jr .loadItem
Func_6cb: ; 0x6cb
srl b
rr c
jp c, Func_6fd ; if lowest bit of bc is set
jp Func_6d5 ; This jumps to the next instruction... Strange.
Func_6d5: ; 0x6d5
ld [hROMBankBuffer], a ; save bank of data to be loaded
ld a, [hLoadedROMBank]
push af
ld a, [hROMBankBuffer] ; a contains bank of data to be loaded
ld [hLoadedROMBank], a
ld [MBC5RomBank], a ; switch bank to the bank of data to be loaded
srl b
rr c
rl a
and $1 ; checks bit 1 of the last word in the data struct
ld [rVBK], a ; set VRAM Bank
.copyByte
ld a, [hli]
ld [de], a
inc de
dec bc
ld a, c
or b ; does bc = 0?
jr nz, .copyByte
xor a
ld [rVBK], a ; set VRAM Bank to Bank 0
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a ; reload the previous ROM Bank
ret
Func_6fd: ; 0x6fd
ld [hROMBankBuffer], a ; save bank of data to be loaded
ld a, [hLoadedROMBank]
push af
ld a, [hROMBankBuffer] ; a contains bank of data to be loaded
ld [hLoadedROMBank], a
ld [MBC5RomBank], a ; switch bank to the bank of data to be loaded
ld a, e
bit 6, a
jr nz, .asm_717
ld de, rBGPI
call Func_724
jr z, .asm_71d
xor a
.asm_717
ld de, rOBPI
call Func_724
.asm_71d
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ret
Func_724: ; 0x724
res 6, a
ld b, a
set 7, a
ld [de], a
inc de
.copyByte
ld a, [hli]
ld [de], a
inc b
dec c
ret z
bit 6, b
jr z, .copyByte
ret
LoadOrCopyVRAMData: ; 0x735
push hl
ld hl, rLCDC
bit 7, [hl]
pop hl
jp z, FarCopyData
; fall through
LoadVRAMData: ; 0x73f
; This loads some data into VRAM. It waits for the LCD H-Blank to copy the data 4 bytes at a time.
; input: hl = source of data
; a = bank of data to load
; de = destination of data
; bc = number of bytes to copy
bit 7, h
jr nz, .asm_752
ld [hROMBankBuffer], a
ld a, [hLoadedROMBank]
push af
ld a, [hROMBankBuffer]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
scf
jr .asm_756
.asm_752
ld [MBC5SRamBank], a
and a
.asm_756
push af
call WaitForLCD
.loop
call Func_61b
.waitForHBlank
ld a, [rSTAT]
and $3
jr nz, .waitForHBlank
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
inc de
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
dec bc
dec bc
dec bc
dec bc
nop
nop
nop
nop
ld a, b
or c
jr nz, .loop
pop af
ret nc
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ret
FarCopyPalettes: ; 0x790
push hl
ld hl, rLCDC
bit 7, [hl]
pop hl
jp nz, Func_7dc
bit 7, h
jr nz, .asm_7ad
ld [hROMBankBuffer], a
ld a, [hLoadedROMBank]
push af
ld a, [hROMBankBuffer]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
scf
jr .asm_7b1
.asm_7ad
ld [MBC5SRamBank], a
and a
.asm_7b1
push af
ld a, e
bit 6, e
ld de, rBGPI
jr z, .asm_7bf
res 6, a
ld de, rOBPI
.asm_7bf
set 7, a
ld [de], a
inc de
.asm_7c3
ld a, [hli]
ld [de], a
ld a, [hli]
ld [de], a
ld a, [hli]
ld [de], a
ld a, [hli]
ld [de], a
dec bc
dec bc
dec bc
dec bc
ld a, b
or c
jr nz, .asm_7c3
pop af
ret nc
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ret
Func_7dc: ; 0x7dc
bit 7, h
jr nz, .asm_7ef
ld [hROMBankBuffer], a
ld a, [hLoadedROMBank]
push af
ld a, [hROMBankBuffer]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
scf
jr .asm_7f3
.asm_7ef
ld [MBC5SRamBank], a
and a
.asm_7f3
push af
ld a, e
bit 6, e
ld de, rBGPI
jr z, .asm_801
res 6, a
ld de, rOBPI
.asm_801
push hl
ld h, d
ld l, e
set 7, a
call PutTileInVRAM
inc de
pop hl
call WaitForLCD
.asm_80e
call Func_61b
.asm_811
ld a, [rSTAT]
and $3
jr nz, .asm_811
ld a, [hli]
ld [de], a
ld a, [hli]
ld [de], a
ld a, [hli]
ld [de], a
ld a, [hli]
ld [de], a
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
dec bc
dec bc
dec bc
dec bc
nop
nop
nop
nop
ld a, b
or c
jr nz, .asm_80e
pop af
ret nc
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ret
PutTileInVRAM: ; 0x848
; Puts a tile in VRAM.
; input: a = tile number
; hl = pointer to VRAM location where tile should be placed
push af
call WaitForLCD
call Func_61b
.asm_84f
ld a, [rSTAT]
and $3
jr nz, .asm_84f ; wait for lcd controller to finish transferring data
pop af
ld [hl], a ; Store tile number in VRAM background map
ret
Func_858: ; 0x858
push af
call WaitForLCD
call Func_61b
.asm_85f
ld a, [rSTAT]
and $3
jr nz, .asm_85f
ld a, $1
ld [rVBK], a
pop af
ld [hl], a
xor a
ld [rVBK], a
ret
LoadBillboardPaletteMap: ; 0x86f
; Loads the background palette map for a 6x4-tile billboard picture.
ld [hROMBankBuffer], a
ld a, [hLoadedROMBank]
push af
ld a, [hROMBankBuffer]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld a, [rLCDC]
bit 7, a
jr nz, .asm_8ac
ld a, $1
ld [rVBK], a
ld b, $4
.loop
push bc
ld a, [de]
ld [hli], a
inc de
ld a, [de]
ld [hli], a
inc de
ld a, [de]
ld [hli], a
inc de
ld a, [de]
ld [hli], a
inc de
ld a, [de]
ld [hli], a
inc de
ld a, [de]
ld [hli], a
inc de
ld bc, $001a
add hl, bc
pop bc
dec b
jr nz, .loop
xor a
ld [rVBK], a
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ret
.asm_8ac
ld b, $4
.asm_8ae
push bc
ld a, [de]
call Func_858
inc hl
inc de
ld a, [de]
call Func_858
inc hl
inc de
ld a, [de]
call Func_858
inc hl
inc de
ld a, [de]
call Func_858
inc hl
inc de
ld a, [de]
call Func_858
inc hl
inc de
ld a, [de]
call Func_858
inc de
ld bc, $001b
add hl, bc
pop bc
dec b
jr nz, .asm_8ae
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ret
Func_8e1: ; 0x8e1
ld [hROMBankBuffer], a
ld a, [hLoadedROMBank]
push af
ld a, [hROMBankBuffer]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld a, [rLCDC]
bit 7, a
jr nz, .asm_902
ld a, c
ld [hli], a
.asm_8f5
ld a, [de]
ld [hl], a
inc de
dec b
jr nz, .asm_8f5
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ret
.asm_902
ld a, c
call PutTileInVRAM
inc hl
.asm_907
ld a, [de]
call PutTileInVRAM
inc de
dec b
jr nz, .asm_907
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ret
ClearOAMBuffer: ; 0x916
; Clears the OAM buffer by loading $f0 into all of the entries.
ld hl, wOAMBuffer ; 0xd000
ld b, 4 * 40 ; wOAMBuffer is 4 * 40 bytes long (40 OAM entries, 4 bytes each)
ld a, $f0 ; byte to write
.loop
ld [hli], a
dec b
jr nz, .loop
xor a
ld [wOAMBufferSize], a
ret
CleanOAMBuffer: ; 0x926
; Cleans up any trailing unused oam slots in the oam buffer.
ld a, [wOAMBufferSize]
cp wOAMBufferEnd % $100
jr nc, .done
ld l, a
ld h, wOAMBufferEnd / $100
cpl
add (wOAMBufferEnd + 1) % $100
ld b, a
ld a, $f0
.loop
ld [hli], a
dec b
jr nz, .loop
.done
xor a
ld [wOAMBufferSize], a
ret
AdvanceFrames: ; 0x93f
push bc
rst AdvanceFrame
pop bc
dec bc
ld a, c
or b
jr nz, AdvanceFrames
ret
SGBWait1750: ; 0x948
ld de, 1750
.asm_94b
nop
nop
nop
dec de
ld a, d
or e
jr nz, .asm_94b
dec bc
ld a, b
or c
jr nz, SGBWait1750
ret
GenRandom: ; 0x959
push bc
push de
push hl
ld a, [wd811]
ld c, a
ld b, $0
inc a
cp $37
jr nz, .asm_96e
call Func_9fa
xor a
ld bc, $0000
.asm_96e
ld [wd811], a
ld hl, wd812
add hl, bc
ld a, [hl]
pop hl
pop de
pop bc
ret
Func_97a: ; 0x97a
ld a, [wd810]
ld d, a
ld a, $0
ld a, [$afff]
.asm_983
cp d
jr c, .asm_989
sub d
jr .asm_983
.asm_989
ld [wd80f], a
ld [wd848], a
ld e, $1
ld hl, Data_9c4
ld a, $36
.asm_996
push af
ld c, [hl]
inc hl
ld b, $0
push hl
ld hl, wd812
add hl, bc
ld [hl], e
ld a, [wd80f]
sub e
jr nc, .asm_9a8
add d
.asm_9a8
ld e, a
ld a, [hl]
ld [wd80f], a
pop hl
pop af
dec a
jr nz, .asm_996
call Func_9fa
call Func_9fa
call Func_9fa
ld a, $0
call GenRandom
ld [$afff], a
ret
Data_9c4:
db $14, $29, $07, $1c, $31, $0f, $24, $02, $17
db $2c, $0a, $1f, $34, $12, $27, $05, $1a, $2f
db $0d, $22, $00, $15, $2a, $08, $1d, $32, $10
db $25, $03, $18, $2d, $0b, $20, $35, $13, $28
db $06, $1b, $30, $0e, $23, $01, $16, $2b, $09
db $1e, $33, $11, $26, $04, $19, $2e, $0c, $21
Func_9fa: ; 0x9fa
ld a, [wd810]
ld d, a
ld bc, wd812
ld hl, wd831
ld e, $18
.asm_a06
ld a, [bc]
sub [hl]
jr nc, .asm_a0b
add d
.asm_a0b
ld [bc], a
dec e
jr nz, .asm_a06
ld bc, wd82a
ld hl, wd812
ld e, $1f
.asm_a17
ld a, [bc]
sub [hl]
jr nc, .asm_a1c
add d
.asm_a1c
ld [bc], a
dec e
jr nz, .asm_a17
ret
Func_a21: ; 0xa21
push bc
push hl
ld c, a
ld b, $0
ld hl, Data_a38
add hl, bc
ld l, [hl]
call GenRandom
call Func_dd4
inc h
srl h
ld a, h
pop hl
pop bc
ret
Data_a38:
x = 0
REPT 128
db x | ((x >> 7) & 1)
x = x + 2
ENDR
ReadJoypad: ; 0xab8
; Reads the current state of the joypad and saves the state into
; some registers the game uses during gameplay. It remembers the joypad state
; from the current frame, previous frame, and two frames ago.
ld a, $20
ld [rJOYP], a
ld a, [rJOYP]
ld a, [rJOYP]
and $f
swap a
ld b, a
ld a, $30
ld [rJOYP], a
ld a, $10
ld [rJOYP], a
ld a, [rJOYP]
ld a, [rJOYP]
ld a, [rJOYP]
ld a, [rJOYP]
ld a, [rJOYP]
ld a, [rJOYP]
and $f
or b
cpl ; a contains currently-pressed buttons
ld [hJoypadState], a
ld a, $30
ld [rJOYP], a
ld a, [hJoypadState]
ld hl, hPreviousJoypadState
xor [hl] ; a contains buttons that are different from previous frame
push af
ld hl, hJoypadState
and [hl] ; a contains newly-pressed buttons compared to last frame
ld [hNewlyPressedButtons], a
ld [hPressedButtons], a
pop af
ld hl, hPreviousJoypadState
and [hl] ; a contains newly-pressed buttons compared to two frames ago
ld [hPrevPreviousJoypadState], a
ld a, [hJoypadState]
and a
jr z, .asm_b15
ld hl, hPreviousJoypadState
cp [hl]
jr nz, .asm_b15
; button(s) is pressed, and they're identical to the buttons pressed last frame.
; this code is related to holding down a button for an extended period of time.
ld hl, hJoyRepeatDelay
dec [hl]
jr nz, .asm_b1a
ld a, [hJoypadState]
ld [hPressedButtons], a
ld a, [wd807]
ld [hJoyRepeatDelay], a
jr .asm_b1a
.asm_b15
ld a, [wd806]
ld [hJoyRepeatDelay], a
.asm_b1a
ld a, [hJoypadState]
ld [hPreviousJoypadState], a
ld hl, wd808
ld a, [hJoypadState]
or [hl]
ld [hli], a
ld a, [hNewlyPressedButtons]
or [hl]
ld [hli], a
ld a, [hPressedButtons]
or [hl]
ld [hli], a
ret
Func_b2e: ; 0xb2e
ld hl, wd808
xor a
ld [hli], a
ld [hli], a
ld [hl], a
ret
IsKeyPressed2: ; 0xb36
ld a, [hJoypadState]
and [hl]
jr z, .asm_b3e
cp [hl]
jr z, .asm_b48
.asm_b3e
inc hl
ld a, [hJoypadState]
and [hl]
ret z
cp [hl]
jr z, .asm_b48
xor a
ret
.asm_b48
ld a, $1
and a
ret
IsKeyPressed: ; 0xb4c
; Checks if a key for the specified key config is pressed.
; input: hl = pointer to key config byte pair (e.g. wKeyConfigLeftFlipper)
; output: zero flag is set if a corresponding key is pressed
; zero flag is reset if no corresponding key is pressed
ld a, [hJoypadState]
and [hl]
jr z, .asm_b58
cp [hl]
jr nz, .asm_b58
ld a, [hNewlyPressedButtons]
and [hl]
ret nz
.asm_b58
inc hl
ld a, [hJoypadState]
and [hl]
ret z
cp [hl]
jr nz, .asm_b64
ld a, [hNewlyPressedButtons]
and [hl]
ret
.asm_b64
xor a
ret
Func_b66: ; 0xb66
ld a, [hGameBoyColorFlag]
and a
jr nz, .asm_b73
xor a
ld [hBGP], a
ld [hOBP0], a
ld [hOBP1], a
ret
.asm_b73
ld de, rBGPI
ld hl, wPaletteData
ld b, $0
ld c, $20
.asm_b7d
ld a, b
ld [rBGPI], a
inc b
ld a, [rBGPD]
ld [hli], a
ld a, b
ld [rBGPI], a
inc b
ld a, [rBGPD]
ld [hli], a
dec c
jr nz, .asm_b7d
ld b, $0
ld c, $20
.asm_b92
ld a, b
ld [rOBPI], a
inc b
ld a, [rOBPD]
ld [hli], a
ld a, b
ld [rOBPI], a
inc b
ld a, [rOBPD]
ld [hli], a
dec c
jr nz, .asm_b92
ld de, rBGPI
ld b, $2
.asm_ba8
ld a, $80
ld [de], a
inc de
ld c, $20
.asm_bae
ld a, $ff
ld [de], a
ld [hli], a
ld a, $7f
ld [de], a
ld [hli], a
dec c
jr nz, .asm_bae
inc de
dec b
jr nz, .asm_ba8
ret
Func_bbe: ; 0xbbe
ld a, [hGameBoyColorFlag]
and a
jp nz, Func_c19
ld hl, hBGP
ld de, wBGP
ld b, $3
.asm_bcc
ld a, [de]
and $55
ld c, a
ld a, [de]
and $aa
srl a
and c
ld [hli], a
inc de
dec b
jr nz, .asm_bcc
ld bc, $0002
call AdvanceFrames
ld hl, hBGP
ld de, wBGP
ld b, $3
.asm_be9
ld a, [de]
and $aa
srl a
add [hl]
ld [hli], a
inc de
dec b
jr nz, .asm_be9
ld bc, $0002
call AdvanceFrames
ld hl, hBGP
ld de, wBGP
ld b, $3
.asm_c02
ld a, [de]
and $55
ld c, a
ld a, [de]
and $aa
srl a
or c
add [hl]
ld [hli], a
inc de
dec b
jr nz, .asm_c02
ld bc, $0002
call AdvanceFrames
ret
Func_c19: ; 0xc19
ld b, $10
.asm_c1b
push bc
ld de, wPaletteData
ld hl, wd280
call Func_c2d
call Func_d61
pop bc
dec b
jr nz, .asm_c1b
ret
Func_c2d: ; 0xc2d
ld a, b
cp $1
jr z, .asm_c49
ld c, $40
.asm_c34
push bc
ld a, [hli]
sub $42
ld c, a
ld a, [hld]
sbc $8
ld b, a
call Func_c60
ld a, c
ld [hli], a
ld a, b
ld [hli], a
pop bc
dec c
jr nz, .asm_c34
ret
.asm_c49
ld c, $40
.asm_c4b
push bc
ld a, [hli]
sub $21
ld c, a
ld a, [hld]
sbc $4
ld b, a
call Func_c60
ld a, c
ld [hli], a
ld a, b
ld [hli], a
pop bc
dec c
jr nz, .asm_c4b
ret
Func_c60: ; 0xc60
push hl
ld a, [de]
and $1f
ld l, a
ld a, c
and $1f
cp l
jr nc, .asm_c70
ld a, c
and $e0
or l
ld c, a
.asm_c70
ld a, [de]
and $e0
ld l, a
inc de
ld a, [de]
srl a
rr l
srl a
rr l
ld a, c
and $e0
ld h, a
ld a, b
srl a
rr h
srl a
rr h
ld a, h
cp l
jr nc, .asm_ca3
ld h, $0
sla l
rl h
sla l
rl h
ld a, c
and $1f
or l
ld c, a
ld a, b
and $7c
or h
ld b, a
.asm_ca3
ld a, [de]
and $7c
ld l, a
ld a, b
and $7c
cp l
jr nc, .asm_cb2
ld a, b
and $3
or l
ld b, a
.asm_cb2
inc de
pop hl
ret
Func_cb5: ; 0xcb5
ld a, [hGameBoyColorFlag]
and a
jp nz, Func_cee
ld hl, hBGP
ld b, $3
.asm_cc0
push bc
push hl
ld b, $3
.asm_cc4
ld a, [hl]
and $55
ld c, a
ld a, [hl]
and $aa
srl a
or c
cpl
inc a
add [hl]
ld [hli], a
dec b
jr nz, .asm_cc4
ld bc, $0002
call AdvanceFrames
pop hl
pop bc
dec b
jr nz, .asm_cc0
xor a
ld hl, hBGP
ld [hli], a
ld [hli], a
ld [hl], a
ld bc, $0002
call AdvanceFrames
ret
Func_cee: ; 0xcee
ld hl, wd280
ld de, rBGPI
call Func_d9d
ld hl, wd2c0
ld de, rOBPI
call Func_d9d
ld b, $10
.asm_d02
push bc
ld hl, wd280
call Func_d11
call Func_d61
pop bc
dec b
jr nz, .asm_d02
ret
Func_d11: ; 0xd11
ld b, $40
.asm_d13
ld a, [hl]
and $1f
add $2
ld e, a
cp $1f
jr c, .asm_d1f
ld e, $1f
.asm_d1f
ld a, [hl]
and $e0
or e
ld [hl], a
ld a, [hli]
and $e0
ld e, [hl]
dec hl
srl e
rr a
srl e
rr a
add $10
ld e, a
jr nc, .asm_d38
ld e, $f8
.asm_d38
ld d, $0
sla e
rl d
sla e
rl d
ld a, [hl]
and $1f
or e
ld [hli], a
ld a, [hl]
and $7c
or d
ld [hl], a
ld a, [hl]
and $7c
add $8
ld e, a
cp $7c
jr c, .asm_d58
ld e, $7c
.asm_d58
ld a, [hl]
and $3
or e
ld [hli], a
dec b
jr nz, .asm_d13
ret
Func_d61: ; 0d61
ld a, [rIE]
res 0, a
ld [rIE], a
ld hl, wd280
ld de, rBGPI
ld a, $80
ld [de], a
inc de
.asm_d71
ld a, [rLY]
cp $90
jr c, .asm_d71
ld b, $10
.asm_d79
ld a, [hli]
ld [de], a
ld a, [hli]
ld [de], a
ld a, [hli]
ld [de], a
ld a, [hli]
ld [de], a
dec b
jr nz, .asm_d79
inc de
ld a, $80
ld [de], a
inc de
ld b, $10
.asm_d8b
ld a, [hli]
ld [de], a
ld a, [hli]
ld [de], a
ld a, [hli]
ld [de], a
ld a, [hli]
ld [de], a
dec b
jr nz, .asm_d8b
ld a, [rIE]
set 0, a
ld [rIE], a
ret
Func_d9d: ; 0xd9d
ld b, $0
ld c, e
inc c
call WaitForLCD
.asm_da4
call Func_61b
.asm_da7
ld a, [rSTAT]
and $3
jr nz, .asm_da7 ; wait for lcd controller to finish transferring data
ld a, b
ld [de], a
ld a, [$ff00+c]
ld [hli], a
inc b
ld a, b
ld [de], a
ld a, [$ff00+c]
ld [hli], a
inc b
ld a, b
ld [de], a
ld a, [$ff00+c]
ld [hli], a
inc b
ld a, b
ld [de], a
ld a, [$ff00+c]
ld [hli], a
inc b
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
ld a, b
cp $40
jr nz, .asm_da4
ret
Func_dd4: ; 0xdd4
; Return a * l to hl
; Stupid waste of space
push bc
ld c, l
ld b, $0
ld hl, $0000
bit 0, a
jr z, .asm_de0
add hl, bc
.asm_de0
sla c
rl b
bit 1, a
jr z, .asm_de9
add hl, bc
.asm_de9
sla c
rl b
bit 2, a
jr z, .asm_df2
add hl, bc
.asm_df2
sla c
rl b
bit 3, a
jr z, .asm_dfb
add hl, bc
.asm_dfb
sla c
rl b
bit 4, a
jr z, .asm_e04
add hl, bc
.asm_e04
sla c
rl b
bit 5, a
jr z, .asm_e0d
add hl, bc
.asm_e0d
sla c
rl b
bit 6, a
jr z, .asm_e16
add hl, bc
.asm_e16
sla c
rl b
bit 7, a
jr z, .asm_e1f
add hl, bc
.asm_e1f
pop bc
ret
ConvertHexByteToDecWord: ; 0xe21
; Convert the base-16 value in register a into a Binary Coded Decimal (base-10) word.
; Example: If a = $97, de = $0151.
ld b, a
ld hl, PowersOfTwo
ld de, $0000
.asm_e28
srl b
ld a, [hli]
jr nc, .asm_e34
add e
daa
ld e, a
ld a, [hl]
adc d
daa
ld d, a
.asm_e34
inc hl
ld a, b
and a
jr nz, .asm_e28
ret
PowersOfTwo: ; 0xe3a
dw $0001
dw $0002
dw $0004
dw $0008
dw $0016
dw $0032
dw $0064
dw $0128
Func_e4a: ; 0xe4a
ld a, [hl]
cp $64
jr z, .asm_e53
inc a
ld [hl], a
scf
ret
.asm_e53
and a
ret
Func_e55: ; 0xe55
cp c
jr c, .asm_e5b
sub c
jr Func_e55
.asm_e5b
and a
ret
Func_e5d: ; 0xe5d
ld a, $1
ld [wd84a], a
.asm_e62
ld a, [wd84a]
and a
jr nz, .asm_e62
ret
Func_e69: ; 0xe69
ld a, [rLY]
cp $90
jr nc, Func_e69
.asm_e6f
ld a, [rSTAT]
and $3
jr nz, .asm_e6f
ld a, $a
.asm_e77
dec a
jr nz, .asm_e77
ld hl, wBottomMessageBuffer + $40
call Func_eef
push hl
ld hl, $9c00
call Func_ef8
pop hl
call Func_eef
push hl
ld hl, $9c04
call Func_ef8
pop hl
call Func_eef
push hl
ld hl, $9c08
call Func_ef8
pop hl
call Func_eef
push hl
ld hl, $9c0c
call Func_ef8
pop hl
call Func_eef
push hl
ld hl, $9c10
call Func_ef8
pop hl
ld hl, wBottomMessageBuffer + $c0
call Func_eef
push hl
ld hl, $9c20
call Func_ef8
pop hl
call Func_eef
push hl
ld hl, $9c24
call Func_ef8
pop hl
call Func_eef
push hl
ld hl, $9c28
call Func_ef8
pop hl
call Func_eef
push hl
ld hl, $9c2c
call Func_ef8
pop hl
call Func_eef
push hl
ld hl, $9c30
call Func_ef8
pop hl
ret
Func_eef: ; 0xeef
ld a, [hli]
ld b, a
ld a, [hli]
ld c, a
ld a, [hli]
ld d, a
ld a, [hli]
ld e, a
ret
Func_ef8: ; 0xef8
ld a, [rSTAT]
and $3
jr nz, Func_ef8
ld a, b
ld [hli], a
ld a, c
ld [hli], a
ld a, d
ld [hli], a
ld a, e
ld [hli], a
ld a, $a
.asm_f08
dec a
jr nz, .asm_f08
ret
INCLUDE "home/save.asm"
Func_fbc: ; 0xfbc
jp Func_3ff
Func_fbf: ; 0xfbf
ld hl, hLastLYC
ld c, [hl]
ld a, [rLY]
cp c
jp c, Func_3ff
inc c
inc c
cp c
jp nc, Func_3ff
ld a, [hLCDCMask]
ld c, a
ld a, [hLCDC]
xor $10
and c
ld c, a
ld hl, rSTAT
.asm_fdb
ld a, [hl]
and $3
jr nz, .asm_fdb
ld a, [rLCDC]
and $80
or c
ld [rLCDC], a
jp Func_3ff
Func_fea: ; 0xfea
ld hl, hLastLYC
ld a, [hLYCSub]
cp [hl]
jr nz, .asm_1015
ld a, [rLY]
cp [hl]
jp nz, Func_3ff
ld a, [hLCDC]
xor $18
ld c, a
ld a, [hHBlankSCX]
ld b, a
ld hl, rSTAT
.asm_1003
ld a, [hl]
and $3
jr nz, .asm_1003
ld a, [rLCDC]
and $80
or c
ld [rLCDC], a
ld a, b
ld [rSCY], a
jp Func_3ff
.asm_1015
ld a, [rLY]
cp [hl]
jr nz, .asm_1037
ld a, [hLastLYC]
ld hl, hLYCSub
sub [hl]
add $40
ld c, a
ld a, [hLYCSub]
ld b, a
ld hl, rSTAT
.asm_1029
ld a, [hl]
and $3
jr nz, .asm_1029
ld a, c
ld [rSCY], a
ld a, b
ld [rLYC], a
jp Func_3ff
.asm_1037
ld hl, hLYCSub
ld a, [rLY]
cp [hl]
jp nz, Func_3ff
ld a, [hLCDC]
xor $18
ld c, a
ld a, [hHBlankSCX]
ld b, a
ld hl, rSTAT
.asm_104b
ld a, [hl]
and $3
jr nz, .asm_104b
ld a, [rLCDC]
and $80
or c
ld [rLCDC], a
ld a, b
ld [rSCY], a
jp Func_3ff
Func_105d: ; 0x105d
ld hl, hLastLYC
ld a, [rLY]
cp [hl]
jr z, .asm_1069
dec a
cp [hl]
jr nz, .asm_1080
.asm_1069
ld a, [hLYCSub]
ld c, a
ld a, [hHBlankSCX]
ld b, a
ld hl, rSTAT
.asm_1072
ld a, [hl]
and $3
jr nz, .asm_1072
ld a, b
ld [rSCY], a
ld a, c
ld [rLYC], a
jp Func_3ff
.asm_1080
ld hl, hLYCSub
ld a, [rLY]
cp [hl]
jr z, .asm_108d
dec a
cp [hl]
jp nz, Func_3ff
.asm_108d
ld a, [hHBlankSCY]
ld b, a
ld hl, rSTAT
.asm_1093
ld a, [hl]
and $3
jr nz, .asm_1093
ld a, b
ld [rSCY], a
jp Func_3ff
Func_109e: ; 0x109e
jp Func_3ff
Func_10a1: ; 0x10a1
jp Func_3ff
Func_10a4: ; 0x10a4
jp Func_3ff
Func_10a7: ; 0x10a7
jp Func_3ff
Func_10aa: ; 0x10aa
ld c, a
ld a, [hli]
ld b, a
.loop
push bc
ld a, c
ld c, [hl]
inc hl
ld b, [hl]
inc hl
push af
ld a, [bc]
ld e, a
inc bc
ld a, [bc]
ld d, a
inc bc
pop af
push hl
call Func_10c5
pop hl
pop bc
dec b
jr nz, .loop
ret
Func_10c5: ; 0x10c5
push af
ld a, [rLCDC]
bit 7, a
jr z, .skip_wait_ly
.wait_ly
ld a, [rLY]
cp $88
jr nc, .wait_ly
.skip_wait_ly
pop af
ld hl, wd7fb
ld l, [hl]
ld h, wcb00 / $100
inc bc
ld [hl], c
inc h
ld [hl], b
inc h
ld [hl], a
inc h
ld [hl], e
inc h
ld [hl], d
ld e, $ff
ld [hROMBankBuffer], a
ld a, [hLoadedROMBank]
push af
ld a, [hROMBankBuffer]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
dec bc
ld a, [bc]
ld hl, wd7fa
add [hl]
cp $30
jr c, .size_okay
ld a, [bc]
ld e, $0
.size_okay
add $4
ld [hl], a
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld hl, wd7fb
ld l, [hl]
ld h, wca00 / $100
inc l
ld [hl], $0
dec l
ld [hl], e
ld hl, wd7fb
inc [hl]
ld a, [rLCDC]
bit 7, a
ret nz
ld a, [rIE]
push af
res 0, a
ld [rIE], a
call Func_113a
pop af
ld [rIE], a
ret
Func_1129: ; 0x1129
ld a, [wd7fb]
ld [wd7fc], a
ret
Func_1130: ; 0x1130
push hl
ld a, [wd7fb]
ld hl, wd7fc
cp [hl]
pop hl
ret
Func_113a: ; 0x113a
ld hl, wd7fc
ld a, [wd7fb]
cp [hl]
ret z
ld l, [hl]
ld h, $ca
ld [hl], $ff
.loop
ld a, [hl]
and a
jr z, .done
push hl
inc h
ld e, [hl]
inc h
ld d, [hl]
inc h
ld a, [hLoadedROMBank]
push af
ld a, [hl]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
inc h
ld a, [hl]
inc h
ld h, [hl]
ld l, a
call JumpToHL
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
pop hl
inc l
jr .loop
.done
ld a, l
ld [wd7fc], a
ld hl, wd7fb
cp [hl]
ret nz
xor a
ld [wd7fa], a
ret
JumpToHL: ; 0x117a
jp [hl]
LoadTileLists: ; 0x117b
; Loads a series of defined tile ids into VRAM
; input: de = pointer to data structure
; data structure: list of VRAM tile data with the following format
; [num tiles][destination pointer][list of tile ids]
ld h, d
ld l, e
.loadTileSequence
ld a, [hli]
and a
ret z
ld b, a
ld a, [hli]
ld e, a
ld a, [hli]
ld d, a ; de = destination for tile data
.loadTileData
ld a, [hli]
ld [de], a
inc de
dec b
jr nz, .loadTileData
jr .loadTileSequence
LoadTileListsBank1: ; 0x118d
ld a, $1
ld [rVBK], a
call LoadTileLists
xor a
ld [rVBK], a
ret
Func_1198:
ld h, d
ld l, e
.asm_119a
ld a, [hli]
and a
ret z
ld b, a
ld a, [hli]
ld e, a
ld a, [hli]
ld d, a
srl b
jr nc, .asm_11a8
ld a, [hli]
ld c, a
.asm_11a8
push hl
ld h, d
ld l, e
ld a, c
.asm_11ac
ld [hli], a
inc a
dec b
jr nz, .asm_11ac
ld c, a
pop hl
jr .asm_119a
Func_11b5: ; 11b5 (0:11b5)
ld h, d
ld l, e
.asm_11b7
ld a, [hli]
and a
ret z
ld b, a
ld a, [hli]
ld e, a
ld a, [hli]
ld d, a
ld a, [hli]
.asm_11c0
ld [de], a
inc de
dec b
jr nz, .asm_11c0
jr .asm_11b7
Func_11c7:
ld a, $1
ld [rVBK], a
call Func_11b5
xor a
ld [rVBK], a
ret
Func_11d2:
ld h, d
ld l, e
ld a, [hLoadedROMBank]
ld [$ff94], a
.asm_11d8
ld a, [hli]
and a
ret z
ld [$ff95], a
ld a, [hli]
ld e, a
ld a, [hli]
ld d, a
ld a, [hli]
ld c, a
ld a, [hli]
ld b, a
ld a, [hli]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
push hl
ld h, b
ld l, c
ld a, [$ff95]
ld b, a
.asm_11f1
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc e
ld a, [hli]
ld [de], a
inc de
dec b
jr nz, .asm_11f1
pop hl
ld a, [$ff94]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
jr .asm_11d8
Func_122e:
ld a, $1
ld [rVBK], a
ld h, d
ld l, e
ld a, [hLoadedROMBank]
ld [$ff94], a
.asm_1238
ld a, [hli]
and a
jr nz, .asm_1240
xor a
ld [rVBK], a
ret
.asm_1240
ld [$ff95], a
ld a, [hli]
ld e, a
ld a, [hli]
ld d, a
ld a, [hli]
ld c, a
ld a, [hli]
ld b, a
ld a, [hli]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
push hl
ld h, b
ld l, c
ld a, [$ff95]
ld b, a
.asm_1256
ld a, [hli]
ld [de], a
inc de
dec b
jr nz, .asm_1256
pop hl
ld a, [$ff94]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
jr .asm_1238
LoadPalettes:
; Loads either BG or OAM palette data
; de = pointer to palette data
; first byte is number of colors to load
; second byte determines BG or OAM palette data
; third and fourth byte are a pointer to actual color data
; fifth byte is Bank of actual color data
; $00 marks the end of the list
ld h, d
ld l, e
.loop
ld a, [hli]
and a
ret z
ld [$ff94], a
ld a, [hli]
bit 6, a
ld de, rBGPI
jr z, .asm_127a
res 6, a
ld de, rOBPI
.asm_127a
set 7, a
ld [de], a
inc de
ld a, [hli]
ld c, a
ld a, [hli]
ld b, a
ld a, [hLoadedROMBank]
push af
ld a, [hli]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
push hl
ld h, b
ld l, c
ld a, [$ff94]
ld b, a
.loadColor
ld a, [hli]
ld [de], a
ld a, [hli]
ld [de], a
dec b
jr nz, .loadColor
pop hl
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
jr .loop
INCLUDE "home/sgb.asm"
INCLUDE "home/serial.asm"
Func_1a21: ; 0x1a21
call Func_1a59
call Func_1a89
jr c, .asm_1a3f
.asm_1a29
call Func_1aa9
call Func_1b3d
jr c, .asm_1a3f
ld a, [wd86c]
and a
jr z, .asm_1a29
call Func_1b60
jr c, .asm_1a3f
call Func_1b88
.asm_1a3f
call Func_1ba7
ret
Func_1a43: ; 0x1a43
xor a
ld [wd86e], a
call Func_1a59
call Func_1a89
jr c, .asm_1a54
ld a, $1
ld [wd86e], a
.asm_1a54
call Func_1ba7
ret
ret ; unused instruction?
Func_1a59: ; 0x1a59
ld [wd86a], a
ld a, h
ld [wd869], a
ld a, l
ld [wd868], a
ld a, $80
ld [wd866], a
ld a, $c2
ld [wd867], a
xor a
ld [wd86b], a
ld [wd86c], a
ld [wd86d], a
call Func_16a2
ld hl, rIE
set 3, [hl]
xor a
ld [$ffb1], a
ld a, $1
ld [wd8e1], a
ret
Func_1a89: ; 0x1a89
call Func_16e2
cp $f0
jr z, .asm_1a9f
cp $ff
jp z, Func_1bb2
ld a, [wd8c8]
cp $81
jp nz, Func_1bb2
and a
ret
.asm_1a9f
ld a, [hNewlyPressedButtons]
bit 1, a
jp nz, Func_1bd3
rst AdvanceFrame
jr Func_1a89
Func_1aa9: ; 0x1aa9
ld a, [wd866]
ld l, a
ld a, [wd867]
ld h, a
ld de, wc000
ld b, $2
.asm_1ab6
ld c, $14
.asm_1ab8
ld a, [hli]
call Func_1ae2
dec c
jr nz, .asm_1ab8
ld a, l
add $c
ld l, a
jr nc, .asm_1ac6
inc h
.asm_1ac6
dec b
jr nz, .asm_1ab6
ld a, l
ld [wd866], a
ld a, h
ld [wd867], a
ld a, [wd86b]
inc a
ld [wd86b], a
cp $9
jr nz, .asm_1ae1
ld a, $1
ld [wd86c], a
.asm_1ae1
ret
Func_1ae2: ; 0x1ae2
push bc
push hl
xor $80
swap a
ld c, a
and $f
ld b, a
ld a, c
and $f0
ld c, a
ld a, [wd868]
ld l, a
ld a, [wd869]
ld h, a
add hl, bc
ld a, [hLoadedROMBank]
push af
ld a, [wd86a]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
REPT 15
ld a, [hli]
ld [de], a
inc e
ENDR
ld a, [hli]
ld [de], a
inc de
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
pop hl
pop bc
ret
Func_1b3d: ; 0x1b3d
ld a, [wd86c]
ld [wd8dd], a
ld hl, wc000
ld a, $1
call Func_1779
cp $ff
jp z, Func_1bb2
cp $f0
jr z, .asm_1b56
and a
ret
.asm_1b56
ld a, [hNewlyPressedButtons]
bit BIT_B_BUTTON, a
jp nz, Func_1bd3
rst AdvanceFrame
jr Func_1b3d
Func_1b60: ; 0x1b60
ld a, $1
ld [wd8a8], a
ld a, $13
ld [wd8a9], a
call Func_1740
cp $ff
jp z, Func_1bb2
cp $f0
jr z, .asm_1b7e
ld bc, $001e
call AdvanceFrames
and a
ret
.asm_1b7e
ld a, [hNewlyPressedButtons]
bit BIT_B_BUTTON, a
jp nz, Func_1bd3
rst AdvanceFrame
jr Func_1b60
Func_1b88: ; 0x1b88
ld a, [wd8c7]
ld b, a
cp $ff
jr z, Func_1bb2
and $f0
jr nz, Func_1bb2
bit 1, b
jr nz, .asm_1b9d
call Func_16a2
and a
ret
.asm_1b9d
ld a, [hNewlyPressedButtons]
bit BIT_B_BUTTON, a
jp nz, Func_1bd3
rst AdvanceFrame
jr Func_1b88
Func_1ba7: ; 0x1ba7
ld hl, rIE
res 3, [hl]
xor a
ld [wd8e1], a
and a
ret
Func_1bb2: ; 0x1bb2
ld hl, Data_1bcf
ld a, [wd8c7]
cp $ff
jr z, .asm_1bc6
ld b, $3
.asm_1bbe
inc hl
sla a
jr c, .asm_1bc6
dec b
jr nz, .asm_1bbe
.asm_1bc6
ld a, [hl]
ld [wd86d], a
call Func_16a2
scf
ret
Data_1bcf:
db $02, $01, $04, $03
Func_1bd3: ; 0x1bd3
lb de, $00, $01
call PlaySoundEffect
ld a, $5
ld [wd86d], a
call Func_16a2
scf
ret
Func_1be3: ; 0x1be3
ld a, $c0
ld [rRP], a
ld a, $ff
ld [wd8ea], a
xor a
ld b, a
.asm_1bee
inc a
jr nz, .asm_1bee
inc b
jr nz, .asm_1bee
ld hl, wd8eb
ld a, [rKEY1]
bit 7, a
jr z, .asm_1c0c
ld [hl], $e
inc hl
ld [hl], $12
inc hl
ld [hl], $8
inc hl
ld [hl], $c
inc hl
ld [hl], $c
ret
.asm_1c0c
ld [hl], $6
inc hl
ld [hl], $8
inc hl
ld [hl], $2
inc hl
ld [hl], $4
inc hl
ld [hl], $5
ret
Func_1c1b: ; 0x1c1b
inc d
ret z
ld a, [$ff00+c]
bit 1, a
jr z, Func_1c1b
ret
Func_1c23: ; 0x1c23
inc d
ret z
ld a, [$ff00+c]
bit 1, a
jr nz, Func_1c23
ret
Func_1c2b: ; 0x1c2b
ld a, $c1
ld [$ff00+c], a
.asm_1c2e
dec d
jr nz, .asm_1c2e
ret
Func_1c32: ; 0x1c32
ld a, $c0
ld [$ff00+c], a
.asm_1c35
dec d
jr nz, .asm_1c35
ret
Func_1c39:
xor a
ld [hNumFramesSinceLastVBlank], a
ld a, $1
ld [wd8e9], a
.asm_1c41
ld b, $2
ld c, rRP % $100
ld a, [$ff00+c]
and b
jr z, Func_1c50
ld a, [hNumFramesSinceLastVBlank]
and a
jr nz, Func_1ca1
jr .asm_1c41
Func_1c50: ; 0x1c50
ld a, $1
ld [wd8e9], a
ld b, $1a
ld c, rRP % $100
ld d, $0
ld e, d
call Func_1c23
ld a, d
and a
jp z, Func_1dc2
ld d, e
call Func_1c1b
ld a, d
and a
jp z, Func_1dc2
call Func_1c23
ld a, d
and a
jp z, Func_1dc2
call Func_1c1b
ld a, d
and a
jp z, Func_1dc2
cp $8
jp c, Func_1dc2
cp $2a
jp nc, Func_1dc2
ld a, $0
ld [wd8ea], a
ld d, b
call Func_1c32
ld d, b
call Func_1c2b
ld d, b
call Func_1c32
ld d, b
call Func_1c2b
ld d, b
call Func_1c32
ret
Func_1ca1: ; 0x1ca1
ld a, $2
ld [wd8e9], a
ld b, $1a
ld c, rRP % $100
ld d, b
ld e, $0
call Func_1c32
ld d, b
call Func_1c2b
ld d, b
call Func_1c32
ld d, b
call Func_1c2b
ld d, b
call Func_1c32
ld d, e
call Func_1c23
ld a, d
and a
jp z, Func_1dc2
ld d, e
call Func_1c1b
ld a, d
and a
jp z, Func_1dc2
ld d, e
call Func_1c23
ld a, d
and a
jp z, Func_1dc2
ld d, e
call Func_1c1b
ld a, d
and a
jp z, Func_1dc2
ld d, $1a
call Func_1c32
ld a, $0
ld [wd8ea], a
ret
Func_1cef:
xor a
ld [rRP], a
ld a, $ff
ld [wd8ea], a
ret
Func_1cf8: ; 0x1cf8
xor a
ld [wd8e4], a
ld [wd8e5], a
push hl
push bc
ld hl, wd8e6
ld a, $5a
ld [hli], a
ld [hl], b
dec hl
ld b, $2
ld d, $1e
call Func_1c32
call Func_1d44
pop bc
pop hl
call Func_1ed3
call Func_1d44
ld a, [wd8e4]
ld [wd8e6], a
ld a, [wd8e5]
ld [wd8e7], a
ld hl, wd8e6
ld b, $2
call Func_1d44
ld hl, wd8ea
ld b, $1
call Func_1e3b
ld a, [wd8e6]
ld [wd8e4], a
ld a, [wd8e7]
ld [wd8e5], a
ret
Func_1d44: ; 0x1d44
ld a, [wd8ea]
cp $0
ret nz
ld c, rRP % $100
ld d, $16
call Func_1c2b
ld d, $16
call Func_1c32
ld a, b
cpl
ld b, a
.asm_1d59
inc b
jr z, .asm_1dae
ld a, $8
ld [wd8e3], a
ld a, [hli]
ld e, a
ld a, [wd8e4]
add e
ld [wd8e4], a
jr nc, .asm_1d75
ld a, [wd8e5]
inc a
ld [wd8e5], a
jr .asm_1d78
.asm_1d75
call Func_1ed3
.asm_1d78
ld a, e
rlca
ld e, a
jr nc, .asm_1d8d
ld a, [wd8eb]
ld d, a
call Func_1c2b
ld a, [wd8ec]
ld d, a
call Func_1c32
jr .asm_1d9b
.asm_1d8d
ld a, [wd8ed]
ld d, a
call Func_1c2b
ld a, [wd8ee]
ld d, a
call Func_1c32
.asm_1d9b
ld a, [wd8e3]
dec a
ld [wd8e3], a
jr z, .asm_1dac
call Func_1ed4
call Func_1ed4
jr .asm_1d78
.asm_1dac
jr .asm_1d59
.asm_1dae
call Func_1ed3
call Func_1ed3
call Func_1ed4
ld d, $16
call Func_1c2b
ld d, $16
call Func_1c32
ret
Func_1dc2: ; 0x1dc2
ld a, $2
ld [wd8ea], a
ret
Func_1dc8:
ld a, [wd8ea]
or $1
ld [wd8ea], a
ret
Func_1dd1: ; 0x1dd1
ld a, [wd8ea]
or $4
ld [wd8ea], a
ret
Func_1dda: ; 0x1dda
xor a
ld [wd8e4], a
ld [wd8e5], a
push hl
ld hl, wd8e6
ld b, $2
call Func_1e3b
ld a, [wd8e7]
ld [wd8e8], a
ld b, a
pop hl
ld a, [wd8e6]
cp $5a
jp nz, Func_1dd1
call Func_1e3b
ld a, [wd8e4]
ld d, a
ld a, [wd8e5]
ld e, a
push de
ld hl, wd8e6
ld b, $2
call Func_1e3b
pop de
ld hl, wd8e6
ld a, [hli]
xor d
ld b, a
ld a, [hl]
xor e
or b
jr z, .asm_1e22
ld a, [wd8ea]
or $1
ld [wd8ea], a
.asm_1e22
push de
ld hl, wd8ea
ld b, $1
call Func_1d44
pop de
ld a, d
ld [wd8e4], a
ld a, e
ld [wd8e5], a
ld a, [wd8e8]
cp $82
ret z
ret
Func_1e3b: ; 0x1e3b
ld a, [wd8ea]
cp $0
ret nz
ld c, rRP % $100
ld d, $0
call Func_1c23
ld a, d
or a
jp z, Func_1dc2
ld d, $0
call Func_1c1b
ld a, d
or a
jp z, Func_1dc2
ld d, $0
call Func_1c23
ld a, d
or a
jp z, Func_1dc2
call Func_1ed4
call Func_1ed4
push af
pop af
ld a, b
cpl
ld b, a
.asm_1e6c
inc b
jr z, .asm_1eb9
ld a, $8
ld [wd8e3], a
.asm_1e74
ld d, $0
call Func_1c1b
call Func_1c23
ld a, [wd8ef]
cp d
jr nc, .asm_1e88
ld a, e
set 0, a
ld e, a
jr .asm_1e8c
.asm_1e88
ld a, e
res 0, a
ld e, a
.asm_1e8c
ld a, [wd8e3]
dec a
ld [wd8e3], a
jr z, .asm_1ea0
ld a, e
rlca
ld e, a
call Func_1ed4
call Func_1ed4
jr .asm_1e74
.asm_1ea0
ld a, e
ld [hli], a
ld a, [wd8e4]
add e
ld [wd8e4], a
jr nc, .asm_1eb4
ld a, [wd8e5]
inc a
ld [wd8e5], a
jr .asm_1eb7
.asm_1eb4
call Func_1ed3
.asm_1eb7
jr .asm_1e6c
.asm_1eb9
ld d, $0
call Func_1c1b
ld a, d
and a
jp z, Func_1dc2
ld d, $11
call Func_1c32
ret
Func_1ec9:
ld b, $00
jp Func_1cf8
Func_1ece:
ld b, $00
jp Func_1dda
Func_1ed3: ; 0x1ed3
ret
Func_1ed4: ; 0x1ed4
jr z, .asm_1ed6
.asm_1ed6
jr nz, .asm_1ed8
.asm_1ed8
ret
Func_1ed9:
push bc
push de
push hl
ld e, a
ld d, $0
sla e
rl d
ld a, [hLoadedROMBank]
push af
ld a, BANK(Data_8f06)
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld hl, Data_8f06
jr asm_1f3b
Func_1ef2:
push bc
push de
push hl
ld e, a
ld d, $0
sla e
rl d
ld a, [hLoadedROMBank]
push af
ld a, BANK(Data_8f06)
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld hl, Data_8f06
jr asm_1f3b
LoadOAMData2: ; 0x1f0b
; This function loads OAM data, but it adds b and c to the x and y values
; input: a = OAM data id (see OAMDataPointers2)
push bc
push de
push hl
ld e, a
ld d, $0
sla e
rl d
ld a, [hLoadedROMBank]
push af
ld a, Bank(OAMDataPointers2)
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld hl, OAMDataPointers2
jr asm_1f3b
LoadOAMData: ; 0x1f24
; This function loads OAM data, but it adds b and c to the x and y values
; input: a = OAM data id (see OAMDataPointers)
push bc
push de
push hl
ld e, a
ld d, $0
sla e
rl d ; multiply de by 2
ld a, [hLoadedROMBank]
push af
ld a, Bank(OAMDataPointers)
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld hl, OAMDataPointers
asm_1f3b: ; 0x1f3b
add hl, de ; hl points to oam pointer in OAMDataPointers
ld a, [hli]
ld e, a
ld a, [hl]
ld d, a ; de points to OAM data
ld a, [wOAMBufferSize]
ld l, a
ld h, (wOAMBuffer >> 8)
.loadOAMDataLoop
ld a, [de]
cp $80 ; OAM data list terminator
jr z, .doneReadingOAMData
add c
ld [hli], a
inc de
ld a, [de]
add b
ld [hli], a
inc de
ld a, [de]
ld [hli], a
inc de
ld a, [de]
ld [hli], a
inc de
jr .loadOAMDataLoop
.doneReadingOAMData
ld a, l
ld [wOAMBufferSize], a
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
pop hl
pop de
pop bc
ret
Func_1f68:
push bc
push de
push hl
ld e, a
ld d, $0
sla e
rl d
ld a, [hLoadedROMBank]
push af
ld a, BANK(Data_8f06)
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld hl, Data_8f06 ; all 0s
jr asm_1fca
Func_1f81:
push bc
push de
push hl
ld e, a
ld d, $0
sla e
rl d
ld a, [hLoadedROMBank]
push af
ld a, BANK(Data_8f06)
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld hl, Data_8f06 ; all 0s
jr asm_1fca
Func_1f9a:
push bc
push de
push hl
ld e, a
ld d, $0
sla e
rl d
ld a, [hLoadedROMBank]
push af
ld a, BANK(OAMDataPointers2)
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld hl, OAMDataPointers2
jr asm_1fca
Func_1fb3:
push bc
push de
push hl
ld e, a
ld d, $0
sla e
rl d
ld a, [hLoadedROMBank]
push af
ld a, BANK(OAMDataPointers)
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld hl, OAMDataPointers
asm_1fca
add hl, de
ld a, [hli]
ld e, a
ld a, [hl]
ld d, a
ld a, [wOAMBufferSize]
ld l, a
ld h, $d0
.asm_1fd5
ld a, [de]
cp $80
jr z, .asm_1fee
add c
ld [hli], a
inc de
ld a, [de]
add b
ld [hli], a
inc de
ld a, [de]
push hl
ld hl, sp+$7
add [hl]
pop hl
ld [hli], a
inc de
ld a, [de]
ld [hli], a
inc de
jr .asm_1fd5
.asm_1fee
ld a, l
ld [wOAMBufferSize], a
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
pop hl
pop de
pop bc
ret
Func_1ffc: ; 0x1ffc
ld a, $b
ld [wd806], a
ld a, $4
ld [wd807], a
callba Func_3c000
ld a, $1
ld [wd85d], a
ld a, $37
ld [wd470], a
ld [wd471], a
ld [wd472], a
ld a, SCREEN_ERASE_ALL_DATA
ld [wCurrentScreen], a
.master_loop
call Func_2034
call DoScreenLogic
call CleanOAMBuffer
call Func_b2e
rst AdvanceFrame
jr .master_loop
Func_2034: ; 0x2034
ld a, [wd804]
and a
jr z, .asm_203f
dec a
ld [wd804], a
ret
.asm_203f
ld [wd803], a
ret
DoScreenLogic: ; 0x2043
ld a, [wCurrentScreen]
call CallInFollowingTable
CallTable_2049: ; 0x2049
; First two bytes is function pointer.
; Third byte is bank of function.
; Fourth byte seems to be unused.
; SCREEN_SELECT_GAMEBOY_TARGET
padded_dab HandleSelectGameboyTargetMenu
; SCREEN_ERASE_ALL_DATA
padded_dab HandleEraseAllDataMenu
; SCREEN_COPYRIGHT
padded_dab HandleCopyrightScreen
; SCREEN_TITLESCREEN
padded_dab HandleTitlescreen
; SCREEN_PINBALL_GAME
padded_dab HandlePinballGame
; SCREEN_POKEDEX
padded_dab HandlePokedexScreen
; SCREEN_OPTIONS
padded_dab HandleOptionsScreen
; SCREEN_HIGH_SCORES
padded_dab HandleHighScoresScreen
; SCREEN_FIELD_SELECT
padded_dab HandleFieldSelectScreen
; end of call table
LoadDexVWFCharacter: ; 0x206d
; Loads a single variable-width-font character used in various parts of the Pokedex screen.
ld a, [hLoadedROMBank]
push af
ld a, Bank(LoadDexVWFCharacter_)
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
call LoadDexVWFCharacter_
jr c, .asm_2084
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
and a
ret
.asm_2084
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
scf
ret
Func_208c: ; 0x208c
ld a, [hLoadedROMBank]
push af
ld a, Bank(Func_8ee0)
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
call Func_8ee0
jr c, .asm_20a3
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
and a
ret
.asm_20a3
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
scf
ret
MultiplyBbyCUnsigned: ; 0x20ab
; u16 bc = (u8)b * (u8)c
push af
xor a
ld [hSignedMathSignBuffer], a
jr asm_20c6
MultiplyBbyCSigned:
; s16 bc = (s8)b * (s8)c
push af
ld a, b
xor c
ld [hSignedMathSignBuffer], a
bit 7, b
jr z, .asm_20be
ld a, b
cpl
inc a
ld b, a
.asm_20be
bit 7, c
jr z, asm_20c6
ld a, c
cpl
inc a
ld c, a
asm_20c6
; b*c == (b**2 + c**2 - (b - c)**2) / 2
push de
push hl
ld a, b
cp c
jr nc, .c_le_b
ld b, c
ld c, a
.c_le_b
; hl = b**2 + c**2
ld h, SquaresLow / $100
ld l, c
ld e, [hl]
inc h ; SquaresHigh / $100
ld d, [hl]
ld l, b
ld a, [hl]
dec h
ld l, [hl]
ld h, a
add hl, de
push af
; hl -= (b - c) ** 2
ld d, SquaresLow / $100
ld a, b
sub c
ld e, a
ld a, [de]
ld c, a
inc d ; SquaresHigh / $100
ld a, [de]
ld b, a
ld a, l
sub c
ld l, a
ld a, h
sbc b
ld h, a
jr nc, .no_carry
pop af
ccf
jr .check_sign
.no_carry
pop af
.check_sign
; hl /= 2
rr h
rr l
ld b, h
ld c, l
ld a, [hSignedMathSignBuffer]
rlca
jr nc, .done
ld a, c
cpl
add $1
ld c, a
ld a, b
cpl
adc $0
ld b, a
.done
pop hl
pop de
pop af
ret
MultiplyBCByEAndRoundToMostSignificantShort: ; 0x210b
; bc = round(bc * e / 256)
; b^d = sign of output
push af
push hl
ld a, b
xor d
ld [hSignedMathSignBuffer2], a
bit 7, b
jr z, .positive1
ld a, c
cpl
add $1
ld c, a
ld a, b
cpl
adc $0
ld b, a
.positive1
push bc
ld b, e
call MultiplyBbyCUnsigned
ld l, c
ld h, b
ld bc, $0080
add hl, bc
ld l, h
ld h, $0
pop bc
ld c, e
call MultiplyBbyCUnsigned
add hl, bc
ld a, [hSignedMathSignBuffer2]
rlca
jr nc, .positive2
ld a, l
cpl
add $1
ld l, a
ld a, h
cpl
adc $0
ld h, a
.positive2
ld c, l
ld b, h
pop hl
pop af
ret
Cosine: ; 0x2147
; cos(a)
add $40
; fall through
Sine: ; 0x2149
; sin(a)
push hl
ld [hSignedMathSignBuffer], a
and $7f ; subtract 180 degrees
cp $40
jr c, .firstQuadrant
; convert angle so it's between 0 and 90 degrees
cpl
add $80+1
.firstQuadrant
ld hl, SineTable
ld e, a
ld d, $0
add hl, de
ld e, [hl]
pop hl
ld d, $0
ld a, [hSignedMathSignBuffer]
sla a
ret nc
ld d, $ff
ret
ApplyGravityToBall: ; 0x2168
; Adds a constant to the pinball's y velocity.
ld a, [wd549]
and a
ret z
ld de, $000b ; gravity added to y velocity every frame
ld hl, wBallYVelocity
ld a, [hli]
ld h, [hl]
ld l, a
add hl, de
ld a, l
ld [wBallYVelocity], a
ld a, h
ld [wBallYVelocity + 1], a
ret
LimitBallVelocity: ; 0x2180
; Ensures that the ball's x and y velocity are kept under a threshold.
; The ball can travel at a higher max speed when moving diagonally, since it
; limits the x and y components independently.
ld hl, wBallXVelocity + 1
call _LimitBallVelocity
ld hl, wBallYVelocity + 1
; fall through
_LimitBallVelocity: ; 0x2189
ld a, [hl]
bit 7, a ; is it negative velocity? (left or up)
jr nz, .negativeVelocity
cp $8
ret c
ld a, $7 ; max positive velocity
ld [hl], a
ret
.negativeVelocity
cp $f9
ret nc
ld a, $f9 ; max negative velocity
ld [hl], a
ret
MoveBallPosition: ; 0x219c
; Updates the ball's position according to its velocity
ld a, [wBallXPos]
ld [wPreviousBallXPos], a
ld a, [wBallXPos + 1]
ld [wPreviousBallXPos + 1], a
ld a, [wBallYPos]
ld [wPreviousBallYPos], a
ld a, [wBallYPos + 1]
ld [wPreviousBallYPos + 1], a
ld de, wBallXVelocity + 1
ld hl, wBallXPos
call AddVelocityToPosition
ld de, wBallYVelocity + 1
ld hl, wBallYPos
; fall through
AddVelocityToPosition: ; 0x21c3
ld a, [de]
bit 7, a
jr nz, .asm_21d1
cp 1+4
jr c, .asm_21da
ld bc, $04ff
jr .asm_21de
.asm_21d1
cp -4
jr nc, .asm_21da
ld bc, -$04ff
jr .asm_21de
.asm_21da
ld b, a
dec de
ld a, [de]
ld c, a
.asm_21de
ld a, [hl]
add c
ld [hli], a
ld a, [hl]
adc b
ld [hl], a
ret
NegateAngleAndApplyCollisionForce: ; 0x21e5
cpl
inc a
; fall through
ApplyCollisionForce: ; 0x21e7
push hl
; bc_ret = bc * cos(a) + de * sin(x)
; de_ret = bc * cos(a) - de * sin(x)
push bc
push de
ld [hSineOrCosineArgumentBuffer], a
call Cosine
ld a, e
ld [hCosineResultBuffer], a
ld a, d
ld [hCosineResultBuffer + 1], a
call MultiplyBCByEAndRoundToMostSignificantShort
ld l, c
ld h, b
pop bc
push bc
ld a, [hSineOrCosineArgumentBuffer]
call Sine
ld a, e
ld [hSineResultBuffer], a
ld a, d
ld [hSineResultBuffer + 1], a
call MultiplyBCByEAndRoundToMostSignificantShort
add hl, bc
pop de
pop bc
push hl
push de
ld a, [hSineResultBuffer]
ld e, a
ld a, [hSineResultBuffer + 1]
cpl
ld d, a
call MultiplyBCByEAndRoundToMostSignificantShort
ld l, c
ld h, b
pop bc
ld a, [hCosineResultBuffer]
ld e, a
ld a, [hCosineResultBuffer + 1]
ld d, a
call MultiplyBCByEAndRoundToMostSignificantShort
add hl, bc
ld d, h
ld e, l
pop bc
pop hl
ret
ApplyTorque: ; 0x222b
push hl
ld hl, wd7f8
ld [hl], $ff
bit 7, d
jr nz, .asm_2297
ld [hl], $0
ld a, d
cp $3
jr c, .asm_2254
ld a, $ff
ld [wd803], a
ld a, $1
ld [wd804], a
ld a, [wFlipperCollision]
and a
jr nz, .asm_2254
push de
ld de, $0008
call Func_4d8
pop de
.asm_2254
srl d
rr e
srl d
rr e
ld h, d
ld l, e
srl d
rr e
ld a, [wd7eb]
and a
jr z, .asm_226c
.asm_2268
add hl, de
dec a
jr nz, .asm_2268
.asm_226c
ld d, h
ld e, l
ld a, e
cpl
add $1
ld e, a
ld a, d
cpl
adc $0
ld d, a
ld a, [wBallSpin]
sra a
ld l, a
ld h, $0
bit 7, l
jr z, .asm_2286
ld h, $ff
.asm_2286
add hl, bc
ld b, h
ld c, l
push bc
sla c
rl b
sla c
rl b
ld a, b
ld [wBallSpin], a
pop bc
.asm_2297
pop hl
ret
LoadBallVelocity: ; 0x2299
; Loads velocity of the ball into bc and de
; bc = x velocity
; de = y velocity
push hl
ld hl, wBallXVelocity
ld a, [hli]
ld c, a
ld a, [hli]
ld b, a
ld a, [hli]
ld e, a
ld a, [hl]
ld d, a
pop hl
ret
SetBallVelocity: ; 0x22a7
; Sets the x and y velocities of the ball.
; bc = x velocity
; de = y velocity
push hl
ld hl, wBallXVelocity
ld a, c
ld [hli], a
ld a, b
ld [hli], a
ld a, e
ld [hli], a
ld a, d
ld [hl], a
pop hl
ret
CheckObjectCollision: ; 0x22b5
ld a, [wBallXPos + 1]
sub $4
push af
and $7
ld [wSubTileBallXPos], a ; sub-tile position
pop af
and $f8
ld c, a
ld a, [wBallYPos + 1]
sub $4
push af
and $7
ld [wSubTileBallYPos], a
pop af
and $f8
ld b, a
ld l, b ; bc contains tile coords of ball position
ld h, $0
sla l
rl h
sla l
rl h ; b was multiplied by 4 (y tile position)
srl c
srl c
srl c ; c was divided by 8 (x tile position)
ld b, $0
add hl, bc
ld a, l
ld [wBallPositionPointerOffsetFromStageTopLeft], a
ld a, h
ld [wBallPositionPointerOffsetFromStageTopLeft + 1], a
ld a, [wStageCollisionMapPointer]
ld c, a
ld a, [wStageCollisionMapPointer + 1]
ld b, a
add hl, bc ; hl = address of upper-left collision byte
ld a, [hLoadedROMBank]
push af
ld a, [wStageCollisionMapBank]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld bc, $001f ; number of tiles wide - 1
ld a, [hli]
ld [wUpperLeftCollisionAttribute], a
ld a, [hl]
ld [wUpperRightCollisionAttribute], a
add hl, bc
ld a, [hli]
ld [wLowerLeftCollisionAttribute], a
ld a, [hl]
ld [wLowerRightCollisionAttribute], a
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld a, [hLoadedROMBank]
push af
ld a, [wStageCollisionMasksBank]
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld a, [wSubTileBallXPos]
sla a
ld c, a
ld b, $0
ld hl, SubTileXPos_CollisionDataPointers
add hl, bc
ld e, [hl]
inc hl
ld d, [hl]
ld a, [wSubTileBallYPos]
ld c, a
ld b, $10 ; number of times to loop over .asm_233d
.asm_233d
push bc
ld a, [de]
inc de
add c ; add the sub tile y pos
push af
srl a
srl a
srl a
ld c, a
ld b, $0
ld hl, wUpperLeftCollisionAttribute
add hl, bc
ld a, [hl]
call Func_248a
jr nc, .asm_235e
pop af
and $7
ld c, a
ld b, $0
add hl, bc
jr .asm_237b
.asm_235e
ld c, a
ld b, $0
sla c
rl b
sla c
rl b
sla c
rl b
ld hl, wStageCollisionMasksPointer
ld a, [hli]
ld h, [hl]
ld l, a
add hl, bc
pop af
and $7
ld c, a
ld b, $0
add hl, bc
.asm_237b
ld a, [de]
inc de
and [hl]
push af
ld a, [de]
inc de
ld c, a
ld hl, wd7c9
add hl, bc
pop af
ld [hl], a
pop bc
dec b
jr nz, .asm_233d
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld hl, wd7c9
ld de, wd7d9
ld b, $4
.asm_239a
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
inc de
dec b
jr nz, .asm_239a
ld hl, wd7c9
ld de, $0000
ld b, $0
ld a, [hl]
and a
jr z, .asm_23c1
.asm_23b5
ld a, [hli]
inc b
and a
jr z, .asm_23c1
ld a, b
cp $11
jr nc, .asm_23ee
jr .asm_23b5
.asm_23c1
ld a, [hli]
inc b
and a
jr nz, .asm_23cd
ld a, b
cp $11
jr nc, .asm_23ee
jr .asm_23c1
.asm_23cd
push de
ld d, $1
ld c, b
dec c
.asm_23d2
ld a, [hli]
inc b
inc d
and a
jr nz, .asm_23d2
dec d
ld a, b
dec a
dec a
and $f
swap c
or c
ld c, a
ld a, d
cp e
pop de
jr c, .asm_23e9
ld e, a
ld d, c
.asm_23e9
ld a, b
cp $10
jr c, .asm_23c1
.asm_23ee
ld a, e
ld [wd7e9], a
and a
ret z
ld a, [hLoadedROMBank]
push af
ld a, Bank(CollisionForceAngles)
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
push de
ld e, d
ld d, $0
ld hl, CollisionForceAngles
add hl, de
ld a, [hl]
ld [wCollisionForceAngle], a
sla e
rl d
ld hl, CollisionYDeltas
add hl, de
ld a, [wBallYPos]
add [hl]
ld [wBallYPos], a
inc hl
ld a, [wBallYPos + 1]
adc [hl]
ld [wBallYPos + 1], a
ld hl, CollisionXDeltas
add hl, de
ld a, [wBallXPos]
add [hl]
ld [wBallXPos], a
inc hl
ld a, [wBallXPos + 1]
adc [hl]
ld [wBallXPos + 1], a
pop de
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld a, d
swap a
and $f
ld e, a
ld a, d
and $f
sub e
jr nc, .asm_2449
add $10
.asm_2449
add e
add e
inc a
and $1e
ld c, a
ld b, $0
ld hl, SubTileBallPosDeltas
add hl, bc
ld a, [wSubTileBallXPos]
add $4
add [hl]
bit 3, a
ld c, b
jr z, .asm_2462
ld c, $2
.asm_2462
ld a, [wSubTileBallYPos]
add $4
inc hl
add [hl]
bit 3, a
jr z, .asm_246e
inc c
.asm_246e
ld hl, wUpperLeftCollisionAttribute
add hl, bc
ld a, [hl]
ld [wCurCollisionAttribute], a
ld hl, BallPositionPointerOffsetDeltas
add hl, bc
ld a, [wBallPositionPointerOffsetFromStageTopLeft]
add [hl]
ld [wd7f6], a
ld a, [wBallPositionPointerOffsetFromStageTopLeft + 1]
adc $0
ld [wd7f7], a
ret
Func_248a: ; 0x248a
push af
ld a, [wCurrentStage]
bit 0, a
jr nz, .asm_2495
pop af
and a
ret
.asm_2495
pop af
cp $d0
ccf
ret nc
cp $e0
jr nc, .asm_24ab
sub $d0
sla a
sla a
sla a
ld l, a
ld h, $c4
scf
ret
.asm_24ab
push de
sub $e0
ld b, a
ld a, [wCurrentStage]
cp $6 ; gengar stage buggy?
jr nc, .bonusStage
bit 4, b
ld hl, BottomLeftCollisionMasks
ld a, [wd7af]
jr z, .asm_24c8
res 4, b
ld hl, BottomRightCollisionMasks
ld a, [wd7b3]
.asm_24c8
ld de, $0080
cp $7
jr c, .asm_24d5
add hl, de
cp $e
jr c, .asm_24d5
add hl, de
.asm_24d5
ld e, b
sla e
sla e
sla e
add hl, de
pop de
scf
ret
.bonusStage
bit 4, b
ld hl, BottomLeftBonusStageCollisionMasks
ld a, [wd7af]
jr z, .asm_24f2
res 4, b
ld hl, BottomRightBonusStageCollisionMasks
ld a, [wd7b3]
.asm_24f2
ld de, $0080
cp $7
jr c, .asm_24ff
add hl, de
cp $e
jr c, .asm_24ff
add hl, de
.asm_24ff
ld e, b
sla e
sla e
sla e
add hl, de
pop de
scf
ret
BallPositionPointerOffsetDeltas:
db $00, $20
db $01, $21
SubTileBallPosDeltas:
db 4, 0
db 4, 1
db 3, 3
db 1, 4
db 0, 4
db -1, 4
db -3, 3
db -4, 1
db -4, 0
db -4, -1
db -3, -3
db -1, -4
db 0, -4
db 1, -4
db 3, -3
db 4, -1
SubTileXPos_CollisionDataPointers: ; 0x252e
dw SubTileXPos_CollisionData0
dw SubTileXPos_CollisionData1
dw SubTileXPos_CollisionData2
dw SubTileXPos_CollisionData3
dw SubTileXPos_CollisionData4
dw SubTileXPos_CollisionData5
dw SubTileXPos_CollisionData6
dw SubTileXPos_CollisionData7
SubTileXPos_CollisionData0: ; 0x253e
db $00, $10, $0B
db $00, $08, $0C
db $00, $04, $0D
db $01, $40, $0A
db $01, $01, $0E
db $03, $80, $09
db $13, $80, $0F
db $04, $80, $08
db $14, $80, $00
db $05, $80, $07
db $15, $80, $01
db $07, $40, $06
db $07, $01, $02
db $08, $10, $05
db $08, $08, $04
db $08, $04, $03
SubTileXPos_CollisionData1: ; 0x256e
db $00, $08, $0B
db $00, $04, $0C
db $00, $02, $0D
db $01, $20, $0A
db $11, $80, $0E
db $03, $40, $09
db $13, $40, $0F
db $04, $40, $08
db $14, $40, $00
db $05, $40, $07
db $15, $40, $01
db $07, $20, $06
db $17, $80, $02
db $08, $08, $05
db $08, $04, $04
db $08, $02, $03
SubTileXPos_CollisionData2: ; 0x259e
db $00, $04, $0B
db $00, $02, $0C
db $00, $01, $0D
db $01, $10, $0A
db $11, $40, $0E
db $03, $20, $09
db $13, $20, $0F
db $04, $20, $08
db $14, $20, $00
db $05, $20, $07
db $15, $20, $01
db $07, $10, $06
db $17, $40, $02
db $08, $04, $05
db $08, $02, $04
db $08, $01, $03
SubTileXPos_CollisionData3: ; 0x25ce
db $00, $02, $0B
db $00, $01, $0C
db $10, $80, $0D
db $01, $08, $0A
db $11, $20, $0E
db $03, $10, $09
db $13, $10, $0F
db $04, $10, $08
db $14, $10, $00
db $05, $10, $07
db $15, $10, $01
db $07, $08, $06
db $17, $20, $02
db $08, $02, $05
db $08, $01, $04
db $18, $80, $03
SubTileXPos_CollisionData4: ; 0x25fe
db $00, $01, $0B
db $10, $80, $0C
db $10, $40, $0D
db $01, $04, $0A
db $11, $10, $0E
db $03, $08, $09
db $13, $08, $0F
db $04, $08, $08
db $14, $08, $00
db $05, $08, $07
db $15, $08, $01
db $07, $04, $06
db $17, $10, $02
db $08, $01, $05
db $18, $80, $04
db $18, $40, $03
SubTileXPos_CollisionData5: ; 0x262e
db $10, $80, $0B
db $10, $40, $0C
db $10, $20, $0D
db $01, $02, $0A
db $11, $08, $0E
db $03, $04, $09
db $13, $04, $0F
db $04, $04, $08
db $14, $04, $00
db $05, $04, $07
db $15, $04, $01
db $07, $02, $06
db $17, $08, $02
db $18, $80, $05
db $18, $40, $04
db $18, $20, $03
SubTileXPos_CollisionData6: ; 0x265e
db $10, $40, $0B
db $10, $20, $0C
db $10, $10, $0D
db $01, $01, $0A
db $11, $04, $0E
db $03, $02, $09
db $13, $02, $0F
db $04, $02, $08
db $14, $02, $00
db $05, $02, $07
db $15, $02, $01
db $07, $01, $06
db $17, $04, $02
db $18, $40, $05
db $18, $20, $04
db $18, $10, $03
SubTileXPos_CollisionData7: ; 0x268e
db $10, $20, $0B
db $10, $10, $0C
db $10, $08, $0D
db $11, $80, $0A
db $11, $02, $0E
db $03, $01, $09
db $13, $01, $0F
db $04, $01, $08
db $14, $01, $00
db $05, $01, $07
db $15, $01, $01
db $17, $80, $06
db $17, $02, $02
db $18, $20, $05
db $18, $10, $04
db $18, $08, $03
INCLUDE "data/sine_table.asm"
CheckGameObjectCollisions: ; 0x2720
ld a, $ff
ld [wTriggeredGameObject], a
call CheckGameObjectCollisions_
ld a, [wTriggeredGameObject]
ld [wPreviousTriggeredGameObject], a
ret
CheckGameObjectCollisions_: ; 0x272f
ld a, [wCurrentStage]
call CallInFollowingTable
GameObjectCollisions_CallTable: ; 0x2735
; STAGE_RED_FIELD_TOP
padded_dab CheckRedStageTopGameObjectCollisions
; STAGE_RED_FIELD_BOTTOM
padded_dab CheckRedStageBottomGameObjectCollisions
padded_dab DoNothing_18061
padded_dab CheckRedStageLaunchAlleyCollision_
; STAGE_BLUE_FIELD_TOP
padded_dab CheckBlueStageTopGameObjectCollisions
; STAGE_BLUE_FIELD_BOTTOM
padded_dab CheckBlueStageBottomGameObjectCollisions
; STAGE_GENGAR_BONUS
padded_dab CheckGengarBonusStageGameObjectCollisions
; STAGE_GENGAR_BONUS
padded_dab CheckGengarBonusStageGameObjectCollisions
; STAGE_MEWTWO_BONUS
padded_dab CheckMewtwoBonusStageGameObjectCollisions
; STAGE_MEWTWO_BONUS
padded_dab CheckMewtwoBonusStageGameObjectCollisions
; STAGE_MEOWTH_BONUS
padded_dab CheckMeowthBonusStageGameObjectCollisions
; STAGE_MEOWTH_BONUS
padded_dab CheckMeowthBonusStageGameObjectCollisions
; STAGE_DIGLETT_BONUS
padded_dab CheckDiglettBonusStageGameObjectCollisions
; STAGE_DIGLETT_BONUS
padded_dab CheckDiglettBonusStageGameObjectCollisions
; STAGE_SEEL_BONUS
padded_dab CheckSeelBonusStageGameObjectCollisions
; STAGE_SEEL_BONUS
padded_dab CheckSeelBonusStageGameObjectCollisions
HandleGameObjectCollision: ; 0x2775
; Handle collision checking for one set of game objects, such as the bumpers, Pikachu savers, etc.
; Input: hl = pointer to collision attribute list for game objects
; de = pointer to object collision struct
; carry flag = unset to skip the collision attribute list check
ld a, [wTriggeredGameObject]
inc a
jr nz, .noTrigger
ld a, [bc]
bit 7, a
jr nz, .noTrigger
push bc
push de
call nc, IsCollisionInList
pop hl
call c, CheckGameObjectCollision
ld a, [wTriggeredGameObject]
ld b, a
pop hl
ld [hl], $0
jr nc, .noTrigger
ld a, [wPreviousTriggeredGameObject]
cp b
jr z, .noTrigger
ld a, [wTriggeredGameObjectIndex]
ld [hli], a
ld a, [wTriggeredGameObject]
ld [hl], a
scf
ret
.noTrigger
and a
ret
CheckGameObjectCollision: ; 0x27a4
; Checks if any of the given game objects are colliding with the pinball.
; Saves information about which game object was collided.
; Sets carry flag if a game object was collided.
; Input: hl = pointer to game object struct with the following format:
; [x distance][y distance] (defines bounding box for the following list of objects)
; [game object id][object x][object y] (terminate this list with $FF)
xor a
ld [wTriggeredGameObjectIndex], a
ld a, [hli] ; x distance threshold
ld d, a
ld a, [hli] ; y distance threshold
ld e, a
ld a, [wBallXPos + 1]
ld b, a
ld a, [wBallYPos + 1]
ld c, a
.loop
ld a, [wTriggeredGameObjectIndex]
inc a
ld [wTriggeredGameObjectIndex], a
ld a, [hli]
ld [wTriggeredGameObject], a
cp $ff
ret z
ld a, [hli]
sub b
bit 7, a
jr z, .compareXDifference
cpl ; calculate absolute value of the difference
inc a
.compareXDifference
cp d
ld a, [hli]
jr nc, .loop
sub c
bit 7, a
jr z, .compareYDifference
cpl ; calculate absolute value of the difference
inc a
.compareYDifference
cp e
jr nc, .loop
scf
ret
IsCollisionInList: ; 0x27da
; Checks if the pinball's current collision attribute is in the given list.
; Input: hl = pointer to list of collision attributes, terminated by $FF.
; Output: Sets carry flag if the attribute is in the list.
; First byte in list is 0 if the list is independent of the stage's current collision state (Red stage's
; top section changes during gameply.)
ld a, [hli]
and a
jr z, .checkList
dec hl
ld a, [wStageCollisionState]
ld c, a
ld b, $0
add hl, bc
ld c, [hl]
add hl, bc
.checkList
ld a, [wd7e9]
and a
ret z
ld a, [wCurCollisionAttribute]
ld b, a
ld c, -1 ; This saves the list offset in C, but the result isn't used by any callers of this routine.
.loop
inc c
ld a, [hli]
cp $ff
ret z
cp b
jr nz, .loop
scf
ret
PinballCollidesWithPoints: ; 0x27fd
; Checks if pinball collides with any of the (x, y) points in the given list.
; Saves the index of the collided point.
; Input: hl = pointer to array of (x, y) points
; Output: Saves index of collided point in wd578
ld a, [wBallXPos + 1]
ld b, a
ld a, [wBallYPos + 1]
ld c, a
ld d, $0
.nextPoint
ld a, [hli]
and a
ret z
inc d
ld a, [hli]
sub b
cp $e8
ld a, [hli]
jr c, .nextPoint
sub c
cp $e8
jr c, .nextPoint
ld a, d
ld [wd578], a
ret
Func_281c: ; 0x281c
ld a, [wCurrentStage]
call CallInFollowingTable
CallTable_2822: ; 0x2822
; not collisions
; STAGE_RED_FIELD_TOP
padded_dab Func_1460e
; STAGE_RED_FIELD_BOTTOM
padded_dab Func_14652
padded_dab DoNothing_1806d
padded_dab Func_1806e
; STAGE_BLUE_FIELD_TOP
padded_dab Func_1c715
; STAGE_BLUE_FIELD_BOTTOM
padded_dab Func_1c769
; STAGE_GENGAR_BONUS
padded_dab Func_18377
; STAGE_GENGAR_BONUS
padded_dab Func_18377
; STAGE_MEWTWO_BONUS
padded_dab Func_19451
; STAGE_MEWTWO_BONUS
padded_dab Func_19451
; STAGE_MEOWTH_BONUS
padded_dab Func_2442a
; STAGE_MEOWTH_BONUS
padded_dab Func_2442a
; STAGE_DIGLETT_BONUS
padded_dab Func_19b88
; STAGE_DIGLETT_BONUS
padded_dab Func_19b88
; STAGE_SEEL_BONUS
padded_dab Func_25c5a
; STAGE_SEEL_BONUS
padded_dab Func_25c5a
Func_2862: ; 0x2862
ld a, [wd7be]
and a
jr nz, .asm_287c
ld a, [hGameBoyColorFlag]
and a
jr z, .asm_287b
ld a, $0
ld hl, Data_2890
ld de, $0052
ld bc, $0004
call FarCopyPalettes
.asm_287b
ret
.asm_287c
ld a, [hGameBoyColorFlag]
and a
jr z, .asm_288f
ld a, $0
ld hl, Data_2894
ld de, $0052
ld bc, $0004
call FarCopyPalettes
.asm_288f
ret
Data_2890:
RGB 31, 31, 31
RGB 21, 21, 27
Data_2894:
RGB 27, 10, 10
RGB 20, 04, 04
CatchBarTiles:
; The tile ids for the blue CATCH! bar under the wild pokemon
db $80, $AE, $AF, $B0, $B1, $B2, $B3, $80
CatchBarTilesEnd:
CopyHLToDE: ; 0x28a0
; Places [hl] into [de]
; Also places $0 into [de + 2]
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
inc de
xor a
ld [de], a
ret
UpdateAnimation: ; 0x28a9
; Updates an animation struct. (See wDugtrioAnimationFrameCounter)
; Input: de = pointer to 3-byte animation struct
; hl = pointer to animation frames data
; Sets carry flag if the animation is over.
ld a, [de]
and a
ret z ; return, if counter is zero
dec a
ld [de], a
ret nz ; return if counter is not zero after the decrement
push de
inc de
inc de
ld a, [de] ; a = current frame index
inc a
ld [de], a
ld c, a
ld b, $0
sla c
rl b
add hl, bc ; hl = pointer to two-byte entry in the frames data table
ld a, [hli]
pop de
and a
scf
ret z ; return if the next entry is $00
push de
ld [de], a ; save the animation duration
inc de
ld a, [hli]
ld [de], a ; save the next animation frame id
pop de
ret
INCLUDE "text.asm"
INCLUDE "home/text.asm"
Func_3500:
ld hl, wd464
ld a, e
ld [hli], a
ld a, d
ld [hli], a
ld a, c
ld [hli], a
ld a, b
ld [hli], a
xor a
ld [hli], a
ld [hl], a
ld bc, wd464
callba AddBigBCD6FromQueueWithBallMultiplier
ret
AddBCDEToCurBufferValue: ; 0x351c
ld hl, wd464
ld a, e
ld [hli], a
ld a, d
ld [hli], a
ld a, c
ld [hli], a
ld a, b
ld [hli], a
xor a
ld [hli], a
ld [hl], a
ld bc, wd464
callba AddBigBCD6FromQueue
ret
Func_3538: ; 0x3538
; Add BCD value bcde to [wd47a]. Cap at $99999999.
ld hl, wd47a
ld a, [hl]
add e
daa
ld [hli], a
ld a, [hl]
adc d
daa
ld [hli], a
ld a, [hl]
adc c
daa
ld [hli], a
ld a, [hl]
adc b
daa
ld [hli], a
ret nc
ld hl, wd47a
ld a, $99
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ret
Retrieve8DigitBCDValueAtwd47a: ; 0x3556
; Retrieves a 4-byte BCD value at wd47a
ld a, [wd47a]
ld e, a
ld a, [wd47a + 1]
ld d, a
ld a, [wd47a + 2]
ld c, a
ld a, [wd47a + 3]
ld b, a
ret
Func_3567:
; BCD add bc to hl
ld a, l
add c
daa
ld l, a
ld a, h
adc b
daa
ld h, a
ret
Func_3570:
; BCD add de to hl
ld a, l
add e
daa
ld l, a
ld a, h
adc d
daa
ld h, a
ret
Func_3579: ; 0x3579
; Delete 4-byte BCD value at wd47a
ld hl, wd47a
xor a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ret
HandleTilts: ; 0x3582
call HandleLeftTilt
call HandleRightTilt
call HandleUpperTilt
ret
HandleLeftTilt: ; 0x358c
ld a, [wLeftTiltReset]
and a
jr nz, .tiltCoolDown
ld hl, wKeyConfigLeftTilt
call IsKeyPressed2
jr z, .tiltCoolDown
ld a, [wLeftTiltCounter]
cp $3
jr z, .startCoolDown
inc a
ld [wLeftTiltCounter], a
cp $1
jr nz, .skipSoundEffect
lb de, $00, $3f
call PlaySoundEffect
.skipSoundEffect
ld a, [wd548]
ld hl, wd549
and [hl]
jr z, .skipBallMovement
ld a, [wBallXPos + 1]
dec a ; move ball's position to the left by 1 pixel
ld [wBallXPos + 1], a
.skipBallMovement
ld a, [wd79f]
inc a
ld [wd79f], a
ld a, $1
ld [wLeftTiltPushing], a
ret
.startCoolDown
ld a, $1
ld [wLeftTiltReset], a
.tiltCoolDown
xor a
ld [wLeftTiltPushing], a
ld a, [wLeftTiltCounter]
and a
jr z, .done
dec a
ld [wLeftTiltCounter], a
ld a, [wd79f]
dec a
ld [wd79f], a
ret
.done
ld hl, wKeyConfigLeftTilt
call IsKeyPressed2
ret nz
xor a
ld [wLeftTiltReset], a
ret
HandleRightTilt: ; 0x35f3
ld a, [wRightTiltReset]
and a
jr nz, .tiltCoolDown
ld hl, wKeyConfigRightTilt
call IsKeyPressed2
jr z, .tiltCoolDown
ld a, [wRightTiltCounter]
cp $3
jr z, .startCoolDown
inc a
ld [wRightTiltCounter], a
cp $1
jr nz, .skipSoundEffect
lb de, $00, $3f
call PlaySoundEffect
.skipSoundEffect
ld a, [wd548]
ld hl, wd549
and [hl]
jr z, .skipBallMovement
ld a, [wBallXPos + 1]
inc a ; move ball's position to the right by 1 pixel
ld [wBallXPos + 1], a
.skipBallMovement
ld a, [wd79f]
dec a
ld [wd79f], a
ld a, $1
ld [wRightTiltPushing], a
ret
.startCoolDown
ld a, $1
ld [wRightTiltReset], a
.tiltCoolDown
xor a
ld [wRightTiltPushing], a
ld a, [wRightTiltCounter]
and a
jr z, .done
dec a
ld [wRightTiltCounter], a
ld a, [wd79f]
inc a
ld [wd79f], a
ret
.done
ld hl, wKeyConfigRightTilt
call IsKeyPressed2
ret nz
xor a
ld [wRightTiltReset], a
ret
HandleUpperTilt: ; 0x365a
ld a, [wUpperTiltReset]
and a
jr nz, .tiltCoolDown
ld hl, wKeyConfigUpperTilt
call IsKeyPressed2
jr z, .tiltCoolDown
ld a, [wUpperTiltCounter]
cp $4
jr z, .startCoolDown
inc a
ld [wUpperTiltCounter], a
cp $1
jr nz, .skipSoundEffect
lb de, $00, $3f
call PlaySoundEffect
.skipSoundEffect
ld a, [wd548]
ld hl, wd549
and [hl]
jr z, .skipBallMovement
ld a, [wBallYPos + 1]
inc a ; move ball's position down by 1 pixel
ld [wBallYPos + 1], a
.skipBallMovement
ld a, [wd7a0]
dec a
ld [wd7a0], a
ld a, $1
ld [wUpperTiltPushing], a
ret
.startCoolDown
ld a, $1
ld [wUpperTiltReset], a
.tiltCoolDown
xor a
ld [wUpperTiltPushing], a
ld a, [wUpperTiltCounter]
and a
jr z, .done
dec a
ld [wUpperTiltCounter], a
ld a, [wd7a0]
inc a
ld [wd7a0], a
ret
.done
ld hl, wKeyConfigUpperTilt
call IsKeyPressed2
ret nz
xor a
ld [wUpperTiltReset], a
ret
ApplyTiltForces: ; 0x36c1
ld a, [wd548]
ld hl, wd549
and [hl]
ret z
ld c, $0
ld a, [wUpperTiltPushing]
srl a
rl c
ld a, [wRightTiltPushing]
srl a
rl c
ld a, [wLeftTiltPushing]
srl a
rl c
ld b, $0
sla c
ld hl, Data_372d
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
bit 7, h
ret nz
ld a, [wCollisionForceAngle]
ld c, a
ld b, $0
sla c
rl b
sla c
rl b
add hl, bc
ld a, [hLoadedROMBank]
push af
ld a, BANK(TiltLeftOnlyForce)
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ld a, [wBallXVelocity]
add [hl]
ld [wBallXVelocity], a
inc hl
ld a, [wBallXVelocity + 1]
adc [hl]
ld [wBallXVelocity + 1], a
inc hl
ld a, [wBallYVelocity]
add [hl]
ld [wBallYVelocity], a
inc hl
ld a, [wBallYVelocity + 1]
adc [hl]
ld [wBallYVelocity + 1], a
pop af
ld [hLoadedROMBank], a
ld [MBC5RomBank], a
ret
Data_372d:
dw -1 ; no tilt
dw TiltLeftOnlyForce
dw TiltRightOnlyForce
dw -1 ; left + right (cancel)
dw TiltUpOnlyForce
dw TiltUpLeftForce
dw TiltUpRightForce
dw TiltUpOnlyForce
SECTION "bank0.2", ROM0 [$3800]
BottomLeftCollisionMasks:
INCBIN "data/collision/masks/bottom_left_masks.masks"
BottomRightCollisionMasks:
INCBIN "data/collision/masks/bottom_right_masks.masks"
BottomLeftBonusStageCollisionMasks:
INCBIN "data/collision/masks/bottom_left_bonus_stage_masks.masks"
BottomRightBonusStageCollisionMasks:
INCBIN "data/collision/masks/bottom_right_bonus_stage_masks.masks"
SquaresLow:
x = 0
rept 256
db (x * x) % $100
x = x + 1
endr
SquaresHigh:
x = 0
rept 256
db (x * x) / $100
x = x + 1
endr