added ppu
This commit is contained in:
parent
1af2c37b70
commit
19d138fb5f
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required (VERSION 3.8)
|
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)
|
if(MSVC)
|
||||||
target_compile_definitions(nesemu PUBLIC _CRT_SECURE_NO_WARNINGS)
|
target_compile_definitions(nesemu PUBLIC _CRT_SECURE_NO_WARNINGS)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "ppu.h"
|
||||||
#include "cartridge.h"
|
#include "cartridge.h"
|
||||||
|
|
||||||
struct Bus* createBus()
|
struct Bus* createBus()
|
||||||
|
@ -35,6 +36,9 @@ struct Bus* createBus()
|
||||||
// Create CPU and attach it
|
// Create CPU and attach it
|
||||||
bus->cpu = createCPU(bus);
|
bus->cpu = createCPU(bus);
|
||||||
|
|
||||||
|
// Create PPU and attack it
|
||||||
|
bus->ppu = createPPU(bus);
|
||||||
|
|
||||||
// Create and insert cartridge
|
// Create and insert cartridge
|
||||||
bus->cartridge = createCartridge(bus, "roms/nestest.nes");
|
bus->cartridge = createCartridge(bus, "roms/nestest.nes");
|
||||||
|
|
||||||
|
@ -46,6 +50,7 @@ struct Bus* createBus()
|
||||||
void destroyBus(struct Bus* bus)
|
void destroyBus(struct Bus* bus)
|
||||||
{
|
{
|
||||||
destroyCartridge(bus->cartridge);
|
destroyCartridge(bus->cartridge);
|
||||||
|
destroyPPU(bus->ppu);
|
||||||
destroyCPU(bus->cpu);
|
destroyCPU(bus->cpu);
|
||||||
|
|
||||||
free(bus->io);
|
free(bus->io);
|
||||||
|
@ -104,5 +109,8 @@ void writeBus(struct Bus* bus, Word addr, Byte val)
|
||||||
|
|
||||||
void tick(struct Bus* bus)
|
void tick(struct Bus* bus)
|
||||||
{
|
{
|
||||||
tickInstr(bus->cpu);
|
for (int i = 0; i < 3; i++)
|
||||||
|
tickPPU(bus->ppu);
|
||||||
|
|
||||||
|
tickCPU(bus->cpu);
|
||||||
}
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
struct CPU;
|
struct CPU;
|
||||||
|
struct PPU;
|
||||||
struct Cartridge;
|
struct Cartridge;
|
||||||
|
|
||||||
// Main communication path for devices and memory in the NES
|
// Main communication path for devices and memory in the NES
|
||||||
|
@ -13,6 +14,7 @@ struct Bus
|
||||||
Byte* io;
|
Byte* io;
|
||||||
|
|
||||||
struct CPU* cpu;
|
struct CPU* cpu;
|
||||||
|
struct PPU* ppu;
|
||||||
struct Cartridge* cartridge;
|
struct Cartridge* cartridge;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "bus.h"
|
#include "bus.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "ppu.h"
|
||||||
|
|
||||||
void logBusState(struct Bus* bus)
|
void logBusState(struct Bus* bus)
|
||||||
{
|
{
|
||||||
|
@ -40,5 +41,11 @@ void logBusState(struct Bus* bus)
|
||||||
|
|
||||||
printf("%-28s", buffer);
|
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
101
NES Emulator/ppu.c
Normal 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
95
NES Emulator/ppu.h
Normal 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_
|
Loading…
Reference in a new issue