Skip to content

Commit

Permalink
UNSTABLE COMMIT. commiting version one of MMC1 shift reg
Browse files Browse the repository at this point in the history
  • Loading branch information
Roeegg2 committed Mar 2, 2024
1 parent 69b4c3b commit 03009e3
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 32 deletions.
1 change: 1 addition & 0 deletions include/mapper_n_cart.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace roee_nes {
friend class NROM_0;
friend class CNROM_3;
friend class UNROM_2;
friend class MMC1_1;
public:
Cartridge(const std::string* rom_path);

Expand Down
8 changes: 7 additions & 1 deletion include/mappers/mmc1_1.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ namespace roee_nes {
void reset();

private:
bool using_chr_ram;
std::vector<uint8_t>* chr_read_mem;
uint8_t shift;
uint8_t load; // NOTE not sure i need this reg

Expand All @@ -37,7 +39,11 @@ namespace roee_nes {
uint8_t bank_1 : 4;
} chr_bank;

uint8_t prg_bank;
struct {
uint8_t bank : 4;
uint8_t ext : 1;
uint8_t : 3;
} prg_bank;

};
}
Expand Down
3 changes: 2 additions & 1 deletion makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# defining compiler and the flags to be used
CXX := g++
CXXFLAGS := -g -Wall -pedantic -std=c++20
CXXFLAGS := -g -Wall -pedantic -std=c++20 # -DDEBUG

# emulator source files
EMU_SRCS := cpu.cpp \
Expand All @@ -15,6 +15,7 @@ EMU_SRCS := cpu.cpp \
mappers/nrom_0.cpp \
mappers/cnrom_3.cpp \
mappers/unrom_2.cpp \
mappers/mmc1_1.cpp \

EMU_OBJS := $(patsubst %.cpp,bin/%.o,$(EMU_SRCS))

Expand Down
29 changes: 12 additions & 17 deletions src/bus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ namespace roee_nes {
}

void Bus::ppu_write(uint16_t addr, uint8_t data, bool came_from_cpu) {
if (0 <= addr && addr <= 0x1fff)
if (0 <= addr && addr <= 0x1fff) {
std::cout << "here\n";
mapper->ppu_write(addr, data);
else if (0x2000 <= addr && addr <= 0x3eff) {
} else if (0x2000 <= addr && addr <= 0x3eff) {
addr %= 0x1000;
addr = mapper->get_nt_mirrored_addr(addr);

Expand All @@ -37,16 +38,16 @@ namespace roee_nes {
if ((addr == 0x10) || (addr == 0x14) || (addr == 0x18) || (addr == 0x1c))
addr -= 0x10;
} else if ((addr & 0b11) == 0)
addr = 0;
addr = 0;

palette_vram[addr] = data;
}
}

uint8_t Bus::ppu_read(uint16_t addr, bool came_from_cpu) {
if (0 <= addr && addr <= 0x1fff)
if (0 <= addr && addr <= 0x1fff) {
return mapper->ppu_read(addr); // pattern table
else if (0x2000 <= addr && addr <= 0x3eff) {
} else if (0x2000 <= addr && addr <= 0x3eff) {
addr %= 0x1000;
addr = mapper->get_nt_mirrored_addr(addr);

Expand Down Expand Up @@ -158,15 +159,13 @@ namespace roee_nes {
} else if (addr == 0x4016) {
controller_1->write(data);
controller_2->write(data);
}
else if (0x4018 <= addr && addr <= 0x401f)
} else if (0x4018 <= addr && addr <= 0x401f)
return; // didnt implement yet
else if (0x4020 <= addr && addr <= 0xffff)
mapper->cpu_write(addr, data);
}

uint8_t Bus::cpu_read(uint16_t addr) {
static std::ofstream c("logs/controller.log");
if (0 <= addr && addr <= 0x1fff)
return ram[addr % 0x800];
else if (0x2000 <= addr && addr <= 0x3fff)
Expand All @@ -175,13 +174,9 @@ namespace roee_nes {
return 0; // didnt implement yet
else if (addr == 0x4016) {
return controller_1->read();
}
else if (addr == 0x4017) {
// c << "before:" << std::bitset<8>(controller_2->read()) << "\n";
} else if (addr == 0x4017) {
return controller_2->read();
// c << "after:" << std::bitset<8>(controller_2->read()) << "\n";
}
else if (0x4018 <= addr && addr <= 0x401f)
} else if (0x4018 <= addr && addr <= 0x401f)
return 0; // didnt implement yet
else if (0x4020 <= addr && addr <= 0xffff)
return mapper->cpu_read(addr);
Expand Down Expand Up @@ -341,10 +336,10 @@ namespace roee_nes {
if (error_found == true) {
std::cerr << "Difference found in " << error << " Line: " << line_cnt << "\n";
return;
}
}
}
}

std::cout << "all goodie!" << "\n";
}
#endif
}
}
6 changes: 5 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ uint16_t emulator_tick(CPU* cpu, PPU* ppu, Bus* bus, NES_Screen* screen, uint8_t
}

int main() {
const std::string rom_path = "roms/PACMAN.nes";
const std::string rom_path = "roms/TETRIS.nes";
const std::string palette_path = "ntscpalette.pal";

Controller* controller_1 = new Controller();
Expand All @@ -42,12 +42,16 @@ int main() {
bus->cpu = cpu;
bus->ppu = ppu;


ppu->reset();
cpu->reset();

uint8_t val = 0;
while (1) {
emulator_tick(cpu, ppu, bus, screen, val);
#ifdef DEBUG
bus->full_log();
#endif
val++;
}

Expand Down
4 changes: 4 additions & 0 deletions src/mapper_n_cart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "../include/mappers/nrom_0.h"
#include "../include/mappers/unrom_2.h"
#include "../include/mappers/cnrom_3.h"
#include "../include/mappers/mmc1_1.h"

namespace roee_nes {
Mapper* Mapper::create_mapper(const std::string* rom_path) {
Expand All @@ -13,6 +14,9 @@ namespace roee_nes {
case 0: // mapper number 0 (NROM)
std::cout << "USER INFO: Game mapper is NROM (iNES 0)\n";
return new NROM_0(cart);
case 1:
std::cout << "USER INFO: Game mapper is MMC1 (iNES 1)\n";
return new MMC1_1(cart);
case 2: // mapper number 2 (UNROM)
std::cout << "USER INFO: Game mapper is UNROM (iNES 2)\n";
return new UNROM_2(cart);
Expand Down
105 changes: 93 additions & 12 deletions src/mappers/mmc1_1.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
#include "../../include/mappers/mmc1_1.h"

#include <bitset>
namespace roee_nes {

MMC1_1::MMC1_1(Cartridge* cart) :
Mapper(cart) {}
Mapper(cart), shift(0b1'0000), ctrl({ 0 }), chr_bank({ 0 }), prg_bank({ 0 }) {
if (cart->chr_rom.size() == 0) {
cart->chr_ram.resize(8 * KILOBYTE);
chr_read_mem = &cart->chr_ram;
using_chr_ram = true;
} else {
using_chr_ram = false;
chr_read_mem = &cart->chr_rom;
}
}

void MMC1_1::cpu_write(uint16_t addr, uint8_t data) {
static std::ofstream templog("logs/TEMP.log");
/**
* NOTE: the initial state of shift reg is 10000. 1 is used to detect 5th write
* if (data has bit 7 set)
Expand All @@ -18,46 +28,117 @@ namespace roee_nes {
* }
*/
if (data & 0b1000'000) {
reset();
shift = 0b0001'0000;
ctrl.comp.prg_rom_mode = 3;
} else {
if (shift & 0b0000'0001) { // if this is the 5th write
// uint8_t temp = (addr & 0b0111'0000'0000'0000) >> 12; // NOTE note sure about this. maybe i should only check bits 13 and 14?
// if ((0x8000 <= addr) && (addr <= 0x9fff)) {

// }
std::cout << "DATA: " << std::bitset<sizeof(data) * 8>(data) << std::endl;
if ((0xa000 <= addr) && (addr <= 0xbfff)) {
chr_bank.bank_0 = ((data & 0b0000'0001) << 5) | (shift & 0b0001'1110);
chr_bank.bank_0 = ((data & 0b0000'0001) << 5) | ((shift & 0b0001'1110) >> 1);
templog << "chr bank 0 is " << (int)prg_bank.bank << "\n";
} else if ((0xc000 <= addr) && (addr <= 0xdfff)) {
chr_bank.bank_1 = ((data & 0b0000'0001) << 5) | (shift & 0b0001'1110);
} else if ((0xe000 <= addr) && (addr <= 0xffff)) {
prg_bank = ((data & 0b0000'0001) << 5) | (shift & 0b0001'1110);
chr_bank.bank_1 = ((data & 0b0000'0001) << 5) | ((shift & 0b0001'1110) >> 1);
templog << "chr bank 1 is " << (int)prg_bank.bank << "\n";
} else {
// if ((0xe000 <= addr) && (addr <= 0xffff)) {
prg_bank.bank = (shift & 0b0001'1110) >> 1;
prg_bank.ext = (data & 0b0000'0001) << 5;
templog << "prg_bank is " << (int)prg_bank.bank << "\n";
}
// else {
// std::cerr << "BAD CPU WRITE! address is " << std::hex << (int)addr << "\n";
// }

shift = 0b0001'0000;
} else { /// emplace back bit 0 of data
std::cout << "data: " << std::bitset<sizeof(data) * 8>(data) << std::endl;
shift >>= 1;
shift |= (0b1000'000 & (data << 7)); // masking just in case
shift |= (0b0001'0000 & (data << 5));
std::cout << "shift: " << std::bitset<sizeof(shift) * 8>(shift) << std::endl;
}
}
}

uint8_t MMC1_1::cpu_read(uint16_t addr) {
switch (ctrl.comp.prg_rom_mode) {
case 0:
case 1: // switch 32 KB at $8000
return cart->prg_rom[((prg_bank.bank & 0b1110) * 32 * KILOBYTE) + addr - 0x8000];
case 2: // fix first bank at $8000 and switch 16 KB bank at $C000
if ((0x8000 <= addr) && (addr <= 0xbfff))
return cart->prg_rom[addr - 0x8000]; // get first bank
else // addr is 0xc000 and over
return cart->prg_rom[(prg_bank.bank * 16 * KILOBYTE) + addr - 0x8000];
case 3:
if ((0x8000 <= addr) && (addr <= 0xbfff))
return cart->prg_rom[(prg_bank.bank * 16 * KILOBYTE) + addr - 0x8000];
else
return cart->prg_rom[addr - 0x8000]; // get first bank
// NOTE WHEN YOU GET BACK!
// you were in the middle of implementing the prg_rom reading, see:
/*
|++--- PRG ROM bank mode (0, 1: switch 32 KB at $8000, ignoring low bit of bank number;
| 2: fix first bank at $8000 and switch 16 KB bank at $C000;
| 3: fix last bank at $C000 and switch 16 KB bank at $8000)
*/
}
}

uint8_t MMC1_1::ppu_read(uint16_t addr) {
static std::ofstream templog("logs/TEMP.log");
switch (ctrl.comp.chr_rom_mode) {
case 0:
return (*chr_read_mem)[(chr_bank.bank_0 * 8 * KILOBYTE) + addr];
default: // case 1:
if ((0x000 <= addr) && (addr <= 0x0fff))
return (*chr_read_mem)[(chr_bank.bank_0 * 4 * KILOBYTE) + addr];
else // if ((0x1000 <= addr) && (addr <= 0x1fff))
return (*chr_read_mem)[(chr_bank.bank_1 * 4 * KILOBYTE) + addr - 0xf000];
}
}

void MMC1_1::ppu_write(uint16_t addr, uint8_t data) {
if (using_chr_ram == true) {
switch (ctrl.comp.chr_rom_mode) {
case 0:
(*chr_read_mem)[(chr_bank.bank_0 * 8 * KILOBYTE) + addr] = data;
case 1:
if ((0x000 <= addr) && (addr <= 0x0fff))
(*chr_read_mem)[(chr_bank.bank_0 * 4 * KILOBYTE) + addr] = data;
else // if ((0x1000 <= addr) && (addr <= 0x1fff))
(*chr_read_mem)[(chr_bank.bank_1 * 4 * KILOBYTE) + addr - 0xf000] = data;

// std::cerr << "MMC1 BAD PPU READ!\n";
// return 0;
}
}
}

void MMC1_1::reset() {
shift = 0b0001'0000;
ctrl.comp.prg_rom_mode = 3;
// set prg rom to bank mode 3 (fixing the last bank at $C000 and allowing the 16 KB bank at $8000 to be switched)
}

uint16_t MMC1_1::get_nt_mirrored_addr(uint16_t addr) {
if (ctrl.comp.mirroring == 0b00)
return addr % 0x400;
else if (ctrl.comp.mirroring == 0b00)
return (addr % 0x400) + 0x400;
return (addr % 0x400) + 0x400;
else if (ctrl.comp.mirroring == 0b10) // vertical
return addr % 0x800;
else if (ctrl.comp.mirroring == 0b11) { // horizontal
else //if (ctrl.comp.mirroring == 0b11)
{ // horizontal
if (addr >= 0x800)
return (addr % 0x400) + 0x400;
else
return addr % 0x400;
}
else
std::cerr << "MMC1 MIRRORING PROBLEM!\n";
// else
// std::cerr << "MMC1 MIRRORING PROBLEM!\n";
}
}

0 comments on commit 03009e3

Please sign in to comment.