mirror of https://github.com/stella-emu/stella.git
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:
parent
4238125b69
commit
a9609b026a
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
||||
}')
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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]; }
|
||||
|
|
Loading…
Reference in New Issue