INCLUDE "game.inc"
|
|
INCLUDE "hardware.inc"
|
|
INCLUDE "util.inc"
|
|
|
|
SECTION "Map Data", WRAM0
|
|
|
|
DEF ROW_BUFFER_SIZE EQUS "SCRN_X_B + 4"
|
|
DEF COL_BUFFER_SIZE EQUS "SCRN_Y_B + 4"
|
|
|
|
PENDING_ROW_PTR:: DW ; Where to write pending row data (0 = no write)
|
|
PENDING_ROW_DATA:: DS ROW_BUFFER_SIZE ; Row to be written
|
|
|
|
PENDING_COL_PTR:: DW ; Where to write pending column data (0 = no write)
|
|
PENDING_COL_DATA: DS COL_BUFFER_SIZE ; Column to be written
|
|
|
|
CURRENT_DATA_START::
|
|
CURRENT_TILE_PTR:: DW ; Location of tile data
|
|
CURRENT_TILE_SIZE:: DB ; Length of tile data (num_tiles * 8)
|
|
CURRENT_MAP_PTR:: DW ; Location of map data
|
|
CURRENT_MAP_COLLISION:: DW ; Location of map collision data
|
|
CURRENT_MAP_WIDTH:: DB ; Width of map in tiles
|
|
CURRENT_MAP_HEIGHT:: DB ; Height of map in tiles
|
|
CURRENT_SPAWN_X:: DB ; X coordinate to spawn player at
|
|
CURRENT_SPAWN_Y:: DB ; Y coordinate to spawn player at
|
|
CURRENT_CAMERA_X:: DB ; X coordinate of camera (top left of viewport)
|
|
CURRENT_CAMERA_Y:: DB ; Y coordinate of camera (top left of viewport)
|
|
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)"
|
|
|
|
|
|
|
|
; Loads a map
|
|
; @param hl Pointer to map metadata
|
|
Map_Load::
|
|
; Initialize scroll state
|
|
ld a, INIT_SCX
|
|
ld [rSCX], a
|
|
|
|
ld a, INIT_SCY
|
|
ld [rSCY], a
|
|
|
|
; Store metadata
|
|
ld bc, CURRENT_DATA_START
|
|
ld d, CURRENT_DATA_END - CURRENT_DATA_START
|
|
call memcpy
|
|
|
|
; Move player to spawn point
|
|
ld a, [CURRENT_CAMERA_X]
|
|
ld b, a
|
|
ld a, [CURRENT_SPAWN_X]
|
|
sub b
|
|
sla a
|
|
sla a
|
|
sla a
|
|
ld [PLAYER_X], a
|
|
|
|
ld a, [CURRENT_CAMERA_Y]
|
|
ld b, a
|
|
ld a, [CURRENT_SPAWN_Y]
|
|
sub b
|
|
sla a
|
|
sla a
|
|
sla a
|
|
ld [PLAYER_Y], a
|
|
|
|
; 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 + TILE_INDEX_BACKGROUND * TILE_SIZE
|
|
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
|
|
|
|
ld a, SCRN_VX_B
|
|
ADD16 hl
|
|
|
|
dec d
|
|
jr nz, .write_rows
|
|
|
|
ret
|
|
|
|
|
|
|
|
; Scroll the map upwards
|
|
; @param d The amount to scroll by (0 < d < 8)
|
|
;
|
|
; SCY_T = SCY % 8;
|
|
; if CAMERA_Y = 0 {
|
|
; if SCY_T != 0 {
|
|
; SCY -= MIN(D, SCY_T);
|
|
; }
|
|
; return;
|
|
; }
|
|
; SCY -= D;
|
|
; if SCY_T - D < 0 {
|
|
; CAMERA_Y -= 1;
|
|
; Map_ScrollRow(CAMERA_X - 2, CAMERA_Y - 2);
|
|
; }
|
|
Map_ScrollUp::
|
|
ld a, [rSCY]
|
|
and %111
|
|
|
|
add sp, -1
|
|
ld hl, sp + 0
|
|
ld [hl], a
|
|
|
|
ld a, [CURRENT_CAMERA_Y]
|
|
or a
|
|
jr nz, .scroll
|
|
|
|
ld hl, sp + 0
|
|
ld a, [hl]
|
|
or a
|
|
jr z, .done
|
|
|
|
ld b, d
|
|
call min
|
|
ld d, a
|
|
ld a, [rSCY]
|
|
sub d
|
|
ld [rSCY], a
|
|
jr .done
|
|
|
|
.scroll:
|
|
ld a, [rSCY]
|
|
sub d
|
|
ld [rSCY], a
|
|
|
|
; Check SCY_T - D < 0
|
|
ld hl, sp + 0
|
|
ld a, [hl]
|
|
sub d
|
|
jr nc, .done
|
|
|
|
; CAMERA_Y -= 1
|
|
ld a, [CURRENT_CAMERA_Y]
|
|
dec a
|
|
ld [CURRENT_CAMERA_Y], a
|
|
|
|
; B = CAMERA_X - 2
|
|
ld a, [CURRENT_CAMERA_X]
|
|
sub 2
|
|
ld b, a
|
|
|
|
; C = CAMERA_Y - 2
|
|
ld a, [CURRENT_CAMERA_Y]
|
|
sub 2
|
|
ld c, a
|
|
|
|
; MAP Y = SCY/8 - 2
|
|
ld a, [rSCY]
|
|
srln a, 3
|
|
sub 2
|
|
|
|
add sp, 1
|
|
jr Map_ScrollRow
|
|
|
|
.done:
|
|
add sp, 1
|
|
ret
|
|
|
|
|
|
|
|
; Map_ScrollDown(D)
|
|
;
|
|
; SCY_T = SCY % 8;
|
|
; if CAMERA_Y + 18 = MAP_HEIGHT {
|
|
; if SCY_T != 0 {
|
|
; SCY += MIN(D, 8 - SCY_T);
|
|
; }
|
|
; return;
|
|
; }
|
|
; SCY += D;
|
|
; if SCY_T + D >= 8 {
|
|
; CAMERA_Y += 1;
|
|
; Map_ScrollRow(CAMERA_X - 2, CAMERA_Y + 18 + 1);
|
|
; }
|
|
Map_ScrollDown::
|
|
ld a, [rSCY]
|
|
and %111
|
|
|
|
add sp, -1
|
|
ld hl, sp + 0
|
|
ld [hl], a
|
|
|
|
ld a, [CURRENT_CAMERA_Y]
|
|
add SCRN_Y_B
|
|
ld hl, CURRENT_MAP_HEIGHT
|
|
cp [hl]
|
|
jr nz, .scroll
|
|
|
|
ld hl, sp + 0
|
|
ld a, [hl]
|
|
or a
|
|
jr z, .done
|
|
|
|
sub 8
|
|
cpl
|
|
|
|
ld b, d
|
|
call min
|
|
ld d, a
|
|
ld a, [rSCY]
|
|
add d
|
|
ld [rSCY], a
|
|
jr .done
|
|
|
|
.scroll:
|
|
ld a, [rSCY]
|
|
add d
|
|
ld [rSCY], a
|
|
|
|
; Check SCY_T + D < 8
|
|
ld hl, sp + 0
|
|
ld a, [hl]
|
|
add d
|
|
cp 8
|
|
jr c, .done
|
|
|
|
; CAMERA_Y += 1
|
|
ld a, [CURRENT_CAMERA_Y]
|
|
inc a
|
|
ld [CURRENT_CAMERA_Y], a
|
|
|
|
; B = CAMERA_X - 2
|
|
ld a, [CURRENT_CAMERA_X]
|
|
sub 2
|
|
ld b, a
|
|
|
|
; C = CAMERA_Y + 18 + 1
|
|
ld a, [CURRENT_CAMERA_Y]
|
|
add SCRN_Y_B + 1
|
|
ld c, a
|
|
|
|
; MAP Y = SCY/8 + SCRN_Y_B + 1
|
|
ld a, [rSCY]
|
|
srln a, 3
|
|
add SCRN_Y_B + 1
|
|
|
|
add sp, 1
|
|
jr Map_ScrollRow
|
|
|
|
.done:
|
|
add sp, 1
|
|
ret
|
|
|
|
|
|
|
|
; Scroll in a new row
|
|
; @param a Map VRAM Y-coordinate
|
|
; @param b Data X-coordinate
|
|
; @param c Data Y-coordinate
|
|
Map_ScrollRow:
|
|
and %11111
|
|
call get_row_ptr
|
|
|
|
ld a, [rSCX]
|
|
sub 16
|
|
srl a
|
|
srl a
|
|
srl a
|
|
ld e, a
|
|
ld d, 0
|
|
add hl, de
|
|
|
|
call enqueue_row_write
|
|
ret
|
|
|
|
|
|
|
|
Map_ScrollLeft::
|
|
ld a, [rSCX]
|
|
and %111
|
|
|
|
add sp, -1
|
|
ld hl, sp + 0
|
|
ld [hl], a
|
|
|
|
ld a, [CURRENT_CAMERA_X]
|
|
or a
|
|
jr nz, .scroll
|
|
|
|
ld hl, sp + 0
|
|
ld a, [hl]
|
|
or a
|
|
jr z, .done
|
|
|
|
ld b, d
|
|
call min
|
|
ld d, a
|
|
ld a, [rSCX]
|
|
sub d
|
|
ld [rSCX], a
|
|
jr .done
|
|
|
|
.scroll:
|
|
ld a, [rSCX]
|
|
sub d
|
|
ld [rSCX], a
|
|
|
|
; Check SCX_T - D < 0
|
|
ld hl, sp + 0
|
|
ld a, [hl]
|
|
sub d
|
|
jr nc, .done
|
|
|
|
ld a, [CURRENT_CAMERA_X]
|
|
dec a
|
|
ld [CURRENT_CAMERA_X], a
|
|
|
|
ld a, [rSCY]
|
|
sub 16
|
|
srl a
|
|
srl a
|
|
srl a
|
|
call get_row_ptr
|
|
|
|
; B = CAMERA_X - 2
|
|
ld a, [CURRENT_CAMERA_X]
|
|
sub 2
|
|
ld b, a
|
|
|
|
; E = VRAM + (SCX/8 - 2)
|
|
ld a, [rSCX]
|
|
srln a, 3
|
|
sub 2
|
|
ADD16 hl
|
|
|
|
add sp, 1
|
|
jr Map_ScrollColumn
|
|
|
|
.done:
|
|
add sp, 1
|
|
ret
|
|
|
|
|
|
|
|
Map_ScrollRight::
|
|
ld a, [rSCX]
|
|
and %111
|
|
|
|
add sp, -1
|
|
ld hl, sp + 0
|
|
ld [hl], a
|
|
|
|
ld a, [CURRENT_CAMERA_X]
|
|
add SCRN_X_B
|
|
ld hl, CURRENT_MAP_WIDTH
|
|
cp [hl]
|
|
jr nz, .scroll
|
|
|
|
ld hl, sp + 0
|
|
ld a, [hl]
|
|
or a
|
|
jr z, .done
|
|
|
|
sub 8
|
|
cpl
|
|
|
|
ld b, d
|
|
call min
|
|
ld d, a
|
|
ld a, [rSCX]
|
|
add d
|
|
ld [rSCX], a
|
|
jr .done
|
|
|
|
.scroll:
|
|
ld a, [rSCX]
|
|
add d
|
|
ld [rSCX], a
|
|
|
|
; Check SCX_T + D < 8
|
|
ld hl, sp + 0
|
|
ld a, [hl]
|
|
add d
|
|
cp 8
|
|
jr c, .done
|
|
|
|
; CAMERA_X += 1
|
|
ld a, [CURRENT_CAMERA_X]
|
|
inc a
|
|
ld [CURRENT_CAMERA_X], a
|
|
|
|
ld a, [rSCY]
|
|
sub 16
|
|
srl a
|
|
srl a
|
|
srl a
|
|
call get_row_ptr
|
|
|
|
; B = CAMERA_X + 20 + 1
|
|
ld a, [CURRENT_CAMERA_X]
|
|
add SCRN_X_B + 1
|
|
ld b, a
|
|
|
|
; E = VRAM + SCX/8 + SCRN_X_B + 1
|
|
ld a, [rSCX]
|
|
srl a
|
|
srl a
|
|
srl a
|
|
add SCRN_X_B + 1
|
|
and %11111
|
|
ADD16 hl
|
|
|
|
add sp, 1
|
|
jr Map_ScrollColumn
|
|
|
|
.done:
|
|
add sp, 1
|
|
ret
|
|
|
|
|
|
|
|
Map_ScrollColumn:
|
|
; C = CAMERA_Y - 2
|
|
ld a, [CURRENT_CAMERA_Y]
|
|
sub 2
|
|
ld c, a
|
|
|
|
call enqueue_col_write
|
|
ret
|
|
|
|
|
|
|
|
|
|
Map_Update::
|
|
; Skip row update if PENDING_ROW_PTR is 0
|
|
ld a, [PENDING_ROW_PTR]
|
|
ld c, a
|
|
ld a, [PENDING_ROW_PTR + 1]
|
|
ld b, a
|
|
or c
|
|
jr z, .update_col
|
|
|
|
ld hl, PENDING_ROW_DATA
|
|
ld d, ROW_BUFFER_SIZE
|
|
.copy_row:
|
|
ld a, [hl+]
|
|
ld [bc], a
|
|
inc bc
|
|
|
|
; if BC % 32 == 0 (we just crossed a row boundary)
|
|
ld a, c
|
|
and %11111
|
|
jr nz, .copy_row1
|
|
|
|
; BC -= 32 (reset back to beginning of row)
|
|
ld a, c
|
|
sub 32
|
|
ld c, a
|
|
ld a, b
|
|
sbc 0
|
|
ld b, a
|
|
|
|
.copy_row1:
|
|
dec d
|
|
jr nz, .copy_row
|
|
|
|
; Reset PENDING_ROW_PTR
|
|
xor a
|
|
ld [PENDING_ROW_PTR], a
|
|
ld [PENDING_ROW_PTR + 1], a
|
|
|
|
.update_col:
|
|
; Skip column update if PENDING_COL_PTR is 0
|
|
ld a, [PENDING_COL_PTR]
|
|
ld c, a
|
|
ld a, [PENDING_COL_PTR + 1]
|
|
ld b, a
|
|
or c
|
|
ret z
|
|
|
|
ld d, COL_BUFFER_SIZE
|
|
ld hl, PENDING_COL_DATA
|
|
.update_col_loop:
|
|
ld a, [hl+]
|
|
ld [bc], a
|
|
|
|
ld a, SCRN_VX_B
|
|
ADD16 bc
|
|
|
|
; If BC = 9c00, set BC = 9800
|
|
CP16 bc, _SCRN0 + SCRN_VY_B * SCRN_VX_B
|
|
jr nz, .update_col_loop_next
|
|
ld b, HIGH(_SCRN0)
|
|
|
|
.update_col_loop_next:
|
|
dec d
|
|
jr nz, .update_col_loop
|
|
|
|
; Reset PENDING_COL_PTR
|
|
xor a
|
|
ld [PENDING_COL_PTR], a
|
|
ld [PENDING_COL_PTR + 1], a
|
|
|
|
ret
|
|
|
|
|
|
|
|
; Computes the offset into map RAM
|
|
; @param a The map RAM y-coordinate
|
|
; @return hl Pointer into map RAM
|
|
get_row_ptr:
|
|
push de
|
|
ld d, 0
|
|
ld e, a
|
|
REPT 5
|
|
SLA16 de
|
|
ENDR
|
|
ld hl, _SCRN0
|
|
add hl, de
|
|
pop de
|
|
ret
|
|
|
|
|
|
|
|
; Write a row of map data into row buffer
|
|
; @param b Map X coordinate (signed)
|
|
; @param c Map Y coordinate (signed)
|
|
; @param hl Where to write the row in map VRAM
|
|
; @destroy All registers
|
|
enqueue_row_write:
|
|
; PENDING_ROW_PTR = HL
|
|
ld a, l
|
|
ld [PENDING_ROW_PTR], a
|
|
ld a, h
|
|
ld [PENDING_ROW_PTR + 1], a
|
|
|
|
; If Y < 0, write 0s
|
|
bit 7, c
|
|
jr nz, .zero_row
|
|
|
|
; If Y >= MAP_HEIGHT, write 0s
|
|
ld a, [CURRENT_MAP_HEIGHT]
|
|
dec a
|
|
cp c
|
|
jr c, .zero_row
|
|
|
|
; HL = CURRENT_MAP_PTR
|
|
ld a, [CURRENT_MAP_PTR]
|
|
ld l, a
|
|
ld a, [CURRENT_MAP_PTR + 1]
|
|
ld h, a
|
|
|
|
; HL = CURRENT_MAP_PTR + Y * MAP_WIDTH
|
|
ld d, 0
|
|
ld a, [CURRENT_MAP_WIDTH]
|
|
ld e, a
|
|
ld a, c
|
|
|
|
.get_map_row_ptr:
|
|
or a
|
|
jr z, .copy_map_row
|
|
add hl, de
|
|
dec a
|
|
jr .get_map_row_ptr
|
|
|
|
.copy_map_row:
|
|
; C = BYTES_LEFT
|
|
ld c, ROW_BUFFER_SIZE
|
|
ld de, PENDING_ROW_DATA
|
|
|
|
; If X > 0, increment map pointer by X
|
|
bit 7, b
|
|
jr nz, .pad_left
|
|
|
|
ld a, b
|
|
ADD16 hl
|
|
jr .copy_middle
|
|
|
|
.pad_left:
|
|
; Check X < 0
|
|
bit 7, b
|
|
jr z, .copy_middle
|
|
|
|
; Check BYTES_LEFT > 0
|
|
ld a, c
|
|
or a
|
|
ret z
|
|
|
|
; *ROW++ = 0
|
|
ld a, TILE_INDEX_BACKGROUND
|
|
ld [de], a
|
|
inc de
|
|
|
|
; X++, BYTES_LEFT--
|
|
inc b
|
|
dec c
|
|
jr .pad_left
|
|
|
|
.copy_middle:
|
|
; Check X < MAP_WIDTH
|
|
ld a, [CURRENT_MAP_WIDTH]
|
|
dec a
|
|
cp b
|
|
jr c, .pad_right
|
|
|
|
; Check BYTES_LEFT > 0
|
|
ld a, c
|
|
or a
|
|
ret z
|
|
|
|
; *ROW++ = *MAP++
|
|
ld a, [hl+]
|
|
add TILE_INDEX_BACKGROUND
|
|
ld [de], a
|
|
inc de
|
|
|
|
; X++, BYTES_LEFT--
|
|
inc b
|
|
dec c
|
|
jr .copy_middle
|
|
|
|
.pad_right:
|
|
; Check BYTES_LEFT > 0
|
|
ld a, c
|
|
or a
|
|
ret z
|
|
|
|
; *ROW++ = 0
|
|
ld a, TILE_INDEX_BACKGROUND
|
|
ld [de], a
|
|
inc de
|
|
|
|
; X++, BYTES_LEFT--
|
|
inc b
|
|
dec c
|
|
jr .pad_right
|
|
|
|
.zero_row:
|
|
ld hl, PENDING_ROW_DATA
|
|
xor a
|
|
ld c, ROW_BUFFER_SIZE
|
|
.zero_row_loop:
|
|
ld [hl+], a
|
|
dec c
|
|
jr nz, .zero_row_loop
|
|
ret
|
|
|
|
|
|
|
|
; NOTE: This works by enqueueing a row to write, and then immediately flushing
|
|
; the queue. The subroutine could be sped up by writing to map RAM directly, but
|
|
; this is simpler to write and saves on code size.
|
|
;
|
|
; Write a row of map data into map RAM.
|
|
; @param b Map X coordinate (signed)
|
|
; @param c Map Y coordinate (signed)
|
|
; @param hl Pointer into map VRAM
|
|
write_map_row:
|
|
push bc
|
|
push de
|
|
push hl
|
|
|
|
call init_row_write
|
|
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
|
|
ret
|
|
|
|
|
|
|
|
; Write a column of map data into column buffer
|
|
; @param b Map X coordinate (signed)
|
|
; @param c Map Y coordinate (signed)
|
|
; @param hl Where to write the column in map VRAM
|
|
; @destroy All registers
|
|
enqueue_col_write:
|
|
; PENDING_COL_PTR = HL
|
|
ld a, l
|
|
ld [PENDING_COL_PTR], a
|
|
ld a, h
|
|
ld [PENDING_COL_PTR + 1], a
|
|
|
|
; If X < 0, write 0s
|
|
bit 7, b
|
|
jr nz, .zero_row
|
|
|
|
; If X >= MAP_WIDTH, write 0s
|
|
ld a, [CURRENT_MAP_WIDTH]
|
|
dec a
|
|
cp b
|
|
jr c, .zero_row
|
|
|
|
; HL = CURRENT_MAP_PTR + X
|
|
ld a, [CURRENT_MAP_PTR]
|
|
ld l, a
|
|
ld a, [CURRENT_MAP_PTR + 1]
|
|
ld h, a
|
|
ld a, b
|
|
ADD16 hl
|
|
|
|
; B = BYTES_LEFT
|
|
ld b, COL_BUFFER_SIZE
|
|
ld de, PENDING_COL_DATA
|
|
|
|
.pad_left:
|
|
; Check Y < 0
|
|
bit 7, c
|
|
jr z, .adjust_hl
|
|
|
|
; Check BYTES_LEFT > 0
|
|
ld a, b
|
|
or a
|
|
ret z
|
|
|
|
; *ROW++ = 0
|
|
ld a, TILE_INDEX_BACKGROUND
|
|
ld [de], a
|
|
inc de
|
|
|
|
; Y++, BYTES_LEFT--
|
|
inc c
|
|
dec b
|
|
jr .pad_left
|
|
|
|
.adjust_hl:
|
|
push de
|
|
|
|
; HL += Y * MAP_WIDTH
|
|
ld d, 0
|
|
ld a, [CURRENT_MAP_WIDTH]
|
|
ld e, a
|
|
ld a, c
|
|
|
|
.get_map_col_ptr:
|
|
or a
|
|
jr z, .done_get_col_map_ptr
|
|
add hl, de
|
|
dec a
|
|
jr .get_map_col_ptr
|
|
|
|
.done_get_col_map_ptr:
|
|
pop de
|
|
|
|
.copy_middle:
|
|
; Check Y < MAP_HEIGHT
|
|
ld a, [CURRENT_MAP_HEIGHT]
|
|
dec a
|
|
cp c
|
|
jr c, .pad_right
|
|
|
|
; Check BYTES_LEFT > 0
|
|
ld a, b
|
|
or a
|
|
ret z
|
|
|
|
; *ROW++ = *MAP
|
|
ld a, [hl]
|
|
add TILE_INDEX_BACKGROUND
|
|
ld [de], a
|
|
inc de
|
|
|
|
; MAP += MAP_WIDTH
|
|
ld a, [CURRENT_MAP_WIDTH]
|
|
ADD16 hl
|
|
|
|
; Y++, BYTES_LEFT--
|
|
inc c
|
|
dec b
|
|
jr .copy_middle
|
|
|
|
.pad_right:
|
|
; Check BYTES_LEFT > 0
|
|
ld a, b
|
|
or a
|
|
ret z
|
|
|
|
; *ROW++ = 0
|
|
ld a, TILE_INDEX_BACKGROUND
|
|
ld [de], a
|
|
inc de
|
|
|
|
; X++, BYTES_LEFT--
|
|
inc c
|
|
dec b
|
|
jr .pad_right
|
|
|
|
.zero_row:
|
|
ld hl, PENDING_COL_DATA
|
|
xor a
|
|
ld c, COL_BUFFER_SIZE
|
|
.zero_row_loop:
|
|
ld [hl+], a
|
|
dec c
|
|
jr nz, .zero_row_loop
|
|
ret
|
|
|
|
|
|
|
|
; Basically enqueue_col_write but for entire row, used during map load
|
|
; TODO: Deduplicate
|
|
; @param b Map X coordinate (signed)
|
|
; @param c Map Y coordinate (signed)
|
|
; @param hl Where to write the column in map VRAM
|
|
; @destroy All registers
|
|
init_row_write:
|
|
; If Y < 0, write 0s
|
|
bit 7, c
|
|
jr nz, .zero_row
|
|
|
|
; If Y >= MAP_HEIGHT, write 0s
|
|
ld a, [CURRENT_MAP_HEIGHT]
|
|
dec a
|
|
cp c
|
|
jr c, .zero_row
|
|
|
|
; DE = HL
|
|
ld d, h
|
|
ld e, l
|
|
|
|
; HL = CURRENT_MAP_PTR
|
|
ld a, [CURRENT_MAP_PTR]
|
|
ld l, a
|
|
ld a, [CURRENT_MAP_PTR + 1]
|
|
ld h, a
|
|
|
|
push de
|
|
|
|
; HL = CURRENT_MAP_PTR + Y * MAP_WIDTH
|
|
ld d, 0
|
|
ld a, [CURRENT_MAP_WIDTH]
|
|
ld e, a
|
|
ld a, c
|
|
|
|
.get_map_row_ptr:
|
|
or a
|
|
jr z, .copy_map_row
|
|
add hl, de
|
|
dec a
|
|
jr .get_map_row_ptr
|
|
|
|
.copy_map_row:
|
|
pop de
|
|
|
|
; C = BYTES_LEFT
|
|
ld c, SCRN_VX_B
|
|
|
|
; If X > 0, increment map pointer by X
|
|
; TODO: Remove this branch by adding X before copy_middle
|
|
bit 7, b
|
|
jr nz, .pad_left
|
|
|
|
ld a, b
|
|
ADD16 hl
|
|
jr .copy_middle
|
|
|
|
.pad_left:
|
|
; Check X < 0
|
|
bit 7, b
|
|
jr z, .copy_middle
|
|
|
|
; Check BYTES_LEFT > 0
|
|
ld a, c
|
|
or a
|
|
ret z
|
|
|
|
; *ROW++ = 0
|
|
ld a, TILE_INDEX_BACKGROUND
|
|
ld [de], a
|
|
inc de
|
|
|
|
; X++, BYTES_LEFT--
|
|
inc b
|
|
dec c
|
|
jr .pad_left
|
|
|
|
.copy_middle:
|
|
; Check X < MAP_WIDTH
|
|
ld a, [CURRENT_MAP_WIDTH]
|
|
dec a
|
|
cp b
|
|
jr c, .pad_right
|
|
|
|
; Check BYTES_LEFT > 0
|
|
ld a, c
|
|
or a
|
|
ret z
|
|
|
|
; *ROW++ = *MAP++
|
|
ld a, [hl+]
|
|
add TILE_INDEX_BACKGROUND
|
|
ld [de], a
|
|
inc de
|
|
|
|
; X++, BYTES_LEFT--
|
|
inc b
|
|
dec c
|
|
jr .copy_middle
|
|
|
|
.pad_right:
|
|
; Check BYTES_LEFT > 0
|
|
ld a, c
|
|
or a
|
|
ret z
|
|
|
|
; *ROW++ = 0
|
|
ld a, TILE_INDEX_BACKGROUND
|
|
ld [de], a
|
|
inc de
|
|
|
|
; X++, BYTES_LEFT--
|
|
inc b
|
|
dec c
|
|
jr .pad_right
|
|
|
|
.zero_row:
|
|
xor a
|
|
ld c, SCRN_VX_B
|
|
.zero_row_loop:
|
|
ld [hl+], a
|
|
dec c
|
|
jr nz, .zero_row_loop
|
|
ret
|