OK, this is the first pass at a huge reorganization of the debugger

classes.  First off, the distella code has been integrated into a
DiStella class.  This code isn't yet tied to the debugger, but it does
at least compile and generate valid output.

The RamDebug class has been replaced by a CartDebug class, which
takes responsibility for the previous RamDebug stuff as well as 
things related to Cart address space (read from write ports,
disassembly, etc).

Fixed E7 bankswitching when reading from the write port in the upper
256byte area.

Fixed 'read from write port functionality' in general for all carts
that supported it previously.  Basically, if _rwport is enabled, the
address is checked to be an actual read (vs. one that's part of a
normal write cycle), *and* it's actually an illegal access (each
cart/bankswitch type now provides a hint to indicate this condition).

Still TODO is clean up the rework, properly integrate DiStella, and
fix labels and defines (which seem to be completely broken).


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1922 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2010-01-17 16:48:45 +00:00
parent e234139a3c
commit 28114a8c51
40 changed files with 3293 additions and 1944 deletions

1062
src/debugger/CartDebug.cxx Normal file

File diff suppressed because it is too large Load Diff

232
src/debugger/CartDebug.hxx Normal file
View File

@ -0,0 +1,232 @@
//============================================================================
//
// 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
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2009 by Bradford W. Mott and the Stella team
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#ifndef CART_DEBUG_HXX
#define CART_DEBUG_HXX
class System;
#include "bspf.hxx"
#include "Array.hxx"
#include "Cart.hxx"
#include "DebuggerSystem.hxx"
// pointer types for CartDebug instance methods
typedef int (CartDebug::*CARTDEBUG_INT_METHOD)();
// call the pointed-to method on the (global) CPU debugger object.
#define CALL_CARTDEBUG_METHOD(method) ( ( Debugger::debugger().cartDebug().*method)() )
class CartState : public DebuggerState
{
public:
IntArray ram; // The actual data values
IntArray rport; // Address for reading from RAM
IntArray wport; // Address for writing to RAM
};
class CartDebug : public DebuggerSystem
{
public:
struct DisassemblyTag {
int address;
string disasm;
string bytes;
};
typedef Common::Array<DisassemblyTag> DisassemblyList;
public:
CartDebug(Debugger& dbg, Console& console, const RamAreaList& areas);
const DebuggerState& getState();
const DebuggerState& getOldState() { return myOldState; }
void saveOldState();
string toString();
// The following assume that the given addresses are using the
// correct read/write port ranges; no checking will be done to
// confirm this.
uInt8 read(uInt16 addr);
void write(uInt16 addr, uInt8 value);
// Return the address at which an invalid read was performed in a
// write port area.
int readFromWritePort();
// Indicate that a read from write port has occurred.
void triggerReadFromWritePort(uInt16 addr) { myRWPortAddress = addr; }
/**
Let the Cart debugger subsystem treat this area as addressable memory.
@param start The beginning of the RAM area (0x0000 - 0x2000)
@param size Total number of bytes of area
@param roffset Offset to use when reading from RAM (read port)
@param woffset Offset to use when writing to RAM (write port)
*/
void addRamArea(uInt16 start, uInt16 size, uInt16 roffset, uInt16 woffset);
////////////////////////////////////////
/**
Disassemble from the starting address the specified number of lines
and place result in a string.
*/
const string& disassemble(int start, int lines);
/**
Disassemble from the starting address to the ending address
and place addresses, bytes and data in given arrays.
*/
void disassemble(IntArray& addr, StringList& addrLabel,
StringList& bytes, StringList& data,
int start, int end);
int getBank();
int bankCount();
string getCartType();
////////////////////////////////////////
/**
Add a label and associated address
*/
void addLabel(const string& label, uInt16 address);
/**
Remove the given label and its associated address
*/
bool removeLabel(const string& label);
/**
Accessor methods for labels and addresses
The mapping from address to label can be one-to-many (ie, an
address can have different labels depending on its context, and
whether its being read or written; if isRead is true, the context
is a read, else it's a write
If places is not -1 and a label hasn't been defined, return a
formatted hexidecimal address
*/
const string& getLabel(uInt16 addr, bool isRead, int places = -1) const;
int getAddress(const string& label) const;
/**
Load user equates from the given symbol file (generated by DASM)
*/
string loadSymbolFile(const string& file);
/**
Save user equates into a symbol file similar to that generated by DASM
*/
bool saveSymbolFile(const string& file);
/**
Methods used by the command parser for tab-completion
*/
int countCompletions(const char *in);
const string& getCompletions() const { return myCompletions; }
const string& getCompletionPrefix() const { return myCompPrefix; }
private:
int disassemble(int address, string& result);
private:
enum equate_t {
EQF_READ = 1 << 0, // address can be read from
EQF_WRITE = 1 << 1, // address can be written to
EQF_RW = EQF_READ | EQF_WRITE // address can be both read and written
};
enum address_t {
ADDR_TIA = 1 << 0,
ADDR_RAM = 1 << 1,
ADDR_RIOT = 1 << 2,
ADDR_ROM = 1 << 3
};
struct Equate {
string label;
uInt16 address;
equate_t flags;
};
typedef map<uInt16, Equate> AddrToLabel;
typedef map<string, Equate> LabelToAddr;
private:
// Extract labels and values from the given character stream
string extractLabel(char *c) const;
int extractValue(char *c) const;
// Count completions for the given mapping
int countCompletions(const char *in, LabelToAddr& addresses);
private:
CartState myState;
CartState myOldState;
DisassemblyList myDisassembly;
LabelToAddr mySystemAddresses;
AddrToLabel mySystemReadLabels; // labels used in a read context
AddrToLabel mySystemWriteLabels; // labels used in a write context
LabelToAddr myUserAddresses;
AddrToLabel myUserLabels;
RamAreaList myRamAreas;
string myCompletions;
string myCompPrefix;
uInt16 myRWPortAddress;
enum { kSystemEquateSize = 158 };
static const Equate ourSystemEquates[kSystemEquateSize];
//////////////////////////////////////////////
/**
Enumeration of the 6502 addressing modes
*/
enum AddressingMode
{
Absolute, AbsoluteX, AbsoluteY, Immediate, Implied,
Indirect, IndirectX, IndirectY, Invalid, Relative,
Zero, ZeroX, ZeroY
};
/**
Enumeration of the 6502 access modes
*/
enum AccessMode
{
Read, Write, None
};
/// Addressing mode for each of the 256 opcodes
/// This specifies how the opcode argument is addressed
static AddressingMode AddressModeTable[256];
/// Access mode for each of the 256 opcodes
/// This specifies how the opcode will access its argument
static AccessMode AccessModeTable[256];
/// Table of instruction mnemonics
static const char* InstructionMnemonicTable[256];
//////////////////////////////////////////////
};
#endif

View File

@ -19,8 +19,8 @@
#include <sstream>
#include "Array.hxx"
#include "EquateList.hxx"
#include "M6502.hxx"
#include "CartDebug.hxx"
#include "TIADebug.hxx"
#include "CpuDebug.hxx"
@ -113,131 +113,10 @@ string CpuDebug::toString()
result += buf;
result += "\n ";
result += myDebugger.disassemble(state.PC, 1);
result += myDebugger.cartDebug().disassemble(state.PC, 1);
return result;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int CpuDebug::disassemble(int address, string& result, EquateList& list)
{
ostringstream buf;
int count = 0;
int opcode = mySystem.peek(address);
// Are we looking at a read or write operation?
// It will determine what type of label to use
bool isRead = (M6502::AccessModeTable[opcode] == M6502::Read);
switch(M6502::AddressModeTable[opcode])
{
case M6502::Absolute:
buf << M6502::InstructionMnemonicTable[opcode] << " "
<< list.getLabel(dpeek(mySystem, address + 1), isRead, 4) << " ; "
<< M6502::InstructionCycleTable[opcode];
count = 3;
break;
case M6502::AbsoluteX:
buf << M6502::InstructionMnemonicTable[opcode] << " "
<< list.getLabel(dpeek(mySystem, address + 1), isRead, 4) << ",x ; "
<< M6502::InstructionCycleTable[opcode];
count = 3;
break;
case M6502::AbsoluteY:
buf << M6502::InstructionMnemonicTable[opcode] << " "
<< list.getLabel(dpeek(mySystem, address + 1), isRead, 4) << ",y ; "
<< M6502::InstructionCycleTable[opcode];
count = 3;
break;
case M6502::Immediate:
buf << M6502::InstructionMnemonicTable[opcode] << " #$"
<< hex << setw(2) << setfill('0') << (int) mySystem.peek(address + 1) << " ; "
<< dec << M6502::InstructionCycleTable[opcode];
count = 2;
break;
case M6502::Implied:
buf << M6502::InstructionMnemonicTable[opcode] << " ; "
<< M6502::InstructionCycleTable[opcode];
count = 1;
break;
case M6502::Indirect:
buf << M6502::InstructionMnemonicTable[opcode] << " ("
<< list.getLabel(dpeek(mySystem, address + 1), isRead, 4) << ") ; "
<< M6502::InstructionCycleTable[opcode];
count = 3;
break;
case M6502::IndirectX:
buf << M6502::InstructionMnemonicTable[opcode] << " ("
<< list.getLabel(mySystem.peek(address + 1), isRead, 2) << ",x) ; "
<< M6502::InstructionCycleTable[opcode];
count = 2;
break;
case M6502::IndirectY:
buf << M6502::InstructionMnemonicTable[opcode] << " ("
<< list.getLabel(mySystem.peek(address + 1), isRead, 2) << "),y ; "
<< M6502::InstructionCycleTable[opcode];
count = 2;
break;
case M6502::Relative:
buf << M6502::InstructionMnemonicTable[opcode] << " "
<< list.getLabel(address + 2 + ((Int16)(Int8)mySystem.peek(address + 1)), isRead, 4)
<< " ; " << M6502::InstructionCycleTable[opcode];
count = 2;
break;
case M6502::Zero:
buf << M6502::InstructionMnemonicTable[opcode] << " "
<< list.getLabel(mySystem.peek(address + 1), isRead, 2) << " ; "
<< M6502::InstructionCycleTable[opcode];
count = 2;
break;
case M6502::ZeroX:
buf << M6502::InstructionMnemonicTable[opcode] << " "
<< list.getLabel(mySystem.peek(address + 1), isRead, 2) << ",x ; "
<< M6502::InstructionCycleTable[opcode];
count = 2;
break;
case M6502::ZeroY:
buf << M6502::InstructionMnemonicTable[opcode] << " "
<< list.getLabel(mySystem.peek(address + 1), isRead, 2) << ",y ; "
<< M6502::InstructionCycleTable[opcode];
count = 2;
break;
default:
buf << "dc $" << hex << setw(2) << setfill('0') << (int) opcode << " ; "
<< dec << M6502::InstructionCycleTable[opcode];
count = 1;
break;
}
result = buf.str();
return count;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// This doesn't really belong here (banks are Cart properties), but it
// makes like much easier for the expression parser.
int CpuDebug::getBank()
{
return Debugger::debugger().getBank();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int CpuDebug::dPeek(int address)
{
return dpeek(mySystem, address);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CpuDebug::setPC(int pc)
{

View File

@ -49,20 +49,16 @@ class CpuDebug : public DebuggerSystem
void saveOldState();
string toString();
// I know, we ain't supposed to do this...
// I know, we ain't supposed to do this...
M6502& m6502() { return mySystem.m6502(); }
int disassemble(int address, string& result, EquateList& list);
int dPeek(int address);
int getBank();
int pc() { return mySystem.m6502().PC; }
int sp() { return mySystem.m6502().SP; }
int a() { return mySystem.m6502().A; }
int x() { return mySystem.m6502().X; }
int y() { return mySystem.m6502().Y; }
// these return int, not boolean!
// These return int, not boolean!
int n() { return mySystem.m6502().N; }
int v() { return mySystem.m6502().V; }
int b() { return mySystem.m6502().B; }
@ -94,12 +90,6 @@ class CpuDebug : public DebuggerSystem
void toggleZ();
void toggleC();
private:
static int dpeek(System& system, int address)
{
return system.peek(address) | (system.peek(address + 1) << 8);
}
private:
CpuState myState;
CpuState myOldState;

View File

@ -36,9 +36,8 @@
#include "M6502.hxx"
#include "Cart.hxx"
#include "EquateList.hxx"
#include "CartDebug.hxx"
#include "CpuDebug.hxx"
#include "RamDebug.hxx"
#include "RiotDebug.hxx"
#include "TIADebug.hxx"
@ -95,15 +94,14 @@ Debugger::Debugger(OSystem* osystem)
myConsole(NULL),
mySystem(NULL),
myParser(NULL),
myCartDebug(NULL),
myCpuDebug(NULL),
myRamDebug(NULL),
myRiotDebug(NULL),
myTiaDebug(NULL),
myTiaInfo(NULL),
myTiaOutput(NULL),
myTiaZoom(NULL),
myRom(NULL),
myEquateList(NULL),
myBreakPoints(NULL),
myReadTraps(NULL),
myWriteTraps(NULL),
@ -138,12 +136,11 @@ Debugger::~Debugger()
{
delete myParser;
delete myCartDebug;
delete myCpuDebug;
delete myRamDebug;
delete myRiotDebug;
delete myTiaDebug;
delete myEquateList;
delete myBreakPoints;
delete myReadTraps;
delete myWriteTraps;
@ -193,12 +190,11 @@ void Debugger::setConsole(Console* console)
delete myCpuDebug;
myCpuDebug = new CpuDebug(*this, *myConsole);
delete myRamDebug;
myRamDebug = new RamDebug(*this, *myConsole);
delete myCartDebug;
// Register any RAM areas in the Cartridge
// Zero-page RAM is automatically recognized by RamDebug
myRamDebug->addRamArea(myConsole->cartridge().ramAreas());
// Zero-page RAM is automatically recognized by CartDebug
myCartDebug = new CartDebug(*this, *myConsole, myConsole->cartridge().ramAreas());
myCartDebug->loadSymbolFile(myOSystem->romFile());
delete myRiotDebug;
myRiotDebug = new RiotDebug(*this, *myConsole);
@ -206,14 +202,12 @@ void Debugger::setConsole(Console* console)
delete myTiaDebug;
myTiaDebug = new TIADebug(*this, *myConsole);
// Initialize equates and breakpoints to known state
delete myEquateList;
myEquateList = new EquateList();
// Initialize breakpoints to known state
clearAllBreakPoints();
clearAllTraps();
autoLoadSymbols(myOSystem->romFile());
loadListFile();
// FIXME - these will probably be removed
// loadListFile();
// Make sure cart RAM is added before this is called,
// otherwise the debugger state won't know about it
@ -243,21 +237,7 @@ void Debugger::quit()
myOSystem->eventHandler().leaveDebugMode();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::autoLoadSymbols(string fileName)
{
string file = fileName;
string::size_type pos;
if( (pos = file.find_last_of('.')) != string::npos )
file.replace(pos, file.size(), ".sym");
else
file += ".sym";
string ret = myEquateList->loadFile(file);
// cerr << "loading syms from file " << file << ": " << ret << endl;
}
#if 0 // FIXME - remove this
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Debugger::loadListFile(string f)
{
@ -335,6 +315,7 @@ string Debugger::getSourceLines(int addr) const
else
return "";
}
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::autoExec()
@ -431,8 +412,7 @@ const string Debugger::invIfChanged(int reg, int oldReg)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::reset()
{
int pc = myCpuDebug->dPeek(0xfffc);
myCpuDebug->setPC(pc);
myCpuDebug->setPC(dpeek(0xfffc));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -579,61 +559,6 @@ int Debugger::cycles()
return mySystem->cycles();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const string& Debugger::disassemble(int start, int lines)
{
static string result;
ostringstream buffer;
string cpubuf;
do {
buffer << myEquateList->getLabel(start, true, 4) << ": ";
int count = myCpuDebug->disassemble(start, cpubuf, *myEquateList);
for(int i = 0; i < count; i++)
buffer << hex << setw(2) << setfill('0') << peek(start++) << dec;
if(count < 3) buffer << " ";
if(count < 2) buffer << " ";
buffer << " " << cpubuf << "\n";
} while(--lines > 0 && start <= 0xffff);
result = buffer.str();
return result;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::disassemble(IntArray& addr, StringList& addrLabel,
StringList& bytes, StringList& data,
int start, int end)
{
if(start < 0x80 || end > 0xffff)
return;
string cpubuf, tmp;
char buf[255];
do
{
addrLabel.push_back(myEquateList->getLabel(start, true, 4) + ":");
addr.push_back(start);
cpubuf = "";
int count = myCpuDebug->disassemble(start, cpubuf, *myEquateList);
tmp = "";
for(int i=0; i<count; i++) {
sprintf(buf, "%02x ", peek(start++));
tmp += buf;
}
bytes.push_back(tmp);
data.push_back(cpubuf);
}
while(start <= end);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::nextScanline(int lines)
{
@ -686,30 +611,12 @@ void Debugger::clearAllTraps()
mySystem->m6502().setTraps(NULL, NULL);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Debugger::peek(int addr)
{
return mySystem->peek(addr);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Debugger::dpeek(int addr)
{
return mySystem->peek(addr) | (mySystem->peek(addr+1) << 8);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Debugger::showWatches()
{
return myParser->showWatches();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::addLabel(string label, int address)
{
myEquateList->addEquate(label, address);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::reloadROM()
{
@ -729,24 +636,6 @@ bool Debugger::setBank(int bank)
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Debugger::getBank()
{
return myConsole->cartridge().bank();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Debugger::bankCount()
{
return myConsole->cartridge().bankCount();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Debugger::getCartType()
{
return myConsole->cartridge().name();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Debugger::patchROM(int addr, int value)
{
@ -756,8 +645,8 @@ bool Debugger::patchROM(int addr, int value)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::saveOldState(bool addrewind)
{
myCartDebug->saveOldState();
myCpuDebug->saveOldState();
myRamDebug->saveOldState();
myRiotDebug->saveOldState();
myTiaDebug->saveOldState();

View File

@ -22,8 +22,8 @@
class OSystem;
class Console;
class System;
class CartDebug;
class CpuDebug;
class RamDebug;
class RiotDebug;
class TIADebug;
class TiaInfoWidget;
@ -40,7 +40,6 @@ class Serializer;
#include "DialogContainer.hxx"
#include "M6502.hxx"
#include "DebuggerParser.hxx"
#include "EquateList.hxx"
#include "PackedBitArray.hxx"
#include "PromptWidget.hxx"
#include "Rect.hxx"
@ -136,9 +135,9 @@ class Debugger : public DialogContainer
CpuDebug& cpuDebug() const { return *myCpuDebug; }
/**
The debugger subsystem responsible for all RAM state
The debugger subsystem responsible for all Cart RAM/ROM state
*/
RamDebug& ramDebug() const { return *myRamDebug; }
CartDebug& cartDebug() const { return *myCartDebug; }
/**
The debugger subsystem responsible for all RIOT state
@ -150,11 +149,6 @@ class Debugger : public DialogContainer
*/
TIADebug& tiaDebug() const { return *myTiaDebug; }
/**
List of English-like aliases for 6502 opcodes and operands.
*/
EquateList& equates() const { return *myEquateList; }
DebuggerParser& parser() const { return *myParser; }
PackedBitArray& breakpoints() const { return *myBreakPoints; }
PackedBitArray& readtraps() const { return *myReadTraps; }
@ -170,20 +164,6 @@ class Debugger : public DialogContainer
*/
int cycles();
/**
Disassemble from the starting address the specified number of lines
and place result in a string.
*/
const string& disassemble(int start, int lines);
/**
Disassemble from the starting address to the ending address
and place addresses, bytes and data in given arrays.
*/
void disassemble(IntArray& addr, StringList& addrLabel,
StringList& bytes, StringList& data,
int start, int end);
void autoExec();
string showWatches();
@ -292,17 +272,11 @@ class Debugger : public DialogContainer
GUI::Rect getTabBounds() const;
/* These are now exposed so Expressions can use them. */
int peek(int addr);
int dpeek(int addr);
int getBank();
int bankCount();
int peek(int addr) { return mySystem->peek(addr); }
int dpeek(int addr) { return mySystem->peek(addr) | (mySystem->peek(addr+1) << 8); }
void setBreakPoint(int bp, bool set);
string loadListFile(string f = "");
string getSourceLines(int addr) const;
bool haveListFile() const { return sourceLines.size() > 0; }
bool saveROM(const string& filename) const;
bool setBank(int bank);
@ -357,26 +331,20 @@ class Debugger : public DialogContainer
const string setRAM(IntArray& args);
void reset();
void autoLoadSymbols(string file);
void clearAllBreakPoints();
PromptWidget *prompt() { return myPrompt; }
void addLabel(string label, int address);
string getCartType();
void saveState(int state);
void loadState(int state);
private:
typedef multimap<string,string> ListFile;
typedef ListFile::const_iterator ListIter;
Console* myConsole;
System* mySystem;
DebuggerParser* myParser;
CartDebug* myCartDebug;
CpuDebug* myCpuDebug;
RamDebug* myRamDebug;
RiotDebug* myRiotDebug;
TIADebug* myTiaDebug;
@ -386,14 +354,11 @@ class Debugger : public DialogContainer
RomWidget* myRom;
EditTextWidget* myMessage;
EquateList* myEquateList;
PackedBitArray* myBreakPoints;
PackedBitArray* myReadTraps;
PackedBitArray* myWriteTraps;
PromptWidget* myPrompt;
ListFile sourceLines;
static Debugger* myStaticDebugger;
FunctionMap functions;

View File

@ -20,8 +20,8 @@
#define DEBUGGER_EXPRESSIONS_HXX
#include "bspf.hxx"
#include "CartDebug.hxx"
#include "CpuDebug.hxx"
#include "RamDebug.hxx"
#include "TIADebug.hxx"
#include "Debugger.hxx"
#include "Expression.hxx"
@ -124,7 +124,7 @@ class EquateExpression : public Expression
{
public:
EquateExpression(const string& label) : Expression(0, 0), myLabel(label) {}
uInt16 evaluate() { return Debugger::debugger().equates().getAddress(myLabel); }
uInt16 evaluate() { return Debugger::debugger().cartDebug().getAddress(myLabel); }
private:
string myLabel;
@ -260,14 +260,14 @@ class PlusExpression : public Expression
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class RamMethodExpression : public Expression
class CartMethodExpression : public Expression
{
public:
RamMethodExpression(RAMDEBUG_INT_METHOD method) : Expression(0, 0), myMethod(method) {}
uInt16 evaluate() { return CALL_RAMDEBUG_METHOD(myMethod); }
CartMethodExpression(CARTDEBUG_INT_METHOD method) : Expression(0, 0), myMethod(method) {}
uInt16 evaluate() { return CALL_CARTDEBUG_METHOD(myMethod); }
private:
RAMDEBUG_INT_METHOD myMethod;
CARTDEBUG_INT_METHOD myMethod;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -22,8 +22,8 @@
#include "Dialog.hxx"
#include "Debugger.hxx"
#include "CartDebug.hxx"
#include "CpuDebug.hxx"
#include "RamDebug.hxx"
#include "RiotDebug.hxx"
#include "TIADebug.hxx"
#include "DebuggerParser.hxx"
@ -266,8 +266,8 @@ int DebuggerParser::decipher_arg(const string &str)
else if(arg == "s") result = state.SP;
else if(arg == "pc" || arg == ".") result = state.PC;
else { // Not a special, must be a regular arg: check for label first
const char *a = arg.c_str();
result = debugger->equates().getAddress(arg);
const char* a = arg.c_str();
result = debugger->cartDebug().getAddress(arg);
if(result < 0) { // if not label, must be a number
if(bin) { // treat as binary
@ -562,7 +562,7 @@ string DebuggerParser::eval()
string ret;
for(int i=0; i<argCount; i++) {
// TODO - technically, we should determine if the label is read or write
string label = debugger->equates().getLabel(args[i], true);
const string& label = debugger->cartDebug().getLabel(args[i], true);
if(label != "") {
ret += label;
ret += ": ";
@ -602,7 +602,7 @@ string DebuggerParser::trapStatus(int addr)
result += " none ";
// TODO - technically, we should determine if the label is read or write
const string& l = debugger->equates().getLabel(addr, true);
const string& l = debugger->cartDebug().getLabel(addr, true);
if(l != "") {
result += " (";
result += l;
@ -668,14 +668,14 @@ void DebuggerParser::executeA()
// "bank"
void DebuggerParser::executeBank()
{
int banks = debugger->bankCount();
int banks = debugger->cartDebug().bankCount();
if(argCount == 0) {
commandResult += debugger->getCartType();
commandResult += debugger->cartDebug().getCartType();
commandResult += ": ";
if(banks < 2)
commandResult += red("bankswitching not supported by this cartridge");
else {
commandResult += debugger->valueToString(debugger->getBank());
commandResult += debugger->valueToString(debugger->cartDebug().getBank());
commandResult += "/";
commandResult += debugger->valueToString(banks);
}
@ -844,7 +844,7 @@ void DebuggerParser::executeD()
void DebuggerParser::executeDefine()
{
// TODO: check if label already defined?
debugger->addLabel(argStrings[0], args[1]);
debugger->cartDebug().addLabel(argStrings[0], args[1]);
debugger->myRom->invalidate();
commandResult = "label " + argStrings[0] + " defined as " + debugger->valueToString(args[1]);
}
@ -888,7 +888,7 @@ void DebuggerParser::executeDisasm()
return;
}
commandResult = debugger->disassemble(start, lines);
commandResult = debugger->cartDebug().disassemble(start, lines);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -971,17 +971,6 @@ void DebuggerParser::executeFunction()
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "list"
void DebuggerParser::executeList()
{
if(!debugger->haveListFile())
commandResult = "no list file loaded (try \"loadlist file.lst\")";
for(int i=args[0] - 2; i<args[0] + 3; i++)
commandResult += debugger->getSourceLines(i);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "listbreaks"
void DebuggerParser::executeListbreaks()
@ -993,7 +982,7 @@ void DebuggerParser::executeListbreaks()
{
if(debugger->breakpoints().isSet(i))
{
buf << debugger->equates().getLabel(i, true, 4) << " ";
buf << debugger->cartDebug().getLabel(i, true, 4) << " ";
if(! (++count % 8) ) buf << "\n";
}
}
@ -1061,18 +1050,11 @@ void DebuggerParser::executeLoadstate()
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "loadlist"
void DebuggerParser::executeLoadlist()
{
commandResult = debugger->loadListFile(argStrings[0]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "loadsym"
void DebuggerParser::executeLoadsym()
{
commandResult = debugger->equates().loadFile(argStrings[0]);
commandResult = debugger->cartDebug().loadSymbolFile(argStrings[0]);
debugger->myRom->invalidate();
}
@ -1105,7 +1087,7 @@ void DebuggerParser::executePrint()
void DebuggerParser::executeRam()
{
if(argCount == 0)
commandResult = debugger->ramDebug().toString();
commandResult = debugger->cartDebug().toString();
else
commandResult = debugger->setRAM(args);
}
@ -1178,7 +1160,7 @@ void DebuggerParser::executeRunTo()
do {
cycles += debugger->step();
string next = debugger->disassemble(debugger->cpuDebug().pc(), 1);
string next = debugger->cartDebug().disassemble(debugger->cpuDebug().pc(), 1);
done = (next.find(argStrings[0]) != string::npos);
++count;
} while(!done && count < 10000);
@ -1246,7 +1228,7 @@ void DebuggerParser::executeSavestate()
// "savesym"
void DebuggerParser::executeSavesym()
{
if(debugger->equates().saveFile(argStrings[0]))
if(debugger->cartDebug().saveSymbolFile(argStrings[0]))
commandResult = "saved symbols to file " + argStrings[0];
else
commandResult = red("I/O error");
@ -1321,7 +1303,7 @@ void DebuggerParser::executeTrapwrite()
// "undef"
void DebuggerParser::executeUndef()
{
if(debugger->equates().removeEquate(argStrings[0]))
if(debugger->cartDebug().removeLabel(argStrings[0]))
{
debugger->myRom->invalidate();
commandResult = argStrings[0] + " now undefined";
@ -1565,15 +1547,6 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
&DebuggerParser::executeHelp
},
{
"list",
"List source (if loaded with loadlist)",
true,
false,
{ kARG_WORD, kARG_END_ARGS },
&DebuggerParser::executeList
},
{
"listbreaks",
"List breakpoints",
@ -1601,15 +1574,6 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
&DebuggerParser::executeListwatches
},
{
"loadlist",
"Load DASM listing file",
true,
true,
{ kARG_FILE, kARG_END_ARGS },
&DebuggerParser::executeLoadlist
},
{
"loadstate",
"Load emulator state (0-9)",

View File

@ -81,7 +81,7 @@ class DebuggerParser
private:
enum {
kNumCommands = 58,
kNumCommands = 56,
kMAX_ARG_TYPES = 10 // TODO: put in separate header file Command.hxx
};
@ -157,11 +157,9 @@ class DebuggerParser
void executeFrame();
void executeFunction();
void executeHelp();
void executeList();
void executeListbreaks();
void executeListtraps();
void executeListwatches();
void executeLoadlist();
void executeLoadstate();
void executeLoadsym();
void executeN();

1360
src/debugger/DiStella.cxx Normal file

File diff suppressed because it is too large Load Diff

146
src/debugger/DiStella.hxx Normal file
View File

@ -0,0 +1,146 @@
//============================================================================
//
// 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
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2009 by Bradford W. Mott and the Stella team
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#ifndef DISTELLA_HXX
#define DISTELLA_HXX
#include <queue>
#include "Array.hxx"
#include "bspf.hxx"
//#include "CartDebug.hxx"
//// The following will go in CartDebug
struct DisassemblyTag {
int address;
string disasm;
string bytes;
};
typedef Common::Array<DisassemblyTag> DisassemblyList;
//////////////////////////////////////////////////////////////
class DiStella
{
public:
DiStella();
~DiStella();
public:
int disassemble(DisassemblyList& list, const char* datafile);
private:
struct resource {
uInt16 start;
uInt16 load;
uInt32 length;
uInt16 end;
int disp_data;
} app_data;
/* Memory */
uInt8* mem;
uInt8* labels;
uInt8 reserved[64];
uInt8 ioresrvd[24];
uInt8 pokresvd[16];
char linebuff[256],nextline[256];
FILE* cfg;
uInt32 pc, pcbeg, pcend, offset, start_adr;
int cflag, dflag, lineno, charcnt;
queue<uInt16> myAddressQueue;
private:
// Marked bits
// This is a reference sheet of bits that can be set for a given address, which
// are stored in the labels[] array.
enum MarkType {
REFERENCED = 1 << 0, /* code somewhere in the program references it, i.e. LDA $F372 referenced $F372 */
VALID_ENTRY = 1 << 1, /* addresses that can have a label placed in front of it. A good counterexample
would be "FF00: LDA $FE00"; $FF01 would be in the middle of a multi-byte
instruction, and therefore cannot be labelled. */
DATA = 1 << 2,
GFX = 1 << 3,
REACHABLE = 1 << 4 /* disassemble-able code segments */
};
/**
Enumeration of the 6502 addressing modes
*/
enum AddressingMode
{
IMPLIED, ACCUMULATOR, IMMEDIATE,
ZERO_PAGE, ZERO_PAGE_X, ZERO_PAGE_Y,
ABSOLUTE, ABSOLUTE_X, ABSOLUTE_Y,
ABS_INDIRECT, INDIRECT_X, INDIRECT_Y,
RELATIVE, ASS_CODE
};
/**
Enumeration of the 6502 access modes
*/
enum AccessMode
{
M_NONE, M_AC, M_XR, M_YR, M_SP, M_SR, M_PC, M_IMM, M_ZERO, M_ZERX, M_ZERY,
M_ABS, M_ABSX, M_ABSY, M_AIND, M_INDX, M_INDY, M_REL, M_FC, M_FD, M_FI,
M_FV, M_ADDR, M_,
M_ACIM, /* Source: AC & IMMED (bus collision) */
M_ANXR, /* Source: AC & XR (bus collision) */
M_AXIM, /* Source: (AC | #EE) & XR & IMMED (bus collision) */
M_ACNC, /* Dest: M_AC and Carry = Negative */
M_ACXR, /* Dest: M_AC, M_XR */
M_SABY, /* Source: (ABS_Y & SP) (bus collision) */
M_ACXS, /* Dest: M_AC, M_XR, M_SP */
M_STH0, /* Dest: Store (src & Addr_Hi+1) to (Addr +0x100) */
M_STH1,
M_STH2,
M_STH3
};
uInt32 filesize(FILE *stream);
uInt32 read_adr();
int file_load(const char* file);
int load_config(const char* file);
void check_range(uInt32 beg, uInt32 end);
void disasm(uInt32 distart, int pass, DisassemblyList& list);
int mark(uInt32 address, MarkType bit);
int check_bit(uInt8 bitflags, int i);
void showgfx(uInt8 c);
struct Instruction_tag {
const char* mnemonic;
AddressingMode addr_mode;
AccessMode source;
AccessMode destination;
uInt8 cycles;
};
static const Instruction_tag ourLookup[256];
/// Table of instruction mnemonics
static const char* ourTIAMnemonic[62];
static const char* ourIOMnemonic[24];
static const int ourCLength[14];
};
#endif

View File

@ -1,542 +0,0 @@
//============================================================================
//
// 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
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2010 by Bradford W. Mott and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#include <fstream>
#include <sstream>
#include "bspf.hxx"
#include "Debugger.hxx"
#include "EquateList.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EquateList::EquateList()
{
for(int i = 0; i < kSystemEquateSize; i++)
{
const Equate& e = ourSystemEquates[i];
mySystemAddresses.insert(make_pair(e.label, e));
// Certain hardcoded addresses have different labels in read and write
// mode; we use separate lists for those
if(e.flags & EQF_READ)
mySystemReadLabels.insert(make_pair(e.address, e));
if(e.flags & EQF_WRITE)
mySystemWriteLabels.insert(make_pair(e.address, e));
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EquateList::~EquateList()
{
mySystemAddresses.clear();
mySystemReadLabels.clear();
mySystemWriteLabels.clear();
myUserAddresses.clear();
myUserLabels.clear();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EquateList::addEquate(const string& label, uInt16 address)
{
// First check if this already exists as a hard-coded equate
LabelToAddr::const_iterator iter = mySystemAddresses.find(label);
if(iter != mySystemAddresses.end() && iter->second.address == address)
return;
// Create a new user equate, and determine if its RAM or ROM
// For now, these are the only types we care about
// Technically, addresses above 0x1000 are ROM and are read-only
// However, somes ROMs have dedicated RAM mapped to those addresses
// as well, and we don't yet have an infrastructure to determine that,
// so the entire region is marked as read-write
equate_t flags = EQF_READ;
#if 0
if(address >= 0x80 && address <= 0xff)
flags = EQF_RW;
else if((address & 0x1000) == 0x1000)
flags = EQF_RW;
else
{
cerr << "label = " << label << ", address = " << hex << address << " discarded\n";
return; // don't know what else to do for now
}
#else
// The above section of code is deactivated until a better means of
// determining constants vs. addresses is found
flags = EQF_RW;
#endif
removeEquate(label);
Equate e;
e.label = label;
e.address = address;
e.flags = flags;
myUserAddresses.insert(make_pair(label, e));
myUserLabels.insert(make_pair(address, e));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EquateList::removeEquate(const string& label)
{
// Note that only user-defined equates can be removed
LabelToAddr::iterator iter = myUserAddresses.find(label);
if(iter != myUserAddresses.end())
{
// Erase the label
myUserAddresses.erase(iter);
// And also erase the address assigned to it
AddrToLabel::iterator iter2 = myUserLabels.find(iter->second.address);
if(iter2 != myUserLabels.end())
myUserLabels.erase(iter2);
return true;
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const string& EquateList::getLabel(uInt16 addr, bool isRead, int places)
{
AddrToLabel::const_iterator iter;
// Is this a read or write?
// For now, there aren't separate read & write lists for user labels
AddrToLabel& systemLabels = isRead ? mySystemReadLabels : mySystemWriteLabels;
// Determine the type of address to access the correct list
addressType(addr);
switch(myAddressType)
{
case ADDR_TIA:
if((iter = systemLabels.find(addr&0x7f)) != systemLabels.end())
return iter->second.label;
else if((iter = myUserLabels.find(addr)) != myUserLabels.end())
return iter->second.label;
break;
case ADDR_RIOT: // FIXME - add mirrors for RIOT
if((iter = systemLabels.find(addr)) != systemLabels.end())
return iter->second.label;
else if((iter = myUserLabels.find(addr)) != myUserLabels.end())
return iter->second.label;
break;
case ADDR_RAM:
case ADDR_ROM:
// These addresses can never be in the system labels list
if((iter = myUserLabels.find(addr)) != myUserLabels.end())
return iter->second.label;
break;
}
if(places > -1)
{
ostringstream buf;
buf << "$" << setw(places) << hex << addr;
return myCurrentLabel = buf.str();
}
return EmptyString;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int EquateList::getAddress(const string& label) const
{
LabelToAddr::const_iterator iter;
if((iter = mySystemAddresses.find(label)) != mySystemAddresses.end())
return iter->second.address;
else if((iter = myUserAddresses.find(label)) != myUserAddresses.end())
return iter->second.address;
else
return -1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string EquateList::loadFile(const string& file)
{
int pos = 0, lines = 0, curVal;
string curLabel;
char line[1024];
ifstream in(file.c_str());
if(!in.is_open())
return "Unable to read symbols from " + file;
myUserAddresses.clear();
myUserLabels.clear();
while( !in.eof() )
{
curVal = 0;
curLabel = "";
int got = in.get();
if(got == -1 || got == '\r' || got == '\n' || pos == 1023) {
line[pos] = '\0';
pos = 0;
if(strlen(line) > 0 && line[0] != '-')
{
curLabel = extractLabel(line);
if((curVal = extractValue(line)) < 0)
return "invalid symbol file";
addEquate(curLabel, curVal);
lines++;
}
}
else
{
line[pos++] = got;
}
}
in.close();
return "loaded " + file + " OK";
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EquateList::saveFile(const string& file)
{
// Only user-defined equates are saved; system equates are always
// available, so there's no need to save them
char buf[256];
ofstream out(file.c_str());
if(!out.is_open())
return false;
out << "--- Symbol List (sorted by symbol)" << endl;
LabelToAddr::const_iterator iter;
for(iter = myUserAddresses.begin(); iter != myUserAddresses.end(); iter++)
{
sprintf(buf, "%-24s %04x \n", iter->second.label.c_str(), iter->second.address);
out << buf;
}
out << "--- End of Symbol List." << endl;
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int EquateList::countCompletions(const char *in)
{
myCompletions = myCompPrefix = "";
return countCompletions(in, mySystemAddresses) +
countCompletions(in, myUserAddresses);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int EquateList::countCompletions(const char *in, LabelToAddr& addresses)
{
int count = 0;
LabelToAddr::iterator iter;
for(iter = addresses.begin(); iter != addresses.end(); iter++)
{
const char *l = iter->first.c_str();
if(BSPF_strncasecmp(l, in, strlen(in)) == 0)
{
if(myCompPrefix == "")
myCompPrefix += l;
else
{
int nonMatch = 0;
const char *c = myCompPrefix.c_str();
while(*c != '\0' && tolower(*c) == tolower(l[nonMatch]))
{
c++;
nonMatch++;
}
myCompPrefix.erase(nonMatch, myCompPrefix.length());
}
if(count++) myCompletions += " ";
myCompletions += l;
}
}
return count;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string EquateList::extractLabel(char *c)
{
string l = "";
while(*c != ' ')
l += *c++;
return l;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int EquateList::extractValue(char *c)
{
while(*c != ' ')
{
if(*c == '\0')
return -1;
c++;
}
while(*c == ' ')
{
if(*c == '\0')
return -1;
c++;
}
int ret = 0;
for(int i=0; i<4; i++)
{
if(*c >= '0' && *c <= '9')
ret = (ret << 4) + (*c) - '0';
else if(*c >= 'a' && *c <= 'f')
ret = (ret << 4) + (*c) - 'a' + 10;
else
return -1;
c++;
}
return ret;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline void EquateList::addressType(uInt16 addr)
{
// These addresses were based on (and checked against) Kroko's 2600 memory
// map, found at http://www.qotile.net/minidig/docs/2600_mem_map.txt
myAddressType = ADDR_ROM;
if(addr % 0x2000 < 0x1000)
{
uInt16 z = addr & 0x00ff;
if(z < 0x80)
myAddressType = ADDR_TIA;
else
{
switch(addr & 0x0f00)
{
case 0x000:
case 0x100:
case 0x400:
case 0x500:
case 0x800:
case 0x900:
case 0xc00:
case 0xd00:
myAddressType = ADDR_RAM;
break;
case 0x200:
case 0x300:
case 0x600:
case 0x700:
case 0xa00:
case 0xb00:
case 0xe00:
case 0xf00:
myAddressType = ADDR_RIOT;
break;
}
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const EquateList::Equate EquateList::ourSystemEquates[kSystemEquateSize] = {
// Standard $00-based TIA write locations:
{ "VSYNC", 0x00, EQF_WRITE },
{ "VBLANK", 0x01, EQF_WRITE },
{ "WSYNC", 0x02, EQF_WRITE },
{ "RSYNC", 0x03, EQF_WRITE },
{ "NUSIZ0", 0x04, EQF_WRITE },
{ "NUSIZ1", 0x05, EQF_WRITE },
{ "COLUP0", 0x06, EQF_WRITE },
{ "COLUP1", 0x07, EQF_WRITE },
{ "COLUPF", 0x08, EQF_WRITE },
{ "COLUBK", 0x09, EQF_WRITE },
{ "CTRLPF", 0x0A, EQF_WRITE },
{ "REFP0", 0x0B, EQF_WRITE },
{ "REFP1", 0x0C, EQF_WRITE },
{ "PF0", 0x0D, EQF_WRITE },
{ "PF1", 0x0E, EQF_WRITE },
{ "PF2", 0x0F, EQF_WRITE },
{ "RESP0", 0x10, EQF_WRITE },
{ "RESP1", 0x11, EQF_WRITE },
{ "RESM0", 0x12, EQF_WRITE },
{ "RESM1", 0x13, EQF_WRITE },
{ "RESBL", 0x14, EQF_WRITE },
{ "AUDC0", 0x15, EQF_WRITE },
{ "AUDC1", 0x16, EQF_WRITE },
{ "AUDF0", 0x17, EQF_WRITE },
{ "AUDF1", 0x18, EQF_WRITE },
{ "AUDV0", 0x19, EQF_WRITE },
{ "AUDV1", 0x1A, EQF_WRITE },
{ "GRP0", 0x1B, EQF_WRITE },
{ "GRP1", 0x1C, EQF_WRITE },
{ "ENAM0", 0x1D, EQF_WRITE },
{ "ENAM1", 0x1E, EQF_WRITE },
{ "ENABL", 0x1F, EQF_WRITE },
{ "HMP0", 0x20, EQF_WRITE },
{ "HMP1", 0x21, EQF_WRITE },
{ "HMM0", 0x22, EQF_WRITE },
{ "HMM1", 0x23, EQF_WRITE },
{ "HMBL", 0x24, EQF_WRITE },
{ "VDELP0", 0x25, EQF_WRITE },
{ "VDEL01", 0x26, EQF_WRITE },
{ "VDELP1", 0x26, EQF_WRITE },
{ "VDELBL", 0x27, EQF_WRITE },
{ "RESMP0", 0x28, EQF_WRITE },
{ "RESMP1", 0x29, EQF_WRITE },
{ "HMOVE", 0x2A, EQF_WRITE },
{ "HMCLR", 0x2B, EQF_WRITE },
{ "CXCLR", 0x2C, EQF_WRITE },
// Mirrored $40-based TIA write locations:
{ "VSYNC.40", 0x40, EQF_WRITE },
{ "VBLANK.40", 0x41, EQF_WRITE },
{ "WSYNC.40", 0x42, EQF_WRITE },
{ "RSYNC.40", 0x43, EQF_WRITE },
{ "NUSIZ0.40", 0x44, EQF_WRITE },
{ "NUSIZ1.40", 0x45, EQF_WRITE },
{ "COLUP0.40", 0x46, EQF_WRITE },
{ "COLUP1.40", 0x47, EQF_WRITE },
{ "COLUPF.40", 0x48, EQF_WRITE },
{ "COLUBK.40", 0x49, EQF_WRITE },
{ "CTRLPF.40", 0x4A, EQF_WRITE },
{ "REFP0.40", 0x4B, EQF_WRITE },
{ "REFP1.40", 0x4C, EQF_WRITE },
{ "PF0.40", 0x4D, EQF_WRITE },
{ "PF1.40", 0x4E, EQF_WRITE },
{ "PF2.40", 0x4F, EQF_WRITE },
{ "RESP0.40", 0x50, EQF_WRITE },
{ "RESP1.40", 0x51, EQF_WRITE },
{ "RESM0.40", 0x52, EQF_WRITE },
{ "RESM1.40", 0x53, EQF_WRITE },
{ "RESBL.40", 0x54, EQF_WRITE },
{ "AUDC0.40", 0x55, EQF_WRITE },
{ "AUDC1.40", 0x56, EQF_WRITE },
{ "AUDF0.40", 0x57, EQF_WRITE },
{ "AUDF1.40", 0x58, EQF_WRITE },
{ "AUDV0.40", 0x59, EQF_WRITE },
{ "AUDV1.40", 0x5A, EQF_WRITE },
{ "GRP0.40", 0x5B, EQF_WRITE },
{ "GRP1.40", 0x5C, EQF_WRITE },
{ "ENAM0.40", 0x5D, EQF_WRITE },
{ "ENAM1.40", 0x5E, EQF_WRITE },
{ "ENABL.40", 0x5F, EQF_WRITE },
{ "HMP0.40", 0x60, EQF_WRITE },
{ "HMP1.40", 0x61, EQF_WRITE },
{ "HMM0.40", 0x62, EQF_WRITE },
{ "HMM1.40", 0x63, EQF_WRITE },
{ "HMBL.40", 0x64, EQF_WRITE },
{ "VDELP0.40", 0x65, EQF_WRITE },
{ "VDEL01.40", 0x66, EQF_WRITE },
{ "VDELP1.40", 0x66, EQF_WRITE },
{ "VDELBL.40", 0x67, EQF_WRITE },
{ "RESMP0.40", 0x68, EQF_WRITE },
{ "RESMP1.40", 0x69, EQF_WRITE },
{ "HMOVE.40", 0x6A, EQF_WRITE },
{ "HMCLR.40", 0x6B, EQF_WRITE },
{ "CXCLR.40", 0x6C, EQF_WRITE },
// Standard $00-based TIA read locations:
{ "CXM0P", 0x00, EQF_READ },
{ "CXM1P", 0x01, EQF_READ },
{ "CXP0FB", 0x02, EQF_READ },
{ "CXP1FB", 0x03, EQF_READ },
{ "CXM0FB", 0x04, EQF_READ },
{ "CXM1FB", 0x05, EQF_READ },
{ "CXBLPF", 0x06, EQF_READ },
{ "CXPPMM", 0x07, EQF_READ },
{ "INPT0", 0x08, EQF_READ },
{ "INPT1", 0x09, EQF_READ },
{ "INPT2", 0x0A, EQF_READ },
{ "INPT3", 0x0B, EQF_READ },
{ "INPT4", 0x0C, EQF_READ },
{ "INPT5", 0x0D, EQF_READ },
// Mirrored $10-based TIA read locations:
{ "CXM0P.10", 0x10, EQF_READ },
{ "CXM1P.10", 0x11, EQF_READ },
{ "CXP0FB.10", 0x12, EQF_READ },
{ "CXP1FB.10", 0x13, EQF_READ },
{ "CXM0FB.10", 0x14, EQF_READ },
{ "CXM1FB.10", 0x15, EQF_READ },
{ "CXBLPF.10", 0x16, EQF_READ },
{ "CXPPMM.10", 0x17, EQF_READ },
{ "INPT0.10", 0x18, EQF_READ },
{ "INPT1.10", 0x19, EQF_READ },
{ "INPT2.10", 0x1A, EQF_READ },
{ "INPT3.10", 0x1B, EQF_READ },
{ "INPT4.10", 0x1C, EQF_READ },
{ "INPT5.10", 0x1D, EQF_READ },
// Mirrored $20-based TIA read locations:
{ "CXM0P.20", 0x20, EQF_READ },
{ "CXM1P.20", 0x21, EQF_READ },
{ "CXP0FB.20", 0x22, EQF_READ },
{ "CXP1FB.20", 0x23, EQF_READ },
{ "CXM0FB.20", 0x24, EQF_READ },
{ "CXM1FB.20", 0x25, EQF_READ },
{ "CXBLPF.20", 0x26, EQF_READ },
{ "CXPPMM.20", 0x27, EQF_READ },
{ "INPT0.20", 0x28, EQF_READ },
{ "INPT1.20", 0x29, EQF_READ },
{ "INPT2.20", 0x2A, EQF_READ },
{ "INPT3.20", 0x2B, EQF_READ },
{ "INPT4.20", 0x2C, EQF_READ },
{ "INPT5.20", 0x2D, EQF_READ },
// Mirrored $30-based TIA read locations:
{ "CXM0P.30", 0x30, EQF_READ },
{ "CXM1P.30", 0x31, EQF_READ },
{ "CXP0FB.30", 0x32, EQF_READ },
{ "CXP1FB.30", 0x33, EQF_READ },
{ "CXM0FB.30", 0x34, EQF_READ },
{ "CXM1FB.30", 0x35, EQF_READ },
{ "CXBLPF.30", 0x36, EQF_READ },
{ "CXPPMM.30", 0x37, EQF_READ },
{ "INPT0.30", 0x38, EQF_READ },
{ "INPT1.30", 0x39, EQF_READ },
{ "INPT2.30", 0x3A, EQF_READ },
{ "INPT3.30", 0x3B, EQF_READ },
{ "INPT4.30", 0x3C, EQF_READ },
{ "INPT5.30", 0x3D, EQF_READ },
// Standard RIOT locations (read, write, or both):
{ "SWCHA", 0x280, EQF_RW },
{ "SWCHB", 0x282, EQF_RW },
{ "SWACNT", 0x281, EQF_WRITE },
{ "SWBCNT", 0x283, EQF_WRITE },
{ "INTIM", 0x284, EQF_READ },
{ "TIMINT", 0x285, EQF_READ },
{ "TIM1T", 0x294, EQF_WRITE },
{ "TIM8T", 0x295, EQF_WRITE },
{ "TIM64T", 0x296, EQF_WRITE },
{ "T1024T", 0x297, EQF_WRITE }
};

View File

@ -1,122 +0,0 @@
//============================================================================
//
// 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
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2010 by Bradford W. Mott and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#ifndef EQUATELIST_HXX
#define EQUATELIST_HXX
#include <map>
#include "bspf.hxx"
class EquateList
{
public:
EquateList();
~EquateList();
/**
Add an equate consisting of the given label and address
*/
void addEquate(const string& label, uInt16 address);
/**
Remove the equate with the given label
*/
bool removeEquate(const string& label);
/**
Accessor methods for labels and addresses
The mapping from address to label can be one-to-many (ie, an
address can have different labels depending on its context, and
whether its being read or written; if isRead is true, the context
is a read, else it's a write
If places is not -1 and a label hasn't been defined, return a
formatted hexidecimal address
*/
const string& getLabel(uInt16 addr, bool isRead, int places = -1);
int getAddress(const string& label) const;
/**
Load user equates from the given symbol file (generated by DASM)
*/
string loadFile(const string& file);
/**
Save user equates into a symbol file similar to that generated by DASM
*/
bool saveFile(const string& file);
/**
Methods used by the command parser for tab-completion
*/
int countCompletions(const char *in);
const string& getCompletions() const { return myCompletions; }
const string& getCompletionPrefix() const { return myCompPrefix; }
private:
enum equate_t {
EQF_READ = 1 << 0, // address can be read from
EQF_WRITE = 1 << 1, // address can be written to
EQF_RW = EQF_READ | EQF_WRITE // address can be both read and written
};
enum address_t {
ADDR_TIA = 1 << 0,
ADDR_RAM = 1 << 1,
ADDR_RIOT = 1 << 2,
ADDR_ROM = 1 << 3
};
struct Equate {
string label;
uInt16 address;
equate_t flags;
};
typedef map<uInt16, Equate> AddrToLabel;
typedef map<string, Equate> LabelToAddr;
private:
// Extract labels and values from the given character stream
string extractLabel(char *c);
int extractValue(char *c);
// Count completions for the given mapping
int countCompletions(const char *in, LabelToAddr& addresses);
// Determine what type address we're dealing with
inline void addressType(uInt16 addr);
private:
enum { kSystemEquateSize = 158 };
static const Equate ourSystemEquates[kSystemEquateSize];
string myCompletions;
string myCompPrefix;
LabelToAddr mySystemAddresses;
AddrToLabel mySystemReadLabels; // labels used in a read context
AddrToLabel mySystemWriteLabels; // labels used in a write context
LabelToAddr myUserAddresses;
AddrToLabel myUserLabels;
address_t myAddressType;
string myCurrentLabel;
};
#endif

View File

@ -1,164 +0,0 @@
//============================================================================
//
// 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
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2010 by Bradford W. Mott and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#include "bspf.hxx"
#include "Array.hxx"
#include "System.hxx"
#include "RamDebug.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RamDebug::RamDebug(Debugger& dbg, Console& console)
: DebuggerSystem(dbg, console)
{
// Zero-page RAM is always present
addRamArea(0x80, 128, 0, 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RamDebug::addRamArea(uInt16 start, uInt16 size,
uInt16 roffset, uInt16 woffset)
{
// First make sure this area isn't already present
for(uInt32 i = 0; i < myState.rport.size(); ++i)
if(myState.rport[i] == start + roffset ||
myState.wport[i] == start + woffset)
return;
// Otherwise, add a new area
for(uInt32 i = 0; i < size; ++i)
{
myState.rport.push_back(i + start + roffset);
myState.wport.push_back(i + start + woffset);
myOldState.rport.push_back(i + start + roffset);
myOldState.wport.push_back(i + start + woffset);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RamDebug::addRamArea(const RamAreaList& areas)
{
myRamAreas = areas;
for(RamAreaList::const_iterator i = areas.begin(); i != areas.end(); ++i)
addRamArea(i->start, i->size, i->roffset, i->woffset);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const DebuggerState& RamDebug::getState()
{
myState.ram.clear();
for(uInt32 i = 0; i < myState.rport.size(); ++i)
myState.ram.push_back(read(myState.rport[i]));
return myState;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RamDebug::saveOldState()
{
myOldState.ram.clear();
for(uInt32 i = 0; i < myOldState.rport.size(); ++i)
myOldState.ram.push_back(read(myOldState.rport[i]));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 RamDebug::read(uInt16 addr)
{
return mySystem.peek(addr);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RamDebug::write(uInt16 addr, uInt8 value)
{
mySystem.poke(addr, value);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int RamDebug::readFromWritePort()
{
uInt16 addr = mySystem.m6502().lastReadAddress();
if(addr & 0x1000)
{
addr &= 0x0FFF;
for(RamAreaList::const_iterator i = myRamAreas.begin(); i != myRamAreas.end(); ++i)
{
uInt16 start = (i->start + i->woffset) & 0x0FFF;
uInt16 end = (i->start + i->woffset + i->size) & 0x0FFF;
if(addr >= start && addr < end)
return addr;
}
}
return 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string RamDebug::toString()
{
string result;
char buf[128];
uInt32 bytesPerLine;
switch(myDebugger.parser().base())
{
case kBASE_16:
case kBASE_10:
bytesPerLine = 0x10;
break;
case kBASE_2:
bytesPerLine = 0x04;
break;
case kBASE_DEFAULT:
default:
return DebuggerParser::red("invalid base, this is a BUG");
}
const RamState& state = (RamState&) getState();
const RamState& oldstate = (RamState&) getOldState();
uInt32 curraddr = 0, bytesSoFar = 0;
for(uInt32 i = 0; i < state.ram.size(); i += bytesPerLine, bytesSoFar += bytesPerLine)
{
// We detect different 'pages' of RAM when the addresses jump by
// more than the number of bytes on the previous line, or when 256
// bytes have been previously output
if(state.rport[i] - curraddr > bytesPerLine || bytesSoFar >= 256)
{
sprintf(buf, "%04x: (rport = %04x, wport = %04x)\n",
state.rport[i], state.rport[i], state.wport[i]);
buf[2] = buf[3] = 'x';
result += DebuggerParser::red(buf);
bytesSoFar = 0;
}
curraddr = state.rport[i];
sprintf(buf, "%.2x: ", curraddr & 0x00ff);
result += buf;
for(uInt8 j = 0; j < bytesPerLine; ++j)
{
result += myDebugger.invIfChanged(state.ram[i+j], oldstate.ram[i+j]);
result += " ";
if(j == 0x07) result += " ";
}
result += "\n";
}
return result;
}

View File

@ -1,82 +0,0 @@
//============================================================================
//
// 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
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2010 by Bradford W. Mott and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#ifndef RAM_DEBUG_HXX
#define RAM_DEBUG_HXX
class System;
#include "bspf.hxx"
#include "Array.hxx"
#include "Cart.hxx"
#include "DebuggerSystem.hxx"
// pointer types for RamDebug instance methods
typedef int (RamDebug::*RAMDEBUG_INT_METHOD)();
// call the pointed-to method on the (global) CPU debugger object.
#define CALL_RAMDEBUG_METHOD(method) ( ( Debugger::debugger().ramDebug().*method)() )
class RamState : public DebuggerState
{
public:
IntArray ram; // The actual data values
IntArray rport; // Address for reading from RAM
IntArray wport; // Address for writing to RAM
};
class RamDebug : public DebuggerSystem
{
public:
RamDebug(Debugger& dbg, Console& console);
/**
Let the RAM debugger subsystem treat this area as addressable memory.
@param start The beginning of the RAM area (0x0000 - 0x2000)
@param size Total number of bytes of area
@param roffset Offset to use when reading from RAM (read port)
@param woffset Offset to use when writing to RAM (write port)
*/
void addRamArea(uInt16 start, uInt16 size, uInt16 roffset, uInt16 woffset);
void addRamArea(const RamAreaList& areas);
const DebuggerState& getState();
const DebuggerState& getOldState() { return myOldState; }
void saveOldState();
string toString();
// The following assume that the given addresses are using the
// correct read/write port ranges; no checking will be done to
// confirm this.
uInt8 read(uInt16 addr);
void write(uInt16 addr, uInt8 value);
// Return the address at which an invalid read was performed in a
// write port area.
int readFromWritePort();
private:
RamState myState;
RamState myOldState;
RamAreaList myRamAreas;
};
#endif

View File

@ -24,6 +24,7 @@
#include "OSystem.hxx"
#include "GuiObject.hxx"
#include "Debugger.hxx"
#include "CartDebug.hxx"
#include "CpuDebug.hxx"
#include "Widget.hxx"
#include "DataGridWidget.hxx"
@ -280,5 +281,5 @@ void CpuWidget::fillGrid()
changed.push_back(state.PSbits[i] != oldstate.PSbits[i]);
myPSRegister->setState(state.PSbits, changed);
myPCLabel->setEditString(dbg.equates().getLabel(state.PC, true));
myPCLabel->setEditString(dbg.cartDebug().getLabel(state.PC, true));
}

View File

@ -31,7 +31,7 @@
#include "DebuggerParser.hxx"
#include "PromptWidget.hxx"
#include "EquateList.hxx"
#include "CartDebug.hxx"
#define PROMPT "> "
@ -253,8 +253,8 @@ bool PromptWidget::handleKeyDown(int ascii, int keycode, int modifiers)
else
{
// we got a delimiter, so this must be a label:
EquateList& equates = instance().debugger().equates();
possibilities = equates.countCompletions(str + lastDelimPos + 1);
CartDebug& cart = instance().debugger().cartDebug();
possibilities = cart.countCompletions(str + lastDelimPos + 1);
if(possibilities < 1) {
delete[] str;
@ -262,8 +262,8 @@ bool PromptWidget::handleKeyDown(int ascii, int keycode, int modifiers)
}
// TODO - perhaps use strings instead of char pointers
completionList = equates.getCompletions().c_str();
prefix = equates.getCompletionPrefix().c_str();
completionList = cart.getCompletions().c_str();
prefix = cart.getCompletionPrefix().c_str();
}
if(possibilities == 1)

View File

@ -27,7 +27,7 @@
#include "GuiObject.hxx"
#include "InputTextDialog.hxx"
#include "OSystem.hxx"
#include "RamDebug.hxx"
#include "CartDebug.hxx"
#include "Widget.hxx"
#include "RamWidget.hxx"
@ -159,8 +159,8 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
// memory location
int addr, value;
RamDebug& dbg = instance().debugger().ramDebug();
const RamState& state = (RamState&) dbg.getState();
CartDebug& dbg = instance().debugger().cartDebug();
const CartState& state = (CartState&) dbg.getState();
switch(cmd)
{
case kDGItemDataChangedCmd:
@ -193,8 +193,7 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
addr = myRamGrid->getSelectedAddr();
value = myRamGrid->getSelectedValue();
myLabel->setEditString(
instance().debugger().equates().getLabel(state.rport[addr], true));
myLabel->setEditString(dbg.getLabel(state.rport[addr], true));
myDecValue->setEditString(instance().debugger().valueToString(value, kBASE_10));
myBinValue->setEditString(instance().debugger().valueToString(value, kBASE_2));
break;
@ -267,10 +266,10 @@ void RamWidget::fillGrid(bool updateOld)
if(updateOld) myOldValueList.clear();
RamDebug& dbg = instance().debugger().ramDebug();
CartDebug& dbg = instance().debugger().cartDebug();
const RamState& state = (RamState&) dbg.getState();
const RamState& oldstate = (RamState&) dbg.getOldState();
const CartState& state = (CartState&) dbg.getState();
const CartState& oldstate = (CartState&) dbg.getOldState();
// Jump to the correct 128 byte 'window' in the RAM area
// This assumes that the RAM areas are aligned on 128 byte boundaries
@ -346,8 +345,8 @@ string RamWidget::doSearch(const string& str)
// Now, search all memory locations for this value, and add it to the
// search array
bool hitfound = false;
RamDebug& dbg = instance().debugger().ramDebug();
const RamState& state = (RamState&) dbg.getState();
CartDebug& dbg = instance().debugger().cartDebug();
const CartState& state = (CartState&) dbg.getState();
for(uInt32 addr = 0; addr < state.ram.size(); ++addr)
{
int value = state.ram[addr];
@ -415,8 +414,8 @@ string RamWidget::doCompare(const string& str)
// Now, search all memory locations previously 'found' for this value
bool hitfound = false;
RamDebug& dbg = instance().debugger().ramDebug();
const RamState& state = (RamState&) dbg.getState();
CartDebug& dbg = instance().debugger().cartDebug();
const CartState& state = (CartState&) dbg.getState();
IntArray tempAddrList, tempValueList;
mySearchState.clear();
for(uInt32 i = 0; i < state.rport.size(); ++i)

View File

@ -41,7 +41,7 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& font,
const int fontWidth = font.getMaxCharWidth(),
numchars = w / fontWidth;
myLabelWidth = BSPF_max(20, int(0.35 * (numchars - 12))) * fontWidth;
myLabelWidth = BSPF_max(16, int(0.35 * (numchars - 12))) * fontWidth;
myBytesWidth = 12 * fontWidth;
}
@ -85,7 +85,7 @@ void RomListWidget::drawWidget(bool hilite)
{
//cerr << "RomListWidget::drawWidget\n";
FBSurface& s = _boss->dialog().surface();
int i, pos, len = _list.size();
int i, pos, xpos, ypos, len = _list.size();
string buffer;
int deltax;
@ -97,18 +97,16 @@ void RomListWidget::drawWidget(bool hilite)
s.vLine(_x + CheckboxWidget::boxSize() + 5, _y, _y + _h - 1, kColor);
// Draw the list items
for (i = 0, pos = _currentPos; i < _rows && pos < len; i++, pos++)
GUI::Rect r = getEditRect();
GUI::Rect l = getLineRect();
xpos = _x + CheckboxWidget::boxSize() + 10; ypos = _y + 2;
for (i = 0, pos = _currentPos; i < _rows && pos < len; i++, pos++, ypos += _fontHeight)
{
// Draw checkboxes for correct lines (takes scrolling into account)
_checkList[i]->setState(_stateList[pos]);
_checkList[i]->setDirty();
_checkList[i]->draw();
const int y = _y + 2 + _fontHeight * i;
GUI::Rect l = getLineRect();
GUI::Rect r = getEditRect();
// Draw highlighted item in a frame
if (_highlightedItem == pos)
{
@ -127,12 +125,13 @@ void RomListWidget::drawWidget(bool hilite)
r.width(), _fontHeight, kTextColorHi);
}
// Draw labels and actual disassembly
s.drawString(_font, myLabel[pos], _x + r.left - myLabelWidth, y,
// Draw labels
s.drawString(_font, myLabel[pos], xpos, ypos,
myLabelWidth, kTextColor);
s.drawString(_font, myDisasm[pos], _x + r.right, y,
_w - r.right, kTextColor);
// Draw disassembly
s.drawString(_font, myDisasm[pos], xpos + myLabelWidth, ypos,
r.left, kTextColor);
// Draw editable bytes
if (_selectedItem == pos && _editMode)
@ -141,14 +140,14 @@ void RomListWidget::drawWidget(bool hilite)
adjustOffset();
deltax = -_editScrollOffset;
s.drawString(_font, buffer, _x + r.left, y, r.width(), kTextColor,
s.drawString(_font, buffer, _x + r.left, ypos, r.width(), kTextColor,
kTextAlignLeft, deltax, false);
}
else
{
buffer = _list[pos];
deltax = 0;
s.drawString(_font, buffer, _x + r.left, y, r.width(), kTextColor);
s.drawString(_font, buffer, _x + r.left, ypos, r.width(), kTextColor);
}
}
@ -176,12 +175,11 @@ GUI::Rect RomListWidget::getLineRect() const
GUI::Rect RomListWidget::getEditRect() const
{
GUI::Rect r(2, 1, _w, _fontHeight);
const int yoffset = (_selectedItem - _currentPos) * _fontHeight,
xoffset = CheckboxWidget::boxSize() + 10;
const int yoffset = (_selectedItem - _currentPos) * _fontHeight;
r.top += yoffset;
r.bottom += yoffset;
r.left += xoffset + myLabelWidth;
r.right = r.left + myBytesWidth;
r.left += _w - myBytesWidth;
r.right = _w;
return r;
}

View File

@ -23,6 +23,7 @@
#include "Debugger.hxx"
#include "DebuggerParser.hxx"
#include "CartDebug.hxx"
#include "CpuDebug.hxx"
#include "DataGridWidget.hxx"
#include "PackedBitArray.hxx"
@ -38,7 +39,6 @@ RomWidget::RomWidget(GuiObject* boss, const GUI::Font& font, int x, int y)
: Widget(boss, font, x, y, 16, 16),
CommandSender(boss),
myListIsDirty(true),
mySourceAvailable(false),
myCurrentBank(-1)
{
_type = kRomWidget;
@ -57,8 +57,8 @@ RomWidget::RomWidget(GuiObject* boss, const GUI::Font& font, int x, int y)
myBank = new DataGridWidget(boss, font, xpos, ypos-2,
1, 1, 4, 8, kBASE_10);
myBank->setTarget(this);
myBank->setRange(0, instance().debugger().bankCount());
if(instance().debugger().bankCount() <= 1)
myBank->setRange(0, instance().debugger().cartDebug().bankCount());
if(instance().debugger().cartDebug().bankCount() <= 1)
myBank->setEditable(false);
addFocusWidget(myBank);
@ -111,10 +111,6 @@ void RomWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
{
switch(cmd)
{
case kListScrolledCmd:
incrementalUpdate(data, myRomList->rows());
break;
case kListItemChecked:
setBreak(data);
break;
@ -164,19 +160,45 @@ void RomWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
void RomWidget::loadConfig()
{
Debugger& dbg = instance().debugger();
bool bankChanged = myCurrentBank != dbg.getBank();
CartDebug& cart = dbg.cartDebug();
bool bankChanged = myCurrentBank != cart.getBank();
myCurrentBank = cart.getBank();
// Fill romlist the current bank of source or disassembly
// Only reload full bank when necessary
if(myListIsDirty || bankChanged)
{
initialUpdate();
// Clear old mappings
myAddrList.clear();
myLineList.clear();
StringList label, data, disasm;
BoolArray state;
// Disassemble zero-page RAM and entire bank and reset breakpoints
cart.disassemble(myAddrList, label, data, disasm, 0x80, 0xff);
cart.disassemble(myAddrList, label, data, disasm, 0xf000, 0xffff);
PackedBitArray& bp = dbg.breakpoints();
for(unsigned int i = 0; i < data.size(); ++i)
{
if(bp.isSet(myAddrList[i]))
state.push_back(true);
else
state.push_back(false);
}
// Create a mapping from addresses to line numbers
for(unsigned int i = 0; i < myAddrList.size(); ++i)
myLineList.insert(make_pair(myAddrList[i], i));
myRomList->setList(label, data, disasm, state);
// Restore the old bank, in case we inadvertently switched while reading.
dbg.setBank(myCurrentBank);
myListIsDirty = false;
}
else // only reload what's in current view
{
incrementalUpdate(myRomList->currentPos(), myRomList->rows());
}
myCurrentBank = dbg.getBank();
// Update romlist to point to current PC
// Take mirroring of PC into account, as well as zero-page RAM
@ -204,62 +226,12 @@ void RomWidget::loadConfig()
BoolArray changed;
alist.push_back(-1);
vlist.push_back(dbg.getBank());
vlist.push_back(cart.getBank());
changed.push_back(bankChanged);
myBank->setList(alist, vlist, changed);
// Indicate total number of banks
myBankCount->setEditString(dbg.valueToString(dbg.bankCount(), kBASE_10));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomWidget::initialUpdate()
{
Debugger& dbg = instance().debugger();
PackedBitArray& bp = dbg.breakpoints();
// Reading from ROM might trigger a bankswitch, so save the current bank
myCurrentBank = dbg.getBank();
// Fill romlist the current bank of source or disassembly
if(mySourceAvailable)
; // TODO - actually implement this
else
{
// Clear old mappings
myAddrList.clear();
myLineList.clear();
StringList label, data, disasm;
BoolArray state;
// Disassemble zero-page RAM and entire bank and reset breakpoints
// dbg.disassemble(myAddrList, label, data, disasm, 0x80, 0xff);
dbg.disassemble(myAddrList, label, data, disasm, 0xf000, 0xffff);
for(unsigned int i = 0; i < data.size(); ++i)
{
if(bp.isSet(myAddrList[i]))
state.push_back(true);
else
state.push_back(false);
}
// Create a mapping from addresses to line numbers
myLineList.clear();
for(unsigned int i = 0; i < myAddrList.size(); ++i)
myLineList.insert(make_pair(myAddrList[i], i));
myRomList->setList(label, data, disasm, state);
}
// Restore the old bank, in case we inadvertently switched while reading.
dbg.setBank(myCurrentBank);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomWidget::incrementalUpdate(int line, int rows)
{
// TODO - implement this
myBankCount->setEditString(dbg.valueToString(cart.bankCount(), kBASE_10));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -50,9 +50,6 @@ class RomWidget : public Widget, public CommandSender
void loadConfig();
private:
void initialUpdate();
void incrementalUpdate(int line, int rows);
void setBreak(int data);
void setPC(int data);
void patchROM(int data, const string& bytes);
@ -76,7 +73,6 @@ class RomWidget : public Widget, public CommandSender
InputTextDialog* mySaveRom;
bool myListIsDirty;
bool mySourceAvailable;
int myCurrentBank;
};

View File

@ -25,6 +25,7 @@
#include "FrameBuffer.hxx"
#include "GuiObject.hxx"
#include "OSystem.hxx"
#include "CartDebug.hxx"
#include "TIADebug.hxx"
#include "ToggleBitWidget.hxx"
#include "TogglePixelWidget.hxx"
@ -598,6 +599,7 @@ void TiaWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
string buf;
Debugger& dbg = instance().debugger();
CartDebug& cart = dbg.cartDebug();
TIADebug& tia = dbg.tiaDebug();
switch(cmd)
@ -751,7 +753,7 @@ void TiaWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
// We're using the read-addresses here
// Should we also add write-addresses, or remove this entirely?
myLabel->setEditString(dbg.equates().getLabel(addr, true));
myLabel->setEditString(cart.getLabel(addr, true));
myDecValue->setEditString(dbg.valueToString(value, kBASE_10));
myBinValue->setEditString(dbg.valueToString(value, kBASE_2));

View File

@ -3,11 +3,11 @@ MODULE := src/debugger
MODULE_OBJS := \
src/debugger/Debugger.o \
src/debugger/DebuggerParser.o \
src/debugger/EquateList.o \
src/debugger/Expression.o \
src/debugger/PackedBitArray.o \
src/debugger/CartDebug.o \
src/debugger/CpuDebug.o \
src/debugger/RamDebug.o \
src/debugger/DiStella.o \
src/debugger/RiotDebug.o \
src/debugger/TIADebug.o

View File

@ -53,7 +53,7 @@
#include "Settings.hxx"
#ifdef DEBUGGER_SUPPORT
#include "Debugger.hxx"
#include "RamDebug.hxx"
#include "CartDebug.hxx"
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -263,6 +263,15 @@ void Cartridge::registerRamArea(uInt16 start, uInt16 size,
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Cartridge::triggerReadFromWritePort(uInt16 address)
{
#ifdef DEBUGGER_SUPPORT
if(&Debugger::debugger().cartDebug())
Debugger::debugger().cartDebug().triggerReadFromWritePort(address);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Cartridge::autodetectType(const uInt8* image, uInt32 size)
{

View File

@ -169,6 +169,13 @@ class Cartridge : public Device
*/
void registerRamArea(uInt16 start, uInt16 size, uInt16 roffset, uInt16 woffset);
/**
Indicate that an illegal read from a write port has occurred.
@param address The address of the illegal read
*/
void triggerReadFromWritePort(uInt16 address);
private:
/**
Get an image pointer and size for a ROM that is part of a larger,

View File

@ -95,6 +95,7 @@ void Cartridge3E::install(System& system)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 Cartridge3E::peek(uInt16 address)
{
uInt16 peekAddress = address;
address &= 0x0FFF;
if(address < 0x0800)
@ -110,8 +111,13 @@ uInt8 Cartridge3E::peek(uInt16 address)
// Reading from the write port triggers an unwanted write
uInt8 value = mySystem->getDataBusState(0xFF);
if(myBankLocked) return value;
else return myRam[(address & 0x03FF) + ((myCurrentBank - 256) << 10)] = value;
if(myBankLocked)
return value;
else
{
triggerReadFromWritePort(peekAddress);
return myRam[(address & 0x03FF) + ((myCurrentBank - 256) << 10)] = value;
}
}
}
}

View File

@ -113,8 +113,13 @@ uInt8 CartridgeCV::peek(uInt16 address)
// Reading from the write port triggers an unwanted write
uInt8 value = mySystem->getDataBusState(0xFF);
if(myBankLocked) return value;
else return myRAM[address & 0x03FF] = value;
if(myBankLocked)
return value;
else
{
triggerReadFromWritePort(address);
return myRAM[address & 0x03FF] = value;
}
}
else
{

View File

@ -92,6 +92,7 @@ void CartridgeE7::install(System& system)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeE7::peek(uInt16 address)
{
uInt16 peekAddress = address;
address &= 0x0FFF;
// Switch banks if necessary
@ -109,16 +110,26 @@ uInt8 CartridgeE7::peek(uInt16 address)
// Reading from the 1K write port @ $1000 triggers an unwanted write
uInt8 value = mySystem->getDataBusState(0xFF);
if(myBankLocked) return value;
else return myRAM[address & 0x03FF] = value;
if(myBankLocked)
return value;
else
{
triggerReadFromWritePort(peekAddress);
return myRAM[address & 0x03FF] = value;
}
}
else if((address >= 0x0800) && (address <= 0x08FF))
{
// Reading from the 256B write port @ $1800 triggers an unwanted write
uInt8 value = mySystem->getDataBusState(0xFF);
if(myBankLocked) return value;
else return myRAM[1024 + (myCurrentRAM << 8) + (address & 0x00FF)] = value;
if(myBankLocked)
return value;
else
{
triggerReadFromWritePort(peekAddress);
return myRAM[1024 + (myCurrentRAM << 8) + (address & 0x00FF)] = value;
}
}
else
return myImage[(myCurrentSlice[address >> 11] << 11) + (address & 0x07FF)];

View File

@ -93,6 +93,7 @@ void CartridgeEFSC::install(System& system)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeEFSC::peek(uInt16 address)
{
uInt16 peekAddress = address;
address &= 0x0FFF;
// Switch banks if necessary
@ -104,8 +105,13 @@ uInt8 CartridgeEFSC::peek(uInt16 address)
// Reading from the write port triggers an unwanted write
uInt8 value = mySystem->getDataBusState(0xFF);
if(myBankLocked) return value;
else return myRAM[address] = value;
if(myBankLocked)
return value;
else
{
triggerReadFromWritePort(peekAddress);
return myRAM[address] = value;
}
}
else
return myImage[(myCurrentBank << 12) + address];

View File

@ -93,6 +93,7 @@ void CartridgeF4SC::install(System& system)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeF4SC::peek(uInt16 address)
{
uInt16 peekAddress = address;
address &= 0x0FFF;
// Switch banks if necessary
@ -104,12 +105,14 @@ uInt8 CartridgeF4SC::peek(uInt16 address)
// Reading from the write port triggers an unwanted write
uInt8 value = mySystem->getDataBusState(0xFF);
if(myBankLocked) return value;
else return myRAM[address] = value;
if(myBankLocked)
return value;
else
{
triggerReadFromWritePort(peekAddress);
return myRAM[address] = value;
}
}
else
return myImage[(myCurrentBank << 12) + address];
// NOTE: This does not handle accessing RAM, however, this function
// should never be called for RAM because of the way page accessing

View File

@ -93,6 +93,7 @@ void CartridgeF6SC::install(System& system)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeF6SC::peek(uInt16 address)
{
uInt16 peekAddress = address;
address &= 0x0FFF;
// Switch banks if necessary
@ -127,8 +128,13 @@ uInt8 CartridgeF6SC::peek(uInt16 address)
// Reading from the write port triggers an unwanted write
uInt8 value = mySystem->getDataBusState(0xFF);
if(myBankLocked) return value;
else return myRAM[address] = value;
if(myBankLocked)
return value;
else
{
triggerReadFromWritePort(peekAddress);
return myRAM[address] = value;
}
}
else
return myImage[(myCurrentBank << 12) + address];

View File

@ -93,6 +93,7 @@ void CartridgeF8SC::install(System& system)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeF8SC::peek(uInt16 address)
{
uInt16 peekAddress = address;
address &= 0x0FFF;
// Switch banks if necessary
@ -117,8 +118,13 @@ uInt8 CartridgeF8SC::peek(uInt16 address)
// Reading from the write port triggers an unwanted write
uInt8 value = mySystem->getDataBusState(0xFF);
if(myBankLocked) return value;
else return myRAM[address] = value;
if(myBankLocked)
return value;
else
{
triggerReadFromWritePort(peekAddress);
return myRAM[address] = value;
}
}
else
return myImage[(myCurrentBank << 12) + address];

View File

@ -93,6 +93,7 @@ void CartridgeFA::install(System& system)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeFA::peek(uInt16 address)
{
uInt16 peekAddress = address;
address &= 0x0FFF;
// Switch banks if necessary
@ -122,8 +123,13 @@ uInt8 CartridgeFA::peek(uInt16 address)
// Reading from the write port triggers an unwanted write
uInt8 value = mySystem->getDataBusState(0xFF);
if(myBankLocked) return value;
else return myRAM[address] = value;
if(myBankLocked)
return value;
else
{
triggerReadFromWritePort(peekAddress);
return myRAM[address] = value;
}
}
else
return myImage[(myCurrentBank << 12) + address];

View File

@ -50,7 +50,7 @@ M6502::M6502(uInt32 systemCyclesPerProcessorCycle)
// Compute the System Cycle table
for(uInt32 t = 0; t < 256; ++t)
{
myInstructionSystemCycleTable[t] = InstructionCycleTable[t] *
myInstructionSystemCycleTable[t] = ourInstructionCycleTable[t] *
mySystemCyclesPerProcessorCycle;
}
@ -537,173 +537,7 @@ void M6502::setTraps(PackedBitArray *read, PackedBitArray *write)
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
M6502::AddressingMode M6502::AddressModeTable[256] = {
Implied, IndirectX, Invalid, IndirectX, // 0x0?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Absolute, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0x1?
ZeroX, ZeroX, ZeroX, ZeroX,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX,
Absolute, IndirectX, Invalid, IndirectX, // 0x2?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Absolute, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0x3?
ZeroX, ZeroX, ZeroX, ZeroX,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX,
Implied, IndirectX, Invalid, IndirectX, // 0x4?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Absolute, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0x5?
ZeroX, ZeroX, ZeroX, ZeroX,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX,
Implied, IndirectX, Invalid, IndirectX, // 0x6?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Indirect, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0x7?
ZeroX, ZeroX, ZeroX, ZeroX,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX,
Immediate, IndirectX, Immediate, IndirectX, // 0x8?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Absolute, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0x9?
ZeroX, ZeroX, ZeroY, ZeroY,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteY, AbsoluteY,
Immediate, IndirectX, Immediate, IndirectX, // 0xA?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Absolute, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0xB?
ZeroX, ZeroX, ZeroY, ZeroY,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteY, AbsoluteY,
Immediate, IndirectX, Immediate, IndirectX, // 0xC?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Absolute, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0xD?
ZeroX, ZeroX, ZeroX, ZeroX,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX,
Immediate, IndirectX, Immediate, IndirectX, // 0xE?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Absolute, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0xF?
ZeroX, ZeroX, ZeroX, ZeroX,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
M6502::AccessMode M6502::AccessModeTable[256] = {
None, Read, None, Write, // 0x0?
None, Read, Write, Write,
None, Read, Write, Read,
None, Read, Write, Write,
Read, Read, None, Write, // 0x1?
None, Read, Write, Write,
None, Read, None, Write,
None, Read, Write, Write,
Read, Read, None, Write, // 0x2?
Read, Read, Write, Write,
None, Read, Write, Read,
Read, Read, Write, Write,
Read, Read, None, Write, // 0x3?
None, Read, Write, Write,
None, Read, None, Write,
None, Read, Write, Write,
None, Read, None, Write, // 0x4?
None, Read, Write, Write,
None, Read, Write, Read,
Read, Read, Write, Write,
Read, Read, None, Write, // 0x5?
None, Read, Write, Write,
None, Read, None, Write,
None, Read, Write, Write,
None, Read, None, Write, // 0x6?
None, Read, Write, Write,
None, Read, Write, Read,
Read, Read, Write, Write,
Read, Read, None, Write, // 0x7?
None, Read, Write, Write,
None, Read, None, Write,
None, Read, Write, Write,
None, Write, None, Write, // 0x8?
Write, Write, Write, Write,
None, None, None, Read,
Write, Write, Write, Write,
Read, Write, None, Write, // 0x9?
Write, Write, Write, Write,
None, Write, None, Write,
Write, Write, Write, Write,
Read, Read, Read, Read, // 0xA?
Read, Read, Read, Read,
None, Read, None, Read,
Read, Read, Read, Read,
Read, Read, None, Read, // 0xB?
Read, Read, Read, Read,
None, Read, None, Read,
Read, Read, Read, Read,
Read, Read, None, Write, // 0xC?
Read, Read, Write, Write,
None, Read, None, Read,
Read, Read, Write, Write,
Read, Read, None, Write, // 0xD?
None, Read, Write, Write,
None, Read, None, Write,
None, Read, Write, Write,
Read, Read, None, Write, // 0xE?
Read, Read, Write, Write,
None, Read, None, Read,
Read, Read, Write, Write,
Read, Read, None, Write, // 0xF?
None, Read, Write, Write,
None, Read, None, Write,
None, Read, Write, Write
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 M6502::InstructionCycleTable[256] = {
uInt32 M6502::ourInstructionCycleTable[256] = {
// 0 1 2 3 4 5 6 7 8 9 a b c d e f
7, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 4, 4, 6, 6, // 0
2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, // 1
@ -721,55 +555,4 @@ uInt32 M6502::InstructionCycleTable[256] = {
2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, // d
2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, // e
2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7 // f
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* M6502::InstructionMnemonicTable[256] = {
"BRK", "ORA", "n/a", "slo", "nop", "ORA", "ASL", "slo", // 0x0?
"PHP", "ORA", "ASLA", "anc", "nop", "ORA", "ASL", "slo",
"BPL", "ORA", "n/a", "slo", "nop", "ORA", "ASL", "slo", // 0x1?
"CLC", "ORA", "nop", "slo", "nop", "ORA", "ASL", "slo",
"JSR", "AND", "n/a", "rla", "BIT", "AND", "ROL", "rla", // 0x2?
"PLP", "AND", "ROLA", "anc", "BIT", "AND", "ROL", "rla",
"BMI", "AND", "n/a", "rla", "nop", "AND", "ROL", "rla", // 0x3?
"SEC", "AND", "nop", "rla", "nop", "AND", "ROL", "rla",
"RTI", "EOR", "n/a", "sre", "nop", "EOR", "LSR", "sre", // 0x4?
"PHA", "EOR", "LSRA", "asr", "JMP", "EOR", "LSR", "sre",
"BVC", "EOR", "n/a", "sre", "nop", "EOR", "LSR", "sre", // 0x5?
"CLI", "EOR", "nop", "sre", "nop", "EOR", "LSR", "sre",
"RTS", "ADC", "n/a", "rra", "nop", "ADC", "ROR", "rra", // 0x6?
"PLA", "ADC", "RORA", "arr", "JMP", "ADC", "ROR", "rra",
"BVS", "ADC", "n/a", "rra", "nop", "ADC", "ROR", "rra", // 0x7?
"SEI", "ADC", "nop", "rra", "nop", "ADC", "ROR", "rra",
"nop", "STA", "nop", "sax", "STY", "STA", "STX", "sax", // 0x8?
"DEY", "nop", "TXA", "ane", "STY", "STA", "STX", "sax",
"BCC", "STA", "n/a", "sha", "STY", "STA", "STX", "sax", // 0x9?
"TYA", "STA", "TXS", "shs", "shy", "STA", "shx", "sha",
"LDY", "LDA", "LDX", "lax", "LDY", "LDA", "LDX", "lax", // 0xA?
"TAY", "LDA", "TAX", "lxa", "LDY", "LDA", "LDX", "lax",
"BCS", "LDA", "n/a", "lax", "LDY", "LDA", "LDX", "lax", // 0xB?
"CLV", "LDA", "TSX", "las", "LDY", "LDA", "LDX", "lax",
"CPY", "CMP", "nop", "dcp", "CPY", "CMP", "DEC", "dcp", // 0xC?
"INY", "CMP", "DEX", "sbx", "CPY", "CMP", "DEC", "dcp",
"BNE", "CMP", "n/a", "dcp", "nop", "CMP", "DEC", "dcp", // 0xD?
"CLD", "CMP", "nop", "dcp", "nop", "CMP", "DEC", "dcp",
"CPX", "SBC", "nop", "isb", "CPX", "SBC", "INC", "isb", // 0xE?
"INX", "SBC", "NOP", "sbc", "CPX", "SBC", "INC", "isb",
"BEQ", "SBC", "n/a", "isb", "nop", "SBC", "INC", "isb", // 0xF?
"SED", "SBC", "nop", "isb", "nop", "SBC", "INC", "isb"
};

View File

@ -19,7 +19,6 @@
#ifndef M6502_HXX
#define M6502_HXX
class D6502;
class M6502;
class Debugger;
class CpuDebug;
@ -49,8 +48,9 @@ typedef Common::Array<Expression*> ExpressionList;
*/
class M6502 : public Serializable
{
// The 6502 debugger class is a friend who needs special access
friend class CpuDebug;
// The 6502 and Cart debugger classes are friends who need special access
friend class CartDebug;
friend class CpuDebug;
public:
/**
@ -132,7 +132,7 @@ class M6502 : public Serializable
*/
bool lastAccessWasRead() const { return myLastAccessWasRead; }
/**
/**
Return the last address that was part of a read/peek. Note that
reads which are part of a write are not considered here, unless
they're not the same as the last write address. This eliminates
@ -315,40 +315,11 @@ class M6502 : public Serializable
#endif
private:
/**
Enumeration of the 6502 addressing modes
*/
enum AddressingMode
{
Absolute, AbsoluteX, AbsoluteY, Immediate, Implied,
Indirect, IndirectX, IndirectY, Invalid, Relative,
Zero, ZeroX, ZeroY
};
/**
Enumeration of the 6502 access modes
*/
enum AccessMode
{
Read, Write, None
};
/// Addressing mode for each of the 256 opcodes
/// This specifies how the opcode argument is addressed
static AddressingMode AddressModeTable[256];
/// Access mode for each of the 256 opcodes
/// This specifies how the opcode will access its argument
static AccessMode AccessModeTable[256];
/**
Table of instruction processor cycle times. In some cases additional
cycles will be added during the execution of an instruction.
*/
static uInt32 InstructionCycleTable[256];
/// Table of instruction mnemonics
static const char* InstructionMnemonicTable[256];
static uInt32 ourInstructionCycleTable[256];
};
#endif

View File

@ -734,7 +734,7 @@
>
</File>
<File
RelativePath="..\debugger\RamDebug.cxx"
RelativePath="..\debugger\CartDebug.cxx"
>
</File>
<File
@ -1352,7 +1352,7 @@
>
</File>
<File
RelativePath="..\debugger\RamDebug.hxx"
RelativePath="..\debugger\CartDebug.hxx"
>
</File>
<File

View File

@ -26,8 +26,8 @@
//#endif
#include "Expression.hxx"
#include "CartDebug.hxx"
#include "CpuDebug.hxx"
#include "RamDebug.hxx"
#include "TIADebug.hxx"
#include "DebuggerExpressions.hxx"
@ -42,22 +42,22 @@ string errMsg;
#include "y.tab.c"
const string& errorMessage() {
return errMsg;
return errMsg;
}
Expression *getResult() {
return result.exp;
lastExp = 0;
return result.exp;
lastExp = 0;
}
const char *input, *c;
enum {
ST_DEFAULT,
ST_IDENTIFIER,
ST_OPERATOR,
ST_SPACE
ST_DEFAULT,
ST_IDENTIFIER,
ST_OPERATOR,
ST_SPACE
};
int state = ST_DEFAULT;
@ -65,35 +65,35 @@ int state = ST_DEFAULT;
//extern int yylval; // bison provides this
void setInput(const char *in) {
input = c = in;
state = ST_DEFAULT;
input = c = in;
state = ST_DEFAULT;
}
int parse(const char *in) {
lastExp = 0;
errMsg = "(no error)";
setInput(in);
return yyparse();
lastExp = 0;
errMsg = "(no error)";
setInput(in);
return yyparse();
}
/* hand-rolled lexer. Hopefully faster than flex... */
inline bool is_base_prefix(char x) { return ( (x=='\\' || x=='$' || x=='#') ); }
inline bool is_identifier(char x) {
return ( (x>='0' && x<='9') ||
(x>='a' && x<='z') ||
(x>='A' && x<='Z') ||
x=='.' || x=='_' );
return ( (x>='0' && x<='9') ||
(x>='a' && x<='z') ||
(x>='A' && x<='Z') ||
x=='.' || x=='_' );
}
inline bool is_operator(char x) {
return ( (x=='+' || x=='-' || x=='*' ||
return ( (x=='+' || x=='-' || x=='*' ||
x=='/' || x=='<' || x=='>' ||
x=='|' || x=='&' || x=='^' ||
x=='!' || x=='~' || x=='(' ||
x==')' || x=='=' || x=='%' ||
x=='[' || x==']' ) );
x=='[' || x==']' ) );
}
// const_to_int converts a string into a number, in either the
@ -101,279 +101,266 @@ inline bool is_operator(char x) {
// Returns -1 on error, since negative numbers are the parser's
// responsibility, not the lexer's
int const_to_int(char *c) {
// what base is the input in?
BaseFormat base = Debugger::debugger().parser().base();
// what base is the input in?
BaseFormat base = Debugger::debugger().parser().base();
switch(*c) {
case '\\':
base = kBASE_2;
c++;
break;
switch(*c) {
case '\\':
base = kBASE_2;
c++;
break;
case '#':
base = kBASE_10;
c++;
break;
case '#':
base = kBASE_10;
c++;
break;
case '$':
base = kBASE_16;
c++;
break;
case '$':
base = kBASE_16;
c++;
break;
default: // not a base_prefix, use default base
break;
}
default: // not a base_prefix, use default base
break;
}
int ret = 0;
switch(base) {
case kBASE_2:
while(*c) {
if(*c != '0' && *c != '1')
return -1;
ret *= 2;
ret += (*c - '0');
c++;
}
return ret;
int ret = 0;
switch(base) {
case kBASE_2:
while(*c) {
if(*c != '0' && *c != '1')
return -1;
ret *= 2;
ret += (*c - '0');
c++;
}
return ret;
case kBASE_10:
while(*c) {
if(!isdigit(*c))
return -1;
ret *= 10;
ret += (*c - '0');
c++;
}
return ret;
case kBASE_10:
while(*c) {
if(!isdigit(*c))
return -1;
ret *= 10;
ret += (*c - '0');
c++;
}
return ret;
case kBASE_16:
while(*c) { // FIXME: error check!
if(!isxdigit(*c))
return -1;
int dig = (*c - '0');
if(dig > 9) dig = tolower(*c) - 'a' + 10;
ret *= 16;
ret += dig;
c++;
}
return ret;
case kBASE_16:
while(*c) { // FIXME: error check!
if(!isxdigit(*c))
return -1;
int dig = (*c - '0');
if(dig > 9) dig = tolower(*c) - 'a' + 10;
ret *= 16;
ret += dig;
c++;
}
return ret;
default:
fprintf(stderr, "INVALID BASE in lexer!");
return 0;
}
default:
fprintf(stderr, "INVALID BASE in lexer!");
return 0;
}
}
// TODO: store in a map or something
// special methods that get e.g. CPU registers
CPUDEBUG_INT_METHOD getCpuSpecial(char *c) {
if(strcmp(c, "a") == 0)
return &CpuDebug::a;
if(strcmp(c, "x") == 0)
return &CpuDebug::x;
if(strcmp(c, "y") == 0)
return &CpuDebug::y;
if(strcmp(c, "pc") == 0)
return &CpuDebug::pc;
if(strcmp(c, "sp") == 0)
return &CpuDebug::sp;
if(strcmp(c, "c") == 0)
return &CpuDebug::c;
if(strcmp(c, "z") == 0)
return &CpuDebug::z;
if(strcmp(c, "n") == 0)
return &CpuDebug::n;
if(strcmp(c, "v") == 0)
return &CpuDebug::v;
if(strcmp(c, "d") == 0)
return &CpuDebug::d;
if(strcmp(c, "i") == 0)
return &CpuDebug::i;
if(strcmp(c, "b") == 0)
return &CpuDebug::b;
if(strcmp(c, "_bank") == 0)
return &CpuDebug::getBank;
return 0;
CPUDEBUG_INT_METHOD getCpuSpecial(char *c)
{
if(strcmp(c, "a") == 0)
return &CpuDebug::a;
else if(strcmp(c, "x") == 0)
return &CpuDebug::x;
else if(strcmp(c, "y") == 0)
return &CpuDebug::y;
else if(strcmp(c, "pc") == 0)
return &CpuDebug::pc;
else if(strcmp(c, "sp") == 0)
return &CpuDebug::sp;
else if(strcmp(c, "c") == 0)
return &CpuDebug::c;
else if(strcmp(c, "z") == 0)
return &CpuDebug::z;
else if(strcmp(c, "n") == 0)
return &CpuDebug::n;
else if(strcmp(c, "v") == 0)
return &CpuDebug::v;
else if(strcmp(c, "d") == 0)
return &CpuDebug::d;
else if(strcmp(c, "i") == 0)
return &CpuDebug::i;
else if(strcmp(c, "b") == 0)
return &CpuDebug::b;
else
return 0;
}
// special methods that get RAM internal state
RAMDEBUG_INT_METHOD getRamSpecial(char *c) {
if(strcmp(c, "_rwport") == 0)
return &RamDebug::readFromWritePort;
return 0;
// special methods that get Cart RAM/ROM internal state
CARTDEBUG_INT_METHOD getCartSpecial(char *c)
{
if(strcmp(c, "_bank") == 0)
return &CartDebug::getBank;
else if(strcmp(c, "_rwport") == 0)
return &CartDebug::readFromWritePort;
else
return 0;
}
// special methods that get TIA internal state
TIADEBUG_INT_METHOD getTiaSpecial(char *c) {
if(strcmp(c, "_scan") == 0)
return &TIADebug::scanlines;
if(strcmp(c, "_fcount") == 0)
return &TIADebug::frameCount;
if(strcmp(c, "_cclocks") == 0)
return &TIADebug::clocksThisLine;
if(strcmp(c, "_vsync") == 0)
return &TIADebug::vsyncAsInt;
if(strcmp(c, "_vblank") == 0)
return &TIADebug::vblankAsInt;
return 0;
TIADEBUG_INT_METHOD getTiaSpecial(char *c)
{
if(strcmp(c, "_scan") == 0)
return &TIADebug::scanlines;
else if(strcmp(c, "_fcount") == 0)
return &TIADebug::frameCount;
else if(strcmp(c, "_cclocks") == 0)
return &TIADebug::clocksThisLine;
else if(strcmp(c, "_vsync") == 0)
return &TIADebug::vsyncAsInt;
else if(strcmp(c, "_vblank") == 0)
return &TIADebug::vblankAsInt;
else
return 0;
}
int yylex() {
static char idbuf[255];
char o, p;
yylval.val = 0;
while(*c != '\0') {
//fprintf(stderr, "looking at %c, state %d\n", *c, state);
switch(state) {
case ST_SPACE:
yylval.val = 0;
if(isspace(*c)) {
c++;
} else if(is_identifier(*c) || is_base_prefix(*c)) {
state = ST_IDENTIFIER;
} else if(is_operator(*c)) {
state = ST_OPERATOR;
} else {
state = ST_DEFAULT;
}
static char idbuf[255];
char o, p;
yylval.val = 0;
while(*c != '\0') {
//fprintf(stderr, "looking at %c, state %d\n", *c, state);
switch(state) {
case ST_SPACE:
yylval.val = 0;
if(isspace(*c)) {
c++;
} else if(is_identifier(*c) || is_base_prefix(*c)) {
state = ST_IDENTIFIER;
} else if(is_operator(*c)) {
state = ST_OPERATOR;
} else {
state = ST_DEFAULT;
}
break;
break;
case ST_IDENTIFIER:
{
CPUDEBUG_INT_METHOD cpuMeth;
RAMDEBUG_INT_METHOD ramMeth;
TIADEBUG_INT_METHOD tiaMeth;
case ST_IDENTIFIER:
{
CARTDEBUG_INT_METHOD cartMeth;
CPUDEBUG_INT_METHOD cpuMeth;
TIADEBUG_INT_METHOD tiaMeth;
char *bufp = idbuf;
*bufp++ = *c++; // might be a base prefix
while(is_identifier(*c)) { // may NOT be base prefixes
*bufp++ = *c++;
//fprintf(stderr, "yylval==%d, *c==%c\n", yylval, *c);
}
*bufp = '\0';
state = ST_DEFAULT;
char *bufp = idbuf;
*bufp++ = *c++; // might be a base prefix
while(is_identifier(*c)) { // may NOT be base prefixes
*bufp++ = *c++;
//fprintf(stderr, "yylval==%d, *c==%c\n", yylval, *c);
}
*bufp = '\0';
state = ST_DEFAULT;
// Note: specials (like "a" for accumulator) have priority over
// numbers. So "a" always means accumulator, not hex 0xa. User
// is welcome to use a base prefix ("$a"), or a capital "A",
// to mean 0xa.
// Note: specials (like "a" for accumulator) have priority over
// numbers. So "a" always means accumulator, not hex 0xa. User
// is welcome to use a base prefix ("$a"), or a capital "A",
// to mean 0xa.
// Also, labels have priority over specials, so Bad Things will
// happen if the user defines a label that matches one of
// the specials. Who would do that, though?
// Also, labels have priority over specials, so Bad Things will
// happen if the user defines a label that matches one of
// the specials. Who would do that, though?
if(Debugger::debugger().equates().getAddress(idbuf) > -1) {
yylval.equate = idbuf;
return EQUATE;
} else if( (cpuMeth = getCpuSpecial(idbuf)) ) {
yylval.cpuMethod = cpuMeth;
return CPU_METHOD;
} else if( (ramMeth = getRamSpecial(idbuf)) ) {
yylval.ramMethod = ramMeth;
return RAM_METHOD;
} else if( (tiaMeth = getTiaSpecial(idbuf)) ) {
yylval.tiaMethod = tiaMeth;
return TIA_METHOD;
} else if( Debugger::debugger().getFunction(idbuf) != 0) {
yylval.function = idbuf;
return FUNCTION;
} else {
yylval.val = const_to_int(idbuf);
if(yylval.val >= 0)
return NUMBER;
else
return ERR;
}
}
if(Debugger::debugger().cartDebug().getAddress(idbuf) > -1) {
yylval.equate = idbuf;
return EQUATE;
} else if( (cpuMeth = getCpuSpecial(idbuf)) ) {
yylval.cpuMethod = cpuMeth;
return CPU_METHOD;
} else if( (cartMeth = getCartSpecial(idbuf)) ) {
yylval.cartMethod = cartMeth;
return CART_METHOD;
} else if( (tiaMeth = getTiaSpecial(idbuf)) ) {
yylval.tiaMethod = tiaMeth;
return TIA_METHOD;
} else if( Debugger::debugger().getFunction(idbuf) != 0) {
yylval.function = idbuf;
return FUNCTION;
} else {
yylval.val = const_to_int(idbuf);
if(yylval.val >= 0)
return NUMBER;
else
return ERR;
}
}
case ST_OPERATOR:
o = *c++;
if(!*c) return o;
if(isspace(*c)) {
state = ST_SPACE;
return o;
} else if(is_identifier(*c) || is_base_prefix(*c)) {
state = ST_IDENTIFIER;
return o;
} else {
state = ST_DEFAULT;
p = *c++;
//fprintf(stderr, "o==%c, p==%c\n", o, p);
if(o == '>' && p == '=')
return GTE;
else if(o == '<' && p == '=')
return LTE;
else if(o == '!' && p == '=')
return NE;
else if(o == '=' && p == '=')
return EQ;
else if(o == '|' && p == '|')
return LOG_OR;
else if(o == '&' && p == '&')
return LOG_AND;
else if(o == '<' && p == '<')
return SHL;
else if(o == '>' && p == '>')
return SHR;
else {
c--;
return o;
}
}
case ST_OPERATOR:
o = *c++;
if(!*c) return o;
if(isspace(*c)) {
state = ST_SPACE;
return o;
} else if(is_identifier(*c) || is_base_prefix(*c)) {
state = ST_IDENTIFIER;
return o;
} else {
state = ST_DEFAULT;
p = *c++;
//fprintf(stderr, "o==%c, p==%c\n", o, p);
if(o == '>' && p == '=')
return GTE;
else if(o == '<' && p == '=')
return LTE;
else if(o == '!' && p == '=')
return NE;
else if(o == '=' && p == '=')
return EQ;
else if(o == '|' && p == '|')
return LOG_OR;
else if(o == '&' && p == '&')
return LOG_AND;
else if(o == '<' && p == '<')
return SHL;
else if(o == '>' && p == '>')
return SHR;
else {
c--;
return o;
}
}
break;
break;
case ST_DEFAULT:
default:
yylval.val = 0;
if(isspace(*c)) {
state = ST_SPACE;
} else if(is_identifier(*c) || is_base_prefix(*c)) {
state = ST_IDENTIFIER;
} else if(is_operator(*c)) {
state = ST_OPERATOR;
} else {
yylval.val = *c++;
return yylval.val;
}
break;
}
}
case ST_DEFAULT:
default:
yylval.val = 0;
if(isspace(*c)) {
state = ST_SPACE;
} else if(is_identifier(*c) || is_base_prefix(*c)) {
state = ST_IDENTIFIER;
} else if(is_operator(*c)) {
state = ST_OPERATOR;
} else {
yylval.val = *c++;
return yylval.val;
}
break;
}
}
//fprintf(stderr, "end of input\n");
return 0; // hit NUL, end of input.
//fprintf(stderr, "end of input\n");
return 0; // hit NUL, end of input.
}
#if 0
int main(int argc, char **argv) {
int l;
int l;
set_input(argv[1]);
while( (l = yylex()) != 0 )
printf("ret %d, %d\n", l, yylval);
set_input(argv[1]);
while( (l = yylex()) != 0 )
printf("ret %d, %d\n", l, yylval);
printf("%d\n", yylval);
printf("%d\n", yylval);
}
#endif
}

View File

@ -6,7 +6,7 @@ Expression* lastExp = 0;
#define YYERROR_VERBOSE 1
/* dump Expression stack during parsing? */
#define DEBUG_EXP 0
#define DEBUG_EXP 1
/* #define DEBUG_EXP 1 */
int yylex();
@ -29,9 +29,9 @@ void yyerror(const char *e) {
%union {
int val;
char *equate;
CPUDEBUG_INT_METHOD cpuMethod;
RAMDEBUG_INT_METHOD ramMethod;
TIADEBUG_INT_METHOD tiaMethod;
CARTDEBUG_INT_METHOD cartMethod;
CPUDEBUG_INT_METHOD cpuMethod;
TIADEBUG_INT_METHOD tiaMethod;
Expression *exp;
char *function;
}
@ -40,9 +40,9 @@ void yyerror(const char *e) {
%token <val> NUMBER
%token <val> ERR
%token <equate> EQUATE
%token <cpuMethod> CPU_METHOD
%token <ramMethod> RAM_METHOD
%token <tiaMethod> TIA_METHOD
%token <cartMethod> CART_METHOD
%token <cpuMethod> CPU_METHOD
%token <tiaMethod> TIA_METHOD
%token <function> FUNCTION
/* Non-terminals */
@ -97,9 +97,9 @@ expression: expression '+' expression { if(DEBUG_EXP) fprintf(stderr, " +"); $$
| NUMBER { if(DEBUG_EXP) fprintf(stderr, " %d", $1); $$ = new ConstExpression($1); lastExp = $$; }
| EQUATE { if(DEBUG_EXP) fprintf(stderr, " %s", $1); $$ = new EquateExpression($1); lastExp = $$; }
| CPU_METHOD { if(DEBUG_EXP) fprintf(stderr, " (CpuMethod)"); $$ = new CpuMethodExpression($1); lastExp = $$; }
| RAM_METHOD { if(DEBUG_EXP) fprintf(stderr, " (RamMethod)"); $$ = new RamMethodExpression($1); lastExp = $$; }
| CART_METHOD { if(DEBUG_EXP) fprintf(stderr, " (CartMethod)"); $$ = new CartMethodExpression($1); lastExp = $$; }
| TIA_METHOD { if(DEBUG_EXP) fprintf(stderr, " (TiaMethod)"); $$ = new TiaMethodExpression($1); lastExp = $$; }
| FUNCTION { if(DEBUG_EXP) fprintf(stderr, " (function)"); $$ = new FunctionExpression($1); lastExp = $$; }
| ERR { if(DEBUG_EXP) fprintf(stderr, " ERR"); yyerror((char*)"Invalid label or constant"); return 1; }
| ERR { if(DEBUG_EXP) fprintf(stderr, " ERR: "); yyerror((char*)"Invalid label or constant"); return 1; }
;
%%

View File

@ -77,7 +77,7 @@ Expression* lastExp = 0;
#define YYERROR_VERBOSE 1
/* dump Expression stack during parsing? */
#define DEBUG_EXP 0
#define DEBUG_EXP 1
/* #define DEBUG_EXP 1 */
int yylex();
@ -128,8 +128,8 @@ void yyerror(const char *e) {
NUMBER = 258,
ERR = 259,
EQUATE = 260,
CPU_METHOD = 261,
RAM_METHOD = 262,
CART_METHOD = 261,
CPU_METHOD = 262,
TIA_METHOD = 263,
FUNCTION = 264,
LOG_OR = 265,
@ -149,8 +149,8 @@ void yyerror(const char *e) {
#define NUMBER 258
#define ERR 259
#define EQUATE 260
#define CPU_METHOD 261
#define RAM_METHOD 262
#define CART_METHOD 261
#define CPU_METHOD 262
#define TIA_METHOD 263
#define FUNCTION 264
#define LOG_OR 265
@ -177,9 +177,9 @@ typedef union YYSTYPE
int val;
char *equate;
CPUDEBUG_INT_METHOD cpuMethod;
RAMDEBUG_INT_METHOD ramMethod;
TIADEBUG_INT_METHOD tiaMethod;
CARTDEBUG_INT_METHOD cartMethod;
CPUDEBUG_INT_METHOD cpuMethod;
TIADEBUG_INT_METHOD tiaMethod;
Expression *exp;
char *function;
@ -489,7 +489,7 @@ static const yytype_int8 yyrhs[] =
32, 40, -1, 33, 40, -1, 12, 40, -1, 34,
40, -1, 23, 40, -1, 24, 40, -1, 35, 40,
36, -1, 40, 31, 40, 37, -1, 3, -1, 5,
-1, 6, -1, 7, -1, 8, -1, 9, -1, 4,
-1, 7, -1, 6, -1, 8, -1, 9, -1, 4,
-1
};
@ -508,8 +508,8 @@ static const yytype_uint8 yyrline[] =
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
"$end", "error", "$undefined", "NUMBER", "ERR", "EQUATE", "CPU_METHOD",
"RAM_METHOD", "TIA_METHOD", "FUNCTION", "'-'", "'+'", "'*'", "'/'",
"$end", "error", "$undefined", "NUMBER", "ERR", "EQUATE", "CART_METHOD",
"CPU_METHOD", "TIA_METHOD", "FUNCTION", "'-'", "'+'", "'*'", "'/'",
"'%'", "LOG_OR", "LOG_AND", "LOG_NOT", "'|'", "'^'", "'&'", "SHL", "SHR",
"'<'", "'>'", "EQ", "NE", "LTE", "GTE", "DEREF", "UMINUS", "'['", "'~'",
"'!'", "'@'", "'('", "')'", "']'", "$accept", "statement", "expression", 0
@ -551,7 +551,7 @@ static const yytype_uint8 yyr2[] =
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
0, 30, 36, 31, 32, 33, 34, 35, 0, 0,
0, 30, 36, 31, 33, 32, 34, 35, 0, 0,
0, 0, 0, 0, 0, 0, 0, 2, 21, 24,
26, 27, 22, 23, 25, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -1687,7 +1687,7 @@ yyreduce:
/* Line 1455 of yacc.c */
#line 100 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " (RamMethod)"); (yyval.exp) = new RamMethodExpression((yyvsp[(1) - (1)].ramMethod)); lastExp = (yyval.exp); }
{ if(DEBUG_EXP) fprintf(stderr, " (CartMethod)"); (yyval.exp) = new CartMethodExpression((yyvsp[(1) - (1)].cartMethod)); lastExp = (yyval.exp); }
break;
case 34:
@ -1708,7 +1708,7 @@ yyreduce:
/* Line 1455 of yacc.c */
#line 103 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " ERR"); yyerror((char*)"Invalid label or constant"); return 1; }
{ if(DEBUG_EXP) fprintf(stderr, " ERR: "); yyerror((char*)"Invalid label or constant"); return 1; }
break;

View File

@ -42,8 +42,8 @@
NUMBER = 258,
ERR = 259,
EQUATE = 260,
CPU_METHOD = 261,
RAM_METHOD = 262,
CART_METHOD = 261,
CPU_METHOD = 262,
TIA_METHOD = 263,
FUNCTION = 264,
LOG_OR = 265,
@ -63,8 +63,8 @@
#define NUMBER 258
#define ERR 259
#define EQUATE 260
#define CPU_METHOD 261
#define RAM_METHOD 262
#define CART_METHOD 261
#define CPU_METHOD 262
#define TIA_METHOD 263
#define FUNCTION 264
#define LOG_OR 265
@ -91,9 +91,9 @@ typedef union YYSTYPE
int val;
char *equate;
CPUDEBUG_INT_METHOD cpuMethod;
RAMDEBUG_INT_METHOD ramMethod;
TIADEBUG_INT_METHOD tiaMethod;
CARTDEBUG_INT_METHOD cartMethod;
CPUDEBUG_INT_METHOD cpuMethod;
TIADEBUG_INT_METHOD tiaMethod;
Expression *exp;
char *function;