stella/src/emucore/System.cxx

345 lines
8.5 KiB
C++
Raw Normal View History

//============================================================================
//
// MM MM 6666 555555 0000 2222
// MMMM MMMM 66 66 55 00 00 22 22
// MM MMM MM 66 55 00 00 22
// MM M MM 66666 55555 00 00 22222 -- "A 6502 Microprocessor Emulator"
// MM MM 66 66 55 00 00 22
// MM MM 66 66 55 55 00 00 22
// MM MM 6666 5555 0000 222222
//
// Copyright (c) 1995-2010 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#include <assert.h>
#include <iostream>
#include "Device.hxx"
#include "M6502.hxx"
#include "M6532.hxx"
#include "TIA.hxx"
#include "System.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
System::System(uInt16 n, uInt16 m)
: myAddressMask((1 << n) - 1),
myPageShift(m),
myPageMask((1 << m) - 1),
myNumberOfPages(1 << (n - m)),
myNumberOfDevices(0),
myM6502(0),
myTIA(0),
myCycles(0),
myDataBusState(0),
myDataBusLocked(false)
{
// Make sure the arguments are reasonable
assert((1 <= m) && (m <= n) && (n <= 16));
// Create a new random number generator
myRandom = new Random();
// Allocate page table and dirty list
myPageAccessTable = new PageAccess[myNumberOfPages];
myPageIsDirtyTable = new bool[myNumberOfPages];
// Initialize page access table
PageAccess access;
access.directPeekBase = 0;
access.directPokeBase = 0;
access.device = &myNullDevice;
for(int page = 0; page < myNumberOfPages; ++page)
{
setPageAccess(page, access);
myPageIsDirtyTable[page] = false;
}
// Bus starts out unlocked (in other words, peek() changes myDataBusState)
myDataBusLocked = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
System::~System()
{
// Free the devices attached to me, since I own them
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
{
delete myDevices[i];
}
// Free the M6502 that I own
delete myM6502;
// Free my page access table and dirty list
delete[] myPageAccessTable;
delete[] myPageIsDirtyTable;
// Free the random number generator
delete myRandom;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::reset()
{
// Reset system cycle counter
resetCycles();
// First we reset the devices attached to myself
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
{
myDevices[i]->reset();
}
// Now we reset the processor if it exists
if(myM6502 != 0)
{
myM6502->reset();
}
// There are no dirty pages upon startup
clearDirtyPages();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::attach(Device* device)
{
assert(myNumberOfDevices < 100);
// Add device to my collection of devices
myDevices[myNumberOfDevices++] = device;
// Ask the device to install itself
device->install(*this);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::attach(M6502* m6502)
{
// Remember the processor
myM6502 = m6502;
// Ask the processor to install itself
myM6502->install(*this);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::attach(M6532* m6532)
{
// Remember the processor
myM6532 = m6532;
// Attach it as a normal device
attach((Device*) m6532);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::attach(TIA* tia)
{
myTIA = tia;
attach((Device*) tia);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::resetCycles()
{
// First we let all of the device attached to me know about the reset
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
{
myDevices[i]->systemCyclesReset();
}
// Now, we reset cycle count to zero
myCycles = 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::setPageAccess(uInt16 page, const PageAccess& access)
{
// Make sure the page is within range
assert(page < myNumberOfPages);
// Make sure the access methods make sense
assert(access.device != 0);
myPageAccessTable[page] = access;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const System::PageAccess& System::getPageAccess(uInt16 page) const
{
// Make sure the page is within range
assert(page < myNumberOfPages);
return myPageAccessTable[page];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
System::PageType System::getPageType(uInt16 addr) const
{
return myPageAccessTable[(addr & myAddressMask) >> myPageShift].type;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::setDirtyPage(uInt16 addr)
{
myPageIsDirtyTable[(addr & myAddressMask) >> myPageShift] = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool System::isPageDirty(uInt16 start_addr, uInt16 end_addr) const
{
uInt16 start_page = (start_addr & myAddressMask) >> myPageShift;
uInt16 end_page = (end_addr & myAddressMask) >> myPageShift;
for(uInt16 page = start_page; page <= end_page; ++page)
if(myPageIsDirtyTable[page])
return true;
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::clearDirtyPages()
{
for(uInt32 i = 0; i < myNumberOfPages; ++i)
myPageIsDirtyTable[i] = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 System::peek(uInt16 addr)
{
PageAccess& access = myPageAccessTable[(addr & myAddressMask) >> myPageShift];
uInt8 result;
// See if this page uses direct accessing or not
if(access.directPeekBase != 0)
{
result = *(access.directPeekBase + (addr & myPageMask));
}
else
{
result = access.device->peek(addr);
}
#ifdef DEBUGGER_SUPPORT
if(!myDataBusLocked)
#endif
myDataBusState = result;
return result;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::poke(uInt16 addr, uInt8 value)
{
uInt16 page = (addr & myAddressMask) >> myPageShift;
PageAccess& access = myPageAccessTable[page];
// See if this page uses direct accessing or not
if(access.directPokeBase != 0)
{
// Since we have direct access to this poke, we can dirty its page
*(access.directPokeBase + (addr & myPageMask)) = value;
myPageIsDirtyTable[page] = true;
}
else
{
// The specific device informs us if the poke succeeded
myPageIsDirtyTable[page] = access.device->poke(addr, value);
}
#ifdef DEBUGGER_SUPPORT
if(!myDataBusLocked)
#endif
myDataBusState = value;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::lockDataBus()
{
myDataBusLocked = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::unlockDataBus()
{
myDataBusLocked = false;
}
OK, another huge commit. I need to commit this now, because things are starting to go out of sync on my development machines. OK, where to begin ... Changed state file format, so older state files will no longer work. The changes aren't finalized yet, so expect more breakage. Added getByte() and putByte() methods to serialized data, resulting in smaller state files (previously, 1-byte values were stored as 4-byte ints). Totally reworked controller handling code. Controller state is now explicitly set with an ::update() method, making it easier to serialize. Some work is still required on the serialization stuff for more advanced controllers. Added a 'Serializable' interface to all carts, device, controllers, etc that can be (de)serialized. This fixes a long-standing design issue which I personally caused many years ago. Console switches state (SWCHB register) is now saved to state files. Added beginnings of movie support. Basically, this saves an initial state file, and thereafter continuously saves controller and console switches state. Support is still somewhat rough and there's no UI for it, but it does successfully save and later load/play state movies. Removed specific events for driving controllers, and have them use joystick events instead. This has the nice side effect that joystick direction remapping 'just works' for driving controllers too. Fixed issues with paddle emulation seen in 'Night Driver' ROM. Related to this, removed a hack wrt paddles when grabmouse is enabled. There's still some work to do when using the mouse to emulate paddles, but the Stelladaptor and real paddles work fine. Added beginnings of TrackBall CX-22 controller emulation. It doesn't actually do anything yet, but the class is there :) Probably some other stuff that I'm forgetting ... git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1385 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2007-10-03 21:41:19 +00:00
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool System::save(Serializer& out) const
{
try
{
out.putString(name());
OK, another huge commit. I need to commit this now, because things are starting to go out of sync on my development machines. OK, where to begin ... Changed state file format, so older state files will no longer work. The changes aren't finalized yet, so expect more breakage. Added getByte() and putByte() methods to serialized data, resulting in smaller state files (previously, 1-byte values were stored as 4-byte ints). Totally reworked controller handling code. Controller state is now explicitly set with an ::update() method, making it easier to serialize. Some work is still required on the serialization stuff for more advanced controllers. Added a 'Serializable' interface to all carts, device, controllers, etc that can be (de)serialized. This fixes a long-standing design issue which I personally caused many years ago. Console switches state (SWCHB register) is now saved to state files. Added beginnings of movie support. Basically, this saves an initial state file, and thereafter continuously saves controller and console switches state. Support is still somewhat rough and there's no UI for it, but it does successfully save and later load/play state movies. Removed specific events for driving controllers, and have them use joystick events instead. This has the nice side effect that joystick direction remapping 'just works' for driving controllers too. Fixed issues with paddle emulation seen in 'Night Driver' ROM. Related to this, removed a hack wrt paddles when grabmouse is enabled. There's still some work to do when using the mouse to emulate paddles, but the Stelladaptor and real paddles work fine. Added beginnings of TrackBall CX-22 controller emulation. It doesn't actually do anything yet, but the class is there :) Probably some other stuff that I'm forgetting ... git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1385 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2007-10-03 21:41:19 +00:00
out.putInt(myCycles);
if(!myM6502->save(out))
return false;
// Now save the state of each device
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
if(!myDevices[i]->save(out))
return false;
}
catch(const char* msg)
OK, another huge commit. I need to commit this now, because things are starting to go out of sync on my development machines. OK, where to begin ... Changed state file format, so older state files will no longer work. The changes aren't finalized yet, so expect more breakage. Added getByte() and putByte() methods to serialized data, resulting in smaller state files (previously, 1-byte values were stored as 4-byte ints). Totally reworked controller handling code. Controller state is now explicitly set with an ::update() method, making it easier to serialize. Some work is still required on the serialization stuff for more advanced controllers. Added a 'Serializable' interface to all carts, device, controllers, etc that can be (de)serialized. This fixes a long-standing design issue which I personally caused many years ago. Console switches state (SWCHB register) is now saved to state files. Added beginnings of movie support. Basically, this saves an initial state file, and thereafter continuously saves controller and console switches state. Support is still somewhat rough and there's no UI for it, but it does successfully save and later load/play state movies. Removed specific events for driving controllers, and have them use joystick events instead. This has the nice side effect that joystick direction remapping 'just works' for driving controllers too. Fixed issues with paddle emulation seen in 'Night Driver' ROM. Related to this, removed a hack wrt paddles when grabmouse is enabled. There's still some work to do when using the mouse to emulate paddles, but the Stelladaptor and real paddles work fine. Added beginnings of TrackBall CX-22 controller emulation. It doesn't actually do anything yet, but the class is there :) Probably some other stuff that I'm forgetting ... git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1385 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2007-10-03 21:41:19 +00:00
{
cerr << "ERROR: System::save" << endl << " " << msg << endl;
OK, another huge commit. I need to commit this now, because things are starting to go out of sync on my development machines. OK, where to begin ... Changed state file format, so older state files will no longer work. The changes aren't finalized yet, so expect more breakage. Added getByte() and putByte() methods to serialized data, resulting in smaller state files (previously, 1-byte values were stored as 4-byte ints). Totally reworked controller handling code. Controller state is now explicitly set with an ::update() method, making it easier to serialize. Some work is still required on the serialization stuff for more advanced controllers. Added a 'Serializable' interface to all carts, device, controllers, etc that can be (de)serialized. This fixes a long-standing design issue which I personally caused many years ago. Console switches state (SWCHB register) is now saved to state files. Added beginnings of movie support. Basically, this saves an initial state file, and thereafter continuously saves controller and console switches state. Support is still somewhat rough and there's no UI for it, but it does successfully save and later load/play state movies. Removed specific events for driving controllers, and have them use joystick events instead. This has the nice side effect that joystick direction remapping 'just works' for driving controllers too. Fixed issues with paddle emulation seen in 'Night Driver' ROM. Related to this, removed a hack wrt paddles when grabmouse is enabled. There's still some work to do when using the mouse to emulate paddles, but the Stelladaptor and real paddles work fine. Added beginnings of TrackBall CX-22 controller emulation. It doesn't actually do anything yet, but the class is there :) Probably some other stuff that I'm forgetting ... git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1385 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2007-10-03 21:41:19 +00:00
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool System::load(Serializer& in)
OK, another huge commit. I need to commit this now, because things are starting to go out of sync on my development machines. OK, where to begin ... Changed state file format, so older state files will no longer work. The changes aren't finalized yet, so expect more breakage. Added getByte() and putByte() methods to serialized data, resulting in smaller state files (previously, 1-byte values were stored as 4-byte ints). Totally reworked controller handling code. Controller state is now explicitly set with an ::update() method, making it easier to serialize. Some work is still required on the serialization stuff for more advanced controllers. Added a 'Serializable' interface to all carts, device, controllers, etc that can be (de)serialized. This fixes a long-standing design issue which I personally caused many years ago. Console switches state (SWCHB register) is now saved to state files. Added beginnings of movie support. Basically, this saves an initial state file, and thereafter continuously saves controller and console switches state. Support is still somewhat rough and there's no UI for it, but it does successfully save and later load/play state movies. Removed specific events for driving controllers, and have them use joystick events instead. This has the nice side effect that joystick direction remapping 'just works' for driving controllers too. Fixed issues with paddle emulation seen in 'Night Driver' ROM. Related to this, removed a hack wrt paddles when grabmouse is enabled. There's still some work to do when using the mouse to emulate paddles, but the Stelladaptor and real paddles work fine. Added beginnings of TrackBall CX-22 controller emulation. It doesn't actually do anything yet, but the class is there :) Probably some other stuff that I'm forgetting ... git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1385 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2007-10-03 21:41:19 +00:00
{
try
{
if(in.getString() != name())
OK, another huge commit. I need to commit this now, because things are starting to go out of sync on my development machines. OK, where to begin ... Changed state file format, so older state files will no longer work. The changes aren't finalized yet, so expect more breakage. Added getByte() and putByte() methods to serialized data, resulting in smaller state files (previously, 1-byte values were stored as 4-byte ints). Totally reworked controller handling code. Controller state is now explicitly set with an ::update() method, making it easier to serialize. Some work is still required on the serialization stuff for more advanced controllers. Added a 'Serializable' interface to all carts, device, controllers, etc that can be (de)serialized. This fixes a long-standing design issue which I personally caused many years ago. Console switches state (SWCHB register) is now saved to state files. Added beginnings of movie support. Basically, this saves an initial state file, and thereafter continuously saves controller and console switches state. Support is still somewhat rough and there's no UI for it, but it does successfully save and later load/play state movies. Removed specific events for driving controllers, and have them use joystick events instead. This has the nice side effect that joystick direction remapping 'just works' for driving controllers too. Fixed issues with paddle emulation seen in 'Night Driver' ROM. Related to this, removed a hack wrt paddles when grabmouse is enabled. There's still some work to do when using the mouse to emulate paddles, but the Stelladaptor and real paddles work fine. Added beginnings of TrackBall CX-22 controller emulation. It doesn't actually do anything yet, but the class is there :) Probably some other stuff that I'm forgetting ... git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1385 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2007-10-03 21:41:19 +00:00
return false;
myCycles = (uInt32) in.getInt();
// Next, load state for the CPU
if(!myM6502->load(in))
return false;
// Now load the state of each device
for(uInt32 i = 0; i < myNumberOfDevices; ++i)
if(!myDevices[i]->load(in))
return false;
}
catch(const char* msg)
OK, another huge commit. I need to commit this now, because things are starting to go out of sync on my development machines. OK, where to begin ... Changed state file format, so older state files will no longer work. The changes aren't finalized yet, so expect more breakage. Added getByte() and putByte() methods to serialized data, resulting in smaller state files (previously, 1-byte values were stored as 4-byte ints). Totally reworked controller handling code. Controller state is now explicitly set with an ::update() method, making it easier to serialize. Some work is still required on the serialization stuff for more advanced controllers. Added a 'Serializable' interface to all carts, device, controllers, etc that can be (de)serialized. This fixes a long-standing design issue which I personally caused many years ago. Console switches state (SWCHB register) is now saved to state files. Added beginnings of movie support. Basically, this saves an initial state file, and thereafter continuously saves controller and console switches state. Support is still somewhat rough and there's no UI for it, but it does successfully save and later load/play state movies. Removed specific events for driving controllers, and have them use joystick events instead. This has the nice side effect that joystick direction remapping 'just works' for driving controllers too. Fixed issues with paddle emulation seen in 'Night Driver' ROM. Related to this, removed a hack wrt paddles when grabmouse is enabled. There's still some work to do when using the mouse to emulate paddles, but the Stelladaptor and real paddles work fine. Added beginnings of TrackBall CX-22 controller emulation. It doesn't actually do anything yet, but the class is there :) Probably some other stuff that I'm forgetting ... git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1385 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2007-10-03 21:41:19 +00:00
{
cerr << "ERROR: System::load" << endl << " " << msg << endl;
OK, another huge commit. I need to commit this now, because things are starting to go out of sync on my development machines. OK, where to begin ... Changed state file format, so older state files will no longer work. The changes aren't finalized yet, so expect more breakage. Added getByte() and putByte() methods to serialized data, resulting in smaller state files (previously, 1-byte values were stored as 4-byte ints). Totally reworked controller handling code. Controller state is now explicitly set with an ::update() method, making it easier to serialize. Some work is still required on the serialization stuff for more advanced controllers. Added a 'Serializable' interface to all carts, device, controllers, etc that can be (de)serialized. This fixes a long-standing design issue which I personally caused many years ago. Console switches state (SWCHB register) is now saved to state files. Added beginnings of movie support. Basically, this saves an initial state file, and thereafter continuously saves controller and console switches state. Support is still somewhat rough and there's no UI for it, but it does successfully save and later load/play state movies. Removed specific events for driving controllers, and have them use joystick events instead. This has the nice side effect that joystick direction remapping 'just works' for driving controllers too. Fixed issues with paddle emulation seen in 'Night Driver' ROM. Related to this, removed a hack wrt paddles when grabmouse is enabled. There's still some work to do when using the mouse to emulate paddles, but the Stelladaptor and real paddles work fine. Added beginnings of TrackBall CX-22 controller emulation. It doesn't actually do anything yet, but the class is there :) Probably some other stuff that I'm forgetting ... git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1385 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2007-10-03 21:41:19 +00:00
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
System::System(const System& s)
: myAddressMask(s.myAddressMask),
myPageShift(s.myPageShift),
myPageMask(s.myPageMask),
myNumberOfPages(s.myNumberOfPages)
{
assert(false);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
System& System::operator = (const System&)
{
assert(false);
return *this;
}