Browse Source

Finish initial pass of map loading

master
Forest Belton 2 years ago
parent
commit
7be733e72a
9 changed files with 93 additions and 29 deletions
  1. +1
    -1
      gbsdk/rules.mk
  2. +3
    -3
      scripts/generate_map.py
  3. +5
    -0
      src/game.h
  4. +5
    -4
      src/level.c
  5. +43
    -12
      src/map.c
  6. +1
    -1
      src/map.h
  7. +0
    -5
      src/title.c
  8. +29
    -1
      src/vram.c
  9. +6
    -2
      src/vram.h

+ 1
- 1
gbsdk/rules.mk View File

@ -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

+ 3
- 3
scripts/generate_map.py View File

@ -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},

+ 5
- 0
src/game.h View File

@ -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

+ 5
- 4
src/level.c View File

@ -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();
}
}

+ 43
- 12
src/map.c View File

@ -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) {}

+ 1
- 1
src/map.h View File

@ -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;

+ 0
- 5
src/title.c View File

@ -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();
}
}

+ 29
- 1
src/vram.c View File

@ -2,6 +2,7 @@
#include <string.h>
#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;

+ 6
- 2
src/vram.h View File

@ -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); \

Loading…
Cancel
Save