mirror of
https://github.com/libretro/Mesen.git
synced 2024-12-11 19:03:35 +00:00
0c91a15fa0
-Rearranged build folders to be cleaner -Required resource files are automatically copied to the output folder
157 lines
4.0 KiB
C++
157 lines
4.0 KiB
C++
#include "stdafx.h"
|
|
|
|
#include "CheatManager.h"
|
|
#include "Console.h"
|
|
#include "MessageManager.h"
|
|
|
|
CheatManager* CheatManager::Instance = new CheatManager();
|
|
|
|
CheatManager::CheatManager()
|
|
{
|
|
for(int i = 0; i <= 0xFFFF; i++) {
|
|
_relativeCheatCodes.push_back(nullptr);
|
|
}
|
|
}
|
|
|
|
uint32_t CheatManager::DecodeValue(uint32_t code, uint32_t* bitIndexes, uint32_t bitCount)
|
|
{
|
|
uint32_t result = 0;
|
|
for(uint32_t i = 0; i < bitCount; i++) {
|
|
result <<= 1;
|
|
result |= (code >> bitIndexes[i]) & 0x01;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
CodeInfo CheatManager::GetGGCodeInfo(string ggCode)
|
|
{
|
|
string ggLetters = "APZLGITYEOXUKSVN";
|
|
|
|
uint32_t rawCode = 0;
|
|
for(size_t i = 0, len = ggCode.size(); i < len; i++) {
|
|
rawCode |= ggLetters.find(ggCode[i]) << (i * 4);
|
|
}
|
|
|
|
CodeInfo code = { 0 };
|
|
code.IsRelativeAddress = true;
|
|
code.CompareValue = -1;
|
|
uint32_t addressBits[15] = { 14, 13, 12, 19, 22, 21, 20, 7, 10, 9, 8, 15, 18, 17, 16 };
|
|
uint32_t valueBits[8] = { 3, 6, 5, 4, 23, 2, 1, 0 };
|
|
if(ggCode.size() == 8) {
|
|
//Bit 5 of the value is stored in a different location for 8-character codes
|
|
valueBits[5] = 31;
|
|
|
|
uint32_t compareValueBits[8] = { 27, 30, 29, 28, 23, 26, 25, 24 };
|
|
code.CompareValue = DecodeValue(rawCode, compareValueBits, 8);
|
|
}
|
|
code.Address = DecodeValue(rawCode, addressBits, 15) + 0x8000;
|
|
code.Value = DecodeValue(rawCode, valueBits, 8);
|
|
|
|
return code;
|
|
}
|
|
|
|
CodeInfo CheatManager::GetPARCodeInfo(uint32_t parCode)
|
|
{
|
|
uint32_t shiftValues[31] = {
|
|
3, 13, 14, 1, 6, 9, 5, 0, 12, 7, 2, 8, 10, 11, 4, //address
|
|
19, 21, 23, 22, 20, 17, 16, 18, //compare
|
|
29, 31, 24, 26, 25, 30, 27, 28 //value
|
|
};
|
|
uint32_t key = 0x7E5EE93A;
|
|
uint32_t xorValue = 0x5C184B91;
|
|
|
|
//Throw away bit 0, not used.
|
|
parCode >>= 1;
|
|
|
|
uint32_t result = 0;
|
|
for(int32_t i = 30; i >= 0; i--) {
|
|
if(((key ^ parCode) >> 30) & 0x01) {
|
|
result |= 0x01 << shiftValues[i];
|
|
key ^= xorValue;
|
|
}
|
|
parCode <<= 1;
|
|
key <<= 1;
|
|
}
|
|
|
|
CodeInfo code = { 0 };
|
|
code.IsRelativeAddress = true;
|
|
code.Address = (result & 0x7fff) + 0x8000;
|
|
code.Value = (result >> 24) & 0xFF;
|
|
code.CompareValue = (result >> 16) & 0xFF;
|
|
|
|
return code;
|
|
}
|
|
|
|
void CheatManager::AddCode(CodeInfo &code)
|
|
{
|
|
if(code.IsRelativeAddress) {
|
|
if(_relativeCheatCodes[code.Address] == nullptr) {
|
|
_relativeCheatCodes[code.Address].reset(new vector<CodeInfo>());
|
|
}
|
|
_relativeCheatCodes[code.Address]->push_back(code);
|
|
} else {
|
|
_absoluteCheatCodes.push_back(code);
|
|
MessageManager::SendNotification(ConsoleNotificationType::CheatAdded);
|
|
}
|
|
}
|
|
|
|
void CheatManager::AddGameGenieCode(string code)
|
|
{
|
|
Instance->AddCode(Instance->GetGGCodeInfo(code));
|
|
}
|
|
|
|
void CheatManager::AddProActionRockyCode(uint32_t code)
|
|
{
|
|
Instance->AddCode(Instance->GetPARCodeInfo(code));
|
|
}
|
|
|
|
void CheatManager::AddCustomCode(uint32_t address, uint8_t value, int32_t compareValue, bool isRelativeAddress)
|
|
{
|
|
CodeInfo code;
|
|
code.Address = address;
|
|
code.Value = value;
|
|
code.CompareValue = compareValue;
|
|
code.IsRelativeAddress = isRelativeAddress;
|
|
|
|
Instance->AddCode(code);
|
|
}
|
|
|
|
void CheatManager::ClearCodes()
|
|
{
|
|
for(int i = 0; i <= 0xFFFF; i++) {
|
|
Instance->_relativeCheatCodes[i] = nullptr;
|
|
}
|
|
|
|
bool sendNotification = Instance->_absoluteCheatCodes.size() > 0;
|
|
Instance->_absoluteCheatCodes.clear();
|
|
if(sendNotification) {
|
|
MessageManager::SendNotification(ConsoleNotificationType::CheatRemoved);
|
|
}
|
|
}
|
|
|
|
void CheatManager::ApplyRamCodes(uint16_t addr, uint8_t &value)
|
|
{
|
|
if(Instance->_relativeCheatCodes[addr] != nullptr) {
|
|
for(uint32_t i = 0, len = i < Instance->_relativeCheatCodes[addr]->size(); i < len; i++) {
|
|
CodeInfo code = Instance->_relativeCheatCodes[addr]->at(i);
|
|
if(code.CompareValue == -1 || code.CompareValue == value) {
|
|
value = code.Value;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CheatManager::ApplyPrgCodes(uint8_t *prgRam, uint32_t prgSize)
|
|
{
|
|
Console::Pause();
|
|
for(uint32_t i = 0, len = i < Instance->_absoluteCheatCodes.size(); i < len; i++) {
|
|
CodeInfo code = Instance->_absoluteCheatCodes[i];
|
|
if(code.Address < prgSize) {
|
|
if(code.CompareValue == -1 || code.CompareValue == prgRam[code.Address]) {
|
|
prgRam[code.Address] = code.Value;
|
|
}
|
|
}
|
|
}
|
|
Console::Resume();
|
|
} |