diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 458a7ea58..f1f4e40a7 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -1168,21 +1168,31 @@ void DebuggerParser::executeRun() void DebuggerParser::executeRunTo() { ostringstream buf; - bool done = false; - int cycles = 0, count = 0; + const CartDebug& cartdbg = debugger->cartDebug(); + const CartDebug::DisassemblyList& list = cartdbg.disassemblyList(); + uInt32 count = 0; + bool done = false; do { - cycles += debugger->step(); - string next = debugger->cartDebug().disassemble(debugger->cpuDebug().pc(), 1); - done = (next.find(argStrings[0]) != string::npos); + debugger->step(); + + // Update romlist to point to current PC + int pcline = cartdbg.addressToLine(debugger->cpuDebug().pc()); + if(pcline >= 0) + { + const string& next = list[pcline].disasm; + done = (next.find(argStrings[0]) != string::npos); + } ++count; - } while(!done && count < 10000); + } while(!done && count < list.size()); if(done) - buf << "found " << argStrings[0] << " in " << debugger->valueToString(cycles) - << " cycles"; + buf << "found " << argStrings[0] << " in " + << debugger->valueToString(count, kBASE_10) + << " disassembled instructions"; else - buf << argStrings[0] << " not found in " << debugger->valueToString(count) + buf << argStrings[0] << " not found in " + << debugger->valueToString(count, kBASE_10) << " disassembled instructions"; commandResult = buf.str(); diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx index 654b9a40d..fc4a257a2 100644 --- a/src/debugger/DebuggerParser.hxx +++ b/src/debugger/DebuggerParser.hxx @@ -47,7 +47,7 @@ class DebuggerParser string exec(const string& file, bool verbose = true); /** Given a substring, determine matching substrings from the list - of available commands. Used in the debugger prompt for tab-completion */ + of available commands. Used in the debugger prompt for tab-completion */ int countCompletions(const char *in); const char *getCompletions(); const char *getCompletionPrefix(); diff --git a/src/emucore/CartDPCPlus.cxx b/src/emucore/CartDPCPlus.cxx index 44fa5af80..540ef0b60 100644 --- a/src/emucore/CartDPCPlus.cxx +++ b/src/emucore/CartDPCPlus.cxx @@ -1,8 +1,8 @@ //============================================================================ // -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa // SSSS tt ee ee ll ll aa // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" // SS SS tt ee ll ll aa aa @@ -22,13 +22,12 @@ #include "System.hxx" #include "CartDPCPlus.hxx" -// TODO - INC AUDV0+$40 music support - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size) : myFastFetch(false), myLDAimmediate(false), mySelectByte(0), + myMusicVolume(0), mySystemCycles(0), myFractionalClocks(0.0) { @@ -41,7 +40,7 @@ CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size) // Copy the display ROM image into my buffer memcpy(myDisplayImage, image + 4096 * 6, 4096); - + // Copy the Frequency ROM image into my buffer memcpy(myFrequencyImage, image + 4096 * 6 + 4096, 1024); @@ -49,9 +48,6 @@ CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size) for(uInt16 i = 0; i < 8; ++i) myTops[i] = myBottoms[i] = myCounters[i] = myFlags[i] = myFractionalIncrements[i] = 0; - // None of the data fetchers are in music mode - myMusicVolumes[0] = myMusicVolumes[1] = myMusicVolumes[2] = 0; - // Set waveforms to square waves myMusicWaveforms[0] = myMusicWaveforms[1] = myMusicWaveforms[2] = 0xAAAAAAAA; @@ -94,10 +90,10 @@ void CartridgeDPCPlus::install(System& system) mySystem = &system; uInt16 shift = mySystem->pageShift(); uInt16 mask = mySystem->pageMask(); - + // Make sure the system we're being installed in has a page size that'll work assert(((0x1080 & mask) == 0) && ((0x1100 & mask) == 0)); - + // Map all of the accesses to call peek and poke System::PageAccess access; access.directPeekBase = 0; @@ -105,7 +101,7 @@ void CartridgeDPCPlus::install(System& system) access.device = this; for(uInt32 i = 0x1000; i < 0x2000; i += (1 << shift)) mySystem->setPageAccess(i >> shift, access); - + // Install pages for the startup bank bank(myStartBank); } @@ -130,25 +126,91 @@ inline void CartridgeDPCPlus::updateMusicModeDataFetchers() // Calculate the number of cycles since the last update Int32 cycles = mySystem->cycles() - mySystemCycles; mySystemCycles = mySystem->cycles(); - + // Calculate the number of DPC OSC clocks since the last update double clocks = ((20000.0 * cycles) / 1193191.66666667) + myFractionalClocks; Int32 wholeClocks = (Int32)clocks; myFractionalClocks = clocks - (double)wholeClocks; - + if(wholeClocks <= 0) { return; } - + // Let's update counters and flags of the music mode data fetchers for(int x = 5; x <= 7; ++x) { - // Update only if the data fetcher is in music mode - if(myMusicVolumes[x - 5]) + myMusicCounters[x - 5] += myMusicFrequencies[x - 5]; + if (myMusicFrequencies[x-5]>myMusicCounters[x-5]) + myMusicWaveforms[x-5] = (myMusicWaveforms[x-5]>>1)|(myMusicWaveforms[x-5]<<31); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +inline void CartridgeDPCPlus::writeByte(uInt8 value) +{ + switch (mySelectByte) + { + case 0x00: { - myMusicCounters[x - 5] += myMusicFrequencies[x - 5]; + myMusicWaveforms[0] = (myMusicWaveforms[0] & 0xFFFFFF00) | value; + break; } + case 0x01: + { + myMusicWaveforms[0] = (myMusicWaveforms[0] & 0xFFFF00FF) | (value<<8); + break; + } + case 0x02: + { + myMusicWaveforms[0] = (myMusicWaveforms[0] & 0xFF00FFFF) | (value<<16); + break; + } + case 0x03: + { + myMusicWaveforms[0] = (myMusicWaveforms[0] & 0x00FFFFFF) | (value<<24); + break; + } + case 0x04: + { + myMusicWaveforms[1] = (myMusicWaveforms[1] & 0xFFFFFF00) | value; + break; + } + case 0x05: + { + myMusicWaveforms[1] = (myMusicWaveforms[1] & 0xFFFF00FF) | (value<<8); + break; + } + case 0x06: + { + myMusicWaveforms[1] = (myMusicWaveforms[1] & 0xFF00FFFF) | (value<<16); + break; + } + case 0x07: + { + myMusicWaveforms[1] = (myMusicWaveforms[1] & 0x00FFFFFF) | (value<<24); + break; + } + case 0x08: + { + myMusicWaveforms[2] = (myMusicWaveforms[2] & 0xFFFFFF00) | value; + break; + } + case 0x09: + { + myMusicWaveforms[2] = (myMusicWaveforms[2] & 0xFFFF00FF) | (value<<8); + break; + } + case 0x0A: + { + myMusicWaveforms[2] = (myMusicWaveforms[2] & 0xFF00FFFF) | (value<<16); + break; + } + case 0x0B: + { + myMusicWaveforms[2] = (myMusicWaveforms[2] & 0x00FFFFFF) | (value<<24); + break; + } } } @@ -158,7 +220,7 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address) address &= 0x0FFF; uInt8 peekvalue = myProgramImage[(myCurrentBank << 12) + address]; - + // In debugger/bank-locked mode, we ignore all hotspots and in general // anything that can change the internal state of the cart if(bankLocked()) @@ -167,20 +229,20 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address) // Check if we're in Fast Fetch mode and the prior byte was an A9 (LDA #value) if(myFastFetch && myLDAimmediate) { - // if #value is a read-register then we want to use that as the address if(peekvalue < 0x0028) + // if #value is a read-register then we want to use that as the address address = peekvalue; } myLDAimmediate = false; - + if(address < 0x0028) { uInt8 result = 0; - + // Get the index of the data fetcher that's being accessed uInt32 index = address & 0x07; uInt32 function = (address >> 3) & 0x07; - + // Update flag register for selected data fetcher if((myCounters[index] & 0x00ff) == ((myTops[index]+1) & 0xff)) { @@ -190,60 +252,48 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address) { myFlags[index] = 0x00; } - + switch(function) { case 0x00: { switch(index) { - case 0x00: // advance and return byte 0 of random + case 0x00: // RANDOM0NEXT - advance and return byte 0 of random clockRandomNumberGenerator(); result = myRandomNumber & 0xFF; break; - - case 0x01: // return to prior and return byte 0 of random + + case 0x01: // RANDOM0PRIOR - return to prior and return byte 0 of random priorClockRandomNumberGenerator(); result = myRandomNumber & 0xFF; break; - - case 0x02: + + case 0x02: // RANDOM1 result = (myRandomNumber>>8) & 0xFF; break; - - case 0x03: + + case 0x03: // RANDOM2 result = (myRandomNumber>>16) & 0xFF; break; - - case 0x04: + + case 0x04: // RANDOM3 result = (myRandomNumber>>24) & 0xFF; break; - - case 0x05: // No, it's a music read + + case 0x05: // AMPLITUDE { - static const uInt8 musicAmplitudes[8] = { - 0x00, 0x04, 0x05, 0x09, 0x06, 0x0a, 0x0b, 0x0f - }; - // Update the music data fetchers (counter & flag) updateMusicModeDataFetchers(); - - uInt8 i = 0; - if(myMusicVolumes[0] && (myMusicCounters[0]>>31)) - { - i |= 0x01; - } - if(myMusicVolumes[1] && (myMusicCounters[1]>>31)) - { - i |= 0x02; - } - if(myMusicVolumes[2] && (myMusicCounters[2]>>31)) - { - i |= 0x04; - } - - result = musicAmplitudes[i]; - break; + + uInt32 i = 0; + + i = myMusicVolume + ((myMusicVolume >> 12) * (uInt8) (myMusicWaveforms[0] >> 31)) + + ((myMusicVolume >> 16) * (uInt8) (myMusicWaveforms[1] >> 31)) + + ((myMusicVolume >> 24) * (uInt8) (myMusicWaveforms[2] >> 31)); + + result = (uInt8)i; + break; } case 0x06: // reserved @@ -252,39 +302,39 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address) } break; } - - // DFx display data read + + // DFxDATA - display data read case 0x01: { result = myDisplayImage[myCounters[index]]; - myCounters[index] = (myCounters[index] + 0x1) & 0x0fff; + myCounters[index] = (myCounters[index] + 0x1) & 0x0fff; break; } - - // DFx display data read AND'd w/flag + + // DFxDATAW - display data read AND'd w/flag ("windowed") case 0x02: { result = myDisplayImage[myCounters[index]] & myFlags[index]; - myCounters[index] = (myCounters[index] + 0x1) & 0x0fff; + myCounters[index] = (myCounters[index] + 0x1) & 0x0fff; break; - } - - // DFx display data read w/fractional increment + } + + // DFxFRACDATA - display data read w/fractional increment case 0x03: { result = myDisplayImage[myFractionalCounters[index] >> 8]; - myFractionalCounters[index] = (myFractionalCounters[index] + myFractionalIncrements[index]) & 0x0fffff; + myFractionalCounters[index] = (myFractionalCounters[index] + myFractionalIncrements[index]) & 0x0fffff; break; - } + } case 0x04: { switch (index) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: + case 0x00: // DF0FLAG + case 0x01: // DF1FLAG + case 0x02: // DF2FLAG + case 0x03: // DF3FLAG { result = myFlags[index]; break; @@ -295,15 +345,15 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address) case 0x07: // reserved break; } - break; + break; } - + default: { result = 0; } } - + return result; } else @@ -315,36 +365,36 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address) // Set the current bank to the first 4k bank bank(0); break; - + case 0x0FF7: // Set the current bank to the second 4k bank bank(1); break; - + case 0x0FF8: // Set the current bank to the third 4k bank bank(2); break; - + case 0x0FF9: // Set the current bank to the fourth 4k bank bank(3); break; - + case 0x0FFA: // Set the current bank to the fifth 4k bank bank(4); break; - + case 0x0FFB: // Set the current bank to the last 4k bank bank(5); break; - + default: break; } - + if(myFastFetch) myLDAimmediate = (peekvalue == 0xA9); @@ -356,208 +406,130 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address) bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value) { address &= 0x0FFF; - - if((address >= 0x0028) && (address < 0x0080)) + + if((address >= 0x0028) && (address < 0x0080)) { // Get the index of the data fetcher that's being accessed - uInt32 index = address & 0x07; + uInt32 index = address & 0x07; uInt32 function = ((address - 0x28) >> 3) & 0x0f; - + switch(function) { - //DFxFrac counter low + //DFxFRACLOW - fractional data pointer low byte case 0x00: - { myFractionalCounters[index] = (myFractionalCounters[index] & 0x0F0000) | ((uInt16)value << 8); break; - } - - // DFxFrac counter high + + // DFxFRACHI - fractional data pointer high byte case 0x01: - { myFractionalCounters[index] = (((uInt16)value & 0x0F) << 16) | (myFractionalCounters[index] & 0x00ffff); break; - } - - //DFx Fraction Increment amount + + //DFxFRACINC - Fractional Increment amount case 0x02: - { myFractionalIncrements[index] = value; myFractionalCounters[index] = myFractionalCounters[index] & 0x0FFF00; break; - } - // DFx top count + // DFxTOP - set top of window (for reads of DFxDATAW) case 0x03: - { myTops[index] = value; myFlags[index] = 0x00; break; - } - - // DFx bottom count + + // DFxBOT - set bottom of window (for reads of DFxDATAW) case 0x04: - { myBottoms[index] = value; break; - } - - // DFx counter low + + // DFxLOW - data pointer low byte case 0x05: - { myCounters[index] = (myCounters[index] & 0x0F00) | value ; break; - } - + // Control registers case 0x06: - { switch (index) { - // FastFetch control - case 0x00: - { + case 0x00: // FASTFETCH - turns on LDA #