NESEmulator/NES Emulator/bus.c

153 lines
2.9 KiB
C
Raw Permalink Normal View History

2021-10-20 20:39:29 +00:00
#include "bus.h"
#include <stdlib.h>
#include <stdio.h>
2021-10-22 22:47:33 +00:00
#include <memory.h>
2021-10-20 20:39:29 +00:00
#include "cpu.h"
2021-10-23 17:30:02 +00:00
#include "ppu.h"
2021-10-20 20:39:29 +00:00
#include "cartridge.h"
2021-10-24 11:47:11 +00:00
struct Bus* createBus(SDL_Renderer* renderer)
2021-10-20 20:39:29 +00:00
{
struct Bus* bus = (struct Bus*)malloc(sizeof(struct Bus));
if (bus == NULL)
{
fprintf(stderr, "Failed to create Bus object, aborting.");
exit(1);
}
// 2KB of memory, equates to 2048 Bytes (0x800)
bus->ram = (Byte*)malloc(0x800);
if (bus->ram == NULL)
{
fprintf(stderr, "Failed to allocate memory for NES RAM, aborting.");
exit(1);
}
2021-10-22 22:47:33 +00:00
memset(bus->ram, 0x00, 0x800);
bus->io = (Byte*)malloc(0x18);
if (bus->io == NULL)
{
fprintf(stderr, "Failed to allocate memory for NES I/O, aborting.");
exit(1);
}
memset(bus->ram, 0x00, 0x18);
2021-10-20 20:39:29 +00:00
2021-10-23 18:16:29 +00:00
// Create and insert cartridge
2021-10-31 00:02:31 +00:00
bus->cartridge = createCartridge(bus, "roms/nestest.nes");
2021-10-23 18:16:29 +00:00
2021-10-20 20:39:29 +00:00
// Create CPU and attach it
bus->cpu = createCPU(bus);
2021-10-23 17:30:02 +00:00
// Create PPU and attack it
2021-10-24 11:47:11 +00:00
bus->screen = renderer;
2021-10-23 17:30:02 +00:00
bus->ppu = createPPU(bus);
2021-10-23 18:36:38 +00:00
bus->masterClockTimer = 0;
2021-10-20 21:23:16 +00:00
2021-10-20 20:39:29 +00:00
return bus;
}
void destroyBus(struct Bus* bus)
{
2021-10-23 17:30:02 +00:00
destroyPPU(bus->ppu);
2021-10-20 20:39:29 +00:00
destroyCPU(bus->cpu);
2021-10-23 18:16:29 +00:00
destroyCartridge(bus->cartridge);
2021-10-20 20:39:29 +00:00
2021-10-22 22:47:33 +00:00
free(bus->io);
2021-10-20 20:39:29 +00:00
free(bus->ram);
free(bus);
}
2021-10-20 21:23:16 +00:00
Byte readBus(struct Bus* bus, Word addr)
2021-10-20 20:39:29 +00:00
{
2021-10-20 21:11:08 +00:00
Byte val = 0;
2021-10-20 20:39:29 +00:00
// Return from the appropriate device depending on the address
if (addr <= 0x1FFF) // RAM (or one of the mirrored addresses)
{
2021-10-20 21:11:08 +00:00
val = bus->ram[addr & 0x7FF];
2021-10-20 20:39:29 +00:00
}
2021-10-23 18:16:29 +00:00
else if (0x2000 <= addr && addr < 0x4000)
{
val = ppuRead(bus->ppu, addr & 0x2007);
}
2021-10-22 22:47:33 +00:00
else if (0x4000 <= addr && addr <= 0x4017) // I/O space
{
2021-10-30 19:01:27 +00:00
switch (addr)
{
case 0x4016:
val = pollInput(&bus->controller);
break;
}
2021-10-22 22:47:33 +00:00
}
2021-10-20 20:39:29 +00:00
else if (0x4020 <= addr && addr <= 0xFFFF) // Cartridge space
{
2021-10-28 14:57:37 +00:00
val = readCartridgeCPU(bus->cartridge, addr);
2021-10-20 20:39:29 +00:00
}
else
{
fprintf(stderr, "Access violation at $%x", addr);
exit(1);
}
2021-10-20 21:11:08 +00:00
return val;
2021-10-20 20:39:29 +00:00
}
2021-10-20 21:23:16 +00:00
void writeBus(struct Bus* bus, Word addr, Byte val)
2021-10-20 20:39:29 +00:00
{
2021-10-20 21:23:16 +00:00
// writeCartridge to the appropriate memory or device
2021-10-20 20:39:29 +00:00
if (addr <= 0x1FFF) // RAM (or one of the mirrored addresses)
{
bus->ram[addr & 0x7FF] = val;
}
2021-10-23 18:16:29 +00:00
else if (0x2000 <= addr && addr < 0x4000)
{
ppuWrite(bus->ppu, addr & 0x2007, val);
}
2021-10-22 22:47:33 +00:00
else if (0x4000 <= addr && addr <= 0x4017) // I/O space
{
2021-10-30 19:01:27 +00:00
switch (addr)
{
case 0x4016:
bus->controller.strobe = (val & 0x1);
if (val & 0x1)
fillRegister(&bus->controller);
break;
}
2021-10-22 22:47:33 +00:00
}
2021-10-20 20:39:29 +00:00
else if (0x4020 <= addr && addr <= 0xFFFF) // Cartridge space
{
2021-10-28 14:57:37 +00:00
writeCartridgeCPU(bus->cartridge, addr, val);
2021-10-20 20:39:29 +00:00
}
else
{
fprintf(stderr, "Access violation at $%x", addr);
exit(1);
}
}
2021-10-21 17:24:53 +00:00
2021-10-23 18:36:38 +00:00
int tick(struct Bus* bus)
2021-10-21 17:24:53 +00:00
{
2021-10-23 18:36:38 +00:00
bus->masterClockTimer++;
2021-10-23 17:30:02 +00:00
2021-10-23 18:36:38 +00:00
tickPPU(bus->ppu);
if (bus->masterClockTimer == 3)
{
tickCPU(bus->cpu);
bus->masterClockTimer = 0;
}
}
int doInstruction(struct Bus* bus)
{
while(bus->cpu->remainingCycles > 0)
tick(bus);
tick(bus);
}
int doFrame(struct Bus* bus)
{
do tick(bus); while (bus->ppu->x != 0 || bus->ppu->y != 0);
2021-10-21 17:24:53 +00:00
}