From 567756d6cc841408bf3363fc064dcbfc7703058d Mon Sep 17 00:00:00 2001 From: MrWint Date: Sat, 25 May 2019 19:18:15 +0200 Subject: [PATCH] formatting/readability --- libgambatte/Makefile | 2 +- libgambatte/include/gambatte.h | 16 +- libgambatte/src/common/array.h | 4 +- libgambatte/src/cpu.cpp | 278 +++++------ libgambatte/src/cpu.h | 30 +- libgambatte/src/file/stdfile.h | 2 +- libgambatte/src/gambatte.cpp | 22 +- libgambatte/src/initstate.cpp | 102 ++-- libgambatte/src/insertion_sort.h | 12 +- libgambatte/src/interrupter.cpp | 2 +- libgambatte/src/interruptrequester.cpp | 18 +- libgambatte/src/interruptrequester.h | 24 +- libgambatte/src/mem/cartridge.cpp | 20 +- libgambatte/src/mem/cartridge.h | 12 +- libgambatte/src/mem/memptrs.cpp | 6 +- libgambatte/src/mem/memptrs.h | 8 +- libgambatte/src/mem/rtc.cpp | 14 +- libgambatte/src/mem/rtc.h | 22 +- libgambatte/src/memory.cpp | 48 +- libgambatte/src/memory.h | 30 +- libgambatte/src/minkeeper.h | 40 +- libgambatte/src/newstate.h | 2 +- libgambatte/src/savestate.h | 28 +- libgambatte/src/sound.cpp | 20 +- libgambatte/src/sound.h | 12 +- libgambatte/src/sound/channel1.cpp | 50 +- libgambatte/src/sound/channel1.h | 24 +- libgambatte/src/sound/channel2.cpp | 32 +- libgambatte/src/sound/channel2.h | 18 +- libgambatte/src/sound/channel3.cpp | 42 +- libgambatte/src/sound/channel3.h | 28 +- libgambatte/src/sound/channel4.cpp | 68 +-- libgambatte/src/sound/channel4.h | 26 +- libgambatte/src/sound/duty_unit.cpp | 14 +- libgambatte/src/sound/duty_unit.h | 2 +- libgambatte/src/sound/envelope_unit.cpp | 28 +- libgambatte/src/sound/envelope_unit.h | 4 +- libgambatte/src/sound/length_counter.cpp | 12 +- libgambatte/src/sound/master_disabler.h | 2 +- libgambatte/src/sound/sound_unit.h | 2 +- libgambatte/src/tima.cpp | 28 +- libgambatte/src/tima.h | 14 +- libgambatte/src/video.cpp | 146 +++--- libgambatte/src/video.h | 44 +- libgambatte/src/video/ly_counter.cpp | 12 +- libgambatte/src/video/ly_counter.h | 8 +- libgambatte/src/video/lyc_irq.cpp | 12 +- libgambatte/src/video/lyc_irq.h | 8 +- libgambatte/src/video/next_m0_time.h | 2 +- libgambatte/src/video/ppu.cpp | 562 +++++++++++------------ libgambatte/src/video/ppu.h | 8 +- libgambatte/src/video/sprite_mapper.cpp | 6 +- libgambatte/src/video/sprite_mapper.h | 2 +- output/dll/libgambatte.dll | Bin 142336 -> 142336 bytes 54 files changed, 989 insertions(+), 989 deletions(-) diff --git a/libgambatte/Makefile b/libgambatte/Makefile index 33e7712716..5ae56f6a29 100644 --- a/libgambatte/Makefile +++ b/libgambatte/Makefile @@ -61,6 +61,6 @@ $(TARGET) : $(OBJS) clean: $(RM) $(OBJS) $(RM) $(TARGET) - + install: $(CP) $(TARGET) $(DEST_$(ARCH)) diff --git a/libgambatte/include/gambatte.h b/libgambatte/include/gambatte.h index a3553bc139..c90620eb01 100644 --- a/libgambatte/include/gambatte.h +++ b/libgambatte/include/gambatte.h @@ -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; diff --git a/libgambatte/src/common/array.h b/libgambatte/src/common/array.h index c650390d4e..cc45e8584a 100644 --- a/libgambatte/src/common/array.h +++ b/libgambatte/src/common/array.h @@ -26,7 +26,7 @@ template 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 class ScopedArray : Uncopyable { T *a_; - + public: explicit ScopedArray(T *a = 0) : a_(a) {} ~ScopedArray() { delete []a_; } diff --git a/libgambatte/src/cpu.cpp b/libgambatte/src/cpu.cpp index 8ea6714cb3..f884e897a6 100644 --- a/libgambatte/src/cpu.cpp +++ b/libgambatte/src/cpu.cpp @@ -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; } diff --git a/libgambatte/src/cpu.h b/libgambatte/src/cpu.h index 8d3d7c99a7..d7ffcd7b17 100644 --- a/libgambatte/src/cpu.h +++ b/libgambatte/src/cpu.h @@ -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(); } diff --git a/libgambatte/src/file/stdfile.h b/libgambatte/src/file/stdfile.h index 625e765c57..72947b11a7 100644 --- a/libgambatte/src/file/stdfile.h +++ b/libgambatte/src/file/stdfile.h @@ -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); } diff --git a/libgambatte/src/gambatte.cpp b/libgambatte/src/gambatte.cpp index 0c05ed4e1a..e8580829c5 100644 --- a/libgambatte/src/gambatte.cpp +++ b/libgambatte/src/gambatte.cpp @@ -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(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(); } diff --git a/libgambatte/src/initstate.cpp b/libgambatte/src/initstate.cpp index d539354112..7134577e2d 100644 --- a/libgambatte/src/initstate.cpp +++ b/libgambatte/src/initstate.cpp @@ -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; diff --git a/libgambatte/src/insertion_sort.h b/libgambatte/src/insertion_sort.h index f6a3c991a4..cfcd3fbd25 100644 --- a/libgambatte/src/insertion_sort.h +++ b/libgambatte/src/insertion_sort.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * + * Copyright (C) 2007 by Sindre Aam�s * * aamas@stud.ntnu.no * * * * This program is free software; you can redistribute it and/or modify * @@ -26,19 +26,19 @@ template 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; } } diff --git a/libgambatte/src/interrupter.cpp b/libgambatte/src/interrupter.cpp index 9eac990516..4223c11a8b 100644 --- a/libgambatte/src/interrupter.cpp +++ b/libgambatte/src/interrupter.cpp @@ -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; } diff --git a/libgambatte/src/interruptrequester.cpp b/libgambatte/src/interruptrequester.cpp index c656ad2368..8e57790d7a 100644 --- a/libgambatte/src/interruptrequester.cpp +++ b/libgambatte/src/interruptrequester.cpp @@ -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(intFlags.imeOrHalted() && pendingIrqs() ? minIntTime : static_cast(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(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(minIntTime); } void InterruptRequester::di() { intFlags.unsetIme(); - + if (!intFlags.imeOrHalted()) eventTimes.setValue(DISABLED_TIME); } void InterruptRequester::halt() { intFlags.setHalted(); - + if (pendingIrqs()) eventTimes.setValue(minIntTime); } void InterruptRequester::unhalt() { intFlags.unsetHalted(); - + if (!intFlags.imeOrHalted()) eventTimes.setValue(DISABLED_TIME); } void InterruptRequester::flagIrq(const unsigned bit) { ifreg_ |= bit; - + if (intFlags.imeOrHalted() && pendingIrqs()) eventTimes.setValue(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(pendingIrqs() ? minIntTime : static_cast(DISABLED_TIME)); } void InterruptRequester::setIfreg(const unsigned ifreg) { ifreg_ = ifreg; - + if (intFlags.imeOrHalted()) eventTimes.setValue(pendingIrqs() ? minIntTime : static_cast(DISABLED_TIME)); } diff --git a/libgambatte/src/interruptrequester.h b/libgambatte/src/interruptrequester.h index 8d22e35afb..5e5cb7d10c 100644 --- a/libgambatte/src/interruptrequester.h +++ b/libgambatte/src/interruptrequester.h @@ -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(eventTimes.min()); } unsigned long minEventTime() const { return eventTimes.minValue(); } template void setEventTime(unsigned long value) { eventTimes.setValue(value); } diff --git a/libgambatte/src/mem/cartridge.cpp b/libgambatte/src/mem/cartridge.cpp index 63e48171f3..5d3dea9e4d 100644 --- a/libgambatte/src/mem/cartridge.cpp +++ b/libgambatte/src/mem/cartridge.cpp @@ -76,11 +76,11 @@ public: }; static inline unsigned rambanks(const MemPtrs &memptrs) { - return static_cast(memptrs.rambankdataend() - memptrs.rambankdata()) / 0x2000; + return std::size_t(memptrs.rambankdataend() - memptrs.rambankdata()) / 0x2000; } static inline unsigned rombanks(const MemPtrs &memptrs) { - return static_cast(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: diff --git a/libgambatte/src/mem/cartridge.h b/libgambatte/src/mem/cartridge.h index 934d44df7e..a71fc5a0f8 100644 --- a/libgambatte/src/mem/cartridge.h +++ b/libgambatte/src/mem/cartridge.h @@ -63,13 +63,13 @@ class Cartridge { MemPtrs memptrs; Rtc rtc; std::auto_ptr 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); diff --git a/libgambatte/src/mem/memptrs.cpp b/libgambatte/src/mem/memptrs.cpp index bd166e86cf..7b6c2c2ee6 100644 --- a/libgambatte/src/mem/memptrs.cpp +++ b/libgambatte/src/mem/memptrs.cpp @@ -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(); } diff --git a/libgambatte/src/mem/memptrs.h b/libgambatte/src/mem/memptrs.h index 68fd2b0006..3d2c6ca3ca 100644 --- a/libgambatte/src/mem/memptrs.h +++ b/libgambatte/src/mem/memptrs.h @@ -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; } diff --git a/libgambatte/src/mem/rtc.cpp b/libgambatte/src/mem/rtc.cpp index ae97d0876c..57b2964548 100644 --- a/libgambatte/src/mem/rtc.cpp +++ b/libgambatte/src/mem/rtc.cpp @@ -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(); diff --git a/libgambatte/src/mem/rtc.h b/libgambatte/src/mem/rtc.h index cdbd7e66d0..67eedb863b 100644 --- a/libgambatte/src/mem/rtc.h +++ b/libgambatte/src/mem/rtc.h @@ -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); diff --git a/libgambatte/src/memory.cpp b/libgambatte/src/memory.cpp index 657a647fcf..a9fa6a031c 100644 --- a/libgambatte/src/memory.cpp +++ b/libgambatte/src/memory.cpp @@ -98,7 +98,7 @@ void Memory::loadState(const SaveState &state) { intreq.setEventTime((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(intreq.eventTime(BLIT) + (70224 << isDoubleSpeed())); - + intreq.setEventTime(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(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(DISABLED_TIME); intreq.setEventTime(DISABLED_TIME); - + while (cycleCounter >= intreq.minEventTime()) cycleCounter = event(cycleCounter); } else blitTime += 70224 << isDoubleSpeed(); - + blanklcd = lcden ^ 1; intreq.setEventTime(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(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(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((ioamhram[0x140] & 0x80) ? display.nextMode1IrqTime() : cycleCounter + (70224 << isDoubleSpeed())); - + if (intreq.eventTime(END) > cycleCounter) { intreq.setEventTime(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; diff --git a/libgambatte/src/memory.h b/libgambatte/src/memory.h index fcd7981730..5529fa71e9 100644 --- a/libgambatte/src/memory.h +++ b/libgambatte/src/memory.h @@ -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((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); diff --git a/libgambatte/src/minkeeper.h b/libgambatte/src/minkeeper.h index ad2d6f79d2..5816a0fad7 100644 --- a/libgambatte/src/minkeeper.h +++ b/libgambatte/src/minkeeper.h @@ -42,26 +42,26 @@ class MinKeeper { enum { LEVELS = MinKeeperUtil::CeiledLog2::R }; template struct Num { enum { R = MinKeeperUtil::RoundedDiv2n::R }; }; template struct Sum { enum { R = MinKeeperUtil::Sum::R }; }; - + template struct UpdateValue { enum { P = Sum::R + id }; enum { C0 = Sum::R + id * 2 }; - + static void updateValue(MinKeeper &m) { // GCC 4.3 generates better code with the ternary operator on i386. m.a[P] = (id * 2 + 1 == Num::R || m.values[m.a[C0]] < m.values[m.a[C0 + 1]]) ? m.a[C0] : m.a[C0 + 1]; UpdateValue::updateValue(m); } }; - + template struct UpdateValue { static void updateValue(MinKeeper &m) { m.minValue_ = m.values[m.a[0]]; } }; - + class UpdateValueLut { template struct FillLut { static void fillLut(UpdateValueLut & l) { @@ -69,42 +69,42 @@ class MinKeeper { FillLut::fillLut(l); } }; - + template struct FillLut<-1,dummy> { static void fillLut(UpdateValueLut &) {} }; - + void (*lut_[Num::R])(MinKeeper&); - + public: UpdateValueLut() { FillLut::R-1,0>::fillLut(*this); } void call(int id, MinKeeper &mk) const { lut_[id](mk); } }; - + static UpdateValueLut updateValueLut; unsigned long values[ids]; unsigned long minValue_; int a[Sum::R]; - + template static void updateValue(MinKeeper &m); - + public: explicit MinKeeper(unsigned long initValue = 0xFFFFFFFF); - + int min() const { return a[0]; } unsigned long minValue() const { return minValue_; } - + template void setValue(const unsigned long cnt) { values[id] = cnt; updateValue(*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 typename MinKeeper::UpdateValueLut MinKeeper::update template MinKeeper::MinKeeper(const unsigned long initValue) { std::fill(values, values + ids, initValue); - + for (int i = 0; i < Num::R; ++i) { a[Sum::R + i] = (i * 2 + 1 == ids || values[i * 2] < values[i * 2 + 1]) ? i * 2 : i * 2 + 1; } - + int n = Num::R; int off = Sum::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]]; } diff --git a/libgambatte/src/newstate.h b/libgambatte/src/newstate.h index d741879cff..576da30bfb 100644 --- a/libgambatte/src/newstate.h +++ b/libgambatte/src/newstate.h @@ -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(NewState *ns);\ template void x::SyncState(NewState *ns);\ diff --git a/libgambatte/src/savestate.h b/libgambatte/src/savestate.h index 014efbb4c8..598426edd8 100644 --- a/libgambatte/src/savestate.h +++ b/libgambatte/src/savestate.h @@ -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 vram; Ptr sram; @@ -83,14 +83,14 @@ struct SaveState { bool agbMode; bool gbIsCgb; } mem; - + struct PPU { Ptr bgpData; Ptr objpData; //SpriteMapper::OamReader Ptr oamReaderBuf; Ptr 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 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; diff --git a/libgambatte/src/sound.cpp b/libgambatte/src/sound.cpp index 508ebaf827..68449b158e 100644 --- a/libgambatte/src/sound.cpp +++ b/libgambatte/src/sound.cpp @@ -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); diff --git a/libgambatte/src/sound.h b/libgambatte/src/sound.h index 7d430d613d..367a10f1a8 100644 --- a/libgambatte/src/sound.h +++ b/libgambatte/src/sound.h @@ -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; } diff --git a/libgambatte/src/sound/channel1.cpp b/libgambatte/src/sound/channel1.cpp index eae98c966c..4a9f0a7578 100644 --- a/libgambatte/src/sound/channel1.cpp +++ b/libgambatte/src/sound/channel1.cpp @@ -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; } } diff --git a/libgambatte/src/sound/channel1.h b/libgambatte/src/sound/channel1.h index 5cd7c23ed2..113629bb8a 100644 --- a/libgambatte/src/sound/channel1.h +++ b/libgambatte/src/sound/channel1.h @@ -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 { templatevoid SyncState(NewState *ns); }; - + friend class StaticOutputTester; - + StaticOutputTester 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); diff --git a/libgambatte/src/sound/channel2.cpp b/libgambatte/src/sound/channel2.cpp index b3135e2299..13bcc23b4a 100644 --- a/libgambatte/src/sound/channel2.cpp +++ b/libgambatte/src/sound/channel2.cpp @@ -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; } } diff --git a/libgambatte/src/sound/channel2.h b/libgambatte/src/sound/channel2.h index 9cc2ef28b6..611d8cd51c 100644 --- a/libgambatte/src/sound/channel2.h +++ b/libgambatte/src/sound/channel2.h @@ -32,37 +32,37 @@ struct SaveState; class Channel2 { friend class StaticOutputTester; - + StaticOutputTester 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); diff --git a/libgambatte/src/sound/channel3.cpp b/libgambatte/src/sound/channel3.cpp index aeab458d6b..d91be4416b 100644 --- a/libgambatte/src/sound/channel3.cpp +++ b/libgambatte/src/sound/channel3.cpp @@ -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); diff --git a/libgambatte/src/sound/channel3.h b/libgambatte/src/sound/channel3.h index fe81789899..a6c5253c44 100644 --- a/libgambatte/src/sound/channel3.h +++ b/libgambatte/src/sound/channel3.h @@ -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; } diff --git a/libgambatte/src/sound/channel4.cpp b/libgambatte/src/sound/channel4.cpp index 31c0590646..cc5a29799f 100644 --- a/libgambatte/src/sound/channel4.cpp +++ b/libgambatte/src/sound/channel4.cpp @@ -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); } diff --git a/libgambatte/src/sound/channel4.h b/libgambatte/src/sound/channel4.h index 785c98f2f6..4490404fa2 100644 --- a/libgambatte/src/sound/channel4.h +++ b/libgambatte/src/sound/channel4.h @@ -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 { templatevoid 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; - + StaticOutputTester 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); diff --git a/libgambatte/src/sound/duty_unit.cpp b/libgambatte/src/sound/duty_unit.cpp index 02ba2a8a04..4d2a0ddde6 100644 --- a/libgambatte/src/sound/duty_unit.cpp +++ b/libgambatte/src/sound/duty_unit.cpp @@ -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); diff --git a/libgambatte/src/sound/duty_unit.h b/libgambatte/src/sound/duty_unit.h index 0a5f3e9412..a45294133e 100644 --- a/libgambatte/src/sound/duty_unit.h +++ b/libgambatte/src/sound/duty_unit.h @@ -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); diff --git a/libgambatte/src/sound/envelope_unit.cpp b/libgambatte/src/sound/envelope_unit.cpp index 7c81607fa0..917c73bc13 100644 --- a/libgambatte/src/sound/envelope_unit.cpp +++ b/libgambatte/src/sound/envelope_unit.cpp @@ -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); } diff --git a/libgambatte/src/sound/envelope_unit.h b/libgambatte/src/sound/envelope_unit.h index 4a0587d141..69f74d1997 100644 --- a/libgambatte/src/sound/envelope_unit.h +++ b/libgambatte/src/sound/envelope_unit.h @@ -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(); diff --git a/libgambatte/src/sound/length_counter.cpp b/libgambatte/src/sound/length_counter.cpp index e1e9f00862..7822fb934f 100644 --- a/libgambatte/src/sound/length_counter.cpp +++ b/libgambatte/src/sound/length_counter.cpp @@ -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; }*/ diff --git a/libgambatte/src/sound/master_disabler.h b/libgambatte/src/sound/master_disabler.h index e9f75382e6..efbc37f114 100644 --- a/libgambatte/src/sound/master_disabler.h +++ b/libgambatte/src/sound/master_disabler.h @@ -22,7 +22,7 @@ namespace gambatte { class MasterDisabler { bool &master; - + public: MasterDisabler(bool &m) : master(m) {} virtual ~MasterDisabler() {} diff --git a/libgambatte/src/sound/sound_unit.h b/libgambatte/src/sound/sound_unit.h index b1ca691e8a..d2a00582ad 100644 --- a/libgambatte/src/sound/sound_unit.h +++ b/libgambatte/src/sound/sound_unit.h @@ -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; diff --git a/libgambatte/src/tima.cpp b/libgambatte/src/tima.cpp index 979ffded65..276385e782 100644 --- a/libgambatte/src/tima.cpp +++ b/libgambatte/src/tima.cpp @@ -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; } diff --git a/libgambatte/src/tima.h b/libgambatte/src/tima.h index a66f987837..df866a903e 100644 --- a/libgambatte/src/tima.h +++ b/libgambatte/src/tima.h @@ -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); templatevoid SyncState(NewState *ns); diff --git a/libgambatte/src/video.cpp b/libgambatte/src/video.cpp index c2b82a6495..a30bf98c01 100644 --- a/libgambatte/src/video.cpp +++ b/libgambatte/src/video.cpp @@ -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(state.ppu.pendingLcdstatIrq ? ppu.now() + 1 : static_cast(DISABLED_TIME)); eventTimes_.setm(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(DISABLED_TIME)); } else for (int i = 0; i < NUM_MEM_EVENTS; ++i) - eventTimes_.set(static_cast(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(i)) != DISABLED_TIME) - eventTimes_.set(static_cast(i), eventTimes_(static_cast(i)) - dec); + if (eventTimes_(MemEvent(i)) != DISABLED_TIME) + eventTimes_.set(MemEvent(i), eventTimes_(MemEvent(i)) - dec); } - + eventTimes_.set(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(ppu.lyCounter().time()); eventTimes_.setm(SpriteMapper::schedule(ppu.lyCounter(), cycleCounter)); eventTimes_.setm(lycIrq.time()); eventTimes_.setm(ppu.lyCounter().nextFrameCycle(144 * 456, cycleCounter)); eventTimes_.setm(mode2IrqSchedule(statReg, ppu.lyCounter(), cycleCounter)); - + if (eventTimes_(MODE0_IRQ) != DISABLED_TIME && eventTimes_(MODE0_IRQ) - cycleCounter > 1) eventTimes_.setm(m0IrqTimeFromXpos166Time(ppu.predictedNextXposTime(166), ppu.cgb(), isDoubleSpeed())); - + if (hdmaIsEnabled() && eventTimes_(HDMA_REQ) - cycleCounter > 1) { eventTimes_.setm(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(nextHdmaTime(ppu.lastM0Time(), nextM0Time_.predictedNextM0Time(), cycleCounter, isDoubleSpeed())); } void LCD::disableHdma(const unsigned long cycleCounter) { if (cycleCounter >= eventTimes_.nextEventTime()) update(cycleCounter); - + eventTimes_.setm(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(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(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(ppu.lyCounter().time()); eventTimes_.setm(SpriteMapper::schedule(ppu.lyCounter(), cycleCounter)); eventTimes_.setm(lycIrq.time()); eventTimes_.setm(ppu.lyCounter().nextFrameCycle(144 * 456, cycleCounter)); eventTimes_.setm(mode2IrqSchedule(statReg, ppu.lyCounter(), cycleCounter)); - + if (statReg & 0x08) eventTimes_.setm(m0IrqTimeFromXpos166Time(ppu.predictedNextXposTime(166), ppu.cgb(), isDoubleSpeed())); - + if (hdmaIsEnabled()) { eventTimes_.setm(nextHdmaTime(ppu.lastM0Time(), nextM0Time_.predictedNextM0Time(), cycleCounter, isDoubleSpeed())); } } else for (int i = 0; i < NUM_MEM_EVENTS; ++i) - eventTimes_.set(static_cast(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(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(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(mode2IrqSchedule(data, ppu.lyCounter(), cycleCounter)); eventTimes_.setm(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(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(nextTime); } else eventTimes_.setm(eventTimes_(MODE2_IRQ) + (70224 << isDoubleSpeed())); @@ -679,7 +679,7 @@ inline void LCD::event() { m1IrqStatReg_ = statReg; eventTimes_.setm(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(lycIrq.time()); break; } - + case SPRITE_MAP: eventTimes_.setm(ppu.doSpriteMapEvent(eventTimes_(SPRITE_MAP))); mode3CyclesChange(); break; - + case HDMA_REQ: eventTimes_.flagHdmaReq(); nextM0Time_.predictNextM0Time(ppu); eventTimes_.setm(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((statReg & 0x08) + + eventTimes_.setm(statReg & 0x08 ? m0IrqTimeFromXpos166Time(ppu.predictedNextXposTime(166), ppu.cgb(), isDoubleSpeed()) : static_cast(DISABLED_TIME)); break; - + case ONESHOT_LCDSTATIRQ: eventTimes_.flagIrq(2); eventTimes_.setm(DISABLED_TIME); break; - + case ONESHOT_UPDATEWY2: ppu.updateWy2(); mode3CyclesChange(); eventTimes_.setm(DISABLED_TIME); break; } - + break; - + case LY_COUNT: ppu.doLyCountEvent(); eventTimes_.set(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); } diff --git a/libgambatte/src/video.h b/libgambatte/src/video.h index a42bd5608f..7b5628b938 100644 --- a/libgambatte/src/video.h +++ b/libgambatte/src/video.h @@ -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 @@ -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 eventMin_; MinKeeper memEventMin_; VideoInterruptRequester memEventRequester_; - + void setMemEvent() { const unsigned long nmet = nextMemEventTime(); eventMin_.setValue(nmet); memEventRequester_.setNextEventTime(nmet); } - + public: explicit EventTimes(const VideoInterruptRequester memEventRequester) : memEventRequester_(memEventRequester) {} - + Event nextEvent() const { return static_cast(eventMin_.min()); } unsigned long nextEventTime() const { return eventMin_.minValue(); } unsigned long operator()(const Event e) const { return eventMin_.value(e); } template void set(const unsigned long time) { eventMin_.setValue(time); } void set(const Event e, const unsigned long time) { eventMin_.setValue(e, time); } - + MemEvent nextMemEvent() const { return static_cast(memEventMin_.min()); } unsigned long nextMemEventTime() const { return memEventMin_.minValue(); } unsigned long operator()(const MemEvent e) const { return memEventMin_.value(e); } template void setm(const unsigned long time) { memEventMin_.setValue(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(); } diff --git a/libgambatte/src/video/ly_counter.cpp b/libgambatte/src/video/ly_counter.cpp index 4b978dfeee..d589bada73 100644 --- a/libgambatte/src/video/ly_counter.cpp +++ b/libgambatte/src/video/ly_counter.cpp @@ -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; } diff --git a/libgambatte/src/video/ly_counter.h b/libgambatte/src/video/ly_counter.h index 9aca9877b1..a493ce55a5 100644 --- a/libgambatte/src/video/ly_counter.h +++ b/libgambatte/src/video/ly_counter.h @@ -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; diff --git a/libgambatte/src/video/lyc_irq.cpp b/libgambatte/src/video/lyc_irq.cpp index 024ef35233..6b95ac6e57 100644 --- a/libgambatte/src/video/lyc_irq.cpp +++ b/libgambatte/src/video/lyc_irq.cpp @@ -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_); diff --git a/libgambatte/src/video/lyc_irq.h b/libgambatte/src/video/lyc_irq.h index 510039d996..497c745d46 100644 --- a/libgambatte/src/video/lyc_irq.h +++ b/libgambatte/src/video/lyc_irq.h @@ -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); } diff --git a/libgambatte/src/video/next_m0_time.h b/libgambatte/src/video/next_m0_time.h index 0a91c4d330..5937b0734a 100644 --- a/libgambatte/src/video/next_m0_time.h +++ b/libgambatte/src/video/next_m0_time.h @@ -7,7 +7,7 @@ namespace gambatte { class NextM0Time { unsigned predictedNextM0Time_; - + public: NextM0Time() : predictedNextM0Time_(0) {} void predictNextM0Time(const class PPU &v); diff --git a/libgambatte/src/video/ppu.cpp b/libgambatte/src/video/ppu.cpp index 70d7db9e54..d5c5e9607a 100644 --- a/libgambatte/src/video/ppu.cpp +++ b/libgambatte/src/video/ppu.cpp @@ -78,7 +78,7 @@ namespace M3Loop { DECLARE_FUNC(4, 0x84); DECLARE_FUNC(5, 0x85); } - + namespace LoadSprites { DECLARE_FUNC(0, 0x88); DECLARE_FUNC(1, 0x89); @@ -87,7 +87,7 @@ namespace M3Loop { DECLARE_FUNC(4, 0x8C); DECLARE_FUNC(5, 0x8D); } - + namespace StartWindowDraw { DECLARE_FUNC(0, 0x90); DECLARE_FUNC(1, 0x91); @@ -129,25 +129,25 @@ namespace M2 { nextCall(m3StartLineCycle(p.cgb), M3Start::f0_, p); } } - + namespace LyNon0 { static void f0(PPUPriv &p) { p.weMaster |= (p.lcdc & 0x20) && p.lyCounter.ly() == p.wy; nextCall(weMasterCheckAfterLyIncLineCycle(p.cgb) - weMasterCheckPriorToLyIncLineCycle(p.cgb), f1_, p); } - + static void f1(PPUPriv &p) { p.weMaster |= (p.lcdc & 0x20) && p.lyCounter.ly() + 1 == p.wy; nextCall(456 - weMasterCheckAfterLyIncLineCycle(p.cgb) + m3StartLineCycle(p.cgb), M3Start::f0_, p); } } - + /*struct SpriteLess { bool operator()(const Sprite lhs, const Sprite rhs) const { return lhs.spx < rhs.spx; } }; - + static void f0(PPUPriv &p) { std::memset(&p.spLut, 0, sizeof p.spLut); p.reg0 = 0; @@ -155,37 +155,37 @@ namespace M2 { p.nextCallPtr = &f1_; f1(p); } - + static void f1(PPUPriv &p) { int cycles = p.cycles; unsigned oampos = p.reg0; unsigned nextSprite = p.nextSprite; const unsigned nly = (p.lyCounter.ly() + 1 == 154 ? 0 : p.lyCounter.ly() + 1) + ((p.lyCounter.time()-(p.now-p.cycles)) <= 4); const bool ls = p.spriteMapper.largeSpritesSource(); - + do { const unsigned spy = p.spriteMapper.oamram()[oampos ]; const unsigned spx = p.spriteMapper.oamram()[oampos+1]; const unsigned ydiff = spy - nly; - + if (ls ? ydiff < 16u : ydiff - 8u < 8u) { p.spriteList[nextSprite].spx = spx; p.spriteList[nextSprite].line = 15u - ydiff; p.spriteList[nextSprite].oampos = oampos; - + if (++nextSprite == 10) { cycles -= (0xA0 - 4 - oampos) >> 1; oampos = 0xA0 - 4; } } - + oampos += 4; } while ((cycles-=2) >= 0 && oampos != 0xA0); - + p.reg0 = oampos; p.nextSprite = nextSprite; p.cycles = cycles; - + if (oampos == 0xA0) { insertionSort(p.spriteList, p.spriteList + nextSprite, SpriteLess()); p.spriteList[nextSprite].spx = 0xFF; @@ -198,23 +198,23 @@ namespace M2 { namespace M3Start { static void f0(PPUPriv &p) { p.xpos = 0; - + if (p.winDrawState & p.lcdc >> 5 & WIN_DRAW_START) { p.winDrawState = WIN_DRAW_STARTED; p.wscx = 8 + (p.scx & 7); ++p.winYPos; } else p.winDrawState = 0; - + p.nextCallPtr = &f1_; f1(p); } - + static void f1(PPUPriv &p) { while (p.xpos < MAX_M3START_CYCLES) { if ((p.xpos & 7) == (p.scx & 7)) break; - + switch (p.xpos & 7) { case 0: if ((p.winDrawState & WIN_DRAW_STARTED) && (p.layersMask & LAYER_MASK_WINDOW)) { @@ -229,31 +229,31 @@ namespace M3Start { case 2: { const unsigned yoffset = ((p.winDrawState & WIN_DRAW_STARTED) && (p.layersMask & LAYER_MASK_WINDOW)) ? p.winYPos : p.scy + p.lyCounter.ly(); - + p.reg0 = p.vram[0x1000 + (p.nattrib << 10 & 0x2000) - ((p.reg1 * 32 | p.lcdc << 8) & 0x1000) + p.reg1 * 16 + ((-(p.nattrib >> 6 & 1) ^ yoffset) & 7) * 2]; } - + break; case 4: { const unsigned yoffset = ((p.winDrawState & WIN_DRAW_STARTED) && (p.layersMask & LAYER_MASK_WINDOW)) ? p.winYPos : p.scy + p.lyCounter.ly(); const unsigned r1 = p.vram[0x1000 + (p.nattrib << 10 & 0x2000) - ((p.reg1 * 32 | p.lcdc << 8) & 0x1000) + p.reg1 * 16 + ((-(p.nattrib >> 6 & 1) ^ yoffset) & 7) * 2 + 1]; - + p.ntileword = (expand_lut + (p.nattrib << 3 & 0x100))[p.reg0] + (expand_lut + (p.nattrib << 3 & 0x100))[r1 ] * 2; } - + break; } - + ++p.xpos; - + if (--p.cycles < 0) return; } - + { const unsigned ly = p.lyCounter.ly(); const unsigned numSprites = p.spriteMapper.numSprites(ly); @@ -269,14 +269,14 @@ namespace M3Start { p.spriteList[i].oampos = pos * 2; p.spwordList[i] = 0; } - + p.spriteList[numSprites].spx = 0xFF; p.nextSprite = 0; } - + p.xpos = 0; p.endx = 8 - (p.scx & 7); - + static const PPUState *const flut[8] = { &M3Loop::Tile::f0_, &M3Loop::Tile::f1_, @@ -287,7 +287,7 @@ namespace M3Start { &M3Loop::Tile::f5_, &M3Loop::Tile::f5_ }; - + nextCall(1-p.cgb, *flut[p.scx & 7], p); } } @@ -298,66 +298,66 @@ namespace M3Loop { const unsigned tileIndexSign = ~p.lcdc << 3 & 0x80; const unsigned char *const tileDataLine = p.vram + tileIndexSign * 32 + tileline * 2; int xpos = p.xpos; - + do { int nextSprite = p.nextSprite; - - if (static_cast(p.spriteList[nextSprite].spx) < xpos + 8) { + + if (int(p.spriteList[nextSprite].spx) < xpos + 8) { int cycles = p.cycles - 8; - + if (p.lcdc & 2) { - cycles -= std::max(11 - (static_cast(p.spriteList[nextSprite].spx) - xpos), 6); - - for (unsigned i = nextSprite + 1; static_cast(p.spriteList[i].spx) < xpos + 8; ++i) + cycles -= std::max(11 - (int(p.spriteList[nextSprite].spx) - xpos), 6); + + for (unsigned i = nextSprite + 1; int(p.spriteList[i].spx) < xpos + 8; ++i) cycles -= 6; - + if (cycles < 0) break; - + p.cycles = cycles; - + do { unsigned reg0, reg1 = p.spriteMapper.oamram()[p.spriteList[nextSprite].oampos + 2] * 16; const unsigned attrib = p.spriteMapper.oamram()[p.spriteList[nextSprite].oampos + 3]; - + { const unsigned spline = (attrib & 0x40 ? p.spriteList[nextSprite].line ^ 15 : p.spriteList[nextSprite].line) * 2; reg0 = p.vram[(p.lcdc & 4 ? (reg1 & ~16) | spline : reg1 | (spline & ~16)) ]; reg1 = p.vram[(p.lcdc & 4 ? (reg1 & ~16) | spline : reg1 | (spline & ~16)) + 1]; } - + p.spwordList[nextSprite] = expand_lut[reg0 + (attrib << 3 & 0x100)] + expand_lut[reg1 + (attrib << 3 & 0x100)] * 2; p.spriteList[nextSprite].attrib = attrib; ++nextSprite; - } while (static_cast(p.spriteList[nextSprite].spx) < xpos + 8); + } while (int(p.spriteList[nextSprite].spx) < xpos + 8); } else { if (cycles < 0) break; - + p.cycles = cycles; - + do { ++nextSprite; - } while (static_cast(p.spriteList[nextSprite].spx) < xpos + 8); + } while (int(p.spriteList[nextSprite].spx) < xpos + 8); } - + p.nextSprite = nextSprite; - } else if (nextSprite-1 < 0 || static_cast(p.spriteList[nextSprite-1].spx) <= xpos - 8) { + } else if (nextSprite-1 < 0 || int(p.spriteList[nextSprite-1].spx) <= xpos - 8) { if (!(p.cycles & ~7)) break; - - int n = (( xend + 7 < static_cast(p.spriteList[nextSprite].spx) - ? xend + 7 : static_cast(p.spriteList[nextSprite].spx)) - xpos) & ~7; + + int n = (( xend + 7 < int(p.spriteList[nextSprite].spx) + ? xend + 7 : int(p.spriteList[nextSprite].spx)) - xpos) & ~7; n = (p.cycles & ~7) < n ? p.cycles & ~7 : n; p.cycles -= n; - + unsigned ntileword = p.ntileword; uint_least32_t * dst = dbufline + xpos - 8; uint_least32_t *const dstend = dst + n; xpos += n; - + if (!(p.lcdc & 1)) { do { *dst++ = p.bgPalette[0]; } while (dst != dstend); tileMapXpos += n >> 3; @@ -375,28 +375,28 @@ namespace M3Loop { dst[6] = p.bgPalette[(ntileword & 0x3000) >> 12]; dst[7] = p.bgPalette[ ntileword >> 14]; dst += 8; - + unsigned const tno = tileMapLine[tileMapXpos & 0x1F]; tileMapXpos = (tileMapXpos & 0x1F) + 1; ntileword = expand_lut[(tileDataLine + tno * 16 - (tno & tileIndexSign) * 32)[0]] + expand_lut[(tileDataLine + tno * 16 - (tno & tileIndexSign) * 32)[1]] * 2; } while (dst != dstend); - + p.ntileword = ntileword; continue; } else { int cycles = p.cycles - 8; - + if (cycles < 0) break; - + p.cycles = cycles; } - + { uint_least32_t *const dst = dbufline + (xpos - 8); const unsigned tileword = -(p.lcdc & 1U) & p.ntileword; - + dst[0] = p.bgPalette[ tileword & 0x0003 ]; dst[1] = p.bgPalette[(tileword & 0x000C) >> 2]; dst[2] = p.bgPalette[(tileword & 0x0030) >> 4]; @@ -405,21 +405,21 @@ namespace M3Loop { dst[5] = p.bgPalette[(tileword & 0x0C00) >> 10]; dst[6] = p.bgPalette[(tileword & 0x3000) >> 12]; dst[7] = p.bgPalette[ tileword >> 14]; - + int i = nextSprite - 1; - + if(p.layersMask & LAYER_MASK_OBJ) { if (!(p.lcdc & 2)) { do { - const int pos = static_cast(p.spriteList[i].spx) - xpos; + const int pos = int(p.spriteList[i].spx) - xpos; p.spwordList[i] >>= pos * 2 >= 0 ? 16 - pos * 2 : 16 + pos * 2; --i; - } while (i >= 0 && static_cast(p.spriteList[i].spx) > xpos - 8); + } while (i >= 0 && int(p.spriteList[i].spx) > xpos - 8); } else { do { int n; - int pos = static_cast(p.spriteList[i].spx) - xpos; + int pos = int(p.spriteList[i].spx) - xpos; if (pos < 0) { n = pos + 8; @@ -471,24 +471,24 @@ namespace M3Loop { p.spwordList[i] = spword; --i; - } while (i >= 0 && static_cast(p.spriteList[i].spx) > xpos - 8); + } while (i >= 0 && int(p.spriteList[i].spx) > xpos - 8); } } } - + { unsigned const tno = tileMapLine[tileMapXpos & 0x1F]; tileMapXpos = (tileMapXpos & 0x1F) + 1; p.ntileword = expand_lut[(tileDataLine + tno * 16 - (tno & tileIndexSign) * 32)[0]] + expand_lut[(tileDataLine + tno * 16 - (tno & tileIndexSign) * 32)[1]] * 2; } - + xpos = xpos + 8; } while (xpos < xend); - + p.xpos = xpos; } - + static void doFullTilesUnrolledCgb(PPUPriv &p, const int xend, uint_least32_t *const dbufline, const unsigned char *const tileMapLine, const unsigned tileline, unsigned tileMapXpos) { int xpos = p.xpos; @@ -501,26 +501,26 @@ namespace M3Loop { dbufline[i] = p.bgPalette[0]; //guessing? return; } - + do { int nextSprite = p.nextSprite; - - if (static_cast(p.spriteList[nextSprite].spx) < xpos + 8) { + + if (int(p.spriteList[nextSprite].spx) < xpos + 8) { int cycles = p.cycles - 8; - cycles -= std::max(11 - (static_cast(p.spriteList[nextSprite].spx) - xpos), 6); - - for (unsigned i = nextSprite + 1; static_cast(p.spriteList[i].spx) < xpos + 8; ++i) + cycles -= std::max(11 - (int(p.spriteList[nextSprite].spx) - xpos), 6); + + for (unsigned i = nextSprite + 1; int(p.spriteList[i].spx) < xpos + 8; ++i) cycles -= 6; - + if (cycles < 0) break; - + p.cycles = cycles; - + do { unsigned reg0, reg1 = p.spriteMapper.oamram()[p.spriteList[nextSprite].oampos + 2] * 16; const unsigned attrib = p.spriteMapper.oamram()[p.spriteList[nextSprite].oampos + 3]; - + { const unsigned spline = (attrib & 0x40 ? p.spriteList[nextSprite].line ^ 15 : p.spriteList[nextSprite].line) * 2; @@ -529,29 +529,29 @@ namespace M3Loop { reg1 = vram[(attrib << 10 & 0x2000) + (p.lcdc & 4 ? (reg1 & ~16) | spline : reg1 | (spline & ~16)) + 1]; } - + p.spwordList[nextSprite] = expand_lut[reg0 + (attrib << 3 & 0x100)] + expand_lut[reg1 + (attrib << 3 & 0x100)] * 2; p.spriteList[nextSprite].attrib = attrib; ++nextSprite; - } while (static_cast(p.spriteList[nextSprite].spx) < xpos + 8); - + } while (int(p.spriteList[nextSprite].spx) < xpos + 8); + p.nextSprite = nextSprite; - } else if (nextSprite-1 < 0 || static_cast(p.spriteList[nextSprite-1].spx) <= xpos - 8) { + } else if (nextSprite-1 < 0 || int(p.spriteList[nextSprite-1].spx) <= xpos - 8) { if (!(p.cycles & ~7)) break; - - int n = (( xend + 7 < static_cast(p.spriteList[nextSprite].spx) - ? xend + 7 : static_cast(p.spriteList[nextSprite].spx)) - xpos) & ~7; + + int n = (( xend + 7 < int(p.spriteList[nextSprite].spx) + ? xend + 7 : int(p.spriteList[nextSprite].spx)) - xpos) & ~7; n = (p.cycles & ~7) < n ? p.cycles & ~7 : n; p.cycles -= n; - + unsigned ntileword = p.ntileword; unsigned nattrib = p.nattrib; uint_least32_t * dst = dbufline + xpos - 8; uint_least32_t *const dstend = dst + n; xpos += n; - + do { const unsigned long *const bgPalette = p.bgPalette + (nattrib & 7) * 4; dst[0] = bgPalette[ ntileword & 0x0003 ]; @@ -563,36 +563,36 @@ namespace M3Loop { dst[6] = bgPalette[(ntileword & 0x3000) >> 12]; dst[7] = bgPalette[ ntileword >> 14]; dst += 8; - + unsigned const tno = tileMapLine[ tileMapXpos & 0x1F ]; nattrib = tileMapLine[(tileMapXpos & 0x1F) + 0x2000]; tileMapXpos = (tileMapXpos & 0x1F) + 1; - + unsigned const tdo = tdoffset & ~(tno << 5); unsigned char const *const td = vram + tno * 16 + (nattrib & 0x40 ? tdo ^ 14 : tdo) + (nattrib << 10 & 0x2000); unsigned short const *const explut = expand_lut + (nattrib << 3 & 0x100); ntileword = explut[td[0]] + explut[td[1]] * 2; } while (dst != dstend); - + p.ntileword = ntileword; p.nattrib = nattrib; continue; } else { int cycles = p.cycles - 8; - + if (cycles < 0) break; - + p.cycles = cycles; } - + { uint_least32_t *const dst = dbufline + (xpos - 8); const unsigned tileword = p.ntileword; const unsigned attrib = p.nattrib; const unsigned long *const bgPalette = p.bgPalette + (attrib & 7) * 4; - + dst[0] = bgPalette[ tileword & 0x0003 ]; dst[1] = bgPalette[(tileword & 0x000C) >> 2]; dst[2] = bgPalette[(tileword & 0x0030) >> 4]; @@ -601,24 +601,24 @@ namespace M3Loop { dst[5] = bgPalette[(tileword & 0x0C00) >> 10]; dst[6] = bgPalette[(tileword & 0x3000) >> 12]; dst[7] = bgPalette[ tileword >> 14]; - + int i = nextSprite - 1; if(p.layersMask & LAYER_MASK_OBJ) { if (!(p.lcdc & 2)) { do { - const int pos = static_cast(p.spriteList[i].spx) - xpos; + const int pos = int(p.spriteList[i].spx) - xpos; p.spwordList[i] >>= pos * 2 >= 0 ? 16 - pos * 2 : 16 + pos * 2; --i; - } while (i >= 0 && static_cast(p.spriteList[i].spx) > xpos - 8); + } while (i >= 0 && int(p.spriteList[i].spx) > xpos - 8); } else { unsigned char idtab[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; const unsigned bgenmask = p.lcdc << 7 & 0x80; do { int n; - int pos = static_cast(p.spriteList[i].spx) - xpos; + int pos = int(p.spriteList[i].spx) - xpos; if (pos < 0) { n = pos + 8; @@ -698,7 +698,7 @@ namespace M3Loop { p.spwordList[i] = spword; --i; - } while (i >= 0 && static_cast(p.spriteList[i].spx) > xpos - 8); + } while (i >= 0 && int(p.spriteList[i].spx) > xpos - 8); } } } @@ -707,7 +707,7 @@ namespace M3Loop { unsigned const tno = tileMapLine[ tileMapXpos & 0x1F ]; unsigned const nattrib = tileMapLine[(tileMapXpos & 0x1F) + 0x2000]; tileMapXpos = (tileMapXpos & 0x1F) + 1; - + unsigned const tdo = tdoffset & ~(tno << 5); unsigned char const *const td = vram + tno * 16 + (nattrib & 0x40 ? tdo ^ 14 : tdo) + (nattrib << 10 & 0x2000); @@ -715,25 +715,25 @@ namespace M3Loop { p.ntileword = explut[td[0]] + explut[td[1]] * 2; p.nattrib = nattrib; } - + xpos = xpos + 8; } while (xpos < xend); - + p.xpos = xpos; } - + static void doFullTilesUnrolled(PPUPriv &p) { int xpos = p.xpos; - const int xend = static_cast(p.wx) < xpos || p.wx >= 168 ? 161 : static_cast(p.wx) - 7; - + const int xend = int(p.wx) < xpos || p.wx >= 168 ? 161 : int(p.wx) - 7; + if (xpos >= xend) return; - + uint_least32_t *const dbufline = p.framebuf.fbline(); const unsigned char *tileMapLine; unsigned tileline; unsigned tileMapXpos; - + if ((p.winDrawState & WIN_DRAW_STARTED) && (p.layersMask & LAYER_MASK_WINDOW)) { tileMapLine = p.vram + (p.lcdc << 4 & 0x400) + (p.winYPos & 0xF8) * 4 + 0x1800; tileMapXpos = (xpos + p.wscx) >> 3; @@ -743,75 +743,75 @@ namespace M3Loop { tileMapXpos = (p.scx + xpos + 1 - p.cgb) >> 3; tileline = (p.scy + p.lyCounter.ly()) & 7; } - + if (xpos < 8) { uint_least32_t prebuf[16]; - + if (p.cgb) { doFullTilesUnrolledCgb(p, xend < 8 ? xend : 8, prebuf + (8 - xpos), tileMapLine, tileline, tileMapXpos); } else doFullTilesUnrolledDmg(p, xend < 8 ? xend : 8, prebuf + (8 - xpos), tileMapLine, tileline, tileMapXpos); - + const int newxpos = p.xpos; - + if (newxpos > 8) { std::memcpy(dbufline, prebuf + (8 - xpos), (newxpos - 8) * sizeof *dbufline); } else if (newxpos < 8) return; - + if (newxpos >= xend) return; - + tileMapXpos += (newxpos - xpos) >> 3; } - + if (p.cgb) { doFullTilesUnrolledCgb(p, xend, dbufline, tileMapLine, tileline, tileMapXpos); } else doFullTilesUnrolledDmg(p, xend, dbufline, tileMapLine, tileline, tileMapXpos); } - + static void plotPixel(PPUPriv &p) { //ZING! const int xpos = p.xpos; const unsigned tileword = p.tileword; uint_least32_t *const fbline = p.framebuf.fbline(); - - if (static_cast(p.wx) == xpos && (p.weMaster || (p.wy2 == p.lyCounter.ly() && (p.lcdc & 0x20))) && xpos < 167) { + + if (int(p.wx) == xpos && (p.weMaster || (p.wy2 == p.lyCounter.ly() && (p.lcdc & 0x20))) && xpos < 167) { if (p.winDrawState == 0 && (p.lcdc & 0x20)) { p.winDrawState = WIN_DRAW_START | WIN_DRAW_STARTED; ++p.winYPos; } else if (!p.cgb && (p.winDrawState == 0 || xpos == 166)) p.winDrawState |= WIN_DRAW_START; } - + const unsigned twdata = tileword & ((p.lcdc & 1) | p.cgb) * 3; unsigned long pixel = p.bgPalette[twdata + (p.attrib & 7) * 4]; - int i = static_cast(p.nextSprite) - 1; + int i = int(p.nextSprite) - 1; if(!(p.layersMask & LAYER_MASK_BG)) { pixel = p.bgPalette[0]; //guessing? clobber the tile that was read } - - if (i >= 0 && static_cast(p.spriteList[i].spx) > xpos - 8) { + + if (i >= 0 && int(p.spriteList[i].spx) > xpos - 8) { unsigned spdata = 0; unsigned attrib = 0; - + if (p.cgb) { unsigned minId = 0xFF; - + do { if ((p.spwordList[i] & 3) && p.spriteList[i].oampos < minId) { spdata = p.spwordList[i] & 3; attrib = p.spriteList[i].attrib; minId = p.spriteList[i].oampos; } - + p.spwordList[i] >>= 2; --i; - } while (i >= 0 && static_cast(p.spriteList[i].spx) > xpos - 8); - + } while (i >= 0 && int(p.spriteList[i].spx) > xpos - 8); + if(p.layersMask & LAYER_MASK_OBJ) { if (spdata && (p.lcdc & 2) && (!((attrib | p.attrib) & 0x80) || !twdata || !(p.lcdc & 1))) @@ -823,11 +823,11 @@ namespace M3Loop { spdata = p.spwordList[i] & 3; attrib = p.spriteList[i].attrib; } - + p.spwordList[i] >>= 2; --i; - } while (i >= 0 && static_cast(p.spriteList[i].spx) > xpos - 8); - + } while (i >= 0 && int(p.spriteList[i].spx) > xpos - 8); + if(p.layersMask & LAYER_MASK_OBJ) { if (spdata && (p.lcdc & 2) && (!(attrib & 0x80) || !twdata)) @@ -835,27 +835,27 @@ namespace M3Loop { } } } - + if (xpos - 8 >= 0) fbline[xpos - 8] = pixel; - + p.xpos = xpos + 1; p.tileword = tileword >> 2; } - + static void plotPixelIfNoSprite(PPUPriv &p) { if (p.spriteList[p.nextSprite].spx == p.xpos) { if (!((p.lcdc & 2) | p.cgb)) { do { ++p.nextSprite; } while (p.spriteList[p.nextSprite].spx == p.xpos); - + plotPixel(p); } } else plotPixel(p); } - + static unsigned long nextM2Time(const PPUPriv &p) { unsigned long nextm2 = p.lyCounter.isDoubleSpeed() ? p.lyCounter.time() + (weMasterCheckPriorToLyIncLineCycle(true ) + M2_DS_OFFSET) * 2 - 456 * 2 @@ -863,62 +863,62 @@ namespace M3Loop { if (p.lyCounter.ly() == 143) nextm2 += (456 * 10 + 456 - weMasterCheckPriorToLyIncLineCycle(p.cgb)) << p.lyCounter.isDoubleSpeed(); - + return nextm2; } - + static void xpos168(PPUPriv &p) { p.lastM0Time = p.now - (p.cycles << p.lyCounter.isDoubleSpeed()); - + const unsigned long nextm2 = nextM2Time(p); - + p.cycles = p.now >= nextm2 - ? (static_cast(p.now - nextm2) >> p.lyCounter.isDoubleSpeed()) - : -(static_cast(nextm2 - p.now) >> p.lyCounter.isDoubleSpeed()); - + ? (long(p.now - nextm2) >> p.lyCounter.isDoubleSpeed()) + : -(long(nextm2 - p.now) >> p.lyCounter.isDoubleSpeed()); + nextCall(0, p.lyCounter.ly() == 143 ? M2::Ly0::f0_ : M2::LyNon0::f0_, p); } - + static bool handleWinDrawStartReq(const PPUPriv &p, const int xpos, unsigned char &winDrawState) { const bool startWinDraw = (xpos < 167 || p.cgb) && (winDrawState &= WIN_DRAW_STARTED); - + if (!(p.lcdc & 0x20)) winDrawState &= ~WIN_DRAW_STARTED; - + return startWinDraw; } - + static bool handleWinDrawStartReq(PPUPriv &p) { return handleWinDrawStartReq(p, p.xpos, p.winDrawState); } - + namespace StartWindowDraw { static void inc(const PPUState &nextf, PPUPriv &p) { if (!(p.lcdc & 0x20) && p.cgb) { plotPixelIfNoSprite(p); - + if (p.xpos == p.endx) { if (p.xpos < 168) { nextCall(1,Tile::f0_,p); } else xpos168(p); - + return; } } - + nextCall(1,nextf,p); } - + static void f0(PPUPriv &p) { if (p.xpos == p.endx) { p.tileword = p.ntileword; p.attrib = p.nattrib; p.endx = p.xpos < 160 ? p.xpos + 8 : 168; } - + p.wscx = 8 - p.xpos; - + if ((p.winDrawState & WIN_DRAW_STARTED) && (p.layersMask & LAYER_MASK_WINDOW)) { p.reg1 = p.vram[(p.lcdc << 4 & 0x400) + (p.winYPos & 0xF8) * 4 + 0x1800]; p.nattrib = p.vram[(p.lcdc << 4 & 0x400) + (p.winYPos & 0xF8) * 4 + 0x3800]; @@ -926,40 +926,40 @@ namespace M3Loop { p.reg1 = p.vram[(p.lcdc << 7 & 0x400) + ((p.scy + p.lyCounter.ly()) & 0xF8) * 4 + 0x1800]; p.nattrib = p.vram[(p.lcdc << 7 & 0x400) + ((p.scy + p.lyCounter.ly()) & 0xF8) * 4 + 0x3800]; } - + inc(f1_,p); } - + static void f1(PPUPriv &p) { inc(f2_,p); } - + static void f2(PPUPriv &p) { const unsigned yoffset = ((p.winDrawState & WIN_DRAW_STARTED) && (p.layersMask & LAYER_MASK_WINDOW)) ? p.winYPos : p.scy + p.lyCounter.ly(); - + p.reg0 = p.vram[0x1000 + (p.nattrib << 10 & 0x2000) - ((p.reg1 * 32 | p.lcdc << 8) & 0x1000) + p.reg1 * 16 + ((-(p.nattrib >> 6 & 1) ^ yoffset) & 7) * 2]; inc(f3_,p); } - + static void f3(PPUPriv &p) { inc(f4_,p); } - + static void f4(PPUPriv &p) { const unsigned yoffset = ((p.winDrawState & WIN_DRAW_STARTED) && (p.layersMask & LAYER_MASK_WINDOW)) ? p.winYPos : p.scy + p.lyCounter.ly(); const unsigned r1 = p.vram[0x1000 + (p.nattrib << 10 & 0x2000) - ((p.reg1 * 32 | p.lcdc << 8) & 0x1000) + p.reg1 * 16 + ((-(p.nattrib >> 6 & 1) ^ yoffset) & 7) * 2 + 1]; - + p.ntileword = (expand_lut + (p.nattrib << 3 & 0x100))[p.reg0] + (expand_lut + (p.nattrib << 3 & 0x100))[r1 ] * 2; - + inc(f5_,p); } - + static void f5(PPUPriv &p) { inc(Tile::f0_,p); } @@ -968,7 +968,7 @@ namespace M3Loop { namespace LoadSprites { static void inc(const PPUState &nextf, PPUPriv &p) { plotPixelIfNoSprite(p); - + if (p.xpos == p.endx) { if (p.xpos < 168) { nextCall(1,Tile::f0_,p); @@ -977,68 +977,68 @@ namespace M3Loop { } else nextCall(1,nextf,p); } - + static void f0(PPUPriv &p) { p.reg1 = p.spriteMapper.oamram()[p.spriteList[p.currentSprite].oampos + 2]; nextCall(1,f1_,p); } - + static void f1(PPUPriv &p) { if ((p.winDrawState & WIN_DRAW_START) && handleWinDrawStartReq(p)) return StartWindowDraw::f0(p); - + p.spriteList[p.currentSprite].attrib = p.spriteMapper.oamram()[p.spriteList[p.currentSprite].oampos + 3]; inc(f2_,p); } - + static void f2(PPUPriv &p) { if ((p.winDrawState & WIN_DRAW_START) && handleWinDrawStartReq(p)) return StartWindowDraw::f0(p); - + const unsigned spline = ((p.spriteList[p.currentSprite].attrib & 0x40) ? p.spriteList[p.currentSprite].line ^ 15 : p.spriteList[p.currentSprite].line) * 2; p.reg0 = p.vram[(p.spriteList[p.currentSprite].attrib << 10 & p.cgb * 0x2000) + ((p.lcdc & 4) ? (p.reg1 * 16 & ~16) | spline : p.reg1 * 16 | (spline & ~16))]; inc(f3_,p); } - + static void f3(PPUPriv &p) { if ((p.winDrawState & WIN_DRAW_START) && handleWinDrawStartReq(p)) return StartWindowDraw::f0(p); - + inc(f4_,p); } - + static void f4(PPUPriv &p) { if ((p.winDrawState & WIN_DRAW_START) && handleWinDrawStartReq(p)) return StartWindowDraw::f0(p); - + const unsigned spline = ((p.spriteList[p.currentSprite].attrib & 0x40) ? p.spriteList[p.currentSprite].line ^ 15 : p.spriteList[p.currentSprite].line) * 2; p.reg1 = p.vram[(p.spriteList[p.currentSprite].attrib << 10 & p.cgb * 0x2000) + ((p.lcdc & 4) ? (p.reg1 * 16 & ~16) | spline : p.reg1 * 16 | (spline & ~16)) + 1]; inc(f5_,p); } - + static void f5(PPUPriv &p) { if ((p.winDrawState & WIN_DRAW_START) && handleWinDrawStartReq(p)) return StartWindowDraw::f0(p); - + plotPixelIfNoSprite(p); - + unsigned entry = p.currentSprite; - + if (entry == p.nextSprite) { ++p.nextSprite; } else { entry = p.nextSprite - 1; p.spriteList[entry] = p.spriteList[p.currentSprite]; } - + p.spwordList[entry] = expand_lut[p.reg0 + (p.spriteList[entry].attrib << 3 & 0x100)] + expand_lut[p.reg1 + (p.spriteList[entry].attrib << 3 & 0x100)] * 2; p.spriteList[entry].spx = p.xpos; - + if (p.xpos == p.endx) { if (p.xpos < 168) { nextCall(1,Tile::f0_,p); @@ -1050,32 +1050,32 @@ namespace M3Loop { } } }; - + namespace Tile { static void inc(const PPUState &nextf, PPUPriv &p) { plotPixelIfNoSprite(p); - + if (p.xpos == 168) { xpos168(p); } else nextCall(1,nextf,p); } - + static void f0(PPUPriv &p) { if ((p.winDrawState & WIN_DRAW_START) && handleWinDrawStartReq(p)) return StartWindowDraw::f0(p); - + doFullTilesUnrolled(p); - + if (p.xpos == 168) { ++p.cycles; return xpos168(p); } - + p.tileword = p.ntileword; p.attrib = p.nattrib; p.endx = p.xpos < 160 ? p.xpos + 8 : 168; - + if ((p.winDrawState & WIN_DRAW_STARTED) && (p.layersMask & LAYER_MASK_WINDOW) ) { p.reg1 = p.vram[(p.lcdc << 4 & 0x400) + (p.winYPos & 0xF8) * 4 + ((p.xpos + p.wscx) >> 3 & 0x1F) + 0x1800]; @@ -1087,84 +1087,84 @@ namespace M3Loop { p.nattrib = p.vram[((p.lcdc << 7 | (p.scx + p.xpos + 1 - p.cgb) >> 3) & 0x41F) + ((p.scy + p.lyCounter.ly()) & 0xF8) * 4 + 0x3800]; } - + inc(f1_,p); } - + static void f1(PPUPriv &p) { if ((p.winDrawState & WIN_DRAW_START) && handleWinDrawStartReq(p)) return StartWindowDraw::f0(p); - + inc(f2_,p); } - + static void f2(PPUPriv &p) { if ((p.winDrawState & WIN_DRAW_START) && handleWinDrawStartReq(p)) return StartWindowDraw::f0(p); - + const unsigned yoffset = ((p.winDrawState & WIN_DRAW_STARTED) && (p.layersMask & LAYER_MASK_WINDOW)) ? p.winYPos : p.scy + p.lyCounter.ly(); - + p.reg0 = p.vram[0x1000 + (p.nattrib << 10 & 0x2000) - ((p.reg1 * 32 | p.lcdc << 8) & 0x1000) + p.reg1 * 16 + ((-(p.nattrib >> 6 & 1) ^ yoffset) & 7) * 2]; inc(f3_,p); } - + static void f3(PPUPriv &p) { if ((p.winDrawState & WIN_DRAW_START) && handleWinDrawStartReq(p)) return StartWindowDraw::f0(p); - + inc(f4_,p); } - + static void f4(PPUPriv &p) { if ((p.winDrawState & WIN_DRAW_START) && handleWinDrawStartReq(p)) return StartWindowDraw::f0(p); - + const unsigned yoffset = ((p.winDrawState & WIN_DRAW_STARTED) && (p.layersMask & LAYER_MASK_WINDOW)) ? p.winYPos : p.scy + p.lyCounter.ly(); const unsigned r1 = p.vram[0x1000 + (p.nattrib << 10 & 0x2000) - ((p.reg1 * 32 | p.lcdc << 8) & 0x1000) + p.reg1 * 16 + ((-(p.nattrib >> 6 & 1) ^ yoffset) & 7) * 2 + 1]; - + p.ntileword = (expand_lut + (p.nattrib << 3 & 0x100))[p.reg0] + (expand_lut + (p.nattrib << 3 & 0x100))[r1 ] * 2; - + plotPixelIfNoSprite(p); - + if (p.xpos == 168) { xpos168(p); } else nextCall(1,f5_,p); } - + static void f5(PPUPriv &p) { int endx = p.endx; p.nextCallPtr = &f5_; - + do { if ((p.winDrawState & WIN_DRAW_START) && handleWinDrawStartReq(p)) return StartWindowDraw::f0(p); - + if (p.spriteList[p.nextSprite].spx == p.xpos) { if ((p.lcdc & 2) | p.cgb) { p.currentSprite = p.nextSprite; return LoadSprites::f0(p); } - + do { ++p.nextSprite; } while (p.spriteList[p.nextSprite].spx == p.xpos); } - + plotPixel(p); - + if (p.xpos == endx) { if (endx < 168) { nextCall(1,f0_,p); } else xpos168(p); - + return; } } while (--p.cycles >= 0); @@ -1177,7 +1177,7 @@ namespace M2 { namespace Ly0 { static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, unsigned winDrawState, int targetxpos, unsigned cycles); } - + namespace LyNon0 { static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, unsigned winDrawState, int targetxpos, unsigned cycles); } @@ -1187,19 +1187,19 @@ namespace M3Loop { static unsigned predictCyclesUntilXposNextLine(const PPUPriv &p, unsigned winDrawState, const int targetx) { if (p.wx == 166 && !p.cgb && p.xpos < 167 && (p.weMaster || (p.wy2 == p.lyCounter.ly() && (p.lcdc & 0x20)))) winDrawState = WIN_DRAW_START | (WIN_DRAW_STARTED & p.lcdc >> 4); - + const unsigned cycles = (nextM2Time(p) - p.now) >> p.lyCounter.isDoubleSpeed(); return p.lyCounter.ly() == 143 ? M2::Ly0::predictCyclesUntilXpos_f0(p, winDrawState, targetx, cycles) : M2::LyNon0::predictCyclesUntilXpos_f0(p, winDrawState, targetx, cycles); } - + namespace StartWindowDraw { static unsigned predictCyclesUntilXpos_fn(const PPUPriv &p, int xpos, int endx, unsigned ly, unsigned nextSprite, bool weMaster, unsigned winDrawState, int fno, int targetx, unsigned cycles); } - + namespace Tile { static const unsigned char* addSpriteCycles(const unsigned char *nextSprite, const unsigned char *spriteEnd, const unsigned char *const spxOf, const unsigned maxSpx, @@ -1223,7 +1223,7 @@ namespace M3Loop { return nextSprite; } - + static unsigned predictCyclesUntilXpos_fn(const PPUPriv &p, const int xpos, const int endx, const unsigned ly, const unsigned nextSprite, const bool weMaster, unsigned char winDrawState, const int fno, const int targetx, unsigned cycles) { @@ -1231,16 +1231,16 @@ namespace M3Loop { return StartWindowDraw::predictCyclesUntilXpos_fn(p, xpos, endx, ly, nextSprite, weMaster, WIN_DRAW_STARTED & p.lcdc >> 4, 0, targetx, cycles); } - + if (xpos > targetx) return predictCyclesUntilXposNextLine(p, winDrawState, targetx); - + enum { NO_TILE_NUMBER = 1 }; // low bit set, so it will never be equal to an actual tile number. - + int nwx = 0xFF; cycles += targetx - xpos; - if (p.wx - static_cast(xpos) < targetx - static_cast(xpos) && (p.lcdc & 0x20) + if (p.wx - unsigned(xpos) < targetx - unsigned(xpos) && (p.lcdc & 0x20) && (weMaster || p.wy2 == ly) && !(winDrawState & WIN_DRAW_STARTED) && (p.cgb || p.wx != 166)) { nwx = p.wx; cycles += 6; @@ -1250,10 +1250,10 @@ namespace M3Loop { const unsigned char *sprite = p.spriteMapper.sprites(ly); const unsigned char *const spriteEnd = sprite + p.spriteMapper.numSprites(ly); sprite += nextSprite; - + if (sprite < spriteEnd) { const int spx = p.spriteMapper.posbuf()[*sprite + 1]; - unsigned firstTileXpos = static_cast(endx) & 7; // ok even if endx is capped at 168, because fno will be used. + unsigned firstTileXpos = unsigned(endx) & 7; // ok even if endx is capped at 168, because fno will be used. unsigned prevSpriteTileNo = (xpos - firstTileXpos) & ~7; // this tile. all sprites on this tile will now add 6 cycles. // except this one @@ -1273,16 +1273,16 @@ namespace M3Loop { targetx, firstTileXpos, prevSpriteTileNo, &cycles); } } - + return cycles; } - + static unsigned predictCyclesUntilXpos_fn(const PPUPriv &p, - const int endx, const int fno, const int targetx, const unsigned cycles) { + int endx, int fno, int targetx, unsigned cycles) { return predictCyclesUntilXpos_fn(p, p.xpos, endx, p.lyCounter.ly(), p.nextSprite, p.weMaster, p.winDrawState, fno, targetx, cycles); } - + static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, int targetx, unsigned cycles) { return predictCyclesUntilXpos_fn(p, p.xpos < 160 ? p.xpos + 8 : 168, 0, targetx, cycles); } @@ -1302,14 +1302,14 @@ namespace M3Loop { return predictCyclesUntilXpos_fn(p, p.endx, 5, targetx, cycles); } } - + namespace StartWindowDraw { static unsigned predictCyclesUntilXpos_fn(const PPUPriv &p, int xpos, const int endx, const unsigned ly, const unsigned nextSprite, const bool weMaster, const unsigned winDrawState, const int fno, const int targetx, unsigned cycles) { if (xpos > targetx) return predictCyclesUntilXposNextLine(p, winDrawState, targetx); - + unsigned cinc = 6 - fno; if (!(p.lcdc & 0x20) && p.cgb) { @@ -1322,23 +1322,23 @@ namespace M3Loop { xpos += xinc; } } - + cycles += cinc; if (xpos <= targetx) { return Tile::predictCyclesUntilXpos_fn(p, xpos, xpos < 160 ? xpos + 8 : 168, ly, nextSprite, weMaster, winDrawState, 0, targetx, cycles); } - + return cycles - 1; } - - static unsigned predictCyclesUntilXpos_fn(const PPUPriv &p, const int endx, - const int fno, const int targetx, const unsigned cycles) { + + static unsigned predictCyclesUntilXpos_fn(const PPUPriv &p, int endx, + int fno, int targetx, unsigned cycles) { return predictCyclesUntilXpos_fn(p, p.xpos, endx, p.lyCounter.ly(), p.nextSprite, p.weMaster, p.winDrawState, fno, targetx, cycles); } - + static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, const int targetx, const unsigned cycles) { return predictCyclesUntilXpos_fn(p, p.xpos == p.endx ? (p.xpos < 160 ? p.xpos + 8 : 168) : p.endx, 0, targetx, cycles); } @@ -1362,16 +1362,16 @@ namespace M3Loop { namespace LoadSprites { static unsigned predictCyclesUntilXpos_fn(const PPUPriv &p, const int fno, const int targetx, unsigned cycles) { unsigned nextSprite = p.nextSprite; - + if ((p.lcdc & 2) | p.cgb) { cycles += 6 - fno; nextSprite += 1; } - + return Tile::predictCyclesUntilXpos_fn(p, p.xpos, p.endx, p.lyCounter.ly(), nextSprite, p.weMaster, p.winDrawState, 5, targetx, cycles); } - + static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, int targetx, unsigned cycles) { return predictCyclesUntilXpos_fn(p, 0, targetx, cycles); } @@ -1394,24 +1394,24 @@ namespace M3Loop { } namespace M3Start { - static unsigned predictCyclesUntilXpos_f1(const PPUPriv &p, const unsigned xpos, const unsigned ly, - const bool weMaster, const unsigned winDrawState, const int targetx, unsigned cycles) { - cycles += std::min((static_cast(p.scx) - static_cast(xpos)) & 7, MAX_M3START_CYCLES - xpos) + 1 - p.cgb; + static unsigned predictCyclesUntilXpos_f1(const PPUPriv &p, unsigned xpos, unsigned ly, + bool weMaster, unsigned winDrawState, int targetx, unsigned cycles) { + cycles += std::min((unsigned(p.scx) - unsigned(xpos)) & 7, MAX_M3START_CYCLES - xpos) + 1 - p.cgb; return M3Loop::Tile::predictCyclesUntilXpos_fn(p, 0, 8 - (p.scx & 7), ly, 0, weMaster, winDrawState, std::min(p.scx & 7, 5), targetx, cycles); } - - static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, const unsigned ly, - const bool weMaster, unsigned winDrawState, const int targetx, const unsigned cycles) { + + static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, unsigned ly, + bool weMaster, unsigned winDrawState, int targetx, unsigned cycles) { winDrawState = (winDrawState & p.lcdc >> 5 & WIN_DRAW_START) ? WIN_DRAW_STARTED : 0; return predictCyclesUntilXpos_f1(p, 0, ly, weMaster, winDrawState, targetx, cycles); } - - static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, const int targetx, const unsigned cycles) { + + static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, int targetx, unsigned cycles) { const unsigned ly = p.lyCounter.ly() + (p.lyCounter.time() - p.now < 16); return predictCyclesUntilXpos_f0(p, ly, p.weMaster, p.winDrawState, targetx, cycles); } - + static unsigned predictCyclesUntilXpos_f1(const PPUPriv &p, const int targetx, const unsigned cycles) { return predictCyclesUntilXpos_f1(p, p.xpos, p.lyCounter.ly(), p.weMaster, p.winDrawState, targetx, cycles); } @@ -1420,44 +1420,44 @@ namespace M3Start { namespace M2 { namespace Ly0 { static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, - const unsigned winDrawState, const int targetx, const unsigned cycles) { - const bool weMaster = (p.lcdc & 0x20) && 0 == p.wy; - const unsigned ly = 0; - + unsigned winDrawState, int targetx, unsigned cycles) { + bool weMaster = (p.lcdc & 0x20) && 0 == p.wy; + unsigned ly = 0; + return M3Start::predictCyclesUntilXpos_f0(p, ly, weMaster, winDrawState, targetx, cycles + m3StartLineCycle(p.cgb)); } - - static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, const int targetx, const unsigned cycles) { + + static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, int targetx, unsigned cycles) { return predictCyclesUntilXpos_f0(p, p.winDrawState, targetx, cycles); } } - + namespace LyNon0 { static unsigned predictCyclesUntilXpos_f1(const PPUPriv &p, bool weMaster, - const unsigned winDrawState, const int targetx, const unsigned cycles) { - const unsigned ly = p.lyCounter.ly() + 1; - + unsigned winDrawState, int targetx, unsigned cycles) { + unsigned ly = p.lyCounter.ly() + 1; + weMaster |= (p.lcdc & 0x20) && ly == p.wy; - + return M3Start::predictCyclesUntilXpos_f0(p, ly, weMaster, winDrawState, targetx, cycles + 456 - weMasterCheckAfterLyIncLineCycle(p.cgb) + m3StartLineCycle(p.cgb)); } - - static unsigned predictCyclesUntilXpos_f1(const PPUPriv &p, const int targetx, const unsigned cycles) { + + static unsigned predictCyclesUntilXpos_f1(const PPUPriv &p, int targetx, unsigned cycles) { return predictCyclesUntilXpos_f1(p, p.weMaster, p.winDrawState, targetx, cycles); } - + static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, - const unsigned winDrawState, const int targetx, const unsigned cycles) { - const bool weMaster = p.weMaster || ((p.lcdc & 0x20) && p.lyCounter.ly() == p.wy); - + unsigned winDrawState, int targetx, unsigned cycles) { + bool weMaster = p.weMaster || ((p.lcdc & 0x20) && p.lyCounter.ly() == p.wy); + return predictCyclesUntilXpos_f1(p, weMaster, winDrawState, targetx, cycles + weMasterCheckAfterLyIncLineCycle(p.cgb) - weMasterCheckPriorToLyIncLineCycle(p.cgb)); } - - static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, const int targetx, const unsigned cycles) { + + static unsigned predictCyclesUntilXpos_f0(const PPUPriv &p, int targetx, unsigned cycles) { return predictCyclesUntilXpos_f0(p, p.winDrawState, targetx, cycles); } } @@ -1508,7 +1508,7 @@ struct BSearch { static std::size_t upperBound(const T a[], const K e) { if (e < a[start + len / 2]) return BSearch::upperBound(a, e); - + return BSearch::upperBound(a, e); } }; @@ -1539,14 +1539,14 @@ static const PPUState * decodeM3LoopState(const unsigned state) { case M3Loop::Tile::ID3: return &M3Loop::Tile::f3_; case M3Loop::Tile::ID4: return &M3Loop::Tile::f4_; case M3Loop::Tile::ID5: return &M3Loop::Tile::f5_; - + case M3Loop::LoadSprites::ID0: return &M3Loop::LoadSprites::f0_; case M3Loop::LoadSprites::ID1: return &M3Loop::LoadSprites::f1_; case M3Loop::LoadSprites::ID2: return &M3Loop::LoadSprites::f2_; case M3Loop::LoadSprites::ID3: return &M3Loop::LoadSprites::f3_; case M3Loop::LoadSprites::ID4: return &M3Loop::LoadSprites::f4_; case M3Loop::LoadSprites::ID5: return &M3Loop::LoadSprites::f5_; - + case M3Loop::StartWindowDraw::ID0: return &M3Loop::StartWindowDraw::f0_; case M3Loop::StartWindowDraw::ID1: return &M3Loop::StartWindowDraw::f1_; case M3Loop::StartWindowDraw::ID2: return &M3Loop::StartWindowDraw::f2_; @@ -1560,10 +1560,10 @@ static const PPUState * decodeM3LoopState(const unsigned state) { static long cyclesUntilM0Upperbound(const PPUPriv &p) { long cycles = 168 - p.xpos + 6; - + for (unsigned i = p.nextSprite; i < 10 && p.spriteList[i].spx < 168; ++i) cycles += 11; - + return cycles; } @@ -1584,13 +1584,13 @@ static void loadSpriteList(PPUPriv &p, const SaveState &ss) { p.spriteList[i].attrib = ss.ppu.spAttribList[i] & 0xFF; p.spwordList[i] = (ss.ppu.spByte1List[i] * 0x100 + ss.ppu.spByte0List[i]) & 0xFFFF; } - + p.spriteList[numSprites].spx = 0xFF; p.nextSprite = std::min(ss.ppu.nextSprite, numSprites); - + while (p.spriteList[p.nextSprite].spx < ss.ppu.xpos) ++p.nextSprite; - + p.currentSprite = std::min(p.nextSprite, ss.ppu.currentSprite); } } @@ -1605,7 +1605,7 @@ void PPU::loadState(const SaveState &ss, const unsigned char *const oamram) { ? videoCycles - ds * M2_DS_OFFSET + 70224 : videoCycles - ds * M2_DS_OFFSET; const long lineCycles = static_cast(vcycs) % 456; - + p_.now = ss.cpu.cycleCounter; p_.lcdc = ss.mem.ioamhram.get()[0x140]; p_.lyCounter.setDoubleSpeed(ds); @@ -1632,12 +1632,12 @@ void PPU::loadState(const SaveState &ss, const unsigned char *const oamram) { p_.lastM0Time = p_.now - ss.ppu.lastM0Time; p_.cgb = ss.ppu.isCgb; loadSpriteList(p_, ss); - + if (m3loopState && videoCycles < 144 * 456L && p_.xpos < 168 - && lineCycles + cyclesUntilM0Upperbound(p_) < static_cast(weMasterCheckPriorToLyIncLineCycle(p_.cgb))) { + && lineCycles + cyclesUntilM0Upperbound(p_) < long(weMasterCheckPriorToLyIncLineCycle(p_.cgb))) { p_.nextCallPtr = m3loopState; p_.cycles = -1; - } else if (vcycs < 143 * 456L + static_cast(m3StartLineCycle(p_.cgb)) + MAX_M3START_CYCLES) { + } else if (vcycs < 143 * 456L + long(m3StartLineCycle(p_.cgb)) + MAX_M3START_CYCLES) { const CycleState lineCycleStates[] = { { &M3Start::f0_, m3StartLineCycle(p_.cgb) }, { &M3Start::f1_, m3StartLineCycle(p_.cgb) + MAX_M3START_CYCLES }, @@ -1645,13 +1645,13 @@ void PPU::loadState(const SaveState &ss, const unsigned char *const oamram) { { &M2::LyNon0::f1_, weMasterCheckAfterLyIncLineCycle(p_.cgb) }, { &M3Start::f0_, m3StartLineCycle(p_.cgb) + 456 } }; - + const std::size_t pos = upperBound(lineCycleStates, lineCycles); - + p_.cycles = lineCycles - lineCycleStates[pos].cycle; p_.nextCallPtr = lineCycleStates[pos].state; - + if (&M3Start::f1_ == lineCycleStates[pos].state) { p_.xpos = lineCycles - m3StartLineCycle(p_.cgb) + 1; p_.cycles = -1; @@ -1671,7 +1671,7 @@ void PPU::reset(const unsigned char *const oamram, const unsigned char *const vr void PPU::resetCc(const unsigned long oldCc, const unsigned long newCc) { const unsigned long dec = oldCc - newCc; const unsigned long videoCycles = p_.lcdc & 0x80 ? p_.lyCounter.frameCycles(p_.now) : 0; - + p_.now -= dec; p_.lastM0Time = p_.lastM0Time ? p_.lastM0Time - dec : p_.lastM0Time; p_.lyCounter.reset(videoCycles, p_.now); @@ -1680,12 +1680,12 @@ void PPU::resetCc(const unsigned long oldCc, const unsigned long newCc) { void PPU::speedChange(const unsigned long cycleCounter) { const unsigned long videoCycles = p_.lcdc & 0x80 ? p_.lyCounter.frameCycles(p_.now) : 0; - + p_.spriteMapper.preSpeedChange(cycleCounter); p_.lyCounter.setDoubleSpeed(!p_.lyCounter.isDoubleSpeed()); p_.lyCounter.reset(videoCycles, p_.now); p_.spriteMapper.postSpeedChange(cycleCounter); - + if (&M2::Ly0::f0_ == p_.nextCallPtr || &M2::LyNon0::f0_ == p_.nextCallPtr) { if (p_.lyCounter.isDoubleSpeed()) { p_.cycles -= M2_DS_OFFSET; @@ -1707,7 +1707,7 @@ void PPU::setLcdc(const unsigned lcdc, const unsigned long cc) { p_.weMaster = (lcdc & 0x20) && 0 == p_.wy; p_.winDrawState = 0; p_.nextCallPtr = &M3Start::f0_; - p_.cycles = -static_cast(m3StartLineCycle(p_.cgb) + M2_DS_OFFSET * p_.lyCounter.isDoubleSpeed()); + p_.cycles = -int(m3StartLineCycle(p_.cgb) + M2_DS_OFFSET * p_.lyCounter.isDoubleSpeed()); } else if ((p_.lcdc ^ lcdc) & 0x20) { if (!(lcdc & 0x20)) { if (p_.winDrawState == WIN_DRAW_STARTED || p_.xpos == 168) @@ -1717,23 +1717,23 @@ void PPU::setLcdc(const unsigned lcdc, const unsigned long cc) { ++p_.winYPos; } } - + if ((p_.lcdc ^ lcdc) & 0x04) { if (p_.lcdc & lcdc & 0x80) p_.spriteMapper.oamChange(cc); - + p_.spriteMapper.setLargeSpritesSource(lcdc & 0x04); } - + p_.lcdc = lcdc; } void PPU::update(const unsigned long cc) { const int cycles = (cc - p_.now) >> p_.lyCounter.isDoubleSpeed(); - + p_.now += cycles << p_.lyCounter.isDoubleSpeed(); p_.cycles += cycles; - + if (p_.cycles >= 0) { p_.framebuf.setFbline(p_.lyCounter.ly()); p_.nextCallPtr->f(p_); diff --git a/libgambatte/src/video/ppu.h b/libgambatte/src/video/ppu.h index a32176d589..9ef73f74d4 100644 --- a/libgambatte/src/video/ppu.h +++ b/libgambatte/src/video/ppu.h @@ -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(); } diff --git a/libgambatte/src/video/sprite_mapper.cpp b/libgambatte/src/video/sprite_mapper.cpp index 208b80e8e7..489af046d2 100644 --- a/libgambatte/src/video/sprite_mapper.cpp +++ b/libgambatte/src/video/sprite_mapper.cpp @@ -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); } diff --git a/libgambatte/src/video/sprite_mapper.h b/libgambatte/src/video/sprite_mapper.h index b6171f842d..254b433cfd 100644 --- a/libgambatte/src/video/sprite_mapper.h +++ b/libgambatte/src/video/sprite_mapper.h @@ -78,7 +78,7 @@ public: private: mutable unsigned char spritemap[144*10]; mutable unsigned char num[144]; - + NextM0Time &nextM0Time_; OamReader oamReader; diff --git a/output/dll/libgambatte.dll b/output/dll/libgambatte.dll index 4fac65dc3a39e0105e69397bffed25ce7456143c..5c29f24fa2a36f6061d21dd0b8062d3379613fce 100644 GIT binary patch delta 2339 zcmY*Z2~-v56`ni1rw>FK5D%y^fLmOXSz(4*o=4@>s3Y}06rG)5078n=p7QX74!6>5#z9xA=hB`1C7eDi%1ai%`Oc#({vOY6A77m#;*+mff_fgnxEsk7MY3oT48E&MBzAKU$y(|{UyQB5l zIV{%nkLRUH?`6LtMpUXVj$SOdu``H9BkbaCzP1ypRhg22cI750bYOx!vc5%vaH(x z%L2%*jn-^Cr1pUZ%jyf;Ln8F|aqMS?mHoo7DkEnIybFV@t3zNpz$ZrXFqj;X$j+tK($P=|;4<3Bz*4YVv&X`58#y7vI9dw>jaU|rK&sWj z!W|OwjH?1HfPRJ;3xmkVGmTaO1fx0@UWM(}-dKnV4qi74?X6pk_WDj*m&U_lAkR;- zl!;IdFvdEb0Hf@XYu%dy(@7|`lxeUz6t{aR6>jx_3hS%4As1k<@kTmK7;u&+2+xlT zPWb-W(cN9vNTuOnOXZs9`3_sv>2NX(l8lr>_$Vnq?olQ0Ac$yJZ}-tSB*eD~UEs3e zm8cn?;yIJpo$uhz&+5+a@~yv-1JL3k3VvaeIHaj?G$ci!iE z`fLviP8h$>hHxXl0_MO|<7@?5UuI0HgmgG)9jJu80kG9dT?3WmjEZ$Y)g!hbb|VfU zjv_eyIZh&PLHq^rH^g1UL&VGYf06gV+z>=0A_g(al4{_s5V&F0Ho#N}(%*U7J;QTv zLHk_m<`(GLgY4R8-P-{(0wB{EzYEV)g0*iKyhR!ydXNr%_)=5G6!gIZ%lnpeitsScXlJmm`mM1La+f1^f@JM7{>7 zGUVP;90++Satif@$X6mKR$y)&P&G)$eTX{pYUGJU*cb<0g}kj8H-@?g`8L#vx?rGI z<4rUMqU)@}eK6ccK0Ih`_re*i&%=ZGE`El!q5~c|;$MEWNqlS);z$HZ90C6wLA;Cw zBMUU$7+;2N5})L+h@9*ygBt$=V_NhE2IqhO*j z(!X5rF9Umgu^->iert)HB%`EGtT2l$WmmE5*=_7T_6U2NJly>`}f_T9lj0BPCGnuZ~nDb+S4~eOLWJtyQSb@hQtYGK+)P0=Q4^R#qr zxwcAc(7alsc181P4>iI`Ib)oxbAmI;xyZTP>2Yp#n$D9Y&Q@oK6SuGph;jIV3ZNtC z(X>RT(CKs$T}SVro9J8gQ@SrRf>D|2OeRyvtY$VbyO_hwpP38HP38duEX78#quDri z0y~|Z$ELG+YzgZ@KlZcVu$S3;ET98}xp?kPZZ5Z!E9BO2o4GHzZ@E^kq>}@_H{YKh z$;6(JwOKu{-cW~W zW3~C(JDN+Y)PASkM{ED+eC#B=K=}Wrq4Y#Lna-vQ=wPNFGl-ePWHT=2W9Bn-tdVJE zt~1Bj8*DpEa-rPo+}tA0&F$b0a9?uYao4#>K89y`ji16N@-zA0@EN>^*ZEESUi71p zzs%p^JNZX^7f%Wfp^p$Q3=pD);ldb!6+}T3CJIx8nZkVGJz=F#DOh7(BQMzMY1{t* DmzMrh delta 2370 zcmY*Z3se+G7VTHez@P}Nl10$~BBD{${*Kd3cMqbRND^02QCtO$CJ~9KEW>I51wk=7 zfW&rf4XF5!pXlg_O=99F7=K5NG4Y4)5#6ZxNzkmTY!2@1n;3Vqbw#|Rv{tj2A_%ob>t~t z3==(JlTL=f22b<*P9SlzHZI2sw>_0Ph0rZ@0H&+Pk}Jzi0Th*0f;6SY67PwcZ3WUJ zPD`J|;hwHJMI_Ru1?IBwP_yUuB(K@D3AtAIhgO|CvrGRWK)Lclv#11$%ErROhj@bj zYzD~DLi2h;}^d-BRM6!^mP?U7dkp;o(l$_urgyQkN8fOgN4i!01% zd-%1!_z4oPrNMH~>T3)@gLdkAFOWSCu5ayug{^3Fz#h+qHZFifZ?E?UH^3R)02mCl z#$ABfek4ve(#?<=3}+0ZD{Kr2Yy1nA{i|VRzcb9x=k$gdFw$u14RZl5>ZAKWa@a!W z%elWdH(%e^2Tl=~V$6?)RuhSuZOj?~1pu4%dvP!eL?eA595s==EWN4%DxZ@?%5dkuLctm%wzdnps{_(Q$%<-3pzFj^lx9fpN_1&VUr&S-3T z-0Jm~9iu1XS-2z=uB4!{BV+xJ+ApWLlG*3`v9eyxM%VDP<%r*usgL0BqzXIr^h_i^Rh}(#t5Yx05c!r!p9*F3I z=z)kqyo?V-Zbdi{BM_;GKN*3QFg67C7@4*3CUltg-oL$Ru7?@-`Wv3L5a3VZJ~h7B z1ZjRyqj%YcCobP8+6H6EsvS@ZhxD~OUtPuQwlM070@3dZ!Q9wM%{(H4)ya@K|n9XK@Wz(VIHv~3;2r!w7zVDDJ7U_S_cxPp|C@Wza<`Ff zCL~gNh+8b-_Hqr}G44EfoonG9bH8wYd=UQ%AHnzK8D8QO`8WBoduqCgc3YCI z%J#M1sXG~1oE)EHueI0P&)A#oPwW=Cr#x6rl+)xaxlpc>H^}?t6LORMqf9AXl~_em zl9dU{4CMo5sj^1dt{hS>D0h@!lwdVl<V{XKg{vAxE=+y1%z zwEdd>vE5(pAxF#ob-3XQ@^;Tk&fL