From 7be733e72a803ef9e62305bcd8f90730c15e36cf Mon Sep 17 00:00:00 2001 From: Forest Belton Date: Wed, 29 Sep 2021 18:27:06 -0400 Subject: [PATCH] Finish initial pass of map loading --- gbsdk/rules.mk | 2 +- scripts/generate_map.py | 6 ++--- src/game.h | 5 ++++ src/level.c | 9 ++++--- src/map.c | 55 ++++++++++++++++++++++++++++++++--------- src/map.h | 2 +- src/title.c | 5 ---- src/vram.c | 30 +++++++++++++++++++++- src/vram.h | 8 ++++-- 9 files changed, 93 insertions(+), 29 deletions(-) diff --git a/gbsdk/rules.mk b/gbsdk/rules.mk index edbc4e0..a04ec36 100644 --- a/gbsdk/rules.mk +++ b/gbsdk/rules.mk @@ -126,7 +126,7 @@ $(BUILD)/%.asm.o: %.asm $(BUILD)/%.asm.d # Rule to build the final rom $(PROJECT_NAME).$(ROM_EXTENSION) $(PROJECT_NAME).map $(PROJECT_NAME).sym: $(OBJS) @echo Linking $@ - rgblink $(LDFLAGS) $^ -o $@ -m $(basename $@).map -n $(basename $@).sym + $(Q)rgblink $(LDFLAGS) $^ -o $@ -m $(basename $@).map -n $(basename $@).sym $(Q)rgbfix $(FIXFLAGS) $@ @python3 $(TOOLS)/romspace.py $(basename $@).map diff --git a/scripts/generate_map.py b/scripts/generate_map.py index 242eed2..6bfa9f9 100644 --- a/scripts/generate_map.py +++ b/scripts/generate_map.py @@ -107,9 +107,9 @@ def generate_map(pngfile: str, compress: bool = False) -> None: "rgbgfx", "-u", "-t", - tilepath, - "-o", mappath, + "-o", + tilepath, pngfile, ] ) @@ -150,7 +150,7 @@ MAP_ASSET({section}_collision, "{section}.collision"); extern const map_t map_{section} = {{ (uint16_t)&{section}_tiles[0], - {tiles_size} / 16, + {tiles_size}, (uint16_t)&{section}_map[0], (uint16_t)&{section}_collision[0], {width}, diff --git a/src/game.h b/src/game.h index 137d931..1e5d721 100644 --- a/src/game.h +++ b/src/game.h @@ -1,6 +1,8 @@ #ifndef IS_GAME_H_ #define IS_GAME_H_ +#include "sdk/video.h" + #define _VRAM 0x8000 #define _VRAM8000 _VRAM #define _VRAM8800 (_VRAM + 0x800) @@ -69,4 +71,7 @@ void interrupts_enable(void) __preserves_regs(a, b, c, d, e, h, l); */ void interrupts_disable(void) __preserves_regs(a, b, c, d, e, h, l); +#define lcd_disable() lcd_off() +#define lcd_enable() rLCDC = LCDC_ON | LCDC_OBJON | LCDC_BGON | LCDC_BG8000 + #endif diff --git a/src/level.c b/src/level.c index 4e47901..a3cfa08 100644 --- a/src/level.c +++ b/src/level.c @@ -4,18 +4,19 @@ #include "sdk/hardware.h" #include "sdk/joypad.h" #include "sdk/video.h" +#include "vram.h" void level(void) { - lcd_off(); - + lcd_disable(); map_load(&map_intro); - - rLCDC |= LCDC_ON; + lcd_enable(); while (1) { joypad_update(); HALT(); rIF = 0; + + vram_update(); } } diff --git a/src/map.c b/src/map.c index 9a9fd98..90185b8 100644 --- a/src/map.c +++ b/src/map.c @@ -11,10 +11,13 @@ map_t MAP; -uint8_t pending_row[SCRN_VX_B]; +#define ROW_BUFFER_SIZE (SCRN_X_B + 4) +#define COL_BUFFER_SIZE (SCRN_Y_B + 4) + +uint8_t pending_row[ROW_BUFFER_SIZE]; uint16_t pending_row_dest; -uint8_t pending_col[SCRN_VY_B]; +uint8_t pending_col[COL_BUFFER_SIZE]; uint16_t pending_col_dest; static void map_write_row(uint16_t map_ptr, int8_t x0, int8_t y0); @@ -30,10 +33,10 @@ void map_load(map_t *map) { // TODO: Update player state memcpy(VRAM_TILE_PTR(TILE_INDEX_BACKGROUND), (uint8_t *)MAP.tile_ptr, - MAP.tile_count); + MAP.tile_size); - int8_t x0 = MAP.camera_x - INIT_SCX; - int8_t y0 = MAP.camera_y - INIT_SCY; + int8_t x0 = MAP.camera_x - INIT_SCX / 8; + int8_t y0 = MAP.camera_y - INIT_SCY / 8; uint16_t map_ptr = _SCRN0; for (uint8_t i = 0; i < SCRN_VY_B; ++i) { @@ -41,11 +44,14 @@ void map_load(map_t *map) { map_ptr += SCRN_VX_B; y0++; } + + pending_row_dest = 0; + pending_col_dest = 0; } void map_update(void) { if (pending_row_dest != 0) { - vram_enqueue_mem_xfer((uint8_t *)pending_row_dest, &pending_row[0], + vram_enqueue_mem_xfer(XFER_TYPE_ROW, pending_row_dest, &pending_row[0], sizeof pending_row); pending_row_dest = 0; } @@ -61,8 +67,8 @@ void map_update(void) { static void map_enqueue_row(uint16_t vram_ptr, int8_t x0, int8_t y0) { pending_row_dest = vram_ptr; - if (y0 < 0 || y0 > MAP.map_height) { - memset(&pending_row[0], 0, sizeof pending_row); + if (y0 < 0 || y0 >= MAP.map_height) { + memset(&pending_row[0], TILE_INDEX_BACKGROUND, sizeof pending_row); return; } @@ -72,11 +78,13 @@ static void map_enqueue_row(uint16_t vram_ptr, int8_t x0, int8_t y0) { while (left > 0 && x0 < 0) { *row++ = TILE_INDEX_BACKGROUND; + x0++; left--; } while (left > 0 && x0 < MAP.map_height) { - *row++ = *map_ptr++; + *row++ = TILE_INDEX_BACKGROUND + *map_ptr++; + x0++; left--; } @@ -87,9 +95,32 @@ static void map_enqueue_row(uint16_t vram_ptr, int8_t x0, int8_t y0) { } static void map_write_row(uint16_t vram_ptr, int8_t x0, int8_t y0) { - map_enqueue_row(vram_ptr, x0, y0); - memcpy((uint8_t *)pending_row_dest, &pending_row[0], sizeof pending_row); - pending_row_dest = 0; + uint8_t *row = (uint8_t *)vram_ptr; + + if (y0 < 0 || y0 >= MAP.map_height) { + memset(row, TILE_INDEX_BACKGROUND, SCRN_VX_B); + return; + } + + uint8_t *map_ptr = (uint8_t *)(MAP.map_ptr + y0 * MAP.map_width); + uint8_t left = SCRN_VX_B; + + while (left > 0 && x0 < 0) { + *row++ = TILE_INDEX_BACKGROUND; + x0++; + left--; + } + + while (left > 0 && x0 < MAP.map_height) { + *row++ = TILE_INDEX_BACKGROUND + *map_ptr++; + x0++; + left--; + } + + while (left > 0) { + *row++ = TILE_INDEX_BACKGROUND; + left--; + } } static void map_write_col(uint16_t map_ptr, int8_t x0, int8_t y0) {} diff --git a/src/map.h b/src/map.h index 5314d96..7cd1f03 100644 --- a/src/map.h +++ b/src/map.h @@ -7,7 +7,7 @@ typedef struct { uint16_t tile_ptr; - uint8_t tile_count; + uint16_t tile_size; uint16_t map_ptr; uint16_t collision_ptr; int8_t map_width; diff --git a/src/title.c b/src/title.c index be6e638..45b15db 100644 --- a/src/title.c +++ b/src/title.c @@ -6,7 +6,6 @@ #include "sdk/joypad.h" #include "sdk/oam.h" #include "sdk/video.h" -#include "vram.h" ASSET(bg_tiles, "bg/title.2bpp"); ASSET(bg_map, "bg/title.map"); @@ -28,8 +27,6 @@ void title(void) { } rLCDC |= LCDC_ON; - interrupts_enable(); - while (1) { joypad_update(); if (joypad_state & PAD_START) { @@ -40,7 +37,5 @@ void title(void) { // Wait for VBLANK. Clear IF since global interrupts are disabled. HALT(); rIF = 0; - - vram_update(); } } diff --git a/src/vram.c b/src/vram.c index 5e93fb0..2fed6a3 100644 --- a/src/vram.c +++ b/src/vram.c @@ -2,6 +2,7 @@ #include +#include "game.h" #include "sdk/video.h" mem_xfer_t mem_xfer_queue[MAX_XFERS]; @@ -9,10 +10,37 @@ uint8_t mem_xfer_queue_size; void vram_init(void) { mem_xfer_queue_size = 0; } +static inline void vram_xfer_row(uint8_t *dest, const uint8_t *source, + uint8_t size) { + while (size > 0) { + *dest++ = *source++; + if ((uint8_t)dest % 32 == 0) { + dest -= 32; + } + size--; + } +} + +static inline void vram_xfer_col(uint8_t *dest, const uint8_t *source, + uint8_t size) { + while (size > 0) { + *dest = *source++; + dest += SCRN_VX_B; + if ((uint16_t)dest >= _SCRN1) { + dest -= _SCRN1 - _SCRN0; + } + size--; + } +} + void vram_update(void) { mem_xfer_t *xfer = &mem_xfer_queue[0]; for (uint8_t i = 0; i < mem_xfer_queue_size; i++) { - vram_memcpy((uint16_t)xfer->dest, (void *)xfer->source, xfer->size); + if (xfer->type == XFER_TYPE_ROW) { + vram_xfer_row((uint8_t *)xfer->dest, xfer->source, xfer->size); + } else { + vram_xfer_col((uint8_t *)xfer->dest, xfer->source, xfer->size); + } xfer++; } mem_xfer_queue_size = 0; diff --git a/src/vram.h b/src/vram.h index 59fa840..58170b4 100644 --- a/src/vram.h +++ b/src/vram.h @@ -5,8 +5,11 @@ #define MAX_XFERS 5 +typedef enum { XFER_TYPE_ROW, XFER_TYPE_COL } MEM_XFER_TYPE; + typedef struct { - uint8_t *dest; + uint8_t type; + uint16_t dest; const uint8_t *source; uint8_t size; } mem_xfer_t; @@ -24,9 +27,10 @@ void vram_init(void); */ void vram_update(void); -#define vram_enqueue_mem_xfer(_dest, _source, _size) \ +#define vram_enqueue_mem_xfer(_type, _dest, _source, _size) \ do { \ mem_xfer_t *node = &mem_xfer_queue[mem_xfer_queue_size++]; \ + node->type = (_type); \ node->dest = (_dest); \ node->source = (_source); \ node->size = (_size); \