mirror of https://github.com/stella-emu/stella.git
Added support for X07 bankswitching, which is used for the 2007 AtariAge Holiday Cart. TODO: Find a way to autodetect this bankswitching type.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1407 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
3882e8e841
commit
7112444714
|
@ -13,7 +13,7 @@
|
||||||
// See the file "license" for information on usage and redistribution of
|
// See the file "license" for information on usage and redistribution of
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//
|
//
|
||||||
// $Id: Cart.cxx,v 1.39 2008-02-24 16:51:52 stephena Exp $
|
// $Id: Cart.cxx,v 1.40 2008-02-27 14:14:38 estolberg Exp $
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
@ -44,6 +44,7 @@
|
||||||
#include "CartCV.hxx"
|
#include "CartCV.hxx"
|
||||||
#include "CartUA.hxx"
|
#include "CartUA.hxx"
|
||||||
#include "CartSB.hxx"
|
#include "CartSB.hxx"
|
||||||
|
#include "CartX07.hxx"
|
||||||
#include "MD5.hxx"
|
#include "MD5.hxx"
|
||||||
#include "Props.hxx"
|
#include "Props.hxx"
|
||||||
#include "Settings.hxx"
|
#include "Settings.hxx"
|
||||||
|
@ -136,6 +137,8 @@ Cartridge* Cartridge::create(const uInt8* image, uInt32 size,
|
||||||
cartridge = new Cartridge0840(image);
|
cartridge = new Cartridge0840(image);
|
||||||
else if(type == "SB")
|
else if(type == "SB")
|
||||||
cartridge = new CartridgeSB(image, size);
|
cartridge = new CartridgeSB(image, size);
|
||||||
|
else if(type == "X07")
|
||||||
|
cartridge = new CartridgeX07(image);
|
||||||
else
|
else
|
||||||
cerr << "ERROR: Invalid cartridge type " << type << " ..." << endl;
|
cerr << "ERROR: Invalid cartridge type " << type << " ..." << endl;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,220 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2008 by Bradford W. Mott and the Stella team
|
||||||
|
//
|
||||||
|
// See the file "license" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//
|
||||||
|
// $Id:
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "System.hxx"
|
||||||
|
#include "M6532.hxx"
|
||||||
|
#include "TIA.hxx"
|
||||||
|
#include "CartX07.hxx"
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
CartridgeX07::CartridgeX07(const uInt8* image)
|
||||||
|
{
|
||||||
|
// Copy the ROM image into my buffer
|
||||||
|
for(uInt32 addr = 0; addr < 65536; ++addr)
|
||||||
|
{
|
||||||
|
myImage[addr] = image[addr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
CartridgeX07::~CartridgeX07()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeX07::reset()
|
||||||
|
{
|
||||||
|
// Upon reset we switch to bank 0
|
||||||
|
bank(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeX07::install(System& system)
|
||||||
|
{
|
||||||
|
mySystem = &system;
|
||||||
|
uInt16 shift = mySystem->pageShift();
|
||||||
|
uInt16 mask = mySystem->pageMask();
|
||||||
|
|
||||||
|
// Make sure the system we're being installed in has a page size that'll work
|
||||||
|
assert((0x1000 & mask) == 0);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
for(uInt32 i = 0x00; i < 0x1000; i += (1 << shift))
|
||||||
|
{
|
||||||
|
access.directPeekBase = 0;
|
||||||
|
access.directPokeBase = 0;
|
||||||
|
access.device = this;
|
||||||
|
mySystem->setPageAccess(i >> shift, access);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Install pages for bank 0
|
||||||
|
bank(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt8 CartridgeX07::peek(uInt16 address)
|
||||||
|
{
|
||||||
|
uInt8 value = 0;
|
||||||
|
|
||||||
|
// Check for RAM or TIA mirroring
|
||||||
|
uInt16 lowAddress = address & 0x3ff;
|
||||||
|
if(lowAddress & 0x80)
|
||||||
|
value = mySystem->m6532().peek(address);
|
||||||
|
else if(!(lowAddress & 0x200))
|
||||||
|
value = mySystem->tia().peek(address);
|
||||||
|
|
||||||
|
// Switch banks if necessary
|
||||||
|
if((address & 0x180f) == 0x080d) bank((address & 0xf0) >> 4);
|
||||||
|
else if((address & 0x1880) == 0)
|
||||||
|
{
|
||||||
|
if((myCurrentBank & 0xe) == 0xe)
|
||||||
|
bank(((address & 0x40) >> 6) | (myCurrentBank & 0xe));
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeX07::poke(uInt16 address, uInt8 value)
|
||||||
|
{
|
||||||
|
// Check for RAM or TIA mirroring
|
||||||
|
uInt16 lowAddress = address & 0x3ff;
|
||||||
|
if(lowAddress & 0x80)
|
||||||
|
mySystem->m6532().poke(address, value);
|
||||||
|
else if(!(lowAddress & 0x200))
|
||||||
|
mySystem->tia().poke(address, value);
|
||||||
|
|
||||||
|
// Switch banks if necessary
|
||||||
|
if((address & 0x180f) == 0x080d) bank((address & 0xf0) >> 4);
|
||||||
|
else if((address & 0x1880) == 0)
|
||||||
|
{
|
||||||
|
if((myCurrentBank & 0xe) == 0xe)
|
||||||
|
bank(((address & 0x40) >> 6) | (myCurrentBank & 0xe));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeX07::bank(uInt16 bank)
|
||||||
|
{
|
||||||
|
if(bankLocked) return;
|
||||||
|
|
||||||
|
// Remember what bank we're in
|
||||||
|
myCurrentBank = (bank & 0x0f);
|
||||||
|
uInt32 offset = myCurrentBank * 4096;
|
||||||
|
uInt16 shift = mySystem->pageShift();
|
||||||
|
// uInt16 mask = mySystem->pageMask();
|
||||||
|
|
||||||
|
// Setup the page access methods for the current bank
|
||||||
|
System::PageAccess access;
|
||||||
|
access.device = this;
|
||||||
|
access.directPokeBase = 0;
|
||||||
|
|
||||||
|
// Map ROM image into the system
|
||||||
|
for(uInt32 address = 0x1000; address < 0x2000; address += (1 << shift))
|
||||||
|
{
|
||||||
|
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
|
||||||
|
mySystem->setPageAccess(address >> shift, access);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
int CartridgeX07::bank()
|
||||||
|
{
|
||||||
|
return myCurrentBank;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
int CartridgeX07::bankCount()
|
||||||
|
{
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool CartridgeX07::patch(uInt16 address, uInt8 value)
|
||||||
|
{
|
||||||
|
address &= 0x0fff;
|
||||||
|
myImage[myCurrentBank * 4096] = value;
|
||||||
|
bank(myCurrentBank); // TODO: see if this is really necessary
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt8* CartridgeX07::getImage(int& size)
|
||||||
|
{
|
||||||
|
size = 65536;
|
||||||
|
return &myImage[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool CartridgeX07::save(Serializer& out) const
|
||||||
|
{
|
||||||
|
string cart = name();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
out.putString(cart);
|
||||||
|
out.putInt(myCurrentBank);
|
||||||
|
}
|
||||||
|
catch(char *msg)
|
||||||
|
{
|
||||||
|
cerr << msg << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
cerr << "Unknown error in save state for " << cart << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool CartridgeX07::load(Deserializer& in)
|
||||||
|
{
|
||||||
|
string cart = name();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(in.getString() != cart)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
myCurrentBank = (uInt16)in.getInt();
|
||||||
|
}
|
||||||
|
catch(char *msg)
|
||||||
|
{
|
||||||
|
cerr << msg << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
cerr << "Unknown error in load state for " << cart << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember what bank we were in
|
||||||
|
bank(myCurrentBank);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2008 by Bradford W. Mott and the Stella team
|
||||||
|
//
|
||||||
|
// See the file "license" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//
|
||||||
|
// $Id:
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#ifndef CARTRIDGEX07_HXX
|
||||||
|
#define CARTRIDGEX07_HXX
|
||||||
|
|
||||||
|
class System;
|
||||||
|
|
||||||
|
#include "bspf.hxx"
|
||||||
|
#include "Cart.hxx"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Bankswitching method as defined/created by John Payson (aka Supercat)
|
||||||
|
and Fred Quimby (aka batari).
|
||||||
|
|
||||||
|
This bankswitching method has 16 4K banks that can be accessed at
|
||||||
|
addresses $1000 to $1FFF. The bankswitching hotspots are all below
|
||||||
|
$1000. X07 uses two types of hotspots:
|
||||||
|
|
||||||
|
0 1xxx nnnn 1101 -- Switch to bank nnnn
|
||||||
|
0 0xxx 0nxx xxxx -- If in bank 111x, switch to bank 111n.
|
||||||
|
In any other bank, do not switch.
|
||||||
|
|
||||||
|
Note that the latter will hit on almost any TIA access.
|
||||||
|
|
||||||
|
@author Eckhard Stolberg
|
||||||
|
@version $Id:
|
||||||
|
*/
|
||||||
|
class CartridgeX07 : public Cartridge
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
Create a new cartridge using the specified image
|
||||||
|
|
||||||
|
@param image Pointer to the ROM image
|
||||||
|
*/
|
||||||
|
CartridgeX07(const uInt8* image);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Destructor
|
||||||
|
*/
|
||||||
|
virtual ~CartridgeX07();
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
Reset device to its power-on state
|
||||||
|
*/
|
||||||
|
virtual void reset();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Install cartridge in the specified system. Invoked by the system
|
||||||
|
when the cartridge is attached to it.
|
||||||
|
|
||||||
|
@param system The system the device should install itself in
|
||||||
|
*/
|
||||||
|
virtual void install(System& system);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Install pages for the specified bank in the system.
|
||||||
|
|
||||||
|
@param bank The bank that should be installed in the system
|
||||||
|
*/
|
||||||
|
virtual void bank(uInt16 bank);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the current bank.
|
||||||
|
|
||||||
|
@return The current bank, or -1 if bankswitching not supported
|
||||||
|
*/
|
||||||
|
virtual int bank();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Query the number of banks supported by the cartridge.
|
||||||
|
*/
|
||||||
|
virtual int bankCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Patch the cartridge ROM.
|
||||||
|
|
||||||
|
@param address The ROM address to patch
|
||||||
|
@param value The value to place into the address
|
||||||
|
@return Success or failure of the patch operation
|
||||||
|
*/
|
||||||
|
virtual bool patch(uInt16 address, uInt8 value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Access the internal ROM image for this cartridge.
|
||||||
|
|
||||||
|
@param size Set to the size of the internal ROM image data
|
||||||
|
@return A pointer to the internal ROM image data
|
||||||
|
*/
|
||||||
|
virtual uInt8* getImage(int& size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Save the current state of this cart to the given Serializer.
|
||||||
|
|
||||||
|
@param out The Serializer object to use
|
||||||
|
@return False on any errors, else true
|
||||||
|
*/
|
||||||
|
virtual bool save(Serializer& out) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Load the current state of this cart from the given Deserializer.
|
||||||
|
|
||||||
|
@param in The Deserializer object to use
|
||||||
|
@return False on any errors, else true
|
||||||
|
*/
|
||||||
|
virtual bool load(Deserializer& in);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get a descriptor for the device name (used in error checking).
|
||||||
|
|
||||||
|
@return The name of the object
|
||||||
|
*/
|
||||||
|
virtual string name() const { return "CartridgeX07"; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
Get the byte at the specified address.
|
||||||
|
|
||||||
|
@return The byte at the specified address
|
||||||
|
*/
|
||||||
|
virtual uInt8 peek(uInt16 address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Change the byte at the specified address to the given value
|
||||||
|
|
||||||
|
@param address The address where the value should be stored
|
||||||
|
@param value The value to be stored at the address
|
||||||
|
*/
|
||||||
|
virtual void poke(uInt16 address, uInt8 value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Indicates which bank is currently active
|
||||||
|
uInt16 myCurrentBank;
|
||||||
|
|
||||||
|
// The 64K ROM image of the cartridge
|
||||||
|
uInt8 myImage[65536];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -27,6 +27,7 @@ MODULE_OBJS := \
|
||||||
src/emucore/CartSB.o \
|
src/emucore/CartSB.o \
|
||||||
src/emucore/CartUA.o \
|
src/emucore/CartUA.o \
|
||||||
src/emucore/Cart0840.o \
|
src/emucore/Cart0840.o \
|
||||||
|
src/emucore/CartX07.o \
|
||||||
src/emucore/Console.o \
|
src/emucore/Console.o \
|
||||||
src/emucore/Control.o \
|
src/emucore/Control.o \
|
||||||
src/emucore/Deserializer.o \
|
src/emucore/Deserializer.o \
|
||||||
|
|
Loading…
Reference in New Issue