Got rid of M6502Low class. No ROM uses it any more, and hasn't for at

least 6 months now. This shouldn't affect anyone running Stella on a
CPU faster than a pentium-166 or -200 anyway.

Implemented a few new debugger commands: "listtraps", "saveses", "savesym",
"undef", and renamed "label" to "define"... See the console help for
details.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@546 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
urchlay 2005-06-23 01:10:26 +00:00
parent 4238125b69
commit a9609b026a
13 changed files with 173 additions and 5081 deletions

View File

@ -13,7 +13,7 @@
## See the file "license" for information on usage and redistribution of
## this file, and for a DISCLAIMER OF ALL WARRANTIES.
##
## $Id: makefile,v 1.104 2005-06-21 18:46:32 stephena Exp $
## $Id: makefile,v 1.105 2005-06-23 01:10:25 urchlay Exp $
##============================================================================
##============================================================================
@ -153,7 +153,7 @@ win32-gl:
###############################################################################
## List of "core" object files
###############################################################################
M6502_OBJS = D6502.o Device.o M6502.o M6502Low.o M6502Hi.o NullDev.o System.o
M6502_OBJS = D6502.o Device.o M6502.o M6502Hi.o NullDev.o System.o
GUI_OBJS = Font.o Menu.o Launcher.o \
Widget.o PopUpWidget.o ScrollBarWidget.o ListWidget.o TabWidget.o \
@ -180,15 +180,9 @@ CORE_OBJS = Booster.o Cart.o Cart2K.o Cart3F.o Cart4K.o CartAR.o CartDPC.o \
stella: $(CORE_OBJS) $(OBJS)
$(LD) -o $(EXE_NAME) $(CORE_OBJS) $(OBJS) $(LDFLAGS) $(LDLIBS)
M6502Low.ins: $(CORE)/m6502/src/M6502Low.m4 $(CORE)/m6502/src/M6502.m4
m4 $(CORE)/m6502/src/M6502Low.m4 $(CORE)/m6502/src/M6502.m4 > $(CORE)/m6502/src/M6502Low.ins
M6502Hi.ins: $(CORE)/m6502/src/M6502Hi.m4 $(CORE)/m6502/src/M6502.m4
m4 $(CORE)/m6502/src/M6502Hi.m4 $(CORE)/m6502/src/M6502.m4 > $(CORE)/m6502/src/M6502Hi.ins
#M6502Low.o: M6502Low.ins
#M6502Hi.o: M6502Hi.ins
clean:
rm -f *.o stella stella.exe core
@ -372,9 +366,6 @@ Device.o: $(CORE)/m6502/src/Device.cxx
M6502.o: $(CORE)/m6502/src/M6502.cxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/m6502/src/M6502.cxx
M6502Low.o: $(CORE)/m6502/src/M6502Low.cxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(CORE)/m6502/src/M6502Low.cxx
M6502Hi.o: $(CORE)/m6502/src/M6502Hi.cxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(CORE)/m6502/src/M6502Hi.cxx

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Debugger.hxx,v 1.25 2005-06-22 20:25:19 urchlay Exp $
// $Id: Debugger.hxx,v 1.26 2005-06-23 01:10:25 urchlay Exp $
//============================================================================
#ifndef DEBUGGER_HXX
@ -51,7 +51,7 @@ enum {
for all debugging operations in Stella (parser, 6502 debugger, etc).
@author Stephen Anthony
@version $Id: Debugger.hxx,v 1.25 2005-06-22 20:25:19 urchlay Exp $
@version $Id: Debugger.hxx,v 1.26 2005-06-23 01:10:25 urchlay Exp $
*/
class Debugger : public DialogContainer
{
@ -199,7 +199,7 @@ class Debugger : public DialogContainer
void formatFlags(int f, char *out);
EquateList *equates();
PromptWidget *prompt();
PromptWidget *prompt() { return myPrompt; }
string showWatches();
void addLabel(string label, int address);

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: DebuggerParser.cxx,v 1.26 2005-06-22 20:25:19 urchlay Exp $
// $Id: DebuggerParser.cxx,v 1.27 2005-06-23 01:10:25 urchlay Exp $
//============================================================================
#include "bspf.hxx"
@ -247,6 +247,24 @@ string DebuggerParser::listBreaks() {
return "no breakpoints set";
}
string DebuggerParser::listTraps() {
int count = 0;
string ret;
for(unsigned int i=0; i<0x10000; i++) {
if(debugger->readTrap(i) || debugger->writeTrap(i)) {
ret += trapStatus(i);
ret += "\n";
count++;
}
}
if(count)
return ret;
else
return "no traps set";
}
string DebuggerParser::disasm() {
int start, lines = 20;
@ -359,10 +377,22 @@ string DebuggerParser::trapStatus(int addr) {
string result;
result += debugger->valueToString(addr);
result += ": ";
if(debugger->readTrap(addr))
result += "read ";
if(debugger->writeTrap(addr))
result += "write ";
bool r = debugger->readTrap(addr);
bool w = debugger->writeTrap(addr);
if(r && w)
result += "read|write";
else if(r)
result += "read";
else if(w)
result += " write";
else result += " none ";
char *l = debugger->equateList->getLabel(addr);
if(l != NULL) {
result += " (";
result += l;
result += ")";
}
return result;
}
@ -375,9 +405,23 @@ string DebuggerParser::run(const string& command) {
if(subStringMatch(verb, "loadsym")) {
result = debugger->equateList->loadFile(argStrings[0]);
return result;
} else if(subStringMatch(verb, "label")) {
debugger->addLabel(argStrings[0], decipher_arg(argStrings[1]));
return "";
} else if(subStringMatch(verb, "savesym")) {
if(debugger->equateList->saveFile(argStrings[0]))
return "saved symbols to file " + argStrings[0];
else
return "I/O error";
} else if(subStringMatch(verb, "define")) {
int arg = decipher_arg(argStrings[1]);
if(arg < 0)
return "invalid argument";
debugger->addLabel(argStrings[0], arg);
return "label " + argStrings[0] + " defined as " + debugger->valueToString(arg);
} else if(subStringMatch(verb, "saveses")) {
if(debugger->prompt()->saveBuffer(argStrings[0]))
return "saved session to file " + argStrings[0];
else
return "I/O error";
} else {
return "invalid label or address";
}
@ -508,6 +552,8 @@ string DebuggerParser::run(const string& command) {
return "Cleared breakpoint";
} else if(subStringMatch(verb, "listbreaks")) {
return listBreaks();
} else if(subStringMatch(verb, "listtraps")) {
return listTraps();
} else if(subStringMatch(verb, "disasm")) {
return disasm();
} else if(subStringMatch(verb, "frame")) {
@ -535,6 +581,13 @@ string DebuggerParser::run(const string& command) {
return delWatch(args[0]);
else
return "one argument required";
} else if(subStringMatch(verb, "define")) {
return argStrings[0] + " already defined";
} else if(subStringMatch(verb, "undef")) {
if(debugger->equateList->undefine(argStrings[0]))
return argStrings[0] + " now undefined";
else
return "no such label";
} else if(subStringMatch(verb, "height")) {
if(argCount != 1)
return "one argument required";
@ -580,6 +633,8 @@ string DebuggerParser::run(const string& command) {
result += "Set base ";
result += buf;
return result;
} else if(subStringMatch(verb, "listsym")) {
return debugger->equateList->dumpAll();
} else if(subStringMatch(verb, "quit") || subStringMatch(verb, "run")) {
debugger->quit();
return "";
@ -600,14 +655,16 @@ string DebuggerParser::run(const string& command) {
"cleartraps - Clear all traps\n"
"clearwatches - Clear all watches\n"
"d - Toggle Decimal Flag\n"
"dump xx - Dump 128 bytes of memory starting at xx (may be ROM, TIA, RAM)\n"
"define ll xx - Define label ll with value xx\n"
"delwatch xx - Delete watch xx\n"
"disasm - Disassemble (from current PC)\n"
"disasm xx - Disassemble (from address xx)\n"
"dump xx - Dump 128 bytes of memory starting at xx (may be ROM, TIA, RAM)\n"
"frame - Advance to next TIA frame, then break\n"
"height xx - Set height of debugger window in pixels\n"
"height xx - Set height of debugger window in pixels (NOT WORKING)\n"
"listbreaks - List all breakpoints\n"
"*listtraps - List all traps\n"
"listtraps - List all traps\n"
"listsym - List all currently defined symbols\n"
"loadsym f - Load DASM symbols from file f\n"
"n - Toggle Negative Flag\n"
"pc xx - Set Program Counter to xx\n"
@ -618,15 +675,17 @@ string DebuggerParser::run(const string& command) {
"reset - Jump to 6502 init vector (does not reset TIA/RIOT)\n"
"run - Exit debugger (back to emulator)\n"
"s xx - Set Stack Pointer to xx\n"
"*save f - Save console session to file f\n"
"saveses f - Save console session to file f\n"
"savesym f - Save symbols to file f\n"
"step - Single-step\n"
"tia - Show TIA register contents\n"
"trace - Single-step treating subroutine calls as 1 instruction\n"
"trap xx - Trap any access to location xx (enter debugger on access)\n"
"trapread xx - Trap any read access from location xx\n"
"trapwrite xx - Trap any write access to location xx\n"
"undef ll - Undefine label ll (if defined)\n"
"v - Toggle Overflow Flag\n"
"watch xx - Print contents of location xx before every prompt\n"
"watch xx - Print contents of location xx before every prompt\n"
"x xx - Set X register to xx\n"
"y xx - Set Y register to xx\n"
"z - Toggle Zero Flag\n"

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: DebuggerParser.hxx,v 1.15 2005-06-21 23:01:25 stephena Exp $
// $Id: DebuggerParser.hxx,v 1.16 2005-06-23 01:10:25 urchlay Exp $
//============================================================================
#ifndef DEBUGGER_PARSER_HXX
@ -58,6 +58,7 @@ class DebuggerParser
bool subStringMatch(const string& needle, const string& haystack);
string disasm();
string listBreaks();
string listTraps();
string eval();
string dump();
string trapStatus(int addr);

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EquateList.cxx,v 1.13 2005-06-22 20:25:20 urchlay Exp $
// $Id: EquateList.cxx,v 1.14 2005-06-23 01:10:25 urchlay Exp $
//============================================================================
#include <string>
@ -23,6 +23,7 @@
#include "bspf.hxx"
#include "Equate.hxx"
#include "EquateList.hxx"
#include "Debugger.hxx"
// built in labels
static Equate hardCodedEquates[] = {
@ -150,12 +151,51 @@ int EquateList::getAddress(const char *lbl) {
for(int i=0; i<currentSize; i++) {
// cerr << "Looking at " << ourVcsEquates[i].label << endl;
if( STR_CASE_CMP(ourVcsEquates[i].label, lbl) == 0 )
return ourVcsEquates[i].address;
if(ourVcsEquates[i].address >= 0)
return ourVcsEquates[i].address;
}
return -1;
}
bool EquateList::undefine(string& label) {
return undefine(label.c_str());
}
bool EquateList::undefine(const char *lbl) {
for(int i=0; i<currentSize; i++) {
if( STR_CASE_CMP(ourVcsEquates[i].label, lbl) == 0 ) {
ourVcsEquates[i].address = -1;
return true;
}
}
return false;
}
bool EquateList::saveFile(string file) {
char buf[256];
ofstream out(file.c_str());
if(!out.is_open())
return false;
out << "--- Symbol List (sorted by symbol)" << endl;
int hardSize = sizeof(hardCodedEquates)/sizeof(struct Equate);
for(int i=hardSize; i<currentSize; i++) {
int a = ourVcsEquates[i].address;
if(a >= 0) {
sprintf(buf, "%-24s %04x \n", ourVcsEquates[i].label, a);
out << buf;
}
}
out << "--- End of Symbol List." << endl;
return true;
}
string EquateList::loadFile(string file) {
int lines = 0;
string curLabel;
@ -215,6 +255,7 @@ void EquateList::addEquate(string label, int address) {
}
int EquateList::parse4hex(char *c) {
//cerr << c << endl;
int ret = 0;
for(int i=0; i<4; i++) {
if(*c >= '0' && *c <= '9')
@ -253,7 +294,16 @@ string EquateList::extractLabel(char *c) {
return l;
}
void EquateList::dumpAll() {
for(int i=0; i<currentSize; i++)
cerr << i << ": " << "label==" << ourVcsEquates[i].label << ", address==" << ourVcsEquates[i].address << endl;
string EquateList::dumpAll() {
string ret;
for(int i=0; i<currentSize; i++) {
if(ourVcsEquates[i].address != -1) {
ret += ourVcsEquates[i].label;
ret += ": ";
ret += Debugger::to_hex_16(ourVcsEquates[i].address);
if(i != currentSize - 1) ret += "\n";
}
}
return ret;
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EquateList.hxx,v 1.7 2005-06-22 20:25:20 urchlay Exp $
// $Id: EquateList.hxx,v 1.8 2005-06-23 01:10:25 urchlay Exp $
//============================================================================
#ifndef EQUATELIST_HXX
@ -33,8 +33,11 @@ class EquateList {
char *getFormatted(int addr, int places);
int getAddress(const char *label);
void addEquate(string label, int address);
bool saveFile(string file);
string loadFile(string file);
void dumpAll();
bool undefine(string& label);
bool undefine(const char *lbl);
string dumpAll();
private:
int calcSize();

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Console.cxx,v 1.58 2005-06-21 04:30:49 urchlay Exp $
// $Id: Console.cxx,v 1.59 2005-06-23 01:10:25 urchlay Exp $
//============================================================================
#include <assert.h>
@ -30,7 +30,6 @@
#include "EventHandler.hxx"
#include "Joystick.hxx"
#include "Keyboard.hxx"
#include "M6502Low.hxx"
#include "M6502Hi.hxx"
#include "M6532.hxx"
#include "MD5.hxx"
@ -137,14 +136,7 @@ Console::Console(const uInt8* image, uInt32 size, OSystem* osystem)
mySystem = new System(13, 6);
M6502* m6502;
if(myProperties.get("Emulation.CPU") == "Low")
{
m6502 = new M6502Low(1);
}
else
{
m6502 = new M6502High(1);
}
m6502 = new M6502High(1);
m6502->attach(myOSystem->debugger());
M6532* m6532 = new M6532(*this);

View File

@ -1,255 +0,0 @@
//============================================================================
//
// MM MM 6666 555555 0000 2222
// MMMM MMMM 66 66 55 00 00 22 22
// MM MMM MM 66 55 00 00 22
// MM M MM 66666 55555 00 00 22222 -- "A 6502 Microprocessor Emulator"
// MM MM 66 66 55 00 00 22
// MM MM 66 66 55 55 00 00 22
// MM MM 6666 5555 0000 222222
//
// Copyright (c) 1995-2005 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: M6502Low.cxx,v 1.6 2005-06-17 03:49:10 urchlay Exp $
//============================================================================
#include "M6502Low.hxx"
#include "Serializer.hxx"
#include "Deserializer.hxx"
#include "Debugger.hxx"
#define debugStream cout
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
M6502Low::M6502Low(uInt32 systemCyclesPerProcessorCycle)
: M6502(systemCyclesPerProcessorCycle)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
M6502Low::~M6502Low()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline uInt8 M6502Low::peek(uInt16 address)
{
return mySystem->peek(address);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline void M6502Low::poke(uInt16 address, uInt8 value)
{
mySystem->poke(address, value);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool M6502Low::execute(uInt32 number)
{
// Clear all of the execution status bits except for the fatal error bit
myExecutionStatus &= FatalErrorBit;
// Loop until execution is stopped or a fatal error occurs
for(;;)
{
for(; !myExecutionStatus && (number != 0); --number)
{
uInt16 operandAddress = 0;
uInt8 operand = 0;
if(breakPoints != NULL)
{
if(breakPoints->isSet(PC))
if(myDebugger->start())
return true;
}
#ifdef DEBUG
debugStream << "PC=" << hex << setw(4) << PC << " ";
#endif
// Fetch instruction at the program counter
IR = peek(PC++);
#ifdef DEBUG
debugStream << "IR=" << hex << setw(2) << (int)IR << " ";
debugStream << "<" << ourAddressingModeTable[IR] << " ";
#endif
// Update system cycles
mySystem->incrementCycles(myInstructionSystemCycleTable[IR]);
// Call code to execute the instruction
switch(IR)
{
// 6502 instruction emulation is generated by an M4 macro file
#include "M6502Low.ins"
default:
// Oops, illegal instruction executed so set fatal error flag
myExecutionStatus |= FatalErrorBit;
cerr << "Illegal Instruction! " << hex << (int) IR << endl;
}
#ifdef DEBUG
debugStream << hex << setw(4) << operandAddress << " ";
debugStream << setw(4) << ourInstructionMnemonicTable[IR];
debugStream << "> ";
debugStream << "A=" << ::hex << setw(2) << (int)A << " ";
debugStream << "X=" << ::hex << setw(2) << (int)X << " ";
debugStream << "Y=" << ::hex << setw(2) << (int)Y << " ";
debugStream << "PS=" << ::hex << setw(2) << (int)PS() << " ";
debugStream << "SP=" << ::hex << setw(2) << (int)SP << " ";
debugStream << "Cyc=" << dec << mySystem->cycles();
debugStream << endl;
#endif
}
// See if we need to handle an interrupt
if((myExecutionStatus & MaskableInterruptBit) ||
(myExecutionStatus & NonmaskableInterruptBit))
{
// Yes, so handle the interrupt
interruptHandler();
}
// See if execution has been stopped
if(myExecutionStatus & StopExecutionBit)
{
// Yes, so answer that everything finished fine
return true;
}
// See if a fatal error has occured
if(myExecutionStatus & FatalErrorBit)
{
// Yes, so answer that something when wrong
return false;
}
// See if we've executed the specified number of instructions
if(number == 0)
{
// Yes, so answer that everything finished fine
return true;
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void M6502Low::interruptHandler()
{
// Handle the interrupt
if((myExecutionStatus & MaskableInterruptBit) && !I)
{
mySystem->incrementCycles(7 * mySystemCyclesPerProcessorCycle);
mySystem->poke(0x0100 + SP--, (PC - 1) >> 8);
mySystem->poke(0x0100 + SP--, (PC - 1) & 0x00ff);
mySystem->poke(0x0100 + SP--, PS() & (~0x10));
D = false;
I = true;
PC = (uInt16)mySystem->peek(0xFFFE) | ((uInt16)mySystem->peek(0xFFFF) << 8);
}
else if(myExecutionStatus & NonmaskableInterruptBit)
{
mySystem->incrementCycles(7 * mySystemCyclesPerProcessorCycle);
mySystem->poke(0x0100 + SP--, (PC - 1) >> 8);
mySystem->poke(0x0100 + SP--, (PC - 1) & 0x00ff);
mySystem->poke(0x0100 + SP--, PS() & (~0x10));
D = false;
PC = (uInt16)mySystem->peek(0xFFFA) | ((uInt16)mySystem->peek(0xFFFB) << 8);
}
// Clear the interrupt bits in myExecutionStatus
myExecutionStatus &= ~(MaskableInterruptBit | NonmaskableInterruptBit);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool M6502Low::save(Serializer& out)
{
string CPU = name();
try
{
out.putString(CPU);
out.putLong(A); // Accumulator
out.putLong(X); // X index register
out.putLong(Y); // Y index register
out.putLong(SP); // Stack Pointer
out.putLong(IR); // Instruction register
out.putLong(PC); // Program Counter
out.putBool(N); // N flag for processor status register
out.putBool(V); // V flag for processor status register
out.putBool(B); // B flag for processor status register
out.putBool(D); // D flag for processor status register
out.putBool(I); // I flag for processor status register
out.putBool(notZ); // Z flag complement for processor status register
out.putBool(C); // C flag for processor status register
out.putLong(myExecutionStatus);
}
catch(char *msg)
{
cerr << msg << endl;
return false;
}
catch(...)
{
cerr << "Unknown error in save state for " << CPU << endl;
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool M6502Low::load(Deserializer& in)
{
string CPU = name();
try
{
if(in.getString() != CPU)
return false;
A = (uInt8) in.getLong(); // Accumulator
X = (uInt8) in.getLong(); // X index register
Y = (uInt8) in.getLong(); // Y index register
SP = (uInt8) in.getLong(); // Stack Pointer
IR = (uInt8) in.getLong(); // Instruction register
PC = (uInt16) in.getLong(); // Program Counter
N = in.getBool(); // N flag for processor status register
V = in.getBool(); // V flag for processor status register
B = in.getBool(); // B flag for processor status register
D = in.getBool(); // D flag for processor status register
I = in.getBool(); // I flag for processor status register
notZ = in.getBool(); // Z flag complement for processor status register
C = in.getBool(); // C flag for processor status register
myExecutionStatus = (uInt8) in.getLong();
}
catch(char *msg)
{
cerr << msg << endl;
return false;
}
catch(...)
{
cerr << "Unknown error in load state for " << CPU << endl;
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* M6502Low::name() const
{
return "M6502Low";
}

View File

@ -1,119 +0,0 @@
//============================================================================
//
// MM MM 6666 555555 0000 2222
// MMMM MMMM 66 66 55 00 00 22 22
// MM MMM MM 66 55 00 00 22
// MM M MM 66666 55555 00 00 22222 -- "A 6502 Microprocessor Emulator"
// MM MM 66 66 55 00 00 22
// MM MM 66 66 55 55 00 00 22
// MM MM 6666 5555 0000 222222
//
// Copyright (c) 1995-2005 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: M6502Low.hxx,v 1.3 2005-06-16 01:11:29 stephena Exp $
//============================================================================
#ifndef M6507LOW_HXX
#define M6507LOW_HXX
class M6507Low;
class Serializer;
class Deserializer;
#include "bspf.hxx"
#include "M6502.hxx"
/**
This class provides a low compatibility 6502 microprocessor emulator.
The memory accesses and cycle updates of this emulator are not 100%
accurate as shown below:
1. Only memory accesses which are actually needed are done
(i.e. no "false" reads and writes are performed)
2. Cycle counts are updated at the beginning of the instruction
execution and not valid at the sub-instruction level
If speed is the most important issue then use this class, however, if
better compatibility is neccessary use one of the other 6502 classes.
@author Bradford W. Mott
@version $Id: M6502Low.hxx,v 1.3 2005-06-16 01:11:29 stephena Exp $
*/
class M6502Low : public M6502
{
public:
/**
Create a new low compatibility 6502 microprocessor with the specified
cycle multiplier.
@param systemCyclesPerProcessorCycle The cycle multiplier
*/
M6502Low(uInt32 systemCyclesPerProcessorCycle);
/**
Destructor
*/
virtual ~M6502Low();
public:
/**
Execute instructions until the specified number of instructions
is executed, someone stops execution, or an error occurs. Answers
true iff execution stops normally.
@param number Indicates the number of instructions to execute
@return true iff execution stops normally
*/
virtual bool execute(uInt32 number);
/**
Saves the current state of this device to the given Serializer.
@param out The serializer device to save to.
@return The result of the save. True on success, false on failure.
*/
virtual bool save(Serializer& out);
/**
Loads the current state of this device from the given Deserializer.
@param in The deserializer device to load from.
@return The result of the load. True on success, false on failure.
*/
virtual bool load(Deserializer& in);
/**
Get a null terminated string which is the processors's name (i.e. "M6532")
@return The name of the device
*/
virtual const char* name() const;
protected:
/**
Called after an interrupt has be requested using irq() or nmi()
*/
void interruptHandler();
protected:
/*
Get the byte at the specified address
@return The byte at the specified address
*/
inline uInt8 peek(uInt16 address);
/**
Change the byte at the specified address to the given value
@param address The address where the value should be stored
@param value The value to be stored at the address
*/
inline void poke(uInt16 address, uInt8 value);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,286 +0,0 @@
//============================================================================
//
// MM MM 6666 555555 0000 2222
// MMMM MMMM 66 66 55 00 00 22 22
// MM MMM MM 66 55 00 00 22
// MM M MM 66666 55555 00 00 22222 -- "A 6502 Microprocessor Emulator"
// MM MM 66 66 55 00 00 22
// MM MM 66 66 55 55 00 00 22
// MM MM 6666 5555 0000 222222
//
// Copyright (c) 1995-2005 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: M6502Low.m4,v 1.2 2005-06-16 01:11:29 stephena Exp $
//============================================================================
/**
Code to handle addressing modes and branch instructions for
low compatibility emulation
@author Bradford W. Mott
@version $Id: M6502Low.m4,v 1.2 2005-06-16 01:11:29 stephena Exp $
*/
#ifndef NOTSAMEPAGE
#define NOTSAMEPAGE(_addr1, _addr2) (((_addr1) ^ (_addr2)) & 0xff00)
#endif
define(M6502_IMPLIED, `{
}')
define(M6502_IMMEDIATE_READ, `{
operandAddress = PC++;
operand = peek(operandAddress);
}')
define(M6502_ABSOLUTE_READ, `{
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
PC += 2;
operand = peek(operandAddress);
}')
define(M6502_ABSOLUTE_WRITE, `{
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
PC += 2;
}')
define(M6502_ABSOLUTE_READMODIFYWRITE, `{
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
PC += 2;
operand = peek(operandAddress);
}')
define(M6502_ABSOLUTEX_READ, `{
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
PC += 2;
// See if we need to add one cycle for indexing across a page boundary
if(NOTSAMEPAGE(operandAddress, operandAddress + X))
{
mySystem->incrementCycles(mySystemCyclesPerProcessorCycle);
}
operandAddress += X;
operand = peek(operandAddress);
}')
define(M6502_ABSOLUTEX_WRITE, `{
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
PC += 2;
operandAddress += X;
}')
define(M6502_ABSOLUTEX_READMODIFYWRITE, `{
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
PC += 2;
operandAddress += X;
operand = peek(operandAddress);
}')
define(M6502_ABSOLUTEY_READ, `{
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
PC += 2;
// See if we need to add one cycle for indexing across a page boundary
if(NOTSAMEPAGE(operandAddress, operandAddress + Y))
{
mySystem->incrementCycles(mySystemCyclesPerProcessorCycle);
}
operandAddress += Y;
operand = peek(operandAddress);
}')
define(M6502_ABSOLUTEY_WRITE, `{
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
PC += 2;
operandAddress += Y;
}')
define(M6502_ABSOLUTEY_READMODIFYWRITE, `{
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
PC += 2;
operandAddress += Y;
operand = peek(operandAddress);
}')
define(M6502_ZERO_READ, `{
operandAddress = peek(PC++);
operand = peek(operandAddress);
}')
define(M6502_ZERO_WRITE, `{
operandAddress = peek(PC++);
}')
define(M6502_ZERO_READMODIFYWRITE, `{
operandAddress = peek(PC++);
operand = peek(operandAddress);
}')
define(M6502_ZEROX_READ, `{
operandAddress = (uInt8)(peek(PC++) + X);
operand = peek(operandAddress);
}')
define(M6502_ZEROX_WRITE, `{
operandAddress = (uInt8)(peek(PC++) + X);
}')
define(M6502_ZEROX_READMODIFYWRITE, `{
operandAddress = (uInt8)(peek(PC++) + X);
operand = peek(operandAddress);
}')
define(M6502_ZEROY_READ, `{
operandAddress = (uInt8)(peek(PC++) + Y);
operand = peek(operandAddress);
}')
define(M6502_ZEROY_WRITE, `{
operandAddress = (uInt8)(peek(PC++) + Y);
}')
define(M6502_ZEROY_READMODIFYWRITE, `{
operandAddress = (uInt8)(peek(PC++) + Y);
operand = peek(operandAddress);
}')
define(M6502_INDIRECT, `{
uInt16 addr = peek(PC) | ((uInt16)peek(PC + 1) << 8);
PC += 2;
// Simulate the error in the indirect addressing mode!
uInt16 high = NOTSAMEPAGE(addr, addr + 1) ? (addr & 0xff00) : (addr + 1);
operandAddress = peek(addr) | ((uInt16)peek(high) << 8);
}')
define(M6502_INDIRECTX_READ, `{
uInt8 pointer = peek(PC++) + X;
operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8);
operand = peek(operandAddress);
}')
define(M6502_INDIRECTX_WRITE, `{
uInt8 pointer = peek(PC++) + X;
operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8);
}')
define(M6502_INDIRECTX_READMODIFYWRITE, `{
uInt8 pointer = peek(PC++) + X;
operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8);
operand = peek(operandAddress);
}')
define(M6502_INDIRECTY_READ, `{
uInt8 pointer = peek(PC++);
operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8);
if(NOTSAMEPAGE(operandAddress, operandAddress + Y))
{
mySystem->incrementCycles(mySystemCyclesPerProcessorCycle);
}
operandAddress += Y;
operand = peek(operandAddress);
}')
define(M6502_INDIRECTY_WRITE, `{
uInt8 pointer = peek(PC++);
operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8);
operandAddress += Y;
}')
define(M6502_INDIRECTY_READMODIFYWRITE, `{
uInt8 pointer = peek(PC++);
operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8);
operandAddress += Y;
operand = peek(operandAddress);
}')
define(M6502_BCC, `{
if(!C)
{
uInt16 address = PC + (Int8)operand;
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
PC = address;
}
}')
define(M6502_BCS, `{
if(C)
{
uInt16 address = PC + (Int8)operand;
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
PC = address;
}
}')
define(M6502_BEQ, `{
if(!notZ)
{
uInt16 address = PC + (Int8)operand;
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
PC = address;
}
}')
define(M6502_BMI, `{
if(N)
{
uInt16 address = PC + (Int8)operand;
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
PC = address;
}
}')
define(M6502_BNE, `{
if(notZ)
{
uInt16 address = PC + (Int8)operand;
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
PC = address;
}
}')
define(M6502_BPL, `{
if(!N)
{
uInt16 address = PC + (Int8)operand;
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
PC = address;
}
}')
define(M6502_BVC, `{
if(!V)
{
uInt16 address = PC + (Int8)operand;
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
PC = address;
}
}')
define(M6502_BVS, `{
if(V)
{
uInt16 address = PC + (Int8)operand;
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
PC = address;
}
}')

View File

@ -13,12 +13,15 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: PromptWidget.cxx,v 1.11 2005-06-21 00:13:49 urchlay Exp $
// $Id: PromptWidget.cxx,v 1.12 2005-06-23 01:10:26 urchlay Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#include <iostream>
#include <fstream>
#include "ScrollBarWidget.hxx"
#include "FrameBuffer.hxx"
#include "EventHandler.hxx"
@ -683,3 +686,29 @@ void PromptWidget::scrollToCurrent()
updateScrollBuffer();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PromptWidget::saveBuffer(string& filename)
{
ofstream out(filename.c_str());
if(!out.is_open())
return false;
for(int start=0; start<_promptStartPos; start+=_lineWidth) {
int end = start+_lineWidth-1;
// look for first non-space char from end of line
while(_buffer[end] == ' ' && end >= start)
end--;
// spit out the line minus its trailing spaces
for(int j=start; j<=end; j++)
out << _buffer[j];
// add a \n
out << endl;
}
out.close();
return true;
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: PromptWidget.hxx,v 1.3 2005-06-17 03:49:10 urchlay Exp $
// $Id: PromptWidget.hxx,v 1.4 2005-06-23 01:10:26 urchlay Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -52,6 +52,7 @@ class PromptWidget : public Widget, public CommandSender
void print(const char *str);
void print(string str);
void printPrompt();
bool saveBuffer(string& filename);
protected:
inline char &buffer(int idx) { return _buffer[idx % kBufferSize]; }