mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
These _M 0xCF00000n lines carry no memory operations - they group the entries that follow them into folders, or turn them into comments. We used to reject them as unsupported TempAR codes, so files using them showed parse errors and listed the folder headings as toggleable cheats that did nothing. Folders now render like the existing cheat titles with their contents indented, comments render as plain text, and enabling an entry in a single select folder turns off its siblings. Fixes #21257 Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
127 lines
3.3 KiB
C++
127 lines
3.3 KiB
C++
// Rough and ready CwCheats implementation, disabled by default.
|
|
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
#include "Common/File/Path.h"
|
|
#include "Core/MemMap.h"
|
|
|
|
class PointerWrap;
|
|
|
|
void __CheatInit();
|
|
void __CheatShutdown();
|
|
void __CheatDoState(PointerWrap &p);
|
|
|
|
// Return whether cheats are enabled and in effect.
|
|
bool CheatsInEffect();
|
|
|
|
struct CheatLine {
|
|
uint32_t part1;
|
|
uint32_t part2;
|
|
};
|
|
|
|
bool DetectCheatTitle(std::string_view name, std::string_view *title);
|
|
bool DetectCheatPostComment(std::string_view name, std::string_view *title);
|
|
|
|
struct CheatCode {
|
|
std::string name;
|
|
std::vector<CheatLine> lines;
|
|
};
|
|
|
|
// Organizational codes from PSPAR/TempAR (the _M 0xCF00000n lines). These carry no memory
|
|
// operations - they just group the entries that follow them in the list.
|
|
enum class CheatStructure {
|
|
None,
|
|
Comment,
|
|
SingleSelectFolder,
|
|
MultiSelectFolder,
|
|
};
|
|
|
|
struct CheatFileInfo {
|
|
int lineNum;
|
|
std::string name;
|
|
bool enabled;
|
|
CheatStructure structure = CheatStructure::None;
|
|
int subItems = 0; // How many of the entries that follow belong to this folder or comment.
|
|
|
|
bool IsTitle(std::string_view *title) const {
|
|
return DetectCheatTitle(name, title);
|
|
}
|
|
bool IsPostComment(std::string_view *comment) const {
|
|
return DetectCheatPostComment(name, comment);
|
|
}
|
|
};
|
|
|
|
struct CheatOperation;
|
|
|
|
class CWCheatEngine {
|
|
public:
|
|
CWCheatEngine(std::string_view gameID);
|
|
std::vector<CheatFileInfo> FileInfo() const;
|
|
void ParseCheats();
|
|
void CreateCheatFile();
|
|
const Path &CheatFilename() const {
|
|
return filename_;
|
|
}
|
|
void Run();
|
|
bool HasCheats();
|
|
static u32 GetAddress(u32 value) {
|
|
// TODO: This comment is weird:
|
|
// Returns static address used by ppsspp. Some games may not like this, and causes cheats to not work without offset
|
|
u32 address = (value + 0x08800000) & 0x3FFFFFFF;
|
|
return address;
|
|
}
|
|
|
|
private:
|
|
void InvalidateICache(u32 addr, int size) const;
|
|
|
|
CheatOperation InterpretNextCwCheat(const CheatCode &cheat, size_t &i);
|
|
|
|
void ExecuteOp(const CheatOperation &op, const CheatCode &cheat, size_t &i);
|
|
inline void ApplyMemoryOperator(const CheatOperation &op, uint32_t(*oper)(uint32_t, uint32_t));
|
|
inline bool TestIf(const CheatOperation &op, bool(*oper)(int a, int b)) const;
|
|
inline bool TestIfAddr(const CheatOperation &op, bool(*oper)(int a, int b)) const;
|
|
|
|
std::vector<CheatCode> cheats_;
|
|
std::string gameID_;
|
|
Path filename_;
|
|
};
|
|
|
|
class CheatFileParser {
|
|
public:
|
|
CheatFileParser(const Path &filename, std::string_view gameID = "");
|
|
~CheatFileParser();
|
|
|
|
bool Parse();
|
|
|
|
const std::vector<std::string> &GetErrors() const { return errors_; }
|
|
const std::vector<CheatCode> &GetCheats() const { return cheats_; }
|
|
const std::vector<CheatFileInfo> &GetFileInfo() const { return cheatInfo_; }
|
|
|
|
protected:
|
|
void Flush();
|
|
void FlushCheatInfo();
|
|
void AddError(const std::string &msg, int lineNumber);
|
|
void ParseLine(const std::string &line, int lineNumber);
|
|
void ParseDataLine(const std::string &line, int lineNumber);
|
|
bool ValidateGameID(std::string_view gameID);
|
|
|
|
FILE *fp_ = nullptr;
|
|
std::string validGameID_;
|
|
|
|
int games_ = 0;
|
|
std::vector<std::string> errors_;
|
|
std::vector<CheatFileInfo> cheatInfo_;
|
|
std::vector<CheatCode> cheats_;
|
|
std::vector<CheatLine> pendingLines_;
|
|
CheatFileInfo lastCheatInfo_;
|
|
bool gameEnabled_ = true;
|
|
bool gameRiskyEnabled_ = false;
|
|
bool cheatEnabled_ = false;
|
|
};
|