From d094413864e0cf60c95d9216028a2c1f49b0370d Mon Sep 17 00:00:00 2001 From: Nathaniel Walizer Date: Wed, 4 Dec 2024 19:32:26 -0800 Subject: [PATCH] Move VRAM mapping into mapper --- Makefile | 4 +-- src/cart.c | 8 ++--- src/map/mmc1.c | 68 +++++++++++++++++++++++++++++++++-- src/map/nrom.c | 15 ++++++-- src/mapper.h | 19 ++++++++++ src/ppu.c | 9 ++--- src/ppu.h | 3 -- src/sdl_render.c | 4 +-- src/vram.c | 92 ------------------------------------------------ src/vram.h | 48 ------------------------- 10 files changed, 109 insertions(+), 161 deletions(-) delete mode 100644 src/vram.c delete mode 100644 src/vram.h diff --git a/Makefile b/Makefile index 97863cf..421d39f 100644 --- a/Makefile +++ b/Makefile @@ -15,8 +15,8 @@ TARGET_1 = nese LDLIBS_1 = -lSDL2 SRC_SRCS_1 = nese.c ines.c -SRC_SRCS_1 += nes.c ppu.c cart.c input.c -SRC_SRCS_1 += vram.c mapper.c +SRC_SRCS_1 += nes.c ppu.c input.c +SRC_SRCS_1 += cart.c mapper.c SRC_SRCS_1 += sdl_render.c sdl_input.c MAPDIR = src/map diff --git a/src/cart.c b/src/cart.c index 0a3f4cb..a73ffeb 100644 --- a/src/cart.c +++ b/src/cart.c @@ -54,10 +54,6 @@ int nes_cart_init_mem(nes_cart* cart, void* mem, int len) { } } - if (0 == status) { - status = nes_map_init(cart->mapper, cart); - } - if (0 == status) { if (hdr->flags_6 & ines_Flag_Horizontal) { cart->flags |= Cart_Flag_Horizontal; @@ -65,6 +61,10 @@ int nes_cart_init_mem(nes_cart* cart, void* mem, int len) { cart->flags &= ~Cart_Flag_Horizontal; } + status = nes_map_init(cart->mapper, cart); + } + + if (0 == status) { cart->ines_mem = mem; cart->ines_size = len; } diff --git a/src/map/mmc1.c b/src/map/mmc1.c index 97ba62f..98da90a 100644 --- a/src/map/mmc1.c +++ b/src/map/mmc1.c @@ -1,8 +1,72 @@ #include "map.h" -// Stub +typedef struct { + uint8_t* prg_rom; + int prg_rom_size; + uint8_t* prg_ram; + int prg_ram_size; + uint8_t* chr_rom; + int chr_rom_size; -nes_mapper mapper_mmc1 = { + uint8_t reg_shift; + uint8_t reg_control; + uint8_t reg_chr_0; + uint8_t reg_chr_1; + uint8_t reg_prg; +} mmc1_mapper; + +/* +int mmc1_init(nes_mapper* nes_map, nes_cart* cart) { + nrom_mapper* map = malloc(sizeof(nrom_mapper)); + nes_map->data = map; + if (NULL != map) { + map->prg_rom = cart->prg_rom; + map->prg_rom_size = cart->prg_rom_size; + map->chr_rom = cart->chr_rom; + map->chr_rom_size = cart->chr_rom_size; + map->prg_ram = cart->wram; + map->prg_ram_size = nes_mem_wram_size; + + map->shift_reg = 0; + } + return (NULL == map ? -1 : 0); +} + +void nrom_done(nes_mapper* nes_map) { + free(nes_map->data); +} + +static inline uint8_t* nrom_prg_addr(nrom_mapper* map, + uint16_t addr) { + if (addr > map->prg_rom_size) { + addr &= 0x3FFF; + } + return &(map->prg_rom[addr]); +} +uint8_t nrom_prg_read(nes_mapper* map, uint16_t addr) { + return *(nrom_prg_addr((nrom_mapper*)map->data, addr)); +} + +void nrom_prg_write(nes_mapper* map, uint16_t addr, uint8_t val) { + // No ROM writes. +} + +uint8_t* nrom_chr_addr(nes_mapper* nes_map, uint16_t addr) { + nrom_mapper* map = (nrom_mapper*)nes_map->data; + return &map->chr_rom[addr % map->chr_rom_size]; +} + +*/ + +nes_mapper mapper_mmc1 = { +/* + .init = mmc1_init, + .done = mmc1_done, + .prg_read = mmc1_prg_read, + .prg_write = mmc1_prg_write, + .chr_addr = mmc1_chr_addr, + .vram_addr = mmc1_chr_addr, +*/ }; diff --git a/src/map/nrom.c b/src/map/nrom.c index a01a05a..0bdf44e 100644 --- a/src/map/nrom.c +++ b/src/map/nrom.c @@ -10,12 +10,13 @@ typedef struct { int prg_ram_size; uint8_t* chr_rom; int chr_rom_size; + uint8_t mirror; + uint8_t vram[nes_vram_page_size * 2]; } nrom_mapper; -// TODO: PRG_ROM region mirroring int nrom_init(nes_mapper* nes_map, nes_cart* cart) { - nrom_mapper* map = malloc(sizeof(nrom_mapper)); + nrom_mapper* map = calloc(1, sizeof(nrom_mapper)); nes_map->data = map; if (NULL != map) { map->prg_rom = cart->prg_rom; @@ -24,6 +25,7 @@ int nrom_init(nes_mapper* nes_map, nes_cart* cart) { map->chr_rom_size = cart->chr_rom_size; map->prg_ram = cart->wram; map->prg_ram_size = nes_mem_wram_size; + map->mirror = (cart->flags & Cart_Flag_Horizontal) ? 0 : 1; } return (NULL == map ? -1 : 0); } @@ -53,10 +55,19 @@ uint8_t* nrom_chr_addr(nes_mapper* nes_map, uint16_t addr) { return &map->chr_rom[addr % map->chr_rom_size]; } +uint8_t* nrom_vram_addr(nes_mapper* nes_map, uint16_t addr) { + nrom_mapper* map = (nrom_mapper*)nes_map->data; + int page = addr >> 10U; + page >>= map->mirror; + addr = ((page & 1) << 10U) | (addr & 0x3FFU); + return &map->vram[addr]; +} + nes_mapper mapper_nrom = { .init = nrom_init, .done = nrom_done, .prg_read = nrom_prg_read, .prg_write = nrom_prg_write, .chr_addr = nrom_chr_addr, + .vram_addr = nrom_vram_addr, }; diff --git a/src/mapper.h b/src/mapper.h index 7b514e2..3c0e01f 100644 --- a/src/mapper.h +++ b/src/mapper.h @@ -4,6 +4,10 @@ #include +#define nes_chr_page_size (0x1000U) +#define nes_vram_page_size (0x0400U) + + struct nes_cart_t; typedef struct nes_mapper_t { @@ -12,6 +16,7 @@ typedef struct nes_mapper_t { uint8_t (*prg_read)(struct nes_mapper_t*, uint16_t addr); void (*prg_write)(struct nes_mapper_t*, uint16_t addr, uint8_t val); uint8_t* (*chr_addr)(struct nes_mapper_t*, uint16_t addr); + uint8_t* (*vram_addr)(struct nes_mapper_t*, uint16_t addr); void* data; } nes_mapper; @@ -40,6 +45,20 @@ static inline uint8_t* nes_map_chr_addr(nes_mapper* map, return map->chr_addr(map, addr); } +static inline uint8_t* nes_map_vram_addr(nes_mapper* map, + uint16_t addr) { + return map->vram_addr(map, addr); +} + +static inline uint8_t nes_vram_read(nes_mapper* map, + uint16_t addr) { + return *(nes_map_vram_addr(map, addr)); +} + +static inline void nes_vram_write(nes_mapper* map, + uint16_t addr, uint8_t val) { + *(nes_map_vram_addr(map, addr)) = val; +} extern nes_mapper* nes_mappers[]; diff --git a/src/ppu.c b/src/ppu.c index e73266a..73c7207 100644 --- a/src/ppu.c +++ b/src/ppu.c @@ -49,7 +49,7 @@ uint8_t nes_ppu_read(nes_ppu* ppu, uint16_t addr) { nes_ppu_mem_vram_size) { VRAM_LOG("PPU: VRAM READ %04x > %02x\n", ppu->addr, val); ppu->data = nes_vram_read( - ppu->vram_map, + ppu->mapper, ppu->addr - nes_ppu_mem_vram_start ); } else if (ppu->addr < nes_ppu_mem_pal_start) { @@ -158,7 +158,7 @@ void nes_ppu_write(nes_ppu* ppu, uint16_t addr, uint8_t val) { } #endif // DEBUG_VRAM // printf("PPU: VRAM %04x < %02x\n", vram_addr, val); - nes_vram_write(ppu->vram_map, vram_addr, val); + nes_vram_write(ppu->mapper, vram_addr, val); } ppu->addr += (ppu->control & ppu_Control_VRAM_Inc) ? @@ -183,11 +183,8 @@ int nes_ppu_init(nes_ppu* ppu, const nes_cart* cart) { ppu->status = 0; ppu->oam_addr = 0; ppu->addr = 0; - ppu->vram_map = ( (cart->flags & Cart_Flag_Horizontal) ? - &vram_horizontal : - &vram_vertical ); nes_ppu_reset(ppu); - return nes_vram_init(ppu->vram_map); + return 0; } int nes_ppu_run(nes_ppu* ppu, int cycles) { diff --git a/src/ppu.h b/src/ppu.h index 846a169..3f563b9 100644 --- a/src/ppu.h +++ b/src/ppu.h @@ -3,8 +3,6 @@ #include -#include "vram.h" - struct nes_mapper_t; struct nes_cart_t; @@ -110,7 +108,6 @@ typedef struct { struct nes_mapper_t* mapper; uint8_t oam[nes_ppu_oam_size]; uint8_t palette[nes_ppu_mem_pal_size]; - nes_vram_map* vram_map; // Timing int frame; diff --git a/src/sdl_render.c b/src/sdl_render.c index d2ba645..651f838 100644 --- a/src/sdl_render.c +++ b/src/sdl_render.c @@ -194,8 +194,8 @@ static void render_background_area(const nes_ppu* ppu, int page, void* buffer, int pitch, int xs, int ys, int w, int h) { int bank = (ppu->control & ppu_Control_Back_Bank) ? 0x100 : 0; - const uint8_t* index_line = nes_vram_page(ppu->vram_map, - page); + const uint8_t* index_line = nes_map_vram_addr(ppu->mapper, + page << 10); const uint8_t* attrs = index_line + 960U; index_line += xs + (ys * nes_ppu_blocks_w); uint8_t* dst_line = (uint8_t*)buffer; diff --git a/src/vram.c b/src/vram.c deleted file mode 100644 index 1a93714..0000000 --- a/src/vram.c +++ /dev/null @@ -1,92 +0,0 @@ -#include - -#include "vram.h" - - -typedef enum { - Mirror_Method_Vertical, - Mirror_Method_Horizontal, -} vram_Mirror_Method; - -typedef struct { - vram_Mirror_Method method; - uint8_t vram[nes_vram_page_size * 2]; -} vram_mirror; - - -static vram_mirror* vram_mirror_create(vram_Mirror_Method method) { - vram_mirror* mirror = calloc(1, sizeof(vram_mirror)); - if (NULL != mirror) mirror->method = method; - return mirror; -} - -static void vram_mirror_destroy(vram_mirror* mirror) { - free(mirror); -} - -static inline uint8_t* vram_mirror_page(vram_mirror* mirror, - int page) { - if (mirror->method == Mirror_Method_Vertical) { - page >>= 1; - } - return &mirror->vram[(page & 1) ? nes_vram_page_size : 0]; -} - -static inline uint8_t* vram_mirror_map(vram_mirror* mirror, - uint16_t addr) { - uint8_t* page = vram_mirror_page(mirror, (addr >> 10)); - return &page[addr & nes_vram_addr_mask]; -} - -static int vram_map_mirror_init_method(nes_vram_map* map, - vram_Mirror_Method method) { - map->data = vram_mirror_create(method); - return (NULL == map->data ? -1 : 0); -} - -static int vram_map_mirror_init_horz(nes_vram_map* map) { - return vram_map_mirror_init_method( - map, Mirror_Method_Horizontal - ); -} - -static int vram_map_mirror_init_vert(nes_vram_map* map) { - return vram_map_mirror_init_method( - map, Mirror_Method_Vertical - ); -} - -static void vram_map_mirror_done(nes_vram_map* map) { - vram_mirror_destroy((vram_mirror*)map->data); -} - -static uint8_t vram_map_mirror_read(nes_vram_map* map, - uint16_t addr) { - return *(vram_mirror_map((vram_mirror*)map->data, addr)); -} - -static void vram_map_mirror_write(nes_vram_map* map, - uint16_t addr, - uint8_t val) { - *(vram_mirror_map((vram_mirror*)map->data, addr)) = val; -} - -static uint8_t* vram_map_mirror_page(nes_vram_map* map, int page) { - return vram_mirror_page((vram_mirror*)map->data, page); -} - -nes_vram_map vram_horizontal = { - .init = vram_map_mirror_init_horz, - .done = vram_map_mirror_done, - .read = vram_map_mirror_read, - .write = vram_map_mirror_write, - .page = vram_map_mirror_page, -}; - -nes_vram_map vram_vertical = { - .init = vram_map_mirror_init_vert, - .done = vram_map_mirror_done, - .read = vram_map_mirror_read, - .write = vram_map_mirror_write, - .page = vram_map_mirror_page, -}; diff --git a/src/vram.h b/src/vram.h deleted file mode 100644 index 33c5464..0000000 --- a/src/vram.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef NES_VRAM_ -#define NES_VRAM_ - -#include - - -#define nes_vram_page_size (0x400U) -#define nes_vram_page_mask (0xC00U) -#define nes_vram_addr_mask (0x3FFU) - - -typedef struct nes_vram_map_t { - int (*init)(struct nes_vram_map_t*); - void (*done)(struct nes_vram_map_t*); - uint8_t* (*page)(struct nes_vram_map_t*, int page); - uint8_t (*read)(struct nes_vram_map_t*, uint16_t addr); - void (*write)(struct nes_vram_map_t*, uint16_t addr, uint8_t val); - void* data; -} nes_vram_map; - -static inline int nes_vram_init(nes_vram_map* map) { - return map->init(map); -} - -static inline void nes_vram_done(nes_vram_map* map) { - map->done(map); -} - -static inline uint8_t* nes_vram_page(nes_vram_map* map, int page) { - return map->page(map, page); -} - -static inline uint8_t nes_vram_read(nes_vram_map* map, - uint16_t addr) { - return map->read(map, addr); -} - -static inline void nes_vram_write(nes_vram_map* map, - uint16_t addr, uint8_t val) { - map->write(map, addr, val); -} - - -extern nes_vram_map vram_horizontal; -extern nes_vram_map vram_vertical; - - -#endif // NES_VRAM_