mirror of https://github.com/stella-emu/stella.git
Added '_rwport' debugger directive, which can be used in conditional
breaks to test whether an illegal read to the write port of cartridge RAM has occurred. It can be used as follows: breakif {_rwport == 100} // break if read was done at wport address 100 breakif {_rwport} // break if read was done at *any* wport address This currently works for all extended RAM carts that worked before. Specifically, 4A50, DPC, AR and possibly several others aren't supported yet. More testing is required. Renamed CartFASC and CartMB to CartFA and CartF0, respectively. This naming now matches that used in other emulators. CartMC now properly handles read from write port, by using random values instead of just zero. However, no test ROMs are available for this scheme, so there may still be issues. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1896 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
3df721e0be
commit
54a5d77542
|
@ -21,8 +21,9 @@
|
|||
|
||||
#include "bspf.hxx"
|
||||
#include "CpuDebug.hxx"
|
||||
#include "Debugger.hxx"
|
||||
#include "RamDebug.hxx"
|
||||
#include "TIADebug.hxx"
|
||||
#include "Debugger.hxx"
|
||||
#include "Expression.hxx"
|
||||
|
||||
/**
|
||||
|
@ -258,6 +259,17 @@ class PlusExpression : public Expression
|
|||
uInt16 evaluate() { return myLHS->evaluate() + myRHS->evaluate(); }
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
class RamMethodExpression : public Expression
|
||||
{
|
||||
public:
|
||||
RamMethodExpression(RAMDEBUG_INT_METHOD method) : Expression(0, 0), myMethod(method) {}
|
||||
uInt16 evaluate() { return CALL_RAMDEBUG_METHOD(myMethod); }
|
||||
|
||||
private:
|
||||
RAMDEBUG_INT_METHOD myMethod;
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
class ShiftLeftExpression : public Expression
|
||||
{
|
||||
|
|
|
@ -931,8 +931,9 @@ void DebuggerParser::executeHelp()
|
|||
commandResult += "\nBuilt-in functions:\n";
|
||||
commandResult += debugger->builtinHelp();
|
||||
commandResult += "\nPseudo-registers:\n";
|
||||
commandResult += "_scan Current scanline count\n";
|
||||
commandResult += "_bank Currently selected bank\n";
|
||||
commandResult += "_rwport Read from a write port was triggered\n";
|
||||
commandResult += "_scan Current scanline count\n";
|
||||
commandResult += "_fcount Number of frames since emulation started\n";
|
||||
commandResult += "_cclocks Color clocks on current scanline\n";
|
||||
commandResult += "_vsync Whether vertical sync is enabled (1 or 0)\n";
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
RamDebug::RamDebug(Debugger& dbg, Console& console)
|
||||
: DebuggerSystem(dbg, console)
|
||||
: DebuggerSystem(dbg, console),
|
||||
myReadFromWritePortAddress(0)
|
||||
{
|
||||
// Zero-page RAM is always present
|
||||
addRamArea(0x80, 128, 0, 0);
|
||||
|
@ -80,6 +81,22 @@ void RamDebug::write(uInt16 addr, uInt8 value)
|
|||
mySystem.poke(addr, value);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int RamDebug::readFromWritePort()
|
||||
{
|
||||
int retval = myReadFromWritePortAddress;
|
||||
if(retval > 0)
|
||||
myReadFromWritePortAddress = 0;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void RamDebug::setReadFromWritePort(uInt16 address)
|
||||
{
|
||||
myReadFromWritePortAddress = address;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string RamDebug::toString()
|
||||
{
|
||||
|
|
|
@ -25,6 +25,12 @@ class System;
|
|||
#include "Array.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:
|
||||
|
@ -60,9 +66,22 @@ class RamDebug : public DebuggerSystem
|
|||
uInt8 read(uInt16 addr);
|
||||
void write(uInt16 addr, uInt8 value);
|
||||
|
||||
// These methods are used by the debugger when we wish to know
|
||||
// if an illegal read from a write port has been performed.
|
||||
// It's up to each Cartridge to report the error, and a
|
||||
// conditional breakpoint must be set in the debugger to check
|
||||
// for occurrences of this.
|
||||
//
|
||||
// Note that each time readFromWritePort() returns a hit, the status
|
||||
// is reset.
|
||||
int readFromWritePort();
|
||||
void setReadFromWritePort(uInt16 address);
|
||||
|
||||
private:
|
||||
RamState myState;
|
||||
RamState myOldState;
|
||||
|
||||
uInt16 myReadFromWritePortAddress;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,16 +34,16 @@
|
|||
#include "CartE7.hxx"
|
||||
#include "CartEF.hxx"
|
||||
#include "CartEFSC.hxx"
|
||||
#include "CartF0.hxx"
|
||||
#include "CartF4.hxx"
|
||||
#include "CartF4SC.hxx"
|
||||
#include "CartF6.hxx"
|
||||
#include "CartF6SC.hxx"
|
||||
#include "CartF8.hxx"
|
||||
#include "CartF8SC.hxx"
|
||||
#include "CartFASC.hxx"
|
||||
#include "CartFA.hxx"
|
||||
#include "CartFE.hxx"
|
||||
#include "CartMC.hxx"
|
||||
#include "CartMB.hxx"
|
||||
#include "CartCV.hxx"
|
||||
#include "CartUA.hxx"
|
||||
#include "CartSB.hxx"
|
||||
|
@ -51,6 +51,8 @@
|
|||
#include "MD5.hxx"
|
||||
#include "Props.hxx"
|
||||
#include "Settings.hxx"
|
||||
#include "Debugger.hxx"
|
||||
#include "RamDebug.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Cartridge* Cartridge::create(const uInt8* image, uInt32 size, string& md5,
|
||||
|
@ -163,13 +165,13 @@ Cartridge* Cartridge::create(const uInt8* image, uInt32 size, string& md5,
|
|||
else if(type == "F8SC")
|
||||
cartridge = new CartridgeF8SC(image);
|
||||
else if(type == "FA" || type == "FASC")
|
||||
cartridge = new CartridgeFASC(image);
|
||||
cartridge = new CartridgeFA(image);
|
||||
else if(type == "FE")
|
||||
cartridge = new CartridgeFE(image);
|
||||
else if(type == "MC")
|
||||
cartridge = new CartridgeMC(image, size);
|
||||
else if(type == "F0" || type == "MB")
|
||||
cartridge = new CartridgeMB(image);
|
||||
cartridge = new CartridgeF0(image);
|
||||
else if(type == "CV")
|
||||
cartridge = new CartridgeCV(image, size);
|
||||
else if(type == "UA")
|
||||
|
@ -257,6 +259,15 @@ void Cartridge::registerRamArea(uInt16 start, uInt16 size,
|
|||
myRamAreaList.push_back(area);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Cartridge::triggerReadFromWritePort(uInt16 address)
|
||||
{
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
if(&Debugger::debugger().ramDebug())
|
||||
Debugger::debugger().ramDebug().setReadFromWritePort(address);
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string Cartridge::autodetectType(const uInt8* image, uInt32 size)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <sstream>
|
||||
|
||||
class Cartridge;
|
||||
class System;
|
||||
class Properties;
|
||||
class Settings;
|
||||
|
||||
|
@ -79,7 +78,9 @@ class Cartridge : public Device
|
|||
bool save(ofstream& out);
|
||||
|
||||
/**
|
||||
Lock/unlock bankswitching capability.
|
||||
Lock/unlock bankswitching capability. The debugger will lock
|
||||
the banks before querying the cart state, otherwise reading values
|
||||
could inadvertantly cause a bankswitch to occur.
|
||||
*/
|
||||
void lockBank() { myBankLocked = true; }
|
||||
void unlockBank() { myBankLocked = false; }
|
||||
|
@ -172,6 +173,14 @@ class Cartridge : public Device
|
|||
*/
|
||||
void registerRamArea(uInt16 start, uInt16 size, uInt16 roffset, uInt16 woffset);
|
||||
|
||||
/**
|
||||
Indicate that an illegal read from the write port has occurred.
|
||||
This message is sent to the debugger (if support exists).
|
||||
|
||||
@param address The write port address where the read occurred
|
||||
*/
|
||||
void triggerReadFromWritePort(uInt16 address);
|
||||
|
||||
private:
|
||||
/**
|
||||
Get an image pointer and size for a ROM that is part of a larger,
|
||||
|
|
|
@ -110,8 +110,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(address);
|
||||
return myRam[(address & 0x03FF) + ((myCurrentBank - 256) << 10)] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#include "TIA.hxx"
|
||||
#include "Cart4A50.hxx"
|
||||
|
||||
// TODO - properly handle read from write port functionality
|
||||
// Note: do r/w port restrictions even exist for this scheme??
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Cartridge4A50::Cartridge4A50(const uInt8* image, uInt32 size)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#include "System.hxx"
|
||||
#include "CartDPC.hxx"
|
||||
|
||||
// TODO - properly handle read from write port functionality
|
||||
// Note: do r/w port restrictions even exist for this scheme??
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeDPC::CartridgeDPC(const uInt8* image, uInt32 size)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "System.hxx"
|
||||
#include "CartE7.hxx"
|
||||
|
||||
// TODO - check for unwanted read from write port in the upper 256B RAM area
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeE7::CartridgeE7(const uInt8* image)
|
||||
{
|
||||
|
@ -109,8 +111,13 @@ uInt8 CartridgeE7::peek(uInt16 address)
|
|||
// Reading from the write port triggers an unwanted write
|
||||
uInt8 value = mySystem->getDataBusState(0xFF);
|
||||
|
||||
if(myBankLocked) return value;
|
||||
else return myImage[(myCurrentSlice[address >> 11] << 11) + (address & 0x07FF)] = value;
|
||||
if(myBankLocked)
|
||||
return value;
|
||||
else
|
||||
{
|
||||
triggerReadFromWritePort(address);
|
||||
return myImage[(myCurrentSlice[address >> 11] << 11) + (address & 0x07FF)] = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
return myImage[(myCurrentSlice[address >> 11] << 11) + (address & 0x07FF)];
|
||||
|
|
|
@ -104,8 +104,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(address);
|
||||
return myRAM[address] = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
return myImage[(myCurrentBank << 12) + address];
|
||||
|
|
|
@ -20,22 +20,22 @@
|
|||
#include <cstring>
|
||||
|
||||
#include "System.hxx"
|
||||
#include "CartMB.hxx"
|
||||
#include "CartF0.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeMB::CartridgeMB(const uInt8* image)
|
||||
CartridgeF0::CartridgeF0(const uInt8* image)
|
||||
{
|
||||
// Copy the ROM image into my buffer
|
||||
memcpy(myImage, image, 65536);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeMB::~CartridgeMB()
|
||||
CartridgeF0::~CartridgeF0()
|
||||
{
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeMB::reset()
|
||||
void CartridgeF0::reset()
|
||||
{
|
||||
// Upon reset we switch to bank 1
|
||||
myCurrentBank = 0;
|
||||
|
@ -43,7 +43,7 @@ void CartridgeMB::reset()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeMB::install(System& system)
|
||||
void CartridgeF0::install(System& system)
|
||||
{
|
||||
mySystem = &system;
|
||||
uInt16 shift = mySystem->pageShift();
|
||||
|
@ -68,7 +68,7 @@ void CartridgeMB::install(System& system)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeMB::peek(uInt16 address)
|
||||
uInt8 CartridgeF0::peek(uInt16 address)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
|
@ -80,7 +80,7 @@ uInt8 CartridgeMB::peek(uInt16 address)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeMB::poke(uInt16 address, uInt8)
|
||||
void CartridgeF0::poke(uInt16 address, uInt8)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
|
@ -90,7 +90,7 @@ void CartridgeMB::poke(uInt16 address, uInt8)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeMB::incbank()
|
||||
void CartridgeF0::incbank()
|
||||
{
|
||||
if(myBankLocked) return;
|
||||
|
||||
|
@ -116,7 +116,7 @@ void CartridgeMB::incbank()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeMB::bank(uInt16 bank)
|
||||
void CartridgeF0::bank(uInt16 bank)
|
||||
{
|
||||
if(myBankLocked) return;
|
||||
|
||||
|
@ -125,33 +125,33 @@ void CartridgeMB::bank(uInt16 bank)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int CartridgeMB::bank()
|
||||
int CartridgeF0::bank()
|
||||
{
|
||||
return myCurrentBank;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int CartridgeMB::bankCount()
|
||||
int CartridgeF0::bankCount()
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeMB::patch(uInt16 address, uInt8 value)
|
||||
bool CartridgeF0::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
myImage[(myCurrentBank << 12) + (address & 0x0FFF)] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8* CartridgeMB::getImage(int& size)
|
||||
uInt8* CartridgeF0::getImage(int& size)
|
||||
{
|
||||
size = 65536;
|
||||
return &myImage[0];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeMB::save(Serializer& out) const
|
||||
bool CartridgeF0::save(Serializer& out) const
|
||||
{
|
||||
const string& cart = name();
|
||||
|
||||
|
@ -163,7 +163,7 @@ bool CartridgeMB::save(Serializer& out) const
|
|||
}
|
||||
catch(const char* msg)
|
||||
{
|
||||
cerr << "ERROR: CartridgeMB::save" << endl << " " << msg << endl;
|
||||
cerr << "ERROR: CartridgeF0::save" << endl << " " << msg << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ bool CartridgeMB::save(Serializer& out) const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeMB::load(Serializer& in)
|
||||
bool CartridgeF0::load(Serializer& in)
|
||||
{
|
||||
const string& cart = name();
|
||||
|
||||
|
@ -184,7 +184,7 @@ bool CartridgeMB::load(Serializer& in)
|
|||
}
|
||||
catch(const char* msg)
|
||||
{
|
||||
cerr << "ERROR: CartridgeMB::load" << endl << " " << msg << endl;
|
||||
cerr << "ERROR: CartridgeF0::load" << endl << " " << msg << endl;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -16,8 +16,8 @@
|
|||
// $Id$
|
||||
//============================================================================
|
||||
|
||||
#ifndef CARTRIDGEMB_HXX
|
||||
#define CARTRIDGEMB_HXX
|
||||
#ifndef CARTRIDGEF0_HXX
|
||||
#define CARTRIDGEF0_HXX
|
||||
|
||||
class System;
|
||||
|
||||
|
@ -29,15 +29,10 @@ class System;
|
|||
There are 16 4K banks.
|
||||
Accessing $1FF0 switches to next bank.
|
||||
|
||||
Note that while the bankswitch type for this class has historically
|
||||
been 'MB', one must now use 'F0' to activate it.
|
||||
This brings the bankswitch names in line with those used in z26 and
|
||||
the various cart programming apps for KrokCart and Harmony/Melody.
|
||||
|
||||
@author Eckhard Stolberg
|
||||
@version $Id$
|
||||
*/
|
||||
class CartridgeMB : public Cartridge
|
||||
class CartridgeF0 : public Cartridge
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
@ -45,12 +40,12 @@ class CartridgeMB : public Cartridge
|
|||
|
||||
@param image Pointer to the ROM image
|
||||
*/
|
||||
CartridgeMB(const uInt8* image);
|
||||
CartridgeF0(const uInt8* image);
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
virtual ~CartridgeMB();
|
||||
virtual ~CartridgeF0();
|
||||
|
||||
public:
|
||||
/**
|
|
@ -104,8 +104,13 @@ 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(address);
|
||||
return myRAM[address] = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
return myImage[(myCurrentBank << 12) + address];
|
||||
|
|
|
@ -127,8 +127,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(address);
|
||||
return myRAM[address] = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
return myImage[(myCurrentBank << 12) + address];
|
||||
|
|
|
@ -117,8 +117,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(address);
|
||||
return myRAM[address] = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
return myImage[(myCurrentBank << 12) + address];
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
#include <cstring>
|
||||
|
||||
#include "System.hxx"
|
||||
#include "CartFASC.hxx"
|
||||
#include "CartFA.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeFASC::CartridgeFASC(const uInt8* image)
|
||||
CartridgeFA::CartridgeFA(const uInt8* image)
|
||||
{
|
||||
// Copy the ROM image into my buffer
|
||||
memcpy(myImage, image, 12288);
|
||||
|
@ -33,12 +33,12 @@ CartridgeFASC::CartridgeFASC(const uInt8* image)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeFASC::~CartridgeFASC()
|
||||
CartridgeFA::~CartridgeFA()
|
||||
{
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeFASC::reset()
|
||||
void CartridgeFA::reset()
|
||||
{
|
||||
// Initialize RAM with random values
|
||||
for(uInt32 i = 0; i < 256; ++i)
|
||||
|
@ -49,7 +49,7 @@ void CartridgeFASC::reset()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeFASC::install(System& system)
|
||||
void CartridgeFA::install(System& system)
|
||||
{
|
||||
mySystem = &system;
|
||||
uInt16 shift = mySystem->pageShift();
|
||||
|
@ -91,7 +91,7 @@ void CartridgeFASC::install(System& system)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeFASC::peek(uInt16 address)
|
||||
uInt8 CartridgeFA::peek(uInt16 address)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
|
@ -122,15 +122,20 @@ uInt8 CartridgeFASC::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(address);
|
||||
return myRAM[address] = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
return myImage[(myCurrentBank << 12) + address];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeFASC::poke(uInt16 address, uInt8)
|
||||
void CartridgeFA::poke(uInt16 address, uInt8)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
|
@ -162,7 +167,7 @@ void CartridgeFASC::poke(uInt16 address, uInt8)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeFASC::bank(uInt16 bank)
|
||||
void CartridgeFA::bank(uInt16 bank)
|
||||
{
|
||||
if(myBankLocked) return;
|
||||
|
||||
|
@ -187,33 +192,33 @@ void CartridgeFASC::bank(uInt16 bank)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int CartridgeFASC::bank()
|
||||
int CartridgeFA::bank()
|
||||
{
|
||||
return myCurrentBank;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int CartridgeFASC::bankCount()
|
||||
int CartridgeFA::bankCount()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFASC::patch(uInt16 address, uInt8 value)
|
||||
bool CartridgeFA::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
myImage[(myCurrentBank << 12) + (address & 0x0FFF)] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8* CartridgeFASC::getImage(int& size)
|
||||
uInt8* CartridgeFA::getImage(int& size)
|
||||
{
|
||||
size = 12288;
|
||||
return &myImage[0];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFASC::save(Serializer& out) const
|
||||
bool CartridgeFA::save(Serializer& out) const
|
||||
{
|
||||
const string& cart = name();
|
||||
|
||||
|
@ -230,7 +235,7 @@ bool CartridgeFASC::save(Serializer& out) const
|
|||
}
|
||||
catch(const char* msg)
|
||||
{
|
||||
cerr << "ERROR: CartridgeFASC::save" << endl << " " << msg << endl;
|
||||
cerr << "ERROR: CartridgeFA::save" << endl << " " << msg << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -238,7 +243,7 @@ bool CartridgeFASC::save(Serializer& out) const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFASC::load(Serializer& in)
|
||||
bool CartridgeFA::load(Serializer& in)
|
||||
{
|
||||
const string& cart = name();
|
||||
|
||||
|
@ -255,7 +260,7 @@ bool CartridgeFASC::load(Serializer& in)
|
|||
}
|
||||
catch(const char* msg)
|
||||
{
|
||||
cerr << "ERROR: CartridgeFASC::load" << endl << " " << msg << endl;
|
||||
cerr << "ERROR: CartridgeFA::load" << endl << " " << msg << endl;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -16,8 +16,8 @@
|
|||
// $Id$
|
||||
//============================================================================
|
||||
|
||||
#ifndef CARTRIDGEFASC_HXX
|
||||
#define CARTRIDGEFASC_HXX
|
||||
#ifndef CARTRIDGEFA_HXX
|
||||
#define CARTRIDGEFA_HXX
|
||||
|
||||
class System;
|
||||
|
||||
|
@ -28,15 +28,10 @@ class System;
|
|||
Cartridge class used for CBS' RAM Plus cartridges. There are
|
||||
three 4K banks and 256 bytes of RAM.
|
||||
|
||||
Note that while the bankswitch type for this class has historically
|
||||
been 'FASC', one must now use 'FA' to activate it.
|
||||
This brings the bankswitch names in line with those used in z26 and
|
||||
the various cart programming apps for KrokCart and Harmony/Melody.
|
||||
|
||||
@author Bradford W. Mott
|
||||
@version $Id$
|
||||
*/
|
||||
class CartridgeFASC : public Cartridge
|
||||
class CartridgeFA : public Cartridge
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
@ -44,12 +39,12 @@ class CartridgeFASC : public Cartridge
|
|||
|
||||
@param image Pointer to the ROM image
|
||||
*/
|
||||
CartridgeFASC(const uInt8* image);
|
||||
CartridgeFA(const uInt8* image);
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
virtual ~CartridgeFASC();
|
||||
virtual ~CartridgeFA();
|
||||
|
||||
public:
|
||||
/**
|
|
@ -22,7 +22,9 @@
|
|||
#include "System.hxx"
|
||||
#include "CartMC.hxx"
|
||||
|
||||
// TODO - properly handle read from write port functionality
|
||||
// TODO - much more testing of this scheme is required
|
||||
// No test ROMs exist as of 2009-11-08, so we can't be sure how
|
||||
// accurate the emulation is
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeMC::CartridgeMC(const uInt8* image, uInt32 size)
|
||||
|
@ -141,8 +143,16 @@ uInt8 CartridgeMC::peek(uInt16 address)
|
|||
else
|
||||
{
|
||||
// Oops, reading from the write port of the RAM block!
|
||||
myRAM[(uInt32)((block & 0x3F) << 9) + (address & 0x01FF)] = 0;
|
||||
return 0;
|
||||
// Reading from the write port triggers an unwanted write
|
||||
uInt8 value = mySystem->getDataBusState(0xFF);
|
||||
|
||||
if(myBankLocked)
|
||||
return value;
|
||||
else
|
||||
{
|
||||
triggerReadFromWritePort(address);
|
||||
return myRAM[(uInt32)((block & 0x3F) << 9) + (address & 0x01FF)] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,15 +16,15 @@ MODULE_OBJS := \
|
|||
src/emucore/CartE7.o \
|
||||
src/emucore/CartEF.o \
|
||||
src/emucore/CartEFSC.o \
|
||||
src/emucore/CartF0.o \
|
||||
src/emucore/CartF4.o \
|
||||
src/emucore/CartF4SC.o \
|
||||
src/emucore/CartF6.o \
|
||||
src/emucore/CartF6SC.o \
|
||||
src/emucore/CartF8.o \
|
||||
src/emucore/CartF8SC.o \
|
||||
src/emucore/CartFASC.o \
|
||||
src/emucore/CartFA.o \
|
||||
src/emucore/CartFE.o \
|
||||
src/emucore/CartMB.o \
|
||||
src/emucore/CartMC.o \
|
||||
src/emucore/CartSB.o \
|
||||
src/emucore/CartUA.o \
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "Expression.hxx"
|
||||
#include "CpuDebug.hxx"
|
||||
#include "RamDebug.hxx"
|
||||
#include "TIADebug.hxx"
|
||||
|
||||
#include "DebuggerExpressions.hxx"
|
||||
|
@ -76,7 +77,6 @@ int parse(const char *in) {
|
|||
}
|
||||
|
||||
/* hand-rolled lexer. Hopefully faster than flex... */
|
||||
|
||||
inline bool is_base_prefix(char x) { return ( (x=='\\' || x=='$' || x=='#') ); }
|
||||
|
||||
inline bool is_identifier(char x) {
|
||||
|
@ -164,8 +164,8 @@ int const_to_int(char *c) {
|
|||
}
|
||||
}
|
||||
|
||||
// special methods that get e.g. CPU registers
|
||||
// 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;
|
||||
|
@ -209,6 +209,14 @@ CPUDEBUG_INT_METHOD getCpuSpecial(char *c) {
|
|||
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 TIA internal state
|
||||
TIADEBUG_INT_METHOD getTiaSpecial(char *c) {
|
||||
if(strcmp(c, "_scan") == 0)
|
||||
|
@ -253,6 +261,7 @@ int yylex() {
|
|||
case ST_IDENTIFIER:
|
||||
{
|
||||
CPUDEBUG_INT_METHOD cpuMeth;
|
||||
RAMDEBUG_INT_METHOD ramMeth;
|
||||
TIADEBUG_INT_METHOD tiaMeth;
|
||||
|
||||
char *bufp = idbuf;
|
||||
|
@ -279,6 +288,9 @@ int yylex() {
|
|||
} 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;
|
||||
|
|
|
@ -30,6 +30,7 @@ void yyerror(const char *e) {
|
|||
int val;
|
||||
char *equate;
|
||||
CPUDEBUG_INT_METHOD cpuMethod;
|
||||
RAMDEBUG_INT_METHOD ramMethod;
|
||||
TIADEBUG_INT_METHOD tiaMethod;
|
||||
Expression *exp;
|
||||
char *function;
|
||||
|
@ -40,6 +41,7 @@ void yyerror(const char *e) {
|
|||
%token <val> ERR
|
||||
%token <equate> EQUATE
|
||||
%token <cpuMethod> CPU_METHOD
|
||||
%token <ramMethod> RAM_METHOD
|
||||
%token <tiaMethod> TIA_METHOD
|
||||
%token <function> FUNCTION
|
||||
|
||||
|
@ -95,6 +97,7 @@ 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 = $$; }
|
||||
| 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; }
|
||||
|
|
702
src/yacc/y.tab.c
702
src/yacc/y.tab.c
File diff suppressed because it is too large
Load Diff
|
@ -1,24 +1,23 @@
|
|||
/* A Bison parser, made by GNU Bison 2.3. */
|
||||
|
||||
/* A Bison parser, made by GNU Bison 2.4.1. */
|
||||
|
||||
/* Skeleton interface for Bison's Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
|
@ -29,10 +28,11 @@
|
|||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
|
@ -43,19 +43,20 @@
|
|||
ERR = 259,
|
||||
EQUATE = 260,
|
||||
CPU_METHOD = 261,
|
||||
TIA_METHOD = 262,
|
||||
FUNCTION = 263,
|
||||
LOG_OR = 264,
|
||||
LOG_AND = 265,
|
||||
LOG_NOT = 266,
|
||||
SHL = 267,
|
||||
SHR = 268,
|
||||
EQ = 269,
|
||||
NE = 270,
|
||||
LTE = 271,
|
||||
GTE = 272,
|
||||
DEREF = 273,
|
||||
UMINUS = 274
|
||||
RAM_METHOD = 262,
|
||||
TIA_METHOD = 263,
|
||||
FUNCTION = 264,
|
||||
LOG_OR = 265,
|
||||
LOG_AND = 266,
|
||||
LOG_NOT = 267,
|
||||
SHL = 268,
|
||||
SHR = 269,
|
||||
EQ = 270,
|
||||
NE = 271,
|
||||
LTE = 272,
|
||||
GTE = 273,
|
||||
DEREF = 274,
|
||||
UMINUS = 275
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
|
@ -63,41 +64,49 @@
|
|||
#define ERR 259
|
||||
#define EQUATE 260
|
||||
#define CPU_METHOD 261
|
||||
#define TIA_METHOD 262
|
||||
#define FUNCTION 263
|
||||
#define LOG_OR 264
|
||||
#define LOG_AND 265
|
||||
#define LOG_NOT 266
|
||||
#define SHL 267
|
||||
#define SHR 268
|
||||
#define EQ 269
|
||||
#define NE 270
|
||||
#define LTE 271
|
||||
#define GTE 272
|
||||
#define DEREF 273
|
||||
#define UMINUS 274
|
||||
#define RAM_METHOD 262
|
||||
#define TIA_METHOD 263
|
||||
#define FUNCTION 264
|
||||
#define LOG_OR 265
|
||||
#define LOG_AND 266
|
||||
#define LOG_NOT 267
|
||||
#define SHL 268
|
||||
#define SHR 269
|
||||
#define EQ 270
|
||||
#define NE 271
|
||||
#define LTE 272
|
||||
#define GTE 273
|
||||
#define DEREF 274
|
||||
#define UMINUS 275
|
||||
|
||||
|
||||
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
#line 29 "stella.y"
|
||||
{
|
||||
|
||||
/* Line 1676 of yacc.c */
|
||||
#line 29 "stella.y"
|
||||
|
||||
int val;
|
||||
char *equate;
|
||||
CPUDEBUG_INT_METHOD cpuMethod;
|
||||
RAMDEBUG_INT_METHOD ramMethod;
|
||||
TIADEBUG_INT_METHOD tiaMethod;
|
||||
Expression *exp;
|
||||
char *function;
|
||||
}
|
||||
/* Line 1489 of yacc.c. */
|
||||
#line 96 "y.tab.h"
|
||||
YYSTYPE;
|
||||
|
||||
|
||||
|
||||
/* Line 1676 of yacc.c */
|
||||
#line 104 "y.tab.h"
|
||||
} YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
#endif
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue