Movies: Save and load cheats when recording/playing a movie file

This commit is contained in:
Sour 2019-10-13 11:57:15 -04:00
parent 9aba01ba0c
commit c6137f4f37
6 changed files with 71 additions and 11 deletions

View file

@ -8,32 +8,42 @@ CheatManager::CheatManager(Console* console)
_console = console;
}
void CheatManager::AddCheat(uint32_t addr, uint8_t value)
void CheatManager::AddCheat(CheatCode code)
{
_cheats.push_back({ addr, value });
_cheats.push_back(code);
_hasCheats = true;
_bankHasCheats[addr >> 16] = true;
_bankHasCheats[code.Address >> 16] = true;
}
void CheatManager::SetCheats(uint32_t codes[], uint32_t length)
void CheatManager::SetCheats(vector<CheatCode> codes)
{
auto lock = _console->AcquireLock();
bool hasCheats = !_cheats.empty();
ClearCheats(false);
for(uint32_t i = 0; i < length; i++) {
AddCheat(codes[i] >> 8, codes[i] & 0xFF);
for(CheatCode &code : codes) {
AddCheat(code);
}
if(length > 1) {
MessageManager::DisplayMessage("Cheats", "CheatsApplied", std::to_string(length));
} else if(length == 1) {
if(codes.size() > 1) {
MessageManager::DisplayMessage("Cheats", "CheatsApplied", std::to_string(codes.size()));
} else if(codes.size() == 1) {
MessageManager::DisplayMessage("Cheats", "CheatApplied");
} else if(hasCheats) {
MessageManager::DisplayMessage("Cheats", "CheatsDisabled");
}
}
void CheatManager::SetCheats(uint32_t codes[], uint32_t length)
{
vector<CheatCode> cheats;
cheats.reserve(length);
for(uint32_t i = 0; i < length; i++) {
cheats.push_back({ codes[i] >> 8, codes[i] & 0xFF });
}
SetCheats(cheats);
}
void CheatManager::ClearCheats(bool showMessage)
{
auto lock = _console->AcquireLock();
@ -46,3 +56,8 @@ void CheatManager::ClearCheats(bool showMessage)
_hasCheats = false;
memset(_bankHasCheats, 0, sizeof(_bankHasCheats));
}
vector<CheatCode> CheatManager::GetCheats()
{
return _cheats;
}

View file

@ -17,14 +17,17 @@ private:
bool _bankHasCheats[0x100] = {};
vector<CheatCode> _cheats;
void AddCheat(uint32_t addr, uint8_t value);
void AddCheat(CheatCode code);
public:
CheatManager(Console* console);
void SetCheats(vector<CheatCode> codes);
void SetCheats(uint32_t codes[], uint32_t length);
void ClearCheats(bool showMessage = true);
vector<CheatCode> GetCheats();
__forceinline void ApplyCheat(uint32_t addr, uint8_t &value);
};

View file

@ -14,6 +14,7 @@
#include "MovieManager.h"
#include "NotificationManager.h"
#include "BatteryManager.h"
#include "CheatManager.h"
MesenMovie::MesenMovie(shared_ptr<Console> console)
{
@ -34,6 +35,8 @@ void MesenMovie::Stop()
_console->Pause();
}
_console->GetCheatManager()->SetCheats(_originalCheats);
_playing = false;
}
_console->GetControlManager()->UnregisterInputProvider(this);
@ -136,7 +139,9 @@ bool MesenMovie::Play(VirtualFile &file)
return false;
}*/
_originalCheats = _console->GetCheatManager()->GetCheats();
_console->PowerCycle();
LoadCheats();
stringstream saveStateData;
if(_reader->GetStream("SaveState.mss", saveStateData)) {
@ -283,3 +288,29 @@ string MesenMovie::LoadString(std::unordered_map<string, string> &settings, stri
return "";
}
}
void MesenMovie::LoadCheats()
{
vector<CheatCode> cheats;
for(string cheatData : _cheats) {
CheatCode code;
if(LoadCheat(cheatData, code)) {
cheats.push_back(code);
}
}
_console->GetCheatManager()->SetCheats(cheats);
}
bool MesenMovie::LoadCheat(string cheatData, CheatCode &code)
{
vector<string> data = StringUtilities::Split(cheatData, ' ');
if(data.size() == 2) {
code.Address = HexUtilities::FromHex(data[0]);
code.Value = HexUtilities::FromHex(data[1]);
return true;
} else {
MessageManager::Log("[Movie] Invalid cheat definition: " + cheatData);
}
return false;
}

View file

@ -8,6 +8,7 @@
class ZipReader;
class Console;
struct CheatCode;
class MesenMovie : public IMovie, public INotificationListener, public IBatteryProvider, public std::enable_shared_from_this<MesenMovie>
{
@ -21,6 +22,7 @@ private:
uint32_t _lastPollCounter = 0;
vector<vector<string>> _inputData;
vector<string> _cheats;
vector<CheatCode> _originalCheats;
std::unordered_map<string, string> _settings;
string _filename;
@ -34,6 +36,9 @@ private:
bool LoadBool(std::unordered_map<string, string> &settings, string name);
string LoadString(std::unordered_map<string, string> &settings, string name);
void LoadCheats();
bool LoadCheat(string cheatData, CheatCode &code);
public:
MesenMovie(shared_ptr<Console> console);
virtual ~MesenMovie();

View file

@ -15,6 +15,7 @@
#include "RewindData.h"
#include "MovieTypes.h"
#include "BatteryManager.h"
#include "CheatManager.h"
MovieRecorder::MovieRecorder(shared_ptr<Console> console)
{
@ -111,6 +112,10 @@ void MovieRecorder::GetGameSettings(stringstream &out)
case RamState::AllOnes: WriteString(out, MovieKeys::RamPowerOnState, "AllOnes"); break;
case RamState::Random: WriteString(out, MovieKeys::RamPowerOnState, "AllOnes"); break; //TODO: Random memory isn't supported for movies yet
}
for(CheatCode &code : _console->GetCheatManager()->GetCheats()) {
out << "Cheat " << HexUtilities::ToHex24(code.Address) << " " << HexUtilities::ToHex(code.Value) << "\n";
}
}
void MovieRecorder::WriteString(stringstream &out, string name, string value)

View file

@ -31,6 +31,7 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \
$(CORE_DIR)/Breakpoint.cpp \
$(CORE_DIR)/BreakpointManager.cpp \
$(CORE_DIR)/CallstackManager.cpp \
$(CORE_DIR)/CheatManager.cpp \
$(CORE_DIR)/CodeDataLogger.cpp \
$(CORE_DIR)/Console.cpp \
$(CORE_DIR)/ConsoleLock.cpp \