Fix memory mapping
This commit is contained in:
parent
07d044c47f
commit
66785039a9
|
@ -11,7 +11,7 @@ add_subdirectory(cpu)
|
||||||
add_subdirectory(ppu)
|
add_subdirectory(ppu)
|
||||||
add_subdirectory(mappers)
|
add_subdirectory(mappers)
|
||||||
add_subdirectory(rom)
|
add_subdirectory(rom)
|
||||||
add_subdirectory(debugger)
|
#add_subdirectory(debugger)
|
||||||
add_subdirectory(utils)
|
add_subdirectory(utils)
|
||||||
add_subdirectory(gui)
|
add_subdirectory(gui)
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ set(SOURCE main.c system.c)
|
||||||
|
|
||||||
add_executable(nes_emulator ${HEADERS} ${SOURCE})
|
add_executable(nes_emulator ${HEADERS} ${SOURCE})
|
||||||
|
|
||||||
target_link_libraries(nes_emulator nes_cpu nes_ppu nes_mappers nes_rom nes_debugger nes_utils nes_gui log.c)
|
target_link_libraries(nes_emulator nes_cpu nes_ppu nes_mappers nes_rom nes_utils nes_gui log.c)
|
||||||
target_include_directories(nes_emulator PUBLIC
|
target_include_directories(nes_emulator PUBLIC
|
||||||
"${PROJECT_BINARY_DIR}"
|
"${PROJECT_BINARY_DIR}"
|
||||||
${EXTRA_INCLUDES})
|
${EXTRA_INCLUDES})
|
|
@ -64,7 +64,7 @@ void cpu_process_nmi() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void oam_dma_upload() {
|
void oam_dma_upload() {
|
||||||
byte page_high_addr = *ppu_get_state()->oam_dma_register; // TODO
|
byte page_high_addr = ppu_get_state()->oam_dma_register; // TODO
|
||||||
address page_addr = ((address) page_high_addr) << 8;
|
address page_addr = ((address) page_high_addr) << 8;
|
||||||
byte n = 0xff;
|
byte n = 0xff;
|
||||||
|
|
||||||
|
|
113
cpu/memory.c
113
cpu/memory.c
|
@ -8,62 +8,107 @@
|
||||||
#include "../include/rom.h"
|
#include "../include/rom.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define RAM_SIZE 0x0800
|
||||||
#define RAM_MAX_ADDR 0x2000
|
#define RAM_MAX_ADDR 0x2000
|
||||||
#define RAM_BANK_SIZE 0x800
|
|
||||||
#define PPU_MAX_ADDR 0x4000
|
#define PPU_MAX_ADDR 0x4000
|
||||||
#define PPU_BANK_SIZE 0x8
|
|
||||||
#define APU_MAX_ADDR 0x4020
|
#define APU_MAX_ADDR 0x4020
|
||||||
#define MAX_ADDR 0xffff
|
#define UNMAPPED_MAX_ADDR 0x6000
|
||||||
|
#define CARTRIDGE_RAM_MAX_ADDR 0x8000
|
||||||
|
#define MEM_ADDR_MAX 0xffff
|
||||||
|
|
||||||
byte ram[RAM_SIZE];
|
byte ram[RAM_SIZE];
|
||||||
|
|
||||||
byte mem_get_byte(address addr) {
|
byte *mem_get_ptr(address addr) {
|
||||||
assert(addr <= MAX_ADDR);
|
assert(addr <= RAM_MAX_ADDR);
|
||||||
|
|
||||||
if (addr >= RAM_MAX_ADDR && addr < PPU_MAX_ADDR) {
|
if (addr < RAM_MAX_ADDR) {
|
||||||
byte reg = (addr - RAM_MAX_ADDR) % PPU_BANK_SIZE;
|
address ram_addr = addr % RAM_SIZE; // There is four mirror of RAM
|
||||||
return ppu_read_reg(reg);
|
return &ram[ram_addr];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ram[addr];
|
// Only supported for RAM
|
||||||
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte *mem_get_ptr(address addr) {
|
byte mem_get_byte(address addr) {
|
||||||
assert(addr <= MAX_ADDR);
|
assert(addr <= MEM_ADDR_MAX);
|
||||||
|
|
||||||
return &ram[addr];
|
if (addr < RAM_MAX_ADDR) {
|
||||||
|
address ram_addr = addr % RAM_SIZE;
|
||||||
|
return ram[ram_addr];
|
||||||
|
} else if (addr < PPU_MAX_ADDR) {
|
||||||
|
address relative_addr = addr - RAM_MAX_ADDR;
|
||||||
|
byte ppu_reg = relative_addr % 8;
|
||||||
|
return ppu_read_reg(ppu_reg);
|
||||||
|
} else if (addr < APU_MAX_ADDR) {
|
||||||
|
// TODO NES API and I/O registers
|
||||||
|
return 0;
|
||||||
|
} else if (addr < UNMAPPED_MAX_ADDR) {
|
||||||
|
// Unmapped
|
||||||
|
assert(false);
|
||||||
|
} else if (addr < CARTRIDGE_RAM_MAX_ADDR) {
|
||||||
|
// TODO Cartridge RAM
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
address rom_addr = addr - CARTRIDGE_RAM_MAX_ADDR;
|
||||||
|
|
||||||
|
Mapper *mapper = system_get_mapper();
|
||||||
|
return *(mapper->mem_read(rom_addr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
word mem_get_word(address addr) {
|
word mem_get_word(address addr) {
|
||||||
assert(addr < MAX_ADDR);
|
assert(addr <= MEM_ADDR_MAX - 1);
|
||||||
|
|
||||||
word word = ram[addr];
|
byte data1;
|
||||||
word += ram[addr + 1] << 8; // Little endian
|
byte data2;
|
||||||
return word;
|
|
||||||
|
if (addr < RAM_MAX_ADDR - 1) {
|
||||||
|
address ram_addr = addr % RAM_SIZE;
|
||||||
|
data1 = ram[ram_addr];
|
||||||
|
data2 = ram[ram_addr + 1];
|
||||||
|
} else if (addr < UNMAPPED_MAX_ADDR) {
|
||||||
|
// Unsupported
|
||||||
|
assert(false);
|
||||||
|
} else if (addr < CARTRIDGE_RAM_MAX_ADDR) {
|
||||||
|
// TODO Cartridge RAM
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
address rom_addr = addr - CARTRIDGE_RAM_MAX_ADDR;
|
||||||
|
|
||||||
|
Mapper *mapper = system_get_mapper();
|
||||||
|
byte *location = mapper->mem_read(rom_addr);
|
||||||
|
|
||||||
|
data1 = *location;
|
||||||
|
data2 = *(location + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data1 + (data2 << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_set_byte(address addr, byte byte) {
|
void mem_set_byte(address addr, byte data) {
|
||||||
assert(addr < MAX_ADDR);
|
assert(addr < MEM_ADDR_MAX);
|
||||||
|
|
||||||
log_trace("Writing '%02x' to address 0x%04x", byte, addr);
|
|
||||||
|
|
||||||
if (addr < RAM_MAX_ADDR) {
|
if (addr < RAM_MAX_ADDR) {
|
||||||
address init_ram_addr = addr % RAM_BANK_SIZE;
|
address ram_addr = addr % RAM_SIZE;
|
||||||
|
ram[ram_addr] = data;
|
||||||
// The value must also be cloned in the three mirrors
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
address ram_addr = init_ram_addr + RAM_BANK_SIZE * i;
|
|
||||||
ram[ram_addr] = byte;
|
|
||||||
}
|
|
||||||
} else if (addr < PPU_MAX_ADDR) {
|
} else if (addr < PPU_MAX_ADDR) {
|
||||||
address reg_addr = (addr - RAM_MAX_ADDR) % PPU_BANK_SIZE;
|
address relative_addr = addr - RAM_MAX_ADDR;
|
||||||
ppu_write_reg(reg_addr, byte);
|
byte ppu_reg = relative_addr % 8;
|
||||||
} else {
|
ppu_write_reg(ppu_reg, data);
|
||||||
ram[addr] = byte;
|
} else if (addr == PPU_REGISTER_OAM_DMA_ADDR) {
|
||||||
|
|
||||||
if (addr == PPU_REGISTER_OAM_DMA_ADDR) {
|
|
||||||
// Writing to this address triggers an upload to the PPU memory
|
// Writing to this address triggers an upload to the PPU memory
|
||||||
cpu_trigger_oam_dma();
|
cpu_trigger_oam_dma();
|
||||||
}
|
} else if (addr < APU_MAX_ADDR) {
|
||||||
|
// TODO NES API and I/O registers
|
||||||
|
} else if (addr < UNMAPPED_MAX_ADDR) {
|
||||||
|
// Unmapped
|
||||||
|
assert(false);
|
||||||
|
} else if (addr < CARTRIDGE_RAM_MAX_ADDR) {
|
||||||
|
// TODO Cartridge RAM
|
||||||
|
} else {
|
||||||
|
// ROM is read-only
|
||||||
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -37,8 +37,8 @@ word mem_get_word(address addr);
|
||||||
* Sets a byte in a system's memory.
|
* Sets a byte in a system's memory.
|
||||||
*
|
*
|
||||||
* @param addr The address to set
|
* @param addr The address to set
|
||||||
* @param value The value to set
|
* @param data The data to set
|
||||||
*/
|
*/
|
||||||
void mem_set_byte(address addr, byte value);
|
void mem_set_byte(address addr, byte data);
|
||||||
|
|
||||||
#endif //NESEMULATOR_MEMORY_H
|
#endif //NESEMULATOR_MEMORY_H
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "../ppu/memory.h"
|
|
||||||
|
|
||||||
#ifndef NESEMULATOR_PPU_H
|
#ifndef NESEMULATOR_PPU_H
|
||||||
#define NESEMULATOR_PPU_H
|
#define NESEMULATOR_PPU_H
|
||||||
|
@ -61,11 +60,18 @@ typedef struct ppu_memory {
|
||||||
byte *palette;
|
byte *palette;
|
||||||
} PPUMemory;
|
} PPUMemory;
|
||||||
|
|
||||||
|
typedef struct ppu_tile_fetch {
|
||||||
|
byte nametable;
|
||||||
|
byte attribute_table;
|
||||||
|
byte pattern_table_tile_low;
|
||||||
|
byte pattern_table_tile_high;
|
||||||
|
} PPUTileFetch;
|
||||||
|
|
||||||
typedef struct ppu {
|
typedef struct ppu {
|
||||||
PPUMemory memory;
|
PPUMemory memory;
|
||||||
|
|
||||||
byte *registers;
|
byte registers[8];
|
||||||
byte *oam_dma_register;
|
byte oam_dma_register;
|
||||||
byte vram[PPU_VRAM_SIZE];
|
byte vram[PPU_VRAM_SIZE];
|
||||||
byte oam[PPU_OAM_SIZE];
|
byte oam[PPU_OAM_SIZE];
|
||||||
bool odd_frame;
|
bool odd_frame;
|
||||||
|
@ -90,8 +96,7 @@ PPU *ppu_get_state();
|
||||||
*
|
*
|
||||||
* @param ppu
|
* @param ppu
|
||||||
*/
|
*/
|
||||||
void ppu_init(byte *registers_ram, byte *oam_dma_register);
|
void ppu_init();
|
||||||
void ppu_uninit();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cycles the PPU.
|
* Cycles the PPU.
|
||||||
|
|
|
@ -19,7 +19,7 @@ typedef struct {
|
||||||
bool nametable_mirrored;
|
bool nametable_mirrored;
|
||||||
|
|
||||||
byte *prg_rom;
|
byte *prg_rom;
|
||||||
int prg_rom_size;
|
unsigned int prg_rom_size;
|
||||||
|
|
||||||
byte *chr_rom;
|
byte *chr_rom;
|
||||||
} Rom;
|
} Rom;
|
||||||
|
|
|
@ -5,14 +5,14 @@
|
||||||
#ifndef NESEMULATOR_TYPES_H
|
#ifndef NESEMULATOR_TYPES_H
|
||||||
#define NESEMULATOR_TYPES_H
|
#define NESEMULATOR_TYPES_H
|
||||||
|
|
||||||
#define RAM_SIZE 0xffff
|
//#define RAM_SIZE 0xffff
|
||||||
#define VRAM_SIZE 0x4000
|
//#define VRAM_SIZE 0x4000
|
||||||
|
|
||||||
typedef unsigned char byte;
|
typedef unsigned char byte;
|
||||||
typedef unsigned short address;
|
typedef unsigned short address;
|
||||||
typedef unsigned short word;
|
typedef unsigned short word;
|
||||||
|
|
||||||
//typedef byte ram[RAM_SIZE];
|
//typedef byte ram[RAM_SIZE];
|
||||||
typedef byte vram[VRAM_SIZE];
|
//typedef byte vram[VRAM_SIZE];
|
||||||
|
|
||||||
#endif //NESEMULATOR_TYPES_H
|
#endif //NESEMULATOR_TYPES_H
|
||||||
|
|
2
main.c
2
main.c
|
@ -27,7 +27,7 @@ int main() {
|
||||||
log_set_level(LOG_INFO);
|
log_set_level(LOG_INFO);
|
||||||
|
|
||||||
system_init();
|
system_init();
|
||||||
char *rom_path = "../test_roms/dk_japan.nes";
|
char *rom_path = "../test_roms/dk_jp.nes";
|
||||||
|
|
||||||
if (!rom_load(rom_path)) {
|
if (!rom_load(rom_path)) {
|
||||||
system_uninit();
|
system_uninit();
|
||||||
|
|
|
@ -2,23 +2,17 @@
|
||||||
#include "../include/rom.h"
|
#include "../include/rom.h"
|
||||||
#include "../cpu/memory.h"
|
#include "../cpu/memory.h"
|
||||||
|
|
||||||
#define SIMPLE_MAPPER_PRG_START_ADDR 0x8000
|
|
||||||
#define PRG_BANK_SIZE 0x4000 // 16Kb
|
#define PRG_BANK_SIZE 0x4000 // 16Kb
|
||||||
|
|
||||||
byte *nrom_mem_read(address addr) {
|
byte *nrom_mem_read(address addr) {
|
||||||
if (addr >= SIMPLE_MAPPER_PRG_START_ADDR) {
|
|
||||||
Rom *rom = rom_get();
|
Rom *rom = rom_get();
|
||||||
address relative_addr = addr - SIMPLE_MAPPER_PRG_START_ADDR;
|
|
||||||
|
|
||||||
if (addr < PRG_BANK_SIZE || rom->prg_rom_size > PRG_BANK_SIZE) {
|
if (addr < PRG_BANK_SIZE || rom->prg_rom_size > PRG_BANK_SIZE) {
|
||||||
return &rom->prg_rom[relative_addr];
|
return &rom->prg_rom[addr];
|
||||||
}
|
}
|
||||||
|
|
||||||
// The second bank is mirrored
|
// The second bank is mirrored
|
||||||
return &rom->prg_rom[relative_addr - PRG_BANK_SIZE];
|
return &rom->prg_rom[addr - PRG_BANK_SIZE];
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte *nrom_ppu_read(address addr) {
|
byte *nrom_ppu_read(address addr) {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
set(HEADERS pattern_table.h ppu.h palette.h
|
set(HEADERS pattern_table.h ppu.h palette.h)
|
||||||
memory.h)
|
set(SOURCE pattern_table.c ppu.c palette.c)
|
||||||
set(SOURCE pattern_table.c ppu.c palette.c
|
|
||||||
memory.c)
|
|
||||||
|
|
||||||
add_library(nes_ppu ${SOURCE} ${HEADERS})
|
add_library(nes_ppu ${SOURCE} ${HEADERS})
|
||||||
|
|
||||||
|
|
48
ppu/memory.c
48
ppu/memory.c
|
@ -1,48 +0,0 @@
|
||||||
//
|
|
||||||
// Created by william on 5/17/24.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
void ppu_vram_fetch(PPUVramFetch *fetch, address addr) {
|
|
||||||
assert(addr < VRAM_SIZE);
|
|
||||||
|
|
||||||
if (fetch->finished) {
|
|
||||||
fetch->finished = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch->data = *fetch->vram[addr];
|
|
||||||
fetch->finished = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ppu_tile_fetch(PPUTileFetch *fetch, address addr) {
|
|
||||||
if (fetch->fetch_cycle >= 8) {
|
|
||||||
fetch->fetch_cycle = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fetch->fetch_cycle % 2 == 0) {
|
|
||||||
// First cycle of a memory fetch
|
|
||||||
ppu_vram_fetch(&fetch->vram_fetch, addr + (fetch->fetch_cycle / 2));
|
|
||||||
} else {
|
|
||||||
// Second cycle of a fetch, the data should be available
|
|
||||||
byte data = fetch->vram_fetch.data;
|
|
||||||
switch (fetch->fetch_cycle) {
|
|
||||||
case 1:
|
|
||||||
fetch->nametable = data;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
fetch->attribute_table = data;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
fetch->pattern_table_tile_low = data;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
fetch->pattern_table_tile_high = data;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
28
ppu/memory.h
28
ppu/memory.h
|
@ -1,28 +0,0 @@
|
||||||
//
|
|
||||||
// Created by william on 5/17/24.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include "../include/types.h"
|
|
||||||
|
|
||||||
#ifndef NES_EMULATOR_MEMORY_H
|
|
||||||
#define NES_EMULATOR_MEMORY_H
|
|
||||||
|
|
||||||
typedef struct ppu_vram_fetch {
|
|
||||||
vram *vram;
|
|
||||||
byte data;
|
|
||||||
bool finished;
|
|
||||||
} PPUVramFetch;
|
|
||||||
|
|
||||||
typedef struct ppu_tile_fetch {
|
|
||||||
byte nametable;
|
|
||||||
byte attribute_table;
|
|
||||||
byte pattern_table_tile_low;
|
|
||||||
byte pattern_table_tile_high;
|
|
||||||
} PPUTileFetch;
|
|
||||||
|
|
||||||
void ppu_vram_fetch(PPUVramFetch *fetch, address addr);
|
|
||||||
|
|
||||||
void ppu_tile_fetch(PPUTileFetch *fetch, address addr);
|
|
||||||
|
|
||||||
#endif //NES_EMULATOR_MEMORY_H
|
|
53
ppu/ppu.c
53
ppu/ppu.c
|
@ -29,12 +29,8 @@
|
||||||
|
|
||||||
PPU ppu_state;
|
PPU ppu_state;
|
||||||
|
|
||||||
void ppu_init(byte *registers_ram, byte *oam_dma_register) {
|
void ppu_init() {
|
||||||
memset(&ppu_state, 0, sizeof(PPU));
|
memset(&ppu_state, 0, sizeof(PPU));
|
||||||
|
|
||||||
ppu_state.oam_dma_register = oam_dma_register;
|
|
||||||
ppu_state.registers = registers_ram;
|
|
||||||
memset(&ppu_state.registers, 0, 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PPU *ppu_get_state() {
|
PPU *ppu_get_state() {
|
||||||
|
@ -62,24 +58,24 @@ void ppu_visible_frame(unsigned int cycle) {
|
||||||
if (cycle == 0) {
|
if (cycle == 0) {
|
||||||
// Idle...
|
// Idle...
|
||||||
} else if (cycle <= 256) {
|
} else if (cycle <= 256) {
|
||||||
byte tile_fetch_cycle = (cycle - 1) % 8;
|
// byte tile_fetch_cycle = (cycle - 1) % 8;
|
||||||
switch (tile_fetch_cycle) {
|
// switch (tile_fetch_cycle) {
|
||||||
case 1:
|
// case 1:
|
||||||
ppu_state.tile_fetch.nametable = ppu_read(ppu_state.ppu_address);
|
// ppu_state.tile_fetch.nametable = ppu_read(ppu_state.ppu_address);
|
||||||
break;
|
// break;
|
||||||
case 3:
|
// case 3:
|
||||||
ppu_state.tile_fetch.attribute_table = ppu_read(ppu_state.ppu_address);
|
// ppu_state.tile_fetch.attribute_table = ppu_read(ppu_state.ppu_address);
|
||||||
break;
|
// break;
|
||||||
case 5:
|
// case 5:
|
||||||
ppu_state.tile_fetch.pattern_table_tile_low = ppu_read(ppu_state.ppu_address);
|
// ppu_state.tile_fetch.pattern_table_tile_low = ppu_read(ppu_state.ppu_address);
|
||||||
break;
|
// break;
|
||||||
case 7:
|
// case 7:
|
||||||
ppu_state.tile_fetch.pattern_table_tile_high = ppu_read(ppu_state.ppu_address);
|
// ppu_state.tile_fetch.pattern_table_tile_high = ppu_read(ppu_state.ppu_address);
|
||||||
ppu_state.ppu_address++;
|
// ppu_state.ppu_address++;
|
||||||
break;
|
// break;
|
||||||
default:
|
// default:
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
} else if (cycle <= 320) {
|
} else if (cycle <= 320) {
|
||||||
// OAMADDR is cleared on sprite loading for pre-render and visible lines
|
// OAMADDR is cleared on sprite loading for pre-render and visible lines
|
||||||
ppu_write_reg(PPU_REGISTER_OAM_ADDR, 0);
|
ppu_write_reg(PPU_REGISTER_OAM_ADDR, 0);
|
||||||
|
@ -180,15 +176,6 @@ byte ppu_read_reg(byte reg) {
|
||||||
return ppu_state.registers[reg];
|
return ppu_state.registers[reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ppu_write_reg_ram(byte reg, byte data) {
|
|
||||||
byte *ppu_ram = mem_get_ptr(PPU_RAM_BASE_ADDR);
|
|
||||||
|
|
||||||
for (int i = 0; i < PPU_RAM_BANK_COUNT; i++) {
|
|
||||||
byte ram_offset = (i * PPU_RAM_BANK_SIZE) + reg;
|
|
||||||
*(ppu_ram + ram_offset) = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ppu_write_reg(byte reg, byte data) {
|
void ppu_write_reg(byte reg, byte data) {
|
||||||
ppu_state.registers[reg] = data;
|
ppu_state.registers[reg] = data;
|
||||||
|
|
||||||
|
@ -234,7 +221,7 @@ void ppu_write_reg(byte reg, byte data) {
|
||||||
ppu_write_reg(PPU_REGISTER_OAM_ADDR, oam_addr + 1);
|
ppu_write_reg(PPU_REGISTER_OAM_ADDR, oam_addr + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ppu_write_reg_ram(reg, data);
|
ppu_state.registers[reg] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte ppu_read(address addr) {
|
byte ppu_read(address addr) {
|
||||||
|
|
|
@ -59,7 +59,7 @@ typedef struct {
|
||||||
struct INesHeaderFlags flags;
|
struct INesHeaderFlags flags;
|
||||||
} INesHeader;
|
} INesHeader;
|
||||||
|
|
||||||
bool rom_is_ines(const char header[16]) {
|
bool rom_is_ines(const byte header[16]) {
|
||||||
return header[0] == 'N' && header[1] == 'E' && header[2] == 'S';
|
return header[0] == 'N' && header[1] == 'E' && header[2] == 'S';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,8 +139,6 @@ bool rom_ines_read_prg_rom(FILE *file, INesHeader *header, Rom *rom) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
system_get_mapper()->post_prg_load(header->prg_rom_size);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,14 +21,13 @@ bool rom_load(char *path) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char header_buffer[ROM_HEADER_SIZE] = {0};
|
size_t read_size = fread(&rom.header, sizeof(byte), ROM_HEADER_SIZE, file);
|
||||||
size_t read_size = fread(header_buffer, sizeof(char), ROM_HEADER_SIZE, file);
|
|
||||||
if (read_size < ROM_HEADER_SIZE) {
|
if (read_size < ROM_HEADER_SIZE) {
|
||||||
log_error("Failed to read ROM");
|
log_error("Failed to read ROM");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rom_is_ines(header_buffer)) {
|
if (!rom_is_ines(rom.header)) {
|
||||||
log_error("Only iNes ROMs are supported");
|
log_error("Only iNes ROMs are supported");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
6
system.c
6
system.c
|
@ -13,11 +13,8 @@
|
||||||
System current_sys;
|
System current_sys;
|
||||||
|
|
||||||
void system_init() {
|
void system_init() {
|
||||||
byte *registers_base_addr = mem_get_ptr(PPU_REGISTERS_BASE_ADDR);
|
|
||||||
byte *oam_dma_register = mem_get_ptr(PPU_REGISTER_OAM_DMA_ADDR);
|
|
||||||
|
|
||||||
cpu_init();
|
cpu_init();
|
||||||
ppu_init(registers_base_addr, oam_dma_register);
|
ppu_init();
|
||||||
|
|
||||||
current_sys.mapper = get_mapper(MAPPER_TYPE_SIMPLE);
|
current_sys.mapper = get_mapper(MAPPER_TYPE_SIMPLE);
|
||||||
current_sys.cycle_count = 7;
|
current_sys.cycle_count = 7;
|
||||||
|
@ -41,7 +38,6 @@ void system_next_frame() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void system_uninit() {
|
void system_uninit() {
|
||||||
ppu_uninit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int system_get_cycles() {
|
unsigned int system_get_cycles() {
|
||||||
|
|
Loading…
Reference in New Issue