Add files
This commit is contained in:
307
src/home/vectors.asm
Normal file
307
src/home/vectors.asm
Normal file
@@ -0,0 +1,307 @@
|
||||
|
||||
SECTION "rst00", ROM0[$0000]
|
||||
; Please do not call
|
||||
; Traps execution errors (mostly to $FFFF / $0000)
|
||||
rst00:
|
||||
; Pad, in case we come from FFFF and read a 2-byte operand
|
||||
nop
|
||||
nop
|
||||
jp NullExecError
|
||||
|
||||
SECTION "rst08", ROM0[$0008]
|
||||
; Please call using `rst memcpy_small`
|
||||
; Copies c bytes of data from de to hl
|
||||
MemcpySmall:
|
||||
ld a, [de]
|
||||
ld [hli], a
|
||||
inc de
|
||||
dec c
|
||||
jr nz, MemcpySmall
|
||||
EmptyFunc::
|
||||
ret
|
||||
|
||||
SECTION "rst10", ROM0[$0010]
|
||||
; Please call using `rst memset_small`
|
||||
; Sets c bytes at hl with the value in a
|
||||
MemsetSmall:
|
||||
ld [hli], a
|
||||
dec c
|
||||
jr nz, MemsetSmall
|
||||
ret
|
||||
|
||||
SECTION "rst18", ROM0[$0017]
|
||||
; Please do not call. Use `rst memset`, or, if absolutely needed, `call rst18`.
|
||||
; Sets bc bytes at hl with the value in d
|
||||
Memset:
|
||||
ld a, d
|
||||
; Please call using `rst memset`
|
||||
; Sets bc bytes at hl with the value in a
|
||||
rst18:
|
||||
ld d, a
|
||||
ld [hli], a
|
||||
dec bc
|
||||
ld a, b
|
||||
or c
|
||||
jr nz, Memset
|
||||
ret
|
||||
|
||||
SECTION "rst20", ROM0[$0020]
|
||||
; Please call using `rst bankswitch`
|
||||
; Properly switches to a ROM bank
|
||||
; @param a The ROM bank to switch to
|
||||
; NOTE: only switches the lower 8 bytes, the upper bit (for 512 banks) is not considered
|
||||
ROMbankswitch:
|
||||
ldh [hCurROMBank], a
|
||||
ld [rROMB0], a
|
||||
ret
|
||||
|
||||
SECTION "rst28", ROM0[$0028]
|
||||
; Please call using `rst call_hl`
|
||||
; Jumps to hl. Use as a placeholder for `call hl`!
|
||||
; Will error out if the target is in RAM
|
||||
CallHL:
|
||||
bit 7, h ; Prevent jumping into RAM (doesn't protec against returning to it, but hey :D)
|
||||
jr nz, .err
|
||||
jp hl
|
||||
.err
|
||||
jp HLJumpingError
|
||||
|
||||
SECTION "rst30", ROM0[$0030]
|
||||
; Please call using `rst wait_vblank`
|
||||
; Waits for the VBlank interrupt
|
||||
; Note: if the interrupt occurs without being waited for, it will skip performing some actions
|
||||
WaitVBlank:
|
||||
xor a
|
||||
ldh [hVBlankFlag], a
|
||||
.waitVBlank
|
||||
halt
|
||||
jr z, .waitVBlank
|
||||
ret
|
||||
|
||||
SECTION "rst38", ROM0[$0038]
|
||||
; Please do not call
|
||||
; Traps execution of the $FF byte (which serves as padding of the ROM)
|
||||
rst38:
|
||||
jp Rst38Error
|
||||
|
||||
|
||||
SECTION "Interrupt vectors", ROM0[$0040]
|
||||
|
||||
transfer_reg: MACRO
|
||||
ldh a, [h\1]
|
||||
ldh [r\1], a
|
||||
ENDM
|
||||
|
||||
; VBlank
|
||||
push af
|
||||
transfer_reg LCDC
|
||||
jp VBlankHandler
|
||||
|
||||
; LCD
|
||||
push af
|
||||
push bc
|
||||
ldh a, [hScanlineFXIndex]
|
||||
ld c, a
|
||||
ld a, [c] ; Get port ID
|
||||
jr LCDHandler
|
||||
|
||||
; Timer
|
||||
reti
|
||||
ds 7
|
||||
|
||||
; Serial
|
||||
reti
|
||||
|
||||
; Fit in a 7-byte function, too!
|
||||
|
||||
; Jumps immediately to de, no questions asked (except RAM targets?).
|
||||
CallDE::
|
||||
push de
|
||||
bit 7, d
|
||||
ret z
|
||||
jp DEJumpingError
|
||||
|
||||
; Joypad
|
||||
reti
|
||||
|
||||
|
||||
LCDHandler:
|
||||
ld b, a ; Save port ID for later
|
||||
inc c
|
||||
inc c
|
||||
ld a, [c] ; Get next effect's scanline
|
||||
dec a ; Compensate for processing time
|
||||
ldh [rLYC], a ; Get set up (hopefully this should reset the interrupt trigger line)
|
||||
ld a, c ; Point to next effect's port ID
|
||||
inc a
|
||||
ldh [hScanlineFXIndex], a
|
||||
dec c
|
||||
; Wait a bit to write during HBlank, to avoid gfx artifacts
|
||||
ld a, 4
|
||||
.waitMode0
|
||||
dec a
|
||||
jr nz, .waitMode0
|
||||
|
||||
; Check if we're trying to write to P1 ($FF*00*)
|
||||
ld a, b
|
||||
and a ; Note: `and $7F` can be used instead to have control on bit 7 (if ever needed)
|
||||
; Perform common ops
|
||||
ld a, [c] ; Get value
|
||||
; rP1 is hardwired to instead perform textbox ops
|
||||
jr nz, .notTextbox
|
||||
|
||||
ldh [rSCY], a ; Store value, which is actually for SCY (dat plot twist, eh?)
|
||||
xor a
|
||||
ldh [rSCX], a
|
||||
ld c, LOW(rLCDC)
|
||||
ldh a, [hLCDC] ; Retrieve LCDC value
|
||||
and ~(LCDCF_WINON | LCDCF_BG8000 | LCDCF_OBJON)
|
||||
or LCDCF_BG9C00
|
||||
; Note: this is scrapped support for sprites on the textbox
|
||||
; It was initially planned for JP diacritics.
|
||||
; If for whatever reason, you need to re-activate this feature...
|
||||
; ...uncomment this, and remove "LCDCF_OBJON" from above.
|
||||
;
|
||||
; ld [c], a ; Apply LCDC modification
|
||||
; ; Perform OAM DMA to get textbox's sprites
|
||||
; ; Luckily, sprites are hidden during DMA
|
||||
; ; Also no sprites should be present on the textbox 1st row, hiding our trickery >:P
|
||||
; ld a, HIGH(wTextboxOAM)
|
||||
; call hOAMDMA
|
||||
; ; Reload OAM on next frame
|
||||
; ldh a, [hCurrentOAMBuffer]
|
||||
; ldh [hOAMBuffer], a
|
||||
; jr .onlyOneEffect
|
||||
|
||||
.notTextbox
|
||||
ld c, b ; Retrieve port
|
||||
res 7, c
|
||||
ld [c], a ; Apply FX
|
||||
bit 7, b
|
||||
jr z, .onlyOneEffect
|
||||
ldh a, [hSecondFXAddr]
|
||||
ld c, a
|
||||
ldh a, [hSecondFXValue]
|
||||
ld [$ff00+c], a
|
||||
.onlyOneEffect
|
||||
pop bc
|
||||
pop af
|
||||
reti
|
||||
|
||||
|
||||
SECTION "VBlank handler", ROM0
|
||||
|
||||
VBlankHandler:
|
||||
push bc
|
||||
|
||||
; ============= Here are things that need to be updated, even on lag frames ==============
|
||||
|
||||
; Update IO from HRAM shadow
|
||||
transfer_reg SCY
|
||||
transfer_reg SCX
|
||||
transfer_reg WY
|
||||
transfer_reg WX
|
||||
|
||||
|
||||
ldh a, [hWhichScanlineBuffer]
|
||||
ld c, a
|
||||
; Get first effect's scanline
|
||||
ld a, [$ff00+c]
|
||||
dec a ; Compensate for the processing time
|
||||
; NOTE: this assumes no effect is scheduled on line 0
|
||||
; This should never happen; instead, use the HRAM shadow regs (hSCY, etc.)
|
||||
ldh [rLYC], a
|
||||
inc c
|
||||
ld a, c
|
||||
ldh [hScanlineFXIndex], a
|
||||
|
||||
|
||||
; Update OAM if needed
|
||||
; Do this last so it will go through even without time
|
||||
; This will simply cause sprites to not be displayed on the top few scanlines, but that's not as bad as palettes not loading at all, huh?
|
||||
ldh a, [hOAMBufferHigh]
|
||||
and a
|
||||
jr z, .dontUpdateOAM
|
||||
ld b, a
|
||||
; Reset OAM buffer high vect
|
||||
xor a
|
||||
ldh [hOAMBufferHigh], a
|
||||
; Perform DMA as specified
|
||||
ld a, b
|
||||
call hOAMDMA
|
||||
.dontUpdateOAM
|
||||
|
||||
|
||||
; ============== In case of lag, don't update further, to avoid breaking stuff ===============
|
||||
|
||||
ldh a, [hVBlankFlag]
|
||||
and a
|
||||
jr nz, .lagFrame
|
||||
|
||||
|
||||
; Poll joypad and update regs
|
||||
|
||||
ld c, LOW(rP1)
|
||||
ld a, $20 ; Select D-pad
|
||||
ld [$ff00+c], a
|
||||
REPT 6
|
||||
ld a, [$ff00+c]
|
||||
ENDR
|
||||
or $F0 ; Set 4 upper bits (give them consistency)
|
||||
ld b, a
|
||||
|
||||
; Filter impossible D-pad combinations
|
||||
and $0C ; Filter only Down and Up
|
||||
ld a, b
|
||||
jr nz, .notUpAndDown
|
||||
or $0C ; If both are pressed, "unpress" them
|
||||
ld b, a
|
||||
.notUpAndDown
|
||||
and $03 ; Filter only Left and Right
|
||||
jr nz, .notLeftAndRight
|
||||
ld a, b
|
||||
or $03 ; If both are pressed, "unpress" them
|
||||
ld b, a
|
||||
.notLeftAndRight
|
||||
swap b ; Put D-pad buttons in upper nibble
|
||||
|
||||
ld a, $10 ; Select buttons
|
||||
ld [$ff00+c], a
|
||||
REPT 6
|
||||
ld a, [$ff00+c]
|
||||
ENDR
|
||||
; On SsAB held, soft-reset
|
||||
and $0F
|
||||
jp z, Reset
|
||||
|
||||
or $F0 ; Set 4 upper bits
|
||||
xor b ; Mix with D-pad bits, and invert all bits (such that pressed=1) thanks to "or $F0"
|
||||
ld b, a
|
||||
|
||||
ldh a, [hHeldButtons]
|
||||
cpl
|
||||
and b
|
||||
ldh [hPressedButtons], a
|
||||
|
||||
ld a, b
|
||||
ldh [hHeldButtons], a
|
||||
|
||||
; Release joypad
|
||||
ld a, $30
|
||||
ld [$ff00+c], a
|
||||
|
||||
pop bc
|
||||
pop af
|
||||
|
||||
|
||||
; The main code was waiting for VBlank, so tell it it's OK by resetting Z
|
||||
xor a
|
||||
inc a ; Clear Z
|
||||
ldh [hVBlankFlag], a ; Mark VBlank as ACK'd
|
||||
reti
|
||||
|
||||
|
||||
.lagFrame
|
||||
pop bc
|
||||
pop af
|
||||
reti
|
||||
Reference in New Issue
Block a user