CDF updates (with versioning) from Spiceware.

This commit is contained in:
Stephen Anthony 2017-08-14 09:11:54 -02:30
parent f57d69a023
commit 7a9cde3e4d
5 changed files with 141 additions and 42 deletions

View File

@ -30,7 +30,7 @@ CartridgeCDFWidget::CartridgeCDFWidget(
uInt16 size = 8 * 4096; uInt16 size = 8 * 4096;
ostringstream info; ostringstream info;
info << "CDF cartridge\n" info << "CDF cartridge (version " << cart.myVersion << ")\n"
<< "32K ROM, seven 4K banks are accessible to 2600\n" << "32K ROM, seven 4K banks are accessible to 2600\n"
<< "8K CDF RAM\n" << "8K CDF RAM\n"
<< "CDF registers accessible @ $FFF0 - $FFF3\n" << "CDF registers accessible @ $FFF0 - $FFF3\n"

View File

@ -27,9 +27,10 @@
#include "TIA.hxx" #include "TIA.hxx"
// Location of data within the RAM copy of the CDF Driver. // Location of data within the RAM copy of the CDF Driver.
#define DSxPTR 0x06E0 // Version 0 1
#define DSxINC 0x0768 const uInt16 DSxPTR[] = {0x06E0, 0x00A0};
#define WAVEFORM 0x07F0 const uInt16 DSxINC[] = {0x0768, 0x0128};
const uInt16 WAVEFORM[] = {0x07F0, 0x01B0};
#define DSRAM 0x0800 #define DSRAM 0x0800
#define COMMSTREAM 0x20 #define COMMSTREAM 0x20
@ -62,10 +63,15 @@ CartridgeCDF::CartridgeCDF(const BytePtr& image, uInt32 size,
// Pointer to the display RAM // Pointer to the display RAM
myDisplayImage = myCDFRAM + DSRAM; myDisplayImage = myCDFRAM + DSRAM;
setVersion();
#ifdef THUMB_SUPPORT #ifdef THUMB_SUPPORT
// Create Thumbulator ARM emulator // Create Thumbulator ARM emulator
myThumbEmulator = make_unique<Thumbulator>((uInt16*)myImage, (uInt16*)myCDFRAM, myThumbEmulator = make_unique<Thumbulator>(
settings.getBool("thumb.trapfatal"), Thumbulator::ConfigureFor::CDF, this); (uInt16*)myImage, (uInt16*)myCDFRAM, settings.getBool("thumb.trapfatal"),
myVersion ? Thumbulator::ConfigureFor::CDF1 : Thumbulator::ConfigureFor::CDF,
this);
#endif #endif
setInitialState(); setInitialState();
} }
@ -576,51 +582,57 @@ bool CartridgeCDF::load(Serializer& in)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeCDF::getDatastreamPointer(uInt8 index) const uInt32 CartridgeCDF::getDatastreamPointer(uInt8 index) const
{ {
// index &= 0x0f; uInt16 address = DSxPTR[myVersion] + index * 4;
return myCDFRAM[DSxPTR + index*4 + 0] + // low byte return myCDFRAM[address + 0] + // low byte
(myCDFRAM[DSxPTR + index*4 + 1] << 8) + (myCDFRAM[address + 1] << 8) +
(myCDFRAM[DSxPTR + index*4 + 2] << 16) + (myCDFRAM[address + 2] << 16) +
(myCDFRAM[DSxPTR + index*4 + 3] << 24) ; // high byte (myCDFRAM[address + 3] << 24) ; // high byte
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeCDF::setDatastreamPointer(uInt8 index, uInt32 value) void CartridgeCDF::setDatastreamPointer(uInt8 index, uInt32 value)
{ {
// index &= 0x1f; uInt16 address = DSxPTR[myVersion] + index * 4;
myCDFRAM[DSxPTR + index*4 + 0] = value & 0xff; // low byte
myCDFRAM[DSxPTR + index*4 + 1] = (value >> 8) & 0xff; myCDFRAM[address + 0] = value & 0xff; // low byte
myCDFRAM[DSxPTR + index*4 + 2] = (value >> 16) & 0xff; myCDFRAM[address + 1] = (value >> 8) & 0xff;
myCDFRAM[DSxPTR + index*4 + 3] = (value >> 24) & 0xff; // high byte myCDFRAM[address + 2] = (value >> 16) & 0xff;
myCDFRAM[address + 3] = (value >> 24) & 0xff; // high byte
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeCDF::getDatastreamIncrement(uInt8 index) const uInt32 CartridgeCDF::getDatastreamIncrement(uInt8 index) const
{ {
return myCDFRAM[DSxINC + index*4 + 0] + // low byte uInt16 address = DSxINC[myVersion] + index * 4;
(myCDFRAM[DSxINC + index*4 + 1] << 8) +
(myCDFRAM[DSxINC + index*4 + 2] << 16) + return myCDFRAM[address + 0] + // low byte
(myCDFRAM[DSxINC + index*4 + 3] << 24) ; // high byte (myCDFRAM[address + 1] << 8) +
(myCDFRAM[address + 2] << 16) +
(myCDFRAM[address + 3] << 24) ; // high byte
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeCDF::setDatastreamIncrement(uInt8 index, uInt32 value) void CartridgeCDF::setDatastreamIncrement(uInt8 index, uInt32 value)
{ {
myCDFRAM[DSxINC + index*4 + 0] = value & 0xff; // low byte uInt16 address = DSxINC[myVersion] + index * 4;
myCDFRAM[DSxINC + index*4 + 1] = (value >> 8) & 0xff;
myCDFRAM[DSxINC + index*4 + 2] = (value >> 16) & 0xff; myCDFRAM[address + 0] = value & 0xff; // low byte
myCDFRAM[DSxINC + index*4 + 3] = (value >> 24) & 0xff; // high 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 CartridgeCDF::getWaveform(uInt8 index) const
{ {
uInt32 result; uInt32 result;
uInt16 address = WAVEFORM[myVersion] + index * 4;
result = myCDFRAM[WAVEFORM + index*4 + 0] + // low byte result = myCDFRAM[address + 0] + // low byte
(myCDFRAM[WAVEFORM + index*4 + 1] << 8) + (myCDFRAM[address + 1] << 8) +
(myCDFRAM[WAVEFORM + index*4 + 2] << 16) + (myCDFRAM[address + 2] << 16) +
(myCDFRAM[WAVEFORM + index*4 + 3] << 24); // high byte (myCDFRAM[address + 3] << 24); // high byte
result -= (0x40000000 + DSRAM); result -= (0x40000000 + DSRAM);
@ -634,11 +646,12 @@ uInt32 CartridgeCDF::getWaveform(uInt8 index) const
uInt32 CartridgeCDF::getSample() uInt32 CartridgeCDF::getSample()
{ {
uInt32 result; uInt32 result;
uInt16 address = WAVEFORM[myVersion];
result = myCDFRAM[WAVEFORM + 0] + // low byte result = myCDFRAM[address + 0] + // low byte
(myCDFRAM[WAVEFORM + 1] << 8) + (myCDFRAM[address + 1] << 8) +
(myCDFRAM[WAVEFORM + 2] << 16) + (myCDFRAM[address + 2] << 16) +
(myCDFRAM[WAVEFORM + 3] << 24); // high byte (myCDFRAM[address + 3] << 24); // high byte
return result; return result;
} }
@ -669,3 +682,21 @@ uInt8 CartridgeCDF::readFromDatastream(uInt8 index)
setDatastreamPointer(index, pointer); setDatastreamPointer(index, pointer);
return value; 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;
}
}
}

View File

@ -36,7 +36,7 @@ class System;
There are seven 4K program banks, a 4K Display Data RAM, 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. CDF chip access is mapped to $1000 - $103F.
@authors: Darrell Spice Jr, Chris Walton, Fred Quimby, @authors: Darrell Spice Jr, Chris Walton, Fred Quimby,
@ -209,6 +209,7 @@ class CartridgeCDF : public Cartridge
uInt32 getWaveform(uInt8 index) const; uInt32 getWaveform(uInt8 index) const;
uInt32 getWaveformSize(uInt8 index) const; uInt32 getWaveformSize(uInt8 index) const;
uInt32 getSample(); uInt32 getSample();
void setVersion();
private: private:
// The 32K ROM image of the cartridge // 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 // 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. // the Cartridge Class via callFunction() so it can emulate the 32 bit audio routines.
/* Register usage for audio: /* Register usage for audio:
r8 = channel0 accumulator r8 = channel0 accumulator
r9 = channel1 accumulator r9 = channel1 accumulator
r10 = channel2 accumulator r10 = channel2 accumulator
r11 = channel0 frequency r11 = channel0 frequency
r12 = channel1 frequency r12 = channel1 frequency
r13 = channel2 frequency r13 = channel2 frequency
r14 = timer base */ 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]; uInt32 myMusicCounters[3];
// The music frequency, ARM FIQ shadow registers r11, r12, r13 // The music frequency, ARM FIQ shadow registers r11, r12, r13
@ -289,6 +290,9 @@ class CartridgeCDF : public Cartridge
uInt8 myFastJumpActive; uInt8 myFastJumpActive;
// version of CDF
uInt16 myVersion;
private: private:
// Following constructors and assignment operators not supported // Following constructors and assignment operators not supported
CartridgeCDF() = delete; CartridgeCDF() = delete;

View File

@ -234,6 +234,7 @@ void Thumbulator::write16(uInt32 addr, uInt32 data)
// as additional RAM // as additional RAM
case ConfigureFor::BUS: case ConfigureFor::BUS:
case ConfigureFor::CDF: case ConfigureFor::CDF:
case ConfigureFor::CDF1:
if((addr > 0x40000028) && (addr < 0x40000800)) if((addr > 0x40000028) && (addr < 0x40000800))
fatalError("write16", addr, "to bankswitch code area"); fatalError("write16", addr, "to bankswitch code area");
break; break;
@ -1198,6 +1199,67 @@ int Thumbulator::execute()
break; 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: case ConfigureFor::DPCplus:
// no 32-bit subroutines in DPC+ // no 32-bit subroutines in DPC+
break; break;
@ -2266,6 +2328,7 @@ int Thumbulator::reset()
// future 2K Harmony/Melody drivers will most likely use these settings // future 2K Harmony/Melody drivers will most likely use these settings
case ConfigureFor::BUS: case ConfigureFor::BUS:
case ConfigureFor::CDF: case ConfigureFor::CDF:
case ConfigureFor::CDF1:
reg_norm[14] = 0x00000800; // Link Register reg_norm[14] = 0x00000800; // Link Register
reg_norm[15] = 0x0000080B; // Program Counter reg_norm[15] = 0x0000080B; // Program Counter
break; break;

View File

@ -50,6 +50,7 @@ class Thumbulator
enum ConfigureFor { enum ConfigureFor {
BUS, // cartridges of type BUS BUS, // cartridges of type BUS
CDF, // cartridges of type CDF CDF, // cartridges of type CDF
CDF1, // cartridges of type CDF version 1
DPCplus // cartridges of type DPC+ DPCplus // cartridges of type DPC+
}; };