add detection of audio data in DiStella (see #596)

This commit is contained in:
thrust26 2020-03-29 10:51:16 +02:00
parent c09b6167a1
commit 09fb69f397
9 changed files with 223 additions and 150 deletions

View File

@ -22,7 +22,7 @@
* Added displaying last write address in debugger. (TOOD: Doc)
* Added detection of color data in DiStella. (TOOD: Doc)
* Added detection of color and audio data in DiStella. (TOOD: Doc)
6.0.2 to 6.1: (March 22, 2020)

View File

@ -916,6 +916,11 @@ string CartDebug::loadConfigFile()
buf >> hex >> start >> hex >> end;
addDirective(Device::BCOL, start, end, currentbank);
}
else if(BSPF::startsWithIgnoreCase(directive, "Device::AUD"))
{
buf >> hex >> start >> hex >> end;
addDirective(Device::AUD, start, end, currentbank);
}
else if(BSPF::startsWithIgnoreCase(directive, "Device::DATA"))
{
buf >> hex >> start >> hex >> end;
@ -1070,57 +1075,54 @@ string CartDebug::saveDisassembly()
switch(tag.type)
{
case Device::CODE:
{
buf << ALIGN(32) << tag.disasm << tag.ccount.substr(0, 5) << tag.ctotal << tag.ccount.substr(5, 2);
if (tag.disasm.find("WSYNC") != std::string::npos)
buf << "\n;---------------------------------------";
break;
}
case Device::ROW:
{
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 8*4-1) << "; $" << Base::HEX4 << tag.address << " (*)";
break;
}
case Device::GFX:
{
buf << ".byte " << (settings.gfxFormat == Base::Fmt::_2 ? "%" : "$")
<< tag.bytes << " ; |";
for(int c = 12; c < 20; ++c)
buf << ((tag.disasm[c] == '\x1e') ? "#" : " ");
buf << ALIGN(13) << "|" << "$" << Base::HEX4 << tag.address << " (G)";
break;
}
case Device::PGFX:
{
buf << ".byte " << (settings.gfxFormat == Base::Fmt::_2 ? "%" : "$")
<< tag.bytes << " ; |";
for(int c = 12; c < 20; ++c)
buf << ((tag.disasm[c] == '\x1f') ? "*" : " ");
buf << ALIGN(13) << "|" << "$" << Base::HEX4 << tag.address << " (P)";
break;
}
case Device::COL:
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 12) << "; $" << Base::HEX4 << tag.address << " (Px)";
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 12) << "; $" << Base::HEX4 << tag.address << " (C)";
break;
case Device::PCOL:
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 12) << "; $" << Base::HEX4 << tag.address << " (PF)";
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 12) << "; $" << Base::HEX4 << tag.address << " (CP)";
break;
case Device::BCOL:
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 12) << "; $" << Base::HEX4 << tag.address << " (BK)";
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 12) << "; $" << Base::HEX4 << tag.address << " (CB)";
break;
case Device::AUD:
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 8 * 4 - 1) << "; $" << Base::HEX4 << tag.address << " (A)";
break;
case Device::DATA:
{
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 8 * 4 - 1) << "; $" << Base::HEX4 << tag.address << " (D)";
break;
}
case Device::NONE:
default:
{
break;
}
} // switch
buf << "\n";
}
@ -1138,6 +1140,10 @@ string CartDebug::saveDisassembly()
<< "; D = Device::DATA directive (referenced in some way)\n"
<< "; G = Device::GFX directive, shown as '#' (stored in player, missile, ball)\n"
<< "; P = Device::PGFX directive, shown as '*' (stored in playfield)\n"
<< "; C = Device::COL directive, shown as '*' (stored in player color)\n"
<< "; CP = Device::PCOL directive, shown as '*' (stored in playfield color)\n"
<< "; CB = Device::BCOL directive, shown as '*' (stored in background color)\n"
<< "; A = Device::AUD directive, shown as '*' (stored in audio registers)\n"
<< "; i = indexed accessed only\n"
<< "; c = used by code executed in RAM\n"
<< "; s = used by stack\n"
@ -1478,6 +1484,8 @@ Device::AccessType CartDebug::accessTypeAbsolute(Device::AccessFlags flags) cons
return Device::PCOL;
else if(flags & Device::BCOL)
return Device::BCOL;
else if(flags & Device::AUD)
return Device::AUD;
else if(flags & Device::DATA)
return Device::DATA;
else if(flags & Device::ROW)
@ -1498,6 +1506,7 @@ void CartDebug::AccessTypeAsString(ostream& buf, Device::AccessType type) const
case Device::COL: buf << "Device::COL"; break;
case Device::PCOL: buf << "Device::PCOL"; break;
case Device::BCOL: buf << "Device::BCOL"; break;
case Device::AUD: buf << "Device::AUD"; break;
case Device::DATA: buf << "Device::DATA"; break;
case Device::ROW: buf << "Device::ROW"; break;
case Device::REFERENCED:
@ -1525,6 +1534,8 @@ void CartDebug::AccessTypeAsString(ostream& buf, Device::AccessFlags flags) cons
buf << "Device::PCOL ";
if(flags & Device::BCOL)
buf << "Device::BCOL ";
if(flags & Device::AUD)
buf << "Device::AUD ";
if(flags & Device::DATA)
buf << "Device::DATA ";
if(flags & Device::ROW)

View File

@ -142,7 +142,7 @@ class CartDebug : public DebuggerSystem
things can't be automatically determined. For now, these directives
have exactly the same syntax as in a distella configuration file.
@param type Currently, CODE/DATA/GFX are supported
@param type Currently, CODE/DATA/GFX/PGFX/COL/PCOL/BCOL/AUD/ROW are supported
@param start The start address (inclusive) to mark with the given type
@param end The end address (inclusive) to mark with the given type
@param bank Bank to which these directive apply (0 indicated current bank)

View File

@ -117,8 +117,8 @@ void DiStella::disasm(uInt32 distart, int pass)
/* pc=myAppData.start; */
myPC = distart - myOffset;
while (myPC <= myAppData.end) {
while(myPC <= myAppData.end)
{
// since -1 is used in m6502.m4 for clearing the last peek
// and this results into an access at e.g. 0xffff,
// we have to fix the consequences here (ugly!).
@ -133,7 +133,8 @@ void DiStella::disasm(uInt32 distart, int pass)
if(pass == 3)
outputGraphics();
++myPC;
} else if (checkBits(myPC, Device::COL | Device::PCOL | Device::BCOL,
}
else if(checkBits(myPC, Device::COL | Device::PCOL | Device::BCOL,
Device::CODE | Device::GFX | Device::PGFX))
{
if(pass == 2)
@ -141,9 +142,22 @@ void DiStella::disasm(uInt32 distart, int pass)
if(pass == 3)
outputColors();
++myPC;
} else if (checkBits(myPC, Device::DATA,
}
else if(checkBits(myPC, Device::AUD,
Device::CODE | Device::GFX | Device::PGFX |
Device::COL | Device::PCOL | Device::BCOL))
{
if(pass == 2)
mark(myPC + myOffset, Device::VALID_ENTRY);
if(pass == 3)
outputBytes(Device::AUD);
else
++myPC;
}
else if(checkBits(myPC, Device::DATA,
Device::CODE | Device::GFX | Device::PGFX |
Device::COL | Device::PCOL | Device::BCOL |
Device::AUD))
{
if(pass == 2)
mark(myPC + myOffset, Device::VALID_ENTRY);
@ -151,10 +165,11 @@ void DiStella::disasm(uInt32 distart, int pass)
outputBytes(Device::DATA);
else
++myPC;
} else if (checkBits(myPC, Device::ROW,
Device::CODE |
Device::DATA | Device::GFX | Device::PGFX |
Device::COL | Device::PCOL | Device::BCOL)) {
}
else if(checkBits(myPC, Device::ROW,
Device::CODE | Device::GFX | Device::PGFX |
Device::COL | Device::PCOL | Device::BCOL |
Device::AUD | Device::DATA)) {
FIX_LAST:
if(pass == 2)
mark(myPC + myOffset, Device::VALID_ENTRY);
@ -163,7 +178,8 @@ FIX_LAST:
outputBytes(Device::ROW);
else
++myPC;
} else {
}
else {
// The following sections must be CODE
// add extra spacing line when switching from non-code to code
@ -221,7 +237,8 @@ FIX_LAST:
}
// continue with the label's opcode
continue;
} else {
}
else {
if(pass == 3) {
// TODO
}
@ -323,16 +340,19 @@ FIX_LAST:
if(labelFound == AddressType::ROM) {
LABEL_A12_HIGH(ad);
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
} else if (labelFound == AddressType::ROM_MIRROR) {
}
else if(labelFound == AddressType::ROM_MIRROR) {
if(mySettings.rFlag) {
int tmp = (ad & myAppData.end) + myOffset;
LABEL_A12_HIGH(tmp);
nextLineBytes << Base::HEX2 << int(tmp & 0xff) << " " << Base::HEX2 << int(tmp >> 8);
} else {
}
else {
nextLine << "$" << Base::HEX4 << ad;
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
}
} else {
}
else {
LABEL_A12_LOW(ad);
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
}
@ -372,7 +392,8 @@ FIX_LAST:
// The processing is left here, however, in case future versions of
// the code can somehow track access to CPU registers
mark(ad, Device::ROW);
} else if (pass == 3) {
}
else if(pass == 3) {
if(ad < 0x100 && mySettings.fFlag)
nextLine << ".wx ";
else
@ -382,17 +403,20 @@ FIX_LAST:
LABEL_A12_HIGH(ad);
nextLine << ",x";
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
} else if (labelFound == AddressType::ROM_MIRROR) {
}
else if(labelFound == AddressType::ROM_MIRROR) {
if(mySettings.rFlag) {
int tmp = (ad & myAppData.end) + myOffset;
LABEL_A12_HIGH(tmp);
nextLine << ",x";
nextLineBytes << Base::HEX2 << int(tmp & 0xff) << " " << Base::HEX2 << int(tmp >> 8);
} else {
}
else {
nextLine << "$" << Base::HEX4 << ad << ",x";
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
}
} else {
}
else {
LABEL_A12_LOW(ad);
nextLine << ",x";
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
@ -411,7 +435,8 @@ FIX_LAST:
// The processing is left here, however, in case future versions of
// the code can somehow track access to CPU registers
mark(ad, Device::ROW);
} else if (pass == 3) {
}
else if(pass == 3) {
if(ad < 0x100 && mySettings.fFlag)
nextLine << ".wy ";
else
@ -421,17 +446,20 @@ FIX_LAST:
LABEL_A12_HIGH(ad);
nextLine << ",y";
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
} else if (labelFound == AddressType::ROM_MIRROR) {
}
else if(labelFound == AddressType::ROM_MIRROR) {
if(mySettings.rFlag) {
int tmp = (ad & myAppData.end) + myOffset;
LABEL_A12_HIGH(tmp);
nextLine << ",y";
nextLineBytes << Base::HEX2 << int(tmp & 0xff) << " " << Base::HEX2 << int(tmp >> 8);
} else {
}
else {
nextLine << "$" << Base::HEX4 << ad << ",y";
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
}
} else {
}
else {
LABEL_A12_LOW(ad);
nextLine << ",y";
nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8);
@ -505,7 +533,8 @@ FIX_LAST:
if(labelFound == AddressType::ROM) {
nextLine << " ";
LABEL_A12_HIGH(ad);
} else
}
else
nextLine << " $" << Base::HEX4 << ad;
nextLineBytes << Base::HEX2 << int(d1);
@ -523,7 +552,8 @@ FIX_LAST:
// The processing is left here, however, in case future versions of
// the code can somehow track access to CPU registers
mark(ad, Device::ROW);
} else if (pass == 3) {
}
else if(pass == 3) {
if(ad < 0x100 && mySettings.fFlag)
nextLine << ".ind ";
else
@ -539,7 +569,8 @@ FIX_LAST:
if(mySettings.rFlag) {
int tmp = (ad & myAppData.end) + myOffset;
LABEL_A12_HIGH(tmp);
} else {
}
else {
LABEL_A12_LOW(ad);
}
nextLine << ")";
@ -571,7 +602,8 @@ FIX_LAST:
// output cycles for previous code block
myDisasmBuf << "'= " << std::setw(3) << std::setfill(' ') << std::dec << cycles;
cycles = 0;
} else {
}
else {
myDisasmBuf << "' ";
}
myDisasmBuf << "'" << nextLineBytes.str();
@ -586,7 +618,7 @@ FIX_LAST:
nextLine.str("");
nextLineBytes.str("");
}
}
} // CODE
} /* while loop */
/* Just in case we are disassembling outside of the address range, force the myPCEnd to EOF */
@ -630,7 +662,7 @@ void DiStella::disasmPass1(CartDebug::AddressList& debuggerAddresses)
// Therefore, we stop at the first such address encountered
for (uInt32 k = pcBeg; k <= myPCEnd; ++k) {
if (checkBits(k, Device::Device::DATA | Device::GFX | Device::PGFX |
Device::COL | Device::PCOL | Device::BCOL,
Device::COL | Device::PCOL | Device::BCOL | Device::AUD,
Device::CODE)) {
//if (Debugger::debugger().getAccessFlags(k) &
// (Device::DATA | Device::GFX | Device::PGFX)) {
@ -692,7 +724,7 @@ void DiStella::disasmPass1(CartDebug::AddressList& debuggerAddresses)
// Must be ROW / unused bytes
if (!checkBit(k, Device::CODE | Device::GFX | Device::PGFX |
Device::COL | Device::PCOL | Device::BCOL |
Device::COL | Device::PCOL | Device::BCOL | Device::AUD |
Device::DATA))
mark(k + myOffset, Device::ROW);
}
@ -711,7 +743,7 @@ void DiStella::disasmFromAddress(uInt32 distart)
// abort when we reach non-code areas
if (checkBits(myPC, Device::Device::DATA | Device::GFX | Device::PGFX |
Device::COL | Device::PCOL | Device::BCOL,
Device::COL | Device::PCOL | Device::BCOL | Device::AUD,
Device::CODE)) {
myPCEnd = (myPC - 1) + myOffset;
return;
@ -1037,18 +1069,11 @@ void DiStella::addEntry(Device::AccessType type)
case Device::GFX:
case Device::PGFX:
getline(myDisasmBuf, tag.disasm, '\'');
getline(myDisasmBuf, tag.bytes);
break;
case Device::COL:
case Device::PCOL:
case Device::BCOL:
getline(myDisasmBuf, tag.disasm, '\'');
getline(myDisasmBuf, tag.bytes);
break;
case Device::DATA:
case Device::AUD:
getline(myDisasmBuf, tag.disasm, '\'');
getline(myDisasmBuf, tag.bytes);
break;
@ -1213,7 +1238,7 @@ void DiStella::outputBytes(Device::AccessType type)
isType = checkBits(myPC, type,
Device::CODE | (type != Device::DATA ? Device::DATA : 0) |
Device::GFX | Device::PGFX |
Device::COL | Device::PCOL | Device::BCOL);
Device::COL | Device::PCOL | Device::BCOL | Device::AUD);
referenced = checkBit(myPC, Device::REFERENCED);
}
if (!lineEmpty)

View File

@ -46,13 +46,14 @@ class Device : public Serializable
// debugger, or specified in a Distella cfg file, and are listed in order
// of decreasing hierarchy
//
CODE = 1 << 10, // 0x400, disassemble-able code segments
TCODE = 1 << 9, // 0x200, (tentative) disassemble-able code segments
GFX = 1 << 8, // 0x100, addresses loaded into GRPx registers
PGFX = 1 << 7, // 0x080, addresses loaded into PFx registers
COL = 1 << 6, // 0x040, addresses loaded into COLUPx registers
PCOL = 1 << 5, // 0x010, addresses loaded into COLUPF register
BCOL = 1 << 4, // 0x010, addresses loaded into COLUBK register
CODE = 1 << 11, // 0x800, disassemble-able code segments
TCODE = 1 << 10, // 0x400, (tentative) disassemble-able code segments
GFX = 1 << 9, // 0x200, addresses loaded into GRPx registers
PGFX = 1 << 8, // 0x100, addresses loaded into PFx registers
COL = 1 << 7, // 0x080, addresses loaded into COLUPx registers
PCOL = 1 << 6, // 0x040, addresses loaded into COLUPF register
BCOL = 1 << 5, // 0x020, addresses loaded into COLUBK register
AUD = 1 << 4, // 0x010, addresses loaded into audio registers
DATA = 1 << 3, // 0x008, addresses loaded into registers other than GRPx / PFx
ROW = 1 << 2, // 0x004, all other addresses
// special type for poke()

View File

@ -23,21 +23,15 @@
// Flags for access types
#define DISASM_CODE Device::CODE
// #define DISASM_GFX Device::GFX
// #define DISASM_PGFX Device::PGFX
#define DISASM_DATA Device::DATA
// #define DISASM_ROW Device::ROW
#define DISASM_WRITE Device::WRITE
#define DISASM_NONE 0
#define DISASM_NONE Device::NONE
#else
// Flags for access types
#define DISASM_CODE 0
// #define DISASM_GFX 0
// #define DISASM_PGFX 0
#define DISASM_DATA 0
// #define DISASM_ROW 0
#define DISASM_NONE 0
#define DISASM_WRITE 0
#define DISASM_NONE 0
#endif
#include "Settings.hxx"
#include "Vec.hxx"

View File

@ -534,8 +534,8 @@ void Settings::usage() const
<< " Arguments are more fully explained in the manual\n"
<< endl
<< " -dis.resolve <1|0> Attempt to resolve code sections in disassembler\n"
<< " -dis.gfxformat <2|16> Set base to use for displaying GFX sections in\n"
<< " disassembler\n"
<< " -dis.gfxformat <2|16> Set base to use for displaying (P)GFX sections\n"
<< " in disassembler\n"
<< " -dis.showaddr <1|0> Show opcode addresses in disassembler\n"
<< " -dis.relocate <1|0> Relocate calls out of address range in\n"
<< " disassembler\n"

View File

@ -234,7 +234,7 @@ class System : public Serializable
/**
Access and modify the access type flags for the given
address. Note that while any flag can be used, the disassembly
only really acts on CODE/GFX/PGFX/COL/PCOL/BCOL/DATA/ROW.
only really acts on CODE/GFX/PGFX/COL/PCOL/BCOL/AUD/DATA/ROW.
*/
Device::AccessFlags getAccessFlags(uInt16 address) const;
void setAccessFlags(uInt16 address, Device::AccessFlags flags);

View File

@ -530,34 +530,76 @@ bool TIA::poke(uInt16 address, uInt8 value)
break;
case AUDV0:
{
myAudio.channel0().audv(value);
myShadowRegisters[address] = value;
#ifdef DEBUGGER_SUPPORT
uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke();
if(dataAddr)
mySystem->setAccessFlags(dataAddr, Device::AUD);
#endif
break;
}
case AUDV1:
{
myAudio.channel1().audv(value);
myShadowRegisters[address] = value;
#ifdef DEBUGGER_SUPPORT
uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke();
if(dataAddr)
mySystem->setAccessFlags(dataAddr, Device::AUD);
#endif
break;
}
case AUDF0:
{
myAudio.channel0().audf(value);
myShadowRegisters[address] = value;
#ifdef DEBUGGER_SUPPORT
uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke();
if(dataAddr)
mySystem->setAccessFlags(dataAddr, Device::AUD);
#endif
break;
}
case AUDF1:
{
myAudio.channel1().audf(value);
myShadowRegisters[address] = value;
#ifdef DEBUGGER_SUPPORT
uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke();
if(dataAddr)
mySystem->setAccessFlags(dataAddr, Device::AUD);
#endif
break;
}
case AUDC0:
{
myAudio.channel0().audc(value);
myShadowRegisters[address] = value;
#ifdef DEBUGGER_SUPPORT
uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke();
if(dataAddr)
mySystem->setAccessFlags(dataAddr, Device::AUD);
#endif
break;
}
case AUDC1:
{
myAudio.channel1().audc(value);
myShadowRegisters[address] = value;
#ifdef DEBUGGER_SUPPORT
uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke();
if(dataAddr)
mySystem->setAccessFlags(dataAddr, Device::AUD);
#endif
break;
}
case HMOVE:
myDelayQueue.push(HMOVE, value, Delay::hmove);