INCLUDE "hardware.inc"
|
|
INCLUDE "util.inc"
|
|
|
|
SECTION "Map Data", WRAM0
|
|
|
|
PAGEX:: DB
|
|
PAGEY:: DB
|
|
|
|
LAST_SCX:: DB
|
|
LAST_SCY:: DB
|
|
|
|
CURRENT_DATA_START::
|
|
CURRENT_TILE_PTR:: DW
|
|
CURRENT_TILE_SIZE:: DB
|
|
CURRENT_MAP_PTR:: DW
|
|
CURRENT_MAP_COLLISION:: DW
|
|
CURRENT_MAP_WIDTH:: DB
|
|
CURRENT_MAP_HEIGHT:: DB
|
|
CURRENT_SPAWN_X:: DB
|
|
CURRENT_SPAWN_Y:: DB
|
|
CURRENT_CAMERA_X:: DB
|
|
CURRENT_CAMERA_Y:: DB
|
|
CURRENT_DATA_END::
|
|
|
|
SECTION "Map Code", ROM0
|
|
|
|
DEF INIT_SCX EQUS "((SCRN_VX - SCRN_X) / 2)"
|
|
DEF INIT_SCY EQUS "((SCRN_VY - SCRN_Y) / 2)"
|
|
|
|
DEF PAGE_SIZE EQU 2
|
|
|
|
DEF STACK_OFFSET_ROW EQU 3
|
|
DEF STACK_OFFSET_MAP EQU 1
|
|
DEF STACK_OFFSET_LEFT EQU 0
|
|
|
|
; Increments a 16-bit value located on the stack
|
|
; \1 Stack offset
|
|
MACRO INC_STACK16
|
|
ld hl, sp + \1
|
|
inc [hl]
|
|
jr nz, .no_carry\@
|
|
|
|
inc hl
|
|
inc [hl]
|
|
|
|
.no_carry\@:
|
|
ENDM
|
|
|
|
MACRO ZERO_ROW_TILE
|
|
ld hl, sp + STACK_OFFSET_ROW
|
|
ld a, [hl+]
|
|
ld e, a
|
|
ld d, [hl]
|
|
xor a
|
|
ld [de], a
|
|
ENDM
|
|
|
|
; Loads a map
|
|
; @param hl Pointer to map metadata
|
|
Map_Load::
|
|
; Initialize scroll state
|
|
ld a, INIT_SCX
|
|
ld [rSCX], a
|
|
ld [LAST_SCX], a
|
|
|
|
ld a, INIT_SCY
|
|
ld [rSCY], a
|
|
ld [LAST_SCY], a
|
|
|
|
ld a, 8
|
|
ld [PAGEX], a
|
|
ld [PAGEY], a
|
|
|
|
; Store metadata
|
|
ld bc, CURRENT_DATA_START
|
|
ld d, CURRENT_DATA_END - CURRENT_DATA_START
|
|
call memcpy
|
|
|
|
; Write tiles to VRAM
|
|
ld hl, CURRENT_TILE_PTR
|
|
ld a, [hl+]
|
|
ld c, a
|
|
ld a, [hl+]
|
|
ld b, a
|
|
|
|
ld a, [CURRENT_TILE_SIZE]
|
|
ld d, a
|
|
|
|
ld hl, _VRAM
|
|
MEMCPY hl, bc, d
|
|
|
|
; Write initial map data
|
|
ld hl, _SCRN0
|
|
|
|
ld a, [CURRENT_CAMERA_X]
|
|
sub INIT_SCX / 8
|
|
ld b, a
|
|
|
|
ld a, [CURRENT_CAMERA_Y]
|
|
sub INIT_SCY / 8
|
|
ld c, a
|
|
|
|
ld d, SCRN_VY_B
|
|
.write_rows:
|
|
call write_map_row
|
|
inc c
|
|
dec d
|
|
jr nz, .write_rows
|
|
|
|
ret
|
|
|
|
; Update map state based on SCX/SCY
|
|
Map_Scroll::
|
|
; Adjust CURRENT_CAMERA_X
|
|
|
|
; ; Adjust CURRENT_CAMERA_Y if [LAST_SCY]/8 != [rSCY]/8
|
|
; ld a, [rSCY]
|
|
; srl a
|
|
; srl a
|
|
; srl a
|
|
|
|
; ld hl, LAST_SCY
|
|
; ld b, [hl]
|
|
; srl b
|
|
; srl b
|
|
; srl b
|
|
|
|
; cp b
|
|
; jr c, .cmp
|
|
; jr z, .scroll_up_check
|
|
|
|
; sub $20
|
|
|
|
; .cmp:
|
|
; sub b
|
|
|
|
; ld hl, CURRENT_CAMERA_Y
|
|
; add [hl]
|
|
; ld [hl], a
|
|
|
|
; min([LAST_SCY]/8 - [SCY/8], [SCY/8] - [LAST_SCY]/8)
|
|
|
|
ld a, [LAST_SCY]
|
|
srl a
|
|
srl a
|
|
srl a
|
|
ld b, a
|
|
|
|
ld a, [rSCY]
|
|
srl a
|
|
srl a
|
|
srl a
|
|
|
|
; c <- scy/8 - last_scy/8
|
|
sub b
|
|
ld c, a
|
|
|
|
ld a, [rSCY]
|
|
srl a
|
|
srl a
|
|
srl a
|
|
ld b, a
|
|
|
|
ld a, [LAST_SCY]
|
|
srl a
|
|
srl a
|
|
srl a
|
|
sub b
|
|
; a <- last_scy/8 - scy/8
|
|
|
|
cp c
|
|
|
|
.tryit:
|
|
ld [CURRENT_CAMERA_Y], a
|
|
|
|
.scroll_up_check:
|
|
; If SCY = PAGEY, write map row
|
|
; map coords = CURRENT_CAMERA_X, CURRENT_CAMERA_Y - 2
|
|
; HL = _SCRN0 + 32 * (32 - page_y/8 - 2)
|
|
ld hl, PAGEY
|
|
ld a, [rSCY]
|
|
cp [hl]
|
|
jr nz, .scroll_down_check
|
|
|
|
ld a, [rSCX]
|
|
ld b, a
|
|
ld a, [CURRENT_CAMERA_X]
|
|
srl b
|
|
srl b
|
|
srl b
|
|
sub b
|
|
ld b, a
|
|
|
|
ld a, [CURRENT_CAMERA_Y]
|
|
cp 2
|
|
jr c, .done
|
|
|
|
sub 2
|
|
ld c, a
|
|
|
|
; a = scy/8 + (scy/8 < 2 ? 30 : -2)
|
|
|
|
ld a, [rSCY]
|
|
srl a
|
|
srl a
|
|
srl a
|
|
|
|
cp 2
|
|
jr nc, .loop0
|
|
add 32
|
|
|
|
.loop0:
|
|
sub 2
|
|
|
|
; hl = _SCRN0 + 32 * a
|
|
ld e, a
|
|
ld hl, _SCRN0
|
|
.loop:
|
|
ld a, e
|
|
or a
|
|
jr z, .write_up
|
|
|
|
ld a, 32
|
|
ADD16 hl
|
|
|
|
dec e
|
|
jr .loop
|
|
|
|
.write_up:
|
|
halt
|
|
call write_map_row
|
|
|
|
ld a, [PAGEY]
|
|
sub 8
|
|
ld [PAGEY], a
|
|
|
|
jr .done
|
|
|
|
.scroll_down_check:
|
|
; If SCY = SCRN_Y - PAGEY, write map row
|
|
; map coords = CURRENT_CAMERA_X, CURRENT_CAMERA_Y + 21
|
|
; HL = _SCRN0 + 32 * ((32 - page_y) - 1)
|
|
; TODO: Check math on these
|
|
|
|
; If SCX = PAGEX, write map col
|
|
; If SCX = SCRN_X - PAGEX, write map col
|
|
|
|
.done:
|
|
ld hl, LAST_SCY
|
|
ld a, [rSCY]
|
|
ld [hl], a
|
|
|
|
ret
|
|
|
|
; Write a row of map data into map RAM
|
|
; @param b Map X coordinate (signed)
|
|
; @param c Map Y coordinate (signed)
|
|
; @param hl Start of the row to write
|
|
write_map_row:
|
|
push bc
|
|
push de
|
|
|
|
; If Y < 0, write a row of 0s
|
|
bit 7, c
|
|
jr nz, .zero_row
|
|
|
|
; If Y >= MAP_HEIGHT, write a row of 0s
|
|
ld a, [CURRENT_MAP_HEIGHT]
|
|
dec a
|
|
cp c
|
|
jr nc, .begin_writing
|
|
|
|
.zero_row:
|
|
ld d, SCRN_VX_B
|
|
xor a
|
|
.zero_row_loop:
|
|
ld a, [hl+]
|
|
dec d
|
|
jr nz, .zero_row_loop
|
|
.zero_row_done:
|
|
pop de
|
|
pop bc
|
|
ret
|
|
|
|
.begin_writing:
|
|
push hl
|
|
|
|
; Allocate 2 bytes for map pointer
|
|
; Allocate 1 byte for number of tiles left
|
|
add sp, -3
|
|
|
|
; left = number of tiles left to write
|
|
ld hl, sp + STACK_OFFSET_LEFT
|
|
ld [hl], SCRN_VX_B
|
|
|
|
; HL = CURRENT_MAP_PTR + Y * CURRENT_MAP_HEIGHT
|
|
ld a, [CURRENT_MAP_PTR]
|
|
ld l, a
|
|
ld a, [CURRENT_MAP_PTR + 1]
|
|
ld h, a
|
|
|
|
.compute_map_row:
|
|
ld a, c
|
|
or a
|
|
jr z, .compute_map_row_done
|
|
|
|
ld a, [CURRENT_MAP_HEIGHT]
|
|
ADD16 HL
|
|
dec c
|
|
jr .compute_map_row
|
|
|
|
; map = HL
|
|
.compute_map_row_done:
|
|
LD16 de, hl
|
|
ld hl, sp + STACK_OFFSET_MAP
|
|
ld a, e
|
|
ld [hl+], a
|
|
ld a, d
|
|
ld [hl], a
|
|
|
|
ld hl, sp + STACK_OFFSET_LEFT
|
|
|
|
; While X < 0 and left > 0, write 0 to the row
|
|
.pad_left:
|
|
bit 7, b
|
|
jr z, .copy_center
|
|
|
|
ld a, [hl]
|
|
or a
|
|
jr z, .done
|
|
|
|
; *row = 0
|
|
ZERO_ROW_TILE
|
|
|
|
; row++
|
|
INC_STACK16 STACK_OFFSET_ROW
|
|
|
|
; X++, left--
|
|
inc b
|
|
ld hl, sp + STACK_OFFSET_LEFT
|
|
dec [hl]
|
|
jr .pad_left
|
|
|
|
; While X < MAP_WIDTH and [SP] > 0, copy from map
|
|
.copy_center:
|
|
ld a, [CURRENT_MAP_WIDTH]
|
|
dec a
|
|
cp b
|
|
jr z, .pad_right
|
|
|
|
ld a, [hl]
|
|
or a
|
|
jr z, .done
|
|
|
|
; A = *map_ptr
|
|
ld hl, sp + STACK_OFFSET_MAP
|
|
ld a, [hl+]
|
|
ld e, a
|
|
ld d, [hl]
|
|
ld a, [de]
|
|
|
|
; map_ptr++
|
|
INC_STACK16 STACK_OFFSET_MAP
|
|
|
|
; *row = A
|
|
ld hl, sp + STACK_OFFSET_ROW
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
ld [de], a
|
|
|
|
; row++
|
|
INC_STACK16 3
|
|
|
|
; X++, [SP]--
|
|
.copy_center_inc:
|
|
inc b
|
|
ld hl, sp + STACK_OFFSET_LEFT
|
|
dec [hl]
|
|
jr .copy_center
|
|
|
|
; While [SP] > 0, write 0 to the row
|
|
.pad_right:
|
|
ld a, [hl]
|
|
or a
|
|
jr z, .done
|
|
|
|
; *row = 0
|
|
ZERO_ROW_TILE
|
|
|
|
; row++
|
|
INC_STACK16 STACK_OFFSET_ROW
|
|
|
|
; [SP]--
|
|
.pad_right_inc:
|
|
ld hl, sp + STACK_OFFSET_ROW
|
|
dec [hl]
|
|
jr .pad_right
|
|
|
|
.done:
|
|
add sp, 3
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
|
|
ret
|