mirror of
https://github.com/libretro/stella2023.git
synced 2025-02-22 18:30:36 +00:00
Second pass at 4A50 bankswitch support. This time it actually works
on all but one of the test ROMs I have :) Thanks must go to Eckhard Stolberg, who did about 95% of the work on this scheme. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1400 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
03cd7ea291
commit
c1f887f731
@ -13,7 +13,7 @@
|
||||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: Cart4A50.cxx,v 1.11 2008-02-21 16:11:15 stephena Exp $
|
||||
// $Id: Cart4A50.cxx,v 1.12 2008-02-21 23:58:09 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include <cassert>
|
||||
@ -39,9 +39,7 @@ Cartridge4A50::Cartridge4A50(const uInt8* image, uInt32 size)
|
||||
// Initialize RAM with random values
|
||||
class Random random;
|
||||
for(uInt32 i = 0; i < 32768; ++i)
|
||||
{
|
||||
myRAM[i] = random.next();
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@ -99,7 +97,7 @@ uInt8 Cartridge4A50::peek(uInt16 address)
|
||||
else if(!(lowAddress & 0x200))
|
||||
value = mySystem->tia().peek(address);
|
||||
|
||||
checkBankSwitch(address);
|
||||
checkBankSwitch(address, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -111,17 +109,17 @@ uInt8 Cartridge4A50::peek(uInt16 address)
|
||||
else if(((address & 0x1fff) >= 0x1800) && // 1.5K region from 0x1800 - 0x1dff
|
||||
((address & 0x1fff) <= 0x1dff))
|
||||
{
|
||||
value = myIsRomMiddle ? myImage[(address & 0x7ff) + mySliceMiddle]
|
||||
value = myIsRomMiddle ? myImage[(address & 0x7ff) + mySliceMiddle + 0x10000]
|
||||
: myRAM[(address & 0x7ff) + mySliceMiddle];
|
||||
}
|
||||
else if((address & 0x1f00) == 0x1e00) // 256B region from 0x1e00 - 0x1eff
|
||||
{
|
||||
value = myIsRomHigh ? myImage[(address & 0xff) + mySliceHigh]
|
||||
value = myIsRomHigh ? myImage[(address & 0xff) + mySliceHigh + 0x10000]
|
||||
: myRAM[(address & 0xff) + mySliceHigh];
|
||||
}
|
||||
else if((address & 0x1f00) == 0x1f00) // 256B region from 0x1f00 - 0x1fff
|
||||
{
|
||||
value = myImage[(address & 0xff) + 0xff00];
|
||||
value = myImage[(address & 0xff) + 0x1ff00];
|
||||
if(((myLastData & 0xe0) == 0x60) &&
|
||||
((myLastAddress >= 0x1000) || (myLastAddress < 0x200)))
|
||||
mySliceHigh = (mySliceHigh & 0xf0ff) | ((address & 0x8) << 8) |
|
||||
@ -146,7 +144,7 @@ void Cartridge4A50::poke(uInt16 address, uInt8 value)
|
||||
else if(!(lowAddress & 0x200))
|
||||
mySystem->tia().poke(address, value);
|
||||
|
||||
checkBankSwitch(address);
|
||||
checkBankSwitch(address, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -174,13 +172,12 @@ void Cartridge4A50::poke(uInt16 address, uInt8 value)
|
||||
((address & 0x70) << 4);
|
||||
}
|
||||
}
|
||||
|
||||
myLastData = value;
|
||||
myLastAddress = address & 0x1fff;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Cartridge4A50::checkBankSwitch(uInt16 address)
|
||||
void Cartridge4A50::checkBankSwitch(uInt16 address, uInt8 value)
|
||||
{
|
||||
// This scheme contains so many hotspots that it's easier to just check
|
||||
// all of them
|
||||
@ -237,46 +234,49 @@ void Cartridge4A50::checkBankSwitch(uInt16 address)
|
||||
}
|
||||
}
|
||||
|
||||
uInt8 databus = mySystem->getDataBusState();
|
||||
// Handle hotspots that mirror TIA or RIOT
|
||||
if((address >= 0x80) && (address < 0x100))
|
||||
{
|
||||
// Zero-page hotspots for upper page
|
||||
// 0xf4, 0xf6, 0xfc, 0xfe for ROM
|
||||
// 0xf5, 0xf7, 0xfd, 0xff for RAM
|
||||
// 0x74 - 0x7f (0x80 bytes lower)
|
||||
if((address & 0xf75) == 0x74) // Enable 256B of ROM at 0x1e00 - 0x1eff
|
||||
{
|
||||
myIsRomHigh = true;
|
||||
mySliceHigh = value << 8;
|
||||
}
|
||||
else if((address & 0xf75) == 0x75) // Enable 256B of RAM at 0x1e00 - 0x1eff
|
||||
{
|
||||
myIsRomHigh = false;
|
||||
mySliceHigh = (value & 0x7f) << 8;
|
||||
}
|
||||
|
||||
// Zero-page hotspots for upper page
|
||||
// 0xf4, 0xf6, 0xfc, 0xfe for ROM
|
||||
// 0xf5, 0xf7, 0xfd, 0xff for RAM
|
||||
// 0x74 - 0x7f (0x80 bytes lower)
|
||||
if((address & 0xf75) == 0x74) // Enable 256B of ROM at 0x1e00 - 0x1eff
|
||||
{
|
||||
myIsRomHigh = true;
|
||||
mySliceHigh = databus << 8;
|
||||
}
|
||||
else if((address & 0xf75) == 0x75) // Enable 256B of RAM at 0x1e00 - 0x1eff
|
||||
{
|
||||
myIsRomHigh = false;
|
||||
mySliceHigh = (databus & 0x7f) << 8;
|
||||
}
|
||||
// Zero-page hotspots for lower and middle blocks
|
||||
// 0xf8, 0xf9, 0xfa, 0xfb
|
||||
// 0x78, 0x79, 0x7a, 0x7b (0x80 bytes lower)
|
||||
else if((address & 0xf7c) == 0x78)
|
||||
{
|
||||
if((databus & 0xf0) == 0) // Enable 2K of ROM at 0x1000 - 0x17ff
|
||||
// Zero-page hotspots for lower and middle blocks
|
||||
// 0xf8, 0xf9, 0xfa, 0xfb
|
||||
// 0x78, 0x79, 0x7a, 0x7b (0x80 bytes lower)
|
||||
else if((address & 0xf7c) == 0x78)
|
||||
{
|
||||
myIsRomLow = true;
|
||||
mySliceLow = (databus & 0xf) << 11;
|
||||
}
|
||||
else if((databus & 0xf0) == 0x40) // Enable 2K of RAM at 0x1000 - 0x17ff
|
||||
{
|
||||
myIsRomLow = false;
|
||||
mySliceLow = (databus & 0xf) << 11;
|
||||
}
|
||||
else if((databus & 0xf0) == 0x90) // Enable 1.5K of ROM at 0x1800 - 0x1dff
|
||||
{
|
||||
myIsRomMiddle = true;
|
||||
mySliceMiddle = ((databus & 0xf) | 0x10) << 11;
|
||||
}
|
||||
else if((databus & 0xf0) == 0xc0) // Enable 1.5K of RAM at 0x1800 - 0x1dff
|
||||
{
|
||||
myIsRomMiddle = false;
|
||||
mySliceMiddle = (databus & 0xf) << 11;
|
||||
if((value & 0xf0) == 0) // Enable 2K of ROM at 0x1000 - 0x17ff
|
||||
{
|
||||
myIsRomLow = true;
|
||||
mySliceLow = (value & 0xf) << 11;
|
||||
}
|
||||
else if((value & 0xf0) == 0x40) // Enable 2K of RAM at 0x1000 - 0x17ff
|
||||
{
|
||||
myIsRomLow = false;
|
||||
mySliceLow = (value & 0xf) << 11;
|
||||
}
|
||||
else if((value & 0xf0) == 0x90) // Enable 1.5K of ROM at 0x1800 - 0x1dff
|
||||
{
|
||||
myIsRomMiddle = true;
|
||||
mySliceMiddle = ((value & 0xf) | 0x10) << 11;
|
||||
}
|
||||
else if((value & 0xf0) == 0xc0) // Enable 1.5K of RAM at 0x1800 - 0x1dff
|
||||
{
|
||||
myIsRomMiddle = false;
|
||||
mySliceMiddle = (value & 0xf) << 11;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -297,19 +297,19 @@ int Cartridge4A50::bank()
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int Cartridge4A50::bankCount()
|
||||
{
|
||||
return 1;
|
||||
return 1; // TODO
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Cartridge4A50::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
return false;
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8* Cartridge4A50::getImage(int& size)
|
||||
{
|
||||
size = 0;
|
||||
size = 0; // TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -317,11 +317,83 @@ uInt8* Cartridge4A50::getImage(int& size)
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Cartridge4A50::save(Serializer& out) const
|
||||
{
|
||||
string cart = name();
|
||||
|
||||
try
|
||||
{
|
||||
out.putString(cart);
|
||||
|
||||
// The 32K bytes of RAM
|
||||
out.putInt(32768);
|
||||
for(uInt32 i = 0; i < 32768; ++i)
|
||||
out.putByte((char)myRAM[i]);
|
||||
|
||||
// Index pointers
|
||||
out.putInt(mySliceLow);
|
||||
out.putInt(mySliceMiddle);
|
||||
out.putInt(mySliceHigh);
|
||||
|
||||
// Whether index pointers are for ROM or RAM
|
||||
out.putBool(myIsRomLow);
|
||||
out.putBool(myIsRomMiddle);
|
||||
out.putBool(myIsRomHigh);
|
||||
|
||||
// Last address and data values
|
||||
out.putByte(myLastData);
|
||||
out.putInt(myLastAddress);
|
||||
}
|
||||
catch(const char* msg)
|
||||
{
|
||||
cerr << msg << endl;
|
||||
return false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "Unknown error in save state for " << cart << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Cartridge4A50::load(Deserializer& in)
|
||||
{
|
||||
string cart = name();
|
||||
|
||||
try
|
||||
{
|
||||
if(in.getString() != cart)
|
||||
return false;
|
||||
|
||||
uInt32 limit = (uInt32) in.getInt();
|
||||
for(uInt32 i = 0; i < limit; ++i)
|
||||
myRAM[i] = (uInt8) in.getByte();
|
||||
|
||||
// Index pointers
|
||||
mySliceLow = (uInt16) in.getInt();
|
||||
mySliceMiddle = (uInt16) in.getInt();
|
||||
mySliceHigh = (uInt16) in.getInt();
|
||||
|
||||
// Whether index pointers are for ROM or RAM
|
||||
myIsRomLow = in.getBool();
|
||||
myIsRomMiddle = in.getBool();
|
||||
myIsRomHigh = in.getBool();
|
||||
|
||||
// Last address and data values
|
||||
myLastData = (uInt8) in.getByte();
|
||||
myLastAddress = (uInt16) in.getInt();
|
||||
}
|
||||
catch(const char* msg)
|
||||
{
|
||||
cerr << msg << endl;
|
||||
return false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "Unknown error in load state for " << cart << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: Cart4A50.hxx,v 1.11 2008-02-19 12:33:03 stephena Exp $
|
||||
// $Id: Cart4A50.hxx,v 1.12 2008-02-21 23:58:09 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifndef CARTRIDGE4A50_HXX
|
||||
@ -37,7 +37,7 @@ class System;
|
||||
bytes of ROM.
|
||||
|
||||
@author Stephen Anthony & Eckhard Stolberg
|
||||
@version $Id: Cart4A50.hxx,v 1.11 2008-02-19 12:33:03 stephena Exp $
|
||||
@version $Id: Cart4A50.hxx,v 1.12 2008-02-21 23:58:09 stephena Exp $
|
||||
*/
|
||||
class Cartridge4A50 : public Cartridge
|
||||
{
|
||||
@ -148,11 +148,11 @@ class Cartridge4A50 : public Cartridge
|
||||
/**
|
||||
Check all possible hotspots
|
||||
*/
|
||||
void checkBankSwitch(uInt16 address);
|
||||
void checkBankSwitch(uInt16 address, uInt8 value);
|
||||
|
||||
private:
|
||||
// The 128K ROM image of the cartridge
|
||||
uInt8 myImage[128*1024];
|
||||
uInt8 myImage[131072];
|
||||
|
||||
// The 32K of RAM on the cartridge
|
||||
uInt8 myRAM[32768];
|
||||
|
Loading…
x
Reference in New Issue
Block a user