Greatly improved the disassembler output, but having Stella keep track of

addresses used as part of code execution (ie, from the PC) during emulation.
This gives Distella much more information than can be determined from a
static analysis alone, resulting in an extremely accurate disassembly.
This also allows to generate very accurate debugger .cfg files.

Not all carts have been ported to this new scheme yet, particularly ones
having extended RAM that can be mapped out dynamically.

Note that this new scheme doubles the amount of RAM used for storing ROM
images, so up to 128KB extra will be used.  There's also a small runtime
check for each instruction executed.  Preliminary testing doesn't show
any slowdowns, but we'll see how it goes.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2138 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2010-10-03 00:23:13 +00:00
parent d6a38c8e44
commit 5fe91e2841
41 changed files with 971 additions and 1048 deletions

View File

@ -53,6 +53,7 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem)
myBankInfo.push_back(info);
// We know the address for the startup bank right now
cerr << "start @ " << HEX4 << myDebugger.dpeek(0xfffc) << endl;
myBankInfo[myConsole.cartridge().startBank()].addressList.push_back(myDebugger.dpeek(0xfffc));
addLabel("START", myDebugger.dpeek(0xfffc));

View File

@ -284,6 +284,7 @@ class Debugger : public DialogContainer
/* These are now exposed so Expressions can use them. */
int peek(int addr) { return mySystem->peek(addr); }
int dpeek(int addr) { return mySystem->peek(addr) | (mySystem->peek(addr+1) << 8); }
int isCode(int addr) { return mySystem->isCode(addr); }
void setBreakPoint(int bp, bool set);

View File

@ -90,6 +90,10 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list,
if(resolvedata)
{
// After we've disassembled from the start address, use all access points
// determined by Stella during emulation
int codeAccessPoint = 0;
while(!myAddressQueue.empty())
{
myPC = myAddressQueue.front();
@ -99,31 +103,29 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list,
for (uInt32 k = myPCBeg; k <= myPCEnd; k++)
mark(k, REACHABLE);
// When we get to this point, all addresses have been processed
// starting from the initial one in the address list
// If so, process the next one in the list that hasn't already
// been marked as REACHABLE
// If it *has* been marked, it can be removed from consideration
// in all subsequent passes
// When we get to this point, the 'start' address has been processed
// Next we process all addresses determined during emulation to represent
// code, which *haven't* already been considered
//
// Note that we can't simply add all addresses right away, since
// the processing of a single address from the address list can
// cause others to be added in the ::disasm method
// All of these have to be exhausted before consulting the address
// list again
// the processing of a single address can cause others to be added in
// the ::disasm method
// All of these have to be exhausted before considering a new address
if(myAddressQueue.empty())
{
while(it != addresses.end())
// Stella itself can provide hints on whether an address has ever
// been referenced as CODE
while(codeAccessPoint <= myAppData.end)
{
uInt16 addr = *it;
if(!check_bit(labels[addr-myOffset], REACHABLE))
if(Debugger::debugger().isCode(codeAccessPoint+myOffset) &&
!check_bit(labels[codeAccessPoint], REACHABLE))
{
myAddressQueue.push(addr);
++it;
cerr << "marking " << hex << (codeAccessPoint+myOffset) << " as CODE\n";
myAddressQueue.push(codeAccessPoint+myOffset);
++codeAccessPoint;
break;
}
else // remove this address, it is redundant
it = addresses.erase(it);
++codeAccessPoint;
}
}
}

View File

@ -231,6 +231,7 @@ Cartridge::Cartridge(const Settings& settings)
: mySettings(settings),
myStartBank(0),
myBankChanged(true),
myCodeAccessBase(NULL),
myBankLocked(false)
{
}
@ -238,6 +239,8 @@ Cartridge::Cartridge(const Settings& settings)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge::~Cartridge()
{
if(myCodeAccessBase)
delete[] myCodeAccessBase;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -294,6 +297,17 @@ void Cartridge::triggerReadFromWritePort(uInt16 address)
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Cartridge::createCodeAccessBase(uInt32 size)
{
#ifdef DEBUGGER_SUPPORT
myCodeAccessBase = new uInt8[size];
memset(myCodeAccessBase, 0, size);
#else
myCodeAccessBase = NULL;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Cartridge::autodetectType(const uInt8* image, uInt32 size)
{

View File

@ -207,6 +207,15 @@ class Cartridge : public Device
*/
void triggerReadFromWritePort(uInt16 address);
/**
Create an array that holds code-access information for every byte
of the ROM (indicated by 'size'). Note that this is only used by
the debugger, and is unavailable otherwise.
@param size The size of the code-access array to create
*/
void createCodeAccessBase(uInt32 size);
private:
/**
Get an image pointer and size for a ROM that is part of a larger,
@ -332,6 +341,10 @@ class Cartridge : public Device
// Indicates if the bank has changed somehow (a bankswitch has occurred)
bool myBankChanged;
// The array containing information about every byte of ROM indicating
// whether it is used as code.
uInt8* myCodeAccessBase;
private:
#ifdef DEBUGGER_SUPPORT
// Contains RamArea entries for those carts with accessible RAM.

View File

@ -29,6 +29,7 @@ Cartridge0840::Cartridge0840(const uInt8* image, const Settings& settings)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, 8192);
createCodeAccessBase(8192);
// Remember startup bank
myStartBank = 0;
@ -68,11 +69,7 @@ void Cartridge0840::install(System& system)
myHotSpotPageAccess[7] = mySystem->getPageAccess(0x0F00 >> shift);
// Set the page accessing methods for the hot spots
System::PageAccess access;
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
for(uInt32 i = 0x0800; i < 0x0FFF; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
@ -157,15 +154,13 @@ bool Cartridge0840::bank(uInt16 bank)
uInt16 shift = mySystem->pageShift();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1000; address < 0x2000; address += (1 << shift))
{
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
mySystem->setPageAccess(address >> shift, access);
}
return myBankChanged = true;

View File

@ -47,6 +47,7 @@ Cartridge2K::Cartridge2K(const uInt8* image, uInt32 size, const Settings& settin
// Copy the ROM image into my buffer
memcpy(myImage, image, size);
createCodeAccessBase(mySize);
// Set mask for accessing the image buffer
// This is guaranteed to work, as mySize is a power of two
@ -76,14 +77,12 @@ void Cartridge2K::install(System& system)
assert((0x1000 & mask) == 0);
// Map ROM image into the system
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
for(uInt32 address = 0x1000; address < 0x2000; address += (1 << shift))
{
access.directPeekBase = &myImage[address & myMask];
access.codeAccessBase = &myCodeAccessBase[address & myMask];
mySystem->setPageAccess(address >> shift, access);
}
}

View File

@ -24,6 +24,8 @@
#include "TIA.hxx"
#include "Cart3E.hxx"
// TODO - add support for code stored in RAM
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge3E::Cartridge3E(const uInt8* image, uInt32 size,
const Settings& settings)
@ -35,6 +37,7 @@ Cartridge3E::Cartridge3E(const uInt8* image, uInt32 size,
// Copy the ROM image into my buffer
memcpy(myImage, image, mySize);
createCodeAccessBase(mySize);
// This cart can address a 1024 byte bank of RAM @ 0x1000
// However, it may not be addressable all the time (it may be swapped out)
@ -75,26 +78,21 @@ void Cartridge3E::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert((0x1800 & mask) == 0);
System::PageAccess access;
System::PageAccess access(0, 0, 0, this, System::PA_READWRITE);
// Set the page accessing methods for the hot spots (for 100% emulation
// we need to chain any accesses below 0x40 to the TIA. Our poke() method
// does this via mySystem->tiaPoke(...), at least until we come up with a
// cleaner way to do it).
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READWRITE;
for(uInt32 i = 0x00; i < 0x40; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
// Setup the second segment to always point to the last ROM slice
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 j = 0x1800; j < 0x2000; j += (1 << shift))
{
access.directPeekBase = &myImage[(mySize - 2048) + (j & 0x07FF)];
access.codeAccessBase = &myCodeAccessBase[(mySize - 2048) + (j & 0x07FF)];
mySystem->setPageAccess(j >> shift, access);
}
@ -185,15 +183,13 @@ bool Cartridge3E::bank(uInt16 bank)
uInt16 shift = mySystem->pageShift();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1000; address < 0x1800; address += (1 << shift))
{
access.directPeekBase = &myImage[offset + (address & 0x07FF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x07FF)];
mySystem->setPageAccess(address >> shift, access);
}
}
@ -208,10 +204,7 @@ bool Cartridge3E::bank(uInt16 bank)
uInt32 address;
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Map read-port RAM image into the system
for(address = 0x1000; address < 0x1400; address += (1 << shift))

View File

@ -35,6 +35,7 @@ Cartridge3F::Cartridge3F(const uInt8* image, uInt32 size,
// Copy the ROM image into my buffer
memcpy(myImage, image, mySize);
createCodeAccessBase(mySize);
// Remember startup bank
myStartBank = 0;
@ -63,25 +64,21 @@ void Cartridge3F::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert((0x1800 & mask) == 0);
System::PageAccess access(0, 0, 0, this, System::PA_READWRITE);
// Set the page accessing methods for the hot spots (for 100% emulation
// we need to chain any accesses below 0x40 to the TIA. Our poke() method
// does this via mySystem->tiaPoke(...), at least until we come up with a
// cleaner way to do it).
System::PageAccess access;
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READWRITE;
for(uInt32 i = 0x00; i < 0x40; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
// Setup the second segment to always point to the last ROM slice
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 j = 0x1800; j < 0x2000; j += (1 << shift))
{
access.directPeekBase = &myImage[(mySize - 2048) + (j & 0x07FF)];
access.codeAccessBase = &myCodeAccessBase[(mySize - 2048) + (j & 0x07FF)];
mySystem->setPageAccess(j >> shift, access);
}
@ -145,15 +142,13 @@ bool Cartridge3F::bank(uInt16 bank)
uInt16 shift = mySystem->pageShift();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1000; address < 0x1800; address += (1 << shift))
{
access.directPeekBase = &myImage[offset + (address & 0x07FF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x07FF)];
mySystem->setPageAccess(address >> shift, access);
}
return myBankChanged = true;

View File

@ -73,12 +73,8 @@ void Cartridge4A50::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert((0x1000 & mask) == 0);
// Map all of the accesses to call peek and poke
System::PageAccess access;
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ; // We don't yet indicate RAM areas
// Map all of the accesses to call peek and poke (We don't yet indicate RAM areas)
System::PageAccess access(0, 0, 0, this, System::PA_READ);
for(uInt32 i = 0x1000; i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);

View File

@ -29,6 +29,7 @@ Cartridge4K::Cartridge4K(const uInt8* image, const Settings& settings)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, 4096);
createCodeAccessBase(4096);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -52,15 +53,13 @@ void Cartridge4K::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert((0x1000 & mask) == 0);
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1000; address < 0x2000; address += (1 << shift))
{
access.directPeekBase = &myImage[address & 0x0FFF];
access.codeAccessBase = &myCodeAccessBase[address & 0x0FFF];
mySystem->setPageAccess(address >> mySystem->pageShift(), access);
}
}

View File

@ -96,12 +96,8 @@ void CartridgeAR::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert((0x1000 & mask) == 0);
// Map all of the accesses to call peek and poke
System::PageAccess access;
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ; // We don't yet indicate RAM areas
// Map all of the accesses to call peek and poke (we don't yet indicate RAM areas)
System::PageAccess access(0, 0, 0, this, System::PA_READ);
for(uInt32 i = 0x1000; i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);

View File

@ -47,6 +47,7 @@ CartridgeCV::CartridgeCV(const uInt8* image, uInt32 size,
myInitialRAM = new uInt8[1024];
memcpy(myInitialRAM, image, 1024);
}
createCodeAccessBase(2048+1024);
// This cart contains 1024 bytes extended RAM @ 0x1000
registerRamArea(0x1000, 1024, 0x00, 0x400);
@ -89,21 +90,19 @@ void CartridgeCV::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert((0x1800 & mask) == 0);
System::PageAccess access;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Map ROM image into the system
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 address = 0x1800; address < 0x2000; address += (1 << shift))
{
access.directPeekBase = &myImage[address & 0x07FF];
access.codeAccessBase = &myCodeAccessBase[address & 0x07FF];
mySystem->setPageAccess(address >> mySystem->pageShift(), access);
}
// Set the page accessing method for the RAM writing pages
access.directPeekBase = 0;
access.device = this;
access.codeAccessBase = 0;
access.type = System::PA_WRITE;
for(uInt32 j = 0x1400; j < 0x1800; j += (1 << shift))
{
@ -113,11 +112,11 @@ void CartridgeCV::install(System& system)
// Set the page accessing method for the RAM reading pages
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 k = 0x1000; k < 0x1400; k += (1 << shift))
{
access.directPeekBase = &myRAM[k & 0x03FF];
access.codeAccessBase = &myCodeAccessBase[2048 + (k & 0x03FF)];
mySystem->setPageAccess(k >> shift, access);
}
}

View File

@ -89,20 +89,13 @@ void CartridgeDPC::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert(((0x1080 & mask) == 0) && ((0x1100 & mask) == 0));
System::PageAccess access;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Set the page accessing methods for the hot spots
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = (0x1FF8 & ~mask); i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
// Set the page accessing method for the DPC reading & writing pages
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READWRITE;
for(uInt32 j = 0x1000; j < 0x1080; j += (1 << shift))
mySystem->setPageAccess(j >> shift, access);
@ -429,10 +422,7 @@ bool CartridgeDPC::bank(uInt16 bank)
uInt16 mask = mySystem->pageMask();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Map Program ROM image into the system
for(uInt32 address = 0x1080; address < (0x1FF8U & ~mask);

View File

@ -109,12 +109,9 @@ void CartridgeDPCPlus::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert(((0x1080 & mask) == 0) && ((0x1100 & mask) == 0));
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Map all of the accesses to call peek and poke
System::PageAccess access;
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = 0x1000; i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);

View File

@ -58,12 +58,9 @@ void CartridgeE0::install(System& system)
assert(((0x1000 & mask) == 0) && ((0x1400 & mask) == 0) &&
((0x1800 & mask) == 0) && ((0x1C00 & mask) == 0));
System::PageAccess access;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Set the page acessing methods for the first part of the last segment
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = 0x1C00; i < (0x1FE0U & ~mask); i += (1 << shift))
{
access.directPeekBase = &myImage[7168 + (i & 0x03FF)];
@ -73,8 +70,6 @@ void CartridgeE0::install(System& system)
// Set the page accessing methods for the hot spots in the last segment
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 j = (0x1FE0 & ~mask); j < 0x2000; j += (1 << shift))
mySystem->setPageAccess(j >> shift, access);
@ -139,10 +134,7 @@ void CartridgeE0::segmentZero(uInt16 slice)
uInt16 shift = mySystem->pageShift();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
for(uInt32 address = 0x1000; address < 0x1400; address += (1 << shift))
{
@ -163,10 +155,7 @@ void CartridgeE0::segmentOne(uInt16 slice)
uInt16 shift = mySystem->pageShift();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
for(uInt32 address = 0x1400; address < 0x1800; address += (1 << shift))
{
@ -187,10 +176,7 @@ void CartridgeE0::segmentTwo(uInt16 slice)
uInt16 shift = mySystem->pageShift();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
for(uInt32 address = 0x1800; address < 0x1C00; address += (1 << shift))
{

View File

@ -74,20 +74,13 @@ void CartridgeE7::install(System& system)
assert(((0x1400 & mask) == 0) && ((0x1800 & mask) == 0) &&
((0x1900 & mask) == 0) && ((0x1A00 & mask) == 0));
System::PageAccess access;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Set the page accessing methods for the hot spots
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = (0x1FE0 & ~mask); i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
// Setup the second segment to always point to the last ROM slice
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 j = 0x1A00; j < (0x1FE0U & ~mask); j += (1 << shift))
{
access.directPeekBase = &myImage[7 * 2048 + (j & 0x07FF)];
@ -178,12 +171,9 @@ void CartridgeE7::bankRAM(uInt16 bank)
uInt16 shift = mySystem->pageShift();
// Setup the page access methods for the current bank
System::PageAccess access;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_WRITE);
// Set the page accessing method for the 256 bytes of RAM writing pages
access.directPeekBase = 0;
access.device = this;
access.type = System::PA_WRITE;
for(uInt32 j = 0x1800; j < 0x1900; j += (1 << shift))
{
access.directPokeBase = &myRAM[1024 + offset + (j & 0x00FF)];
@ -192,7 +182,6 @@ void CartridgeE7::bankRAM(uInt16 bank)
// Set the page accessing method for the 256 bytes of RAM reading pages
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 k = 0x1900; k < 0x1A00; k += (1 << shift))
{
@ -212,15 +201,12 @@ bool CartridgeE7::bank(uInt16 slice)
uInt16 offset = slice << 11;
uInt16 shift = mySystem->pageShift();
System::PageAccess access;
// Setup the page access methods for the current bank
if(slice != 7)
{
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Map ROM image into first segment
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 address = 0x1000; address < 0x1800; address += (1 << shift))
{
access.directPeekBase = &myImage[offset + (address & 0x07FF)];
@ -229,10 +215,9 @@ bool CartridgeE7::bank(uInt16 slice)
}
else
{
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_WRITE);
// Set the page accessing method for the 1K slice of RAM writing pages
access.directPeekBase = 0;
access.device = this;
access.type = System::PA_WRITE;
for(uInt32 j = 0x1000; j < 0x1400; j += (1 << shift))
{
access.directPokeBase = &myRAM[j & 0x03FF];
@ -241,7 +226,6 @@ bool CartridgeE7::bank(uInt16 slice)
// Set the page accessing method for the 1K slice of RAM reading pages
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 k = 0x1400; k < 0x1800; k += (1 << shift))
{

View File

@ -56,13 +56,9 @@ void CartridgeEF::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert((0x1000 & mask) == 0);
System::PageAccess access;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Set the page accessing methods for the hot spots
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = (0x1FE0 & ~mask); i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
@ -105,12 +101,8 @@ bool CartridgeEF::bank(uInt16 bank)
uInt16 shift = mySystem->pageShift();
uInt16 mask = mySystem->pageMask();
System::PageAccess access;
// Setup the page access methods for the current bank
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1000; address < (0x1FE0U & ~mask);

View File

@ -66,19 +66,13 @@ void CartridgeEFSC::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert((0x1000 & mask) == 0);
System::PageAccess access;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Set the page accessing methods for the hot spots
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = (0x1FE0 & ~mask); i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
// Set the page accessing method for the RAM writing pages
access.directPeekBase = 0;
access.device = this;
access.type = System::PA_WRITE;
for(uInt32 j = 0x1000; j < 0x1080; j += (1 << shift))
{
@ -88,7 +82,6 @@ void CartridgeEFSC::install(System& system)
// Set the page accessing method for the RAM reading pages
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 k = 0x1080; k < 0x1100; k += (1 << shift))
{
@ -154,10 +147,7 @@ bool CartridgeEFSC::bank(uInt16 bank)
uInt16 mask = mySystem->pageMask();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1100; address < (0x1FE0U & ~mask);

View File

@ -57,13 +57,9 @@ void CartridgeF0::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert((0x1000 & mask) == 0);
System::PageAccess access;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Set the page accessing methods for the hot spots
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = (0x1FF0 & ~mask); i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
@ -109,10 +105,7 @@ void CartridgeF0::incbank()
uInt16 mask = mySystem->pageMask();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1000; address < (0x1FF0U & ~mask);

View File

@ -30,6 +30,7 @@ CartridgeF4::CartridgeF4(const uInt8* image, const Settings& settings)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, 32768);
createCodeAccessBase(32768);
// Remember startup bank
myStartBank = 0;
@ -57,13 +58,9 @@ void CartridgeF4::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert((0x1000 & mask) == 0);
System::PageAccess access;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Set the page accessing methods for the hot spots
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = (0x1FF4 & ~mask); i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
@ -111,16 +108,14 @@ bool CartridgeF4::bank(uInt16 bank)
uInt16 mask = mySystem->pageMask();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1000; address < (0x1FF4U & ~mask);
address += (1 << shift))
{
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
mySystem->setPageAccess(address >> shift, access);
}
return myBankChanged = true;

View File

@ -29,6 +29,7 @@ CartridgeF4SC::CartridgeF4SC(const uInt8* image, const Settings& settings)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, 32768);
createCodeAccessBase(32768);
// This cart contains 128 bytes extended RAM @ 0x1000
registerRamArea(0x1000, 128, 0x80, 0x00);
@ -66,19 +67,13 @@ void CartridgeF4SC::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert(((0x1080 & mask) == 0) && ((0x1100 & mask) == 0));
System::PageAccess access;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Set the page accessing methods for the hot spots
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = (0x1FF4 & ~mask); i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
// Set the page accessing method for the RAM writing pages
access.directPeekBase = 0;
access.device = this;
access.type = System::PA_WRITE;
for(uInt32 j = 0x1000; j < 0x1080; j += (1 << shift))
{
@ -88,11 +83,11 @@ void CartridgeF4SC::install(System& system)
// Set the page accessing method for the RAM reading pages
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 k = 0x1080; k < 0x1100; k += (1 << shift))
{
access.directPeekBase = &myRAM[k & 0x007F];
access.codeAccessBase = &myCodeAccessBase[0x80 + (k & 0x007F)];
mySystem->setPageAccess(k >> shift, access);
}
@ -157,16 +152,14 @@ bool CartridgeF4SC::bank(uInt16 bank)
uInt16 mask = mySystem->pageMask();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1100; address < (0x1FF4U & ~mask);
address += (1 << shift))
{
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
mySystem->setPageAccess(address >> shift, access);
}
return myBankChanged = true;

View File

@ -29,6 +29,7 @@ CartridgeF6::CartridgeF6(const uInt8* image, const Settings& settings)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, 16384);
createCodeAccessBase(16384);
// Remember startup bank
myStartBank = 0;
@ -56,13 +57,9 @@ void CartridgeF6::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert((0x1000 & mask) == 0);
System::PageAccess access;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Set the page accessing methods for the hot spots
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = (0x1FF6 & ~mask); i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
@ -151,16 +148,14 @@ bool CartridgeF6::bank(uInt16 bank)
uInt16 mask = mySystem->pageMask();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1000; address < (0x1FF6U & ~mask);
address += (1 << shift))
{
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
mySystem->setPageAccess(address >> shift, access);
}
return myBankChanged = true;

View File

@ -29,6 +29,7 @@ CartridgeF6SC::CartridgeF6SC(const uInt8* image, const Settings& settings)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, 16384);
createCodeAccessBase(16384);
// This cart contains 128 bytes extended RAM @ 0x1000
registerRamArea(0x1000, 128, 0x80, 0x00);
@ -66,19 +67,13 @@ void CartridgeF6SC::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert(((0x1080 & mask) == 0) && ((0x1100 & mask) == 0));
System::PageAccess access;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Set the page accessing methods for the hot spots
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = (0x1FF6 & ~mask); i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
// Set the page accessing method for the RAM writing pages
access.directPeekBase = 0;
access.device = this;
access.type = System::PA_WRITE;
for(uInt32 j = 0x1000; j < 0x1080; j += (1 << shift))
{
@ -88,11 +83,11 @@ void CartridgeF6SC::install(System& system)
// Set the page accessing method for the RAM reading pages
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 k = 0x1080; k < 0x1100; k += (1 << shift))
{
access.directPeekBase = &myRAM[k & 0x007F];
access.codeAccessBase = &myCodeAccessBase[0x80 + (k & 0x007F)];
mySystem->setPageAccess(k >> shift, access);
}
@ -200,16 +195,14 @@ bool CartridgeF6SC::bank(uInt16 bank)
uInt16 mask = mySystem->pageMask();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1100; address < (0x1FF6U & ~mask);
address += (1 << shift))
{
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
mySystem->setPageAccess(address >> shift, access);
}
return myBankChanged = true;

View File

@ -30,6 +30,7 @@ CartridgeF8::CartridgeF8(const uInt8* image, const string& md5,
{
// Copy the ROM image into my buffer
memcpy(myImage, image, 8192);
createCodeAccessBase(8192);
// Normally bank 1 is the reset bank, unless we're dealing with ROMs
// that have been incorrectly created with banks in the opposite order
@ -63,13 +64,9 @@ void CartridgeF8::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert((0x1000 & mask) == 0);
System::PageAccess access;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Set the page accessing methods for the hot spots
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = (0x1FF8 & ~mask); i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
@ -138,16 +135,14 @@ bool CartridgeF8::bank(uInt16 bank)
uInt16 mask = mySystem->pageMask();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1000; address < (0x1FF8U & ~mask);
address += (1 << shift))
{
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
mySystem->setPageAccess(address >> shift, access);
}
return myBankChanged = true;

View File

@ -29,6 +29,7 @@ CartridgeF8SC::CartridgeF8SC(const uInt8* image, const Settings& settings)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, 8192);
createCodeAccessBase(8192);
// This cart contains 128 bytes extended RAM @ 0x1000
registerRamArea(0x1000, 128, 0x80, 0x00);
@ -66,33 +67,27 @@ void CartridgeF8SC::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert(((0x1080 & mask) == 0) && ((0x1100 & mask) == 0));
System::PageAccess access;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Set the page accessing methods for the hot spots
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = (0x1FF8 & ~mask); i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
// Set the page accessing method for the RAM writing pages
access.directPeekBase = 0;
access.device = this;
access.type = System::PA_WRITE;
for(uInt32 j = 0x1000; j < 0x1080; j += (1 << shift))
{
access.directPokeBase = &myRAM[j & 0x007F];
mySystem->setPageAccess(j >> shift, access);
}
// Set the page accessing method for the RAM reading pages
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 k = 0x1080; k < 0x1100; k += (1 << shift))
{
access.directPeekBase = &myRAM[k & 0x007F];
access.codeAccessBase = &myCodeAccessBase[0x80 + (k & 0x007F)];
mySystem->setPageAccess(k >> shift, access);
}
@ -180,16 +175,14 @@ bool CartridgeF8SC::bank(uInt16 bank)
uInt16 mask = mySystem->pageMask();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1100; address < (0x1FF8U & ~mask);
address += (1 << shift))
{
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
mySystem->setPageAccess(address >> shift, access);
}
return myBankChanged = true;

View File

@ -29,6 +29,7 @@ CartridgeFA::CartridgeFA(const uInt8* image, const Settings& settings)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, 12288);
createCodeAccessBase(12288);
// This cart contains 256 bytes extended RAM @ 0x1000
registerRamArea(0x1000, 256, 0x100, 0x00);
@ -66,19 +67,13 @@ void CartridgeFA::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert(((0x1100 & mask) == 0) && ((0x1200 & mask) == 0));
System::PageAccess access;
System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Set the page accessing methods for the hot spots
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = (0x1FF8 & ~mask); i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
// Set the page accessing method for the RAM writing pages
access.directPeekBase = 0;
access.device = this;
access.type = System::PA_WRITE;
for(uInt32 j = 0x1000; j < 0x1100; j += (1 << shift))
{
@ -88,11 +83,11 @@ void CartridgeFA::install(System& system)
// Set the page accessing method for the RAM reading pages
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 k = 0x1100; k < 0x1200; k += (1 << shift))
{
access.directPeekBase = &myRAM[k & 0x00FF];
access.codeAccessBase = &myCodeAccessBase[0x100 + (k & 0x00FF)];
mySystem->setPageAccess(k >> shift, access);
}
@ -190,16 +185,14 @@ bool CartridgeFA::bank(uInt16 bank)
uInt16 mask = mySystem->pageMask();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1200; address < (0x1FF8U & ~mask);
address += (1 << shift))
{
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)];
mySystem->setPageAccess(address >> shift, access);
}
return myBankChanged = true;

View File

@ -54,12 +54,9 @@ void CartridgeFE::install(System& system)
// Make sure the system we're being installed in has a page size that'll work
assert((0x1000 & mask) == 0);
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Map all of the accesses to call peek and poke
System::PageAccess access;
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = 0x1000; i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
}

View File

@ -81,18 +81,12 @@ void CartridgeMC::install(System& system)
// TODO: These TIA accesses may need to be chained, however, at this
// point Chris isn't sure if the hardware will allow it or not
//
System::PageAccess access;
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READWRITE;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READWRITE);
for(uInt32 i = 0x00; i < 0x40; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
// Map the cartridge into the system
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ; // We don't yet indicate RAM areas
for(uInt32 j = 0x1000; j < 0x2000; j += (1 << shift))
mySystem->setPageAccess(j >> shift, access);

View File

@ -73,13 +73,9 @@ void CartridgeSB::install(System& system)
myHotSpotPageAccess[6] = mySystem->getPageAccess(0x0E00 >> shift);
myHotSpotPageAccess[7] = mySystem->getPageAccess(0x0F00 >> shift);
System::PageAccess access;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Set the page accessing methods for the hot spots
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
for(uInt32 i = 0x0800; i < 0x0FFF; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
@ -137,10 +133,7 @@ bool CartridgeSB::bank(uInt16 bank)
uInt16 shift = mySystem->pageShift();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1000; address < 0x2000; address += (1 << shift))

View File

@ -61,11 +61,7 @@ void CartridgeUA::install(System& system)
myHotSpotPageAccess = mySystem->getPageAccess(0x0220 >> shift);
// Set the page accessing methods for the hot spots
System::PageAccess access;
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
mySystem->setPageAccess(0x0220 >> shift, access);
mySystem->setPageAccess(0x0240 >> shift, access);
@ -145,10 +141,7 @@ bool CartridgeUA::bank(uInt16 bank)
uInt16 shift = mySystem->pageShift();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1000; address < 0x2000; address += (1 << shift))

View File

@ -61,11 +61,7 @@ void CartridgeX07::install(System& system)
// Set the page accessing methods for the hot spots
// The hotspots use almost all addresses below 0x1000, so we simply grab them
// all and forward the TIA/RIOT calls from the peek and poke methods.
System::PageAccess access;
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READWRITE;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READWRITE);
for(uInt32 i = 0x00; i < 0x1000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
@ -129,10 +125,7 @@ bool CartridgeX07::bank(uInt16 bank)
uInt16 shift = mySystem->pageShift();
// Setup the page access methods for the current bank
System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
access.type = System::PA_READ;
System::PageAccess access(0, 0, myCodeAccessBase, this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1000; address < 0x2000; address += (1 << shift))

View File

@ -152,7 +152,7 @@ void M6502::PS(uInt8 ps)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline uInt8 M6502::peek(uInt16 address)
inline uInt8 M6502::peek(uInt16 address, bool isCode)
{
if(address != myLastAddress)
{
@ -170,7 +170,7 @@ inline uInt8 M6502::peek(uInt16 address)
}
#endif
uInt8 result = mySystem->peek(address);
uInt8 result = mySystem->peek(address, isCode);
myLastAccessWasRead = true;
myLastPeekAddress = address;
return result;
@ -245,7 +245,7 @@ bool M6502::execute(uInt32 number)
myLastPeekAddress = myLastPokeAddress = 0;
// Fetch instruction at the program counter
IR = peek(PC++);
IR = peek(PC++, true); // This address represents a code section
#ifdef DEBUG_OUTPUT
debugStream << ::hex << setw(2) << (int)A << " "
@ -256,7 +256,7 @@ bool M6502::execute(uInt32 number)
<< setw(2) << (int)IR << " "
// << "<" << ourAddressingModeTable[IR] << " ";
// debugStream << hex << setw(4) << operandAddress << " ";
<< setw(3) << ourInstructionMnemonicTable[IR]
// << setw(3) << ourInstructionMnemonicTable[IR]
// debugStream << "PS=" << ::hex << setw(2) << (int)PS() << " ";
@ -274,7 +274,6 @@ bool M6502::execute(uInt32 number)
// Oops, illegal instruction executed so set fatal error flag
myExecutionStatus |= FatalErrorBit;
}
myTotalInstructionCount++;
}

View File

@ -206,17 +206,23 @@ class M6502 : public Serializable
private:
/**
Get the byte at the specified address and update the cycle count.
Addresses marked as code are hints to the debugger/disassembler to
conclusively determine code sections, even if the disassembler cannot
find them itself.
@param address The address from which the value should be loaded
@param isCode Indicates that this address is part of an instruction
@return The byte at the specified address
*/
inline uInt8 peek(uInt16 address);
inline uInt8 peek(uInt16 address, bool isCode);
/**
Change the byte at the specified address to the given value and
update the cycle count.
@param address The address where the value should be stored
@param value The value to be stored at the address
@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);

File diff suppressed because it is too large Load Diff

View File

@ -32,197 +32,197 @@
#endif
define(M6502_IMPLIED, `{
peek(PC);
peek(PC, false);
}')
define(M6502_IMMEDIATE_READ, `{
operand = peek(PC++);
operand = peek(PC++, true);
}')
define(M6502_ABSOLUTE_READ, `{
uInt16 address = peek(PC++);
address |= ((uInt16)peek(PC++) << 8);
operand = peek(address);
uInt16 address = peek(PC++, true);
address |= ((uInt16)peek(PC++, true) << 8);
operand = peek(address, false);
}')
define(M6502_ABSOLUTE_WRITE, `{
operandAddress = peek(PC++);
operandAddress |= ((uInt16)peek(PC++) << 8);
operandAddress = peek(PC++, true);
operandAddress |= ((uInt16)peek(PC++, true) << 8);
}')
define(M6502_ABSOLUTE_READMODIFYWRITE, `{
operandAddress = peek(PC++);
operandAddress |= ((uInt16)peek(PC++) << 8);
operand = peek(operandAddress);
operandAddress = peek(PC++, true);
operandAddress |= ((uInt16)peek(PC++, true) << 8);
operand = peek(operandAddress, false);
poke(operandAddress, operand);
}')
define(M6502_ABSOLUTEX_READ, `{
uInt16 low = peek(PC++);
uInt16 high = ((uInt16)peek(PC++) << 8);
operand = peek(high | (uInt8)(low + X));
uInt16 low = peek(PC++, true);
uInt16 high = ((uInt16)peek(PC++, true) << 8);
operand = peek(high | (uInt8)(low + X), false);
if((low + X) > 0xFF)
operand = peek((high | low) + X);
operand = peek((high | low) + X, false);
}')
define(M6502_ABSOLUTEX_WRITE, `{
uInt16 low = peek(PC++);
uInt16 high = ((uInt16)peek(PC++) << 8);
peek(high | (uInt8)(low + X));
uInt16 low = peek(PC++, true);
uInt16 high = ((uInt16)peek(PC++, true) << 8);
peek(high | (uInt8)(low + X), false);
operandAddress = (high | low) + X;
}')
define(M6502_ABSOLUTEX_READMODIFYWRITE, `{
uInt16 low = peek(PC++);
uInt16 high = ((uInt16)peek(PC++) << 8);
peek(high | (uInt8)(low + X));
uInt16 low = peek(PC++, true);
uInt16 high = ((uInt16)peek(PC++, true) << 8);
peek(high | (uInt8)(low + X), false);
operandAddress = (high | low) + X;
operand = peek(operandAddress);
operand = peek(operandAddress, false);
poke(operandAddress, operand);
}')
define(M6502_ABSOLUTEY_READ, `{
uInt16 low = peek(PC++);
uInt16 high = ((uInt16)peek(PC++) << 8);
operand = peek(high | (uInt8)(low + Y));
uInt16 low = peek(PC++, true);
uInt16 high = ((uInt16)peek(PC++, true) << 8);
operand = peek(high | (uInt8)(low + Y), false);
if((low + Y) > 0xFF)
operand = peek((high | low) + Y);
operand = peek((high | low) + Y, false);
}')
define(M6502_ABSOLUTEY_WRITE, `{
uInt16 low = peek(PC++);
uInt16 high = ((uInt16)peek(PC++) << 8);
peek(high | (uInt8)(low + Y));
uInt16 low = peek(PC++, true);
uInt16 high = ((uInt16)peek(PC++, true) << 8);
peek(high | (uInt8)(low + Y), false);
operandAddress = (high | low) + Y;
}')
define(M6502_ABSOLUTEY_READMODIFYWRITE, `{
uInt16 low = peek(PC++);
uInt16 high = ((uInt16)peek(PC++) << 8);
peek(high | (uInt8)(low + Y));
uInt16 low = peek(PC++, true);
uInt16 high = ((uInt16)peek(PC++, true) << 8);
peek(high | (uInt8)(low + Y), false);
operandAddress = (high | low) + Y;
operand = peek(operandAddress);
operand = peek(operandAddress, false);
poke(operandAddress, operand);
}')
define(M6502_ZERO_READ, `{
operand = peek(peek(PC++));
operand = peek(peek(PC++, true), false);
}')
define(M6502_ZERO_WRITE, `{
operandAddress = peek(PC++);
operandAddress = peek(PC++, true);
}')
define(M6502_ZERO_READMODIFYWRITE, `{
operandAddress = peek(PC++);
operand = peek(operandAddress);
operandAddress = peek(PC++, true);
operand = peek(operandAddress, false);
poke(operandAddress, operand);
}')
define(M6502_ZEROX_READ, `{
uInt8 address = peek(PC++);
peek(address);
uInt8 address = peek(PC++, true);
peek(address, false);
address += X;
operand = peek(address);
operand = peek(address, false);
}')
define(M6502_ZEROX_WRITE, `{
operandAddress = peek(PC++);
peek(operandAddress);
operandAddress = peek(PC++, true);
peek(operandAddress, false);
operandAddress = (operandAddress + X) & 0xFF;
}')
define(M6502_ZEROX_READMODIFYWRITE, `{
operandAddress = peek(PC++);
peek(operandAddress);
operandAddress = peek(PC++, true);
peek(operandAddress, false);
operandAddress = (operandAddress + X) & 0xFF;
operand = peek(operandAddress);
operand = peek(operandAddress, false);
poke(operandAddress, operand);
}')
define(M6502_ZEROY_READ, `{
uInt8 address = peek(PC++);
peek(address);
uInt8 address = peek(PC++, true);
peek(address, false);
address += Y;
operand = peek(address);
operand = peek(address, false);
}')
define(M6502_ZEROY_WRITE, `{
operandAddress = peek(PC++);
peek(operandAddress);
operandAddress = peek(PC++, true);
peek(operandAddress, false);
operandAddress = (operandAddress + Y) & 0xFF;
}')
define(M6502_ZEROY_READMODIFYWRITE, `{
operandAddress = peek(PC++);
peek(operandAddress);
operandAddress = peek(PC++, true);
peek(operandAddress, false);
operandAddress = (operandAddress + Y) & 0xFF;
operand = peek(operandAddress);
operand = peek(operandAddress, false);
poke(operandAddress, operand);
}')
define(M6502_INDIRECT, `{
uInt16 addr = peek(PC++);
addr |= ((uInt16)peek(PC++) << 8);
uInt16 addr = peek(PC++, true);
addr |= ((uInt16)peek(PC++, true) << 8);
// Simulate the error in the indirect addressing mode!
uInt16 high = NOTSAMEPAGE(addr, addr + 1) ? (addr & 0xff00) : (addr + 1);
operandAddress = peek(addr);
operandAddress |= ((uInt16)peek(high) << 8);
operandAddress = peek(addr, false);
operandAddress |= ((uInt16)peek(high, false) << 8);
}')
define(M6502_INDIRECTX_READ, `{
uInt8 pointer = peek(PC++);
peek(pointer);
uInt8 pointer = peek(PC++, true);
peek(pointer, false);
pointer += X;
uInt16 address = peek(pointer++);
address |= ((uInt16)peek(pointer) << 8);
operand = peek(address);
uInt16 address = peek(pointer++, false);
address |= ((uInt16)peek(pointer, false) << 8);
operand = peek(address, false);
}')
define(M6502_INDIRECTX_WRITE, `{
uInt8 pointer = peek(PC++);
peek(pointer);
uInt8 pointer = peek(PC++, true);
peek(pointer, false);
pointer += X;
operandAddress = peek(pointer++);
operandAddress |= ((uInt16)peek(pointer) << 8);
operandAddress = peek(pointer++, false);
operandAddress |= ((uInt16)peek(pointer, false) << 8);
}')
define(M6502_INDIRECTX_READMODIFYWRITE, `{
uInt8 pointer = peek(PC++);
peek(pointer);
uInt8 pointer = peek(PC++, true);
peek(pointer, false);
pointer += X;
operandAddress = peek(pointer++);
operandAddress |= ((uInt16)peek(pointer) << 8);
operand = peek(operandAddress);
operandAddress = peek(pointer++, false);
operandAddress |= ((uInt16)peek(pointer, false) << 8);
operand = peek(operandAddress, false);
poke(operandAddress, operand);
}')
define(M6502_INDIRECTY_READ, `{
uInt8 pointer = peek(PC++);
uInt16 low = peek(pointer++);
uInt16 high = ((uInt16)peek(pointer) << 8);
operand = peek(high | (uInt8)(low + Y));
uInt8 pointer = peek(PC++, true);
uInt16 low = peek(pointer++, false);
uInt16 high = ((uInt16)peek(pointer, false) << 8);
operand = peek(high | (uInt8)(low + Y), false);
if((low + Y) > 0xFF)
operand = peek((high | low) + Y);
operand = peek((high | low) + Y, false);
}')
define(M6502_INDIRECTY_WRITE, `{
uInt8 pointer = peek(PC++);
uInt16 low = peek(pointer++);
uInt16 high = ((uInt16)peek(pointer) << 8);
peek(high | (uInt8)(low + Y));
uInt8 pointer = peek(PC++, true);
uInt16 low = peek(pointer++, false);
uInt16 high = ((uInt16)peek(pointer, false) << 8);
peek(high | (uInt8)(low + Y), false);
operandAddress = (high | low) + Y;
}')
define(M6502_INDIRECTY_READMODIFYWRITE, `{
uInt8 pointer = peek(PC++);
uInt16 low = peek(pointer++);
uInt16 high = ((uInt16)peek(pointer) << 8);
peek(high | (uInt8)(low + Y));
uInt8 pointer = peek(PC++, true);
uInt16 low = peek(pointer++, false);
uInt16 high = ((uInt16)peek(pointer, false) << 8);
peek(high | (uInt8)(low + Y), false);
operandAddress = (high | low) + Y;
operand = peek(operandAddress);
operand = peek(operandAddress, false);
poke(operandAddress, operand);
}')
@ -230,10 +230,10 @@ define(M6502_INDIRECTY_READMODIFYWRITE, `{
define(M6502_BCC, `{
if(!C)
{
peek(PC);
peek(PC, false);
uInt16 address = PC + (Int8)operand;
if(NOTSAMEPAGE(PC, address))
peek((PC & 0xFF00) | (address & 0x00FF));
peek((PC & 0xFF00) | (address & 0x00FF), false);
PC = address;
}
}')
@ -241,10 +241,10 @@ define(M6502_BCC, `{
define(M6502_BCS, `{
if(C)
{
peek(PC);
peek(PC, false);
uInt16 address = PC + (Int8)operand;
if(NOTSAMEPAGE(PC, address))
peek((PC & 0xFF00) | (address & 0x00FF));
peek((PC & 0xFF00) | (address & 0x00FF), false);
PC = address;
}
}')
@ -252,10 +252,10 @@ define(M6502_BCS, `{
define(M6502_BEQ, `{
if(!notZ)
{
peek(PC);
peek(PC, false);
uInt16 address = PC + (Int8)operand;
if(NOTSAMEPAGE(PC, address))
peek((PC & 0xFF00) | (address & 0x00FF));
peek((PC & 0xFF00) | (address & 0x00FF), false);
PC = address;
}
}')
@ -263,10 +263,10 @@ define(M6502_BEQ, `{
define(M6502_BMI, `{
if(N)
{
peek(PC);
peek(PC, false);
uInt16 address = PC + (Int8)operand;
if(NOTSAMEPAGE(PC, address))
peek((PC & 0xFF00) | (address & 0x00FF));
peek((PC & 0xFF00) | (address & 0x00FF), false);
PC = address;
}
}')
@ -274,10 +274,10 @@ define(M6502_BMI, `{
define(M6502_BNE, `{
if(notZ)
{
peek(PC);
peek(PC, false);
uInt16 address = PC + (Int8)operand;
if(NOTSAMEPAGE(PC, address))
peek((PC & 0xFF00) | (address & 0x00FF));
peek((PC & 0xFF00) | (address & 0x00FF), false);
PC = address;
}
}')
@ -285,10 +285,10 @@ define(M6502_BNE, `{
define(M6502_BPL, `{
if(!N)
{
peek(PC);
peek(PC, false);
uInt16 address = PC + (Int8)operand;
if(NOTSAMEPAGE(PC, address))
peek((PC & 0xFF00) | (address & 0x00FF));
peek((PC & 0xFF00) | (address & 0x00FF), false);
PC = address;
}
}')
@ -296,10 +296,10 @@ define(M6502_BPL, `{
define(M6502_BVC, `{
if(!V)
{
peek(PC);
peek(PC, false);
uInt16 address = PC + (Int8)operand;
if(NOTSAMEPAGE(PC, address))
peek((PC & 0xFF00) | (address & 0x00FF));
peek((PC & 0xFF00) | (address & 0x00FF), false);
PC = address;
}
}')
@ -307,10 +307,10 @@ define(M6502_BVC, `{
define(M6502_BVS, `{
if(V)
{
peek(PC);
peek(PC, false);
uInt16 address = PC + (Int8)operand;
if(NOTSAMEPAGE(PC, address))
peek((PC & 0xFF00) | (address & 0x00FF));
peek((PC & 0xFF00) | (address & 0x00FF), false);
PC = address;
}
}')
@ -449,7 +449,7 @@ define(M6502_BIT, `{
}')
define(M6502_BRK, `{
peek(PC++);
peek(PC++, true);
B = true;
@ -459,8 +459,8 @@ define(M6502_BRK, `{
I = true;
PC = peek(0xfffe);
PC |= ((uInt16)peek(0xffff) << 8);
PC = peek(0xfffe, false);
PC |= ((uInt16)peek(0xffff, false) << 8);
}')
define(M6502_CLC, `{
@ -598,8 +598,8 @@ define(M6502_JMP, `{
}')
define(M6502_JSR, `{
uInt8 low = peek(PC++);
peek(0x0100 + SP);
uInt8 low = peek(PC++, true);
peek(0x0100 + SP, false);
// It seems that the 650x does not push the address of the next instruction
// on the stack it actually pushes the address of the next instruction
@ -607,7 +607,7 @@ define(M6502_JSR, `{
poke(0x0100 + SP--, PC >> 8);
poke(0x0100 + SP--, PC & 0xff);
PC = low | ((uInt16)peek(PC++) << 8);
PC = low | ((uInt16)peek(PC++, true) << 8);
}')
define(M6502_LAS, `{
@ -689,15 +689,15 @@ define(M6502_PHP, `{
}')
define(M6502_PLA, `{
peek(0x0100 + SP++);
A = peek(0x0100 + SP);
peek(0x0100 + SP++, false);
A = peek(0x0100 + SP, false);
notZ = A;
N = A & 0x80;
}')
define(M6502_PLP, `{
peek(0x0100 + SP++);
PS(peek(0x0100 + SP));
peek(0x0100 + SP++, false);
PS(peek(0x0100 + SP, false));
}')
define(M6502_RLA, `{
@ -800,17 +800,17 @@ define(M6502_RRA, `{
}')
define(M6502_RTI, `{
peek(0x0100 + SP++);
PS(peek(0x0100 + SP++));
PC = peek(0x0100 + SP++);
PC |= ((uInt16)peek(0x0100 + SP) << 8);
peek(0x0100 + SP++, false);
PS(peek(0x0100 + SP++, false));
PC = peek(0x0100 + SP++, false);
PC |= ((uInt16)peek(0x0100 + SP, false) << 8);
}')
define(M6502_RTS, `{
peek(0x0100 + SP++);
PC = peek(0x0100 + SP++);
PC |= ((uInt16)peek(0x0100 + SP) << 8);
peek(PC++);
peek(0x0100 + SP++, false);
PC = peek(0x0100 + SP++, false);
PC |= ((uInt16)peek(0x0100 + SP, false) << 8);
peek(PC++, true);
}')
define(M6502_SAX, `{

View File

@ -95,11 +95,7 @@ void M6532::install(System& system, Device& device)
assert((0x1080 & mask) == 0);
// All accesses are to the given device
System::PageAccess access;
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = &device;
access.type = System::PA_READWRITE;
System::PageAccess access(0, 0, 0, &device, System::PA_READWRITE);
// We're installing in a 2600 system
for(int address = 0; address < 8192; address += (1 << shift))

View File

@ -212,14 +212,14 @@ void System::clearDirtyPages()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 System::peek(uInt16 addr)
uInt8 System::peek(uInt16 addr, bool isCode)
{
PageAccess& access = myPageAccessTable[(addr & myAddressMask) >> myPageShift];
uInt8 result;
// See if this page uses direct accessing or not
if(access.directPeekBase != 0)
if(access.directPeekBase)
{
result = *(access.directPeekBase + (addr & myPageMask));
}
@ -230,8 +230,15 @@ uInt8 System::peek(uInt16 addr)
#ifdef DEBUGGER_SUPPORT
if(!myDataBusLocked)
#endif
{
if(access.codeAccessBase)
*(access.codeAccessBase + (addr & myPageMask)) = isCode;
myDataBusState = result;
}
#else
myDataBusState = result;
#endif
return result;
}
@ -261,6 +268,21 @@ void System::poke(uInt16 addr, uInt8 value)
myDataBusState = value;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool System::isCode(uInt16 addr)
{
#ifdef DEBUGGER_SUPPORT
PageAccess& access = myPageAccessTable[(addr & myAddressMask) >> myPageShift];
if(access.codeAccessBase)
return *(access.codeAccessBase + (addr & myPageMask)) ? true : false;
else
return false;
#else
return false;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::lockDataBus()
{

View File

@ -255,9 +255,12 @@ class System : public Serializable
address occurs before it's sent to the device mapped at
the address.
@param address The address from which the value should be loaded
@param isCode Indicates that this address is part of an instruction
@return The byte at the specified address
*/
uInt8 peek(uInt16 address);
uInt8 peek(uInt16 address, bool isCode = false);
/**
Change the byte at the specified address to the given value.
@ -269,8 +272,8 @@ class System : public Serializable
if the device is handling the poke, we depend on its return value
for this information.
@param address The address where the value should be stored
@param value The value to be stored at the address
@param address The address where the value should be stored
@param value The value to be stored at the address
*/
void poke(uInt16 address, uInt8 value);
@ -286,6 +289,13 @@ class System : public Serializable
void lockDataBus();
void unlockDataBus();
/**
Answer whether or not the given address has ever been used as
code. That is, it has ever been stored in either the IR or the PC,
or otherwise been executed.
*/
bool isCode(uInt16 address);
public:
/**
Describes how a page can be accessed
@ -317,6 +327,15 @@ class System : public Serializable
*/
uInt8* directPokeBase;
/**
Pointer to a lookup table for marking an address as CODE. A CODE
section is defined as any address that appears in the program
counter. Currently, this is used by the debugger/disassembler to
conclusively determine if a section of address space is CODE, even
if the disassembler failed to mark it as such.
*/
uInt8* codeAccessBase;
/**
Pointer to the device associated with this page or to the system's
null device if the page hasn't been mapped to a device.
@ -328,7 +347,23 @@ class System : public Serializable
(READ, WRITE, READWRITE)
*/
PageAccessType type;
};
// Constructors
PageAccess()
: directPeekBase(0),
directPokeBase(0),
codeAccessBase(0),
device(0),
type(System::PA_READ) { }
PageAccess(uInt8* peek, uInt8* poke, uInt8* code, Device* dev,
PageAccessType access)
: directPeekBase(peek),
directPokeBase(poke),
codeAccessBase(code),
device(dev),
type(access) { }
};
/**
Set the page accessing method for the specified page.

View File

@ -293,11 +293,7 @@ void TIA::install(System& system, Device& device)
mySystem->resetCycles();
// All accesses are to the given device
System::PageAccess access;
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = &device;
access.type = System::PA_READWRITE;
System::PageAccess access(0, 0, 0, &device, System::PA_READWRITE);
// We're installing in a 2600 system
for(uInt32 i = 0; i < 8192; i += (1 << shift))

View File

@ -1503,7 +1503,14 @@
};
buildConfigurationList = 2D91752109BA903B0026E9FF /* Build configuration list for PBXProject "stella_intel" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
Japanese,
French,
German,
);
mainGroup = 29B97314FDCFA39411CA2CEA /* «PROJECTNAMEASXML» */;
projectDirPath = "";
projectRoot = "";