Further work on support for cheats

Cheats can now be enabled/disabled and games can be launched with cheats
This commit is contained in:
Gericom
2026-02-28 17:00:02 +01:00
parent dddee0bb94
commit f54a379ff2
27 changed files with 660 additions and 171 deletions

View File

@@ -3,57 +3,16 @@
#include "fat/File.h"
#include "CheatsViewModel.h"
#define CRCPOLY 0xEDB88320
static u32 crc32(const void* buffer, u32 length)
{
u32 crc = ~0u;
const u8* p = (u8*)buffer;
while (length--)
{
crc ^= *p++;
for (int i = 0; i < 8; i++)
{
crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY : 0);
}
}
return crc;
}
CheatsViewModel::CheatsViewModel(const FileInfo& romFileInfo, IRomBrowserController* romBrowserController)
: _romFileInfo(romFileInfo), _romBrowserController(romBrowserController)
{
_categoryStack.fill(nullptr);
_loadCheatsTask = _romBrowserController->GetIoTaskQueue()->Enqueue([this] (const vu8& cancelRequested)
{
LOG_DEBUG("%s\n", _romFileInfo.GetFileName());
auto file = std::make_unique<File>();
file->Open(_romFileInfo.GetFastFileRef(), FA_READ);
auto headerBuffer = std::make_unique_for_overwrite<u8[]>(512);
if (!file->ReadExact(headerBuffer.get(), 512))
{
LOG_ERROR("Could not read rom header\n");
return TaskResult<void>::Failed();
}
file->Close();
if (cancelRequested)
{
return TaskResult<void>::Canceled();
}
u32 gameCode = *(u32*)(headerBuffer.get() + 0xC);
u32 crc = crc32(headerBuffer.get(), 512);
headerBuffer.reset();
if (cancelRequested)
{
return TaskResult<void>::Canceled();
}
_cheats = _romBrowserController->GetCheatRepository().GetCheatsForGame(gameCode, crc);
_cheats = _romBrowserController->GetCheatRepository().GetCheatsForGame(_romFileInfo.GetFastFileRef());
if (_cheats)
{
_categoryStack[0] = _cheats.get();
_state = State::DisplayCheats;
}
else
@@ -64,3 +23,64 @@ CheatsViewModel::CheatsViewModel(const FileInfo& romFileInfo, IRomBrowserControl
return TaskResult<void>::Completed();
});
}
void CheatsViewModel::ItemActivated()
{
auto cheatCategory = GetCurrentCheatCategory();
u32 numberOfCategories = 0;
auto categories = cheatCategory->GetCategories(numberOfCategories);
u32 numberOfCheats = 0;
auto cheats = cheatCategory->GetCheats(numberOfCheats);
if (_selectedItem < (int)numberOfCategories)
{
// Category activated
if (_categoryStackLevel + 1 != _categoryStack.size())
{
_categoryStack[++_categoryStackLevel] = &categories[_selectedItem];
}
}
else
{
// Toggle cheat on/off
auto& cheat = cheats[_selectedItem - numberOfCategories];
bool isEnabled = !cheat.GetIsCheatActive();
if (isEnabled && cheatCategory->GetIsMaxOneCheatActive())
{
for (u32 i = 0; i < numberOfCheats; i++)
{
cheats[i].SetIsCheatActive(false);
}
}
cheat.SetIsCheatActive(isEnabled);
_changed = true;
}
}
void CheatsViewModel::Back()
{
if (_categoryStackLevel == 0)
{
Close();
}
else
{
_categoryStack[_categoryStackLevel--] = nullptr;
}
}
void CheatsViewModel::Close()
{
if (_changed)
{
// Save which cheats are enabled/disabled
_romBrowserController->GetIoTaskQueue()->Enqueue(
[romBrowserController = _romBrowserController, cheats = move(_cheats)] (const vu8& cancelRequested)
{
romBrowserController->GetCheatRepository().UpdateEnabledCheatsForGame(cheats);
return TaskResult<void>::Completed();
});
}
_romBrowserController->HideGameInfo();
}

View File

@@ -1,4 +1,5 @@
#pragma once
#include <array>
#include <memory>
#include "core/task/TaskQueue.h"
#include "cheats/GameCheats.h"
@@ -18,13 +19,15 @@ public:
CheatsViewModel(const FileInfo& romFileInfo, IRomBrowserController* romBrowserController);
void Close()
{
_romBrowserController->HideGameInfo();
}
void ItemActivated();
void Back();
void Close();
State GetState() const { return _state; }
const GameCheats* GetCheats() const { return _cheats.get(); }
const ICheatCategory* GetCurrentCheatCategory() const { return _categoryStack[_categoryStackLevel]; }
constexpr int GetSelectedItem() const { return _selectedItem; }
void SetSelectedItem(int selectedItem) { _selectedItem = selectedItem; }
private:
FileInfo _romFileInfo;
@@ -32,4 +35,8 @@ private:
QueueTask<void> _loadCheatsTask;
std::unique_ptr<GameCheats> _cheats;
State _state = State::Loading;
int _selectedItem = -1;
bool _changed = false;
u32 _categoryStackLevel = 0;
std::array<const ICheatCategory*, 8> _categoryStack;
};