added 0FA0 (Mania) bankswitching

modified UA bankswitching accordingly
This commit is contained in:
Thomas Jentzsch 2022-04-09 10:26:22 +02:00
parent 3b9184ec5f
commit 544f662f1d
27 changed files with 409 additions and 31 deletions

View File

@ -39,6 +39,8 @@
* Enhanced support for CDFJ+ bankswitching type. * Enhanced support for CDFJ+ bankswitching type.
* Added 0FA0 bankswitching for Mania ROMs
* Added ARM chip auto detection. * Added ARM chip auto detection.
* Fixed Stella crash due to invalid ZIP files. * Fixed Stella crash due to invalid ZIP files.

View File

@ -21,7 +21,7 @@
<img src="graphics/stella_icon.png"> <img src="graphics/stella_icon.png">
<h2><b>A multi-platform Atari 2600 VCS emulator</b></h2> <h2><b>A multi-platform Atari 2600 VCS emulator</b></h2>
<h4><b>Release 6.6</b></h4> <h4><b>Release 6.7</b></h4>
<br> <br>
<h2><b>User's Guide</b></h2> <h2><b>User's Guide</b></h2>
@ -354,7 +354,6 @@
the following:</p> the following:</p>
<ul> <ul>
<li>i386 or x86_64 class machine, with 32 or 64-bit distribution</li> <li>i386 or x86_64 class machine, with 32 or 64-bit distribution</li>
<li>OpenGL capable video card</li>
<li>Other architectures (MIPS, PPC, PPC64, etc.) have been confirmed to work, <li>Other architectures (MIPS, PPC, PPC64, etc.) have been confirmed to work,
but aren't as well tested as i386/x86_64</li> but aren't as well tested as i386/x86_64</li>
<li>GNU g++ v/7 or Clang v/5 (with C++17 support) and the make utility are required for compiling the Stella source code</li> <li>GNU g++ v/7 or Clang v/5 (with C++17 support) and the make utility are required for compiling the Stella source code</li>
@ -368,7 +367,6 @@
<ul> <ul>
<li>macOS 10.7 or above</li> <li>macOS 10.7 or above</li>
<li>64-bit Intel processor</li> <li>64-bit Intel processor</li>
<li>OpenGL capable video card</li>
<li>Xcode 8.0 is required to compile the Stella source code</li> <li>Xcode 8.0 is required to compile the Stella source code</li>
</ul> </ul>
@ -379,7 +377,6 @@
with the following:</p> with the following:</p>
<ul> <ul>
<li>Direct3D or OpenGL capable video card</li>
<li>Visual C++ 2017/2019 Community is required to compile the Stella source code</li> <li>Visual C++ 2017/2019 Community is required to compile the Stella source code</li>
</ul> </ul>
@ -2759,7 +2756,7 @@
</tr> </tr>
<tr> <tr>
<td><pre>-video &lt;direct3d|opengl|opengles2|opengles|software&gt;</pre></td> <td><pre>-video &lt;direct3d|metal|opengl|opengles2|opengles|software&gt;</pre></td>
<td>Use the given rendering backend (where applicable); default is the best available <td>Use the given rendering backend (where applicable); default is the best available
mode detected.</td> mode detected.</td>
</tr> </tr>
@ -5064,7 +5061,8 @@ Ms Pac-Man (Stella extended codes):
are not fully supported in the debugger. are not fully supported in the debugger.
<table cellpadding="2" border="1"> <table cellpadding="2" border="1">
<tr><th>&nbsp;Type&nbsp;</th><th>Description</th><th>File Extension<br>(to force type)</th></tr> <tr><th>&nbsp;Type&nbsp;</th><th>Description</th><th>File Extension<br>(to force type)</th></tr>
<tr><td>0840 </td><td>8K ECONObanking </td><td>.084, .0840</td></tr> <tr><td>0840 </td><td>8K ECONObanking</td><td>.084, .0840</td></tr>
<tr><td>0FA0 </td><td>8K Mania</td><td>.0FA, .0FA0</td></tr>
<tr><td>2IN1 &#185;</td><td>4-64K Multicart (2 games)</td><td>.2N1 </td></tr> <tr><td>2IN1 &#185;</td><td>4-64K Multicart (2 games)</td><td>.2N1 </td></tr>
<tr><td>4IN1 &#185;</td><td>8-64K Multicart (4 games)</td><td>.4N1 </td></tr> <tr><td>4IN1 &#185;</td><td>8-64K Multicart (4 games)</td><td>.4N1 </td></tr>
<tr><td>8IN1 &#185;</td><td>16-64K Multicart (8 games)</td><td>.8N1 </td></tr> <tr><td>8IN1 &#185;</td><td>16-64K Multicart (8 games)</td><td>.8N1 </td></tr>

View File

@ -48,8 +48,7 @@ string CartridgeUAWidget::hotspotStr(int bank, int, bool prefix)
const uInt16 hotspot = myCart.hotspot() + (bank ^ (mySwappedHotspots ? 1 : 0)) * myHotspotDelta; const uInt16 hotspot = myCart.hotspot() + (bank ^ (mySwappedHotspots ? 1 : 0)) * myHotspotDelta;
info << "(" << (prefix ? "hotspot " : "") info << "(" << (prefix ? "hotspot " : "")
<< "$" << Common::Base::HEX1 << hotspot << ", $" << (hotspot | 0x80) << "$" << Common::Base::HEX1 << hotspot << ", $" << (hotspot | 0x80) << ")";
<< ", $" << (hotspot | 0xf80) << ")";
return info.str(); return info.str();
} }

View File

@ -7,6 +7,7 @@ MODULE_OBJS := \
src/debugger/gui/AudioWidget.o \ src/debugger/gui/AudioWidget.o \
src/debugger/gui/BoosterWidget.o \ src/debugger/gui/BoosterWidget.o \
src/debugger/gui/Cart0840Widget.o \ src/debugger/gui/Cart0840Widget.o \
src/debugger/gui/Cart0FA0Widget.o \
src/debugger/gui/Cart2KWidget.o \ src/debugger/gui/Cart2KWidget.o \
src/debugger/gui/Cart3EPlusWidget.o \ src/debugger/gui/Cart3EPlusWidget.o \
src/debugger/gui/Cart3EWidget.o \ src/debugger/gui/Cart3EWidget.o \

View File

@ -96,6 +96,7 @@ const std::array<Bankswitch::Description, static_cast<int>(Bankswitch::Type::Num
Bankswitch::BSList = {{ Bankswitch::BSList = {{
{ "AUTO" , "Auto-detect" }, { "AUTO" , "Auto-detect" },
{ "0840" , "0840 (8K ECONObank)" }, { "0840" , "0840 (8K ECONObank)" },
{ "0FA0" , "0FA0 (8K Mania)" },
{ "2IN1" , "2IN1 Multicart (4-64K)" }, { "2IN1" , "2IN1 Multicart (4-64K)" },
{ "4IN1" , "4IN1 Multicart (8-64K)" }, { "4IN1" , "4IN1 Multicart (8-64K)" },
{ "8IN1" , "8IN1 Multicart (16-64K)" }, { "8IN1" , "8IN1 Multicart (16-64K)" },
@ -167,6 +168,8 @@ Bankswitch::ExtensionMap Bankswitch::ourExtensions = {
// All bankswitch types (those that UnoCart and HarmonyCart support have the same name) // All bankswitch types (those that UnoCart and HarmonyCart support have the same name)
{ "084" , Bankswitch::Type::_0840 }, { "084" , Bankswitch::Type::_0840 },
{ "0840" , Bankswitch::Type::_0840 }, { "0840" , Bankswitch::Type::_0840 },
{ "0FA" , Bankswitch::Type::_0FA0 },
{ "0FA0" , Bankswitch::Type::_0FA0 },
{ "2N1" , Bankswitch::Type::_2IN1 }, { "2N1" , Bankswitch::Type::_2IN1 },
{ "4N1" , Bankswitch::Type::_4IN1 }, { "4N1" , Bankswitch::Type::_4IN1 },
{ "8N1" , Bankswitch::Type::_8IN1 }, { "8N1" , Bankswitch::Type::_8IN1 },
@ -241,6 +244,7 @@ Bankswitch::ExtensionMap Bankswitch::ourExtensions = {
Bankswitch::NameToTypeMap Bankswitch::ourNameToTypes = { Bankswitch::NameToTypeMap Bankswitch::ourNameToTypes = {
{ "AUTO" , Bankswitch::Type::_AUTO }, { "AUTO" , Bankswitch::Type::_AUTO },
{ "0840" , Bankswitch::Type::_0840 }, { "0840" , Bankswitch::Type::_0840 },
{ "0FA0" , Bankswitch::Type::_0FA0 },
{ "2IN1" , Bankswitch::Type::_2IN1 }, { "2IN1" , Bankswitch::Type::_2IN1 },
{ "4IN1" , Bankswitch::Type::_4IN1 }, { "4IN1" , Bankswitch::Type::_4IN1 },
{ "8IN1" , Bankswitch::Type::_8IN1 }, { "8IN1" , Bankswitch::Type::_8IN1 },

View File

@ -38,14 +38,13 @@ class Bankswitch
public: public:
// Currently supported bankswitch schemes // Currently supported bankswitch schemes
enum class Type { enum class Type {
_AUTO, _0840, _2IN1, _4IN1, _8IN1, _16IN1, _32IN1, _AUTO, _0840, _0FA0, _2IN1, _4IN1, _8IN1, _16IN1, _32IN1,
_64IN1, _128IN1, _2K, _3E, _3EX, _3EP, _3F, _64IN1, _128IN1, _2K, _3E, _3EX, _3EP, _3F, _4A50,
_4A50, _4K, _4KSC, _AR, _BF, _BFSC, _BUS, _4K, _4KSC, _AR, _BF, _BFSC, _BUS, _CDF, _CM,
_CDF, _CM, _CTY, _CV, _DF, _DFSC, _DPC, _CTY, _CV, _DF, _DFSC, _DPC, _DPCP, _E0, _E7,
_DPCP, _E0, _E7, _EF, _EFSC, _F0, _F4, _EF, _EFSC, _F0, _F4, _F4SC, _F6, _F6SC, _F8,
_F4SC, _F6, _F6SC, _F8, _F8SC, _FA, _FA2, _F8SC, _FA, _FA2, _FC, _FE, _MDM, _MVC, _SB,
_FC, _FE, _MDM, _MVC, _SB, _TVBOY, _UA, _TVBOY, _UA, _UASW, _WD, _WDSW, _X07,
_UASW, _WD, _WDSW, _X07,
#ifdef CUSTOM_ARM #ifdef CUSTOM_ARM
_CUSTOM, _CUSTOM,
#endif #endif

104
src/emucore/Cart0FA0.cxx Normal file
View File

@ -0,0 +1,104 @@
//============================================================================
//
// 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-2022 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 "Cart0FA0.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge0FA0::Cartridge0FA0(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings, 8_KB)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Cartridge0FA0::install(System& system)
{
CartridgeEnhanced::install(system);
// Get the page accessing methods for the hot spots since they overlap
// areas within the TIA we'll need to forward requests to the TIA
myHotSpotPageAccess = mySystem->getPageAccess(0x06a0);
// Set the page accessing methods for the hot spots
const System::PageAccess access(this, System::PageAccessType::READ);
// Map all potential addresses
// - A11 and A8 are not connected to RIOT
// - A10, A9 and A7 are the fixed part of the hotspot address
// - A6 and A5 determine bank
for(uInt16 a11 = 0; a11 <= 1; ++a11)
for(uInt16 a8 = 0; a8 <= 1; ++a8)
{
const uInt16 addr = (a11 << 11) + (a8 << 8);
mySystem->setPageAccess(0x06a0 | addr, access);
mySystem->setPageAccess(0x06c0 | addr, access);
}
// Install pages for the startup bank
bank(startBank());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Cartridge0FA0::checkSwitchBank(uInt16 address, uInt8)
{
// Switch banks if necessary
switch(address & 0x16e0)
{
case 0x06a0:
// Set the current bank to the lower 4k bank
bank(0);
return true;
case 0x06c0:
// Set the current bank to the upper 4k bank
bank(1);
return true;
default:
break;
}
return false;
}
//// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 Cartridge0FA0::peek(uInt16 address)
{
address &= myBankMask;
checkSwitchBank(address);
// Because of the way accessing is set up, we will only get here
// when doing a TIA read
return myHotSpotPageAccess.device->peek(address);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Cartridge0FA0::poke(uInt16 address, uInt8 value)
{
address &= myBankMask;
checkSwitchBank(address);
// Because of the way accessing is set up, we will may get here by
// doing a write to TIA or cart; we ignore the cart write
if (!(address & 0x1000))
{
myHotSpotPageAccess.device->poke(address, value);
}
return false;
}

127
src/emucore/Cart0FA0.hxx Normal file
View File

@ -0,0 +1,127 @@
//============================================================================
//
// 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-2022 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 CARTRIDGEBR_HXX
#define CARTRIDGEBR_HXX
#include "bspf.hxx"
#include "CartEnhanced.hxx"
#include "System.hxx"
#ifdef DEBUGGER_SUPPORT
#include "Cart0FA0Widget.hxx"
#endif
/**
Cartridge class used for some brazilian 8K bankswitched games. There
are two 4K banks, which are switched by accessing
(address & $16A0) = $06a0 (bank 0) and = $06c0 (bank 1).
Actual addresses used by these carts are e.g. $0FA0, $0FC0 and $EFC0.
The code accepts further potential hotspot addresses.
@author Thomas Jentzsch
*/
class Cartridge0FA0 : public CartridgeEnhanced
{
friend class Cartridge0FA0Widget;
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)
*/
Cartridge0FA0(const ByteBuffer& image, size_t size, const string& md5,
const Settings& settings);
~Cartridge0FA0() override = default;
public:
/**
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 "Cartridge0FA0";
}
#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 Cartridge0FA0Widget(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:
/**
Checks if startup bank randomization is enabled. For this scheme,
randomization is not supported (see above).
*/
bool randomStartBank() const override { return false; }
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
uInt16 hotspot() const override { return 0x06a0; }
uInt16 getStartBank() const override { return 1; }
private:
// Previous Device's page access
System::PageAccess myHotSpotPageAccess;
private:
// Following constructors and assignment operators not supported
Cartridge0FA0() = delete;
Cartridge0FA0(const Cartridge0FA0&) = delete;
Cartridge0FA0(Cartridge0FA0&&) = delete;
Cartridge0FA0& operator=(const Cartridge0FA0&) = delete;
Cartridge0FA0& operator=(Cartridge0FA0&&) = delete;
};
#endif

View File

@ -0,0 +1,53 @@
//============================================================================
//
// 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-2022 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 "Cart0FA0.hxx"
#include "Cart0FA0Widget.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge0FA0Widget::Cartridge0FA0Widget(
GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont,
int x, int y, int w, int h, Cartridge0FA0& cart)
: CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart)
{
myHotspotDelta = 0x20;
initialize();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Cartridge0FA0Widget::description()
{
ostringstream info;
info << "8K BR cartridge, two 4K banks\n"
<< CartridgeEnhancedWidget::description();
return info.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Cartridge0FA0Widget::hotspotStr(int bank, int, bool prefix)
{
ostringstream info;
const uInt16 hotspot = myCart.hotspot() + bank * myHotspotDelta;
info << "(" << (prefix ? "hotspot " : "")
<< "$" << Common::Base::HEX1 << hotspot
<< ", $" << (hotspot | 0xf80) << ")";
return info.str();
}

View File

@ -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-2022 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 CARTRIDGEBR_WIDGET_HXX
#define CARTRIDGEBR_WIDGET_HXX
class Cartridge0FA0;
#include "CartEnhancedWidget.hxx"
class Cartridge0FA0Widget : public CartridgeEnhancedWidget
{
public:
Cartridge0FA0Widget(GuiObject* boss, const GUI::Font& lfont,
const GUI::Font& nfont,
int x, int y, int w, int h,
Cartridge0FA0& cart);
~Cartridge0FA0Widget() override = default;
private:
string manufacturer() override { return "Mania"; }
string description() override;
string hotspotStr(int bank, int seg, bool prefix = false) override;
private:
// Following constructors and assignment operators not supported
Cartridge0FA0Widget() = delete;
Cartridge0FA0Widget(const Cartridge0FA0Widget&) = delete;
Cartridge0FA0Widget(Cartridge0FA0Widget&&) = delete;
Cartridge0FA0Widget& operator=(const Cartridge0FA0Widget&) = delete;
Cartridge0FA0Widget& operator=(Cartridge0FA0Widget&&) = delete;
};
#endif

View File

@ -18,6 +18,7 @@
#include "bspf.hxx" #include "bspf.hxx"
#include "Cart.hxx" #include "Cart.hxx"
#include "Cart0840.hxx" #include "Cart0840.hxx"
#include "Cart0FA0.hxx"
#include "Cart2K.hxx" #include "Cart2K.hxx"
#include "Cart3E.hxx" #include "Cart3E.hxx"
#include "Cart3EX.hxx" #include "Cart3EX.hxx"
@ -245,7 +246,7 @@ CartCreator::createFromMultiCart(const ByteBuffer& image, size_t& size,
type = Bankswitch::Type::_2K; type = Bankswitch::Type::_2K;
else if(size == 4_KB) else if(size == 4_KB)
type = Bankswitch::Type::_4K; type = Bankswitch::Type::_4K;
else if(size == 8_KB || size == 16_KB || size == 32_KB || size == 64_KB) else if(size == 8_KB || size == 16_KB || size == 32_KB || size == 64_KB || size == 128_KB)
type = CartDetector::autodetectType(slice, size); type = CartDetector::autodetectType(slice, size);
else /* default */ else /* default */
type = Bankswitch::Type::_4K; type = Bankswitch::Type::_4K;
@ -263,6 +264,8 @@ CartCreator::createFromImage(const ByteBuffer& image, size_t size, Bankswitch::T
{ {
case Bankswitch::Type::_0840: case Bankswitch::Type::_0840:
return make_unique<Cartridge0840>(image, size, md5, settings); return make_unique<Cartridge0840>(image, size, md5, settings);
case Bankswitch::Type::_0FA0:
return make_unique<Cartridge0FA0>(image, size, md5, settings);
case Bankswitch::Type::_2K: case Bankswitch::Type::_2K:
return make_unique<Cartridge2K>(image, size, md5, settings); return make_unique<Cartridge2K>(image, size, md5, settings);
case Bankswitch::Type::_3E: case Bankswitch::Type::_3E:

View File

@ -75,6 +75,8 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si
type = Bankswitch::Type::_3F; type = Bankswitch::Type::_3F;
else if(isProbablyUA(image, size)) else if(isProbablyUA(image, size))
type = Bankswitch::Type::_UA; type = Bankswitch::Type::_UA;
else if(isProbably0FA0(image, size))
type = Bankswitch::Type::_0FA0;
else if(isProbablyFE(image, size) && !f8) else if(isProbablyFE(image, size) && !f8)
type = Bankswitch::Type::_FE; type = Bankswitch::Type::_FE;
else if(isProbably0840(image, size)) else if(isProbably0840(image, size))
@ -344,6 +346,25 @@ bool CartDetector::isProbably0840(const ByteBuffer& image, size_t size)
return false; return false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbably0FA0(const ByteBuffer& image, size_t size)
{
// Other Brazilian (Atari Mania) ROM's bankswitching switches to bank 1 by
// accessing address 0xFC0 using 'BIT $FC0', 'BIT $FC0' or 'STA $FC0'
// Also a game (Motocross) using 'BIT $EFC0' has been found
static constexpr uInt8 signature[4][3] = {
{ 0x2C, 0xC0, 0x0F }, // BIT $FC0 (H.E.R.O., Kung-Fu Master)
{ 0x8D, 0xC0, 0x0F }, // STA $FC0 (Pole Position, Subterranea)
{ 0xAD, 0xC0, 0x0F }, // LDA $FC0 (Front Line, Zaxxon)
{ 0x2C, 0xC0, 0xEF } // BIT $EFC0 (Motocross)
};
for(uInt32 i = 0; i < 4; ++i)
if(searchForBytes(image, size, signature[i], 3))
return true;
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbably3E(const ByteBuffer& image, size_t size) bool CartDetector::isProbably3E(const ByteBuffer& image, size_t size)
{ {
@ -755,25 +776,18 @@ bool CartDetector::isProbablyTVBoy(const ByteBuffer& image, size_t size)
bool CartDetector::isProbablyUA(const ByteBuffer& image, size_t size) bool CartDetector::isProbablyUA(const ByteBuffer& image, size_t size)
{ {
// UA cart bankswitching switches to bank 1 by accessing address 0x240 // UA cart bankswitching switches to bank 1 by accessing address 0x240
// using 'STA $240' or 'LDA $240' // using 'STA $240' or 'LDA $240'.
// Similar Brazilian (Digivison) cart bankswitching switches to bank 1 by accessing address 0x2C0 // Brazilian (Digivison) cart bankswitching switches to bank 1 by accessing address 0x2C0
// using 'BIT $2C0', 'STA $2C0' or 'LDA $2C0' // using 'BIT $2C0', 'STA $2C0' or 'LDA $2C0'
// Other Brazilian (Atari Mania) ROM's bankswitching switches to bank 1 by accessing address 0xFC0 static constexpr uInt8 signature[6][3] = {
// using 'BIT $FA0', 'BIT $FC0' or 'STA $FC0'
// Also a game (Motocross) using 'BIT $EFC0' has been found
static constexpr uInt8 signature[10][3] = {
{ 0x8D, 0x40, 0x02 }, // STA $240 (Funky Fish, Pleiades) { 0x8D, 0x40, 0x02 }, // STA $240 (Funky Fish, Pleiades)
{ 0xAD, 0x40, 0x02 }, // LDA $240 (???) { 0xAD, 0x40, 0x02 }, // LDA $240 (???)
{ 0xBD, 0x1F, 0x02 }, // LDA $21F,X (Gingerbread Man) { 0xBD, 0x1F, 0x02 }, // LDA $21F,X (Gingerbread Man)
{ 0x2C, 0xC0, 0x02 }, // BIT $2C0 (Time Pilot) { 0x2C, 0xC0, 0x02 }, // BIT $2C0 (Time Pilot)
{ 0x8D, 0xC0, 0x02 }, // STA $2C0 (Fathom, Vanguard) { 0x8D, 0xC0, 0x02 }, // STA $2C0 (Fathom, Vanguard)
{ 0xAD, 0xC0, 0x02 }, // LDA $2C0 (Mickey) { 0xAD, 0xC0, 0x02 }, // LDA $2C0 (Mickey)
{ 0x2C, 0xC0, 0x0F }, // BIT $FC0 (H.E.R.O., Kung-Fu Master)
{ 0x8D, 0xC0, 0x0F }, // STA $FC0 (Pole Position, Subterranea)
{ 0xAD, 0xC0, 0x0F }, // LDA $FC0 (Front Line, Zaxxon)
{ 0x2C, 0xC0, 0xEF } // BIT $EFC0 (Motocross)
}; };
for(uInt32 i = 0; i < 10; ++i) for(uInt32 i = 0; i < 6; ++i)
if(searchForBytes(image, size, signature[i], 3)) if(searchForBytes(image, size, signature[i], 3))
return true; return true;

View File

@ -91,6 +91,11 @@ class CartDetector
*/ */
static bool isProbably0840(const ByteBuffer& image, size_t size); static bool isProbably0840(const ByteBuffer& image, size_t size);
/**
Returns true if the image is probably a BRazilian bankswitching cartridge
*/
static bool isProbably0FA0(const ByteBuffer& image, size_t size);
/** /**
Returns true if the image is probably a 3E bankswitching cartridge Returns true if the image is probably a 3E bankswitching cartridge
*/ */

View File

@ -43,7 +43,7 @@ void CartridgeUA::install(System& system)
// - A11, A10 and A8 are not connected to RIOT // - A11, A10 and A8 are not connected to RIOT
// - A9 is the fixed part of the hotspot address // - A9 is the fixed part of the hotspot address
// - A7 is used by Brazilian carts // - A7 is used by Brazilian carts
// - A5 and A4 determine bank // - A6 and A5 determine bank
for(uInt16 a11 = 0; a11 <= 1; ++a11) for(uInt16 a11 = 0; a11 <= 1; ++a11)
for(uInt16 a10 = 0; a10 <= 1; ++a10) for(uInt16 a10 = 0; a10 <= 1; ++a10)
for(uInt16 a8 = 0; a8 <= 1; ++a8) for(uInt16 a8 = 0; a8 <= 1; ++a8)

View File

@ -29,8 +29,7 @@
Cartridge class used for UA Limited's 8K bankswitched games. There Cartridge class used for UA Limited's 8K bankswitched games. There
are two 4K banks, which are switched by accessing $0220 (bank 0) and are two 4K banks, which are switched by accessing $0220 (bank 0) and
$0240 (bank 1). Similar addresses are used by Brazilian carts, e.g. $0240 (bank 1). Similar addresses are used by Brazilian carts, e.g.
$02A0, $02C0 and $0FA0, $0FC0. The code accepts further potential $02A0 and $02C0. The code accepts further potential hotspot addresses.
hotspot addresses.
@author Bradford W. Mott, Thomas Jentzsch @author Bradford W. Mott, Thomas Jentzsch
*/ */

View File

@ -10,6 +10,7 @@ MODULE_OBJS := \
src/emucore/CartDetector.o \ src/emucore/CartDetector.o \
src/emucore/CartEnhanced.o \ src/emucore/CartEnhanced.o \
src/emucore/Cart0840.o \ src/emucore/Cart0840.o \
src/emucore/Cart0FA0.o \
src/emucore/Cart2K.o \ src/emucore/Cart2K.o \
src/emucore/Cart3E.o \ src/emucore/Cart3E.o \
src/emucore/Cart3EPlus.o \ src/emucore/Cart3EPlus.o \

View File

@ -49,6 +49,7 @@ SOURCES_CXX := \
$(CORE_DIR)/emucore/CartDetector.cxx \ $(CORE_DIR)/emucore/CartDetector.cxx \
$(CORE_DIR)/emucore/CartEnhanced.cxx \ $(CORE_DIR)/emucore/CartEnhanced.cxx \
$(CORE_DIR)/emucore/Cart0840.cxx \ $(CORE_DIR)/emucore/Cart0840.cxx \
$(CORE_DIR)/emucore/Cart0FA0.cxx \
$(CORE_DIR)/emucore/Cart2K.cxx \ $(CORE_DIR)/emucore/Cart2K.cxx \
$(CORE_DIR)/emucore/Cart3E.cxx \ $(CORE_DIR)/emucore/Cart3E.cxx \
$(CORE_DIR)/emucore/Cart3EPlus.cxx \ $(CORE_DIR)/emucore/Cart3EPlus.cxx \

View File

@ -225,6 +225,7 @@
<ClCompile Include="..\emucore\Booster.cxx" /> <ClCompile Include="..\emucore\Booster.cxx" />
<ClCompile Include="..\emucore\Cart.cxx" /> <ClCompile Include="..\emucore\Cart.cxx" />
<ClCompile Include="..\emucore\Cart0840.cxx" /> <ClCompile Include="..\emucore\Cart0840.cxx" />
<ClCompile Include="..\emucore\Cart0FA0.cxx" />
<ClCompile Include="..\emucore\Cart2K.cxx" /> <ClCompile Include="..\emucore\Cart2K.cxx" />
<ClCompile Include="..\emucore\Cart3E.cxx" /> <ClCompile Include="..\emucore\Cart3E.cxx" />
<ClCompile Include="..\emucore\Cart3F.cxx" /> <ClCompile Include="..\emucore\Cart3F.cxx" />
@ -385,6 +386,7 @@
<ClInclude Include="..\emucore\Booster.hxx" /> <ClInclude Include="..\emucore\Booster.hxx" />
<ClInclude Include="..\emucore\Cart.hxx" /> <ClInclude Include="..\emucore\Cart.hxx" />
<ClInclude Include="..\emucore\Cart0840.hxx" /> <ClInclude Include="..\emucore\Cart0840.hxx" />
<ClInclude Include="..\emucore\Cart0FA0.hxx" />
<ClInclude Include="..\emucore\Cart2K.hxx" /> <ClInclude Include="..\emucore\Cart2K.hxx" />
<ClInclude Include="..\emucore\Cart3E.hxx" /> <ClInclude Include="..\emucore\Cart3E.hxx" />
<ClInclude Include="..\emucore\Cart3F.hxx" /> <ClInclude Include="..\emucore\Cart3F.hxx" />

View File

@ -857,6 +857,8 @@
<ClCompile Include="..\emucore\Cart3EX.cxx" /> <ClCompile Include="..\emucore\Cart3EX.cxx" />
<ClCompile Include="..\emucore\Cart4KSC.cxx" /> <ClCompile Include="..\emucore\Cart4KSC.cxx" />
<ClCompile Include="..\emucore\CartARM.cxx" /> <ClCompile Include="..\emucore\CartARM.cxx" />
<ClCompile Include="..\emucore\Cart0FA0.cxx" />
<ClCompile Include="..\emucore\Cart0FA0Widget.cxx" />
<ClCompile Include="..\emucore\CartCreator.cxx" /> <ClCompile Include="..\emucore\CartCreator.cxx" />
<ClCompile Include="..\emucore\CartE7.cxx" /> <ClCompile Include="..\emucore\CartE7.cxx" />
<ClCompile Include="..\emucore\CartEnhanced.cxx" /> <ClCompile Include="..\emucore\CartEnhanced.cxx" />
@ -2048,6 +2050,7 @@
<ClInclude Include="..\emucore\Cart3EX.hxx" /> <ClInclude Include="..\emucore\Cart3EX.hxx" />
<ClInclude Include="..\emucore\Cart4KSC.hxx" /> <ClInclude Include="..\emucore\Cart4KSC.hxx" />
<ClInclude Include="..\emucore\CartARM.hxx" /> <ClInclude Include="..\emucore\CartARM.hxx" />
<ClInclude Include="..\emucore\Cart0FA0.hxx" />
<ClInclude Include="..\emucore\CartCreator.hxx" /> <ClInclude Include="..\emucore\CartCreator.hxx" />
<ClInclude Include="..\emucore\CartE7.hxx" /> <ClInclude Include="..\emucore\CartE7.hxx" />
<ClInclude Include="..\emucore\CartEnhanced.hxx" /> <ClInclude Include="..\emucore\CartEnhanced.hxx" />
@ -2064,6 +2067,7 @@
<ClInclude Include="..\emucore\CartFC.hxx" /> <ClInclude Include="..\emucore\CartFC.hxx" />
<ClInclude Include="..\emucore\CartMDM.hxx" /> <ClInclude Include="..\emucore\CartMDM.hxx" />
<ClInclude Include="..\emucore\CartMVC.hxx" /> <ClInclude Include="..\emucore\CartMVC.hxx" />
<ClInclude Include="..\emucore\Cart0FA0Widget.hxx" />
<ClInclude Include="..\emucore\CartTVBoy.hxx" /> <ClInclude Include="..\emucore\CartTVBoy.hxx" />
<ClInclude Include="..\emucore\CartWD.hxx" /> <ClInclude Include="..\emucore\CartWD.hxx" />
<ClInclude Include="..\emucore\CompuMate.hxx" /> <ClInclude Include="..\emucore\CompuMate.hxx" />

View File

@ -1131,6 +1131,12 @@
<ClCompile Include="..\gui\NavigationWidget.cxx"> <ClCompile Include="..\gui\NavigationWidget.cxx">
<Filter>Source Files\gui</Filter> <Filter>Source Files\gui</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\emucore\Cart0FA0.cxx">
<Filter>Source Files\emucore</Filter>
</ClCompile>
<ClCompile Include="..\emucore\Cart0FA0Widget.cxx">
<Filter>Source Files\debugger</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\common\bspf.hxx"> <ClInclude Include="..\common\bspf.hxx">
@ -2342,6 +2348,12 @@
<ClInclude Include="..\emucore\ConsoleTiming.hxx"> <ClInclude Include="..\emucore\ConsoleTiming.hxx">
<Filter>Header Files\emucore</Filter> <Filter>Header Files\emucore</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\emucore\Cart0FA0.hxx">
<Filter>Header Files\emucore</Filter>
</ClInclude>
<ClInclude Include="..\emucore\Cart0FA0Widget.hxx">
<Filter>Header Files\debugger</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="stella.ico"> <None Include="stella.ico">

Binary file not shown.

Binary file not shown.

Binary file not shown.