Browse Source

Deduplicate code to write map rows

master
Forest Belton 2 years ago
parent
commit
cf038bd0dd
1 changed files with 16 additions and 168 deletions
  1. +16
    -168
      src/map.s

+ 16
- 168
src/map.s View File

@ -30,35 +30,6 @@ SECTION "Map Code", ROM0
DEF INIT_SCX EQUS "((SCRN_VX - SCRN_X) / 2)"
DEF INIT_SCY EQUS "((SCRN_VY - SCRN_Y) / 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
; if carry, 14 * 4 = 56 cycles
; otherwise, 8 * 4 = 32 cycles
MACRO INC_STACK16
ld hl, sp + \1 ; 3
inc [hl] ; 3
jr nz, .no_carry\@ ; 3/2
inc hl ; 2
inc [hl] ; 3
.no_carry\@:
ENDM
; 11 * 4 = 44 cycles
MACRO ZERO_ROW_TILE
ld hl, sp + STACK_OFFSET_ROW ; 3
ld a, [hl+] ; 2
ld e, a ; 1
ld d, [hl] ; 2
xor a ; 1
ld [de], a ; 2
ENDM
; Loads a map
; @param hl Pointer to map metadata
Map_Load::
@ -108,6 +79,10 @@ Map_Load::
.write_rows:
call write_map_row
inc c
ld a, SCRN_VX_B
ADD16 hl
dec d
jr nz, .write_rows
@ -369,157 +344,30 @@ enqueue_row_write:
jr nz, .zero_row_loop
ret
; TODO: Deduplicate with enqueue_row_write? This version is needed when
; loading a map, which happens synchronously while LCD is disabled. One trick to
; achieve this would be to call enqueue_row_write then Map_Update
; 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
; 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
; 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 [hl+], a
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_WIDTH
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_WIDTH]
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
call enqueue_row_write
; row++
INC_STACK16 STACK_OFFSET_ROW
ld a, [PENDING_ROW_PTR]
ld c, a
ld a, [PENDING_ROW_PTR + 1]
ld b, a
; [SP]--
.pad_right_inc:
ld hl, sp + STACK_OFFSET_ROW
dec [hl]
jr .pad_right
ld hl, PENDING_ROW_DATA
ld d, SCRN_VX_B
MEMCPY bc, hl, d
.done:
add sp, 3
pop hl
pop de
pop bc

Loading…
Cancel
Save