refactored CartDPC class

replaced DPC ROM
This commit is contained in:
thrust26 2020-04-24 11:20:01 +02:00
parent 42c7f45c42
commit 4699a28af8
4 changed files with 37 additions and 171 deletions

View File

@ -22,45 +22,36 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDPC::CartridgeDPC(const ByteBuffer& image, size_t size, CartridgeDPC::CartridgeDPC(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: Cartridge(settings, md5), : CartridgeF8(image, size, md5, settings)
mySize(size)
{ {
// Make a copy of the entire image
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
createRomAccessArrays(8_KB);
// Pointer to the program ROM (8K @ 0 byte offset)
myProgramImage = myImage.data();
// Pointer to the display ROM (2K @ 8K offset)
myDisplayImage = myProgramImage + 8_KB;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeDPC::reset() void CartridgeDPC::reset()
{ {
CartridgeEnhanced::reset();
myAudioCycles = 0; myAudioCycles = 0;
myFractionalClocks = 0.0; myFractionalClocks = 0.0;
// Upon reset we switch to the startup bank
initializeStartBank(1);
bank(startBank());
myDpcPitch = mySettings.getInt(AudioSettings::SETTING_DPC_PITCH); myDpcPitch = mySettings.getInt(AudioSettings::SETTING_DPC_PITCH);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeDPC::install(System& system) void CartridgeDPC::install(System& system)
{ {
mySystem = &system; CartridgeEnhanced::install(system);
myRomOffset = 0x80;
// Pointer to the display ROM (2K @ 8K offset)
myDisplayImage = myImage.get() + 8_KB;
createRomAccessArrays(8_KB);
// Set the page accessing method for the DPC reading & writing pages // Set the page accessing method for the DPC reading & writing pages
System::PageAccess access(this, System::PageAccessType::READWRITE); System::PageAccess access(this, System::PageAccessType::READWRITE);
for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE) for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE)
mySystem->setPageAccess(addr, access); mySystem->setPageAccess(addr, access);
// Install pages for the startup bank
bank(startBank());
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -128,12 +119,15 @@ inline void CartridgeDPC::updateMusicModeDataFetchers()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeDPC::peek(uInt16 address) uInt8 CartridgeDPC::peek(uInt16 address)
{ {
uInt16 peekAddress = address;
address &= 0x0FFF; address &= 0x0FFF;
// In debugger/bank-locked mode, we ignore all hotspots and in general // In debugger/bank-locked mode, we ignore all hotspots and in general
// anything that can change the internal state of the cart // anything that can change the internal state of the cart
if(bankLocked()) if(bankLocked())
return myProgramImage[myBankOffset + address]; return myImage[myCurrentSegOffset[0] + address];
// Clock the random number generator. This should be done for every // Clock the random number generator. This should be done for every
// cartridge access, however, we're only doing it for the DPC and // cartridge access, however, we're only doing it for the DPC and
@ -232,30 +226,14 @@ uInt8 CartridgeDPC::peek(uInt16 address)
return result; return result;
} }
else else
{ return CartridgeEnhanced::peek(peekAddress);
// Switch banks if necessary
switch(address)
{
case 0x0FF8:
// Set the current bank to the lower 4k bank
bank(0);
break;
case 0x0FF9:
// Set the current bank to the upper 4k bank
bank(1);
break;
default:
break;
}
return myProgramImage[myBankOffset + address];
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDPC::poke(uInt16 address, uInt8 value) bool CartridgeDPC::poke(uInt16 address, uInt8 value)
{ {
uInt16 pokeAddress = address;
address &= 0x0FFF; address &= 0x0FFF;
// Clock the random number generator. This should be done for every // Clock the random number generator. This should be done for every
@ -338,102 +316,31 @@ bool CartridgeDPC::poke(uInt16 address, uInt8 value)
} }
} }
else else
{ CartridgeEnhanced::poke(pokeAddress, value);
// Switch banks if necessary
switch(address)
{
case 0x0FF8:
// Set the current bank to the lower 4k bank
bank(0);
break;
case 0x0FF9:
// Set the current bank to the upper 4k bank
bank(1);
break;
default:
break;
}
}
return false; return false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDPC::bank(uInt16 bank)
{
if(bankLocked()) return false;
// Remember what bank we're in
myBankOffset = bank << 12;
System::PageAccess access(this, System::PageAccessType::READ);
// Set the page accessing methods for the hot spots
for(uInt16 addr = (0x1FF8 & ~System::PAGE_MASK); addr < 0x2000;
addr += System::PAGE_SIZE)
{
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
// Setup the page access methods for the current bank
for(uInt16 addr = 0x1080; addr < static_cast<uInt16>(0x1FF8U & ~System::PAGE_MASK);
addr += System::PAGE_SIZE)
{
access.directPeekBase = &myProgramImage[myBankOffset + (addr & 0x0FFF)];
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeDPC::getBank(uInt16) const
{
return myBankOffset >> 12;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeDPC::romBankCount() const
{
return 2;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDPC::patch(uInt16 address, uInt8 value) bool CartridgeDPC::patch(uInt16 address, uInt8 value)
{ {
address &= 0x0FFF;
// For now, we ignore attempts to patch the DPC address space // For now, we ignore attempts to patch the DPC address space
if(address >= 0x0080) if((address & ADDR_MASK) >= ROM_OFFSET + myRomOffset)
{ {
myProgramImage[myBankOffset + (address & 0x0FFF)] = value; return CartridgeEnhanced::patch(address, value);
return myBankChanged = true;
} }
else else
return false; return false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgeDPC::getImage(size_t& size) const
{
size = mySize;
return myImage.data();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDPC::save(Serializer& out) const bool CartridgeDPC::save(Serializer& out) const
{ {
if(!CartridgeEnhanced::save(out))
return false;
try try
{ {
// Indicates which bank is currently active
out.putShort(myBankOffset);
// The top registers for the data fetchers // The top registers for the data fetchers
out.putByteArray(myTops.data(), myTops.size()); out.putByteArray(myTops.data(), myTops.size());
@ -468,11 +375,11 @@ bool CartridgeDPC::save(Serializer& out) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDPC::load(Serializer& in) bool CartridgeDPC::load(Serializer& in)
{ {
if(!CartridgeEnhanced::load(in))
return false;
try try
{ {
// Indicates which bank is currently active
myBankOffset = in.getShort();
// The top registers for the data fetchers // The top registers for the data fetchers
in.getByteArray(myTops.data(), myTops.size()); in.getByteArray(myTops.data(), myTops.size());
@ -501,9 +408,5 @@ bool CartridgeDPC::load(Serializer& in)
cerr << "ERROR: CartridgeDPC::load" << endl; cerr << "ERROR: CartridgeDPC::load" << endl;
return false; return false;
} }
// Now, go to the current bank
bank(myBankOffset >> 12);
return true; return true;
} }

View File

@ -18,10 +18,7 @@
#ifndef CARTRIDGE_DPC_HXX #ifndef CARTRIDGE_DPC_HXX
#define CARTRIDGE_DPC_HXX #define CARTRIDGE_DPC_HXX
class System; #include "CartF8.hxx"
#include "bspf.hxx"
#include "Cart.hxx"
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
#include "CartDPCWidget.hxx" #include "CartDPCWidget.hxx"
#endif #endif
@ -35,9 +32,9 @@ class System;
For complete details on the DPC chip see David P. Crane's United States For complete details on the DPC chip see David P. Crane's United States
Patent Number 4,644,495. Patent Number 4,644,495.
@author Bradford W. Mott @author Bradford W. Mott, Thomas Jentzsch
*/ */
class CartridgeDPC : public Cartridge class CartridgeDPC : public CartridgeF8
{ {
friend class CartridgeDPCWidget; friend class CartridgeDPCWidget;
@ -55,11 +52,6 @@ class CartridgeDPC : public Cartridge
virtual ~CartridgeDPC() = default; virtual ~CartridgeDPC() = default;
public: public:
/**
Reset device to its power-on state
*/
void reset() override;
/** /**
Install cartridge in the specified system. Invoked by the system Install cartridge in the specified system. Invoked by the system
when the cartridge is attached to it. when the cartridge is attached to it.
@ -69,23 +61,9 @@ class CartridgeDPC : public Cartridge
void install(System& system) override; void install(System& system) override;
/** /**
Install pages for the specified bank in the system. Reset device to its power-on state
@param bank The bank that should be installed in the system
*/ */
bool bank(uInt16 bank) override; void reset() override;
/**
Get the current bank.
@param address The address to use when querying the bank
*/
uInt16 getBank(uInt16 address = 0) const override;
/**
Query the number of banks supported by the cartridge.
*/
uInt16 romBankCount() const override;
/** /**
Patch the cartridge ROM. Patch the cartridge ROM.
@ -96,14 +74,6 @@ class CartridgeDPC : public Cartridge
*/ */
bool patch(uInt16 address, uInt8 value) override; bool patch(uInt16 address, uInt8 value) override;
/**
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
*/
const uInt8* getImage(size_t& size) const override;
/** /**
Save the current state of this cart to the given Serializer. Save the current state of this cart to the given Serializer.
@ -127,6 +97,11 @@ class CartridgeDPC : public Cartridge
*/ */
string name() const override { return "CartridgeDPC"; } string name() const override { return "CartridgeDPC"; }
/**
Change the DPC audio pitch
@param pitch The new pitch value
*/
void setDpcPitch(double pitch) { myDpcPitch = pitch; } void setDpcPitch(double pitch) { myDpcPitch = pitch; }
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
@ -171,15 +146,6 @@ class CartridgeDPC : public Cartridge
void updateMusicModeDataFetchers(); void updateMusicModeDataFetchers();
private: private:
// The ROM image
std::array<uInt8, 8_KB + 2_KB + 256> myImage;
// (Actual) Size of the ROM image
size_t mySize{0};
// Pointer to the 8K program ROM image of the cartridge
uInt8* myProgramImage{nullptr};
// Pointer to the 2K display ROM image of the cartridge // Pointer to the 2K display ROM image of the cartridge
uInt8* myDisplayImage{nullptr}; uInt8* myDisplayImage{nullptr};
@ -207,9 +173,6 @@ class CartridgeDPC : public Cartridge
// Fractional DPC music OSC clocks unused during the last update // Fractional DPC music OSC clocks unused during the last update
double myFractionalClocks{0.0}; double myFractionalClocks{0.0};
// Indicates the offset into the ROM image (aligns to current bank)
uInt16 myBankOffset{0};
// DPC pitch // DPC pitch
double myDpcPitch{0.0}; double myDpcPitch{0.0};