mirror of https://github.com/stella-emu/stella.git
CDF updates (with versioning) from Spiceware.
This commit is contained in:
parent
f57d69a023
commit
7a9cde3e4d
|
@ -30,7 +30,7 @@ CartridgeCDFWidget::CartridgeCDFWidget(
|
|||
uInt16 size = 8 * 4096;
|
||||
|
||||
ostringstream info;
|
||||
info << "CDF cartridge\n"
|
||||
info << "CDF cartridge (version " << cart.myVersion << ")\n"
|
||||
<< "32K ROM, seven 4K banks are accessible to 2600\n"
|
||||
<< "8K CDF RAM\n"
|
||||
<< "CDF registers accessible @ $FFF0 - $FFF3\n"
|
||||
|
|
|
@ -27,9 +27,10 @@
|
|||
#include "TIA.hxx"
|
||||
|
||||
// Location of data within the RAM copy of the CDF Driver.
|
||||
#define DSxPTR 0x06E0
|
||||
#define DSxINC 0x0768
|
||||
#define WAVEFORM 0x07F0
|
||||
// Version 0 1
|
||||
const uInt16 DSxPTR[] = {0x06E0, 0x00A0};
|
||||
const uInt16 DSxINC[] = {0x0768, 0x0128};
|
||||
const uInt16 WAVEFORM[] = {0x07F0, 0x01B0};
|
||||
#define DSRAM 0x0800
|
||||
|
||||
#define COMMSTREAM 0x20
|
||||
|
@ -62,10 +63,15 @@ CartridgeCDF::CartridgeCDF(const BytePtr& image, uInt32 size,
|
|||
|
||||
// Pointer to the display RAM
|
||||
myDisplayImage = myCDFRAM + DSRAM;
|
||||
|
||||
setVersion();
|
||||
|
||||
#ifdef THUMB_SUPPORT
|
||||
// Create Thumbulator ARM emulator
|
||||
myThumbEmulator = make_unique<Thumbulator>((uInt16*)myImage, (uInt16*)myCDFRAM,
|
||||
settings.getBool("thumb.trapfatal"), Thumbulator::ConfigureFor::CDF, this);
|
||||
myThumbEmulator = make_unique<Thumbulator>(
|
||||
(uInt16*)myImage, (uInt16*)myCDFRAM, settings.getBool("thumb.trapfatal"),
|
||||
myVersion ? Thumbulator::ConfigureFor::CDF1 : Thumbulator::ConfigureFor::CDF,
|
||||
this);
|
||||
#endif
|
||||
setInitialState();
|
||||
}
|
||||
|
@ -576,51 +582,57 @@ bool CartridgeCDF::load(Serializer& in)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 CartridgeCDF::getDatastreamPointer(uInt8 index) const
|
||||
{
|
||||
// index &= 0x0f;
|
||||
uInt16 address = DSxPTR[myVersion] + index * 4;
|
||||
|
||||
return myCDFRAM[DSxPTR + index*4 + 0] + // low byte
|
||||
(myCDFRAM[DSxPTR + index*4 + 1] << 8) +
|
||||
(myCDFRAM[DSxPTR + index*4 + 2] << 16) +
|
||||
(myCDFRAM[DSxPTR + index*4 + 3] << 24) ; // high byte
|
||||
return myCDFRAM[address + 0] + // low byte
|
||||
(myCDFRAM[address + 1] << 8) +
|
||||
(myCDFRAM[address + 2] << 16) +
|
||||
(myCDFRAM[address + 3] << 24) ; // high byte
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeCDF::setDatastreamPointer(uInt8 index, uInt32 value)
|
||||
{
|
||||
// index &= 0x1f;
|
||||
myCDFRAM[DSxPTR + index*4 + 0] = value & 0xff; // low byte
|
||||
myCDFRAM[DSxPTR + index*4 + 1] = (value >> 8) & 0xff;
|
||||
myCDFRAM[DSxPTR + index*4 + 2] = (value >> 16) & 0xff;
|
||||
myCDFRAM[DSxPTR + index*4 + 3] = (value >> 24) & 0xff; // high byte
|
||||
uInt16 address = DSxPTR[myVersion] + index * 4;
|
||||
|
||||
myCDFRAM[address + 0] = value & 0xff; // low byte
|
||||
myCDFRAM[address + 1] = (value >> 8) & 0xff;
|
||||
myCDFRAM[address + 2] = (value >> 16) & 0xff;
|
||||
myCDFRAM[address + 3] = (value >> 24) & 0xff; // high byte
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 CartridgeCDF::getDatastreamIncrement(uInt8 index) const
|
||||
{
|
||||
return myCDFRAM[DSxINC + index*4 + 0] + // low byte
|
||||
(myCDFRAM[DSxINC + index*4 + 1] << 8) +
|
||||
(myCDFRAM[DSxINC + index*4 + 2] << 16) +
|
||||
(myCDFRAM[DSxINC + index*4 + 3] << 24) ; // high byte
|
||||
uInt16 address = DSxINC[myVersion] + index * 4;
|
||||
|
||||
return myCDFRAM[address + 0] + // low byte
|
||||
(myCDFRAM[address + 1] << 8) +
|
||||
(myCDFRAM[address + 2] << 16) +
|
||||
(myCDFRAM[address + 3] << 24) ; // high byte
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeCDF::setDatastreamIncrement(uInt8 index, uInt32 value)
|
||||
{
|
||||
myCDFRAM[DSxINC + index*4 + 0] = value & 0xff; // low byte
|
||||
myCDFRAM[DSxINC + index*4 + 1] = (value >> 8) & 0xff;
|
||||
myCDFRAM[DSxINC + index*4 + 2] = (value >> 16) & 0xff;
|
||||
myCDFRAM[DSxINC + index*4 + 3] = (value >> 24) & 0xff; // high byte
|
||||
uInt16 address = DSxINC[myVersion] + index * 4;
|
||||
|
||||
myCDFRAM[address + 0] = value & 0xff; // low byte
|
||||
myCDFRAM[address + 1] = (value >> 8) & 0xff;
|
||||
myCDFRAM[address + 2] = (value >> 16) & 0xff;
|
||||
myCDFRAM[address + 3] = (value >> 24) & 0xff; // high byte
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 CartridgeCDF::getWaveform(uInt8 index) const
|
||||
{
|
||||
uInt32 result;
|
||||
uInt16 address = WAVEFORM[myVersion] + index * 4;
|
||||
|
||||
result = myCDFRAM[WAVEFORM + index*4 + 0] + // low byte
|
||||
(myCDFRAM[WAVEFORM + index*4 + 1] << 8) +
|
||||
(myCDFRAM[WAVEFORM + index*4 + 2] << 16) +
|
||||
(myCDFRAM[WAVEFORM + index*4 + 3] << 24); // high byte
|
||||
result = myCDFRAM[address + 0] + // low byte
|
||||
(myCDFRAM[address + 1] << 8) +
|
||||
(myCDFRAM[address + 2] << 16) +
|
||||
(myCDFRAM[address + 3] << 24); // high byte
|
||||
|
||||
result -= (0x40000000 + DSRAM);
|
||||
|
||||
|
@ -634,11 +646,12 @@ uInt32 CartridgeCDF::getWaveform(uInt8 index) const
|
|||
uInt32 CartridgeCDF::getSample()
|
||||
{
|
||||
uInt32 result;
|
||||
uInt16 address = WAVEFORM[myVersion];
|
||||
|
||||
result = myCDFRAM[WAVEFORM + 0] + // low byte
|
||||
(myCDFRAM[WAVEFORM + 1] << 8) +
|
||||
(myCDFRAM[WAVEFORM + 2] << 16) +
|
||||
(myCDFRAM[WAVEFORM + 3] << 24); // high byte
|
||||
result = myCDFRAM[address + 0] + // low byte
|
||||
(myCDFRAM[address + 1] << 8) +
|
||||
(myCDFRAM[address + 2] << 16) +
|
||||
(myCDFRAM[address + 3] << 24); // high byte
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -669,3 +682,21 @@ uInt8 CartridgeCDF::readFromDatastream(uInt8 index)
|
|||
setDatastreamPointer(index, pointer);
|
||||
return value;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeCDF::setVersion()
|
||||
{
|
||||
myVersion = 0;
|
||||
|
||||
for(uInt32 i = 0; i < 2048; i += 4)
|
||||
{
|
||||
// CDF signature occurs 3 times in a row, i+3 (+7 or +11) is version
|
||||
if ( myImage[i+0] == 0x43 && myImage[i + 4] == 0x43 && myImage[i + 8] == 0x43) // C
|
||||
if ( myImage[i+1] == 0x44 && myImage[i + 5] == 0x44 && myImage[i + 9] == 0x44) // D
|
||||
if (myImage[i+2] == 0x46 && myImage[i + 6] == 0x46 && myImage[i +10] == 0x46) // F
|
||||
{
|
||||
myVersion = myImage[i+3];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ class System;
|
|||
|
||||
|
||||
There are seven 4K program banks, a 4K Display Data RAM,
|
||||
1K C Varaible and Stack, and the CDF chip.
|
||||
1K C Variable and Stack, and the CDF chip.
|
||||
CDF chip access is mapped to $1000 - $103F.
|
||||
|
||||
@authors: Darrell Spice Jr, Chris Walton, Fred Quimby,
|
||||
|
@ -209,6 +209,7 @@ class CartridgeCDF : public Cartridge
|
|||
uInt32 getWaveform(uInt8 index) const;
|
||||
uInt32 getWaveformSize(uInt8 index) const;
|
||||
uInt32 getSample();
|
||||
void setVersion();
|
||||
|
||||
private:
|
||||
// The 32K ROM image of the cartridge
|
||||
|
@ -250,16 +251,16 @@ class CartridgeCDF : public Cartridge
|
|||
// Thumbulator will trap these calls and pass the appropriate information to
|
||||
// the Cartridge Class via callFunction() so it can emulate the 32 bit audio routines.
|
||||
|
||||
/* Register usage for audio:
|
||||
r8 = channel0 accumulator
|
||||
r9 = channel1 accumulator
|
||||
r10 = channel2 accumulator
|
||||
r11 = channel0 frequency
|
||||
r12 = channel1 frequency
|
||||
r13 = channel2 frequency
|
||||
r14 = timer base */
|
||||
/* Register usage for audio:
|
||||
r8 = channel0 accumulator
|
||||
r9 = channel1 accumulator
|
||||
r10 = channel2 accumulator
|
||||
r11 = channel0 frequency
|
||||
r12 = channel1 frequency
|
||||
r13 = channel2 frequency
|
||||
r14 = timer base */
|
||||
|
||||
// The music counters, ARM FIQ shadow registers r8, r9, r10
|
||||
// The music counters, ARM FIQ shadow registers r8, r9, r10
|
||||
uInt32 myMusicCounters[3];
|
||||
|
||||
// The music frequency, ARM FIQ shadow registers r11, r12, r13
|
||||
|
@ -289,6 +290,9 @@ class CartridgeCDF : public Cartridge
|
|||
|
||||
uInt8 myFastJumpActive;
|
||||
|
||||
// version of CDF
|
||||
uInt16 myVersion;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
CartridgeCDF() = delete;
|
||||
|
|
|
@ -234,6 +234,7 @@ void Thumbulator::write16(uInt32 addr, uInt32 data)
|
|||
// as additional RAM
|
||||
case ConfigureFor::BUS:
|
||||
case ConfigureFor::CDF:
|
||||
case ConfigureFor::CDF1:
|
||||
if((addr > 0x40000028) && (addr < 0x40000800))
|
||||
fatalError("write16", addr, "to bankswitch code area");
|
||||
break;
|
||||
|
@ -1198,6 +1199,67 @@ int Thumbulator::execute()
|
|||
|
||||
break;
|
||||
|
||||
case ConfigureFor::CDF1:
|
||||
// this subroutine interface is used in the CDF driver,
|
||||
// it starts at address 0x00000750
|
||||
// _SetNote:
|
||||
// ldr r4, =NoteStore
|
||||
// bx r4 // bx instruction at 0x000006e2
|
||||
// _ResetWave:
|
||||
// ldr r4, =ResetWaveStore
|
||||
// bx r4 // bx instruction at 0x000006e6
|
||||
// _GetWavePtr:
|
||||
// ldr r4, =WavePtrFetch
|
||||
// bx r4 // bx instruction at 0x000006ea
|
||||
// _SetWaveSize:
|
||||
// ldr r4, =WaveSizeStore
|
||||
// bx r4 // bx instruction at 0x000006ee
|
||||
|
||||
// address to test for is + 4 due to pipelining
|
||||
|
||||
#define CDF1_SetNote (0x00000752 + 4)
|
||||
#define CDF1_ResetWave (0x00000756 + 4)
|
||||
#define CDF1_GetWavePtr (0x0000075a + 4)
|
||||
#define CDF1_SetWaveSize (0x0000075e + 4)
|
||||
|
||||
if (pc == CDF1_SetNote)
|
||||
{
|
||||
myCartridge->thumbCallback(0, read_register(2), read_register(3));
|
||||
handled = true;
|
||||
}
|
||||
else if (pc == CDF1_ResetWave)
|
||||
{
|
||||
myCartridge->thumbCallback(1, read_register(2), 0);
|
||||
handled = true;
|
||||
}
|
||||
else if (pc == CDF1_GetWavePtr)
|
||||
{
|
||||
write_register(2, myCartridge->thumbCallback(2, read_register(2), 0));
|
||||
handled = true;
|
||||
}
|
||||
else if (pc == CDF1_SetWaveSize)
|
||||
{
|
||||
myCartridge->thumbCallback(3, read_register(2), read_register(3));
|
||||
handled = true;
|
||||
}
|
||||
else if (pc == 0x0000083a)
|
||||
{
|
||||
// exiting Custom ARM code, returning to BUS Driver control
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0 // uncomment this for testing
|
||||
uInt32 r0 = read_register(0);
|
||||
uInt32 r1 = read_register(1);
|
||||
uInt32 r2 = read_register(2);
|
||||
uInt32 r3 = read_register(3);
|
||||
uInt32 r4 = read_register(4);
|
||||
#endif
|
||||
myCartridge->thumbCallback(255, 0, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ConfigureFor::DPCplus:
|
||||
// no 32-bit subroutines in DPC+
|
||||
break;
|
||||
|
@ -2266,6 +2328,7 @@ int Thumbulator::reset()
|
|||
// future 2K Harmony/Melody drivers will most likely use these settings
|
||||
case ConfigureFor::BUS:
|
||||
case ConfigureFor::CDF:
|
||||
case ConfigureFor::CDF1:
|
||||
reg_norm[14] = 0x00000800; // Link Register
|
||||
reg_norm[15] = 0x0000080B; // Program Counter
|
||||
break;
|
||||
|
|
|
@ -50,6 +50,7 @@ class Thumbulator
|
|||
enum ConfigureFor {
|
||||
BUS, // cartridges of type BUS
|
||||
CDF, // cartridges of type CDF
|
||||
CDF1, // cartridges of type CDF version 1
|
||||
DPCplus // cartridges of type DPC+
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue