Emu?
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

167 lines
4.7 KiB

/* SharpLr35902.h
*
* An implementation of the Sharp LR35902 (GameBoy) CPU.
*/
#pragma once
#include <string>
#include <tuple>
#include <vector>
#include "../PlipCpu.h"
#include "../../PlipSupport.h"
#include "../../Memory/PlipMemoryMap.h"
#define INTERRUPT_VBLANK 0b00000001
#define INTERRUPT_LCDSTAT 0b00000010
#define INTERRUPT_TIMER 0b00000100
#define INTERRUPT_SERIAL 0b00010000
#define INTERRUPT_JOYPAD 0b00100000
namespace Plip::Cpu {
class SharpLr35902 : public PlipCpu {
public:
SharpLr35902(long hz, PlipMemoryMap* memoryMap);
struct Registers {
uint8_t a;
uint8_t f;
uint8_t b;
uint8_t c;
uint8_t d;
uint8_t e;
uint8_t h;
uint8_t l;
uint16_t sp;
uint16_t pc;
};
void Cycle() override;
[[nodiscard]] std::string DumpRegisters() const;
void Interrupt(uint8_t irq);
[[nodiscard]] uint32_t GetPc() override { return m_reg.pc; }
Registers GetRegisters() { return m_reg; }
void Reset() override;
static const uint16_t MemInterruptEnabled = 0xFFFF;
static const uint16_t MemInterruptFlag = 0xFF0F;
private:
void PerformReset();
void Decode();
void DecodeCB();
uint8_t* GetRegister8(uint8_t idx);
std::tuple<uint8_t*, uint8_t*> GetRegisterPair(uint8_t idx);
uint16_t GetRegister16Pointer(uint8_t idx);
uint16_t GetRegister16Value(uint8_t idx);
[[nodiscard]] bool TestConditional(uint8_t idx) const;
static inline uint16_t Combine(const uint8_t *high, const uint8_t *low) {
return ((*high << 8) + *low);
}
static inline void Split(uint16_t val, uint8_t *high, uint8_t *low) {
*high = val >> 8;
*low = val & 0xFF;
}
static inline void DecPair(uint8_t *high, uint8_t *low, uint16_t amount = 1) {
uint16_t val = Combine(high, low) - amount;
Split(val, high, low);
}
static inline void IncPair(uint8_t *high, uint8_t *low, uint16_t amount = 1) {
uint16_t val = Combine(high, low) + amount;
Split(val, high, low);
}
// Standard opcodes.
void OpAccumAddImm();
void OpAccumAddCarryImm();
void OpAccumAndImm();
void OpAccumBcd();
void OpAccumCarryImm();
void OpAccumFlip();
void OpAccumOrImm();
void OpAccumRotateLeft();
void OpAccumRotateLeftThruCarry();
void OpAccumRotateRight();
void OpAccumRotateRightThruCarry();
void OpAccumSubImm();
void OpAccumSubBorrowImm();
void OpAccumXorImm();
void OpAdd();
void OpAdd16();
void OpAddCarry();
void OpAddSpOffset();
void OpAnd();
void OpCallCond();
void OpCallUnc();
void OpCarry();
void OpDecReg();
void OpDecPair();
void OpDisableInterrupts();
void OpEnableInterrupts();
void OpFlipCarry();
void OpFuncFixedUnc();
void OpHalt();
void OpIncReg();
void OpIncPair();
void OpJumpAbsCond();
void OpJumpAbsUnc();
void OpJumpRegUnc();
void OpJumpRelCond();
void OpJumpRelUnc();
void OpLdAccumMem();
void OpLdAccumMemHighImm();
void OpLdAccumMemHighC();
void OpLdHlSpOffset();
void OpLdMemAccum();
void OpLdMemHighImmAccum();
void OpLdMemHighCAccum();
void OpLdMemReg();
void OpLdMemSp();
void OpLdReg16Imm16();
void OpLdRegImm();
void OpLdRegMem();
void OpLdRegReg();
void OpLdSpHl();
void OpOr();
void OpPopReg16();
void OpPushReg16();
void OpRetCond();
void OpRetUnc();
void OpRetImeUnc();
void OpSetCarry();
void OpStop() const;
void OpSub();
void OpSubBorrow();
void OpXor();
// CB-prefixed opcodes.
void OpBitClear();
void OpBitSet();
void OpBitTest();
void OpNibbleSwap();
void OpRotateLeft();
void OpRotateLeftThruCarry();
void OpRotateRight();
void OpRotateRightThruCarry();
void OpShiftLeftArithmetic();
void OpShiftRightArithmetic();
void OpShiftRightLogical();
bool m_allowFetch = true;
bool m_cancelInterrupt = false;
bool m_isr = false;
uint8_t m_isrIdx = 0;
bool m_halt = false;
ScheduledState m_ime = ScheduledState::Disabled;
std::vector<uint8_t> m_instr;
Registers m_reg {};
uint8_t m_mcycle = 0;
};
}