diff --git a/Changes.txt b/Changes.txt index 2d44ec96e..eb605d984 100644 --- a/Changes.txt +++ b/Changes.txt @@ -34,6 +34,8 @@ * Acclerated emulation up to ~15% (ARM). + * Added limited GameLine Master Module bankswitching support. + * Added BUS bankswitching support for some older demos. * Fixed broken 7800 pause key support. diff --git a/docs/index.html b/docs/index.html index 51d20a55a..b95740a3c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -4947,6 +4947,7 @@ Ms Pac-Man (Stella extended codes): FA2 CBS RAM Plus 24/28K .FA2 FC Amiga Power Play Aracde 16/32K .FC FE 8K Activision (aka SCABS).FE + GL GameLine Master Module.GL MDM Menu Driven Megacart .MDM MVC Movie Cart.MVC SB 128-256K SUPERbanking .SB diff --git a/src/debugger/gui/Cart4KWidget.cxx b/src/debugger/gui/Cart4KWidget.cxx index 4d9c75b69..bfd9bba00 100644 --- a/src/debugger/gui/Cart4KWidget.cxx +++ b/src/debugger/gui/Cart4KWidget.cxx @@ -25,16 +25,6 @@ Cartridge4KWidget::Cartridge4KWidget( : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { initialize(); - - //// Eventually, we should query this from the debugger/disassembler - //uInt16 start = (cart.myImage[0xFFD] << 8) | cart.myImage[0xFFC]; - //start -= start % 0x1000; - - //ostringstream info; - //info << "Standard 4K cartridge, non-bankswitched\n" - // << "Accessible @ $" << Common::Base::HEX4 << start << " - " - // << "$" << (start + 0xFFF); - //addBaseInformation(4096, "Atari", info.str()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/gui/CartEnhancedWidget.cxx b/src/debugger/gui/CartEnhancedWidget.cxx index 4b017a984..3cd486d5f 100644 --- a/src/debugger/gui/CartEnhancedWidget.cxx +++ b/src/debugger/gui/CartEnhancedWidget.cxx @@ -181,11 +181,20 @@ void CartridgeEnhancedWidget::bankList(uInt16 bankCount, int seg, VariantList& i { width = 0; + const bool hasRamBanks = myCart.myRamBankCount > 0; + for(int bank = 0; bank < bankCount; ++bank) { ostringstream buf; + const bool isRamBank = (bank >= myCart.romBankCount()); + const int bankNum = (bank - (isRamBank ? myCart.romBankCount() : 0)); + + buf << std::setw(bankNum < 10 ? 2 : 1) << "#" << std::dec << bankNum; + if(isRamBank) // was RAM mapped here? + buf << " RAM"; + else if (hasRamBanks) + buf << " ROM"; - buf << std::setw(bank < 10 ? 2 : 1) << "#" << std::dec << bank; if(myCart.hotspot() != 0 && myHotspotDelta > 0) buf << " " << hotspotStr(bank, seg); VarList::push_back(items, buf.str()); @@ -196,7 +205,7 @@ void CartridgeEnhancedWidget::bankList(uInt16 bankCount, int seg, VariantList& i // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeEnhancedWidget::bankSelect(int& ypos) { - if(myCart.romBankCount() > 1) + if(myCart.romBankCount() + myCart.ramBankCount() > 1) { constexpr int xpos = 2; @@ -208,7 +217,7 @@ void CartridgeEnhancedWidget::bankSelect(int& ypos) VariantList items; int pw = 0; - bankList(myCart.romBankCount(), seg, items, pw); + bankList(myCart.romBankCount() + myCart.ramBankCount(), seg, items, pw); // create widgets ostringstream buf; @@ -249,7 +258,6 @@ string CartridgeEnhancedWidget::bankState() const int bank = myCart.getSegmentBank(seg); const bool isRamBank = (bank >= myCart.romBankCount()); - if(seg > 0) buf << " / "; diff --git a/src/debugger/gui/CartGLWidget.cxx b/src/debugger/gui/CartGLWidget.cxx new file mode 100644 index 000000000..b4b6668ce --- /dev/null +++ b/src/debugger/gui/CartGLWidget.cxx @@ -0,0 +1,50 @@ +//============================================================================ +// +// 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-2023 by Bradford W. Mott, Stephen Anthony +// 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. +//============================================================================ + +#include "CartGL.hxx" +#include "CartGLWidget.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeGLWidget::CartridgeGLWidget( + GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, + int x, int y, int w, int h, CartridgeGL& cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) +{ + initialize(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeGLWidget::description() +{ + ostringstream info; + + info << "GameLine Master Module cartridge, 4K ROM, 10/12K RAM\n" + << "mapped into four 1K segments\n" + << "THIS SCHEME IS NOT FULLY IMPLEMENTED OR TESTED"; + + return info.str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeGLWidget::internalRamDescription() +{ + ostringstream desc; + + desc << "Accessible 1K" << " at a time"; + + return desc.str(); +} diff --git a/src/debugger/gui/CartGLWidget.hxx b/src/debugger/gui/CartGLWidget.hxx new file mode 100644 index 000000000..70dd87fe2 --- /dev/null +++ b/src/debugger/gui/CartGLWidget.hxx @@ -0,0 +1,50 @@ +//============================================================================ +// +// 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-2023 by Bradford W. Mott, Stephen Anthony +// 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. +//============================================================================ + +#ifndef CARTRIDGEGL_WIDGET_HXX +#define CARTRIDGEGL_WIDGET_HXX + +class CartridgeGL; + +#include "CartEnhanced.hxx" + +class CartridgeGLWidget : public CartridgeEnhancedWidget +{ + public: + CartridgeGLWidget(GuiObject* boss, const GUI::Font& lfont, + const GUI::Font& nfont, + int x, int y, int w, int h, + CartridgeGL& cart); + ~CartridgeGLWidget() override = default; + + private: + string manufacturer() override { return "Control Video Corporation (CVC)"; } + + string description() override; + + string internalRamDescription() override; + + private: + // Following constructors and assignment operators not supported + CartridgeGLWidget() = delete; + CartridgeGLWidget(const CartridgeGLWidget&) = delete; + CartridgeGLWidget(CartridgeGLWidget&&) = delete; + CartridgeGLWidget& operator=(const CartridgeGLWidget&) = delete; + CartridgeGLWidget& operator=(CartridgeGLWidget&&) = delete; +}; + +#endif diff --git a/src/debugger/gui/module.mk b/src/debugger/gui/module.mk index f0c64410c..45ea9b5ae 100644 --- a/src/debugger/gui/module.mk +++ b/src/debugger/gui/module.mk @@ -46,6 +46,7 @@ MODULE_OBJS := \ src/debugger/gui/CartFAWidget.o \ src/debugger/gui/CartFCWidget.o \ src/debugger/gui/CartFEWidget.o \ + src/debugger/gui/CartGLWidget.o \ src/debugger/gui/CartMDMWidget.o \ src/debugger/gui/CartRamWidget.o \ src/debugger/gui/CartSBWidget.o \ diff --git a/src/emucore/Bankswitch.cxx b/src/emucore/Bankswitch.cxx index 7f9ceae81..afabf2575 100644 --- a/src/emucore/Bankswitch.cxx +++ b/src/emucore/Bankswitch.cxx @@ -119,6 +119,7 @@ Bankswitch::BSList = {{ { "FA2" , "FA2 (CBS RAM Plus 24-32K)" }, { "FC" , "FC (32K Amiga)" }, { "FE" , "FE (8K Activision)" }, + { "GL" , "GL (GameLine Master Module)" }, { "MDM" , "MDM (Menu Driven Megacart)" }, { "MVC" , "MVC (Movie Cart)" }, { "SB" , "SB (128-256K SUPERbank)" }, @@ -129,7 +130,7 @@ Bankswitch::BSList = {{ { "WDSW" , "WDSW (Pink Panther, bad)" }, { "X07" , "X07 (64K AtariAge)" }, #if defined(CUSTOM_ARM) - { "CUSTOM" , "CUSTOM (ARM)" } + { "CUSTOM" , "CUSTOM (ARM)" } #endif }}; @@ -181,6 +182,7 @@ Bankswitch::Sizes = {{ { 24_KB, 32_KB }, // _FA2 { 32_KB, 32_KB }, // _FC { 8_KB, 8_KB }, // _FE + { 4_KB, 4_KB }, // _GL { 8_KB, Bankswitch::any_KB }, // _MDM { 1024_KB, Bankswitch::any_KB }, // _MVC { 128_KB, 256_KB }, // _SB @@ -270,6 +272,7 @@ Bankswitch::ExtensionMap Bankswitch::ourExtensions = { { "FA2" , Bankswitch::Type::_FA2 }, { "FC" , Bankswitch::Type::_FC }, { "FE" , Bankswitch::Type::_FE }, + { "GL" , Bankswitch::Type::_GL }, { "MDM" , Bankswitch::Type::_MDM }, { "MVC" , Bankswitch::Type::_MVC }, { "SB" , Bankswitch::Type::_SB }, @@ -329,6 +332,7 @@ Bankswitch::NameToTypeMap Bankswitch::ourNameToTypes = { { "FA2" , Bankswitch::Type::_FA2 }, { "FC" , Bankswitch::Type::_FC }, { "FE" , Bankswitch::Type::_FE }, + { "GL" , Bankswitch::Type::_GL }, { "MDM" , Bankswitch::Type::_MDM }, { "MVC" , Bankswitch::Type::_MVC }, { "SB" , Bankswitch::Type::_SB }, diff --git a/src/emucore/Bankswitch.hxx b/src/emucore/Bankswitch.hxx index 229f30e08..d7eebd9a4 100644 --- a/src/emucore/Bankswitch.hxx +++ b/src/emucore/Bankswitch.hxx @@ -43,8 +43,8 @@ class Bankswitch _4K, _4KSC, _AR, _BF, _BFSC, _BUS, _CDF, _CM, _CTY, _CV, _DF, _DFSC, _DPC, _DPCP, _E0, _E7, _EF, _EFSC, _F0, _F4, _F4SC, _F6, _F6SC, _F8, - _F8SC, _FA, _FA2, _FC, _FE, _MDM, _MVC, _SB, - _TVBOY, _UA, _UASW, _WD, _WDSW, _X07, + _F8SC, _FA, _FA2, _FC, _FE, _GL, _MDM, _MVC, + _SB, _TVBOY, _UA, _UASW, _WD, _WDSW, _X07, #ifdef CUSTOM_ARM _CUSTOM, #endif diff --git a/src/emucore/Cart.hxx b/src/emucore/Cart.hxx index be56e4d10..b5f6555ca 100644 --- a/src/emucore/Cart.hxx +++ b/src/emucore/Cart.hxx @@ -434,6 +434,9 @@ class Cartridge : public Device // Callback to output messages messageCallback myMsgCallback{nullptr}; + // Semi-random values to use when a read from write port occurs + std::array myRWPRandomValues; + private: // The startup bank to use (where to look for the reset vector address) uInt16 myStartBank{0}; @@ -442,9 +445,6 @@ class Cartridge : public Device // by the debugger, when disassembling/dumping ROM. bool myHotspotsLocked{false}; - // Semi-random values to use when a read from write port occurs - std::array myRWPRandomValues; - // Contains various info about this cartridge // This needs to be stored separately from child classes, since // sometimes the information in both do not match diff --git a/src/emucore/CartCreator.cxx b/src/emucore/CartCreator.cxx index 04e742310..111695afe 100644 --- a/src/emucore/CartCreator.cxx +++ b/src/emucore/CartCreator.cxx @@ -54,6 +54,7 @@ #include "CartFA2.hxx" #include "CartFC.hxx" #include "CartFE.hxx" +#include "CartGL.hxx" #include "CartMDM.hxx" #include "CartMVC.hxx" #include "CartSB.hxx" @@ -305,6 +306,8 @@ CartCreator::createFromImage(const ByteBuffer& image, size_t size, return make_unique(image, size, md5, settings); case Bankswitch::Type::_FE: return make_unique(image, size, md5, settings); + case Bankswitch::Type::_GL: + return make_unique(image, size, md5, settings); case Bankswitch::Type::_MDM: return make_unique(image, size, md5, settings); case Bankswitch::Type::_UA: diff --git a/src/emucore/CartDetector.cxx b/src/emucore/CartDetector.cxx index ced6c349d..2d611290e 100644 --- a/src/emucore/CartDetector.cxx +++ b/src/emucore/CartDetector.cxx @@ -27,9 +27,12 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si // Guess type based on size Bankswitch::Type type = Bankswitch::Type::_AUTO; - if((size % 8448) == 0 || size == 6144) + if((size % 8448) == 0 || size == 6_KB) { - type = Bankswitch::Type::_AR; + if(size == 6_KB && isProbablyGL(image, size)) + type = Bankswitch::Type::_GL; + else + type = Bankswitch::Type::_AR; } else if(size < 2_KB) // Sub2K images { @@ -48,6 +51,8 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si type = Bankswitch::Type::_4KSC; else if (isProbablyFC(image, size)) type = Bankswitch::Type::_FC; + else if (isProbablyGL(image, size)) + type = Bankswitch::Type::_GL; else type = Bankswitch::Type::_4K; } @@ -706,6 +711,14 @@ bool CartDetector::isProbablyFE(const ByteBuffer& image, size_t size) return false; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartDetector::isProbablyGL(const ByteBuffer& image, size_t size) +{ + static constexpr uInt8 signature[] = { 0xad, 0xb8, 0x0c }; // LDA $0CB8 + + return searchForBytes(image, size, signature, 3); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartDetector::isProbablyMDM(const ByteBuffer& image, size_t size) { diff --git a/src/emucore/CartDetector.hxx b/src/emucore/CartDetector.hxx index 9e5716888..e2d346f0a 100644 --- a/src/emucore/CartDetector.hxx +++ b/src/emucore/CartDetector.hxx @@ -201,6 +201,11 @@ class CartDetector */ static bool isProbablyFE(const ByteBuffer& image, size_t size); + /** + Returns true if the image is probably a GameLine cartridge + */ + static bool isProbablyGL(const ByteBuffer& image, size_t size); + /** Returns true if the image is probably a MDM bankswitching cartridge */ diff --git a/src/emucore/CartEnhanced.cxx b/src/emucore/CartEnhanced.cxx index c15727f6c..fa983f0fb 100644 --- a/src/emucore/CartEnhanced.cxx +++ b/src/emucore/CartEnhanced.cxx @@ -65,8 +65,11 @@ CartridgeEnhanced::CartridgeEnhanced(const ByteBuffer& image, size_t size, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeEnhanced::install(System& system) { + if(!myRamBankShift) + myRamBankShift = myBankShift - 1; + // limit banked RAM size to the size of one RAM bank - const uInt16 ramSize = myRamBankCount > 0 ? 1 << (myBankShift - 1) : + const uInt16 ramSize = myRamBankCount > 0 ? 1 << myRamBankShift : static_cast(myRamSize); // calculate bank switching and RAM sizes and masks @@ -200,7 +203,8 @@ bool CartridgeEnhanced::poke(uInt16 address, uInt8 value) if(isRamBank(address)) { - if(static_cast(address & (myBankSize >> 1)) == myRamWpHigh) + if(static_cast(address & (myBankSize >> 1)) == myRamWpHigh + || myBankShift == myRamBankShift) { address &= myRamMask; // The RAM banks follow the ROM banks and are half the size of a ROM bank @@ -271,7 +275,7 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment) const uInt16 ramBank = (bank - romBankCount()) % myRamBankCount; // The RAM banks follow the ROM banks and are half the size of a ROM bank const uInt32 bankOffset = static_cast(mySize) + - (ramBank << (myBankShift - 1)); + (ramBank << myRamBankShift); // Remember what bank is in this segment myCurrentSegOffset[segment] = static_cast(mySize) + @@ -280,7 +284,8 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment) // Set the page accessing method for the RAM writing pages // Note: Writes are mapped to poke() (NOT using directPokeBase) to check for read from write port (RWP) uInt16 fromAddr = (ROM_OFFSET + segmentOffset + myWriteOffset) & ~System::PAGE_MASK; - uInt16 toAddr = (ROM_OFFSET + segmentOffset + myWriteOffset + (myBankSize >> 1)) & ~System::PAGE_MASK; + uInt16 toAddr = (ROM_OFFSET + segmentOffset + myWriteOffset + + (myBankSize >> (myBankShift - myRamBankShift))) & ~System::PAGE_MASK; System::PageAccess access(this, System::PageAccessType::WRITE); for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE) @@ -295,7 +300,8 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment) // Set the page accessing method for the RAM reading pages fromAddr = (ROM_OFFSET + segmentOffset + myReadOffset) & ~System::PAGE_MASK; - toAddr = (ROM_OFFSET + segmentOffset + myReadOffset + (myBankSize >> 1)) & ~System::PAGE_MASK; + toAddr = (ROM_OFFSET + segmentOffset + myReadOffset + + (myBankSize >> (myBankShift - myRamBankShift))) & ~System::PAGE_MASK; access.type = System::PageAccessType::READ; for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE) diff --git a/src/emucore/CartEnhanced.hxx b/src/emucore/CartEnhanced.hxx index 4d47411f2..d45c0c758 100644 --- a/src/emucore/CartEnhanced.hxx +++ b/src/emucore/CartEnhanced.hxx @@ -214,6 +214,9 @@ class CartridgeEnhanced : public Cartridge // The mask for a bank segment uInt16 myBankMask{ROM_MASK}; + // Usually myBankShift - 1 + uInt16 myRamBankShift{0}; + protected: // The extra RAM size size_t myRamSize{RAM_SIZE}; // default 0 @@ -318,7 +321,7 @@ class CartridgeEnhanced : public Cartridge virtual uInt16 getStartBank() const { return 0; } /** - Get the ROM offset of the segment of the given address + Get the ROM offset of the segment of the given address. @param address The address to get the offset for @return The calculated offset @@ -328,14 +331,16 @@ class CartridgeEnhanced : public Cartridge } /** - Get the RAM offset of the segment of the given address + Get the RAM offset of the segment of the given address. + The RAM banks are half the size of a ROM bank. @param address The address to get the offset for @return The calculated offset */ uInt16 ramAddressSegmentOffset(uInt16 address) const { - return static_cast((myCurrentSegOffset[ - ((address & ROM_MASK) >> myBankShift) % myBankSegs] - mySize) >> 1); + return static_cast( + (myCurrentSegOffset[((address & ROM_MASK) >> myBankShift) % myBankSegs] - mySize) + >> (myBankShift - myRamBankShift)); } private: diff --git a/src/emucore/CartGL.cxx b/src/emucore/CartGL.cxx new file mode 100644 index 000000000..bf9d9c496 --- /dev/null +++ b/src/emucore/CartGL.cxx @@ -0,0 +1,133 @@ +//============================================================================ +// +// 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-2023 by Bradford W. Mott, Stephen Anthony +// 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. +//============================================================================ + +#include "System.hxx" +#include "CartGL.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeGL::CartridgeGL(const ByteBuffer& image, size_t size, + string_view md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) +{ + myBankShift = myRamBankShift = BANK_SHIFT; + myRamSize = RAM_SIZE; + myRamBankCount = RAM_BANKS; + + if(size == 4_KB + 2_KB) // ROM containing RAM data? + { + myInitialRAM = make_unique(2_KB); + // Copy the RAM image into a buffer for use in reset() + std::copy_n(image.get() + 4_KB, 2_KB, myInitialRAM.get()); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeGL::reset() +{ + CartridgeEnhanced::reset(); + + // Initially bank 0 is mapped into all four segments + bank(0, 0); + bank(0, 1); + bank(0, 2); + bank(0, 3); + myBankChanged = true; + + myOrgAccess = mySystem->getPageAccess(0x1fc0); + + initializeRAM(myRAM.get(), myRamSize); + if(myInitialRAM != nullptr) + { + // Copy the RAM image into my RAM buffer + std::copy_n(myInitialRAM.get(), 2_KB, myRAM.get()); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeGL::install(System& system) +{ + CartridgeEnhanced::install(system); + + System::PageAccess access(this, System::PageAccessType::READ); + + mySystem->setPageAccess(0x480, access); + mySystem->setPageAccess(0x580, access); + mySystem->setPageAccess(0x680, access); + mySystem->setPageAccess(0x880, access); + mySystem->setPageAccess(0x980, access); + mySystem->setPageAccess(0xc80, access); + mySystem->setPageAccess(0xd80, access); + + myReadOffset = myWriteOffset = 0; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeGL::checkSwitchBank(uInt16 address, uInt8) +{ + int slice = -1; + bool control = false; + + // Switch banks if necessary + switch(address & 0x1f80) + { + case 0x480: + slice = 0; + break; + case 0x580: + slice = 1; + break; + case 0x880: + slice = 2; + break; + case 0x980: + slice = 3; + break; + case 0xc80: + control = true; + break; + } + if(slice >= 0) + { + //const bool isWrite = address & 0x20; // could be checked, but not necessary for known GL ROMs + bank(address & 0xf, slice); + return true; + } + if(control) + { + myEnablePROM = (address & 0x30) == 0x30; + if(myEnablePROM) + mySystem->setPageAccess(0x1fc0, System::PageAccess(this, System::PageAccessType::READ)); + else + mySystem->setPageAccess(0x1fc0, myOrgAccess); + return true; + } + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 CartridgeGL::peek(uInt16 address) +{ + if(myEnablePROM && ((address & ADDR_MASK) >= 0x1fc0) && ((address & ADDR_MASK) <= 0x1fdf)) + { + return 0; // sufficient for PROM check + } + + checkSwitchBank(address, 0); + + return myRWPRandomValues[address & 0xFF]; +} diff --git a/src/emucore/CartGL.hxx b/src/emucore/CartGL.hxx new file mode 100644 index 000000000..77f34d1b7 --- /dev/null +++ b/src/emucore/CartGL.hxx @@ -0,0 +1,134 @@ +//============================================================================ +// +// 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-2023 by Bradford W. Mott, Stephen Anthony +// 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. +//============================================================================ + +#ifndef CARTRIDGEGL_HXX +#define CARTRIDGEGL_HXX + +#include "CartEnhanced.hxx" +#ifdef DEBUGGER_SUPPORT + #include "CartGLWidget.hxx" +#endif +#include "System.hxx" + +/** + Cartridge class used for the GameLine Master module. In this bankswitching + scheme the 2600's 4K cartridge address space is broken into four 1K segments. + The desired 1K bank of the ROM or RAM is selected as follows: + - $0480 + x: 1st 1K segment + - $0580 + x: 2nd 1K segment + - $0880 + x: 3rd 1K segment + - $0980 + x: 4th 1K segment + Where x is defined as follows: + - bits 0..3: mapped 1K bank (0..3 = ROM bank, 4..f = RAM bank) + - bit 5: 0 = read, 1 = write (RAM only) + Initially bank 0 is mapped to all four segments. + The scheme supports 4K ROM and 2K RAM. + + $0c80.. and $0d80.. control the modem (not implemented, except for PROM access). + + @author Thomas Jentzsch +*/ +class CartridgeGL : public CartridgeEnhanced +{ + friend class CartridgeGLWidget; + + public: + /** + Create a new cartridge using the specified image + + @param image Pointer to the ROM image + @param size The size of the ROM image + @param md5 The md5sum of the ROM image + @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme + */ + CartridgeGL(const ByteBuffer& image, size_t size, string_view md5, + const Settings& settings, size_t bsSize = 4_KB); + ~CartridgeGL() override = default; + + public: + /** + Reset device to its power-on state + */ + void reset() override; + + /** + 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 + */ + void install(System& system) override; + + /** + Get a descriptor for the device name (used in error checking). + + @return The name of the object + */ + string name() const override { return "CartridgeGL"; } + + #ifdef DEBUGGER_SUPPORT + /** + Get debugger widget responsible for accessing the inner workings + of the cart. + */ + CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont, + const GUI::Font& nfont, int x, int y, int w, int h) override + { + return new CartridgeGLWidget(boss, lfont, nfont, x, y, w, h, *this); + } + #endif + + public: + /** + Get the byte at the specified address. + + @return The byte at the specified address + */ + uInt8 peek(uInt16 address) override; + + private: + bool checkSwitchBank(uInt16 address, uInt8) override; + + protected: + // log(ROM bank segment size) / log(2) + static constexpr uInt16 BANK_SHIFT = 10; // = 1K = 0x0400 + + // The number of RAM banks + static constexpr uInt16 RAM_BANKS = 12; + + // RAM size + static constexpr size_t RAM_SIZE = RAM_BANKS << BANK_SHIFT; // = 12K; + + private: + // Initial RAM data from the cart (doesn't always exist) + ByteBuffer myInitialRAM{nullptr}; + + bool myEnablePROM{false}; + + System::PageAccess myOrgAccess; + + private: + // Following constructors and assignment operators not supported + CartridgeGL() = delete; + CartridgeGL(const CartridgeGL&) = delete; + CartridgeGL(CartridgeGL&&) = delete; + CartridgeGL& operator=(const CartridgeGL&) = delete; + CartridgeGL& operator=(CartridgeGL&&) = delete; +}; + +#endif diff --git a/src/emucore/module.mk b/src/emucore/module.mk index c85875e8b..be23f42ee 100644 --- a/src/emucore/module.mk +++ b/src/emucore/module.mk @@ -46,6 +46,7 @@ MODULE_OBJS := \ src/emucore/CartFA2.o \ src/emucore/CartFC.o \ src/emucore/CartFE.o \ + src/emucore/CartGL.o \ src/emucore/CartMDM.o \ src/emucore/CartMVC.o \ src/emucore/CartSB.o \ diff --git a/src/os/windows/Stella.vcxproj b/src/os/windows/Stella.vcxproj index 1b88ac41f..05ab4683f 100755 --- a/src/os/windows/Stella.vcxproj +++ b/src/os/windows/Stella.vcxproj @@ -911,6 +911,7 @@ true + true @@ -996,6 +997,7 @@ + @@ -2223,6 +2225,7 @@ true + true @@ -2319,6 +2322,7 @@ + diff --git a/src/os/windows/Stella.vcxproj.filters b/src/os/windows/Stella.vcxproj.filters index 071b641e8..7d3849df5 100644 --- a/src/os/windows/Stella.vcxproj.filters +++ b/src/os/windows/Stella.vcxproj.filters @@ -1197,6 +1197,12 @@ Source Files\debugger + + Source Files\emucore + + + Source Files\debugger\gui + @@ -2441,6 +2447,12 @@ Header Files\debugger + + Header Files\emucore + + + Header Files\debugger\gui + diff --git a/test/roms/bankswitching/GL/GameLine Master Module ROM (1983) (Control Video Corporation) (fixed V2).bin b/test/roms/bankswitching/GL/GameLine Master Module ROM (1983) (Control Video Corporation) (fixed V2).bin new file mode 100644 index 000000000..d9ad832be Binary files /dev/null and b/test/roms/bankswitching/GL/GameLine Master Module ROM (1983) (Control Video Corporation) (fixed V2).bin differ diff --git a/test/roms/bankswitching/GL/download_rom.bin b/test/roms/bankswitching/GL/download_rom.bin new file mode 100644 index 000000000..e5b1c3c7d Binary files /dev/null and b/test/roms/bankswitching/GL/download_rom.bin differ diff --git a/test/roms/bankswitching/GL/ramdata_rom.bin b/test/roms/bankswitching/GL/ramdata_rom.bin new file mode 100644 index 000000000..73b1e6262 Binary files /dev/null and b/test/roms/bankswitching/GL/ramdata_rom.bin differ