diff --git a/docs/index.html b/docs/index.html index 88c55e07c..e98355786 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2779,6 +2779,7 @@ Ms Pac-Man (Stella extended codes): AR ²Supercharger CV Commavid extra ram DPC ²Pitfall II + DPC+ ²Enhanced DPC E0 8K Parker Bros E7 16K M-network EF 64K Homestar Runner diff --git a/src/emucore/Cart.cxx b/src/emucore/Cart.cxx index f40189800..caf595351 100644 --- a/src/emucore/Cart.cxx +++ b/src/emucore/Cart.cxx @@ -30,6 +30,7 @@ #include "Cart4K.hxx" #include "CartAR.hxx" #include "CartDPC.hxx" +#include "CartDPCPlus.hxx" #include "CartE0.hxx" #include "CartE7.hxx" #include "CartEF.hxx" @@ -144,6 +145,8 @@ Cartridge* Cartridge::create(const uInt8* image, uInt32 size, string& md5, cartridge = new CartridgeAR(image, size, settings); else if(type == "DPC") cartridge = new CartridgeDPC(image, size); + else if(type == "DPC+") + cartridge = new CartridgeDPCPlus(image, size); else if(type == "E0") cartridge = new CartridgeE0(image); else if(type == "E7") @@ -317,7 +320,7 @@ string Cartridge::autodetectType(const uInt8* image, uInt32 size) else type = "4K"; } - else if(size == 8192) // 8K + else if(size == 8*1024) // 8K { if(isProbablySC(image, size)) type = "F8SC"; @@ -342,7 +345,7 @@ string Cartridge::autodetectType(const uInt8* image, uInt32 size) { type = "DPC"; } - else if(size == 12288) // 12K + else if(size == 12*1024) // 12K { // TODO - this should really be in a method that checks the first // 512 bytes of ROM and finds if either the lower 256 bytes or @@ -350,7 +353,7 @@ string Cartridge::autodetectType(const uInt8* image, uInt32 size) // all carts of 12K are CBS RAM Plus/FA. type = "FA"; } - else if(size == 16384) // 16K + else if(size == 16*1024) // 16K { if(isProbablySC(image, size)) type = "F6SC"; @@ -363,7 +366,11 @@ string Cartridge::autodetectType(const uInt8* image, uInt32 size) else type = "F6"; } - else if(size == 32768) // 32K + else if(size == 28*1024) // 28K + { + type = "DPC+"; + } + else if(size == 32*1024) // 32K { if(isProbablySC(image, size)) type = "F4SC"; @@ -374,7 +381,7 @@ string Cartridge::autodetectType(const uInt8* image, uInt32 size) else type = "F4"; } - else if(size == 65536) // 64K + else if(size == 64*1024) // 64K { if(isProbably3E(image, size)) type = "3E"; diff --git a/src/emucore/CartDPC.cxx b/src/emucore/CartDPC.cxx index f24e0ac45..4ec02ed80 100644 --- a/src/emucore/CartDPC.cxx +++ b/src/emucore/CartDPC.cxx @@ -33,7 +33,7 @@ CartridgeDPC::CartridgeDPC(const uInt8* image, uInt32 size) { // Make a copy of the entire image as-is, for use by getImage() // (this wastes 12K of RAM, should be controlled by a #ifdef) - memcpy(myImageCopy, image, size); + memcpy(myImageCopy, image, BSPF_min(size, 8192u + 2048u + 255u)); // Copy the program ROM image into my buffer memcpy(myProgramImage, image, 8192); diff --git a/src/emucore/CartDPC.hxx b/src/emucore/CartDPC.hxx index 5b10683f5..0e0cb6efc 100644 --- a/src/emucore/CartDPC.hxx +++ b/src/emucore/CartDPC.hxx @@ -16,8 +16,8 @@ // $Id$ //============================================================================ -#ifndef CARTRIDGEDCP_HXX -#define CARTRIDGEDCP_HXX +#ifndef CARTRIDGE_DPC_HXX +#define CARTRIDGE_DPC_HXX class System; diff --git a/src/emucore/CartDPCPlus.cxx b/src/emucore/CartDPCPlus.cxx new file mode 100644 index 000000000..008faed05 --- /dev/null +++ b/src/emucore/CartDPCPlus.cxx @@ -0,0 +1,633 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2010 by Bradford W. Mott and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id$ +//============================================================================ + +#include +#include +#include + +#include "System.hxx" +#include "CartDPCPlus.hxx" + +// TODO - properly handle read from write port functionality +// Note: do r/w port restrictions even exist for this scheme?? +// Port to new CartDebug/disassembler scheme +// Add bankchanged code + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size) +{ + // Make a copy of the entire image as-is, for use by getImage() + // (this wastes 28K of RAM, should be controlled by a #ifdef) + memcpy(myImageCopy, image, size); + + // Copy the program ROM image into my buffer + memcpy(myProgramImage, image, 4096 * 6); + + // Copy the display ROM image into my buffer + memcpy(myDisplayImage, image + 4096 * 6, 4096); + + // Initialize the DPC data fetcher registers + for(uInt16 i = 0; i < 8; ++i) + myTops[i] = myBottoms[i] = myCounters[i] = myFlags[i] = 0; + + // None of the data fetchers are in music mode + myMusicMode[0] = myMusicMode[1] = myMusicMode[2] = false; + + // Initialize the DPC's random number generator register (must be non-zero) + myRandomNumber = 1; + + // Initialize the system cycles counter & fractional clock values + mySystemCycles = 0; + myFractionalClocks = 0.0; + + // Remember startup bank + myStartBank = 1; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeDPCPlus::~CartridgeDPCPlus() +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeDPCPlus::reset() +{ + // Update cycles to the current system cycles + mySystemCycles = mySystem->cycles(); + myFractionalClocks = 0.0; + + // Upon reset we switch to the startup bank + bank(myStartBank); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeDPCPlus::systemCyclesReset() +{ + // Get the current system cycle + uInt32 cycles = mySystem->cycles(); + + // Adjust the cycle counter so that it reflects the new value + mySystemCycles -= cycles; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeDPCPlus::install(System& system) +{ + mySystem = &system; + uInt16 shift = mySystem->pageShift(); + uInt16 mask = mySystem->pageMask(); + + // Make sure the system we're being installed in has a page size that'll work + assert(((0x1080 & mask) == 0) && ((0x1100 & mask) == 0)); + + // Set the page accessing methods for the hot spots + System::PageAccess access; + for(uInt32 i = (0x1FF6 & ~mask); i < 0x2000; i += (1 << shift)) + { + access.directPeekBase = 0; + access.directPokeBase = 0; + access.device = this; + mySystem->setPageAccess(i >> shift, access); + } + + // Set the page accessing method for the DPC reading & writing pages + for(uInt32 j = 0x1000; j < 0x1080; j += (1 << shift)) + { + access.directPeekBase = 0; + access.directPokeBase = 0; + access.device = this; + mySystem->setPageAccess(j >> shift, access); + } + + // Install pages for bank 5 + bank(5); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +inline void CartridgeDPCPlus::clockRandomNumberGenerator() +{ + // Table for computing the input bit of the random number generator's + // shift register (it's the NOT of the EOR of four bits) + static const uInt8 f[16] = { + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 + }; + + // Using bits 7, 5, 4, & 3 of the shift register compute the input + // bit for the shift register + uInt8 bit = f[((myRandomNumber >> 3) & 0x07) | + ((myRandomNumber & 0x80) ? 0x08 : 0x00)]; + + // Update the shift register + myRandomNumber = (myRandomNumber << 1) | bit; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +inline void CartridgeDPCPlus::updateMusicModeDataFetchers() +{ + // Calculate the number of cycles since the last update + Int32 cycles = mySystem->cycles() - mySystemCycles; + mySystemCycles = mySystem->cycles(); + + // Calculate the number of DPC OSC clocks since the last update + double clocks = ((20000.0 * cycles) / 1193191.66666667) + myFractionalClocks; + Int32 wholeClocks = (Int32)clocks; + myFractionalClocks = clocks - (double)wholeClocks; + + if(wholeClocks <= 0) + { + return; + } + + // Let's update counters and flags of the music mode data fetchers + for(int x = 5; x <= 7; ++x) + { + // Update only if the data fetcher is in music mode + if(myMusicMode[x - 5]) + { + Int32 top = myTops[x] + 1; + Int32 newLow = (Int32)(myCounters[x] & 0x00ff); + + if(myTops[x] != 0) + { + newLow -= (wholeClocks % top); + if(newLow < 0) + { + newLow += top; + } + } + else + { + newLow = 0; + } + + // Update flag register for this data fetcher + if(newLow <= myBottoms[x]) + { + myFlags[x] = 0x00; + } + else if(newLow <= myTops[x]) + { + myFlags[x] = 0xff; + } + + myCounters[x] = (myCounters[x] & 0x0F00) | (uInt16)newLow; + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 CartridgeDPCPlus::peek(uInt16 address) +{ + address &= 0x0FFF; + + // Clock the random number generator. This should be done for every + // cartridge access, however, we're only doing it for the DPC and + // hot-spot accesses to save time. + clockRandomNumberGenerator(); + + if(address < 0x0040) + { + uInt8 result = 0; + + // Get the index of the data fetcher that's being accessed + uInt32 index = address & 0x07; + uInt32 function = (address >> 3) & 0x07; + + // Update flag register for selected data fetcher + if((myCounters[index] & 0x00ff) == myTops[index]) + { + myFlags[index] = 0xff; + } + else if((myCounters[index] & 0x00ff) == myBottoms[index]) + { + myFlags[index] = 0x00; + } + + switch(function) + { + case 0x00: + { + // Is this a random number read + if(index < 4) + { + result = myRandomNumber; + } + // No, it's a music read + else + { + static const uInt8 musicAmplitudes[8] = { + 0x00, 0x04, 0x05, 0x09, 0x06, 0x0a, 0x0b, 0x0f + }; + + // Update the music data fetchers (counter & flag) + updateMusicModeDataFetchers(); + + uInt8 i = 0; + if(myMusicMode[0] && myFlags[5]) + { + i |= 0x01; + } + if(myMusicMode[1] && myFlags[6]) + { + i |= 0x02; + } + if(myMusicMode[2] && myFlags[7]) + { + i |= 0x04; + } + + result = musicAmplitudes[i]; + } + break; + } + + // DFx display data read + case 0x01: + { + result = myDisplayImage[ /* 4095 - */ myCounters[index]]; + break; + } + + // DFx display data read AND'd w/flag + case 0x02: + { + result = myDisplayImage[ /* 4095 - */ myCounters[index]] & myFlags[index]; + break; + } + + // DFx flag + case 0x07: + { + result = myFlags[index]; + break; + } + + default: + { + result = 0; + } + } + + // Clock the selected data fetcher's counter if needed + if((index < 5) || ((index >= 5) && (!myMusicMode[index - 5]))) + { + myCounters[index] = (myCounters[index] /*-*/ + 1) & 0x0fff; + } + + return result; + } + else + { + // Switch banks if necessary + switch(address) + { + case 0x0FF6: + // Set the current bank to the first 4k bank + bank(0); + break; + + case 0x0FF7: + // Set the current bank to the second 4k bank + bank(1); + break; + + case 0x0FF8: + // Set the current bank to the third 4k bank + bank(2); + break; + + case 0x0FF9: + // Set the current bank to the fourth 4k bank + bank(3); + break; + + case 0x0FFA: + // Set the current bank to the fifth 4k bank + bank(4); + break; + + case 0x0FFB: + // Set the current bank to the last 4k bank + bank(5); + break; + + default: + break; + } + return myProgramImage[myCurrentBank * 4096 + address]; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeDPCPlus::poke(uInt16 address, uInt8 value) +{ + address &= 0x0FFF; + + // Clock the random number generator. This should be done for every + // cartridge access, however, we're only doing it for the DPC and + // hot-spot accesses to save time. + clockRandomNumberGenerator(); + + if((address >= 0x0040) && (address < 0x0080)) + { + // Get the index of the data fetcher that's being accessed + uInt32 index = address & 0x07; + uInt32 function = (address >> 3) & 0x07; + + switch(function) + { + // DFx top count + case 0x00: + { + myTops[index] = value; + myFlags[index] = 0x00; + break; + } + + // DFx bottom count + case 0x01: + { + myBottoms[index] = value; + break; + } + + // DFx counter low + case 0x02: + { + if((index >= 5) && myMusicMode[index - 5]) + { + // Data fecther is in music mode so its low counter value + // should be loaded from the top register not the poked value + myCounters[index] = (myCounters[index] & 0x0F00) | + (uInt16)myTops[index]; + } + else + { + // Data fecther is either not a music mode data fecther or it + // isn't in music mode so it's low counter value should be loaded + // with the poked value + myCounters[index] = (myCounters[index] & 0x0F00) | (uInt16)value; + } + break; + } + + // DFx counter high + case 0x03: + { + myCounters[index] = (((uInt16)value & 0x0F) << 8) | + (myCounters[index] & 0x00ff); + + // Execute special code for music mode data fetchers + if(index >= 5) + { + myMusicMode[index - 5] = (value & 0x10); + + // NOTE: We are not handling the clock source input for + // the music mode data fetchers. We're going to assume + // they always use the OSC input. + } + break; + } + + // Random Number Generator Reset + case 0x06: + { + myRandomNumber = 1; + break; + } + + default: + { + break; + } + } + } + else + { + // Switch banks if necessary + switch(address) + { + case 0x0FF6: + // Set the current bank to the first 4k bank + bank(0); + break; + + case 0x0FF7: + // Set the current bank to the second 4k bank + bank(1); + break; + + case 0x0FF8: + // Set the current bank to the third 4k bank + bank(2); + break; + + case 0x0FF9: + // Set the current bank to the fourth 4k bank + bank(3); + break; + + case 0x0FFA: + // Set the current bank to the fifth 4k bank + bank(4); + break; + + case 0x0FFB: + // Set the current bank to the last 4k bank + bank(5); + break; + + default: + break; + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeDPCPlus::bank(uInt16 bank) +{ + if(bankLocked()) return; + + // Remember what bank we're in + myCurrentBank = bank; + uInt16 offset = myCurrentBank * 4096; + uInt16 shift = mySystem->pageShift(); + uInt16 mask = mySystem->pageMask(); + + // Setup the page access methods for the current bank + System::PageAccess access; + access.device = this; + access.directPokeBase = 0; + + // Map Program ROM image into the system + for(uInt32 address = 0x1080; address < (0x1FF8U & ~mask); + address += (1 << shift)) + { + access.directPeekBase = &myProgramImage[offset + (address & 0x0FFF)]; + mySystem->setPageAccess(address >> shift, access); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int CartridgeDPCPlus::bank() +{ + return myCurrentBank; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int CartridgeDPCPlus::bankCount() +{ + // TODO - add support for debugger (support the display ROM somehow) + return 6; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeDPCPlus::patch(uInt16 address, uInt8 value) +{ + // TODO - check if this actually works + myProgramImage[(myCurrentBank << 12) + (address & 0x0FFF)] = value; + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8* CartridgeDPCPlus::getImage(int& size) +{ + size = 4096 * 6 + 4096 + 255; + + int i; + for(i = 0; i < 4096 * 6; i++) + myImageCopy[i] = myProgramImage[i]; + + for(i = 0; i < 4096; i++) + myImageCopy[i + 4096 * 6] = myDisplayImage[i]; + + return &myImageCopy[0]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeDPCPlus::save(Serializer& out) const +{ + const string& cart = name(); + + try + { + uInt32 i; + + out.putString(cart); + + // Indicates which bank is currently active + out.putInt(myCurrentBank); + + // The top registers for the data fetchers + out.putInt(8); + for(i = 0; i < 8; ++i) + out.putByte((char)myTops[i]); + + // The bottom registers for the data fetchers + out.putInt(8); + for(i = 0; i < 8; ++i) + out.putByte((char)myBottoms[i]); + + // The counter registers for the data fetchers + out.putInt(8); + for(i = 0; i < 8; ++i) + out.putInt(myCounters[i]); + + // The flag registers for the data fetchers + out.putInt(8); + for(i = 0; i < 8; ++i) + out.putByte((char)myFlags[i]); + + // The music mode flags for the data fetchers + out.putInt(3); + for(i = 0; i < 3; ++i) + out.putBool(myMusicMode[i]); + + // The random number generator register + out.putByte((char)myRandomNumber); + + out.putInt(mySystemCycles); + out.putInt((uInt32)(myFractionalClocks * 100000000.0)); + } + catch(const char* msg) + { + cerr << "ERROR: CartridgeDPCPlus::save" << endl << " " << msg << endl; + return false; + } + + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeDPCPlus::load(Serializer& in) +{ + const string& cart = name(); + + try + { + if(in.getString() != cart) + return false; + + uInt32 i, limit; + + // Indicates which bank is currently active + myCurrentBank = (uInt16) in.getInt(); + + // The top registers for the data fetchers + limit = (uInt32) in.getInt(); + for(i = 0; i < limit; ++i) + myTops[i] = (uInt8) in.getByte(); + + // The bottom registers for the data fetchers + limit = (uInt32) in.getInt(); + for(i = 0; i < limit; ++i) + myBottoms[i] = (uInt8) in.getByte(); + + // The counter registers for the data fetchers + limit = (uInt32) in.getInt(); + for(i = 0; i < limit; ++i) + myCounters[i] = (uInt16) in.getInt(); + + // The flag registers for the data fetchers + limit = (uInt32) in.getInt(); + for(i = 0; i < limit; ++i) + myFlags[i] = (uInt8) in.getByte(); + + // The music mode flags for the data fetchers + limit = (uInt32) in.getInt(); + for(i = 0; i < limit; ++i) + myMusicMode[i] = in.getBool(); + + // The random number generator register + myRandomNumber = (uInt8) in.getByte(); + + // Get system cycles and fractional clocks + mySystemCycles = in.getInt(); + myFractionalClocks = (double)in.getInt() / 100000000.0; + } + catch(const char* msg) + { + cerr << "ERROR: CartridgeDPCPlus::load" << endl << " " << msg << endl; + return false; + } + + // Now, go to the current bank + bank(myCurrentBank); + + return true; +} diff --git a/src/emucore/CartDPCPlus.hxx b/src/emucore/CartDPCPlus.hxx new file mode 100644 index 000000000..02b7e5275 --- /dev/null +++ b/src/emucore/CartDPCPlus.hxx @@ -0,0 +1,196 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2010 by Bradford W. Mott and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id$ +//============================================================================ + +#ifndef CARTRIDGE_DPC_PLUS_HXX +#define CARTRIDGE_DPC_PLUS_HXX + +class System; + +#include "bspf.hxx" +#include "Cart.hxx" + +/** + Cartridge class used for DPC+. There are six 4K program banks, a + 4K display bank, and the DPC chip. For complete details on the DPC chip + see David P. Crane's United States Patent Number 4,644,495. + + @author Spiceware, Batari, Stephen Anthony + @version $Id$ +*/ +class CartridgeDPCPlus : public Cartridge +{ + public: + /** + Create a new cartridge using the specified image + + @param image Pointer to the ROM image + */ + CartridgeDPCPlus(const uInt8* image, uInt32 size); + + /** + Destructor + */ + virtual ~CartridgeDPCPlus(); + + public: + /** + Reset device to its power-on state + */ + virtual void reset(); + + /** + Notification method invoked by the system right before the + system resets its cycle counter to zero. It may be necessary + to override this method for devices that remember cycle counts. + */ + virtual void systemCyclesReset(); + + /** + Install cartridge in the specified system. Invoked by the system + when the cartridge is attached to it. + + @param system The system the device should install itself in + */ + virtual void install(System& system); + + /** + Install pages for the specified bank in the system. + + @param bank The bank that should be installed in the system + */ + virtual void bank(uInt16 bank); + + /** + Get the current bank. + + @return The current bank, or -1 if bankswitching not supported + */ + virtual int bank(); + + /** + Query the number of banks supported by the cartridge. + */ + virtual int bankCount(); + + /** + Patch the cartridge ROM. + + @param address The ROM address to patch + @param value The value to place into the address + @return Success or failure of the patch operation + */ + virtual bool patch(uInt16 address, uInt8 value); + + /** + 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 + */ + virtual uInt8* getImage(int& size); + + /** + Save the current state of this cart to the given Serializer. + + @param out The Serializer object to use + @return False on any errors, else true + */ + virtual bool save(Serializer& out) const; + + /** + Load the current state of this cart from the given Serializer. + + @param in The Serializer object to use + @return False on any errors, else true + */ + virtual bool load(Serializer& in); + + /** + Get a descriptor for the device name (used in error checking). + + @return The name of the object + */ + virtual string name() const { return "CartridgeDPCPlus"; } + + public: + /** + Get the byte at the specified address. + + @return The byte at the specified address + */ + virtual uInt8 peek(uInt16 address); + + /** + Change the byte at the specified address to the given value + + @param address The address where the value should be stored + @param value The value to be stored at the address + */ + virtual void poke(uInt16 address, uInt8 value); + + private: + /** + Clocks the random number generator to move it to its next state + */ + void clockRandomNumberGenerator(); + + /** + Updates any data fetchers in music mode based on the number of + CPU cycles which have passed since the last update. + */ + void updateMusicModeDataFetchers(); + + private: + // Indicates which bank is currently active + uInt16 myCurrentBank; + + // The 8K program ROM image of the cartridge + uInt8 myProgramImage[4096 * 6]; + + // The 2K display ROM image of the cartridge + uInt8 myDisplayImage[4096]; + + // Copy of the raw image, for use by getImage() + uInt8 myImageCopy[4096 * 6 + 4096 + 255]; + + // The top registers for the data fetchers + uInt8 myTops[8]; + + // The bottom registers for the data fetchers + uInt8 myBottoms[8]; + + // The counter registers for the data fetchers + uInt16 myCounters[8]; + + // The flag registers for the data fetchers + uInt8 myFlags[8]; + + // The music mode DF5, DF6, & DF7 enabled flags + bool myMusicMode[3]; + + // The random number generator register + uInt8 myRandomNumber; + + // System cycle count when the last update to music data fetchers occurred + Int32 mySystemCycles; + + // Fractional DPC music OSC clocks unused during the last update + double myFractionalClocks; +}; + +#endif diff --git a/src/emucore/module.mk b/src/emucore/module.mk index 01ab96649..4cf482e1c 100644 --- a/src/emucore/module.mk +++ b/src/emucore/module.mk @@ -12,6 +12,7 @@ MODULE_OBJS := \ src/emucore/CartCV.o \ src/emucore/Cart.o \ src/emucore/CartDPC.o \ + src/emucore/CartDPCPlus.o \ src/emucore/CartE0.o \ src/emucore/CartE7.o \ src/emucore/CartEF.o \ diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index ef36f34ae..81a4e9761 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -147,6 +147,7 @@ GameInfoDialog::GameInfoDialog( items.push_back("AR (Supercharger)", "AR" ); items.push_back("CV (Commavid extra ram)", "CV" ); items.push_back("DPC (Pitfall II)", "DPC" ); + items.push_back("DPC+ (Enhanced DPC)", "DPC+" ); items.push_back("E0 (8K Parker Bros)", "E0" ); items.push_back("E7 (16K M-network)", "E7" ); items.push_back("EF (64K H. Runner)", "EF" ); diff --git a/src/gui/GlobalPropsDialog.cxx b/src/gui/GlobalPropsDialog.cxx index 2c1182d6e..dd73dcb60 100644 --- a/src/gui/GlobalPropsDialog.cxx +++ b/src/gui/GlobalPropsDialog.cxx @@ -78,6 +78,7 @@ GlobalPropsDialog:: items.push_back("AR (Supercharger)", "AR" ); items.push_back("CV (Commavid extra ram)", "CV" ); items.push_back("DPC (Pitfall II)", "DPC" ); + items.push_back("DPC+ (Enhanced DPC)", "DPC+" ); items.push_back("E0 (8K Parker Bros)", "E0" ); items.push_back("E7 (16K M-network)", "E7" ); items.push_back("EF (64K H. Runner)", "EF" );