formatting/readability

This commit is contained in:
MrWint 2019-05-25 19:18:15 +02:00
parent 98076d286d
commit 567756d6cc
54 changed files with 989 additions and 989 deletions

View File

@ -61,6 +61,6 @@ $(TARGET) : $(OBJS)
clean:
$(RM) $(OBJS)
$(RM) $(TARGET)
install:
$(CP) $(TARGET) $(DEST_$(ARCH))

View File

@ -55,7 +55,7 @@ public:
GBA_CGB = 2, /**< Use GBA intial CPU register values when in CGB mode. */
MULTICART_COMPAT = 4, /**< Use heuristics to detect and support some multicart MBCs disguised as MBC1. */
};
/** Load ROM image.
*
* @param romfile Path to rom image file. Typically a .gbc, .gb, or .zip-file (if zip-support is compiled in).
@ -63,7 +63,7 @@ public:
* @return 0 on success, negative value on failure.
*/
LoadRes load(const char *romfiledata, unsigned romfilelength, std::uint32_t now, unsigned flags, unsigned div);
int loadGBCBios(const char* biosfiledata);
int loadDMGBios(const char* biosfiledata);
@ -96,17 +96,17 @@ public:
* Equivalent to reloading a ROM image, or turning a Game Boy Color off and on again.
*/
void reset(std::uint32_t now, unsigned div);
/** @param palNum 0 <= palNum < 3. One of BG_PALETTE, SP1_PALETTE and SP2_PALETTE.
* @param colorNum 0 <= colorNum < 4
*/
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32);
void setCgbPalette(unsigned *lut);
/** Sets the callback used for getting input state. */
void setInputGetter(unsigned (*getInput)());
void setReadCallback(MemoryCallback);
void setWriteCallback(MemoryCallback);
void setExecCallback(MemoryCallback);
@ -118,7 +118,7 @@ public:
/** Returns true if the currently loaded ROM image is treated as having CGB support. */
bool isCgb() const;
/** Returns true if a ROM image is loaded. */
bool isLoaded() const;
@ -126,10 +126,10 @@ public:
void loadSavedata(const char *data);
int saveSavedataLength();
void saveSavedata(char *dest);
// 0 = vram, 1 = rom, 2 = wram, 3 = cartram, 4 = oam, 5 = hram
bool getMemoryArea(int which, unsigned char **data, int *length);
/** ROM header title of currently loaded ROM image. */
const std::string romTitle() const;

View File

@ -26,7 +26,7 @@ template<typename T>
class Array : Uncopyable {
T *a;
std::size_t sz;
public:
explicit Array(const std::size_t size = 0) : a(size ? new T[size] : 0), sz(size) {}
~Array() { delete []a; }
@ -39,7 +39,7 @@ public:
template<typename T>
class ScopedArray : Uncopyable {
T *a_;
public:
explicit ScopedArray(T *a = 0) : a_(a) {}
~ScopedArray() { delete []a_; }

View File

@ -47,12 +47,12 @@ CPU::CPU()
long CPU::runFor(const unsigned long cycles) {
memory.setBasetime(cycleCounter_);
process(cycles/* << memory.isDoubleSpeed()*/);
const long csb = memory.cyclesSinceBlit(cycleCounter_);
if (cycleCounter_ & 0x80000000)
cycleCounter_ = memory.resetCounters(cycleCounter_);
return csb;
}
@ -63,7 +63,7 @@ long CPU::runFor(const unsigned long cycles) {
static void calcHF(const unsigned HF1, unsigned& HF2) {
unsigned arg1 = HF1 & 0xF;
unsigned arg2 = (HF2 & 0xF) + (HF2 >> 8 & 1);
if (HF2 & 0x800) {
arg1 = arg2;
arg2 = 1;
@ -73,7 +73,7 @@ static void calcHF(const unsigned HF1, unsigned& HF2) {
arg1 -= arg2;
else
arg1 = (arg1 + arg2) << 5;
HF2 |= arg1 & 0x200;
}
@ -93,7 +93,7 @@ void CPU::setStatePtrs(SaveState &state) {
void CPU::loadState(const SaveState &state) {
memory.loadState(state/*, cycleCounter_*/);
cycleCounter_ = state.cpu.cycleCounter;
PC = state.cpu.PC & 0xFFFF;
SP = state.cpu.SP & 0xFFFF;
@ -497,10 +497,10 @@ void CPU::process(const unsigned long cycles) {
//unsigned char A = A_;
unsigned long cycleCounter = cycleCounter_;
while (memory.isActive()) {
//unsigned short PC = PC_;
if (memory.halted()) {
if (cycleCounter < memory.nextEventTime()) {
const unsigned long cycles = memory.nextEventTime() - cycleCounter;
@ -508,7 +508,7 @@ void CPU::process(const unsigned long cycles) {
}
} else while (cycleCounter < memory.nextEventTime()) {
unsigned char opcode = 0x00;
int FullPC = PC;
if (PC >= 0x4000 && PC <= 0x7FFF)
@ -552,7 +552,7 @@ void CPU::process(const unsigned long cycles) {
skip = false;
}
}
switch (opcode) {
//nop (4 cycles):
//Do nothing for 4 cycles:
@ -591,12 +591,12 @@ void CPU::process(const unsigned long cycles) {
case 0x08:
{
unsigned l, h;
PC_READ(l);
PC_READ(h);
const unsigned addr = h << 8 | l;
WRITE(addr, SP & 0xFF);
WRITE((addr + 1) & 0xFFFF, SP >> 8);
}
@ -669,7 +669,7 @@ void CPU::process(const unsigned long cycles) {
CF = A << 1;
A = (CF | oldcf) & 0xFF;
}
HF2 = 0;
ZF = 1;
break;
@ -704,7 +704,7 @@ void CPU::process(const unsigned long cycles) {
CF = A << 8;
A = (A | oldcf) >> 1;
}
HF2 = 0;
ZF = 1;
break;
@ -728,9 +728,9 @@ void CPU::process(const unsigned long cycles) {
case 0x22:
{
unsigned addr = HL();
WRITE(addr, A);
addr = (addr + 1) & 0xFFFF;
L = addr;
H = addr >> 8;
@ -756,38 +756,38 @@ void CPU::process(const unsigned long cycles) {
case 0x27:
/*{
unsigned correction = ((A > 0x99) || (CF & 0x100)) ? 0x60 : 0x00;
calcHF(HF1, HF2);
if ((A & 0x0F) > 0x09 || (HF2 & 0x200))
correction |= 0x06;
HF1 = A;
HF2 = (HF2 & 0x400) | correction;
CF = (correction & 0x40) << 2;
A = (HF2 & 0x400) ? A - correction : (A + correction);
ZF = A;
}*/
calcHF(HF1, HF2);
{
unsigned correction = (CF & 0x100) ? 0x60 : 0x00;
if (HF2 & 0x200)
correction |= 0x06;
if (!(HF2 &= 0x400)) {
if ((A & 0x0F) > 0x09)
correction |= 0x06;
if (A > 0x99)
correction |= 0x60;
A += correction;
} else
A -= correction;
CF = correction << 2 & 0x100;
ZF = A;
A &= 0xFF;
@ -815,9 +815,9 @@ void CPU::process(const unsigned long cycles) {
case 0x2A:
{
unsigned addr = HL();
READ(A, addr);
addr = (addr + 1) & 0xFFFF;
L = addr;
H = addr >> 8;
@ -859,10 +859,10 @@ void CPU::process(const unsigned long cycles) {
case 0x31:
{
unsigned l, h;
PC_READ(l);
PC_READ(h);
SP = h << 8 | l;
}
break;
@ -872,9 +872,9 @@ void CPU::process(const unsigned long cycles) {
case 0x32:
{
unsigned addr = HL();
WRITE(addr, A);
addr = (addr - 1) & 0xFFFF;
L = addr;
H = addr >> 8;
@ -888,10 +888,10 @@ void CPU::process(const unsigned long cycles) {
//inc (hl) (12 cycles):
//Increment value at address in hl, check flags except CF:
case 0x34:
case 0x34:
{
const unsigned addr = HL();
READ(HF2, addr);
ZF = HF2 + 1;
WRITE(addr, ZF & 0xFF);
@ -904,7 +904,7 @@ void CPU::process(const unsigned long cycles) {
case 0x35:
{
const unsigned addr = HL();
READ(HF2, addr);
ZF = HF2 - 1;
WRITE(addr, ZF & 0xFF);
@ -917,7 +917,7 @@ void CPU::process(const unsigned long cycles) {
case 0x36:
{
unsigned tmp;
PC_READ(tmp);
WRITE(HL(), tmp);
}
@ -958,10 +958,10 @@ void CPU::process(const unsigned long cycles) {
case 0x3A:
{
unsigned addr = HL();
A = memory.read(addr, cycleCounter);
cycleCounter += 4;
addr = (addr - 1) & 0xFFFF;
L = addr;
H = addr >> 8;
@ -1221,7 +1221,7 @@ void CPU::process(const unsigned long cycles) {
unsigned data;
READ(data, HL());
add_a_u8(data);
}
break;
@ -1249,9 +1249,9 @@ void CPU::process(const unsigned long cycles) {
case 0x8E:
{
unsigned data;
READ(data, HL());
adc_a_u8(data);
}
break;
@ -1279,9 +1279,9 @@ void CPU::process(const unsigned long cycles) {
case 0x96:
{
unsigned data;
READ(data, HL());
sub_a_u8(data);
}
break;
@ -1311,9 +1311,9 @@ void CPU::process(const unsigned long cycles) {
case 0x9E:
{
unsigned data;
READ(data, HL());
sbc_a_u8(data);
}
break;
@ -1341,9 +1341,9 @@ void CPU::process(const unsigned long cycles) {
case 0xA6:
{
unsigned data;
READ(data, HL());
and_a_u8(data);
}
break;
@ -1374,9 +1374,9 @@ void CPU::process(const unsigned long cycles) {
case 0xAE:
{
unsigned data;
READ(data, HL());
xor_a_u8(data);
}
break;
@ -1405,9 +1405,9 @@ void CPU::process(const unsigned long cycles) {
case 0xB6:
{
unsigned data;
READ(data, HL());
or_a_u8(data);
}
break;
@ -1437,9 +1437,9 @@ void CPU::process(const unsigned long cycles) {
case 0xBE:
{
unsigned data;
READ(data, HL());
cp_a_u8(data);
}
break;
@ -1453,7 +1453,7 @@ void CPU::process(const unsigned long cycles) {
//Pop two bytes from the stack and jump to that address, if ZF is unset:
case 0xC0:
cycleCounter += 4;
if (ZF & 0xFF) {
ret();
}
@ -1495,9 +1495,9 @@ void CPU::process(const unsigned long cycles) {
case 0xC6:
{
unsigned data;
PC_READ(data);
add_a_u8(data);
}
break;
@ -1509,11 +1509,11 @@ void CPU::process(const unsigned long cycles) {
//Pop two bytes from the stack and jump to that address, if ZF is set:
case 0xC8:
cycleCounter += 4;
if (!(ZF & 0xFF)) {
ret();
}
break;
//ret (16 cycles):
@ -1537,7 +1537,7 @@ void CPU::process(const unsigned long cycles) {
//CB OPCODES (Shifts, rotates and bits):
case 0xCB:
PC_READ(opcode);
switch (opcode) {
case 0x00:
rlc_r(B);
@ -1562,14 +1562,14 @@ void CPU::process(const unsigned long cycles) {
case 0x06:
{
const unsigned addr = HL();
READ(CF, addr);
CF <<= 1;
ZF = CF | (CF >> 8);
WRITE(addr, ZF & 0xFF);
HF2 = 0;
}
break;
@ -1599,13 +1599,13 @@ void CPU::process(const unsigned long cycles) {
case 0x0E:
{
const unsigned addr = HL();
READ(ZF, addr);
CF = ZF << 8;
WRITE(addr, (ZF | CF) >> 1 & 0xFF);
HF2 = 0;
}
break;
@ -1636,14 +1636,14 @@ void CPU::process(const unsigned long cycles) {
{
const unsigned addr = HL();
const unsigned oldcf = CF >> 8 & 1;
READ(CF, addr);
CF <<= 1;
ZF = CF | oldcf;
WRITE(addr, ZF & 0xFF);
HF2 = 0;
}
break;
@ -1673,15 +1673,15 @@ void CPU::process(const unsigned long cycles) {
case 0x1E:
{
const unsigned addr = HL();
READ(ZF, addr);
const unsigned oldcf = CF & 0x100;
CF = ZF << 8;
ZF = (ZF | oldcf) >> 1;
WRITE(addr, ZF);
HF2 = 0;
}
break;
@ -1711,14 +1711,14 @@ void CPU::process(const unsigned long cycles) {
case 0x26:
{
const unsigned addr = HL();
READ(CF, addr);
CF <<= 1;
ZF = CF;
WRITE(addr, ZF & 0xFF);
HF2 = 0;
}
break;
@ -1748,13 +1748,13 @@ void CPU::process(const unsigned long cycles) {
case 0x2E:
{
const unsigned addr = HL();
READ(CF, addr);
ZF = CF >> 1;
WRITE(addr, ZF | (CF & 0x80));
CF <<= 8;
HF2 = 0;
}
@ -1785,11 +1785,11 @@ void CPU::process(const unsigned long cycles) {
case 0x36:
{
const unsigned addr = HL();
READ(ZF, addr);
WRITE(addr, (ZF << 4 | ZF >> 4) & 0xFF);
CF = HF2 = 0;
}
break;
@ -1819,13 +1819,13 @@ void CPU::process(const unsigned long cycles) {
case 0x3E:
{
const unsigned addr = HL();
READ(CF, addr);
ZF = CF >> 1;
WRITE(addr, ZF);
CF <<= 8;
HF2 = 0;
}
@ -1854,9 +1854,9 @@ void CPU::process(const unsigned long cycles) {
case 0x46:
{
unsigned data;
READ(data, HL());
bit0_u8(data);
}
break;
@ -1884,9 +1884,9 @@ void CPU::process(const unsigned long cycles) {
case 0x4E:
{
unsigned data;
READ(data, HL());
bit1_u8(data);
}
break;
@ -1914,9 +1914,9 @@ void CPU::process(const unsigned long cycles) {
case 0x56:
{
unsigned data;
READ(data, HL());
bit2_u8(data);
}
break;
@ -1944,9 +1944,9 @@ void CPU::process(const unsigned long cycles) {
case 0x5E:
{
unsigned data;
READ(data, HL());
bit3_u8(data);
}
break;
@ -1974,9 +1974,9 @@ void CPU::process(const unsigned long cycles) {
case 0x66:
{
unsigned data;
READ(data, HL());
bit4_u8(data);
}
break;
@ -2004,9 +2004,9 @@ void CPU::process(const unsigned long cycles) {
case 0x6E:
{
unsigned data;
READ(data, HL());
bit5_u8(data);
}
break;
@ -2034,9 +2034,9 @@ void CPU::process(const unsigned long cycles) {
case 0x76:
{
unsigned data;
READ(data, HL());
bit6_u8(data);
}
break;
@ -2064,9 +2064,9 @@ void CPU::process(const unsigned long cycles) {
case 0x7E:
{
unsigned data;
READ(data, HL());
bit7_u8(data);
}
break;
@ -2479,9 +2479,9 @@ void CPU::process(const unsigned long cycles) {
case 0xCE:
{
unsigned data;
PC_READ(data);
adc_a_u8(data);
}
break;
@ -2493,11 +2493,11 @@ void CPU::process(const unsigned long cycles) {
//Pop two bytes from the stack and jump to that address, if CF is unset:
case 0xD0:
cycleCounter += 4;
if (!(CF & 0x100)) {
ret();
}
break;
case 0xD1:
@ -2537,9 +2537,9 @@ void CPU::process(const unsigned long cycles) {
case 0xD6:
{
unsigned data;
PC_READ(data);
sub_a_u8(data);
}
break;
@ -2551,11 +2551,11 @@ void CPU::process(const unsigned long cycles) {
//Pop two bytes from the stack and jump to that address, if CF is set:
case 0xD8:
cycleCounter += 4;
if (CF & 0x100) {
ret();
}
break;
//reti (16 cycles):
@ -2563,11 +2563,11 @@ void CPU::process(const unsigned long cycles) {
case 0xD9:
{
unsigned l, h;
pop_rr(h, l);
memory.ei(cycleCounter);
PC_MOD(h << 8 | l);
}
break;
@ -2607,9 +2607,9 @@ void CPU::process(const unsigned long cycles) {
case 0xDE:
{
unsigned data;
PC_READ(data);
sbc_a_u8(data);
}
break;
@ -2622,9 +2622,9 @@ void CPU::process(const unsigned long cycles) {
case 0xE0:
{
unsigned tmp;
PC_READ(tmp);
FF_WRITE(0xFF00 | tmp, A);
}
break;
@ -2652,9 +2652,9 @@ void CPU::process(const unsigned long cycles) {
case 0xE6:
{
unsigned data;
PC_READ(data);
and_a_u8(data);
}
break;
@ -2690,10 +2690,10 @@ void CPU::process(const unsigned long cycles) {
case 0xEA:
{
unsigned l, h;
PC_READ(l);
PC_READ(h);
WRITE(h << 8 | l, A);
}
break;
@ -2713,9 +2713,9 @@ void CPU::process(const unsigned long cycles) {
case 0xEE:
{
unsigned data;
PC_READ(data);
xor_a_u8(data);
}
break;
@ -2728,9 +2728,9 @@ void CPU::process(const unsigned long cycles) {
case 0xF0:
{
unsigned tmp;
PC_READ(tmp);
FF_READ(A, 0xFF00 | tmp);
}
break;
@ -2738,9 +2738,9 @@ void CPU::process(const unsigned long cycles) {
case 0xF1: /*pop_rr(A, F); Cycles(12); break;*/
{
unsigned F;
pop_rr(A, F);
FROM_F(F);
}
break;
@ -2762,10 +2762,10 @@ void CPU::process(const unsigned long cycles) {
break;
case 0xF5: /*push_rr(A, F); Cycles(16); break;*/
calcHF(HF1, HF2);
{
unsigned F = F();
push_rr(A, F);
}
break;
@ -2775,7 +2775,7 @@ void CPU::process(const unsigned long cycles) {
unsigned data;
PC_READ(data);
or_a_u8(data);
}
break;
@ -2816,10 +2816,10 @@ void CPU::process(const unsigned long cycles) {
case 0xFA:
{
unsigned l, h;
PC_READ(l);
PC_READ(h);
READ(A, h << 8 | l);
}
break;
@ -2843,7 +2843,7 @@ void CPU::process(const unsigned long cycles) {
unsigned data;
PC_READ(data);
cp_a_u8(data);
}
break;
@ -2853,11 +2853,11 @@ void CPU::process(const unsigned long cycles) {
// default: break;
}
}
//PC_ = PC;
cycleCounter = memory.event(cycleCounter);
}
//A_ = A;
cycleCounter_ = cycleCounter;
}

View File

@ -26,48 +26,48 @@ namespace gambatte {
class CPU {
Memory memory;
unsigned long cycleCounter_;
unsigned short PC;
unsigned short SP;
unsigned HF1, HF2, ZF, CF;
unsigned char A, B, C, D, E, /*F,*/ H, L;
bool skip;
int *interruptAddresses;
int numInterruptAddresses;
int hitInterruptAddress;
void process(unsigned long cycles);
void (*tracecallback)(void *);
public:
CPU();
// void halt();
// unsigned interrupt(unsigned address, unsigned cycleCounter);
long runFor(unsigned long cycles);
void setStatePtrs(SaveState &state);
void loadState(const SaveState &state);
void setLayers(unsigned mask) { memory.setLayers(mask); }
void loadSavedata(const char *data) { memory.loadSavedata(data); }
int saveSavedataLength() {return memory.saveSavedataLength(); }
void saveSavedata(char *dest) { memory.saveSavedata(dest); }
bool getMemoryArea(int which, unsigned char **data, int *length) { return memory.getMemoryArea(which, data, length); }
void setVideoBuffer(uint_least32_t *const videoBuf, const int pitch) {
memory.setVideoBuffer(videoBuf, pitch);
}
void setInputGetter(unsigned (*getInput)()) {
memory.setInputGetter(getInput);
}
@ -103,19 +103,19 @@ public:
void setLinkCallback(void(*callback)()) {
memory.setLinkCallback(callback);
}
LoadRes load(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat) {
return memory.loadROM(romfiledata, romfilelength, forceDmg, multicartCompat);
}
bool loaded() const { return memory.loaded(); }
const char * romTitle() const { return memory.romTitle(); }
void setSoundBuffer(uint_least32_t *const buf) { memory.setSoundBuffer(buf); }
unsigned fillSoundBuffer() { return memory.fillSoundBuffer(cycleCounter_); }
bool isCgb() const { return memory.isCgb(); }
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) {
memory.setDmgPaletteColor(palNum, colorNum, rgb32);
}
@ -123,7 +123,7 @@ public:
void setCgbPalette(unsigned *lut) {
memory.setCgbPalette(lut);
}
unsigned char* cgbBiosBuffer() { return memory.cgbBiosBuffer(); }
unsigned char* dmgBiosBuffer() { return memory.dmgBiosBuffer(); }
bool gbIsCgb() { return memory.gbIsCgb(); }

View File

@ -41,7 +41,7 @@ public:
stream.seekg(0, std::ios::beg);
}
}
virtual void rewind() { stream.seekg(0, std::ios::beg); }
virtual std::size_t size() const { return fsize; };
virtual void read(char *buffer, std::size_t amount) { stream.read(buffer, amount); }

View File

@ -30,7 +30,7 @@ struct GB::Priv {
unsigned layersMask;
uint_least32_t vbuff[160*144];
Priv() : loadflags(0), layersMask(LAYER_MASK_BG | LAYER_MASK_OBJ)
{
}
@ -39,13 +39,13 @@ struct GB::Priv {
{
}
};
GB::GB() : p_(new Priv) {}
GB::~GB() {
//if (p_->cpu.loaded())
// p_->cpu.saveSavedata();
delete p_;
}
@ -54,12 +54,12 @@ long GB::runFor(gambatte::uint_least32_t *const soundBuf, unsigned &samples) {
samples = 0;
return -1;
}
p_->cpu.setVideoBuffer(p_->vbuff, 160);
p_->cpu.setSoundBuffer(soundBuf);
const long cyclesSinceBlit = p_->cpu.runFor(samples * 2);
samples = p_->cpu.fillSoundBuffer();
return cyclesSinceBlit < 0 ? cyclesSinceBlit : static_cast<long>(samples) - (cyclesSinceBlit >> 1);
}
@ -83,7 +83,7 @@ void GB::blitTo(gambatte::uint_least32_t *videoBuf, int pitch)
void GB::reset(const std::uint32_t now, const unsigned div) {
if (p_->cpu.loaded()) {
int length = p_->cpu.saveSavedataLength();
char *s;
if (length > 0)
@ -91,7 +91,7 @@ void GB::reset(const std::uint32_t now, const unsigned div) {
s = (char *) std::malloc(length);
p_->cpu.saveSavedata(s);
}
SaveState state;
p_->cpu.setStatePtrs(state);
setInitState(state, !(p_->loadflags & FORCE_DMG), p_->loadflags & GBA_CGB, now, div);
@ -143,9 +143,9 @@ void GB::setLinkCallback(void(*callback)()) {
LoadRes GB::load(const char *romfiledata, unsigned romfilelength, const std::uint32_t now, unsigned const flags, const unsigned div) {
//if (p_->cpu.loaded())
// p_->cpu.saveSavedata();
LoadRes const loadres = p_->cpu.load(romfiledata, romfilelength, flags & FORCE_DMG, flags & MULTICART_COMPAT);
if (loadres == LOADRES_OK) {
SaveState state;
p_->cpu.setStatePtrs(state);
@ -154,7 +154,7 @@ LoadRes GB::load(const char *romfiledata, unsigned romfilelength, const std::uin
p_->cpu.loadState(state);
//p_->cpu.loadSavedata();
}
return loadres;
}
@ -226,7 +226,7 @@ const std::string GB::romTitle() const {
title[title[0xF] & 0x80 ? 0xF : 0x10] = '\0';
return std::string(title);
}
return std::string();
}

View File

@ -677,29 +677,29 @@ static void setInitialCgbWram(unsigned char *const wram) {
{ 0x7FCD, 0xBF }, { 0x7FCE, 0x7F }, { 0x7FCF, 0xFB }, { 0x7FDB, 0xF7 },
{ 0x7FDF, 0x7F }, { 0x7FE8, 0xDF }, { 0x7FEC, 0xFB }, { 0x7FF2, 0xF7 }
};
for (unsigned addr = 0x0000; addr < 0x0800; addr += 0x10) {
std::memset(wram + addr + 0x00, 0xFF, 0x08);
std::memset(wram + addr + 0x08, 0x00, 0x08);
}
for (unsigned addr = 0x0800; addr < 0x1000; addr += 0x10) {
std::memset(wram + addr + 0x00, 0x00, 0x08);
std::memset(wram + addr + 0x08, 0xFF, 0x08);
}
for (unsigned addr = 0x0E00; addr < 0x1000; addr += 0x10) {
wram[addr + 0x02] = 0xFF;
wram[addr + 0x0A] = 0x00;
}
for (unsigned addr = 0x1000; addr < 0x8000; addr += 0x1000) {
if (0x2000 != addr)
std::memcpy(wram + addr, wram, 0x1000);
}
std::memset(wram + 0x2000, 0, 0x1000);
for (std::size_t i = 0; i < sizeof cgbWramDumpDiff / sizeof cgbWramDumpDiff[0]; ++i)
wram[cgbWramDumpDiff[i].addr] = cgbWramDumpDiff[i].val;
}
@ -959,19 +959,19 @@ static void setInitialDmgWram(unsigned char *const wram) {
{ 0x1FA2, 0x40 }, { 0x1FB6, 0x80 }, { 0x1FC6, 0x10 }, { 0x1FCC, 0x20 },
{ 0x1FD2, 0x20 }, { 0x1FD8, 0x04 }, { 0x1FDC, 0x10 }, { 0x1FDE, 0x04 }
};
for (unsigned addr = 0x0000; addr < 0x0800; addr += 0x200) {
std::memset(wram + addr , 0x00, 0x100);
std::memset(wram + addr + 0x100, 0xFF, 0x100);
}
for (unsigned addr = 0x0800; addr < 0x1000; addr += 0x200) {
std::memset(wram + addr , 0xFF, 0x100);
std::memset(wram + addr + 0x100, 0x00, 0x100);
}
std::memcpy(wram + 0x1000, wram, 0x1000);
for (std::size_t i = 0; i < sizeof dmgWramDumpDiff / sizeof dmgWramDumpDiff[0]; ++i)
wram[dmgWramDumpDiff[i].addr] = dmgWramDumpDiff[i].val;
}
@ -1004,21 +1004,21 @@ static void setInitialVram(unsigned char *const vram, const bool cgb) {
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFC, 0xFC,
0x3C, 0x42, 0xB9, 0xA5, 0xB9, 0xA5, 0x42, 0x3C
};
std::memset(vram, 0, 0x4000);
for (std::size_t i = 0; i < sizeof even_numbered_8010_to_81a0_dump; ++i) {
vram[0x0010 + i * 2] = even_numbered_8010_to_81a0_dump[i];
}
if (!cgb) {
unsigned i = 1;
for (unsigned addr = 0x1904; addr < 0x1910; ++addr)
vram[addr] = i++;
vram[0x1910] = 0x19;
for (unsigned addr = 0x1924; addr < 0x1930; ++addr)
vram[addr] = i++;
}
@ -1039,7 +1039,7 @@ static void setInitialCgbIoamhram(unsigned char *const ioamhram) {
0x24, 0x13, 0xFD, 0x3A, 0x10, 0x10, 0xAD, 0x45,
0x24, 0x13, 0xFD, 0x3A, 0x10, 0x10, 0xAD, 0x45
};
static const unsigned char ffxxDump[0x100] = {
0xCF, 0x00, 0x7C, 0xFF, 0x00, 0x00, 0x00, 0xF8,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1,
@ -1074,7 +1074,7 @@ static void setInitialCgbIoamhram(unsigned char *const ioamhram) {
0x98, 0xD1, 0x71, 0x02, 0x4D, 0x01, 0xC1, 0xFF,
0x0D, 0x00, 0xD3, 0x05, 0xF9, 0x00, 0x0B, 0x00
};
std::memset(ioamhram, 0x00, 0x0A0);
std::memcpy(ioamhram + 0x0A0, feaxDump, sizeof feaxDump);
std::memcpy(ioamhram + 0x100, ffxxDump, sizeof ffxxDump);
@ -1103,7 +1103,7 @@ static void setInitialDmgIoamhram(unsigned char *const ioamhram) {
0x24, 0x40, 0x42, 0x05, 0x0E, 0x04, 0x20, 0xA6,
0x5E, 0xC1, 0x97, 0x7E, 0x44, 0x05, 0x01, 0xA9
};
static const unsigned char ffxxDump[0x100] = {
0xCF, 0x00, 0x7E, 0xFF, 0xD3, 0x00, 0x00, 0xF8,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1,
@ -1138,7 +1138,7 @@ static void setInitialDmgIoamhram(unsigned char *const ioamhram) {
0xBC, 0x7F, 0x7E, 0xD0, 0xC7, 0xC3, 0xBD, 0xCF,
0x59, 0xEA, 0x39, 0x01, 0x2E, 0x00, 0x69, 0x00
};
std::memcpy(ioamhram , oamDump, sizeof oamDump);
std::memset(ioamhram + 0x0A0, 0x00, 0x060);
std::memcpy(ioamhram + 0x100, ffxxDump, sizeof ffxxDump);
@ -1148,24 +1148,24 @@ static void setInitialDmgIoamhram(unsigned char *const ioamhram) {
void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbMode, const std::uint32_t now, const unsigned div) {
static const unsigned char cgbObjpDump[0x40] = {
0x00, 0x00, 0xF2, 0xAB,
0x61, 0xC2, 0xD9, 0xBA,
0x88, 0x6E, 0xDD, 0x63,
0x28, 0x27, 0xFB, 0x9F,
0x35, 0x42, 0xD6, 0xD4,
0x50, 0x48, 0x57, 0x5E,
0x23, 0x3E, 0x3D, 0xCA,
0x71, 0x21, 0x37, 0xC0,
0xC6, 0xB3, 0xFB, 0xF9,
0x08, 0x00, 0x8D, 0x29,
0xA3, 0x20, 0xDB, 0x87,
0x62, 0x05, 0x5D, 0xD4,
0x0E, 0x08, 0xFE, 0xAF,
0x20, 0x02, 0xD7, 0xFF,
0x07, 0x6A, 0x55, 0xEC,
0x00, 0x00, 0xF2, 0xAB,
0x61, 0xC2, 0xD9, 0xBA,
0x88, 0x6E, 0xDD, 0x63,
0x28, 0x27, 0xFB, 0x9F,
0x35, 0x42, 0xD6, 0xD4,
0x50, 0x48, 0x57, 0x5E,
0x23, 0x3E, 0x3D, 0xCA,
0x71, 0x21, 0x37, 0xC0,
0xC6, 0xB3, 0xFB, 0xF9,
0x08, 0x00, 0x8D, 0x29,
0xA3, 0x20, 0xDB, 0x87,
0x62, 0x05, 0x5D, 0xD4,
0x0E, 0x08, 0xFE, 0xAF,
0x20, 0x02, 0xD7, 0xFF,
0x07, 0x6A, 0x55, 0xEC,
0x83, 0x40, 0x0B, 0x77
};
state.cpu.cycleCounter = 8;
state.cpu.PC = 0;
state.cpu.SP = 0;
@ -1183,7 +1183,7 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
state.mem.agbMode = gbaCgbMode;
std::memset(state.mem.sram.ptr, 0xFF, state.mem.sram.getSz());
setInitialVram(state.mem.vram.ptr, cgb);
if (cgb) {
@ -1193,11 +1193,11 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
setInitialDmgWram(state.mem.wram.ptr);
setInitialDmgIoamhram(state.mem.ioamhram.ptr);
}
state.mem.ioamhram.ptr[0x104] = 0;
state.mem.ioamhram.ptr[0x140] = 0;
state.mem.ioamhram.ptr[0x144] = 0x00;
state.mem.divLastUpdate = 0 - div;
state.mem.timaLastUpdate = 0;
state.mem.tmatime = DISABLED_TIME;
@ -1217,23 +1217,23 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
state.mem.hdmaTransfer = false;
state.mem.gbIsCgb = cgb;
for (unsigned i = 0x00; i < 0x40; i += 0x02) {
state.ppu.bgpData.ptr[i ] = 0xFF;
state.ppu.bgpData.ptr[i + 1] = 0x7F;
}
std::memcpy(state.ppu.objpData.ptr, cgbObjpDump, sizeof cgbObjpDump);
if (!cgb) {
state.ppu.bgpData.ptr[0] = state.mem.ioamhram.get()[0x147];
state.ppu.objpData.ptr[0] = state.mem.ioamhram.get()[0x148];
state.ppu.objpData.ptr[1] = state.mem.ioamhram.get()[0x149];
}
for (unsigned pos = 0; pos < 80; ++pos)
state.ppu.oamReaderBuf.ptr[pos] = state.mem.ioamhram.ptr[(pos * 2 & ~3) | (pos & 1)];
std::fill_n(state.ppu.oamReaderSzbuf.ptr, 40, false);
std::memset(state.ppu.spAttribList, 0, sizeof state.ppu.spAttribList);
std::memset(state.ppu.spByte0List, 0, sizeof state.ppu.spByte0List);
@ -1263,9 +1263,9 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
state.ppu.pendingLcdstatIrq = false;
state.ppu.isCgb = cgb;
state.spu.cycleCounter = 0; // spu.cycleCounter >> 12 & 7 represents the frame sequencer position.
state.spu.ch1.sweep.counter = SoundUnit::COUNTER_DISABLED;
state.spu.ch1.sweep.shadow = 0;
state.spu.ch1.sweep.nr0 = 0;
@ -1279,7 +1279,7 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
state.spu.ch1.lcounter.lengthCounter = 0;
state.spu.ch1.nr4 = 0;
state.spu.ch1.master = false;
state.spu.ch2.duty.nextPosUpdate = SoundUnit::COUNTER_DISABLED;
state.spu.ch2.duty.nr3 = 0;
state.spu.ch2.duty.pos = 0;
@ -1289,10 +1289,10 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
state.spu.ch2.lcounter.lengthCounter = 0;
state.spu.ch2.nr4 = 0;
state.spu.ch2.master = false;
for (unsigned i = 0; i < 0x10; ++i)
state.spu.ch3.waveRam.ptr[i] = state.mem.ioamhram.get()[0x130 + i];
state.spu.ch3.lcounter.counter = SoundUnit::COUNTER_DISABLED;
state.spu.ch3.lcounter.lengthCounter = 0x100;
state.spu.ch3.waveCounter = SoundUnit::COUNTER_DISABLED;
@ -1302,7 +1302,7 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
state.spu.ch3.wavePos = 0;
state.spu.ch3.sampleBuf = 0;
state.spu.ch3.master = false;
state.spu.ch4.lfsr.counter = state.spu.cycleCounter + 4;
state.spu.ch4.lfsr.reg = 0xFF;
state.spu.ch4.env.counter = SoundUnit::COUNTER_DISABLED;
@ -1311,7 +1311,7 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
state.spu.ch4.lcounter.lengthCounter = 0;
state.spu.ch4.nr4 = 0;
state.spu.ch4.master = false;
state.rtc.baseTime = now;
state.rtc.haltTime = state.rtc.baseTime;
state.rtc.dataDh = 0;

View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
@ -26,19 +26,19 @@ template<typename T, class Less>
void insertionSort(T *const start, T *const end, Less less) {
if (start >= end)
return;
T *a = start;
while (++a < end) {
const T e = *a;
T *b = a;
while (b != start && less(e, *(b - 1))) {
*b = *(b - 1);
b = b - 1;
}
*b = e;
}
}

View File

@ -35,7 +35,7 @@ unsigned long Interrupter::interrupt(const unsigned address, unsigned long cycle
memory.write(SP, PC & 0xFF, cycleCounter);
PC = address;
cycleCounter += 8;
return cycleCounter;
}

View File

@ -28,13 +28,13 @@ void InterruptRequester::loadState(const SaveState &state) {
ifreg_ = state.mem.ioamhram.get()[0x10F];
iereg_ = state.mem.ioamhram.get()[0x1FF] & 0x1F;
intFlags.set(state.mem.IME, state.mem.halted);
eventTimes.setValue<INTERRUPTS>(intFlags.imeOrHalted() && pendingIrqs() ? minIntTime : static_cast<unsigned long>(DISABLED_TIME));
}
void InterruptRequester::resetCc(const unsigned long oldCc, const unsigned long newCc) {
minIntTime = minIntTime < oldCc ? 0 : minIntTime - (oldCc - newCc);
if (eventTimes.value(INTERRUPTS) != DISABLED_TIME)
eventTimes.setValue<INTERRUPTS>(minIntTime);
}
@ -42,35 +42,35 @@ void InterruptRequester::resetCc(const unsigned long oldCc, const unsigned long
void InterruptRequester::ei(const unsigned long cc) {
intFlags.setIme();
minIntTime = cc + 1;
if (pendingIrqs())
eventTimes.setValue<INTERRUPTS>(minIntTime);
}
void InterruptRequester::di() {
intFlags.unsetIme();
if (!intFlags.imeOrHalted())
eventTimes.setValue<INTERRUPTS>(DISABLED_TIME);
}
void InterruptRequester::halt() {
intFlags.setHalted();
if (pendingIrqs())
eventTimes.setValue<INTERRUPTS>(minIntTime);
}
void InterruptRequester::unhalt() {
intFlags.unsetHalted();
if (!intFlags.imeOrHalted())
eventTimes.setValue<INTERRUPTS>(DISABLED_TIME);
}
void InterruptRequester::flagIrq(const unsigned bit) {
ifreg_ |= bit;
if (intFlags.imeOrHalted() && pendingIrqs())
eventTimes.setValue<INTERRUPTS>(minIntTime);
}
@ -82,14 +82,14 @@ void InterruptRequester::ackIrq(const unsigned bit) {
void InterruptRequester::setIereg(const unsigned iereg) {
iereg_ = iereg & 0x1F;
if (intFlags.imeOrHalted())
eventTimes.setValue<INTERRUPTS>(pendingIrqs() ? minIntTime : static_cast<unsigned long>(DISABLED_TIME));
}
void InterruptRequester::setIfreg(const unsigned ifreg) {
ifreg_ = ifreg;
if (intFlags.imeOrHalted())
eventTimes.setValue<INTERRUPTS>(pendingIrqs() ? minIntTime : static_cast<unsigned long>(DISABLED_TIME));
}

View File

@ -32,41 +32,41 @@ class InterruptRequester {
unsigned long minIntTime;
unsigned ifreg_;
unsigned iereg_;
class IntFlags {
friend class InterruptRequester;
unsigned char flags_;
enum { IME_MASK = 1, HALTED_MASK = 2 };
public:
IntFlags() : flags_(0) {}
bool ime() const { return flags_ & IME_MASK; }
bool halted() const { return flags_ & HALTED_MASK; }
bool imeOrHalted() const { return flags_; }
void setIme() { flags_ |= IME_MASK; }
void unsetIme() { flags_ &= ~IME_MASK; }
void setHalted() { flags_ |= HALTED_MASK; }
void unsetHalted() { flags_ &= ~HALTED_MASK; }
void set(const bool ime, const bool halted) { flags_ = halted * HALTED_MASK + ime * IME_MASK; }
} intFlags;
public:
InterruptRequester();
void loadState(const SaveState &);
void resetCc(unsigned long oldCc, unsigned long newCc);
unsigned ifreg() const { return ifreg_; }
unsigned iereg() const { return iereg_; }
unsigned pendingIrqs() const { return ifreg_ & iereg_; }
bool ime() const { return intFlags.ime(); }
bool halted() const { return intFlags.halted(); }
void ei(unsigned long cc);
void di();
void halt();
@ -75,7 +75,7 @@ public:
void ackIrq(unsigned bit);
void setIereg(unsigned iereg);
void setIfreg(unsigned ifreg);
MemEventId minEventId() const { return static_cast<MemEventId>(eventTimes.min()); }
unsigned long minEventTime() const { return eventTimes.minValue(); }
template<MemEventId id> void setEventTime(unsigned long value) { eventTimes.setValue<id>(value); }

View File

@ -76,11 +76,11 @@ public:
};
static inline unsigned rambanks(const MemPtrs &memptrs) {
return static_cast<std::size_t>(memptrs.rambankdataend() - memptrs.rambankdata()) / 0x2000;
return std::size_t(memptrs.rambankdataend() - memptrs.rambankdata()) / 0x2000;
}
static inline unsigned rombanks(const MemPtrs &memptrs) {
return static_cast<std::size_t>(memptrs.romdataend() - memptrs.romdata() ) / 0x4000;
return std::size_t(memptrs.romdataend() - memptrs.romdata() ) / 0x4000;
}
class Mbc1 : public DefaultMbc {
@ -219,7 +219,7 @@ public:
memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0);
setRombank();
}
virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned addr, unsigned bank) const {
return (addr < 0x4000) == ((bank & 0xF) == 0);
}
@ -287,10 +287,10 @@ class Mbc3 : public DefaultMbc {
static unsigned adjustedRombank(unsigned bank) { return bank & 0x7F ? bank : bank | 1; }
void setRambank() const {
unsigned flags = enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0;
if (rtc) {
rtc->set(enableRam, rambank);
if (rtc->getActive())
flags |= MemPtrs::RTC_EN;
}
@ -546,7 +546,7 @@ LoadRes Cartridge::loadROM(const char *romfiledata, unsigned romfilelength, bool
//if (rom->fail())
// return -1;
unsigned rambanks = 1;
unsigned rombanks = 2;
bool cgb = false;
@ -609,8 +609,8 @@ LoadRes Cartridge::loadROM(const char *romfiledata, unsigned romfilelength, bool
default: return -1;
}*/
rambanks = numRambanksFromH14x(header[0x147], header[0x149]);
rambanks = numRambanksFromH14x(header[0x147], header[0x149]);
cgb = !forceDmg;
}
std::size_t const filesize = romfilelength; //rom->size();
@ -625,10 +625,10 @@ LoadRes Cartridge::loadROM(const char *romfiledata, unsigned romfilelength, bool
std::memcpy(memptrs.romdata(), romfiledata, (filesize / 0x4000) * 0x4000ul);
std::memset(memptrs.romdata() + (filesize / 0x4000) * 0x4000ul, 0xFF, (rombanks - filesize / 0x4000) * 0x4000ul);
enforce8bit(memptrs.romdata(), rombanks * 0x4000ul);
//if (rom->fail())
// return -1;
switch (type) {
case PLAIN: mbc.reset(new Mbc0(memptrs)); break;
case MBC1:

View File

@ -63,13 +63,13 @@ class Cartridge {
MemPtrs memptrs;
Rtc rtc;
std::auto_ptr<Mbc> mbc;
public:
void setStatePtrs(SaveState &);
void loadState(const SaveState &);
bool loaded() const { return mbc.get(); }
const unsigned char * rmem(unsigned area) const { return memptrs.rmem(area); }
unsigned char * wmem(unsigned area) const { return memptrs.wmem(area); }
unsigned char * vramdata() const { return memptrs.vramdata(); }
@ -85,14 +85,14 @@ public:
void setVrambank(unsigned bank) { memptrs.setVrambank(bank); }
void setWrambank(unsigned bank) { memptrs.setWrambank(bank); }
void setOamDmaSrc(OamDmaSrc oamDmaSrc) { memptrs.setOamDmaSrc(oamDmaSrc); }
void mbcWrite(unsigned addr, unsigned data) { mbc->romWrite(addr, data); }
bool isCgb() const { return gambatte::isCgb(memptrs); }
void rtcWrite(unsigned data) { rtc.write(data); }
unsigned char rtcRead() const { return *rtc.getActive(); }
void loadSavedata(const char *data);
int saveSavedataLength();
void saveSavedata(char *dest);

View File

@ -45,7 +45,7 @@ void MemPtrs::reset(const unsigned rombanks, const unsigned rambanks, const unsi
wramdataend_ = wramdata_[0] + wrambanks * 0x1000ul;
std::memset(rdisabledRamw(), 0xFF, 0x2000);
oamDmaSrc_ = OAM_DMA_SRC_OFF;
rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0];
rmem_[0xC] = wmem_[0xC] = wramdata_[0] - 0xC000;
@ -87,7 +87,7 @@ void MemPtrs::setRambank(const unsigned flags, const unsigned rambank) {
}
void MemPtrs::setWrambank(const unsigned bank) {
wramdata_[1] = wramdata_[0] + ((bank & 0x07) ? (bank & 0x07) : 1) * 0x1000;
wramdata_[1] = wramdata_[0] + (bank & 0x07 ? bank & 0x07 : 1) * 0x1000;
rmem_[0xD] = wmem_[0xD] = wramdata_[1] - 0xD000;
disconnectOamDmaAreas();
}
@ -100,7 +100,7 @@ void MemPtrs::setOamDmaSrc(const OamDmaSrc oamDmaSrc) {
rmem_[0xC] = wmem_[0xC] = wramdata_[0] - 0xC000;
rmem_[0xD] = wmem_[0xD] = wramdata_[1] - 0xD000;
rmem_[0xE] = wmem_[0xE] = wramdata_[0] - 0xE000;
oamDmaSrc_ = oamDmaSrc;
disconnectOamDmaAreas();
}

View File

@ -29,7 +29,7 @@ enum OamDmaSrc { OAM_DMA_SRC_ROM, OAM_DMA_SRC_SRAM, OAM_DMA_SRC_VRAM,
class MemPtrs {
const unsigned char *rmem_[0x10];
unsigned char *wmem_[0x10];
unsigned char *romdata_[2];
unsigned char *wramdata_[2];
unsigned char *vrambankptr_;
@ -38,7 +38,7 @@ class MemPtrs {
unsigned char *memchunk_;
unsigned char *rambankdata_;
unsigned char *wramdataend_;
OamDmaSrc oamDmaSrc_;
unsigned curRomBank_;
@ -54,11 +54,11 @@ class MemPtrs {
unsigned char * wdisabledRam() const { return wramdataend_ + 0x2000; }
public:
enum RamFlag { READ_EN = 1, WRITE_EN = 2, RTC_EN = 4 };
MemPtrs();
~MemPtrs();
void reset(unsigned rombanks, unsigned rambanks, unsigned wrambanks);
const unsigned char * rmem(unsigned area) const { return rmem_[area]; }
unsigned char * wmem(unsigned area) const { return wmem_[area]; }
unsigned char * vramdata() const { return rambankdata_ - 0x4000; }

View File

@ -41,24 +41,24 @@ Rtc::Rtc()
void Rtc::doLatch() {
std::uint32_t tmp = ((dataDh & 0x40) ? haltTime : timeCB()) - baseTime;
while (tmp > 0x1FF * 86400) {
baseTime += 0x1FF * 86400;
tmp -= 0x1FF * 86400;
dataDh |= 0x80;
}
dataDl = (tmp / 86400) & 0xFF;
dataDh &= 0xFE;
dataDh |= ((tmp / 86400) & 0x100) >> 8;
tmp %= 86400;
dataH = tmp / 3600;
tmp %= 3600;
dataM = tmp / 60;
tmp %= 60;
dataS = tmp;
}
@ -99,7 +99,7 @@ void Rtc::loadState(const SaveState &state) {
dataM = state.rtc.dataM;
dataS = state.rtc.dataS;
lastLatchData = state.rtc.lastLatchData;
doSwapActive();
}
@ -108,7 +108,7 @@ void Rtc::setDh(const unsigned new_dh) {
const std::uint32_t old_highdays = ((unixtime - baseTime) / 86400) & 0x100;
baseTime += old_highdays * 86400;
baseTime -= ((new_dh & 0x1) << 8) * 86400;
if ((dataDh ^ new_dh) & 0x40) {
if (new_dh & 0x40)
haltTime = timeCB();

View File

@ -41,7 +41,7 @@ private:
bool enabled;
bool lastLatchData;
std::uint32_t (*timeCB)();
void doLatch();
void doSwapActive();
void setDh(unsigned new_dh);
@ -49,37 +49,37 @@ private:
void setH(unsigned new_hours);
void setM(unsigned new_minutes);
void setS(unsigned new_seconds);
public:
Rtc();
const unsigned char* getActive() const { return activeData; }
std::uint32_t getBaseTime() const { return baseTime; }
void setBaseTime(const std::uint32_t baseTime) {
this->baseTime = baseTime;
// doLatch();
}
void latch(const unsigned data) {
if (!lastLatchData && data == 1)
doLatch();
lastLatchData = data;
}
void loadState(const SaveState &state);
void set(const bool enabled, unsigned bank) {
bank &= 0xF;
bank -= 8;
this->enabled = enabled;
this->index = bank;
doSwapActive();
}
void write(const unsigned data) {
// if (activeSet)
(this->*activeSet)(data);

View File

@ -98,7 +98,7 @@ void Memory::loadState(const SaveState &state) {
intreq.setEventTime<BLIT>((ioamhram[0x140] & 0x80) ? display.nextMode1IrqTime() : state.cpu.cycleCounter);
blanklcd = false;
if (!isCgb())
std::memset(cart.vramdata() + 0x2000, 0, 0x2000);
}
@ -106,7 +106,7 @@ void Memory::loadState(const SaveState &state) {
void Memory::setEndtime(const unsigned long cycleCounter, const unsigned long inc) {
if (intreq.eventTime(BLIT) <= cycleCounter)
intreq.setEventTime<BLIT>(intreq.eventTime(BLIT) + (70224 << isDoubleSpeed()));
intreq.setEventTime<END>(cycleCounter + (inc << isDoubleSpeed()));
}
@ -165,7 +165,7 @@ unsigned long Memory::event(unsigned long cycleCounter) {
while (cycleCounter >= intreq.minEventTime() && intreq.eventTime(END) != DISABLED_TIME)
cycleCounter = event(cycleCounter);
intreq.setEventTime<END>(DISABLED_TIME);
break;
@ -173,17 +173,17 @@ unsigned long Memory::event(unsigned long cycleCounter) {
{
const bool lcden = ioamhram[0x140] >> 7 & 1;
unsigned long blitTime = intreq.eventTime(BLIT);
if (lcden | blanklcd) {
display.updateScreen(blanklcd, cycleCounter);
intreq.setEventTime<BLIT>(DISABLED_TIME);
intreq.setEventTime<END>(DISABLED_TIME);
while (cycleCounter >= intreq.minEventTime())
cycleCounter = event(cycleCounter);
} else
blitTime += 70224 << isDoubleSpeed();
blanklcd = lcden ^ 1;
intreq.setEventTime<BLIT>(blitTime);
}
@ -202,7 +202,7 @@ unsigned long Memory::event(unsigned long cycleCounter) {
unsigned dmaDest = dmaDestination;
unsigned dmaLength = ((ioamhram[0x155] & 0x7F) + 0x1) * 0x10;
unsigned length = hdmaReqFlagged(intreq) ? 0x10 : dmaLength;
ackDmaReq(&intreq);
if ((static_cast<unsigned long>(dmaDest) + length) & 0x10000) {
@ -255,7 +255,7 @@ unsigned long Memory::event(unsigned long cycleCounter) {
if ((ioamhram[0x155] & 0x80) && display.hdmaIsEnabled()) {
if (lastOamDmaUpdate != DISABLED_TIME)
updateOamDma(cycleCounter);
display.disableHdma(cycleCounter);
}
}
@ -275,11 +275,11 @@ unsigned long Memory::event(unsigned long cycleCounter) {
if (halted()) {
if (gbIsCgb_ || (!gbIsCgb_ && cycleCounter <= halttime + 4))
cycleCounter += 4;
intreq.unhalt();
intreq.setEventTime<UNHALT>(DISABLED_TIME);
}
if (ime()) {
unsigned address;
@ -297,7 +297,7 @@ unsigned long Memory::event(unsigned long cycleCounter) {
cycleCounter += 4;
display.update(cycleCounter);
const unsigned n = pendingIrqs & -pendingIrqs;
if (n == 0) {
address = 0;
}
@ -306,11 +306,11 @@ unsigned long Memory::event(unsigned long cycleCounter) {
address = lut[n-1];
} else
address = 0x50 + n;
intreq.ackIrq(n);
PC = address;
}
break;
}
@ -319,15 +319,15 @@ unsigned long Memory::event(unsigned long cycleCounter) {
unsigned long Memory::stop(unsigned long cycleCounter) {
cycleCounter += 4;
if (ioamhram[0x14D] & isCgb()) {
sound.generate_samples(cycleCounter, isDoubleSpeed());
display.speedChange(cycleCounter);
ioamhram[0x14D] ^= 0x81;
intreq.setEventTime<BLIT>((ioamhram[0x140] & 0x80) ? display.nextMode1IrqTime() : cycleCounter + (70224 << isDoubleSpeed()));
if (intreq.eventTime(END) > cycleCounter) {
intreq.setEventTime<END>(cycleCounter + (isDoubleSpeed() ?
(intreq.eventTime(END) - cycleCounter) << 1 : (intreq.eventTime(END) - cycleCounter) >> 1));
@ -381,7 +381,7 @@ unsigned long Memory::resetCounters(unsigned long cycleCounter) {
decEventCycles(UNHALT, dec);
cycleCounter -= dec;
intreq.resetCc(oldCC, cycleCounter);
tima.resetCc(oldCC, cycleCounter, TimaInterruptRequester(intreq));
display.resetCc(oldCC, cycleCounter);
@ -453,7 +453,7 @@ const unsigned char * Memory::oamDmaSrcPtr() const {
case OAM_DMA_SRC_INVALID:
case OAM_DMA_SRC_OFF: break;
}
return ioamhram[0x146] == 0xFF && !isCgb() ? oamDmaSrcZero() : cart.rdisabledRam();
}
@ -536,7 +536,7 @@ unsigned Memory::nontrivial_ff_read(const unsigned P, const unsigned long cycleC
static bool isInOamDmaConflictArea(const OamDmaSrc oamDmaSrc, const unsigned addr, const bool cgb) {
struct Area { unsigned short areaUpper, exceptAreaLower, exceptAreaWidth, pad; };
static const Area cgbAreas[] = {
{ 0xC000, 0x8000, 0x2000, 0 },
{ 0xC000, 0x8000, 0x2000, 0 },
@ -545,7 +545,7 @@ static bool isInOamDmaConflictArea(const OamDmaSrc oamDmaSrc, const unsigned add
{ 0xC000, 0x8000, 0x2000, 0 },
{ 0x0000, 0x0000, 0x0000, 0 }
};
static const Area dmgAreas[] = {
{ 0xFE00, 0x8000, 0x2000, 0 },
{ 0xFE00, 0x8000, 0x2000, 0 },
@ -554,7 +554,7 @@ static bool isInOamDmaConflictArea(const OamDmaSrc oamDmaSrc, const unsigned add
{ 0xFE00, 0x8000, 0x2000, 0 },
{ 0x0000, 0x0000, 0x0000, 0 }
};
const Area *const a = cgb ? cgbAreas : dmgAreas;
return addr < a[oamDmaSrc].areaUpper && addr - a[oamDmaSrc].exceptAreaLower >= a[oamDmaSrc].exceptAreaWidth;
@ -564,7 +564,7 @@ unsigned Memory::nontrivial_read(const unsigned P, const unsigned long cycleCoun
if (P < 0xFF80) {
if (lastOamDmaUpdate != DISABLED_TIME) {
updateOamDma(cycleCounter);
if (isInOamDmaConflictArea(cart.oamDmaSrc(), P, isCgb()) && oamDmaPos < 0xA0)
return ioamhram[oamDmaPos];
}
@ -830,7 +830,7 @@ void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned
if ((ioamhram[0x140] ^ data) & 0x80) {
const unsigned lyc = display.getStat(ioamhram[0x145], cycleCounter) & 4;
const bool hdmaEnabled = display.hdmaIsEnabled();
display.lcdcChange(data, cycleCounter);
ioamhram[0x144] = 0;
ioamhram[0x141] &= 0xF8;
@ -1022,7 +1022,7 @@ void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned
void Memory::nontrivial_write(const unsigned P, const unsigned data, const unsigned long cycleCounter) {
if (lastOamDmaUpdate != DISABLED_TIME) {
updateOamDma(cycleCounter);
if (isInOamDmaConflictArea(cart.oamDmaSrc(), P, isCgb()) && oamDmaPos < 0xA0) {
ioamhram[oamDmaPos] = data;
return;

View File

@ -57,13 +57,13 @@ class Memory {
unsigned (*getInput)();
unsigned long divLastUpdate;
unsigned long lastOamDmaUpdate;
InterruptRequester intreq;
Tima tima;
LCD display;
PSG sound;
Interrupter interrupter;
unsigned short dmaSource;
unsigned short dmaDestination;
unsigned char oamDmaPos;
@ -80,24 +80,24 @@ class Memory {
void startOamDma(unsigned long cycleCounter);
void endOamDma(unsigned long cycleCounter);
const unsigned char * oamDmaSrcPtr() const;
unsigned nontrivial_ff_read(unsigned P, unsigned long cycleCounter);
unsigned nontrivial_read(unsigned P, unsigned long cycleCounter);
void nontrivial_ff_write(unsigned P, unsigned data, unsigned long cycleCounter);
void nontrivial_write(unsigned P, unsigned data, unsigned long cycleCounter);
unsigned nontrivial_peek(unsigned P);
unsigned nontrivial_ff_peek(unsigned P);
void updateSerial(unsigned long cc);
void updateTimaIrq(unsigned long cc);
void updateIrqs(unsigned long cc);
bool isDoubleSpeed() const { return display.isDoubleSpeed(); }
public:
explicit Memory(const Interrupter &interrupter, unsigned short &sp, unsigned short &pc);
bool loaded() const { return cart.loaded(); }
unsigned curRomBank() const { return cart.curRomBank(); }
const char * romTitle() const { return cart.romTitle(); }
@ -124,9 +124,9 @@ public:
unsigned long nextEventTime() const { return intreq.minEventTime(); }
void setLayers(unsigned mask) { display.setLayers(mask); }
bool isActive() const { return intreq.eventTime(END) != DISABLED_TIME; }
long cyclesSinceBlit(const unsigned long cc) const {
return cc < intreq.eventTime(BLIT) ? -1 : static_cast<long>((cc - intreq.eventTime(BLIT)) >> isDoubleSpeed());
}
@ -155,7 +155,7 @@ public:
CDMapResult ret = { eCDLog_AddrType_ROM, P };
return ret;
}
else if(P<0x8000)
else if(P<0x8000)
{
unsigned bank = cart.rmem(P>>12) - cart.rmem(0);
unsigned addr = P+bank;
@ -187,7 +187,7 @@ public:
return ret;
}
else if(P<0xFF80) {}
else
else
{
////this is just for debugging, really, it's pretty useless
//CDMapResult ret = { eCDLog_AddrType_HRAM, (P-0xFF80) };
@ -262,7 +262,7 @@ public:
} else
nontrivial_write(P, data, cycleCounter);
}
void write(const unsigned P, const unsigned data, const unsigned long cycleCounter) {
if (cart.wmem(P >> 12)) {
cart.wmem(P >> 12)[P] = data;
@ -277,7 +277,7 @@ public:
cdCallback(map.addr,map.type,eCDLog_Flags_Data);
}
}
void ff_write(const unsigned P, const unsigned data, const unsigned long cycleCounter) {
if (P - 0xFF80u < 0x7Fu) {
ioamhram[P - 0xFE00] = data;
@ -329,14 +329,14 @@ public:
void setBasetime(unsigned long cc) { basetime = cc; }
void setEndtime(unsigned long cc, unsigned long inc);
void setSoundBuffer(uint_least32_t *const buf) { sound.setBuffer(buf); }
unsigned fillSoundBuffer(unsigned long cc);
void setVideoBuffer(uint_least32_t *const videoBuf, const int pitch) {
display.setVideoBuffer(videoBuf, pitch);
}
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32);
void setCgbPalette(unsigned *lut);

View File

@ -42,26 +42,26 @@ class MinKeeper {
enum { LEVELS = MinKeeperUtil::CeiledLog2<ids>::R };
template<int l> struct Num { enum { R = MinKeeperUtil::RoundedDiv2n<ids, LEVELS + 1 - l>::R }; };
template<int l> struct Sum { enum { R = MinKeeperUtil::Sum<Num, l>::R }; };
template<int id, int level>
struct UpdateValue {
enum { P = Sum<level-1>::R + id };
enum { C0 = Sum<level>::R + id * 2 };
static void updateValue(MinKeeper<ids> &m) {
// GCC 4.3 generates better code with the ternary operator on i386.
m.a[P] = (id * 2 + 1 == Num<level>::R || m.values[m.a[C0]] < m.values[m.a[C0 + 1]]) ? m.a[C0] : m.a[C0 + 1];
UpdateValue<id / 2, level - 1>::updateValue(m);
}
};
template<int id>
struct UpdateValue<id,0> {
static void updateValue(MinKeeper<ids> &m) {
m.minValue_ = m.values[m.a[0]];
}
};
class UpdateValueLut {
template<int id, int dummy> struct FillLut {
static void fillLut(UpdateValueLut & l) {
@ -69,42 +69,42 @@ class MinKeeper {
FillLut<id-1,dummy>::fillLut(l);
}
};
template<int dummy> struct FillLut<-1,dummy> {
static void fillLut(UpdateValueLut &) {}
};
void (*lut_[Num<LEVELS-1>::R])(MinKeeper<ids>&);
public:
UpdateValueLut() { FillLut<Num<LEVELS-1>::R-1,0>::fillLut(*this); }
void call(int id, MinKeeper<ids> &mk) const { lut_[id](mk); }
};
static UpdateValueLut updateValueLut;
unsigned long values[ids];
unsigned long minValue_;
int a[Sum<LEVELS>::R];
template<int id> static void updateValue(MinKeeper<ids> &m);
public:
explicit MinKeeper(unsigned long initValue = 0xFFFFFFFF);
int min() const { return a[0]; }
unsigned long minValue() const { return minValue_; }
template<int id>
void setValue(const unsigned long cnt) {
values[id] = cnt;
updateValue<id / 2>(*this);
}
void setValue(const int id, const unsigned long cnt) {
values[id] = cnt;
updateValueLut.call(id >> 1, *this);
}
unsigned long value(const int id) const { return values[id]; }
// not sure if i understood everything in minkeeper correctly, so something might be missing here?
@ -122,28 +122,28 @@ template<int ids> typename MinKeeper<ids>::UpdateValueLut MinKeeper<ids>::update
template<int ids>
MinKeeper<ids>::MinKeeper(const unsigned long initValue) {
std::fill(values, values + ids, initValue);
for (int i = 0; i < Num<LEVELS-1>::R; ++i) {
a[Sum<LEVELS-1>::R + i] = (i * 2 + 1 == ids || values[i * 2] < values[i * 2 + 1]) ? i * 2 : i * 2 + 1;
}
int n = Num<LEVELS-1>::R;
int off = Sum<LEVELS-1>::R;
while (off) {
const int pn = (n + 1) >> 1;
const int poff = off - pn;
for (int i = 0; i < pn; ++i) {
a[poff + i] = (i * 2 + 1 == n ||
values[a[off + i * 2]] < values[a[off + i * 2 + 1]]) ?
a[off + i * 2] : a[off + i * 2 + 1];
}
off = poff;
n = pn;
}
minValue_ = values[a[0]];
}

View File

@ -65,7 +65,7 @@ public:
virtual void ExitSection(const char *name);
};
// defines and explicitly instantiates
// defines and explicitly instantiates
#define SYNCFUNC(x)\
template void x::SyncState<false>(NewState *ns);\
template void x::SyncState<true>(NewState *ns);\

View File

@ -30,13 +30,13 @@ struct SaveState {
class Ptr {
T *ptr;
unsigned long sz;
public:
Ptr() : ptr(0), sz(0) {}
const T* get() const { return ptr; }
unsigned long getSz() const { return sz; }
void set(T *ptr, const unsigned long sz) { this->ptr = ptr; this->sz = sz; }
friend class SaverList;
friend void setInitState(SaveState &, bool, bool, std::uint32_t, unsigned);
};
@ -55,7 +55,7 @@ struct SaveState {
unsigned char L;
bool skip;
} cpu;
struct Mem {
Ptr<unsigned char> vram;
Ptr<unsigned char> sram;
@ -83,14 +83,14 @@ struct SaveState {
bool agbMode;
bool gbIsCgb;
} mem;
struct PPU {
Ptr<unsigned char> bgpData;
Ptr<unsigned char> objpData;
//SpriteMapper::OamReader
Ptr<unsigned char> oamReaderBuf;
Ptr<bool> oamReaderSzbuf;
unsigned long videoCycles;
unsigned long enableDisplayM0Time;
unsigned short lastM0Time;
@ -119,24 +119,24 @@ struct SaveState {
bool pendingLcdstatIrq;
bool isCgb;
} ppu;
struct SPU {
struct Duty {
unsigned long nextPosUpdate;
unsigned char nr3;
unsigned char pos;
};
struct Env {
unsigned long counter;
unsigned char volume;
};
struct LCounter {
unsigned long counter;
unsigned short lengthCounter;
};
struct {
struct {
unsigned long counter;
@ -150,7 +150,7 @@ struct SaveState {
unsigned char nr4;
bool master;
} ch1;
struct {
Duty duty;
Env env;
@ -158,7 +158,7 @@ struct SaveState {
unsigned char nr4;
bool master;
} ch2;
struct {
Ptr<unsigned char> waveRam;
LCounter lcounter;
@ -170,7 +170,7 @@ struct SaveState {
unsigned char sampleBuf;
bool master;
} ch3;
struct {
struct {
unsigned long counter;
@ -181,10 +181,10 @@ struct SaveState {
unsigned char nr4;
bool master;
} ch4;
unsigned long cycleCounter;
} spu;
struct RTC {
unsigned long baseTime;
unsigned long haltTime;

View File

@ -75,7 +75,7 @@ void PSG::loadState(const SaveState &state) {
ch2.loadState(state);
ch3.loadState(state);
ch4.loadState(state);
lastUpdate = state.cpu.cycleCounter;
set_so_volume(state.mem.ioamhram.get()[0x124]);
map_so(state.mem.ioamhram.get()[0x125]);
@ -84,7 +84,7 @@ void PSG::loadState(const SaveState &state) {
void PSG::accumulate_channels(const unsigned long cycles) {
uint_least32_t *const buf = buffer + bufferPos;
std::memset(buf, 0, cycles * sizeof *buf);
ch1.update(buf, soVol, cycles);
ch2.update(buf, soVol, cycles);
@ -98,7 +98,7 @@ void PSG::generate_samples(const unsigned long cycleCounter, const unsigned doub
if (cycles)
accumulate_channels(cycles);
bufferPos += cycles;
}
@ -111,10 +111,10 @@ unsigned PSG::fillBuffer() {
uint_least32_t sum = rsum;
uint_least32_t *b = buffer;
unsigned n = bufferPos;
if (unsigned n2 = n >> 3) {
n -= n2 << 3;
do {
sum += b[0];
b[0] = sum ^ 0x8000;
@ -132,18 +132,18 @@ unsigned PSG::fillBuffer() {
b[6] = sum ^ 0x8000;
sum += b[7];
b[7] = sum ^ 0x8000;
b += 8;
} while (--n2);
}
while (n--) {
sum += *b;
*b++ = sum ^ 0x8000; // xor away the initial rsum value of 0x8000 (which prevents borrows from the high word) from the low word
}
rsum = sum;
return bufferPos;
}
@ -161,7 +161,7 @@ void PSG::set_so_volume(const unsigned nr50) {
void PSG::map_so(const unsigned nr51) {
const unsigned long tmp = nr51 * so1Mul + (nr51 >> 4) * so2Mul;
ch1.setSo((tmp & 0x00010001) * 0xFFFF);
ch2.setSo((tmp >> 1 & 0x00010001) * 0xFFFF);
ch3.setSo((tmp >> 2 & 0x00010001) * 0xFFFF);

View File

@ -32,16 +32,16 @@ class PSG {
Channel2 ch2;
Channel3 ch3;
Channel4 ch4;
uint_least32_t *buffer;
unsigned long lastUpdate;
unsigned long soVol;
uint_least32_t rsum;
unsigned bufferPos;
bool enabled;
void accumulate_channels(unsigned long cycles);
@ -57,7 +57,7 @@ public:
void resetCounter(unsigned long newCc, unsigned long oldCc, unsigned doubleSpeed);
unsigned fillBuffer();
void setBuffer(uint_least32_t *const buf) { buffer = buf; bufferPos = 0; }
bool isEnabled() const { return enabled; }
void setEnabled(bool value) { enabled = value; }

View File

@ -33,31 +33,31 @@ Channel1::SweepUnit::SweepUnit(MasterDisabler &disabler, DutyUnit &dutyUnit) :
unsigned Channel1::SweepUnit::calcFreq() {
unsigned freq = shadow >> (nr0 & 0x07);
if (nr0 & 0x08) {
freq = shadow - freq;
negging = true;
} else
freq = shadow + freq;
if (freq & 2048)
disableMaster();
return freq;
}
void Channel1::SweepUnit::event() {
const unsigned long period = nr0 >> 4 & 0x07;
if (period) {
const unsigned freq = calcFreq();
if (!(freq & 2048) && (nr0 & 0x07)) {
shadow = freq;
dutyUnit.setFreq(freq, counter);
calcFreq();
}
counter += period << 14;
} else
counter += 8ul << 14;
@ -66,22 +66,22 @@ void Channel1::SweepUnit::event() {
void Channel1::SweepUnit::nr0Change(const unsigned newNr0) {
if (negging && !(newNr0 & 0x08))
disableMaster();
nr0 = newNr0;
}
void Channel1::SweepUnit::nr4Init(const unsigned long cc) {
negging = false;
shadow = dutyUnit.getFreq();
const unsigned period = nr0 >> 4 & 0x07;
const unsigned shift = nr0 & 0x07;
if (period | shift)
counter = ((cc >> 14) + (period ? period : 8)) << 14;
else
counter = COUNTER_DISABLED;
if (shift)
calcFreq();
}
@ -139,7 +139,7 @@ void Channel1::setNr0(const unsigned data) {
void Channel1::setNr1(const unsigned data) {
lengthCounter.nr1Change(data, nr4, cycleCounter);
dutyUnit.nr1Change(data, cycleCounter);
setEvent();
}
@ -148,7 +148,7 @@ void Channel1::setNr2(const unsigned data) {
disableMaster();
else
staticOutputTest(cycleCounter);
setEvent();
}
@ -159,18 +159,18 @@ void Channel1::setNr3(const unsigned data) {
void Channel1::setNr4(const unsigned data) {
lengthCounter.nr4Change(nr4, data, cycleCounter);
nr4 = data;
dutyUnit.nr4Change(data, cycleCounter);
if (data & 0x80) { //init-bit
nr4 &= 0x7F;
master = !envelopeUnit.nr4Init(cycleCounter);
sweepUnit.nr4Init(cycleCounter);
staticOutputTest(cycleCounter);
}
setEvent();
}
@ -187,7 +187,7 @@ void Channel1::reset() {
dutyUnit.reset();
envelopeUnit.reset();
sweepUnit.reset();
setEvent();
}
@ -200,7 +200,7 @@ void Channel1::loadState(const SaveState &state) {
dutyUnit.loadState(state.spu.ch1.duty, state.mem.ioamhram.get()[0x111], state.spu.ch1.nr4, state.spu.cycleCounter);
envelopeUnit.loadState(state.spu.ch1.env, state.mem.ioamhram.get()[0x112], state.spu.cycleCounter);
lengthCounter.loadState(state.spu.ch1.lcounter, state.spu.cycleCounter);
cycleCounter = state.spu.cycleCounter;
nr4 = state.spu.ch1.nr4;
master = state.spu.ch1.master;
@ -210,42 +210,42 @@ void Channel1::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign
const unsigned long outBase = envelopeUnit.dacIsOn() ? soBaseVol & soMask : 0;
const unsigned long outLow = outBase * (0 - 15ul);
const unsigned long endCycles = cycleCounter + cycles;
for (;;) {
const unsigned long outHigh = master ? outBase * (envelopeUnit.getVolume() * 2 - 15ul) : outLow;
const unsigned long nextMajorEvent = nextEventUnit->getCounter() < endCycles ? nextEventUnit->getCounter() : endCycles;
unsigned long out = dutyUnit.isHighState() ? outHigh : outLow;
while (dutyUnit.getCounter() <= nextMajorEvent) {
*buf = out - prevOut;
prevOut = out;
buf += dutyUnit.getCounter() - cycleCounter;
cycleCounter = dutyUnit.getCounter();
dutyUnit.event();
out = dutyUnit.isHighState() ? outHigh : outLow;
}
if (cycleCounter < nextMajorEvent) {
*buf = out - prevOut;
prevOut = out;
buf += nextMajorEvent - cycleCounter;
cycleCounter = nextMajorEvent;
}
if (nextEventUnit->getCounter() == nextMajorEvent) {
nextEventUnit->event();
setEvent();
} else
break;
}
if (cycleCounter & SoundUnit::COUNTER_MAX) {
dutyUnit.resetCounters(cycleCounter);
lengthCounter.resetCounters(cycleCounter);
envelopeUnit.resetCounters(cycleCounter);
sweepUnit.resetCounters(cycleCounter);
cycleCounter -= SoundUnit::COUNTER_MAX;
}
}

View File

@ -38,9 +38,9 @@ class Channel1 {
unsigned short shadow;
unsigned char nr0;
bool negging;
unsigned calcFreq();
public:
SweepUnit(MasterDisabler &disabler, DutyUnit &dutyUnit);
void event();
@ -51,27 +51,27 @@ class Channel1 {
template<bool isReader>void SyncState(NewState *ns);
};
friend class StaticOutputTester<Channel1,DutyUnit>;
StaticOutputTester<Channel1,DutyUnit> staticOutputTest;
DutyMasterDisabler disableMaster;
LengthCounter lengthCounter;
DutyUnit dutyUnit;
EnvelopeUnit envelopeUnit;
SweepUnit sweepUnit;
SoundUnit *nextEventUnit;
unsigned long cycleCounter;
unsigned long soMask;
unsigned long prevOut;
unsigned char nr4;
bool master;
void setEvent();
public:
Channel1();
void setNr0(unsigned data);
@ -79,12 +79,12 @@ public:
void setNr2(unsigned data);
void setNr3(unsigned data);
void setNr4(unsigned data);
void setSo(unsigned long soMask);
bool isActive() const { return master; }
void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles);
void reset();
void init(bool cgb);
void loadState(const SaveState &state);

View File

@ -46,7 +46,7 @@ void Channel2::setEvent() {
void Channel2::setNr1(const unsigned data) {
lengthCounter.nr1Change(data, nr4, cycleCounter);
dutyUnit.nr1Change(data, cycleCounter);
setEvent();
}
@ -55,7 +55,7 @@ void Channel2::setNr2(const unsigned data) {
disableMaster();
else
staticOutputTest(cycleCounter);
setEvent();
}
@ -66,17 +66,17 @@ void Channel2::setNr3(const unsigned data) {
void Channel2::setNr4(const unsigned data) {
lengthCounter.nr4Change(nr4, data, cycleCounter);
nr4 = data;
if (data & 0x80) { //init-bit
nr4 &= 0x7F;
master = !envelopeUnit.nr4Init(cycleCounter);
staticOutputTest(cycleCounter);
}
dutyUnit.nr4Change(data, cycleCounter);
setEvent();
}
@ -88,11 +88,11 @@ void Channel2::setSo(const unsigned long soMask) {
void Channel2::reset() {
cycleCounter = 0x1000 | (cycleCounter & 0xFFF); // cycleCounter >> 12 & 7 represents the frame sequencer position.
// lengthCounter.reset();
dutyUnit.reset();
envelopeUnit.reset();
setEvent();
}
@ -104,7 +104,7 @@ void Channel2::loadState(const SaveState &state) {
dutyUnit.loadState(state.spu.ch2.duty, state.mem.ioamhram.get()[0x116], state.spu.ch2.nr4,state.spu.cycleCounter);
envelopeUnit.loadState(state.spu.ch2.env, state.mem.ioamhram.get()[0x117], state.spu.cycleCounter);
lengthCounter.loadState(state.spu.ch2.lcounter, state.spu.cycleCounter);
cycleCounter = state.spu.cycleCounter;
nr4 = state.spu.ch2.nr4;
master = state.spu.ch2.master;
@ -114,41 +114,41 @@ void Channel2::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign
const unsigned long outBase = envelopeUnit.dacIsOn() ? soBaseVol & soMask : 0;
const unsigned long outLow = outBase * (0 - 15ul);
const unsigned long endCycles = cycleCounter + cycles;
for (;;) {
const unsigned long outHigh = master ? outBase * (envelopeUnit.getVolume() * 2 - 15ul) : outLow;
const unsigned long nextMajorEvent = nextEventUnit->getCounter() < endCycles ? nextEventUnit->getCounter() : endCycles;
unsigned long out = dutyUnit.isHighState() ? outHigh : outLow;
while (dutyUnit.getCounter() <= nextMajorEvent) {
*buf += out - prevOut;
prevOut = out;
buf += dutyUnit.getCounter() - cycleCounter;
cycleCounter = dutyUnit.getCounter();
dutyUnit.event();
out = dutyUnit.isHighState() ? outHigh : outLow;
}
if (cycleCounter < nextMajorEvent) {
*buf += out - prevOut;
prevOut = out;
buf += nextMajorEvent - cycleCounter;
cycleCounter = nextMajorEvent;
}
if (nextEventUnit->getCounter() == nextMajorEvent) {
nextEventUnit->event();
setEvent();
} else
break;
}
if (cycleCounter & SoundUnit::COUNTER_MAX) {
dutyUnit.resetCounters(cycleCounter);
lengthCounter.resetCounters(cycleCounter);
envelopeUnit.resetCounters(cycleCounter);
cycleCounter -= SoundUnit::COUNTER_MAX;
}
}

View File

@ -32,37 +32,37 @@ struct SaveState;
class Channel2 {
friend class StaticOutputTester<Channel2,DutyUnit>;
StaticOutputTester<Channel2,DutyUnit> staticOutputTest;
DutyMasterDisabler disableMaster;
LengthCounter lengthCounter;
DutyUnit dutyUnit;
EnvelopeUnit envelopeUnit;
SoundUnit *nextEventUnit;
unsigned long cycleCounter;
unsigned long soMask;
unsigned long prevOut;
unsigned char nr4;
bool master;
void setEvent();
public:
Channel2();
void setNr1(unsigned data);
void setNr2(unsigned data);
void setNr3(unsigned data);
void setNr4(unsigned data);
void setSo(unsigned long soMask);
// void deactivate() { disableMaster(); setEvent(); }
bool isActive() const { return master; }
void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles);
void reset();
void init(bool cgb);
void loadState(const SaveState &state);

View File

@ -47,33 +47,33 @@ Channel3::Channel3() :
void Channel3::setNr0(const unsigned data) {
nr0 = data & 0x80;
if (!(data & 0x80))
disableMaster();
}
void Channel3::setNr2(const unsigned data) {
rShift = (data >> 5 & 3U) - 1;
if (rShift > 3)
rShift = 4;
}
void Channel3::setNr4(const unsigned data) {
lengthCounter.nr4Change(nr4, data, cycleCounter);
nr4 = data & 0x7F;
if (data & nr0/* & 0x80*/) {
if (!cgb && waveCounter == cycleCounter + 1) {
const unsigned pos = ((wavePos + 1) & 0x1F) >> 1;
if (pos < 4)
waveRam[0] = waveRam[pos];
else
std::memcpy(waveRam, waveRam + (pos & ~3), 4);
}
master = true;
wavePos = 0;
lastReadTime = waveCounter = cycleCounter + toPeriod(nr3, data) + 3;
@ -102,7 +102,7 @@ void Channel3::setStatePtrs(SaveState &state) {
void Channel3::loadState(const SaveState &state) {
lengthCounter.loadState(state.spu.ch3.lcounter, state.spu.cycleCounter);
cycleCounter = state.spu.cycleCounter;
waveCounter = std::max(state.spu.ch3.waveCounter, state.spu.cycleCounter);
lastReadTime = state.spu.ch3.lastReadTime;
@ -111,7 +111,7 @@ void Channel3::loadState(const SaveState &state) {
wavePos = state.spu.ch3.wavePos & 0x1F;
sampleBuf = state.spu.ch3.sampleBuf;
master = state.spu.ch3.master;
nr0 = state.mem.ioamhram.get()[0x11A] & 0x80;
setNr2(state.mem.ioamhram.get()[0x11C]);
}
@ -133,20 +133,20 @@ void Channel3::updateWaveCounter(const unsigned long cc) {
void Channel3::update(uint_least32_t *buf, const unsigned long soBaseVol, unsigned long cycles) {
const unsigned long outBase = (nr0/* & 0x80*/) ? soBaseVol & soMask : 0;
if (outBase && rShift != 4) {
const unsigned long endCycles = cycleCounter + cycles;
for (;;) {
const unsigned long nextMajorEvent = lengthCounter.getCounter() < endCycles ? lengthCounter.getCounter() : endCycles;
unsigned long out = outBase * (master ? ((sampleBuf >> (~wavePos << 2 & 4) & 0xF) >> rShift) * 2 - 15ul : 0 - 15ul);
while (waveCounter <= nextMajorEvent) {
*buf += out - prevOut;
prevOut = out;
buf += waveCounter - cycleCounter;
cycleCounter = waveCounter;
lastReadTime = waveCounter;
waveCounter += toPeriod(nr3, nr4);
++wavePos;
@ -154,14 +154,14 @@ void Channel3::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign
sampleBuf = waveRam[wavePos >> 1];
out = outBase * (/*master ? */((sampleBuf >> (~wavePos << 2 & 4) & 0xF) >> rShift) * 2 - 15ul/* : 0 - 15ul*/);
}
if (cycleCounter < nextMajorEvent) {
*buf += out - prevOut;
prevOut = out;
buf += nextMajorEvent - cycleCounter;
cycleCounter = nextMajorEvent;
}
if (lengthCounter.getCounter() == nextMajorEvent) {
lengthCounter.event();
} else
@ -171,23 +171,23 @@ void Channel3::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign
const unsigned long out = outBase * (0 - 15ul);
*buf += out - prevOut;
prevOut = out;
cycleCounter += cycles;
while (lengthCounter.getCounter() <= cycleCounter) {
updateWaveCounter(lengthCounter.getCounter());
lengthCounter.event();
}
updateWaveCounter(cycleCounter);
}
if (cycleCounter & SoundUnit::COUNTER_MAX) {
lengthCounter.resetCounters(cycleCounter);
if (waveCounter != SoundUnit::COUNTER_DISABLED)
waveCounter -= SoundUnit::COUNTER_MAX;
lastReadTime -= SoundUnit::COUNTER_MAX;
cycleCounter -= SoundUnit::COUNTER_MAX;
}
@ -196,7 +196,7 @@ void Channel3::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign
SYNCFUNC(Channel3)
{
NSS(waveRam);
SSS(lengthCounter);
NSS(cycleCounter);

View File

@ -31,35 +31,35 @@ struct SaveState;
class Channel3 {
class Ch3MasterDisabler : public MasterDisabler {
unsigned long &waveCounter;
public:
Ch3MasterDisabler(bool &m, unsigned long &wC) : MasterDisabler(m), waveCounter(wC) {}
void operator()() { MasterDisabler::operator()(); waveCounter = SoundUnit::COUNTER_DISABLED; }
};
unsigned char waveRam[0x10];
Ch3MasterDisabler disableMaster;
LengthCounter lengthCounter;
unsigned long cycleCounter;
unsigned long soMask;
unsigned long prevOut;
unsigned long waveCounter;
unsigned long lastReadTime;
unsigned char nr0;
unsigned char nr3;
unsigned char nr4;
unsigned char wavePos;
unsigned char rShift;
unsigned char sampleBuf;
bool master;
bool cgb;
void updateWaveCounter(unsigned long cc);
public:
Channel3();
bool isActive() const { return master; }
@ -74,26 +74,26 @@ public:
void setNr4(unsigned data);
void setSo(unsigned long soMask);
void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles);
unsigned waveRamRead(unsigned index) const {
if (master) {
if (!cgb && cycleCounter != lastReadTime)
return 0xFF;
index = wavePos >> 1;
}
return waveRam[index];
}
void waveRamWrite(unsigned index, unsigned data) {
if (master) {
if (!cgb && cycleCounter != lastReadTime)
return;
index = wavePos >> 1;
}
waveRam[index] = data;
}

View File

@ -23,12 +23,12 @@
static unsigned long toPeriod(const unsigned nr3) {
unsigned s = (nr3 >> 4) + 3;
unsigned r = nr3 & 7;
if (!r) {
r = 1;
--s;
}
return r << s;
}
@ -46,13 +46,13 @@ void Channel4::Lfsr::updateBackupCounter(const unsigned long cc) {
const unsigned long period = toPeriod(nr3);
backupCounter = cc - (cc - backupCounter) % period + period;
}*/
if (backupCounter <= cc) {
const unsigned long period = toPeriod(nr3);
unsigned long periods = (cc - backupCounter) / period + 1;
backupCounter += periods * period;
if (master && nr3 < 0xE0) {
if (nr3 & 8) {
while (periods > 6) {
@ -60,7 +60,7 @@ void Channel4::Lfsr::updateBackupCounter(const unsigned long cc) {
reg = (reg >> 6 & ~0x7E) | xored | xored << 8;
periods -= 6;
}
const unsigned xored = ((reg ^ reg >> 1) << (7 - periods)) & 0x7F;
reg = (reg >> periods & ~(0x80 - (0x80 >> periods))) | xored | xored << 8;
} else {
@ -68,7 +68,7 @@ void Channel4::Lfsr::updateBackupCounter(const unsigned long cc) {
reg = reg ^ reg >> 1;
periods -= 15;
}
reg = reg >> periods | (((reg ^ reg >> 1) << (15 - periods)) & 0x7FFF);
}
}
@ -95,27 +95,27 @@ inline void Channel4::Lfsr::event() {
if (nr3 < 0xE0) {
const unsigned shifted = reg >> 1;
const unsigned xored = (reg ^ shifted) & 1;
reg = shifted | xored << 14;
if (nr3 & 8)
reg = (reg & ~0x40) | xored << 6;
}
counter += toPeriod(nr3);
backupCounter = counter;
/*if (nr3 < 0xE0) {
const unsigned periods = nextStateDistance[reg & 0x3F];
const unsigned xored = ((reg ^ reg >> 1) << (7 - periods)) & 0x7F;
reg = reg >> periods | xored << 8;
if (nr3 & 8)
reg = reg & ~(0x80 - (0x80 >> periods)) | xored;
}
const unsigned long period = toPeriod(nr3);
backupCounter = counter + period;
counter += period * nextStateDistance[reg & 0x3F];*/
@ -124,7 +124,7 @@ inline void Channel4::Lfsr::event() {
void Channel4::Lfsr::nr3Change(const unsigned newNr3, const unsigned long cc) {
updateBackupCounter(cc);
nr3 = newNr3;
// if (counter != COUNTER_DISABLED)
// counter = backupCounter + toPeriod(nr3) * (nextStateDistance[reg & 0x3F] - 1);
}
@ -191,7 +191,7 @@ void Channel4::setEvent() {
void Channel4::setNr1(const unsigned data) {
lengthCounter.nr1Change(data, nr4, cycleCounter);
setEvent();
}
@ -200,26 +200,26 @@ void Channel4::setNr2(const unsigned data) {
disableMaster();
else
staticOutputTest(cycleCounter);
setEvent();
}
void Channel4::setNr4(const unsigned data) {
lengthCounter.nr4Change(nr4, data, cycleCounter);
nr4 = data;
if (data & 0x80) { //init-bit
nr4 &= 0x7F;
master = !envelopeUnit.nr4Init(cycleCounter);
if (master)
lfsr.nr4Init(cycleCounter);
staticOutputTest(cycleCounter);
}
setEvent();
}
@ -235,7 +235,7 @@ void Channel4::reset() {
// lengthCounter.reset();
lfsr.reset(cycleCounter);
envelopeUnit.reset();
setEvent();
}
@ -247,7 +247,7 @@ void Channel4::loadState(const SaveState &state) {
lfsr.loadState(state);
envelopeUnit.loadState(state.spu.ch4.env, state.mem.ioamhram.get()[0x121], state.spu.cycleCounter);
lengthCounter.loadState(state.spu.ch4.lcounter, state.spu.cycleCounter);
cycleCounter = state.spu.cycleCounter;
nr4 = state.spu.ch4.nr4;
master = state.spu.ch4.master;
@ -257,41 +257,41 @@ void Channel4::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign
const unsigned long outBase = envelopeUnit.dacIsOn() ? soBaseVol & soMask : 0;
const unsigned long outLow = outBase * (0 - 15ul);
const unsigned long endCycles = cycleCounter + cycles;
for (;;) {
const unsigned long outHigh = /*master ? */outBase * (envelopeUnit.getVolume() * 2 - 15ul)/* : outLow*/;
const unsigned long nextMajorEvent = nextEventUnit->getCounter() < endCycles ? nextEventUnit->getCounter() : endCycles;
unsigned long out = lfsr.isHighState() ? outHigh : outLow;
while (lfsr.getCounter() <= nextMajorEvent) {
*buf += out - prevOut;
prevOut = out;
buf += lfsr.getCounter() - cycleCounter;
cycleCounter = lfsr.getCounter();
lfsr.event();
out = lfsr.isHighState() ? outHigh : outLow;
}
if (cycleCounter < nextMajorEvent) {
*buf += out - prevOut;
prevOut = out;
buf += nextMajorEvent - cycleCounter;
cycleCounter = nextMajorEvent;
}
if (nextEventUnit->getCounter() == nextMajorEvent) {
nextEventUnit->event();
setEvent();
} else
break;
}
if (cycleCounter & SoundUnit::COUNTER_MAX) {
lengthCounter.resetCounters(cycleCounter);
lfsr.resetCounters(cycleCounter);
envelopeUnit.resetCounters(cycleCounter);
cycleCounter -= SoundUnit::COUNTER_MAX;
}
}
@ -311,7 +311,7 @@ SYNCFUNC(Channel4)
NSS(cycleCounter);
NSS(soMask);
NSS(prevOut);
NSS(nr4);
NSS(master);
}

View File

@ -36,9 +36,9 @@ class Channel4 {
unsigned short reg;
unsigned char nr3;
bool master;
void updateBackupCounter(unsigned long cc);
public:
Lfsr();
void event();
@ -54,45 +54,45 @@ class Channel4 {
template<bool isReader>void SyncState(NewState *ns);
};
class Ch4MasterDisabler : public MasterDisabler {
Lfsr &lfsr;
public:
Ch4MasterDisabler(bool &m, Lfsr &lfsr) : MasterDisabler(m), lfsr(lfsr) {}
void operator()() { MasterDisabler::operator()(); lfsr.disableMaster(); }
};
friend class StaticOutputTester<Channel4,Lfsr>;
StaticOutputTester<Channel4,Lfsr> staticOutputTest;
Ch4MasterDisabler disableMaster;
LengthCounter lengthCounter;
EnvelopeUnit envelopeUnit;
Lfsr lfsr;
SoundUnit *nextEventUnit;
unsigned long cycleCounter;
unsigned long soMask;
unsigned long prevOut;
unsigned char nr4;
bool master;
void setEvent();
public:
Channel4();
void setNr1(unsigned data);
void setNr2(unsigned data);
void setNr3(unsigned data) { lfsr.nr3Change(data, cycleCounter); /*setEvent();*/ }
void setNr4(unsigned data);
void setSo(unsigned long soMask);
bool isActive() const { return master; }
void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles);
void reset();
void init(bool cgb);
void loadState(const SaveState &state);

View File

@ -21,7 +21,7 @@
static inline bool toOutState(const unsigned duty, const unsigned pos) {
static const unsigned char duties[4] = { 0x80, 0x81, 0xE1, 0x7E };
return duties[duty] >> pos & 1;
}
@ -52,7 +52,7 @@ void DutyUnit::setCounter() {
0, 3, 2, 1, 0, 3, 2, 1,
0, 5, 4, 3, 2, 1, 0, 1
};
if (enableEvents && nextPosUpdate != COUNTER_DISABLED)
counter = nextPosUpdate + period * nextStateDistance[(duty * 8) | pos];
else
@ -67,13 +67,13 @@ void DutyUnit::setFreq(const unsigned newFreq, const unsigned long cc) {
void DutyUnit::event() {
unsigned inc = period << duty;
if (duty == 3)
inc -= period * 2;
if (!(high ^= true))
inc = period * 8 - inc;
counter += inc;
}
@ -89,7 +89,7 @@ void DutyUnit::nr3Change(const unsigned newNr3, const unsigned long cc) {
void DutyUnit::nr4Change(const unsigned newNr4, const unsigned long cc) {
setFreq((newNr4 << 8 & 0x700) | (getFreq() & 0xFF), cc);
if (newNr4 & 0x80) {
nextPosUpdate = (cc & ~1) + period;
setCounter();
@ -124,7 +124,7 @@ void DutyUnit::loadState(const SaveState::SPU::Duty &dstate, const unsigned nr1,
void DutyUnit::resetCounters(const unsigned long oldCc) {
if (nextPosUpdate == COUNTER_DISABLED)
return;
updatePos(oldCc);
nextPosUpdate -= COUNTER_MAX;
SoundUnit::resetCounters(oldCc);

View File

@ -50,7 +50,7 @@ public:
void resetCounters(unsigned long oldCc);
void killCounter();
void reviveCounter(unsigned long cc);
//intended for use by SweepUnit only.
unsigned getFreq() const { return 2048 - (period >> 1); }
void setFreq(unsigned newFreq, unsigned long cc);

View File

@ -25,21 +25,21 @@ EnvelopeUnit::VolOnOffEvent EnvelopeUnit::nullEvent;
void EnvelopeUnit::event() {
const unsigned long period = nr2 & 7;
if (period) {
unsigned newVol = volume;
if (nr2 & 8)
++newVol;
else
--newVol;
if (newVol < 0x10U) {
volume = newVol;
if (volume < 2)
volOnOffEvent(counter);
counter += period << 15;
} else
counter = COUNTER_DISABLED;
@ -52,32 +52,32 @@ bool EnvelopeUnit::nr2Change(const unsigned newNr2) {
++volume;
else if (!(nr2 & 8))
volume += 2;
if ((nr2 ^ newNr2) & 8)
volume = 0x10 - volume;
volume &= 0xF;
nr2 = newNr2;
return !(newNr2 & 0xF8);
}
bool EnvelopeUnit::nr4Init(const unsigned long cc) {
{
unsigned long period = nr2 & 7;
if (!period)
period = 8;
if (!(cc & 0x7000))
++period;
counter = cc - ((cc - 0x1000) & 0x7FFF) + period * 0x8000;
}
volume = nr2 >> 4;
return !(nr2 & 0xF8);
}

View File

@ -31,13 +31,13 @@ public:
virtual ~VolOnOffEvent() {}
virtual void operator()(unsigned long /*cc*/) {}
};
private:
static VolOnOffEvent nullEvent;
VolOnOffEvent &volOnOffEvent;
unsigned char nr2;
unsigned char volume;
public:
explicit EnvelopeUnit(VolOnOffEvent &volOnOffEvent = nullEvent);
void event();

View File

@ -44,23 +44,23 @@ void LengthCounter::nr1Change(const unsigned newNr1, const unsigned nr4, const u
void LengthCounter::nr4Change(const unsigned oldNr4, const unsigned newNr4, const unsigned long cycleCounter) {
if (counter != COUNTER_DISABLED)
lengthCounter = (counter >> 13) - (cycleCounter >> 13);
{
unsigned dec = 0;
if (newNr4 & 0x40) {
dec = ~cycleCounter >> 12 & 1;
if (!(oldNr4 & 0x40) && lengthCounter) {
if (!(lengthCounter -= dec))
disableMaster();
}
}
if ((newNr4 & 0x80) && !lengthCounter)
lengthCounter = lengthMask + 1 - dec;
}
if ((newNr4 & 0x40) && lengthCounter)
counter = ((cycleCounter >> 13) + lengthCounter) << 13;
else
@ -69,7 +69,7 @@ void LengthCounter::nr4Change(const unsigned oldNr4, const unsigned newNr4, cons
/*void LengthCounter::reset() {
counter = COUNTER_DISABLED;
if (cgb)
lengthCounter = lengthMask + 1;
}*/

View File

@ -22,7 +22,7 @@
namespace gambatte {
class MasterDisabler {
bool &master;
public:
MasterDisabler(bool &m) : master(m) {}
virtual ~MasterDisabler() {}

View File

@ -26,7 +26,7 @@ protected:
unsigned long counter;
public:
enum { COUNTER_MAX = 0x80000000u, COUNTER_DISABLED = 0xFFFFFFFFu };
SoundUnit() : counter(COUNTER_DISABLED) {}
virtual ~SoundUnit() {}
virtual void event() = 0;

View File

@ -34,11 +34,11 @@ tac_(0)
void Tima::loadState(const SaveState &state, const TimaInterruptRequester timaIrq) {
lastUpdate_ = state.mem.timaLastUpdate;
tmatime_ = state.mem.tmatime;
tima_ = state.mem.ioamhram.get()[0x105];
tma_ = state.mem.ioamhram.get()[0x106];
tac_ = state.mem.ioamhram.get()[0x107];
timaIrq.setNextIrqEventTime((tac_ & 4)
?
(tmatime_ != DISABLED_TIME && tmatime_ > state.cpu.cycleCounter
@ -51,14 +51,14 @@ void Tima::loadState(const SaveState &state, const TimaInterruptRequester timaIr
void Tima::resetCc(const unsigned long oldCc, const unsigned long newCc, const TimaInterruptRequester timaIrq) {
const unsigned long dec = oldCc - newCc;
if (tac_ & 0x04) {
updateIrq(oldCc, timaIrq);
updateTima(oldCc);
lastUpdate_ -= dec;
timaIrq.setNextIrqEventTime(timaIrq.nextIrqEventTime() - dec);
if (tmatime_ != DISABLED_TIME)
tmatime_ -= dec;
}
@ -106,7 +106,7 @@ void Tima::setTima(const unsigned data, const unsigned long cycleCounter, const
timaIrq.setNextIrqEventTime(lastUpdate_ + ((256u - data) << timaClock[tac_ & 3]) + 3);
}
tima_ = data;
}
@ -115,14 +115,14 @@ void Tima::setTma(const unsigned data, const unsigned long cycleCounter, const T
updateIrq(cycleCounter, timaIrq);
updateTima(cycleCounter);
}
tma_ = data;
}
void Tima::setTac(const unsigned data, const unsigned long cycleCounter, const TimaInterruptRequester timaIrq, bool gbIsCgb) {
if (tac_ ^ data) {
unsigned long nextIrqEventTime = timaIrq.nextIrqEventTime();
if (tac_ & 0x04) {
updateIrq(cycleCounter, timaIrq);
updateTima(cycleCounter);
@ -130,10 +130,10 @@ void Tima::setTac(const unsigned data, const unsigned long cycleCounter, const T
lastUpdate_ -= (1u << (timaClock[tac_ & 3] - 1)) + 3;
tmatime_ -= (1u << (timaClock[tac_ & 3] - 1)) + 3;
nextIrqEventTime -= (1u << (timaClock[tac_ & 3] - 1)) + 3;
if (cycleCounter >= nextIrqEventTime)
timaIrq.flagIrq();
updateTima(cycleCounter);
tmatime_ = DISABLED_TIME;
@ -143,18 +143,18 @@ void Tima::setTac(const unsigned data, const unsigned long cycleCounter, const T
if (data & 4) {
lastUpdate_ = (cycleCounter >> timaClock[data & 3]) << timaClock[data & 3];
unsigned long diff = cycleCounter - basetime_;
if (gbIsCgb) {
if (((diff >> (timaClock[tac_ & 3] - 1)) & 1) == 1 && ((diff >> (timaClock[data & 3] - 1)) & 1) == 0)
tima_++;
}
}
lastUpdate_ = basetime_ + ((diff >> timaClock[data & 3]) << timaClock[data & 3]);
nextIrqEventTime = lastUpdate_ + ((256u - tima_) << timaClock[data & 3]) + 3;
}
timaIrq.setNextIrqEventTime(nextIrqEventTime);
}
tac_ = data;
}

View File

@ -25,7 +25,7 @@ namespace gambatte {
class TimaInterruptRequester {
InterruptRequester &intreq;
public:
explicit TimaInterruptRequester(InterruptRequester &intreq) : intreq(intreq) {}
void flagIrq() const { intreq.flagIrq(4); }
@ -37,29 +37,29 @@ class Tima {
unsigned long basetime_;
unsigned long lastUpdate_;
unsigned long tmatime_;
unsigned char tima_;
unsigned char tma_;
unsigned char tac_;
void updateIrq(const unsigned long cc, const TimaInterruptRequester timaIrq) {
while (cc >= timaIrq.nextIrqEventTime())
doIrqEvent(timaIrq);
}
void updateTima(unsigned long cc);
public:
Tima();
void loadState(const SaveState &, TimaInterruptRequester timaIrq);
void resetCc(unsigned long oldCc, unsigned long newCc, TimaInterruptRequester timaIrq);
void setTima(unsigned tima, unsigned long cc, TimaInterruptRequester timaIrq);
void setTma(unsigned tma, unsigned long cc, TimaInterruptRequester timaIrq);
void setTac(unsigned tac, unsigned long cc, TimaInterruptRequester timaIrq, bool gbIsCgb);
void resTac(unsigned long cc, TimaInterruptRequester timaIrq);
unsigned tima(unsigned long cc);
void doIrqEvent(TimaInterruptRequester timaIrq);
template<bool isReader>void SyncState(NewState *ns);

View File

@ -23,7 +23,7 @@
namespace gambatte {
void LCD::setDmgPalette(unsigned long *const palette, const unsigned long *const dmgColors, const unsigned data) {
void LCD::setDmgPalette(unsigned long palette[], const unsigned long dmgColors[], unsigned data) {
palette[0] = dmgColors[data & 3];
palette[1] = dmgColors[data >> 2 & 3];
palette[2] = dmgColors[data >> 4 & 3];
@ -77,18 +77,18 @@ void LCD::setCgb(bool cgb) {
static unsigned long mode2IrqSchedule(const unsigned statReg, const LyCounter &lyCounter, const unsigned long cycleCounter) {
if (!(statReg & 0x20))
return DISABLED_TIME;
unsigned next = lyCounter.time() - cycleCounter;
if (lyCounter.ly() >= 143 || (lyCounter.ly() == 142 && next <= 4) || (statReg & 0x08)) {
next += (153u - lyCounter.ly()) * lyCounter.lineTime();
} else {
if (next <= 4)
next += lyCounter.lineTime();
next -= 4;
}
return cycleCounter + next;
}
@ -96,12 +96,12 @@ static inline unsigned long m0IrqTimeFromXpos166Time(const unsigned long xpos166
return xpos166Time + cgb - ds;
}
static inline unsigned long hdmaTimeFromM0Time(const unsigned long m0Time, const bool ds) {
static inline unsigned long hdmaTimeFromM0Time(unsigned long m0Time, bool ds) {
return m0Time + 1 - ds;
}
static unsigned long nextHdmaTime(const unsigned long lastM0Time,
const unsigned long nextM0Time, const unsigned long cycleCounter, const bool ds) {
static unsigned long nextHdmaTime(unsigned long lastM0Time,
unsigned long nextM0Time, unsigned long cycleCounter, bool ds) {
return cycleCounter < hdmaTimeFromM0Time(lastM0Time, ds)
? hdmaTimeFromM0Time(lastM0Time, ds)
: hdmaTimeFromM0Time(nextM0Time, ds);
@ -125,7 +125,7 @@ void LCD::loadState(const SaveState &state, const unsigned char *const oamram) {
if (ppu.lcdc() & 0x80) {
nextM0Time_.predictNextM0Time(ppu);
lycIrq.reschedule(ppu.lyCounter(), ppu.now());
eventTimes_.setm<ONESHOT_LCDSTATIRQ>(state.ppu.pendingLcdstatIrq
? ppu.now() + 1 : static_cast<unsigned long>(DISABLED_TIME));
eventTimes_.setm<ONESHOT_UPDATEWY2>(state.ppu.oldWy != state.mem.ioamhram.get()[0x14A]
@ -140,8 +140,8 @@ void LCD::loadState(const SaveState &state, const unsigned char *const oamram) {
? nextHdmaTime(ppu.lastM0Time(), nextM0Time_.predictedNextM0Time(), ppu.now(), isDoubleSpeed())
: static_cast<unsigned long>(DISABLED_TIME));
} else for (int i = 0; i < NUM_MEM_EVENTS; ++i)
eventTimes_.set(static_cast<MemEvent>(i), DISABLED_TIME);
eventTimes_.set(MemEvent(i), DISABLED_TIME);
refreshPalettes();
}
@ -200,7 +200,7 @@ static void clear(T *buf, const unsigned long color, const int dpitch) {
void LCD::updateScreen(const bool blanklcd, const unsigned long cycleCounter) {
update(cycleCounter);
if (blanklcd && ppu.frameBuf().fb()) {
const unsigned long color = ppu.cgb() ? gbcToRgb32(0xFFFF) : dmgColorsRgb32[0];
clear(ppu.frameBuf().fb(), color, ppu.frameBuf().pitch());
@ -210,18 +210,18 @@ void LCD::updateScreen(const bool blanklcd, const unsigned long cycleCounter) {
void LCD::resetCc(const unsigned long oldCc, const unsigned long newCc) {
update(oldCc);
ppu.resetCc(oldCc, newCc);
if (ppu.lcdc() & 0x80) {
const unsigned long dec = oldCc - newCc;
nextM0Time_.invalidatePredictedNextM0Time();
lycIrq.reschedule(ppu.lyCounter(), newCc);
for (int i = 0; i < NUM_MEM_EVENTS; ++i) {
if (eventTimes_(static_cast<MemEvent>(i)) != DISABLED_TIME)
eventTimes_.set(static_cast<MemEvent>(i), eventTimes_(static_cast<MemEvent>(i)) - dec);
if (eventTimes_(MemEvent(i)) != DISABLED_TIME)
eventTimes_.set(MemEvent(i), eventTimes_(MemEvent(i)) - dec);
}
eventTimes_.set<LY_COUNT>(ppu.lyCounter().time());
}
}
@ -229,20 +229,20 @@ void LCD::resetCc(const unsigned long oldCc, const unsigned long newCc) {
void LCD::speedChange(const unsigned long cycleCounter) {
update(cycleCounter);
ppu.speedChange(cycleCounter);
if (ppu.lcdc() & 0x80) {
nextM0Time_.predictNextM0Time(ppu);
lycIrq.reschedule(ppu.lyCounter(), cycleCounter);
eventTimes_.set<LY_COUNT>(ppu.lyCounter().time());
eventTimes_.setm<SPRITE_MAP>(SpriteMapper::schedule(ppu.lyCounter(), cycleCounter));
eventTimes_.setm<LYC_IRQ>(lycIrq.time());
eventTimes_.setm<MODE1_IRQ>(ppu.lyCounter().nextFrameCycle(144 * 456, cycleCounter));
eventTimes_.setm<MODE2_IRQ>(mode2IrqSchedule(statReg, ppu.lyCounter(), cycleCounter));
if (eventTimes_(MODE0_IRQ) != DISABLED_TIME && eventTimes_(MODE0_IRQ) - cycleCounter > 1)
eventTimes_.setm<MODE0_IRQ>(m0IrqTimeFromXpos166Time(ppu.predictedNextXposTime(166), ppu.cgb(), isDoubleSpeed()));
if (hdmaIsEnabled() && eventTimes_(HDMA_REQ) - cycleCounter > 1) {
eventTimes_.setm<HDMA_REQ>(nextHdmaTime(ppu.lastM0Time(),
nextM0Time_.predictedNextM0Time(), cycleCounter, isDoubleSpeed()));
@ -261,7 +261,7 @@ unsigned long LCD::m0TimeOfCurrentLine(const unsigned long cc) {
update(cc);
nextM0Time_.predictNextM0Time(ppu);
}
return gambatte::m0TimeOfCurrentLine(ppu.lyCounter().time(), ppu.lastM0Time(), nextM0Time_.predictedNextM0Time());
}
@ -269,7 +269,7 @@ static bool isHdmaPeriod(const LyCounter &lyCounter,
const unsigned long m0TimeOfCurrentLy, const unsigned long cycleCounter)
{
const unsigned timeToNextLy = lyCounter.time() - cycleCounter;
return /*(ppu.lcdc & 0x80) && */lyCounter.ly() < 144 && timeToNextLy > 4
&& cycleCounter >= hdmaTimeFromM0Time(m0TimeOfCurrentLy, lyCounter.isDoubleSpeed());
}
@ -280,27 +280,27 @@ void LCD::enableHdma(const unsigned long cycleCounter) {
nextM0Time_.predictNextM0Time(ppu);
} else if (cycleCounter >= eventTimes_.nextEventTime())
update(cycleCounter);
if (isHdmaPeriod(ppu.lyCounter(),
gambatte::m0TimeOfCurrentLine(ppu.lyCounter().time(),
ppu.lastM0Time(), nextM0Time_.predictedNextM0Time()), cycleCounter)) {
eventTimes_.flagHdmaReq();
}
eventTimes_.setm<HDMA_REQ>(nextHdmaTime(ppu.lastM0Time(), nextM0Time_.predictedNextM0Time(), cycleCounter, isDoubleSpeed()));
}
void LCD::disableHdma(const unsigned long cycleCounter) {
if (cycleCounter >= eventTimes_.nextEventTime())
update(cycleCounter);
eventTimes_.setm<HDMA_REQ>(DISABLED_TIME);
}
bool LCD::vramAccessible(const unsigned long cycleCounter) {
if (cycleCounter >= eventTimes_.nextEventTime())
update(cycleCounter);
return !(ppu.lcdc() & 0x80) || ppu.lyCounter().ly() >= 144
|| ppu.lyCounter().lineCycles(cycleCounter) < 80U
|| cycleCounter + isDoubleSpeed() - ppu.cgb() + 2 >= m0TimeOfCurrentLine(cycleCounter);
@ -309,7 +309,7 @@ bool LCD::vramAccessible(const unsigned long cycleCounter) {
bool LCD::cgbpAccessible(const unsigned long cycleCounter) {
if (cycleCounter >= eventTimes_.nextEventTime())
update(cycleCounter);
return !(ppu.lcdc() & 0x80) || ppu.lyCounter().ly() >= 144
|| ppu.lyCounter().lineCycles(cycleCounter) < 80U + isDoubleSpeed()
|| cycleCounter >= m0TimeOfCurrentLine(cycleCounter) + 3 - isDoubleSpeed();
@ -319,17 +319,17 @@ void LCD::doCgbColorChange(unsigned char *const pdata,
unsigned long *const palette, unsigned index, const unsigned data) {
pdata[index] = data;
index >>= 1;
palette[index] = gbcToRgb32(pdata[index << 1] | pdata[(index << 1) + 1] << 8);
palette[index] = gbcToRgb32(pdata[index * 2] | pdata[(index * 2) + 1] << 8);
}
void LCD::doCgbBgColorChange(unsigned index, const unsigned data, const unsigned long cycleCounter) {
void LCD::doCgbBgColorChange(unsigned index, unsigned data, unsigned long cycleCounter) {
if (cgbpAccessible(cycleCounter)) {
update(cycleCounter);
doCgbColorChange(bgpData, ppu.bgPalette(), index, data);
}
}
void LCD::doCgbSpColorChange(unsigned index, const unsigned data, const unsigned long cycleCounter) {
void LCD::doCgbSpColorChange(unsigned index, unsigned data, unsigned long cycleCounter) {
if (cgbpAccessible(cycleCounter)) {
update(cycleCounter);
doCgbColorChange(objpData, ppu.spPalette(), index, data);
@ -339,7 +339,7 @@ void LCD::doCgbSpColorChange(unsigned index, const unsigned data, const unsigned
bool LCD::oamReadable(const unsigned long cycleCounter) {
if (!(ppu.lcdc() & 0x80) || ppu.inactivePeriodAfterDisplayEnable(cycleCounter))
return true;
if (cycleCounter >= eventTimes_.nextEventTime())
update(cycleCounter);
@ -352,7 +352,7 @@ bool LCD::oamReadable(const unsigned long cycleCounter) {
bool LCD::oamWritable(const unsigned long cycleCounter) {
if (!(ppu.lcdc() & 0x80) || ppu.inactivePeriodAfterDisplayEnable(cycleCounter))
return true;
if (cycleCounter >= eventTimes_.nextEventTime())
update(cycleCounter);
@ -387,7 +387,7 @@ void LCD::wyChange(const unsigned newValue, const unsigned long cycleCounter) {
update(cycleCounter + 1);
ppu.setWy(newValue);
// mode3CyclesChange(); // should be safe to wait until after wy2 delay, because no mode3 events are close to when wy1 is read.
// wy2 is a delayed version of wy. really just slowness of ly == wy comparison.
if (ppu.cgb() && (ppu.lcdc() & 0x80)) {
eventTimes_.setm<ONESHOT_UPDATEWY2>(cycleCounter + 5);
@ -420,7 +420,7 @@ void LCD::oamChange(const unsigned long cycleCounter) {
void LCD::oamChange(const unsigned char *const oamram, const unsigned long cycleCounter) {
update(cycleCounter);
ppu.oamChange(oamram, cycleCounter);
if (ppu.lcdc() & 0x80)
eventTimes_.setm<SPRITE_MAP>(SpriteMapper::schedule(ppu.lyCounter(), cycleCounter));
}
@ -428,53 +428,53 @@ void LCD::oamChange(const unsigned char *const oamram, const unsigned long cycle
void LCD::lcdcChange(const unsigned data, const unsigned long cycleCounter) {
const unsigned oldLcdc = ppu.lcdc();
update(cycleCounter);
if ((oldLcdc ^ data) & 0x80) {
ppu.setLcdc(data, cycleCounter);
if (data & 0x80) {
lycIrq.lcdReset();
m0Irq_.lcdReset(statReg, lycIrq.lycReg());
if (lycIrq.lycReg() == 0 && (statReg & 0x40))
eventTimes_.flagIrq(2);
nextM0Time_.predictNextM0Time(ppu);
lycIrq.reschedule(ppu.lyCounter(), cycleCounter);
eventTimes_.set<LY_COUNT>(ppu.lyCounter().time());
eventTimes_.setm<SPRITE_MAP>(SpriteMapper::schedule(ppu.lyCounter(), cycleCounter));
eventTimes_.setm<LYC_IRQ>(lycIrq.time());
eventTimes_.setm<MODE1_IRQ>(ppu.lyCounter().nextFrameCycle(144 * 456, cycleCounter));
eventTimes_.setm<MODE2_IRQ>(mode2IrqSchedule(statReg, ppu.lyCounter(), cycleCounter));
if (statReg & 0x08)
eventTimes_.setm<MODE0_IRQ>(m0IrqTimeFromXpos166Time(ppu.predictedNextXposTime(166), ppu.cgb(), isDoubleSpeed()));
if (hdmaIsEnabled()) {
eventTimes_.setm<HDMA_REQ>(nextHdmaTime(ppu.lastM0Time(),
nextM0Time_.predictedNextM0Time(), cycleCounter, isDoubleSpeed()));
}
} else for (int i = 0; i < NUM_MEM_EVENTS; ++i)
eventTimes_.set(static_cast<MemEvent>(i), DISABLED_TIME);
eventTimes_.set(MemEvent(i), DISABLED_TIME);
} else if (data & 0x80) {
if (ppu.cgb()) {
ppu.setLcdc((oldLcdc & ~0x14) | (data & 0x14), cycleCounter);
if ((oldLcdc ^ data) & 0x04)
eventTimes_.setm<SPRITE_MAP>(SpriteMapper::schedule(ppu.lyCounter(), cycleCounter));
update(cycleCounter + isDoubleSpeed() + 1);
ppu.setLcdc(data, cycleCounter + isDoubleSpeed() + 1);
if ((oldLcdc ^ data) & 0x20)
mode3CyclesChange();
} else {
ppu.setLcdc(data, cycleCounter);
if ((oldLcdc ^ data) & 0x04)
eventTimes_.setm<SPRITE_MAP>(SpriteMapper::schedule(ppu.lyCounter(), cycleCounter));
if ((oldLcdc ^ data) & 0x22)
mode3CyclesChange();
}
@ -512,7 +512,7 @@ void LCD::lcdstatChange(unsigned const data, unsigned long const cycleCounter) {
unsigned const old = statReg;
statReg = data;
lycIrq.statRegChange(data, ppu.lyCounter(), cycleCounter);
if (ppu.lcdc() & 0x80) {
int const timeToNextLy = ppu.lyCounter().time() - cycleCounter;
LyCnt const lycCmp = getLycCmpLy(ppu.lyCounter(), cycleCounter);
@ -565,12 +565,12 @@ void LCD::lcdstatChange(unsigned const data, unsigned long const cycleCounter) {
eventTimes_.setm<MODE2_IRQ>(mode2IrqSchedule(data, ppu.lyCounter(), cycleCounter));
eventTimes_.setm<LYC_IRQ>(lycIrq.time());
}
m2IrqStatReg_ = eventTimes_(MODE2_IRQ) - cycleCounter > (ppu.cgb() - isDoubleSpeed()) * 4U
? data : (m2IrqStatReg_ & 0x10) | (statReg & ~0x10);
m1IrqStatReg_ = eventTimes_(MODE1_IRQ) - cycleCounter > (ppu.cgb() - isDoubleSpeed()) * 4U
? data : (m1IrqStatReg_ & 0x08) | (statReg & ~0x08);
m0Irq_.statRegChange(data, eventTimes_(MODE0_IRQ), cycleCounter, ppu.cgb());
}
@ -583,16 +583,16 @@ void LCD::lycRegChange(unsigned const data, unsigned long const cycleCounter) {
if (cycleCounter >= eventTimes_.nextEventTime())
update(cycleCounter);
m0Irq_.lycRegChange(data, eventTimes_(MODE0_IRQ), cycleCounter, isDoubleSpeed(), ppu.cgb());
m0Irq_.lycRegChange(data, eventTimes_(MODE0_IRQ), cycleCounter, isDoubleSpeed(), ppu.cgb());
lycIrq.lycRegChange(data, ppu.lyCounter(), cycleCounter);
if (!(ppu.lcdc() & 0x80))
return;
eventTimes_.setm<LYC_IRQ>(lycIrq.time());
int const timeToNextLy = ppu.lyCounter().time() - cycleCounter;
if ((statReg & 0x40) && data < 154
&& (ppu.lyCounter().ly() < 144
? !(statReg & 0x08) || cycleCounter < m0TimeOfCurrentLine(cycleCounter) || timeToNextLy <= 4 << ppu.cgb()
@ -649,22 +649,22 @@ inline void LCD::doMode2IrqEvent() {
const unsigned ly = eventTimes_(LY_COUNT) - eventTimes_(MODE2_IRQ) < 8
? (ppu.lyCounter().ly() == 153 ? 0 : ppu.lyCounter().ly() + 1)
: ppu.lyCounter().ly();
if ((ly != 0 || !(m2IrqStatReg_ & 0x10)) &&
(!(m2IrqStatReg_ & 0x40) || (lycIrq.lycReg() != 0 ? ly != (lycIrq.lycReg() + 1U) : ly > 1))) {
eventTimes_.flagIrq(2);
}
m2IrqStatReg_ = statReg;
if (!(statReg & 0x08)) {
unsigned long nextTime = eventTimes_(MODE2_IRQ) + ppu.lyCounter().lineTime();
if (ly == 0) {
nextTime -= 4;
} else if (ly == 143)
nextTime += ppu.lyCounter().lineTime() * 10 + 4;
eventTimes_.setm<MODE2_IRQ>(nextTime);
} else
eventTimes_.setm<MODE2_IRQ>(eventTimes_(MODE2_IRQ) + (70224 << isDoubleSpeed()));
@ -679,7 +679,7 @@ inline void LCD::event() {
m1IrqStatReg_ = statReg;
eventTimes_.setm<MODE1_IRQ>(eventTimes_(MODE1_IRQ) + (70224 << isDoubleSpeed()));
break;
case LYC_IRQ: {
unsigned char ifreg = 0;
lycIrq.doEvent(&ifreg, ppu.lyCounter());
@ -687,48 +687,48 @@ inline void LCD::event() {
eventTimes_.setm<LYC_IRQ>(lycIrq.time());
break;
}
case SPRITE_MAP:
eventTimes_.setm<SPRITE_MAP>(ppu.doSpriteMapEvent(eventTimes_(SPRITE_MAP)));
mode3CyclesChange();
break;
case HDMA_REQ:
eventTimes_.flagHdmaReq();
nextM0Time_.predictNextM0Time(ppu);
eventTimes_.setm<HDMA_REQ>(hdmaTimeFromM0Time(nextM0Time_.predictedNextM0Time(), isDoubleSpeed()));
break;
case MODE2_IRQ:
doMode2IrqEvent();
break;
case MODE0_IRQ:
{
unsigned char ifreg = 0;
m0Irq_.doEvent(&ifreg, ppu.lyCounter().ly(), statReg, lycIrq.lycReg());
eventTimes_.flagIrq(ifreg);
}
eventTimes_.setm<MODE0_IRQ>((statReg & 0x08)
eventTimes_.setm<MODE0_IRQ>(statReg & 0x08
? m0IrqTimeFromXpos166Time(ppu.predictedNextXposTime(166), ppu.cgb(), isDoubleSpeed())
: static_cast<unsigned long>(DISABLED_TIME));
break;
case ONESHOT_LCDSTATIRQ:
eventTimes_.flagIrq(2);
eventTimes_.setm<ONESHOT_LCDSTATIRQ>(DISABLED_TIME);
break;
case ONESHOT_UPDATEWY2:
ppu.updateWy2();
mode3CyclesChange();
eventTimes_.setm<ONESHOT_UPDATEWY2>(DISABLED_TIME);
break;
}
break;
case LY_COUNT:
ppu.doLyCountEvent();
eventTimes_.set<LY_COUNT>(ppu.lyCounter().time());
@ -741,12 +741,12 @@ inline void LCD::event() {
void LCD::update(const unsigned long cycleCounter) {
if (!(ppu.lcdc() & 0x80))
return;
while (cycleCounter >= eventTimes_.nextEventTime()) {
ppu.update(eventTimes_.nextEventTime());
event();
}
ppu.update(cycleCounter);
}

View File

@ -31,7 +31,7 @@ namespace gambatte {
class VideoInterruptRequester {
InterruptRequester * intreq;
public:
explicit VideoInterruptRequester(InterruptRequester * intreq) : intreq(intreq) {}
void flagHdmaReq() const { gambatte::flagHdmaReq(intreq); }
@ -42,40 +42,40 @@ public:
class M0Irq {
unsigned char statReg_;
unsigned char lycReg_;
public:
M0Irq() : statReg_(0), lycReg_(0) {}
void lcdReset(const unsigned statReg, const unsigned lycReg) {
statReg_ = statReg;
lycReg_ = lycReg;
}
void statRegChange(const unsigned statReg,
const unsigned long nextM0IrqTime, const unsigned long cc, const bool cgb) {
if (nextM0IrqTime - cc > cgb * 2U)
statReg_ = statReg;
}
void lycRegChange(const unsigned lycReg,
const unsigned long nextM0IrqTime, const unsigned long cc, const bool ds, const bool cgb) {
if (nextM0IrqTime - cc > cgb * 5 + 1U - ds)
lycReg_ = lycReg;
}
void doEvent(unsigned char *const ifreg, const unsigned ly, const unsigned statReg, const unsigned lycReg) {
if (((statReg_ | statReg) & 0x08) && (!(statReg_ & 0x40) || ly != lycReg_))
*ifreg |= 2;
statReg_ = statReg;
lycReg_ = lycReg;
}
void loadState(const SaveState &state) {
lycReg_ = state.ppu.m0lyc;
statReg_ = state.mem.ioamhram.get()[0x141];
}
unsigned statReg() const { return statReg_; }
template<bool isReader>
@ -90,33 +90,33 @@ class LCD {
enum Event { MEM_EVENT, LY_COUNT }; enum { NUM_EVENTS = LY_COUNT + 1 };
enum MemEvent { ONESHOT_LCDSTATIRQ, ONESHOT_UPDATEWY2, MODE1_IRQ, LYC_IRQ, SPRITE_MAP,
HDMA_REQ, MODE2_IRQ, MODE0_IRQ }; enum { NUM_MEM_EVENTS = MODE0_IRQ + 1 };
class EventTimes {
MinKeeper<NUM_EVENTS> eventMin_;
MinKeeper<NUM_MEM_EVENTS> memEventMin_;
VideoInterruptRequester memEventRequester_;
void setMemEvent() {
const unsigned long nmet = nextMemEventTime();
eventMin_.setValue<MEM_EVENT>(nmet);
memEventRequester_.setNextEventTime(nmet);
}
public:
explicit EventTimes(const VideoInterruptRequester memEventRequester) : memEventRequester_(memEventRequester) {}
Event nextEvent() const { return static_cast<Event>(eventMin_.min()); }
unsigned long nextEventTime() const { return eventMin_.minValue(); }
unsigned long operator()(const Event e) const { return eventMin_.value(e); }
template<Event e> void set(const unsigned long time) { eventMin_.setValue<e>(time); }
void set(const Event e, const unsigned long time) { eventMin_.setValue(e, time); }
MemEvent nextMemEvent() const { return static_cast<MemEvent>(memEventMin_.min()); }
unsigned long nextMemEventTime() const { return memEventMin_.minValue(); }
unsigned long operator()(const MemEvent e) const { return memEventMin_.value(e); }
template<MemEvent e> void setm(const unsigned long time) { memEventMin_.setValue<e>(time); setMemEvent(); }
void set(const MemEvent e, const unsigned long time) { memEventMin_.setValue(e, time); setMemEvent(); }
void flagIrq(const unsigned bit) { memEventRequester_.flagIrq(bit); }
void flagHdmaReq() { memEventRequester_.flagHdmaReq(); }
@ -128,7 +128,7 @@ class LCD {
//SSS(memEventRequester_); // not needed
}
};
PPU ppu;
unsigned long dmgColorsRgb32[3 * 4];
unsigned long cgbColorsRgb32[32768];
@ -144,7 +144,7 @@ class LCD {
unsigned char m2IrqStatReg_;
unsigned char m1IrqStatReg_;
static void setDmgPalette(unsigned long *palette, const unsigned long *dmgColors, unsigned data);
static void setDmgPalette(unsigned long palette[], const unsigned long dmgColors[], unsigned data);
void setDmgPaletteColor(unsigned index, unsigned long rgb32);
unsigned long gbcToRgb32(const unsigned bgr15);
@ -158,7 +158,7 @@ class LCD {
unsigned long m0TimeOfCurrentLine(unsigned long cc);
bool cgbpAccessible(unsigned long cycleCounter);
void mode3CyclesChange();
void doCgbBgColorChange(unsigned index, unsigned data, unsigned long cycleCounter);
void doCgbSpColorChange(unsigned index, unsigned data, unsigned long cycleCounter);
@ -242,7 +242,7 @@ public:
update(cycleCounter);
lyReg = ppu.lyCounter().ly();
if (lyReg == 153) {
if (isDoubleSpeed()) {
if (ppu.lyCounter().time() - cycleCounter <= 456 * 2 - 8)
@ -261,13 +261,13 @@ public:
void lcdcChange(unsigned data, unsigned long cycleCounter);
void lcdstatChange(unsigned data, unsigned long cycleCounter);
void lycRegChange(unsigned data, unsigned long cycleCounter);
void enableHdma(unsigned long cycleCounter);
void disableHdma(unsigned long cycleCounter);
bool hdmaIsEnabled() const { return eventTimes_(HDMA_REQ) != DISABLED_TIME; }
void update(unsigned long cycleCounter);
bool isCgb() const { return ppu.cgb(); }
bool isDoubleSpeed() const { return ppu.lyCounter().isDoubleSpeed(); }

View File

@ -30,28 +30,28 @@ LyCounter::LyCounter()
void LyCounter::doEvent() {
++ly_;
if (ly_ == 154)
ly_ = 0;
time_ = time_ + lineTime_;
}
unsigned long LyCounter::nextLineCycle(const unsigned lineCycle, const unsigned long cycleCounter) const {
unsigned long tmp = time_ + (lineCycle << ds);
if (tmp - cycleCounter > lineTime_)
tmp -= lineTime_;
return tmp;
}
unsigned long LyCounter::nextFrameCycle(const unsigned long frameCycle, const unsigned long cycleCounter) const {
unsigned long tmp = time_ + (((153U - ly()) * 456U + frameCycle) << ds);
if (tmp - cycleCounter > 70224U << ds)
tmp -= 70224U << ds;
return tmp;
}

View File

@ -30,20 +30,20 @@ class LyCounter {
unsigned short lineTime_;
unsigned char ly_;
bool ds;
public:
LyCounter();
void doEvent();
bool isDoubleSpeed() const { return ds; }
unsigned long frameCycles(const unsigned long cc) const {
return ly_ * 456ul + lineCycles(cc);
}
unsigned lineCycles(const unsigned long cc) const {
return 456u - ((time_ - cc) >> isDoubleSpeed());
}
unsigned lineTime() const { return lineTime_; }
unsigned ly() const { return ly_; }
unsigned long nextLineCycle(unsigned lineCycle, unsigned long cycleCounter) const;

View File

@ -45,20 +45,20 @@ void LycIrq::regChange(const unsigned statReg, const unsigned lycReg, const LyCo
statRegSrc_ = statReg;
lycRegSrc_ = lycReg;
time_ = std::min(time_, timeSrc);
if (cgb_) {
if (time_ - cc > 8 || (timeSrc != time_ && time_ - cc > 4U - lyCounter.isDoubleSpeed() * 4U))
lycReg_ = lycReg;
if (time_ - cc > 4U - lyCounter.isDoubleSpeed() * 4U)
statReg_ = statReg;
} else {
if (time_ - cc > 4 || timeSrc != time_)
lycReg_ = lycReg;
if (time_ - cc > 4 || lycReg_ != 0)
statReg_ = statReg;
statReg_ = (statReg_ & 0x40) | (statReg & ~0x40);
}
}
@ -66,13 +66,13 @@ void LycIrq::regChange(const unsigned statReg, const unsigned lycReg, const LyCo
void LycIrq::doEvent(unsigned char *const ifreg, const LyCounter &lyCounter) {
if ((statReg_ | statRegSrc_) & 0x40) {
const unsigned cmpLy = lyCounter.time() - time_ < lyCounter.lineTime() ? 0 : lyCounter.ly();
if (lycReg_ == cmpLy &&
(lycReg_ - 1U < 144U - 1U ? !(statReg_ & 0x20) : !(statReg_ & 0x10))) {
*ifreg |= 2;
}
}
lycReg_ = lycRegSrc_;
statReg_ = statRegSrc_;
time_ = schedule(statReg_, lycReg_, lyCounter, time_);

View File

@ -33,9 +33,9 @@ class LycIrq {
unsigned char lycReg_;
unsigned char statReg_;
bool cgb_;
void regChange(unsigned statReg, unsigned lycReg, const LyCounter &lyCounter, unsigned long cc);
public:
LycIrq();
void doEvent(unsigned char *ifreg, const LyCounter &lyCounter);
@ -45,11 +45,11 @@ public:
void setCgb(const bool cgb) { cgb_ = cgb; }
void lcdReset();
void reschedule(const LyCounter & lyCounter, unsigned long cc);
void statRegChange(unsigned statReg, const LyCounter &lyCounter, unsigned long cc) {
regChange(statReg, lycRegSrc_, lyCounter, cc);
}
void lycRegChange(unsigned lycReg, const LyCounter &lyCounter, unsigned long cc) {
regChange(statRegSrc_, lycReg, lyCounter, cc);
}

View File

@ -7,7 +7,7 @@ namespace gambatte {
class NextM0Time {
unsigned predictedNextM0Time_;
public:
NextM0Time() : predictedNextM0Time_(0) {}
void predictNextM0Time(const class PPU &v);

File diff suppressed because it is too large Load Diff

View File

@ -33,9 +33,9 @@ class PPUFrameBuf {
uint_least32_t *buf_;
uint_least32_t *fbline_;
int pitch_;
static uint_least32_t * nullfbline() { static uint_least32_t nullfbline_[160]; return nullfbline_; }
public:
PPUFrameBuf() : buf_(0), fbline_(nullfbline()), pitch_(0) {}
uint_least32_t * fb() const { return buf_; }
@ -93,7 +93,7 @@ struct PPUPriv {
bool cgb;
bool weMaster;
PPUPriv(NextM0Time &nextM0Time, const unsigned char *oamram, const unsigned char *vram);
};
@ -104,7 +104,7 @@ public:
: p_(nextM0Time, oamram, vram)
{
}
unsigned long * bgPalette() { return p_.bgPalette; }
bool cgb() const { return p_.cgb; }
void doLyCountEvent() { p_.lyCounter.doEvent(); }

View File

@ -83,10 +83,10 @@ void SpriteMapper::OamReader::update(const unsigned long cc) {
if (!(pos & 1)) {
if (pos == 80)
pos = 0;
if (cgb_)
szbuf[pos >> 1] = largeSpritesSrc;
buf[pos ] = oamram[pos * 2 ];
buf[pos + 1] = oamram[pos * 2 + 1];
} else
@ -194,7 +194,7 @@ SYNCFUNC(SpriteMapper)
{
NSS(spritemap);
NSS(num);
SSS(nextM0Time_);
SSS(oamReader);
}

View File

@ -78,7 +78,7 @@ public:
private:
mutable unsigned char spritemap[144*10];
mutable unsigned char num[144];
NextM0Time &nextM0Time_;
OamReader oamReader;

Binary file not shown.