2014-04-04 19:46:41 +00:00
using System ;
2014-04-19 16:28:03 +00:00
using System.Linq ;
2017-04-24 15:09:17 +00:00
2014-04-04 19:46:41 +00:00
using BizHawk.Common ;
/ * *
This is the cartridge class for Arcadia ( aka Starpath ) Supercharger
games . Christopher Salomon provided most of the technical details
used in creating this class . A good description of the Supercharger
is provided in the Cuttle Cart ' s manual .
The Supercharger has four 2 K banks . There are three banks of RAM
and one bank of ROM . All 6 K of the RAM can be read and written .
2014-04-12 17:52:49 +00:00
D7 - D5 of this byte : Write Pulse Delay ( n / a for emulator )
D4 - D0 : RAM / ROM configuration :
$ F000 - F7FF $ F800 - FFFF Address range that banks map into
000 wp 2 ROM
001 wp 0 ROM
010 wp 2 0 as used in Commie Mutants and many others
011 wp 0 2 as used in Suicide Mission
100 wp 2 ROM
101 wp 1 ROM
110 wp 2 1 as used in Killer Satellites
111 wp 1 2 as we use for 2 k / 4 k ROM cloning
w = Write Enable ( 1 = enabled ; accesses to $ F000 - $ F0FF cause writes
to happen . 0 = disabled , and the cart acts like ROM . )
p = ROM Power ( 0 = enabled , 1 = off . ) Only power the ROM if you ' re
wanting to access the ROM for multiloads . Otherwise set to 1.
2014-04-04 19:46:41 +00:00
* /
namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
internal class mAR : MapperBase
{
2014-04-16 01:18:38 +00:00
public mAR ( Atari2600 core )
2014-05-26 00:55:12 +00:00
{
Core = core ;
InitializeSettings ( ) ;
}
private ByteBuffer _superChargerImage = new ByteBuffer ( 8192 ) ;
private IntBuffer _imageOffsets = new IntBuffer ( 2 ) ;
2017-04-24 15:09:17 +00:00
private bool _writePending ;
private int _distinctAccesses ;
private bool _writeEnabled ;
2014-05-26 00:55:12 +00:00
private byte _dataHoldRegister ;
private byte _numberOfLoadImages ;
private ByteBuffer _loadedImages ;
private ByteBuffer _header = new ByteBuffer ( 256 ) ;
private bool _powerIndicator ; // Indicates if the ROM's power is on or off
private int _powerRomCycle ; // Indicates when the power was last turned on
private int _size ;
private ulong _elapsedCycles ;
private void InitializeSettings ( )
2014-04-04 19:46:41 +00:00
{
2014-04-19 16:28:03 +00:00
// TODO: clean this stuff up
/*****************************************/
2014-05-26 00:55:12 +00:00
int size = Core . Rom . Length ;
2017-04-24 15:09:17 +00:00
_size = Core . Rom . Length < 8448 ? 8448 : Core . Rom . Length ; // 8448 or Rom size, whichever is bigger
2014-04-19 16:28:03 +00:00
2014-05-26 00:55:12 +00:00
_numberOfLoadImages = ( byte ) ( _size / 8448 ) ;
2014-04-19 16:28:03 +00:00
// TODO: why are we making a redundant copy?
2014-05-26 00:55:12 +00:00
_loadedImages = new ByteBuffer ( _size ) ;
2014-04-19 16:28:03 +00:00
for ( int i = 0 ; i < size ; i + + )
{
2014-05-26 00:55:12 +00:00
_loadedImages [ i ] = Core . Rom [ i ] ;
2014-04-19 16:28:03 +00:00
}
if ( size < 8448 )
{
2014-05-26 00:55:12 +00:00
for ( int i = size ; i < _size ; i + + )
2014-04-19 16:28:03 +00:00
{
2017-04-24 15:09:17 +00:00
_loadedImages [ i ] = _defaultHeader [ i ] ;
2014-04-19 16:28:03 +00:00
}
}
2017-04-24 15:09:17 +00:00
2014-04-19 16:28:03 +00:00
/*****************************************/
2014-04-16 01:18:38 +00:00
InitializeRom ( ) ;
BankConfiguration ( 0 ) ;
2014-04-04 19:46:41 +00:00
}
2014-04-19 16:28:03 +00:00
#region SuperCharger Data
2017-04-24 15:09:17 +00:00
private readonly byte [ ] _dummyRomCode =
{
2014-04-12 17:52:49 +00:00
0xa5 , 0xfa , 0x85 , 0x80 , 0x4c , 0x18 , 0xf8 , 0xff ,
0xff , 0xff , 0x78 , 0xd8 , 0xa0 , 0x00 , 0xa2 , 0x00 ,
0x94 , 0x00 , 0xe8 , 0xd0 , 0xfb , 0x4c , 0x50 , 0xf8 ,
0xa2 , 0x00 , 0xbd , 0x06 , 0xf0 , 0xad , 0xf8 , 0xff ,
0xa2 , 0x00 , 0xad , 0x00 , 0xf0 , 0xea , 0xbd , 0x00 ,
0xf7 , 0xca , 0xd0 , 0xf6 , 0x4c , 0x50 , 0xf8 , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xa2 , 0x03 , 0xbc , 0x22 , 0xf9 , 0x94 , 0xfa , 0xca ,
0x10 , 0xf8 , 0xa0 , 0x00 , 0xa2 , 0x28 , 0x94 , 0x04 ,
0xca , 0x10 , 0xfb , 0xa2 , 0x1c , 0x94 , 0x81 , 0xca ,
0x10 , 0xfb , 0xa9 , 0xff , 0xc9 , 0x00 , 0xd0 , 0x03 ,
0x4c , 0x13 , 0xf9 , 0xa9 , 0x00 , 0x85 , 0x1b , 0x85 ,
0x1c , 0x85 , 0x1d , 0x85 , 0x1e , 0x85 , 0x1f , 0x85 ,
0x19 , 0x85 , 0x1a , 0x85 , 0x08 , 0x85 , 0x01 , 0xa9 ,
0x10 , 0x85 , 0x21 , 0x85 , 0x02 , 0xa2 , 0x07 , 0xca ,
0xca , 0xd0 , 0xfd , 0xa9 , 0x00 , 0x85 , 0x20 , 0x85 ,
0x10 , 0x85 , 0x11 , 0x85 , 0x02 , 0x85 , 0x2a , 0xa9 ,
0x05 , 0x85 , 0x0a , 0xa9 , 0xff , 0x85 , 0x0d , 0x85 ,
0x0e , 0x85 , 0x0f , 0x85 , 0x84 , 0x85 , 0x85 , 0xa9 ,
0xf0 , 0x85 , 0x83 , 0xa9 , 0x74 , 0x85 , 0x09 , 0xa9 ,
0x0c , 0x85 , 0x15 , 0xa9 , 0x1f , 0x85 , 0x17 , 0x85 ,
0x82 , 0xa9 , 0x07 , 0x85 , 0x19 , 0xa2 , 0x08 , 0xa0 ,
0x00 , 0x85 , 0x02 , 0x88 , 0xd0 , 0xfb , 0x85 , 0x02 ,
0x85 , 0x02 , 0xa9 , 0x02 , 0x85 , 0x02 , 0x85 , 0x00 ,
0x85 , 0x02 , 0x85 , 0x02 , 0x85 , 0x02 , 0xa9 , 0x00 ,
0x85 , 0x00 , 0xca , 0x10 , 0xe4 , 0x06 , 0x83 , 0x66 ,
0x84 , 0x26 , 0x85 , 0xa5 , 0x83 , 0x85 , 0x0d , 0xa5 ,
0x84 , 0x85 , 0x0e , 0xa5 , 0x85 , 0x85 , 0x0f , 0xa6 ,
0x82 , 0xca , 0x86 , 0x82 , 0x86 , 0x17 , 0xe0 , 0x0a ,
0xd0 , 0xc3 , 0xa9 , 0x02 , 0x85 , 0x01 , 0xa2 , 0x1c ,
0xa0 , 0x00 , 0x84 , 0x19 , 0x84 , 0x09 , 0x94 , 0x81 ,
0xca , 0x10 , 0xfb , 0xa6 , 0x80 , 0xdd , 0x00 , 0xf0 ,
0xa9 , 0x9a , 0xa2 , 0xff , 0xa0 , 0x00 , 0x9a , 0x4c ,
0xfa , 0x00 , 0xcd , 0xf8 , 0xff , 0x4c
} ;
2017-04-24 15:09:17 +00:00
private readonly byte [ ] _defaultHeader =
{
2014-04-12 17:52:49 +00:00
0xac , 0xfa , 0x0f , 0x18 , 0x62 , 0x00 , 0x24 , 0x02 ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0x00 , 0x04 , 0x08 , 0x0c , 0x10 , 0x14 , 0x18 , 0x1c ,
0x01 , 0x05 , 0x09 , 0x0d , 0x11 , 0x15 , 0x19 , 0x1d ,
0x02 , 0x06 , 0x0a , 0x0e , 0x12 , 0x16 , 0x1a , 0x1e ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0x00
} ;
2014-04-19 16:28:03 +00:00
#endregion
2017-04-24 15:09:17 +00:00
public override bool HasCartRam = > true ;
2014-05-26 01:01:47 +00:00
2017-04-24 15:09:17 +00:00
public override ByteBuffer CartRam = > _superChargerImage ;
2014-05-26 01:01:47 +00:00
2014-05-26 00:55:12 +00:00
public override void HardReset ( )
{
_superChargerImage = new ByteBuffer ( 8192 ) ;
_imageOffsets = new IntBuffer ( 2 ) ;
_writePending = false ;
_distinctAccesses = 0 ;
_writeEnabled = false ;
_dataHoldRegister = 0 ;
_numberOfLoadImages = 0 ;
_loadedImages = null ;
_header = new ByteBuffer ( 256 ) ;
_powerIndicator = false ;
_powerRomCycle = 0 ;
_size = 0 ;
_elapsedCycles = 0 ;
InitializeSettings ( ) ;
base . HardReset ( ) ;
}
public override void Dispose ( )
{
_superChargerImage . Dispose ( ) ;
_imageOffsets . Dispose ( ) ;
_loadedImages . Dispose ( ) ;
2016-11-10 00:23:54 +00:00
_header . Dispose ( ) ;
2014-05-26 00:55:12 +00:00
base . Dispose ( ) ;
}
public override void SyncState ( Serializer ser )
{
ser . Sync ( "superChargerImage" , ref _superChargerImage ) ;
ser . Sync ( "imageOffsets" , ref _imageOffsets ) ;
ser . Sync ( "writePending" , ref _writePending ) ;
ser . Sync ( "distinctAccesses" , ref _distinctAccesses ) ;
ser . Sync ( "writeEnabled" , ref _writeEnabled ) ;
ser . Sync ( "dataHoldRegister" , ref _dataHoldRegister ) ;
ser . Sync ( "numberOfLoadImages" , ref _numberOfLoadImages ) ;
ser . Sync ( "loadedImages" , ref _loadedImages ) ;
ser . Sync ( "header" , ref _header ) ;
ser . Sync ( "powerIndicator" , ref _powerIndicator ) ;
ser . Sync ( "powerRomCycle" , ref _powerRomCycle ) ;
ser . Sync ( "size" , ref _size ) ;
ser . Sync ( "elapsedCycles" , ref _elapsedCycles ) ;
base . SyncState ( ser ) ;
}
2014-04-16 01:18:38 +00:00
public override void ClockCpu ( )
2014-04-11 01:31:10 +00:00
{
2014-04-16 01:18:38 +00:00
_elapsedCycles + + ;
2014-04-06 22:40:10 +00:00
}
2014-04-04 19:46:41 +00:00
private byte ReadMem ( ushort addr , bool peek )
{
2017-04-24 15:09:17 +00:00
if ( addr < 0x1000 )
{
if ( peek )
{
return base . PeekMemory ( addr ) ;
}
return base . ReadMemory ( addr ) ;
}
2014-04-04 19:46:41 +00:00
2014-04-19 16:28:03 +00:00
/*---------------------------*/
2014-04-04 19:46:41 +00:00
2017-04-24 15:09:17 +00:00
if ( addr = = 0x1850 & & _imageOffsets [ 1 ] = = 3 < < 11 )
2014-04-12 17:52:49 +00:00
{
2014-04-19 16:28:03 +00:00
LoadIntoRam ( Core . MemoryDomains [ "System Bus" ] . PeekByte ( 0x80 ) ) ; // Get load that's being accessed (BIOS places load number at 0x80) // TODO: a better way to do this
2014-05-26 00:55:12 +00:00
return _superChargerImage [ ( addr & 0x7FF ) + _imageOffsets [ 1 ] ] ;
2014-04-12 17:52:49 +00:00
}
2017-04-24 15:09:17 +00:00
if ( _writePending // Cancel any pending write if more than 5 distinct accesses have occurred // TODO: Modify to handle when the distinct counter wraps around...
& & Core . DistinctAccessCount > _distinctAccesses + 5 )
2014-04-16 01:18:38 +00:00
{
2014-05-26 00:55:12 +00:00
_writePending = false ;
2014-04-16 01:18:38 +00:00
}
2014-04-19 16:28:03 +00:00
/*---------------------------*/
2014-05-26 00:55:12 +00:00
if ( ! ( ( addr & 0x0F00 ) > 0 ) & & ( ! _writeEnabled | | ! _writePending ) )
2014-04-16 01:18:38 +00:00
{
2014-05-26 00:55:12 +00:00
_dataHoldRegister = ( byte ) addr ;
_distinctAccesses = Core . DistinctAccessCount ;
_writePending = true ;
2014-04-16 01:18:38 +00:00
}
2014-04-19 16:28:03 +00:00
else if ( ( addr & 0x1FFF ) = = 0x1FF8 ) // Is the bank configuration hotspot being accessed?
2014-04-12 17:52:49 +00:00
{
2014-05-26 00:55:12 +00:00
_writePending = false ;
BankConfiguration ( _dataHoldRegister ) ;
2014-04-12 17:52:49 +00:00
}
2014-05-26 00:55:12 +00:00
else if ( _writeEnabled & & _writePending & &
2017-04-24 15:09:17 +00:00
Core . DistinctAccessCount = = _distinctAccesses + 5 )
2014-04-16 01:18:38 +00:00
{
if ( ( addr & 0x800 ) = = 0 )
{
2014-05-26 00:55:12 +00:00
_superChargerImage [ ( addr & 0x07FF ) + _imageOffsets [ 0 ] ] = _dataHoldRegister ;
2014-04-16 01:18:38 +00:00
}
2014-05-26 00:55:12 +00:00
else if ( _imageOffsets [ 1 ] ! = ( 3 < < 11 ) ) // Don't poke Rom
2014-04-16 01:18:38 +00:00
{
2014-05-26 00:55:12 +00:00
_superChargerImage [ ( addr & 0x07FF ) + _imageOffsets [ 1 ] ] = _dataHoldRegister ;
2014-04-16 01:18:38 +00:00
}
2014-05-26 00:55:12 +00:00
_writePending = false ;
2014-04-16 01:18:38 +00:00
}
2014-04-12 17:52:49 +00:00
2014-04-19 16:28:03 +00:00
/*---------------------------*/
2014-05-26 00:55:12 +00:00
return _superChargerImage [ ( addr & 0x07FF ) + _imageOffsets [ ( ( addr & 0x800 ) > 0 ) ? 1 : 0 ] ] ;
2014-04-04 19:46:41 +00:00
}
public override byte ReadMemory ( ushort addr )
{
return ReadMem ( addr , false ) ;
}
public override byte PeekMemory ( ushort addr )
{
return ReadMem ( addr , true ) ;
}
2014-05-26 00:55:12 +00:00
private void WriteMem ( ushort addr , byte value , bool poke )
2014-04-04 19:46:41 +00:00
{
2014-04-19 16:28:03 +00:00
if ( addr < 0x1000 )
2014-04-04 19:46:41 +00:00
{
2014-04-19 16:28:03 +00:00
base . WriteMemory ( addr , value ) ;
return ;
}
2014-05-26 00:55:12 +00:00
if ( ! poke & & _writePending & & ( Core . DistinctAccessCount > _distinctAccesses + 5 ) )
2014-04-19 16:28:03 +00:00
{
2014-05-26 00:55:12 +00:00
_writePending = false ;
2014-04-19 16:28:03 +00:00
}
// Is the data hold register being set?
2014-05-26 00:55:12 +00:00
if ( ! poke & & ! ( ( addr & 0x0F00 ) > 0 ) & & ( ! _writeEnabled | | ! _writePending ) )
2014-04-19 16:28:03 +00:00
{
2014-05-26 00:55:12 +00:00
_dataHoldRegister = ( byte ) addr ;
_distinctAccesses = Core . DistinctAccessCount ;
_writePending = true ;
2014-04-19 16:28:03 +00:00
}
2017-04-24 15:09:17 +00:00
2014-04-19 16:28:03 +00:00
// Is the bank configuration hotspot being accessed?
2014-05-26 00:55:12 +00:00
else if ( ! poke & & ( addr & 0x1FFF ) = = 0x1FF8 )
2014-04-19 16:28:03 +00:00
{
// Yes, so handle bank configuration
2014-05-26 00:55:12 +00:00
_writePending = false ;
BankConfiguration ( _dataHoldRegister ) ;
2014-04-19 16:28:03 +00:00
}
// Handle poke if writing enabled
2014-05-26 00:55:12 +00:00
else if ( _writeEnabled & & _writePending & &
( Core . DistinctAccessCount = = ( _distinctAccesses + 5 ) ) )
2014-04-19 16:28:03 +00:00
{
if ( ( addr & 0x0800 ) = = 0 )
{
2014-05-26 00:55:12 +00:00
_superChargerImage [ ( addr & 0x07FF ) + _imageOffsets [ 0 ] ] = _dataHoldRegister ;
2014-04-19 16:28:03 +00:00
}
2014-05-26 00:55:12 +00:00
else if ( _imageOffsets [ 1 ] ! = ( 3 < < 11 ) ) // Can't poke to ROM
2014-04-19 16:28:03 +00:00
{
2014-05-26 00:55:12 +00:00
_superChargerImage [ ( addr & 0x07FF ) + _imageOffsets [ 1 ] ] = _dataHoldRegister ;
2014-04-19 16:28:03 +00:00
}
2014-05-26 00:55:12 +00:00
_writePending = false ;
2014-04-04 19:46:41 +00:00
}
}
2014-04-16 01:18:38 +00:00
2014-05-26 00:55:12 +00:00
public override void WriteMemory ( ushort addr , byte value )
{
WriteMem ( addr , value , poke : false ) ;
}
public override void PokeMemory ( ushort addr , byte value )
{
WriteMem ( addr , value , poke : true ) ;
}
2014-04-16 01:18:38 +00:00
private void InitializeRom ( )
{
/ * scrom . asm data borrowed from Stella :
// Note that the following offsets depend on the 'scrom.asm' file
// in src/emucore/misc. If that file is ever recompiled (and its
// contents placed in the ourDummyROMCode array), the offsets will
// almost definitely change
* /
// The scrom.asm code checks a value at offset 109 as follows:
// 0xFF -> do a complete jump over the SC BIOS progress bars code
// 0x00 -> show SC BIOS progress bars as normal
2017-04-24 15:09:17 +00:00
_dummyRomCode [ 109 ] = ( byte ) ( Core . SyncSettings . FastScBios ? 0xFF : 0x00 ) ;
2014-04-16 01:18:38 +00:00
// Stella does this, but randomness is bad for determinacy! Hopefully we don't really need it
2017-04-24 15:09:17 +00:00
// ourDummyROMCode[281] = mySystem->randGenerator().next();
2014-04-16 01:18:38 +00:00
// Initialize ROM with illegal 6502 opcode that causes a real 6502 to jam
for ( int i = 0 ; i < 2048 ; i + + )
{
2014-05-26 00:55:12 +00:00
_superChargerImage [ ( 3 < < 11 ) + i ] = 0x02 ;
2014-04-16 01:18:38 +00:00
}
// Copy the "dummy" Supercharger BIOS code into the ROM area
2017-04-24 15:09:17 +00:00
for ( int i = 0 ; i < _dummyRomCode . Length ; i + + )
2014-04-16 01:18:38 +00:00
{
2017-04-24 15:09:17 +00:00
_superChargerImage [ ( 3 < < 11 ) + i ] = _dummyRomCode [ i ] ;
2014-04-16 01:18:38 +00:00
}
// Finally set 6502 vectors to point to initial load code at 0xF80A of BIOS
2014-05-26 00:55:12 +00:00
_superChargerImage [ ( 3 < < 11 ) + 2044 ] = 0x0A ;
_superChargerImage [ ( 3 < < 11 ) + 2045 ] = 0xF8 ;
_superChargerImage [ ( 3 < < 11 ) + 2046 ] = 0x0A ;
_superChargerImage [ ( 3 < < 11 ) + 2047 ] = 0xF8 ;
2014-04-16 01:18:38 +00:00
}
private void BankConfiguration ( byte configuration )
{
// D7-D5 of this byte: Write Pulse Delay (n/a for emulator)
/ /
// D4-D0: RAM/ROM configuration:
// $F000-F7FF $F800-FFFF Address range that banks map into
// 000wp 2 ROM
// 001wp 0 ROM
// 010wp 2 0 as used in Commie Mutants and many others
// 011wp 0 2 as used in Suicide Mission
// 100wp 2 ROM
// 101wp 1 ROM
// 110wp 2 1 as used in Killer Satellites
// 111wp 1 2 as we use for 2k/4k ROM cloning
//
// w = Write Enable (1 = enabled; accesses to $F000-$F0FF cause writes
// to happen. 0 = disabled, and the cart acts like ROM.)
// p = ROM Power (0 = enabled, 1 = off.) Only power the ROM if you're
// wanting to access the ROM for multiloads. Otherwise set to 1.
2014-04-19 16:28:03 +00:00
//_bank2k = configuration & 0x1F; // remember for the bank() method
2014-05-26 00:55:12 +00:00
_powerIndicator = ! ( ( configuration & 0x01 ) > 0 ) ;
if ( _powerIndicator )
2014-04-16 01:18:38 +00:00
{
2014-05-26 00:55:12 +00:00
_powerRomCycle = ( int ) _elapsedCycles ;
2014-04-16 01:18:38 +00:00
}
2014-05-26 00:55:12 +00:00
_writeEnabled = ( configuration & 0x02 ) > 0 ;
2014-04-19 16:28:03 +00:00
2014-04-16 01:18:38 +00:00
switch ( ( configuration > > 2 ) & 0x07 )
{
case 0x00 :
2014-05-26 00:55:12 +00:00
_imageOffsets [ 0 ] = 2 < < 11 ;
_imageOffsets [ 1 ] = 3 < < 11 ;
2014-04-16 01:18:38 +00:00
break ;
case 0x01 :
2014-05-26 00:55:12 +00:00
_imageOffsets [ 0 ] = 0 ;
_imageOffsets [ 1 ] = 3 < < 11 ;
2014-04-16 01:18:38 +00:00
break ;
case 0x02 :
2014-05-26 00:55:12 +00:00
_imageOffsets [ 0 ] = 2 < < 11 ;
_imageOffsets [ 1 ] = 0 ;
2014-04-16 01:18:38 +00:00
break ;
case 0x03 :
2014-05-26 00:55:12 +00:00
_imageOffsets [ 0 ] = 0 ;
_imageOffsets [ 1 ] = 2 < < 11 ;
2014-04-16 01:18:38 +00:00
break ;
case 0x04 :
2014-05-26 00:55:12 +00:00
_imageOffsets [ 0 ] = 2 < < 11 ;
_imageOffsets [ 1 ] = 3 < < 11 ;
2014-04-16 01:18:38 +00:00
break ;
case 0x05 :
2014-05-26 00:55:12 +00:00
_imageOffsets [ 0 ] = 1 < < 11 ;
_imageOffsets [ 1 ] = 3 < < 11 ;
2014-04-16 01:18:38 +00:00
break ;
case 0x06 :
2014-05-26 00:55:12 +00:00
_imageOffsets [ 0 ] = 2 < < 11 ;
_imageOffsets [ 1 ] = 1 < < 11 ;
2014-04-16 01:18:38 +00:00
break ;
case 0x07 :
2014-05-26 00:55:12 +00:00
_imageOffsets [ 0 ] = 1 < < 11 ;
_imageOffsets [ 1 ] = 2 < < 11 ;
2014-04-16 01:18:38 +00:00
break ;
}
}
2014-04-19 16:28:03 +00:00
private void LoadIntoRam ( byte load )
{
ushort image ;
2014-05-26 00:55:12 +00:00
for ( image = 0 ; image < _numberOfLoadImages ; image + + )
2014-04-19 16:28:03 +00:00
{
2014-05-26 00:55:12 +00:00
if ( _loadedImages [ ( image * 8448 ) + 8192 + 5 ] = = load )
2014-04-19 16:28:03 +00:00
{
for ( int i = 0 ; i < 256 ; i + + )
{
2014-05-26 00:55:12 +00:00
_header [ i ] = _loadedImages [ ( image * 8448 ) + 8192 + i ] ;
2014-04-19 16:28:03 +00:00
}
2014-05-26 00:55:12 +00:00
if ( Checksum ( _header . Arr . Take ( 8 ) . ToArray ( ) ) ! = 0x55 )
2014-04-19 16:28:03 +00:00
{
Console . WriteLine ( "WARNING: The Supercharger header checksum is invalid..." ) ;
}
// TODO: verify the load's header
// Load all of the pages from the load
bool invalidPageChecksumSeen = false ;
2014-05-26 00:55:12 +00:00
for ( int j = 0 ; j < _header [ 3 ] ; j + + )
2014-04-19 16:28:03 +00:00
{
2014-05-26 00:55:12 +00:00
int bank = _header [ 16 + j ] & 0x03 ;
int page = ( _header [ 16 + j ] > > 2 ) & 0x07 ;
var src = _loadedImages . Arr . Skip ( ( image * 8448 ) + ( j * 256 ) ) . Take ( 256 ) . ToArray ( ) ;
byte sum = ( byte ) ( Checksum ( src ) + _header [ 16 + j ] + _header [ 64 + j ] ) ;
2014-04-19 16:28:03 +00:00
if ( ! invalidPageChecksumSeen & & ( sum ! = 0x55 ) )
{
Console . WriteLine ( "WARNING: Some Supercharger page checksums are invalid..." ) ;
invalidPageChecksumSeen = true ;
}
if ( bank < 3 )
{
for ( int k = 0 ; k < src . Length ; k + + )
{
2014-05-26 00:55:12 +00:00
_superChargerImage [ ( bank * 2048 ) + ( page * 256 ) + k ] = src [ k ] ;
2014-04-19 16:28:03 +00:00
}
}
}
// TODO: is this the correct Write to do?
2014-05-26 00:55:12 +00:00
base . WriteMemory ( 0xFE , _header [ 0 ] ) ;
base . WriteMemory ( 0xFF , _header [ 1 ] ) ;
base . WriteMemory ( 0x80 , _header [ 2 ] ) ;
2014-04-19 16:28:03 +00:00
}
}
}
private byte Checksum ( byte [ ] s )
{
byte sum = 0 ;
for ( int i = 0 ; i < s . Count ( ) ; i + + )
{
sum + = s [ i ] ;
}
return sum ;
}
2014-04-04 19:46:41 +00:00
}
}