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

@@ -6,14 +6,16 @@
#include "gui/OamBuilder.h"
#include "CheatListItemView.h"
#define ICON_X 20
#define ICON_Y 3
#define ICON_X 4
#define ICON_Y 4
#define NAME_LABEL_X 40
#define NAME_LABEL_Y 4
#define NAME_LABEL_X 24
#define NAME_LABEL_Y 5
CheatListItemView::CheatListItemView(const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository)
CheatListItemView::CheatListItemView(const VramOffsets& vramOffsets,
const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository)
: _nameLabel(200, 16, 64, fontRepository->GetFont(FontType::Regular10))
, _vramOffsets(vramOffsets)
, _materialColorScheme(materialColorScheme)
{
_nameLabel.SetEllipsis(true);
@@ -22,15 +24,57 @@ CheatListItemView::CheatListItemView(const MaterialColorScheme* materialColorSch
void CheatListItemView::Update()
{
_nameLabel.SetPosition(NAME_LABEL_X, _position.y + NAME_LABEL_Y);
_nameLabel.SetPosition(_position.x + NAME_LABEL_X, _position.y + NAME_LABEL_Y);
if (_cheat != nullptr)
{
_iconVramOffset = _cheat->GetIsCheatActive()
? _vramOffsets.checkboxCheckedIconVramOffset
: _vramOffsets.checkboxUncheckedIconVramOffset;
}
ViewContainer::Update();
}
void CheatListItemView::Draw(GraphicsContext& graphicsContext)
{
if (!graphicsContext.IsVisible(GetBounds()))
{
return;
}
auto backColor = _materialColorScheme->GetColor(md::sys::color::surfaceContainerLow);
if (IsFocused())
{
auto selectorFullColor = _materialColorScheme->GetColor(md::sys::color::onSurface);
backColor = RgbMixer::Lerp(backColor, selectorFullColor, 10, 100);
}
_nameLabel.SetBackgroundColor(backColor);
_nameLabel.SetForegroundColor(_materialColorScheme->onSurface);
if (IsFocused())
{
u32 selectorPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
GradientPalette(backColor, backColor),
_position.y, _position.y + 24);
auto selectorOam = graphicsContext.GetOamManager().AllocOams(4);
OamBuilder::OamWithSize<64, 32>(_position.x, _position.y, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(selectorPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(selectorOam[0]);
OamBuilder::OamWithSize<64, 32>(_position.x + 64, _position.y, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(selectorPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(selectorOam[1]);
OamBuilder::OamWithSize<64, 32>(_position.x + 2 * 64, _position.y, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(selectorPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(selectorOam[2]);
OamBuilder::OamWithSize<64, 32>(_position.x + 2 * 64 + 32, _position.y, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(selectorPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(selectorOam[3]);
}
ViewContainer::Draw(graphicsContext);
if (graphicsContext.IsVisible(Rectangle(_position.x + ICON_X, _position.y + ICON_Y, 16, 16)))

View File

@@ -1,6 +1,8 @@
#pragma once
#include "gui/views/ViewContainer.h"
#include "gui/views/Label2DView.h"
#include "cheats/CheatCategory.h"
#include "cheats/Cheat.h"
class MaterialColorScheme;
class IFontRepository;
@@ -8,14 +10,22 @@ class IFontRepository;
class CheatListItemView : public ViewContainer
{
public:
CheatListItemView(const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository);
struct VramOffsets
{
u32 folderIconVramOffset = 0;
u32 checkboxUncheckedIconVramOffset = 0;
u32 checkboxCheckedIconVramOffset = 0;
u32 cheatSelectorVramOffset = 0;
};
CheatListItemView(const VramOffsets& vramOffsets, const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository);
void Update() override;
void Draw(GraphicsContext& graphicsContext) override;
Rectangle GetBounds() const override
{
return Rectangle(_position.x, _position.y, 256, 24);
return Rectangle(_position.x, _position.y, 224, 24);
}
void SetName(const char* name)
@@ -23,13 +33,23 @@ public:
_nameLabel.SetText(name);
}
void SetIcon(u32 iconVramOffset)
void SetCategory(const CheatCategory* cheatCategory)
{
_iconVramOffset = iconVramOffset;
_cheat = nullptr;
_nameLabel.SetText(cheatCategory->GetName());
_iconVramOffset = _vramOffsets.folderIconVramOffset;
}
void SetCheat(const Cheat* cheat)
{
_cheat = cheat;
_nameLabel.SetText(_cheat->GetName());
}
private:
Label2DView _nameLabel;
u32 _iconVramOffset = 0;
VramOffsets _vramOffsets;
const MaterialColorScheme* _materialColorScheme;
u32 _iconVramOffset = 0;
const Cheat* _cheat = nullptr;
};

View File

@@ -7,30 +7,30 @@
class CheatsAdapter : public RecyclerAdapter
{
public:
CheatsAdapter(const CheatCategory* categories, u32 numberOfCategories, const Cheat* cheats, u32 numberOfCheats,
const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository,
u32 folderIconVramOffset, u32 checkboxUncheckedIconVramOffset, u32 checkboxCheckedIconVramOffset)
: _categories(categories), _numberOfCategories(numberOfCategories), _cheats(cheats), _numberOfCheats(numberOfCheats)
, _materialColorScheme(materialColorScheme), _fontRepository(fontRepository)
, _folderIconVramOffset(folderIconVramOffset)
, _checkboxUncheckedIconVramOffset(checkboxUncheckedIconVramOffset)
, _checkboxCheckedIconVramOffset(checkboxCheckedIconVramOffset) { }
CheatsAdapter(const ICheatCategory* cheatCategory, const MaterialColorScheme* materialColorScheme,
const IFontRepository* fontRepository, const CheatListItemView::VramOffsets& vramOffsets)
: _cheatCategory(cheatCategory), _materialColorScheme(materialColorScheme)
, _fontRepository(fontRepository), _vramOffsets(vramOffsets) { }
u32 GetItemCount() const override
{
return _numberOfCategories + _numberOfCheats;
u32 numberOfCategories = 0;
_cheatCategory->GetCategories(numberOfCategories);
u32 numberOfCheats = 0;
_cheatCategory->GetCheats(numberOfCheats);
return numberOfCategories + numberOfCheats;
}
void GetViewSize(int& width, int& height) const override
{
width = 256;
width = 224;
height = 24;
}
View* CreateView() const override
{
LOG_DEBUG("CheatsAdapter::CreateView\n");
return new CheatListItemView(_materialColorScheme, _fontRepository);
return new CheatListItemView(_vramOffsets, _materialColorScheme, _fontRepository);
}
void DestroyView(View* view) const override
@@ -43,16 +43,18 @@ public:
{
LOG_DEBUG("CheatsAdapter::BindView\n");
auto listItemView = static_cast<CheatListItemView*>(view);
if ((u32)index < _numberOfCategories)
u32 numberOfCategories = 0;
auto categories = _cheatCategory->GetCategories(numberOfCategories);
if ((u32)index < numberOfCategories)
{
listItemView->SetName(_categories[index].GetName());
listItemView->SetIcon(_folderIconVramOffset);
listItemView->SetCategory(&categories[index]);
}
else
{
index -= _numberOfCategories;
listItemView->SetName(_cheats[index].GetName());
listItemView->SetIcon(_cheats[index].GetIsCheatActive() ? _checkboxCheckedIconVramOffset : _checkboxUncheckedIconVramOffset);
index -= numberOfCategories;
u32 numberOfCheats = 0;
auto cheats = _cheatCategory->GetCheats(numberOfCheats);
listItemView->SetCheat(&cheats[index]);
}
}
@@ -62,13 +64,8 @@ public:
}
private:
const CheatCategory* _categories;
u32 _numberOfCategories;
const Cheat* _cheats;
u32 _numberOfCheats;
const ICheatCategory* _cheatCategory;
const MaterialColorScheme* _materialColorScheme;
const IFontRepository* _fontRepository;
u32 _folderIconVramOffset;
u32 _checkboxUncheckedIconVramOffset;
u32 _checkboxCheckedIconVramOffset;
CheatListItemView::VramOffsets _vramOffsets;
};

View File

@@ -4,27 +4,34 @@
#include "themes/IFontRepository.h"
#include "gui/input/InputProvider.h"
#include "gui/VramContext.h"
#include "gui/palette/GradientPalette.h"
#include "gui/OamBuilder.h"
#include "folderIcon.h"
#include "checkboxChecked.h"
#include "checkboxUnchecked.h"
#include "cheatSelector.h"
#include "gui/DescendingStackVramManager.h"
#include "CheatsBottomSheetView.h"
#define TITLE_LABEL_X 20
#define TITLE_LABEL_Y 16
#define LIST_X 16
#define LIST_Y 36
CheatsBottomSheetView::CheatsBottomSheetView(std::unique_ptr<CheatsViewModel> viewModel,
const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository,
FocusManager* focusManager)
: _viewModel(std::move(viewModel))
, _titleLabel(128, 16, 25, fontRepository->GetFont(FontType::Medium11))
, _cheatListRecycler(0, 36, 256, 124, RecyclerView::Mode::VerticalList)
, _cheatListRecycler(std::make_unique<RecyclerView>(LIST_X, LIST_Y, 224, 124, RecyclerView::Mode::VerticalList))
, _materialColorScheme(materialColorScheme)
, _fontRepository(fontRepository)
, _focusManager(focusManager)
{
_titleLabel.SetText(u"Cheats");
AddChildTail(&_titleLabel);
AddChildTail(&_cheatListRecycler);
AddChildTail(_cheatListRecycler.get());
}
void CheatsBottomSheetView::InitVram(const VramContext& vramContext)
@@ -34,17 +41,21 @@ void CheatsBottomSheetView::InitVram(const VramContext& vramContext)
const auto objVramManager = vramContext.GetObjVramManager();
if (objVramManager)
{
_folderIconVramOffset = objVramManager->Alloc(folderIconTilesLen);
_vramOffsets.folderIconVramOffset = objVramManager->Alloc(folderIconTilesLen);
dma_ntrCopy32(3, folderIconTiles,
objVramManager->GetVramAddress(_folderIconVramOffset), folderIconTilesLen);
objVramManager->GetVramAddress(_vramOffsets.folderIconVramOffset), folderIconTilesLen);
_checkboxUncheckedIconVramOffset = objVramManager->Alloc(checkboxUncheckedTilesLen);
_vramOffsets.checkboxUncheckedIconVramOffset = objVramManager->Alloc(checkboxUncheckedTilesLen);
dma_ntrCopy32(3, checkboxUncheckedTiles,
objVramManager->GetVramAddress(_checkboxUncheckedIconVramOffset), checkboxUncheckedTilesLen);
objVramManager->GetVramAddress(_vramOffsets.checkboxUncheckedIconVramOffset), checkboxUncheckedTilesLen);
_checkboxCheckedIconVramOffset = objVramManager->Alloc(checkboxCheckedTilesLen);
_vramOffsets.checkboxCheckedIconVramOffset = objVramManager->Alloc(checkboxCheckedTilesLen);
dma_ntrCopy32(3, checkboxCheckedTiles,
objVramManager->GetVramAddress(_checkboxCheckedIconVramOffset), checkboxCheckedTilesLen);
objVramManager->GetVramAddress(_vramOffsets.checkboxCheckedIconVramOffset), checkboxCheckedTilesLen);
_vramOffsets.cheatSelectorVramOffset = objVramManager->Alloc(cheatSelectorTilesLen);
dma_ntrCopy32(3, cheatSelectorTiles,
objVramManager->GetVramAddress(_vramOffsets.cheatSelectorVramOffset), cheatSelectorTilesLen);
}
_objVramManager = vramContext.GetObjVramManager();
@@ -53,27 +64,24 @@ void CheatsBottomSheetView::InitVram(const VramContext& vramContext)
void CheatsBottomSheetView::Update()
{
_titleLabel.SetPosition(TITLE_LABEL_X, _position.y + TITLE_LABEL_Y);
_cheatListRecycler.SetPosition(0, _position.y + 36);
_cheatListRecycler->SetPosition(LIST_X, _position.y + LIST_Y);
if (_viewModel->GetState() == CheatsViewModel::State::DisplayCheats)
{
if (_cheatsAdapter == nullptr)
{
LOG_DEBUG("Setting adapter\n");
auto gameCheats = _viewModel->GetCheats();
u32 numberOfCategories = 0;
auto categories = gameCheats->GetCheatCategories(numberOfCategories);
u32 numberOfCheats = 0;
auto cheats = gameCheats->GetCheats(numberOfCheats);
_cheatsAdapter = new CheatsAdapter(categories, numberOfCategories, cheats, numberOfCheats,
_materialColorScheme, _fontRepository, _folderIconVramOffset,
_checkboxUncheckedIconVramOffset, _checkboxCheckedIconVramOffset);
_cheatListRecycler.SetAdapter(_cheatsAdapter);
_cheatListRecycler.InitVram(VramContext(nullptr, _objVramManager, nullptr, nullptr));
_cheatListRecycler.Focus(*_focusManager);
LOG_DEBUG("Setting adapter done\n");
_cheatsAdapter = new CheatsAdapter(
_viewModel->GetCurrentCheatCategory(), _materialColorScheme, _fontRepository, _vramOffsets);
_cheatListRecycler->SetAdapter(_cheatsAdapter);
// Ugly hack
_savedVramState = ((DescendingStackVramManager*)_objVramManager)->GetState();
_cheatListRecycler->InitVram(VramContext(nullptr, _objVramManager, nullptr, nullptr));
_cheatListRecycler->Focus(*_focusManager);
}
}
BottomSheetView::Update();
_viewModel->SetSelectedItem(_cheatListRecycler->GetSelectedItem());
}
void CheatsBottomSheetView::Draw(GraphicsContext& graphicsContext)
@@ -81,12 +89,36 @@ void CheatsBottomSheetView::Draw(GraphicsContext& graphicsContext)
graphicsContext.SetClipArea(GetBounds());
u32 oldPrio = graphicsContext.SetPriority(1);
{
_titleLabel.SetBackgroundColor(_materialColorScheme->GetColor(md::sys::color::surfaceContainerLow));
graphicsContext.SetClipArea(_cheatListRecycler->GetBounds());
_cheatListRecycler->Draw(graphicsContext);
graphicsContext.SetClipArea(GetBounds());
auto backColor = _materialColorScheme->GetColor(md::sys::color::surfaceContainerLow);
u32 maskPaletteRow = graphicsContext.GetPaletteManager().AllocRow(
GradientPalette(backColor, backColor),
_position.y + LIST_Y - 24, _position.y + LIST_Y);
auto maskOam = graphicsContext.GetOamManager().AllocOams(4);
OamBuilder::OamWithSize<64, 32>(LIST_X, _position.y + LIST_Y - 24, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(maskPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(maskOam[0]);
OamBuilder::OamWithSize<64, 32>(LIST_X + 64, _position.y + LIST_Y - 24, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(maskPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(maskOam[1]);
OamBuilder::OamWithSize<64, 32>(LIST_X + 2 * 64, _position.y + LIST_Y - 24, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(maskPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(maskOam[2]);
OamBuilder::OamWithSize<64, 32>(LIST_X + 2 * 64 + 32, _position.y + LIST_Y - 24, _vramOffsets.cheatSelectorVramOffset >> 7)
.WithPalette16(maskPaletteRow)
.WithPriority(graphicsContext.GetPriority())
.Build(maskOam[3]);
_titleLabel.SetBackgroundColor(backColor);
_titleLabel.SetForegroundColor(_materialColorScheme->onSurface);
_titleLabel.Draw(graphicsContext);
graphicsContext.SetClipArea(_cheatListRecycler.GetBounds());
_cheatListRecycler.Draw(graphicsContext);
// BottomSheetView::Draw(graphicsContext);
}
graphicsContext.SetPriority(oldPrio);
graphicsContext.ResetClipArea();
@@ -94,10 +126,48 @@ void CheatsBottomSheetView::Draw(GraphicsContext& graphicsContext)
bool CheatsBottomSheetView::HandleInput(const InputProvider& inputProvider, FocusManager& focusManager)
{
if (inputProvider.Triggered(InputKey::B))
if (inputProvider.Triggered(InputKey::A))
{
if (focusManager.IsFocusInside(_cheatListRecycler.get()))
{
auto oldCategory = _viewModel->GetCurrentCheatCategory();
_viewModel->ItemActivated();
if (oldCategory != _viewModel->GetCurrentCheatCategory())
{
UpdateCheatList();
}
return true;
}
}
else if (inputProvider.Triggered(InputKey::B))
{
auto oldCategory = _viewModel->GetCurrentCheatCategory();
_viewModel->Back();
if (oldCategory != _viewModel->GetCurrentCheatCategory())
{
UpdateCheatList();
}
return true;
}
else if (inputProvider.Triggered(InputKey::Y))
{
_viewModel->Close();
return true;
}
return false;
}
void CheatsBottomSheetView::UpdateCheatList()
{
auto oldAdapter = _cheatsAdapter;
_cheatsAdapter = new CheatsAdapter(_viewModel->GetCurrentCheatCategory(), _materialColorScheme, _fontRepository, _vramOffsets);
_cheatListRecycler->SetAdapter(_cheatsAdapter);
delete oldAdapter;
// Ugly hack
((DescendingStackVramManager*)_objVramManager)->SetState(_savedVramState);
_cheatListRecycler->InitVram(VramContext(nullptr, _objVramManager, nullptr, nullptr));
_cheatListRecycler->Focus(*_focusManager);
}

View File

@@ -5,6 +5,7 @@
#include "gui/views/RecyclerView.h"
#include "romBrowser/viewModels/CheatsViewModel.h"
#include "CheatsAdapter.h"
#include "CheatListItemView.h"
class MaterialColorScheme;
class IFontRepository;
@@ -17,6 +18,15 @@ public:
const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository,
FocusManager* focusManager);
~CheatsBottomSheetView() override
{
_cheatListRecycler.reset();
if (_cheatsAdapter != nullptr)
{
delete _cheatsAdapter;
}
}
void InitVram(const VramContext& vramContext) override;
void Update() override;
void Draw(GraphicsContext& graphicsContext) override;
@@ -24,19 +34,20 @@ public:
void Focus(FocusManager& focusManager) override
{
_cheatListRecycler.Focus(focusManager);
_cheatListRecycler->Focus(focusManager);
}
private:
std::unique_ptr<CheatsViewModel> _viewModel;
Label2DView _titleLabel;
RecyclerView _cheatListRecycler;
std::unique_ptr<RecyclerView> _cheatListRecycler;
CheatsAdapter* _cheatsAdapter = nullptr;
const MaterialColorScheme* _materialColorScheme;
const IFontRepository* _fontRepository;
IVramManager* _objVramManager;
FocusManager* _focusManager;
u32 _folderIconVramOffset = 0;
u32 _checkboxUncheckedIconVramOffset = 0;
u32 _checkboxCheckedIconVramOffset = 0;
CheatListItemView::VramOffsets _vramOffsets;
u32 _savedVramState = 0;
void UpdateCheatList();
};