More work on the CheatManager. Stella now reads from a user-specific

'stella.cht' file, where each line/record consists of a ROM md5sum
and a comma-separated list of cheats.  Each cheat is specified as a
colon-separated string, defined as "NAME:CODE:ENABLE".


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@895 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2005-11-27 00:17:16 +00:00
parent 8e5cb83f60
commit ac914c699a
4 changed files with 185 additions and 33 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: CheatManager.cxx,v 1.1 2005-11-11 21:44:18 stephena Exp $ // $Id: CheatManager.cxx,v 1.2 2005-11-27 00:17:16 stephena Exp $
//============================================================================ //============================================================================
#include "OSystem.hxx" #include "OSystem.hxx"
@ -33,16 +33,9 @@ CheatManager::CheatManager(OSystem* osystem)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CheatManager::~CheatManager() CheatManager::~CheatManager()
{ {
// Don't delete the items from per-frame list, since it will be done in saveAllCheats();
// the following loop myCheatMap.clear();
myPerFrameList.clear(); clear();
for(unsigned int i = 0; i < myCheatList.size(); i++)
{
cerr << myCheatList[i]->name() << ": " << myCheatList[i]->code() << endl;
delete myCheatList[i];
}
myCheatList.clear();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -132,10 +125,58 @@ void CheatManager::addPerFrame(Cheat* cheat, bool enable)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheatManager::parse(const string& cheats) void CheatManager::parse(const string& cheats)
{ {
// FIXME - deal with comma-separated cheats
cerr << "parsing cheats: " << cheats << endl; cerr << "parsing cheats: " << cheats << endl;
add("TEST", cheats, true); StringList s;
string::size_type lastPos = cheats.find_first_not_of(",", 0);
string::size_type pos = cheats.find_first_of(",", lastPos);
string cheat, name, code;
// Split string by comma, getting each cheat
while(string::npos != pos || string::npos != lastPos)
{
// Get the next cheat
cheat = cheats.substr(lastPos, pos - lastPos);
// Split cheat by colon, separating each part
string::size_type lastColonPos = cheat.find_first_not_of(":", 0);
string::size_type colonPos = cheat.find_first_of(":", lastColonPos);
while(string::npos != colonPos || string::npos != lastColonPos)
{
s.push_back(cheat.substr(lastColonPos, colonPos - lastColonPos));
lastColonPos = cheat.find_first_not_of(":", colonPos);
colonPos = cheat.find_first_of(":", lastColonPos);
}
// Account for variable number of items specified for cheat
switch(s.size())
{
case 1:
name = s[0];
code = name;
add(name, code, true);
break;
case 2:
name = s[0];
code = s[1];
add(name, code, true);
break;
case 3:
name = s[0];
code = s[1];
add(name, code, s[2] == "1");
break;
}
s.clear();
lastPos = cheats.find_first_not_of(",", pos);
pos = cheats.find_first_of(",", lastPos);
}
// add("TEST", cheats, true);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -153,3 +194,81 @@ void CheatManager::enable(const string& code, bool enable)
} }
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheatManager::loadAllCheats()
{
string cheatfile = myOSystem->baseDir() + BSPF_PATH_SEPARATOR + "stella.cht";
ifstream in(cheatfile.c_str(), ios::in);
if(!in)
return;
string line, md5, cheat;
string::size_type one, two, three, four;
// Loop reading cheats
while(getline(in, line))
{
if(line.length() == 0)
continue;
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 ms5sum and associated cheats
md5 = line.substr(one + 1, two - one - 1);
cheat = line.substr(three + 1, four - three - 1);
myCheatMap.insert(make_pair(md5, cheat));
}
in.close();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheatManager::saveAllCheats()
{
string cheatfile = myOSystem->baseDir() + BSPF_PATH_SEPARATOR + "stella.cht";
ofstream out(cheatfile.c_str(), ios::out);
if(!out)
return;
CheatCodeMap::iterator iter;
for(iter = myCheatMap.begin(); iter != myCheatMap.end(); ++iter)
out << "\"" << iter->first << "\" "
<< "\"" << iter->second << "\""
<< endl;
out.close();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheatManager::loadCheats(const string& md5sum)
{
clear();
CheatCodeMap::iterator iter = myCheatMap.find(md5sum);
if(iter == myCheatMap.end())
return;
parse(iter->second);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheatManager::clear()
{
// Don't delete the items from per-frame list, since it will be done in
// the following loop
myPerFrameList.clear();
for(unsigned int i = 0; i < myCheatList.size(); i++)
delete myCheatList[i];
myCheatList.clear();
}

View File

@ -13,12 +13,14 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: CheatManager.hxx,v 1.1 2005-11-11 21:44:18 stephena Exp $ // $Id: CheatManager.hxx,v 1.2 2005-11-27 00:17:16 stephena Exp $
//============================================================================ //============================================================================
#ifndef CHEAT_MANAGER_HXX #ifndef CHEAT_MANAGER_HXX
#define CHEAT_MANAGER_HXX #define CHEAT_MANAGER_HXX
#include <map>
#include "OSystem.hxx" #include "OSystem.hxx"
#include "bspf.hxx" #include "bspf.hxx"
#include "Array.hxx" #include "Array.hxx"
@ -26,6 +28,7 @@
#include "Cheat.hxx" #include "Cheat.hxx"
typedef GUI::Array<Cheat*> CheatList; typedef GUI::Array<Cheat*> CheatList;
typedef map<string,string> CheatCodeMap;
/** /**
This class provides an interface for performing all cheat operations This class provides an interface for performing all cheat operations
@ -33,7 +36,7 @@ typedef GUI::Array<Cheat*> CheatList;
the list of all cheats currently in use. the list of all cheats currently in use.
@author Stephen Anthony @author Stephen Anthony
@version $Id: CheatManager.hxx,v 1.1 2005-11-11 21:44:18 stephena Exp $ @version $Id: CheatManager.hxx,v 1.2 2005-11-27 00:17:16 stephena Exp $
*/ */
class CheatManager class CheatManager
{ {
@ -77,21 +80,40 @@ class CheatManager
*/ */
void enable(const string& code, bool enable); void enable(const string& code, bool enable);
/**
Clear all lists of all cheats.
*/
void clear();
/** /**
Returns the per-frame cheatlist (needed to evaluate cheats each frame) Returns the per-frame cheatlist (needed to evaluate cheats each frame)
*/ */
const CheatList& perFrame() { return myPerFrameList; } const CheatList& perFrame() { return myPerFrameList; }
/**
Load all cheats (for all ROMs) from disk to internal database.
*/
void loadAllCheats();
/**
Save all cheats (for all ROMs) in internal database to disk.
*/
void saveAllCheats();
/**
Load cheats for ROM with given MD5sum to cheatlist(s).
*/
void loadCheats(const string& md5sum);
private:
/**
Clear all per-ROM cheats lists.
*/
void clear();
private: private:
OSystem* myOSystem; OSystem* myOSystem;
CheatList myCheatList; CheatList myCheatList;
CheatList myPerFrameList; CheatList myPerFrameList;
CheatCodeMap myCheatMap;
string myCheatFile;
}; };
#endif #endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: mainSDL.cxx,v 1.54 2005-11-12 22:04:57 stephena Exp $ // $Id: mainSDL.cxx,v 1.55 2005-11-27 00:17:16 stephena Exp $
//============================================================================ //============================================================================
#include <fstream> #include <fstream>
@ -208,6 +208,20 @@ int main(int argc, char* argv[])
theOSystem->createLauncher(); theOSystem->createLauncher();
else else
{ {
#ifdef CHEATCODE_SUPPORT
// Create internal cheat database for all ROMs
theOSystem->cheat().loadAllCheats();
// Set up any cheeetah code that was on the command line
// (and remove the key from the settings, so they won't get set again)
string cheats = theOSystem->settings().getString("cheat");
if(cheats != "")
{
theOSystem->cheat().parse(cheats);
theOSystem->settings().setString("cheat", "", false);
}
#endif
theOSystem->createConsole(romfile); theOSystem->createConsole(romfile);
if(theOSystem->settings().getBool("holdreset")) if(theOSystem->settings().getBool("holdreset"))
@ -219,17 +233,6 @@ int main(int argc, char* argv[])
if(theOSystem->settings().getBool("holdbutton0")) if(theOSystem->settings().getBool("holdbutton0"))
theOSystem->eventHandler().handleEvent(Event::JoystickZeroFire, 1); theOSystem->eventHandler().handleEvent(Event::JoystickZeroFire, 1);
#ifdef CHEATCODE_SUPPORT
// Set up any cheeetah code that was on the command line
// (and remove the key from the settings, so they won't get set again)
string cheats = theOSystem->settings().getString("cheat");
if(cheats != "")
{
theOSystem->cheat().parse(cheats);
theOSystem->settings().setString("cheat", "", false);
}
#endif
#ifdef DEVELOPER_SUPPORT #ifdef DEVELOPER_SUPPORT
Debugger& dbg = theOSystem->debugger(); Debugger& dbg = theOSystem->debugger();

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Console.cxx,v 1.74 2005-10-19 00:59:51 stephena Exp $ // $Id: Console.cxx,v 1.75 2005-11-27 00:17:16 stephena Exp $
//============================================================================ //============================================================================
#include <assert.h> #include <assert.h>
@ -55,6 +55,10 @@
#include "Debugger.hxx" #include "Debugger.hxx"
#endif #endif
#ifdef CHEATCODE_SUPPORT
#include "CheatManager.hxx"
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Console::Console(const uInt8* image, uInt32 size, const string& md5, Console::Console(const uInt8* image, uInt32 size, const string& md5,
OSystem* osystem) OSystem* osystem)
@ -211,6 +215,10 @@ Console::Console(const uInt8* image, uInt32 size, const string& md5,
myOSystem->debugger().setConsole(this); myOSystem->debugger().setConsole(this);
myOSystem->debugger().initialize(); myOSystem->debugger().initialize();
#endif #endif
#ifdef CHEATCODE_SUPPORT
myOSystem->cheat().loadCheats(md5);
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -