2001-12-27 19:54:36 +00:00
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
//
|
2005-06-16 01:11:29 +00:00
|
|
|
// Copyright (c) 1995-2005 by Bradford W. Mott and the Stella team
|
2001-12-27 19:54:36 +00:00
|
|
|
//
|
|
|
|
// See the file "license" for information on usage and redistribution of
|
|
|
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
|
|
//
|
2005-06-16 01:11:29 +00:00
|
|
|
// $Id: Props.cxx,v 1.10 2005-06-16 01:11:28 stephena Exp $
|
2001-12-27 19:54:36 +00:00
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
#include "Props.hxx"
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
Properties::Properties(const Properties* defaults)
|
|
|
|
{
|
|
|
|
myDefaults = defaults;
|
|
|
|
myCapacity = 16;
|
|
|
|
myProperties = new Property[myCapacity];
|
|
|
|
mySize = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
Properties::Properties(const Properties& properties)
|
|
|
|
{
|
|
|
|
copy(properties);
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
Properties::~Properties()
|
|
|
|
{
|
|
|
|
// Free the properties array
|
|
|
|
delete[] myProperties;
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
string Properties::get(const string& key) const
|
|
|
|
{
|
|
|
|
// Try to find the named property and answer its value
|
|
|
|
for(uInt32 i = 0; i < mySize; ++i)
|
|
|
|
{
|
|
|
|
if(key == myProperties[i].key)
|
|
|
|
{
|
|
|
|
return myProperties[i].value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Oops, property wasn't found so ask defaults if we have one
|
|
|
|
if(myDefaults != 0)
|
|
|
|
{
|
|
|
|
// Ask the default properties object to find the key
|
|
|
|
return myDefaults->get(key);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// No default properties object so just return the empty string
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void Properties::set(const string& key, const string& value)
|
|
|
|
{
|
|
|
|
// See if the property already exists
|
|
|
|
for(uInt32 i = 0; i < mySize; ++i)
|
|
|
|
{
|
|
|
|
if(key == myProperties[i].key)
|
|
|
|
{
|
|
|
|
myProperties[i].value = value;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// See if the array needs to be resized
|
|
|
|
if(mySize == myCapacity)
|
|
|
|
{
|
|
|
|
// Yes, so we'll make the array twice as large
|
|
|
|
Property* newProperties = new Property[myCapacity * 2];
|
|
|
|
|
|
|
|
for(uInt32 i = 0; i < mySize; ++i)
|
|
|
|
{
|
|
|
|
newProperties[i] = myProperties[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
delete[] myProperties;
|
|
|
|
|
|
|
|
myProperties = newProperties;
|
|
|
|
myCapacity *= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add new property to the array
|
|
|
|
myProperties[mySize].key = key;
|
|
|
|
myProperties[mySize].value = value;
|
|
|
|
|
|
|
|
++mySize;
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void Properties::load(istream& in)
|
|
|
|
{
|
|
|
|
// Empty my property array
|
|
|
|
mySize = 0;
|
|
|
|
|
2002-01-08 17:11:32 +00:00
|
|
|
string line, key, value;
|
2005-05-12 18:45:21 +00:00
|
|
|
string::size_type one, two, three, four, garbage;
|
2002-01-08 17:11:32 +00:00
|
|
|
|
2001-12-27 19:54:36 +00:00
|
|
|
// Loop reading properties
|
2002-01-08 17:11:32 +00:00
|
|
|
while(getline(in, line))
|
2001-12-27 19:54:36 +00:00
|
|
|
{
|
2002-01-08 17:11:32 +00:00
|
|
|
// Strip all tabs from the line
|
|
|
|
while((garbage = line.find("\t")) != string::npos)
|
|
|
|
line.erase(garbage, 1);
|
2001-12-27 19:54:36 +00:00
|
|
|
|
2002-01-08 17:11:32 +00:00
|
|
|
// Ignore commented and empty lines
|
|
|
|
if((line.length() == 0) || (line[0] == ';'))
|
|
|
|
continue;
|
2001-12-27 19:54:36 +00:00
|
|
|
|
2002-01-08 17:11:32 +00:00
|
|
|
// End of this record
|
|
|
|
if(line == "\"\"")
|
2001-12-27 19:54:36 +00:00
|
|
|
break;
|
|
|
|
|
2002-01-08 17:11:32 +00:00
|
|
|
one = line.find("\"", 0);
|
|
|
|
two = line.find("\"", one + 1);
|
|
|
|
three = line.find("\"", two + 1);
|
|
|
|
four = line.find("\"", three + 1);
|
2001-12-27 19:54:36 +00:00
|
|
|
|
2002-01-08 17:11:32 +00:00
|
|
|
// 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);
|
2001-12-27 19:54:36 +00:00
|
|
|
|
|
|
|
// Set the property
|
|
|
|
set(key, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void Properties::save(ostream& out)
|
|
|
|
{
|
|
|
|
// Write out each of the key and value pairs
|
|
|
|
for(uInt32 i = 0; i < mySize; ++i)
|
|
|
|
{
|
2004-07-28 23:54:39 +00:00
|
|
|
// Try to save some space by only saving the items that differ from default
|
|
|
|
if(myProperties[i].value != myDefaults->get(myProperties[i].key))
|
|
|
|
{
|
|
|
|
writeQuotedString(out, myProperties[i].key);
|
|
|
|
out.put(' ');
|
|
|
|
writeQuotedString(out, myProperties[i].value);
|
|
|
|
out.put('\n');
|
|
|
|
}
|
2001-12-27 19:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Put a trailing null string so we know when to stop reading
|
|
|
|
writeQuotedString(out, "");
|
|
|
|
out.put('\n');
|
2002-11-11 02:49:02 +00:00
|
|
|
out.put('\n');
|
2001-12-27 19:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
// Free the properties array
|
|
|
|
delete[] myProperties;
|
|
|
|
|
|
|
|
// Now, make myself a copy of the given object
|
|
|
|
copy(properties);
|
|
|
|
}
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void Properties::copy(const Properties& properties)
|
|
|
|
{
|
|
|
|
// Remember the defaults to use
|
|
|
|
myDefaults = properties.myDefaults;
|
|
|
|
|
|
|
|
// Create an array of the same size as properties
|
|
|
|
myCapacity = properties.myCapacity;
|
|
|
|
myProperties = new Property[myCapacity];
|
|
|
|
|
|
|
|
// Now, copy each property from properties
|
|
|
|
mySize = properties.mySize;
|
|
|
|
for(uInt32 i = 0; i < mySize; ++i)
|
|
|
|
{
|
|
|
|
myProperties[i] = properties.myProperties[i];
|
|
|
|
}
|
|
|
|
}
|
2002-11-09 23:29:51 +00:00
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void Properties::merge(const Properties& properties)
|
|
|
|
{
|
|
|
|
// Merge each property from properties if it isn't -1
|
|
|
|
for(uInt32 i = 0; i < properties.mySize; ++i)
|
|
|
|
{
|
|
|
|
if(properties.myProperties[i].value != "-1")
|
|
|
|
{
|
|
|
|
cerr << "Properties::merge ==> changing " << properties.myProperties[i].key
|
|
|
|
<< " from value " << get(properties.myProperties[i].key) << " to "
|
|
|
|
<< properties.myProperties[i].value << endl;
|
|
|
|
|
|
|
|
set(properties.myProperties[i].key, properties.myProperties[i].value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-07-05 00:53:48 +00:00
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void Properties::print()
|
|
|
|
{
|
Changed some things wrt DEVELOPER_SUPPORT. The only extra things which are
now activated when Stella is built with DEVELOPER_SUPPORT is the ability
to change Xstart, Ystart, Width, and Height. Specifically, the ability
to change NTSC/PAL mode, toggle different palettes, and save/merge changes
into the properties file is now standard in all ports, and is *not* strictly
a developer-only thing. So that means that people who use a version of
Stella compiled without DEVELOPER_SUPPORT won't really miss much (the above
features are used by very few people).
Removed the commandline arguments -Dxxx, since they haven't worked for quite
some time anyway, and I doubt that many people really use them. Besides,
there are still keyboard shortcuts to do the same thing. To any developers
who don't want to see these things disappear; the next version of Stella
will include a debugger, and _that's_ the proper place to put those things.
Removed starting and ending '|' characters from the -listrominfo output,
since parsers have an easier time when those are present only _between_
elements, not at the beginning and end.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@297 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2004-07-07 22:46:01 +00:00
|
|
|
cout << get("Cartridge.MD5") << "|"
|
2004-07-05 00:53:48 +00:00
|
|
|
<< get("Cartridge.Name") << "|"
|
|
|
|
<< get("Cartridge.Rarity") << "|"
|
2004-07-12 04:05:03 +00:00
|
|
|
<< get("Cartridge.Manufacturer") << "|"
|
Changed some things wrt DEVELOPER_SUPPORT. The only extra things which are
now activated when Stella is built with DEVELOPER_SUPPORT is the ability
to change Xstart, Ystart, Width, and Height. Specifically, the ability
to change NTSC/PAL mode, toggle different palettes, and save/merge changes
into the properties file is now standard in all ports, and is *not* strictly
a developer-only thing. So that means that people who use a version of
Stella compiled without DEVELOPER_SUPPORT won't really miss much (the above
features are used by very few people).
Removed the commandline arguments -Dxxx, since they haven't worked for quite
some time anyway, and I doubt that many people really use them. Besides,
there are still keyboard shortcuts to do the same thing. To any developers
who don't want to see these things disappear; the next version of Stella
will include a debugger, and _that's_ the proper place to put those things.
Removed starting and ending '|' characters from the -listrominfo output,
since parsers have an easier time when those are present only _between_
elements, not at the beginning and end.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@297 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2004-07-07 22:46:01 +00:00
|
|
|
<< get("Cartridge.Note")
|
2004-07-05 00:53:48 +00:00
|
|
|
<< endl;
|
|
|
|
}
|