diff --git a/src/emucore/DefProps.hxx b/src/emucore/DefProps.hxx index e53dcff0e..5959b8238 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 = 3522; +static constexpr uInt32 DEF_PROPS_SIZE = 3524; static const BSPF::array2D DefProps = {{ { "000509d1ed2b8d30a9d94be1b3b5febb", "Greg Zumwalt", "", "Jungle Jane (2003) (Greg Zumwalt) (Hack)", "Hack of Pitfall!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "{\"score_addresses\":[\"0xd5\",\"0xd6\",\"0xd7\"],\"score_digits\":6,\"variations_count\":1}", "" }, @@ -1482,7 +1482,7 @@ static const BSPF::array2D DefProps = {{ { "68760b82fc5dcf3fedf84376a4944bf9", "CCE", "C-860", "Laser Gate (1983) (CCE)", "AKA Innerspace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, { "687c23224e26f81c56e431c24faea36d", "", "", "Qb (Simple Background Animation) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "" }, { "68878250e106eb6c7754bc2519d780a0", "CCE", "C-809", "Squirrel (1983) (CCE)", "AKA Snail Against Squirrel", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "689f49e31cac68db8a2cf8f44fa7a01a", "Oscar Toledo G., Thomas Jentzsch, Nathan Strum", "", "Aardvark (2019) (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "" }, + { "689f49e31cac68db8a2cf8f44fa7a01a", "Oscar Toledo G., Thomas Jentzsch, Nathan Strum", "", "Aardvark (2019) (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "https://atariage.com/store/index.php?l=product_detail&p=1212" }, { "68ac69b8e1ba83af8792f693f5ae7783", "Digivision", "", "Fathon (Digivision)", "AKA Fathom", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, { "68c80e7e1d30df98a0cf67ecbf39cc67", "Hozer Video Games", "", "Gunfight 2600 - One Step Forward & Two Steps Back (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, { "68c938a2a2b45c37db50509f1037fe6e", "Omegamatrix", "", "Star Wars Arcade (Atari Mouse) v4 (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, @@ -1618,6 +1618,7 @@ static const BSPF::array2D DefProps = {{ { "721a5567f76856f6b50a6707aa8f8316", "Activision, David Crane, Dan Kitchen", "EAG-108-04, EAZ-108-04B", "Ghostbusters (1985) (Activision) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, { "72305c997f2cec414fe6f8c946172f83", "Arcadia Corporation, Dennis Caswell", "AR-4000, AR-4100", "Phaser Patrol (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "" }, { "724613effaf7743cbcd695fab469c2a8", "", "", "Super-Ferrari (Unknown)", "AKA Enduro", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "{\"score_addresses\":[\"0xaa\",\"0xa9\",\"0xa8\"],\"score_digits\":6,\"special_address\":\"0xad\",\"special_label\":\"Day\",\"variations_count\":1}", "" }, + { "726af33d9acfc8616a8df05de4f560af", "Thomas Jentzsch", "", "Robot City RC8 (PAL-60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "https://atariage.com/store/index.php?l=product_detail&p=1233" }, { "728152f5ae6fdd0d3a9b88709bee6c7a", "Spectravideo, Mark Turmell", "SA-217", "Gas Hog (1983) (Spectravideo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, { "72876fd7c7435f41d571f1101fc456ea", "Quelle", "688.383 9", "Die Ente und der Wolf (1983) (Quelle) (PAL)", "AKA Pooyan", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, { "72a46e0c21f825518b7261c267ab886e", "Xonox - K-Tel Software - Computer Magic", "99005, 6220, 6250", "Robin Hood (1983) (Xonox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, @@ -1859,7 +1860,7 @@ static const BSPF::array2D DefProps = {{ { "82c25d1c35e6ac6f893d1d7c2fc2f9c8", "Atari, Larry Kaplan", "CX2628, CX2628P", "Bowling (1979) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, { "82de957d155fc041fc6afb8315a28550", "Coleco, Joseph Biel", "2457", "Venture (1982) (Coleco) (Prototype)", "2K", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, { "82e7aab602c378cffdd8186a099e807e", "", "", "Space Robot (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "82ee056af81203af58092ff2e6cf079d", "Oscar Toledo G., Thomas Jentzsch, Nathan Strum", "", "Aardvark (2019) (NTSC)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "" }, + { "82ee056af81203af58092ff2e6cf079d", "Oscar Toledo G., Thomas Jentzsch, Nathan Strum", "", "Aardvark (2019) (NTSC)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "https://atariage.com/store/index.php?l=product_detail&p=1212" }, { "82efe7984783e23a7c55266a5125c68e", "CCE", "C-837", "Pizza Chef (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, { "834a2273e97aec3181ee127917b4b269", "Quelle", "043.151 0, 874.382 5", "Die hungrigen Froesche (1983) (Quelle) (PAL)", "AKA Frogs and Flies", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, { "835759ff95c2cdc2324d7c1e7c5fa237", "20th Century Fox Video Games, Frank Cohen, Douglas 'Dallas North' Neubauer", "11011", "M.A.S.H (1983) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, @@ -3256,6 +3257,7 @@ static const BSPF::array2D DefProps = {{ { "ebf9038e927e6a0db3e0d170c59911e6", "", "", "Pac-2600 (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, { "ec3beb6d8b5689e867bafb5d5f507491", "U.S. Games Corporation - Vidtec - JWDA, Todd Marshall, Henry Will IV", "VC1003", "Word Zapper (1982) (U.S. Games)", "AKA Word Grabber", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, { "ec407a206b718a0a9f69b03e920a0185", "Quelle", "876.482 1", "Landung in der Normandie (1983) (Quelle) (PAL)", "AKA Commando Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ec44dcf2ddb4319962fc43b725a902e8", "Thomas Jentzsch", "", "Robot City RC8 (NTSC)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "https://atariage.com/store/index.php?l=product_detail&p=1233" }, { "ec5c861b487a5075876ab01155e74c6c", "Apollo - Games by Apollo, Ed Salvo, Byron Parks", "AP-2001", "Spacechase (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, { "ece463abde92e8b89bcd867ec71751b8", "Puzzy - Bit Corporation", "PG205", "Dancing Plate (1982) (Puzzy) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "" }, { "ece908d77ab944f7bac84322b9973549", "", "", "Tom Boy (Unknown) (PAL60)", "AKA Pitfall!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "{\"score_addresses\":[\"0xd5\",\"0xd6\",\"0xd7\"],\"score_digits\":6,\"variations_count\":1}", "" }, diff --git a/src/emucore/FBSurface.cxx b/src/emucore/FBSurface.cxx index b4d793cad..9ed4d7971 100644 --- a/src/emucore/FBSurface.cxx +++ b/src/emucore/FBSurface.cxx @@ -347,9 +347,10 @@ bool FBSurface::isWhiteSpace(const char s) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int FBSurface::drawString(const GUI::Font& font, const string& s, - int x, int y, int w, int h, - ColorId color, TextAlign align, - int deltax, bool useEllipsis, ColorId shadowColor) + int x, int y, int w, int h, + ColorId color, TextAlign align, + int deltax, bool useEllipsis, ColorId shadowColor, + size_t linkStart, int linkLen, bool underline) { int lines = 0; @@ -357,14 +358,17 @@ int FBSurface::drawString(const GUI::Font& font, const string& s, string inStr = s; // draw multiline string - //while (font.getStringWidth(inStr) > w && h >= font.getFontHeight() * 2) while(inStr.length() && h >= font.getFontHeight() * 2) { // String is too wide. string leftStr, rightStr; splitString(font, inStr, w, leftStr, rightStr); - drawString(font, leftStr, x, y, w, color, align, deltax, false, shadowColor); + drawString(font, leftStr, x, y, w, color, align, deltax, false, shadowColor, + linkStart, linkLen, underline); + if(linkStart != string::npos) + linkStart = std::max(0, int(linkStart - leftStr.length())); + h -= font.getFontHeight(); y += font.getFontHeight(); inStr = rightStr; @@ -372,7 +376,8 @@ int FBSurface::drawString(const GUI::Font& font, const string& s, } if(inStr.length()) { - drawString(font, inStr, x, y, w, color, align, deltax, useEllipsis, shadowColor); + drawString(font, inStr, x, y, w, color, align, deltax, useEllipsis, shadowColor, + linkStart, linkLen, underline); lines++; } #endif @@ -426,7 +431,7 @@ void FBSurface::drawString(const GUI::Font& font, const string& s, x += deltax; - int x0 = 0, x1 = 0; + int x0 = x, x1 = 0; for(i = 0; i < str.size(); ++i) { diff --git a/src/emucore/FBSurface.hxx b/src/emucore/FBSurface.hxx index 902a7094f..f1ebbdd80 100644 --- a/src/emucore/FBSurface.hxx +++ b/src/emucore/FBSurface.hxx @@ -211,42 +211,50 @@ class FBSurface /** This method should be called to draw the specified string. - @param font The font to draw the string with - @param s The string to draw - @param x The x coordinate - @param y The y coordinate - @param w The width of the string area - @param h The height of the string area (for multi line strings) - @param color The color of the text - @param align The alignment of the text in the string width area - @param deltax FIXME + @param font The font to draw the string with + @param s The string to draw + @param x The x coordinate + @param y The y coordinate + @param w The width of the string area + @param h The height of the string area (for multi line strings) + @param color The color of the text + @param align The alignment of the text in the string width area + @param deltax The horizontal scroll offset @param useEllipsis Whether to use '...' when the string is too long + @param shadowColor The shadow color of the text + @param linkStart The start position of a link in drawn string + @param linkLen The length of a link in drawn string + @param underline Whether to underline the link @return Number of lines drawn */ - virtual int drawString( - const GUI::Font& font, const string& s, int x, int y, int w, int h, - ColorId color, TextAlign align = TextAlign::Left, - int deltax = 0, bool useEllipsis = true, ColorId shadowColor = kNone); + virtual int drawString(const GUI::Font& font, const string& s, int x, int y, int w, int h, + ColorId color, TextAlign align = TextAlign::Left, + int deltax = 0, bool useEllipsis = true, ColorId shadowColor = kNone, + size_t linkStart = string::npos, int linkLen = 0, bool underline = false); /** This method should be called to draw the specified string. - @param font The font to draw the string with - @param s The string to draw - @param x The x coordinate - @param y The y coordinate - @param w The width of the string area - @param color The color of the text - @param align The alignment of the text in the string width area - @param deltax FIXME + @param font The font to draw the string with + @param s The string to draw + @param x The x coordinate + @param y The y coordinate + @param w The width of the string area + @param color The color of the text + @param align The alignment of the text in the string width area + @param deltax The horizontal scroll offset @param useEllipsis Whether to use '...' when the string is too long + @param shadowColor The shadow color of the text + @param linkStart The start position of a link in drawn string + @param linkLen The length of a link in drawn string + @param underline Whether to underline the link + */ - virtual void drawString( - const GUI::Font& font, const string& s, int x, int y, int w, - ColorId color, TextAlign align = TextAlign::Left, - int deltax = 0, bool useEllipsis = true, ColorId shadowColor = kNone, - size_t linkStart = string::npos, int linkLen = 0, bool underline = false); + virtual void drawString(const GUI::Font& font, const string& s, int x, int y, int w, + ColorId color, TextAlign align = TextAlign::Left, + int deltax = 0, bool useEllipsis = true, ColorId shadowColor = kNone, + size_t linkStart = string::npos, int linkLen = 0, bool underline = false); /** Splits a given string to a given width considering whitespaces. diff --git a/src/emucore/stella.pro b/src/emucore/stella.pro index 7be5d2e51..47f0740a0 100644 --- a/src/emucore/stella.pro +++ b/src/emucore/stella.pro @@ -9101,6 +9101,7 @@ "Cart.Manufacturer" "Oscar Toledo G., Thomas Jentzsch, Nathan Strum" "Cart.Name" "Aardvark (2019) (PAL60)" "Cart.Rarity" "Homebrew" +"Cart.Url" "https://atariage.com/store/index.php?l=product_detail&p=1212" "Display.Phosphor" "YES" "" @@ -9948,6 +9949,14 @@ "Cart.Highscore" "{\"score_addresses\":[\"0xaa\",\"0xa9\",\"0xa8\"],\"score_digits\":6,\"special_address\":\"0xad\",\"special_label\":\"Day\",\"variations_count\":1}" "" +"Cart.MD5" "726af33d9acfc8616a8df05de4f560af" +"Cart.Manufacturer" "Thomas Jentzsch" +"Cart.Name" "Robot City RC8 (PAL-60)" +"Cart.Rarity" "Homebrew" +"Cart.Url" "https://atariage.com/store/index.php?l=product_detail&p=1233" +"Display.Phosphor" "YES" +"" + "Cart.MD5" "728152f5ae6fdd0d3a9b88709bee6c7a" "Cart.Manufacturer" "Spectravideo, Mark Turmell" "Cart.ModelNo" "SA-217" @@ -11449,6 +11458,7 @@ "Cart.Manufacturer" "Oscar Toledo G., Thomas Jentzsch, Nathan Strum" "Cart.Name" "Aardvark (2019) (NTSC)" "Cart.Rarity" "Homebrew" +"Cart.Url" "https://atariage.com/store/index.php?l=product_detail&p=1212" "Display.Phosphor" "YES" "" @@ -20104,6 +20114,14 @@ "Cart.Note" "AKA Commando Raid" "" +"Cart.MD5" "ec44dcf2ddb4319962fc43b725a902e8" +"Cart.Manufacturer" "Thomas Jentzsch" +"Cart.Name" "Robot City RC8 (NTSC)" +"Cart.Rarity" "Homebrew" +"Cart.Url" "https://atariage.com/store/index.php?l=product_detail&p=1233" +"Display.Phosphor" "YES +"" + "Cart.MD5" "ec5c861b487a5075876ab01155e74c6c" "Cart.Manufacturer" "Apollo - Games by Apollo, Ed Salvo, Byron Parks" "Cart.ModelNo" "AP-2001" diff --git a/src/gui/AboutDialog.cxx b/src/gui/AboutDialog.cxx index c49f7d780..7a4488b7a 100644 --- a/src/gui/AboutDialog.cxx +++ b/src/gui/AboutDialog.cxx @@ -286,7 +286,7 @@ void AboutDialog::handleCommand(CommandSender* sender, int cmd, int data, int id case StaticTextWidget::kOpenUrlCmd: { - const string url = myDesc[id]->getUrl(); // getUrl(myDescStr[id]); + const string url = myDesc[id]->getUrl(); if(url != EmptyString) MediaFactory::openURL(url); diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 5e6194225..a0dc9d18b 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -972,7 +972,7 @@ void GameInfoDialog::saveProperties() myGameProperties.set(PropType::Cart_ModelNo, myModelNo->getText()); myGameProperties.set(PropType::Cart_Rarity, myRarity->getText()); myGameProperties.set(PropType::Cart_Note, myNote->getText()); - myGameProperties.set(PropType::Cart_Note, myUrl->getText()); + myGameProperties.set(PropType::Cart_Url, myUrl->getText()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index b6a0ed915..f9064f790 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -56,6 +56,7 @@ #include "Stella14x28tFont.hxx" #include "Stella16x32tFont.hxx" #include "Version.hxx" +#include "MediaFactory.hxx" #include "LauncherDialog.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -865,6 +866,15 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd, handleContextMenu(); break; + case RomInfoWidget::kClickedCmd: + { + const string url = myRomInfoWidget->getUrl(); + + if(url != EmptyString) + MediaFactory::openURL(url); + break; + } + default: Dialog::handleCommand(sender, cmd, data, 0); } diff --git a/src/gui/LauncherDialog.hxx b/src/gui/LauncherDialog.hxx index 162032065..767157b27 100644 --- a/src/gui/LauncherDialog.hxx +++ b/src/gui/LauncherDialog.hxx @@ -182,6 +182,7 @@ class LauncherDialog : public Dialog ButtonWidget* myOptionsButton{nullptr}; ButtonWidget* myQuitButton{nullptr}; + StaticTextWidget* myRomLink{nullptr}; RomInfoWidget* myRomInfoWidget{nullptr}; std::unordered_map myMD5List; diff --git a/src/gui/RomInfoWidget.cxx b/src/gui/RomInfoWidget.cxx index 152718c48..938ef92ed 100644 --- a/src/gui/RomInfoWidget.cxx +++ b/src/gui/RomInfoWidget.cxx @@ -37,6 +37,7 @@ RomInfoWidget::RomInfoWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h, const Common::Size& imgSize) : Widget(boss, font, x, y, w, h), + CommandSender(boss), myAvail{imgSize} { _flags = Widget::FLAG_ENABLED; @@ -214,6 +215,16 @@ bool RomInfoWidget::loadPng(const string& filename) } #endif +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void RomInfoWidget::handleMouseUp(int x, int y, MouseButton b, int clickCount) +{ + if(isEnabled() && x >= 0 && x < _w && y >= 0 && y < _h) + { + clearFlags(Widget::FLAG_HILITED); + sendCommand(kClickedCmd, 0, _id); + } +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void RomInfoWidget::drawWidget(bool hilite) { @@ -261,8 +272,17 @@ void RomInfoWidget::drawWidget(bool hilite) if(ypos + _font.getLineHeight() + _font.getFontHeight() > _h + _y ) break; } - int lines = s.drawString(_font, info, xpos, ypos, _w - 16, _font.getFontHeight() * 3, - _textcolor); + + int lines; + if(BSPF::startsWithIgnoreCase(info, "Link: ")) + { + lines = s.drawString(_font, info, xpos, ypos, _w - 16, _font.getFontHeight() * 3, + _textcolor, TextAlign::Left, 0, true, kNone, + 6, 2000, hilite); + } + else + lines = s.drawString(_font, info, xpos, ypos, _w - 16, _font.getFontHeight() * 3, + _textcolor); ypos += _font.getLineHeight() + (lines - 1) * _font.getFontHeight(); } clearDirty(); diff --git a/src/gui/RomInfoWidget.hxx b/src/gui/RomInfoWidget.hxx index f21f85e3b..3cb1392b9 100644 --- a/src/gui/RomInfoWidget.hxx +++ b/src/gui/RomInfoWidget.hxx @@ -27,8 +27,13 @@ namespace Common { #include "Widget.hxx" #include "bspf.hxx" -class RomInfoWidget : public Widget +class RomInfoWidget : public Widget, public CommandSender { + public: + enum { + kClickedCmd = 'RIcl' + }; + public: RomInfoWidget(GuiObject *boss, const GUI::Font& font, int x, int y, int w, int h, @@ -41,8 +46,11 @@ class RomInfoWidget : public Widget void resetSurfaces(); + const string& getUrl() const { return myProperties.get(PropType::Cart_Url); } + protected: void drawWidget(bool hilite) override; + void handleMouseUp(int x, int y, MouseButton b, int clickCount) override; private: void parseProperties(const FilesystemNode& node);