Merge branch 'master' into feature/precise-audio

This commit is contained in:
Christian Speckner 2018-02-12 23:32:03 +01:00
commit 5c1bd83904
42 changed files with 518 additions and 312 deletions

View File

@ -1,3 +1,12 @@
5.1 to 5.2: (MMM d, 2018)
* Extra functionality for Time Machine dialog (start/stop recording;
minor fixes; TODO button and initial key repeats...)
* Fixes for collision corner cases (during HBlank)
* UI modernization (new widget look, dialog titles added, dialogs refactored)
5.0.2 to 5.1: (February 4, 2018) 5.0.2 to 5.1: (February 4, 2018)
* Added "Time Machine" mode, which automatically creates save states * Added "Time Machine" mode, which automatically creates save states

View File

@ -44,20 +44,11 @@ class FixedStack
bool full() const { return _size >= CAPACITY; } bool full() const { return _size >= CAPACITY; }
T top() const { return _stack[_size - 1]; } T top() const { return _stack[_size - 1]; }
T get(uInt32 pos) { return _stack[pos]; }; T get(uInt32 pos) { return _stack[pos]; }
void push(const T& x) { _stack[_size++] = x; } void push(const T& x) { _stack[_size++] = x; }
T pop() { return std::move(_stack[--_size]); } T pop() { return std::move(_stack[--_size]); }
uInt32 size() const { return _size; } uInt32 size() const { return _size; }
void replace(const T& oldItem, const T& newItem) {
for(uInt32 i = 0; i < _size; ++i) {
if(_stack[i] == oldItem) {
_stack[i] = newItem;
return;
}
}
}
// Apply the given function to every item in the stack // Apply the given function to every item in the stack
// We do it this way so the stack API can be preserved, // We do it this way so the stack API can be preserved,
// and no access to individual elements is allowed outside // and no access to individual elements is allowed outside

View File

@ -18,7 +18,7 @@
#ifndef VERSION_HXX #ifndef VERSION_HXX
#define VERSION_HXX #define VERSION_HXX
#define STELLA_VERSION "5.1" #define STELLA_VERSION "5.2_pre"
#define STELLA_BUILD "4138" #define STELLA_BUILD "4138"
#endif #endif

View File

@ -26,8 +26,7 @@ PaddleWidget::PaddleWidget(GuiObject* boss, const GUI::Font& font,
bool leftport = isLeftPort(); bool leftport = isLeftPort();
const string& label = getHeader(); const string& label = getHeader();
const int fontWidth = font.getMaxCharWidth(), const int fontHeight = font.getFontHeight(),
fontHeight = font.getFontHeight(),
lineHeight = font.getLineHeight(); lineHeight = font.getLineHeight();
int xpos = x, ypos = y, lwidth = font.getStringWidth("Right (Paddles)"); int xpos = x, ypos = y, lwidth = font.getStringWidth("Right (Paddles)");

View File

@ -301,19 +301,19 @@ void EventHandler::handleKeyEvent(StellaKey key, StellaMod mod, bool state)
{ {
case KBDK_LEFT: // Alt-left(-shift) rewinds 1(10) states case KBDK_LEFT: // Alt-left(-shift) rewinds 1(10) states
enterTimeMachineMenuMode((StellaModTest::isShift(mod) && state) ? 10 : 1, false); enterTimeMachineMenuMode((StellaModTest::isShift(mod) && state) ? 10 : 1, false);
return; break;
case KBDK_RIGHT: // Alt-right(-shift) unwinds 1(10) states case KBDK_RIGHT: // Alt-right(-shift) unwinds 1(10) states
enterTimeMachineMenuMode((StellaModTest::isShift(mod) && state) ? 10 : 1, true); enterTimeMachineMenuMode((StellaModTest::isShift(mod) && state) ? 10 : 1, true);
return; break;
case KBDK_DOWN: // Alt-down rewinds to start of list case KBDK_DOWN: // Alt-down rewinds to start of list
enterTimeMachineMenuMode(1000, false); enterTimeMachineMenuMode(1000, false);
return; break;
case KBDK_UP: // Alt-up rewinds to end of list case KBDK_UP: // Alt-up rewinds to end of list
enterTimeMachineMenuMode(1000, true); enterTimeMachineMenuMode(1000, true);
return; break;
// These can work in pause mode too // These can work in pause mode too
case KBDK_EQUALS: case KBDK_EQUALS:
@ -2151,13 +2151,11 @@ void EventHandler::enterTimeMachineMenuMode(uInt32 numWinds, bool unwind)
// add one extra state if we are in Time Machine mode // add one extra state if we are in Time Machine mode
// TODO: maybe remove this state if we leave the menu at this new state // TODO: maybe remove this state if we leave the menu at this new state
myOSystem.state().addExtraState("enter Time Machine dialog"); // force new state myOSystem.state().addExtraState("enter Time Machine dialog"); // force new state
if(numWinds)
myOSystem.state().windStates(numWinds, unwind);
if(numWinds) if(numWinds)
myOSystem.state().windStates(numWinds, unwind); // hande winds and display wind message (numWinds != 0) in time machine dialog
myOSystem.timeMachine().setEnterWinds(unwind ? numWinds : -numWinds);
// TODO: display last wind message (numWinds != 0) in time machine dialog
enterMenuMode(EventHandlerState::TIMEMACHINE); enterMenuMode(EventHandlerState::TIMEMACHINE);
} }

View File

@ -268,14 +268,12 @@ void FBSurface::frameRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
break; break;
case FrameStyle::Dashed: case FrameStyle::Dashed:
uInt32 i, skip, lwidth = 1; for(uInt32 i = x; i < x + w; i += 2)
for(i = x; i < x + w; i += 2)
{ {
hLine(i, y, i, color); hLine(i, y, i, color);
hLine(i, y + h - 1, i, color); hLine(i, y + h - 1, i, color);
} }
for(i = y; i < y + h; i += 2) for(uInt32 i = y; i < y + h; i += 2)
{ {
vLine(x, i, i, color); vLine(x, i, i, color);
vLine(x + w - 1, i, i, color); vLine(x + w - 1, i, i, color);

View File

@ -385,9 +385,8 @@ void FrameBuffer::drawFrameStats()
int xPos = XPOS; int xPos = XPOS;
myStatsMsg.surface->invalidate(); myStatsMsg.surface->invalidate();
string bsinfo = info.BankSwitch +
(myOSystem.settings().getBool("dev.settings") ? "| Developer" : ""); // draw scanlines
// draw shadowed text
color = myOSystem.console().tia().scanlinesLastFrame() != myLastScanlines ? color = myOSystem.console().tia().scanlinesLastFrame() != myLastScanlines ?
uInt32(kDbgColorRed) : myStatsMsg.color; uInt32(kDbgColorRed) : myStatsMsg.color;
std::snprintf(msg, 30, "%3u", myOSystem.console().tia().scanlinesLastFrame()); std::snprintf(msg, 30, "%3u", myOSystem.console().tia().scanlinesLastFrame());
@ -395,16 +394,20 @@ void FrameBuffer::drawFrameStats()
myStatsMsg.w, color, TextAlign::Left, 0, true, kBGColor); myStatsMsg.w, color, TextAlign::Left, 0, true, kBGColor);
xPos += font().getStringWidth(msg); xPos += font().getStringWidth(msg);
// draw frequency
std::snprintf(msg, 30, " => %s", info.DisplayFormat.c_str()); std::snprintf(msg, 30, " => %s", info.DisplayFormat.c_str());
myStatsMsg.surface->drawString(font(), msg, xPos, YPOS, myStatsMsg.surface->drawString(font(), msg, xPos, YPOS,
myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor); myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor);
xPos += font().getStringWidth(msg); xPos += font().getStringWidth(msg);
std::snprintf(msg, 30, " @ %5.2ffps", myOSystem.console().getFramerate()); std::snprintf(msg, 30, " @ %5.2ffps", myOSystem.console().getFramerate());
myStatsMsg.surface->drawString(font(), msg, xPos, YPOS, myStatsMsg.surface->drawString(font(), msg, xPos, YPOS,
myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor); myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor);
// draw bankswitching type // draw bankswitching type
string bsinfo = info.BankSwitch +
(myOSystem.settings().getBool("dev.settings") ? "| Developer" : "");
myStatsMsg.surface->drawString(font(), bsinfo, XPOS, YPOS + font().getFontHeight(), myStatsMsg.surface->drawString(font(), bsinfo, XPOS, YPOS + font().getFontHeight(),
myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor); myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor);
@ -1016,7 +1019,7 @@ uInt32 FrameBuffer::ourGUIColors[3][kNumColors-256] = {
0x20a020, 0x00ff00, // scrollbar 0x20a020, 0x00ff00, // scrollbar
0x20a020, 0x00ff00, 0x404040, 0x686868, 0x404040, // slider 0x20a020, 0x00ff00, 0x404040, 0x686868, 0x404040, // slider
0xc80000, 0x00ff00, 0xc8c8ff, 0xc80000, // debugger 0xc80000, 0x00ff00, 0xc8c8ff, 0xc80000, // debugger
0x20a020, 0x20a020, 0x000000, 0x686868, 0x404040 // other 0x00ff00, 0x20a020, 0x000000, 0x686868, 0x404040 // other
}, },
// Light // Light
{ 0x808080, 0x000000, 0xc0c0c0, 0xe1e1e1, 0x333333, // base { 0x808080, 0x000000, 0xc0c0c0, 0xe1e1e1, 0x333333, // base

View File

@ -213,6 +213,56 @@ void OSystem::setConfigPaths()
mySettings->setValue("propsfile", node.getShortPath()); mySettings->setValue("propsfile", node.getShortPath());
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PropertiesSet& OSystem::propSet(const string& md5)
{
FilesystemNode node = FilesystemNode();
return propSet(md5, node);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PropertiesSet& OSystem::propSet(const string& md5, const FilesystemNode& node)
{
if(md5 == EmptyString)
return *myPropSet;
else if(md5 == myGamePropSetMD5)
return *myGamePropSet;
else if (!node.exists())
return *myPropSet;
// Get a valid set of game specific properties
Properties props;
string path = myBaseDir + node.getNameWithExt(".pro");
// Create a properties set based on ROM name
FilesystemNode propNode = FilesystemNode(path);
myGamePropertiesFile = propNode.getPath();
myGamePropSet = make_unique<PropertiesSet>(myGamePropertiesFile);
// Check if game specific property file exists and has matching md5
if(myGamePropSet->size() && myGamePropSet->getMD5(md5, props))
{
myGamePropSetMD5 = md5;
return *myGamePropSet;
}
else
{
myGamePropSetMD5 = "";
return *myPropSet;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystem::saveGamePropSet(const string& md5)
{
if(myGamePropSet->size() && md5 == myGamePropSetMD5)
{
myGamePropSet->save(myGamePropertiesFile);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystem::setBaseDir(const string& basedir) void OSystem::setBaseDir(const string& basedir)
{ {
@ -428,8 +478,7 @@ void OSystem::logMessage(const string& message, uInt8 level)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unique_ptr<Console> unique_ptr<Console> OSystem::openConsole(const FilesystemNode& romfile, string& md5)
OSystem::openConsole(const FilesystemNode& romfile, string& md5)
{ {
unique_ptr<Console> console; unique_ptr<Console> console;
@ -441,8 +490,15 @@ OSystem::openConsole(const FilesystemNode& romfile, string& md5)
// Get a valid set of properties, including any entered on the commandline // Get a valid set of properties, including any entered on the commandline
// For initial creation of the Cart, we're only concerned with the BS type // For initial creation of the Cart, we're only concerned with the BS type
Properties props; Properties props;
myPropSet->getMD5(md5, props);
// Load and use game specific props if existing
FilesystemNode node = FilesystemNode(romfile);
string path = myBaseDir + node.getNameWithExt(".pro");
PropertiesSet& propset = propSet(md5, romfile);
propset.getMD5(md5, props);
// Local helper method
auto CMDLINE_PROPS_UPDATE = [&](const string& name, PropertyType prop) auto CMDLINE_PROPS_UPDATE = [&](const string& name, PropertyType prop)
{ {
const string& s = mySettings->getString(name); const string& s = mySettings->getString(name);
@ -462,12 +518,12 @@ OSystem::openConsole(const FilesystemNode& romfile, string& md5)
// and that the md5 (and hence the cart) has changed // and that the md5 (and hence the cart) has changed
if(props.get(Cartridge_MD5) != cartmd5) if(props.get(Cartridge_MD5) != cartmd5)
{ {
if(!myPropSet->getMD5(cartmd5, props)) if(!propset.getMD5(cartmd5, props))
{ {
// Cart md5 wasn't found, so we create a new props for it // Cart md5 wasn't found, so we create a new props for it
props.set(Cartridge_MD5, cartmd5); props.set(Cartridge_MD5, cartmd5);
props.set(Cartridge_Name, props.get(Cartridge_Name)+cart->multiCartID()); props.set(Cartridge_Name, props.get(Cartridge_Name)+cart->multiCartID());
myPropSet->insert(props, false); propset.insert(props, false);
} }
} }

View File

@ -107,7 +107,13 @@ class OSystem
@return The properties set object @return The properties set object
*/ */
PropertiesSet& propSet() const { return *myPropSet; } PropertiesSet& propSet(const string& md5 = EmptyString);
PropertiesSet& propSet(const string& md5, const FilesystemNode& node);
/**
Save the game specific property file.
*/
void saveGamePropSet(const string& md5);
/** /**
Get the console of the system. The console won't always exist, Get the console of the system. The console won't always exist,
@ -427,6 +433,12 @@ class OSystem
// Pointer to the PropertiesSet object // Pointer to the PropertiesSet object
unique_ptr<PropertiesSet> myPropSet; unique_ptr<PropertiesSet> myPropSet;
// Pointer to the game's PropertiesSet object
unique_ptr<PropertiesSet> myGamePropSet;
// MD5 of the currently loaded game PropertiesSet object
string myGamePropSetMD5;
// Pointer to the (currently defined) Console object // Pointer to the (currently defined) Console object
unique_ptr<Console> myConsole; unique_ptr<Console> myConsole;
@ -480,6 +492,7 @@ class OSystem
string myConfigFile; string myConfigFile;
string myPaletteFile; string myPaletteFile;
string myPropertiesFile; string myPropertiesFile;
string myGamePropertiesFile;
FilesystemNode myRomFile; FilesystemNode myRomFile;
string myRomMD5; string myRomMD5;

View File

@ -112,6 +112,11 @@ class PropertiesSet
*/ */
void print() const; void print() const;
/**
Return the size of the myExternalProps list
*/
uInt32 size() { return myExternalProps.size(); }
private: private:
using PropsList = std::map<string, Properties>; using PropsList = std::map<string, Properties>;

View File

@ -40,6 +40,7 @@ void Ball::reset()
myIsEnabledNew = false; myIsEnabledNew = false;
myIsEnabled = false; myIsEnabled = false;
myIsDelaying = false; myIsDelaying = false;
myIsVisible = false;
myHmmClocks = 0; myHmmClocks = 0;
myCounter = 0; myCounter = 0;
myIsMoving = false; myIsMoving = false;
@ -49,8 +50,7 @@ void Ball::reset()
myIsRendering = false; myIsRendering = false;
myDebugEnabled = false; myDebugEnabled = false;
myRenderCounter = 0; myRenderCounter = 0;
myIsEnabled = false;
updateEnabled();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -62,7 +62,10 @@ void Ball::enabl(uInt8 value)
if (myIsEnabledNew != enabledNewOldValue && !myIsDelaying) { if (myIsEnabledNew != enabledNewOldValue && !myIsDelaying) {
myTIA->flushLineCache(); myTIA->flushLineCache();
updateEnabled(); updateEnabled();
collision = (myIsVisible && myIsEnabled) ? myCollisionMaskEnabled : myCollisionMaskDisabled;
myTIA->updateCollision();
} }
} }
@ -173,9 +176,8 @@ bool Ball::movementTick(uInt32 clock, bool apply)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::tick(bool isReceivingMclock) void Ball::tick(bool isReceivingMclock)
{ {
collision = (myIsRendering && myRenderCounter >= 0 && myIsEnabled) ? myIsVisible = myIsRendering && myRenderCounter >= 0;
myCollisionMaskEnabled : collision = (myIsVisible && myIsEnabled) ? myCollisionMaskEnabled : myCollisionMaskDisabled;
myCollisionMaskDisabled;
bool starfieldEffect = myIsMoving && isReceivingMclock; bool starfieldEffect = myIsMoving && isReceivingMclock;
@ -207,6 +209,13 @@ void Ball::tick(bool isReceivingMclock)
myCounter = 0; myCounter = 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::nextLine()
{
myIsVisible = myIsRendering && myRenderCounter >= 0;
collision = (myIsVisible && myIsEnabled) ? myCollisionMaskEnabled : myCollisionMaskDisabled;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Ball::setENABLOld(bool enabled) void Ball::setENABLOld(bool enabled)
{ {
@ -233,6 +242,9 @@ void Ball::shuffleStatus()
void Ball::updateEnabled() void Ball::updateEnabled()
{ {
myIsEnabled = !myIsSuppressed && (myIsDelaying ? myIsEnabledOld : myIsEnabledNew); myIsEnabled = !myIsSuppressed && (myIsDelaying ? myIsEnabledOld : myIsEnabledNew);
collision = (myIsVisible && myIsEnabled) ? myCollisionMaskEnabled : myCollisionMaskDisabled;
myTIA->updateCollision();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -293,6 +305,7 @@ bool Ball::save(Serializer& out) const
out.putBool(myIsEnabled); out.putBool(myIsEnabled);
out.putBool(myIsSuppressed); out.putBool(myIsSuppressed);
out.putBool(myIsDelaying); out.putBool(myIsDelaying);
out.putBool(myIsVisible);
out.putByte(myHmmClocks); out.putByte(myHmmClocks);
out.putByte(myCounter); out.putByte(myCounter);
@ -335,6 +348,7 @@ bool Ball::load(Serializer& in)
myIsEnabled = in.getBool(); myIsEnabled = in.getBool();
myIsSuppressed = in.getBool(); myIsSuppressed = in.getBool();
myIsDelaying = in.getBool(); myIsDelaying = in.getBool();
myIsVisible = in.getBool();
myHmmClocks = in.getByte(); myHmmClocks = in.getByte();
myCounter = in.getByte(); myCounter = in.getByte();

View File

@ -62,6 +62,8 @@ class Ball : public Serializable
void tick(bool isReceivingMclock = true); void tick(bool isReceivingMclock = true);
void nextLine();
bool isOn() const { return (collision & 0x8000); } bool isOn() const { return (collision & 0x8000); }
uInt8 getColor() const { return myColor; } uInt8 getColor() const { return myColor; }
@ -105,6 +107,7 @@ class Ball : public Serializable
bool myIsEnabled; bool myIsEnabled;
bool myIsSuppressed; bool myIsSuppressed;
bool myIsDelaying; bool myIsDelaying;
bool myIsVisible;
uInt8 myHmmClocks; uInt8 myHmmClocks;
uInt8 myCounter; uInt8 myCounter;

View File

@ -47,12 +47,12 @@ void Missile::reset()
myWidth = 1; myWidth = 1;
myEffectiveWidth = 1; myEffectiveWidth = 1;
myIsRendering = false; myIsRendering = false;
myIsVisible = false;
myRenderCounter = 0; myRenderCounter = 0;
myColor = myObjectColor = myDebugColor = 0; myColor = myObjectColor = myDebugColor = 0;
myDebugEnabled = false; myDebugEnabled = false;
collision = myCollisionMaskDisabled; collision = myCollisionMaskDisabled;
myIsEnabled = false;
updateEnabled();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -62,9 +62,11 @@ void Missile::enam(uInt8 value)
myEnam = (value & 0x02) > 0; myEnam = (value & 0x02) > 0;
if (oldEnam != myEnam) myTIA->flushLineCache(); if (oldEnam != myEnam) {
myTIA->flushLineCache();
updateEnabled(); updateEnabled();
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -166,28 +168,27 @@ bool Missile::movementTick(uInt8 clock, uInt8 hclock, bool apply)
if (clock == myHmmClocks) myIsMoving = false; if (clock == myHmmClocks) myIsMoving = false;
if (myIsMoving && apply) tick(hclock); if (myIsMoving && apply) tick(hclock, false);
return myIsMoving; return myIsMoving;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Missile::tick(uInt8 hclock) void Missile::tick(uInt8 hclock, bool isReceivingMclock)
{ {
const bool render = myIsVisible =
myIsRendering && myIsRendering &&
(myRenderCounter >= 0 || (myIsMoving && myRenderCounter == -1 && myWidth < 4 && ((hclock + 1) % 4 == 3))) && (myRenderCounter >= 0 || (myIsMoving && isReceivingMclock && myRenderCounter == -1 && myWidth < 4 && ((hclock + 1) % 4 == 3)));
myIsEnabled;
collision = render ? myCollisionMaskEnabled : myCollisionMaskDisabled; collision = (myIsVisible && myIsEnabled) ? myCollisionMaskEnabled : myCollisionMaskDisabled;
if (myDecodes[myCounter] && !myResmp) { if (myDecodes[myCounter] && !myResmp) {
myIsRendering = true; myIsRendering = true;
myRenderCounter = Count::renderCounterOffset; myRenderCounter = Count::renderCounterOffset;
} else if (myIsRendering) { } else if (myIsRendering) {
if (myIsMoving && myRenderCounter == -1) { if (myRenderCounter == -1) {
if (myIsMoving && isReceivingMclock) {
switch ((hclock + 1) % 4) { switch ((hclock + 1) % 4) {
case 3: case 3:
myEffectiveWidth = myWidth == 1 ? 2 : myWidth; myEffectiveWidth = myWidth == 1 ? 2 : myWidth;
@ -202,6 +203,9 @@ void Missile::tick(uInt8 hclock)
myEffectiveWidth = myWidth; myEffectiveWidth = myWidth;
break; break;
} }
} else {
myEffectiveWidth = myWidth;
}
} }
if (++myRenderCounter >= (myIsMoving ? myEffectiveWidth : myWidth)) myIsRendering = false; if (++myRenderCounter >= (myIsMoving ? myEffectiveWidth : myWidth)) myIsRendering = false;
@ -210,6 +214,13 @@ void Missile::tick(uInt8 hclock)
if (++myCounter >= 160) myCounter = 0; if (++myCounter >= 160) myCounter = 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Missile::nextLine()
{
myIsVisible = myIsRendering && (myRenderCounter >= 0);
collision = (myIsVisible && myIsEnabled) ? myCollisionMaskEnabled : myCollisionMaskDisabled;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Missile::setColor(uInt8 color) void Missile::setColor(uInt8 color)
{ {
@ -246,6 +257,9 @@ void Missile::applyColorLoss()
void Missile::updateEnabled() void Missile::updateEnabled()
{ {
myIsEnabled = !myIsSuppressed && myEnam && !myResmp; myIsEnabled = !myIsSuppressed && myEnam && !myResmp;
collision = (myIsVisible && myIsEnabled) ? myCollisionMaskEnabled : myCollisionMaskDisabled;
myTIA->updateCollision();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -308,6 +322,7 @@ bool Missile::save(Serializer& out) const
out.putByte(myEffectiveWidth); out.putByte(myEffectiveWidth);
out.putByte(myLastMovementTick); out.putByte(myLastMovementTick);
out.putBool(myIsVisible);
out.putBool(myIsRendering); out.putBool(myIsRendering);
out.putByte(myRenderCounter); out.putByte(myRenderCounter);
@ -350,6 +365,7 @@ bool Missile::load(Serializer& in)
myEffectiveWidth = in.getByte(); myEffectiveWidth = in.getByte();
myLastMovementTick = in.getByte(); myLastMovementTick = in.getByte();
myIsVisible = in.getBool();
myIsRendering = in.getBool(); myIsRendering = in.getBool();
myRenderCounter = in.getByte(); myRenderCounter = in.getByte();

View File

@ -50,7 +50,9 @@ class Missile : public Serializable
bool movementTick(uInt8 clock, uInt8 hclock, bool apply); bool movementTick(uInt8 clock, uInt8 hclock, bool apply);
void tick(uInt8 hclock); void tick(uInt8 hclock, bool isReceivingMclock = true);
void nextLine();
void setColor(uInt8 color); void setColor(uInt8 color);
@ -103,6 +105,7 @@ class Missile : public Serializable
uInt8 myLastMovementTick; uInt8 myLastMovementTick;
bool myIsRendering; bool myIsRendering;
bool myIsVisible;
Int8 myRenderCounter; Int8 myRenderCounter;
const uInt8* myDecodes; const uInt8* myDecodes;

View File

@ -52,9 +52,9 @@ void Player::reset()
mySampleCounter = 0; mySampleCounter = 0;
myDividerPending = 0; myDividerPending = 0;
myDividerChangeCounter = -1; myDividerChangeCounter = -1;
myPattern = 0;
setDivider(1); setDivider(1);
updatePattern();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -309,6 +309,15 @@ void Player::tick()
if (++myCounter >= 160) myCounter = 0; if (++myCounter >= 160) myCounter = 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Player::nextLine()
{
if (!myIsRendering || myRenderCounter < myRenderCounterTripPoint)
collision = myCollisionMaskDisabled;
else
collision = (myPattern & (1 << mySampleCounter)) ? myCollisionMaskEnabled : myCollisionMaskDisabled;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Player::shufflePatterns() void Player::shufflePatterns()
{ {
@ -372,6 +381,11 @@ void Player::updatePattern()
((myPattern & 0x80) >> 7) ((myPattern & 0x80) >> 7)
); );
} }
if (myIsRendering && myRenderCounter >= myRenderCounterTripPoint) {
collision = (myPattern & (1 << mySampleCounter)) ? myCollisionMaskEnabled : myCollisionMaskDisabled;
myTIA->updateCollision();
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -62,6 +62,9 @@ class Player : public Serializable
bool movementTick(uInt32 clock, bool apply); bool movementTick(uInt32 clock, bool apply);
void tick(); void tick();
void nextLine();
uInt8 getClock() const { return myCounter; } uInt8 getClock() const { return myCounter; }
bool isOn() const { return (collision & 0x8000); } bool isOn() const { return (collision & 0x8000); }

View File

@ -204,6 +204,12 @@ void Playfield::tick(uInt32 x)
collision = currentPixel ? myCollisionMaskEnabled : myCollisionMaskDisabled; collision = currentPixel ? myCollisionMaskEnabled : myCollisionMaskDisabled;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Playfield::nextLine()
{
collision = myCollisionMaskDisabled;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Playfield::applyColors() void Playfield::applyColors()
{ {

View File

@ -59,6 +59,8 @@ class Playfield : public Serializable
void tick(uInt32 x); void tick(uInt32 x);
void nextLine();
bool isOn() const { return (collision & 0x8000); } bool isOn() const { return (collision & 0x8000); }
uInt8 getColor() const; uInt8 getColor() const;

View File

@ -1273,7 +1273,6 @@ void TIA::nextLine()
cloneLastLine(); cloneLastLine();
} }
myPlayfield.tick(0);
myHctr = 0; myHctr = 0;
if (!myMovementInProgress && myLinesSinceChange < 2) myLinesSinceChange++; if (!myMovementInProgress && myLinesSinceChange < 2) myLinesSinceChange++;
@ -1282,6 +1281,12 @@ void TIA::nextLine()
myHctrDelta = 0; myHctrDelta = 0;
myFrameManager->nextLine(); myFrameManager->nextLine();
myMissile0.nextLine();
myMissile1.nextLine();
myPlayer0.nextLine();
myPlayer1.nextLine();
myBall.nextLine();
myPlayfield.nextLine();
if (myFrameManager->isRendering() && myFrameManager->getY() == 0) flushLineCache(); if (myFrameManager->isRendering() && myFrameManager->getY() == 0) flushLineCache();

View File

@ -415,6 +415,11 @@ class TIA : public Device
*/ */
void flushLineCache(); void flushLineCache();
/**
* Update the collision bitfield.
*/
void updateCollision();
/** /**
Create a new delayQueueIterator for the debugger. Create a new delayQueueIterator for the debugger.
*/ */
@ -511,11 +516,6 @@ class TIA : public Device
*/ */
void applyRsync(); void applyRsync();
/**
* Update the collision bitfield.
*/
void updateCollision();
/** /**
* Render the current pixel into the framebuffer. * Render the current pixel into the framebuffer.
*/ */

View File

@ -42,9 +42,7 @@ AudioDialog::AudioDialog(OSystem& osystem, DialogContainer& parent,
const int INDENT = 20; const int INDENT = 20;
const int lineHeight = font.getLineHeight(), const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(), fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(), fontHeight = font.getFontHeight();
buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4;
int xpos, ypos; int xpos, ypos;
int lwidth = font.getStringWidth("Sample Size (*) "), int lwidth = font.getStringWidth("Sample Size (*) "),
pwidth = font.getStringWidth("512 bytes"); pwidth = font.getStringWidth("512 bytes");

View File

@ -33,10 +33,7 @@ ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font,
myComboEvent(Event::NoType) myComboEvent(Event::NoType)
{ {
const int lineHeight = font.getLineHeight(), const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(), fontWidth = font.getMaxCharWidth();
fontHeight = font.getFontHeight(),
buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4;
int xpos, ypos; int xpos, ypos;
WidgetArray wid; WidgetArray wid;

View File

@ -27,13 +27,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CommandDialog::CommandDialog(OSystem& osystem, DialogContainer& parent) CommandDialog::CommandDialog(OSystem& osystem, DialogContainer& parent)
: Dialog(osystem, parent) : Dialog(osystem, parent, osystem.frameBuffer().font(), "Commands")
{ {
const GUI::Font& font = instance().frameBuffer().font(); const int buttonWidth = _font.getStringWidth("Right Diff B") + 20,
initTitle(font, "Commands"); buttonHeight = _font.getLineHeight() + 6,
const int buttonWidth = font.getStringWidth("Right Diff B") + 20,
buttonHeight = font.getLineHeight() + 6,
rowHeight = buttonHeight + 8; rowHeight = buttonHeight + 8;
// Set real dimensions // Set real dimensions
@ -46,7 +43,7 @@ CommandDialog::CommandDialog(OSystem& osystem, DialogContainer& parent)
auto ADD_CD_BUTTON = [&](const string& label, int cmd) auto ADD_CD_BUTTON = [&](const string& label, int cmd)
{ {
ButtonWidget* bw = new ButtonWidget(this, font, xoffset, yoffset, ButtonWidget* bw = new ButtonWidget(this, _font, xoffset, yoffset,
buttonWidth, buttonHeight, label, cmd); buttonWidth, buttonHeight, label, cmd);
xoffset += buttonWidth + 8; xoffset += buttonWidth + 8;
return bw; return bw;

View File

@ -28,7 +28,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ContextMenu::ContextMenu(GuiObject* boss, const GUI::Font& font, ContextMenu::ContextMenu(GuiObject* boss, const GUI::Font& font,
const VariantList& items, int cmd, int width) const VariantList& items, int cmd, int width)
: Dialog(boss->instance(), boss->parent()), : Dialog(boss->instance(), boss->parent(), font),
CommandSender(boss), CommandSender(boss),
_rowHeight(font.getLineHeight()), _rowHeight(font.getLineHeight()),
_firstEntry(0), _firstEntry(0),
@ -39,7 +39,6 @@ ContextMenu::ContextMenu(GuiObject* boss, const GUI::Font& font,
_isScrolling(false), _isScrolling(false),
_scrollUpColor(kColor), _scrollUpColor(kColor),
_scrollDnColor(kColor), _scrollDnColor(kColor),
_font(font),
_cmd(cmd), _cmd(cmd),
_xorig(0), _xorig(0),
_yorig(0), _yorig(0),

View File

@ -120,7 +120,6 @@ class ContextMenu : public Dialog, public CommandSender
bool _isScrolling; bool _isScrolling;
uInt32 _scrollUpColor, _scrollDnColor; uInt32 _scrollUpColor, _scrollDnColor;
const GUI::Font& _font;
int _cmd; int _cmd;
uInt32 _xorig, _yorig; uInt32 _xorig, _yorig;

View File

@ -44,13 +44,10 @@
* ... * ...
*/ */
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Dialog::Dialog(OSystem& instance, DialogContainer& parent, const GUI::Font& font,
Dialog::Dialog(OSystem& instance, DialogContainer& parent, const GUI::Font& font, const string& title, const string& title, int x, int y, int w, int h)
int x, int y, int w, int h)
: GuiObject(instance, parent, *this, x, y, w, h), : GuiObject(instance, parent, *this, x, y, w, h),
_font(&font), _font(font),
_title(title),
_th(0),
_mouseWidget(nullptr), _mouseWidget(nullptr),
_focusedWidget(nullptr), _focusedWidget(nullptr),
_dragWidget(nullptr), _dragWidget(nullptr),
@ -58,30 +55,19 @@ Dialog::Dialog(OSystem& instance, DialogContainer& parent, const GUI::Font& font
_cancelWidget(nullptr), _cancelWidget(nullptr),
_visible(false), _visible(false),
_processCancel(false), _processCancel(false),
_title(title),
_th(0),
_surface(nullptr), _surface(nullptr),
_tabID(0), _tabID(0),
_flags(WIDGET_ENABLED | WIDGET_BORDER | WIDGET_CLEARBG) _flags(WIDGET_ENABLED | WIDGET_BORDER | WIDGET_CLEARBG)
{ {
initTitle(font, title); setTitle(title);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Dialog::Dialog(OSystem& instance, DialogContainer& parent, Dialog::Dialog(OSystem& instance, DialogContainer& parent,
int x, int y, int w, int h) int x, int y, int w, int h)
: GuiObject(instance, parent, *this, x, y, w, h), : Dialog(instance, parent, instance.frameBuffer().font(), "", x, y, w, h)
_font(nullptr),
_title(""),
_th(0),
_fh(0),
_mouseWidget(nullptr),
_focusedWidget(nullptr),
_dragWidget(nullptr),
_okWidget(nullptr),
_cancelWidget(nullptr),
_visible(false),
_processCancel(false),
_surface(nullptr),
_tabID(0),
_flags(WIDGET_ENABLED | WIDGET_BORDER | WIDGET_CLEARBG)
{ {
} }
@ -133,27 +119,16 @@ void Dialog::close(bool refresh)
parent().removeDialog(); parent().removeDialog();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::initTitle(const GUI::Font& font, const string& title)
{
_font = &font;
_fh = font.getLineHeight();
setTitle(title);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::setTitle(const string& title) void Dialog::setTitle(const string& title)
{ {
if(_font != nullptr)
{
_title = title; _title = title;
_h -= _th; _h -= _th;
if(title.empty()) if(title.empty())
_th = 0; _th = 0;
else else
_th = _fh + 4; _th = _font.getLineHeight() + 4;
_h += _th; _h += _th;
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -326,8 +301,8 @@ void Dialog::drawDialog()
{ {
// dialog is still on top if e.g a ContextMenu is opened // dialog is still on top if e.g a ContextMenu is opened
bool onTop = parent().myDialogStack.top() == this bool onTop = parent().myDialogStack.top() == this
|| parent().myDialogStack.get(parent().myDialogStack.size() - 2) == this || (parent().myDialogStack.get(parent().myDialogStack.size() - 2) == this
&& !parent().myDialogStack.top()->hasTitle(); && !parent().myDialogStack.top()->hasTitle());
if(_flags & WIDGET_CLEARBG) if(_flags & WIDGET_CLEARBG)
{ {
@ -336,7 +311,7 @@ void Dialog::drawDialog()
if(_th) if(_th)
{ {
s.fillRect(_x, _y, _w, _th, onTop ? kColorTitleBar : kColorTitleBarLo); s.fillRect(_x, _y, _w, _th, onTop ? kColorTitleBar : kColorTitleBarLo);
s.drawString(*_font, _title, _x + 10, _y + 2 + 1, _font->getStringWidth(_title), s.drawString(_font, _title, _x + 10, _y + 2 + 1, _font.getStringWidth(_title),
onTop ? kColorTitleText : kColorTitleTextLo); onTop ? kColorTitleText : kColorTitleTextLo);
} }
} }

View File

@ -46,8 +46,8 @@ class Dialog : public GuiObject
public: public:
Dialog(OSystem& instance, DialogContainer& parent, Dialog(OSystem& instance, DialogContainer& parent,
int x = 0, int y = 0, int w = 0, int h = 0); int x = 0, int y = 0, int w = 0, int h = 0);
Dialog(OSystem& instance, DialogContainer& parent, const GUI::Font& font, const string& title, Dialog(OSystem& instance, DialogContainer& parent, const GUI::Font& font,
int x = 0, int y = 0, int w = 0, int h = 0); const string& title = "", int x = 0, int y = 0, int w = 0, int h = 0);
virtual ~Dialog(); virtual ~Dialog();
@ -129,8 +129,6 @@ class Dialog : public GuiObject
void processCancelWithoutWidget(bool state) { _processCancel = state; } void processCancelWithoutWidget(bool state) { _processCancel = state; }
void initTitle(const GUI::Font& font, const string& title);
private: private:
void buildCurrentFocusList(int tabID = -1); void buildCurrentFocusList(int tabID = -1);
bool handleNavEvent(Event::Type e); bool handleNavEvent(Event::Type e);
@ -138,18 +136,19 @@ class Dialog : public GuiObject
bool cycleTab(int direction); bool cycleTab(int direction);
protected: protected:
const GUI::Font& _font;
Widget* _mouseWidget; Widget* _mouseWidget;
Widget* _focusedWidget; Widget* _focusedWidget;
Widget* _dragWidget; Widget* _dragWidget;
Widget* _defaultWidget; Widget* _defaultWidget;
Widget* _okWidget; Widget* _okWidget;
Widget* _cancelWidget; Widget* _cancelWidget;
bool _visible; bool _visible;
bool _processCancel; bool _processCancel;
string _title; string _title;
int _th; int _th;
const GUI::Font* _font;
int _fh;
Common::FixedStack<shared_ptr<FBSurface>> mySurfaceStack; Common::FixedStack<shared_ptr<FBSurface>> mySurfaceStack;

View File

@ -47,7 +47,6 @@ GameInfoDialog::GameInfoDialog(
const int lineHeight = font.getLineHeight(), const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(), fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(), fontHeight = font.getFontHeight(),
buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4; buttonHeight = font.getLineHeight() + 4;
const int vBorder = 8; const int vBorder = 8;
const int hBorder = 8; const int hBorder = 8;
@ -349,7 +348,7 @@ void GameInfoDialog::loadConfig()
const string& md5 = instance().launcher().selectedRomMD5(); const string& md5 = instance().launcher().selectedRomMD5();
if(md5 != "") if(md5 != "")
{ {
instance().propSet().getMD5(md5, myGameProperties); instance().propSet(md5).getMD5(md5, myGameProperties);
myPropertiesLoaded = true; myPropertiesLoaded = true;
loadView(); loadView();
} }
@ -487,10 +486,13 @@ void GameInfoDialog::saveConfig()
myPPBlend->getValueLabel()); myPPBlend->getValueLabel());
// Determine whether to add or remove an entry from the properties set // Determine whether to add or remove an entry from the properties set
const string& md5 = myGameProperties.get(Cartridge_MD5);
if(myDefaultsSelected) if(myDefaultsSelected)
instance().propSet().removeMD5(myGameProperties.get(Cartridge_MD5)); instance().propSet(md5).removeMD5(myGameProperties.get(Cartridge_MD5));
else else
instance().propSet().insert(myGameProperties); instance().propSet(md5).insert(myGameProperties);
instance().saveGamePropSet(myGameProperties.get(Cartridge_MD5));
// In any event, inform the Console // In any event, inform the Console
if(instance().hasConsole()) if(instance().hasConsole())
@ -502,7 +504,7 @@ void GameInfoDialog::setDefaults()
{ {
// Load the default properties // Load the default properties
string md5 = myGameProperties.get(Cartridge_MD5); string md5 = myGameProperties.get(Cartridge_MD5);
instance().propSet().getMD5(md5, myGameProperties, true); instance().propSet(md5).getMD5(md5, myGameProperties, true);
// Reload the current dialog // Reload the current dialog
loadView(); loadView();

View File

@ -36,7 +36,6 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font)
const int lineHeight = font.getLineHeight(), const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(), fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(), fontHeight = font.getFontHeight(),
buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4; buttonHeight = font.getLineHeight() + 4;
int xpos, ypos; int xpos, ypos;
int lwidth = font.getStringWidth("Right Difficulty "), int lwidth = font.getStringWidth("Right Difficulty "),

View File

@ -45,7 +45,6 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
{ {
const int lineHeight = font.getLineHeight(), const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(), fontWidth = font.getMaxCharWidth(),
buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4; buttonHeight = font.getLineHeight() + 4;
const int vBorder = 4; const int vBorder = 4;
int xpos, ypos, tabID; int xpos, ypos, tabID;

View File

@ -349,7 +349,7 @@ void LauncherDialog::loadRomInfo()
// Get the properties for this entry // Get the properties for this entry
Properties props; Properties props;
instance().propSet().getMD5WithInsert(node, myGameList->md5(item), props); instance().propSet(myGameList->md5(item), node).getMD5WithInsert(node, myGameList->md5(item), props);
myRomInfoWidget->setProperties(props); myRomInfoWidget->setProperties(props);
} }

View File

@ -48,16 +48,13 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent,
GuiObject* boss, int max_w, int max_h, stellaMode mode) GuiObject* boss, int max_w, int max_h, stellaMode mode)
: Dialog(osystem, parent), : Dialog(osystem, parent, osystem.frameBuffer().font(), "Options"),
myMode(mode), myMode(mode),
_boss(boss) _boss(boss)
{ {
const GUI::Font& font = instance().frameBuffer().font(); const int buttonWidth = _font.getStringWidth("Game Properties" + ELLIPSIS) + 20,
initTitle(font, "Options"); buttonHeight = _font.getLineHeight() + 6,
rowHeight = _font.getLineHeight() + 10;
const int buttonWidth = font.getStringWidth("Game Properties" + ELLIPSIS) + 20,
buttonHeight = font.getLineHeight() + 6,
rowHeight = font.getLineHeight() + 10;
const int VBORDER = 10 + _th; const int VBORDER = 10 + _th;
_w = 2 * buttonWidth + 30; _w = 2 * buttonWidth + 30;
@ -69,7 +66,7 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent,
auto ADD_OD_BUTTON = [&](const string& label, int cmd) auto ADD_OD_BUTTON = [&](const string& label, int cmd)
{ {
ButtonWidget* bw = new ButtonWidget(this, font, xoffset, yoffset, ButtonWidget* bw = new ButtonWidget(this, _font, xoffset, yoffset,
buttonWidth, buttonHeight, label, cmd); buttonWidth, buttonHeight, label, cmd);
yoffset += rowHeight; yoffset += rowHeight;
return bw; return bw;
@ -128,21 +125,21 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent,
addCancelWidget(b); addCancelWidget(b);
// Now create all the dialogs attached to each menu button // Now create all the dialogs attached to each menu button
myVideoDialog = make_unique<VideoDialog>(osystem, parent, font, max_w, max_h); myVideoDialog = make_unique<VideoDialog>(osystem, parent, _font, max_w, max_h);
myAudioDialog = make_unique<AudioDialog>(osystem, parent, font); myAudioDialog = make_unique<AudioDialog>(osystem, parent, _font);
myInputDialog = make_unique<InputDialog>(osystem, parent, font, max_w, max_h); myInputDialog = make_unique<InputDialog>(osystem, parent, _font, max_w, max_h);
myUIDialog = make_unique<UIDialog>(osystem, parent, font); myUIDialog = make_unique<UIDialog>(osystem, parent, _font);
mySnapshotDialog = make_unique<SnapshotDialog>(osystem, parent, font, max_w, max_h); mySnapshotDialog = make_unique<SnapshotDialog>(osystem, parent, _font, max_w, max_h);
myConfigPathDialog = make_unique<ConfigPathDialog>(osystem, parent, font, boss, max_w, max_h); myConfigPathDialog = make_unique<ConfigPathDialog>(osystem, parent, _font, boss, max_w, max_h);
myRomAuditDialog = make_unique<RomAuditDialog>(osystem, parent, font, max_w, max_h); myRomAuditDialog = make_unique<RomAuditDialog>(osystem, parent, _font, max_w, max_h);
myGameInfoDialog = make_unique<GameInfoDialog>(osystem, parent, font, this); myGameInfoDialog = make_unique<GameInfoDialog>(osystem, parent, _font, this);
#ifdef CHEATCODE_SUPPORT #ifdef CHEATCODE_SUPPORT
myCheatCodeDialog = make_unique<CheatCodeDialog>(osystem, parent, font); myCheatCodeDialog = make_unique<CheatCodeDialog>(osystem, parent, _font);
#endif #endif
myLoggerDialog = make_unique<LoggerDialog>(osystem, parent, font, max_w, max_h); myLoggerDialog = make_unique<LoggerDialog>(osystem, parent, _font, max_w, max_h);
myDeveloperDialog = make_unique<DeveloperDialog>(osystem, parent, font, max_w, max_h); myDeveloperDialog = make_unique<DeveloperDialog>(osystem, parent, _font, max_w, max_h);
myHelpDialog = make_unique<HelpDialog>(osystem, parent, font); myHelpDialog = make_unique<HelpDialog>(osystem, parent, _font);
myAboutDialog = make_unique<AboutDialog>(osystem, parent, font); myAboutDialog = make_unique<AboutDialog>(osystem, parent, _font);
addToFocusList(wid); addToFocusList(wid);

View File

@ -263,11 +263,6 @@ void TabWidget::drawWidget(bool hilite)
FBSurface& s = dialog().surface(); FBSurface& s = dialog().surface();
const int left1 = _x + 1;
const int right1 = _x + kTabLeftOffset + _activeTab * (_tabWidth + kTabSpacing);
const int left2 = right1 + _tabWidth;
const int right2 = _x + _w - 2;
// Iterate over all tabs and draw them // Iterate over all tabs and draw them
int i, x = _x + kTabLeftOffset; int i, x = _x + kTabLeftOffset;
for (i = 0; i < int(_tabs.size()); ++i) for (i = 0; i < int(_tabs.size()); ++i)

View File

@ -25,6 +25,9 @@
#include "TimeLineWidget.hxx" #include "TimeLineWidget.hxx"
const int HANDLE_W = 3;
const int HANDLE_H = 3; // size above/below the slider
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TimeLineWidget::TimeLineWidget(GuiObject* boss, const GUI::Font& font, TimeLineWidget::TimeLineWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int w, int h, int x, int y, int w, int h,
@ -85,7 +88,7 @@ void TimeLineWidget::setStepValues(const IntArray& steps)
if(steps.size() > _stepValue.capacity()) if(steps.size() > _stepValue.capacity())
_stepValue.reserve(2 * steps.size()); _stepValue.reserve(2 * steps.size());
double scale = (_w - _labelWidth - 2) / double(steps.back()); double scale = (_w - _labelWidth - 2 - HANDLE_W*0) / double(steps.back());
// Skip the very last value; we take care of it outside the end of the loop // Skip the very last value; we take care of it outside the end of the loop
for(uInt32 i = 0; i < steps.size() - 1; ++i) for(uInt32 i = 0; i < steps.size() - 1; ++i)
@ -93,7 +96,7 @@ void TimeLineWidget::setStepValues(const IntArray& steps)
// Due to integer <-> double conversion, the last value is sometimes // Due to integer <-> double conversion, the last value is sometimes
// slightly less than the maximum value; we assign it manually to fix this // slightly less than the maximum value; we assign it manually to fix this
_stepValue.push_back(_w - _labelWidth - 2); _stepValue.push_back(_w - _labelWidth - 2 - HANDLE_W*0);
} }
else else
_stepValue.push_back(0); _stepValue.push_back(0);
@ -142,48 +145,64 @@ void TimeLineWidget::drawWidget(bool hilite)
{ {
FBSurface& s = _boss->dialog().surface(); FBSurface& s = _boss->dialog().surface();
#ifndef FLAT_UI
// Draw the label, if any // Draw the label, if any
if(_labelWidth > 0) if(_labelWidth > 0)
s.drawString(_font, _label, _x, _y + 2, _labelWidth, s.drawString(_font, _label, _x, _y + 2, _labelWidth,
isEnabled() ? kTextColor : kColor, TextAlign::Right); isEnabled() ? kTextColor : kColor, TextAlign::Left);
int p = valueToPos(_value),
x = _x + _labelWidth,
w = _w - _labelWidth;
// Frame the handle
const int HANDLE_W2 = (HANDLE_W + 1) / 2;
s.hLine(x + p - HANDLE_W2, _y + 0, x + p - HANDLE_W2 + HANDLE_W, kColorInfo);
s.vLine(x + p - HANDLE_W2, _y + 1, _y + _h - 2, kColorInfo);
s.hLine(x + p - HANDLE_W2 + 1, _y + _h - 1, x + p - HANDLE_W2 + 1 + HANDLE_W, kBGColor);
s.vLine(x + p - HANDLE_W2 + 1 + HANDLE_W, _y + 1, _y + _h - 2, kBGColor);
// Frame the box
s.hLine(x, _y + HANDLE_H, x + w - 2, kColorInfo);
s.vLine(x, _y + HANDLE_H, _y + _h - 2 - HANDLE_H, kColorInfo);
s.hLine(x + 1, _y + _h - 1 - HANDLE_H, x + w - 1, kBGColor);
s.vLine(x + w - 1, _y + 1 + HANDLE_H, _y + _h - 2 - HANDLE_H, kBGColor);
// Draw the box
s.frameRect(_x + _labelWidth, _y, _w - _labelWidth, _h, kColor);
// Fill the box // Fill the box
s.fillRect(_x + _labelWidth + 1, _y + 1, _w - _labelWidth - 2, _h - 2, s.fillRect(x + 1, _y + 1 + HANDLE_H, w - 2, _h - 2 - HANDLE_H * 2,
!isEnabled() ? kBGColorHi : kWidColor); !isEnabled() ? kSliderBGColorLo : hilite ? kSliderBGColorHi : kSliderBGColor);
// Draw the 'bar' // Draw the 'bar'
int vp = valueToPos(_value); s.fillRect(x + 1, _y + 1 + HANDLE_H, p, _h - 2 - HANDLE_H * 2,
s.fillRect(_x + _labelWidth + 1, _y + 1, vp, _h - 2,
!isEnabled() ? kColor : hilite ? kSliderColorHi : kSliderColor); !isEnabled() ? kColor : hilite ? kSliderColorHi : kSliderColor);
// add 4 tickmarks for 5 intervals // Add 4 tickmarks for 5 intervals
int numTicks = std::min(5, int(_stepValue.size())); int numTicks = std::min(5, int(_stepValue.size()));
for(int i = 1; i < numTicks; ++i) for(int i = 1; i < numTicks; ++i)
{ {
int idx = int((_stepValue.size() * i + numTicks / 2) / numTicks); int idx = int((_stepValue.size() * i + numTicks / 2) / numTicks);
if(idx > 1) if(idx > 1)
{ {
int tp = valueToPos(idx - 1); int xt = x + valueToPos(idx - 1);
s.vLine(_x + _labelWidth + tp, _y + _h / 2, _y + _h - 2, tp > vp ? kSliderColor : kWidColor); uInt32 color;
}
}
#else
// Draw the label, if any
if(_labelWidth > 0)
s.drawString(_font, _label, _x, _y + 2, _labelWidth,
isEnabled() ? kTextColor : kColor, TextAlign::Left);
// Draw the box if(isEnabled())
s.frameRect(_x + _labelWidth, _y, _w - _labelWidth, _h, isEnabled() && hilite ? kSliderColorHi : kShadowColor); {
// Fill the box if(xt > x + p)
s.fillRect(_x + _labelWidth + 1, _y + 1, _w - _labelWidth - 2, _h - 2, color = hilite ? kSliderColorHi : kSliderColor;
!isEnabled() ? kBGColorHi : kWidColor); else
// Draw the 'bar' color = hilite ? kSliderBGColorHi : kSliderBGColor;
s.fillRect(_x + _labelWidth + 2, _y + 2, valueToPos(_value), _h - 4, }
else
{
if(xt > x + p)
color = kColor;
else
color = kSliderBGColorLo;
}
s.vLine(xt, _y + _h / 2, _y + _h - 2 - HANDLE_H, color);
}
}
// Draw the handle
s.fillRect(x + p + 1 - HANDLE_W2, _y + 1, HANDLE_W, _h - 2,
!isEnabled() ? kColor : hilite ? kSliderColorHi : kSliderColor); !isEnabled() ? kColor : hilite ? kSliderColorHi : kSliderColor);
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -47,12 +47,25 @@ void TimeMachine::requestResize()
{ {
myWidth = newWidth; myWidth = newWidth;
Dialog* oldPtr = myBaseDialog; Dialog* oldPtr = myBaseDialog;
Int32 enterWinds = static_cast<TimeMachineDialog*>(myBaseDialog)->getEnterWinds();
delete myBaseDialog; delete myBaseDialog;
myBaseDialog = new TimeMachineDialog(myOSystem, *this, myWidth); myBaseDialog = new TimeMachineDialog(myOSystem, *this, myWidth);
setEnterWinds(enterWinds);
Dialog* newPtr = myBaseDialog; Dialog* newPtr = myBaseDialog;
// Update the container stack; it may contain a reference to the old pointer // Update the container stack; it may contain a reference to the old pointer
if(oldPtr != newPtr) if(oldPtr != newPtr)
myDialogStack.replace(oldPtr, newPtr); {
myDialogStack.applyAll([&oldPtr,&newPtr](Dialog*& d){
if(d == oldPtr)
d = newPtr;
});
}
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TimeMachine::setEnterWinds(Int32 numWinds)
{
static_cast<TimeMachineDialog*>(myBaseDialog)->setEnterWinds(numWinds);
}

View File

@ -39,6 +39,11 @@ class TimeMachine : public DialogContainer
*/ */
void requestResize() override; void requestResize() override;
/**
Set number of winds when entering the dialog.
*/
void setEnterWinds(Int32 numWinds);
private: private:
int myWidth; int myWidth;

View File

@ -34,102 +34,140 @@
#include "Base.hxx" #include "Base.hxx"
using Common::Base; using Common::Base;
const int BUTTON_W = 14, BUTTON_H = 14;
static uInt32 RECORD[BUTTON_H] =
{
0b00000111100000,
0b00011111111000,
0b00111111111100,
0b01111111111110,
0b01111111111110,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b01111111111110,
0b01111111111110,
0b00111111111100,
0b00011111111000,
0b00000111100000
};
static uInt32 STOP[BUTTON_H] =
{
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111111111111
};
static uInt32 PLAY[BUTTON_H] =
{
0b11000000000000,
0b11110000000000,
0b11111100000000,
0b11111111000000,
0b11111111110000,
0b11111111111100,
0b11111111111111,
0b11111111111111,
0b11111111111100,
0b11111111110000,
0b11111111000000,
0b11111100000000,
0b11110000000000,
0b11000000000000
};
static uInt32 REWIND_ALL[BUTTON_H] =
{
0,
0b11000011000011,
0b11000111000111,
0b11001111001111,
0b11011111011111,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11011111011111,
0b11001111001111,
0b11000111000111,
0b11000011000011,
0
};
static uInt32 REWIND_1[BUTTON_H] =
{
0,
0b00000110001110,
0b00001110001110,
0b00011110001110,
0b00111110001110,
0b01111110001110,
0b11111110001110,
0b11111110001110,
0b01111110001110,
0b00111110001110,
0b00011110001110,
0b00001110001110,
0b00000110001110,
0
};
static uInt32 UNWIND_1[BUTTON_H] =
{
0,
0b01110001100000,
0b01110001110000,
0b01110001111000,
0b01110001111100,
0b01110001111110,
0b01110001111111,
0b01110001111111,
0b01110001111110,
0b01110001111100,
0b01110001111000,
0b01110001110000,
0b01110001100000,
0
};
static uInt32 UNWIND_ALL[BUTTON_H] =
{
0,
0b11000011000011,
0b11100011100011,
0b11110011110011,
0b11111011111011,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111111111111,
0b11111011111011,
0b11110011110011,
0b11100011100011,
0b11000011000011,
0
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent, TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent,
int width) int width)
: Dialog(osystem, parent) : Dialog(osystem, parent),
_enterWinds(0)
{ {
const int BUTTON_W = 16, BUTTON_H = 14;
static uInt32 PLAY[BUTTON_H] =
{
0b0110000000000000,
0b0111100000000000,
0b0111111000000000,
0b0111111110000000,
0b0111111111100000,
0b0111111111111000,
0b0111111111111110,
0b0111111111111110,
0b0111111111111000,
0b0111111111100000,
0b0111111110000000,
0b0111111000000000,
0b0111100000000000,
0b0110000000000000
};
static uInt32 REWIND_ALL[BUTTON_H] =
{
0,
0b0110000110000110,
0b0110001110001110,
0b0110011110011110,
0b0110111110111110,
0b0111111111111110,
0b0111111111111110,
0b0111111111111110,
0b0111111111111110,
0b0110111110111110,
0b0110011110011110,
0b0110001110001110,
0b0110000110000110,
0
};
static uInt32 REWIND_1[BUTTON_H] =
{
0,
0b0000001100011100,
0b0000011100011100,
0b0000111100011100,
0b0001111100011100,
0b0011111100011100,
0b0111111100011100,
0b0111111100011100,
0b0011111100011100,
0b0001111100011100,
0b0000111100011100,
0b0000011100011100,
0b0000001100011100,
0
};
static uInt32 UNWIND_1[BUTTON_H] =
{
0,
0b0011100011000000,
0b0011100011100000,
0b0011100011110000,
0b0011100011111000,
0b0011100011111100,
0b0011100011111110,
0b0011100011111110,
0b0011100011111100,
0b0011100011111000,
0b0011100011110000,
0b0011100011100000,
0b0011100011000000,
0
};
static uInt32 UNWIND_ALL[BUTTON_H] =
{
0,
0b0110000110000110,
0b0111000111000110,
0b0111100111100110,
0b0111110111110110,
0b0111111111111110,
0b0111111111111110,
0b0111111111111110,
0b0111111111111110,
0b0111110111110110,
0b0111100111100110,
0b0111000111000110,
0b0110000110000110,
0
};
const GUI::Font& font = instance().frameBuffer().font(); const GUI::Font& font = instance().frameBuffer().font();
const int H_BORDER = 6, BUTTON_GAP = 4, V_BORDER = 4; const int H_BORDER = 6, BUTTON_GAP = 4, V_BORDER = 4;
const int buttonWidth = BUTTON_W + 8, const int buttonWidth = BUTTON_W + 10,
buttonHeight = BUTTON_H + 10, buttonHeight = BUTTON_H + 10,
rowHeight = font.getLineHeight(); rowHeight = font.getLineHeight();
@ -146,14 +184,14 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent,
ypos = V_BORDER; ypos = V_BORDER;
// Add index info // Add index info
myCurrentIdxWidget = new StaticTextWidget(this, font, xpos, ypos, " ", TextAlign::Left, kBGColor); myCurrentIdxWidget = new StaticTextWidget(this, font, xpos, ypos, "1000", TextAlign::Left, kBGColor);
myCurrentIdxWidget->setTextColor(kColorInfo); myCurrentIdxWidget->setTextColor(kColorInfo);
myLastIdxWidget = new StaticTextWidget(this, font, _w - H_BORDER - font.getStringWidth("8888"), ypos, myLastIdxWidget = new StaticTextWidget(this, font, _w - H_BORDER - font.getStringWidth("1000"), ypos,
" ", TextAlign::Right, kBGColor); "1000", TextAlign::Right, kBGColor);
myLastIdxWidget->setTextColor(kColorInfo); myLastIdxWidget->setTextColor(kColorInfo);
// Add timeline // Add timeline
const uInt32 tl_h = myCurrentIdxWidget->getHeight() / 2, const uInt32 tl_h = myCurrentIdxWidget->getHeight() / 2 + 6,
tl_x = xpos + myCurrentIdxWidget->getWidth() + 8, tl_x = xpos + myCurrentIdxWidget->getWidth() + 8,
tl_y = ypos + (myCurrentIdxWidget->getHeight() - tl_h) / 2 - 1, tl_y = ypos + (myCurrentIdxWidget->getHeight() - tl_h) / 2 - 1,
tl_w = myLastIdxWidget->getAbsX() - tl_x - 8; tl_w = myLastIdxWidget->getAbsX() - tl_x - 8;
@ -162,25 +200,29 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent,
ypos += rowHeight; ypos += rowHeight;
// Add time info // Add time info
myCurrentTimeWidget = new StaticTextWidget(this, font, xpos, ypos + 3, "04:32 59", TextAlign::Left, kBGColor); myCurrentTimeWidget = new StaticTextWidget(this, font, xpos, ypos + 3, "00:00.00", TextAlign::Left, kBGColor);
myCurrentTimeWidget->setTextColor(kColorInfo); myCurrentTimeWidget->setTextColor(kColorInfo);
myLastTimeWidget = new StaticTextWidget(this, font, _w - H_BORDER - font.getStringWidth("XX:XX XX"), ypos + 3, myLastTimeWidget = new StaticTextWidget(this, font, _w - H_BORDER - font.getStringWidth("00:00.00"), ypos + 3,
"12:25 59", TextAlign::Right, kBGColor); "00:00.00", TextAlign::Right, kBGColor);
myLastTimeWidget->setTextColor(kColorInfo); myLastTimeWidget->setTextColor(kColorInfo);
xpos = myCurrentTimeWidget->getRight() + BUTTON_GAP * 4; xpos = myCurrentTimeWidget->getRight() + BUTTON_GAP * 4;
// Add buttons // Add buttons
myToggleWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, STOP,
BUTTON_W, BUTTON_H, kToggle);
xpos += buttonWidth + BUTTON_GAP;
myPlayWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, PLAY,
BUTTON_W, BUTTON_H, kPlay);
xpos += buttonWidth + BUTTON_GAP * 4;
myRewindAllWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, REWIND_ALL, myRewindAllWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, REWIND_ALL,
BUTTON_W, BUTTON_H, kRewindAll); BUTTON_W, BUTTON_H, kRewindAll);
xpos += buttonWidth + BUTTON_GAP; xpos += buttonWidth + BUTTON_GAP;
myRewind1Widget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, REWIND_1, myRewind1Widget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, REWIND_1,
BUTTON_W, BUTTON_H, kRewind1); BUTTON_W, BUTTON_H, kRewind1);
xpos += buttonWidth + BUTTON_GAP*2; xpos += buttonWidth + BUTTON_GAP;
myPlayWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, PLAY,
BUTTON_W, BUTTON_H, kPlay);
xpos += buttonWidth + BUTTON_GAP*2;
myUnwind1Widget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, UNWIND_1, myUnwind1Widget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, UNWIND_1,
BUTTON_W, BUTTON_H, kUnwind1); BUTTON_W, BUTTON_H, kUnwind1);
@ -188,7 +230,7 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent,
myUnwindAllWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, UNWIND_ALL, myUnwindAllWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, UNWIND_ALL,
BUTTON_W, BUTTON_H, kUnwindAll); BUTTON_W, BUTTON_H, kUnwindAll);
xpos = myUnwindAllWidget->getRight() + BUTTON_GAP * 3; xpos = myUnwindAllWidget->getRight() + BUTTON_GAP * 4;
// Add message // Add message
myMessageWidget = new StaticTextWidget(this, font, xpos, ypos + 3, " ", myMessageWidget = new StaticTextWidget(this, font, xpos, ypos + 3, " ",
@ -224,8 +266,10 @@ void TimeMachineDialog::loadConfig()
surface().applyAttributes(); surface().applyAttributes();
} }
handleWinds();
myMessageWidget->setLabel(""); myMessageWidget->setLabel("");
handleWinds(_enterWinds);
_enterWinds = 0;
handleToggle();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -278,6 +322,11 @@ void TimeMachineDialog::handleCommand(CommandSender* sender, int cmd,
break; break;
} }
case kToggle:
instance().state().toggleTimeMachine();
handleToggle();
break;
case kPlay: case kPlay:
instance().eventHandler().leaveMenuMode(); instance().eventHandler().leaveMenuMode();
break; break;
@ -368,3 +417,11 @@ void TimeMachineDialog::handleWinds(Int32 numWinds)
myUnwindAllWidget->setEnabled(!r.atLast()); myUnwindAllWidget->setEnabled(!r.atLast());
myUnwind1Widget->setEnabled(!r.atLast()); myUnwind1Widget->setEnabled(!r.atLast());
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TimeMachineDialog::handleToggle()
{
myToggleWidget->setBitmap(instance().state().mode() == StateManager::Mode::Off ? RECORD : STOP,
BUTTON_W, BUTTON_H);
}

View File

@ -31,6 +31,10 @@ class TimeMachineDialog : public Dialog
TimeMachineDialog(OSystem& osystem, DialogContainer& parent, int width); TimeMachineDialog(OSystem& osystem, DialogContainer& parent, int width);
virtual ~TimeMachineDialog() = default; virtual ~TimeMachineDialog() = default;
/** set/get number of winds when entering the dialog */
void setEnterWinds(Int32 numWinds) { _enterWinds = numWinds; }
Int32 getEnterWinds() { return _enterWinds; }
private: private:
void loadConfig() override; void loadConfig() override;
void handleKeyDown(StellaKey key, StellaMod mod) override; void handleKeyDown(StellaKey key, StellaMod mod) override;
@ -43,11 +47,14 @@ class TimeMachineDialog : public Dialog
string getTimeString(uInt64 cycles); string getTimeString(uInt64 cycles);
/** re/unwind and update display */ /** re/unwind and update display */
void handleWinds(Int32 numWinds = 0); void handleWinds(Int32 numWinds = 0);
/** toggle Time Machine mode */
void handleToggle();
private: private:
enum enum
{ {
kTimeline = 'TMtl', kTimeline = 'TMtl',
kToggle = 'TMtg',
kPlay = 'TMpl', kPlay = 'TMpl',
kRewindAll = 'TMra', kRewindAll = 'TMra',
kRewind10 = 'TMr1', kRewind10 = 'TMr1',
@ -59,6 +66,7 @@ class TimeMachineDialog : public Dialog
TimeLineWidget* myTimeline; TimeLineWidget* myTimeline;
ButtonWidget* myToggleWidget;
ButtonWidget* myPlayWidget; ButtonWidget* myPlayWidget;
ButtonWidget* myRewindAllWidget; ButtonWidget* myRewindAllWidget;
ButtonWidget* myRewind1Widget; ButtonWidget* myRewind1Widget;
@ -72,6 +80,8 @@ class TimeMachineDialog : public Dialog
StaticTextWidget* myLastIdxWidget; StaticTextWidget* myLastIdxWidget;
StaticTextWidget* myMessageWidget; StaticTextWidget* myMessageWidget;
Int32 _enterWinds;
private: private:
// Following constructors and assignment operators not supported // Following constructors and assignment operators not supported
TimeMachineDialog() = delete; TimeMachineDialog() = delete;

View File

@ -41,7 +41,6 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
const int lineHeight = font.getLineHeight(), const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(), fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(), fontHeight = font.getFontHeight(),
buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4; buttonHeight = font.getLineHeight() + 4;
const int VBORDER = 8; const int VBORDER = 8;
const int HBORDER = 10; const int HBORDER = 10;
@ -49,7 +48,6 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
int lwidth, pwidth = font.getStringWidth("Standard"); int lwidth, pwidth = font.getStringWidth("Standard");
WidgetArray wid; WidgetArray wid;
VariantList items; VariantList items;
ButtonWidget* b;
const GUI::Size& ds = instance().frameBuffer().desktopSize(); const GUI::Size& ds = instance().frameBuffer().desktopSize();
// Set real dimensions // Set real dimensions

View File

@ -44,7 +44,6 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent,
const int lineHeight = font.getLineHeight(), const int lineHeight = font.getLineHeight(),
fontWidth = font.getMaxCharWidth(), fontWidth = font.getMaxCharWidth(),
fontHeight = font.getFontHeight(), fontHeight = font.getFontHeight(),
buttonWidth = font.getStringWidth("Defaults") + 20,
buttonHeight = font.getLineHeight() + 4; buttonHeight = font.getLineHeight() + 4;
int xpos, ypos, tabID; int xpos, ypos, tabID;
int lwidth = font.getStringWidth("TIA Palette "), int lwidth = font.getStringWidth("TIA Palette "),

View File

@ -435,6 +435,15 @@ void ButtonWidget::handleMouseUp(int x, int y, MouseButton b, int clickCount)
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ButtonWidget::setBitmap(uInt32* bitmap, int bmw, int bmh)
{
_bitmap = bitmap;
_bmh = bmh;
_bmw = bmw;
_useBitmap = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ButtonWidget::drawWidget(bool hilite) void ButtonWidget::drawWidget(bool hilite)
{ {
@ -635,10 +644,10 @@ SliderWidget::SliderWidget(GuiObject* boss, const GUI::Font& font,
_valueMax(100), _valueMax(100),
_isDragging(false), _isDragging(false),
_labelWidth(labelWidth), _labelWidth(labelWidth),
_valueLabelGap(valueLabelGap),
_valueLabelWidth(valueLabelWidth),
_valueLabel(""), _valueLabel(""),
_valueUnit(valueUnit), _valueUnit(valueUnit),
_valueLabelGap(valueLabelGap),
_valueLabelWidth(valueLabelWidth),
_numIntervals(0) _numIntervals(0)
{ {
_flags = WIDGET_ENABLED | WIDGET_TRACK_MOUSE; _flags = WIDGET_ENABLED | WIDGET_TRACK_MOUSE;

View File

@ -229,6 +229,8 @@ class ButtonWidget : public StaticTextWidget, public CommandSender
void setCmd(int cmd) { _cmd = cmd; } void setCmd(int cmd) { _cmd = cmd; }
int getCmd() const { return _cmd; } int getCmd() const { return _cmd; }
/* Sets/changes the button's bitmap **/
void setBitmap(uInt32* bitmap, int bmw, int bmh);
protected: protected:
void handleMouseUp(int x, int y, MouseButton b, int clickCount) override; void handleMouseUp(int x, int y, MouseButton b, int clickCount) override;
@ -349,8 +351,8 @@ class SliderWidget : public ButtonWidget
int _labelWidth; int _labelWidth;
string _valueLabel; string _valueLabel;
string _valueUnit; string _valueUnit;
int _valueLabelWidth;
int _valueLabelGap; int _valueLabelGap;
int _valueLabelWidth;
int _numIntervals; int _numIntervals;
private: private: