mirror of
https://github.com/LNH-team/pico-launcher.git
synced 2026-06-02 00:56:55 +02:00
Add cheat documentation, enable input repeat for L and R, show cheat category name
This commit is contained in:
@@ -15,6 +15,7 @@ This repository contains Pico Launcher, which is a front-end for [Pico Loader](h
|
||||
- [Covers](docs/Covers.md)
|
||||
- [Material Design 3 and custom themes](docs/Themes.md)
|
||||
- Support for background music (see [Themes](docs/Themes.md))
|
||||
- Support for cheats (See [Cheats](docs/Cheats.md))
|
||||
|
||||
General usage documentation can be found here: [Usage](docs/Usage.md).
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ App::App(IAppSettingsService& appSettingsService, IBgmService& bgmService)
|
||||
, _bgmService(bgmService)
|
||||
, _inputProvider(&_inputSource)
|
||||
, _inputRepeater(&_inputProvider,
|
||||
InputKey::DpadLeft | InputKey::DpadRight | InputKey::DpadUp | InputKey::DpadDown,
|
||||
InputKey::DpadLeft | InputKey::DpadRight | InputKey::DpadUp | InputKey::DpadDown | InputKey::L | InputKey::R,
|
||||
25, 8)
|
||||
, _romBrowserController(&appSettingsService, &_ioTaskQueue, &_bgTaskQueue)
|
||||
, _displaySettingsBottomSheetViewModel(&_romBrowserController)
|
||||
|
||||
@@ -1,27 +1,48 @@
|
||||
#pragma once
|
||||
#include "CheatTreeItem.h"
|
||||
|
||||
class Cheat : public CheatTreeItem
|
||||
/// @brief Class representing a single cheat.
|
||||
class Cheat
|
||||
{
|
||||
public:
|
||||
Cheat()
|
||||
: _cheatData(nullptr), _cheatDataLength(0) { }
|
||||
Cheat() { }
|
||||
|
||||
Cheat(const char* name, const char* description, u32* flagsPointer, const void* cheatData, u32 cheatDataLength)
|
||||
: CheatTreeItem(name, description), _flagsPointer(flagsPointer)
|
||||
: _name(name), _description(description), _flagsPointer(flagsPointer)
|
||||
, _cheatData(cheatData), _cheatDataLength(cheatDataLength) { }
|
||||
|
||||
/// @brief Gets the name of this cheat.
|
||||
/// @return A pointer to the name of this cheat.
|
||||
const char* GetName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
/// @brief Gets the description of this cheat.
|
||||
/// @return A pointer to the description of this cheat.
|
||||
const char* GetDescription() const
|
||||
{
|
||||
return _description;
|
||||
}
|
||||
|
||||
/// @brief Gets a pointer to the data of this cheat.
|
||||
/// @param cheatDataLength The length of the cheat data is returned in this reference.
|
||||
/// @return A pointer to the cheat data.
|
||||
/// This pointer is only valid for the lifetime of the \see GameCheats instance this cheat belongs to.
|
||||
const void* GetCheatData(u32& cheatDataLength) const
|
||||
{
|
||||
cheatDataLength = _cheatDataLength;
|
||||
return _cheatData;
|
||||
}
|
||||
|
||||
/// @brief Gets whether this cheat is active (enabled) or not.
|
||||
/// @return \c true when this cheat is active, or \c false when not active.
|
||||
bool GetIsCheatActive() const
|
||||
{
|
||||
return ((*_flagsPointer >> 24) & 1) == 1;
|
||||
}
|
||||
|
||||
/// @brief Sets whether this cheat is active (enabled) or not.
|
||||
/// @param isCheatActive \c true to enable this cheat, or \c false to disable this cheat.
|
||||
void SetIsCheatActive(bool isCheatActive) const
|
||||
{
|
||||
u32 flags = *_flagsPointer;
|
||||
@@ -34,7 +55,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
u32* _flagsPointer;
|
||||
const void* _cheatData;
|
||||
u32 _cheatDataLength;
|
||||
const char* _name = nullptr;
|
||||
const char* _description = nullptr;
|
||||
u32* _flagsPointer = nullptr;
|
||||
const void* _cheatData = nullptr;
|
||||
u32 _cheatDataLength = 0;
|
||||
};
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "CheatTreeItem.h"
|
||||
#include "Cheat.h"
|
||||
#include "ICheatCategory.h"
|
||||
|
||||
class CheatCategory : public CheatTreeItem, public ICheatCategory
|
||||
/// @brief Class representing a cheat category, containing sub-categories and cheats.
|
||||
class CheatCategory : public ICheatCategory
|
||||
{
|
||||
public:
|
||||
CheatCategory()
|
||||
: _isMaxOneCheatActive(false), _subCategories(nullptr), _numberOfSubCategories(0)
|
||||
, _cheats(nullptr), _numberOfCheats(0) { }
|
||||
CheatCategory() { }
|
||||
|
||||
CheatCategory(const char* name, const char* description, bool isMaxOneCheatActive,
|
||||
CheatCategory* subCategories, u32 numberOfSubCategories, Cheat* cheats, u32 numberOfCheats)
|
||||
: CheatTreeItem(name, description), _isMaxOneCheatActive(isMaxOneCheatActive)
|
||||
: _name(name), _description(description), _isMaxOneCheatActive(isMaxOneCheatActive)
|
||||
, _subCategories(subCategories), _numberOfSubCategories(numberOfSubCategories)
|
||||
, _cheats(cheats), _numberOfCheats(numberOfCheats) { }
|
||||
|
||||
@@ -56,6 +53,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
const char* GetName() const override
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
/// @brief Gets the description of this cheat category.
|
||||
/// @return A pointer to the description of this cheat category.
|
||||
const char* GetDescription() const
|
||||
{
|
||||
return _description;
|
||||
}
|
||||
|
||||
bool GetIsMaxOneCheatActive() const override
|
||||
{
|
||||
return _isMaxOneCheatActive;
|
||||
@@ -74,9 +83,11 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
bool _isMaxOneCheatActive;
|
||||
CheatCategory* _subCategories;
|
||||
u32 _numberOfSubCategories;
|
||||
Cheat* _cheats;
|
||||
u32 _numberOfCheats;
|
||||
const char* _name = nullptr;
|
||||
const char* _description = nullptr;
|
||||
bool _isMaxOneCheatActive = false;
|
||||
CheatCategory* _subCategories = nullptr;
|
||||
u32 _numberOfSubCategories = 0;
|
||||
Cheat* _cheats = nullptr;
|
||||
u32 _numberOfCheats = 0;
|
||||
};
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
class CheatTreeItem
|
||||
{
|
||||
public:
|
||||
const char* GetName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
const char* GetDescription() const
|
||||
{
|
||||
return _description;
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* _name;
|
||||
const char* _description;
|
||||
|
||||
CheatTreeItem()
|
||||
: _name(nullptr), _description(nullptr) { }
|
||||
|
||||
CheatTreeItem(const char* name, const char* description)
|
||||
: _name(name), _description(description) { }
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "ICheatRepository.h"
|
||||
|
||||
/// @brief Class implementing an empty cheat repository.
|
||||
class EmptyCheatRepository : public ICheatRepository
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "CheatCategory.h"
|
||||
#include "ICheatCategory.h"
|
||||
|
||||
/// @brief Class holding the cheats for a game.
|
||||
class GameCheats : public ICheatCategory
|
||||
{
|
||||
public:
|
||||
@@ -24,16 +25,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Gets the name of the game.
|
||||
/// @return A pointer to the name of the game.
|
||||
const char* GetGameName() const
|
||||
{
|
||||
return _gameName;
|
||||
}
|
||||
|
||||
bool GetIsMaxOneCheatActive() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const CheatCategory* GetCategories(u32& numberOfCategories) const override
|
||||
{
|
||||
numberOfCategories = _numberOfCategories;
|
||||
@@ -46,6 +44,9 @@ public:
|
||||
return _cheats;
|
||||
}
|
||||
|
||||
/// @brief Gets a pointer to the cheat data.
|
||||
/// @param cheatDataLength The length of the cheat data is returned in this reference.
|
||||
/// @return A pointer to the cheat data. This pointer is only valid for the lifetime of this \see GameCheats instance.
|
||||
u8* GetCheatData(u32& cheatDataLength) const
|
||||
{
|
||||
cheatDataLength = _cheatDataLength;
|
||||
@@ -66,4 +67,15 @@ private:
|
||||
u32 _numberOfCategories;
|
||||
Cheat* _cheats;
|
||||
u32 _numberOfCheats;
|
||||
|
||||
// From ICheatCategory
|
||||
const char* GetName() const override
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
bool GetIsMaxOneCheatActive() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,13 +3,28 @@
|
||||
class CheatCategory;
|
||||
class Cheat;
|
||||
|
||||
/// @brief Interface for a collection of cheats.
|
||||
class ICheatCategory
|
||||
{
|
||||
public:
|
||||
virtual ~ICheatCategory() = default;
|
||||
|
||||
/// @brief Gets the name of this category.
|
||||
/// @return The name of this category.
|
||||
virtual const char* GetName() const = 0;
|
||||
|
||||
/// @brief Indicates if only one cheat in this category is allowed to be on or not.
|
||||
/// @return \c true when only one cheat is allowed to be active in this category, or \c false otherwise.
|
||||
virtual bool GetIsMaxOneCheatActive() const = 0;
|
||||
|
||||
/// @brief Gets the sub-categories of this category.
|
||||
/// @param numberOfCategories The number of categories is returned through this reference.
|
||||
/// @return A pointer to an array of categories. This may be \c nullptr when \p numberOfCategories is 0.
|
||||
virtual const CheatCategory* GetCategories(u32& numberOfCategories) const;
|
||||
|
||||
/// @brief Gets the cheats in this category.
|
||||
/// @param numberOfCheats The number of cheats is returned through this reference.
|
||||
/// @return A pointer to an array of cheats. This may be \c nullptr when \p numberOfCheats is 0.
|
||||
virtual const Cheat* GetCheats(u32& numberOfCheats) const;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -2,12 +2,19 @@
|
||||
#include "GameCheats.h"
|
||||
#include "fat/FastFileRef.h"
|
||||
|
||||
/// @brief Interface for a repository providing access to cheats.
|
||||
class ICheatRepository
|
||||
{
|
||||
public:
|
||||
virtual ~ICheatRepository() { }
|
||||
|
||||
/// @brief Gets the available cheats for the given \p romFile.
|
||||
/// @param romFile Reference to the rom file.
|
||||
/// @return A unique pointer to the found cheats, or an empty unique pointer when no cheats were found.
|
||||
virtual std::unique_ptr<GameCheats> GetCheatsForGame(const FastFileRef& romFile) const = 0;
|
||||
|
||||
/// @brief Writes the enable/disabled status of the given \p cheats.
|
||||
/// @param cheats The cheats to update.
|
||||
virtual void UpdateEnabledCheatsForGame(const std::unique_ptr<GameCheats>& cheats) const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -3,9 +3,13 @@
|
||||
#include "GameCheats.h"
|
||||
#include "picoLoader7.h"
|
||||
|
||||
/// @brief Factory for creating Pico Loader compatible cheat data.
|
||||
class PicoLoaderCheatDataFactory
|
||||
{
|
||||
public:
|
||||
/// @brief Converts the given \p gameCheats to Pico Loader format. Only the enabled cheats will be included.
|
||||
/// @param gameCheats The cheats to convert.
|
||||
/// @return Pointer to the created cheat data.
|
||||
pload_cheats_t* CreateCheatData(const std::unique_ptr<GameCheats>& gameCheats) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
/// @brief Struct representing an index entry of usrcheat.dat.
|
||||
struct usr_cheat_index_entry_t
|
||||
{
|
||||
u32 gameCode;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "ICheatRepository.h"
|
||||
#include "UsrCheatDat.h"
|
||||
|
||||
/// @brief Class implementing a cheat repository for usrcheat.dat.
|
||||
class UsrCheatRepository : public ICheatRepository
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -2,8 +2,12 @@
|
||||
#include <memory>
|
||||
#include "UsrCheatRepository.h"
|
||||
|
||||
/// @brief Factory for constructing a \see UsrCheatRepository for a usrcheat.dat file.
|
||||
class UsrCheatRepositoryFactory
|
||||
{
|
||||
public:
|
||||
/// @brief Constructs a \see UsrCheatRepository for the given \p usrCheatDatPath.
|
||||
/// @param usrCheatDatPath The path to the usrcheat.dat file.
|
||||
/// @return A unique pointer to the constructed repository, or an empty unique pointer when construction failed.
|
||||
std::unique_ptr<UsrCheatRepository> FromUsrCheatDat(const TCHAR* usrCheatDatPath);
|
||||
};
|
||||
|
||||
@@ -24,7 +24,7 @@ CheatsViewModel::CheatsViewModel(const FileInfo& romFileInfo, IRomBrowserControl
|
||||
});
|
||||
}
|
||||
|
||||
void CheatsViewModel::ItemActivated()
|
||||
void CheatsViewModel::ActivateSelectedItem()
|
||||
{
|
||||
auto cheatCategory = GetCurrentCheatCategory();
|
||||
u32 numberOfCategories = 0;
|
||||
@@ -58,21 +58,25 @@ void CheatsViewModel::ItemActivated()
|
||||
}
|
||||
}
|
||||
|
||||
void CheatsViewModel::Back()
|
||||
bool CheatsViewModel::NavigateUp()
|
||||
{
|
||||
if (_categoryStackLevel == 0)
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectedItem = _categoryStack[_categoryStackLevel].index;
|
||||
_categoryStack[_categoryStackLevel--] = { nullptr, 0 };
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void CheatsViewModel::Close()
|
||||
{
|
||||
_categoryStack.fill({ nullptr, 0 });
|
||||
|
||||
if (_changed)
|
||||
{
|
||||
// Save which cheats are enabled/disabled
|
||||
|
||||
@@ -10,26 +10,57 @@
|
||||
class CheatsViewModel
|
||||
{
|
||||
public:
|
||||
/// @brief Enum representing the state of the cheats panel.
|
||||
enum class State
|
||||
{
|
||||
/// @brief Cheats are being loaded.
|
||||
Loading,
|
||||
|
||||
/// @brief No cheats were found.
|
||||
NoCheats,
|
||||
|
||||
/// @brief Cheats are being displayed.
|
||||
DisplayCheats
|
||||
};
|
||||
|
||||
CheatsViewModel(const FileInfo& romFileInfo, IRomBrowserController* romBrowserController);
|
||||
|
||||
void ItemActivated();
|
||||
void Back();
|
||||
/// @brief Activates the selected cheat or category.
|
||||
void ActivateSelectedItem();
|
||||
|
||||
/// @brief Navigates up in the cheat hierachy, or closes the cheats panel when at the root.
|
||||
/// @return \c true when navigation happened in the cheats tree, or \c false when the cheats panel was closed.
|
||||
bool NavigateUp();
|
||||
|
||||
/// @brief Closes the cheats panel.
|
||||
void Close();
|
||||
|
||||
/// @brief Disables all cheats.
|
||||
void DisableAllCheats();
|
||||
|
||||
/// @brief Gets the current state of the cheats panel.
|
||||
/// @return The current state of the cheats panel.
|
||||
State GetState() const { return _state; }
|
||||
|
||||
/// @brief Gets the current cheat category.
|
||||
/// @return The current cheat category.
|
||||
const ICheatCategory* GetCurrentCheatCategory() const { return _categoryStack[_categoryStackLevel].cheatCategory; }
|
||||
|
||||
/// @brief Gets the index of the selected item.
|
||||
/// @return The index of the selected item.
|
||||
constexpr int GetSelectedItem() const { return _selectedItem; }
|
||||
|
||||
/// @brief Sets the index of the selected item.
|
||||
/// @param selectedItem The index of the selected item to set.
|
||||
void SetSelectedItem(int selectedItem) { _selectedItem = selectedItem; }
|
||||
|
||||
/// @brief Returns whether the category name should be displayed.
|
||||
/// @return \c true when the category name should be displayed, or \c false otherwise.
|
||||
bool ShouldShowCategoryName() const
|
||||
{
|
||||
return _categoryStackLevel > 0;
|
||||
}
|
||||
|
||||
private:
|
||||
struct CategoryStackEntry
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
class MaterialColorScheme;
|
||||
class IFontRepository;
|
||||
|
||||
/// @brief List item view for the cheats panel, representing a single cheat or cheat category.
|
||||
class CheatListItemView : public ViewContainer
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "cheats/Cheat.h"
|
||||
#include "CheatListItemView.h"
|
||||
|
||||
/// @brief Recycler adapter for cheats.
|
||||
class CheatsAdapter : public RecyclerAdapter
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
#define TITLE_LABEL_X 20
|
||||
#define TITLE_LABEL_Y 16
|
||||
|
||||
#define CATEGORY_NAME_LABEL_X (TITLE_LABEL_X + 43)
|
||||
#define CATEGORY_NAME_LABEL_Y (TITLE_LABEL_Y + 1)
|
||||
|
||||
#define NO_CHEATS_FOUND_LABEL_X 20
|
||||
#define NO_CHEATS_FOUND_LABEL_Y 36
|
||||
|
||||
@@ -32,7 +35,7 @@ CheatsBottomSheetView::CheatsBottomSheetView(std::unique_ptr<CheatsViewModel> vi
|
||||
FocusManager* focusManager)
|
||||
: _viewModel(std::move(viewModel))
|
||||
, _titleLabel(64, 16, 25, fontRepository->GetFont(FontType::Medium11))
|
||||
, _noCheatsFoundLabel(96, 16, 25, fontRepository->GetFont(FontType::Regular10))
|
||||
, _secondaryLabel(177, 16, 64, fontRepository->GetFont(FontType::Regular10))
|
||||
, _descriptionLabel(224, 16, 256, fontRepository->GetFont(FontType::Medium7_5))
|
||||
, _cheatListRecycler(std::make_unique<RecyclerView>(
|
||||
LIST_X, LIST_Y, LIST_WIDTH, LIST_HEIGHT, RecyclerView::Mode::VerticalList))
|
||||
@@ -41,11 +44,12 @@ CheatsBottomSheetView::CheatsBottomSheetView(std::unique_ptr<CheatsViewModel> vi
|
||||
, _focusManager(focusManager)
|
||||
{
|
||||
_titleLabel.SetText(u"Cheats");
|
||||
_noCheatsFoundLabel.SetText(u"No cheats found.");
|
||||
_secondaryLabel.SetText(u"No cheats found.");
|
||||
_secondaryLabel.SetEllipsisStyle(LabelView::EllipsisStyle::Ellipsis);
|
||||
_descriptionLabel.SetEllipsisStyle(LabelView::EllipsisStyle::Marquee);
|
||||
_descriptionLabel.SetText("");
|
||||
AddChildTail(&_titleLabel);
|
||||
AddChildTail(&_noCheatsFoundLabel);
|
||||
AddChildTail(&_secondaryLabel);
|
||||
AddChildTail(&_descriptionLabel);
|
||||
AddChildTail(_cheatListRecycler.get());
|
||||
}
|
||||
@@ -80,7 +84,14 @@ void CheatsBottomSheetView::InitVram(const VramContext& vramContext)
|
||||
void CheatsBottomSheetView::Update()
|
||||
{
|
||||
_titleLabel.SetPosition(TITLE_LABEL_X, _position.y + TITLE_LABEL_Y);
|
||||
_noCheatsFoundLabel.SetPosition(NO_CHEATS_FOUND_LABEL_X, _position.y + NO_CHEATS_FOUND_LABEL_Y);
|
||||
if (_viewModel->GetState() == CheatsViewModel::State::DisplayCheats)
|
||||
{
|
||||
_secondaryLabel.SetPosition(CATEGORY_NAME_LABEL_X, _position.y + CATEGORY_NAME_LABEL_Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
_secondaryLabel.SetPosition(NO_CHEATS_FOUND_LABEL_X, _position.y + NO_CHEATS_FOUND_LABEL_Y);
|
||||
}
|
||||
_descriptionLabel.SetPosition(DESCRIPTION_LABEL_X, _position.y + DESCRIPTION_LABEL_Y);
|
||||
_cheatListRecycler->SetPosition(LIST_X, _position.y + LIST_Y);
|
||||
if (_viewModel->GetState() == CheatsViewModel::State::DisplayCheats)
|
||||
@@ -168,11 +179,12 @@ void CheatsBottomSheetView::Draw(GraphicsContext& graphicsContext)
|
||||
_titleLabel.SetForegroundColor(_materialColorScheme->onSurface);
|
||||
_titleLabel.Draw(graphicsContext);
|
||||
|
||||
if (_viewModel->GetState() == CheatsViewModel::State::NoCheats)
|
||||
if (_viewModel->GetState() == CheatsViewModel::State::NoCheats ||
|
||||
_viewModel->ShouldShowCategoryName())
|
||||
{
|
||||
_noCheatsFoundLabel.SetBackgroundColor(backColor);
|
||||
_noCheatsFoundLabel.SetForegroundColor(_materialColorScheme->onSurface);
|
||||
_noCheatsFoundLabel.Draw(graphicsContext);
|
||||
_secondaryLabel.SetBackgroundColor(backColor);
|
||||
_secondaryLabel.SetForegroundColor(_materialColorScheme->onSurfaceVariant);
|
||||
_secondaryLabel.Draw(graphicsContext);
|
||||
}
|
||||
|
||||
_descriptionLabel.SetBackgroundColor(backColor);
|
||||
@@ -190,9 +202,10 @@ bool CheatsBottomSheetView::HandleInput(const InputProvider& inputProvider, Focu
|
||||
if (focusManager.IsFocusInside(_cheatListRecycler.get()))
|
||||
{
|
||||
auto oldCategory = _viewModel->GetCurrentCheatCategory();
|
||||
_viewModel->ItemActivated();
|
||||
_viewModel->ActivateSelectedItem();
|
||||
if (oldCategory != _viewModel->GetCurrentCheatCategory())
|
||||
{
|
||||
_secondaryLabel.SetText(_viewModel->GetCurrentCheatCategory()->GetName());
|
||||
UpdateCheatList();
|
||||
}
|
||||
|
||||
@@ -202,8 +215,8 @@ bool CheatsBottomSheetView::HandleInput(const InputProvider& inputProvider, Focu
|
||||
else if (inputProvider.Triggered(InputKey::B))
|
||||
{
|
||||
auto oldCategory = _viewModel->GetCurrentCheatCategory();
|
||||
_viewModel->Back();
|
||||
if (oldCategory != _viewModel->GetCurrentCheatCategory())
|
||||
if (_viewModel->NavigateUp() &&
|
||||
oldCategory != _viewModel->GetCurrentCheatCategory())
|
||||
{
|
||||
UpdateCheatList();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ class MaterialColorScheme;
|
||||
class IFontRepository;
|
||||
class IVramManager;
|
||||
|
||||
/// @brief Bottom sheet for browsing and enabling/disabling cheats.
|
||||
class CheatsBottomSheetView : public BottomSheetView
|
||||
{
|
||||
public:
|
||||
@@ -40,7 +41,7 @@ public:
|
||||
private:
|
||||
std::unique_ptr<CheatsViewModel> _viewModel;
|
||||
Label2DView _titleLabel;
|
||||
Label2DView _noCheatsFoundLabel;
|
||||
Label2DView _secondaryLabel;
|
||||
Label2DView _descriptionLabel;
|
||||
std::unique_ptr<RecyclerView> _cheatListRecycler;
|
||||
CheatsAdapter* _cheatsAdapter = nullptr;
|
||||
|
||||
15
docs/Cheats.md
Normal file
15
docs/Cheats.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Cheats
|
||||
Pico Launcher supports cheats from a `usrcheat.dat` file placed at `/_pico/usrcheat.dat`. The file stores the cheat codes, as well as which cheats are enabled. When a game is started which has cheats enabled, the enabled cheats are passed to Pico Loader.
|
||||
|
||||
## Usage
|
||||
To display the available cheats highlight a game in the rom browser and press Y to access the cheats panel.
|
||||
|
||||

|
||||
|
||||
### Controls
|
||||
- DPAD up/down: Scroll through the list of cheats.
|
||||
- L and R: Scroll quickly when there are many cheats.
|
||||
- A: Toggle a cheat on/off, or go into a cheat category.
|
||||
- B: Go up in the cheat hierarchy, or close the cheats panel when at the root.
|
||||
- Y: Close the cheats panel.
|
||||
- X: Disable all cheats.
|
||||
@@ -12,6 +12,7 @@ From here you can browse your SD card to launch homebrew and games.
|
||||
- A: Open a folder, or to launch a homebrew or game.
|
||||
- B: Go to the parent folder or close a menu.
|
||||
- L and R: Scroll quickly when there are many items in a folder.
|
||||
- Y: Open the cheats panel (see [Cheats](Cheats.md)).
|
||||
|
||||
The back arrow on the top left of the bottom screen can also be used to go up to the parent folder.
|
||||
|
||||
|
||||
BIN
docs/images/Cheats.png
Normal file
BIN
docs/images/Cheats.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
Reference in New Issue
Block a user