mirror of https://github.com/stella-emu/stella.git
353 lines
9.3 KiB
C++
353 lines
9.3 KiB
C++
//============================================================================
|
|
//
|
|
// SSSS tt lll lll
|
|
// SS SS tt ll ll
|
|
// SS tttttt eeee ll ll aaaa
|
|
// SSSS tt ee ee ll ll aa
|
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
// SS SS tt ee ll ll aa aa
|
|
// SSSS ttt eeeee llll llll aaaaa
|
|
//
|
|
// Copyright (c) 1995-2014 by Bradford W. Mott, Stephen Anthony
|
|
// and the Stella Team
|
|
//
|
|
// See the file "License.txt" for information on usage and redistribution of
|
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
//
|
|
// $Id$
|
|
//============================================================================
|
|
|
|
#include <cctype>
|
|
#include <algorithm>
|
|
#include <sstream>
|
|
|
|
#include "bspf.hxx"
|
|
#include "Props.hxx"
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
Properties::Properties()
|
|
{
|
|
setDefaults();
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
Properties::Properties(const Properties& properties)
|
|
{
|
|
copy(properties);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
Properties::~Properties()
|
|
{
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
const string& Properties::get(PropertyType key) const
|
|
{
|
|
if(key >= 0 && key < LastPropType)
|
|
return myProperties[key];
|
|
else
|
|
return EmptyString;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void Properties::set(PropertyType key, const string& value)
|
|
{
|
|
if(key >= 0 && key < LastPropType)
|
|
{
|
|
myProperties[key] = value;
|
|
|
|
switch(key)
|
|
{
|
|
case Cartridge_Type:
|
|
case Display_Format:
|
|
if(BSPF_equalsIgnoreCase(myProperties[key], "AUTO-DETECT"))
|
|
myProperties[key] = "AUTO";
|
|
case Cartridge_Sound:
|
|
case Console_LeftDifficulty:
|
|
case Console_RightDifficulty:
|
|
case Console_TelevisionType:
|
|
case Console_SwapPorts:
|
|
case Controller_Left:
|
|
case Controller_Right:
|
|
case Controller_SwapPaddles:
|
|
case Controller_MouseAxis:
|
|
case Display_Phosphor:
|
|
{
|
|
transform(myProperties[key].begin(), myProperties[key].end(),
|
|
myProperties[key].begin(), (int(*)(int)) toupper);
|
|
break;
|
|
}
|
|
|
|
case Display_PPBlend:
|
|
{
|
|
int blend = atoi(myProperties[key].c_str());
|
|
if(blend < 0 || blend > 100) blend = 77;
|
|
ostringstream buf;
|
|
buf << blend;
|
|
myProperties[key] = buf.str();
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void Properties::load(istream& in)
|
|
{
|
|
setDefaults();
|
|
|
|
// Loop reading properties
|
|
string key, value;
|
|
for(;;)
|
|
{
|
|
// Get the key associated with this property
|
|
key = readQuotedString(in);
|
|
|
|
// Make sure the stream is still okay
|
|
if(!in)
|
|
return;
|
|
|
|
// A null key signifies the end of the property list
|
|
if(key == "")
|
|
break;
|
|
|
|
// Get the value associated with this property
|
|
value = readQuotedString(in);
|
|
|
|
// Make sure the stream is still okay
|
|
if(!in)
|
|
return;
|
|
|
|
// Set the property
|
|
PropertyType type = getPropertyType(key);
|
|
set(type, value);
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void Properties::save(ostream& out) const
|
|
{
|
|
// Write out each of the key and value pairs
|
|
bool changed = false;
|
|
for(int i = 0; i < LastPropType; ++i)
|
|
{
|
|
// Try to save some space by only saving the items that differ from default
|
|
if(myProperties[i] != ourDefaultProperties[i])
|
|
{
|
|
writeQuotedString(out, ourPropertyNames[i]);
|
|
out.put(' ');
|
|
writeQuotedString(out, myProperties[i]);
|
|
out.put('\n');
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if(changed)
|
|
{
|
|
// Put a trailing null string so we know when to stop reading
|
|
writeQuotedString(out, "");
|
|
out.put('\n');
|
|
out.put('\n');
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
string Properties::readQuotedString(istream& in)
|
|
{
|
|
char c;
|
|
|
|
// Read characters until we see a quote
|
|
while(in.get(c))
|
|
{
|
|
if(c == '"')
|
|
break;
|
|
}
|
|
|
|
// Read characters until we see the close quote
|
|
string s;
|
|
while(in.get(c))
|
|
{
|
|
if((c == '\\') && (in.peek() == '"'))
|
|
in.get(c);
|
|
else if((c == '\\') && (in.peek() == '\\'))
|
|
in.get(c);
|
|
else if(c == '"')
|
|
break;
|
|
else if(c == '\r')
|
|
continue;
|
|
|
|
s += c;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void Properties::writeQuotedString(ostream& out, const string& s)
|
|
{
|
|
out.put('"');
|
|
for(uInt32 i = 0; i < s.length(); ++i)
|
|
{
|
|
if(s[i] == '\\')
|
|
{
|
|
out.put('\\');
|
|
out.put('\\');
|
|
}
|
|
else if(s[i] == '\"')
|
|
{
|
|
out.put('\\');
|
|
out.put('"');
|
|
}
|
|
else
|
|
out.put(s[i]);
|
|
}
|
|
out.put('"');
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
Properties& Properties::operator = (const Properties& properties)
|
|
{
|
|
// Do the assignment only if this isn't a self assignment
|
|
if(this != &properties)
|
|
{
|
|
// Now, make myself a copy of the given object
|
|
copy(properties);
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void Properties::copy(const Properties& properties)
|
|
{
|
|
// Now, copy each property from properties
|
|
for(int i = 0; i < LastPropType; ++i)
|
|
myProperties[i] = properties.myProperties[i];
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void Properties::print() const
|
|
{
|
|
cout << get(Cartridge_MD5) << "|"
|
|
<< get(Cartridge_Name) << "|"
|
|
<< get(Cartridge_Manufacturer) << "|"
|
|
<< get(Cartridge_ModelNo) << "|"
|
|
<< get(Cartridge_Note) << "|"
|
|
<< get(Cartridge_Rarity) << "|"
|
|
<< get(Cartridge_Sound) << "|"
|
|
<< get(Cartridge_Type) << "|"
|
|
<< get(Console_LeftDifficulty) << "|"
|
|
<< get(Console_RightDifficulty)<< "|"
|
|
<< get(Console_TelevisionType) << "|"
|
|
<< get(Console_SwapPorts) << "|"
|
|
<< get(Controller_Left) << "|"
|
|
<< get(Controller_Right) << "|"
|
|
<< get(Controller_SwapPaddles) << "|"
|
|
<< get(Controller_MouseAxis) << "|"
|
|
<< get(Display_Format) << "|"
|
|
<< get(Display_YStart) << "|"
|
|
<< get(Display_Height) << "|"
|
|
<< get(Display_Phosphor) << "|"
|
|
<< get(Display_PPBlend)
|
|
<< endl;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void Properties::setDefaults()
|
|
{
|
|
for(int i = 0; i < LastPropType; ++i)
|
|
myProperties[i] = ourDefaultProperties[i];
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
PropertyType Properties::getPropertyType(const string& name)
|
|
{
|
|
for(int i = 0; i < LastPropType; ++i)
|
|
if(ourPropertyNames[i] == name)
|
|
return (PropertyType)i;
|
|
|
|
// Otherwise, indicate that the item wasn't found
|
|
return LastPropType;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void Properties::printHeader()
|
|
{
|
|
cout << "Cartridge_MD5|"
|
|
<< "Cartridge_Name|"
|
|
<< "Cartridge_Manufacturer|"
|
|
<< "Cartridge_ModelNo|"
|
|
<< "Cartridge_Note|"
|
|
<< "Cartridge_Rarity|"
|
|
<< "Cartridge_Sound|"
|
|
<< "Cartridge_Type|"
|
|
<< "Console_LeftDifficulty|"
|
|
<< "Console_RightDifficulty|"
|
|
<< "Console_TelevisionType|"
|
|
<< "Console_SwapPorts|"
|
|
<< "Controller_Left|"
|
|
<< "Controller_Right|"
|
|
<< "Controller_SwapPaddles|"
|
|
<< "Controller_MouseAxis|"
|
|
<< "Display_Format|"
|
|
<< "Display_YStart|"
|
|
<< "Display_Height|"
|
|
<< "Display_Phosphor|"
|
|
<< "Display_PPBlend"
|
|
<< endl;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
const char* Properties::ourDefaultProperties[LastPropType] = {
|
|
"", // Cartridge.MD5
|
|
"", // Cartridge.Manufacturer
|
|
"", // Cartridge.ModelNo
|
|
"Untitled", // Cartridge.Name
|
|
"", // Cartridge.Note
|
|
"", // Cartridge.Rarity
|
|
"MONO", // Cartridge.Sound
|
|
"AUTO", // Cartridge.Type
|
|
"B", // Console.LeftDifficulty
|
|
"B", // Console.RightDifficulty
|
|
"COLOR", // Console.TelevisionType
|
|
"NO", // Console.SwapPorts
|
|
"JOYSTICK", // Controller.Left
|
|
"JOYSTICK", // Controller.Right
|
|
"NO", // Controller.SwapPaddles
|
|
"AUTO", // Controller.MouseAxis
|
|
"AUTO", // Display.Format
|
|
"34", // Display.YStart
|
|
"210", // Display.Height
|
|
"NO", // Display.Phosphor
|
|
"77" // Display.PPBlend
|
|
};
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
const char* Properties::ourPropertyNames[LastPropType] = {
|
|
"Cartridge.MD5",
|
|
"Cartridge.Manufacturer",
|
|
"Cartridge.ModelNo",
|
|
"Cartridge.Name",
|
|
"Cartridge.Note",
|
|
"Cartridge.Rarity",
|
|
"Cartridge.Sound",
|
|
"Cartridge.Type",
|
|
"Console.LeftDifficulty",
|
|
"Console.RightDifficulty",
|
|
"Console.TelevisionType",
|
|
"Console.SwapPorts",
|
|
"Controller.Left",
|
|
"Controller.Right",
|
|
"Controller.SwapPaddles",
|
|
"Controller.MouseAxis",
|
|
"Display.Format",
|
|
"Display.YStart",
|
|
"Display.Height",
|
|
"Display.Phosphor",
|
|
"Display.PPBlend"
|
|
};
|