mirror of https://github.com/stella-emu/stella.git
Merge branch 'master' into feature/filesystem
This commit is contained in:
commit
d6b88336cf
|
@ -314,7 +314,7 @@ bool FileListWidget::handleKeyDown(StellaKey key, StellaMod mod)
|
|||
{
|
||||
handled = true;
|
||||
#ifdef DEBUG_BUILD
|
||||
cerr << " " << mod << ", " << key << endl;
|
||||
cerr << " FileListWidget::handleKeyDown " << mod << ", " << key << endl;
|
||||
#endif
|
||||
switch(key)
|
||||
{
|
||||
|
|
|
@ -476,7 +476,7 @@ void LauncherDialog::tick()
|
|||
reload();
|
||||
|
||||
if(myPendingRomInfo && myRomInfoTime < TimerManager::getTicks() / 1000)
|
||||
loadRomInfo(true);
|
||||
loadPendingRomInfo();
|
||||
|
||||
Dialog::tick();
|
||||
}
|
||||
|
@ -515,7 +515,7 @@ void LauncherDialog::loadConfig()
|
|||
}
|
||||
Dialog::setFocus(getFocusList()[mySelectedItem]);
|
||||
|
||||
if(myRomInfoWidget)
|
||||
if(myRomImageWidget && myRomInfoWidget)
|
||||
{
|
||||
myRomImageWidget->reloadProperties(currentNode());
|
||||
myRomInfoWidget->reloadProperties(currentNode());
|
||||
|
@ -551,10 +551,7 @@ void LauncherDialog::updateUI()
|
|||
<< (myShortCount ? " items" : " items found");
|
||||
myRomCount->setLabel(buf.str());
|
||||
|
||||
// Update ROM info UI item, delayed
|
||||
myRomInfoTime = TimerManager::getTicks() / 1000 + 250; // TODO: define delay
|
||||
myPendingRomInfo = true;
|
||||
loadRomInfo(false);
|
||||
loadRomInfo();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -673,23 +670,41 @@ void LauncherDialog::setRomInfoFont(const Common::Size& area)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void LauncherDialog::loadRomInfo(bool complete)
|
||||
void LauncherDialog::loadRomInfo()
|
||||
{
|
||||
myPendingRomInfo = !complete;
|
||||
if(!myRomImageWidget || !myRomInfoWidget)
|
||||
return;
|
||||
|
||||
if(!myRomImageWidget || !myROMInfoFont)
|
||||
// Update ROM info UI item, delayed
|
||||
myRomInfoTime = TimerManager::getTicks() / 1000 + 250; // TODO: define pending load delay
|
||||
myPendingRomInfo = true;
|
||||
|
||||
const string& md5 = selectedRomMD5();
|
||||
if(md5 != EmptyString)
|
||||
{
|
||||
myRomImageWidget->setProperties(currentNode(), md5, false);
|
||||
myRomInfoWidget->setProperties(currentNode(), md5, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
myRomImageWidget->clearProperties();
|
||||
myRomInfoWidget->clearProperties();
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------
|
||||
void LauncherDialog::loadPendingRomInfo()
|
||||
{
|
||||
myPendingRomInfo = false;
|
||||
|
||||
if(!myRomImageWidget || !myRomInfoWidget)
|
||||
return;
|
||||
|
||||
const string& md5 = selectedRomMD5();
|
||||
if(md5 != EmptyString)
|
||||
{
|
||||
myRomImageWidget->setProperties(currentNode(), md5, complete);
|
||||
myRomInfoWidget->setProperties(currentNode(), md5); // TODO: skip controller detector?
|
||||
}
|
||||
else if(!complete)
|
||||
{
|
||||
myRomImageWidget->clearProperties();
|
||||
myRomInfoWidget->clearProperties();
|
||||
myRomImageWidget->setProperties(currentNode(), md5);
|
||||
myRomInfoWidget->setProperties(currentNode(), md5);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -146,7 +146,8 @@ class LauncherDialog : public Dialog, CommandSender
|
|||
void setRomInfoFont(const Common::Size& area);
|
||||
|
||||
void loadRom();
|
||||
void loadRomInfo(bool complete);
|
||||
void loadRomInfo();
|
||||
void loadPendingRomInfo();
|
||||
void openSettings();
|
||||
void openGameProperties();
|
||||
void openContextMenu(int x = -1, int y = -1);
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include <regex>
|
||||
#include "EventHandler.hxx"
|
||||
#include "FrameBuffer.hxx"
|
||||
#include "Dialog.hxx"
|
||||
#include "FBSurface.hxx"
|
||||
#include "Font.hxx"
|
||||
|
@ -24,7 +24,6 @@
|
|||
#include "PNGLibrary.hxx"
|
||||
#include "Props.hxx"
|
||||
#include "PropsSet.hxx"
|
||||
#include "bspf.hxx"
|
||||
#include "RomImageWidget.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -40,7 +39,7 @@ RomImageWidget::RomImageWidget(GuiObject* boss, const GUI::Font& font,
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void RomImageWidget::setProperties(const FSNode& node, const string& md5, bool complete)
|
||||
void RomImageWidget::setProperties(const FSNode& node, const string& md5, bool full)
|
||||
{
|
||||
myHaveProperties = true;
|
||||
|
||||
|
@ -52,7 +51,7 @@ void RomImageWidget::setProperties(const FSNode& node, const string& md5, bool c
|
|||
|
||||
// Decide whether the information should be shown immediately
|
||||
if(instance().eventHandler().state() == EventHandlerState::LAUNCHER)
|
||||
parseProperties(node, complete);
|
||||
parseProperties(node, full);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -74,11 +73,11 @@ void RomImageWidget::reloadProperties(const FSNode& node)
|
|||
// by saving a different image or through a change in video renderer,
|
||||
// so we reload the properties
|
||||
if(myHaveProperties)
|
||||
parseProperties(node, true);
|
||||
parseProperties(node);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void RomImageWidget::parseProperties(const FSNode& node, bool complete)
|
||||
void RomImageWidget::parseProperties(const FSNode& node, bool full)
|
||||
{
|
||||
if(myNavSurface == nullptr)
|
||||
{
|
||||
|
@ -112,47 +111,49 @@ void RomImageWidget::parseProperties(const FSNode& node, bool complete)
|
|||
});
|
||||
}
|
||||
|
||||
// Initialize to empty properties entry
|
||||
mySurfaceErrorMsg = "";
|
||||
mySurfaceIsValid = false;
|
||||
|
||||
#ifdef PNG_SUPPORT
|
||||
// TODO: RETRON_77
|
||||
|
||||
// Get a valid filename representing a snapshot file for this rom and load the snapshot
|
||||
myImageList.clear();
|
||||
myImageIdx = 0;
|
||||
|
||||
if(complete)
|
||||
#ifdef PNG_SUPPORT
|
||||
if(!full)
|
||||
{
|
||||
// Try to load snapshots by property name and ROM file name
|
||||
getImageList(myProperties.get(PropType::Cart_Name), node.getNameWithExt());
|
||||
myImageIdx = 0;
|
||||
myImageList.clear();
|
||||
mySurfaceErrorMsg = "";
|
||||
|
||||
if(myImageList.size())
|
||||
mySurfaceIsValid = loadPng(myImageList[0].getPath());
|
||||
// Get a valid filename representing a snapshot file for this rom and load the snapshot
|
||||
const string& path = instance().snapshotLoadDir().getPath();
|
||||
// 1. Try to load first snapshot by property name
|
||||
string fileName = path + myProperties.get(PropType::Cart_Name) + ".png";
|
||||
|
||||
mySurfaceIsValid = loadPng(fileName);
|
||||
if(!mySurfaceIsValid)
|
||||
{
|
||||
// 2. If none exists, try to load first snapshot by ROM file name
|
||||
fileName = path + node.getNameWithExt("png");
|
||||
mySurfaceIsValid = loadPng(fileName);
|
||||
}
|
||||
if(mySurfaceIsValid)
|
||||
myImageList.emplace_back(fileName);
|
||||
else
|
||||
// 3. If no ROM snapshots exist, try to load a default snapshot
|
||||
mySurfaceIsValid = loadPng(path + "default_snapshot.png");
|
||||
}
|
||||
else
|
||||
{
|
||||
const string& path = instance().snapshotLoadDir().getPath();
|
||||
string filename = path + myProperties.get(PropType::Cart_Name) + ".png";
|
||||
const string& oldFileName = myImageList.size() ? myImageList[0].getPath() : "";
|
||||
|
||||
mySurfaceIsValid = loadPng(filename);
|
||||
if(!mySurfaceIsValid)
|
||||
// Try to find all snapshots by property and ROM file name
|
||||
myImageList.clear();
|
||||
getImageList(myProperties.get(PropType::Cart_Name), node.getNameWithExt());
|
||||
|
||||
// The first file found before must not be the first file now, if files by
|
||||
// property *and* ROM name are found
|
||||
if(myImageList.size() && myImageList[0].getPath() != oldFileName)
|
||||
{
|
||||
filename = path + node.getNameWithExt("png");
|
||||
mySurfaceIsValid = loadPng(filename);
|
||||
mySurfaceErrorMsg = "";
|
||||
mySurfaceIsValid = loadPng(myImageList[0].getPath());
|
||||
}
|
||||
if(mySurfaceIsValid)
|
||||
myImageList.emplace_back(filename);
|
||||
}
|
||||
|
||||
if(!mySurfaceIsValid)
|
||||
{
|
||||
// If no ROM snapshots exist, try to load a default snapshot
|
||||
mySurfaceIsValid = loadPng(instance().snapshotLoadDir().getPath() + "default_snapshot.png");
|
||||
}
|
||||
|
||||
#else
|
||||
mySurfaceIsValid = false;
|
||||
mySurfaceErrorMsg = "PNG image loading not supported";
|
||||
#endif
|
||||
if(mySurface)
|
||||
|
@ -174,29 +175,21 @@ bool RomImageWidget::changeImage(int direction)
|
|||
|
||||
#ifdef PNG_SUPPORT
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool RomImageWidget::getImageList(const string& propname, const string& filename)
|
||||
bool RomImageWidget::getImageList(const string& propName, const string& romName)
|
||||
{
|
||||
// TODO: search for consecutive digits and letters instead of getChildren
|
||||
//std::ifstream in(filename, std::ios_base::binary);
|
||||
//if(!in.is_open())
|
||||
// loadImageERROR("No snapshot found");
|
||||
// or use a timer before updating the images
|
||||
const std::regex symbols{R"([-[\]{}()*+?.,\^$|#])"}; // \s
|
||||
const string rgxPropName = std::regex_replace(propName, symbols, R"(\$&)");
|
||||
const string rgxRomName = std::regex_replace(romName, symbols, R"(\$&)");
|
||||
// Look for <name.png> or <name_#.png> (# is a number)
|
||||
const std::regex rgx("^(" + rgxPropName + "|" + rgxRomName + ")(_\\d+){0,1}\\.png$");
|
||||
|
||||
const string pngPropName = propname + ".png";
|
||||
const string pngFileName = filename + ".png";
|
||||
FSNode::NameFilter filter = ([&](const FSNode& node)
|
||||
{
|
||||
const string& nodeName = node.getName();
|
||||
return
|
||||
(nodeName == pngPropName || nodeName == pngFileName ||
|
||||
(nodeName.find(propname + " #") == 0 &&
|
||||
nodeName.find(".png") == nodeName.length() - 4) ||
|
||||
(nodeName.find(filename + " #") == 0 &&
|
||||
nodeName.find(".png") == nodeName.length() - 4));
|
||||
return std::regex_match(node.getName(), rgx);
|
||||
}
|
||||
);
|
||||
|
||||
// Find all images matching the filename and the extension
|
||||
// Find all images matching the given names and the extension
|
||||
FSNode node(instance().snapshotLoadDir().getPath());
|
||||
node.getChildren(myImageList, FSNode::ListMode::FilesOnly, filter, false, false);
|
||||
|
||||
|
@ -212,12 +205,12 @@ bool RomImageWidget::getImageList(const string& propname, const string& filename
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool RomImageWidget::loadPng(const string& filename)
|
||||
bool RomImageWidget::loadPng(const string& fileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
VariantList comments;
|
||||
instance().png().loadImage(filename, *mySurface, comments);
|
||||
instance().png().loadImage(fileName, *mySurface, comments);
|
||||
|
||||
// Scale surface to available image area
|
||||
const Common::Rect& src = mySurface->srcRect();
|
||||
|
@ -271,7 +264,7 @@ void RomImageWidget::drawWidget(bool hilite)
|
|||
FBSurface& s = dialog().surface();
|
||||
const int yoff = myImageHeight;
|
||||
|
||||
s.fillRect(_x+1, _y+1, _w-2, _h-1, _bgcolor);
|
||||
s.fillRect(_x+1, _y+1, _w-2, _h-2, _bgcolor);
|
||||
s.frameRect(_x, _y, _w, myImageHeight, kColor);
|
||||
|
||||
if(!myHaveProperties)
|
||||
|
|
|
@ -22,7 +22,6 @@ class FBSurface;
|
|||
class Properties;
|
||||
|
||||
#include "Widget.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
class RomImageWidget : public Widget, public CommandSender
|
||||
{
|
||||
|
@ -36,7 +35,7 @@ class RomImageWidget : public Widget, public CommandSender
|
|||
return font.getFontHeight() * 9 / 8;
|
||||
}
|
||||
|
||||
void setProperties(const FSNode& node, const string& md5, bool complete);
|
||||
void setProperties(const FSNode& node, const string& md5, bool full = true);
|
||||
void clearProperties();
|
||||
void reloadProperties(const FSNode& node);
|
||||
bool changeImage(int direction = 1);
|
||||
|
@ -49,10 +48,10 @@ class RomImageWidget : public Widget, public CommandSender
|
|||
#endif
|
||||
|
||||
private:
|
||||
void parseProperties(const FSNode& node, bool complete);
|
||||
void parseProperties(const FSNode& node, bool full = true);
|
||||
#ifdef PNG_SUPPORT
|
||||
bool getImageList(const string& propname, const string& filename);
|
||||
bool loadPng(const string& filename);
|
||||
bool getImageList(const string& propName, const string& romName);
|
||||
bool loadPng(const string& fileName);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
//============================================================================
|
||||
|
||||
#include "EventHandler.hxx"
|
||||
#include "FrameBuffer.hxx"
|
||||
#include "Dialog.hxx"
|
||||
#include "FBSurface.hxx"
|
||||
#include "Font.hxx"
|
||||
|
@ -40,7 +39,7 @@ RomInfoWidget::RomInfoWidget(GuiObject* boss, const GUI::Font& font,
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void RomInfoWidget::setProperties(const FSNode& node, const string& md5)
|
||||
void RomInfoWidget::setProperties(const FSNode& node, const string& md5, bool full)
|
||||
{
|
||||
myHaveProperties = true;
|
||||
|
||||
|
@ -52,7 +51,7 @@ void RomInfoWidget::setProperties(const FSNode& node, const string& md5)
|
|||
|
||||
// Decide whether the information should be shown immediately
|
||||
if(instance().eventHandler().state() == EventHandlerState::LAUNCHER)
|
||||
parseProperties(node);
|
||||
parseProperties(node, full);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -77,7 +76,7 @@ void RomInfoWidget::reloadProperties(const FSNode& node)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void RomInfoWidget::parseProperties(const FSNode& node)
|
||||
void RomInfoWidget::parseProperties(const FSNode& node, bool full)
|
||||
{
|
||||
// Initialize to empty properties entry
|
||||
myRomInfo.clear();
|
||||
|
@ -97,63 +96,68 @@ void RomInfoWidget::parseProperties(const FSNode& node)
|
|||
myRomInfo.push_back("Rarity: " + value);
|
||||
if((value = myProperties.get(PropType::Cart_Note)) != EmptyString)
|
||||
myRomInfo.push_back("Note: " + value);
|
||||
const bool swappedPorts = myProperties.get(PropType::Console_SwapPorts) == "YES";
|
||||
|
||||
// Load the image for controller and bankswitch type auto detection
|
||||
string left = myProperties.get(PropType::Controller_Left);
|
||||
string right = myProperties.get(PropType::Controller_Right);
|
||||
const Controller::Type leftType = Controller::getType(left);
|
||||
const Controller::Type rightType = Controller::getType(right);
|
||||
string bsDetected = myProperties.get(PropType::Cart_Type);
|
||||
bool isPlusCart = false;
|
||||
size_t size = 0;
|
||||
try
|
||||
|
||||
if(full)
|
||||
{
|
||||
ByteBuffer image;
|
||||
string md5 = "";
|
||||
const bool swappedPorts = myProperties.get(PropType::Console_SwapPorts) == "YES";
|
||||
|
||||
if(node.exists() && !node.isDirectory() &&
|
||||
(image = instance().openROM(node, md5, size)) != nullptr)
|
||||
// Load the image for controller and bankswitch type auto detection
|
||||
string left = myProperties.get(PropType::Controller_Left);
|
||||
string right = myProperties.get(PropType::Controller_Right);
|
||||
const Controller::Type leftType = Controller::getType(left);
|
||||
const Controller::Type rightType = Controller::getType(right);
|
||||
string bsDetected = myProperties.get(PropType::Cart_Type);
|
||||
bool isPlusCart = false;
|
||||
size_t size = 0;
|
||||
try
|
||||
{
|
||||
Logger::debug(myProperties.get(PropType::Cart_Name) + ":");
|
||||
left = ControllerDetector::detectName(image, size, leftType,
|
||||
ByteBuffer image;
|
||||
string md5 = "";
|
||||
|
||||
if(node.exists() && !node.isDirectory() &&
|
||||
(image = instance().openROM(node, md5, size)) != nullptr)
|
||||
{
|
||||
Logger::debug(myProperties.get(PropType::Cart_Name) + ":");
|
||||
left = ControllerDetector::detectName(image, size, leftType,
|
||||
!swappedPorts ? Controller::Jack::Left : Controller::Jack::Right,
|
||||
instance().settings());
|
||||
right = ControllerDetector::detectName(image, size, rightType,
|
||||
instance().settings());
|
||||
right = ControllerDetector::detectName(image, size, rightType,
|
||||
!swappedPorts ? Controller::Jack::Right : Controller::Jack::Left,
|
||||
instance().settings());
|
||||
if (bsDetected == "AUTO")
|
||||
bsDetected = Bankswitch::typeToName(CartDetector::autodetectType(image, size));
|
||||
instance().settings());
|
||||
if(bsDetected == "AUTO")
|
||||
bsDetected = Bankswitch::typeToName(CartDetector::autodetectType(image, size));
|
||||
|
||||
isPlusCart = CartDetector::isProbablyPlusROM(image, size);
|
||||
isPlusCart = CartDetector::isProbablyPlusROM(image, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(const runtime_error&)
|
||||
{
|
||||
// Do nothing; we simply don't update the controllers if openROM
|
||||
// failed for any reason
|
||||
left = right = "";
|
||||
}
|
||||
if(left != "" && right != "")
|
||||
myRomInfo.push_back("Controllers: " + (left + " (left), " + right + " (right)"));
|
||||
|
||||
if(bsDetected != "")
|
||||
{
|
||||
ostringstream buf;
|
||||
|
||||
// Display actual ROM size in developer mode
|
||||
if(instance().settings().getBool("dev.settings"))
|
||||
catch(const runtime_error&)
|
||||
{
|
||||
buf << " - ";
|
||||
if(size < 1_KB)
|
||||
buf << size << "B";
|
||||
else
|
||||
buf << (std::round(size / static_cast<float>(1_KB))) << "K";
|
||||
// Do nothing; we simply don't update the controllers if openROM
|
||||
// failed for any reason
|
||||
left = right = "";
|
||||
}
|
||||
if(left != "" && right != "")
|
||||
myRomInfo.push_back("Controllers: " + (left + " (left), " + right + " (right)"));
|
||||
|
||||
if(bsDetected != "")
|
||||
{
|
||||
ostringstream buf;
|
||||
|
||||
// Display actual ROM size in developer mode
|
||||
if(instance().settings().getBool("dev.settings"))
|
||||
{
|
||||
buf << " - ";
|
||||
if(size < 1_KB)
|
||||
buf << size << "B";
|
||||
else
|
||||
buf << (std::round(size / static_cast<float>(1_KB))) << "K";
|
||||
}
|
||||
myRomInfo.push_back("Type: " + Bankswitch::typeToDesc(Bankswitch::nameToType(bsDetected))
|
||||
+ (isPlusCart ? " - PlusROM" : "")
|
||||
+ buf.str());
|
||||
}
|
||||
myRomInfo.push_back("Type: " + Bankswitch::typeToDesc(Bankswitch::nameToType(bsDetected))
|
||||
+ (isPlusCart ? " - PlusROM" : "")
|
||||
+ buf.str());
|
||||
}
|
||||
|
||||
setDirty();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ class FBSurface;
|
|||
class Properties;
|
||||
|
||||
#include "Widget.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
class RomInfoWidget : public Widget, public CommandSender
|
||||
{
|
||||
|
@ -36,7 +35,7 @@ class RomInfoWidget : public Widget, public CommandSender
|
|||
int x, int y, int w, int h);
|
||||
~RomInfoWidget() override = default;
|
||||
|
||||
void setProperties(const FSNode& node, const string& md5);
|
||||
void setProperties(const FSNode& node, const string& md5, bool full = true);
|
||||
void clearProperties();
|
||||
void reloadProperties(const FSNode& node);
|
||||
|
||||
|
@ -47,7 +46,7 @@ class RomInfoWidget : public Widget, public CommandSender
|
|||
void handleMouseUp(int x, int y, MouseButton b, int clickCount) override;
|
||||
|
||||
private:
|
||||
void parseProperties(const FSNode& node);
|
||||
void parseProperties(const FSNode& node, bool full = true);
|
||||
|
||||
private:
|
||||
// Some ROM properties info, as well as 'tEXt' chunks from the PNG image
|
||||
|
|
Loading…
Reference in New Issue