INCLUDE "hardware.inc" INCLUDE "util.inc" SECTION "Map Data", WRAM0 PAGEX:: DB PAGEY:: 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 ; TODO: Don't hardcode DEF CAMERAX EQU 0 DEF CAMERAY EQU 14 ; 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 a, INIT_SCY ld [rSCY], a xor a 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 ; 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 ; sp + 7 push de ; sp + 5 push hl ; sp + 3 ; 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 hl pop de pop bc ret .begin_writing: ; 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