diff --git a/SConstruct b/SConstruct index 22a0aa6..524c08d 100644 --- a/SConstruct +++ b/SConstruct @@ -9,4 +9,4 @@ env = Environment(ENV = { 'TERM' : environ['TERM'] }, LINKFLAGS = flags, LIBS = ['SDL2']) -env.Program('laines', Glob('src/*.cpp')) +env.Program('laines', Glob('src/*.cpp') + Glob('src/*/*.cpp')) diff --git a/src/cartridge.cpp b/src/cartridge.cpp index 4ef87b0..7c085c7 100644 --- a/src/cartridge.cpp +++ b/src/cartridge.cpp @@ -6,7 +6,7 @@ namespace Cartridge { -Mapper* mapper; +Mapper* mapper; // Mapper chip. /* PRG-ROM access */ template u8 access(u16 addr, u8 v) diff --git a/src/io.cpp b/src/io.cpp index fb771f0..391f81e 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -4,6 +4,7 @@ namespace IO { + // Screen size: const unsigned width = 256; const unsigned height = 240; @@ -18,6 +19,7 @@ u32 pixels[width * height]; // Video buffer. u8 joypad_bits[2]; // Joypad shift registers. bool strobe; // Joypad strobe latch. +/* Initialize SDL */ void init() { SDL_Init(SDL_INIT_VIDEO); @@ -37,6 +39,7 @@ void init() signal(SIGINT, SIG_DFL); } +/* Get the joypad state from SDL */ u8 get_joypad_state(int n) { u8 j = 0; @@ -56,6 +59,7 @@ u8 get_joypad_state(int n) return j; } +/* Read joypad state (NES register format) */ u8 read_joypad(int n) { // When strobe is high, it keeps reading A: @@ -78,11 +82,13 @@ void write_joypad_strobe(bool v) strobe = v; } +/* Draw a pixel at the given coordinates */ void draw_pixel(unsigned x, unsigned y, u32 rgb) { pixels[y*width + x] = rgb; } +/* Put the pixels on screen */ void flush_screen() { SDL_UpdateTexture(texture, NULL, pixels, width * sizeof(u32)); diff --git a/src/mapper.cpp b/src/mapper.cpp index 90e1971..d9ba898 100644 --- a/src/mapper.cpp +++ b/src/mapper.cpp @@ -2,6 +2,7 @@ Mapper::Mapper(u8* rom) { + // Read infos from header: prgSize = rom[4] * 0x4000; chrSize = rom[5] * 0x2000; prgRamSize = rom[8] ? rom[8] * 0x2000 : 0x2000; @@ -9,8 +10,10 @@ Mapper::Mapper(u8* rom) this->prg = rom + 16; this->prgRam = new u8[prgRamSize]; + // CHR ROM: if (chrSize) this->chr = rom + 16 + prgSize; + // CHR RAM: else { chrSize = 0x2000; diff --git a/src/mappers/mapper1.cpp b/src/mappers/mapper1.cpp new file mode 100644 index 0000000..9f55b8b --- /dev/null +++ b/src/mappers/mapper1.cpp @@ -0,0 +1,76 @@ +#include "mappers/mapper1.hpp" + + +/* Apply the registers state */ +void Mapper1::apply() +{ + // Mirroring. + + // 16KB PRG: + if (regs[0] & 0b1000) + { + // 0x8000 swappable, 0xC000 fixed to bank 0x0F: + if (regs[0] & 0b100) + { + map_prg16k(0, regs[3] & 0xF); + map_prg16k(1, 0xF); + } + // 0x8000 fixed to bank 0x00, 0xC000 swappable: + else + { + map_prg16k(0, 0); + map_prg16k(1, regs[3] & 0xF); + } + } + // 32KB PRG: + else + map_prg32k((regs[3] & 0xF) >> 1); + + // 4KB CHR: + if (regs[0] & 0b10000) + { + map_chr4k(0, regs[1]); + map_chr4k(1, regs[2]); + } + // 8KB CHR: + else + map_chr8k(regs[1] >> 1); +} + +u8 Mapper1::write(u16 addr, u8 v) +{ + // PRG RAM write; + if (addr < 0x8000) + prgRam[addr - 0x6000] = v; + // Mapper register write: + else if (addr & 0x8000) + { + // Reset: + if (v & 0x80) + { + writeN = 0; + tmpReg = 0; + regs[0] |= 0x0C; + apply(); + } + else + { + // Write a bit into the temporary register: + tmpReg = ((v & 1) << 4) | (tmpReg >> 1); + // Finished writing all the bits: + if (++writeN == 5) + { + regs[(addr >> 13) & 0b11] = tmpReg; + writeN = 0; + tmpReg = 0; + apply(); + } + } + } + return v; +} + +u8 Mapper1::chr_write(u16 addr, u8 v) +{ + return chr[addr] = v; +} diff --git a/src/mappers/mapper1.hpp b/src/mappers/mapper1.hpp index 0ef9b30..756b21b 100644 --- a/src/mappers/mapper1.hpp +++ b/src/mappers/mapper1.hpp @@ -4,45 +4,11 @@ class Mapper1 : public Mapper { - private: int writeN; u8 tmpReg; u8 regs[4]; - void apply() - { - // Mirroring. - - // 16KB PRG: - if (regs[0] & 0b1000) - { - // 0x8000 swappable, 0xC000 fixed to bank 0x0F: - if (regs[0] & 0b100) - { - map_prg16k(0, regs[3] & 0xF); - map_prg16k(1, 0xF); - } - // 0x8000 fixed to bank 0x00, 0xC000 swappable: - else - { - map_prg16k(0, 0); - map_prg16k(1, regs[3] & 0xF); - } - } - // 32KB PRG: - else - map_prg32k((regs[3] & 0xF) >> 1); - - // 4KB CHR: - if (regs[0] & 0b10000) - { - map_chr4k(0, regs[1]); - map_chr4k(1, regs[2]); - } - // 8KB CHR: - else - map_chr8k(regs[1] >> 1); - } + void apply(); public: Mapper1(u8* rom) : Mapper(rom) @@ -52,38 +18,6 @@ class Mapper1 : public Mapper apply(); } - u8 write(u16 addr, u8 v) - { - if (addr < 0x8000) - { - prgRam[addr - 0x6000] = v; - } - else if (addr & 0x8000) - { - if (v & 0x80) - { - writeN = 0; - tmpReg = 0; - regs[0] |= 0x0C; - apply(); - } - else - { - tmpReg = ((v & 1) << 4) | (tmpReg >> 1); - if (++writeN == 5) - { - regs[(addr >> 13) & 0b11] = tmpReg; - writeN = 0; - tmpReg = 0; - apply(); - } - } - } - return v; - } - - u8 chr_write(u16 addr, u8 v) - { - return chr[addr] = v; - } + u8 write(u16 addr, u8 v); + u8 chr_write(u16 addr, u8 v); };