Browse Source

Move VRAM mapping into mapper

master
Nathaniel Walizer 1 year ago
parent
commit
d094413864
10 changed files with 109 additions and 161 deletions
  1. +2
    -2
      Makefile
  2. +4
    -4
      src/cart.c
  3. +66
    -2
      src/map/mmc1.c
  4. +13
    -2
      src/map/nrom.c
  5. +19
    -0
      src/mapper.h
  6. +3
    -6
      src/ppu.c
  7. +0
    -3
      src/ppu.h
  8. +2
    -2
      src/sdl_render.c
  9. +0
    -92
      src/vram.c
  10. +0
    -48
      src/vram.h

+ 2
- 2
Makefile View File

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


+ 4
- 4
src/cart.c View File

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


+ 66
- 2
src/map/mmc1.c View File

@@ -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,
*/
};

+ 13
- 2
src/map/nrom.c View File

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

+ 19
- 0
src/mapper.h View File

@@ -4,6 +4,10 @@
#include <stdint.h>


#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[];



+ 3
- 6
src/ppu.c View File

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


+ 0
- 3
src/ppu.h View File

@@ -3,8 +3,6 @@

#include <stdint.h>

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


+ 2
- 2
src/sdl_render.c View File

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


+ 0
- 92
src/vram.c View File

@@ -1,92 +0,0 @@
#include <stdlib.h>

#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,
};

+ 0
- 48
src/vram.h View File

@@ -1,48 +0,0 @@
#ifndef NES_VRAM_
#define NES_VRAM_

#include <stdint.h>


#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_

Loading…
Cancel
Save