From 12fffa16902de549e83d04f082e2baaf8bb541af Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 2 Nov 2019 13:23:23 +0100 Subject: [PATCH] add missing files --- src/debugger/gui/CartFCWidget.cxx | 96 +++++++++++++++ src/debugger/gui/CartFCWidget.hxx | 55 +++++++++ src/emucore/CartFC.cxx | 188 ++++++++++++++++++++++++++++++ src/emucore/CartFC.hxx | 184 +++++++++++++++++++++++++++++ 4 files changed, 523 insertions(+) create mode 100644 src/debugger/gui/CartFCWidget.cxx create mode 100644 src/debugger/gui/CartFCWidget.hxx create mode 100644 src/emucore/CartFC.cxx create mode 100644 src/emucore/CartFC.hxx diff --git a/src/debugger/gui/CartFCWidget.cxx b/src/debugger/gui/CartFCWidget.cxx new file mode 100644 index 000000000..22e8662c9 --- /dev/null +++ b/src/debugger/gui/CartFCWidget.cxx @@ -0,0 +1,96 @@ +//============================================================================ +// +// 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-2019 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 "CartFC.hxx" +#include "PopUpWidget.hxx" +#include "CartFCWidget.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeFCWidget::CartridgeFCWidget( + GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, + int x, int y, int w, int h, CartridgeFC& cart) + : CartDebugWidget(boss, lfont, nfont, x, y, w, h), + myCart(cart) +{ + uInt16 size = cart.bankCount() * 4096; + + ostringstream info; + info << "FC cartridge, up to eight 4K banks\n" + << "Startup bank = " << cart.startBank() << " or undetermined\n"; + + // Eventually, we should query this from the debugger/disassembler + info << "Bank selected by hotspots\n" + << " $FFF8 (defines low 2 bits)\n" + << " $FFF9 (defines high bits)\n" + << " $FFFC (triggers bank switch)"; + + int xpos = 2, + ypos = addBaseInformation(size, "Amiga Corp.", info.str()) + myLineHeight; + + VariantList items; + for (uInt16 i = 0; i < cart.bankCount(); ++i) + VarList::push_back(items, Variant(i).toString() + + " ($FFF8 = " + Variant(i & 0b11).toString() + + "/$FFF9 = " + Variant(i >> 2).toString() +")"); + + + myBank = + new PopUpWidget(boss, _font, xpos, ypos - 2, _font.getStringWidth("7 ($FFF8 = 3/$FFF9 = 1)"), + myLineHeight, items, "Set bank ", + 0, kBankChanged); + myBank->setTarget(this); + addFocusWidget(myBank); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeFCWidget::loadConfig() +{ + Debugger& dbg = instance().debugger(); + CartDebug& cart = dbg.cartDebug(); + const CartState& state = static_cast(cart.getState()); + const CartState& oldstate = static_cast(cart.getOldState()); + + myBank->setSelectedIndex(myCart.getBank(), state.bank != oldstate.bank); + + CartDebugWidget::loadConfig(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeFCWidget::handleCommand(CommandSender* sender, + int cmd, int data, int id) +{ + if (cmd == kBankChanged) + { + myCart.unlockBank(); + myCart.bank(myBank->getSelected()); + myCart.lockBank(); + invalidate(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeFCWidget::bankState() +{ + ostringstream& buf = buffer(); + uInt16 bank = myCart.getBank(); + + buf << "Bank = #" << std::dec << bank + << ", hotspots $FFF8 = " << (bank & 0b11) + << "/$FF99 = " << (bank >> 2); + + return buf.str(); +} diff --git a/src/debugger/gui/CartFCWidget.hxx b/src/debugger/gui/CartFCWidget.hxx new file mode 100644 index 000000000..b91f6327b --- /dev/null +++ b/src/debugger/gui/CartFCWidget.hxx @@ -0,0 +1,55 @@ +//============================================================================ +// +// 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-2019 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 CARTRIDGEFC_WIDGET_HXX +#define CARTRIDGEFC_WIDGET_HXX + +class CartridgeFC; +class PopUpWidget; + +#include "CartDebugWidget.hxx" + +class CartridgeFCWidget : public CartDebugWidget +{ +public: + CartridgeFCWidget(GuiObject* boss, const GUI::Font& lfont, + const GUI::Font& nfont, + int x, int y, int w, int h, + CartridgeFC& cart); + virtual ~CartridgeFCWidget() = default; + +private: + CartridgeFC& myCart; + PopUpWidget* myBank; + + enum { kBankChanged = 'bkCH' }; + +private: + void loadConfig() override; + void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + + string bankState() override; + + // Following constructors and assignment operators not supported + CartridgeFCWidget() = delete; + CartridgeFCWidget(const CartridgeFCWidget&) = delete; + CartridgeFCWidget(CartridgeFCWidget&&) = delete; + CartridgeFCWidget& operator=(const CartridgeFCWidget&) = delete; + CartridgeFCWidget& operator=(CartridgeFCWidget&&) = delete; +}; + +#endif diff --git a/src/emucore/CartFC.cxx b/src/emucore/CartFC.cxx new file mode 100644 index 000000000..b2053ce8c --- /dev/null +++ b/src/emucore/CartFC.cxx @@ -0,0 +1,188 @@ +//============================================================================ +// +// 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-2019 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 "CartFC.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeFC::CartridgeFC(const ByteBuffer& image, size_t size, + const string& md5, const Settings& settings) + : Cartridge(settings, md5), + myBankOffset(0), + myCurrentBank(0), + mySize(size), + myTargetBank(0) +{ + // Copy the ROM image into my buffer + std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); + createCodeAccessBase(myImage.size()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeFC::reset() +{ + initializeStartBank(0); + myTargetBank = 0; + + // Upon reset we switch to the reset bank + bank(startBank()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeFC::install(System& system) +{ + mySystem = &system; + + // Install pages for the startup bank + bank(startBank()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 CartridgeFC::peek(uInt16 address) +{ + address &= 0x0FFF; + + // Switch banks if necessary + switch (address) + { + case 0x0FFC: + // Trigger the bank switch + bank(myTargetBank); + break; + + default: + break; + } + + return myImage[myBankOffset + address]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeFC::poke(uInt16 address, uInt8 value) +{ + address &= 0x0FFF; + + // Switch banks if necessary + switch (address) + { + case 0x0FF8: + // Set the two lowest bits of target 4k bank + myTargetBank = value & 0b11; + break; + + case 0x0FF9: + // Set the high bits of target 4k bank + myTargetBank += value << 2; + myTargetBank %= bankCount(); + break; + + default: + break; + } + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeFC::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.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; + mySystem->setPageAccess(addr, access); + } + + // Setup the page access methods for the current bank + for (uInt16 addr = 0x1000; addr < (0x1FF8U & ~System::PAGE_MASK); + addr += System::PAGE_SIZE) + { + access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; + access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; + mySystem->setPageAccess(addr, access); + } + myCurrentBank = myTargetBank; + return myBankChanged = true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt16 CartridgeFC::getBank(uInt16) const +{ + return myBankOffset >> 12; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt16 CartridgeFC::bankCount() const +{ + return uInt16(mySize >> 12); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeFC::patch(uInt16 address, uInt8 value) +{ + myImage[myBankOffset + (address & 0x0FFF)] = value; + return myBankChanged = true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const uInt8* CartridgeFC::getImage(size_t& size) const +{ + size = mySize; + return myImage.data(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeFC::save(Serializer& out) const +{ + try + { + out.putShort(myBankOffset); + } + catch (...) + { + cerr << "ERROR: CartridgeFC::save" << endl; + return false; + } + + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeFC::load(Serializer& in) +{ + try + { + myBankOffset = in.getShort(); + } + catch (...) + { + cerr << "ERROR: CartridgeFC::load" << endl; + return false; + } + + // Remember what bank we were in + bank(myBankOffset >> 12); + + return true; +} diff --git a/src/emucore/CartFC.hxx b/src/emucore/CartFC.hxx new file mode 100644 index 000000000..6869d7915 --- /dev/null +++ b/src/emucore/CartFC.hxx @@ -0,0 +1,184 @@ +//============================================================================ +// +// 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-2019 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 CARTRIDGEFC_HXX +#define CARTRIDGEFC_HXX + +class System; + +#include "bspf.hxx" +#include "Cart.hxx" +#ifdef DEBUGGER_SUPPORT +#include "CartFCWidget.hxx" +#endif + +/** + Cartridge class used for Amiga's 32K Power Play Arcade Video Game Album. + There are eight 4K banks, writing to $1FF8 definies the two lowest bits + of the wanted bank, writeing to $1FF9 defines the high bits. Reading from + $1FFC triggers the bank switching + + @author Thomas Jentzsch +*/ +class CartridgeFC : public Cartridge +{ + friend class CartridgeFCWidget; + +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) + */ + CartridgeFC(const ByteBuffer& image, size_t size, const string& md5, + const Settings& settings); + virtual ~CartridgeFC() = 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; + + /** + Install pages for the specified bank in the system. + + @param bank The bank that should be installed in the system + */ + bool bank(uInt16 bank) 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 bankCount() const override; + + /** + 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 + */ + 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. + + @param out The Serializer object to use + @return False on any errors, else true + */ + bool save(Serializer& out) const override; + + /** + 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 + */ + bool load(Serializer& in) override; + + /** + Get a descriptor for the device name (used in error checking). + + @return The name of the object + */ + string name() const override { return "CartridgeFC"; } + +#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 CartridgeFCWidget(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; + + /** + 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 + @return True if the poke changed the device address space, else false + */ + bool poke(uInt16 address, uInt8 value) override; + +private: + // The 32K ROM image of the cartridge + std::array myImage; + + // Size of the ROM image + size_t mySize; + + + // Indicates the offset into the ROM image (aligns to current bank) + uInt16 myBankOffset; + + // Indicates which bank is currently active for the first segment + uInt16 myCurrentBank; + + + // Target bank defined by writing to $1FF8/9 + uInt16 myTargetBank; + +private: + // Following constructors and assignment operators not supported + CartridgeFC() = delete; + CartridgeFC(const CartridgeFC&) = delete; + CartridgeFC(CartridgeFC&&) = delete; + CartridgeFC& operator=(const CartridgeFC&) = delete; + CartridgeFC& operator=(CartridgeFC&&) = delete; +}; + +#endif +