added TIA access tracking

improved ZP-RAM/Stack tracking
This commit is contained in:
thrust26 2017-09-17 10:35:45 +02:00
parent 2f497fe13c
commit 7d72265088
6 changed files with 112 additions and 32 deletions

View File

@ -970,8 +970,8 @@ string CartDebug::saveDisassembly()
ostringstream buf;
buf << "\n\n;***********************************************************\n"
<< "; Bank " << myConsole.cartridge().getBank();
if (myConsole.cartridge().bankCount() > 0)
buf << " / (0.." << myConsole.cartridge().bankCount() - 1 << ")";
if (myConsole.cartridge().bankCount() > 1)
buf << " / 0.." << myConsole.cartridge().bankCount() - 1;
buf << "\n;***********************************************************\n\n";
// Use specific settings for disassembly output
@ -1084,9 +1084,9 @@ string CartDebug::saveDisassembly()
bool addrUsed = false;
for(uInt16 addr = 0x00; addr <= 0x0F; ++addr)
addrUsed = addrUsed || myReserved.TIARead[addr];
addrUsed = addrUsed || myReserved.TIARead[addr] || (mySystem.getAccessFlags(addr) & WRITE);
for(uInt16 addr = 0x00; addr <= 0x3F; ++addr)
addrUsed = addrUsed || myReserved.TIAWrite[addr];
addrUsed = addrUsed || myReserved.TIAWrite[addr] || (mySystem.getAccessFlags(addr) & DATA);
for(uInt16 addr = 0x00; addr <= 0x17; ++addr)
addrUsed = addrUsed || myReserved.IOReadWrite[addr];
if(addrUsed)
@ -1094,16 +1094,28 @@ string CartDebug::saveDisassembly()
out << "\n;-----------------------------------------------------------\n"
<< "; TIA and IO constants accessed\n"
<< ";-----------------------------------------------------------\n\n";
// TIA read access
for(uInt16 addr = 0x00; addr <= 0x0F; ++addr)
if(myReserved.TIARead[addr] && ourTIAMnemonicR[addr])
out << ALIGN(16) << ourTIAMnemonicR[addr] << "= $"
<< Base::HEX2 << right << addr << " ; (R)\n";
else if (mySystem.getAccessFlags(addr) & DATA)
out << ";" << ALIGN(16-1) << ourTIAMnemonicR[addr] << "= $"
<< Base::HEX2 << right << addr << " ; (Ri)\n";
out << "\n";
// TIA write access
for(uInt16 addr = 0x00; addr <= 0x3F; ++addr)
if(myReserved.TIAWrite[addr] && ourTIAMnemonicW[addr])
out << ALIGN(16) << ourTIAMnemonicW[addr] << "= $"
<< Base::HEX2 << right << addr << " ; (W)\n";
else if (mySystem.getAccessFlags(addr) & WRITE)
out << ";" << ALIGN(16-1) << ourTIAMnemonicW[addr] << "= $"
<< Base::HEX2 << right << addr << " ; (Wi)\n";
out << "\n";
// RIOT IO access
for(uInt16 addr = 0x00; addr <= 0x17; ++addr)
if(myReserved.IOReadWrite[addr] && ourIOMnemonic[addr])
out << ALIGN(16) << ourIOMnemonic[addr] << "= $"
@ -1126,7 +1138,6 @@ string CartDebug::saveDisassembly()
bool ramUsed = (mySystem.getAccessFlags(addr) & (DATA | WRITE));
bool codeUsed = (mySystem.getAccessFlags(addr) & CODE);
bool stackUsed = (mySystem.getAccessFlags(addr|0x100) & (DATA | WRITE));
ramUsed = true;
if (myReserved.ZPRAM[addr - 0x80] &&
myUserLabels.find(addr) == myUserLabels.end()) {
@ -1427,7 +1438,7 @@ void CartDebug::disasmTypeAsString(ostream& buf, uInt8 flags) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* const CartDebug::ourTIAMnemonicR[16] = {
"CXM0P", "CXM1P", "CXP0FB", "CXP1FB", "CXM0FB", "CXM1FB", "CXBLPF", "CXPPMM",
"INPT0", "INPT1", "INPT2", "INPT3", "INPT4", "INPT5", 0, 0
"INPT0", "INPT1", "INPT2", "INPT3", "INPT4", "INPT5", "$1e", "$1f"
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1437,8 +1448,9 @@ const char* const CartDebug::ourTIAMnemonicW[64] = {
"RESP0", "RESP1", "RESM0", "RESM1", "RESBL", "AUDC0", "AUDC1", "AUDF0",
"AUDF1", "AUDV0", "AUDV1", "GRP0", "GRP1", "ENAM0", "ENAM1", "ENABL",
"HMP0", "HMP1", "HMM0", "HMM1", "HMBL", "VDELP0", "VDELP1", "VDELBL",
"RESMP0", "RESMP1", "HMOVE", "HMCLR", "CXCLR", 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
"RESMP0", "RESMP1", "HMOVE", "HMCLR", "CXCLR", "$2d", "$2e", "$2f",
"$30", "$31", "$32", "$33", "$34", "$35", "$36", "$37",
"$38", "$39", "$3a", "$3b", "$3c", "$3d", "$3e", "$3f"
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -63,14 +63,14 @@ class CartDebug : public DebuggerSystem
// debugger, or specified in a Distella cfg file, and are listed in order
// of decreasing hierarchy
//
CODE = 1 << 7, // 0x80, disassemble-able code segments
TCODE = 1 << 6, // 0x40, (tentative) disassemble-able code segments
GFX = 1 << 5, // 0x20, addresses loaded into GRPx registers
PGFX = 1 << 4, // 0x10, addresses loaded into PFx registers
DATA = 1 << 3, // 0x08, addresses loaded into registers other than GRPx / PFx
ROW = 1 << 2, // 0x04, all other addresses
CODE = 1 << 7, // 0x80, disassemble-able code segments
TCODE = 1 << 6, // 0x40, (tentative) disassemble-able code segments
GFX = 1 << 5, // 0x20, addresses loaded into GRPx registers
PGFX = 1 << 4, // 0x10, addresses loaded into PFx registers
DATA = 1 << 3, // 0x08, addresses loaded into registers other than GRPx / PFx
ROW = 1 << 2, // 0x04, all other addresses
// special type for poke()
WRITE = TCODE // 0x40, address written to
WRITE = TCODE // 0x40, address written to
};
struct DisassemblyTag {
DisasmType type;

View File

@ -78,7 +78,9 @@ void M6532::reset()
myConsole.leftController().reset();
myConsole.rightController().reset();
#ifdef DEBUGGER_SUPPORT
createAccessBases();
#endif // DEBUGGER_SUPPORT
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -166,7 +168,6 @@ void M6532::installDelegate(System& system, Device& device)
// (addr & 0x0300) == 0x0000 is ZP RAM (A8 is 0, A9 is 0)
for (uInt16 addr = 0; addr < 0x1000; addr += System::PAGE_SIZE)
if ((addr & 0x0080) == 0x0080) {
//access.codeAccessBase = &myRAMAccessBase[addr & 0x7f];
mySystem->setPageAccess(addr, access);
}
}
@ -456,6 +457,7 @@ uInt32 M6532::timerClocks() const
return uInt32(mySystem->cycles() - mySetTimerCycle);
}
#ifdef DEBUGGER_SUPPORT
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void M6532::createAccessBases()
{
@ -466,6 +468,9 @@ void M6532::createAccessBases()
memset(myStackAccessBase.get(), CartDebug::NONE, STACK_SIZE);
myIOAccessBase = make_unique<uInt8[]>(IO_SIZE);
memset(myIOAccessBase.get(), CartDebug::NONE, IO_SIZE);
myZPAccessDelay = make_unique<uInt8[]>(RAM_SIZE);
memset(myZPAccessDelay.get(), ZP_DELAY, RAM_SIZE);
#else
myRAMAccessBase = myStackAccessBase = myIOAccessBase = nullptr;
#endif
@ -492,19 +497,13 @@ void M6532::setAccessFlags(uInt16 address, uInt8 flags)
myIOAccessBase[address & IO_MASK] |= flags;
else {
// the first access, either by direct RAM or stack access is assumed as initialization
bool initialized = (myStackAccessBase[address & STACK_MASK] & CartDebug::ROW) != 0
|| (myRAMAccessBase[address & RAM_MASK] & CartDebug::ROW) != 0;
if (address & STACK_BIT)
if (!initialized)
myStackAccessBase[address & STACK_MASK] |= CartDebug::ROW;
else
myStackAccessBase[address & STACK_MASK] |= flags;
if (myZPAccessDelay[address & RAM_MASK])
myZPAccessDelay[address & RAM_MASK]--;
else if (address & STACK_BIT)
myStackAccessBase[address & STACK_MASK] |= flags;
else
if (!initialized)
myRAMAccessBase[address & RAM_MASK] |= CartDebug::ROW;
else
myRAMAccessBase[address & RAM_MASK] |= flags;
myRAMAccessBase[address & RAM_MASK] |= flags;
}
}
}
}
#endif // DEBUGGER_SUPPORT

View File

@ -209,16 +209,21 @@ class M6532 : public Device
// Last value written to the timer registers
uInt8 myOutTimer[4];
#ifdef DEBUGGER_SUPPORT
// The arrays containing information about every byte of RIOT
// indicating whether and how (RW) it is used.
BytePtr myRAMAccessBase;
BytePtr myStackAccessBase;
BytePtr myIOAccessBase;
// The array used to skip the first ZP access tracking
BytePtr myZPAccessDelay;
static constexpr uInt16
RAM_SIZE = 0x80, RAM_MASK = RAM_SIZE - 1,
STACK_SIZE = 0x80, STACK_MASK = STACK_SIZE - 1, STACK_BIT = 0x100,
IO_SIZE = 0x20, IO_MASK = IO_SIZE - 1, IO_BIT = 0x200;
STACK_SIZE = RAM_SIZE, STACK_MASK = RAM_MASK, STACK_BIT = 0x100,
IO_SIZE = 0x20, IO_MASK = IO_SIZE - 1, IO_BIT = 0x200,
ZP_DELAY = 1;
#endif // DEBUGGER_SUPPORT
private:
// Following constructors and assignment operators not supported

View File

@ -152,6 +152,10 @@ void TIA::reset()
// Must be done last, after all other items have reset
enableFixedColors(false);
setFixedColorPalette(mySettings.getString("tia.dbgcolors"));
#ifdef DEBUGGER_SUPPORT
createAccessBase();
#endif // DEBUGGER_SUPPORT
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -181,7 +185,7 @@ void TIA::installDelegate(System& system, Device& device)
// That is, all mirrors of ($00 - $3F) in the lower 4K of the 2600
// address space are mapped here
for(uInt16 addr = 0; addr < 0x1000; addr += System::PAGE_SIZE)
if((addr & 0x0080) == 0x0000)
if((addr & TIA_BIT) == 0x0000)
mySystem->setPageAccess(addr, access);
mySystem->m6502().setOnHaltCallback(
@ -1584,3 +1588,40 @@ uInt8 TIA::collCXBLPF() const
{
return (myCollisionMask & CollisionMask::ball & CollisionMask::playfield) ? 0x80 : 0;
}
#ifdef DEBUGGER_SUPPORT
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::createAccessBase()
{
#ifdef DEBUGGER_SUPPORT
myAccessBase = make_unique<uInt8[]>(TIA_SIZE);
memset(myAccessBase.get(), CartDebug::NONE, TIA_SIZE);
myAccessDelay = make_unique<uInt8[]>(TIA_SIZE);
memset(myAccessDelay.get(), TIA_DELAY, TIA_SIZE);
#else
myAccessBase = nullptr;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 TIA::getAccessFlags(uInt16 address) const
{
return myAccessBase[address & TIA_MASK];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::setAccessFlags(uInt16 address, uInt8 flags)
{
// ignore none flag
if (flags != CartDebug::NONE) {
if (flags == CartDebug::WRITE) {
// the first two write accesses are assumed as initialization
if (myAccessDelay[address & TIA_MASK])
myAccessDelay[address & TIA_MASK]--;
else
myAccessBase[address & TIA_MASK] |= flags;
} else
myAccessBase[address & TIA_READ_MASK] |= flags;
}
}
#endif // DEBUGGER_SUPPORT

View File

@ -540,6 +540,18 @@ class TIA : public Device
uInt8 collCXPPMM() const;
uInt8 collCXBLPF() const;
#ifdef DEBUGGER_SUPPORT
void createAccessBase();
/**
Query/change the given address type to use the given disassembly flags
@param address The address to modify
@param flags A bitfield of DisasmType directives for the given address
*/
uInt8 getAccessFlags(uInt16 address) const override;
void setAccessFlags(uInt16 address, uInt8 flags) override;
#endif // DEBUGGER_SUPPORT
private:
Console& myConsole;
@ -711,6 +723,17 @@ class TIA : public Device
*/
uInt64 myCyclesAtFrameStart;
#ifdef DEBUGGER_SUPPORT
// The arrays containing information about every byte of TIA
// indicating whether and how (RW) it is used.
BytePtr myAccessBase;
// The array used to skip the first two TIA access trackings
BytePtr myAccessDelay;
static constexpr uInt16
TIA_SIZE = 0x40, TIA_MASK = TIA_SIZE - 1, TIA_READ_MASK = 0x0f, TIA_BIT = 0x080, TIA_DELAY = 2;
#endif // DEBUGGER_SUPPORT
private:
TIA() = delete;
TIA(const TIA&) = delete;