added ppu

This commit is contained in:
Lauchmelder 2021-10-23 19:30:02 +02:00
parent 1af2c37b70
commit 19d138fb5f
6 changed files with 216 additions and 3 deletions

View file

@ -1,6 +1,6 @@
cmake_minimum_required (VERSION 3.8)
add_executable (nesemu "main.c" "cpu.h" "types.h" "bus.h" "bus.c" "cartridge.h" "cpu.c" "cartridge.c" "opcodes.c" "log.c")
add_executable (nesemu "main.c" "cpu.h" "types.h" "bus.h" "bus.c" "cartridge.h" "cpu.c" "cartridge.c" "opcodes.c" "log.c" "ppu.h" "ppu.c")
if(MSVC)
target_compile_definitions(nesemu PUBLIC _CRT_SECURE_NO_WARNINGS)

View file

@ -4,6 +4,7 @@
#include <memory.h>
#include "cpu.h"
#include "ppu.h"
#include "cartridge.h"
struct Bus* createBus()
@ -35,6 +36,9 @@ struct Bus* createBus()
// 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");
@ -46,6 +50,7 @@ struct Bus* createBus()
void destroyBus(struct Bus* bus)
{
destroyCartridge(bus->cartridge);
destroyPPU(bus->ppu);
destroyCPU(bus->cpu);
free(bus->io);
@ -104,5 +109,8 @@ void writeBus(struct Bus* bus, Word addr, Byte val)
void tick(struct Bus* bus)
{
tickInstr(bus->cpu);
for (int i = 0; i < 3; i++)
tickPPU(bus->ppu);
tickCPU(bus->cpu);
}

View file

@ -4,6 +4,7 @@
#include "types.h"
struct CPU;
struct PPU;
struct Cartridge;
// Main communication path for devices and memory in the NES
@ -13,6 +14,7 @@ struct Bus
Byte* io;
struct CPU* cpu;
struct PPU* ppu;
struct Cartridge* cartridge;
};

View file

@ -3,6 +3,7 @@
#include <stdio.h>
#include "bus.h"
#include "cpu.h"
#include "ppu.h"
void logBusState(struct Bus* bus)
{
@ -40,5 +41,11 @@ void logBusState(struct Bus* bus)
printf("%-28s", buffer);
printf("A:%02X X:%02X Y:%02X SP:%02X P:%02X CYC:%zu\n", bus->cpu->acc, bus->cpu->x, bus->cpu->y, bus->cpu->sp, bus->cpu->status.raw, bus->cpu->totalCycles);
printf("A:%02X X:%02X Y:%02X SP:%02X P:%02X PPU:%3d,%3d CYC:%zu\n",
bus->cpu->acc,
bus->cpu->x, bus->cpu->y,
bus->cpu->sp,
bus->cpu->status.raw,
bus->ppu->y, bus->ppu->x,
bus->cpu->totalCycles);
}

101
NES Emulator/ppu.c Normal file
View file

@ -0,0 +1,101 @@
#include "ppu.h"
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "bus.h"
struct PPU* createPPU(struct Bus* parent)
{
struct PPU* ppu = (struct PPU*)malloc(sizeof(struct PPU));
if (ppu == NULL)
{
fprintf(stderr, "Failed to allocate memory for PPU object.\n");
exit(1);
}
ppu->bus = parent;
for (int i = 0; i < 2; i++)
{
ppu->patternTables[i] = (Byte*)malloc(0x1000);
if (ppu->patternTables[i] == NULL)
{
fprintf(stderr, "Failed to allocate memory for PPU pattern table #%d object.\n", i);
exit(1);
}
memset(ppu->patternTables[i], 0, 0x1000);
}
for (int i = 0; i < 4; i++)
{
ppu->nametables[i] = (Byte*)malloc(0x0400);
if (ppu->nametables[i] == NULL)
{
fprintf(stderr, "Failed to allocate memory for PPU nametable #%d object.\n", i);
exit(1);
}
memset(ppu->nametables[i], 0, 0x0400);
}
ppu->paletteIndexes = (Byte*)malloc(0x20);
if (ppu->paletteIndexes == NULL)
{
fprintf(stderr, "Failed to allocate memory for PPU palette RAM indexes.\n");
exit(1);
}
ppu->oam = (Byte*)malloc(0x100);
if (ppu->oam == NULL)
{
fprintf(stderr, "Failed to allocate memory for PPU OAM.\n");
exit(1);
}
ppu->ppuctrl.raw = 0b00000000;
ppu->ppumask.raw = 0b00000000;
ppu->ppustatus.raw = 0b10100000;
ppu->oamaddr = 0x00;
ppu->ppuAddr = 0x00;
ppu->ppuData = 0x00;
ppu->x = 0;
ppu->y = 0;
return ppu;
}
void destroyPPU(struct PPU* ppu)
{
free(ppu->oam);
free(ppu->paletteIndexes);
free(ppu->nametables);
free(ppu->patternTables);
free(ppu);
}
Byte ppuRead(struct PPU* ppu, Word addr)
{
return 0x00;
}
void ppuWrite(struct PPU* ppu, Word addr, Byte val)
{
}
void tickPPU(struct PPU* ppu)
{
ppu->x++;
if (ppu->x == 341)
{
ppu->x = 0;
ppu->y++;
if (ppu->y == 261)
ppu->y = 0;
}
}

95
NES Emulator/ppu.h Normal file
View file

@ -0,0 +1,95 @@
#ifndef _PPU_H_
#define _PPU_H_
#include "types.h"
struct Bus;
struct PPU
{
// REGISTERS
union
{
struct
{
Byte nametable : 2;
Byte increment : 1;
Byte spriteTile : 1;
Byte bgTile : 1;
Byte spriteHeight : 1;
Byte master : 1;
Byte nmiEnable : 1;
};
Byte raw;
} ppuctrl;
union
{
struct
{
Byte greyscale : 1;
Byte bgLeftColumn : 1;
Byte spriteLeftColumn : 1;
Byte bgEnable : 1;
Byte spriteEnable : 1;
Byte colorEmphasis : 3;
};
Byte raw;
} ppumask;
union
{
struct
{
Byte padding : 5;
Byte overflow : 1;
Byte spriteZeroHit : 1;
Byte vBlank : 1;
};
Byte raw;
} ppustatus;
Byte oamaddr;
Byte oamdata;
Byte ppuScroll;
Byte ppuAddr;
Byte ppuData;
Byte oamdma;
Byte* patternTables[2];
Byte* nametables[4];
Byte* paletteIndexes;
union
{
struct
{
Byte y;
Byte tile;
Byte attr;
Byte x;
};
DWord raw;
}* oam;
Word x, y;
struct Bus* bus;
};
struct PPU* createPPU(struct Bus* parent);
void destroyPPU(struct PPU* ppu);
Byte ppuRead(struct PPU* ppu, Word addr);
void ppuWrite(struct PPU* ppu, Word addr, Byte val);
void tickPPU(struct PPU* ppu);
#endif // _PPU_H_