first commit

This commit is contained in:
tA 2020-05-09 11:40:26 +12:00
commit f3fd560eae
25 changed files with 1840 additions and 0 deletions

BIN
src/.actor.asm.swp Normal file

Binary file not shown.

BIN
src/.animation.asm.swo Normal file

Binary file not shown.

BIN
src/.entry.asm.swp Normal file

Binary file not shown.

59
src/actor.asm Normal file
View file

@ -0,0 +1,59 @@
;-----------------
; Actor Animation
;-----------------
SECTION "Actor Variables Struct", WRAM, ALIGN[8]
wWorldX: dw
wWorldY: dw
wActorState: db
wActorCounter: db
wActorData: dw
wActorTile: dw
SECTION "Actor", ROM0
Actor::
.structs:
dw ActorIdle
.tiles:
ActorIdle::
db 60
dw .framePa
db 15
dw .frameRe
db 15
dw .frameCi
db 15
dw .frameVo
.framePa
db (.framePaEnd - @) / 4
db -8, -8, 1, 0
db -8, 0, 2, 0
db 0, -8, 9, 0
db 0, 0, 10, 0
.framePaEnd
.frameRe
db (.frameReEnd - @) / 4
db -8, -8, 3, 0
db -8, 0, 4, 0
db 0, -8, 11, 0
db 0, 0, 12, 0
.frameReEnd
.frameCi
db (.frameCiEnd - @) / 4
db -8, -8, 5, 0
db -8, 0, 6, 0
db 0, -8, 13, 0
db 0, 0, 14, 0
.frameCiEnd
.frameVo
db (.frameVoEnd - @) / 4
db -8, -8, 7, 0
db -8, 0, 8, 0
db 0, -8, 15, 0
db 0, 0, 16, 0
.frameVoEnd

59
src/animation.asm Normal file
View file

@ -0,0 +1,59 @@
;----------------
; Animation Subs
;----------------
SECTION "Animation Variables", HRAM
hCameraX: dw
hCameraY: dw
hWorkingX: dw
hWorkingY: dw
hWorkingScreenX: db
hWorkingScreenY: db
hWorkingState: db
hWorkingCounter: db
hWorkingData: dw
hWorkingTile: dw
hWorkingEnd:
SECTION "Animations Subs", ROM0
; RenderActor:
; takes a pointer to an actor struct
; and renders it to shadow OAM, advancinc
; the animation frame and constructing
; each frame as needed.
; initial input:
; [hl] <- start of Actor Struct in WRAM
; output:
; an oam object for each line in the frame data,
; copied to shadowOAM (wShadowOAM)
RenderActor::
; load world X and Y to temp RAM
ld a, [hli]
ld [hWorkingX], a
ld a, [hli]
ld [hWorkingX+1], a
ld a, [hli]
ld [hWorkingY], a
ld a, [hli]
ld [hWorkingY+1], a
; done loading X and Y
; figure out if within 256 of camera
; ---------
; first compare upper byte of XXYY
; if this is more than 1 away, break
ld a, [hCameraX]
ld b, a
ld a, [hWorkingX]
; b = camera byte
; a = actor byte
; work out if actor minus camera is <= 1
sub b
; ---------
.skipRendering

33
src/defines.asm Normal file
View file

@ -0,0 +1,33 @@
;----------------
; Definitions
;----------------
P1F_NONE EQU $30
P1F_BUTTONS EQU $10
P1F_DPAD EQU $20
;----------------
; RAM Vars
;----------------
SECTION "ROM Vars", ROM0
dPlayerWidth: db 2
dPlayerHeight: db 2
dPlayerSpriteTiles: db $01, $02, $09, $0A
SECTION "WRAM Vars", WRAM0[$C000]
X: dw
N: dw
ANS: db
rPlayerX: db
rPlayerY: db
SECTION "HRAM Vars", HRAM
hVBlankFlag: db
hCurKeys: db
hNewKeys: db

59
src/dma.asm Normal file
View file

@ -0,0 +1,59 @@
;------------------
; DMA Subroutines
;------------------
; In order to use, simply put your destination
; address into the `a` register, and call `hOAMDMA`
; Here we copy our DMA Routine into
; HRAM, which it needs to be in so
; it can function.
; Note: we can only copy into HRAM
; while the screen /ISN'T/ updating
SECTION "OAM DMA Routine", ROM0
; A DMA Transfor takes 160 microseconds
; to complete, which is 40 machine cycles.
; here we copy the high bit of our destination
; address (stored in a) to the DMA register
; then wait the time needed for the copy to
; complete.
DMARoutine:
ldh [rDMA], a
ld a, 40
.wait
dec a
jr nz, .wait
ret
.end
CopyDMARoutine:
ld hl, DMARoutine
ld b, DMARoutine.end - DMARoutine
ld c, LOW(hOAMDMA)
.copy
ld a, [hli]
ldh [c], a
inc c
dec b
jr nz, .copy
ret
; We reserve space in HRAM to keep our
; DMA routine.
SECTION "OAM DMA", HRAM
hOAMDMA:
ds DMARoutine.end - DMARoutine
; We also reserve space to have a copy
; of OAM that we can write to at any time
; The DMA will then mirror this data to
; the real OAM.
SECTION "Shadow OAM", WRAM0,ALIGN[8]
wShadowOAM::
ds 4*40

160
src/entry.asm Normal file
View file

@ -0,0 +1,160 @@
;----------------
; Program Start
;----------------
BUFFER EQU 160
TRUE EQU $42
FALSE EQU $69
SECTION "Program Start", ROM0[$150]
Start:
ei
ld a, IEF_VBLANK
ld [rIE], a
xor a
ld [hVBlankFlag], a
call Wait_VBlank
xor a
ldh [rLCDC], a
call Clear_Map
call Load_Tiles
; call Load_Map
ld a, %11100100
ld [rBGP], a
ld [rOBP0], a
xor a
ld [rSCY], a
ld [rSCX], a
ld [rNR52], a
ld a, LCDCF_ON | LCDCF_OBJON | LCDCF_BGON
ld [rLCDC], a
call CopyDMARoutine
ld a, 72
ld [rPlayerX], a
ld a, 88
ld [rPlayerY], a
;----
; Testing
;----
ld a, HIGH(ANS)
ld h, a
ld a, LOW(ANS)
ld l, a
; Case One: Camera@E100 vs Actor@E195 (Pass)
ld a, $E1
ld [N], a
ld a, $E1
ld [X], a
ld a, $00
ld [N+1], a
ld a, $95
ld [X+1], a
call CheckBoundry
; Case One: Camera@E095 vs Actor@E120 (Pass)
ld a, $E0
ld [N], a
ld a, $E1
ld [X], a
ld a, $95
ld [N+1], a
ld a, $20
ld [X+1], a
call CheckBoundry
; Case One: Camera@E100 vs Actor@E1FF (Fail)
ld a, $E1
ld [N], a
ld a, $E1
ld [X], a
ld a, $00
ld [N+1], a
ld a, $FF
ld [X+1], a
call CheckBoundry
; Case One: Camera@E1F0 vs Actor@E2DE (Fail)
ld a, $E1
ld [N], a
ld a, $E2
ld [X], a
ld a, $F0
ld [N+1], a
ld a, $DE
ld [X+1], a
call CheckBoundry
game_loop:
call Wait_VBlank
call Read_Pad
call PC_Update
call Player_To_OAM
ld a, HIGH(wShadowOAM)
call hOAMDMA
jr game_loop
CheckBoundry::
;-----
; Check if word X is within BUFFER ahead of N
; BUFFER is always <= 255
; hl contains address to save result to
;-----
;= load high bytes
ld a, [N]
ld b, a
ld a, [X]
sub b
;= if carry is set, N is behind X, so skip
jr c, .skipRender
ld b, a
ld a, 2
cp b
;= if the difference is 2 or greater
;= we are not within BUFFER, so skip
jr c, .skipRender
jr z, .skipRender
dec a
cp b
;= if the high byte differ by 1, we
;= need to check over a a page
jr z, .swap
;= load the low bytes
ld a, [N+1]
ld b, a
ld a, [X+1]
sub b
ld b, a
ld a, BUFFER
cp b
;= if the difference is greater than
;= the buffer, skip
jr c, .skipRender
jr .render
.swap
;= load the low bytes in the opposite order
ld a, [X+1]
ld b, a
ld a, [N+1]
sub b
ld b, a
ld a, $FF - BUFFER
cp b
;= if they differ by the inverse of the buffer
;= they will not be within the gap between pages
jr nc, .skipRender
.render
;= success, do rendering stuff
; beep boop rendering stuff
ld a, TRUE
ld [hli], a
ret
.skipRender
;= failure, skip this one
; doing other stuff here
ld a, FALSE
ld [hli], a
ret

45
src/header.asm Normal file
View file

@ -0,0 +1,45 @@
;-----------------
; Gameboy Header
;-----------------
SECTION "Header", ROM0[$100]
; Jump to the "Start" label
; which we must define ourselves
EntryPoint:
nop
jp Start;
; ROM Header $104 to $150
RomHeader:
; Nintendo Logo $104-$133
db $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D
db $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99
db $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E
; Title (11 characters) $134-$13E
db "ANIMATION",$00,$00
; Manufacturer Code (4 characters) $13F-$142
db "LATA"
; CGB Flag $143
db $00
; Licensee Code (2 characters) $144-$145
db "00"
; SGB Flag $146
db $00
; Cartridge Type $147
db $00
; ROM Size $148
db $00
; RAM Size $149
db $00
; Destination Code $14A
db $01
; Depreciated Licensee Code $14B
db $33
; Version Number $14C
db $00
; Header Checksum $14D
db $00
; Global Checksum $14E-$14F
db $00, $00

11
src/main.asm Normal file
View file

@ -0,0 +1,11 @@
INCLUDE "inc/hardware.inc"
INCLUDE "ass/parecivo.ass"
INCLUDE "ass/tiles.ass"
INCLUDE "ass/map.ass"
INCLUDE "src/entry.asm"
INCLUDE "src/header.asm"
INCLUDE "src/defines.asm"
INCLUDE "src/dma.asm"
INCLUDE "src/util.asm"
INCLUDE "src/vid.asm"
INCLUDE "src/misc.asm"

167
src/misc.asm Normal file
View file

@ -0,0 +1,167 @@
Player_To_OAM:
; -- first loop --
ld hl, wShadowOAM
ld a, [dPlayerHeight]
ld b, a
ld d, 16
ld a, [rPlayerY]
add d ; d has the base Y value (counting offsets)
ld d, a
.fouter
ld a, [dPlayerWidth]
ld c, a ; c is finner counter
.finner
ld a, d
ld [hl], a
ld a, 4
call .add4hl
; end of finner loop
dec c
jr nz, .finner
ld a, d
ld d, 8
add d
ld d, a
; end of fouter loop
dec b
jr nz, .fouter
; -- second loop --
ld hl, wShadowOAM+1
ld a, [dPlayerHeight]
ld b, a
.souter
ld d, 8
ld a, [rPlayerX]
add d
ld d, a
ld a, [dPlayerWidth]
ld c, a
.sinner
ld a, d
ld [hl], a
add 8
ld d, a
ld a, 4
call .add4hl
dec c
jr nz, .sinner
dec b
jr nz, .souter
; -- third loop --
ld hl, wShadowOAM+2
ld de, dPlayerSpriteTiles
ld a, [dPlayerHeight]
ld b, a
ld a, [dPlayerWidth]
ld c, a
xor a
.tloop1
add b
dec c
jr nz, .tloop1
ld c, a
.tloop2
ld a, [de]
ld [hl], a
ld a, 4
call .add4hl
inc de
dec c
jr nz, .tloop2
; -- fourth loop --
ld hl, wShadowOAM+3
ld a, [dPlayerHeight]
ld b, a
ld a, [dPlayerWidth]
ld c, a
xor a
.lloop1
add b
dec c
jr nz, .lloop1
ld c, a
.lloop2
xor a
ld [hl], a
ld a, 4
call .add4hl
dec c
jr nz, .lloop2
ret
.add4hl:
add a, l ; a = low + old_l
ld l, a ; a = low + old_l = new_l
adc a, h ; a = new_l + old_h + carry
sub l ; a = old_h + carry
ld h, a
ret
PC_Update:
ld b, 0
ld c, 0
ld a, [hCurKeys]
and %10000000
cp %10000000 ; 0 if down pressed
jr nz, .up
ld b, 1
.up:
ld a, [hCurKeys]
and %01000000
cp %01000000 ; 0 if up pressed
jr nz, .left
ld b, 255
.left:
ld a, [hCurKeys]
and %00100000
cp %00100000 ; 0 if down pressed
jr nz, .right
ld c, 255
.right:
ld a, [hCurKeys]
and %00010000
cp %00010000 ; 0 if up pressed
jr nz, .last
ld c, 1
.last:
ld a, [rPlayerX]
add c
ld [rPlayerX], a
ld a, [rPlayerY]
add b
ld [rPlayerY], a
.end:
ret
Clear_Map:
xor a
ld hl, _SCRN0
ld bc, _SCRN0_END - _SCRN0
.loop:
ld [hli], a
dec bc
ld a, b
or c
jr z, .loop
ret
Load_Tiles:
ld hl, _BGTILES
ld de, parecivo_tile_data
ld bc, parecivo_tile_data_size
call MemCpy
ld hl, _VRAM
ld de, parecivo_tile_data
ld bc, parecivo_tile_data_size
call MemCpy
ret
Load_Map:
ld hl, _SCRN0
ld de, Map
ld bc, Map_Size
call MemCpy
ret

70
src/util.asm Normal file
View file

@ -0,0 +1,70 @@
;----------------------
; Utility Subroutines
;----------------------
SECTION "Util Subs", ROM0
; MemCpy assumes:
; hl contains destination address
; de contains source address
; bc contains number of bytes to copy
MemCpy:
.copy
ld a, [de]
ld [hli], a
inc de
dec bc
ld a, b
or c
jr nz, .copy
ret
; Read_Pad will set the variable _PAD
; such that bits are as follows:
; 7 - 4: down up left right
; 3 - 0: start select b a
Read_Pad:
ld a,P1F_BUTTONS
call .onenibble
ld b,a ; B7-4 = 1; B3-0 = unpressed buttons
ld a,P1F_DPAD
call .onenibble
swap a ; A3-0 = unpressed directions; A7-4 = 1
xor b ; A = pressed buttons + directions
ld b,a ; B = pressed buttons + directions
; check illegal buttons
and %11000000 ; Up and Down buttons
cp %11000000
jr nz, .legalUpDown
ld a, b
and %00111111
ld b, a
.legalUpDown
and %00110000 ; Left and Right buttons
cp %00110000
jr nz, .legalLeftRight
ld a, b
and %11001111
.legalLeftRight
ld a,P1F_NONE
ld [rP1],a
ldh a,[hCurKeys]
xor b ; A = keys that changed state
and b ; A = keys that changed to pressed
ldh [hNewKeys],a
ld a,b
ldh [hCurKeys],a
ret
.onenibble:
ldh [rP1],a
ldh a,[rP1]
ldh a,[rP1]
ldh a,[rP1]
or $F0
ret

22
src/vid.asm Normal file
View file

@ -0,0 +1,22 @@
;--------------------
; Video Subroutines
;--------------------
SECTION "VBlank Int", ROM0[$40]
ld a, 1
ld [hVBlankFlag], a
reti
SECTION "Vid Subs", ROM0
Wait_VBlank::
ld hl, hVBlankFlag ; hl=pointer to vblank_flag
.wait: ; wait...
halt ; suspend CPU - wait for ANY interrupt
nop
xor a
cp a,[hl] ; vblank flag still zero?
jr z, .wait ; wait more if zero
ld [hl],a ; set vblank_flag back to zero
ret