bootrom mostly works, refactoring and all opcodes added
This commit is contained in:
200
src/gameboy.hpp
200
src/gameboy.hpp
@@ -35,9 +35,8 @@ union RegisterPair {
|
||||
};
|
||||
|
||||
class AddressSpace {
|
||||
private:
|
||||
bool bootromLoaded = true;
|
||||
Byte bootrom[BOOTROM_SIZE];
|
||||
Byte bootrom[BOOTROM_SIZE] = {0};
|
||||
std::ifstream game;
|
||||
|
||||
public:
|
||||
@@ -65,50 +64,54 @@ public:
|
||||
Byte specialRam[0x7F]; // Mapped to 0xFF80
|
||||
Byte interuptEnableReg; // Mapped to 0xFFFF
|
||||
};
|
||||
} memoryLayout;
|
||||
} memoryLayout{};
|
||||
|
||||
bool getBootromState();
|
||||
void unmapBootrom();
|
||||
void mapBootrom();
|
||||
void loadBootrom(std::string filename);
|
||||
void loadGame(std::string filename);
|
||||
bool getBootromState() const;
|
||||
void loadBootrom(const std::string& filename);
|
||||
void loadGame(const std::string& filename);
|
||||
|
||||
//overload [] for echo ram and bootrom support
|
||||
Byte operator[](uint32_t address) const {
|
||||
Byte operator[](const uint32_t address) const {
|
||||
if (address >= 0xE000 && address < 0xFE00)
|
||||
return memoryLayout.echoRam[address - 0xE000];
|
||||
return memoryLayout.echoRam[address - 0x2000];
|
||||
if (address < 0x0100 && bootromLoaded)
|
||||
return bootrom[address];
|
||||
else
|
||||
return memoryLayout.memory[address];
|
||||
|
||||
return memoryLayout.memory[address];
|
||||
}
|
||||
|
||||
Byte& operator[](uint32_t address) {
|
||||
Byte& operator[](const uint32_t address) {
|
||||
if (address >= 0xE000 && address < 0xFE00)
|
||||
return memoryLayout.echoRam[address - 0xE000];
|
||||
return memoryLayout.echoRam[address - 0x2000];
|
||||
if (address < 0x0100 && bootromLoaded)
|
||||
return bootrom[address];
|
||||
else
|
||||
return memoryLayout.memory[address];
|
||||
|
||||
return memoryLayout.memory[address];
|
||||
}
|
||||
};
|
||||
|
||||
class GameBoy {
|
||||
private:
|
||||
uint32_t cycles = 0;
|
||||
uint32_t lastOpTicks = 0;
|
||||
uint32_t lastRefresh = 0;
|
||||
uint32_t lastScanline = 0;
|
||||
uint32_t cyclesToStayInHblank = -1;
|
||||
//T-cycles not M-cycles (4 T-cycles = 1 M-cycle)
|
||||
uint64_t cycles = 0;
|
||||
//Start at 2 T-cycles https://github.com/Gekkio/mooneye-test-suite/blob/main/acceptance/ppu/lcdon_timing-GS.s
|
||||
uint64_t ppuCycles = 2;
|
||||
bool ppuEnabled = false;
|
||||
uint64_t lastOpTicks = 0;
|
||||
uint64_t lastRefresh = 0;
|
||||
uint64_t lastScanline = 0;
|
||||
uint64_t cyclesToStayInHblank = -1;
|
||||
uint64_t lastDivUpdate = 0;
|
||||
|
||||
uint8_t IME = 0; //enables interupts
|
||||
|
||||
//Accumulator and flags
|
||||
RegisterPair AF;
|
||||
RegisterPair AF = {0};
|
||||
//General purpose CPU registers
|
||||
RegisterPair BC;
|
||||
RegisterPair DE;
|
||||
RegisterPair HL;
|
||||
RegisterPair BC = {0};
|
||||
RegisterPair DE = {0};
|
||||
RegisterPair HL = {0};
|
||||
|
||||
Word SP = 0xFFFE; //stack pointer
|
||||
Word PC = 0x0000; //program counter
|
||||
@@ -116,70 +119,74 @@ private:
|
||||
AddressSpace addressSpace;
|
||||
|
||||
//General purpose hardware registers
|
||||
Byte* JOYP = &addressSpace[0xFF00];
|
||||
Byte* SB = &addressSpace[0xFF01];
|
||||
Byte* SC = &addressSpace[0xFF02];
|
||||
Byte* DIV = &addressSpace[0xFF04];
|
||||
Byte* const JOYP = &addressSpace[0xFF00];
|
||||
|
||||
Byte* const SB = &addressSpace[0xFF01];
|
||||
Byte* const SC = &addressSpace[0xFF02];
|
||||
Byte* const DIV = &addressSpace[0xFF04];
|
||||
|
||||
//Timer registers
|
||||
Byte* TIMA = &addressSpace[0xFF05];
|
||||
Byte* TMA = &addressSpace[0xFF15]; //unused
|
||||
Byte* TAC = &addressSpace[0xFF16];
|
||||
Byte* const TIMA = &addressSpace[0xFF05];
|
||||
Byte* const TMA = &addressSpace[0xFF15]; //unused
|
||||
Byte* const TAC = &addressSpace[0xFF16];
|
||||
|
||||
//interrupt flag and enable
|
||||
Byte* IF = &addressSpace[0xFF0F];
|
||||
Byte* IE = &addressSpace[0xFFFF];
|
||||
Byte* const IF = &addressSpace[0xFF0F];
|
||||
Byte* const IE = &addressSpace[0xFFFF];
|
||||
|
||||
//Sound registers
|
||||
Byte* NR10 = &addressSpace[0xFF10];
|
||||
Byte* NR11 = &addressSpace[0xFF11];
|
||||
Byte* NR12 = &addressSpace[0xFF12];
|
||||
Byte* NR13 = &addressSpace[0xFF13];
|
||||
Byte* NR14 = &addressSpace[0xFF14];
|
||||
Byte* NR20 = &addressSpace[0xFF15]; //unused
|
||||
Byte* NR21 = &addressSpace[0xFF16];
|
||||
Byte* NR22 = &addressSpace[0xFF17];
|
||||
Byte* NR23 = &addressSpace[0xFF18];
|
||||
Byte* NR24 = &addressSpace[0xFF19];
|
||||
Byte* NR30 = &addressSpace[0xFF1A];
|
||||
Byte* NR31 = &addressSpace[0xFF1B];
|
||||
Byte* NR32 = &addressSpace[0xFF1C];
|
||||
Byte* NR33 = &addressSpace[0xFF1D];
|
||||
Byte* NR34 = &addressSpace[0xFF1E];
|
||||
Byte* NR40 = &addressSpace[0xFF1F]; //unused
|
||||
Byte* NR41 = &addressSpace[0xFF20];
|
||||
Byte* NR42 = &addressSpace[0xFF21];
|
||||
Byte* NR43 = &addressSpace[0xFF22];
|
||||
Byte* NR44 = &addressSpace[0xFF23];
|
||||
Byte* NR50 = &addressSpace[0xFF24];
|
||||
Byte* NR51 = &addressSpace[0xFF25];
|
||||
Byte* NR52 = &addressSpace[0xFF26];
|
||||
Byte* waveRam = &addressSpace[0xFF30]; //WaveRam[0x10]
|
||||
Byte* const NR10 = &addressSpace[0xFF10];
|
||||
Byte* const NR11 = &addressSpace[0xFF11];
|
||||
Byte* const NR12 = &addressSpace[0xFF12];
|
||||
Byte* const NR13 = &addressSpace[0xFF13];
|
||||
Byte* const NR14 = &addressSpace[0xFF14];
|
||||
Byte* const NR20 = &addressSpace[0xFF15]; //unused
|
||||
Byte* const NR21 = &addressSpace[0xFF16];
|
||||
Byte* const NR22 = &addressSpace[0xFF17];
|
||||
Byte* const NR23 = &addressSpace[0xFF18];
|
||||
Byte* const NR24 = &addressSpace[0xFF19];
|
||||
Byte* const NR30 = &addressSpace[0xFF1A];
|
||||
Byte* const NR31 = &addressSpace[0xFF1B];
|
||||
Byte* const NR32 = &addressSpace[0xFF1C];
|
||||
Byte* const NR33 = &addressSpace[0xFF1D];
|
||||
Byte* const NR34 = &addressSpace[0xFF1E];
|
||||
Byte* const NR40 = &addressSpace[0xFF1F]; //unused
|
||||
Byte* const NR41 = &addressSpace[0xFF20];
|
||||
Byte* const NR42 = &addressSpace[0xFF21];
|
||||
Byte* const NR43 = &addressSpace[0xFF22];
|
||||
Byte* const NR44 = &addressSpace[0xFF23];
|
||||
Byte* const NR50 = &addressSpace[0xFF24];
|
||||
Byte* const NR51 = &addressSpace[0xFF25];
|
||||
Byte* const NR52 = &addressSpace[0xFF26];
|
||||
Byte* const waveRam = &addressSpace[0xFF30]; //WaveRam[0x10]
|
||||
|
||||
//PPU registers
|
||||
Byte* LCDC = &addressSpace[0xFF40];
|
||||
Byte* STAT = &addressSpace[0xFF41];
|
||||
Byte* SCY = &addressSpace[0xFF42];
|
||||
Byte* SCX = &addressSpace[0xFF43];
|
||||
Byte* LY = &addressSpace[0xFF44];
|
||||
Byte* LYC = &addressSpace[0xFF45];
|
||||
Byte* DMA = &addressSpace[0xFF46];
|
||||
Byte* BGP = &addressSpace[0xFF47];
|
||||
Byte* OBP0 = &addressSpace[0xFF48];
|
||||
Byte* OBP1 = &addressSpace[0xFF49];
|
||||
Byte* WY = &addressSpace[0xFF4A];
|
||||
Byte* WX = &addressSpace[0xFF4B];
|
||||
Byte* const LCDC = &addressSpace[0xFF40];
|
||||
Byte* const STAT = &addressSpace[0xFF41];
|
||||
Byte* const SCY = &addressSpace[0xFF42];
|
||||
Byte* const SCX = &addressSpace[0xFF43];
|
||||
Byte* const LY = &addressSpace[0xFF44];
|
||||
Byte* const LYC = &addressSpace[0xFF45];
|
||||
Byte* const DMA = &addressSpace[0xFF46];
|
||||
Byte* const BGP = &addressSpace[0xFF47];
|
||||
Byte* const OBP0 = &addressSpace[0xFF48];
|
||||
Byte* const OBP1 = &addressSpace[0xFF49];
|
||||
Byte* const WY = &addressSpace[0xFF4A];
|
||||
Byte* const WX = &addressSpace[0xFF4B];
|
||||
|
||||
PPUMode currentMode;
|
||||
PPUMode currentMode = PPUMode::mode0;
|
||||
|
||||
//3 colour channels
|
||||
uint32_t* framebuffer = new uint32_t[RESOLUTION_X * RESOLUTION_Y * SCREEN_BPP];
|
||||
SDL_Window* screen;
|
||||
SDL_Renderer* renderer;
|
||||
SDL_Texture* texture;
|
||||
SDL_Event event;
|
||||
SDL_Window* screen = nullptr;
|
||||
SDL_Renderer* renderer = nullptr;
|
||||
SDL_Texture* texture = nullptr;
|
||||
SDL_Event event = {0};
|
||||
uint32_t frameStart = 0;
|
||||
uint32_t frameTime = 0;
|
||||
const int frameDelay = 1000 / V_SYNC;
|
||||
|
||||
void opcodeHandler();
|
||||
void opcodeResolver();
|
||||
void incLY();
|
||||
void ppuUpdate();
|
||||
void drawLine();
|
||||
@@ -187,12 +194,14 @@ private:
|
||||
|
||||
void checkPPUMode();
|
||||
void setPPUMode(PPUMode mode);
|
||||
uint32_t cyclesSinceLastScanline();
|
||||
uint32_t cyclesSinceLastRefresh();
|
||||
uint64_t cyclesSinceLastScanline() const;
|
||||
uint64_t cyclesSinceLastRefresh() const;
|
||||
|
||||
void timingHandler();
|
||||
|
||||
void interruptHandler();
|
||||
bool testInterruptEnabled(Byte interrupt);
|
||||
void resetInterrupt(Byte interrupt);
|
||||
bool testInterruptEnabled(Byte interrupt) const;
|
||||
void resetInterrupt(Byte interrupt) const;
|
||||
|
||||
void VBlankHandle();
|
||||
void LCDStatHandle();
|
||||
@@ -220,17 +229,24 @@ private:
|
||||
void andBitwise(T& dest, T src);
|
||||
template <typename T>
|
||||
void xorBitwise(T& dest, T src);
|
||||
template <typename T>
|
||||
void bit(T testBit, T reg);
|
||||
void bit(Byte testBit, Byte reg);
|
||||
void extendedOpcodeResolver();
|
||||
static void set(const uint8_t testBit, uint8_t& reg);
|
||||
static void res(const uint8_t testBit, uint8_t& reg);
|
||||
template <typename T>
|
||||
void jp(T address);
|
||||
template <typename T>
|
||||
bool jrNZ(T offset);
|
||||
template <class T>
|
||||
bool jrNC(T offset);
|
||||
template <class T>
|
||||
bool jrC(T offset);
|
||||
template <typename T>
|
||||
void inc(T& reg);
|
||||
template <typename T>
|
||||
void call(T address);
|
||||
void halt();
|
||||
void daa();
|
||||
void stop();
|
||||
template <typename T>
|
||||
void ldW(T dest, T src);
|
||||
@@ -242,29 +258,41 @@ private:
|
||||
bool jrZ(T offset);
|
||||
template <typename T>
|
||||
void sub(T value);
|
||||
template <class T>
|
||||
void sbc(T value);
|
||||
template <typename T>
|
||||
void jr(T OFFSET);
|
||||
template <typename T>
|
||||
void push(T reg);
|
||||
template <typename T>
|
||||
void rl(T& reg);
|
||||
void rl(Byte& reg);
|
||||
void sla(Byte& reg);
|
||||
void sra(uint8_t& reg);
|
||||
void srl(uint8_t& reg);
|
||||
void rrc(Byte& reg);
|
||||
void rrca();
|
||||
void rra();
|
||||
void rr(Byte& reg);
|
||||
void rlc(Byte& reg);
|
||||
void rlca();
|
||||
void rla();
|
||||
template <typename T>
|
||||
void pop(T& reg);
|
||||
template <typename T>
|
||||
void rla(T& reg);
|
||||
template <typename T>
|
||||
void rst(T address);
|
||||
void ret();
|
||||
template <typename T>
|
||||
void add(T& reg, T value);
|
||||
template <class T>
|
||||
void adc(T& reg, T value);
|
||||
void cpl();
|
||||
void scf();
|
||||
void ccf();
|
||||
void swap(Byte& value);
|
||||
|
||||
public:
|
||||
void start(std::string bootrom, std::string game);
|
||||
void SDL2setup();
|
||||
void SDL2destroy();
|
||||
void SDL2destroy() const;
|
||||
};
|
||||
|
||||
#endif //GBPP_SRC_GAMEBOY_HPP_
|
||||
|
||||
Reference in New Issue
Block a user