gb3dplatformer/main.asm

474 lines
7.5 KiB
NASM
Raw Normal View History

INCLUDE "hardware.inc"
INCLUDE "sprobjs_lib.asm"
SECTION "Header", ROM0[$100]
jp Init
ds $150 - @, 0 ; Make room for the header
SECTION "Main", ROM0
Init:
; Shut down audio circuitry
ld a, 0
ld [rNR52], a
; Do not turn the LCD off outside of VBlank
WaitVBlank:
ld a, [rLY]
cp 144
jp c, WaitVBlank
; Turn the LCD off
ld a, 0
ld [rLCDC], a
; Initialize Sprite Object Library
call InitSprObjLib
; Reset hardware OAM
xor a, a
ld b, 160
ld hl, _OAMRAM
.resetOAM
ld [hli], a
dec b
jr nz, .resetOAM
; Copy cat sprite
ld de, GfxCat
ld hl, $8000
ld bc, GfxCat.end - GfxCat
call Memcopy
; Reset positions
ld hl, wMetaspritePosition.x
2024-04-19 14:03:13 -06:00
ld a, $10
ld [wMetaspritePosition.x], a
2024-04-19 14:03:13 -06:00
ld a, $0
ld [wMetaspritePosition.x + 1], a
ld hl, wMetaspritePosition.y
2024-04-19 14:03:13 -06:00
ld a, $10
ld [wMetaspritePosition.y], a
2024-04-19 14:03:13 -06:00
ld a, $01
ld [wMetaspritePosition.y + 1], a
ld hl, wMetaspritePosition.z
2024-04-19 14:03:13 -06:00
ld a, $00
ld [wMetaspritePosition.z], a
2024-04-19 14:03:13 -06:00
ld a, $0
ld [wMetaspritePosition.z + 1], a
2024-04-19 14:03:13 -06:00
; Reset velocity
ld hl, wMetaspriteVelocity.x
ld a, $0
ld [wMetaspriteVelocity.x], a
ld a, $0
ld [wMetaspriteVelocity.x + 1], a
ld hl, wMetaspriteVelocity.y
ld a, $0
ld [wMetaspriteVelocity.y], a
ld a, $0
ld [wMetaspriteVelocity.y + 1], a
ld hl, wMetaspriteVelocity.z
ld a, $0
ld [wMetaspriteVelocity.z], a
ld a, $0
ld [wMetaspriteVelocity.z + 1], a
ld hl, wMetaspriteVelocity.boost
ld a, $0
ld [wMetaspriteVelocity.boost], a
ld [wMetaspriteVelocity.boosting], a
; Copy the tile data
ld de, Tiles
ld hl, $9000
ld bc, TilesEnd - Tiles
call Memcopy
; Copy the tilemap
ld de, Tilemap
ld hl, $9800
ld bc, TilemapEnd - Tilemap
call Memcopy
; Turn the LCD on
ld a, LCDCF_ON | LCDCF_BGON | LCDCF_OBJON | LCDCF_OBJ8
ld [rLCDC], a
; During the first (blank) frame, initialize display registers
ld a, %11100100
ld [rBGP], a
ld [rOBP0], a
ld [rOBP1], a
; Enable vblank interrupt
ld a, IEF_VBLANK
ldh [rIE], a
; Clear interrupt register to 0
xor a, a
ldh [rIF], a
; Enable interrupts
ei
2024-04-19 14:03:13 -06:00
Main::
call ResetShadowOAM
call UpdateJoypadState
2024-04-19 14:03:13 -06:00
call HandleInput
call HandlePhysics
call HandleRender
2024-04-19 14:03:13 -06:00
halt
nop
jp Main
HandleInput::
ld a, [wJoypadState]
bit PADB_LEFT, a
jr nz, .leftend
ld a, [wMetaspritePosition.x]
add a, 16
ld b, a
ld [wMetaspritePosition.x], a
ld a, [wMetaspritePosition.x+1]
adc 0
ld c, a
ld [wMetaspritePosition.x+1], a
.leftend:
ld a, [wJoypadState]
bit PADB_RIGHT, a
jr nz, .rightend
ld a, [wMetaspritePosition.x]
sub a, 16
ld b, a
ld [wMetaspritePosition.x], a
ld a, [wMetaspritePosition.x+1]
sbc 0
ld c, a
ld [wMetaspritePosition.x+1], a
.rightend:
ld a, [wJoypadState]
bit PADB_UP, a
jr nz, .upend
ld a, [wMetaspritePosition.y]
add a, 16
ld b, a
ld [wMetaspritePosition.y], a
ld a, [wMetaspritePosition.y+1]
adc 0
ld c, a
ld [wMetaspritePosition.y+1], a
.upend:
ld a, [wJoypadState]
bit PADB_DOWN, a
jr nz, .downend
ld a, [wMetaspritePosition.y]
sub a, 16
ld b, a
ld [wMetaspritePosition.y], a
ld a, [wMetaspritePosition.y+1]
sbc 0
ld c, a
ld [wMetaspritePosition.y+1], a
.downend:
; Skip jump code if not on ground
ld a, [wMetaspritePosition.z]
ld b, a
ld a, [wMetaspritePosition.z + 1]
or a, b
jr nz, .jumpend
; While on ground, set boost
ld a, $8
ld [wMetaspriteVelocity.boost], a
2024-04-19 14:03:13 -06:00
ld a, [wJoypadPressed]
bit PADB_A, a
jr z, .boostclear
2024-04-19 14:03:13 -06:00
ld a, [wMetaspriteVelocity.z]
sub a, $20
ld b, a
2024-04-19 14:03:13 -06:00
ld [wMetaspriteVelocity.z], a
ld a, [wMetaspriteVelocity.z+1]
sbc a, $00
ld c, a
2024-04-19 14:03:13 -06:00
ld [wMetaspriteVelocity.z+1], a
jr .boostend
2024-04-19 09:07:20 -06:00
.jumpend:
ld a, [wJoypadState]
bit PADB_A, a
jr z, .boostclear
ld a, $FF
ld [wMetaspriteVelocity.boosting], a
jr .boostend
.boostclear:
ld a, $00
ld [wMetaspriteVelocity.boosting], a
.boostend:
2024-04-19 14:03:13 -06:00
ret
2024-04-19 14:03:13 -06:00
HandleRender::
2024-04-19 09:07:20 -06:00
; Render the player
; load de
ld a, [wMetaspritePosition.x]
ld e, a
ld a, [wMetaspritePosition.x + 1]
ld d, a
; load bc
ld a, [wMetaspritePosition.z]
ld c, a
ld a, [wMetaspritePosition.y]
2024-04-19 14:03:13 -06:00
add a, c
ld c, a
ld a, [wMetaspritePosition.z + 1]
ld b, a
ld a, [wMetaspritePosition.y + 1]
2024-04-19 14:03:13 -06:00
adc a, b
ld b, a
ld hl, CatMetasprite
call RenderMetasprite
2024-04-19 09:07:20 -06:00
; Render the shadow
; load de
ld a, [wMetaspritePosition.x]
ld e, a
ld a, [wMetaspritePosition.x + 1]
ld d, a
; load bc
ld a, [wMetaspritePosition.y]
ld c, a
ld a, [wMetaspritePosition.y + 1]
ld b, a
ld hl, ShadowMetasprite
call RenderMetasprite
2024-04-19 14:03:13 -06:00
ret
2024-04-19 09:07:20 -06:00
2024-04-19 14:03:13 -06:00
HandlePhysics::
2024-04-19 09:07:20 -06:00
2024-04-19 14:03:13 -06:00
; Skip gravity if on ground
ld a, [wMetaspritePosition.z]
ld b, a
ld a, [wMetaspritePosition.z + 1]
or a, b
jr z, .endGravity
; Skip gravity if boosting
ld a, [wMetaspriteVelocity.boosting]
ld b, a
ld a, [wMetaspriteVelocity.boost]
and a, b
cp 0
jr z, .startGravity
ld a, [wMetaspriteVelocity.boost]
dec a
ld [wMetaspriteVelocity.boost], a
jr .endGravity
.startGravity
2024-04-19 14:03:13 -06:00
; Apply gravity
ld a, [wMetaspriteVelocity.z]
add a, $04
2024-04-19 14:03:13 -06:00
ld [wMetaspriteVelocity.z], a
ld a, [wMetaspriteVelocity.z+1]
adc a, $00
ld [wMetaspriteVelocity.z+1], a
.endGravity:
2024-04-19 14:03:13 -06:00
; Calculate new z, place in bc
ld a, [wMetaspriteVelocity.z]
ld c, a
ld a, [wMetaspritePosition.z]
add c
ld c, a
2024-04-19 14:03:13 -06:00
ld a, [wMetaspriteVelocity.z + 1]
ld b, a
ld a, [wMetaspritePosition.z + 1]
adc b
ld b, a
2024-04-19 14:03:13 -06:00
; If z is greater than or equal to 0, pos/vel to 0
jr nz, .endLanding
jr nc, .endLanding
2024-04-19 14:03:13 -06:00
.startLanding
ld a, 0
ld [wMetaspritePosition.z], a
ld [wMetaspritePosition.z+1], a
2024-04-19 14:03:13 -06:00
ld [wMetaspriteVelocity.z], a
ld [wMetaspriteVelocity.z+1], a
ld b, a
ld c, a
2024-04-19 14:03:13 -06:00
.endLanding
2024-04-19 14:03:13 -06:00
; Update z position
ld a, c
ld [wMetaspritePosition.z], a
ld a, b
ld [wMetaspritePosition.z+1], a
ret
2024-04-19 14:03:13 -06:00
SECTION "Joypad Routine", ROM0
UpdateJoypadState::
ld hl, rP1
ld [hl], P1F_GET_BTN
; Read button state twice to ensure we get the proper state
ld a, [hl]
ld a, [hl]
ld [hl], P1F_GET_DPAD
cpl ; Inputs are active low - invert so it makes more sense
and PADF_A | PADF_B | PADF_SELECT | PADF_START
ld c, a ; Store lower 4 button bits in c
; On real hardware, rP1 needs to be read 8 times to ensure proper state is read
ld b, 8
.dpadDebounceLoop:
ld a, [hl]
dec b
jr nz, .dpadDebounceLoop
ld [hl], P1F_GET_NONE ; Disable joypad inputs
swap a ; Swap the nibbles to store dpad in upper 4 bits
cpl ; invert the bits
and PADF_RIGHT | PADF_LEFT | PADF_UP | PADF_DOWN
or c
ld c, a
; Compare with previously stored state
ld hl, wJoypadState
xor [hl]
and c
ld [wJoypadPressed], a
ld a, c
ld [wJoypadState], a
ret
2024-04-19 14:03:13 -06:00
SECTION "MemCopy Routine", ROM0
Memcopy::
dec bc
inc b
inc c
.loop:
ld a, [de]
ld [hli], a
inc de
dec c
jr nz, .loop
dec b
jr nz, .loop
ret
SECTION "VBlank Interrupt", ROM0[$0040]
VBlankInterrupt:
; Store registers to prevent clobbering
push af
push bc
push de
push hl
jp VBlankHandler
SECTION "VBlank Handler", ROM0
VBlankHandler:
ldh a, [hFrameCounter]
/*
bit 5, a
ld a, %11100100
jr z, .skipCpl
cpl ; Invert a
.skipCpl:
ldh [rBGP], a
*/
ld a, HIGH(wShadowOAM)
call hOAMDMA
; Reset registers to orignal state
pop hl
pop de
pop bc
pop af
reti
SECTION "Frame Counter", HRAM
hFrameCounter:
db
SECTION "Tile data", ROM0
Tiles:
INCBIN "tileset.2bpp"
TilesEnd:
SECTION "Tilemap", ROM0
Tilemap:
INCBIN "tileset.tilemap"
TilemapEnd:
SECTION "Graphics", ROM0
GfxCat:
INCBIN "sprites.2bpp"
.end::
CatMetasprite:
db 0, 0, 2, 0
db 8, 0, 6, 0
db 128
2024-04-19 09:07:20 -06:00
ShadowMetasprite:
db 12, 0, 1, 0
2024-04-19 09:07:20 -06:00
db 128
2024-04-19 09:07:20 -06:00
SECTION "Position Vars", WRAM0
; Q12.4 fixed-point X posiition
2024-04-19 14:03:13 -06:00
wMetaspritePosition::
.x:
dw
.y:
dw
.z:
dw
; Q4.4 fixed-point velocity
wMetaspriteVelocity::
2024-04-19 14:03:13 -06:00
.x:
dw
.y:
dw
.z:
dw
.boost:
db
.boosting:
db
SECTION "Joypad Vars", WRAM0
wJoypadState:
ds 1
wJoypadPressed:
ds 1