mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 15:45:42 +00:00
libretro: Cheat support
This commit is contained in:
parent
1e6815634a
commit
40037d6e90
|
@ -13,6 +13,7 @@ A "BIOS" ROM image is required to to start the emulator and to play games. You c
|
|||
|
||||
## Latest News
|
||||
|
||||
- 2020/09/25: Cheat support added for libretro core.
|
||||
- 2020/09/23: Game covers added to Qt frontend (see [Adding Game Covers](https://github.com/stenzek/duckstation/wiki/Adding-Game-Covers)).
|
||||
- 2020/09/19: Memory card importer/editor added to Qt frontend.
|
||||
- 2020/09/13: Support for chaining post processing shaders added.
|
||||
|
|
|
@ -196,49 +196,55 @@ bool CheatList::LoadFromLibretroFile(const char* filename)
|
|||
CheatCode cc;
|
||||
cc.description = *desc;
|
||||
cc.enabled = StringUtil::FromChars<bool>(*enable).value_or(false);
|
||||
|
||||
const char* current_ptr = code->c_str();
|
||||
while (current_ptr)
|
||||
{
|
||||
char* end_ptr;
|
||||
CheatCode::Instruction inst;
|
||||
inst.first = static_cast<u32>(std::strtoul(current_ptr, &end_ptr, 16));
|
||||
current_ptr = end_ptr;
|
||||
if (end_ptr)
|
||||
{
|
||||
if (*end_ptr != ' ')
|
||||
{
|
||||
Log_WarningPrintf("Malformed code '%s'", code->c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
end_ptr++;
|
||||
inst.second = static_cast<u32>(std::strtoul(current_ptr, &end_ptr, 16));
|
||||
current_ptr = end_ptr;
|
||||
|
||||
if (end_ptr)
|
||||
{
|
||||
if (*end_ptr != '+')
|
||||
{
|
||||
Log_WarningPrintf("Malformed code '%s'", code->c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
end_ptr++;
|
||||
current_ptr = end_ptr;
|
||||
}
|
||||
|
||||
cc.instructions.push_back(inst);
|
||||
}
|
||||
}
|
||||
|
||||
m_codes.push_back(std::move(cc));
|
||||
if (ParseLibretroCheat(&cc, code->c_str()))
|
||||
m_codes.push_back(std::move(cc));
|
||||
}
|
||||
|
||||
Log_InfoPrintf("Loaded %zu cheats from '%s' (libretro format)", m_codes.size(), filename);
|
||||
return !m_codes.empty();
|
||||
}
|
||||
|
||||
bool CheatList::ParseLibretroCheat(CheatCode* cc, const char* line)
|
||||
{
|
||||
const char* current_ptr = line;
|
||||
while (current_ptr)
|
||||
{
|
||||
char* end_ptr;
|
||||
CheatCode::Instruction inst;
|
||||
inst.first = static_cast<u32>(std::strtoul(current_ptr, &end_ptr, 16));
|
||||
current_ptr = end_ptr;
|
||||
if (end_ptr)
|
||||
{
|
||||
if (*end_ptr != ' ')
|
||||
{
|
||||
Log_WarningPrintf("Malformed code '%s'", line);
|
||||
break;
|
||||
}
|
||||
|
||||
end_ptr++;
|
||||
inst.second = static_cast<u32>(std::strtoul(current_ptr, &end_ptr, 16));
|
||||
if (end_ptr && *end_ptr == '\0')
|
||||
end_ptr = nullptr;
|
||||
|
||||
if (end_ptr)
|
||||
{
|
||||
if (*end_ptr != '+')
|
||||
{
|
||||
Log_WarningPrintf("Malformed code '%s'", line);
|
||||
break;
|
||||
}
|
||||
|
||||
end_ptr++;
|
||||
}
|
||||
|
||||
current_ptr = end_ptr;
|
||||
cc->instructions.push_back(inst);
|
||||
}
|
||||
}
|
||||
|
||||
return !cc->instructions.empty();
|
||||
}
|
||||
|
||||
void CheatList::Apply()
|
||||
{
|
||||
for (const CheatCode& code : m_codes)
|
||||
|
@ -253,6 +259,20 @@ void CheatList::AddCode(CheatCode cc)
|
|||
m_codes.push_back(std::move(cc));
|
||||
}
|
||||
|
||||
void CheatList::SetCode(u32 index, CheatCode cc)
|
||||
{
|
||||
if (index > m_codes.size())
|
||||
return;
|
||||
|
||||
if (index == m_codes.size())
|
||||
{
|
||||
m_codes.push_back(std::move(cc));
|
||||
return;
|
||||
}
|
||||
|
||||
m_codes[index] = std::move(cc);
|
||||
}
|
||||
|
||||
void CheatList::RemoveCode(u32 i)
|
||||
{
|
||||
m_codes.erase(m_codes.begin() + i);
|
||||
|
|
|
@ -71,6 +71,7 @@ public:
|
|||
ALWAYS_INLINE bool IsCodeEnabled(u32 index) const { return m_codes[index].enabled; }
|
||||
|
||||
void AddCode(CheatCode cc);
|
||||
void SetCode(u32 index, CheatCode cc);
|
||||
void RemoveCode(u32 i);
|
||||
|
||||
u32 GetEnabledCodeCount() const;
|
||||
|
@ -79,6 +80,7 @@ public:
|
|||
void SetCodeEnabled(u32 index, bool state);
|
||||
|
||||
static std::optional<Format> DetectFileFormat(const char* filename);
|
||||
static bool ParseLibretroCheat(CheatCode* cc, const char* line);
|
||||
|
||||
bool LoadFromFile(const char* filename, Format format);
|
||||
bool LoadFromPCSXRFile(const char* filename);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "common/string_util.h"
|
||||
#include "core/analog_controller.h"
|
||||
#include "core/bus.h"
|
||||
#include "core/cheats.h"
|
||||
#include "core/digital_controller.h"
|
||||
#include "core/gpu.h"
|
||||
#include "core/system.h"
|
||||
|
@ -369,6 +370,29 @@ size_t LibretroHostInterface::retro_get_memory_size(unsigned id)
|
|||
}
|
||||
}
|
||||
|
||||
void LibretroHostInterface::retro_cheat_reset()
|
||||
{
|
||||
System::SetCheatList(nullptr);
|
||||
}
|
||||
|
||||
void LibretroHostInterface::retro_cheat_set(unsigned index, bool enabled, const char* code)
|
||||
{
|
||||
CheatList* cl = System::GetCheatList();
|
||||
if (!cl)
|
||||
{
|
||||
System::SetCheatList(std::make_unique<CheatList>());
|
||||
cl = System::GetCheatList();
|
||||
}
|
||||
|
||||
CheatCode cc;
|
||||
cc.description = StringUtil::StdStringFromFormat("Cheat%u", index);
|
||||
cc.enabled = true;
|
||||
if (!CheatList::ParseLibretroCheat(&cc, code))
|
||||
Log_ErrorPrintf("Failed to parse cheat %u '%s'", index, code);
|
||||
|
||||
cl->SetCode(index, std::move(cc));
|
||||
}
|
||||
|
||||
bool LibretroHostInterface::AcquireHostDisplay()
|
||||
{
|
||||
// start in software mode, switch to hardware later
|
||||
|
|
|
@ -40,6 +40,8 @@ public:
|
|||
bool retro_unserialize(const void* data, size_t size);
|
||||
void* retro_get_memory_data(unsigned id);
|
||||
size_t retro_get_memory_size(unsigned id);
|
||||
void retro_cheat_reset();
|
||||
void retro_cheat_set(unsigned index, bool enabled, const char* code);
|
||||
|
||||
protected:
|
||||
bool AcquireHostDisplay() override;
|
||||
|
|
|
@ -79,12 +79,14 @@ RETRO_API bool retro_unserialize(const void* data, size_t size)
|
|||
|
||||
RETRO_API void retro_cheat_reset(void)
|
||||
{
|
||||
Log_ErrorPrintf("retro_cheat_reset()");
|
||||
Log_InfoPrint("retro_cheat_reset()");
|
||||
g_libretro_host_interface.retro_cheat_reset();
|
||||
}
|
||||
|
||||
RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char* code)
|
||||
{
|
||||
Log_ErrorPrintf("retro_cheat_set(%u, %u, %s)", index, enabled, code);
|
||||
Log_InfoPrintf("retro_cheat_set(%u, %u, %s)", index, enabled, code);
|
||||
g_libretro_host_interface.retro_cheat_set(index, enabled, code);
|
||||
}
|
||||
|
||||
RETRO_API bool retro_load_game(const struct retro_game_info* game)
|
||||
|
|
Loading…
Reference in a new issue