mirror of https://github.com/stella-emu/stella.git
add display format auto-detection from filename (resolves #561)
This commit is contained in:
parent
c1781e5492
commit
792cbb4ffa
|
@ -152,6 +152,8 @@
|
|||
|
||||
* Added FC bankswitching for Amiga's Power Play Arcade Video Game Album
|
||||
|
||||
* Added auto-detection of display format based on filename.
|
||||
|
||||
* Auto-detection of bankswitch scheme by file extension now includes
|
||||
more human-readable formats (not restricted to DOS 3-char length).
|
||||
See the documentation for the new names.
|
||||
|
|
|
@ -300,6 +300,7 @@
|
|||
including <a href="http://thumbulator.blogspot.ca">partial emulation of the ARM processor</a></li>
|
||||
<li>Supports cartridge autodetection for almost all bankswitching schemes</li>
|
||||
<li>Supports using ROM filename extensions to force specific bankswitching schemes</li>
|
||||
<li>Supports using ROM filename to force specific display formats</li>
|
||||
<li>Supports Supercharger single-load and multi-load games</li>
|
||||
<li>Supports ROMs stored in ZIP and GZIP format, as well as the usual raw A26/BIN/ROM formats</li>
|
||||
<li>Supports property file for setting the properties associated with games</li>
|
||||
|
@ -3723,7 +3724,7 @@ Ms Pac-Man (Stella extended codes):
|
|||
The value of this property must be either <b>Auto</b> or one of the following
|
||||
(for more information about bank-switching see Kevin Horton's <a href="http://kevtris.org/files/sizes.txt">2600 bankswitching
|
||||
document</a> or the documentation in each cartridge's source code file) types. Types marked
|
||||
as (¹) do not currently have reliable auto-detection, those marked as (²)
|
||||
as (¹) do currently have no reliable auto-detection, those marked as (²)
|
||||
are not fully supported in the debugger:
|
||||
<table cellpadding="2" border="1">
|
||||
<tr><th> Type </th><th>Description</th><th>File Extension<br>(to force type)</th></tr>
|
||||
|
@ -3790,8 +3791,18 @@ Ms Pac-Man (Stella extended codes):
|
|||
<tr>
|
||||
<td VALIGN="TOP"><i>Display.Format:</i></td>
|
||||
<td>Indicates the television format the game was designed for. The value
|
||||
must be <b>Auto</b>, <b>NTSC</b>, <b>PAL</b>, <b>SECAM</b>, <b>NTSC50</b>,
|
||||
<b>PAL60</b> or <b>SECAM60</b>.</td>
|
||||
must be <b>Auto</b> or one of the following. Types marked as (¹)
|
||||
do currently have no reliable auto-detection. A format can be enforced
|
||||
by using one of the following pattern in the filename.
|
||||
<table cellpadding="2" border="1">
|
||||
<tr><th> Format </th><th>Filename Pattern (to force format)</th></tr>
|
||||
<tr><td>NTSC</td><td>NTSC, NTSC60, NTSC 60, NTSC-60</td></tr>
|
||||
<tr><td>PAL</td><td>PAL, PAL50, PAL 50, PAL-50</td></tr>
|
||||
<tr><td>SECAM ¹</td><td>SECAM, SECAM50, SECAM 50, SECAM-50</td></tr>
|
||||
<tr><td>NTSC50 ¹</td><td>NTSC50, NTSC 50, NTSC-50</td></tr>
|
||||
<tr><td>PAL60 ¹</td><td>PAL60, PAL 60, PAL-60</td></tr>
|
||||
<tr><td>SECAM60 ¹</td><td>SECAM60, SECAM 60, SECAM-60</td></tr>
|
||||
</table></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
|
|
@ -119,6 +119,9 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
|
|||
string autodetected = "";
|
||||
myDisplayFormat = myProperties.get(PropType::Display_Format);
|
||||
|
||||
if (myDisplayFormat == "AUTO")
|
||||
myDisplayFormat = formatFromFilename();
|
||||
|
||||
// Add the real controllers for this system
|
||||
// This must be done before the debugger is initialized
|
||||
const string& md5 = myProperties.get(PropType::Cart_MD5);
|
||||
|
@ -149,33 +152,28 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
|
|||
if(myDisplayFormat == "NTSC")
|
||||
{
|
||||
myCurrentFormat = 1;
|
||||
myConsoleTiming = ConsoleTiming::ntsc;
|
||||
}
|
||||
else if(myDisplayFormat == "PAL")
|
||||
{
|
||||
myCurrentFormat = 2;
|
||||
myConsoleTiming = ConsoleTiming::pal;
|
||||
}
|
||||
else if(myDisplayFormat == "SECAM")
|
||||
{
|
||||
myCurrentFormat = 3;
|
||||
myConsoleTiming = ConsoleTiming::secam;
|
||||
}
|
||||
else if(myDisplayFormat == "NTSC50")
|
||||
{
|
||||
myCurrentFormat = 4;
|
||||
myConsoleTiming = ConsoleTiming::ntsc;
|
||||
}
|
||||
else if(myDisplayFormat == "PAL60")
|
||||
{
|
||||
myCurrentFormat = 5;
|
||||
myConsoleTiming = ConsoleTiming::pal;
|
||||
}
|
||||
else if(myDisplayFormat == "SECAM60")
|
||||
{
|
||||
myCurrentFormat = 6;
|
||||
myConsoleTiming = ConsoleTiming::secam;
|
||||
}
|
||||
setConsoleTiming();
|
||||
|
||||
setTIAProperties();
|
||||
|
||||
|
@ -213,6 +211,24 @@ Console::~Console()
|
|||
myOSystem.sound().close();
|
||||
}
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Console::setConsoleTiming()
|
||||
{
|
||||
if (myDisplayFormat == "NTSC" || myDisplayFormat == "NTSC50")
|
||||
{
|
||||
myConsoleTiming = ConsoleTiming::ntsc;
|
||||
}
|
||||
else if (myDisplayFormat == "PAL" || myDisplayFormat == "PAL60")
|
||||
{
|
||||
myConsoleTiming = ConsoleTiming::pal;
|
||||
}
|
||||
else if (myDisplayFormat == "SECAM" || myDisplayFormat == "SECAM60")
|
||||
{
|
||||
myConsoleTiming = ConsoleTiming::secam;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Console::autodetectFrameLayout(bool reset)
|
||||
{
|
||||
|
@ -255,6 +271,48 @@ void Console::redetectFrameLayout()
|
|||
initializeAudio();
|
||||
}
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string Console::formatFromFilename() const
|
||||
{
|
||||
std::map<string, string> Pattern = {
|
||||
{"NTSC50", "NTSC50"}, {"NTSC 50", "NTSC50"}, {"NTSC-50", "NTSC50"},
|
||||
{"PAL60", "PAL60"}, {"PAL 60", "PAL60"}, {"PAL-60", "PAL60"},
|
||||
{"SECAM60", "SECAM60"}, {"SECAM 60", "SECAM60"}, {"SECAM-60", "SECAM60"},
|
||||
{"NTSC60", "NTSC" }, {"NTSC", "NTSC"}, // also finds "NTSC 60" and "NTSC-60"
|
||||
{"PAL50", "PAL" }, {"PAL", "PAL"}, // also finds "PAL 50" and "PAL-50"
|
||||
{"SECAM50", "SECAM"}, {"SECAM", "SECAM"}, // also finds "SECAM 50" and "SECAM-50"
|
||||
};
|
||||
string filename = myOSystem.romFile().getNameWithExt(""); // get filename *without* extension
|
||||
|
||||
for (const auto& item : Pattern)
|
||||
{
|
||||
size_t pos = filename.find(item.first);
|
||||
if (pos != string::npos)
|
||||
{
|
||||
// avoid false positives
|
||||
if (pos == filename.length() - (item.first).length() || // pattern at the very end
|
||||
((pos == 0 || isWhiteSpace(filename.at(pos - 1))) && // pattern within withspaces
|
||||
isWhiteSpace(filename.at(pos + (item.first).length()))))
|
||||
return item.second;
|
||||
}
|
||||
}
|
||||
// nothing found
|
||||
return "AUTO";
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Console::isWhiteSpace(const char s) const
|
||||
{
|
||||
const string WHITESPACES = " _-()[]<>";
|
||||
|
||||
for (size_t i = 0; i < WHITESPACES.length(); ++i)
|
||||
if (s == WHITESPACES[i])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Console::save(Serializer& out) const
|
||||
{
|
||||
|
@ -331,13 +389,20 @@ void Console::setFormat(uInt32 format)
|
|||
{
|
||||
if (myFormatAutodetected) return;
|
||||
|
||||
string oldDisplayFormat = myDisplayFormat;
|
||||
redetectFrameLayout();
|
||||
myFormatAutodetected = true;
|
||||
myDisplayFormat = formatFromFilename();
|
||||
if (myDisplayFormat == "AUTO")
|
||||
{
|
||||
redetectFrameLayout();
|
||||
myFormatAutodetected = true;
|
||||
autodetected = "*";
|
||||
message = "Auto-detect mode: " + myDisplayFormat;
|
||||
}
|
||||
else
|
||||
{
|
||||
message = myDisplayFormat + " mode";
|
||||
}
|
||||
saveformat = "AUTO";
|
||||
autodetected = "*";
|
||||
myConsoleTiming = myDisplayFormat == "PAL" ? ConsoleTiming::pal : ConsoleTiming::ntsc;
|
||||
message = "Auto-detect mode: " + myDisplayFormat;
|
||||
setConsoleTiming();
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
|
|
|
@ -327,6 +327,11 @@ class Console : public Serializable, public ConsoleIO
|
|||
void setTIAProperties();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Define console timing based on current display format
|
||||
*/
|
||||
void setConsoleTiming();
|
||||
|
||||
/**
|
||||
* Dry-run the emulation and detect the frame layout (PAL / NTSC).
|
||||
*/
|
||||
|
@ -337,6 +342,19 @@ class Console : public Serializable, public ConsoleIO
|
|||
*/
|
||||
void redetectFrameLayout();
|
||||
|
||||
/**
|
||||
* Determine display format by filename
|
||||
* Returns "AUTO" if nothing is found
|
||||
*/
|
||||
string formatFromFilename() const;
|
||||
|
||||
/**
|
||||
Check if the given character is a whitespace.
|
||||
@param s Character to check
|
||||
@return True if whitespace character
|
||||
*/
|
||||
bool isWhiteSpace(const char s) const;
|
||||
|
||||
/**
|
||||
Create the audio queue
|
||||
*/
|
||||
|
|
|
@ -59,7 +59,7 @@ void KidVid::update()
|
|||
myBlockIdx = KVBLOCKBITS;
|
||||
myBlock = 0;
|
||||
openSampleFile();
|
||||
cerr << "myTape = " << myTape << endl;
|
||||
//cerr << "myTape = " << myTape << endl;
|
||||
}
|
||||
else if(myEvent.get(Event::KeyboardOne2))
|
||||
{
|
||||
|
@ -68,7 +68,7 @@ cerr << "myTape = " << myTape << endl;
|
|||
myBlockIdx = KVBLOCKBITS;
|
||||
myBlock = 0;
|
||||
openSampleFile();
|
||||
cerr << "myTape = " << myTape << endl;
|
||||
//cerr << "myTape = " << myTape << endl;
|
||||
}
|
||||
else if(myEvent.get(Event::KeyboardOne3))
|
||||
{
|
||||
|
@ -76,13 +76,13 @@ cerr << "myTape = " << myTape << endl;
|
|||
{
|
||||
myTape = 4;
|
||||
myIdx = KVBLOCKBITS;
|
||||
cerr << "myTape = " << myTape << endl;
|
||||
//cerr << "myTape = " << myTape << endl;
|
||||
}
|
||||
else /* no, Smurf Save The Day */
|
||||
{
|
||||
myTape = 1;
|
||||
myIdx = 0;
|
||||
cerr << "myTape = " << myTape << endl;
|
||||
//cerr << "myTape = " << myTape << endl;
|
||||
}
|
||||
myBlockIdx = KVBLOCKBITS;
|
||||
myBlock = 0;
|
||||
|
|
|
@ -438,7 +438,11 @@ void GameInfoDialog::loadEmulationProperties(const Properties& props)
|
|||
if(instance().hasConsole() && myFormat->getSelectedTag().toString() == "AUTO")
|
||||
{
|
||||
const string& format = instance().console().about().DisplayFormat;
|
||||
string label = format.substr(0, format.length() - 1);
|
||||
string label;
|
||||
if (format.at(format.length() - 1) == '*')
|
||||
label = format.substr(0, format.length() - 1);
|
||||
else
|
||||
label = format;
|
||||
myFormatDetected->setLabel(label + " detected");
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue