//============================================================================ // // 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-2016 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. // // $Id$ //============================================================================ #include "System.hxx" #include "CartFE.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeFE::CartridgeFE(const uInt8* image, uInt32 size, const Settings& settings) : Cartridge(settings), myLastAddress1(0), myLastAddress2(0), myLastAddressChanged(false) { // Copy the ROM image into my buffer memcpy(myImage, image, std::min(8192u, size)); // We use System::PageAccess.codeAccessBase, but don't allow its use // through a pointer, since the address space of FE carts can change // at the instruction level, and PageAccess is normally defined at an // interval of 64 bytes // // Instead, access will be through the getAccessFlags and setAccessFlags // methods below createCodeAccessBase(8192); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeFE::reset() { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeFE::install(System& system) { mySystem = &system; // Map all of the accesses to call peek and poke System::PageAccess access(this, System::PA_READ); for(uInt32 i = 0x1000; i < 0x2000; i += (1 << System::PAGE_SHIFT)) mySystem->setPageAccess(i >> System::PAGE_SHIFT, access); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeFE::peek(uInt16 address) { // The bank is determined by A13 of the processor // We keep track of the two most recent accesses to determine which bank // we're in, and when the values actually changed myLastAddress2 = myLastAddress1; myLastAddress1 = address; myLastAddressChanged = true; return myImage[(address & 0x0FFF) + (((address & 0x2000) == 0) ? 4096 : 0)]; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeFE::poke(uInt16, uInt8) { return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeFE::getAccessFlags(uInt16 address) const { return myCodeAccessBase[(address & 0x0FFF) + (((address & 0x2000) == 0) ? 4096 : 0)]; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeFE::setAccessFlags(uInt16 address, uInt8 flags) { myCodeAccessBase[(address & 0x0FFF) + (((address & 0x2000) == 0) ? 4096 : 0)] |= flags; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt16 CartridgeFE::getBank() const { // The current bank depends on the last address accessed return ((myLastAddress1 & 0x2000) == 0) ? 1 : 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt16 CartridgeFE::bankCount() const { return 2; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeFE::bankChanged() { if(myLastAddressChanged) { // A bankswitch occurs when the addresses transition from state to another myBankChanged = ((myLastAddress1 & 0x2000) == 0) != ((myLastAddress2 & 0x2000) == 0); myLastAddressChanged = false; } else myBankChanged = false; // In any event, let the base class know about it return Cartridge::bankChanged(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeFE::patch(uInt16 address, uInt8 value) { myImage[(address & 0x0FFF) + (((address & 0x2000) == 0) ? 4096 : 0)] = value; return myBankChanged = true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const uInt8* CartridgeFE::getImage(int& size) const { size = 8192; return myImage; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeFE::save(Serializer& out) const { try { out.putString(name()); out.putShort(myLastAddress1); out.putShort(myLastAddress2); } catch(...) { cerr << "ERROR: CartridgeFE::save" << endl; return false; } return true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeFE::load(Serializer& in) { try { if(in.getString() != name()) return false; myLastAddress1 = in.getShort(); myLastAddress2 = in.getShort(); } catch(...) { cerr << "ERROR: CartridgeF8SC::load" << endl; return false; } return true; }