From 9a8394122f573370c058a2d62ea6127faa00cd7e Mon Sep 17 00:00:00 2001 From: Forest Belton <65484+forestbelton@users.noreply.github.com> Date: Fri, 16 Jul 2021 00:11:34 -0400 Subject: [PATCH] Begin simplifying map API --- inc/dir.inc | 10 --- src/main.s | 136 +++----------------------------- src/map.s | 222 +++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 195 insertions(+), 173 deletions(-) delete mode 100644 inc/dir.inc diff --git a/inc/dir.inc b/inc/dir.inc deleted file mode 100644 index de6c65f..0000000 --- a/inc/dir.inc +++ /dev/null @@ -1,10 +0,0 @@ -DEF DIRF_UP EQU (1 << 0) -DEF DIRF_RIGHT EQU (1 << 1) -DEF DIRF_DOWN EQU (1 << 2) -DEF DIRF_LEFT EQU (1 << 3) - -RSRESET -DEF DIRB_UP RB 1 -DEF DIRB_RIGHT RB 1 -DEF DIRB_DOWN RB 1 -DEF DIRB_LEFT RB 1 diff --git a/src/main.s b/src/main.s index 3120b89..e311841 100644 --- a/src/main.s +++ b/src/main.s @@ -1,4 +1,3 @@ -INCLUDE "dir.inc" INCLUDE "hardware.inc" INCLUDE "util.inc" @@ -57,13 +56,6 @@ start: call Keys_Update - ; Clear pending map state - xor a - ld [PENDING_ROW_PTR], a - ld [PENDING_ROW_PTR + 1], a - ld [PENDING_COL_PTR], a - ld [PENDING_COL_PTR + 1], a - call scroll_update ; wait for vblank @@ -77,42 +69,15 @@ start: jp .loop -; TODO: remove once scrolling is implemented +; TODO: Move into player movement routine scroll_update: ; scroll map with arrow keys ld a, [keys] and PADF_UP jr z, .down - ; don't scroll up if on last tile - ld hl, rSCY - ld a, [hl] - and %111 - jr nz, .update_up - - ld hl, CURRENT_CAMERA_Y - ld a, [hl] - or a - ret z - -.update_up: - ld hl, rSCY - dec [hl] - - ld a, DIRB_UP - ld [SCROLL_DIR], a - - ld a, [hl] - and %111 - cp %111 - jr nz, .update_up_map - - ld a, [CURRENT_CAMERA_Y] - dec a - ld [CURRENT_CAMERA_Y], a - -.update_up_map: - call Map_Scroll + ld d, 1 + call Map_ScrollUp ret .down: @@ -120,35 +85,8 @@ scroll_update: and PADF_DOWN jr z, .right - ; don't scroll down if on last tile - ld a, [rSCY] - and %111 - jr nz, .update_down - - ld a, [CURRENT_MAP_HEIGHT] - ld b, a - ld a, [CURRENT_CAMERA_Y] - add 18 - cp b - ret z - -.update_down: - ld hl, rSCY - inc [hl] - - ld a, DIRB_DOWN - ld [SCROLL_DIR], a - - ld a, [hl] - and %111 - jr nz, .update_down_map - - ld a, [CURRENT_CAMERA_Y] - inc a - ld [CURRENT_CAMERA_Y], a - -.update_down_map: - call Map_Scroll + ld d, 1 + call Map_ScrollDown ret .right: @@ -156,36 +94,8 @@ scroll_update: and PADF_RIGHT jr z, .left - ; don't scroll right if on last tile - ld hl, rSCX - ld a, [hl] - and %111 - jr nz, .update_right - - ld a, [CURRENT_MAP_WIDTH] - ld b, a - ld a, [CURRENT_CAMERA_X] - add SCRN_X_B - cp b - ret z - -.update_right: - ld hl, rSCX - inc [hl] - - ld a, DIRB_RIGHT - ld [SCROLL_DIR], a - - ld a, [hl] - and %111 - jr nz, .update_right_map - - ld a, [CURRENT_CAMERA_X] - inc a - ld [CURRENT_CAMERA_X], a - -.update_right_map: - call Map_Scroll + ld d, 1 + call Map_ScrollRight ret .left: @@ -193,33 +103,5 @@ scroll_update: and PADF_LEFT ret z - ; don't scroll left if on last tile - ld hl, rSCX - ld a, [hl] - and %111 - jr nz, .update_left - - ld hl, CURRENT_CAMERA_X - ld a, [hl] - or a - ret z - -.update_left: - ld hl, rSCX - dec [hl] - - ld a, DIRB_LEFT - ld [SCROLL_DIR], a - - ld a, [hl] - and %111 - cp %111 - jr nz, .update_left_map - - ld a, [CURRENT_CAMERA_X] - dec a - ld [CURRENT_CAMERA_X], a - -.update_left_map: - call Map_Scroll - ret + ld d, 1 + call Map_ScrollLeft diff --git a/src/map.s b/src/map.s index e34d652..4e8da18 100644 --- a/src/map.s +++ b/src/map.s @@ -1,4 +1,3 @@ -INCLUDE "dir.inc" INCLUDE "hardware.inc" INCLUDE "util.inc" @@ -7,8 +6,6 @@ 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 ROW_BUFFER_SIZE ; Row to be written @@ -33,6 +30,8 @@ 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:: @@ -85,27 +84,35 @@ Map_Load:: ret -; Update map state based on SCX/SCY -Map_Scroll:: - ; Check scroll up/down - ld a, [SCROLL_DIR] - and DIRF_UP | DIRF_DOWN - jr nz, .scroll_horiz - ; Check SCY % 8 = 0 + +; Scroll the map upwards +; @param d The amount to scroll by (0 < d < 8) +Map_ScrollUp:: + ; Check whether we crossed tile boundary ld a, [rSCY] and %111 - ret nz + cp d + jr nc, .done + + ; Don't scroll if at top tile + ld a, [CURRENT_CAMERA_Y] + or a + ret z + + ld a, [rSCY] + sub d + ld [rSCY], a + + ; CAMERA_Y -= 1 + dec a + ld [CURRENT_CAMERA_Y], a ; B = CAMERA_X - 2 ld a, [CURRENT_CAMERA_X] sub 2 ld b, a - ld a, [SCROLL_DIR] - cp DIRB_UP - jr nz, .scroll_down - ; C = CAMERA_Y - 2 ld a, [CURRENT_CAMERA_Y] sub 2 @@ -116,9 +123,65 @@ Map_Scroll:: srln a, 3 sub 2 - jr .write_row + jr Map_ScrollRow + +.done: + ld a, [rSCY] + sub d + ld [rSCY], a + ret + + + +Map_ScrollDown:: + ; Don't scroll if at bottom tile + ld a, [CURRENT_CAMERA_Y] + add SCRN_Y_B + ld hl, CURRENT_MAP_HEIGHT + cp [hl] + jr nz, .down + + ld a, [rSCY] + add d + and %111 + ld [rSCY], a + ret + + ; Check whether we crossed tile boundary +.down: + ld a, [rSCY] + and %111 + add d + cp 8 + jr c, .done + + ; TODO: + ; if CAMERA_Y + 18 = MAP_HEIGHT { + ; if SCY % 8 != 0 { + ; SCY += MIN(D, 8 - SCY % 8) + ; } + ; return + ; } + ; if SCY % 8 + D > 8 { + ; SCY += D + ; LOAD_COLUMN(CAMERA_X - 2, CAMERA_Y + 18 + 1); + ; } else { + ; SCY += D + ; } + + ld a, [rSCY] + add d + ld [rSCY], a + + ; CAMERA_Y += 1 + inc a + ld [CURRENT_CAMERA_Y], a + + ; B = CAMERA_X - 2 + ld a, [CURRENT_CAMERA_X] + sub 2 + ld b, a -.scroll_down: ; C = CAMERA_Y + 18 + 1 ld a, [CURRENT_CAMERA_Y] add SCRN_Y_B + 1 @@ -129,7 +192,21 @@ Map_Scroll:: srln a, 3 add SCRN_Y_B + 1 -.write_row: + jr Map_ScrollRow + +.done: + ld a, [rSCY] + add d + ld [rSCY], a + 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 @@ -145,16 +222,21 @@ Map_Scroll:: call enqueue_row_write ret -.scroll_horiz: - ; Check SCX % 8 = 0 +Map_ScrollLeft:: + ; Check whether we crossed tile boundary ld a, [rSCX] and %111 - ret nz + cp d + jr nc, .done - ; C = CAMERA_Y - 2 - ld a, [CURRENT_CAMERA_Y] - sub 2 - ld c, a + ld a, [rSCX] + sub d + ld [rSCX], a + + ; Don't scroll if at left tile + ld a, [CURRENT_CAMERA_X] + or a + ret z ld a, [rSCY] sub 16 @@ -163,42 +245,91 @@ Map_Scroll:: srl a call get_row_ptr - ld a, [SCROLL_DIR] - cp DIRB_LEFT - jr nz, .scroll_right - ; B = CAMERA_X - 2 ld a, [CURRENT_CAMERA_X] sub 2 ld b, a - ; HL = VRAM + (SCX/8 - 2) + ; E = VRAM + (SCX/8 - 2) ld a, [rSCX] srln a, 3 sub 2 - jr .write_col + jr Map_ScrollColumn + +.done: + ld a, [rSCX] + sub d + ld [rSCX], a + ret + + + +Map_ScrollRight:: + ; Check whether we crossed tile boundary + ld a, [rSCX] + and %111 + add d + cp 8 + jr nc, .done + + ld a, [rSCX] + add d + ld [rSCX], a + + ; Don't scroll if at bottom tile + ld a, [CURRENT_CAMERA_X] + inc a + ld hl, CURRENT_MAP_WIDTH + cp [hl] + ret z + + ; CAMERA_X += 1 + inc a + ld [CURRENT_CAMERA_X], a + + ld a, [rSCY] + sub 16 + srl a + srl a + srl a + call get_row_ptr -.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 + ; E = VRAM + SCX/8 + SCRN_X_B + 1 ld a, [rSCX] srl a srl a srl a add SCRN_X_B + 1 + ld e, a -.write_col: - and %11111 - ADD16 hl + jr Map_ScrollColumn + +.done: + ld a, [rSCX] + add d + ld [rSCX], a + 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] @@ -232,6 +363,11 @@ Map_Update:: 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] @@ -259,8 +395,15 @@ Map_Update:: 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 @@ -276,6 +419,8 @@ get_row_ptr: pop de ret + + ; Write a row of map data into row buffer ; @param b Map X coordinate (signed) ; @param c Map Y coordinate (signed) @@ -398,6 +543,8 @@ enqueue_row_write: 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. @@ -419,6 +566,8 @@ write_map_row: ret + + ; Write a column of map data into column buffer ; @param b Map X coordinate (signed) ; @param c Map Y coordinate (signed) @@ -545,6 +694,7 @@ enqueue_col_write: ret + ; Basically enqueue_col_write but for entire row, used during map load ; TODO: Deduplicate ; @param b Map X coordinate (signed)