mirror of
https://github.com/pret/pokepinball.git
synced 2024-11-23 13:49:42 +00:00
3313 lines
54 KiB
NASM
3313 lines
54 KiB
NASM
SECTION "rst 00", ROM0
|
|
di
|
|
jp Entry
|
|
|
|
SECTION "rst 10", ROM0
|
|
jp DelayFrame
|
|
|
|
SECTION "rst 18", ROM0
|
|
jp JumpToFuncInTable
|
|
|
|
SECTION "rst 20", ROM0
|
|
jp _ReadHalfword
|
|
|
|
SECTION "VBlankInt", ROM0
|
|
jp VBlank
|
|
|
|
SECTION "STATInt", ROM0
|
|
jp LCDCStatus
|
|
|
|
SECTION "TimerInt", ROM0
|
|
jp Timer
|
|
|
|
SECTION "SerialInt", ROM0
|
|
jp Serial
|
|
|
|
SECTION "JoypadInt", ROM0
|
|
jp Joypad
|
|
|
|
SECTION "Entry", ROM0
|
|
|
|
Entry: ; 0x100
|
|
nop
|
|
jp Start
|
|
|
|
SECTION "Header", ROM0
|
|
|
|
; The header is generated by rgbfix.
|
|
; The space here is allocated to prevent code from being overwritten.
|
|
rept $150 - $104
|
|
db 0 ;using ds fills the area with the fill value (which may not be $00); if this is changed from $00 the ROM won't build
|
|
endr
|
|
|
|
SECTION "Main", ROM0
|
|
|
|
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 [hStatIntrRoutine], 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 [wUpdateAudioEngineUsingTimerInterrupt], a
|
|
ld [wToggleAudioEngineUpdateMethod], 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 [wRNGModulus], a
|
|
call ResetRNG
|
|
xor a
|
|
ld [wBootCheck], a
|
|
ld a, BANK(Main)
|
|
ld hl, Main
|
|
call BankSwitchSimple
|
|
Func_23b: ; 0x23b
|
|
ld a, [hGameBoyColorFlag]
|
|
cp $11
|
|
jr nz, .asm_248
|
|
ld a, $1
|
|
ld [hGameBoyColorFlag], a
|
|
ld [hGameBoyColorFlagBackup], a
|
|
ret
|
|
|
|
.asm_248
|
|
xor a
|
|
ld [hGameBoyColorFlag], a
|
|
ld [hGameBoyColorFlagBackup], 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 [hStatIntrRoutine], 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 [wUpdateAudioEngineUsingTimerInterrupt], a
|
|
ld [wToggleAudioEngineUpdateMethod], 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 [wRNGModulus], a
|
|
call ResetRNG
|
|
ld a, [hGameBoyColorFlag]
|
|
ld [hGameBoyColorFlagBackup], a
|
|
xor a
|
|
ld [wBootCheck], a
|
|
ld a, Bank(Main)
|
|
ld hl, Main
|
|
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] ;hWY
|
|
ld [$ff00+c], a ;into FF4A
|
|
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, [wBootCheck]
|
|
and a
|
|
jr nz, .skipBootCheck
|
|
ld a, [hJoypadState]
|
|
cp $f
|
|
jr nz, .skipBootCheck
|
|
ld a, [hNewlyPressedButtons]
|
|
and $f
|
|
jr z, .skipBootCheck
|
|
ld hl, sp + 8
|
|
ld [hl], FadeAndSoftReset & $ff
|
|
inc hl
|
|
ld [hl], FadeAndSoftReset >> 8
|
|
ld a, $1
|
|
ld [wBootCheck], a
|
|
.skipBootCheck
|
|
ld hl, hNumFramesSinceLastVBlank
|
|
ld a, [hl]
|
|
inc [hl]
|
|
and a
|
|
jr nz, .asm_365
|
|
ld hl, hFrameCounter
|
|
inc [hl]
|
|
.asm_365
|
|
ld hl, hVBlankCount
|
|
inc [hl]
|
|
ld a, [wd8e1]
|
|
and a
|
|
call nz, Func_167b
|
|
ld a, [wUpdateAudioEngineUsingTimerInterrupt]
|
|
and a
|
|
jr nz, .skipAudioEngineUpdate
|
|
ld a, [wAudioEngineEnabled]
|
|
and a
|
|
call nz, UpdateSFX
|
|
.skipAudioEngineUpdate
|
|
ld a, [wToggleAudioEngineUpdateMethod]
|
|
and a
|
|
jr z, .skipTimerToggle
|
|
; Enable timer interrupts for audio engine updating.
|
|
xor a
|
|
ld [wToggleAudioEngineUpdateMethod], a
|
|
ld a, $1
|
|
ld [wUpdateAudioEngineUsingTimerInterrupt], a
|
|
ld a, -68
|
|
ld [rTMA], a
|
|
ld a, $0
|
|
ld [rTAC], a
|
|
ld hl, rIE
|
|
set 2, [hl]
|
|
ld a, $4
|
|
ld [rTAC], a ; Timer interrupt will fire ~60 times per second
|
|
.skipTimerToggle
|
|
ld hl, MBC5SRamBank
|
|
ld a, [wd917]
|
|
and a
|
|
jr nz, .asm_3b5
|
|
ld a, [wRumblePattern]
|
|
rrca
|
|
ld [wRumblePattern], a
|
|
and $1
|
|
jr z, .asm_3b5
|
|
set 3, [hl]
|
|
jr .asm_3b7
|
|
|
|
.asm_3b5
|
|
res 3, [hl]
|
|
.asm_3b7
|
|
ld a, [wDrawBottomMessageBox]
|
|
and a
|
|
call nz, DrawBottomMessageBox
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
pop af
|
|
reti
|
|
|
|
FadeAndSoftReset:
|
|
ld a, [rLCDC]
|
|
bit 7, a
|
|
jr z, .LCD_disabled
|
|
call FadeOut
|
|
; Fades palettes in from white screen.
|
|
call DisableLCD
|
|
.LCD_disabled
|
|
ld hl, hSTAT
|
|
res 6, [hl] ; disable LYC=LY interrupt
|
|
ld hl, rIE
|
|
res 1, [hl] ; disable STAT interrupt
|
|
xor a
|
|
ld [MBC5SRamEnable], a
|
|
ld [rSB], a
|
|
ld [rSC], a
|
|
ld [rIE], a
|
|
ld [rNR52], a
|
|
ld a, [hGameBoyColorFlagBackup]
|
|
ld [hGameBoyColorFlag], a
|
|
jp SoftReset
|
|
|
|
LCDCStatus: ; 0x3ec
|
|
push af
|
|
push bc
|
|
push de
|
|
push hl
|
|
ld a, [hStatIntrRoutine]
|
|
sla a
|
|
ld c, a
|
|
ld b, 0
|
|
ld hl, StatIntrRoutines
|
|
add hl, bc
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
jp hl
|
|
|
|
StatIntrDone: ; 0x3ff
|
|
ld a, $1
|
|
ld [hStatIntrFired], a
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
pop af
|
|
reti
|
|
|
|
StatIntrRoutines: ; 0x408s
|
|
dw StatIntrNothing
|
|
dw StatIntrTogglePinballWindow
|
|
dw StatIntrTogglePokedexWindow
|
|
dw StatIntrToggleHighScoresWindow
|
|
dw StatIntrNothing2
|
|
dw StatIntrNothing3
|
|
dw StatIntrNothing4
|
|
dw StatIntrNothing5
|
|
|
|
Timer: ; 0x418
|
|
ei
|
|
push af
|
|
push bc
|
|
push de
|
|
push hl
|
|
ld a, [wUpdateAudioEngineUsingTimerInterrupt]
|
|
and a
|
|
jr z, .asm_42a
|
|
ld a, [wAudioEngineEnabled]
|
|
and a
|
|
call nz, UpdateSFX
|
|
.asm_42a
|
|
ld a, [wToggleAudioEngineUpdateMethod]
|
|
and a
|
|
jr z, .skipTimer
|
|
xor a
|
|
ld [wToggleAudioEngineUpdateMethod], a
|
|
ld [wUpdateAudioEngineUsingTimerInterrupt], a
|
|
; disable timer
|
|
ld a, $0
|
|
ld [rTAC], a
|
|
ld hl, rIE
|
|
res 2, [hl]
|
|
.skipTimer
|
|
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
|
|
|
|
_ReadHalfword: ; 0x486
|
|
rlca
|
|
add l
|
|
ld l, a
|
|
jr nc, .noCarry
|
|
inc h
|
|
.noCarry
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
ret
|
|
|
|
INCLUDE "home/audio.asm"
|
|
|
|
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
|
|
|
|
DisableLCD: ; 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
|
|
|
|
EnableLCD: ; 0x588
|
|
ld a, [hFFC4]
|
|
and a
|
|
call nz, .UpdatePals
|
|
ld a, [hLCDC]
|
|
set 7, a
|
|
ld [rLCDC], a
|
|
ld [hLCDC], a
|
|
ret
|
|
|
|
.UpdatePals
|
|
ld de, rBGPI
|
|
ld a, $80
|
|
ld [de], a
|
|
inc de
|
|
ld b, $8
|
|
.asm_5a0
|
|
ld a, [wBGP]
|
|
call .UpdateDMGPals
|
|
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 .UpdateDMGPals
|
|
ld a, [wOBP1]
|
|
call .UpdateDMGPals
|
|
dec b
|
|
jr nz, .asm_5b2
|
|
ret
|
|
|
|
.UpdateDMGPals
|
|
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
|
|
|
|
VBlankIntDisable:
|
|
ld a, [rIE]
|
|
res 0, a
|
|
ld [rIE], a
|
|
ret
|
|
|
|
VBlankIntEnable:
|
|
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
|
|
.delay40Cycles
|
|
dec a
|
|
jr nz, .delay40Cycles
|
|
ret
|
|
|
|
INCLUDE "home/copy.asm"
|
|
|
|
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
|
|
|
|
INCLUDE "home/random.asm"
|
|
INCLUDE "home/joypad.asm"
|
|
INCLUDE "home/palettes.asm"
|
|
|
|
MultiplyAbyL_AncientEgyptian: ; 0xdd4
|
|
; Return a * l to hl
|
|
; This is a constant-time multiplication algorithm that uses binary decomposition to achieve the result.
|
|
; See https://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication
|
|
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
|
|
|
|
Increment_Max100: ; 0xe4a
|
|
; Increments the value at [hl], but caps it at 100.
|
|
; Sets carry flag if the increment happens.
|
|
ld a, [hl]
|
|
cp 100
|
|
jr z, .maxValue
|
|
inc a
|
|
ld [hl], a
|
|
scf
|
|
ret
|
|
|
|
.maxValue
|
|
and a
|
|
ret
|
|
|
|
Modulo_C: ; 0xe55
|
|
; Calculates A modulo C
|
|
; Sets zero flag if result is zero
|
|
cp c
|
|
jr c, .done
|
|
sub c
|
|
jr Modulo_C
|
|
|
|
.done
|
|
and a
|
|
ret
|
|
|
|
ToggleAudioEngineUpdateMethod: ; 0xe5d
|
|
; The audio engine is normally updated once every V-Blank interrupt. However, during pinball gameplay,
|
|
; the LCD is disabled (no V-Blanks) when the pinball is transitioning between the Top- and Bottom-halfs of
|
|
; the Red and Blue Fields. Therefore, the audio engine wouldn't get updated for a fraction of a second, which
|
|
; would has a noticeable pause in the music. To solve this, the Timer interrupt is enabled while the V-Blank is
|
|
; disabled, and the audio engine gets updated during the Timer interrupt.
|
|
ld a, $1
|
|
ld [wToggleAudioEngineUpdateMethod], a
|
|
.wait
|
|
ld a, [wToggleAudioEngineUpdateMethod]
|
|
and a
|
|
jr nz, .wait
|
|
ret
|
|
|
|
DrawBottomMessageBox: ; 0xe69
|
|
; Draws the current scrolling bottom message box to VRAM during V-Blank.
|
|
; Note, this only applies to the 1-tile high message bar. When it displays, things like Ball Bonus summary, and
|
|
; the Save/Cancel menu, this is not used to draw the message buffer.
|
|
ld a, [rLY]
|
|
cp $90
|
|
jr nc, DrawBottomMessageBox ; ensure we're in V-Blank
|
|
.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 Load4BottomMessageBytes
|
|
push hl
|
|
ld hl, $9c00
|
|
call Write4BottomMessageBytes
|
|
pop hl
|
|
call Load4BottomMessageBytes
|
|
push hl
|
|
ld hl, $9c04
|
|
call Write4BottomMessageBytes
|
|
pop hl
|
|
call Load4BottomMessageBytes
|
|
push hl
|
|
ld hl, $9c08
|
|
call Write4BottomMessageBytes
|
|
pop hl
|
|
call Load4BottomMessageBytes
|
|
push hl
|
|
ld hl, $9c0c
|
|
call Write4BottomMessageBytes
|
|
pop hl
|
|
call Load4BottomMessageBytes
|
|
push hl
|
|
ld hl, $9c10
|
|
call Write4BottomMessageBytes
|
|
pop hl
|
|
ld hl, wBottomMessageBuffer + $c0
|
|
call Load4BottomMessageBytes
|
|
push hl
|
|
ld hl, $9c20
|
|
call Write4BottomMessageBytes
|
|
pop hl
|
|
call Load4BottomMessageBytes
|
|
push hl
|
|
ld hl, $9c24
|
|
call Write4BottomMessageBytes
|
|
pop hl
|
|
call Load4BottomMessageBytes
|
|
push hl
|
|
ld hl, $9c28
|
|
call Write4BottomMessageBytes
|
|
pop hl
|
|
call Load4BottomMessageBytes
|
|
push hl
|
|
ld hl, $9c2c
|
|
call Write4BottomMessageBytes
|
|
pop hl
|
|
call Load4BottomMessageBytes
|
|
push hl
|
|
ld hl, $9c30
|
|
call Write4BottomMessageBytes
|
|
pop hl
|
|
ret
|
|
|
|
Load4BottomMessageBytes: ; 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
|
|
|
|
Write4BottomMessageBytes: ; 0xef8
|
|
ld a, [rSTAT]
|
|
and $3
|
|
jr nz, Write4BottomMessageBytes
|
|
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"
|
|
|
|
StatIntrNothing: ; 0xfbc
|
|
jp StatIntrDone
|
|
|
|
StatIntrTogglePinballWindow:
|
|
; Handles switching the tile data to the black status bar
|
|
; window anchored to the bottom of the screen during pinball
|
|
; gameplay.
|
|
ld hl, hLastLYC
|
|
ld c, [hl]
|
|
ld a, [rLY]
|
|
cp c
|
|
jp c, StatIntrDone
|
|
inc c
|
|
inc c
|
|
cp c
|
|
jp nc, StatIntrDone
|
|
ld a, [hLCDCMask]
|
|
ld c, a
|
|
ld a, [hLCDC]
|
|
xor $10 ; toggle window tile data
|
|
and c
|
|
ld c, a
|
|
ld hl, rSTAT
|
|
.waitForHBlank
|
|
ld a, [hl]
|
|
and $3
|
|
jr nz, .waitForHBlank
|
|
ld a, [rLCDC]
|
|
and $80 ; enable LCD display
|
|
or c
|
|
ld [rLCDC], a
|
|
jp StatIntrDone
|
|
|
|
StatIntrTogglePokedexWindow: ; 0xfea
|
|
ld hl, hLastLYC
|
|
ld a, [hLYCSub]
|
|
cp [hl]
|
|
jr nz, .asm_1015
|
|
ld a, [rLY]
|
|
cp [hl]
|
|
jp nz, StatIntrDone
|
|
ld a, [hLCDC]
|
|
xor $18 ; toggle window tile data and tile map
|
|
ld c, a
|
|
ld a, [hHBlankSCX]
|
|
ld b, a
|
|
ld hl, rSTAT
|
|
.waitForHBlank
|
|
ld a, [hl]
|
|
and $3
|
|
jr nz, .waitForHBlank
|
|
ld a, [rLCDC]
|
|
and $80 ; enable LCD display
|
|
or c
|
|
ld [rLCDC], a
|
|
ld a, b
|
|
ld [rSCY], a
|
|
jp StatIntrDone
|
|
|
|
.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
|
|
.waitForHBlank_2
|
|
ld a, [hl]
|
|
and $3
|
|
jr nz, .waitForHBlank_2
|
|
ld a, c
|
|
ld [rSCY], a
|
|
ld a, b
|
|
ld [rLYC], a
|
|
jp StatIntrDone
|
|
|
|
.asm_1037
|
|
ld hl, hLYCSub
|
|
ld a, [rLY]
|
|
cp [hl]
|
|
jp nz, StatIntrDone
|
|
ld a, [hLCDC]
|
|
xor $18 ; toggle window tile data and tile map
|
|
ld c, a
|
|
ld a, [hHBlankSCX]
|
|
ld b, a
|
|
ld hl, rSTAT
|
|
.waitForHBlank_3
|
|
ld a, [hl]
|
|
and $3
|
|
jr nz, .waitForHBlank_3
|
|
ld a, [rLCDC]
|
|
and $80
|
|
or c
|
|
ld [rLCDC], a
|
|
ld a, b
|
|
ld [rSCY], a
|
|
jp StatIntrDone
|
|
|
|
StatIntrToggleHighScoresWindow:
|
|
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
|
|
.waitForHBlank
|
|
ld a, [hl]
|
|
and $3
|
|
jr nz, .waitForHBlank
|
|
ld a, b
|
|
ld [rSCY], a
|
|
ld a, c
|
|
ld [rLYC], a
|
|
jp StatIntrDone
|
|
|
|
.asm_1080
|
|
ld hl, hLYCSub
|
|
ld a, [rLY]
|
|
cp [hl]
|
|
jr z, .asm_108d
|
|
dec a
|
|
cp [hl]
|
|
jp nz, StatIntrDone
|
|
.asm_108d
|
|
ld a, [hHBlankSCY]
|
|
ld b, a
|
|
ld hl, rSTAT
|
|
.waitForHBlank_2
|
|
ld a, [hl]
|
|
and $3
|
|
jr nz, .waitForHBlank_2
|
|
ld a, b
|
|
ld [rSCY], a
|
|
jp StatIntrDone
|
|
|
|
StatIntrNothing2: ; 0x109e
|
|
jp StatIntrDone
|
|
|
|
StatIntrNothing3: ; 0x10a1
|
|
jp StatIntrDone
|
|
|
|
StatIntrNothing4: ; 0x10a4
|
|
jp StatIntrDone
|
|
|
|
StatIntrNothing5: ; 0x10a7
|
|
jp StatIntrDone
|
|
|
|
QueueGraphicsToLoad: ; 0x10aa
|
|
; Queues graphics data to be loaded into VRAM at the next available time.
|
|
; See the data/queued_tiledata/ directory to view the data that is loaded by this function.
|
|
; Input: hl = pointer to async tile data header
|
|
; byte 1 = number of chunks to load
|
|
; 2*(byte 1) = list of pointers to chunks
|
|
; a = bank of async tile data
|
|
ld c, a
|
|
ld a, [hli]
|
|
ld b, a
|
|
.loop
|
|
push bc
|
|
ld a, c
|
|
ld c, [hl]
|
|
inc hl
|
|
ld b, [hl] ;pull pointer from HL, load into BC
|
|
inc hl
|
|
push af
|
|
ld a, [bc]
|
|
ld e, a
|
|
inc bc
|
|
ld a, [bc]
|
|
ld d, a ;pull de from bc
|
|
inc bc
|
|
pop af
|
|
push hl
|
|
call QueueGraphicsToLoadWithFunc
|
|
pop hl
|
|
pop bc
|
|
dec b
|
|
jr nz, .loop
|
|
ret
|
|
|
|
QueueGraphicsToLoadWithFunc: ; 0x10c5
|
|
; Queues graphics data to be loaded into VRAM with the given function at the next available time.
|
|
; See the data/queued_tiledata/ directory to view the data that is loaded by this function.
|
|
; Input: de: function that is responsible for loading the chunk of VRAM data
|
|
; hl: pointer to data
|
|
; a: bank of data
|
|
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:
|
|
; $ff, >$7f, >$3f, else
|
|
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
|
|
|
|
INCLUDE "home/ir.asm"
|
|
|
|
Unused_Func_1ed9:
|
|
; unused
|
|
push bc
|
|
push de
|
|
push hl
|
|
ld e, a
|
|
ld d, $0
|
|
sla e
|
|
rl d
|
|
ld a, [hLoadedROMBank]
|
|
push af
|
|
ld a, $2
|
|
ld [hLoadedROMBank], a
|
|
ld [MBC5RomBank], a
|
|
ld hl, $4f06
|
|
jr asm_1f3b
|
|
|
|
Unused_Func_1ef2:
|
|
; unused
|
|
push bc
|
|
push de
|
|
push hl
|
|
ld e, a
|
|
ld d, $0
|
|
sla e
|
|
rl d
|
|
ld a, [hLoadedROMBank]
|
|
push af
|
|
ld a, $2
|
|
ld [hLoadedROMBank], a
|
|
ld [MBC5RomBank], a
|
|
ld hl, $4f06
|
|
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
|
|
|
|
Unused_Func_1f68:
|
|
; unused
|
|
push bc
|
|
push de
|
|
push hl
|
|
ld e, a
|
|
ld d, $0
|
|
sla e
|
|
rl d
|
|
ld a, [hLoadedROMBank]
|
|
push af
|
|
ld a, $2
|
|
ld [hLoadedROMBank], a
|
|
ld [MBC5RomBank], a
|
|
ld hl, $4f06
|
|
jr asm_1fca
|
|
|
|
Unused_Func_1f81:
|
|
; unused
|
|
push bc
|
|
push de
|
|
push hl
|
|
ld e, a
|
|
ld d, $0
|
|
sla e
|
|
rl d
|
|
ld a, [hLoadedROMBank]
|
|
push af
|
|
ld a, $2
|
|
ld [hLoadedROMBank], a
|
|
ld [MBC5RomBank], a
|
|
ld hl, $4f06
|
|
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
|
|
|
|
Main: ; 0x1ffc
|
|
; This is the main game loop.
|
|
ld a, $b
|
|
ld [wd806], a
|
|
ld a, $4
|
|
ld [wd807], a
|
|
callba Func_3c000
|
|
ld a, $1
|
|
ld [wAudioEngineEnabled], a
|
|
ld a, $37 ; space character for player high scores name
|
|
ld [wPlayerName], a
|
|
ld [wPlayerName + 1], a
|
|
ld [wPlayerName + 2], a
|
|
ld a, SCREEN_ERASE_ALL_DATA
|
|
ld [wCurrentScreen], a
|
|
.master_loop
|
|
call TickRumbleDuration
|
|
call DoScreenLogic
|
|
call CleanOAMBuffer
|
|
call ClearPersistentJoypadStates
|
|
rst AdvanceFrame
|
|
jr .master_loop
|
|
|
|
TickRumbleDuration: ; 0x2034
|
|
; Decrements the Gameboy rumble duration.
|
|
; Turns off rumble when it gets to 0.
|
|
ld a, [wRumbleDuration]
|
|
and a
|
|
jr z, .rumbleOff
|
|
dec a
|
|
ld [wRumbleDuration], a
|
|
ret
|
|
|
|
.rumbleOff
|
|
ld [wRumblePattern], a
|
|
ret
|
|
|
|
DoScreenLogic: ; 0x2043
|
|
ld a, [wCurrentScreen]
|
|
call CallInFollowingTable
|
|
CallTable_2049: ; 0x2049
|
|
padded_dab HandleSelectGameboyTargetMenu ; SCREEN_SELECT_GAMEBOY_TARGET
|
|
padded_dab HandleEraseAllDataMenu ; SCREEN_ERASE_ALL_DATA
|
|
padded_dab HandleCopyrightScreen ; SCREEN_COPYRIGHT
|
|
padded_dab HandleTitlescreen ; SCREEN_TITLESCREEN
|
|
padded_dab HandlePinballGame ; SCREEN_PINBALL_GAME
|
|
padded_dab HandlePokedexScreen ; SCREEN_POKEDEX
|
|
padded_dab HandleOptionsScreen ; SCREEN_OPTIONS
|
|
padded_dab HandleHighScoresScreen ; SCREEN_HIGH_SCORES
|
|
padded_dab HandleFieldSelectScreen ; SCREEN_FIELD_SELECT
|
|
|
|
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 MultiplyBbyCSigned.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
|
|
|
|
MultiplyVectorComponentByAngleFactor: ; 0x210b
|
|
; Input: bc = velocity
|
|
; e = multiplier
|
|
; d = $0 if multiplier is treated as positive, $ff if multiplier is treated as negative
|
|
; Output: bc = bc * e / 256
|
|
push af
|
|
push hl
|
|
ld a, b
|
|
xor d
|
|
ld [hSignedMathSignBuffer2], a
|
|
bit 7, b
|
|
jr z, .positive
|
|
; negate bc
|
|
ld a, c
|
|
cpl
|
|
add 1
|
|
ld c, a
|
|
ld a, b
|
|
cpl
|
|
adc 0
|
|
ld b, a
|
|
.positive
|
|
push bc
|
|
; first, multiply the lo byte of the vector
|
|
ld b, e
|
|
call MultiplyBbyCUnsigned
|
|
ld l, c
|
|
ld h, b
|
|
; round to nearest hi byte
|
|
ld bc, $0080
|
|
add hl, bc
|
|
ld l, h
|
|
ld h, $0
|
|
pop bc
|
|
; then, multiply the hi byte of the vector
|
|
ld c, e
|
|
call MultiplyBbyCUnsigned
|
|
add hl, bc
|
|
ld a, [hSignedMathSignBuffer2]
|
|
rlca
|
|
jr nc, .positive2
|
|
; negate hl
|
|
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
|
|
; Input: a = angle
|
|
; Output: e = cos(a)
|
|
; d = 0 if cos(a) is positive, $ff if cos(a) is negative
|
|
add $40
|
|
; fall through
|
|
Sine: ; 0x2149
|
|
; Input: a = angle
|
|
; Output: e = sin(a)
|
|
; d = 0 if sin(a) is positive, $ff if sin(a) is negative
|
|
push hl
|
|
ld [hSignedMathSignBuffer], a
|
|
and $7f ; ensure angle is between 0 and 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, [wEnableBallGravityAndTilt]
|
|
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 greater 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 -7
|
|
ret nc
|
|
ld a, -7 ; 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, .negativeVelocity
|
|
cp 5
|
|
jr c, .readLoByte
|
|
ld bc, $04ff
|
|
jr .updateBallPos
|
|
|
|
.negativeVelocity
|
|
cp -4
|
|
jr nc, .readLoByte
|
|
ld bc, -$04ff
|
|
jr .updateBallPos
|
|
|
|
.readLoByte
|
|
ld b, a
|
|
dec de
|
|
ld a, [de]
|
|
ld c, a
|
|
.updateBallPos
|
|
ld a, [hl]
|
|
add c
|
|
ld [hli], a
|
|
ld a, [hl]
|
|
adc b
|
|
ld [hl], a
|
|
ret
|
|
|
|
NegateAngleAndRotateVector: ; 0x21e5
|
|
cpl
|
|
inc a
|
|
; fall through
|
|
RotateVector: ; 0x21e7
|
|
; Rotates a vector by an angle using the standard rotation matrix calculation. Note, that
|
|
; the matrix is inverted vertically to account for negative y values mean "up" in this world.
|
|
; Input: bc = vector x component
|
|
; de = vector y component
|
|
; a = rotation angle
|
|
; Returns: bc = resulting x component = xComponent * cos(angle) + yComponent * sin(angle)
|
|
; de = resulting y component = yComponent * cos(angle) - xComponent * sin(angle)
|
|
push hl
|
|
push bc
|
|
push de
|
|
ld [hRotationAngleBuffer], a
|
|
call Cosine
|
|
ld a, e
|
|
ld [hCosineResultBuffer], a
|
|
ld a, d
|
|
ld [hCosineResultBuffer + 1], a
|
|
; xComponent * cos(angle)
|
|
call MultiplyVectorComponentByAngleFactor
|
|
ld l, c
|
|
ld h, b
|
|
pop bc
|
|
push bc
|
|
ld a, [hRotationAngleBuffer]
|
|
call Sine
|
|
ld a, e
|
|
ld [hSineResultBuffer], a
|
|
ld a, d
|
|
ld [hSineResultBuffer + 1], a
|
|
; yComponent * sin(angle)
|
|
call MultiplyVectorComponentByAngleFactor
|
|
add hl, bc ; hl = xComponent * cos(angle) + yComponent * sin(angle)
|
|
pop de
|
|
pop bc
|
|
push hl
|
|
push de
|
|
ld a, [hSineResultBuffer]
|
|
ld e, a
|
|
ld a, [hSineResultBuffer + 1]
|
|
cpl
|
|
ld d, a
|
|
; xComponent * -sin(angle)
|
|
call MultiplyVectorComponentByAngleFactor
|
|
ld l, c
|
|
ld h, b
|
|
pop bc
|
|
ld a, [hCosineResultBuffer]
|
|
ld e, a
|
|
ld a, [hCosineResultBuffer + 1]
|
|
ld d, a
|
|
; yComponent * cos(angle)
|
|
call MultiplyVectorComponentByAngleFactor
|
|
add hl, bc ; hl = yComponent * cos(angle) - xComponent * sin(angle)
|
|
ld d, h
|
|
ld e, l
|
|
pop bc
|
|
pop hl
|
|
ret
|
|
|
|
ApplyCollisionForces: ; 0x222b
|
|
; Applies the collision force to the ball's velocity and spin.
|
|
; When this function is called, the ball's velocity has already been rotated
|
|
; by the collision's normal angle, so that the velocity components are in a
|
|
; standardized coordinate system, where the normal is pointing directly upward
|
|
; at the colliding ball. If the ball is traveling away from the normal, then this
|
|
; function is a no-op.
|
|
; Input: bc = ball x velocity in rotated coordinate system
|
|
; de = ball y velocity in rotated coordinate system
|
|
; Output: bc = updated ball x velocity in rotated coordinate system
|
|
; de = updated ball y velocity in rotated coordinate system
|
|
push hl
|
|
ld hl, wNoCollisionApplied
|
|
ld [hl], $ff
|
|
; Early exit if the ball is traveling away from the collision normal.
|
|
bit 7, d
|
|
jr nz, .exit
|
|
ld [hl], $0
|
|
ld a, d
|
|
cp 3
|
|
jr c, .applyforces
|
|
; The ball collided hard because its y velocity is a
|
|
; large value. Shake the rumble pack, and play a little
|
|
; sound effect to enhance the collision.
|
|
ld a, $ff
|
|
ld [wRumblePattern], a
|
|
ld a, 1
|
|
ld [wRumbleDuration], a
|
|
ld a, [wFlipperCollision]
|
|
and a
|
|
jr nz, .applyforces
|
|
push de
|
|
ld de, $0008
|
|
call PlaySFXIfNoneActive
|
|
pop de
|
|
.applyforces
|
|
; First, apply some dampening of the vertical
|
|
; velocity component, so that walls absorb some
|
|
; of the ball's speed. Colliding with certain objects
|
|
; dampen the speed less that normal, like the flippers
|
|
; and Poliwag button.
|
|
; Divide y velocity by 4.
|
|
srl d
|
|
rr e
|
|
srl d
|
|
rr e
|
|
ld h, d
|
|
ld l, e ; hl = yVelocity / 4
|
|
srl d
|
|
rr e ; de = yVelocity / 8
|
|
ld a, [wCollisionForceAmplification]
|
|
and a
|
|
jr z, .updateYVelocity
|
|
.amplify
|
|
add hl, de
|
|
dec a
|
|
jr nz, .amplify
|
|
.updateYVelocity
|
|
; Negate the dampened dampened y velocity so that the ball
|
|
; bounces off.
|
|
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]
|
|
; Divide ball spin by 2, signed, and extend to 2 bytes (hl)
|
|
sra a
|
|
ld l, a
|
|
ld h, $0
|
|
bit 7, l
|
|
jr z, .updateXVelocity
|
|
ld h, $ff
|
|
.updateXVelocity
|
|
; hl = ballSpin / 2
|
|
; bc = x velocity component in rotated coordinate system
|
|
; Add the spin to the x velocity component.
|
|
add hl, bc
|
|
ld b, h
|
|
ld c, l
|
|
push bc
|
|
; Recalculate ball spin.
|
|
; new ball spin = (xVelocity * 4) >> 8
|
|
sla c
|
|
rl b
|
|
sla c
|
|
rl b
|
|
ld a, b
|
|
ld [wBallSpin], a
|
|
pop bc
|
|
.exit
|
|
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
|
|
|
|
CheckStageCollision: ; 0x22b5
|
|
ld a, [wBallXPos + 1]
|
|
sub 4
|
|
push af
|
|
and $7
|
|
ld [wSubTileBallXPos], a ; sub-tile position
|
|
pop af
|
|
and $f8
|
|
ld c, a ; c = tile x pos
|
|
ld a, [wBallYPos + 1]
|
|
sub 4
|
|
push af
|
|
and $7
|
|
ld [wSubTileBallYPos], a
|
|
pop af
|
|
and $f8
|
|
ld b, a ; b = tile y pos
|
|
ld l, b ; bc contains tile coords of ball position
|
|
; Calculate the tile offset for the ball's position, as if the
|
|
; board was composed of a 1D array starting from the top-left
|
|
; going left-to-right.
|
|
ld h, $0
|
|
sla l
|
|
rl h
|
|
sla l
|
|
rl h ; b was multiplied by 4 ((y tile) * 32)
|
|
srl c
|
|
srl c
|
|
srl c ; c was divided by 8 (x tile)
|
|
ld b, $0
|
|
add hl, bc
|
|
ld a, l
|
|
ld [wBallPositionTileOffset], a
|
|
ld a, h
|
|
ld [wBallPositionTileOffset + 1], a
|
|
ld a, [wStageCollisionMapPointer]
|
|
ld c, a
|
|
ld a, [wStageCollisionMapPointer + 1]
|
|
ld b, a
|
|
add hl, bc ; hl = address of ball tile's collision attribute
|
|
ld a, [hLoadedROMBank]
|
|
push af
|
|
ld a, [wStageCollisionMapBank]
|
|
ld [hLoadedROMBank], a
|
|
ld [MBC5RomBank], a
|
|
ld bc, 32 - 1 ; stage's 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, CollisionTests
|
|
add hl, bc
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
ld a, [wSubTileBallYPos]
|
|
ld c, a
|
|
ld b, 16 ; length of wCollisionPointTests
|
|
.testCollisionPointLoop
|
|
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 TryLoadSpecialCollisionMask
|
|
jr nc, .staticMask
|
|
; Load the special mask pointer.
|
|
; hl = pointer to array of collision masks.
|
|
pop af
|
|
and $7
|
|
ld c, a
|
|
ld b, $0
|
|
add hl, bc
|
|
jr .testCollisionPoint
|
|
|
|
.staticMask
|
|
ld c, a
|
|
ld b, $0 ; bc = static collision mask id
|
|
; Multiply bc by 8. Each collision mask is an
|
|
; 8x8-tile of 1-bit-per-pixel data. Therefore,
|
|
; each collision mask tile is 8 bytes.
|
|
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 ; hl = pointer to collision mask tile
|
|
pop af
|
|
and $7 ; a = y subtile offset
|
|
ld c, a
|
|
ld b, $0
|
|
add hl, bc
|
|
.testCollisionPoint
|
|
; hl = pointer to the collision mask row for the y position
|
|
ld a, [de]
|
|
inc de
|
|
and [hl]
|
|
push af
|
|
ld a, [de]
|
|
inc de
|
|
ld c, a
|
|
ld hl, wCollisionPointTests
|
|
add hl, bc
|
|
pop af
|
|
ld [hl], a
|
|
pop bc
|
|
dec b
|
|
jr nz, .testCollisionPointLoop
|
|
pop af
|
|
ld [hLoadedROMBank], a
|
|
ld [MBC5RomBank], a
|
|
ld hl, wCollisionPointTests
|
|
ld de, wd7d9
|
|
ld b, 4
|
|
.copyLoop
|
|
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, .copyLoop
|
|
ld hl, wCollisionPointTests
|
|
ld de, $0000
|
|
ld b, 0
|
|
ld a, [hl]
|
|
and a
|
|
jr z, .findNextCollisionPoint
|
|
.findNextCollisionPoint2
|
|
; This loop is nearly identical to .findNextCollisionPoint
|
|
; It exists to handle the improbable (impossible?) event that
|
|
; the ball could be completely inside a collision wall.
|
|
ld a, [hli]
|
|
inc b
|
|
and a
|
|
jr z, .findNextCollisionPoint
|
|
ld a, b
|
|
cp 16 + 1
|
|
jr nc, .determinedCollisionStatus
|
|
jr .findNextCollisionPoint2
|
|
|
|
.findNextCollisionPoint
|
|
ld a, [hli]
|
|
inc b
|
|
and a
|
|
jr nz, .handleCollisionPoint
|
|
ld a, b
|
|
cp 16 + 1
|
|
jr nc, .determinedCollisionStatus
|
|
jr .findNextCollisionPoint
|
|
|
|
.handleCollisionPoint
|
|
push de
|
|
ld d, $1
|
|
ld c, b
|
|
dec c
|
|
.findNextFailedCollisionPoint
|
|
ld a, [hli]
|
|
inc b
|
|
inc d
|
|
and a
|
|
jr nz, .findNextFailedCollisionPoint
|
|
dec d
|
|
ld a, b
|
|
dec a
|
|
dec a
|
|
and $f
|
|
swap c
|
|
or c
|
|
ld c, a ; c = (index of first collision point << 8) | (index of last consecutive collision point)
|
|
ld a, d ; d = number of consecutive successful collision points
|
|
cp e
|
|
pop de
|
|
jr c, .updatedMaxConsecutivePoints
|
|
ld e, a ; e = max number of consecutive successful collision points
|
|
ld d, c ; d = (index of first collision point << 8) | (index of last consecutive collision point)
|
|
.updatedMaxConsecutivePoints
|
|
ld a, b
|
|
cp 16
|
|
jr c, .findNextCollisionPoint
|
|
.determinedCollisionStatus
|
|
; e = maximum number of consecutive successful collision points
|
|
; d = the start and last index of that consecutive string of collision points (wCollisionPointTests)
|
|
; the hi nybble is the start index, lo nybble is the end index
|
|
ld a, e
|
|
ld [wIsBallColliding], a
|
|
and a
|
|
ret z
|
|
ld a, [hLoadedROMBank]
|
|
push af
|
|
ld a, Bank(CollisionForceAngles)
|
|
ld [hLoadedROMBank], a
|
|
ld [MBC5RomBank], a
|
|
push de
|
|
; Based on the start and end collision point indices, look
|
|
; up the corresponding normal angle for them.
|
|
ld e, d
|
|
ld d, 0
|
|
ld hl, CollisionForceAngles
|
|
add hl, de
|
|
ld a, [hl]
|
|
ld [wCollisionNormalAngle], a
|
|
; Again, based on the start and end collision point indices, apply
|
|
; position offsets to position the ball safely outside of the wall
|
|
; it collided with.
|
|
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, .loadTestPointOffsets
|
|
add 16
|
|
.loadTestPointOffsets
|
|
; e = start index of consecutive collision points
|
|
; a = length of consecutive collision points
|
|
; The rest of the code here determines which of
|
|
; the collision mask tiles was the one that triggered
|
|
; the collision. It can be multiple tiles, so it uses
|
|
; first collision test point that was colliding. Then,
|
|
; that tile's collision attribute is saved in wCurCollisionAttribute.
|
|
add e
|
|
add e
|
|
inc a
|
|
and $1e
|
|
ld c, a
|
|
ld b, 0
|
|
ld hl, BallCollisionTestPointOffsets
|
|
add hl, bc
|
|
ld a, [wSubTileBallXPos]
|
|
add 4
|
|
add [hl]
|
|
bit 3, a
|
|
ld c, b
|
|
jr z, .checkY
|
|
ld c, 2
|
|
.checkY
|
|
ld a, [wSubTileBallYPos]
|
|
add 4
|
|
inc hl
|
|
add [hl]
|
|
bit 3, a
|
|
jr z, .saveCollisionAttribute
|
|
inc c
|
|
.saveCollisionAttribute
|
|
ld hl, wUpperLeftCollisionAttribute
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld [wCurCollisionAttribute], a
|
|
ld hl, BallPositionPointerOffsetDeltas
|
|
add hl, bc
|
|
ld a, [wBallPositionTileOffset]
|
|
add [hl]
|
|
ld [wCurCollisionTileOffset], a
|
|
ld a, [wBallPositionTileOffset + 1]
|
|
adc 0
|
|
ld [wCurCollisionTileOffset + 1], a
|
|
ret
|
|
|
|
TryLoadSpecialCollisionMask: ; 0x248a
|
|
; If it's a special collision mask attribute, load the
|
|
; pointer to its mask and set the carry flag.
|
|
; If it's a regular static collision mask attribute, simply
|
|
; reset the carry flag and don't return anything.
|
|
push af
|
|
ld a, [wCurrentStage]
|
|
bit 0, a
|
|
jr nz, .bottomStage
|
|
pop af
|
|
and a
|
|
ret
|
|
|
|
.bottomStage
|
|
pop af
|
|
cp $d0
|
|
ccf
|
|
ret nc
|
|
cp $e0
|
|
jr nc, .notAnimatedMonCollision
|
|
sub $d0
|
|
sla a
|
|
sla a
|
|
sla a
|
|
ld l, a
|
|
ld h, (wMonAnimatedCollisionMask >> 8)
|
|
scf
|
|
ret
|
|
|
|
.notAnimatedMonCollision
|
|
push de
|
|
sub $e0
|
|
ld b, a
|
|
ld a, [wCurrentStage]
|
|
cp FIRST_BONUS_STAGE
|
|
jr nc, .bonusStage
|
|
bit 4, b
|
|
ld hl, BottomLeftCollisionMasks
|
|
ld a, [wLeftFlipperState + 1]
|
|
jr z, .checkFlipperPosition
|
|
res 4, b
|
|
ld hl, BottomRightCollisionMasks
|
|
ld a, [wRightFlipperState + 1]
|
|
.checkFlipperPosition
|
|
ld de, $0080
|
|
cp 7
|
|
jr c, .loadMaskPointer
|
|
add hl, de
|
|
cp 14
|
|
jr c, .loadMaskPointer
|
|
add hl, de
|
|
.loadMaskPointer
|
|
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, [wLeftFlipperState + 1]
|
|
jr z, .checkFlipperPosition2
|
|
res 4, b
|
|
ld hl, BottomRightBonusStageCollisionMasks
|
|
ld a, [wRightFlipperState + 1]
|
|
.checkFlipperPosition2
|
|
ld de, $0080
|
|
cp 7
|
|
jr c, .loadMaskPointer2
|
|
add hl, de
|
|
cp 14
|
|
jr c, .loadMaskPointer2
|
|
add hl, de
|
|
.loadMaskPointer2
|
|
ld e, b
|
|
sla e
|
|
sla e
|
|
sla e
|
|
add hl, de
|
|
pop de
|
|
scf
|
|
ret
|
|
|
|
BallPositionPointerOffsetDeltas:
|
|
db $00, $20
|
|
db $01, $21
|
|
|
|
BallCollisionTestPointOffsets:
|
|
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
|
|
|
|
; These tables facilitate testing the 16 collision points around the ball's origin.
|
|
; Each table corresponds to an x sub-tile offset for a base point 4 pixels up and left of
|
|
; the ball's origin.
|
|
;
|
|
; First byte: y sub-tile offset, if its greater than 8, it bleeds over to the next tile in the 2x2 tile region
|
|
; Second byte: bitmask to test against the 1bpp collision mask's row
|
|
; Third byte: index of wCollisionPointTests to save the result in
|
|
CollisionTests: ; 0x252e
|
|
dw CollisionTest_X0
|
|
dw CollisionTest_X1
|
|
dw CollisionTest_X2
|
|
dw CollisionTest_X3
|
|
dw CollisionTest_X4
|
|
dw CollisionTest_X5
|
|
dw CollisionTest_X6
|
|
dw CollisionTest_X7
|
|
|
|
CollisionTest_X0: ; 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
|
|
|
|
CollisionTest_X1: ; 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
|
|
|
|
CollisionTest_X2: ; 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
|
|
|
|
CollisionTest_X3: ; 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
|
|
|
|
CollisionTest_X4: ; 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
|
|
|
|
CollisionTest_X5: ; 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
|
|
|
|
CollisionTest_X6: ; 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
|
|
|
|
CollisionTest_X7: ; 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"
|
|
INCLUDE "engine/pinball_game/object_collision/object_collision.asm"
|
|
|
|
LoadFlippersPalette: ; 0x2862
|
|
; Loads the flippers' color palette.
|
|
; When the flippers are active, they are white/blue. When disabled at the end of a Bonus Stage, they turn Red.
|
|
ld a, [wFlippersDisabled]
|
|
and a
|
|
jr nz, .flippersDisabled
|
|
ld a, [hGameBoyColorFlag]
|
|
and a
|
|
jr z, .done
|
|
ld a, Bank(ActiveFlippersPalette)
|
|
ld hl, ActiveFlippersPalette
|
|
ld de, $0052
|
|
ld bc, $0004
|
|
call FarCopyPalettes
|
|
.done
|
|
ret
|
|
|
|
.flippersDisabled
|
|
ld a, [hGameBoyColorFlag]
|
|
and a
|
|
jr z, .done2
|
|
ld a, Bank(DisabledFlippersPalette)
|
|
ld hl, DisabledFlippersPalette
|
|
ld de, $0052
|
|
ld bc, $0004
|
|
call FarCopyPalettes
|
|
.done2
|
|
ret
|
|
|
|
ActiveFlippersPalette:
|
|
; The white/blue color when the flippers are active.
|
|
RGB 31, 31, 31
|
|
RGB 21, 21, 27
|
|
|
|
DisabledFlippersPalette:
|
|
; The reddish colors when the flippers are disabled at the end of a Bonus Stage.
|
|
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:
|
|
|
|
INCLUDE "home/animation.asm"
|
|
INCLUDE "home/text.asm"
|
|
INCLUDE "home/bcd.asm"
|
|
INCLUDE "home/tilt.asm"
|
|
|
|
SECTION "bank0.2", ROM0
|
|
|
|
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"
|
|
|
|
; These two squares data arrays must be aligned to $100 bytes and appear contiguously.
|
|
SquaresLow:
|
|
FOR X, 256
|
|
db (X * X) % $100
|
|
ENDR
|
|
|
|
SquaresHigh:
|
|
FOR X, 256
|
|
db (X * X) / $100
|
|
ENDR
|
|
|