- Cartridge.Sound: |
+ Cart.Sound: |
Indicates if the game should use 1 or 2 channels for sound output.
All original Atari 2600 machines supported 1 channel only,
but some homebrew games have been written to take advantage of stereo
@@ -4089,19 +4133,19 @@ Ms Pac-Man (Stella extended codes):
- Console.TelevisionType: |
+ Console.TVType: |
Indicates the default television setting for the
game. The value must be Color or BW. |
- Console.LeftDifficulty: |
+ Console.LeftDiff: |
Indicates the default difficulty setting for the left
player. The value must be A or B. |
- Console.RightDifficulty: |
+ Console.RightDiff: |
Indicates the default difficulty setting for the
right player. The value must be A or B. |
@@ -4202,14 +4246,14 @@ Ms Pac-Man (Stella extended codes):
- Cartridge.Name: |
+ Cart.Name: |
Indicates the actual name of the game. When you save snapshots,
load/save state files, or use the ROM Audit Mode functionality,
this is the name that will be used for the respective file(s). |
- Cartridge.MD5: |
+ Cart.MD5: |
Indicates the MD5 checksum of the ROM image as a
string of hexadecimal digits. Stella uses this property while
attempting to match a game with its block of properties. If the
@@ -4220,27 +4264,37 @@ Ms Pac-Man (Stella extended codes):
|
- Cartridge.Manufacturer: |
+ Cart.Manufacturer: |
Indicates the game's manufacturer. |
- Cartridge.ModelNo: |
+ Cart.ModelNo: |
Indicates the manufacturer's model number for the game. |
- Cartridge.Rarity: |
+ Cart.Rarity: |
Indicates how rare a cartridge is, based on the scale described on AtariAge. |
- Cartridge.Note: |
+ Cart.Note: |
Contains any special notes about playing the game. |
+ The buttons at the bottom of the dialogs work as follows:
+
+ - Defaults: Reset the properties to those built into Stella.
+ - Save: Save the properties for the currently selected ROM only
+ to a properties file in the users default save directory.
+ - OK: Merge/commit any changes into the ROM properties database, which
+ contains info on all ROMs.
+ - Cancel: Revert any changes in the dialog, and cancel the operation.
+
+
The name of the properties file will depend on the version of Stella, as follows:
@@ -4261,7 +4315,7 @@ Ms Pac-Man (Stella extended codes):
_BASEDIR_/stella.pro |
- Stella will require a restart for changes to this file to take effect.
+ Note: For manual changes to the property files Stella will require a restart to take effect.
diff --git a/docs/index_r77.html b/docs/index_r77.html
index 710f5e561..cc15b11ab 100644
--- a/docs/index_r77.html
+++ b/docs/index_r77.html
@@ -58,7 +58,7 @@
Stella for RetroN 77
Atari 2600 VCS emulator
- Release 6.1
+ Release 6.2.1
Quick Navigation Guide
diff --git a/src/common/FrameBufferSDL2.cxx b/src/common/FrameBufferSDL2.cxx
index 4d013a35d..d930b2fc0 100644
--- a/src/common/FrameBufferSDL2.cxx
+++ b/src/common/FrameBufferSDL2.cxx
@@ -15,6 +15,8 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
+#include
+
#include "SDL_lib.hxx"
#include "bspf.hxx"
#include "Logger.hxx"
@@ -99,19 +101,32 @@ void FrameBufferSDL2::queryHardware(vector& fullscreenRes,
int numModes = SDL_GetNumDisplayModes(i);
ostringstream s;
- s << "Supported video modes for display " << i << ":";
- Logger::debug(s.str());
+ s << "Supported video modes (" << numModes << ") for display " << i << ":";
+
+ string lastRes = "";
+
for (int m = 0; m < numModes; m++)
{
SDL_DisplayMode mode;
+ ostringstream res;
SDL_GetDisplayMode(i, m, &mode);
- s.str("");
- s << " " << m << ": " << mode.w << "x" << mode.h << "@" << mode.refresh_rate << "Hz";
- if (mode.w == display.w && mode.h == display.h && mode.refresh_rate == display.refresh_rate)
- s << " (active)";
- Logger::debug(s.str());
+ res << std::setw(4) << mode.w << "x" << std::setw(4) << mode.h;
+
+ if(lastRes != res.str())
+ {
+ Logger::debug(s.str());
+ s.str("");
+ lastRes = res.str();
+ s << lastRes << ": ";
+ }
+ s << mode.refresh_rate << "Hz";
+ if(mode.w == display.w && mode.h == display.h && mode.refresh_rate == display.refresh_rate)
+ s << "* ";
+ else
+ s << " ";
}
+ Logger::debug(s.str());
}
// Now get the maximum windowed desktop resolution
@@ -218,21 +233,14 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
if(SDL_WasInit(SDL_INIT_VIDEO) == 0)
return false;
- // TODO: On multiple displays, switching from centered mode, does not respect
- // current window's display (which many not be centered anymore)
+ const bool fullScreen = mode.fsIndex != -1;
+ bool forceCreateRenderer = false;
// Get windowed window's last display
Int32 displayIndex = std::min(myNumDisplays, myOSystem.settings().getInt(getDisplayKey()));
// Get windowed window's last position
myWindowedPos = myOSystem.settings().getPoint(getPositionKey());
- // Always recreate renderer (some systems need this)
- if(myRenderer)
- {
- SDL_DestroyRenderer(myRenderer);
- myRenderer = nullptr;
- }
-
int posX, posY;
myCenter = myOSystem.settings().getBool("center");
@@ -261,49 +269,45 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
posX = BSPF::clamp(posX, x0 - Int32(mode.screen.w) + 50, x1 - 50);
posY = BSPF::clamp(posY, y0 + 50, y1 - 50);
}
- uInt32 flags = mode.fsIndex != -1 ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0;
- flags |= SDL_WINDOW_ALLOW_HIGHDPI;
- // macOS seems to have issues with destroying the window, and wants to
- // keep the same handle
- // Problem is, doing so on other platforms results in flickering when
- // toggling fullscreen windowed mode
- // So we have a special case for macOS
-#ifndef BSPF_MACOS
+#ifdef ADAPTABLE_REFRESH_SUPPORT
+ SDL_DisplayMode adaptedSdlMode;
+ const bool shouldAdapt = fullScreen && myOSystem.settings().getBool("tia.fs_refresh")
+ && gameRefreshRate()
+ // take care of 59.94 Hz
+ && refreshRate() % gameRefreshRate() != 0 && refreshRate() % (gameRefreshRate() - 1) != 0;
+ const bool adaptRefresh = shouldAdapt && adaptRefreshRate(displayIndex, adaptedSdlMode);
+#else
+ const bool adaptRefresh = false;
+#endif
+ const uInt32 flags = SDL_WINDOW_ALLOW_HIGHDPI
+ | (fullScreen ? adaptRefresh ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
+
// Don't re-create the window if its display and size hasn't changed,
// as it's not necessary, and causes flashing in fullscreen mode
if(myWindow)
{
- int d = SDL_GetWindowDisplayIndex(myWindow);
+ const int d = SDL_GetWindowDisplayIndex(myWindow);
int w, h;
SDL_GetWindowSize(myWindow, &w, &h);
- if(d != displayIndex || uInt32(w) != mode.screen.w || uInt32(h) != mode.screen.h)
+ if(d != displayIndex || uInt32(w) != mode.screen.w || uInt32(h) != mode.screen.h
+ || adaptRefresh)
{
SDL_DestroyWindow(myWindow);
myWindow = nullptr;
}
}
+
if(myWindow)
{
// Even though window size stayed the same, the title may have changed
SDL_SetWindowTitle(myWindow, title.c_str());
SDL_SetWindowPosition(myWindow, posX, posY);
}
-#else
- // macOS wants to *never* re-create the window
- // This sometimes results in the window being resized *after* it's displayed,
- // but at least the code works and doesn't crash
- if(myWindow)
- {
- SDL_SetWindowFullscreen(myWindow, flags);
- SDL_SetWindowSize(myWindow, mode.screen.w, mode.screen.h);
- SDL_SetWindowPosition(myWindow, posX, posY);
- SDL_SetWindowTitle(myWindow, title.c_str());
- }
-#endif
else
{
+ forceCreateRenderer = true;
myWindow = SDL_CreateWindow(title.c_str(), posX, posY,
mode.screen.w, mode.screen.h, flags);
if(myWindow == nullptr)
@@ -312,31 +316,133 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
Logger::error(msg);
return false;
}
+
setWindowIcon();
}
+#ifdef ADAPTABLE_REFRESH_SUPPORT
+ if(adaptRefresh)
+ {
+ // Switch to mode for adapted refresh rate
+ if(SDL_SetWindowDisplayMode(myWindow, &adaptedSdlMode) != 0)
+ {
+ Logger::error("ERROR: Display refresh rate change failed");
+ }
+ else
+ {
+ ostringstream msg;
+
+ msg << "Display refresh rate changed to " << adaptedSdlMode.refresh_rate << " Hz";
+ Logger::info(msg.str());
+ }
+ }
+#endif
+
+ return createRenderer(forceCreateRenderer);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode)
+{
+ SDL_DisplayMode sdlMode;
+
+ if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) != 0)
+ {
+ Logger::error("ERROR: Display mode could not be retrieved");
+ return false;
+ }
+
+ const int currentRefreshRate = sdlMode.refresh_rate;
+ const int wantedRefreshRate = gameRefreshRate();
+ // Take care of rounded refresh rates (e.g. 59.94 Hz)
+ float factor = std::min(float(currentRefreshRate) / wantedRefreshRate,
+ float(currentRefreshRate) / (wantedRefreshRate - 1));
+ // Calculate difference taking care of integer factors (e.g. 100/120)
+ float bestDiff = std::abs(factor - std::round(factor)) / factor;
+ bool adapt = false;
+
+ // Display refresh rate should be an integer factor of the game's refresh rate
+ // Note: Modes are scanned with size being first priority,
+ // therefore the size will never change.
+ // Check for integer factors 1 (60/50 Hz) and 2 (120/100 Hz)
+ for(int m = 1; m <= 2; ++m)
+ {
+ SDL_DisplayMode closestSdlMode;
+
+ sdlMode.refresh_rate = wantedRefreshRate * m;
+ if(SDL_GetClosestDisplayMode(displayIndex, &sdlMode, &closestSdlMode) == nullptr)
+ {
+ Logger::error("ERROR: Closest display mode could not be retrieved");
+ return adapt;
+ }
+ factor = std::min(float(sdlMode.refresh_rate) / sdlMode.refresh_rate,
+ float(sdlMode.refresh_rate) / (sdlMode.refresh_rate - 1));
+ const float diff = std::abs(factor - std::round(factor)) / factor;
+ if(diff < bestDiff)
+ {
+ bestDiff = diff;
+ adaptedSdlMode = closestSdlMode;
+ adapt = true;
+ }
+ }
+ //cerr << "refresh rate adapt ";
+ //if(adapt)
+ // cerr << "required (" << currentRefreshRate << " Hz -> " << adaptedSdlMode.refresh_rate << " Hz)";
+ //else
+ // cerr << "not required/possible";
+ //cerr << endl;
+
+ // Only change if the display supports a better refresh rate
+ return adapt;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool FrameBufferSDL2::createRenderer(bool force)
+{
+ // A new renderer is only created when necessary:
+ // - new myWindow (force = true)
+ // - no renderer existing
+ // - different renderer flags
+ // - different renderer name
+ bool recreate = force || myRenderer == nullptr;
uInt32 renderFlags = SDL_RENDERER_ACCELERATED;
+ const string& video = myOSystem.settings().getString("video"); // Render hint
+ SDL_RendererInfo renderInfo;
+
if(myOSystem.settings().getBool("vsync")
&& !myOSystem.settings().getBool("turbo")) // V'synced blits option
renderFlags |= SDL_RENDERER_PRESENTVSYNC;
- const string& video = myOSystem.settings().getString("video"); // Render hint
- if(video != "")
- SDL_SetHint(SDL_HINT_RENDER_DRIVER, video.c_str());
- myRenderer = SDL_CreateRenderer(myWindow, -1, renderFlags);
+ // check renderer flags and name
+ recreate |= (SDL_GetRendererInfo(myRenderer, &renderInfo) != 0)
+ || ((renderInfo.flags & (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)) != renderFlags
+ || (video != renderInfo.name));
- detectFeatures();
- determineDimensions();
-
- if(myRenderer == nullptr)
+ if(recreate)
{
- string msg = "ERROR: Unable to create SDL renderer: " + string(SDL_GetError());
- Logger::error(msg);
- return false;
+ //cerr << "Create new renderer for buffer type #" << int(myBufferType) << endl;
+ if(myRenderer)
+ SDL_DestroyRenderer(myRenderer);
+
+ if(video != "")
+ SDL_SetHint(SDL_HINT_RENDER_DRIVER, video.c_str());
+
+ myRenderer = SDL_CreateRenderer(myWindow, -1, renderFlags);
+
+ detectFeatures();
+ determineDimensions();
+
+ if(myRenderer == nullptr)
+ {
+ string msg = "ERROR: Unable to create SDL renderer: " + string(SDL_GetError());
+ Logger::error(msg);
+ return false;
+ }
}
clear();
SDL_RendererInfo renderinfo;
+
if(SDL_GetRendererInfo(myRenderer, &renderinfo) >= 0)
myOSystem.settings().setValue("video", renderinfo.name);
@@ -404,6 +510,36 @@ bool FrameBufferSDL2::fullScreen() const
#endif
}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+int FrameBufferSDL2::refreshRate() const
+{
+ ASSERT_MAIN_THREAD;
+
+ const uInt32 displayIndex = SDL_GetWindowDisplayIndex(myWindow);
+ SDL_DisplayMode sdlMode;
+
+ if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) == 0)
+ return sdlMode.refresh_rate;
+
+ if(myWindow != nullptr)
+ Logger::error("Could not retrieve current display mode");
+
+ return 0;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+int FrameBufferSDL2::gameRefreshRate() const
+{
+ if(myOSystem.hasConsole())
+ {
+ const string format = myOSystem.console().getFormatString();
+ const bool isNtsc = format == "NTSC" || format == "PAL60" || format == "SECAM60";
+
+ return isNtsc ? 60 : 50; // The code will take care of 59/49 Hz
+ }
+ return 0;
+}
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::renderToScreen()
{
@@ -416,10 +552,9 @@ void FrameBufferSDL2::renderToScreen()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::setWindowIcon()
{
- ASSERT_MAIN_THREAD;
-
#if !defined(BSPF_MACOS) && !defined(RETRON77)
#include "stella_icon.hxx"
+ ASSERT_MAIN_THREAD;
SDL_Surface* surface = SDL_CreateRGBSurfaceFrom(stella_icon, 32, 32, 32,
32 * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000);
diff --git a/src/common/FrameBufferSDL2.hxx b/src/common/FrameBufferSDL2.hxx
index d2825037c..7904ed0ee 100644
--- a/src/common/FrameBufferSDL2.hxx
+++ b/src/common/FrameBufferSDL2.hxx
@@ -181,6 +181,25 @@ class FrameBufferSDL2 : public FrameBuffer
*/
bool setVideoMode(const string& title, const VideoMode& mode) override;
+ /**
+ Checks if the display refresh rate should be adapted to game refresh rate in (real) fullscreen mode
+
+ @param displayIndex The display which should be checked
+ @param adaptedSdlMode The best matching mode if the refresh rate should be changed
+
+ @return True if the refresh rate should be changed
+ */
+ bool adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode);
+
+ /**
+ Create a new renderer if required
+
+ @param force If true, force new renderer creation
+
+ @return False on any errors, else true
+ */
+ bool createRenderer(bool force);
+
/**
This method is called to create a surface with the given attributes.
@@ -233,6 +252,16 @@ class FrameBufferSDL2 : public FrameBuffer
*/
void determineDimensions();
+ /**
+ Retrieve the current display's refresh rate, or 0 if no window
+ */
+ int refreshRate() const override;
+
+ /**
+ Retrieve the current game's refresh rate, or 60 if no game
+ */
+ int gameRefreshRate() const;
+
private:
// The SDL video buffer
SDL_Window* myWindow{nullptr};
diff --git a/src/common/PJoystickHandler.cxx b/src/common/PJoystickHandler.cxx
index 3b2452798..1af10feac 100644
--- a/src/common/PJoystickHandler.cxx
+++ b/src/common/PJoystickHandler.cxx
@@ -687,27 +687,32 @@ void PhysicalJoystickHandler::handleAxisEvent(int stick, int axis, int value)
}
j->axisLastValue[axis] = value;
}
+ #ifdef GUI_SUPPORT
else if(myHandler.hasOverlay())
{
- // First, clamp the values to simulate digital input
- // (the only thing that the underlying code understands)
- if(value > Joystick::deadzone())
- value = 32000;
- else if(value < -Joystick::deadzone())
- value = -32000;
- else
- value = 0;
-
- // Now filter out consecutive, similar values
- // (only pass on the event if the state has changed)
- if(value != j->axisLastValue[axis])
+ // A value change lower than Joystick::deadzone indicates analog input which is ignored
+ if((abs(j->axisLastValue[axis] - value) > Joystick::deadzone()))
{
-#ifdef GUI_SUPPORT
- myHandler.overlay().handleJoyAxisEvent(stick, JoyAxis(axis), convertAxisValue(value), button);
-#endif
- j->axisLastValue[axis] = value;
+ // First, clamp the values to simulate digital input
+ // (the only thing that the underlying code understands)
+ if(value > Joystick::deadzone())
+ value = 32000;
+ else if(value < -Joystick::deadzone())
+ value = -32000;
+ else
+ value = 0;
+
+ // Now filter out consecutive, similar values
+ // (only pass on the event if the state has changed)
+ if(value != j->axisLastValue[axis])
+ {
+ myHandler.overlay().handleJoyAxisEvent(stick, JoyAxis(axis), convertAxisValue(value), button);
+
+ }
}
+ j->axisLastValue[axis] = value;
}
+ #endif
}
}
diff --git a/src/common/PKeyboardHandler.cxx b/src/common/PKeyboardHandler.cxx
index cf4a31831..59beffdac 100644
--- a/src/common/PKeyboardHandler.cxx
+++ b/src/common/PKeyboardHandler.cxx
@@ -39,6 +39,7 @@ PhysicalKeyboardHandler::PhysicalKeyboardHandler(OSystem& system, EventHandler&
myHandler(handler)
{
Int32 version = myOSystem.settings().getInt("event_ver");
+ bool updateDefaults = false;
// Compare if event list version has changed so that key maps became invalid
if (version == Event::VERSION)
@@ -53,11 +54,12 @@ PhysicalKeyboardHandler::PhysicalKeyboardHandler(OSystem& system, EventHandler&
myKeyMap.loadMapping(list, EventMode::kKeypadMode);
list = myOSystem.settings().getString("keymap_ui");
myKeyMap.loadMapping(list, EventMode::kMenuMode);
+ updateDefaults = true;
}
myKeyMap.enableMod() = myOSystem.settings().getBool("modcombo");
- setDefaultMapping(Event::NoType, EventMode::kEmulationMode, true);
- setDefaultMapping(Event::NoType, EventMode::kMenuMode, true);
+ setDefaultMapping(Event::NoType, EventMode::kEmulationMode, updateDefaults);
+ setDefaultMapping(Event::NoType, EventMode::kMenuMode, updateDefaults);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -443,7 +445,11 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo
{Event::LoadState, KBDK_F11},
{Event::LoadAllStates, KBDK_F11, MOD3},
{Event::TakeSnapshot, KBDK_F12},
+#ifdef BSPF_MACOS
+ {Event::TogglePauseMode, KBDK_P, KBDM_SHIFT | MOD3},
+#else
{Event::TogglePauseMode, KBDK_PAUSE},
+#endif
{Event::OptionsMenuMode, KBDK_TAB},
{Event::CmdMenuMode, KBDK_BACKSLASH},
{Event::TimeMachineMode, KBDK_T, KBDM_SHIFT},
@@ -455,6 +461,7 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo
{Event::Quit, KBDK_Q, KBDM_CTRL},
#endif
{Event::ReloadConsole, KBDK_R, KBDM_CTRL},
+ {Event::PreviousMultiCartRom, KBDK_R, KBDM_SHIFT | KBDM_CTRL},
{Event::VidmodeDecrease, KBDK_MINUS, MOD3},
{Event::VidmodeIncrease, KBDK_EQUALS, MOD3},
@@ -467,6 +474,7 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo
{Event::SoundToggle, KBDK_RIGHTBRACKET, KBDM_CTRL},
{Event::ToggleFullScreen, KBDK_RETURN, MOD3},
+ {Event::ToggleAdaptRefresh, KBDK_R, MOD3},
{Event::OverscanDecrease, KBDK_PAGEDOWN, KBDM_SHIFT},
{Event::OverscanIncrease, KBDK_PAGEUP, KBDM_SHIFT},
//{Event::VidmodeStd, KBDK_1, MOD3},
@@ -497,9 +505,13 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo
#ifndef BSPF_MACOS
{Event::PreviousSetting, KBDK_END},
{Event::NextSetting, KBDK_HOME},
+ {Event::PreviousSettingGroup, KBDK_END, KBDM_CTRL},
+ {Event::NextSettingGroup, KBDK_HOME, KBDM_CTRL},
#else
{Event::PreviousSetting, KBDK_HOME},
{Event::NextSetting, KBDK_END},
+ {Event::PreviousSettingGroup, KBDK_HOME, KBDM_CTRL},
+ {Event::NextSettingGroup, KBDK_END, KBDM_CTRL},
#endif
{Event::SettingDecrease, KBDK_PAGEDOWN},
{Event::SettingIncrease, KBDK_PAGEUP},
diff --git a/src/common/PNGLibrary.cxx b/src/common/PNGLibrary.cxx
index e1980a975..23dd798d6 100644
--- a/src/common/PNGLibrary.cxx
+++ b/src/common/PNGLibrary.cxx
@@ -89,7 +89,7 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface)
}
else if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
- loadImageERROR("Greyscale PNG images not supported");
+ png_set_gray_to_rgb(png_ptr);
}
else if(color_type == PNG_COLOR_TYPE_PALETTE)
{
diff --git a/src/common/PaletteHandler.cxx b/src/common/PaletteHandler.cxx
index d2a2a7768..ec0d7691b 100644
--- a/src/common/PaletteHandler.cxx
+++ b/src/common/PaletteHandler.cxx
@@ -139,7 +139,7 @@ void PaletteHandler::changeCurrentAdjustable(int direction)
{
int newVal = scaleTo100(*myAdjustables[myCurrentAdjustable].value);
- newVal = BSPF::clamp(newVal + direction * 2, 0, 100);
+ newVal = BSPF::clamp(newVal + direction * 1, 0, 100);
*myAdjustables[myCurrentAdjustable].value = scaleFrom100(newVal);
@@ -385,7 +385,7 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
for(int chroma = 1; chroma < NUM_CHROMA; chroma++)
{
color[chroma][0] = SATURATION * sinf(offset + shift * (chroma - 1));
- color[chroma][1] = SATURATION * sinf(offset + shift * (chroma - 1 - BSPF::PI_f));
+ color[chroma][1] = SATURATION * cosf(offset + shift * (chroma - 1) - BSPF::PI_f);
}
for(int chroma = 0; chroma < NUM_CHROMA; chroma++)
diff --git a/src/common/PaletteHandler.hxx b/src/common/PaletteHandler.hxx
index bd102d9f0..ed46da516 100644
--- a/src/common/PaletteHandler.hxx
+++ b/src/common/PaletteHandler.hxx
@@ -125,8 +125,8 @@ class PaletteHandler
/**
Convert adjustables from/to 100% scale
*/
- constexpr float scaleFrom100(float x) const { return (x / 50.F) - 1.F; }
- constexpr uInt32 scaleTo100(float x) const { return uInt32(50 * (x + 1.F)); }
+ static constexpr float scaleFrom100(float x) { return (x / 50.F) - 1.F; }
+ static constexpr uInt32 scaleTo100(float x) { return uInt32(50.0001F * (x + 1.F)); }
/**
Convert palette settings name to enumeration.
diff --git a/src/common/StateManager.hxx b/src/common/StateManager.hxx
index 3da98499c..efb9286cb 100644
--- a/src/common/StateManager.hxx
+++ b/src/common/StateManager.hxx
@@ -18,7 +18,7 @@
#ifndef STATE_MANAGER_HXX
#define STATE_MANAGER_HXX
-#define STATE_HEADER "06010000state"
+#define STATE_HEADER "06020100state"
class OSystem;
class RewindManager;
diff --git a/src/common/Version.hxx b/src/common/Version.hxx
index 09c706540..9c070d208 100644
--- a/src/common/Version.hxx
+++ b/src/common/Version.hxx
@@ -18,7 +18,7 @@
#ifndef VERSION_HXX
#define VERSION_HXX
-#define STELLA_VERSION "6.2_pre"
-#define STELLA_BUILD "5741"
+#define STELLA_VERSION "6.2.1"
+#define STELLA_BUILD "6041"
#endif
diff --git a/src/common/ZipHandler.hxx b/src/common/ZipHandler.hxx
index 861e1350a..aaf289357 100644
--- a/src/common/ZipHandler.hxx
+++ b/src/common/ZipHandler.hxx
@@ -297,7 +297,7 @@ class ZipHandler
void addToCache();
private:
- static constexpr uInt32 DECOMPRESS_BUFSIZE = 16_KB;
+ static constexpr size_t DECOMPRESS_BUFSIZE = 16_KB;
static constexpr uInt32 CACHE_SIZE = 8; // number of open files to cache
ZipFilePtr myZip;
diff --git a/src/common/bspf.hxx b/src/common/bspf.hxx
index f21a99a4c..5201ef2ff 100644
--- a/src/common/bspf.hxx
+++ b/src/common/bspf.hxx
@@ -90,9 +90,9 @@ using DWordBuffer = std::unique_ptr; // NOLINT
using AdjustFunction = std::function;
// We use KB a lot; let's make a literal for it
-constexpr uInt32 operator "" _KB(unsigned long long size)
+constexpr size_t operator "" _KB(unsigned long long size)
{
- return static_cast(size * 1024);
+ return static_cast(size * 1024);
}
static const string EmptyString("");
@@ -101,6 +101,12 @@ static const string EmptyString("");
#undef PAGE_SIZE
#undef PAGE_MASK
+// Adaptable refresh is currently not available on MacOS
+// In the future, this may expand to other systems
+#if !defined(BSPF_MACOS)
+ #define ADAPTABLE_REFRESH_SUPPORT
+#endif
+
namespace BSPF
{
static constexpr float PI_f = 3.141592653589793238462643383279502884F;
@@ -122,6 +128,21 @@ namespace BSPF
static const string ARCH = "NOARCH";
#endif
+ // Get next power of two greater than or equal to the given value
+ inline size_t nextPowerOfTwo(size_t size) {
+ if(size < 2) return 1;
+ size_t power2 = 1;
+ while(power2 < size)
+ power2 <<= 1;
+ return power2;
+ }
+
+ // Get next multiple of the given value
+ // Note that this only works when multiple is a power of two
+ inline size_t nextMultipleOf(size_t size, size_t multiple) {
+ return (size + multiple - 1) & ~(multiple - 1);
+ }
+
// Make 2D-arrays using std::array less verbose
template
using array2D = std::array, ROW>;
diff --git a/src/common/tv_filters/NTSCFilter.cxx b/src/common/tv_filters/NTSCFilter.cxx
index 9764f1ac3..5a61dd140 100644
--- a/src/common/tv_filters/NTSCFilter.cxx
+++ b/src/common/tv_filters/NTSCFilter.cxx
@@ -20,8 +20,8 @@
#include "NTSCFilter.hxx"
-constexpr float scaleFrom100(float x) { return (x/50.F) - 1.F; }
-constexpr uInt32 scaleTo100(float x) { return uInt32(50*(x+1.F)); }
+constexpr float scaleFrom100(float x) { return (x / 50.F) - 1.F; }
+constexpr uInt32 scaleTo100(float x) { return uInt32(50.0001F * (x + 1.F)); }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string NTSCFilter::setPreset(Preset preset)
@@ -119,7 +119,7 @@ void NTSCFilter::changeCurrentAdjustable(int direction,
// return "'Custom' TV mode not selected";
newValue = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value);
- newValue = BSPF::clamp(newValue + direction * 2, 0, 100);
+ newValue = BSPF::clamp(newValue + direction * 1, 0, 100);
*ourCustomAdjustables[myCurrentAdjustable].value = scaleFrom100(newValue);
diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx
index 49692ef8a..9e3c0745b 100644
--- a/src/debugger/DebuggerParser.cxx
+++ b/src/debugger/DebuggerParser.cxx
@@ -112,6 +112,8 @@ string DebuggerParser::run(const string& command)
if(validateArgs(i))
{
myCommand = i;
+ if(commands[i].refreshRequired)
+ debugger.baseDialog()->saveConfig();
commands[i].executor(this);
}
@@ -1733,6 +1735,8 @@ void DebuggerParser::executeRunTo()
const CartDebug& cartdbg = debugger.cartDebug();
const CartDebug::DisassemblyList& list = cartdbg.disassembly().list;
+ debugger.saveOldState();
+
uInt32 count = 0, max_iterations = uInt32(list.size());
// Create a progress dialog box to show the progress searching through the
@@ -1776,6 +1780,8 @@ void DebuggerParser::executeRunToPc()
const CartDebug& cartdbg = debugger.cartDebug();
const CartDebug::DisassemblyList& list = cartdbg.disassembly().list;
+ debugger.saveOldState();
+
uInt32 count = 0;
bool done = false;
constexpr uInt32 max_iterations = 1000000;
diff --git a/src/debugger/gui/Cart3EPlusWidget.cxx b/src/debugger/gui/Cart3EPlusWidget.cxx
index 8e7cdf063..cd0fda251 100644
--- a/src/debugger/gui/Cart3EPlusWidget.cxx
+++ b/src/debugger/gui/Cart3EPlusWidget.cxx
@@ -35,18 +35,18 @@ string Cartridge3EPlusWidget::description()
{
ostringstream info;
size_t size;
- const uInt8* image = myCart.getImage(size);
+ const ByteBuffer& image = myCart.getImage(size);
uInt16 numRomBanks = myCart.romBankCount();
uInt16 numRamBanks = myCart.ramBankCount();
- info << "3E+ cartridge - (4..64K ROM + RAM)\n"
+ info << "3E+ cartridge - (4" << ELLIPSIS << "64K ROM + RAM)\n"
<< " " << numRomBanks << " 1K ROM banks + " << numRamBanks << " 512b RAM banks\n"
<< " mapped into four segments\n"
"ROM bank & segment selected by writing to $3F\n"
"RAM bank & segment selected by writing to $3E\n"
" Lower 512b of segment for read access\n"
" Upper 512b of segment for write access\n"
- "Startup bank = 0/-1/-1/0 (ROM)\n";
+ "Startup bank = -1/-1/-1/0 (ROM)\n";
// Eventually, we should query this from the debugger/disassembler
uInt16 start = (image[0x400 - 3] << 8) | image[0x400 - 4];
@@ -60,7 +60,8 @@ string Cartridge3EPlusWidget::description()
void Cartridge3EPlusWidget::bankSelect(int& ypos)
{
size_t size;
- const uInt8* image = myCart.getImage(size);
+ const ByteBuffer& image = myCart.getImage(size);
+ const int VGAP = myFontHeight / 4;
VariantList banktype;
VarList::push_back(banktype, "ROM", "ROM");
@@ -68,6 +69,8 @@ void Cartridge3EPlusWidget::bankSelect(int& ypos)
myBankWidgets = make_unique(bankSegs());
+ ypos -= VGAP * 2;
+
for(uInt32 seg = 0; seg < bankSegs(); ++seg)
{
int xpos = 2, xpos_s, ypos_s = ypos + 1, width;
@@ -77,20 +80,25 @@ void Cartridge3EPlusWidget::bankSelect(int& ypos)
label << "Set segment " << seg << " as ";
new StaticTextWidget(_boss, _font, xpos, ypos, label.str());
- ypos += myLineHeight + 8;
+ ypos += myLineHeight + VGAP * 2;
xpos += _font.getMaxCharWidth() * 2;
- CartridgeEnhancedWidget::bankList(myCart.romBankCount(), seg, items, width);
+ CartridgeEnhancedWidget::bankList(std::max(myCart.romBankCount(), myCart.ramBankCount()),
+ seg, items, width);
myBankWidgets[seg] =
new PopUpWidget(_boss, _font, xpos, ypos - 2, width,
- myLineHeight, items, "Bank ");
+ myLineHeight, items, "Bank ", 0, kBankChanged);
+ myBankWidgets[seg]->setID(seg);
+ myBankWidgets[seg]->setTarget(this);
addFocusWidget(myBankWidgets[seg]);
xpos += myBankWidgets[seg]->getWidth();
myBankType[seg] =
new PopUpWidget(_boss, _font, xpos, ypos - 2, 3 * _font.getMaxCharWidth(),
- myLineHeight, banktype, " of ");
+ myLineHeight, banktype, " of ", 0, kRomRamChanged);
+ myBankType[seg]->setID(seg);
+ myBankType[seg]->setTarget(this);
addFocusWidget(myBankType[seg]);
xpos = myBankType[seg]->getRight() + _font.getMaxCharWidth();
@@ -98,7 +106,8 @@ void Cartridge3EPlusWidget::bankSelect(int& ypos)
// add "Commit" button (why required?)
myBankCommit[seg] = new ButtonWidget(_boss, _font, xpos, ypos - 4,
_font.getStringWidth(" Commit "), myButtonHeight,
- "Commit", bankEnum[seg]);
+ "Commit", kChangeBank);
+ myBankCommit[seg]->setID(seg);
myBankCommit[seg]->setTarget(this);
addFocusWidget(myBankCommit[seg]);
@@ -117,7 +126,7 @@ void Cartridge3EPlusWidget::bankSelect(int& ypos)
myBankState[2 * seg] = new EditTextWidget(_boss, _font, xoffset, ypos_s,
_w - xoffset - 10, myLineHeight, "");
myBankState[2 * seg]->setEditable(false, true);
- ypos_s += myLineHeight + 4;
+ ypos_s += myLineHeight + VGAP;
label.str("");
label << "$" << Common::Base::HEX4 << addr2 << "-$" << Common::Base::HEX4 << (addr2 + 0x1FF);
@@ -127,7 +136,7 @@ void Cartridge3EPlusWidget::bankSelect(int& ypos)
_w - xoffset - 10, myLineHeight, "");
myBankState[2 * seg + 1]->setEditable(false, true);
- ypos += 2 * myLineHeight;
+ ypos += myLineHeight + VGAP * 4;
}
}
@@ -142,42 +151,44 @@ void Cartridge3EPlusWidget::loadConfig()
void Cartridge3EPlusWidget::handleCommand(CommandSender* sender,
int cmd, int data, int id)
{
- uInt16 segment = 0;
+ const uInt16 segment = id;
+
switch(cmd)
{
- case kBank0Changed:
- segment = 0;
+ case kBankChanged:
+ case kRomRamChanged:
+ {
+ const bool isROM = myBankType[segment]->getSelectedTag() == "ROM";
+ int bank = myBankWidgets[segment]->getSelected();
+
+ myBankCommit[segment]->setEnabled((isROM && bank < myCart.romBankCount())
+ || (!isROM && bank < myCart.ramBankCount()));
break;
- case kBank1Changed:
- segment = 1;
- break;
- case kBank2Changed:
- segment = 2;
- break;
- case kBank3Changed:
- segment = 3;
+ }
+ case kChangeBank:
+ {
+ // Ignore bank if either number or type hasn't been selected
+ if(myBankWidgets[segment]->getSelected() < 0 ||
+ myBankType[segment]->getSelected() < 0)
+ return;
+
+ uInt8 bank = myBankWidgets[segment]->getSelected();
+
+ myCart.unlockBank();
+
+ if(myBankType[segment]->getSelectedTag() == "ROM")
+ myCart.bank(bank, segment);
+ else
+ myCart.bank(bank + myCart.romBankCount(), segment);
+
+ myCart.lockBank();
+ invalidate();
+ updateUIState();
break;
+ }
default:
break;
}
-
- // Ignore bank if either number or type hasn't been selected
- if(myBankWidgets[segment]->getSelected() < 0 ||
- myBankType[segment]->getSelected() < 0)
- return;
-
- uInt8 bank = myBankWidgets[segment]->getSelected();
-
- myCart.unlockBank();
-
- if(myBankType[segment]->getSelectedTag() == "ROM")
- myCart.bank(bank, segment);
- else
- myCart.bank(bank + myCart.romBankCount(), segment);
-
- myCart.lockBank();
- invalidate();
- updateUIState();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -234,8 +245,3 @@ string Cartridge3EPlusWidget::internalRamDescription()
return desc.str();
}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-const std::array Cartridge3EPlusWidget::bankEnum = {
- kBank0Changed, kBank1Changed, kBank2Changed, kBank3Changed
-};
diff --git a/src/debugger/gui/Cart3EPlusWidget.hxx b/src/debugger/gui/Cart3EPlusWidget.hxx
index 7cde61042..44473e0cf 100644
--- a/src/debugger/gui/Cart3EPlusWidget.hxx
+++ b/src/debugger/gui/Cart3EPlusWidget.hxx
@@ -56,13 +56,10 @@ class Cartridge3EPlusWidget : public CartridgeEnhancedWidget
std::array myBankCommit{nullptr};
std::array myBankState{nullptr};
- enum BankID {
- kBank0Changed = 'b0CH',
- kBank1Changed = 'b1CH',
- kBank2Changed = 'b2CH',
- kBank3Changed = 'b3CH'
+ enum {
+ kRomRamChanged = 'rrCh',
+ kChangeBank = 'chBk',
};
- static const std::array bankEnum;
private:
// Following constructors and assignment operators not supported
diff --git a/src/debugger/gui/Cart3EWidget.cxx b/src/debugger/gui/Cart3EWidget.cxx
index 4683ea7d4..910f03368 100644
--- a/src/debugger/gui/Cart3EWidget.cxx
+++ b/src/debugger/gui/Cart3EWidget.cxx
@@ -33,7 +33,7 @@ string Cartridge3EWidget::description()
{
ostringstream info;
size_t size;
- const uInt8* image = myCart.getImage(size);
+ const ByteBuffer& image = myCart.getImage(size);
uInt16 numRomBanks = myCart.romBankCount();
uInt16 numRamBanks = myCart.ramBankCount();
diff --git a/src/debugger/gui/Cart3FWidget.cxx b/src/debugger/gui/Cart3FWidget.cxx
index ff5b0d219..a84f0fd4f 100644
--- a/src/debugger/gui/Cart3FWidget.cxx
+++ b/src/debugger/gui/Cart3FWidget.cxx
@@ -33,7 +33,7 @@ string Cartridge3FWidget::description()
{
ostringstream info;
size_t size;
- const uInt8* image = myCart.getImage(size);
+ const ByteBuffer& image = myCart.getImage(size);
info << "Tigervision 3F cartridge, 2 - 256 2K banks\n"
<< "First 2K bank selected by writing to " << hotspotStr() << "\n"
diff --git a/src/debugger/gui/CartEnhancedWidget.cxx b/src/debugger/gui/CartEnhancedWidget.cxx
index 0bf38f529..97beb1f6b 100644
--- a/src/debugger/gui/CartEnhancedWidget.cxx
+++ b/src/debugger/gui/CartEnhancedWidget.cxx
@@ -94,7 +94,7 @@ string CartridgeEnhancedWidget::romDescription()
{
ostringstream info;
size_t size;
- const uInt8* image = myCart.getImage(size);
+ const ByteBuffer& image = myCart.getImage(size);
if(myCart.romBankCount() > 1)
{
@@ -125,7 +125,7 @@ string CartridgeEnhancedWidget::romDescription()
start -= start % std::min(int(size), 0x1000);
end = start + uInt16(myCart.mySize) - 1;
// special check for ROMs where the extra RAM is not included in the image (e.g. CV).
- if((start & 0xFFF) < size)
+ if((start & 0xFFFU) < size)
{
start += myCart.myRomOffset;
}
diff --git a/src/debugger/gui/CartRamWidget.cxx b/src/debugger/gui/CartRamWidget.cxx
index 84cc8b9ab..76c8e972a 100644
--- a/src/debugger/gui/CartRamWidget.cxx
+++ b/src/debugger/gui/CartRamWidget.cxx
@@ -74,7 +74,6 @@ CartRamWidget::CartRamWidget(
myDesc->setEditable(false);
myDesc->setEnabled(false);
myDesc->setList(sl);
- addFocusWidget(myDesc);
ypos += myDesc->getHeight() + myFontHeight / 2;
diff --git a/src/debugger/gui/CartTVBoyWidget.cxx b/src/debugger/gui/CartTVBoyWidget.cxx
new file mode 100644
index 000000000..5012642ba
--- /dev/null
+++ b/src/debugger/gui/CartTVBoyWidget.cxx
@@ -0,0 +1,79 @@
+//============================================================================
+//
+// 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-2020 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 "CartTVBoy.hxx"
+#include "PopUpWidget.hxx"
+#include "CartTVBoyWidget.hxx"
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CartridgeTVBoyWidget::CartridgeTVBoyWidget(
+ GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont,
+ int x, int y, int w, int h, CartridgeTVBoy& cart)
+ : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart),
+ myCartTVBoy(cart)
+{
+ initialize();
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+string CartridgeTVBoyWidget::description()
+{
+ ostringstream info;
+
+ info << "TV Boy, " << myCart.romBankCount() << " 4K banks\n"
+ << "Hotspots are from $" << Common::Base::HEX2 << 0xf800 << " to $"
+ << Common::Base::HEX2 << (0xf800 + myCart.romBankCount() - 1) << "\n";
+ info << CartridgeEnhancedWidget::description();
+
+ return info.str();
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void CartridgeTVBoyWidget::bankSelect(int& ypos)
+{
+ CartridgeEnhancedWidget::bankSelect(ypos);
+ int xpos = myBankWidgets[0]->getRight() + _font.getMaxCharWidth() * 4;
+ ypos = myBankWidgets[0]->getTop();
+
+ myBankLocked = new CheckboxWidget(_boss, _font, xpos, ypos + 1,
+ "Bankswitching is locked",
+ kBankLocked);
+ myBankLocked->setTarget(this);
+ addFocusWidget(myBankLocked);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void CartridgeTVBoyWidget::loadConfig()
+{
+ myBankWidgets[0]->setEnabled(!myCartTVBoy.myBankingDisabled);
+ myBankLocked->setState(myCartTVBoy.myBankingDisabled);
+
+ CartridgeEnhancedWidget::loadConfig();
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void CartridgeTVBoyWidget::handleCommand(CommandSender* sender,
+ int cmd, int data, int id)
+{
+ if(cmd == kBankLocked)
+ {
+ myCartTVBoy.myBankingDisabled = myBankLocked->getState();
+ myBankWidgets[0]->setEnabled(!myCartTVBoy.myBankingDisabled);
+ }
+ else
+ CartridgeEnhancedWidget::handleCommand(sender, cmd, data, id);
+}
diff --git a/src/debugger/gui/CartTVBoyWidget.hxx b/src/debugger/gui/CartTVBoyWidget.hxx
new file mode 100644
index 000000000..e1c2780e6
--- /dev/null
+++ b/src/debugger/gui/CartTVBoyWidget.hxx
@@ -0,0 +1,62 @@
+//============================================================================
+//
+// 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-2020 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 CARTRIDGETVBOY_WIDGET_HXX
+#define CARTRIDGETVBOY_WIDGET_HXX
+
+class CartridgeTVBoy;
+class CheckboxWidget;
+
+#include "CartEnhancedWidget.hxx"
+
+class CartridgeTVBoyWidget : public CartridgeEnhancedWidget
+{
+ public:
+ CartridgeTVBoyWidget(GuiObject* boss, const GUI::Font& lfont,
+ const GUI::Font& nfont,
+ int x, int y, int w, int h,
+ CartridgeTVBoy& cart);
+ virtual ~CartridgeTVBoyWidget() = default;
+
+ private:
+ string manufacturer() override { return "Akor"; }
+
+ string description() override;
+
+ void bankSelect(int& ypos) override;
+
+ CartridgeTVBoy& myCartTVBoy;
+ CheckboxWidget* myBankLocked{nullptr};
+
+ enum {
+ kBankLocked = 'bkLO'
+ };
+
+ private:
+ void loadConfig() override;
+ void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
+
+ private:
+ // Following constructors and assignment operators not supported
+ CartridgeTVBoyWidget() = delete;
+ CartridgeTVBoyWidget(const CartridgeTVBoyWidget&) = delete;
+ CartridgeTVBoyWidget(CartridgeTVBoyWidget&&) = delete;
+ CartridgeTVBoyWidget& operator=(const CartridgeTVBoyWidget&) = delete;
+ CartridgeTVBoyWidget& operator=(CartridgeTVBoyWidget&&) = delete;
+};
+
+#endif
diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx
index 6674311f6..be9ad7515 100644
--- a/src/debugger/gui/DebuggerDialog.cxx
+++ b/src/debugger/gui/DebuggerDialog.cxx
@@ -251,6 +251,7 @@ void DebuggerDialog::handleCommand(CommandSender* sender, int cmd,
break;
case kDDOptionsCmd:
+ saveConfig();
myOptions->open();
loadConfig();
break;
diff --git a/src/debugger/gui/RomWidget.cxx b/src/debugger/gui/RomWidget.cxx
index 010ae5f0b..52b2e81b8 100644
--- a/src/debugger/gui/RomWidget.cxx
+++ b/src/debugger/gui/RomWidget.cxx
@@ -165,13 +165,16 @@ void RomWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomWidget::toggleBreak(int disasm_line)
{
+ Debugger& debugger = instance().debugger();
const CartDebug::DisassemblyList& list =
- instance().debugger().cartDebug().disassembly().list;
+ debugger.cartDebug().disassembly().list;
+
if(disasm_line >= int(list.size())) return;
- if(list[disasm_line].address != 0 && list[disasm_line].bytes != "")
- instance().debugger().toggleBreakPoint(list[disasm_line].address,
- instance().debugger().cartDebug().getBank(list[disasm_line].address));
+ const uInt16 address = list[disasm_line].address;
+
+ if(address != 0)
+ debugger.toggleBreakPoint(address, debugger.cartDebug().getBank(address));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/debugger/gui/TiaOutputWidget.cxx b/src/debugger/gui/TiaOutputWidget.cxx
index 5277647dc..01d6d094b 100644
--- a/src/debugger/gui/TiaOutputWidget.cxx
+++ b/src/debugger/gui/TiaOutputWidget.cxx
@@ -179,7 +179,7 @@ void TiaOutputWidget::drawWidget(bool hilite)
bool visible = instance().console().tia().electronBeamPos(scanx, scany);
scanoffset = width * scany + scanx;
uInt8* tiaOutputBuffer = instance().console().tia().outputBuffer();
- TIASurface& tiaSurface(instance().frameBuffer().tiaSurface());
+ const TIASurface& tiaSurface = instance().frameBuffer().tiaSurface();
for(uInt32 y = 0, i = yStart * width; y < height; ++y)
{
diff --git a/src/debugger/gui/module.mk b/src/debugger/gui/module.mk
index 8f19ce5fa..d992ae85a 100644
--- a/src/debugger/gui/module.mk
+++ b/src/debugger/gui/module.mk
@@ -48,6 +48,7 @@ MODULE_OBJS := \
src/debugger/gui/CartMDMWidget.o \
src/debugger/gui/CartRamWidget.o \
src/debugger/gui/CartSBWidget.o \
+ src/debugger/gui/CartTVBoyWidget.o \
src/debugger/gui/CartUAWidget.o \
src/debugger/gui/CartWDWidget.o \
src/debugger/gui/CartX07Widget.o \
diff --git a/src/emucore/Bankswitch.cxx b/src/emucore/Bankswitch.cxx
index 1b907eea7..2ea053df1 100644
--- a/src/emucore/Bankswitch.cxx
+++ b/src/emucore/Bankswitch.cxx
@@ -141,6 +141,7 @@ Bankswitch::BSList = {{
{ "FE" , "FE (8K Decathlon)" },
{ "MDM" , "MDM (Menu Driven Megacart)" },
{ "SB" , "SB (128-256K SUPERbank)" },
+ { "TVBOY" , "TV Boy (512K)" },
{ "UA" , "UA (8K UA Ltd.)" },
{ "UASW" , "UASW (8K UA swapped banks)" },
{ "WD" , "WD (Pink Panther)" },
@@ -226,6 +227,8 @@ Bankswitch::ExtensionMap Bankswitch::ourExtensions = {
{ "FE" , Bankswitch::Type::_FE },
{ "MDM" , Bankswitch::Type::_MDM },
{ "SB" , Bankswitch::Type::_SB },
+ { "TVB" , Bankswitch::Type::_TVBOY },
+ { "TVBOY" , Bankswitch::Type::_TVBOY },
{ "UA" , Bankswitch::Type::_UA },
{ "UASW" , Bankswitch::Type::_UASW },
{ "WD" , Bankswitch::Type::_WD },
@@ -282,6 +285,7 @@ Bankswitch::NameToTypeMap Bankswitch::ourNameToTypes = {
{ "FE" , Bankswitch::Type::_FE },
{ "MDM" , Bankswitch::Type::_MDM },
{ "SB" , Bankswitch::Type::_SB },
+ { "TVBOY" , Bankswitch::Type::_TVBOY },
{ "UA" , Bankswitch::Type::_UA },
{ "UASW" , Bankswitch::Type::_UASW },
{ "WD" , Bankswitch::Type::_WD },
diff --git a/src/emucore/Bankswitch.hxx b/src/emucore/Bankswitch.hxx
index 0dd3871c7..6ef5da867 100644
--- a/src/emucore/Bankswitch.hxx
+++ b/src/emucore/Bankswitch.hxx
@@ -38,14 +38,14 @@ class Bankswitch
public:
// Currently supported bankswitch schemes
enum class Type {
- _AUTO, _0840, _2IN1, _4IN1, _8IN1, _16IN1, _32IN1,
- _64IN1, _128IN1, _2K, _3E, _3EX, _3EP, _3F,
- _4A50, _4K, _4KSC, _AR, _BF, _BFSC, _BUS,
- _CDF, _CM, _CTY, _CV, _DF, _DFSC, _DPC,
- _DPCP, _E0, _E7, _E78K, _EF, _EFSC, _F0,
- _F4, _F4SC, _F6, _F6SC, _F8, _F8SC, _FA,
- _FA2, _FC, _FE, _MDM, _SB, _UA, _UASW,
- _WD, _WDSW, _X07,
+ _AUTO, _0840, _2IN1, _4IN1, _8IN1, _16IN1, _32IN1,
+ _64IN1, _128IN1, _2K, _3E, _3EX, _3EP, _3F,
+ _4A50, _4K, _4KSC, _AR, _BF, _BFSC, _BUS,
+ _CDF, _CM, _CTY, _CV, _DF, _DFSC, _DPC,
+ _DPCP, _E0, _E7, _E78K, _EF, _EFSC, _F0,
+ _F4, _F4SC, _F6, _F6SC, _F8, _F8SC, _FA,
+ _FA2, _FC, _FE, _MDM, _SB, _TVBOY, _UA,
+ _UASW, _WD, _WDSW, _X07,
#ifdef CUSTOM_ARM
_CUSTOM,
#endif
diff --git a/src/emucore/Cart.cxx b/src/emucore/Cart.cxx
index 7639101ff..045d4c784 100644
--- a/src/emucore/Cart.cxx
+++ b/src/emucore/Cart.cxx
@@ -56,14 +56,14 @@ bool Cartridge::saveROM(ofstream& out) const
{
size_t size = 0;
- const uInt8* image = getImage(size);
- if(image == nullptr || size == 0)
+ const ByteBuffer& image = getImage(size);
+ if(size == 0)
{
cerr << "save not supported" << endl;
return false;
}
- out.write(reinterpret_cast(image), size);
+ out.write(reinterpret_cast(image.get()), size);
return true;
}
@@ -80,10 +80,10 @@ bool Cartridge::bankChanged()
uInt16 Cartridge::bankSize(uInt16 bank) const
{
size_t size;
-
getImage(size);
- return std::min(uInt32(size) / romBankCount(), 4_KB); // assuming that each bank has the same size
+ return static_cast(
+ std::min(size / romBankCount(), 4_KB)); // assuming that each bank has the same size
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/Cart.hxx b/src/emucore/Cart.hxx
index b04a95f10..8a2e4656e 100644
--- a/src/emucore/Cart.hxx
+++ b/src/emucore/Cart.hxx
@@ -48,6 +48,9 @@ class Cartridge : public Device
public:
using StartBankFromPropsFunc = std::function;
+ // Maximum size of a ROM cart that Stella can support
+ static constexpr size_t maxSize() { return 512_KB; }
+
public:
/**
Create a new cartridge
@@ -140,7 +143,6 @@ class Cartridge : public Device
*/
uInt16 getIllegalRAMWriteAccess() const { return myRamWriteAccess; }
-
/**
Query the access counters
@@ -169,8 +171,13 @@ class Cartridge : public Device
scheme defines banks in a standard format (ie, 0 for first bank,
1 for second, etc). Carts which will handle their own bankswitching
completely or non-bankswitched carts can ignore this method.
+
+ @param bank The bank that should be installed in the system
+ @param segment The segment the bank should be using
+
+ @return true, if bank has changed
*/
- virtual bool bank(uInt16) { return false; }
+ virtual bool bank(uInt16 bank, uInt16 segment = 0) { return false; }
/**
Get the current bank for the provided address. Carts which have only
@@ -197,7 +204,6 @@ class Cartridge : public Device
*/
virtual uInt16 romBankCount() const { return 1; }
-
/**
Query the number of RAM 'banks' supported by the cartridge. Note that
this information is cart-specific, where each cart basically defines
@@ -226,9 +232,9 @@ class Cartridge : public Device
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
+ @return A reference to the internal ROM image data
*/
- virtual const uInt8* getImage(size_t& size) const = 0;
+ virtual const ByteBuffer& getImage(size_t& size) const = 0;
/**
Get a descriptor for the cart name.
diff --git a/src/emucore/Cart0840.cxx b/src/emucore/Cart0840.cxx
index e071f61a2..c560b0a1b 100644
--- a/src/emucore/Cart0840.cxx
+++ b/src/emucore/Cart0840.cxx
@@ -20,8 +20,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge0840::Cartridge0840(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
}
diff --git a/src/emucore/Cart0840.hxx b/src/emucore/Cart0840.hxx
index af1977485..0d120aad4 100644
--- a/src/emucore/Cart0840.hxx
+++ b/src/emucore/Cart0840.hxx
@@ -44,9 +44,10 @@ class Cartridge0840 : public CartridgeEnhanced
@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
*/
Cartridge0840(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 8_KB);
virtual ~Cartridge0840() = default;
public:
diff --git a/src/emucore/Cart2K.cxx b/src/emucore/Cart2K.cxx
index f4d4ef7bd..d204d93ed 100644
--- a/src/emucore/Cart2K.cxx
+++ b/src/emucore/Cart2K.cxx
@@ -20,12 +20,15 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge2K::Cartridge2K(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
+ // When creating a 2K cart, we always initially create a buffer of size 2_KB
+ // Sometimes we only use a portion of that buffer; we check for that now
+
// Size can be a maximum of 2K
- if(size > 2_KB)
- size = 2_KB;
+ size = std::min(size, bsSize);
// Set image size to closest power-of-two for the given size
mySize = 1; myBankShift = 0;
@@ -35,24 +38,14 @@ Cartridge2K::Cartridge2K(const ByteBuffer& image, size_t size,
myBankShift++;
}
- // Initialize ROM with illegal 6502 opcode that causes a real 6502 to jam
- size_t bufSize = std::max(mySize, System::PAGE_SIZE);
- myImage = make_unique(bufSize);
- std::fill_n(myImage.get(), bufSize, 0x02);
-
// Handle cases where ROM is smaller than the page size
// It's much easier to do it this way rather than changing the page size
- if(mySize >= System::PAGE_SIZE)
- {
- // Directly copy the ROM image into the buffer
- std::copy_n(image.get(), mySize, myImage.get());
- }
- else
+ if(mySize < System::PAGE_SIZE)
{
// Manually 'mirror' the ROM image into the buffer
for(size_t i = 0; i < System::PAGE_SIZE; i += mySize)
std::copy_n(image.get(), mySize, myImage.get() + i);
mySize = System::PAGE_SIZE;
- myBankShift = 6;
+ myBankShift = System::PAGE_SHIFT;
}
}
diff --git a/src/emucore/Cart2K.hxx b/src/emucore/Cart2K.hxx
index 0ed6fedef..878df4714 100644
--- a/src/emucore/Cart2K.hxx
+++ b/src/emucore/Cart2K.hxx
@@ -47,9 +47,10 @@ class Cartridge2K : public CartridgeEnhanced
@param size The size of the ROM image (<= 2048 bytes)
@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
*/
Cartridge2K(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 2_KB);
virtual ~Cartridge2K() = default;
public:
diff --git a/src/emucore/Cart3E.cxx b/src/emucore/Cart3E.cxx
index be69d105d..e3d049eea 100644
--- a/src/emucore/Cart3E.cxx
+++ b/src/emucore/Cart3E.cxx
@@ -21,8 +21,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge3E::Cartridge3E(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings,
+ bsSize == 0 ? BSPF::nextMultipleOf(size, 2_KB) : bsSize)
{
myBankShift = BANK_SHIFT;
myRamSize = RAM_SIZE;
diff --git a/src/emucore/Cart3E.hxx b/src/emucore/Cart3E.hxx
index f2ead51f5..60e50613a 100644
--- a/src/emucore/Cart3E.hxx
+++ b/src/emucore/Cart3E.hxx
@@ -65,15 +65,17 @@ class Cartridge3E : public CartridgeEnhanced
public:
/**
- Create a new cartridge using the specified image and size
+ Create a new cartridge using the specified image and size.
@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
+ (where 0 means variable-sized ROM)
*/
Cartridge3E(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 0);
virtual ~Cartridge3E() = default;
public:
diff --git a/src/emucore/Cart3EPlus.cxx b/src/emucore/Cart3EPlus.cxx
index 6c9fe7c2a..2233b0d71 100644
--- a/src/emucore/Cart3EPlus.cxx
+++ b/src/emucore/Cart3EPlus.cxx
@@ -21,8 +21,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge3EPlus::Cartridge3EPlus(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : Cartridge3E(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : Cartridge3E(image, size, md5, settings,
+ bsSize == 0 ? BSPF::nextMultipleOf(size, 1_KB) : bsSize)
{
myBankShift = BANK_SHIFT;
myRamSize = RAM_SIZE;
@@ -34,7 +36,7 @@ void Cartridge3EPlus::reset()
{
CartridgeEnhanced::reset();
- // 1st segment in mapped to start bank in CartridgeEnhanced
+ bank(mySystem->randGenerator().next() % romBankCount(), 0);
bank(mySystem->randGenerator().next() % romBankCount(), 1);
bank(mySystem->randGenerator().next() % romBankCount(), 2);
bank(startBank(), 3);
diff --git a/src/emucore/Cart3EPlus.hxx b/src/emucore/Cart3EPlus.hxx
index fe6a0a263..2ba54d313 100644
--- a/src/emucore/Cart3EPlus.hxx
+++ b/src/emucore/Cart3EPlus.hxx
@@ -42,7 +42,7 @@ class System;
ROM:
- Note: in descriptions $F000 is equivalent to $1000 -- that is, we only deal
+ Note: In descriptions $F000 is equivalent to $1000 -- that is, we only deal
with the low 13 bits of addressing. Stella code uses $1000, I'm used to $F000
So, mask with top bits clear :) when reading this document.
@@ -51,16 +51,10 @@ class System;
The last 1K ROM ($FC00-$FFFF) segment in the 6502 address space (ie: $1C00-$1FFF)
is initialised to point to the FIRST 1K of the ROM image, so the reset vectors
- must be placed at the end of the first 1K in the ROM image. Note, this is
- DIFFERENT to 3E which switches in the UPPER bank and this bank is fixed. This
- allows variable sized ROM without having to detect size. First bank (0) in ROM is
- the default fixed bank mapped to $FC00.
+ must be placed at the end of the first 1K in the ROM image.
- The system requires the reset vectors to be valid on a reset, so either the
- hardware first switches in the first bank, or the programmer must ensure
- that the reset vector is present in ALL ROM banks which might be switched
- into the last bank area. Currently the latter (programmer onus) is required,
- but it would be nice for the cartridge hardware to auto-switch on reset.
+ Note: This is DIFFERENT to 3E which switches in the UPPER bank and this bank is
+ fixed. This allows variable sized ROM without having to detect size.
ROM switching (write of block+bank number to $3F) D7D6 upper 2 bits of bank #
indicates the destination segment (0-3, corresponding to $F000, $F400, $F800,
@@ -100,9 +94,11 @@ class Cartridge3EPlus: public Cartridge3E
@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
+ (where 0 means variable-sized ROM)
*/
Cartridge3EPlus(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 0);
virtual ~Cartridge3EPlus() = default;
public:
diff --git a/src/emucore/Cart3F.cxx b/src/emucore/Cart3F.cxx
index 21b21b9c7..a44c28a5e 100644
--- a/src/emucore/Cart3F.cxx
+++ b/src/emucore/Cart3F.cxx
@@ -21,8 +21,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge3F::Cartridge3F(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings,
+ bsSize == 0 ? BSPF::nextPowerOfTwo(size) : bsSize)
{
myBankShift = BANK_SHIFT;
}
diff --git a/src/emucore/Cart3F.hxx b/src/emucore/Cart3F.hxx
index 7bdcbd99c..f5eeac809 100644
--- a/src/emucore/Cart3F.hxx
+++ b/src/emucore/Cart3F.hxx
@@ -50,9 +50,11 @@ class Cartridge3F : public CartridgeEnhanced
@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
+ (where 0 means variable-sized ROM)
*/
Cartridge3F(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 0);
virtual ~Cartridge3F() = default;
public:
diff --git a/src/emucore/Cart4A50.cxx b/src/emucore/Cart4A50.cxx
index 845229bc4..6939bc0ef 100644
--- a/src/emucore/Cart4A50.cxx
+++ b/src/emucore/Cart4A50.cxx
@@ -24,6 +24,7 @@
Cartridge4A50::Cartridge4A50(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
: Cartridge(settings, md5),
+ myImage(make_unique(128_KB)),
mySize(size)
{
// Copy the ROM image into my buffer
@@ -32,7 +33,7 @@ Cartridge4A50::Cartridge4A50(const ByteBuffer& image, size_t size,
else if(size < 128_KB) size = 64_KB;
else size = 128_KB;
for(uInt32 slice = 0; slice < 128_KB / size; ++slice)
- std::copy_n(image.get(), size, myImage.begin() + (slice*size));
+ std::copy_n(image.get(), size, myImage.get() + (slice*size));
// We use System::PageAccess.romAccessBase, but don't allow its use
// through a pointer, since the address space of 4A50 carts can change
@@ -41,7 +42,7 @@ Cartridge4A50::Cartridge4A50(const ByteBuffer& image, size_t size,
//
// Instead, access will be through the getAccessFlags and setAccessFlags
// methods below
- createRomAccessArrays(myImage.size() + myRAM.size());
+ createRomAccessArrays(128_KB + myRAM.size());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -350,10 +351,10 @@ bool Cartridge4A50::patch(uInt16 address, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-const uInt8* Cartridge4A50::getImage(size_t& size) const
+const ByteBuffer& Cartridge4A50::getImage(size_t& size) const
{
size = mySize;
- return myImage.data();
+ return myImage;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/Cart4A50.hxx b/src/emucore/Cart4A50.hxx
index e68bb8f4a..8a4fdaa2d 100644
--- a/src/emucore/Cart4A50.hxx
+++ b/src/emucore/Cart4A50.hxx
@@ -96,9 +96,9 @@ class Cartridge4A50 : public Cartridge
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
+ @return A reference to the internal ROM image data
*/
- const uInt8* getImage(size_t& size) const override;
+ const ByteBuffer& getImage(size_t& size) const override;
/**
Save the current state of this cart to the given Serializer.
@@ -220,7 +220,7 @@ class Cartridge4A50 : public Cartridge
private:
// The 128K ROM image of the cartridge
- std::array myImage;
+ ByteBuffer myImage;
// The 32K of RAM on the cartridge
std::array myRAM;
diff --git a/src/emucore/Cart4K.cxx b/src/emucore/Cart4K.cxx
index 9e684afad..830cffd49 100644
--- a/src/emucore/Cart4K.cxx
+++ b/src/emucore/Cart4K.cxx
@@ -20,7 +20,8 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge4K::Cartridge4K(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
}
diff --git a/src/emucore/Cart4K.hxx b/src/emucore/Cart4K.hxx
index 1a7c428f4..cc2bb5aef 100644
--- a/src/emucore/Cart4K.hxx
+++ b/src/emucore/Cart4K.hxx
@@ -44,9 +44,10 @@ class Cartridge4K : public CartridgeEnhanced
@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
*/
Cartridge4K(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 4_KB);
virtual ~Cartridge4K() = default;
public:
diff --git a/src/emucore/Cart4KSC.cxx b/src/emucore/Cart4KSC.cxx
index 92d2e946e..50ad78e8b 100644
--- a/src/emucore/Cart4KSC.cxx
+++ b/src/emucore/Cart4KSC.cxx
@@ -20,8 +20,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge4KSC::Cartridge4KSC(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : Cartridge4K(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : Cartridge4K(image, size, md5, settings, bsSize)
{
myRamSize = RAM_SIZE;
}
diff --git a/src/emucore/Cart4KSC.hxx b/src/emucore/Cart4KSC.hxx
index 3f28de9ce..a2197e018 100644
--- a/src/emucore/Cart4KSC.hxx
+++ b/src/emucore/Cart4KSC.hxx
@@ -45,9 +45,10 @@ class Cartridge4KSC : public Cartridge4K
@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
*/
Cartridge4KSC(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 4_KB);
virtual ~Cartridge4KSC() = default;
public:
diff --git a/src/emucore/CartAR.cxx b/src/emucore/CartAR.cxx
index a0eea7486..cc58d60be 100644
--- a/src/emucore/CartAR.cxx
+++ b/src/emucore/CartAR.cxx
@@ -392,7 +392,7 @@ void CartridgeAR::loadIntoRAM(uInt8 load)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool CartridgeAR::bank(uInt16 bank)
+bool CartridgeAR::bank(uInt16 bank, uInt16)
{
if(!bankLocked())
return bankConfiguration(uInt8(bank));
@@ -420,10 +420,10 @@ bool CartridgeAR::patch(uInt16 address, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-const uInt8* CartridgeAR::getImage(size_t& size) const
+const ByteBuffer& CartridgeAR::getImage(size_t& size) const
{
size = mySize;
- return myLoadImages.get();
+ return myLoadImages;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/CartAR.hxx b/src/emucore/CartAR.hxx
index 0bc74a291..0b4369f31 100644
--- a/src/emucore/CartAR.hxx
+++ b/src/emucore/CartAR.hxx
@@ -73,9 +73,12 @@ class CartridgeAR : public Cartridge
/**
Install pages for the specified bank in the system.
- @param bank The bank that should be installed in the system
+ @param bank The bank that should be installed in the system
+ @param segment The segment the bank should be using
+
+ @return true, if bank has changed
*/
- bool bank(uInt16 bank) override;
+ bool bank(uInt16 bank, uInt16 segment = 0) override;
/**
Get the current bank.
@@ -102,9 +105,9 @@ class CartridgeAR : public Cartridge
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
+ @return A reference to the internal ROM image data
*/
- const uInt8* getImage(size_t& size) const override;
+ const ByteBuffer& getImage(size_t& size) const override;
/**
Save the current state of this cart to the given Serializer.
diff --git a/src/emucore/CartBF.cxx b/src/emucore/CartBF.cxx
index ce3c53198..cd815c518 100644
--- a/src/emucore/CartBF.cxx
+++ b/src/emucore/CartBF.cxx
@@ -20,8 +20,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeBF::CartridgeBF(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
}
diff --git a/src/emucore/CartBF.hxx b/src/emucore/CartBF.hxx
index 23c51f760..5190f73da 100644
--- a/src/emucore/CartBF.hxx
+++ b/src/emucore/CartBF.hxx
@@ -45,9 +45,10 @@ class CartridgeBF : public CartridgeEnhanced
@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
*/
CartridgeBF(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 256_KB);
virtual ~CartridgeBF() = default;
public:
diff --git a/src/emucore/CartBFSC.cxx b/src/emucore/CartBFSC.cxx
index bd9793893..ac8a105b3 100644
--- a/src/emucore/CartBFSC.cxx
+++ b/src/emucore/CartBFSC.cxx
@@ -20,8 +20,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeBFSC::CartridgeBFSC(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeBF(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeBF(image, size, md5, settings, bsSize)
{
myRamSize = RAM_SIZE;
}
diff --git a/src/emucore/CartBFSC.hxx b/src/emucore/CartBFSC.hxx
index 9bb22aa0a..4a660ecc8 100644
--- a/src/emucore/CartBFSC.hxx
+++ b/src/emucore/CartBFSC.hxx
@@ -45,9 +45,10 @@ class CartridgeBFSC : public CartridgeBF
@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
*/
CartridgeBFSC(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 256_KB);
virtual ~CartridgeBFSC() = default;
/**
diff --git a/src/emucore/CartBUS.cxx b/src/emucore/CartBUS.cxx
index e2eb9b74a..46d220bbf 100644
--- a/src/emucore/CartBUS.cxx
+++ b/src/emucore/CartBUS.cxx
@@ -43,17 +43,18 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeBUS::CartridgeBUS(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
- : Cartridge(settings, md5)
+ : Cartridge(settings, md5),
+ myImage(make_unique(32_KB))
{
// Copy the ROM image into my buffer
- std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
+ std::copy_n(image.get(), std::min(32_KB, size), myImage.get());
// Even though the ROM is 32K, only 28K is accessible to the 6507
createRomAccessArrays(28_KB);
// Pointer to the program ROM (28K @ 0 byte offset)
// which starts after the 2K BUS Driver and 2K C Code
- myProgramImage = myImage.data() + 4_KB;
+ myProgramImage = myImage.get() + 4_KB;
// Pointer to BUS driver in RAM
myDriverImage = myRAM.data();
@@ -64,9 +65,9 @@ CartridgeBUS::CartridgeBUS(const ByteBuffer& image, size_t size,
// Create Thumbulator ARM emulator
bool devSettings = settings.getBool("dev.settings");
myThumbEmulator = make_unique(
- reinterpret_cast(myImage.data()),
+ reinterpret_cast(myImage.get()),
reinterpret_cast(myRAM.data()),
- static_cast(myImage.size()),
+ static_cast(32_KB),
devSettings ? settings.getBool("dev.thumb.trapfatal") : false, Thumbulator::ConfigureFor::BUS, this
);
@@ -95,7 +96,7 @@ void CartridgeBUS::reset()
void CartridgeBUS::setInitialState()
{
// Copy initial BUS driver to Harmony RAM
- std::copy_n(myImage.begin(), 2_KB, myDriverImage);
+ std::copy_n(myImage.get(), 2_KB, myDriverImage);
myMusicWaveformSize.fill(27);
@@ -429,7 +430,7 @@ bool CartridgeBUS::poke(uInt16 address, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool CartridgeBUS::bank(uInt16 bank)
+bool CartridgeBUS::bank(uInt16 bank, uInt16)
{
if(bankLocked()) return false;
@@ -478,10 +479,10 @@ bool CartridgeBUS::patch(uInt16 address, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-const uInt8* CartridgeBUS::getImage(size_t& size) const
+const ByteBuffer& CartridgeBUS::getImage(size_t& size) const
{
- size = myImage.size();
- return myImage.data();
+ size = 32_KB;
+ return myImage;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/CartBUS.hxx b/src/emucore/CartBUS.hxx
index 3ab40f7ec..2e21b5f24 100644
--- a/src/emucore/CartBUS.hxx
+++ b/src/emucore/CartBUS.hxx
@@ -84,9 +84,12 @@ class CartridgeBUS : public Cartridge
/**
Install pages for the specified bank in the system.
- @param bank The bank that should be installed in the system
+ @param bank The bank that should be installed in the system
+ @param segment The segment the bank should be using
+
+ @return true, if bank has changed
*/
- bool bank(uInt16 bank) override;
+ bool bank(uInt16 bank, uInt16 segment = 0) override;
/**
Get the current bank.
@@ -113,9 +116,9 @@ class CartridgeBUS : public Cartridge
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
+ @return A reference to the internal ROM image data
*/
- const uInt8* getImage(size_t& size) const override;
+ const ByteBuffer& getImage(size_t& size) const override;
/**
Save the current state of this cart to the given Serializer.
@@ -211,7 +214,7 @@ class CartridgeBUS : public Cartridge
private:
// The 32K ROM image of the cartridge
- std::array myImage;
+ ByteBuffer myImage;
// Pointer to the 28K program ROM image of the cartridge
uInt8* myProgramImage{nullptr};
diff --git a/src/emucore/CartCDF.cxx b/src/emucore/CartCDF.cxx
index 6f9a5f4f7..e09480464 100644
--- a/src/emucore/CartCDF.cxx
+++ b/src/emucore/CartCDF.cxx
@@ -59,17 +59,19 @@ namespace {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCDF::CartridgeCDF(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
- : Cartridge(settings, md5)
+ : Cartridge(settings, md5),
+ myImage(make_unique(32_KB))
{
// Copy the ROM image into my buffer
- std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
+ std::fill_n(myImage.get(), 32_KB, 0);
+ std::copy_n(image.get(), std::min(32_KB, size), myImage.get());
// even though the ROM is 32K, only 28K is accessible to the 6507
createRomAccessArrays(28_KB);
// Pointer to the program ROM (28K @ 0 byte offset)
// which starts after the 2K CDF Driver and 2K C Code
- myProgramImage = myImage.data() + 4_KB;
+ myProgramImage = myImage.get() + 4_KB;
// Pointer to CDF driver in RAM
myDriverImage = myRAM.data();
@@ -82,9 +84,9 @@ CartridgeCDF::CartridgeCDF(const ByteBuffer& image, size_t size,
// Create Thumbulator ARM emulator
bool devSettings = settings.getBool("dev.settings");
myThumbEmulator = make_unique(
- reinterpret_cast(myImage.data()),
+ reinterpret_cast(myImage.get()),
reinterpret_cast(myRAM.data()),
- static_cast(myImage.size()),
+ static_cast(32_KB),
devSettings ? settings.getBool("dev.thumb.trapfatal") : false, thumulatorConfiguration(myCDFSubtype), this);
setInitialState();
@@ -111,7 +113,7 @@ void CartridgeCDF::reset()
void CartridgeCDF::setInitialState()
{
// Copy initial CDF driver to Harmony RAM
- std::copy_n(myImage.begin(), 2_KB, myDriverImage);
+ std::copy_n(myImage.get(), 2_KB, myDriverImage);
myMusicWaveformSize.fill(27);
@@ -402,7 +404,7 @@ bool CartridgeCDF::poke(uInt16 address, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool CartridgeCDF::bank(uInt16 bank)
+bool CartridgeCDF::bank(uInt16 bank, uInt16)
{
if(bankLocked()) return false;
@@ -451,10 +453,10 @@ bool CartridgeCDF::patch(uInt16 address, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-const uInt8* CartridgeCDF::getImage(size_t& size) const
+const ByteBuffer& CartridgeCDF::getImage(size_t& size) const
{
- size = myImage.size();
- return myImage.data();
+ size = 32_KB;
+ return myImage;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/CartCDF.hxx b/src/emucore/CartCDF.hxx
index 14b1eda26..99374de2b 100644
--- a/src/emucore/CartCDF.hxx
+++ b/src/emucore/CartCDF.hxx
@@ -90,9 +90,12 @@ class CartridgeCDF : public Cartridge
/**
Install pages for the specified bank in the system.
- @param bank The bank that should be installed in the system
+ @param bank The bank that should be installed in the system
+ @param segment The segment the bank should be using
+
+ @return true, if bank has changed
*/
- bool bank(uInt16 bank) override;
+ bool bank(uInt16 bank, uInt16 segment = 0) override;
/**
Get the current bank.
@@ -119,9 +122,9 @@ class CartridgeCDF : public Cartridge
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
+ @return A reference to the internal ROM image data
*/
- const uInt8* getImage(size_t& size) const override;
+ const ByteBuffer& getImage(size_t& size) const override;
/**
Save the current state of this cart to the given Serializer.
@@ -211,7 +214,7 @@ class CartridgeCDF : public Cartridge
private:
// The 32K ROM image of the cartridge
- std::array myImage;
+ ByteBuffer myImage;
// Pointer to the 28K program ROM image of the cartridge
uInt8* myProgramImage{nullptr};
diff --git a/src/emucore/CartCM.cxx b/src/emucore/CartCM.cxx
index 40ec603e5..dbaac7a54 100644
--- a/src/emucore/CartCM.cxx
+++ b/src/emucore/CartCM.cxx
@@ -23,11 +23,12 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCM::CartridgeCM(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
- : Cartridge(settings, md5)
+ : Cartridge(settings, md5),
+ myImage(make_unique(16_KB))
{
// Copy the ROM image into my buffer
- std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
- createRomAccessArrays(myImage.size());
+ std::copy_n(image.get(), std::min(16_KB, size), myImage.get());
+ createRomAccessArrays(16_KB);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -98,7 +99,7 @@ uInt8 CartridgeCM::column() const
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool CartridgeCM::bank(uInt16 bank)
+bool CartridgeCM::bank(uInt16 bank, uInt16)
{
if(bankLocked()) return false;
@@ -184,10 +185,10 @@ bool CartridgeCM::patch(uInt16 address, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-const uInt8* CartridgeCM::getImage(size_t& size) const
+const ByteBuffer& CartridgeCM::getImage(size_t& size) const
{
- size = myImage.size();
- return myImage.data();
+ size = 16_KB;
+ return myImage;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/CartCM.hxx b/src/emucore/CartCM.hxx
index bf8b2586e..3a58889b4 100644
--- a/src/emucore/CartCM.hxx
+++ b/src/emucore/CartCM.hxx
@@ -141,9 +141,12 @@ class CartridgeCM : public Cartridge
/**
Install pages for the specified bank in the system.
- @param bank The bank that should be installed in the system
+ @param bank The bank that should be installed in the system
+ @param segment The segment the bank should be using
+
+ @return true, if bank has changed
*/
- bool bank(uInt16 bank) override;
+ bool bank(uInt16 bank, uInt16 segment = 0) override;
/**
Get the current bank.
@@ -170,9 +173,9 @@ class CartridgeCM : public Cartridge
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
+ @return A reference to the internal ROM image data
*/
- const uInt8* getImage(size_t& size) const override;
+ const ByteBuffer& getImage(size_t& size) const override;
/**
Save the current state of this cart to the given Serializer.
@@ -243,7 +246,7 @@ class CartridgeCM : public Cartridge
shared_ptr myCompuMate;
// The 16K ROM image of the cartridge
- std::array myImage;
+ ByteBuffer myImage;
// The 2K of RAM
std::array myRAM;
diff --git a/src/emucore/CartCTY.cxx b/src/emucore/CartCTY.cxx
index 822473081..67647f89c 100644
--- a/src/emucore/CartCTY.cxx
+++ b/src/emucore/CartCTY.cxx
@@ -24,18 +24,19 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCTY::CartridgeCTY(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
- : Cartridge(settings, md5)
+ : Cartridge(settings, md5),
+ myImage(make_unique(32_KB))
{
// Copy the ROM image into my buffer
- std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
- createRomAccessArrays(myImage.size());
+ std::copy_n(image.get(), std::min(32_KB, size), myImage.get());
+ createRomAccessArrays(32_KB);
// Default to no tune data in case user is utilizing an old ROM
myTuneData.fill(0);
// Extract tune data if it exists
- if(size > myImage.size())
- std::copy_n(image.get() + myImage.size(), size - myImage.size(), myTuneData.begin());
+ if(size > 32_KB)
+ std::copy_n(image.get() + 32_KB, size - 32_KB, myTuneData.begin());
// Point to the first tune
myFrequencyImage = myTuneData.data();
@@ -229,7 +230,7 @@ bool CartridgeCTY::poke(uInt16 address, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool CartridgeCTY::bank(uInt16 bank)
+bool CartridgeCTY::bank(uInt16 bank, uInt16)
{
if(bankLocked()) return false;
@@ -279,10 +280,10 @@ bool CartridgeCTY::patch(uInt16 address, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-const uInt8* CartridgeCTY::getImage(size_t& size) const
+const ByteBuffer& CartridgeCTY::getImage(size_t& size) const
{
- size = myImage.size();
- return myImage.data();
+ size = 32_KB;
+ return myImage;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/CartCTY.hxx b/src/emucore/CartCTY.hxx
index fdd6c1e19..5af3ceff4 100644
--- a/src/emucore/CartCTY.hxx
+++ b/src/emucore/CartCTY.hxx
@@ -139,9 +139,12 @@ class CartridgeCTY : public Cartridge
/**
Install pages for the specified bank in the system.
- @param bank The bank that should be installed in the system
+ @param bank The bank that should be installed in the system
+ @param segment The segment the bank should be using
+
+ @return true, if bank has changed
*/
- bool bank(uInt16 bank) override;
+ bool bank(uInt16 bank, uInt16 segment = 0) override;
/**
Get the current bank.
@@ -168,9 +171,9 @@ class CartridgeCTY : public Cartridge
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
+ @return A reference to the internal ROM image data
*/
- const uInt8* getImage(size_t& size) const override;
+ const ByteBuffer& getImage(size_t& size) const override;
/**
Save the current state of this cart to the given Serializer.
@@ -260,7 +263,7 @@ class CartridgeCTY : public Cartridge
private:
// The 32K ROM image of the cartridge
- std::array myImage;
+ ByteBuffer myImage;
// The 28K ROM image of the music
std::array myTuneData;
diff --git a/src/emucore/CartCV.cxx b/src/emucore/CartCV.cxx
index 8d7ac9d89..8fe746f1a 100644
--- a/src/emucore/CartCV.cxx
+++ b/src/emucore/CartCV.cxx
@@ -20,24 +20,21 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCV::CartridgeCV(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
myBankShift = BANK_SHIFT;
myRamSize = RAM_SIZE;
myRamWpHigh = RAM_HIGH_WP;
- if(mySize == 4_KB)
+ if(size == 4_KB)
{
// The game has something saved in the RAM
// Useful for MagiCard program listings
- // Allocate array for the ROM image
- mySize = 2_KB;
- myImage = make_unique(mySize);
-
// Copy the ROM image into my buffer
- std::copy_n(image.get() + mySize, mySize, myImage.get());
+ std::copy_n(image.get() + 2_KB, 2_KB, myImage.get());
myInitialRAM = make_unique(1_KB);
// Copy the RAM image into a buffer for use in reset()
diff --git a/src/emucore/CartCV.hxx b/src/emucore/CartCV.hxx
index a5403b19f..809d9b373 100644
--- a/src/emucore/CartCV.hxx
+++ b/src/emucore/CartCV.hxx
@@ -47,9 +47,10 @@ class CartridgeCV : public CartridgeEnhanced
@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
*/
CartridgeCV(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 2_KB);
virtual ~CartridgeCV() = default;
public:
diff --git a/src/emucore/CartCreator.cxx b/src/emucore/CartCreator.cxx
new file mode 100644
index 000000000..fe7faed55
--- /dev/null
+++ b/src/emucore/CartCreator.cxx
@@ -0,0 +1,348 @@
+//============================================================================
+//
+// 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-2020 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 "bspf.hxx"
+#include "Cart.hxx"
+#include "Cart0840.hxx"
+#include "Cart2K.hxx"
+#include "Cart3E.hxx"
+#include "Cart3EX.hxx"
+#include "Cart3EPlus.hxx"
+#include "Cart3F.hxx"
+#include "Cart4A50.hxx"
+#include "Cart4K.hxx"
+#include "Cart4KSC.hxx"
+#include "CartAR.hxx"
+#include "CartBF.hxx"
+#include "CartBFSC.hxx"
+#include "CartBUS.hxx"
+#include "CartCDF.hxx"
+#include "CartCM.hxx"
+#include "CartCTY.hxx"
+#include "CartCV.hxx"
+#include "CartDF.hxx"
+#include "CartDFSC.hxx"
+#include "CartDPC.hxx"
+#include "CartDPCPlus.hxx"
+#include "CartE0.hxx"
+#include "CartE7.hxx"
+#include "CartE78K.hxx"
+#include "CartEF.hxx"
+#include "CartEFSC.hxx"
+#include "CartF0.hxx"
+#include "CartF4.hxx"
+#include "CartF4SC.hxx"
+#include "CartF6.hxx"
+#include "CartF6SC.hxx"
+#include "CartF8.hxx"
+#include "CartF8SC.hxx"
+#include "CartFA.hxx"
+#include "CartFA2.hxx"
+#include "CartFC.hxx"
+#include "CartFE.hxx"
+#include "CartMDM.hxx"
+#include "CartSB.hxx"
+#include "CartTVBoy.hxx"
+#include "CartUA.hxx"
+#include "CartWD.hxx"
+#include "CartX07.hxx"
+#include "MD5.hxx"
+#include "Props.hxx"
+#include "Logger.hxx"
+#include "OSystem.hxx"
+
+#include "CartDetector.hxx"
+#include "CartCreator.hxx"
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+unique_ptr CartCreator::create(const FilesystemNode& file,
+ const ByteBuffer& image, size_t size, string& md5,
+ const string& propertiesType, Settings& settings)
+{
+ unique_ptr cartridge;
+ Bankswitch::Type type = Bankswitch::nameToType(propertiesType),
+ detectedType = type;
+ string id;
+
+ // Collect some info about the ROM
+ ostringstream buf;
+
+ // First inspect the file extension itself
+ // If a valid type is found, it will override the one passed into this method
+ Bankswitch::Type typeByName = Bankswitch::typeFromExtension(file);
+ if(typeByName != Bankswitch::Type::_AUTO)
+ type = detectedType = typeByName;
+
+ // See if we should try to auto-detect the cartridge type
+ // If we ask for extended info, always do an autodetect
+ if(type == Bankswitch::Type::_AUTO || settings.getBool("rominfo"))
+ {
+ detectedType = CartDetector::autodetectType(image, size);
+ if(type != Bankswitch::Type::_AUTO && type != detectedType)
+ cerr << "Auto-detection not consistent: "
+ << Bankswitch::typeToName(type) << ", "
+ << Bankswitch::typeToName(detectedType) << endl;
+
+ type = detectedType;
+ buf << Bankswitch::typeToName(type) << "*";
+ }
+ else
+ buf << Bankswitch::typeToName(type);
+
+ // Check for multicart first; if found, get the correct part of the image
+ switch(type)
+ {
+ case Bankswitch::Type::_2IN1:
+ // Make sure we have a valid sized image
+ if(size == 2*2_KB || size == 2*4_KB || size == 2*8_KB || size == 2*16_KB)
+ {
+ cartridge =
+ createFromMultiCart(image, size, 2, md5, detectedType, id, settings);
+ buf << id;
+ }
+ else
+ throw runtime_error("Invalid cart size for type '" +
+ Bankswitch::typeToName(type) + "'");
+ break;
+
+ case Bankswitch::Type::_4IN1:
+ // Make sure we have a valid sized image
+ if(size == 4*2_KB || size == 4*4_KB || size == 4*8_KB)
+ {
+ cartridge =
+ createFromMultiCart(image, size, 4, md5, detectedType, id, settings);
+ buf << id;
+ }
+ else
+ throw runtime_error("Invalid cart size for type '" +
+ Bankswitch::typeToName(type) + "'");
+ break;
+
+ case Bankswitch::Type::_8IN1:
+ // Make sure we have a valid sized image
+ if(size == 8*2_KB || size == 8*4_KB || size == 8*8_KB)
+ {
+ cartridge =
+ createFromMultiCart(image, size, 8, md5, detectedType, id, settings);
+ buf << id;
+ }
+ else
+ throw runtime_error("Invalid cart size for type '" +
+ Bankswitch::typeToName(type) + "'");
+ break;
+
+ case Bankswitch::Type::_16IN1:
+ // Make sure we have a valid sized image
+ if(size == 16*2_KB || size == 16*4_KB || size == 16*8_KB)
+ {
+ cartridge =
+ createFromMultiCart(image, size, 16, md5, detectedType, id, settings);
+ buf << id;
+ }
+ else
+ throw runtime_error("Invalid cart size for type '" +
+ Bankswitch::typeToName(type) + "'");
+ break;
+
+ case Bankswitch::Type::_32IN1:
+ // Make sure we have a valid sized image
+ if(size == 32*2_KB || size == 32*4_KB)
+ {
+ cartridge =
+ createFromMultiCart(image, size, 32, md5, detectedType, id, settings);
+ buf << id;
+ }
+ else
+ throw runtime_error("Invalid cart size for type '" +
+ Bankswitch::typeToName(type) + "'");
+ break;
+
+ case Bankswitch::Type::_64IN1:
+ // Make sure we have a valid sized image
+ if(size == 64*2_KB || size == 64*4_KB)
+ {
+ cartridge =
+ createFromMultiCart(image, size, 64, md5, detectedType, id, settings);
+ buf << id;
+ }
+ else
+ throw runtime_error("Invalid cart size for type '" +
+ Bankswitch::typeToName(type) + "'");
+ break;
+
+ case Bankswitch::Type::_128IN1:
+ // Make sure we have a valid sized image
+ if(size == 128*2_KB || size == 128*4_KB)
+ {
+ cartridge =
+ createFromMultiCart(image, size, 128, md5, detectedType, id, settings);
+ buf << id;
+ }
+ else
+ throw runtime_error("Invalid cart size for type '" +
+ Bankswitch::typeToName(type) + "'");
+ break;
+
+ default:
+ cartridge = createFromImage(image, size, detectedType, md5, settings);
+ break;
+ }
+
+ if(size < 1_KB)
+ buf << " (" << size << "B) ";
+ else
+ buf << " (" << (size/1_KB) << "K) ";
+
+ cartridge->setAbout(buf.str(), Bankswitch::typeToName(type), id);
+
+ return cartridge;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+unique_ptr
+CartCreator::createFromMultiCart(const ByteBuffer& image, size_t& size,
+ uInt32 numroms, string& md5, Bankswitch::Type type, string& id, Settings& settings)
+{
+ // Get a piece of the larger image
+ uInt32 i = settings.getInt("romloadcount");
+
+ // Move to the next game
+ if(!settings.getBool("romloadprev"))
+ i = (i + 1) % numroms;
+ else
+ i = (i - 1) % numroms;
+ settings.setValue("romloadcount", i);
+
+ size /= numroms;
+ ByteBuffer slice = make_unique(size);
+ std::copy_n(image.get()+i*size, size, slice.get());
+
+ // We need a new md5 and name
+ md5 = MD5::hash(slice, uInt32(size)); // FIXME
+ ostringstream buf;
+ buf << " [G" << (i+1) << "]";
+ id = buf.str();
+
+ if(size <= 2_KB) type = Bankswitch::Type::_2K;
+ else if(size == 4_KB) type = Bankswitch::Type::_4K;
+ else if(size == 8_KB) type = Bankswitch::Type::_F8;
+ else /* default */ type = Bankswitch::Type::_4K;
+
+ return createFromImage(slice, size, type, md5, settings);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+unique_ptr
+CartCreator::createFromImage(const ByteBuffer& image, size_t size, Bankswitch::Type type,
+ const string& md5, Settings& settings)
+{
+ // We should know the cart's type by now so let's create it
+ switch(type)
+ {
+ case Bankswitch::Type::_0840:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_2K:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_3E:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_3EX:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_3EP:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_3F:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_4A50:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_4K:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_4KSC:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_AR:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_BF:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_BFSC:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_BUS:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_CDF:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_CM:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_CTY:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_CV:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_DF:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_DFSC:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_DPC:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_DPCP:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_E0:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_E7:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_E78K:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_EF:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_EFSC:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_F0:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_F4:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_F4SC:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_F6:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_F6SC:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_F8:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_F8SC:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_FA:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_FA2:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_FC:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_FE:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_MDM:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_UA:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_UASW:
+ return make_unique(image, size, md5, settings, true);
+ case Bankswitch::Type::_SB:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_TVBOY:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_WD:
+ case Bankswitch::Type::_WDSW:
+ return make_unique(image, size, md5, settings);
+ case Bankswitch::Type::_X07:
+ return make_unique(image, size, md5, settings);
+ default:
+ return nullptr; // The remaining types have already been handled
+ }
+}
diff --git a/src/emucore/CartCreator.hxx b/src/emucore/CartCreator.hxx
new file mode 100644
index 000000000..757d306ba
--- /dev/null
+++ b/src/emucore/CartCreator.hxx
@@ -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-2020 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 CARTRIDGE_CREATOR_HXX
+#define CARTRIDGE_CREATOR_HXX
+
+class Cartridge;
+class Properties;
+class Settings;
+
+#include "Bankswitch.hxx"
+#include "bspf.hxx"
+
+/**
+ Create a cartridge based on the given information. Internally, it will
+ use autodetection and various heuristics to determine the cart type.
+
+ @author Stephen Anthony
+*/
+class CartCreator
+{
+ public:
+ /**
+ Create a new cartridge object allocated on the heap. The
+ type of cartridge created depends on the properties object.
+
+ @param image A pointer to the ROM image
+ @param size The size of the ROM image
+ @param md5 The md5sum for the given ROM image (can be updated)
+ @param dtype The detected bankswitch type of the ROM image
+ @param settings The settings container
+ @return Pointer to the new cartridge object allocated on the heap
+ */
+ static unique_ptr create(const FilesystemNode& file,
+ const ByteBuffer& image, size_t size, string& md5,
+ const string& dtype, Settings& settings);
+
+ private:
+ /**
+ Create a cartridge from a multi-cart image pointer; internally this
+ takes a slice of the ROM image ues that for the cartridge.
+
+ @param image A pointer to the complete ROM image
+ @param size The size of the ROM image slice
+ @param numroms The number of ROMs in the multicart
+ @param md5 The md5sum for the slice of the ROM image
+ @param type The detected type of the slice of the ROM image
+ @param id The ID for the slice of the ROM image
+ @param settings The settings container
+
+ @return Pointer to the new cartridge object allocated on the heap
+ */
+ static unique_ptr
+ createFromMultiCart(const ByteBuffer& image, size_t& size,
+ uInt32 numroms, string& md5, Bankswitch::Type type, string& id,
+ Settings& settings);
+
+ /**
+ Create a cartridge from the entire image pointer.
+
+ @param image A pointer to the complete ROM image
+ @param size The size of the ROM image
+ @param type The bankswitch type of the ROM image
+ @param md5 The md5sum for the ROM image
+ @param settings The settings container
+
+ @return Pointer to the new cartridge object allocated on the heap
+ */
+ static unique_ptr
+ createFromImage(const ByteBuffer& image, size_t size, Bankswitch::Type type,
+ const string& md5, Settings& settings);
+
+ private:
+ // Following constructors and assignment operators not supported
+ CartCreator() = delete;
+ CartCreator(const CartCreator&) = delete;
+ CartCreator(CartCreator&&) = delete;
+ CartCreator& operator=(const CartCreator&) = delete;
+ CartCreator& operator=(CartCreator&&) = delete;
+};
+
+#endif
diff --git a/src/emucore/CartDF.cxx b/src/emucore/CartDF.cxx
index 0f4d9a1ca..58206a3b5 100644
--- a/src/emucore/CartDF.cxx
+++ b/src/emucore/CartDF.cxx
@@ -20,8 +20,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDF::CartridgeDF(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
}
diff --git a/src/emucore/CartDF.hxx b/src/emucore/CartDF.hxx
index 3c33e8bff..18d0f2489 100644
--- a/src/emucore/CartDF.hxx
+++ b/src/emucore/CartDF.hxx
@@ -45,9 +45,10 @@ class CartridgeDF : public CartridgeEnhanced
@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
*/
CartridgeDF(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 128_KB);
virtual ~CartridgeDF() = default;
public:
diff --git a/src/emucore/CartDFSC.cxx b/src/emucore/CartDFSC.cxx
index f759136a7..4dafe3bb7 100644
--- a/src/emucore/CartDFSC.cxx
+++ b/src/emucore/CartDFSC.cxx
@@ -20,8 +20,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDFSC::CartridgeDFSC(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeDF(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeDF(image, size, md5, settings, bsSize)
{
myRamSize = RAM_SIZE;
}
diff --git a/src/emucore/CartDFSC.hxx b/src/emucore/CartDFSC.hxx
index 637dde3da..efc6d30e8 100644
--- a/src/emucore/CartDFSC.hxx
+++ b/src/emucore/CartDFSC.hxx
@@ -45,9 +45,10 @@ class CartridgeDFSC : public CartridgeDF
@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
*/
CartridgeDFSC(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 128_KB);
virtual ~CartridgeDFSC() = default;
public:
diff --git a/src/emucore/CartDPC.cxx b/src/emucore/CartDPC.cxx
index bc8962b1b..c77aacd8a 100644
--- a/src/emucore/CartDPC.cxx
+++ b/src/emucore/CartDPC.cxx
@@ -22,8 +22,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDPC::CartridgeDPC(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeF8(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeF8(image, size, md5, settings, bsSize)
{
}
diff --git a/src/emucore/CartDPC.hxx b/src/emucore/CartDPC.hxx
index e0a1b866e..4d90fb140 100644
--- a/src/emucore/CartDPC.hxx
+++ b/src/emucore/CartDPC.hxx
@@ -46,9 +46,10 @@ class CartridgeDPC : public CartridgeF8
@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
*/
CartridgeDPC(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 10_KB);
virtual ~CartridgeDPC() = default;
public:
diff --git a/src/emucore/CartDPCPlus.cxx b/src/emucore/CartDPCPlus.cxx
index b71f5a8c0..71500ee94 100644
--- a/src/emucore/CartDPCPlus.cxx
+++ b/src/emucore/CartDPCPlus.cxx
@@ -29,17 +29,18 @@
CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
: Cartridge(settings, md5),
- mySize(std::min(size, myImage.size()))
+ myImage(make_unique(32_KB)),
+ mySize(std::min(size, 32_KB))
{
- // Image is always 32K, but in the case of ROM > 29K, the image is
+ // Image is always 32K, but in the case of ROM < 32K, the image is
// copied to the end of the buffer
- if(mySize < myImage.size())
- myImage.fill(0);
- std::copy_n(image.get(), size, myImage.begin() + (myImage.size() - mySize));
+ if(mySize < 32_KB)
+ std::fill_n(myImage.get(), mySize, 0);
+ std::copy_n(image.get(), size, myImage.get() + (32_KB - mySize));
createRomAccessArrays(24_KB);
// Pointer to the program ROM (24K @ 3K offset; ignore first 3K)
- myProgramImage = myImage.data() + 3_KB;
+ myProgramImage = myImage.get() + 3_KB;
// Pointer to the display RAM
myDisplayImage = myDPCRAM.data() + 3_KB;
@@ -50,9 +51,9 @@ CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size,
// Create Thumbulator ARM emulator
bool devSettings = settings.getBool("dev.settings");
myThumbEmulator = make_unique
- (reinterpret_cast(myImage.data()),
+ (reinterpret_cast(myImage.get()),
reinterpret_cast(myDPCRAM.data()),
- static_cast(myImage.size()),
+ static_cast(32_KB),
devSettings ? settings.getBool("dev.thumb.trapfatal") : false,
Thumbulator::ConfigureFor::DPCplus,
this);
@@ -591,7 +592,7 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool CartridgeDPCPlus::bank(uInt16 bank)
+bool CartridgeDPCPlus::bank(uInt16 bank, uInt16)
{
if(bankLocked()) return false;
@@ -640,10 +641,10 @@ bool CartridgeDPCPlus::patch(uInt16 address, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-const uInt8* CartridgeDPCPlus::getImage(size_t& size) const
+const ByteBuffer& CartridgeDPCPlus::getImage(size_t& size) const
{
size = mySize;
- return myImage.data() + (myImage.size() - mySize);
+ return myImage;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/CartDPCPlus.hxx b/src/emucore/CartDPCPlus.hxx
index 9617d6545..04a1b0de4 100644
--- a/src/emucore/CartDPCPlus.hxx
+++ b/src/emucore/CartDPCPlus.hxx
@@ -86,9 +86,12 @@ class CartridgeDPCPlus : public Cartridge
/**
Install pages for the specified bank in the system.
- @param bank The bank that should be installed in the system
+ @param bank The bank that should be installed in the system
+ @param segment The segment the bank should be using
+
+ @return true, if bank has changed
*/
- bool bank(uInt16 bank) override;
+ bool bank(uInt16 bank, uInt16 segment = 0) override;
/**
Get the current bank.
@@ -115,9 +118,9 @@ class CartridgeDPCPlus : public Cartridge
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
+ @return A reference to the internal ROM image data
*/
- const uInt8* getImage(size_t& size) const override;
+ const ByteBuffer& getImage(size_t& size) const override;
/**
Save the current state of this cart to the given Serializer.
@@ -200,7 +203,7 @@ class CartridgeDPCPlus : public Cartridge
private:
// The ROM image and size
- std::array myImage;
+ ByteBuffer myImage;
size_t mySize{0};
// Pointer to the 24K program ROM image of the cartridge
diff --git a/src/emucore/CartDetector.cxx b/src/emucore/CartDetector.cxx
index 976d56579..0ecc6e82e 100644
--- a/src/emucore/CartDetector.cxx
+++ b/src/emucore/CartDetector.cxx
@@ -16,328 +16,10 @@
//============================================================================
#include "bspf.hxx"
-#include "Cart.hxx"
-#include "Cart0840.hxx"
-#include "Cart2K.hxx"
-#include "Cart3E.hxx"
-#include "Cart3EX.hxx"
-#include "Cart3EPlus.hxx"
-#include "Cart3F.hxx"
-#include "Cart4A50.hxx"
-#include "Cart4K.hxx"
-#include "Cart4KSC.hxx"
-#include "CartAR.hxx"
-#include "CartBF.hxx"
-#include "CartBFSC.hxx"
-#include "CartBUS.hxx"
-#include "CartCDF.hxx"
-#include "CartCM.hxx"
-#include "CartCTY.hxx"
-#include "CartCV.hxx"
-#include "CartDF.hxx"
-#include "CartDFSC.hxx"
-#include "CartDPC.hxx"
-#include "CartDPCPlus.hxx"
-#include "CartE0.hxx"
-#include "CartE7.hxx"
-#include "CartE78K.hxx"
-#include "CartEF.hxx"
-#include "CartEFSC.hxx"
-#include "CartF0.hxx"
-#include "CartF4.hxx"
-#include "CartF4SC.hxx"
-#include "CartF6.hxx"
-#include "CartF6SC.hxx"
-#include "CartF8.hxx"
-#include "CartF8SC.hxx"
-#include "CartFA.hxx"
-#include "CartFA2.hxx"
-#include "CartFC.hxx"
-#include "CartFE.hxx"
-#include "CartMDM.hxx"
-#include "CartSB.hxx"
-#include "CartUA.hxx"
-#include "CartWD.hxx"
-#include "CartX07.hxx"
-#include "MD5.hxx"
-#include "Props.hxx"
#include "Logger.hxx"
-#include "OSystem.hxx"
#include "CartDetector.hxx"
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-unique_ptr CartDetector::create(const FilesystemNode& file,
- const ByteBuffer& image, size_t size, string& md5,
- const string& propertiesType, Settings& settings)
-{
- unique_ptr cartridge;
- Bankswitch::Type type = Bankswitch::nameToType(propertiesType),
- detectedType = type;
- string id;
-
- // Collect some info about the ROM
- ostringstream buf;
-
- // First inspect the file extension itself
- // If a valid type is found, it will override the one passed into this method
- Bankswitch::Type typeByName = Bankswitch::typeFromExtension(file);
- if(typeByName != Bankswitch::Type::_AUTO)
- type = detectedType = typeByName;
-
- // See if we should try to auto-detect the cartridge type
- // If we ask for extended info, always do an autodetect
- if(type == Bankswitch::Type::_AUTO || settings.getBool("rominfo"))
- {
- detectedType = autodetectType(image, size);
- if(type != Bankswitch::Type::_AUTO && type != detectedType)
- cerr << "Auto-detection not consistent: "
- << Bankswitch::typeToName(type) << ", "
- << Bankswitch::typeToName(detectedType) << endl;
-
- type = detectedType;
- buf << Bankswitch::typeToName(type) << "*";
- }
- else
- buf << Bankswitch::typeToName(type);
-
- // Check for multicart first; if found, get the correct part of the image
- switch(type)
- {
- case Bankswitch::Type::_2IN1:
- // Make sure we have a valid sized image
- if(size == 2*2_KB || size == 2*4_KB || size == 2*8_KB || size == 2*16_KB)
- {
- cartridge =
- createFromMultiCart(image, size, 2, md5, detectedType, id, settings);
- buf << id;
- }
- else
- throw runtime_error("Invalid cart size for type '" +
- Bankswitch::typeToName(type) + "'");
- break;
-
- case Bankswitch::Type::_4IN1:
- // Make sure we have a valid sized image
- if(size == 4*2_KB || size == 4*4_KB || size == 4*8_KB)
- {
- cartridge =
- createFromMultiCart(image, size, 4, md5, detectedType, id, settings);
- buf << id;
- }
- else
- throw runtime_error("Invalid cart size for type '" +
- Bankswitch::typeToName(type) + "'");
- break;
-
- case Bankswitch::Type::_8IN1:
- // Make sure we have a valid sized image
- if(size == 8*2_KB || size == 8*4_KB || size == 8*8_KB)
- {
- cartridge =
- createFromMultiCart(image, size, 8, md5, detectedType, id, settings);
- buf << id;
- }
- else
- throw runtime_error("Invalid cart size for type '" +
- Bankswitch::typeToName(type) + "'");
- break;
-
- case Bankswitch::Type::_16IN1:
- // Make sure we have a valid sized image
- if(size == 16*2_KB || size == 16*4_KB || size == 16*8_KB)
- {
- cartridge =
- createFromMultiCart(image, size, 16, md5, detectedType, id, settings);
- buf << id;
- }
- else
- throw runtime_error("Invalid cart size for type '" +
- Bankswitch::typeToName(type) + "'");
- break;
-
- case Bankswitch::Type::_32IN1:
- // Make sure we have a valid sized image
- if(size == 32*2_KB || size == 32*4_KB)
- {
- cartridge =
- createFromMultiCart(image, size, 32, md5, detectedType, id, settings);
- buf << id;
- }
- else
- throw runtime_error("Invalid cart size for type '" +
- Bankswitch::typeToName(type) + "'");
- break;
-
- case Bankswitch::Type::_64IN1:
- // Make sure we have a valid sized image
- if(size == 64*2_KB || size == 64*4_KB)
- {
- cartridge =
- createFromMultiCart(image, size, 64, md5, detectedType, id, settings);
- buf << id;
- }
- else
- throw runtime_error("Invalid cart size for type '" +
- Bankswitch::typeToName(type) + "'");
- break;
-
- case Bankswitch::Type::_128IN1:
- // Make sure we have a valid sized image
- if(size == 128*2_KB || size == 128*4_KB)
- {
- cartridge =
- createFromMultiCart(image, size, 128, md5, detectedType, id, settings);
- buf << id;
- }
- else
- throw runtime_error("Invalid cart size for type '" +
- Bankswitch::typeToName(type) + "'");
- break;
-
- default:
- cartridge = createFromImage(image, size, detectedType, md5, settings);
- break;
- }
-
- if(size < 1_KB)
- buf << " (" << size << "B) ";
- else
- buf << " (" << (size/1_KB) << "K) ";
-
- cartridge->setAbout(buf.str(), Bankswitch::typeToName(type), id);
-
- return cartridge;
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-unique_ptr
-CartDetector::createFromMultiCart(const ByteBuffer& image, size_t& size,
- uInt32 numroms, string& md5, Bankswitch::Type type, string& id, Settings& settings)
-{
- // Get a piece of the larger image
- uInt32 i = settings.getInt("romloadcount");
- size /= numroms;
- ByteBuffer slice = make_unique(size);
- std::copy_n(image.get()+i*size, size, slice.get());
-
- // We need a new md5 and name
- md5 = MD5::hash(slice, uInt32(size)); // FIXME
- ostringstream buf;
- buf << " [G" << (i+1) << "]";
- id = buf.str();
-
- // Move to the next game the next time this ROM is loaded
- settings.setValue("romloadcount", (i+1)%numroms);
-
- if(size <= 2_KB) type = Bankswitch::Type::_2K;
- else if(size == 4_KB) type = Bankswitch::Type::_4K;
- else if(size == 8_KB) type = Bankswitch::Type::_F8;
- else /* default */ type = Bankswitch::Type::_4K;
-
- return createFromImage(slice, size, type, md5, settings);
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-unique_ptr
-CartDetector::createFromImage(const ByteBuffer& image, size_t size, Bankswitch::Type type,
- const string& md5, Settings& settings)
-{
- // We should know the cart's type by now so let's create it
- switch(type)
- {
- case Bankswitch::Type::_0840:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_2K:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_3E:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_3EX:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_3EP:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_3F:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_4A50:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_4K:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_4KSC:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_AR:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_BF:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_BFSC:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_BUS:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_CDF:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_CM:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_CTY:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_CV:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_DF:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_DFSC:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_DPC:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_DPCP:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_E0:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_E7:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_E78K:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_EF:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_EFSC:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_F0:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_F4:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_F4SC:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_F6:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_F6SC:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_F8:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_F8SC:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_FA:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_FA2:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_FC:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_FE:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_MDM:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_UA:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_UASW:
- return make_unique(image, size, md5, settings, true);
- case Bankswitch::Type::_SB:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_WD:
- case Bankswitch::Type::_WDSW:
- return make_unique(image, size, md5, settings);
- case Bankswitch::Type::_X07:
- return make_unique(image, size, md5, settings);
- default:
- return nullptr; // The remaining types have already been handled
- }
-}
-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t size)
{
@@ -524,6 +206,17 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si
else /*if(isProbablySB(image, size))*/
type = Bankswitch::Type::_SB;
}
+ else if(size == 512_KB)
+ {
+ if(isProbablyTVBoy(image, size))
+ type = Bankswitch::Type::_TVBOY;
+ else if(isProbably3EX(image, size))
+ type = Bankswitch::Type::_3EX;
+ else if(isProbably3E(image, size))
+ type = Bankswitch::Type::_3E;
+ else if(isProbably3F(image, size))
+ type = Bankswitch::Type::_3F;
+ }
else // what else can we do?
{
if(isProbably3EX(image, size))
@@ -936,7 +629,7 @@ bool CartDetector::isProbablyFA2(const ByteBuffer& image, size_t)
// file sizes
// 32K version has all zeros in 29K-32K area
- for(uInt32 i = 29_KB; i < 32_KB; ++i)
+ for(size_t i = 29_KB; i < 32_KB; ++i)
if(image[i] != 0)
return false;
@@ -1000,6 +693,14 @@ bool CartDetector::isProbablySB(const ByteBuffer& image, size_t size)
return searchForBytes(image, size, signature[1], 3);
}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool CartDetector::isProbablyTVBoy(const ByteBuffer& image, size_t size)
+{
+ // TV Boy cart bankswitching switches banks by accessing addresses 0x1800..$187F
+ uInt8 signature[5] = {0x91, 0x82, 0x6c, 0xfc, 0xff}; // STA ($82),Y; JMP ($FFFC)
+ return searchForBytes(image, size, signature, 5);
+}
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyUA(const ByteBuffer& image, size_t size)
{
diff --git a/src/emucore/CartDetector.hxx b/src/emucore/CartDetector.hxx
index 9ff193c87..810ed24a7 100644
--- a/src/emucore/CartDetector.hxx
+++ b/src/emucore/CartDetector.hxx
@@ -18,10 +18,6 @@
#ifndef CARTRIDGE_DETECTOR_HXX
#define CARTRIDGE_DETECTOR_HXX
-class Cartridge;
-class Properties;
-class Settings;
-
#include "Bankswitch.hxx"
#include "bspf.hxx"
@@ -34,21 +30,6 @@ class Settings;
class CartDetector
{
public:
- /**
- Create a new cartridge object allocated on the heap. The
- type of cartridge created depends on the properties object.
-
- @param image A pointer to the ROM image
- @param size The size of the ROM image
- @param md5 The md5sum for the given ROM image (can be updated)
- @param dtype The detected bankswitch type of the ROM image
- @param settings The settings container
- @return Pointer to the new cartridge object allocated on the heap
- */
- static unique_ptr create(const FilesystemNode& file,
- const ByteBuffer& image, size_t size, string& md5,
- const string& dtype, Settings& settings);
-
/**
Try to auto-detect the bankswitching type of the cartridge
@@ -60,40 +41,6 @@ class CartDetector
static Bankswitch::Type autodetectType(const ByteBuffer& image, size_t size);
private:
- /**
- Create a cartridge from a multi-cart image pointer; internally this
- takes a slice of the ROM image ues that for the cartridge.
-
- @param image A pointer to the complete ROM image
- @param size The size of the ROM image slice
- @param numroms The number of ROMs in the multicart
- @param md5 The md5sum for the slice of the ROM image
- @param type The detected type of the slice of the ROM image
- @param id The ID for the slice of the ROM image
- @param settings The settings container
-
- @return Pointer to the new cartridge object allocated on the heap
- */
- static unique_ptr
- createFromMultiCart(const ByteBuffer& image, size_t& size,
- uInt32 numroms, string& md5, Bankswitch::Type type, string& id,
- Settings& settings);
-
- /**
- Create a cartridge from the entire image pointer.
-
- @param image A pointer to the complete ROM image
- @param size The size of the ROM image
- @param type The bankswitch type of the ROM image
- @param md5 The md5sum for the ROM image
- @param settings The settings container
-
- @return Pointer to the new cartridge object allocated on the heap
- */
- static unique_ptr
- createFromImage(const ByteBuffer& image, size_t size, Bankswitch::Type type,
- const string& md5, Settings& settings);
-
/**
Search the image for the specified byte signature
@@ -247,6 +194,11 @@ class CartDetector
*/
static bool isProbablySB(const ByteBuffer& image, size_t size);
+ /**
+ Returns true if the image is probably a TV Boy bankswitching cartridge
+ */
+ static bool isProbablyTVBoy(const ByteBuffer& image, size_t size);
+
/**
Returns true if the image is probably a UA bankswitching cartridge
*/
diff --git a/src/emucore/CartE0.cxx b/src/emucore/CartE0.cxx
index 07afae5a2..9204d5619 100644
--- a/src/emucore/CartE0.cxx
+++ b/src/emucore/CartE0.cxx
@@ -20,8 +20,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeE0::CartridgeE0(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
myBankShift = BANK_SHIFT;
}
diff --git a/src/emucore/CartE0.hxx b/src/emucore/CartE0.hxx
index 84c9ae667..70af8f85d 100644
--- a/src/emucore/CartE0.hxx
+++ b/src/emucore/CartE0.hxx
@@ -53,9 +53,10 @@ class CartridgeE0 : public CartridgeEnhanced
@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
*/
CartridgeE0(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 8_KB);
virtual ~CartridgeE0() = default;
public:
diff --git a/src/emucore/CartEF.cxx b/src/emucore/CartEF.cxx
index 039f4aa5c..c063b0c05 100644
--- a/src/emucore/CartEF.cxx
+++ b/src/emucore/CartEF.cxx
@@ -20,8 +20,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeEF::CartridgeEF(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
}
diff --git a/src/emucore/CartEF.hxx b/src/emucore/CartEF.hxx
index ff71b9909..2c86d0d71 100644
--- a/src/emucore/CartEF.hxx
+++ b/src/emucore/CartEF.hxx
@@ -45,9 +45,10 @@ class CartridgeEF : public CartridgeEnhanced
@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
*/
CartridgeEF(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 64_KB);
virtual ~CartridgeEF() = default;
public:
diff --git a/src/emucore/CartEFSC.cxx b/src/emucore/CartEFSC.cxx
index c70cff194..f73557245 100644
--- a/src/emucore/CartEFSC.cxx
+++ b/src/emucore/CartEFSC.cxx
@@ -20,8 +20,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeEFSC::CartridgeEFSC(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEF(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEF(image, size, md5, settings, bsSize)
{
myRamSize = RAM_SIZE;
}
diff --git a/src/emucore/CartEFSC.hxx b/src/emucore/CartEFSC.hxx
index f6c7e40ea..ac95c9e2c 100644
--- a/src/emucore/CartEFSC.hxx
+++ b/src/emucore/CartEFSC.hxx
@@ -46,9 +46,10 @@ class CartridgeEFSC : public CartridgeEF
@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
*/
CartridgeEFSC(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 64_KB);
virtual ~CartridgeEFSC() = default;
public:
diff --git a/src/emucore/CartEnhanced.cxx b/src/emucore/CartEnhanced.cxx
index 27fa425b5..633104cf3 100644
--- a/src/emucore/CartEnhanced.cxx
+++ b/src/emucore/CartEnhanced.cxx
@@ -15,20 +15,45 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
+#include "Logger.hxx"
#include "System.hxx"
#include "CartEnhanced.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeEnhanced::CartridgeEnhanced(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : Cartridge(settings, md5),
- mySize(size)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : Cartridge(settings, md5)
{
- // Allocate array for the ROM image (at least 64 bytzes)
- myImage = make_unique(std::max(uInt32(mySize), uInt32(System::PAGE_SIZE)));
+ // ROMs are not always at the 'legal' size for their associated
+ // bankswitching scheme; here we deal with the differing sizes
- // Copy the ROM image into my buffer
- std::copy_n(image.get(), mySize, myImage.get());
+ // Is the ROM too large? If so, we cap it
+ if(size > bsSize)
+ {
+ ostringstream buf;
+ buf << "ROM larger than expected (" << size << " > " << bsSize
+ << "), truncating " << (size - bsSize) << " bytes\n";
+ Logger::info(buf.str());
+ }
+ else if(size < mySize)
+ {
+ ostringstream buf;
+ buf << "ROM smaller than expected (" << mySize << " > " << size
+ << "), appending " << (mySize - size) << " bytes\n";
+ Logger::info(buf.str());
+ }
+
+ mySize = bsSize;
+
+ // Initialize ROM with all 0's, to fill areas that the ROM may not cover
+ myImage = make_unique(mySize);
+ std::fill_n(myImage.get(), mySize, 0);
+
+ // Directly copy the ROM image into the buffer
+ // Only copy up to the amount of data the ROM provides; extra unused
+ // space will be filled with 0's from above
+ std::copy_n(image.get(), std::min(mySize, size), myImage.get());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -44,7 +69,7 @@ void CartridgeEnhanced::install(System& system)
// or the ROM is < 4K (-> 1 segment)
myBankSegs = std::min(1 << (MAX_BANK_SHIFT - myBankShift),
int(mySize) / myBankSize); // e.g. = 1
- myRomOffset = myRamBankCount > 0 ? 0 : uInt32(myRamSize) * 2;
+ myRomOffset = myRamBankCount > 0U ? 0U : static_cast(myRamSize * 2);
myRamMask = ramSize - 1; // e.g. = 0xFFFF (doesn't matter for RAM size 0)
myWriteOffset = myRamWpHigh ? ramSize : 0; // e.g. = 0x0000
myReadOffset = myRamWpHigh ? 0 : ramSize; // e.g. = 0x0080
@@ -130,8 +155,7 @@ uInt8 CartridgeEnhanced::peek(uInt16 address)
// This is a read access to a write port!
// Reading from the write port triggers an unwanted write
// The RAM banks follow the ROM banks and are half the size of a ROM bank
- return peekRAM(myRAM[((myCurrentSegOffset[(peekAddress & ROM_MASK) >> myBankShift] - mySize) >> 1) + address],
- peekAddress);
+ return peekRAM(myRAM[ramAddressSegmentOffset(peekAddress) + address], peekAddress);
}
address &= ROM_MASK;
@@ -143,8 +167,7 @@ uInt8 CartridgeEnhanced::peek(uInt16 address)
return peekRAM(myRAM[address], peekAddress);
}
- return myImage[myCurrentSegOffset[(peekAddress & ROM_MASK) >> myBankShift]
- + (peekAddress & myBankMask)];
+ return myImage[romAddressSegmentOffset(peekAddress) + (peekAddress & myBankMask)];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -165,7 +188,7 @@ bool CartridgeEnhanced::poke(uInt16 address, uInt8 value)
{
address &= myRamMask;
// The RAM banks follow the ROM banks and are half the size of a ROM bank
- pokeRAM(myRAM[((myCurrentSegOffset[(pokeAddress & ROM_MASK) >> myBankShift] - mySize) >> 1) + address],
+ pokeRAM(myRAM[ramAddressSegmentOffset(pokeAddress) + address],
pokeAddress, value);
return true;
}
@@ -275,10 +298,22 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
return myBankChanged = true;
}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+inline uInt16 CartridgeEnhanced::romAddressSegmentOffset(uInt16 address) const
+{
+ return myCurrentSegOffset[((address & ROM_MASK) >> myBankShift) % myBankSegs];
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+inline uInt16 CartridgeEnhanced::ramAddressSegmentOffset(uInt16 address) const
+{
+ return uInt16(myCurrentSegOffset[((address & ROM_MASK) >> myBankShift) % myBankSegs] - mySize) >> 1;
+}
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeEnhanced::getBank(uInt16 address) const
{
- return myCurrentSegOffset[(address & ROM_MASK) >> myBankShift] >> myBankShift;
+ return romAddressSegmentOffset(address) >> myBankShift;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -310,11 +345,11 @@ bool CartridgeEnhanced::patch(uInt16 address, uInt8 value)
{
if(isRamBank(address))
{
- myRAM[((myCurrentSegOffset[(address & ROM_MASK) >> myBankShift] - mySize) >> 1) + (address & myRamMask)] = value;
+ myRAM[ramAddressSegmentOffset(address) + (address & myRamMask)] = value;
}
else
{
- if((address & myBankMask) < myRamSize * 2)
+ if(static_cast(address & myBankMask) < myRamSize * 2)
{
// Normally, a write to the read port won't do anything
// However, the patch command is special in that ignores such
@@ -322,17 +357,17 @@ bool CartridgeEnhanced::patch(uInt16 address, uInt8 value)
myRAM[address & myRamMask] = value;
}
else
- myImage[myCurrentSegOffset[(address & ROM_MASK) >> myBankShift] + (address & myBankMask)] = value;
+ myImage[romAddressSegmentOffset(address) + (address & myBankMask)] = value;
}
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-const uInt8* CartridgeEnhanced::getImage(size_t& size) const
+const ByteBuffer& CartridgeEnhanced::getImage(size_t& size) const
{
size = mySize;
- return myImage.get();
+ return myImage;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/CartEnhanced.hxx b/src/emucore/CartEnhanced.hxx
index 743a4b50e..e99afc917 100644
--- a/src/emucore/CartEnhanced.hxx
+++ b/src/emucore/CartEnhanced.hxx
@@ -43,9 +43,11 @@ class CartridgeEnhanced : public Cartridge
@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
*/
- CartridgeEnhanced(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ CartridgeEnhanced(const ByteBuffer& image, size_t size,
+ const string& md5, const Settings& settings,
+ size_t bsSize);
virtual ~CartridgeEnhanced() = default;
public:
@@ -70,16 +72,7 @@ class CartridgeEnhanced : public Cartridge
@return true, if bank has changed
*/
- virtual bool bank(uInt16 bank, uInt16 segment);
-
- /**
- Install pages for the specified bank in the system.
-
- @param bank The bank that should be installed in the system
-
- @return true, if bank has changed
- */
- bool bank(uInt16 bank) override { return this->bank(bank, 0); }
+ bool bank(uInt16 bank, uInt16 segment = 0) override;
/**
Get the current bank.
@@ -127,9 +120,9 @@ class CartridgeEnhanced : public Cartridge
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
+ @return A reference to the internal ROM image data
*/
- const uInt8* getImage(size_t& size) const override;
+ const ByteBuffer& getImage(size_t& size) const override;
/**
Save the current state of this cart to the given Serializer.
@@ -263,6 +256,7 @@ class CartridgeEnhanced : public Cartridge
@param address The address to check
@param value The optional value used to determine the bank switched to
+
@return True if a bank switch happened.
*/
virtual bool checkSwitchBank(uInt16 address, uInt8 value = 0) = 0;
@@ -275,6 +269,22 @@ class CartridgeEnhanced : public Cartridge
*/
virtual uInt16 getStartBank() const { return 0; }
+ /**
+ Get the ROM offset of the segment of the given address
+
+ @param address The address to get the offset for
+ @return The calculated offset
+ */
+ uInt16 romAddressSegmentOffset(uInt16 address) const;
+
+ /**
+ Get the RAM offset of the segment of the given address
+
+ @param address The address to get the offset for
+ @return The calculated offset
+ */
+ uInt16 ramAddressSegmentOffset(uInt16 address) const;
+
private:
// Following constructors and assignment operators not supported
CartridgeEnhanced() = delete;
diff --git a/src/emucore/CartF0.cxx b/src/emucore/CartF0.cxx
index 8747c57f3..0429109e3 100644
--- a/src/emucore/CartF0.cxx
+++ b/src/emucore/CartF0.cxx
@@ -19,8 +19,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF0::CartridgeF0(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
}
diff --git a/src/emucore/CartF0.hxx b/src/emucore/CartF0.hxx
index 0d5837066..e49b8ce31 100644
--- a/src/emucore/CartF0.hxx
+++ b/src/emucore/CartF0.hxx
@@ -42,9 +42,10 @@ class CartridgeF0 : public CartridgeEnhanced
@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
*/
CartridgeF0(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 64_KB);
virtual ~CartridgeF0() = default;
public:
diff --git a/src/emucore/CartF4.cxx b/src/emucore/CartF4.cxx
index 6a8cd6e00..c00163efb 100644
--- a/src/emucore/CartF4.cxx
+++ b/src/emucore/CartF4.cxx
@@ -19,8 +19,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF4::CartridgeF4(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
}
diff --git a/src/emucore/CartF4.hxx b/src/emucore/CartF4.hxx
index d44e96640..81a5e176e 100644
--- a/src/emucore/CartF4.hxx
+++ b/src/emucore/CartF4.hxx
@@ -41,9 +41,10 @@ class CartridgeF4 : public CartridgeEnhanced
@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
*/
CartridgeF4(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 32_KB);
virtual ~CartridgeF4() = default;
public:
diff --git a/src/emucore/CartF4SC.cxx b/src/emucore/CartF4SC.cxx
index 4fe6e13eb..d012874c6 100644
--- a/src/emucore/CartF4SC.cxx
+++ b/src/emucore/CartF4SC.cxx
@@ -19,9 +19,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF4SC::CartridgeF4SC(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeF4(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeF4(image, size, md5, settings, bsSize)
{
myRamSize = RAM_SIZE;
- myRamMask = RAM_SIZE - 1;
+ myRamMask = RAM_SIZE - 1;
}
diff --git a/src/emucore/CartF4SC.hxx b/src/emucore/CartF4SC.hxx
index 58b255e42..49f1278ac 100644
--- a/src/emucore/CartF4SC.hxx
+++ b/src/emucore/CartF4SC.hxx
@@ -42,9 +42,10 @@ class CartridgeF4SC : public CartridgeF4
@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
*/
CartridgeF4SC(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 32_KB);
virtual ~CartridgeF4SC() = default;
public:
diff --git a/src/emucore/CartF6.cxx b/src/emucore/CartF6.cxx
index 50e993e26..7b120d0b0 100644
--- a/src/emucore/CartF6.cxx
+++ b/src/emucore/CartF6.cxx
@@ -19,8 +19,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF6::CartridgeF6(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
}
@@ -36,4 +37,3 @@ bool CartridgeF6::checkSwitchBank(uInt16 address, uInt8)
}
return false;
}
-
diff --git a/src/emucore/CartF6.hxx b/src/emucore/CartF6.hxx
index 16faeebab..7707f1ef6 100644
--- a/src/emucore/CartF6.hxx
+++ b/src/emucore/CartF6.hxx
@@ -41,9 +41,10 @@ class CartridgeF6 : public CartridgeEnhanced
@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
*/
CartridgeF6(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 16_KB);
virtual ~CartridgeF6() = default;
public:
diff --git a/src/emucore/CartF6SC.cxx b/src/emucore/CartF6SC.cxx
index 15613a357..084091d12 100644
--- a/src/emucore/CartF6SC.cxx
+++ b/src/emucore/CartF6SC.cxx
@@ -19,9 +19,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF6SC::CartridgeF6SC(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeF6(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeF6(image, size, md5, settings, bsSize)
{
myRamSize = RAM_SIZE;
- myRamMask = RAM_SIZE - 1;
+ myRamMask = RAM_SIZE - 1;
}
diff --git a/src/emucore/CartF6SC.hxx b/src/emucore/CartF6SC.hxx
index c61c9715f..4365036bb 100644
--- a/src/emucore/CartF6SC.hxx
+++ b/src/emucore/CartF6SC.hxx
@@ -42,9 +42,10 @@ class CartridgeF6SC : public CartridgeF6
@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
*/
CartridgeF6SC(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 16_KB);
virtual ~CartridgeF6SC() = default;
public:
diff --git a/src/emucore/CartF8.cxx b/src/emucore/CartF8.cxx
index 5d898091c..732cb306d 100644
--- a/src/emucore/CartF8.cxx
+++ b/src/emucore/CartF8.cxx
@@ -19,8 +19,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF8::CartridgeF8(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
}
diff --git a/src/emucore/CartF8.hxx b/src/emucore/CartF8.hxx
index 29b308808..90b34497a 100644
--- a/src/emucore/CartF8.hxx
+++ b/src/emucore/CartF8.hxx
@@ -41,9 +41,10 @@ class CartridgeF8 : public CartridgeEnhanced
@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
*/
CartridgeF8(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 8_KB);
virtual ~CartridgeF8() = default;
public:
diff --git a/src/emucore/CartF8SC.cxx b/src/emucore/CartF8SC.cxx
index 98ce4357f..9607d9687 100644
--- a/src/emucore/CartF8SC.cxx
+++ b/src/emucore/CartF8SC.cxx
@@ -19,8 +19,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF8SC::CartridgeF8SC(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeF8(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeF8(image, size, md5, settings, bsSize)
{
myRamSize = RAM_SIZE;
}
diff --git a/src/emucore/CartF8SC.hxx b/src/emucore/CartF8SC.hxx
index c5a005543..3eb3539ae 100644
--- a/src/emucore/CartF8SC.hxx
+++ b/src/emucore/CartF8SC.hxx
@@ -42,9 +42,10 @@ class CartridgeF8SC : public CartridgeF8
@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
*/
CartridgeF8SC(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 8_KB);
virtual ~CartridgeF8SC() = default;
public:
diff --git a/src/emucore/CartFA.cxx b/src/emucore/CartFA.cxx
index 082e403f7..ec242f615 100644
--- a/src/emucore/CartFA.cxx
+++ b/src/emucore/CartFA.cxx
@@ -20,8 +20,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeFA::CartridgeFA(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
myRamSize = RAM_SIZE;
}
diff --git a/src/emucore/CartFA.hxx b/src/emucore/CartFA.hxx
index a2f197b75..d234de743 100644
--- a/src/emucore/CartFA.hxx
+++ b/src/emucore/CartFA.hxx
@@ -45,9 +45,10 @@ class CartridgeFA : public CartridgeEnhanced
@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
*/
CartridgeFA(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 12_KB);
virtual ~CartridgeFA() = default;
public:
diff --git a/src/emucore/CartFA2.cxx b/src/emucore/CartFA2.cxx
index 14c8f2156..2443b106a 100644
--- a/src/emucore/CartFA2.cxx
+++ b/src/emucore/CartFA2.cxx
@@ -20,8 +20,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeFA2::CartridgeFA2(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeFA(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeFA(image, size, md5, settings, bsSize)
{
// 29/32K version of FA2 has valid data @ 1K - 29K
const uInt8* img_ptr = image.get();
diff --git a/src/emucore/CartFA2.hxx b/src/emucore/CartFA2.hxx
index 16d33bf2b..ea60fbe45 100644
--- a/src/emucore/CartFA2.hxx
+++ b/src/emucore/CartFA2.hxx
@@ -57,9 +57,10 @@ class CartridgeFA2 : public CartridgeFA
@param size The size of the ROM image
@param md5 The md5sum of the ROM image
@param settings A reference to the settings object
+ @param bsSize The size specified by the bankswitching scheme
*/
CartridgeFA2(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 28_KB);
virtual ~CartridgeFA2() = default;
public:
diff --git a/src/emucore/CartFC.cxx b/src/emucore/CartFC.cxx
index c415ba1af..1b431592e 100644
--- a/src/emucore/CartFC.cxx
+++ b/src/emucore/CartFC.cxx
@@ -20,8 +20,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeFC::CartridgeFC(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings,
+ bsSize == 0 ? BSPF::nextPowerOfTwo(size) : bsSize)
{
}
diff --git a/src/emucore/CartFC.hxx b/src/emucore/CartFC.hxx
index 5858ae85a..92be2a421 100644
--- a/src/emucore/CartFC.hxx
+++ b/src/emucore/CartFC.hxx
@@ -47,9 +47,11 @@ class CartridgeFC : public CartridgeEnhanced
@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
+ (where 0 means variable-sized ROM)
*/
CartridgeFC(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 0);
virtual ~CartridgeFC() = default;
public:
diff --git a/src/emucore/CartFE.cxx b/src/emucore/CartFE.cxx
index 7c3debda3..d0c01886b 100644
--- a/src/emucore/CartFE.cxx
+++ b/src/emucore/CartFE.cxx
@@ -21,8 +21,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeFE::CartridgeFE(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
myDirectPeek = false;
}
diff --git a/src/emucore/CartFE.hxx b/src/emucore/CartFE.hxx
index 6c453d284..77ebee767 100644
--- a/src/emucore/CartFE.hxx
+++ b/src/emucore/CartFE.hxx
@@ -87,9 +87,10 @@ class CartridgeFE : public CartridgeEnhanced
@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
*/
CartridgeFE(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 8_KB);
virtual ~CartridgeFE() = default;
public:
diff --git a/src/emucore/CartMDM.cxx b/src/emucore/CartMDM.cxx
index decb634ec..f92563ec2 100644
--- a/src/emucore/CartMDM.cxx
+++ b/src/emucore/CartMDM.cxx
@@ -20,8 +20,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeMDM::CartridgeMDM(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings,
+ bsSize == 0 ? BSPF::nextPowerOfTwo(size) : bsSize)
{
}
@@ -88,7 +90,7 @@ bool CartridgeMDM::poke(uInt16 address, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool CartridgeMDM::bank(uInt16 bank)
+bool CartridgeMDM::bank(uInt16 bank, uInt16)
{
if(bankLocked() || myBankingDisabled) return false;
diff --git a/src/emucore/CartMDM.hxx b/src/emucore/CartMDM.hxx
index 4b0786e42..4e12571e1 100644
--- a/src/emucore/CartMDM.hxx
+++ b/src/emucore/CartMDM.hxx
@@ -56,9 +56,11 @@ class CartridgeMDM : public CartridgeEnhanced
@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
+ (where 0 means variable-sized ROM)
*/
CartridgeMDM(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 0);
virtual ~CartridgeMDM() = default;
public:
@@ -73,9 +75,12 @@ class CartridgeMDM : public CartridgeEnhanced
/**
Install pages for the specified bank in the system.
- @param bank The bank that should be installed in the system
+ @param bank The bank that should be installed in the system
+ @param segment The segment the bank should be using
+
+ @return true, if bank has changed
*/
- bool bank(uInt16 bank) override;
+ bool bank(uInt16 bank, uInt16 segment = 0) override;
/**
Save the current state of this cart to the given Serializer.
diff --git a/src/emucore/CartMNetwork.cxx b/src/emucore/CartMNetwork.cxx
index c6542b2b8..78c68e6a0 100644
--- a/src/emucore/CartMNetwork.cxx
+++ b/src/emucore/CartMNetwork.cxx
@@ -201,7 +201,7 @@ void CartridgeMNetwork::bankRAM(uInt16 bank)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool CartridgeMNetwork::bank(uInt16 bank)
+bool CartridgeMNetwork::bank(uInt16 bank, uInt16)
{
if(bankLocked()) return false;
@@ -263,10 +263,10 @@ bool CartridgeMNetwork::patch(uInt16 address, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-const uInt8* CartridgeMNetwork::getImage(size_t& size) const
+const ByteBuffer& CartridgeMNetwork::getImage(size_t& size) const
{
size = romBankCount() * BANK_SIZE;
- return myImage.get();
+ return myImage;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/CartMNetwork.hxx b/src/emucore/CartMNetwork.hxx
index 95cd24b56..9b17a4b67 100644
--- a/src/emucore/CartMNetwork.hxx
+++ b/src/emucore/CartMNetwork.hxx
@@ -94,9 +94,12 @@ class CartridgeMNetwork : public Cartridge
/**
Install pages for the specified bank in the system.
- @param bank The bank that should be installed in the system
+ @param bank The bank that should be installed in the system
+ @param segment The segment the bank should be using
+
+ @return true, if bank has changed
*/
- bool bank(uInt16 bank) override;
+ bool bank(uInt16 bank, uInt16 segment = 0) override;
/**
Get the current bank.
@@ -123,9 +126,9 @@ class CartridgeMNetwork : public Cartridge
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
+ @return A reference to the internal ROM image data
*/
- const uInt8* getImage(size_t& size) const override;
+ const ByteBuffer& getImage(size_t& size) const override;
/**
Save the current state of this cart to the given Serializer.
diff --git a/src/emucore/CartSB.cxx b/src/emucore/CartSB.cxx
index 5caa01be7..18d160cff 100644
--- a/src/emucore/CartSB.cxx
+++ b/src/emucore/CartSB.cxx
@@ -20,8 +20,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeSB::CartridgeSB(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings,
+ bsSize == 0 ? BSPF::nextPowerOfTwo(size) : bsSize)
{
}
diff --git a/src/emucore/CartSB.hxx b/src/emucore/CartSB.hxx
index 85c8e9ccb..17cea387c 100644
--- a/src/emucore/CartSB.hxx
+++ b/src/emucore/CartSB.hxx
@@ -45,9 +45,11 @@ class CartridgeSB : public CartridgeEnhanced
@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
+ (where 0 means variable-sized ROM)
*/
CartridgeSB(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 0);
virtual ~CartridgeSB() = default;
public:
diff --git a/src/emucore/CartTVBoy.cxx b/src/emucore/CartTVBoy.cxx
new file mode 100644
index 000000000..50d66cb57
--- /dev/null
+++ b/src/emucore/CartTVBoy.cxx
@@ -0,0 +1,88 @@
+//============================================================================
+//
+// 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-2020 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 "CartTVBoy.hxx"
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CartridgeTVBoy::CartridgeTVBoy(const ByteBuffer& image, size_t size,
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
+{
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool CartridgeTVBoy::checkSwitchBank(uInt16 address, uInt8)
+{
+ // Switch banks if necessary
+ if((address & ADDR_MASK) >= 0x1800 && (address & ADDR_MASK) <= 0x187F)
+ {
+ bank(address & (romBankCount() - 1));
+ return true;
+ }
+ return false;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool CartridgeTVBoy::bank(uInt16 bank, uInt16)
+{
+ if(myBankingDisabled) return false;
+
+ bool banked = CartridgeEnhanced::bank(bank);
+
+ // Any bankswitching locks further bankswitching, we check for bank 0
+ // to avoid locking on cart init.
+ if (banked && bank != 0)
+ myBankingDisabled = true;
+
+ return banked;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool CartridgeTVBoy::save(Serializer& out) const
+{
+ CartridgeEnhanced::save(out);
+ try
+ {
+ out.putBool(myBankingDisabled);
+ }
+ catch(...)
+ {
+ cerr << "ERROR: CartridgeTVBoy::save" << endl;
+ return false;
+ }
+
+ return true;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool CartridgeTVBoy::load(Serializer& in)
+{
+ CartridgeEnhanced::load(in);
+ try
+ {
+ myBankingDisabled = in.getBool();
+ }
+ catch(...)
+ {
+ cerr << "ERROR: CartridgeTVBoy::load" << endl;
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/emucore/CartTVBoy.hxx b/src/emucore/CartTVBoy.hxx
new file mode 100644
index 000000000..d1787e55b
--- /dev/null
+++ b/src/emucore/CartTVBoy.hxx
@@ -0,0 +1,117 @@
+//============================================================================
+//
+// 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-2020 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 CARTRIDGETVBOY_HXX
+#define CARTRIDGETVBOY_HXX
+
+#include "bspf.hxx"
+#include "CartEnhanced.hxx"
+#include "System.hxx"
+#ifdef DEBUGGER_SUPPORT
+#include "CartTVBoyWidget.hxx"
+#endif
+
+/**
+ Cartridge class used for TV Boy
+ There are 128 4K banks, accessing $F800..$F87F selects bank and locks any
+ further bankswitching.
+
+ @author Thomas Jentzsch
+*/
+class CartridgeTVBoy : public CartridgeEnhanced
+{
+ friend class CartridgeTVBoyWidget;
+
+ 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
+ */
+ CartridgeTVBoy(const ByteBuffer& image, size_t size, const string& md5,
+ const Settings& settings, size_t bsSize = 512_KB);
+ virtual ~CartridgeTVBoy() = default;
+
+ public:
+ /**
+ Install pages for the specified bank in the system.
+
+ @param bank The bank that should be installed in the system
+ @param segment The segment the bank should be using
+
+ @return true, if bank has changed
+ */
+ bool bank(uInt16 bank, uInt16 segment = 0) 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 "CartridgeTVBoy"; }
+
+ #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 CartridgeTVBoyWidget(boss, lfont, nfont, x, y, w, h, *this);
+ }
+ #endif
+
+ private:
+ bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
+
+ uInt16 hotspot() const override { return 0x1800; }
+
+ private:
+ // Indicates whether banking has been disabled due to a bankswitch
+ bool myBankingDisabled{false};
+
+ private:
+ // Following constructors and assignment operators not supported
+ CartridgeTVBoy() = delete;
+ CartridgeTVBoy(const CartridgeTVBoy&) = delete;
+ CartridgeTVBoy(CartridgeTVBoy&&) = delete;
+ CartridgeTVBoy& operator=(const CartridgeTVBoy&) = delete;
+ CartridgeTVBoy& operator=(CartridgeTVBoy&&) = delete;
+};
+
+#endif
diff --git a/src/emucore/CartUA.cxx b/src/emucore/CartUA.cxx
index 74ccc3773..e73f166db 100644
--- a/src/emucore/CartUA.cxx
+++ b/src/emucore/CartUA.cxx
@@ -22,7 +22,7 @@
CartridgeUA::CartridgeUA(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings,
bool swapHotspots)
- : CartridgeEnhanced(image, size, md5, settings),
+ : CartridgeEnhanced(image, size, md5, settings, 8_KB),
mySwappedHotspots(swapHotspots)
{
}
diff --git a/src/emucore/CartWD.cxx b/src/emucore/CartWD.cxx
index 11ebc653e..d985abd00 100644
--- a/src/emucore/CartWD.cxx
+++ b/src/emucore/CartWD.cxx
@@ -22,11 +22,12 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeWD::CartridgeWD(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
// Copy the ROM image into my buffer
- if (mySize == 8_KB + 3)
+ if(size == 8_KB + 3)
{
// swap banks 2 & 3 of bad dump and correct size
std::copy_n(image.get() + 1_KB * 3, 1_KB * 1, myImage.get() + 1_KB * 2);
diff --git a/src/emucore/CartWD.hxx b/src/emucore/CartWD.hxx
index 398571a52..4c1d9d3d9 100644
--- a/src/emucore/CartWD.hxx
+++ b/src/emucore/CartWD.hxx
@@ -65,9 +65,10 @@ class CartridgeWD : public CartridgeEnhanced
@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
*/
CartridgeWD(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 8_KB);
virtual ~CartridgeWD() = default;
public:
diff --git a/src/emucore/CartX07.cxx b/src/emucore/CartX07.cxx
index ac40b6ac6..4f3294d5c 100644
--- a/src/emucore/CartX07.cxx
+++ b/src/emucore/CartX07.cxx
@@ -22,8 +22,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeX07::CartridgeX07(const ByteBuffer& image, size_t size,
- const string& md5, const Settings& settings)
- : CartridgeEnhanced(image, size, md5, settings)
+ const string& md5, const Settings& settings,
+ size_t bsSize)
+ : CartridgeEnhanced(image, size, md5, settings, bsSize)
{
}
diff --git a/src/emucore/CartX07.hxx b/src/emucore/CartX07.hxx
index 3cde4efdf..3f59ca7c3 100644
--- a/src/emucore/CartX07.hxx
+++ b/src/emucore/CartX07.hxx
@@ -54,9 +54,10 @@ class CartridgeX07 : public CartridgeEnhanced
@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
*/
CartridgeX07(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
+ const Settings& settings, size_t bsSize = 64_KB);
virtual ~CartridgeX07() = default;
public:
diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx
index 1e796a0bd..1f828ee94 100644
--- a/src/emucore/Console.cxx
+++ b/src/emucore/Console.cxx
@@ -444,7 +444,7 @@ void Console::setFormat(uInt32 format, bool force)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::toggleColorLoss()
+void Console::toggleColorLoss(bool toggle)
{
bool colorloss = !myTIA->colorLossEnabled();
if(myTIA->enableColorLoss(colorloss))
@@ -726,7 +726,7 @@ void Console::setControllers(const string& romMd5)
Controller::Type leftType = Controller::getType(myProperties.get(PropType::Controller_Left));
Controller::Type rightType = Controller::getType(myProperties.get(PropType::Controller_Right));
size_t size = 0;
- const uInt8* image = myCart->getImage(size);
+ const ByteBuffer& image = myCart->getImage(size);
const bool swappedPorts = myProperties.get(PropType::Console_SwapPorts) == "YES";
// Try to detect controllers
@@ -876,51 +876,56 @@ float Console::getFramerate() const
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::toggleTIABit(TIABit bit, const string& bitname, bool show) const
+void Console::toggleTIABit(TIABit bit, const string& bitname, bool show, bool toggle) const
{
- bool result = myTIA->toggleBit(bit);
- string message = bitname + (result ? " enabled" : " disabled");
+ bool result = myTIA->toggleBit(bit, toggle ? 2 : 3);
+ const string message = bitname + (result ? " enabled" : " disabled");
+
myOSystem.frameBuffer().showMessage(message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::toggleBits() const
+void Console::toggleBits(bool toggle) const
{
- bool enabled = myTIA->toggleBits();
- string message = string("TIA bits") + (enabled ? " enabled" : " disabled");
+ bool enabled = myTIA->toggleBits(toggle);
+ const string message = string("TIA bits ") + (enabled ? "enabled" : "disabled");
+
myOSystem.frameBuffer().showMessage(message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::toggleTIACollision(TIABit bit, const string& bitname, bool show) const
+void Console::toggleTIACollision(TIABit bit, const string& bitname, bool show, bool toggle) const
{
- bool result = myTIA->toggleCollision(bit);
- string message = bitname + (result ? " collision enabled" : " collision disabled");
+ bool result = myTIA->toggleCollision(bit, toggle ? 2 : 3);
+ const string message = bitname + (result ? " collision enabled" : " collision disabled");
+
myOSystem.frameBuffer().showMessage(message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::toggleCollisions() const
+void Console::toggleCollisions(bool toggle) const
{
- bool enabled = myTIA->toggleCollisions();
- string message = string("TIA collisions") + (enabled ? " enabled" : " disabled");
+ bool enabled = myTIA->toggleCollisions(toggle);
+ const string message = string("TIA collisions ") + (enabled ? "enabled" : "disabled");
+
myOSystem.frameBuffer().showMessage(message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::toggleFixedColors() const
+void Console::toggleFixedColors(bool toggle) const
{
- if(myTIA->toggleFixedColors())
- myOSystem.frameBuffer().showMessage("Fixed debug colors enabled");
- else
- myOSystem.frameBuffer().showMessage("Fixed debug colors disabled");
+ bool enabled = toggle ? myTIA->toggleFixedColors() : myTIA->usingFixedColors();
+ const string message = string("Fixed debug colors ") + (enabled ? "enabled" : "disabled");
+
+ myOSystem.frameBuffer().showMessage(message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::toggleJitter() const
+void Console::toggleJitter(bool toggle) const
{
- bool enabled = myTIA->toggleJitter();
- string message = string("TV scanline jitter") + (enabled ? " enabled" : " disabled");
+ bool enabled = myTIA->toggleJitter(toggle ? 2 : 3);
+ const string message = string("TV scanline jitter ") + (enabled ? "enabled" : "disabled");
+
myOSystem.frameBuffer().showMessage(message);
}
diff --git a/src/emucore/Console.hxx b/src/emucore/Console.hxx
index d13588b07..1cc37fc0b 100644
--- a/src/emucore/Console.hxx
+++ b/src/emucore/Console.hxx
@@ -229,7 +229,7 @@ class Console : public Serializable, public ConsoleIO
/**
Toggles the PAL color-loss effect.
*/
- void toggleColorLoss();
+ void toggleColorLoss(bool toggle = true);
void enableColorLoss(bool state);
/**
@@ -278,34 +278,34 @@ class Console : public Serializable, public ConsoleIO
/**
Toggles the TIA bit specified in the method name.
*/
- void toggleP0Bit() const { toggleTIABit(P0Bit, "P0"); }
- void toggleP1Bit() const { toggleTIABit(P1Bit, "P1"); }
- void toggleM0Bit() const { toggleTIABit(M0Bit, "M0"); }
- void toggleM1Bit() const { toggleTIABit(M1Bit, "M1"); }
- void toggleBLBit() const { toggleTIABit(BLBit, "BL"); }
- void togglePFBit() const { toggleTIABit(PFBit, "PF"); }
- void toggleBits() const;
+ void toggleP0Bit(bool toggle = true) const { toggleTIABit(P0Bit, "P0", true, toggle); }
+ void toggleP1Bit(bool toggle = true) const { toggleTIABit(P1Bit, "P1", true, toggle); }
+ void toggleM0Bit(bool toggle = true) const { toggleTIABit(M0Bit, "M0", true, toggle); }
+ void toggleM1Bit(bool toggle = true) const { toggleTIABit(M1Bit, "M1", true, toggle); }
+ void toggleBLBit(bool toggle = true) const { toggleTIABit(BLBit, "BL", true, toggle); }
+ void togglePFBit(bool toggle = true) const { toggleTIABit(PFBit, "PF", true, toggle); }
+ void toggleBits(bool toggle = true) const;
/**
Toggles the TIA collisions specified in the method name.
*/
- void toggleP0Collision() const { toggleTIACollision(P0Bit, "P0"); }
- void toggleP1Collision() const { toggleTIACollision(P1Bit, "P1"); }
- void toggleM0Collision() const { toggleTIACollision(M0Bit, "M0"); }
- void toggleM1Collision() const { toggleTIACollision(M1Bit, "M1"); }
- void toggleBLCollision() const { toggleTIACollision(BLBit, "BL"); }
- void togglePFCollision() const { toggleTIACollision(PFBit, "PF"); }
- void toggleCollisions() const;
+ void toggleP0Collision(bool toggle = true) const { toggleTIACollision(P0Bit, "P0", true, toggle); }
+ void toggleP1Collision(bool toggle = true) const { toggleTIACollision(P1Bit, "P1", true, toggle); }
+ void toggleM0Collision(bool toggle = true) const { toggleTIACollision(M0Bit, "M0", true, toggle); }
+ void toggleM1Collision(bool toggle = true) const { toggleTIACollision(M1Bit, "M1", true, toggle); }
+ void toggleBLCollision(bool toggle = true) const { toggleTIACollision(BLBit, "BL", true, toggle); }
+ void togglePFCollision(bool toggle = true) const { toggleTIACollision(PFBit, "PF", true, toggle); }
+ void toggleCollisions(bool toggle = true) const;
/**
Toggles the TIA 'fixed debug colors' mode.
*/
- void toggleFixedColors() const;
+ void toggleFixedColors(bool toggle = true) const;
/**
Toggles the TIA 'scanline jitter' mode.
*/
- void toggleJitter() const;
+ void toggleJitter(bool toggle = true) const;
/**
* Update vcenter
@@ -351,8 +351,10 @@ class Console : public Serializable, public ConsoleIO
unique_ptr getControllerPort(const Controller::Type type,
const Controller::Jack port, const string& romMd5);
- void toggleTIABit(TIABit bit, const string& bitname, bool show = true) const;
- void toggleTIACollision(TIABit bit, const string& bitname, bool show = true) const;
+ void toggleTIABit(TIABit bit, const string& bitname,
+ bool show = true, bool toggle = true) const;
+ void toggleTIACollision(TIABit bit, const string& bitname,
+ bool show = true, bool toggle = true) const;
private:
// Reference to the osystem object
diff --git a/src/emucore/ControllerDetector.cxx b/src/emucore/ControllerDetector.cxx
index 023302d81..95922051b 100644
--- a/src/emucore/ControllerDetector.cxx
+++ b/src/emucore/ControllerDetector.cxx
@@ -22,8 +22,10 @@
#include "ControllerDetector.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Controller::Type ControllerDetector::detectType(const uInt8* image, size_t size,
- const Controller::Type type, const Controller::Jack port, const Settings& settings)
+Controller::Type ControllerDetector::detectType(
+ const ByteBuffer& image, size_t size,
+ const Controller::Type type, const Controller::Jack port,
+ const Settings& settings)
{
if(type == Controller::Type::Unknown || settings.getBool("rominfo"))
{
@@ -43,7 +45,7 @@ Controller::Type ControllerDetector::detectType(const uInt8* image, size_t size,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-string ControllerDetector::detectName(const uInt8* image, size_t size,
+string ControllerDetector::detectName(const ByteBuffer& image, size_t size,
const Controller::Type controller, const Controller::Jack port,
const Settings& settings)
{
@@ -51,7 +53,8 @@ string ControllerDetector::detectName(const uInt8* image, size_t size,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Controller::Type ControllerDetector::autodetectPort(const uInt8* image, size_t size,
+Controller::Type ControllerDetector::autodetectPort(
+ const ByteBuffer& image, size_t size,
Controller::Jack port, const Settings& settings)
{
// default type joystick
@@ -88,7 +91,7 @@ Controller::Type ControllerDetector::autodetectPort(const uInt8* image, size_t s
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool ControllerDetector::searchForBytes(const uInt8* image, size_t imagesize,
+bool ControllerDetector::searchForBytes(const ByteBuffer& image, size_t imagesize,
const uInt8* signature, uInt32 sigsize)
{
if (imagesize >= sigsize)
@@ -112,7 +115,7 @@ bool ControllerDetector::searchForBytes(const uInt8* image, size_t imagesize,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool ControllerDetector::usesJoystickButton(const uInt8* image, size_t size,
+bool ControllerDetector::usesJoystickButton(const ByteBuffer& image, size_t size,
Controller::Jack port)
{
if(port == Controller::Jack::Left)
@@ -242,7 +245,7 @@ bool ControllerDetector::usesJoystickButton(const uInt8* image, size_t size,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool ControllerDetector::usesKeyboard(const uInt8* image, size_t size,
+bool ControllerDetector::usesKeyboard(const ByteBuffer& image, size_t size,
Controller::Jack port)
{
if(port == Controller::Jack::Left)
@@ -314,13 +317,14 @@ bool ControllerDetector::usesKeyboard(const uInt8* image, size_t size,
else if(port == Controller::Jack::Right)
{
// check for INPT2 *AND* INPT3 access
- const int NUM_SIGS_0_0 = 5;
+ const int NUM_SIGS_0_0 = 6;
const int SIG_SIZE_0_0 = 3;
uInt8 signature_0_0[NUM_SIGS_0_0][SIG_SIZE_0_0] = {
{ 0x24, 0x3a, 0x30 }, // bit INPT2|$30; bmi
{ 0xa5, 0x3a, 0x10 }, // lda INPT2|$30; bpl
{ 0xa4, 0x3a, 0x30 }, // ldy INPT2|$30; bmi
{ 0x24, 0x0a, 0x30 }, // bit INPT2; bmi
+ { 0x24, 0x0a, 0x10 }, // bit INPT2; bpl
{ 0xa6, 0x0a, 0x30 } // ldx INPT2; bmi
};
const int NUM_SIGS_0_2 = 1;
@@ -329,13 +333,14 @@ bool ControllerDetector::usesKeyboard(const uInt8* image, size_t size,
{ 0xb5, 0x38, 0x29, 0x80, 0xd0 } // lda INPT2,x; and #80; bne
};
- const int NUM_SIGS_1_0 = 5;
+ const int NUM_SIGS_1_0 = 6;
const int SIG_SIZE_1_0 = 3;
uInt8 signature_1_0[NUM_SIGS_1_0][SIG_SIZE_1_0] = {
{ 0x24, 0x3b, 0x30 }, // bit INPT3|$30; bmi
{ 0xa5, 0x3b, 0x10 }, // lda INPT3|$30; bpl
{ 0xa4, 0x3b, 0x30 }, // ldy INPT3|$30; bmi
{ 0x24, 0x0b, 0x30 }, // bit INPT3; bmi
+ { 0x24, 0x0b, 0x10 }, // bit INPT3; bpl
{ 0xa6, 0x0b, 0x30 } // ldx INPT3; bmi
};
const int NUM_SIGS_1_2 = 1;
@@ -381,7 +386,7 @@ bool ControllerDetector::usesKeyboard(const uInt8* image, size_t size,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool ControllerDetector::usesGenesisButton(const uInt8* image, size_t size,
+bool ControllerDetector::usesGenesisButton(const ByteBuffer& image, size_t size,
Controller::Jack port)
{
if(port == Controller::Jack::Left)
@@ -438,7 +443,7 @@ bool ControllerDetector::usesGenesisButton(const uInt8* image, size_t size,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool ControllerDetector::usesPaddle(const uInt8* image, size_t size,
+bool ControllerDetector::usesPaddle(const ByteBuffer& image, size_t size,
Controller::Jack port, const Settings& settings)
{
if(port == Controller::Jack::Left)
@@ -547,7 +552,7 @@ bool ControllerDetector::usesPaddle(const uInt8* image, size_t size,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool ControllerDetector::isProbablyTrakBall(const uInt8* image, size_t size)
+bool ControllerDetector::isProbablyTrakBall(const ByteBuffer& image, size_t size)
{
// check for TrakBall tables
const int NUM_SIGS = 3;
@@ -566,7 +571,7 @@ bool ControllerDetector::isProbablyTrakBall(const uInt8* image, size_t size)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool ControllerDetector::isProbablyAtariMouse(const uInt8* image, size_t size)
+bool ControllerDetector::isProbablyAtariMouse(const ByteBuffer& image, size_t size)
{
// check for Atari Mouse tables
const int NUM_SIGS = 3;
@@ -585,7 +590,7 @@ bool ControllerDetector::isProbablyAtariMouse(const uInt8* image, size_t size)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool ControllerDetector::isProbablyAmigaMouse(const uInt8* image, size_t size)
+bool ControllerDetector::isProbablyAmigaMouse(const ByteBuffer& image, size_t size)
{
// check for Amiga Mouse tables
const int NUM_SIGS = 4;
@@ -605,7 +610,7 @@ bool ControllerDetector::isProbablyAmigaMouse(const uInt8* image, size_t size)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool ControllerDetector::isProbablySaveKey(const uInt8* image, size_t size,
+bool ControllerDetector::isProbablySaveKey(const ByteBuffer& image, size_t size,
Controller::Jack port)
{
// check for known SaveKey code, only supports right port
@@ -650,7 +655,7 @@ bool ControllerDetector::isProbablySaveKey(const uInt8* image, size_t size,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool ControllerDetector::isProbablyLightGun(const uInt8* image, size_t size,
+bool ControllerDetector::isProbablyLightGun(const ByteBuffer& image, size_t size,
Controller::Jack port)
{
if (port == Controller::Jack::Left)
diff --git a/src/emucore/ControllerDetector.hxx b/src/emucore/ControllerDetector.hxx
index d37076eb1..be24ae09d 100644
--- a/src/emucore/ControllerDetector.hxx
+++ b/src/emucore/ControllerDetector.hxx
@@ -34,14 +34,14 @@ class ControllerDetector
/**
Detects the controller type at the given port if no controller is provided.
- @param image A pointer to the ROM image
+ @param image A reference to the ROM image
@param size The size of the ROM image
@param controller The provided controller type of the ROM image
@param port The port to be checked
@param settings A reference to the various settings (read-only)
@return The detected controller type
*/
- static Controller::Type detectType(const uInt8* image, size_t size,
+ static Controller::Type detectType(const ByteBuffer& image, size_t size,
const Controller::Type controller, const Controller::Jack port,
const Settings& settings);
@@ -49,7 +49,7 @@ class ControllerDetector
Detects the controller type at the given port if no controller is provided
and returns its name.
- @param image A pointer to the ROM image
+ @param image A reference to the ROM image
@param size The size of the ROM image
@param type The provided controller type of the ROM image
@param port The port to be checked
@@ -57,7 +57,7 @@ class ControllerDetector
@return The (detected) controller name
*/
- static string detectName(const uInt8* image, size_t size,
+ static string detectName(const ByteBuffer& image, size_t size,
const Controller::Type type, const Controller::Jack port,
const Settings& settings);
@@ -65,14 +65,14 @@ class ControllerDetector
/**
Detects the controller type at the given port.
- @param image A pointer to the ROM image
+ @param image A reference to the ROM image
@param size The size of the ROM image
@param port The port to be checked
@param settings A reference to the various settings (read-only)
@return The detected controller type
*/
- static Controller::Type autodetectPort(const uInt8* image, size_t size,
+ static Controller::Type autodetectPort(const ByteBuffer& image, size_t size,
Controller::Jack port, const Settings& settings);
/**
@@ -85,36 +85,41 @@ class ControllerDetector
@return True if the signature was found, else false
*/
- static bool searchForBytes(const uInt8* image, size_t imagesize,
+ static bool searchForBytes(const ByteBuffer& image, size_t imagesize,
const uInt8* signature, uInt32 sigsize);
// Returns true if the port's joystick button access code is found.
- static bool usesJoystickButton(const uInt8* image, size_t size, Controller::Jack port);
+ static bool usesJoystickButton(const ByteBuffer& image, size_t size,
+ Controller::Jack port);
// Returns true if the port's keyboard access code is found.
- static bool usesKeyboard(const uInt8* image, size_t size, Controller::Jack port);
+ static bool usesKeyboard(const ByteBuffer& image, size_t size,
+ Controller::Jack port);
// Returns true if the port's 2nd Genesis button access code is found.
- static bool usesGenesisButton(const uInt8* image, size_t size, Controller::Jack port);
+ static bool usesGenesisButton(const ByteBuffer& image, size_t size,
+ Controller::Jack port);
// Returns true if the port's paddle button access code is found.
- static bool usesPaddle(const uInt8* image, size_t size, Controller::Jack port,
- const Settings& settings);
+ static bool usesPaddle(const ByteBuffer& image, size_t size,
+ Controller::Jack port, const Settings& settings);
// Returns true if a Trak-Ball table is found.
- static bool isProbablyTrakBall(const uInt8* image, size_t size);
+ static bool isProbablyTrakBall(const ByteBuffer& image, size_t size);
// Returns true if an Atari Mouse table is found.
- static bool isProbablyAtariMouse(const uInt8* image, size_t size);
+ static bool isProbablyAtariMouse(const ByteBuffer& image, size_t size);
// Returns true if an Amiga Mouse table is found.
- static bool isProbablyAmigaMouse(const uInt8* image, size_t size);
+ static bool isProbablyAmigaMouse(const ByteBuffer& image, size_t size);
// Returns true if a SaveKey code pattern is found.
- static bool isProbablySaveKey(const uInt8* image, size_t size, Controller::Jack port);
+ static bool isProbablySaveKey(const ByteBuffer& image, size_t size,
+ Controller::Jack port);
// Returns true if a Lightgun code pattern is found
- static bool isProbablyLightGun(const uInt8* image, size_t size, Controller::Jack port);
+ static bool isProbablyLightGun(const ByteBuffer& image, size_t size,
+ Controller::Jack port);
private:
@@ -127,4 +132,3 @@ class ControllerDetector
};
#endif
-
diff --git a/src/emucore/DefProps.hxx b/src/emucore/DefProps.hxx
index fc0fe6155..65f2d67ca 100644
--- a/src/emucore/DefProps.hxx
+++ b/src/emucore/DefProps.hxx
@@ -25,7 +25,7 @@
regenerated and the application recompiled.
*/
-static constexpr uInt32 DEF_PROPS_SIZE = 3514;
+static constexpr uInt32 DEF_PROPS_SIZE = 3518;
static const BSPF::array2D DefProps = {{
{ "000509d1ed2b8d30a9d94be1b3b5febb", "Greg Zumwalt", "", "Jungle Jane (2003) (Greg Zumwalt) (Hack)", "Hack of Pitfall!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
@@ -405,6 +405,7 @@ static const BSPF::array2D DefProps = {{
{ "1b1daaa9aa5cded3d633bfcbeb06479c", "", "", "Ship Demo (V 1502) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "1b22a3d79ddd79335b69c94dd9b3e44e", "Tron", "", "Moon Patrol (Tron)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "1b4b06c2a14ed3ee73b7d0fd61b6aaf5", "Arcadia Corporation, Stephen H. Landrum", "AR-4400", "Excalibur (Dragonstomper Beta) (1982) (Arcadia) (Prototype) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
+ { "1b5a8da0622bffcee4c5b42aed4e0ef0", "Akor", "", "TV Boy II (1992) (Akor)", "Includes 127 games", "", "", "", "", "", "", "", "", "JOYSTICK", "JOYSTICK", "", "", "", "", "", "", "", "" },
{ "1b8c3c0bfb815b2a1010bba95998b66e", "Telegames", "", "Frogs and Flies (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "1b8d35d93697450ea26ebf7ff17bd4d1", "Quelle - Otto Versand", "176.764 9 - 781644", "Marineflieger (1983) (Quelle) (PAL)", "AKA Seahawk", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "1bb91bae919ddbd655fa25c54ea6f532", "Suntek", "SS-026", "Treasure Island (1983) (Suntek) (PAL)", "AKA Treasure Discovery", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
@@ -1426,6 +1427,7 @@ static const BSPF::array2D DefProps = {{
{ "65917ae29a8c9785bb1f2acb0d6aafd0", "", "", "Junkosoft One Year Demo (1999) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "6596b3737ae4b976e4aadb68d836c5c7", "Digivision", "", "Defender (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "659a20019de4a23c748ec2292ea5f221", "Retroactive", "", "Qb (V2.05) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "" },
+ { "65a6f1255fe22468a8bf84ff28a4d289", "Akor", "", "Super TV Boy (1995) (Akor)", "Includes 127 games", "", "", "", "", "", "", "", "", "JOYSTICK", "JOYSTICK", "", "", "", "", "", "", "", "" },
{ "65b106eba3e45f3dab72ea907f39f8b4", "Christian Software Development - HomeComputer Software, Dan Schafer, Glenn Stohel, Jon Tedesco - Sparrow", "GCG 1001T", "Music Machine, The (1983) (Sparrow)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "" },
{ "65ba1a4c643d1ab44481bdddeb403827", "Quelle", "876.013 4", "Katastrophen-Einsatz (1983) (Quelle) (PAL)", "AKA M.A.S.H.", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "65bd29e8ab1b847309775b0de6b2e4fe", "Coleco, Ed English", "2667", "Roc 'n Rope (1984) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
@@ -3146,6 +3148,7 @@ static const BSPF::array2D DefProps = {{
{ "e4c666ca0c36928b95b13d33474dbb44", "Arcadia Corporation, Steve Hales, Stephen H. Landrum", "4 AR-4102", "Suicide Mission (1982) (Arcadia)", "AKA Meteoroids", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "" },
{ "e4d41f2d59a56a9d917038682b8e0b8c", "Cody Pittman", "", "Kiss Meets Pacman (Cody Pittman) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "e4e9125a8741977583776729359614e1", "SnailSoft", "", "Comitoid beta 4 (SnailSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
+ { "e4fa739c81b003c92bea7da5e84c7feb", "Akor", "", "TV Boy (1992) (Akor) (NTSC) [bad dump]", "Includes 127 games", "", "", "", "", "", "", "", "", "JOYSTICK", "JOYSTICK", "", "", "", "", "", "", "", "" },
{ "e505bd8e59e31aaed20718d47b15c61b", "Funvision - Fund. Int'l Co.", "", "Space War (1982) (Funvision) (PAL)", "AKA Condor Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "e51030251e440cffaab1ac63438b44ae", "Parker Brothers - On-Time Software, Joe Gaucher, Louis Marbel", "PB5110", "James Bond 007 (1984) (Parker Bros)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "" },
{ "e51c23389e43ab328ccfb05be7d451da", "Arcadia Corporation, Scott Nelson", "13", "Sweat! - The Decathlon Game (1983) (Arcadia) (Prototype)", "Uses the Paddle Controllers (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
@@ -3357,7 +3360,7 @@ static const BSPF::array2D DefProps = {{
{ "f39e4bc99845edd8621b0f3c7b8c4fd9", "AtariAge", "", "Toyshop Trouble (AtariAge)", "F8 Emulator Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "f3c431930e035a457fe370ed4d230659", "", "", "Crackpots (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "f3cd0f886201d1376f3abab2df53b1b9", "Commavid, Ben Burch", "CM-010", "Rush Hour (1983) (Commavid) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
- { "f3dfae774f3bd005a026e29894db40d3", "Otto Versand", "649635", "See Saw (Double-Game Package) (1983) (Otto Versand) (PAL)", "AKA Circus Atari", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
+ { "f3dfae774f3bd005a026e29894db40d3", "Otto Versand", "649635", "See Saw (Double-Game Package) (1983) (Otto Versand) (PAL)", "AKA Circus Atari", "", "", "", "", "", "", "", "", "JOYSTICK", "JOYSTICK", "", "", "", "", "", "", "", "" },
{ "f3f5f72bfdd67f3d0e45d097e11b8091", "Sears Tele-Games, Marilyn Churchill, Matthew L. Hubbard", "CX2647 - 49-75142", "Submarine Commander (1982) (Sears)", "AKA Seawolf 3", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "f3f92aad3a335f0a1ead24a0214ff446", "", "", "Spectrum Color Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "f40e437a9ebf0bdfe26204152f74f868", "Bit Corporation", "R320", "Jawbreaker (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
@@ -3420,6 +3423,7 @@ static const BSPF::array2D DefProps = {{
{ "f7af41a87533524d9a478575b0d873d0", "Quelle", "495.663 7", "Spiderman (1983) (Quelle) (PAL)", "AKA Spider-Man", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "f7d6592dcb773c81c278140ed4d01669", "Activision, David Crane, Dan Kitchen", "EAG-108-04, EAZ-108-04B", "Ghostbusters (1985) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "f7e07080ed8396b68f2e5788a5c245e2", "Video Game Cartridge - Ariola", "TP-617", "Farmyard Fun (Ariola)", "AKA Play Farm", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
+ { "f7ec2f2bdbe8fbea048c0d5fa6503b0b", "Akor", "", "TV Boy (1992) (Akor) (PAL)", "Includes 127 games", "", "", "", "", "", "", "", "", "JOYSTICK", "JOYSTICK", "", "", "", "", "", "", "", "" },
{ "f7f50d9c9d28bcc9f7d3075668b7ac89", "Activision, David Crane - Ariola", "EAG-008, PAG-008, EAG-008-04I - 711 008-720", "Laser Blast (1981) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "f7fac15cf54b55c5597718b6742dbec2", "Spiceware", "SW-01", "Medieval Mayhem (NTSC)", "", "Homebrew", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "AUTO 55", "", "", "", "" },
{ "f802fa61011dd9eb6f80b271bac479d0", "Suntek", "SS-023", "Mole Hunter (1983) (Suntek) (PAL)", "AKA Topy", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
diff --git a/src/emucore/Event.hxx b/src/emucore/Event.hxx
index fa8a4d04d..f666e19bc 100644
--- a/src/emucore/Event.hxx
+++ b/src/emucore/Event.hxx
@@ -121,8 +121,10 @@ class Event
ToggleCollisions, ToggleBits, ToggleFixedColors,
ToggleFrameStats, ToggleSAPortOrder, ExitGame,
- // add new events from here to avoid that user remapped events get overwritten
SettingDecrease, SettingIncrease, PreviousSetting, NextSetting,
+ ToggleAdaptRefresh, PreviousMultiCartRom,
+ // add new events from here to avoid that user remapped events get overwritten
+ PreviousSettingGroup, NextSettingGroup,
LastType
};
diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx
index fa87be91d..536b33e65 100644
--- a/src/emucore/EventHandler.cxx
+++ b/src/emucore/EventHandler.cxx
@@ -342,6 +342,16 @@ void EventHandler::handleSystemEvent(SystemEvent e, int, int)
}
}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+EventHandler::AdjustGroup EventHandler::getAdjustGroup()
+{
+ if (myAdjustSetting >= AdjustSetting::START_DEBUG_ADJ && myAdjustSetting <= AdjustSetting::END_DEBUG_ADJ)
+ return AdjustGroup::DEBUG;
+
+ return AdjustGroup::AV;
+}
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AdjustFunction EventHandler::cycleAdjustSetting(int direction)
{
@@ -350,17 +360,42 @@ AdjustFunction EventHandler::cycleAdjustSetting(int direction)
myOSystem.settings().getString("palette") == PaletteHandler::SETTING_CUSTOM;
const bool isCustomFilter =
myOSystem.settings().getInt("tv.filter") == int(NTSCFilter::Preset::CUSTOM);
+ const bool isPAL = myOSystem.console().timing() == ConsoleTiming::pal;
+ bool repeat = false;
do
{
- myAdjustSetting =
- AdjustSetting(BSPF::clampw(int(myAdjustSetting) + direction, 0, int(AdjustSetting::MAX_ADJ)));
- // skip currently non-relevant adjustments
- } while((myAdjustSetting == AdjustSetting::OVERSCAN && !isFullScreen)
+ switch (getAdjustGroup())
+ {
+ case AdjustGroup::AV:
+ myAdjustSetting =
+ AdjustSetting(BSPF::clampw(int(myAdjustSetting) + direction,
+ int(AdjustSetting::START_AV_ADJ), int(AdjustSetting::END_AV_ADJ)));
+ // skip currently non-relevant adjustments
+ repeat = (myAdjustSetting == AdjustSetting::OVERSCAN && !isFullScreen)
+ #ifdef ADAPTABLE_REFRESH_SUPPORT
+ || (myAdjustSetting == AdjustSetting::ADAPT_REFRESH && !isFullScreen)
+ #endif
|| (myAdjustSetting == AdjustSetting::PALETTE_PHASE && !isCustomPalette)
|| (myAdjustSetting >= AdjustSetting::NTSC_SHARPNESS
&& myAdjustSetting <= AdjustSetting::NTSC_BLEEDING
- && !isCustomFilter));
+ && !isCustomFilter);
+ break;
+
+ case AdjustGroup::DEBUG:
+ myAdjustSetting =
+ AdjustSetting(BSPF::clampw(int(myAdjustSetting) + direction,
+ int(AdjustSetting::START_DEBUG_ADJ), int(AdjustSetting::END_DEBUG_ADJ)));
+ repeat = (myAdjustSetting == AdjustSetting::COLOR_LOSS && !isPAL);
+ break;
+
+ default:
+ break;
+ }
+ // avoid endless loop
+ if(repeat && !direction)
+ direction = 1;
+ } while(repeat);
return getAdjustSetting(myAdjustSetting);
}
@@ -373,9 +408,13 @@ AdjustFunction EventHandler::getAdjustSetting(AdjustSetting setting)
// - This array MUST have the same order as AdjustSetting
const AdjustFunction ADJUST_FUNCTIONS[int(AdjustSetting::NUM_ADJ)] =
{
+ // Audio & Video settings
std::bind(&Sound::adjustVolume, &myOSystem.sound(), _1),
std::bind(&FrameBuffer::selectVidMode, &myOSystem.frameBuffer(), _1),
std::bind(&FrameBuffer::toggleFullscreen, &myOSystem.frameBuffer(), _1),
+ #ifdef ADAPTABLE_REFRESH_SUPPORT
+ std::bind(&FrameBuffer::toggleAdaptRefresh, &myOSystem.frameBuffer(), _1),
+ #endif
std::bind(&FrameBuffer::changeOverscan, &myOSystem.frameBuffer(), _1),
std::bind(&Console::selectFormat, &myOSystem.console(), _1),
std::bind(&Console::changeVerticalCenter, &myOSystem.console(), _1),
@@ -409,6 +448,25 @@ AdjustFunction EventHandler::getAdjustSetting(AdjustSetting setting)
std::bind(&Console::changePhosphor, &myOSystem.console(), _1),
std::bind(&TIASurface::setScanlineIntensity, &myOSystem.frameBuffer().tiaSurface(), _1),
std::bind(&Console::toggleInter, &myOSystem.console(), _1),
+ // Debug settings
+ std::bind(&FrameBuffer::toggleFrameStats, &myOSystem.frameBuffer(), _1),
+ std::bind(&Console::toggleP0Bit, &myOSystem.console(), _1),
+ std::bind(&Console::toggleP1Bit, &myOSystem.console(), _1),
+ std::bind(&Console::toggleM0Bit, &myOSystem.console(), _1),
+ std::bind(&Console::toggleM1Bit, &myOSystem.console(), _1),
+ std::bind(&Console::toggleBLBit, &myOSystem.console(), _1),
+ std::bind(&Console::togglePFBit, &myOSystem.console(), _1),
+ std::bind(&Console::toggleBits, &myOSystem.console(), _1),
+ std::bind(&Console::toggleP0Collision, &myOSystem.console(), _1),
+ std::bind(&Console::toggleP1Collision, &myOSystem.console(), _1),
+ std::bind(&Console::toggleM0Collision, &myOSystem.console(), _1),
+ std::bind(&Console::toggleM1Collision, &myOSystem.console(), _1),
+ std::bind(&Console::toggleBLCollision, &myOSystem.console(), _1),
+ std::bind(&Console::togglePFCollision, &myOSystem.console(), _1),
+ std::bind(&Console::toggleCollisions, &myOSystem.console(), _1),
+ std::bind(&Console::toggleFixedColors, &myOSystem.console(), _1),
+ std::bind(&Console::toggleColorLoss, &myOSystem.console(), _1),
+ std::bind(&Console::toggleJitter, &myOSystem.console(), _1),
// Following functions are not used when cycling settings but for "direct only" hotkeys
std::bind(&StateManager::changeState, &myOSystem.state(), _1),
std::bind(&PaletteHandler::changeCurrentAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), _1),
@@ -435,8 +493,10 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
myAdjustActive = false;
myAdjustDirect = AdjustSetting::NONE;
}
+
const bool adjustActive = myAdjustActive;
- const AdjustSetting adjustDirect = myAdjustDirect;
+ const AdjustSetting adjustAVDirect = myAdjustDirect;
+
if(pressed)
{
myAdjustActive = false;
@@ -446,6 +506,36 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
switch(event)
{
////////////////////////////////////////////////////////////////////////
+ // Allow adjusting several (mostly repeated) settings using the same four hotkeys
+ case Event::PreviousSettingGroup:
+ case Event::NextSettingGroup:
+ if (pressed && !repeated)
+ {
+ const int direction = event == Event::PreviousSettingGroup ? -1 : +1;
+ AdjustGroup adjustGroup = AdjustGroup(BSPF::clampw(int(getAdjustGroup()) + direction,
+ 0, int(AdjustGroup::NUM_GROUPS) - 1));
+ string msg;
+
+ switch (adjustGroup)
+ {
+ case AdjustGroup::AV:
+ msg = "Audio & Video";
+ myAdjustSetting = AdjustSetting::START_AV_ADJ;
+ break;
+
+ case AdjustGroup::DEBUG:
+ msg = "Debug";
+ myAdjustSetting = AdjustSetting::START_DEBUG_ADJ;
+ break;
+
+ default:
+ break;
+ }
+ myOSystem.frameBuffer().showMessage(msg + " settings");
+ myAdjustActive = false;
+ }
+ break;
+
// Allow adjusting several (mostly repeated) settings using the same four hotkeys
case Event::PreviousSetting:
case Event::NextSetting:
@@ -470,9 +560,9 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
const int direction = event == Event::SettingDecrease ? -1 : +1;
// if a "direct only" hotkey was pressed last, use this one
- if(adjustDirect != AdjustSetting::NONE)
+ if(adjustAVDirect != AdjustSetting::NONE)
{
- myAdjustDirect = adjustDirect;
+ myAdjustDirect = adjustAVDirect;
getAdjustSetting(myAdjustDirect)(direction);
}
else
@@ -526,16 +616,9 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
if(!myAllowAllDirectionsFlag && pressed)
myEvent.set(Event::JoystickOneLeft, 0);
break;
- ////////////////////////////////////////////////////////////////////////
-
- case Event::Fry:
- if(!repeated) myFryingFlag = pressed;
- return;
-
- case Event::ReloadConsole:
- if(pressed && !repeated) myOSystem.reloadConsole();
- return;
+ ///////////////////////////////////////////////////////////////////////////
+ // Audio & Video events (with global hotkeys)
case Event::VolumeDecrease:
if(pressed)
{
@@ -581,6 +664,62 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
}
return;
+ case Event::ToggleFullScreen:
+ if (pressed && !repeated)
+ {
+ myOSystem.frameBuffer().toggleFullscreen();
+ myAdjustSetting = AdjustSetting::FULLSCREEN;
+ myAdjustActive = true;
+ }
+ return;
+
+ #ifdef ADAPTABLE_REFRESH_SUPPORT
+ case Event::ToggleAdaptRefresh:
+ if (pressed && !repeated)
+ {
+ myOSystem.frameBuffer().toggleAdaptRefresh();
+ myAdjustSetting = AdjustSetting::ADAPT_REFRESH;
+ myAdjustActive = true;
+ }
+ return;
+ #endif
+
+ case Event::OverscanDecrease:
+ if (pressed)
+ {
+ myOSystem.frameBuffer().changeOverscan(-1);
+ myAdjustSetting = AdjustSetting::OVERSCAN;
+ myAdjustActive = true;
+ }
+ return;
+
+ case Event::OverscanIncrease:
+ if (pressed)
+ {
+ myOSystem.frameBuffer().changeOverscan(+1);
+ myAdjustSetting = AdjustSetting::OVERSCAN;
+ myAdjustActive = true;
+ }
+ return;
+
+ case Event::FormatDecrease:
+ if (pressed && !repeated)
+ {
+ myOSystem.console().selectFormat(-1);
+ myAdjustSetting = AdjustSetting::TVFORMAT;
+ myAdjustActive = true;
+ }
+ return;
+
+ case Event::FormatIncrease:
+ if (pressed && !repeated)
+ {
+ myOSystem.console().selectFormat(+1);
+ myAdjustSetting = AdjustSetting::TVFORMAT;
+ myAdjustActive = true;
+ }
+ return;
+
case Event::VCenterDecrease:
if(pressed)
{
@@ -617,61 +756,20 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
}
return;
- case Event::PreviousPaletteAttribute:
- if(pressed)
+ case Event::PaletteDecrease:
+ if (pressed && !repeated)
{
- myOSystem.frameBuffer().tiaSurface().paletteHandler().cycleAdjustable(-1);
- myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
- }
- return;
-
- case Event::NextPaletteAttribute:
- if(pressed)
- {
- myOSystem.frameBuffer().tiaSurface().paletteHandler().cycleAdjustable(+1);
- myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
- }
- return;
-
- case Event::PaletteAttributeDecrease:
- if(pressed)
- {
- myOSystem.frameBuffer().tiaSurface().paletteHandler().changeCurrentAdjustable(-1);
- myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
- }
- return;
-
- case Event::PaletteAttributeIncrease:
- if(pressed)
- {
- myOSystem.frameBuffer().tiaSurface().paletteHandler().changeCurrentAdjustable(+1);
- myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
- }
- return;
-
- case Event::ToggleFullScreen:
- if(pressed && !repeated)
- {
- myOSystem.frameBuffer().toggleFullscreen();
- myAdjustSetting = AdjustSetting::FULLSCREEN;
+ myOSystem.frameBuffer().tiaSurface().paletteHandler().cyclePalette(-1);
+ myAdjustSetting = AdjustSetting::PALETTE;
myAdjustActive = true;
}
return;
- case Event::OverscanDecrease:
- if(pressed)
+ case Event::PaletteIncrease:
+ if (pressed && !repeated)
{
- myOSystem.frameBuffer().changeOverscan(-1);
- myAdjustSetting = AdjustSetting::OVERSCAN;
- myAdjustActive = true;
- }
- return;
-
- case Event::OverscanIncrease:
- if(pressed)
- {
- myOSystem.frameBuffer().changeOverscan(+1);
- myAdjustSetting = AdjustSetting::OVERSCAN;
+ myOSystem.frameBuffer().tiaSurface().paletteHandler().cyclePalette(+1);
+ myAdjustSetting = AdjustSetting::PALETTE;
myAdjustActive = true;
}
return;
@@ -695,80 +793,58 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
return;
case Event::VidmodeStd:
- if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::OFF);
+ if(pressed && !repeated)
+ {
+ myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::OFF);
+ myAdjustDirect = AdjustSetting::NTSC_PRESET;
+ myAdjustActive = true;
+ }
return;
case Event::VidmodeRGB:
- if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::RGB);
+ if(pressed && !repeated)
+ {
+ myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::RGB);
+ myAdjustSetting = AdjustSetting::NTSC_PRESET;
+ myAdjustActive = true;
+ }
return;
case Event::VidmodeSVideo:
- if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::SVIDEO);
+ if(pressed && !repeated)
+ {
+ myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::SVIDEO);
+ myAdjustSetting = AdjustSetting::NTSC_PRESET;
+ myAdjustActive = true;
+ }
return;
case Event::VidModeComposite:
- if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::COMPOSITE);
+ if(pressed && !repeated)
+ {
+ myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::COMPOSITE);
+ myAdjustSetting = AdjustSetting::NTSC_PRESET;
+ myAdjustActive = true;
+ }
return;
case Event::VidModeBad:
- if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::BAD);
+ if(pressed && !repeated)
+ {
+ myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::BAD);
+ myAdjustSetting = AdjustSetting::NTSC_PRESET;
+ myAdjustActive = true;
+ }
return;
case Event::VidModeCustom:
- if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM);
- return;
-
- case Event::PreviousAttribute:
- if(pressed)
+ if(pressed && !repeated)
{
- myOSystem.frameBuffer().tiaSurface().setNTSCAdjustable(-1);
- myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
- }
- return;
-
- case Event::NextAttribute:
- if(pressed)
- {
- myOSystem.frameBuffer().tiaSurface().setNTSCAdjustable(+1);
- myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
- }
- return;
-
- case Event::DecreaseAttribute:
- if(pressed)
- {
- myOSystem.frameBuffer().tiaSurface().changeCurrentNTSCAdjustable(-1);
- myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
- }
- return;
-
- case Event::IncreaseAttribute:
- if(pressed)
- {
- myOSystem.frameBuffer().tiaSurface().changeCurrentNTSCAdjustable(+1);
- myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
- }
- return;
-
- case Event::ScanlinesDecrease:
- if(pressed)
- {
- myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(-1);
- myAdjustSetting = AdjustSetting::SCANLINES;
- myAdjustActive = true;
-
- }
- return;
-
- case Event::ScanlinesIncrease:
- if(pressed)
- {
- myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(+1);
- myAdjustSetting = AdjustSetting::SCANLINES;
+ myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM);
+ myAdjustSetting = AdjustSetting::NTSC_PRESET;
myAdjustActive = true;
}
return;
-
case Event::PhosphorDecrease:
if(pressed)
{
@@ -796,24 +872,20 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
}
return;
- case Event::ToggleColorLoss:
- if (pressed && !repeated) myOSystem.console().toggleColorLoss();
- return;
-
- case Event::PaletteDecrease:
- if(pressed && !repeated)
+ case Event::ScanlinesDecrease:
+ if (pressed)
{
- myOSystem.frameBuffer().tiaSurface().paletteHandler().cyclePalette(-1);
- myAdjustSetting = AdjustSetting::PALETTE;
+ myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(-1);
+ myAdjustSetting = AdjustSetting::SCANLINES;
myAdjustActive = true;
}
return;
- case Event::PaletteIncrease:
- if(pressed && !repeated)
+ case Event::ScanlinesIncrease:
+ if (pressed)
{
- myOSystem.frameBuffer().tiaSurface().paletteHandler().cyclePalette(+1);
- myAdjustSetting = AdjustSetting::PALETTE;
+ myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(+1);
+ myAdjustSetting = AdjustSetting::SCANLINES;
myAdjustActive = true;
}
return;
@@ -827,125 +899,242 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
}
return;
- case Event::ToggleTurbo:
- if (pressed && !repeated) myOSystem.console().toggleTurbo();
+ ///////////////////////////////////////////////////////////////////////////
+ // Direct key Audio & Video events
+ case Event::PreviousPaletteAttribute:
+ if (pressed)
+ {
+ myOSystem.frameBuffer().tiaSurface().paletteHandler().cycleAdjustable(-1);
+ myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
+ }
return;
- case Event::ToggleJitter:
- if (pressed && !repeated) myOSystem.console().toggleJitter();
+ case Event::NextPaletteAttribute:
+ if (pressed)
+ {
+ myOSystem.frameBuffer().tiaSurface().paletteHandler().cycleAdjustable(+1);
+ myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
+ }
return;
+ case Event::PaletteAttributeDecrease:
+ if (pressed)
+ {
+ myOSystem.frameBuffer().tiaSurface().paletteHandler().changeCurrentAdjustable(-1);
+ myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
+ }
+ return;
+
+ case Event::PaletteAttributeIncrease:
+ if (pressed)
+ {
+ myOSystem.frameBuffer().tiaSurface().paletteHandler().changeCurrentAdjustable(+1);
+ myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
+ }
+ return;
+
+ case Event::PreviousAttribute:
+ if (pressed)
+ {
+ myOSystem.frameBuffer().tiaSurface().setNTSCAdjustable(-1);
+ myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
+ }
+ return;
+
+ case Event::NextAttribute:
+ if (pressed)
+ {
+ myOSystem.frameBuffer().tiaSurface().setNTSCAdjustable(+1);
+ myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
+ }
+ return;
+
+ case Event::DecreaseAttribute:
+ if (pressed)
+ {
+ myOSystem.frameBuffer().tiaSurface().changeCurrentNTSCAdjustable(-1);
+ myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
+ }
+ return;
+
+ case Event::IncreaseAttribute:
+ if (pressed)
+ {
+ myOSystem.frameBuffer().tiaSurface().changeCurrentNTSCAdjustable(+1);
+ myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
+ }
+ return;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Debug events (with global hotkeys)
+
case Event::ToggleFrameStats:
- if (pressed) myOSystem.frameBuffer().toggleFrameStats();
- return;
-
- case Event::ToggleTimeMachine:
- if (pressed && !repeated) myOSystem.state().toggleTimeMachine();
- return;
-
- #ifdef PNG_SUPPORT
- case Event::ToggleContSnapshots:
- if (pressed && !repeated) myOSystem.png().toggleContinuousSnapshots(false);
- return;
-
- case Event::ToggleContSnapshotsFrame:
- if (pressed && !repeated) myOSystem.png().toggleContinuousSnapshots(true);
- return;
- #endif
-
- case Event::HandleMouseControl:
- if (pressed && !repeated) handleMouseControl();
- return;
-
- case Event::ToggleSAPortOrder:
- if (pressed && !repeated) toggleSAPortOrder();
- return;
-
- case Event::FormatDecrease:
- if(pressed && !repeated)
+ if (pressed && !repeated)
{
- myOSystem.console().selectFormat(-1);
- myAdjustSetting = AdjustSetting::TVFORMAT;
+ myOSystem.frameBuffer().toggleFrameStats();
+ myAdjustSetting = AdjustSetting::STATS;
myAdjustActive = true;
}
return;
- case Event::FormatIncrease:
- if(pressed && !repeated)
- {
- myOSystem.console().selectFormat(+1);
- myAdjustSetting = AdjustSetting::TVFORMAT;
- myAdjustActive = true;
- }
- return;
-
- case Event::ToggleGrabMouse:
- if (pressed && !repeated && !myOSystem.frameBuffer().fullScreen())
- myOSystem.frameBuffer().toggleGrabMouse();
- return;
-
case Event::ToggleP0Collision:
- if (pressed && !repeated) myOSystem.console().toggleP0Collision();
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleP0Collision();
+ myAdjustSetting = AdjustSetting::P0_CX;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleP0Bit:
- if (pressed && !repeated) myOSystem.console().toggleP0Bit();
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleP0Bit();
+ myAdjustSetting = AdjustSetting::P0_ENAM;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleP1Collision:
- if (pressed && !repeated) myOSystem.console().toggleP1Collision();
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleP1Collision();
+ myAdjustSetting = AdjustSetting::P1_CX;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleP1Bit:
- if (pressed && !repeated) myOSystem.console().toggleP1Bit();
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleP1Bit();
+ myAdjustSetting = AdjustSetting::P1_ENAM;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleM0Collision:
- if (pressed && !repeated) myOSystem.console().toggleM0Collision();
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleM0Collision();
+ myAdjustSetting = AdjustSetting::M0_CX;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleM0Bit:
- if (pressed && !repeated) myOSystem.console().toggleM0Bit();
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleM0Bit();
+ myAdjustSetting = AdjustSetting::M0_ENAM;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleM1Collision:
- if (pressed && !repeated) myOSystem.console().toggleM1Collision();
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleM1Collision();
+ myAdjustSetting = AdjustSetting::M1_CX;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleM1Bit:
- if (pressed && !repeated) myOSystem.console().toggleM1Bit();
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleM1Bit();
+ myAdjustSetting = AdjustSetting::M1_ENAM;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleBLCollision:
- if (pressed && !repeated) myOSystem.console().toggleBLCollision();
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleBLCollision();
+ myAdjustSetting = AdjustSetting::BL_CX;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleBLBit:
- if (pressed) myOSystem.console().toggleBLBit();
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleBLBit();
+ myAdjustSetting = AdjustSetting::BL_ENAM;
+ myAdjustActive = true;
+ }
return;
case Event::TogglePFCollision:
- if (pressed && !repeated) myOSystem.console().togglePFCollision();
+ if (pressed && !repeated)
+ {
+ myOSystem.console().togglePFCollision();
+ myAdjustSetting = AdjustSetting::PF_CX;
+ myAdjustActive = true;
+ }
return;
case Event::TogglePFBit:
- if (pressed && !repeated) myOSystem.console().togglePFBit();
- return;
-
- case Event::ToggleFixedColors:
- if (pressed) myOSystem.console().toggleFixedColors();
+ if (pressed && !repeated)
+ {
+ myOSystem.console().togglePFBit();
+ myAdjustSetting = AdjustSetting::PF_ENAM;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleCollisions:
- if (pressed && !repeated) myOSystem.console().toggleCollisions();
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleCollisions();
+ myAdjustSetting = AdjustSetting::ALL_CX;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleBits:
- if (pressed && !repeated) myOSystem.console().toggleBits();
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleBits();
+ myAdjustSetting = AdjustSetting::ALL_ENAM;
+ myAdjustActive = true;
+ }
return;
+ case Event::ToggleFixedColors:
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleFixedColors();
+ myAdjustSetting = AdjustSetting::FIXED_COL;
+ myAdjustActive = true;
+ }
+ return;
+
+ case Event::ToggleColorLoss:
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleColorLoss();
+ myAdjustSetting = AdjustSetting::COLOR_LOSS;
+ myAdjustActive = true;
+ }
+ return;
+
+ case Event::ToggleJitter:
+ if (pressed && !repeated)
+ {
+ myOSystem.console().toggleJitter();
+ myAdjustSetting = AdjustSetting::JITTER;
+ myAdjustActive = true;
+ }
+ return;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // State events
+
case Event::SaveState:
- if(pressed && !repeated)
+ if (pressed && !repeated)
{
myOSystem.state().saveState();
myAdjustDirect = AdjustSetting::STATE;
@@ -958,7 +1147,7 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
return;
case Event::PreviousState:
- if(pressed)
+ if (pressed)
{
myOSystem.state().changeState(-1);
myAdjustDirect = AdjustSetting::STATE;
@@ -966,7 +1155,7 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
return;
case Event::NextState:
- if(pressed)
+ if (pressed)
{
myOSystem.state().changeState(+1);
myAdjustDirect = AdjustSetting::STATE;
@@ -978,7 +1167,7 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
return;
case Event::LoadState:
- if(pressed && !repeated)
+ if (pressed && !repeated)
{
myOSystem.state().loadState();
myAdjustDirect = AdjustSetting::STATE;
@@ -1026,6 +1215,52 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
if (pressed) enterTimeMachineMenuMode(1000, true);
return;
+ ///////////////////////////////////////////////////////////////////////////
+ // Misc events
+
+ case Event::ToggleTurbo:
+ if (pressed && !repeated) myOSystem.console().toggleTurbo();
+ return;
+
+ case Event::Fry:
+ if (!repeated) myFryingFlag = pressed;
+ return;
+
+ case Event::ReloadConsole:
+ if (pressed && !repeated) myOSystem.reloadConsole(true);
+ return;
+
+ case Event::PreviousMultiCartRom:
+ if (pressed && !repeated) myOSystem.reloadConsole(false);
+ return;
+
+ case Event::ToggleTimeMachine:
+ if (pressed && !repeated) myOSystem.state().toggleTimeMachine();
+ return;
+
+ #ifdef PNG_SUPPORT
+ case Event::ToggleContSnapshots:
+ if (pressed && !repeated) myOSystem.png().toggleContinuousSnapshots(false);
+ return;
+
+ case Event::ToggleContSnapshotsFrame:
+ if (pressed && !repeated) myOSystem.png().toggleContinuousSnapshots(true);
+ return;
+ #endif
+
+ case Event::HandleMouseControl:
+ if (pressed && !repeated) handleMouseControl();
+ return;
+
+ case Event::ToggleSAPortOrder:
+ if (pressed && !repeated) toggleSAPortOrder();
+ return;
+
+ case Event::ToggleGrabMouse:
+ if (pressed && !repeated && !myOSystem.frameBuffer().fullScreen())
+ myOSystem.frameBuffer().toggleGrabMouse();
+ return;
+
case Event::TakeSnapshot:
if(pressed && !repeated) myOSystem.frameBuffer().tiaSurface().saveSnapShot();
return;
@@ -1138,7 +1373,6 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
if(myComboTable[combo][i] != Event::NoType)
handleEvent(myComboTable[combo][i], pressed, repeated);
return;
- ////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// Events which relate to switches()
@@ -1263,6 +1497,7 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
myOSystem.console().switches().update();
}
return;
+
////////////////////////////////////////////////////////////////////////
case Event::NoType: // Ignore unmapped events
@@ -2120,6 +2355,7 @@ void EventHandler::exitEmulation(bool checkLauncher)
EventHandler::EmulActionList EventHandler::ourEmulActionList = { {
{ Event::Quit, "Quit", "" },
{ Event::ReloadConsole, "Reload current ROM/load next game", "" },
+ { Event::PreviousMultiCartRom, "Load previous multicart game", "" },
{ Event::ExitMode, "Exit current Stella menu/mode", "" },
{ Event::OptionsMenuMode, "Enter Options menu UI", "" },
{ Event::CmdMenuMode, "Toggle Commands menu UI", "" },
@@ -2218,6 +2454,9 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { {
{ Event::KeyboardOnePound, "P1 Keyboard #", "" },
// Video
{ Event::ToggleFullScreen, "Toggle fullscreen", "" },
+#ifdef ADAPTABLE_REFRESH_SUPPORT
+ { Event::ToggleAdaptRefresh, "Toggle fullscreen refresh rate adapt", "" },
+#endif
{ Event::OverscanDecrease, "Decrease overscan in fullscreen mode", "" },
{ Event::OverscanIncrease, "Increase overscan in fullscreen mode", "" },
{ Event::VidmodeDecrease, "Previous zoom level", "" },
@@ -2256,6 +2495,8 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { {
{ Event::ScanlinesDecrease, "Decrease scanlines", "" },
{ Event::ScanlinesIncrease, "Increase scanlines", "" },
+ { Event::PreviousSettingGroup, "Select previous setting group", "" },
+ { Event::NextSettingGroup, "Select next setting group", "" },
{ Event::PreviousSetting, "Select previous setting", "" },
{ Event::NextSetting, "Select next setting", "" },
{ Event::SettingDecrease, "Decrease current setting", "" },
@@ -2354,14 +2595,17 @@ const Event::EventSet EventHandler::MiscEvents = {
// Event::MouseAxisXMove, Event::MouseAxisYMove,
// Event::MouseButtonLeftValue, Event::MouseButtonRightValue,
Event::HandleMouseControl, Event::ToggleGrabMouse,
- Event::ToggleSAPortOrder,
+ Event::ToggleSAPortOrder, Event::PreviousMultiCartRom,
+ Event::PreviousSettingGroup, Event::NextSettingGroup,
+ Event::PreviousSetting, Event::NextSetting,
+ Event::SettingDecrease, Event::SettingIncrease,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Event::EventSet EventHandler::AudioVideoEvents = {
Event::VolumeDecrease, Event::VolumeIncrease, Event::SoundToggle,
Event::VidmodeDecrease, Event::VidmodeIncrease,
- Event::ToggleFullScreen,
+ Event::ToggleFullScreen, Event::ToggleAdaptRefresh,
Event::OverscanDecrease, Event::OverscanIncrease,
Event::FormatDecrease, Event::FormatIncrease,
Event::VCenterDecrease, Event::VCenterIncrease,
@@ -2375,8 +2619,6 @@ const Event::EventSet EventHandler::AudioVideoEvents = {
Event::PhosphorDecrease, Event::PhosphorIncrease, Event::TogglePhosphor,
Event::ScanlinesDecrease, Event::ScanlinesIncrease,
Event::ToggleInter,
- Event::PreviousSetting, Event::NextSetting,
- Event::SettingDecrease, Event::SettingIncrease,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/EventHandler.hxx b/src/emucore/EventHandler.hxx
index 0ab40c7cd..0ff428998 100644
--- a/src/emucore/EventHandler.hxx
+++ b/src/emucore/EventHandler.hxx
@@ -395,9 +395,13 @@ class EventHandler
enum class AdjustSetting
{
NONE = -1,
+ // *** Audio & Video group ***
VOLUME,
ZOOM,
FULLSCREEN,
+ #ifdef ADAPTABLE_REFRESH_SUPPORT
+ ADAPT_REFRESH,
+ #endif
OVERSCAN,
TVFORMAT,
VCENTER,
@@ -417,15 +421,45 @@ class EventHandler
NTSC_ARTIFACTS,
NTSC_FRINGING,
NTSC_BLEEDING,
+ // Other TV effects adjustables
PHOSPHOR,
SCANLINES,
INTERPOLATION,
- MAX_ADJ = INTERPOLATION,
- // Only used via direct hotkeys
+ // *** Debug group ***
+ STATS,
+ P0_ENAM,
+ P1_ENAM,
+ M0_ENAM,
+ M1_ENAM,
+ BL_ENAM,
+ PF_ENAM,
+ ALL_ENAM,
+ P0_CX,
+ P1_CX,
+ M0_CX,
+ M1_CX,
+ BL_CX,
+ PF_CX,
+ ALL_CX,
+ FIXED_COL,
+ COLOR_LOSS,
+ JITTER,
+ // *** Only used via direct hotkeys ***
STATE,
PALETTE_CHANGE_ATTRIBUTE,
NTSC_CHANGE_ATTRIBUTE,
- NUM_ADJ
+ // *** Ranges ***
+ NUM_ADJ,
+ START_AV_ADJ = VOLUME,
+ END_AV_ADJ = INTERPOLATION,
+ START_DEBUG_ADJ = STATS,
+ END_DEBUG_ADJ = JITTER,
+ };
+ enum class AdjustGroup
+ {
+ AV,
+ DEBUG,
+ NUM_GROUPS
};
private:
@@ -456,6 +490,7 @@ class EventHandler
// The following two methods are used for adjusting several settings using global hotkeys
// They return the function used to adjust the currenly selected setting
+ AdjustGroup getAdjustGroup();
AdjustFunction cycleAdjustSetting(int direction);
AdjustFunction getAdjustSetting(AdjustSetting setting);
@@ -467,10 +502,10 @@ class EventHandler
string key;
};
- // ID of the currently selected global setting
- AdjustSetting myAdjustSetting{AdjustSetting::VOLUME};
// If true, the setting is visible and its value can be changed
bool myAdjustActive{false};
+ // ID of the currently selected global setting
+ AdjustSetting myAdjustSetting{AdjustSetting::START_AV_ADJ};
// ID of the currently selected direct hotkey setting (0 if none)
AdjustSetting myAdjustDirect{AdjustSetting::NONE};
@@ -517,7 +552,12 @@ class EventHandler
#else
PNG_SIZE = 0,
#endif
- EMUL_ACTIONLIST_SIZE = 156 + PNG_SIZE + COMBO_SIZE,
+ #ifdef ADAPTABLE_REFRESH_SUPPORT
+ REFRESH_SIZE = 1,
+ #else
+ REFRESH_SIZE = 0,
+ #endif
+ EMUL_ACTIONLIST_SIZE = 159 + PNG_SIZE + COMBO_SIZE + REFRESH_SIZE,
MENU_ACTIONLIST_SIZE = 18
;
diff --git a/src/emucore/FSNode.cxx b/src/emucore/FSNode.cxx
index 64af7212e..e9da05b03 100644
--- a/src/emucore/FSNode.cxx
+++ b/src/emucore/FSNode.cxx
@@ -18,6 +18,7 @@
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
+#include "Cart.hxx"
#include "FSNodeFactory.hxx"
#include "FSNode.hxx"
@@ -47,7 +48,8 @@ bool FilesystemNode::exists() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FilesystemNode::getChildren(FSList& fslist, ListMode mode,
- const NameFilter& filter) const
+ const NameFilter& filter,
+ bool includeParentDirectory) const
{
if (!_realNode || !_realNode->isDirectory())
return false;
@@ -83,7 +85,7 @@ bool FilesystemNode::getChildren(FSList& fslist, ListMode mode,
);
// Add parent node, if it is valid to do so
- if (hasParent())
+ if (includeParentDirectory && hasParent())
{
FilesystemNode parent = getParent();
parent.setName(" [..]");
@@ -236,7 +238,7 @@ size_t FilesystemNode::read(ByteBuffer& image) const
return size;
// Otherwise, the default behaviour is to read from a normal C++ ifstream
- image = make_unique(512 * 1024);
+ image = make_unique(Cartridge::maxSize());
ifstream in(getPath(), std::ios::binary);
if (in)
{
@@ -247,7 +249,7 @@ size_t FilesystemNode::read(ByteBuffer& image) const
if (length == 0)
throw runtime_error("Zero-byte file");
- size = std::min(length, 512 * 1024);
+ size = std::min(length, Cartridge::maxSize());
in.read(reinterpret_cast(image.get()), size);
}
else
diff --git a/src/emucore/FSNode.hxx b/src/emucore/FSNode.hxx
index 2a8acc278..16360cafe 100644
--- a/src/emucore/FSNode.hxx
+++ b/src/emucore/FSNode.hxx
@@ -134,7 +134,8 @@ class FilesystemNode
* does not exist).
*/
bool getChildren(FSList& fslist, ListMode mode = ListMode::DirectoriesOnly,
- const NameFilter& filter = [](const FilesystemNode&){ return true; }) const;
+ const NameFilter& filter = [](const FilesystemNode&){ return true; },
+ bool includeParentDirectory = true) const;
/**
* Set/get a string representation of the name of the file. This is can be
diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx
index 4599a3860..2f4626968 100644
--- a/src/emucore/FrameBuffer.cxx
+++ b/src/emucore/FrameBuffer.cxx
@@ -513,7 +513,8 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position,
myMsg.text = message;
myMsg.color = kBtnTextColor;
myMsg.showGauge = false;
- myMsg.w = font().getStringWidth(myMsg.text) + HBORDER * 2;
+ myMsg.w = std::min(fontWidth * (MESSAGE_WIDTH) - HBORDER * 2,
+ font().getStringWidth(myMsg.text) + HBORDER * 2);
myMsg.h = fontHeight + VBORDER * 2;
myMsg.position = position;
myMsg.enabled = true;
@@ -533,7 +534,7 @@ void FrameBuffer::showMessage(const string& message, const string& valueText,
return;
const int fontWidth = font().getMaxCharWidth(),
- fontHeight = font().getFontHeight();
+ fontHeight = font().getFontHeight();
const int VBORDER = fontHeight / 4;
const int HBORDER = fontWidth * 1.25 / 2.0;
@@ -565,7 +566,7 @@ void FrameBuffer::showMessage(const string& message, const string& valueText,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool FrameBuffer::messageShown()
+bool FrameBuffer::messageShown() const
{
#ifdef GUI_SUPPORT
return myMsg.enabled;
@@ -633,11 +634,15 @@ void FrameBuffer::drawFrameStats(float framesPerSecond)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void FrameBuffer::toggleFrameStats()
+void FrameBuffer::toggleFrameStats(bool toggle)
{
- showFrameStats(!myStatsEnabled);
+ if (toggle)
+ showFrameStats(!myStatsEnabled);
myOSystem.settings().setValue(
myOSystem.settings().getBool("dev.settings") ? "dev.stats" : "plr.stats", myStatsEnabled);
+
+ myOSystem.frameBuffer().showMessage(string("Console info ") +
+ (myStatsEnabled ? "enabled" : "disabled"));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -861,6 +866,7 @@ void FrameBuffer::setUIPalette()
const UIPaletteArray& ui_palette =
(myOSystem.settings().getString("uipalette") == "classic") ? ourClassicUIPalette :
(myOSystem.settings().getString("uipalette") == "light") ? ourLightUIPalette :
+ (myOSystem.settings().getString("uipalette") == "dark") ? ourDarkUIPalette :
ourStandardUIPalette;
for(size_t i = 0, j = myFullPalette.size() - ui_palette.size();
@@ -959,6 +965,7 @@ void FrameBuffer::setFullscreen(bool enable)
default:
return;
}
+ saveCurrentWindowPosition();
// Changing the video mode can take some time, during which the last
// sound played may get 'stuck'
@@ -989,13 +996,65 @@ void FrameBuffer::setFullscreen(bool enable)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::toggleFullscreen(bool toggle)
{
- const bool isFullscreen = toggle ? !fullScreen() : fullScreen();
+ switch (myOSystem.eventHandler().state())
+ {
+ case EventHandlerState::LAUNCHER:
+ case EventHandlerState::EMULATION:
+ case EventHandlerState::PAUSE:
+ case EventHandlerState::DEBUGGER:
+ {
+ const bool isFullscreen = toggle ? !fullScreen() : fullScreen();
- setFullscreen(isFullscreen);
+ setFullscreen(isFullscreen);
- showMessage(string("Fullscreen ") + (isFullscreen ? "enabled" : "disabled"));
+ if (myBufferType != BufferType::Launcher)
+ {
+ ostringstream msg;
+
+ msg << "Fullscreen ";
+ if (isFullscreen)
+ msg << "enabled (" << refreshRate() << " Hz)";
+ else
+ msg << "disabled";
+
+ showMessage(msg.str());
+ }
+ break;
+ }
+ default:
+ break;
+ }
}
+#ifdef ADAPTABLE_REFRESH_SUPPORT
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void FrameBuffer::toggleAdaptRefresh(bool toggle)
+{
+ bool isAdaptRefresh = myOSystem.settings().getInt("tia.fs_refresh");
+
+ if(toggle)
+ isAdaptRefresh = !isAdaptRefresh;
+
+ if(myBufferType == BufferType::Emulator)
+ {
+ if(toggle)
+ {
+ myOSystem.settings().setValue("tia.fs_refresh", isAdaptRefresh);
+ // issue a complete framebuffer re-initialization
+ myOSystem.createFrameBuffer();
+ }
+
+ ostringstream msg;
+
+ msg << "Adapt refresh rate ";
+ msg << (isAdaptRefresh ? "enabled" : "disabled");
+ msg << " (" << refreshRate() << " Hz)";
+
+ showMessage(msg.str());
+ }
+}
+#endif
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::changeOverscan(int direction)
{
@@ -1511,3 +1570,16 @@ UIPaletteArray FrameBuffer::ourLightUIPalette = {
0xffffff, 0x333333, 0xf0f0f0, 0x808080, 0xc0c0c0 // other
}
};
+
+UIPaletteArray FrameBuffer::ourDarkUIPalette = {
+ { 0x646464, 0xc0c0c0, 0x3c3c3c, 0x282828, 0x989898, // base
+ 0xc0c0c0, 0x1567a5, 0x0059a3, 0xc0c0c0, // text
+ 0x202020, 0x000000, 0x0059a3, 0xb0b0b0, // UI elements
+ 0x282828, 0x00467f, 0x646464, 0x0059a3, 0xc0c0c0, 0xc0c0c0, // buttons
+ 0x989898, // checkbox
+ 0x3c3c3c, 0x646464, // scrollbar
+ 0x7f2020, 0xc0c0c0, 0xe00000, 0xc00000, // debugger
+ 0x989898, 0x0059a3, 0x3c3c3c, 0x000000, 0x3c3c3c, // slider
+ 0x000000, 0x989898, 0x202020, 0x646464, 0x3c3c3c // other
+ }
+};
diff --git a/src/emucore/FrameBuffer.hxx b/src/emucore/FrameBuffer.hxx
index 3912f38cd..58d61dfd3 100644
--- a/src/emucore/FrameBuffer.hxx
+++ b/src/emucore/FrameBuffer.hxx
@@ -81,6 +81,13 @@ class FrameBuffer
}
};
+ struct DisplayMode
+ {
+ uInt32 display;
+ Common::Size size;
+ uInt32 refresh_rate;
+ };
+
enum class BufferType {
None,
Launcher,
@@ -159,12 +166,12 @@ class FrameBuffer
void showMessage(const string& message, const string& valueText,
float value, float minValue = 0.F, float maxValue = 100.F);
- bool messageShown();
+ bool messageShown() const;
/**
Toggles showing or hiding framerate statistics.
*/
- void toggleFrameStats();
+ void toggleFrameStats(bool toggle = true);
/**
Shows a message containing frame statistics for the current frame.
@@ -262,6 +269,13 @@ class FrameBuffer
*/
void toggleFullscreen(bool toggle = true);
+ #ifdef ADAPTABLE_REFRESH_SUPPORT
+ /**
+ Toggles between adapt fullscreen refresh rate on and off.
+ */
+ void toggleAdaptRefresh(bool toggle = true);
+ #endif
+
/**
Changes the fullscreen overscan.
@@ -439,6 +453,7 @@ class FrameBuffer
virtual int scaleY(int y) const { return y; }
protected:
+
/**
This method is called to query and initialize the video hardware
for desktop and fullscreen resolution information. Since several
@@ -510,6 +525,11 @@ class FrameBuffer
*/
virtual string about() const = 0;
+ /**
+ Retrieve the current display's refresh rate
+ */
+ virtual int refreshRate() const { return 0; }
+
protected:
// The parent system for the framebuffer
OSystem& myOSystem;
@@ -694,7 +714,8 @@ class FrameBuffer
FullPaletteArray myFullPalette;
// Holds UI palette data (for each variation)
- static UIPaletteArray ourStandardUIPalette, ourClassicUIPalette, ourLightUIPalette;
+ static UIPaletteArray ourStandardUIPalette, ourClassicUIPalette,
+ ourLightUIPalette, ourDarkUIPalette;
private:
// Following constructors and assignment operators not supported
diff --git a/src/emucore/M6532.cxx b/src/emucore/M6532.cxx
index f9eb8025c..18f950e62 100644
--- a/src/emucore/M6532.cxx
+++ b/src/emucore/M6532.cxx
@@ -59,7 +59,6 @@ void M6532::reset()
myTimer = mySystem->randGenerator().next() & 0xff;
myDivider = 1024;
mySubTimer = 0;
- myTimerWrapped = false;
myWrappedThisCycle = false;
mySetTimerCycle = myLastCycle = 0;
@@ -121,16 +120,16 @@ void M6532::updateEmulation()
myWrappedThisCycle = false;
mySubTimer = (cycles + mySubTimer) % myDivider;
- if(!myTimerWrapped)
+ if ((myInterruptFlag & TimerBit) == 0)
{
uInt32 timerTicks = (cycles + subTimer) / myDivider;
if(timerTicks > myTimer)
{
cycles -= ((myTimer + 1) * myDivider - subTimer);
+
myWrappedThisCycle = cycles == 0;
myTimer = 0xFF;
- myTimerWrapped = true;
myInterruptFlag |= TimerBit;
}
else
@@ -140,8 +139,10 @@ void M6532::updateEmulation()
}
}
- if(myTimerWrapped)
+ if((myInterruptFlag & TimerBit) != 0) {
myTimer = (myTimer - cycles) & 0xFF;
+ myWrappedThisCycle = myTimer == 0xFF;
+ }
myLastCycle = mySystem->cycles();
}
@@ -219,7 +220,7 @@ uInt8 M6532::peek(uInt16 addr)
{
// Timer Flag is always cleared when accessing INTIM
if (!myWrappedThisCycle) myInterruptFlag &= ~TimerBit;
- myTimerWrapped = false;
+
return myTimer;
}
@@ -312,10 +313,9 @@ void M6532::setTimerRegister(uInt8 value, uInt8 interval)
myTimer = value;
mySubTimer = myDivider - 1;
- myTimerWrapped = false;
// Interrupt timer flag is cleared (and invalid) when writing to the timer
- myInterruptFlag &= ~TimerBit;
+ if (!myWrappedThisCycle) myInterruptFlag &= ~TimerBit;
mySetTimerCycle = mySystem->cycles();
}
@@ -364,7 +364,6 @@ bool M6532::save(Serializer& out) const
out.putInt(myTimer);
out.putInt(mySubTimer);
out.putInt(myDivider);
- out.putBool(myTimerWrapped);
out.putBool(myWrappedThisCycle);
out.putLong(myLastCycle);
out.putLong(mySetTimerCycle);
@@ -397,7 +396,6 @@ bool M6532::load(Serializer& in)
myTimer = in.getInt();
mySubTimer = in.getInt();
myDivider = in.getInt();
- myTimerWrapped = in.getBool();
myWrappedThisCycle = in.getBool();
myLastCycle = in.getLong();
mySetTimerCycle = in.getLong();
@@ -446,7 +444,7 @@ Int32 M6532::intimClocks()
// INTIM value, it will give the current number of clocks between one
// INTIM value and the next
- return myTimerWrapped ? 1 : (myDivider - mySubTimer);
+ return ((myInterruptFlag & TimerBit) != 0) ? 1 : (myDivider - mySubTimer);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/M6532.hxx b/src/emucore/M6532.hxx
index 9aa4368b9..6e7408798 100644
--- a/src/emucore/M6532.hxx
+++ b/src/emucore/M6532.hxx
@@ -196,8 +196,7 @@ class M6532 : public Device
// The divider
uInt32 myDivider{1};
- // Has the timer wrapped?
- bool myTimerWrapped{false};
+ // Has the timer wrapped this very cycle?
bool myWrappedThisCycle{false};
// Cycle when the timer set. Debugging only.
diff --git a/src/emucore/MT24LC256.hxx b/src/emucore/MT24LC256.hxx
index 2832aef6c..94b894b21 100644
--- a/src/emucore/MT24LC256.hxx
+++ b/src/emucore/MT24LC256.hxx
@@ -46,9 +46,9 @@ class MT24LC256
public:
// Sizes of the EEPROM
- static constexpr uInt32 FLASH_SIZE = 32_KB;
- static constexpr uInt32 PAGE_SIZE = 64;
- static constexpr uInt32 PAGE_NUM = FLASH_SIZE / PAGE_SIZE;
+ static constexpr size_t FLASH_SIZE = 32_KB;
+ static constexpr size_t PAGE_SIZE = 64;
+ static constexpr size_t PAGE_NUM = FLASH_SIZE / PAGE_SIZE;
// Initial state value of flash EEPROM
static constexpr uInt8 INITIAL_VALUE = 0xff;
diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx
index 9c84b4165..0d1364790 100644
--- a/src/emucore/OSystem.cxx
+++ b/src/emucore/OSystem.cxx
@@ -46,7 +46,7 @@
#include "FSNode.hxx"
#include "MD5.hxx"
#include "Cart.hxx"
-#include "CartDetector.hxx"
+#include "CartCreator.hxx"
#include "FrameBuffer.hxx"
#include "TIASurface.hxx"
#include "PaletteHandler.hxx"
@@ -399,7 +399,7 @@ string OSystem::createConsole(const FilesystemNode& rom, const string& md5sum,
// Each time a new console is loaded, we simulate a cart removal
// Some carts need knowledge of this, as they behave differently
// based on how many power-cycles they've been through since plugged in
- mySettings->setValue("romloadcount", 0);
+ mySettings->setValue("romloadcount", -1); // we move to the next game initially
}
// Create an instance of the 2600 game console
@@ -414,7 +414,7 @@ string OSystem::createConsole(const FilesystemNode& rom, const string& md5sum,
}
catch(const runtime_error& e)
{
- buf << "ERROR: Couldn't create console (" << e.what() << ")";
+ buf << "ERROR: " << e.what();
Logger::error(buf.str());
return buf.str();
}
@@ -474,8 +474,10 @@ string OSystem::createConsole(const FilesystemNode& rom, const string& md5sum,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool OSystem::reloadConsole()
+bool OSystem::reloadConsole(bool nextrom)
{
+ mySettings->setValue("romloadprev", !nextrom);
+
return createConsole(myRomFile, myRomMD5, false) == EmptyString;
}
@@ -569,7 +571,7 @@ unique_ptr OSystem::openConsole(const FilesystemNode& romfile, string&
string cartmd5 = md5;
const string& type = props.get(PropType::Cart_Type);
unique_ptr cart =
- CartDetector::create(romfile, image, size, cartmd5, type, *mySettings);
+ CartCreator::create(romfile, image, size, cartmd5, type, *mySettings);
// Some properties may not have a name set; we can't leave it blank
if(props.get(PropType::Cart_Name) == EmptyString)
diff --git a/src/emucore/OSystem.hxx b/src/emucore/OSystem.hxx
index 2bc5368c6..4958efead 100644
--- a/src/emucore/OSystem.hxx
+++ b/src/emucore/OSystem.hxx
@@ -345,9 +345,11 @@ class OSystem
Reloads the current console (essentially deletes and re-creates it).
This can be thought of as a real console off/on toggle.
+ @param nextrom If true select next multicart ROM, else previous one
+
@return True on successful creation, otherwise false
*/
- bool reloadConsole();
+ bool reloadConsole(bool nextrom = true);
/**
Creates a new ROM launcher, to select a new ROM to emulate.
diff --git a/src/emucore/ProfilingRunner.cxx b/src/emucore/ProfilingRunner.cxx
index e7d81b997..877d35934 100644
--- a/src/emucore/ProfilingRunner.cxx
+++ b/src/emucore/ProfilingRunner.cxx
@@ -20,8 +20,8 @@
#include "ProfilingRunner.hxx"
#include "FSNode.hxx"
-#include "CartDetector.hxx"
#include "Cart.hxx"
+#include "CartCreator.hxx"
#include "MD5.hxx"
#include "Control.hxx"
#include "M6502.hxx"
@@ -109,7 +109,8 @@ bool ProfilingRunner::runOne(const ProfilingRun& run)
string md5 = MD5::hash(image, size);
string type = "";
- unique_ptr cartridge = CartDetector::create(imageFile, image, size, md5, type, mySettings);
+ unique_ptr cartridge = CartCreator::create(
+ imageFile, image, size, md5, type, mySettings);
if (!cartridge) {
cout << "ERROR: unable to determine cartridge type" << endl;
diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx
index f5e120408..0c5073d45 100644
--- a/src/emucore/Settings.cxx
+++ b/src/emucore/Settings.cxx
@@ -52,6 +52,7 @@ Settings::Settings()
setPermanent("tia.zoom", "3");
setPermanent("fullscreen", "false");
setPermanent("tia.fs_stretch", "false");
+ setPermanent("tia.fs_refresh", "false");
setPermanent("tia.fs_overscan", "0");
setPermanent("tia.vsizeadjust", 0);
setPermanent("tia.dbgcolors", "roygpb");
@@ -68,7 +69,7 @@ Settings::Settings()
setPermanent("tv.filter", "0");
setPermanent("tv.phosphor", "byrom");
setPermanent("tv.phosblend", "50");
- setPermanent("tv.scanlines", "25");
+ setPermanent("tv.scanlines", "0");
// TV options when using 'custom' mode
setPermanent("tv.sharpness", "0.0");
setPermanent("tv.resolution", "0.0");
@@ -441,6 +442,7 @@ void Settings::usage() const
<< " -tia.inter <1|0> Enable interpolated (smooth) scaling for TIA\n"
<< " image\n"
<< " -tia.fs_stretch <1|0> Stretch TIA image to fill fullscreen mode\n"
+ << " -tia.fs_refresh <1|0> Try to adapt display refresh rate to game's FPS\n"
<< " -tia.fs_overscan <0-10> Add overscan to TIA image in fullscreen mode\n"
<< " -tia.dbgcolors Debug colors to use for each object (see manual\n"
<< " for description)\n"
@@ -522,7 +524,8 @@ void Settings::usage() const
<< " launcher\n"
<< " -romloadcount Number of ROM to load next from multicard\n"
<< " -uipalette \n"
+ << " classic|\n"
+ << " light|dark>\n"
<< " -hidpi <0|1> Enable HiDPI mode\n"
<< " -dialogfont width(), width = tiaw * 2, height = myTIA->height();
rect.setBounds(0, 0, width, height);
- // Get Blargg buffer and width
- uInt32 *blarggBuf, blarggPitch;
- myTiaSurface->basePtr(blarggBuf, blarggPitch);
- double blarggXFactor = double(blarggPitch) / width;
- bool useBlargg = ntscEnabled();
-
// Fill the surface with pixels from the TIA, scaled 2x horizontally
uInt32 *buf_ptr, pitch;
myBaseTiaSurface->basePtr(buf_ptr, pitch);
for(uInt32 y = 0; y < height; ++y)
- {
for(uInt32 x = 0; x < width; ++x)
- {
- if (useBlargg)
- *buf_ptr++ = blarggBuf[y * blarggPitch + uInt32(nearbyint(x * blarggXFactor))];
- else
*buf_ptr++ = myPalette[*(myTIA->frameBuffer() + y * tiaw + x / 2)];
- }
- }
return *myBaseTiaSurface;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-uInt32 TIASurface::mapIndexedPixel(uInt8 indexedColor, uInt8 shift)
+uInt32 TIASurface::mapIndexedPixel(uInt8 indexedColor, uInt8 shift) const
{
return myPalette[indexedColor | shift];
}
diff --git a/src/emucore/TIASurface.hxx b/src/emucore/TIASurface.hxx
index 826ff75d9..2b6213785 100644
--- a/src/emucore/TIASurface.hxx
+++ b/src/emucore/TIASurface.hxx
@@ -70,14 +70,18 @@ class TIASurface
void setPalette(const PaletteArray& tia_palette, const PaletteArray& rgb_palette);
/**
- Get the TIA base surface for use in saving to a PNG image.
+ Get a TIA surface that has no post-processing whatsoever. This is
+ currently used to save PNG image in the so-called '1x mode'.
+
+ @param rect Specifies the area in which the surface data is valid
*/
const FBSurface& baseSurface(Common::Rect& rect) const;
/**
- Use the palette to map a single indexed pixel color. This is used by the TIA output widget.
+ Use the palette to map a single indexed pixel color. This is used by the
+ TIA output widget.
*/
- uInt32 mapIndexedPixel(uInt8 indexedColor, uInt8 shift = 0);
+ uInt32 mapIndexedPixel(uInt8 indexedColor, uInt8 shift = 0) const;
/**
Get the NTSCFilter object associated with the framebuffer
@@ -220,7 +224,7 @@ class TIASurface
bool mySaveSnapFlag{false};
// The palette handler
- unique_ptrmyPaletteHandler;
+ unique_ptr myPaletteHandler;
private:
// Following constructors and assignment operators not supported
diff --git a/src/emucore/module.mk b/src/emucore/module.mk
index e0dd4f96f..71bd33847 100644
--- a/src/emucore/module.mk
+++ b/src/emucore/module.mk
@@ -5,6 +5,7 @@ MODULE_OBJS := \
src/emucore/Bankswitch.o \
src/emucore/Booster.o \
src/emucore/Cart.o \
+ src/emucore/CartCreator.o \
src/emucore/CartDetector.o \
src/emucore/CartEnhanced.o \
src/emucore/Cart0840.o \
@@ -47,6 +48,7 @@ MODULE_OBJS := \
src/emucore/CartFE.o \
src/emucore/CartMDM.o \
src/emucore/CartSB.o \
+ src/emucore/CartTVBoy.o \
src/emucore/CartUA.o \
src/emucore/CartWD.o \
src/emucore/CartX07.o \
diff --git a/src/emucore/stella.pro b/src/emucore/stella.pro
index 8b783bba4..6253c7bfb 100644
--- a/src/emucore/stella.pro
+++ b/src/emucore/stella.pro
@@ -2291,6 +2291,14 @@
"Cart.Name" "Excalibur (Dragonstomper Beta) (1982) (Arcadia) (Prototype) [a]"
""
+"Cart.MD5" "1b5a8da0622bffcee4c5b42aed4e0ef0"
+"Cart.Manufacturer" "Akor"
+"Cart.Name" "TV Boy II (1992) (Akor)"
+"Cart.Note" "Includes 127 games"
+"Controller.Left" "JOYSTICK"
+"Controller.Right" "JOYSTICK"
+""
+
"Cart.MD5" "1b8c3c0bfb815b2a1010bba95998b66e"
"Cart.Manufacturer" "Telegames"
"Cart.Name" "Frogs and Flies (1988) (Telegames) (PAL)"
@@ -7084,6 +7092,16 @@
"Cart.Name" "Carnival Shooter (PD)"
""
+"Cart.MD5" "541cac55ebcf7891d9d51c415922303f"
+"Cart.Manufacturer" "SpiceWare - Darrell Spice Jr."
+"Cart.ModelNo" "SW-05"
+"Cart.Name" "Stay Frosty 2"
+"Cart.Note" "AtariAge Holiday Greetings 2014"
+"Cart.Rarity" "Homebrew"
+"Controller.Left" "JOYSTICK"
+"Display.Phosphor" "YES"
+""
+
"Cart.MD5" "5428cdfada281c569c74c7308c7f2c26"
"Cart.Manufacturer" "Activision, Larry Kaplan, David Crane"
"Cart.ModelNo" "AG-010, AG-010-04"
@@ -8526,6 +8544,14 @@
"Display.Phosphor" "YES"
""
+"Cart.MD5" "65a6f1255fe22468a8bf84ff28a4d289"
+"Cart.Manufacturer" "Akor"
+"Cart.Name" "Super TV Boy (1995) (Akor)"
+"Cart.Note" "Includes 127 games"
+"Controller.Left" "JOYSTICK"
+"Controller.Right" "JOYSTICK"
+""
+
"Cart.MD5" "65b106eba3e45f3dab72ea907f39f8b4"
"Cart.Manufacturer" "Christian Software Development - HomeComputer Software, Dan Schafer, Glenn Stohel, Jon Tedesco - Sparrow"
"Cart.ModelNo" "GCG 1001T"
@@ -10223,6 +10249,16 @@
"Cart.Note" "Abenteuer im Urwald (Jungle Runner)"
""
+"Cart.MD5" "791c88eca9836af8c34bf32b07cb58a7"
+"Cart.Manufacturer" "SpiceWare - Darrell Spice Jr."
+"Cart.ModelNo" "SW-05"
+"Cart.Name" "Stay Frosty 2 (PAL60)"
+"Cart.Note" "AtariAge Holiday Greetings 2014"
+"Cart.Rarity" "Homebrew"
+"Controller.Left" "JOYSTICK"
+"Display.Phosphor" "YES"
+""
+
"Cart.MD5" "7926083ad423ed685de3b3a04a914315"
"Cart.Manufacturer" "Barry Laws Jr."
"Cart.Name" "Face Invaders 2 (Barry Laws Jr.) (Hack)"
@@ -18954,6 +18990,14 @@
"Cart.Name" "Comitoid beta 4 (SnailSoft)"
""
+"Cart.MD5" "e4fa739c81b003c92bea7da5e84c7feb"
+"Cart.Manufacturer" "Akor"
+"Cart.Name" "TV Boy (1992) (Akor) (NTSC) [bad dump]"
+"Cart.Note" "Includes 127 games"
+"Controller.Left" "JOYSTICK"
+"Controller.Right" "JOYSTICK"
+""
+
"Cart.MD5" "e505bd8e59e31aaed20718d47b15c61b"
"Cart.Manufacturer" "Funvision - Fund. Int'l Co."
"Cart.Name" "Space War (1982) (Funvision) (PAL)"
@@ -20241,6 +20285,8 @@
"Cart.ModelNo" "649635"
"Cart.Name" "See Saw (Double-Game Package) (1983) (Otto Versand) (PAL)"
"Cart.Note" "AKA Circus Atari"
+"Controller.Left" "JOYSTICK"
+"Controller.Right" "JOYSTICK"
""
"Cart.MD5" "f3f5f72bfdd67f3d0e45d097e11b8091"
@@ -20611,6 +20657,14 @@
"Cart.Note" "AKA Play Farm"
""
+"Cart.MD5" "f7ec2f2bdbe8fbea048c0d5fa6503b0b"
+"Cart.Manufacturer" "Akor"
+"Cart.Name" "TV Boy (1992) (Akor) (PAL)"
+"Cart.Note" "Includes 127 games"
+"Controller.Left" "JOYSTICK"
+"Controller.Right" "JOYSTICK"
+""
+
"Cart.MD5" "f7f50d9c9d28bcc9f7d3075668b7ac89"
"Cart.Manufacturer" "Activision, David Crane - Ariola"
"Cart.ModelNo" "EAG-008, PAG-008, EAG-008-04I - 711 008-720"
@@ -21353,23 +21407,3 @@
"Cart.MD5" "ffebb0070689b9d322687edd9c0a2bae"
"Cart.Name" "Spitfire Attack (1983) (Milton Bradley) [h1]"
""
-
-"Cart.MD5" "541cac55ebcf7891d9d51c415922303f"
-"Cart.Manufacturer" "SpiceWare - Darrell Spice Jr."
-"Cart.ModelNo" "SW-05"
-"Cart.Name" "Stay Frosty 2"
-"Cart.Note" "AtariAge Holiday Greetings 2014"
-"Cart.Rarity" "Homebrew"
-"Controller.Left" "JOYSTICK"
-"Display.Phosphor" "YES"
-""
-
-"Cart.MD5" "791c88eca9836af8c34bf32b07cb58a7"
-"Cart.Manufacturer" "SpiceWare - Darrell Spice Jr."
-"Cart.ModelNo" "SW-05"
-"Cart.Name" "Stay Frosty 2 (PAL60)"
-"Cart.Note" "AtariAge Holiday Greetings 2014"
-"Cart.Rarity" "Homebrew"
-"Controller.Left" "JOYSTICK"
-"Display.Phosphor" "YES"
-""
diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx
index 656524eae..b3a48c335 100644
--- a/src/emucore/tia/TIA.cxx
+++ b/src/emucore/tia/TIA.cxx
@@ -414,85 +414,81 @@ uInt8 TIA::peek(uInt16 address)
{
updateEmulation();
- // If pins are undriven, we start with the last databus value
- // Otherwise, there is some randomness injected into the mix
- // In either case, we start out with D7 and D6 disabled (the only
- // valid bits in a TIA read), and selectively enable them
- uInt8 lastDataBusValue =
- !myTIAPinsDriven ? mySystem->getDataBusState() : mySystem->getDataBusState(0xFF);
-
- uInt8 result;
+ // Start with all bits disabled
+ // In some cases both D7 and D6 are used; in other cases only D7 is used
+ uInt8 result = 0b0000000;
switch (address & 0x0F) {
case CXM0P:
- result = collCXM0P();
+ result = collCXM0P() & 0b11000000;
break;
case CXM1P:
- result = collCXM1P();
+ result = collCXM1P() & 0b11000000;
break;
case CXP0FB:
- result = collCXP0FB();
+ result = collCXP0FB() & 0b11000000;
break;
case CXP1FB:
- result = collCXP1FB();
+ result = collCXP1FB() & 0b11000000;
break;
case CXM0FB:
- result = collCXM0FB();
+ result = collCXM0FB() & 0b11000000;
break;
case CXM1FB:
- result = collCXM1FB();
+ result = collCXM1FB() & 0b11000000;
break;
case CXPPMM:
- result = collCXPPMM();
+ result = collCXPPMM() & 0b11000000;
break;
case CXBLPF:
- result = collCXBLPF();
+ result = collCXBLPF() & 0b10000000;
break;
case INPT0:
updatePaddle(0);
- result = myPaddleReaders[0].inpt(myTimestamp) | (lastDataBusValue & 0x40);
+ result = myPaddleReaders[0].inpt(myTimestamp) & 0b10000000;
break;
case INPT1:
updatePaddle(1);
- result = myPaddleReaders[1].inpt(myTimestamp) | (lastDataBusValue & 0x40);
+ result = myPaddleReaders[1].inpt(myTimestamp) & 0b10000000;
break;
case INPT2:
updatePaddle(2);
- result = myPaddleReaders[2].inpt(myTimestamp) | (lastDataBusValue & 0x40);
+ result = myPaddleReaders[2].inpt(myTimestamp) & 0b10000000;
break;
case INPT3:
updatePaddle(3);
- result = myPaddleReaders[3].inpt(myTimestamp) | (lastDataBusValue & 0x40);
+ result = myPaddleReaders[3].inpt(myTimestamp) & 0b10000000;
break;
case INPT4:
- result =
- myInput0.inpt(!myConsole.leftController().read(Controller::DigitalPin::Six)) |
- (lastDataBusValue & 0x40);
+ result = myInput0.inpt(!myConsole.leftController().read(Controller::DigitalPin::Six))
+ & 0b10000000;
break;
case INPT5:
- result =
- myInput1.inpt(!myConsole.rightController().read(Controller::DigitalPin::Six)) |
- (lastDataBusValue & 0x40);
+ result = myInput1.inpt(!myConsole.rightController().read(Controller::DigitalPin::Six))
+ & 0b10000000;
break;
default:
- result = 0;
+ break;
}
- return (result & 0xC0) | (lastDataBusValue & 0x3F);
+ // Bits D5 .. D0 are floating
+ // The options are either to use the last databus value, or use random data
+ return result | ((!myTIAPinsDriven ? mySystem->getDataBusState() :
+ mySystem->randGenerator().next()) & 0b00111111);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1033,9 +1029,13 @@ bool TIA::toggleBit(TIABit b, uInt8 mode)
mask = b;
break;
- default:
+ case 2:
mask = (~mySpriteEnabledBits & b);
break;
+
+ default:
+ mask = (mySpriteEnabledBits & b);
+ break;
}
mySpriteEnabledBits = (mySpriteEnabledBits & ~b) | mask;
@@ -1051,9 +1051,11 @@ bool TIA::toggleBit(TIABit b, uInt8 mode)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool TIA::toggleBits()
+bool TIA::toggleBits(bool toggle)
{
- toggleBit(TIABit(0xFF), mySpriteEnabledBits > 0 ? 0 : 1);
+ toggleBit(TIABit(0xFF), toggle
+ ? mySpriteEnabledBits > 0 ? 0 : 1
+ : mySpriteEnabledBits);
return mySpriteEnabledBits;
}
@@ -1072,9 +1074,13 @@ bool TIA::toggleCollision(TIABit b, uInt8 mode)
mask = b;
break;
- default:
+ case 2:
mask = (~myCollisionsEnabledBits & b);
break;
+
+ default:
+ mask = (myCollisionsEnabledBits & b);
+ break;
}
myCollisionsEnabledBits = (myCollisionsEnabledBits & ~b) | mask;
@@ -1090,9 +1096,11 @@ bool TIA::toggleCollision(TIABit b, uInt8 mode)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool TIA::toggleCollisions()
+bool TIA::toggleCollisions(bool toggle)
{
- toggleCollision(TIABit(0xFF), myCollisionsEnabledBits > 0 ? 0 : 1);
+ toggleCollision(TIABit(0xFF), toggle
+ ? myCollisionsEnabledBits > 0 ? 0 : 1
+ : myCollisionsEnabledBits);
return myCollisionsEnabledBits;
}
@@ -1211,6 +1219,9 @@ bool TIA::toggleJitter(uInt8 mode)
myEnableJitter = !myEnableJitter;
break;
+ case 3:
+ break;
+
default:
throw runtime_error("invalid argument for toggleJitter");
}
diff --git a/src/emucore/tia/TIA.hxx b/src/emucore/tia/TIA.hxx
index de3c373a4..3b2cbea7c 100644
--- a/src/emucore/tia/TIA.hxx
+++ b/src/emucore/tia/TIA.hxx
@@ -356,23 +356,25 @@ class TIA : public Device
disabling a graphical object also disables its collisions.
@param mode 1/0 indicates on/off, and values greater than 1 mean
- flip the bit from its current state
+ 2 means flip the bit from its current state
+ and values greater than 2 mean return current state
@return Whether the bit was enabled or disabled
*/
bool toggleBit(TIABit b, uInt8 mode = 2);
- bool toggleBits();
+ bool toggleBits(bool toggle = true);
/**
Enables/disable/toggle the specified (or all) TIA bit collision(s).
- @param mode 1/0 indicates on/off, and values greater than 1 mean
- flip the collision from its current state
+ @param mode 1/0 indicates on/off,
+ 2 means flip the collision from its current state
+ and values greater than 2 mean return current state
@return Whether the collision was enabled or disabled
*/
bool toggleCollision(TIABit b, uInt8 mode = 2);
- bool toggleCollisions();
+ bool toggleCollisions(bool toggle = true);
/**
Enables/disable/toggle/query 'fixed debug colors' mode.
diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx
index 1cc0b3b8c..e455a976c 100644
--- a/src/gui/Dialog.cxx
+++ b/src/gui/Dialog.cxx
@@ -835,6 +835,34 @@ void Dialog::addDefaultsOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
addOKCancelBGroup(wid, font, okText, cancelText, focusOKButton, buttonWidth);
}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void Dialog::addDefaultsExtraOKCancelBGroup(
+ WidgetArray& wid, const GUI::Font& font,
+ const string& extraText, int extraCmd,
+ const string& okText, const string& cancelText, const string& defaultsText,
+ bool focusOKButton)
+{
+ const int fontWidth = font.getMaxCharWidth(),
+ fontHeight = font.getFontHeight(),
+ buttonHeight = font.getLineHeight() * 1.25;
+ const int VBORDER = fontHeight / 2;
+ const int HBORDER = fontWidth * 1.25;
+ const int BTN_BORDER = fontWidth * 2.5;
+ const int BUTTON_GAP = fontWidth;
+ const int buttonWidth = font.getStringWidth(defaultsText) + BTN_BORDER;
+
+ addDefaultWidget(new ButtonWidget(this, font, HBORDER, _h - buttonHeight - VBORDER,
+ buttonWidth, buttonHeight, defaultsText, GuiObject::kDefaultsCmd));
+ wid.push_back(_defaultWidget);
+
+ wid.push_back(new ButtonWidget(this, font, HBORDER + buttonWidth + BUTTON_GAP,
+ _h - buttonHeight - VBORDER, buttonWidth, buttonHeight,
+ extraText, extraCmd)
+ );
+
+ addOKCancelBGroup(wid, font, okText, cancelText, focusOKButton, buttonWidth);
+}
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::TabFocus::appendFocusList(WidgetArray& list)
{
diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx
index 5b95fe5e0..0dc5e7118 100644
--- a/src/gui/Dialog.hxx
+++ b/src/gui/Dialog.hxx
@@ -158,6 +158,15 @@ class Dialog : public GuiObject
const string& defaultsText = "Defaults",
bool focusOKButton = true);
+ // NOTE: This method, and the two above it, are due to be refactored at some
+ // point, since the parameter list is kind of getting ridiculous
+ void addDefaultsExtraOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
+ const string& extraText, int extraCmd,
+ const string& okText = "OK",
+ const string& cancelText = "Cancel",
+ const string& defaultsText = "Defaults",
+ bool focusOKButton = true);
+
void processCancelWithoutWidget(bool state) { _processCancel = state; }
virtual void processCancel() { close(); }
diff --git a/src/gui/EmulationDialog.cxx b/src/gui/EmulationDialog.cxx
index e9bb3804a..dcbb42859 100644
--- a/src/gui/EmulationDialog.cxx
+++ b/src/gui/EmulationDialog.cxx
@@ -237,6 +237,7 @@ void EmulationDialog::saveConfig()
instance().console().initializeAudio();
// update VSync
instance().console().initializeVideo();
+ instance().createFrameBuffer();
instance().frameBuffer().tiaSurface().ntsc().enableThreading(myUseThreads->getState());
}
diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx
index fd646c6ed..ff1fca0c6 100644
--- a/src/gui/GameInfoDialog.cxx
+++ b/src/gui/GameInfoDialog.cxx
@@ -383,7 +383,7 @@ GameInfoDialog::GameInfoDialog(
// Add Defaults, OK and Cancel buttons
wid.clear();
- addDefaultsOKCancelBGroup(wid, font);
+ addDefaultsExtraOKCancelBGroup(wid, font, "Save", kSavePressed);
addBGroupToFocusList(wid);
}
@@ -393,11 +393,13 @@ void GameInfoDialog::loadConfig()
if(instance().hasConsole())
{
myGameProperties = instance().console().properties();
+ myGameFile = instance().romFile();
}
else
{
const string& md5 = instance().launcher().selectedRomMD5();
instance().propSet().getMD5(md5, myGameProperties);
+ myGameFile = FilesystemNode(instance().launcher().selectedRom());
}
loadEmulationProperties(myGameProperties);
@@ -568,7 +570,7 @@ void GameInfoDialog::loadCartridgeProperties(const Properties& props)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void GameInfoDialog::saveConfig()
+void GameInfoDialog::saveProperties()
{
// Emulation properties
myGameProperties.set(PropType::Cart_Type, myBSType->getSelectedTag().toString());
@@ -613,6 +615,12 @@ void GameInfoDialog::saveConfig()
myGameProperties.set(PropType::Cart_ModelNo, myModelNo->getText());
myGameProperties.set(PropType::Cart_Rarity, myRarity->getText());
myGameProperties.set(PropType::Cart_Note, myNote->getText());
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void GameInfoDialog::saveConfig()
+{
+ saveProperties();
// Always insert; if the properties are already present, nothing will happen
instance().propSet().insert(myGameProperties);
@@ -626,7 +634,7 @@ void GameInfoDialog::saveConfig()
// update 'Emulation' tab settings immediately
instance().console().setFormat(myFormat->getSelected());
instance().frameBuffer().tiaSurface().enablePhosphor(myPhosphor->getState(), myPPBlend->getValue());
- instance().console().updateVcenter(vcenter);
+ instance().console().updateVcenter(myVCenter->getValue());
instance().console().initializeAudio();
// update 'Console' tab settings immediately
@@ -699,7 +707,7 @@ void GameInfoDialog::updateControllerStates()
label = (!swapPorts ? instance().console().leftController().name()
: instance().console().rightController().name()) + " detected";
else if(autoDetect)
- label = ControllerDetector::detectName(image.get(), size, type,
+ label = ControllerDetector::detectName(image, size, type,
!swapPorts ? Controller::Jack::Left : Controller::Jack::Right,
instance().settings()) + " detected";
}
@@ -714,7 +722,7 @@ void GameInfoDialog::updateControllerStates()
label = (!swapPorts ? instance().console().rightController().name()
: instance().console().leftController().name()) + " detected";
else if(autoDetect)
- label = ControllerDetector::detectName(image.get(), size, type,
+ label = ControllerDetector::detectName(image, size, type,
!swapPorts ? Controller::Jack::Right : Controller::Jack::Left,
instance().settings()) + " detected";
}
@@ -782,19 +790,38 @@ void GameInfoDialog::eraseEEPROM()
Controller& lport = instance().console().leftController();
Controller& rport = instance().console().rightController();
- if(lport.type() == Controller::Type::SaveKey || lport.type() == Controller::Type::AtariVox)
+ if(lport.type() == Controller::Type::SaveKey ||
+ lport.type() == Controller::Type::AtariVox)
{
SaveKey& skey = static_cast(lport);
skey.eraseCurrent();
}
- if(rport.type() == Controller::Type::SaveKey || rport.type() == Controller::Type::AtariVox)
+ if(rport.type() == Controller::Type::SaveKey ||
+ rport.type() == Controller::Type::AtariVox)
{
SaveKey& skey = static_cast(rport);
skey.eraseCurrent();
}
}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void GameInfoDialog::saveCurrentPropertiesToDisk()
+{
+ saveProperties();
+
+ FilesystemNode propfile(instance().defaultSaveDir() + myGameFile.getNameWithExt(".pro"));
+ ofstream out(propfile.getPath());
+ if(out)
+ {
+ out << myGameProperties;
+ instance().frameBuffer().showMessage("Properties saved to " +
+ propfile.getShortPath());
+ }
+ else
+ instance().frameBuffer().showMessage("Error saving properties");
+}
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GameInfoDialog::handleCommand(CommandSender* sender, int cmd,
int data, int id)
@@ -810,6 +837,10 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd,
setDefaults();
break;
+ case kSavePressed:
+ saveCurrentPropertiesToDisk();
+ break;
+
case TabWidget::kTabChangedCmd:
if(data == 2) // 'Controllers' tab selected
updateControllerStates();
diff --git a/src/gui/GameInfoDialog.hxx b/src/gui/GameInfoDialog.hxx
index 2e2dc4f8a..7e5febdde 100644
--- a/src/gui/GameInfoDialog.hxx
+++ b/src/gui/GameInfoDialog.hxx
@@ -53,9 +53,12 @@ class GameInfoDialog : public Dialog, public CommandSender
void loadControllerProperties(const Properties& props);
// load the properties for the 'Cartridge' tab
void loadCartridgeProperties(const Properties& props);
+ // save properties from all tabs into the local properties object
+ void saveProperties();
void updateControllerStates();
void eraseEEPROM();
+ void saveCurrentPropertiesToDisk();
private:
TabWidget* myTab{nullptr};
@@ -115,10 +118,13 @@ class GameInfoDialog : public Dialog, public CommandSender
kEEButtonPressed = 'EEgb',
kPXCenterChanged = 'Pxch',
kPYCenterChanged = 'Pych',
+ kSavePressed = 'GIsp'
};
// Game properties for currently loaded ROM
Properties myGameProperties;
+ // Filename of the currently loaded ROM
+ FilesystemNode myGameFile;
private:
// Following constructors and assignment operators not supported
diff --git a/src/gui/RomInfoWidget.cxx b/src/gui/RomInfoWidget.cxx
index 3cfa43185..b90a45fb2 100644
--- a/src/gui/RomInfoWidget.cxx
+++ b/src/gui/RomInfoWidget.cxx
@@ -152,10 +152,10 @@ void RomInfoWidget::parseProperties(const FilesystemNode& node)
(image = instance().openROM(node, md5, size)) != nullptr)
{
Logger::debug(myProperties.get(PropType::Cart_Name) + ":");
- left = ControllerDetector::detectName(image.get(), size, leftType,
+ left = ControllerDetector::detectName(image, size, leftType,
!swappedPorts ? Controller::Jack::Left : Controller::Jack::Right,
instance().settings());
- right = ControllerDetector::detectName(image.get(), size, rightType,
+ right = ControllerDetector::detectName(image, size, rightType,
!swappedPorts ? Controller::Jack::Right : Controller::Jack::Left,
instance().settings());
if (bsDetected == "AUTO")
diff --git a/src/gui/SnapshotDialog.cxx b/src/gui/SnapshotDialog.cxx
index 870a82b54..e7f5795ed 100644
--- a/src/gui/SnapshotDialog.cxx
+++ b/src/gui/SnapshotDialog.cxx
@@ -89,7 +89,7 @@ SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& parent,
// Snapshot in 1x mode (ignore scaling)
ypos += lineHeight + VGAP;
mySnap1x = new CheckboxWidget(this, font, xpos, ypos,
- "Ignore scaling (1x mode)");
+ "Create pixel-exact image (no zoom/post-processing)");
wid.push_back(mySnap1x);
// Add Defaults, OK and Cancel buttons
diff --git a/src/gui/StellaSettingsDialog.cxx b/src/gui/StellaSettingsDialog.cxx
index b5c1e5106..74e8ca35f 100644
--- a/src/gui/StellaSettingsDialog.cxx
+++ b/src/gui/StellaSettingsDialog.cxx
@@ -540,7 +540,7 @@ void StellaSettingsDialog::updateControllerStates()
if(instance().hasConsole())
label = (instance().console().leftController().name()) + " detected";
else if(autoDetect)
- label = ControllerDetector::detectName(image.get(), size, type,
+ label = ControllerDetector::detectName(image, size, type,
Controller::Jack::Left,
instance().settings()) + " detected";
}
@@ -554,7 +554,7 @@ void StellaSettingsDialog::updateControllerStates()
if(instance().hasConsole())
label = (instance().console().rightController().name()) + " detected";
else if(autoDetect)
- label = ControllerDetector::detectName(image.get(), size, type,
+ label = ControllerDetector::detectName(image, size, type,
Controller::Jack::Right,
instance().settings()) + " detected";
}
diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx
index eafc2e00b..598dd0756 100644
--- a/src/gui/UIDialog.cxx
+++ b/src/gui/UIDialog.cxx
@@ -85,6 +85,7 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
VarList::push_back(items, "Standard", "standard");
VarList::push_back(items, "Classic", "classic");
VarList::push_back(items, "Light", "light");
+ VarList::push_back(items, "Dark", "dark");
myPalettePopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
items, "Theme ", lwidth);
wid.push_back(myPalettePopup);
diff --git a/src/gui/VideoAudioDialog.cxx b/src/gui/VideoAudioDialog.cxx
index 48fdcc8de..e87cbe221 100644
--- a/src/gui/VideoAudioDialog.cxx
+++ b/src/gui/VideoAudioDialog.cxx
@@ -47,7 +47,7 @@
new SliderWidget(myTab, _font, xpos, ypos-1, swidth, lineHeight, \
desc, lwidth, cmd, fontWidth*4, "%"); \
myTV ## obj->setMinValue(0); myTV ## obj->setMaxValue(100); \
- myTV ## obj->setStepValue(2); \
+ myTV ## obj->setStepValue(1); \
myTV ## obj->setTickmarkIntervals(2); \
wid.push_back(myTV ## obj); \
ypos += lineHeight + VGAP;
@@ -83,14 +83,6 @@ VideoAudioDialog::VideoAudioDialog(OSystem& osystem, DialogContainer& parent,
addTVEffectsTab();
addAudioTab();
- //const int req_w = std::max(myFastSCBios->getRight(), myCloneBad->getRight()) + HBORDER + 1;
- //const int req_h = _th + VGAP * 3
- // + std::max(myUseVSync->getBottom(), myTVScanIntense->getBottom())
- // + buttonHeight + VBORDER * 2;
- //// Set real dimensions
- //setSize(req_w, req_h, max_w, max_h);
-
-
// Add Defaults, OK and Cancel buttons
WidgetArray wid;
addDefaultsOKCancelBGroup(wid, _font);
@@ -149,26 +141,29 @@ void VideoAudioDialog::addDisplayTab()
wid.push_back(myFullscreen);
ypos += lineHeight + VGAP;
- /*pwidth = font.getStringWidth("0: 3840x2860@120Hz");
- myFullScreenMode = new PopUpWidget(myTab, font, xpos + INDENT + 2, ypos, pwidth, lineHeight,
- instance().frameBuffer().supportedScreenModes(), "Mode ");
- wid.push_back(myFullScreenMode);
- ypos += lineHeight + VGAP;*/
-
// FS stretch
myUseStretch = new CheckboxWidget(myTab, _font, xpos + INDENT, ypos + 1, "Stretch");
wid.push_back(myUseStretch);
+
+#ifdef ADAPTABLE_REFRESH_SUPPORT
+ // Adapt refresh rate
ypos += lineHeight + VGAP;
+ myRefreshAdapt = new CheckboxWidget(myTab, _font, xpos + INDENT, ypos + 1, "Adapt display refresh rate");
+ wid.push_back(myRefreshAdapt);
+#else
+ myRefreshAdapt = nullptr;
+#endif
// FS overscan
+ ypos += lineHeight + VGAP;
myTVOverscan = new SliderWidget(myTab, _font, xpos + INDENT, ypos - 1, swidth, lineHeight,
"Overscan", lwidth - INDENT, kOverscanChanged, fontWidth * 3, "%");
myTVOverscan->setMinValue(0); myTVOverscan->setMaxValue(10);
myTVOverscan->setTickmarkIntervals(2);
wid.push_back(myTVOverscan);
- ypos += lineHeight + VGAP;
// Vertical size
+ ypos += lineHeight + VGAP;
myVSizeAdjust =
new SliderWidget(myTab, _font, xpos, ypos-1, swidth, lineHeight,
"V-Size adjust", lwidth, kVSizeChanged, fontWidth * 7, "%", 0, true);
@@ -176,6 +171,7 @@ void VideoAudioDialog::addDisplayTab()
myVSizeAdjust->setTickmarkIntervals(2);
wid.push_back(myVSizeAdjust);
+
// Add items for tab 0
addToFocusList(wid, myTab, tabID);
}
@@ -480,10 +476,12 @@ void VideoAudioDialog::loadConfig()
// Fullscreen
myFullscreen->setState(instance().settings().getBool("fullscreen"));
- /*string mode = instance().settings().getString("fullscreenmode");
- myFullScreenMode->setSelected(mode);*/
// Fullscreen stretch setting
myUseStretch->setState(instance().settings().getBool("tia.fs_stretch"));
+#ifdef ADAPTABLE_REFRESH_SUPPORT
+ // Adapt refresh rate
+ myRefreshAdapt->setState(instance().settings().getBool("tia.fs_refresh"));
+#endif
// Fullscreen overscan setting
myTVOverscan->setValue(instance().settings().getInt("tia.fs_overscan"));
handleFullScreenChange();
@@ -595,6 +593,10 @@ void VideoAudioDialog::saveConfig()
instance().settings().setValue("fullscreen", myFullscreen->getState());
// Fullscreen stretch setting
instance().settings().setValue("tia.fs_stretch", myUseStretch->getState());
+#ifdef ADAPTABLE_REFRESH_SUPPORT
+ // Adapt refresh rate
+ instance().settings().setValue("tia.fs_refresh", myRefreshAdapt->getState());
+#endif
// Fullscreen overscan
instance().settings().setValue("tia.fs_overscan", myTVOverscan->getValueLabel());
@@ -611,7 +613,6 @@ void VideoAudioDialog::saveConfig()
// Note: Palette values are saved directly when changed!
-
/////////////////////////////////////////////////////////////////////////////
// TV Effects tab
// TV Mode
@@ -706,8 +707,10 @@ void VideoAudioDialog::setDefaults()
myTIAInterpolate->setState(false);
// screen size
myFullscreen->setState(false);
- //myFullScreenMode->setSelectedIndex(0);
myUseStretch->setState(false);
+ #ifdef ADAPTABLE_REFRESH_SUPPORT
+ myRefreshAdapt->setState(false);
+ #endif
myTVOverscan->setValue(0);
myTIAZoom->setValue(300);
myVSizeAdjust->setValue(0);
@@ -726,6 +729,7 @@ void VideoAudioDialog::setDefaults()
myTVBright->setValue(50);
myTVGamma->setValue(50);
handlePaletteChange();
+ handlePaletteUpdate();
break;
case 2: // TV effects
@@ -833,6 +837,9 @@ void VideoAudioDialog::handleFullScreenChange()
{
bool enable = myFullscreen->getState();
myUseStretch->setEnabled(enable);
+#ifdef ADAPTABLE_REFRESH_SUPPORT
+ myRefreshAdapt->setEnabled(enable);
+#endif
myTVOverscan->setEnabled(enable);
}
@@ -998,24 +1005,21 @@ void VideoAudioDialog::handleCommand(CommandSender* sender, int cmd,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void VideoAudioDialog::addPalette(int x, int y, int w, int h)
{
- if(instance().hasConsole())
- {
- constexpr int NUM_LUMA = 8;
- constexpr int NUM_CHROMA = 16;
- const GUI::Font& ifont = instance().frameBuffer().infoFont();
- const int lwidth = ifont.getMaxCharWidth() * 1.5;
- const float COLW = float(w - lwidth) / NUM_LUMA;
- const float COLH = float(h) / NUM_CHROMA;
- const int yofs = (COLH - ifont.getFontHeight() + 1) / 2;
+ constexpr int NUM_LUMA = 8;
+ constexpr int NUM_CHROMA = 16;
+ const GUI::Font& ifont = instance().frameBuffer().infoFont();
+ const int lwidth = ifont.getMaxCharWidth() * 1.5;
+ const float COLW = float(w - lwidth) / NUM_LUMA;
+ const float COLH = float(h) / NUM_CHROMA;
+ const int yofs = (COLH - ifont.getFontHeight() + 1) / 2;
- for(int idx = 0; idx < NUM_CHROMA; ++idx)
+ for(int idx = 0; idx < NUM_CHROMA; ++idx)
+ {
+ myColorLbl[idx] = new StaticTextWidget(myTab, ifont, x, y + yofs + idx * COLH, " ");
+ for(int lum = 0; lum < NUM_LUMA; ++lum)
{
- myColorLbl[idx] = new StaticTextWidget(myTab, ifont, x, y + yofs + idx * COLH, " ");
- for(int lum = 0; lum < NUM_LUMA; ++lum)
- {
- myColor[idx][lum] = new ColorWidget(myTab, _font, x + lwidth + lum * COLW, y + idx * COLH,
- COLW + 1, COLH + 1, 0, false);
- }
+ myColor[idx][lum] = new ColorWidget(myTab, _font, x + lwidth + lum * COLW, y + idx * COLH,
+ COLW + 1, COLH + 1, 0, false);
}
}
}
diff --git a/src/gui/VideoAudioDialog.hxx b/src/gui/VideoAudioDialog.hxx
index f46740ae6..0961f776e 100644
--- a/src/gui/VideoAudioDialog.hxx
+++ b/src/gui/VideoAudioDialog.hxx
@@ -71,9 +71,9 @@ class VideoAudioDialog : public Dialog
PopUpWidget* myRenderer{nullptr};
CheckboxWidget* myTIAInterpolate{nullptr};
CheckboxWidget* myFullscreen{nullptr};
- //PopUpWidget* myFullScreenMode;
CheckboxWidget* myUseStretch{nullptr};
SliderWidget* myTVOverscan{nullptr};
+ CheckboxWidget* myRefreshAdapt{nullptr};
SliderWidget* myTIAZoom{nullptr};
SliderWidget* myVSizeAdjust{nullptr};
diff --git a/src/libretro/FSNodeLIBRETRO.cxx b/src/libretro/FSNodeLIBRETRO.cxx
index c2ee02b97..f3670f0a2 100644
--- a/src/libretro/FSNodeLIBRETRO.cxx
+++ b/src/libretro/FSNodeLIBRETRO.cxx
@@ -15,6 +15,8 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
+#include "bspf.hxx"
+#include "Cart.hxx"
#include "FSNodeLIBRETRO.hxx"
#ifdef _WIN32
@@ -92,7 +94,7 @@ AbstractFSNodePtr FilesystemNodeLIBRETRO::getParent() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
size_t FilesystemNodeLIBRETRO::read(ByteBuffer& image) const
{
- image = make_unique(512 * 1024);
+ image = make_unique(Cartridge::maxSize());
extern uInt32 libretro_read_rom(void* data);
return libretro_read_rom(image.get());
diff --git a/src/libretro/Makefile.common b/src/libretro/Makefile.common
index 5fafdd855..994628725 100644
--- a/src/libretro/Makefile.common
+++ b/src/libretro/Makefile.common
@@ -39,6 +39,7 @@ SOURCES_CXX := \
$(CORE_DIR)/emucore/Bankswitch.cxx \
$(CORE_DIR)/emucore/Booster.cxx \
$(CORE_DIR)/emucore/Cart.cxx \
+ $(CORE_DIR)/emucore/CartCreator.cxx \
$(CORE_DIR)/emucore/CartDetector.cxx \
$(CORE_DIR)/emucore/CartEnhanced.cxx \
$(CORE_DIR)/emucore/Cart0840.cxx \
@@ -81,6 +82,7 @@ SOURCES_CXX := \
$(CORE_DIR)/emucore/CartMDM.cxx \
$(CORE_DIR)/emucore/CartMNetwork.cxx \
$(CORE_DIR)/emucore/CartSB.cxx \
+ $(CORE_DIR)/emucore/CartTVBoy.cxx \
$(CORE_DIR)/emucore/CartUA.cxx \
$(CORE_DIR)/emucore/CartWD.cxx \
$(CORE_DIR)/emucore/CartX07.cxx \
diff --git a/src/libretro/StellaLIBRETRO.cxx b/src/libretro/StellaLIBRETRO.cxx
index d670c45a9..38e52e734 100644
--- a/src/libretro/StellaLIBRETRO.cxx
+++ b/src/libretro/StellaLIBRETRO.cxx
@@ -188,7 +188,6 @@ void StellaLIBRETRO::updateVideo()
if(tia.scanlines() == 0) break;
}
-
video_ready = tia.newFramePending();
if (video_ready)
@@ -221,7 +220,7 @@ bool StellaLIBRETRO::loadState(const void* data, size_t size)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool StellaLIBRETRO::saveState(void* data, size_t size)
+bool StellaLIBRETRO::saveState(void* data, size_t size) const
{
Serializer state;
@@ -236,7 +235,7 @@ bool StellaLIBRETRO::saveState(void* data, size_t size)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-size_t StellaLIBRETRO::getStateSize()
+size_t StellaLIBRETRO::getStateSize() const
{
Serializer state;
@@ -247,52 +246,52 @@ size_t StellaLIBRETRO::getStateSize()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-float StellaLIBRETRO::getVideoAspectPar()
+float StellaLIBRETRO::getVideoAspectPar() const
{
float par;
if (getVideoNTSC())
{
- if (!video_aspect_ntsc)
- {
- if (video_filter != NTSCFilter::Preset::OFF)
+ if (!video_aspect_ntsc)
{
- // non-interlace square pixel clock -- 1.0 pixel @ color burst -- double-width pixels
- par = (6.1363635f / 3.579545454f) / 2.0;
+ if (video_filter != NTSCFilter::Preset::OFF)
+ {
+ // non-interlace square pixel clock -- 1.0 pixel @ color burst -- double-width pixels
+ par = (6.1363635f / 3.579545454f) / 2.0;
+ }
+ else
+ {
+ // blargg filter
+ par = 1.0;
+ }
}
else
- {
- // blargg filter
- par = 1.0;
- }
- }
- else
- par = video_aspect_ntsc / 100.0;
+ par = video_aspect_ntsc / 100.0;
}
else
{
- if (!video_aspect_pal)
- {
- if (video_filter != NTSCFilter::Preset::OFF)
+ if (!video_aspect_pal)
{
- // non-interlace square pixel clock -- 0.8 pixel @ color burst -- double-width pixels
- par = (7.3750000f / (4.43361875f * 4.0f / 5.0f)) / 2.0f;
+ if (video_filter != NTSCFilter::Preset::OFF)
+ {
+ // non-interlace square pixel clock -- 0.8 pixel @ color burst -- double-width pixels
+ par = (7.3750000f / (4.43361875f * 4.0f / 5.0f)) / 2.0f;
+ }
+ else
+ {
+ // blargg filter
+ par = 1.0;
+ }
}
else
- {
- // blargg filter
- par = 1.0;
- }
- }
- else
- par = video_aspect_pal / 100.0;
+ par = video_aspect_pal / 100.0;
}
return par;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-float StellaLIBRETRO::getVideoAspect()
+float StellaLIBRETRO::getVideoAspect() const
{
uInt32 width = myOSystem->console().tia().width() * 2;
@@ -301,7 +300,7 @@ float StellaLIBRETRO::getVideoAspect()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void* StellaLIBRETRO::getVideoBuffer()
+void* StellaLIBRETRO::getVideoBuffer() const
{
FrameBufferLIBRETRO& frame = static_cast(myOSystem->frameBuffer());
@@ -309,7 +308,7 @@ void* StellaLIBRETRO::getVideoBuffer()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool StellaLIBRETRO::getVideoNTSC()
+bool StellaLIBRETRO::getVideoNTSC() const
{
const ConsoleInfo& console_info = myOSystem->console().about();
string format = console_info.DisplayFormat;
@@ -348,13 +347,13 @@ void StellaLIBRETRO::setConsoleFormat(uInt32 mode)
{
switch(mode)
{
- case 0: console_format = "AUTO"; break;
- case 1: console_format = "NTSC"; break;
- case 2: console_format = "PAL"; break;
- case 3: console_format = "SECAM"; break;
- case 4: console_format = "NTSC50"; break;
- case 5: console_format = "PAL60"; break;
- case 6: console_format = "SECAM60"; break;
+ case 0: console_format = "AUTO"; break;
+ case 1: console_format = "NTSC"; break;
+ case 2: console_format = "PAL"; break;
+ case 3: console_format = "SECAM"; break;
+ case 4: console_format = "NTSC50"; break;
+ case 5: console_format = "PAL60"; break;
+ case 6: console_format = "SECAM60"; break;
}
if (system_ready)
@@ -388,9 +387,9 @@ void StellaLIBRETRO::setVideoPhosphor(uInt32 mode, uInt32 blend)
{
switch (mode)
{
- case 0: video_phosphor = "byrom"; break;
- case 1: video_phosphor = "never"; break;
- case 2: video_phosphor = "always"; break;
+ case 0: video_phosphor = "byrom"; break;
+ case 1: video_phosphor = "never"; break;
+ case 2: video_phosphor = "always"; break;
}
video_phosphor_blend = blend;
@@ -414,9 +413,9 @@ void StellaLIBRETRO::setAudioStereo(int mode)
{
switch (mode)
{
- case 0: audio_mode = "byrom"; break;
- case 1: audio_mode = "mono"; break;
- case 2: audio_mode = "stereo"; break;
+ case 0: audio_mode = "byrom"; break;
+ case 1: audio_mode = "mono"; break;
+ case 2: audio_mode = "stereo"; break;
}
if (system_ready)
diff --git a/src/libretro/StellaLIBRETRO.hxx b/src/libretro/StellaLIBRETRO.hxx
index 3078e8eb1..b3d87725b 100644
--- a/src/libretro/StellaLIBRETRO.hxx
+++ b/src/libretro/StellaLIBRETRO.hxx
@@ -21,6 +21,7 @@
#include "bspf.hxx"
#include "OSystemLIBRETRO.hxx"
+#include "Cart.hxx"
#include "Console.hxx"
#include "ConsoleTiming.hxx"
#include "Control.hxx"
@@ -32,7 +33,6 @@
#include "TIA.hxx"
#include "TIASurface.hxx"
-
/**
This class wraps Stella core for easier libretro maintenance
*/
@@ -52,46 +52,59 @@ class StellaLIBRETRO
void runFrame();
bool loadState(const void* data, size_t size);
- bool saveState(void* data, size_t size);
+ bool saveState(void* data, size_t size) const;
public:
- const char* getCoreName() { return "Stella"; }
- const char* getROMExtensions() { return "a26|bin"; }
+ const char* getCoreName() const { return "Stella"; }
+ const char* getROMExtensions() const { return "a26|bin"; }
- void* getROM() { return rom_image.get(); }
- uInt32 getROMSize() { return rom_size; }
- uInt32 getROMMax() { return 512 * 1024; }
+ void* getROM() const { return rom_image.get(); }
+ uInt32 getROMSize() const { return rom_size; }
+ constexpr uInt32 getROMMax() const { return Cartridge::maxSize(); }
uInt8* getRAM() { return system_ram; }
- uInt32 getRAMSize() { return 128; }
+ constexpr uInt32 getRAMSize() const { return 128; }
- size_t getStateSize();
+ size_t getStateSize() const;
- bool getConsoleNTSC() { return console_timing == ConsoleTiming::ntsc; }
+ bool getConsoleNTSC() const { return console_timing == ConsoleTiming::ntsc; }
- float getVideoAspectPar();
- float getVideoAspect();
- bool getVideoNTSC();
- float getVideoRate() { return getVideoNTSC() ? 60.0 : 50.0; }
+ float getVideoAspectPar() const;
+ float getVideoAspect() const;
+ bool getVideoNTSC() const;
+ float getVideoRate() const { return getVideoNTSC() ? 60.0 : 50.0; }
- bool getVideoReady() { return video_ready; }
- uInt32 getVideoZoom() { return myOSystem->frameBuffer().tiaSurface().ntscEnabled() ? 2 : 1; }
+ bool getVideoReady() const { return video_ready; }
+ uInt32 getVideoZoom() const {
+ return myOSystem->frameBuffer().tiaSurface().ntscEnabled() ? 2 : 1;
+ }
bool getVideoResize();
- void* getVideoBuffer();
- uInt32 getVideoWidth() { return getVideoZoom()==1 ? myOSystem->console().tia().width() : getVideoWidthMax(); }
- uInt32 getVideoHeight() { return myOSystem->console().tia().height(); }
- uInt32 getVideoPitch() { return getVideoWidthMax() * 4; }
+ void* getVideoBuffer() const;
+ uInt32 getVideoWidth() const {
+ return getVideoZoom() == 1 ? myOSystem->console().tia().width() : getVideoWidthMax();
+ }
+ uInt32 getVideoHeight() const {
+ return myOSystem->console().tia().height();
+ }
+ constexpr uInt32 getVideoPitch() const { return getVideoWidthMax() * 4; }
- uInt32 getVideoWidthMax() { return AtariNTSC::outWidth(160); }
- uInt32 getVideoHeightMax() { return 312; }
+ constexpr uInt32 getVideoWidthMax() const { return AtariNTSC::outWidth(160); }
+ constexpr uInt32 getVideoHeightMax() const { return 312; }
- uInt32 getRenderWidth() { return getVideoZoom()==1 ? myOSystem->console().tia().width() * 2 : getVideoWidthMax(); }
- uInt32 getRenderHeight() { return myOSystem->console().tia().height() * getVideoZoom(); }
+ uInt32 getRenderWidth() const {
+ return getVideoZoom() == 1 ? myOSystem->console().tia().width() * 2
+ : getVideoWidthMax();
+ }
+ uInt32 getRenderHeight() const {
+ return myOSystem->console().tia().height() * getVideoZoom();
+ }
- float getAudioRate() { return getConsoleNTSC() ? (262 * 76 * 60) / 38.0 : (312 * 76 * 50) / 38.0; }
- bool getAudioReady() { return audio_samples > 0; }
- uInt32 getAudioSize() { return audio_samples; }
+ float getAudioRate() const {
+ return getConsoleNTSC() ? (262 * 76 * 60) / 38.0 : (312 * 76 * 50) / 38.0;
+ }
+ bool getAudioReady() const { return audio_samples > 0; }
+ uInt32 getAudioSize() const { return audio_samples; }
Int16* getAudioBuffer() { return audio_buffer.get(); }
@@ -101,7 +114,7 @@ class StellaLIBRETRO
void setConsoleFormat(uInt32 mode);
void setVideoAspectNTSC(uInt32 value) { video_aspect_ntsc = value; };
- void setVideoAspectPAL(uInt32 value) { video_aspect_pal = value; };
+ void setVideoAspectPAL(uInt32 value) { video_aspect_pal = value; };
void setVideoFilter(NTSCFilter::Preset mode);
void setVideoPalette(const string& mode);
@@ -109,12 +122,18 @@ class StellaLIBRETRO
void setAudioStereo(int mode);
- void setInputEvent(Event::Type type, Int32 state) { myOSystem->eventHandler().handleEvent(type, state); }
+ void setInputEvent(Event::Type type, Int32 state) {
+ myOSystem->eventHandler().handleEvent(type, state);
+ }
- Controller::Type getLeftControllerType() { return myOSystem->console().leftController().type(); }
- Controller::Type getRightControllerType() { return myOSystem->console().rightController().type(); }
+ Controller::Type getLeftControllerType() const {
+ return myOSystem->console().leftController().type();
+ }
+ Controller::Type getRightControllerType() const {
+ return myOSystem->console().rightController().type();
+ }
- void setPaddleJoypadSensitivity(int sensitivity)
+ void setPaddleJoypadSensitivity(int sensitivity)
{
if(getLeftControllerType() == Controller::Type::Paddles)
static_cast(myOSystem->console().leftController()).setDigitalSensitivity(sensitivity);
@@ -137,7 +156,7 @@ class StellaLIBRETRO
unique_ptr myOSystem;
uInt32 system_ready;
- unique_ptr rom_image;
+ ByteBuffer rom_image;
uInt32 rom_size;
string rom_path;
diff --git a/src/libretro/libretro.cxx b/src/libretro/libretro.cxx
index 8caae3765..42408bd97 100644
--- a/src/libretro/libretro.cxx
+++ b/src/libretro/libretro.cxx
@@ -559,7 +559,7 @@ bool retro_load_game(const struct retro_game_info *info)
{ 0, 0, 0, 0, NULL },
};
- if(!info || info->size >= stella.getROMMax()) return false;
+ if(!info || info->size > stella.getROMMax()) return false;
environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc);
diff --git a/src/macos/Info-Stella.plist b/src/macos/Info-Stella.plist
index 8f37a40c3..d9eb7520e 100644
--- a/src/macos/Info-Stella.plist
+++ b/src/macos/Info-Stella.plist
@@ -45,7 +45,7 @@
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
- 6.1
+ 6.2.1
CFBundleName
Stella
CFBundlePackageType
@@ -53,7 +53,7 @@
CFBundleSignature
StLa
CFBundleVersion
- 6.1
+ 6.2.1
LSApplicationCategoryType
public.app-category.games
LSMinimumSystemVersionByArchitecture
diff --git a/src/macos/stella.xcodeproj/project.pbxproj b/src/macos/stella.xcodeproj/project.pbxproj
index d59aac510..f8c0789ce 100644
--- a/src/macos/stella.xcodeproj/project.pbxproj
+++ b/src/macos/stella.xcodeproj/project.pbxproj
@@ -407,6 +407,12 @@
DC8078DB0B4BD5F3005E9305 /* DebuggerExpressions.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC8078DA0B4BD5F3005E9305 /* DebuggerExpressions.hxx */; };
DC8078EA0B4BD697005E9305 /* UIDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC8078E60B4BD697005E9305 /* UIDialog.cxx */; };
DC8078EB0B4BD697005E9305 /* UIDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC8078E70B4BD697005E9305 /* UIDialog.hxx */; };
+ DC84397B247B294E00C6A4FC /* CartTVBoy.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC843979247B294D00C6A4FC /* CartTVBoy.hxx */; };
+ DC84397C247B294E00C6A4FC /* CartTVBoy.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC84397A247B294D00C6A4FC /* CartTVBoy.cxx */; };
+ DC84397F247B297A00C6A4FC /* CartTVBoyWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC84397D247B297A00C6A4FC /* CartTVBoyWidget.hxx */; };
+ DC843980247B297A00C6A4FC /* CartTVBoyWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC84397E247B297A00C6A4FC /* CartTVBoyWidget.cxx */; };
+ DC857D352482F66200C7C14F /* CartCreator.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC857D332482F66200C7C14F /* CartCreator.cxx */; };
+ DC857D362482F66200C7C14F /* CartCreator.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC857D342482F66200C7C14F /* CartCreator.hxx */; };
DC8C1BAD14B25DE7006440EE /* CartCM.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC8C1BA714B25DE7006440EE /* CartCM.cxx */; };
DC8C1BAE14B25DE7006440EE /* CartCM.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC8C1BA814B25DE7006440EE /* CartCM.hxx */; };
DC8C1BAF14B25DE7006440EE /* CompuMate.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC8C1BA914B25DE7006440EE /* CompuMate.cxx */; };
@@ -700,6 +706,8 @@
isa = PBXBuildRule;
compilerSpec = com.apple.compilers.llvm.clang.1_0;
fileType = sourcecode.c;
+ inputFiles = (
+ );
isEditable = 1;
outputFiles = (
);
@@ -709,6 +717,8 @@
isa = PBXBuildRule;
compilerSpec = com.apple.compilers.llvm.clang.1_0;
fileType = sourcecode.asm;
+ inputFiles = (
+ );
isEditable = 1;
outputFiles = (
);
@@ -718,6 +728,8 @@
isa = PBXBuildRule;
compilerSpec = com.apple.compilers.llvm.clang.1_0;
fileType = sourcecode.cpp;
+ inputFiles = (
+ );
isEditable = 1;
outputFiles = (
);
@@ -1146,6 +1158,12 @@
DC8078DA0B4BD5F3005E9305 /* DebuggerExpressions.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = DebuggerExpressions.hxx; sourceTree = ""; };
DC8078E60B4BD697005E9305 /* UIDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = UIDialog.cxx; sourceTree = ""; };
DC8078E70B4BD697005E9305 /* UIDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = UIDialog.hxx; sourceTree = ""; };
+ DC843979247B294D00C6A4FC /* CartTVBoy.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartTVBoy.hxx; sourceTree = ""; };
+ DC84397A247B294D00C6A4FC /* CartTVBoy.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartTVBoy.cxx; sourceTree = ""; };
+ DC84397D247B297A00C6A4FC /* CartTVBoyWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartTVBoyWidget.hxx; sourceTree = ""; };
+ DC84397E247B297A00C6A4FC /* CartTVBoyWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartTVBoyWidget.cxx; sourceTree = ""; };
+ DC857D332482F66200C7C14F /* CartCreator.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartCreator.cxx; sourceTree = ""; };
+ DC857D342482F66200C7C14F /* CartCreator.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartCreator.hxx; sourceTree = ""; };
DC8C1BA714B25DE7006440EE /* CartCM.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartCM.cxx; sourceTree = ""; };
DC8C1BA814B25DE7006440EE /* CartCM.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartCM.hxx; sourceTree = ""; };
DC8C1BA914B25DE7006440EE /* CompuMate.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompuMate.cxx; sourceTree = ""; };
@@ -1643,6 +1661,8 @@
DC2AADB3194F390F0026C7A4 /* CartRamWidget.hxx */,
DC676A3D1729A0B000E4E73D /* CartSBWidget.cxx */,
DC676A3E1729A0B000E4E73D /* CartSBWidget.hxx */,
+ DC84397E247B297A00C6A4FC /* CartTVBoyWidget.cxx */,
+ DC84397D247B297A00C6A4FC /* CartTVBoyWidget.hxx */,
DCAAE5D11715887B0080BB82 /* CartUAWidget.cxx */,
DCAAE5D21715887B0080BB82 /* CartUAWidget.hxx */,
DC6D39851A3CE65000171E71 /* CartWDWidget.cxx */,
@@ -1848,6 +1868,8 @@
CFE3F6121E84A9CE00A8204E /* CartCDF.hxx */,
DC8C1BA714B25DE7006440EE /* CartCM.cxx */,
DC8C1BA814B25DE7006440EE /* CartCM.hxx */,
+ DC857D332482F66200C7C14F /* CartCreator.cxx */,
+ DC857D342482F66200C7C14F /* CartCreator.hxx */,
DC6727081556F4860023653B /* CartCTY.cxx */,
DC6727091556F4860023653B /* CartCTY.hxx */,
2DE2DF1C0627AE07006BEC99 /* CartCV.cxx */,
@@ -1902,6 +1924,8 @@
DC71EA9C1FDA06D2008827CB /* CartMNetwork.hxx */,
DC0984830D3985160073C852 /* CartSB.cxx */,
DC0984840D3985160073C852 /* CartSB.hxx */,
+ DC84397A247B294D00C6A4FC /* CartTVBoy.cxx */,
+ DC843979247B294D00C6A4FC /* CartTVBoy.hxx */,
2DDBEB7008457B7D00812C11 /* CartUA.cxx */,
2DDBEB7108457B7D00812C11 /* CartUA.hxx */,
DCDA03AE1A2009BA00711920 /* CartWD.cxx */,
@@ -2362,6 +2386,7 @@
2D9173CF09BA90380026E9FF /* Cart3F.hxx in Headers */,
DC3EE86D1E2C0E6D00905161 /* zlib.h in Headers */,
E08FCD5523A037EB0051F59B /* Blitter.hxx in Headers */,
+ DC84397F247B297A00C6A4FC /* CartTVBoyWidget.hxx in Headers */,
E034A5EF209FB25D00C89E9E /* EmulationTiming.hxx in Headers */,
DC3EE86A1E2C0E6D00905161 /* trees.h in Headers */,
2D9173D009BA90380026E9FF /* Cart4K.hxx in Headers */,
@@ -2563,6 +2588,7 @@
DC9EA8880F729A36000452B5 /* KidVid.hxx in Headers */,
DCF7F128223D796000701A47 /* ConsoleIO.hxx in Headers */,
DCF467B80F93993B00B25D7A /* SoundNull.hxx in Headers */,
+ DC857D362482F66200C7C14F /* CartCreator.hxx in Headers */,
DCBDDE9F1D6A5F2F009DF1E9 /* Cart3EPlus.hxx in Headers */,
DCF467BD0F9399F500B25D7A /* Version.hxx in Headers */,
DC2B85E81EF5EF2300379EB9 /* AtariNTSC.hxx in Headers */,
@@ -2696,6 +2722,7 @@
DCAACAFB188D631500A4D282 /* CartBFSC.hxx in Headers */,
DCAACAFD188D631500A4D282 /* CartDF.hxx in Headers */,
DCAACAFF188D631500A4D282 /* CartDFSC.hxx in Headers */,
+ DC84397B247B294E00C6A4FC /* CartTVBoy.hxx in Headers */,
DCAACB0F188D636F00A4D282 /* Cart4KSCWidget.hxx in Headers */,
DCAACB11188D636F00A4D282 /* CartBFSCWidget.hxx in Headers */,
DCA82C741FEB4E780059340F /* TimeMachineDialog.hxx in Headers */,
@@ -2833,6 +2860,7 @@
2D91747D09BA90380026E9FF /* CartE0.cxx in Sources */,
DCF8621921C9D43300F95F52 /* StaggeredLogger.cxx in Sources */,
E0DCD3AA20A64E96000B614E /* ConvolutionBuffer.cxx in Sources */,
+ DC843980247B297A00C6A4FC /* CartTVBoyWidget.cxx in Sources */,
2D91747E09BA90380026E9FF /* CartE7.cxx in Sources */,
DC9616321F817830008A2206 /* PointingDeviceWidget.cxx in Sources */,
2D91747F09BA90380026E9FF /* CartF4.cxx in Sources */,
@@ -2893,6 +2921,7 @@
2D9174BD09BA90380026E9FF /* Widget.cxx in Sources */,
2D9174BE09BA90380026E9FF /* CartUA.cxx in Sources */,
DC3EE86E1E2C0E6D00905161 /* zutil.c in Sources */,
+ DC857D352482F66200C7C14F /* CartCreator.cxx in Sources */,
CFE3F60B1E84A9A200A8204E /* CartBUSWidget.cxx in Sources */,
DCEC58581E945125002F0246 /* DelayQueueWidget.cxx in Sources */,
2D9174BF09BA90380026E9FF /* FSNode.cxx in Sources */,
@@ -3068,6 +3097,7 @@
DCDA03B01A2009BB00711920 /* CartWD.cxx in Sources */,
DCC6A4B220A2622500863C59 /* SimpleResampler.cxx in Sources */,
DC21E5BF21CA903E007D0E1A /* OSystemMACOS.cxx in Sources */,
+ DC84397C247B294E00C6A4FC /* CartTVBoy.cxx in Sources */,
DCAAE5D91715887B0080BB82 /* Cart0840Widget.cxx in Sources */,
DCAAE5DB1715887B0080BB82 /* CartCVWidget.cxx in Sources */,
DCA233B423BAB1300032ABF3 /* Lightgun.cxx in Sources */,
diff --git a/src/tools/PropSet.pm b/src/tools/PropSet.pm
index 7cba557f9..0c40d7452 100755
--- a/src/tools/PropSet.pm
+++ b/src/tools/PropSet.pm
@@ -3,29 +3,29 @@ package PropSet;
# NOTE: If the property types ever change in Stella, the following hashmap
# and array must be updated (and stay in sequence)
my %prop_type = (
- "Cart.MD5" => 0,
- "Cart.Manufacturer" => 1,
- "Cart.ModelNo" => 2,
- "Cart.Name" => 3,
- "Cart.Note" => 4,
- "Cart.Rarity" => 5,
- "Cart.Sound" => 6,
- "Cart.StartBank" => 7,
- "Cart.Type" => 8,
- "Console.LeftDiff" => 9,
- "Console.RightDiff" => 10,
- "Console.TVType" => 11,
- "Console.SwapPorts" => 12,
- "Controller.Left" => 13,
- "Controller.Right" => 14,
- "Controller.SwapPaddles" => 15,
+ "Cart.MD5" => 0,
+ "Cart.Manufacturer" => 1,
+ "Cart.ModelNo" => 2,
+ "Cart.Name" => 3,
+ "Cart.Note" => 4,
+ "Cart.Rarity" => 5,
+ "Cart.Sound" => 6,
+ "Cart.StartBank" => 7,
+ "Cart.Type" => 8,
+ "Console.LeftDiff" => 9,
+ "Console.RightDiff" => 10,
+ "Console.TVType" => 11,
+ "Console.SwapPorts" => 12,
+ "Controller.Left" => 13,
+ "Controller.Right" => 14,
+ "Controller.SwapPaddles" => 15,
"Controller.PaddlesXCenter" => 16,
- "Controller.PaddlesYCenter" => 17,
- "Controller.MouseAxis" => 18,
- "Display.Format" => 19,
- "Display.VCenter" => 20,
- "Display.Phosphor" => 21,
- "Display.PPBlend" => 22
+ "Controller.PaddlesYCenter" => 17,
+ "Controller.MouseAxis" => 18,
+ "Display.Format" => 19,
+ "Display.VCenter" => 20,
+ "Display.Phosphor" => 21,
+ "Display.PPBlend" => 22
);
my @prop_type_as_string = (
"Cart.MD5",
diff --git a/src/unix/FSNodePOSIX.cxx b/src/unix/FSNodePOSIX.cxx
index 33f6b5226..f483dc899 100644
--- a/src/unix/FSNodePOSIX.cxx
+++ b/src/unix/FSNodePOSIX.cxx
@@ -159,7 +159,7 @@ bool FilesystemNodePOSIX::getChildren(AbstractFSList& myList, ListMode mode) con
if (entry._isDirectory)
entry._path += "/";
- entry._isValid = entry._isDirectory || entry._isFile;
+ entry._isValid = true;
}
#endif
diff --git a/src/unix/stella.spec b/src/unix/stella.spec
index 796217ea6..c54cf259a 100644
--- a/src/unix/stella.spec
+++ b/src/unix/stella.spec
@@ -1,5 +1,5 @@
%define name stella
-%define version 6.1.2
+%define version 6.2.1
%define rel 1
%define enable_sound 1
@@ -100,6 +100,12 @@ rm -rf $RPM_BUILD_DIR/%{name}-%{version}
%_datadir/icons/large/%{name}.png
%changelog
+* Sat Jun 20 2020 Stephen Anthony 6.2.1-1
+- Version 6.2.1 release
+
+* Sun Jun 7 2020 Stephen Anthony 6.2-1
+- Version 6.2 release
+
* Sat Apr 25 2020 Stephen Anthony 6.1.2-1
- Version 6.1.2 release
diff --git a/src/windows/Stella.vcxproj b/src/windows/Stella.vcxproj
index 6fef5d589..33abbe73e 100644
--- a/src/windows/Stella.vcxproj
+++ b/src/windows/Stella.vcxproj
@@ -662,6 +662,9 @@
true
+
+ true
+
true
@@ -714,6 +717,7 @@
+
@@ -729,6 +733,7 @@
+
@@ -1671,6 +1676,9 @@
true
+
+ true
+
true
@@ -1732,6 +1740,7 @@
+
@@ -1747,6 +1756,7 @@
+
diff --git a/src/windows/Stella.vcxproj.filters b/src/windows/Stella.vcxproj.filters
index 0e4f58929..ded397f71 100644
--- a/src/windows/Stella.vcxproj.filters
+++ b/src/windows/Stella.vcxproj.filters
@@ -1005,6 +1005,15 @@
Source Files\gui
+
+ Source Files\emucore
+
+
+ Source Files
+
+
+ Source Files\emucore
+
@@ -2063,6 +2072,15 @@
Header Files\gui
+
+ Header Files\emucore
+
+
+ Header Files
+
+
+ Header Files\emucore
+
diff --git a/src/windows/stella.rc b/src/windows/stella.rc
index d6fcd5ce3..0958a136d 100755
--- a/src/windows/stella.rc
+++ b/src/windows/stella.rc
@@ -36,8 +36,8 @@ IDI_ICON ICON "stella.ico"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 6,1,0,0
- PRODUCTVERSION 6,1,0,0
+ FILEVERSION 6,2,1,0
+ PRODUCTVERSION 6,2,1,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -55,12 +55,12 @@ BEGIN
VALUE "Comments", "The multi-platform Atari 2600 emulator. Stella is released under the GPLv2."
VALUE "CompanyName", "The Stella Team (https://stella-emu.github.io)"
VALUE "FileDescription", "Stella"
- VALUE "FileVersion", "6.1"
+ VALUE "FileVersion", "6.2.1"
VALUE "InternalName", "Stella"
VALUE "LegalCopyright", "Copyright (c) 1995-2020 The Stella Team"
VALUE "OriginalFilename", "Stella.exe"
VALUE "ProductName", "Stella"
- VALUE "ProductVersion", "6.1"
+ VALUE "ProductVersion", "6.2.1"
END
END
BLOCK "VarFileInfo"
diff --git a/test/roms/bankswitching/TVBoy/Super TV Boy.bin b/test/roms/bankswitching/TVBoy/Super TV Boy.bin
new file mode 100644
index 000000000..bd2d29392
Binary files /dev/null and b/test/roms/bankswitching/TVBoy/Super TV Boy.bin differ
diff --git a/test/roms/bankswitching/TVBoy/TV Boy (NTSC) (bad).bin b/test/roms/bankswitching/TVBoy/TV Boy (NTSC) (bad).bin
new file mode 100644
index 000000000..ab1a0ec54
Binary files /dev/null and b/test/roms/bankswitching/TVBoy/TV Boy (NTSC) (bad).bin differ
diff --git a/test/roms/bankswitching/TVBoy/TV Boy (PAL).bin b/test/roms/bankswitching/TVBoy/TV Boy (PAL).bin
new file mode 100644
index 000000000..9af5fb68c
Binary files /dev/null and b/test/roms/bankswitching/TVBoy/TV Boy (PAL).bin differ
diff --git a/test/roms/bankswitching/TVBoy/TV Boy 2.bin b/test/roms/bankswitching/TVBoy/TV Boy 2.bin
new file mode 100644
index 000000000..8dd5df76b
Binary files /dev/null and b/test/roms/bankswitching/TVBoy/TV Boy 2.bin differ
diff --git a/test/roms/bankswitching/odd_sized/An Exercise In Minimalism (V1) (1999) (Marc de Smet) (PD).a26 b/test/roms/bankswitching/odd_sized/An Exercise In Minimalism (V1) (1999) (Marc de Smet) (PD).a26
new file mode 100644
index 000000000..ebf137a09
Binary files /dev/null and b/test/roms/bankswitching/odd_sized/An Exercise In Minimalism (V1) (1999) (Marc de Smet) (PD).a26 differ
|