atari_py/ale_interface/src/emucore/Props.cxx (246 lines of code) (raw):
//============================================================================
//
// 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-2007 by Bradford W. Mott and the Stella team
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Props.cxx,v 1.20 2007/02/06 23:34:33 stephena Exp $
//============================================================================
#include <cctype>
#include <algorithm>
#include <sstream>
#include <string>
using namespace std;
#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 {
static std::string EmptyString("");
return EmptyString;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Properties::set(PropertyType key, const string& value)
{
if(key >= 0 && key < LastPropType)
{
myProperties[key] = value;
switch(key)
{
case Cartridge_Sound:
case Cartridge_Type:
case Console_LeftDifficulty:
case Console_RightDifficulty:
case Console_TelevisionType:
case Console_SwapPorts:
case Controller_Left:
case Controller_Right:
case Controller_SwapPaddles:
case Display_Format:
case Display_Phosphor:
case Emulation_HmoveBlanks:
{
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();
string line, key, value;
string::size_type one, two, three, four, garbage;
// Loop reading properties
while(getline(in, line))
{
// Strip all tabs from the line
while((garbage = line.find("\t")) != string::npos)
line.erase(garbage, 1);
// Ignore commented and empty lines
if((line.length() == 0) || (line[0] == ';'))
continue;
// End of this record
if(line == "\"\"")
break;
one = line.find("\"", 0);
two = line.find("\"", one + 1);
three = line.find("\"", two + 1);
four = line.find("\"", three + 1);
// Invalid line if it doesn't contain 4 quotes
if((one == string::npos) || (two == string::npos) ||
(three == string::npos) || (four == string::npos))
break;
// Otherwise get the key and value
key = line.substr(one + 1, two - one - 1);
value = line.substr(three + 1, four - three - 1);
// 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
{
cerr << get(Cartridge_MD5) << "|"
<< get(Cartridge_Name) << "|"
<< get(Cartridge_Rarity) << "|"
<< get(Cartridge_Manufacturer) << "|"
<< get(Cartridge_Note)
<< 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;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* Properties::ourDefaultProperties[LastPropType] = {
"", // Cartridge.MD5
"", // Cartridge.Manufacturer
"", // Cartridge.ModelNo
"Untitled", // Cartridge.Name
"", // Cartridge.Note
"", // Cartridge.Rarity
"MONO", // Cartridge.Sound
"AUTO-DETECT", // Cartridge.Type
"B", // Console.LeftDifficulty
"B", // Console.RightDifficulty
"COLOR", // Console.TelevisionType
"NO", // Console.SwapPorts
"JOYSTICK", // Controller.Left
"JOYSTICK", // Controller.Right
"NO", // Controller.SwapPaddles
"AUTO-DETECT", // Display.Format
"34", // Display.YStart
"210", // Display.Height
"NO", // Display.Phosphor
"77", // Display.PPBlend
"YES" // Emulation.HmoveBlanks
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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",
"Display.Format",
"Display.YStart",
"Display.Height",
"Display.Phosphor",
"Display.PPBlend",
"Emulation.HmoveBlanks"
};