diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..712e7b5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vendor/SDL"] + path = vendor/SDL + url = https://github.com/libsdl-org/SDL diff --git a/NES Emulator/bus.c b/NES Emulator/bus.c index 19b8a63..31429b7 100644 --- a/NES Emulator/bus.c +++ b/NES Emulator/bus.c @@ -33,15 +33,15 @@ struct Bus* createBus() } memset(bus->ram, 0x00, 0x18); + // Create and insert cartridge + bus->cartridge = createCartridge(bus, "roms/nestest.nes"); + // Create CPU and attach it bus->cpu = createCPU(bus); // Create PPU and attack it bus->ppu = createPPU(bus); - // Create and insert cartridge - bus->cartridge = createCartridge(bus, "roms/nestest.nes"); - printf("Reset vector: $%x\n", ((Word)readCartridge(bus->cartridge, 0xFFFD) << 8) | (readCartridge(bus->cartridge, 0xFFFC))); return bus; @@ -49,9 +49,9 @@ struct Bus* createBus() void destroyBus(struct Bus* bus) { - destroyCartridge(bus->cartridge); destroyPPU(bus->ppu); destroyCPU(bus->cpu); + destroyCartridge(bus->cartridge); free(bus->io); free(bus->ram); @@ -67,6 +67,10 @@ Byte readBus(struct Bus* bus, Word addr) { val = bus->ram[addr & 0x7FF]; } + else if (0x2000 <= addr && addr < 0x4000) + { + val = ppuRead(bus->ppu, addr & 0x2007); + } else if (0x4000 <= addr && addr <= 0x4017) // I/O space { val = bus->io[addr - 0x4000]; @@ -91,6 +95,10 @@ void writeBus(struct Bus* bus, Word addr, Byte val) { bus->ram[addr & 0x7FF] = val; } + else if (0x2000 <= addr && addr < 0x4000) + { + ppuWrite(bus->ppu, addr & 0x2007, val); + } else if (0x4000 <= addr && addr <= 0x4017) // I/O space { bus->io[addr - 0x4000] = val; diff --git a/NES Emulator/cartridge.c b/NES Emulator/cartridge.c index 828a837..ab4e989 100644 --- a/NES Emulator/cartridge.c +++ b/NES Emulator/cartridge.c @@ -85,7 +85,7 @@ Byte readCartridge(struct Cartridge* cartridge, Word addr) } else if (0x8000 <= addr && addr <= 0xFFFF) // PRG ROM { - val = cartridge->prg_rom[addr & 0x3FFF]; + val = cartridge->prg_rom[addr % 0x4000]; } return val; @@ -101,7 +101,7 @@ void writeCartridge(struct Cartridge* cartridge, Word addr, Byte val) } else if (0x8000 <= addr && addr <= 0xFFFF) // PRG ROM { - cartridge->prg_rom[addr & 0x1FFF] = val; + cartridge->prg_rom[addr % 0x4000] = val; } } diff --git a/NES Emulator/cpu.c b/NES Emulator/cpu.c index 29c074d..4e35d7a 100644 --- a/NES Emulator/cpu.c +++ b/NES Emulator/cpu.c @@ -25,7 +25,8 @@ struct CPU* createCPU(struct Bus* parent) } // TODO: THIS IS JUST FOR THE TEST ROM - cpu->pc.word = 0xC000; + // cpu->pc.word = 0xC000; + cpu->pc.word = ((Word)readBus(parent, 0xFFFD) << 8) | readBus(parent, 0xFFFC); cpu->status.raw = 0x34; cpu->acc = 0; diff --git a/NES Emulator/ppu.c b/NES Emulator/ppu.c index c9a1cbd..f723d27 100644 --- a/NES Emulator/ppu.c +++ b/NES Emulator/ppu.c @@ -54,12 +54,17 @@ struct PPU* createPPU(struct Bus* parent) exit(1); } - ppu->ppuctrl.raw = 0b00000000; - ppu->ppumask.raw = 0b00000000; - ppu->ppustatus.raw = 0b10100000; + ppu->ppuCtrl.raw = 0b00000000; + ppu->ppuMask.raw = 0b00000000; + ppu->ppuStatus.raw = 0b10100000; ppu->oamaddr = 0x00; - ppu->ppuAddr = 0x00; - ppu->ppuData = 0x00; + + ppu->scrollX = 0; + ppu->scrollY = 0; + ppu->scrollWriteTarget = 0; + + ppu->ppuAddress.raw = 0x00; + ppu->ppuAddressWriteTarget = 0; ppu->x = 0; ppu->y = 0; @@ -79,11 +84,72 @@ void destroyPPU(struct PPU* ppu) Byte ppuRead(struct PPU* ppu, Word addr) { - return 0x00; + Byte val = 0x00; + switch (addr) + { + case 0x2000: + break; + + case 0x2001: + break; + + case 0x2002: + val = ppu->ppuStatus.raw; + break; + + case 0x2005: + break; + + case 0x2006: + break; + + case 0x2007: + val = ppu->nametables[ppu->ppuAddress.raw & 0x2000][ppu->ppuAddress.raw & 0x1FFF]; + ppu->ppuAddress.raw += ppu->ppuCtrl.increment; + break; + + default: + fprintf(stderr, "Read access violation at PPU register $%04X", addr); + exit(1); + } + + return val; } void ppuWrite(struct PPU* ppu, Word addr, Byte val) { + switch (addr) + { + case 0x2000: + ppu->ppuCtrl.raw = val; + break; + + case 0x2001: + ppu->ppuMask.raw = val; + break; + + case 0x2002: + break; + + case 0x2005: + *((&ppu->scrollX) + ppu->scrollWriteTarget) = val; + ppu->scrollWriteTarget = 1 - ppu->scrollWriteTarget; + break; + + case 0x2006: + *((&ppu->ppuAddress.lo) + ppu->ppuAddressWriteTarget) = val; + ppu->ppuAddressWriteTarget = 1 - ppu->ppuAddressWriteTarget; + break; + + case 0x2007: + ppu->nametables[ppu->ppuAddress.raw & 0x2000][ppu->ppuAddress.raw & 0x1FFF] = val; + ppu->ppuAddress.raw += ppu->ppuCtrl.increment; + break; + + default: + fprintf(stderr, "Write access violation at PPU register: $%04X", addr); + exit(1); + } } void tickPPU(struct PPU* ppu) diff --git a/NES Emulator/ppu.h b/NES Emulator/ppu.h index 91ee4dd..f5b8d71 100644 --- a/NES Emulator/ppu.h +++ b/NES Emulator/ppu.h @@ -23,7 +23,7 @@ struct PPU Byte raw; - } ppuctrl; + } ppuCtrl; union { @@ -39,7 +39,7 @@ struct PPU Byte raw; - } ppumask; + } ppuMask; union { @@ -53,13 +53,26 @@ struct PPU Byte raw; - } ppustatus; + } ppuStatus; Byte oamaddr; Byte oamdata; - Byte ppuScroll; - Byte ppuAddr; - Byte ppuData; + + Byte scrollX, scrollY; + Byte scrollWriteTarget; + + union + { + struct + { + Byte lo; + Byte hi; + }; + + Word raw; + } ppuAddress; + Byte ppuAddressWriteTarget; + Byte oamdma; Byte* patternTables[2]; @@ -81,6 +94,8 @@ struct PPU Word x, y; + + struct Bus* bus; }; diff --git a/vendor/SDL b/vendor/SDL new file mode 160000 index 0000000..a76b73d --- /dev/null +++ b/vendor/SDL @@ -0,0 +1 @@ +Subproject commit a76b73dd2cbf50102c7c9a8fa1ebdda128db72fc