Kaynağa Gözat

Fix CHR RAM saves in MMC1 & MMC3

master
Nathaniel Walizer 10 ay önce
ebeveyn
işleme
baaad1f15d
9 değiştirilmiş dosya ile 157 ekleme ve 62 silme
  1. +1
    -1
      Makefile
  2. +2
    -2
      src/map/cnrom.c
  3. +45
    -25
      src/map/mmc1.c
  4. +33
    -14
      src/map/mmc3.c
  5. +21
    -11
      src/map/nrom.c
  6. +2
    -2
      src/map/uxrom.c
  7. +2
    -2
      src/mapper.h
  8. +37
    -5
      src/save.c
  9. +14
    -0
      src/save.h

+ 1
- 1
Makefile Dosyayı Görüntüle

@@ -30,7 +30,7 @@ PFLAGS += -g
#PFLAGS += -DDEBUG_APU
#PFLAGS += -DDEBUG_INPUT
#PFLAGS += -DE6502_DEBUG
#PFLAGS += -DE6502_ILLEGAL
PFLAGS += -DE6502_ILLEGAL
CFLAGS += $(PFLAGS) -Wall -Werror -Wshadow -Wunused -I../ -Isrc/
CFLAGS += -Iinc/$(PLATFORM)/SDL2
LDFLAGS += $(PFLAGS)


+ 2
- 2
src/map/cnrom.c Dosyayı Görüntüle

@@ -96,7 +96,7 @@ static int cnrom_state_size(const void* _map) {
return (sizeof(map->bank) + sizeof(map->vram));
}

static int cnrom_state_read(void* _map, const void* data) {
static int cnrom_state_read(void* _map, const void* data, int len) {
cnrom_mapper* map = (cnrom_mapper*)_map;
const void* ptr = data;

@@ -111,7 +111,7 @@ static int cnrom_state_read(void* _map, const void* data) {
return (ptr - data);
}

static int cnrom_state_write(const void* _map, void* data) {
static int cnrom_state_write(const void* _map, void* data, int len) {
cnrom_mapper* map = (cnrom_mapper*)_map;
void* ptr = data;



+ 45
- 25
src/map/mmc1.c Dosyayı Görüntüle

@@ -15,9 +15,11 @@ typedef struct {
uint8_t* chr_bank[2];
uint8_t* vram_bank[4];
uint8_t* prg_bank[2];
uint8_t* chr_ram;
uint8_t* chr;

int chr_bank_offset[2];
int chr_ram_lim;

uint8_t reg_shift;
uint8_t reg_n_shift;
uint8_t reg_control;
@@ -27,6 +29,8 @@ typedef struct {

uint8_t vram[2][nes_vram_page_size];
uint8_t wram[nes_mem_wram_size];

uint8_t chr_ram[];
} mmc1_mapper;


@@ -55,21 +59,22 @@ static void mmc1_update_vram(mmc1_mapper* map) {
}

static void mmc1_update_chr(mmc1_mapper* map) {
// CHR RAM selection
int banks[2] = {0};
if (!(map->reg_control & 0b10000)) {
int bank = (map->reg_chr_0 & 0b11110);
MAP_LOG("CHR: 8 KB: %d + %d", bank, bank + 1);
map->chr_bank[0] = &map->chr[ bank *
nes_chr_page_size];
map->chr_bank[1] = &map->chr[ (bank + 1) *
nes_chr_page_size];
banks[0] = (map->reg_chr_0 & 0b11110);
banks[1] = banks[0] + 1;
} else {
MAP_LOG("CHR: %d + %d", map->reg_chr_0, map->reg_chr_1);
map->chr_bank[0] = &map->chr[ map->reg_chr_0 *
nes_chr_page_size];
map->chr_bank[1] = &map->chr[ map->reg_chr_1 *
nes_chr_page_size];
banks[0] = map->reg_chr_0;
banks[1] = map->reg_chr_1;
}

MAP_LOG("CHR: %d + %d", banks[0], banks[1]);

map->chr_bank_offset[0] = banks[0] * nes_chr_page_size;
map->chr_bank_offset[1] = banks[1] * nes_chr_page_size;

map->chr_bank[0] = &map->chr[map->chr_bank_offset[0]];
map->chr_bank[1] = &map->chr[map->chr_bank_offset[1]];
}

static void mmc1_update_prg(mmc1_mapper* map) {
@@ -103,20 +108,22 @@ static void mmc1_reset(void* data) {
}

static void* mmc1_init(nes_mapper* nes_map, nes_cart* cart) {
mmc1_mapper* map = calloc(1, sizeof(mmc1_mapper));
int chr_ram_size = ( cart->chr_rom_banks > 0 ?
0 : 128 * 1024);
mmc1_mapper* map = calloc(1, sizeof(mmc1_mapper) +
chr_ram_size);
if (NULL != map) {
map->prg_rom = cart->prg_rom;
map->prg_rom_banks = cart->prg_rom_banks;
map->chr_rom_banks = cart->chr_rom_banks / 2;
if (map->chr_rom_banks > 0) {
map->chr_rom = cart->chr_rom;
map->chr_ram = NULL;
map->chr = map->chr_rom;
} else {
map->chr_rom = NULL;
map->chr_ram = calloc(32, nes_chr_page_size);
map->chr = map->chr_ram;
}
map->chr_ram_lim = 0;

map->battery = !!(cart->flags & Cart_Flag_Battery);

@@ -126,10 +133,7 @@ static void* mmc1_init(nes_mapper* nes_map, nes_cart* cart) {
}

static void mmc1_done(void* data) {
if (NULL != data) {
free(((mmc1_mapper*)data)->chr_ram);
free(data);
}
free(data);
}

static inline uint8_t* mmc1_prg_addr(mmc1_mapper* map,
@@ -207,7 +211,11 @@ static uint8_t* mmc1_chr_addr(void* data, uint16_t addr) {

static void mmc1_chr_write(void* data,
uint16_t addr, uint8_t val) {
if (NULL != ((mmc1_mapper*)data)->chr_ram) {
mmc1_mapper* map = (mmc1_mapper*)data;
if (NULL == map->chr_rom) {
int pos = map->chr_bank_offset[(addr >> 12) & 1] +
(addr & 0xFFFU);
if (pos >= map->chr_ram_lim) map->chr_ram_lim = pos + 1;
*(mmc1_chr_addr(data, addr)) = val;
}
}
@@ -233,17 +241,27 @@ static int mmc1_sram_size(void* data) {

/* Save State */

static inline int mmc1_chr_ram_size(const mmc1_mapper* map) {
return (map->chr_rom_banks <= 0 ? (128 * 1024) : 0);
}

static int mmc1_state_size(const void* _map) {
mmc1_mapper* map = (mmc1_mapper*)_map;
return ( (void*)map +

return ( map->chr_ram_lim +
(void*)map +
sizeof(*map) -
(void*)&(map->reg_shift));
}

static int mmc1_state_read(void* _map, const void* data) {
static int mmc1_state_read(void* _map, const void* data,
int data_len) {
mmc1_mapper* map = (mmc1_mapper*)_map;

int size = mmc1_state_size(_map);
int base_size = mmc1_state_size(map) - map->chr_ram_lim;
int size = base_size + mmc1_chr_ram_size(map);
if (size > data_len) size = data_len;
map->chr_ram_lim = data_len - base_size;
memcpy(&(map->reg_shift), data, size);

mmc1_update_prg(map);
@@ -253,9 +271,11 @@ static int mmc1_state_read(void* _map, const void* data) {
return size;
}

static int mmc1_state_write(const void* _map, void* data) {
static int mmc1_state_write(const void* _map, void* data,
int data_len) {
mmc1_mapper* map = (mmc1_mapper*)_map;
int size = mmc1_state_size(_map);
if (size > data_len) size = data_len;
memcpy(data, &(map->reg_shift), size);
return size;
}


+ 33
- 14
src/map/mmc3.c Dosyayı Görüntüle

@@ -32,6 +32,9 @@ typedef struct {
uint8_t* chr_bank[8]; // 1 KB
uint8_t* vram_bank[4];

int chr_bank_offset[8];
int chr_ram_lim;

uint8_t r[8];
uint8_t flags;
uint8_t bank_select;
@@ -40,6 +43,7 @@ typedef struct {

uint8_t wram[nes_mem_wram_size];
uint8_t vram[2][nes_vram_page_size];
uint8_t chr_ram[];
} mmc3_mapper;

static inline uint8_t* mmc3_prg_bank(mmc3_mapper* map, int bank) {
@@ -79,6 +83,8 @@ static inline void mmc3_map_2k_chr(mmc3_mapper* map,
MAP_LOG("CHR ROM: 2k $%04x <- bank %d + %d", reg << 10, bank, bank | 1);
map->chr_bank[reg + 0] = mmc3_chr_bank(map, bank);
map->chr_bank[reg + 1] = mmc3_chr_bank(map, bank | 1);
map->chr_bank_offset[reg + 0] = map->chr_bank[reg + 0] - map->chr_rom;
map->chr_bank_offset[reg + 1] = map->chr_bank[reg + 1] - map->chr_rom;
}

static inline void mmc3_map_1k_chr(mmc3_mapper* map,
@@ -89,6 +95,7 @@ static inline void mmc3_map_1k_chr(mmc3_mapper* map,
}
MAP_LOG("CHR ROM: 1k $%04x <- bank %d", reg << 10, bank);
map->chr_bank[reg] = mmc3_chr_bank(map, bank);
map->chr_bank_offset[reg] = map->chr_bank[reg] - map->chr_rom;
}

static inline void mmc3_update_chr(mmc3_mapper* map,
@@ -159,7 +166,10 @@ static void mmc3_reset(void* data) {
}

static void* mmc3_init(nes_mapper* nes_map, nes_cart* cart) {
mmc3_mapper* map = calloc(1, sizeof(mmc3_mapper));
int chr_ram_size = ( cart->chr_rom_banks <= 0 ?
(256 * 1024) : 0);
mmc3_mapper* map = calloc(1, sizeof(mmc3_mapper) +
chr_ram_size);
if (NULL != map) {
map->mapper = nes_map;
map->flags = (cart->flags & Cart_Flag_Horizontal) ?
@@ -167,7 +177,7 @@ static void* mmc3_init(nes_mapper* nes_map, nes_cart* cart) {
map->prg_rom = cart->prg_rom;
map->prg_rom_banks = cart->prg_rom_banks * 2;
if (cart->chr_rom_banks <= 0) {
map->chr_rom = calloc(1024, 256);
map->chr_rom = map->chr_ram;
map->chr_rom_banks = 256;
map->flags |= mmc3_Flag_CHR_RAM;
} else {
@@ -188,13 +198,7 @@ static void* mmc3_init(nes_mapper* nes_map, nes_cart* cart) {
}

static void mmc3_done(void* data) {
mmc3_mapper* map = (mmc3_mapper*)data;
if (NULL != map) {
if (map->flags & mmc3_Flag_CHR_RAM) {
free(map->chr_rom);
}
free(map);
}
free(data);
}

static inline uint8_t* mmc3_prg_addr(mmc3_mapper* map,
@@ -328,7 +332,10 @@ static void mmc3_chr_write(void* data,
uint16_t addr, uint8_t val) {
mmc3_mapper* map = (mmc3_mapper*)data;
if (map->flags & mmc3_Flag_CHR_RAM) {
*(mmc3_chr_addr(data, addr)) = val;
uint8_t* ptr = mmc3_chr_addr(data, addr);
int pos = (ptr - map->chr_ram);
if (pos >= map->chr_ram_lim) map->chr_ram_lim = pos + 1;
*ptr = val;
}
// MAP_LOG("CHR ROM Write: $%04x < %02x\n", addr, val);
}
@@ -349,17 +356,27 @@ static int mmc3_sram_size(void* data) {

/* Save State */

static inline int mmc3_chr_ram_size(const mmc3_mapper* map) {
return ( (map->flags & mmc3_Flag_CHR_RAM) ?
(256 * 1024) : 0);
}

static int mmc3_state_size(const void* data) {
const mmc3_mapper* map = (mmc3_mapper*)data;
return ( (map->wram - map->r) +
sizeof(map->wram) +
sizeof(map->vram));
sizeof(map->vram) +
map->chr_ram_lim);
}

static int mmc3_state_read(void* _map, const void* data) {
static int mmc3_state_read(void* _map, const void* data,
int data_len) {
mmc3_mapper* map = (mmc3_mapper*)_map;

int size = mmc3_state_size(_map);
int base_size = mmc3_state_size(map) - map->chr_ram_lim;
int size = base_size + mmc3_chr_ram_size(map);
if (size > data_len) size = data_len;
map->chr_ram_lim = data_len - base_size;
memcpy(map->r, data, size);

uint8_t new_bank_select = map->bank_select;
@@ -371,9 +388,11 @@ static int mmc3_state_read(void* _map, const void* data) {
return size;
}

static int mmc3_state_write(const void* _map, void* data) {
static int mmc3_state_write(const void* _map, void* data,
int data_len) {
mmc3_mapper* map = (mmc3_mapper*)_map;
int size = mmc3_state_size(_map);
if (size > data_len) size = data_len;
memcpy(data, map->r, size);
return size;
}


+ 21
- 11
src/map/nrom.c Dosyayı Görüntüle

@@ -10,20 +10,24 @@ typedef struct {
uint8_t* chr_rom;
int chr_rom_banks;
uint8_t mirror;

uint8_t vram[nes_vram_page_size * 2];
uint8_t wram[nes_mem_wram_size];
uint8_t chr_ram[];
} nrom_mapper;


static void nrom_reset(void* data) {}

static void* nrom_init(nes_mapper* nes_map, nes_cart* cart) {
nrom_mapper* map = calloc(1, sizeof(nrom_mapper));
int chr_ram_size = (cart->chr_rom_banks <= 0 ? 8192U : 0);
nrom_mapper* map = calloc(1, sizeof(nrom_mapper) +
chr_ram_size);
if (NULL != map) {
map->prg_rom = cart->prg_rom;
map->prg_rom_banks = cart->prg_rom_banks;
if (cart->chr_rom_banks <= 0) {
map->chr_rom = calloc(8, 1024);
map->chr_rom = map->chr_ram;
} else {
map->chr_rom = cart->chr_rom;
}
@@ -97,23 +101,29 @@ static void nrom_chr_write(void* data,

/* Save State */

static inline int nrom_chr_ram_size(const nrom_mapper* map) {
return (map->chr_rom_banks <= 0 ? (8 * 1024) : 0);
}

static int nrom_state_size(const void* _map) {
nrom_mapper* map = (nrom_mapper*)_map;
return (sizeof(map->vram) + sizeof(map->wram));
return ( sizeof(map->vram) + sizeof(map->wram) +
nrom_chr_ram_size(map));
}

static int nrom_state_read(void* _map, const void* data) {
static int nrom_state_read(void* _map, const void* data, int len) {
nrom_mapper* map = (nrom_mapper*)_map;
memcpy(map->vram, data, sizeof(map->vram));
memcpy(map->wram, data + sizeof(map->vram), sizeof(map->wram));
return (sizeof(map->vram) + sizeof(map->wram));
int max_size = nrom_state_size(_map);
if (max_size > len) max_size = len;
memcpy(map->vram, data, max_size);
return max_size;
}

static int nrom_state_write(const void* _map, void* data) {
static int nrom_state_write(const void* _map, void* data, int len) {
nrom_mapper* map = (nrom_mapper*)_map;
memcpy(data, map->vram, sizeof(map->vram));
memcpy(data + sizeof(map->vram), map->wram, sizeof(map->wram));
return (sizeof(map->vram) + sizeof(map->wram));
int size = nrom_state_size(_map);
memcpy(data, map->vram, size);
return size;
}




+ 2
- 2
src/map/uxrom.c Dosyayı Görüntüle

@@ -97,7 +97,7 @@ int uxrom_state_size(const void* _map) {
sizeof(map->chr_ram));
}

int uxrom_state_read(void* _map, const void* data) {
int uxrom_state_read(void* _map, const void* data, int len) {
uxrom_mapper* map = (uxrom_mapper*)_map;
const void* ptr = data;

@@ -113,7 +113,7 @@ int uxrom_state_read(void* _map, const void* data) {
return (ptr - data);
}

int uxrom_state_write(const void* _map, void* data) {
int uxrom_state_write(const void* _map, void* data, int len) {
uxrom_mapper* map = (uxrom_mapper*)_map;
void* ptr = data;



+ 2
- 2
src/mapper.h Dosyayı Görüntüle

@@ -33,8 +33,8 @@ typedef struct nes_mapper_t {
int (*sram_size)(void*);

int (*state_size)(const void* map);
int (*state_read)(void* map, const void* data);
int (*state_write)(const void* map, void* data);
int (*state_read)(void* map, const void* data, int len);
int (*state_write)(const void* map, void* data, int len);
} nes_mapper;

static inline void* nes_map_init(nes_mapper* map,


+ 37
- 5
src/save.c Dosyayı Görüntüle

@@ -76,7 +76,13 @@ int load_state(nes* sys, const char* cart_filename) {
FILE* file = fopen(state_filename, "rb");

if (NULL != file) {
int file_size = state_size(sys);
// int expected_size = state_size(sys);

fseek(file, 0L, SEEK_END);
int file_size = ftell(file);
// rewind(file);
// if (max_size < size) size = max_size;

void* mem = map_file(file, file_size, Filemap_Mode_Read);

if (NULL != mem) {
@@ -278,9 +284,9 @@ int state_write(const nes* sys, void* mem, int size) {

const nes_mapper* mapper = sys->cart.mapper;
const void* map_data = sys->cart.map_data;
ptr = write_header(ptr, tag_mapper,
mapper->state_size(map_data));
ptr += mapper->state_write(map_data, ptr);
int state_size = mapper->state_size(map_data);
ptr = write_header(ptr, tag_mapper, state_size);
ptr += mapper->state_write(map_data, ptr, state_size);

return (ptr - mem);
}
@@ -342,7 +348,7 @@ int state_read(nes* sys, const void* mem, int mem_size) {

} else if (tag_mapper == tag) {
n_read = sys->cart.mapper->state_read(
sys->cart.map_data, ptr
sys->cart.map_data, ptr, size
);
loaded |= Component_Mapper;

@@ -395,3 +401,29 @@ int state_read(nes* sys, const void* mem, int mem_size) {

return result;
}

/*
// Chunking

int write_chunks(void* dst, int dst_len, const void* src,
const nese_io_chunk* chunks, int n_chunks) {
void* ptr = dst;
for ( void* end = dst + dst_len;
n_chunks > 0 && ptr < end;
ptr += chunks->size, --n_chunks, ++chunks) {
memcpy(ptr, src + chunks->offset, chunks->size);
}
return (ptr - dst);
}

int read_chunks(const void* src, int src_len, void* dst,
const nese_io_chunk* chunks, int n_chunks) {
const void* ptr = src;
for ( const void* end = src + src_len;
n_chunks > 0 && ptr < end;
ptr += chunks->size, --n_chunks, ++chunks) {
memcpy(dst + chunks->offset, ptr, chunks->size);
}
return (ptr - dst);
}
*/

+ 14
- 0
src/save.h Dosyayı Görüntüle

@@ -14,5 +14,19 @@ int state_write(const nes*, void* mem, int size);
int load_state(nes*, const char* filename);
int save_state(const nes*, const char* filename);

/*
// Chunking

typedef struct {
int offset;
int size;
} nese_io_chunk;

int write_chunks(void* dst, int dst_len, const void* src,
const nese_io_chunk* chunks, int n_chunks);

int read_chunks(const void* src, int src_len, void* dst,
const nese_io_chunk* chunks, int n_chunks);
*/

#endif // NESE_SAVE_H_

Yükleniyor…
İptal
Kaydet