diff --git a/src/map.s b/src/map.s index 6c75fb4..e34d652 100644 --- a/src/map.s +++ b/src/map.s @@ -4,13 +4,16 @@ 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" + SCROLL_DIR:: DB PENDING_ROW_PTR:: DW ; Where to write pending row data (0 = no write) -PENDING_ROW_DATA:: DS SCRN_VX_B ; Row to be written +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 SCRN_VY_B ; Column to be written +PENDING_COL_DATA: DS COL_BUFFER_SIZE ; Column to be written CURRENT_DATA_START:: CURRENT_TILE_PTR:: DW ; Location of tile data @@ -82,77 +85,6 @@ Map_Load:: ret -; Loads the map X-coordinate into B -MACRO LOAD_MAPX - ; if SCX <= 0x7f - ; ld a, [rSCX] - ; cp $80 - ; jr nc, .wrap\@ - - ; B = CAMERA_X - SCX/8 - ld a, [rSCX] - ld b, a - ld a, [CURRENT_CAMERA_X] - srln b, 3 - sub b - ld b, a - ; jr .done\@ - - ; else SCX > 0x7f -; .wrap\@: -; ; B = CAMERA_X - PAGE_X/8 -; ld a, [PAGEX] -; ld b, a -; ld a, [CURRENT_CAMERA_X] -; srln b, 3 -; sub b -; ld b, a - -; ; HL += PAGE_X/8 -; ld a, [PAGEX] -; srln a, 3 -; ADD16 hl - -; .done\@: -ENDM - -; Loads the map Y-coordinate into C -MACRO LOAD_MAPY - ; if SCY <= 0x7f - ; ld a, [rSCY] - ; cp $80 - ; jr nc, .wrap\@ - - ; C = CAMERA_Y - SCY/8 - ld a, [rSCY] - ld c, a - ld a, [CURRENT_CAMERA_Y] - srln c, 3 - sub c - ld c, a -; jr .done\@ - -; ; else SCY > 0x7f -; .wrap\@: -; ; C = CAMERA_Y - SCY/8 -; ld a, [PAGEY] -; ld c, a -; ld a, [CURRENT_CAMERA_Y] -; srln c, 3 -; sub c -; ld c, a - -; ; HL += 32 * PAGE_Y/8 -; ld d, 0 -; ld a, [PAGEY] -; ld e, a -; REPT 5 -; SLA16 de -; ENDR -; add hl, de -; .done\@: -ENDM - ; Update map state based on SCX/SCY Map_Scroll:: ; Check scroll up/down @@ -165,7 +97,10 @@ Map_Scroll:: and %111 ret nz - LOAD_MAPX + ; B = CAMERA_X - 2 + ld a, [CURRENT_CAMERA_X] + sub 2 + ld b, a ld a, [SCROLL_DIR] cp DIRB_UP @@ -176,12 +111,10 @@ Map_Scroll:: sub 2 ld c, a - ; HL = _SCRN0 + 32 * ((SCX/8 - 2) % 32) - ld a, [rSCX] + ; MAP Y = SCY/8 - 2 + ld a, [rSCY] srln a, 3 sub 2 - and %11111 - call get_row_ptr jr .write_row @@ -191,13 +124,24 @@ Map_Scroll:: add SCRN_Y_B + 1 ld c, a - ; HL = _SCRN0 + 32 * (SCY/8 + SCRN_Y_B + 1) + ; MAP Y = SCY/8 + SCRN_Y_B + 1 ld a, [rSCY] srln a, 3 add SCRN_Y_B + 1 - call get_row_ptr .write_row: + 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 @@ -207,43 +151,51 @@ Map_Scroll:: and %111 ret nz - LOAD_MAPY + ; C = CAMERA_Y - 2 + ld a, [CURRENT_CAMERA_Y] + sub 2 + ld c, a + + ld a, [rSCY] + sub 16 + srl a + srl a + srl a + call get_row_ptr ld a, [SCROLL_DIR] cp DIRB_LEFT jr nz, .scroll_right - ; HL = VRAM + (SCX/8 - 2) % 32 - ld hl, _SCRN0 - ld a, [rSCX] - srln a, 3 - sub 2 - and %11111 - ADD16 hl - ; B = CAMERA_X - 2 ld a, [CURRENT_CAMERA_X] sub 2 ld b, a + ; HL = VRAM + (SCX/8 - 2) + ld a, [rSCX] + srln a, 3 + sub 2 + jr .write_col .scroll_right: + ; B = CAMERA_X + 20 + 1 + ld a, [CURRENT_CAMERA_X] + add SCRN_X_B + 1 + ld b, a + ; HL = VRAM + SCX/8 + SCRN_X_B + 1 - ld hl, _SCRN0 ld a, [rSCX] srl a srl a srl a add SCRN_X_B + 1 - ADD16 hl - - ; B = CAMERA_X + 20 + 1 - ld a, [CURRENT_CAMERA_X] - add SCRN_X_B + 1 - ld b, a .write_col: + and %11111 + ADD16 hl + call enqueue_col_write ret @@ -257,7 +209,7 @@ Map_Update:: jr z, .update_col ld hl, PENDING_ROW_DATA - ld d, SCRN_VX_B + ld d, ROW_BUFFER_SIZE .copy_row: ld a, [hl+] ld [bc], a @@ -289,7 +241,7 @@ Map_Update:: or c ret z - ld d, SCRN_VY_B + ld d, COL_BUFFER_SIZE ld hl, PENDING_COL_DATA .update_col_loop: ld a, [hl+] @@ -367,7 +319,7 @@ enqueue_row_write: .copy_map_row: ; C = BYTES_LEFT - ld c, SCRN_VX_B + ld c, ROW_BUFFER_SIZE ld de, PENDING_ROW_DATA ; If X > 0, increment map pointer by X @@ -378,15 +330,18 @@ enqueue_row_write: ADD16 hl jr .copy_middle - ; Note: Can skip checking BYTES_LEFT > 0 in this loop. If there were - ; SCRN_VX_B zeros to write, then Y would be 1 greater and we would have - ; jumped into .zero_row before reaching this code .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 + xor a ld [de], a inc de @@ -436,7 +391,7 @@ enqueue_row_write: .zero_row: ld hl, PENDING_ROW_DATA xor a - ld c, SCRN_VX_B + ld c, ROW_BUFFER_SIZE .zero_row_loop: ld [hl+], a dec c @@ -456,17 +411,7 @@ write_map_row: push de push hl - call enqueue_row_write - - ld a, [PENDING_ROW_PTR] - ld c, a - ld a, [PENDING_ROW_PTR + 1] - ld b, a - - ; TODO: Fix - ld hl, PENDING_ROW_DATA - ld d, SCRN_VX_B - MEMCPY bc, hl, d + call init_row_write pop hl pop de @@ -493,43 +438,30 @@ enqueue_col_write: ; If X >= MAP_WIDTH, write 0s ld a, [CURRENT_MAP_WIDTH] dec a - cp c + cp b jr c, .zero_row - ; HL = CURRENT_MAP_PTR + ; HL = CURRENT_MAP_PTR + X ld a, [CURRENT_MAP_PTR] ld l, a ld a, [CURRENT_MAP_PTR + 1] ld h, a - - ; HL = CURRENT_MAP_PTR + Y * MAP_WIDTH + X - ld d, 0 - ld a, [CURRENT_MAP_WIDTH] - ld e, a - ld a, c - -.get_map_col_ptr: - or a - jr z, .copy_map_column - add hl, de - dec a - jr .get_map_col_ptr - -.copy_map_column: ld a, b ADD16 hl ; B = BYTES_LEFT - ld b, SCRN_VY_B + ld b, COL_BUFFER_SIZE ld de, PENDING_COL_DATA - ; Note: Can skip checking BYTES_LEFT > 0 in this loop. If there were - ; SCRN_VY_B zeros to write, then X would be 1 greater and we would have - ; jumped into .zero_row before reaching this code .pad_left: ; Check Y < 0 bit 7, c - jr z, .copy_middle + jr z, .adjust_hl + + ; Check BYTES_LEFT > 0 + ld a, b + or a + ret z ; *ROW++ = 0 xor a @@ -541,6 +473,25 @@ enqueue_col_write: 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] @@ -586,43 +537,133 @@ enqueue_col_write: .zero_row: ld hl, PENDING_COL_DATA xor a - ld c, SCRN_VY_B + ld c, COL_BUFFER_SIZE .zero_row_loop: ld [hl+], a dec c jr nz, .zero_row_loop ret -; Compute the distance (modulo 32) between two values -; @param b Value 1 -; @param c Value 2 -mmd2: - push bc - ld a, b - sub c +; 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 - cpl - ld b, a - cpl + ; 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 z, .0 + jr nz, .pad_left - ld b, a + 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 -.0: - ld a, 32 - sub b + ; *ROW++ = 0 + 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 nc, .1 + jr c, .pad_right - pop bc - ret + ; Check BYTES_LEFT > 0 + ld a, c + or a + ret z -.1: - ld a, b + ; *ROW++ = *MAP++ + ld a, [hl+] + ld [de], a + inc de - pop bc - ret + ; 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 + xor a + 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 \ No newline at end of file