mirror of https://github.com/stella-emu/stella.git
Move highscores to DB.
This commit is contained in:
parent
3171114a47
commit
8204d0fb6e
|
@ -64,6 +64,12 @@ HighScoresManager::HighScoresManager(OSystem& osystem)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void HighScoresManager::setRepository(shared_ptr<CompositeKeyValueRepositoryAtomic> repo)
|
||||||
|
{
|
||||||
|
myHighscoreRepository = repo;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Int16 HighScoresManager::peek(uInt16 addr) const
|
Int16 HighScoresManager::peek(uInt16 addr) const
|
||||||
{
|
{
|
||||||
|
@ -559,97 +565,7 @@ Int32 HighScoresManager::fromBCD(uInt8 bcd) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void HighScoresManager::saveHighScores(const string& cartName, ScoresData& data) const
|
void HighScoresManager::saveHighScores(ScoresData& data) const
|
||||||
{
|
|
||||||
ostringstream buf;
|
|
||||||
|
|
||||||
buf << myOSystem.stateDir() << cartName << ".hs" << data.variation;
|
|
||||||
|
|
||||||
// Make sure the file can be opened for writing
|
|
||||||
FilesystemNode node(buf.str());
|
|
||||||
|
|
||||||
if(!node.isWritable())
|
|
||||||
{
|
|
||||||
buf.str("");
|
|
||||||
buf << "Can't open/save to high scores file for variation " << data.variation;
|
|
||||||
myOSystem.frameBuffer().showTextMessage(buf.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do a complete high data save
|
|
||||||
if(!save(node, data))
|
|
||||||
{
|
|
||||||
buf.str("");
|
|
||||||
buf << "Error saving high scores for variation" << data.variation;
|
|
||||||
myOSystem.frameBuffer().showTextMessage(buf.str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void HighScoresManager::loadHighScores(const string& cartName, ScoresData& data)
|
|
||||||
{
|
|
||||||
for(uInt32 r = 0; r < NUM_RANKS; ++r)
|
|
||||||
{
|
|
||||||
data.scores[r].score = 0;
|
|
||||||
data.scores[r].special = 0;
|
|
||||||
data.scores[r].name = "";
|
|
||||||
data.scores[r].date = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
ostringstream buf;
|
|
||||||
|
|
||||||
buf << myOSystem.stateDir() << cartName << ".hs" << data.variation;
|
|
||||||
|
|
||||||
FilesystemNode node(buf.str());
|
|
||||||
stringstream in;
|
|
||||||
|
|
||||||
// Make sure the file can be opened
|
|
||||||
try {
|
|
||||||
node.read(in);
|
|
||||||
}
|
|
||||||
catch(...) { return; }
|
|
||||||
|
|
||||||
bool invalid = false;
|
|
||||||
try {
|
|
||||||
string highscores;
|
|
||||||
|
|
||||||
buf.str("");
|
|
||||||
|
|
||||||
if(getline(in, highscores) && highscores.length() != 0)
|
|
||||||
{
|
|
||||||
const json hsObject = json::parse(highscores);
|
|
||||||
|
|
||||||
if(hsObject.contains(DATA))
|
|
||||||
{
|
|
||||||
const json hsData = hsObject.at(DATA);
|
|
||||||
|
|
||||||
// First test if we have a valid header
|
|
||||||
// If so, do a complete high data load
|
|
||||||
if(!hsData.contains(VERSION) || hsData.at(VERSION) != HIGHSCORE_HEADER)
|
|
||||||
buf << "Error: Incompatible high scores file for variation "
|
|
||||||
<< data.variation << ".";
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(!load(hsData, data)
|
|
||||||
|| !hsData.contains(PROPCHECK) || hsData.at(PROPCHECK) != md5Props()
|
|
||||||
|| !hsObject.contains(CHECKSUM) || hsObject.at(CHECKSUM) != MD5::hash(hsData.dump()))
|
|
||||||
invalid = true;
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
invalid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(...) { invalid = true; }
|
|
||||||
|
|
||||||
if(invalid)
|
|
||||||
buf << "Error: Invalid data in high scores file for variation " << data.variation << ".";
|
|
||||||
myOSystem.frameBuffer().showTextMessage(buf.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool HighScoresManager::save(FilesystemNode& node, const ScoresData& data) const
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -681,15 +597,64 @@ bool HighScoresManager::save(FilesystemNode& node, const ScoresData& data) const
|
||||||
hsObject[DATA] = hsData;
|
hsObject[DATA] = hsData;
|
||||||
hsObject[CHECKSUM] = MD5::hash(hsData.dump());
|
hsObject[CHECKSUM] = MD5::hash(hsData.dump());
|
||||||
|
|
||||||
stringstream ss(hsObject.dump());
|
myHighscoreRepository->save(data.md5, to_string(data.variation), hsObject.dump(2));
|
||||||
node.write(ss);
|
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
cerr << "ERROR: HighScoresManager::save() exception\n";
|
cerr << "ERROR: HighScoresManager::save() exception\n";
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void HighScoresManager::loadHighScores(ScoresData& data)
|
||||||
|
{
|
||||||
|
for(uInt32 r = 0; r < NUM_RANKS; ++r)
|
||||||
|
{
|
||||||
|
data.scores[r].score = 0;
|
||||||
|
data.scores[r].special = 0;
|
||||||
|
data.scores[r].name = "";
|
||||||
|
data.scores[r].date = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
ostringstream buf;
|
||||||
|
|
||||||
|
bool invalid = false;
|
||||||
|
try {
|
||||||
|
Variant serializedHighscore;
|
||||||
|
|
||||||
|
if(myHighscoreRepository->get(data.md5, to_string(data.variation), serializedHighscore))
|
||||||
|
{
|
||||||
|
const json hsObject = json::parse(serializedHighscore.toString());
|
||||||
|
|
||||||
|
if(hsObject.contains(DATA))
|
||||||
|
{
|
||||||
|
const json hsData = hsObject.at(DATA);
|
||||||
|
|
||||||
|
// First test if we have a valid header
|
||||||
|
// If so, do a complete high data load
|
||||||
|
if(!hsData.contains(VERSION) || hsData.at(VERSION) != HIGHSCORE_HEADER)
|
||||||
|
buf << "Error: Incompatible high scores file for variation "
|
||||||
|
<< data.variation << ".";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!load(hsData, data)
|
||||||
|
|| !hsData.contains(PROPCHECK) || hsData.at(PROPCHECK) != md5Props()
|
||||||
|
|| !hsObject.contains(CHECKSUM) || hsObject.at(CHECKSUM) != MD5::hash(hsData.dump()))
|
||||||
|
invalid = true;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
invalid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(...) { invalid = true; }
|
||||||
|
|
||||||
|
if (invalid)
|
||||||
|
buf << "Error: Invalid data in high scores file for variation " << data.variation << ".";
|
||||||
|
|
||||||
|
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -25,6 +25,8 @@ class OSystem;
|
||||||
#include "Props.hxx"
|
#include "Props.hxx"
|
||||||
#include "json_lib.hxx"
|
#include "json_lib.hxx"
|
||||||
#include "FSNode.hxx"
|
#include "FSNode.hxx"
|
||||||
|
#include "repository/CompositeKeyValueRepository.hxx"
|
||||||
|
#include "repository/CompositeKeyValueRepositoryNoop.hxx"
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
@ -95,6 +97,7 @@ class HighScoresManager
|
||||||
explicit HighScoresManager(OSystem& osystem);
|
explicit HighScoresManager(OSystem& osystem);
|
||||||
virtual ~HighScoresManager() = default;
|
virtual ~HighScoresManager() = default;
|
||||||
|
|
||||||
|
void setRepository(shared_ptr<CompositeKeyValueRepositoryAtomic> repo);
|
||||||
|
|
||||||
// check if high score data has been defined
|
// check if high score data has been defined
|
||||||
bool enabled() const;
|
bool enabled() const;
|
||||||
|
@ -147,8 +150,8 @@ class HighScoresManager
|
||||||
// Peek into memory
|
// Peek into memory
|
||||||
Int16 peek(uInt16 addr) const;
|
Int16 peek(uInt16 addr) const;
|
||||||
|
|
||||||
void saveHighScores(const string& cartName, HSM::ScoresData& scores) const;
|
void loadHighScores(HSM::ScoresData& scores);
|
||||||
void loadHighScores(const string& cartName, HSM::ScoresData& scores);
|
void saveHighScores(HSM::ScoresData& scores) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const string VARIATIONS_COUNT;
|
static const string VARIATIONS_COUNT;
|
||||||
|
@ -230,16 +233,6 @@ class HighScoresManager
|
||||||
uInt16 fromHexStr(const string& addr) const;
|
uInt16 fromHexStr(const string& addr) const;
|
||||||
Int32 fromBCD(uInt8 bcd) const;
|
Int32 fromBCD(uInt8 bcd) const;
|
||||||
|
|
||||||
/**
|
|
||||||
Saves the current high scores for this game and variation to the given file system node.
|
|
||||||
|
|
||||||
@param node The file system node to save to.
|
|
||||||
@param scores The saved high score data
|
|
||||||
|
|
||||||
@return The result of the save. True on success, false on failure.
|
|
||||||
*/
|
|
||||||
bool save(FilesystemNode& node, const HSM::ScoresData& scores) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Loads the current high scores for this game and variation from the given JSON object.
|
Loads the current high scores for this game and variation from the given JSON object.
|
||||||
|
|
||||||
|
@ -254,6 +247,9 @@ class HighScoresManager
|
||||||
// Reference to the osystem object
|
// Reference to the osystem object
|
||||||
OSystem& myOSystem;
|
OSystem& myOSystem;
|
||||||
|
|
||||||
|
shared_ptr<CompositeKeyValueRepositoryAtomic> myHighscoreRepository
|
||||||
|
= make_shared<CompositeKeyValueRepositoryNoop>();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
HighScoresManager() = delete;
|
HighScoresManager() = delete;
|
||||||
|
|
|
@ -35,7 +35,8 @@ MODULE_OBJS := \
|
||||||
src/common/repository/KeyValueRepositoryPropertyFile.o \
|
src/common/repository/KeyValueRepositoryPropertyFile.o \
|
||||||
src/common/repository/KeyValueRepositoryJsonFile.o \
|
src/common/repository/KeyValueRepositoryJsonFile.o \
|
||||||
src/common/repository/KeyValueRepositoryConfigfile.o \
|
src/common/repository/KeyValueRepositoryConfigfile.o \
|
||||||
src/common/repository/CompositeKVRJsonAdapter.o
|
src/common/repository/CompositeKVRJsonAdapter.o \
|
||||||
|
src/common/repository/CompositeKeyValueRepository.o
|
||||||
|
|
||||||
MODULE_DIRS += \
|
MODULE_DIRS += \
|
||||||
src/common
|
src/common
|
||||||
|
|
|
@ -30,10 +30,10 @@ namespace {
|
||||||
std::map<string, Variant> load() override {
|
std::map<string, Variant> load() override {
|
||||||
if (!myKvr.has(myKey)) return std::map<string, Variant>();
|
if (!myKvr.has(myKey)) return std::map<string, Variant>();
|
||||||
|
|
||||||
string serialized;
|
Variant serialized;
|
||||||
myKvr.get(myKey, serialized);
|
myKvr.get(myKey, serialized);
|
||||||
|
|
||||||
stringstream in{serialized};
|
stringstream in{serialized.toString()};
|
||||||
|
|
||||||
return KeyValueRepositoryJsonFile::load(in);
|
return KeyValueRepositoryJsonFile::load(in);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// 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-2021 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.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#include "repository/CompositeKeyValueRepository.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool CompositeKeyValueRepositoryAtomic::get(const string& key1, const string& key2, Variant& value)
|
||||||
|
{
|
||||||
|
return getAtomic(key1)->get(key2, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
shared_ptr<KeyValueRepositoryAtomic> CompositeKeyValueRepositoryAtomic::getAtomic(const string& key)
|
||||||
|
{
|
||||||
|
auto repo = get(key);
|
||||||
|
|
||||||
|
return shared_ptr<KeyValueRepositoryAtomic>(repo, repo->atomic());
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool CompositeKeyValueRepositoryAtomic::save(const string& key1, const string& key2, const Variant& value)
|
||||||
|
{
|
||||||
|
return getAtomic(key1)->save(key2, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool CompositeKeyValueRepositoryAtomic::has(const string& key1, const string& key2)
|
||||||
|
{
|
||||||
|
return getAtomic(key1)->has(key2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CompositeKeyValueRepositoryAtomic::remove(const string& key1, const string key2)
|
||||||
|
{
|
||||||
|
getAtomic(key1)->remove(key2);
|
||||||
|
}
|
|
@ -23,6 +23,8 @@
|
||||||
#include "KeyValueRepository.hxx"
|
#include "KeyValueRepository.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
|
||||||
|
class CompositeKeyValueRepositoryAtomic;
|
||||||
|
|
||||||
class CompositeKeyValueRepository
|
class CompositeKeyValueRepository
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -34,6 +36,28 @@ class CompositeKeyValueRepository
|
||||||
virtual bool has(const string& key) = 0;
|
virtual bool has(const string& key) = 0;
|
||||||
|
|
||||||
virtual void remove(const string& key) = 0;
|
virtual void remove(const string& key) = 0;
|
||||||
|
|
||||||
|
virtual CompositeKeyValueRepositoryAtomic* atomic() { return nullptr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class CompositeKeyValueRepositoryAtomic : public CompositeKeyValueRepository
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using CompositeKeyValueRepository::get;
|
||||||
|
using CompositeKeyValueRepository::remove;
|
||||||
|
using CompositeKeyValueRepository::has;
|
||||||
|
|
||||||
|
virtual bool get(const string& key1, const string& key2, Variant& value);
|
||||||
|
|
||||||
|
virtual shared_ptr<KeyValueRepositoryAtomic> getAtomic(const string& key);
|
||||||
|
|
||||||
|
virtual bool save(const string& key1, const string& key2, const Variant& value);
|
||||||
|
|
||||||
|
virtual bool has(const string& key1, const string& key2);
|
||||||
|
|
||||||
|
virtual void remove(const string& key1, const string key2);
|
||||||
|
|
||||||
|
CompositeKeyValueRepositoryAtomic* atomic() override { return this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // COMPOSITE_KEY_VALUE_REPOSITORY_HXX
|
#endif // COMPOSITE_KEY_VALUE_REPOSITORY_HXX
|
||||||
|
|
|
@ -22,9 +22,12 @@
|
||||||
#include "repository/KeyValueRepositoryNoop.hxx"
|
#include "repository/KeyValueRepositoryNoop.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
|
||||||
class CompositeKeyValueRepositoryNoop : public CompositeKeyValueRepository
|
class CompositeKeyValueRepositoryNoop : public CompositeKeyValueRepositoryAtomic
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using CompositeKeyValueRepositoryAtomic::has;
|
||||||
|
using CompositeKeyValueRepositoryAtomic::remove;
|
||||||
|
using CompositeKeyValueRepositoryAtomic::get;
|
||||||
|
|
||||||
shared_ptr<KeyValueRepository> get(const string& key) { return make_shared<KeyValueRepositoryNoop>(); }
|
shared_ptr<KeyValueRepository> get(const string& key) { return make_shared<KeyValueRepositoryNoop>(); }
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ class KeyValueRepositoryAtomic : public KeyValueRepository {
|
||||||
|
|
||||||
virtual bool has(const string& key) = 0;
|
virtual bool has(const string& key) = 0;
|
||||||
|
|
||||||
virtual bool get(const string& key, string& value) = 0;
|
virtual bool get(const string& key, Variant& value) = 0;
|
||||||
|
|
||||||
virtual bool save(const string& key, const Variant& value) = 0;
|
virtual bool save(const string& key, const Variant& value) = 0;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ class KeyValueRepositoryNoop : public KeyValueRepositoryAtomic
|
||||||
|
|
||||||
bool has(const string& key) override { return false; }
|
bool has(const string& key) override { return false; }
|
||||||
|
|
||||||
bool get(const string& key, string& value) override { return false; }
|
bool get(const string& key, Variant& value) override { return false; }
|
||||||
|
|
||||||
bool save(const std::map<string, Variant>& values) override { return false; }
|
bool save(const std::map<string, Variant>& values) override { return false; }
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ bool AbstractKeyValueRepositorySqlite::has(const string& key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool AbstractKeyValueRepositorySqlite::get(const string& key, string& value)
|
bool AbstractKeyValueRepositorySqlite::get(const string& key, Variant& value)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
SqliteStatement& stmt{stmtSelectOne(key)};
|
SqliteStatement& stmt{stmtSelectOne(key)};
|
||||||
|
|
|
@ -12,7 +12,7 @@ class AbstractKeyValueRepositorySqlite : public KeyValueRepositoryAtomic
|
||||||
|
|
||||||
bool has(const string& key) override;
|
bool has(const string& key) override;
|
||||||
|
|
||||||
bool get(const string& key, string& value) override;
|
bool get(const string& key, Variant& value) override;
|
||||||
|
|
||||||
std::map<string, Variant> load() override;
|
std::map<string, Variant> load() override;
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,11 @@
|
||||||
#include "SqliteStatement.hxx"
|
#include "SqliteStatement.hxx"
|
||||||
#include "AbstractKeyValueRepositorySqlite.hxx"
|
#include "AbstractKeyValueRepositorySqlite.hxx"
|
||||||
|
|
||||||
class CompositeKeyValueRepositorySqlite : public CompositeKeyValueRepository {
|
class CompositeKeyValueRepositorySqlite : public CompositeKeyValueRepositoryAtomic {
|
||||||
public:
|
public:
|
||||||
|
using CompositeKeyValueRepositoryAtomic::has;
|
||||||
|
using CompositeKeyValueRepositoryAtomic::remove;
|
||||||
|
using CompositeKeyValueRepositoryAtomic::get;
|
||||||
|
|
||||||
CompositeKeyValueRepositorySqlite(
|
CompositeKeyValueRepositorySqlite(
|
||||||
SqliteDatabase& db,
|
SqliteDatabase& db,
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "repository/KeyValueRepositoryConfigfile.hxx"
|
#include "repository/KeyValueRepositoryConfigfile.hxx"
|
||||||
#include "repository/KeyValueRepositoryPropertyFile.hxx"
|
#include "repository/KeyValueRepositoryPropertyFile.hxx"
|
||||||
#include "KeyValueRepositorySqlite.hxx"
|
#include "KeyValueRepositorySqlite.hxx"
|
||||||
|
#include "CompositeKeyValueRepositorySqlite.hxx"
|
||||||
#include "SqliteStatement.hxx"
|
#include "SqliteStatement.hxx"
|
||||||
#include "FSNode.hxx"
|
#include "FSNode.hxx"
|
||||||
|
|
||||||
|
@ -59,6 +60,10 @@ void StellaDb::initialize()
|
||||||
propertyRepositoryHost->initialize();
|
propertyRepositoryHost->initialize();
|
||||||
myPropertyRepositoryHost = std::move(propertyRepositoryHost);
|
myPropertyRepositoryHost = std::move(propertyRepositoryHost);
|
||||||
|
|
||||||
|
auto highscoreRepository = make_unique<CompositeKeyValueRepositorySqlite>(*myDb, "highscores", "md5", "variation", "highscore_data");
|
||||||
|
highscoreRepository->initialize();
|
||||||
|
myHighscoreRepository = std::move(highscoreRepository);
|
||||||
|
|
||||||
myPropertyRepository = make_unique<CompositeKVRJsonAdapter>(*myPropertyRepositoryHost);
|
myPropertyRepository = make_unique<CompositeKVRJsonAdapter>(*myPropertyRepositoryHost);
|
||||||
|
|
||||||
if (myDb->getUserVersion() == 0) {
|
if (myDb->getUserVersion() == 0) {
|
||||||
|
|
|
@ -33,8 +33,8 @@ class StellaDb
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
||||||
KeyValueRepositoryAtomic& settingsRepository() const { return *mySettingsRepository; }
|
KeyValueRepositoryAtomic& settingsRepository() const { return *mySettingsRepository; }
|
||||||
|
|
||||||
CompositeKeyValueRepository& propertyRepository() const { return *myPropertyRepository; }
|
CompositeKeyValueRepository& propertyRepository() const { return *myPropertyRepository; }
|
||||||
|
CompositeKeyValueRepositoryAtomic& highscoreRepository() const { return *myHighscoreRepository; }
|
||||||
|
|
||||||
const string databaseFileName() const;
|
const string databaseFileName() const;
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ class StellaDb
|
||||||
unique_ptr<KeyValueRepositoryAtomic> mySettingsRepository;
|
unique_ptr<KeyValueRepositoryAtomic> mySettingsRepository;
|
||||||
unique_ptr<KeyValueRepositoryAtomic> myPropertyRepositoryHost;
|
unique_ptr<KeyValueRepositoryAtomic> myPropertyRepositoryHost;
|
||||||
unique_ptr<CompositeKeyValueRepository> myPropertyRepository;
|
unique_ptr<CompositeKeyValueRepository> myPropertyRepository;
|
||||||
|
unique_ptr<CompositeKeyValueRepositoryAtomic> myHighscoreRepository;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // STELLA_DB_HXX
|
#endif // STELLA_DB_HXX
|
||||||
|
|
|
@ -181,6 +181,8 @@ bool OSystem::initialize(const Settings::Options& options)
|
||||||
myMessageMenu = make_unique<MessageMenu>(*this);
|
myMessageMenu = make_unique<MessageMenu>(*this);
|
||||||
myTimeMachine = make_unique<TimeMachine>(*this);
|
myTimeMachine = make_unique<TimeMachine>(*this);
|
||||||
myLauncher = make_unique<Launcher>(*this);
|
myLauncher = make_unique<Launcher>(*this);
|
||||||
|
|
||||||
|
myHighScoresManager->setRepository(getHighscoreRepository());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PNG_SUPPORT
|
#ifdef PNG_SUPPORT
|
||||||
|
@ -222,6 +224,7 @@ void OSystem::loadConfig(const Settings::Options& options)
|
||||||
|
|
||||||
mySettings->setRepository(getSettingsRepository());
|
mySettings->setRepository(getSettingsRepository());
|
||||||
myPropSet->setRepository(getPropertyRepository());
|
myPropSet->setRepository(getPropertyRepository());
|
||||||
|
|
||||||
mySettings->load(options);
|
mySettings->load(options);
|
||||||
|
|
||||||
// userDir is NOT affected by '-baseDir'and '-basedirinapp' params
|
// userDir is NOT affected by '-baseDir'and '-basedirinapp' params
|
||||||
|
|
|
@ -443,6 +443,8 @@ class OSystem
|
||||||
|
|
||||||
virtual shared_ptr<CompositeKeyValueRepository> getPropertyRepository() = 0;
|
virtual shared_ptr<CompositeKeyValueRepository> getPropertyRepository() = 0;
|
||||||
|
|
||||||
|
virtual shared_ptr<CompositeKeyValueRepositoryAtomic> getHighscoreRepository() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -42,3 +42,9 @@ shared_ptr<CompositeKeyValueRepository> OSystemStandalone::getPropertyRepository
|
||||||
{
|
{
|
||||||
return shared_ptr<CompositeKeyValueRepository>(myStellaDb, &myStellaDb->propertyRepository());
|
return shared_ptr<CompositeKeyValueRepository>(myStellaDb, &myStellaDb->propertyRepository());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
shared_ptr<CompositeKeyValueRepositoryAtomic> OSystemStandalone::getHighscoreRepository()
|
||||||
|
{
|
||||||
|
return shared_ptr<CompositeKeyValueRepositoryAtomic>(myStellaDb, &myStellaDb->highscoreRepository());
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@ class OSystemStandalone : public OSystem
|
||||||
|
|
||||||
shared_ptr<CompositeKeyValueRepository> getPropertyRepository() override;
|
shared_ptr<CompositeKeyValueRepository> getPropertyRepository() override;
|
||||||
|
|
||||||
|
shared_ptr<CompositeKeyValueRepositoryAtomic> getHighscoreRepository() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void initPersistence(FilesystemNode& basedir) override;
|
void initPersistence(FilesystemNode& basedir) override;
|
||||||
|
|
|
@ -296,7 +296,7 @@ void HighScoresDialog::saveConfig()
|
||||||
instance().settings().setValue("initials", myInitials);
|
instance().settings().setValue("initials", myInitials);
|
||||||
}
|
}
|
||||||
// save selected variation
|
// save selected variation
|
||||||
instance().highScores().saveHighScores(cartName(), myScores);
|
instance().highScores().saveHighScores(myScores);
|
||||||
if(myScores.variation == instance().highScores().variation() || myUserDefVar)
|
if(myScores.variation == instance().highScores().variation() || myUserDefVar)
|
||||||
myHighScoreSaved = true;
|
myHighScoreSaved = true;
|
||||||
}
|
}
|
||||||
|
@ -360,7 +360,7 @@ void HighScoresDialog::handleVariation(bool init)
|
||||||
{
|
{
|
||||||
myScores.variation = myVariationPopup->getSelectedTag().toInt();
|
myScores.variation = myVariationPopup->getSelectedTag().toInt();
|
||||||
|
|
||||||
instance().highScores().loadHighScores(cartName(), myScores);
|
instance().highScores().loadHighScores(myScores);
|
||||||
|
|
||||||
myEditRank = -1;
|
myEditRank = -1;
|
||||||
|
|
||||||
|
|
|
@ -55,3 +55,9 @@ shared_ptr<CompositeKeyValueRepository> OSystemLIBRETRO::getPropertyRepository()
|
||||||
{
|
{
|
||||||
return make_shared<CompositeKeyValueRepositoryNoop>();
|
return make_shared<CompositeKeyValueRepositoryNoop>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
shared_ptr<CompositeKeyValueRepositoryAtomic> OSystemLIBRETRO::getHighscoreRepository()
|
||||||
|
{
|
||||||
|
return make_shared<CompositeKeyValueRepositoryNoop>();
|
||||||
|
}
|
||||||
|
|
|
@ -53,6 +53,8 @@ class OSystemLIBRETRO : public OSystem
|
||||||
|
|
||||||
shared_ptr<CompositeKeyValueRepository> getPropertyRepository() override;
|
shared_ptr<CompositeKeyValueRepository> getPropertyRepository() override;
|
||||||
|
|
||||||
|
shared_ptr<CompositeKeyValueRepositoryAtomic> getHighscoreRepository() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void initPersistence(FilesystemNode& basedir) override;
|
void initPersistence(FilesystemNode& basedir) override;
|
||||||
|
|
|
@ -745,6 +745,7 @@
|
||||||
E0A755792244294600101889 /* CartCDFInfoWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = E0A755772244294600101889 /* CartCDFInfoWidget.cxx */; };
|
E0A755792244294600101889 /* CartCDFInfoWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = E0A755772244294600101889 /* CartCDFInfoWidget.cxx */; };
|
||||||
E0D4153C25A120340031A8D6 /* SettingsRepositoryMACOS.hxx in Headers */ = {isa = PBXBuildFile; fileRef = E0D4153A25A120340031A8D6 /* SettingsRepositoryMACOS.hxx */; };
|
E0D4153C25A120340031A8D6 /* SettingsRepositoryMACOS.hxx in Headers */ = {isa = PBXBuildFile; fileRef = E0D4153A25A120340031A8D6 /* SettingsRepositoryMACOS.hxx */; };
|
||||||
E0D4153D25A120340031A8D6 /* SettingsRepositoryMACOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = E0D4153B25A120340031A8D6 /* SettingsRepositoryMACOS.mm */; };
|
E0D4153D25A120340031A8D6 /* SettingsRepositoryMACOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = E0D4153B25A120340031A8D6 /* SettingsRepositoryMACOS.mm */; };
|
||||||
|
E0D7E6F425A271A0006991C7 /* CompositeKeyValueRepository.cxx in Sources */ = {isa = PBXBuildFile; fileRef = E0D7E6F325A271A0006991C7 /* CompositeKeyValueRepository.cxx */; };
|
||||||
E0DCD3A720A64E96000B614E /* LanczosResampler.hxx in Headers */ = {isa = PBXBuildFile; fileRef = E0DCD3A320A64E95000B614E /* LanczosResampler.hxx */; };
|
E0DCD3A720A64E96000B614E /* LanczosResampler.hxx in Headers */ = {isa = PBXBuildFile; fileRef = E0DCD3A320A64E95000B614E /* LanczosResampler.hxx */; };
|
||||||
E0DCD3A820A64E96000B614E /* LanczosResampler.cxx in Sources */ = {isa = PBXBuildFile; fileRef = E0DCD3A420A64E95000B614E /* LanczosResampler.cxx */; };
|
E0DCD3A820A64E96000B614E /* LanczosResampler.cxx in Sources */ = {isa = PBXBuildFile; fileRef = E0DCD3A420A64E95000B614E /* LanczosResampler.cxx */; };
|
||||||
E0DCD3A920A64E96000B614E /* ConvolutionBuffer.hxx in Headers */ = {isa = PBXBuildFile; fileRef = E0DCD3A520A64E96000B614E /* ConvolutionBuffer.hxx */; };
|
E0DCD3A920A64E96000B614E /* ConvolutionBuffer.hxx in Headers */ = {isa = PBXBuildFile; fileRef = E0DCD3A520A64E96000B614E /* ConvolutionBuffer.hxx */; };
|
||||||
|
@ -1552,6 +1553,7 @@
|
||||||
E0A755772244294600101889 /* CartCDFInfoWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartCDFInfoWidget.cxx; sourceTree = "<group>"; };
|
E0A755772244294600101889 /* CartCDFInfoWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartCDFInfoWidget.cxx; sourceTree = "<group>"; };
|
||||||
E0D4153A25A120340031A8D6 /* SettingsRepositoryMACOS.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SettingsRepositoryMACOS.hxx; sourceTree = "<group>"; };
|
E0D4153A25A120340031A8D6 /* SettingsRepositoryMACOS.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SettingsRepositoryMACOS.hxx; sourceTree = "<group>"; };
|
||||||
E0D4153B25A120340031A8D6 /* SettingsRepositoryMACOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SettingsRepositoryMACOS.mm; sourceTree = "<group>"; };
|
E0D4153B25A120340031A8D6 /* SettingsRepositoryMACOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SettingsRepositoryMACOS.mm; sourceTree = "<group>"; };
|
||||||
|
E0D7E6F325A271A0006991C7 /* CompositeKeyValueRepository.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompositeKeyValueRepository.cxx; sourceTree = "<group>"; };
|
||||||
E0DCD3A320A64E95000B614E /* LanczosResampler.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = LanczosResampler.hxx; path = audio/LanczosResampler.hxx; sourceTree = "<group>"; };
|
E0DCD3A320A64E95000B614E /* LanczosResampler.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = LanczosResampler.hxx; path = audio/LanczosResampler.hxx; sourceTree = "<group>"; };
|
||||||
E0DCD3A420A64E95000B614E /* LanczosResampler.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LanczosResampler.cxx; path = audio/LanczosResampler.cxx; sourceTree = "<group>"; };
|
E0DCD3A420A64E95000B614E /* LanczosResampler.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LanczosResampler.cxx; path = audio/LanczosResampler.cxx; sourceTree = "<group>"; };
|
||||||
E0DCD3A520A64E96000B614E /* ConvolutionBuffer.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ConvolutionBuffer.hxx; path = audio/ConvolutionBuffer.hxx; sourceTree = "<group>"; };
|
E0DCD3A520A64E96000B614E /* ConvolutionBuffer.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ConvolutionBuffer.hxx; path = audio/ConvolutionBuffer.hxx; sourceTree = "<group>"; };
|
||||||
|
@ -2481,6 +2483,7 @@
|
||||||
E06508B72272447200B341AC /* repository */ = {
|
E06508B72272447200B341AC /* repository */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
E0D7E6F325A271A0006991C7 /* CompositeKeyValueRepository.cxx */,
|
||||||
DC2ABA5B259BD544007E57D3 /* CompositeKeyValueRepository.hxx */,
|
DC2ABA5B259BD544007E57D3 /* CompositeKeyValueRepository.hxx */,
|
||||||
DC2ABA66259D466C007E57D3 /* CompositeKeyValueRepositoryNoop.hxx */,
|
DC2ABA66259D466C007E57D3 /* CompositeKeyValueRepositoryNoop.hxx */,
|
||||||
DC2ABA6B25A0C9B1007E57D3 /* CompositeKVRJsonAdapter.cxx */,
|
DC2ABA6B25A0C9B1007E57D3 /* CompositeKVRJsonAdapter.cxx */,
|
||||||
|
@ -3070,6 +3073,7 @@
|
||||||
DC3EE8671E2C0E6D00905161 /* inftrees.c in Sources */,
|
DC3EE8671E2C0E6D00905161 /* inftrees.c in Sources */,
|
||||||
2D91747609BA90380026E9FF /* Cart.cxx in Sources */,
|
2D91747609BA90380026E9FF /* Cart.cxx in Sources */,
|
||||||
2D91747709BA90380026E9FF /* Cart2K.cxx in Sources */,
|
2D91747709BA90380026E9FF /* Cart2K.cxx in Sources */,
|
||||||
|
E0D7E6F425A271A0006991C7 /* CompositeKeyValueRepository.cxx in Sources */,
|
||||||
E034A5EE209FB25D00C89E9E /* EmulationTiming.cxx in Sources */,
|
E034A5EE209FB25D00C89E9E /* EmulationTiming.cxx in Sources */,
|
||||||
2D91747809BA90380026E9FF /* Cart3F.cxx in Sources */,
|
2D91747809BA90380026E9FF /* Cart3F.cxx in Sources */,
|
||||||
2D91747909BA90380026E9FF /* Cart4K.cxx in Sources */,
|
2D91747909BA90380026E9FF /* Cart4K.cxx in Sources */,
|
||||||
|
|
Loading…
Reference in New Issue