2017-06-04 20:38:34 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
2017-09-01 15:41:50 +00:00
|
|
|
#include <IntelProcessor.h>
|
|
|
|
#include <Signal.h>
|
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
#include "GameBoyBus.h"
|
2017-08-29 21:23:32 +00:00
|
|
|
#include "Display.h"
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
namespace EightBit {
|
2017-09-07 00:15:28 +00:00
|
|
|
namespace GameBoy {
|
|
|
|
class LR35902 : public IntelProcessor {
|
|
|
|
public:
|
|
|
|
enum StatusBits {
|
|
|
|
ZF = Bit7,
|
|
|
|
NF = Bit6,
|
|
|
|
HC = Bit5,
|
|
|
|
CF = Bit4,
|
|
|
|
};
|
|
|
|
|
|
|
|
LR35902(Bus& memory);
|
|
|
|
|
|
|
|
Signal<LR35902> ExecutingInstruction;
|
|
|
|
|
|
|
|
virtual register16_t& AF() override {
|
|
|
|
af.low &= 0xf0;
|
|
|
|
return af;
|
|
|
|
}
|
2017-08-29 21:23:32 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
virtual register16_t& BC() override { return bc; }
|
|
|
|
virtual register16_t& DE() override { return de; }
|
|
|
|
virtual register16_t& HL() override { return hl; }
|
|
|
|
|
|
|
|
virtual void reset() override;
|
|
|
|
|
|
|
|
static int framesPerSecond() { return 60; }
|
|
|
|
static int cyclesPerFrame() { return cyclesPerSecond() / framesPerSecond(); }
|
|
|
|
|
|
|
|
int runRasterLines();
|
|
|
|
int runRasterLine();
|
|
|
|
int runVerticalBlankLines();
|
|
|
|
|
|
|
|
int singleStep();
|
|
|
|
|
|
|
|
protected:
|
|
|
|
int runRasterLines(int limit);
|
|
|
|
virtual int execute(uint8_t opcode);
|
|
|
|
int step();
|
|
|
|
|
|
|
|
private:
|
|
|
|
Bus& m_bus;
|
|
|
|
|
|
|
|
register16_t af;
|
|
|
|
register16_t bc;
|
|
|
|
register16_t de;
|
|
|
|
register16_t hl;
|
|
|
|
|
|
|
|
bool m_ime;
|
|
|
|
bool m_stopped;
|
|
|
|
|
|
|
|
bool m_prefixCB;
|
|
|
|
|
|
|
|
static int cyclesPerSecond() { return 4 * 1024 * 1024; }
|
|
|
|
static int cyclesPerLine() { return cyclesPerFrame() / Bus::TotalLineCount; }
|
|
|
|
|
|
|
|
bool& IME() { return m_ime; }
|
|
|
|
|
|
|
|
uint8_t R(int r, uint8_t& a) {
|
|
|
|
switch (r) {
|
|
|
|
case 0:
|
|
|
|
return B();
|
|
|
|
case 1:
|
|
|
|
return C();
|
|
|
|
case 2:
|
|
|
|
return D();
|
|
|
|
case 3:
|
|
|
|
return E();
|
|
|
|
case 4:
|
|
|
|
return H();
|
|
|
|
case 5:
|
|
|
|
return L();
|
|
|
|
case 6:
|
|
|
|
return getByte(HL());
|
|
|
|
case 7:
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
throw std::logic_error("Unhandled registry mechanism");
|
2017-06-09 10:42:32 +00:00
|
|
|
}
|
2017-09-07 00:15:28 +00:00
|
|
|
|
|
|
|
void R(int r, uint8_t& a, uint8_t value) {
|
|
|
|
switch (r) {
|
|
|
|
case 0:
|
|
|
|
B() = value;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
C() = value;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
D() = value;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
E() = value;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
H() = value;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
L() = value;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
setByte(HL(), value);
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
a = value;
|
|
|
|
break;
|
|
|
|
}
|
2017-08-06 16:06:48 +00:00
|
|
|
}
|
2017-09-07 00:15:28 +00:00
|
|
|
|
|
|
|
register16_t& RP(int rp) {
|
|
|
|
__assume(rp < 4);
|
|
|
|
__assume(rp >= 0);
|
|
|
|
switch (rp) {
|
|
|
|
case 0b00:
|
|
|
|
return BC();
|
|
|
|
case 0b01:
|
|
|
|
return DE();
|
|
|
|
case 0b10:
|
|
|
|
return HL();
|
|
|
|
case 0b11:
|
|
|
|
return SP();
|
|
|
|
default:
|
|
|
|
__assume(0);
|
|
|
|
}
|
2017-06-09 10:42:32 +00:00
|
|
|
}
|
2017-09-07 00:15:28 +00:00
|
|
|
|
|
|
|
register16_t& RP2(int rp) {
|
|
|
|
__assume(rp < 4);
|
|
|
|
__assume(rp >= 0);
|
|
|
|
switch (rp) {
|
|
|
|
case 0b00:
|
|
|
|
return BC();
|
|
|
|
case 0b01:
|
|
|
|
return DE();
|
|
|
|
case 0b10:
|
|
|
|
return HL();
|
|
|
|
case 0b11:
|
|
|
|
return AF();
|
|
|
|
default:
|
|
|
|
__assume(0);
|
|
|
|
}
|
2017-06-09 10:42:32 +00:00
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
static void adjustHalfCarryAdd(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
|
|
|
setFlag(f, HC, calculateHalfCarryAdd(before, value, calculation));
|
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
static void adjustHalfCarrySub(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
|
|
|
setFlag(f, HC, calculateHalfCarrySub(before, value, calculation));
|
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
static void subtract(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0);
|
2017-07-19 12:59:28 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
int interrupt(uint8_t value);
|
2017-08-18 08:49:06 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
void executeCB(int x, int y, int z, int p, int q);
|
|
|
|
void executeOther(int x, int y, int z, int p, int q);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
static void increment(uint8_t& f, uint8_t& operand);
|
|
|
|
static void decrement(uint8_t& f, uint8_t& operand);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
void stop() { m_stopped = true; }
|
|
|
|
void start() { m_stopped = false; }
|
|
|
|
bool stopped() const { return m_stopped; }
|
2017-08-30 22:17:34 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
void di();
|
|
|
|
void ei();
|
2017-08-30 22:17:34 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
void reti();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
bool jrConditionalFlag(uint8_t& f, int flag);
|
|
|
|
bool returnConditionalFlag(uint8_t& f, int flag);
|
|
|
|
bool jumpConditionalFlag(uint8_t& f, int flag);
|
|
|
|
bool callConditionalFlag(uint8_t& f, int flag);
|
2017-07-19 12:59:28 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
void add(uint8_t& f, register16_t& operand, register16_t value);
|
2017-07-19 12:59:28 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
static void add(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0);
|
|
|
|
static void adc(uint8_t& f, uint8_t& operand, uint8_t value);
|
|
|
|
static void sbc(uint8_t& f, uint8_t& operand, uint8_t value);
|
|
|
|
static void andr(uint8_t& f, uint8_t& operand, uint8_t value);
|
|
|
|
static void xorr(uint8_t& f, uint8_t& operand, uint8_t value);
|
|
|
|
static void orr(uint8_t& f, uint8_t& operand, uint8_t value);
|
|
|
|
static void compare(uint8_t& f, uint8_t check, uint8_t value);
|
2017-07-19 12:59:28 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
static uint8_t rlc(uint8_t& f, uint8_t operand);
|
|
|
|
static uint8_t rrc(uint8_t& f, uint8_t operand);
|
|
|
|
static uint8_t rl(uint8_t& f, uint8_t operand);
|
|
|
|
static uint8_t rr(uint8_t& f, uint8_t operand);
|
|
|
|
static uint8_t sla(uint8_t& f, uint8_t operand);
|
|
|
|
static uint8_t sra(uint8_t& f, uint8_t operand);
|
|
|
|
static uint8_t srl(uint8_t& f, uint8_t operand);
|
2017-07-21 18:23:36 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
static uint8_t bit(uint8_t& f, int n, uint8_t operand);
|
|
|
|
static uint8_t res(int n, uint8_t operand);
|
|
|
|
static uint8_t set(int n, uint8_t operand);
|
2017-07-19 12:59:28 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
static void daa(uint8_t& a, uint8_t& f);
|
2017-07-19 12:59:28 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
static void scf(uint8_t& a, uint8_t& f);
|
|
|
|
static void ccf(uint8_t& a, uint8_t& f);
|
|
|
|
static void cpl(uint8_t& a, uint8_t& f);
|
2017-07-19 12:59:28 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
static uint8_t swap(uint8_t& f, uint8_t operand);
|
|
|
|
};
|
|
|
|
}
|
2017-06-09 10:42:32 +00:00
|
|
|
}
|