WIP initial state
This commit is contained in:
parent
6cacf1ae80
commit
ba5b55a196
10 changed files with 337 additions and 0 deletions
5
Makeconf
Normal file
5
Makeconf
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
modules := test \
|
||||||
|
memory/bus \
|
||||||
|
memory/ram
|
||||||
|
|
||||||
|
CXX_FLAGS := -I $(CURDIR)
|
10
Makefile
Normal file
10
Makefile
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
include Makeconf
|
||||||
|
|
||||||
|
$(info $(modules))
|
||||||
|
objs := $(addsuffix .o,$(modules))
|
||||||
|
|
||||||
|
%.o: %.cpp
|
||||||
|
g++ $(CXX_FLAGS) -c -o $@ $^
|
||||||
|
|
||||||
|
vgbc: $(objs)
|
||||||
|
g++ -o $@ $^
|
62
cpu/cpu.h
Normal file
62
cpu/cpu.h
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
class Cpu;
|
||||||
|
class Mem_device;
|
||||||
|
|
||||||
|
enum Flags {
|
||||||
|
F_ZERO = 0x8,
|
||||||
|
F_SUB = 0x4,
|
||||||
|
F_HALF = 0x2,
|
||||||
|
F_CARRY = 0x1,
|
||||||
|
};
|
||||||
|
|
||||||
|
union Register_pair {
|
||||||
|
struct { u8 hi; u8 lo; }
|
||||||
|
u16 hilo;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Cpu_state {
|
||||||
|
// Registers
|
||||||
|
union {
|
||||||
|
u16 BC;
|
||||||
|
struct { u8 B; u8 C; };
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
u16 DE;
|
||||||
|
struct { u8 D; u8 E; };
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
u16 HL;
|
||||||
|
struct { u8 H; u8 L; };
|
||||||
|
};
|
||||||
|
|
||||||
|
u8 A;
|
||||||
|
u16 SP;
|
||||||
|
u16 PC;
|
||||||
|
|
||||||
|
bool zero;
|
||||||
|
bool subtract;
|
||||||
|
bool halfcarry;
|
||||||
|
bool carry;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Cpu {
|
||||||
|
private:
|
||||||
|
Cpu_state state;
|
||||||
|
Mem_device* bus;
|
||||||
|
|
||||||
|
typedef u8 opcode_t;
|
||||||
|
|
||||||
|
private:
|
||||||
|
u8 readPC();
|
||||||
|
|
||||||
|
void pushStack(u8 data);
|
||||||
|
u8 popStack();
|
||||||
|
|
||||||
|
public:
|
||||||
|
Cpu();
|
||||||
|
|
||||||
|
void step();
|
||||||
|
};
|
108
cpu/decoder.cpp
Normal file
108
cpu/decoder.cpp
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
#include "cpu/cpu.h"
|
||||||
|
|
||||||
|
u8 Cpu::readPC8()
|
||||||
|
{
|
||||||
|
u8 data = bus->read8(state.PC);
|
||||||
|
state.PC++;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 Cpu::readPC16()
|
||||||
|
{
|
||||||
|
u16 data = bus->read16(state.PC);
|
||||||
|
state.PC+=2;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pushStack8(u8 data)
|
||||||
|
{
|
||||||
|
bus->write8(state.SP, data);
|
||||||
|
state.SP--;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 popStack8()
|
||||||
|
{
|
||||||
|
u8 data = bus->read8(state.SP);
|
||||||
|
state.SP++;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pushStack16(u16 data)
|
||||||
|
{
|
||||||
|
bus->write16(state.SP,data);
|
||||||
|
state.SP-=2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void popStack16()
|
||||||
|
{
|
||||||
|
u16 data = bus->read16(state.SP);
|
||||||
|
state.SP+=2;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cpu::step()
|
||||||
|
{
|
||||||
|
opcode_t op = readPC();
|
||||||
|
int mcycles = 1;
|
||||||
|
switch(op) {
|
||||||
|
0x00: // NOP
|
||||||
|
(void) ;;
|
||||||
|
|
||||||
|
0x01: // LD BC, n16
|
||||||
|
state.BC = readPC16(); mcycles = 12;;
|
||||||
|
0x11: // LD DE, n16
|
||||||
|
state.DE = readPC16(); mcycles = 12;;
|
||||||
|
0x21: // LD HL, n16
|
||||||
|
state.HL = readPC16(); mcycles = 12;;
|
||||||
|
0x31: // LD SP, n16
|
||||||
|
state.SP = readPC16(); mcycles = 12;;
|
||||||
|
|
||||||
|
0x02: // LD [BC], A
|
||||||
|
bus->write8(state.BC, state.A); mcycles = 8;;
|
||||||
|
0x12: // LD [DE], A
|
||||||
|
bus->write8(state.DE, state.A); mcycles = 8;;
|
||||||
|
0x22: // LD [HL+], A
|
||||||
|
bus->write8(state.HL, state.A); state.HL++; mcycles = 8;;
|
||||||
|
0x32: // LD [HL-], A
|
||||||
|
bus->write8(state.HL, state.A); state.HL--; mcycles = 8;;
|
||||||
|
|
||||||
|
0x03: // INC BC
|
||||||
|
state.BC++; mcycles = 2;;
|
||||||
|
0x13: // INC DE
|
||||||
|
state.DE++; mcycles = 2;;
|
||||||
|
0x23: // INC HL
|
||||||
|
state.HL++; mcycles = 2;;
|
||||||
|
0x33: // INC SP
|
||||||
|
state.SP++; mcycles = 2;;
|
||||||
|
|
||||||
|
0x04: // INC B
|
||||||
|
state.B++;
|
||||||
|
state.zero = (state.B == 0);
|
||||||
|
state.subtract = false;
|
||||||
|
state.halfcarry = (state.B & 0x0F == 0);
|
||||||
|
;
|
||||||
|
0x14: // INC D
|
||||||
|
state.D++;
|
||||||
|
state.zero = (state.D == 0);
|
||||||
|
state.subtract = false;
|
||||||
|
state.halfcarry = (state.D & 0x0F == 0);
|
||||||
|
;
|
||||||
|
0x24: // INC H
|
||||||
|
state.H++;
|
||||||
|
state.zero = (state.H == 0);
|
||||||
|
state.subtract = false;
|
||||||
|
state.halfcarry = (state.H & 0x0F == 0);
|
||||||
|
;
|
||||||
|
0x34: // INC [HL]
|
||||||
|
u8 data = bus->read8(state.HL);
|
||||||
|
data++;
|
||||||
|
bus->write8(state.HL, data);
|
||||||
|
state.zero = (data == 0);
|
||||||
|
state.subtract = false;
|
||||||
|
state.halfcarry = (data & 0x0F == 0);
|
||||||
|
mcycles = 3;
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
51
memory/bus.cpp
Normal file
51
memory/bus.cpp
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#include "bus.h"
|
||||||
|
|
||||||
|
Bus::Bus() : map() {}
|
||||||
|
|
||||||
|
std::optional<Bus::MapEntry> Bus::find_entry(u16 addr)
|
||||||
|
{
|
||||||
|
for(auto it = map.begin(); it != map.end(); ++it)
|
||||||
|
{
|
||||||
|
if (addr >= it->start && addr <= it->end)
|
||||||
|
return std::make_optional(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bus::map_device(u16 start, u16 end, Mem_device* dev)
|
||||||
|
{
|
||||||
|
map.push_back(Bus::MapEntry{ start, end, dev });
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bus::write8(u16 addr, u8 data)
|
||||||
|
{
|
||||||
|
auto mapentry = find_entry(addr);
|
||||||
|
|
||||||
|
if(!mapentry) return;
|
||||||
|
|
||||||
|
mapentry->dev->write8(addr - mapentry->start, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 Bus::read8(u16 addr)
|
||||||
|
{
|
||||||
|
auto mapentry = find_entry(addr);
|
||||||
|
|
||||||
|
if(!mapentry) return 0xFFu;
|
||||||
|
|
||||||
|
return mapentry->dev->read8(addr - mapentry->start);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bus::write16(u16 addr, u16 data)
|
||||||
|
{
|
||||||
|
auto mapentry = find_entry(addr);
|
||||||
|
if(!mapentry) return;
|
||||||
|
mapentry->dev->write16(addr - mapentry->start, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 Bus::read16(u16 addr)
|
||||||
|
{
|
||||||
|
auto mapentry = find_entry(addr);
|
||||||
|
if(!mapentry) return 0xFFFFu;
|
||||||
|
return mapentry->dev->read16(addr - mapentry->start);
|
||||||
|
}
|
31
memory/bus.h
Normal file
31
memory/bus.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "mem_device.h"
|
||||||
|
|
||||||
|
class Bus : public Mem_device {
|
||||||
|
private:
|
||||||
|
struct MapEntry {
|
||||||
|
u16 start;
|
||||||
|
u16 end;
|
||||||
|
Mem_device *dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::optional<MapEntry> find_entry(u16 addr);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Bus();
|
||||||
|
|
||||||
|
void map_device(u16 start, u16 end, Mem_device* dev);
|
||||||
|
|
||||||
|
virtual void write8(u16 addr, u8 data);
|
||||||
|
virtual u8 read8(u16 addr);
|
||||||
|
|
||||||
|
virtual void write16(u16 addr, u16 data);
|
||||||
|
virtual u16 read16(u16 addr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<MapEntry> map;
|
||||||
|
};
|
12
memory/mem_device.h
Normal file
12
memory/mem_device.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
class Mem_device {
|
||||||
|
public:
|
||||||
|
virtual void write8(u16 addr, u8 data) = 0;
|
||||||
|
virtual u8 read8(u16 addr) = 0;
|
||||||
|
|
||||||
|
virtual void write16(u16 addr, u16 data) = 0;
|
||||||
|
virtual u16 read16(u16 addr) = 0;
|
||||||
|
};
|
31
memory/ram.cpp
Normal file
31
memory/ram.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "ram.h"
|
||||||
|
|
||||||
|
RAM::RAM(u16 size) : size(size), readonly(false) {
|
||||||
|
memory = new u8[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
RAM::RAM(u8* memory, u16 size, bool readonly = false)
|
||||||
|
: memory(memory), size(size), readonly(readonly)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void RAM::write8(u16 addr, u8 data) {
|
||||||
|
if(addr >= size || readonly) return;
|
||||||
|
memory[addr] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 RAM::read8(u16 addr) {
|
||||||
|
if (addr >= size) return 0xFFu;
|
||||||
|
return memory[addr];
|
||||||
|
}
|
||||||
|
|
||||||
|
void RAM::write16(u16 addr, u16 data) {
|
||||||
|
if(addr >= size - 1 || readonly) return;
|
||||||
|
u16 *ptr = (u16*)&memory[addr];
|
||||||
|
*ptr = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 RAM::read16(u16 addr) {
|
||||||
|
if(addr >= size - 1) return;
|
||||||
|
u16 *ptr = (u16*)&memory[addr];
|
||||||
|
return *ptr;
|
||||||
|
}
|
20
memory/ram.h
Normal file
20
memory/ram.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "mem_device.h"
|
||||||
|
|
||||||
|
class RAM : public Mem_device {
|
||||||
|
private:
|
||||||
|
u8* memory;
|
||||||
|
u16 size;
|
||||||
|
bool readonly;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RAM(u16 size);
|
||||||
|
RAM(u8* memory, u16 size, bool readonly = false);
|
||||||
|
|
||||||
|
virtual void write8(u16 addr, u8 data);
|
||||||
|
virtual u8 read8(u16 addr);
|
||||||
|
|
||||||
|
virtual void write16(u16 addr, u16 data);
|
||||||
|
virtual u16 read16(u16 addr);
|
||||||
|
};
|
7
types.h
Normal file
7
types.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef unsigned char u8;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
|
||||||
|
typedef signed char s8;
|
||||||
|
typedef signed short s16;
|
Loading…
Reference in a new issue