Skip to content

Commit

Permalink
Configurable key binding and offset (mCount) save/restore (#10)
Browse files Browse the repository at this point in the history
* working on mcount offset

* mcount and configure works

* format

* extra space
  • Loading branch information
Pistonight authored Sep 10, 2022
1 parent c2041f5 commit faf8486
Show file tree
Hide file tree
Showing 36 changed files with 1,225 additions and 904 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# CHANGELOG

### `1.6.0-SS1.0` `2022-08-26` `LATEST`
### `1.6.0-SS1.1` `2022-09-10` `LATEST`
- Add save and restore offset between pouch item list count (i.e. `mCount`) and actual inventory size to level 3
- Make save and restore key binding configurable
- In setting mode, hold the current key binding for 3 seconds, then hold the new key binding for 3 seconds.

### `1.6.0-SS1.0` `2022-08-26`
- Level 3 save and restore
- Change save/restore key combo to include both left triggers (`L` and `ZL`). This is so that you don't accidentally save or restore during a super launch
- Enable logging (except for debug logging) in ship builds
Expand Down
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,13 @@ In setting mode. You can switch between levels of save state.

- Hold `L` for 1 second: Decrease level
- Hold `R` for 1 second: Increase level
- Hold save/restore to memory/file key binding for 3 seconds: Change the key binding (Hold the new keys for 3 seconds to change)

The level settings are preserved through restarts, meaning that when you close the game on a level, you will be on the same level when you boot up the game again.
The settings are preserved through restarts. For example, if you close the game on a level, you will be on the same level when you boot up the game again.

If you somehow messed up the settings and want to reset them, you can do so by deleting `/botwsavs/worker.txt` file on your sd card.

### Levels

There are currently 4 levels:

Expand Down Expand Up @@ -101,6 +106,8 @@ Level 3 save state includes everything available, which includes all from Level
- Flame Resist
- Shock Resist
- Stealth
- Inventory offset:
- i.e. the number of broken slots

### Save/Restore with Different Levels
If you save a state with a high level (for example, level 3), then switch to a lower level (for example, level 1) and restore, only the lower level values will be restored. However, the state still contains the higher level data. You can switch back to the higher level and be able to restore all the values
Expand All @@ -110,7 +117,16 @@ If you save a state with a low level (for example, level 1), then switch to a hi
You need to lower the setting level to restore!
```

### Save State Transfer Script
### Change Key Binding

You can change the key binding for save/restore following these steps:
1. Hold all triggers + whistle for 3 seconds to enter setting mode
2. Hold the current key binding for the one you want to change for 3 seconds
3. Let go of all buttons. You will see a message telling you to hold the new binding for 3 seconds
4. Hold the new binding for 3 seconds and you will see a confirmation message
5. Hold all triggers + whistle for 3 seconds to exit setting mode

### FTP Transfer Script
A python script `ftp.py` is also included for transfering save state files over FTP (with the `ftpd` homebrew app). Run `python3 ftp.py` to see how to use.

(This has nothing to do in game, just makes managing the save state files generated by the mod easier)
Expand Down Expand Up @@ -143,7 +159,7 @@ Need Python 3. (3.10 is preferred but other version probably works as well).

Install these packages
```
python3 -m pip install toml pylint pylint-quotes keystone
python3 -m pip install toml pylint pylint-quotes keystone-engine
```
#### clang-format
clang-format-12 is required. Run this on linux or the mac-equivalent on mac
Expand Down
7 changes: 5 additions & 2 deletions lib/botw/Game/UI/uiPauseMenuDataMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ class PauseMenuDataMgr {

void grabbedItemStuff(PouchItem* item);

// SAVE-STATE-HACK expose equipped weapons aray
// SAVE-STATE-HACK expose equipped weapons array
PouchItem* getEquippedWeapon(PouchItemType type) {
return mEquippedWeapons[u32(type)];
}
Expand Down Expand Up @@ -412,9 +412,12 @@ class PauseMenuDataMgr {
sead::SafeArray<PouchItem, NumPouchItemsMax> buffer;
};

// BOTW-SAVE-STATE hack: make these public
public:
sead::OffsetList<PouchItem>& getItems() { return mItemLists.list1; }
const sead::OffsetList<PouchItem>& getItems() const { return mItemLists.list1; }

// BOTW-SAVE-STATE hack end
private:
// FIXME: types
bool useItemFromRecipe(Lists* lists, void* unk, int multiplier, PouchItem* item);

Expand Down
11 changes: 11 additions & 0 deletions lib/sead/include/container/seadListImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ class ListImpl

bool isEmpty() const { return mCount == 0; }
s32 size() const { return mCount; }
// BOTW-sAVE-STATE hack
void setSize(s32 size) { mCount = size; }
s32 sizeSlow() const {
s32 size = 0;
ListNode* ptr = mStartEnd.mNext;
while(ptr && ptr != &mStartEnd){
ptr = ptr->mNext;
size++;
}
return size;
}

void reverse();
void shuffle();
Expand Down
37 changes: 5 additions & 32 deletions src/core/Controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@

namespace botwsavs::core {

Controller::~Controller() {
mpController = nullptr;
}

bool Controller::TryGetController() {
if (mpController) {
return true;
Expand All @@ -27,41 +23,18 @@ bool Controller::TryGetController() {
return false;
}

fs::FileBuffer buf;
buf.SafeAppendF("Found controller instance: %p", pController);
info(buf);
infof("Found controller instance: %p", pController);

mpController = pController;
return true;
}

bool Controller::ShouldSaveState() {
return mpController->isHoldAll(Key::ZL | Key::L | Key::Plus | Key::DpadLeft) &&
!mpController->isHold(Key::RStick);
}

bool Controller::ShouldRestoreState() {
return mpController->isHoldAll(Key::ZL | Key::L | Key::Plus | Key::DpadRight) &&
!mpController->isHold(Key::RStick);
}

bool Controller::ShouldSaveStateToFile() {
return mpController->isHoldAll(Key::ZL | Key::L | Key::Plus | Key::DpadLeft | Key::RStick);
bool Controller::IsOnlyHolding(u32 mask) {
return mpController->isHoldAll(mask) && !mpController->isHold(~mask);
}

bool Controller::ShouldRestoreStateFromFile() {
return mpController->isHoldAll(Key::ZL | Key::L | Key::Plus | Key::DpadRight | Key::RStick);
}

bool Controller::ShouldSwitchMode() {
return mpController->isHoldAll(Key::DpadDown | Key::ZL | Key::ZR | Key::L | Key::R);
}

bool Controller::ShouldIncreaseLevel() {
return mpController->isHold(Key::R);
}
bool Controller::ShouldDecreaseLevel() {
return mpController->isHold(Key::L);
u32 Controller::GetHoldKeys() {
return mpController->getHoldMask();
}

} // namespace botwsavs::core
29 changes: 5 additions & 24 deletions src/core/Controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,20 @@ namespace botwsavs {

namespace core {
class Controller {
public:
enum Key : u32 {
B = 1 << 1,
ZL = 1 << 2,
ZR = 1 << 5,
RStick = 1 << 6,
Plus = 1 << 10,

L = 1 << 13,
R = 1 << 14,
DpadDown = 1 << 17,
DpadLeft = 1 << 18,
DpadRight = 1 << 19
};

public:
Controller() = default;
~Controller();
~Controller() { mpController = nullptr; }

bool isInitialized() {
bool IsInitialized() {
if (!mpController) {
TryGetController();
}
return mpController != nullptr;
}

bool ShouldSaveState();
bool ShouldRestoreState();
bool ShouldSaveStateToFile();
bool ShouldRestoreStateFromFile();
bool ShouldSwitchMode();
bool ShouldIncreaseLevel();
bool ShouldDecreaseLevel();
bool IsOnlyHolding(u32 mask);

u32 GetHoldKeys();

private:
// Return true if controller is cached succesfully
Expand Down
88 changes: 88 additions & 0 deletions src/core/Key.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#pragma once

#include "types.h"
#include "util/StringBuffer.hpp"

namespace botwsavs::core {
enum Key : u32 {
A = 0,
B = 1 << 1,
ZL = 1 << 2,
Y = 1 << 3,
X = 1 << 4,
ZR = 1 << 5,
RStick = 1 << 6,
LStick = 1 << 7,

Minus = (1 << 9) | (1 << 12),
Plus = (1 << 10) | (1 << 11),

L = 1 << 13,
R = 1 << 14,

DpadUp = 1 << 16,
DpadDown = 1 << 17,
DpadLeft = 1 << 18,
DpadRight = 1 << 19
};

namespace key {
template <u32 L>
void GetKeyString(u32 mask, util::StringBuffer<L>& outBuffer) {
static_assert(L >= 100, "Key string buffer length should be at least 100");
outBuffer.Clear();
if (mask == 0) {
return;
}
if (mask & Key::A) {
outBuffer.SafeAppend("A+");
}
if (mask & Key::B) {
outBuffer.SafeAppend("B+");
}
if (mask & Key::X) {
outBuffer.SafeAppend("X+");
}
if (mask & Key::Y) {
outBuffer.SafeAppend("Y+");
}
if (mask & Key::L) {
outBuffer.SafeAppend("L+");
}
if (mask & Key::R) {
outBuffer.SafeAppend("R+");
}
if (mask & Key::ZL) {
outBuffer.SafeAppend("ZL+");
}
if (mask & Key::ZR) {
outBuffer.SafeAppend("ZR+");
}
if (mask & Key::DpadUp) {
outBuffer.SafeAppend("DpadUp+");
}
if (mask & Key::DpadDown) {
outBuffer.SafeAppend("DpadDown+");
}
if (mask & Key::DpadLeft) {
outBuffer.SafeAppend("DpadLeft+");
}
if (mask & Key::DpadRight) {
outBuffer.SafeAppend("DpadRight+");
}
if (mask & Key::Minus) {
outBuffer.SafeAppend("Minus+");
}
if (mask & Key::Plus) {
outBuffer.SafeAppend("Plus+");
}
if (mask & Key::LStick) {
outBuffer.SafeAppend("LStick+");
}
if (mask & Key::RStick) {
outBuffer.SafeAppend("RStick+");
}
outBuffer.SafeDeleteEnd(1);
}
} // namespace key
} // namespace botwsavs::core
66 changes: 66 additions & 0 deletions src/core/KeyMgr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "KeyMgr.hpp"
#include "fs/ConfigFile.hpp"
#include "fs/Logger.hpp"

namespace botwsavs::core {

bool KeyMgr::DidHoldFor(u32 keys, u32 seconds) {
if (mHoldingKeys != keys) {
mHoldCounter = 0;
mHoldingKeys = keys;
} else {
mHoldCounter++;
}
// 1 tick = 3 frames
// 1s = 30 frames = 10 ticks
u32 ticks = seconds * 10;
if (mHoldCounter >= ticks) {
mHoldCounter = 0;
return true;
}
return false;
}

void KeyMgr::StartConfigure(u32* configureKey) {
info("Configuring key binding");
ClearHold();
mpConfiguringKey = configureKey;
mConfigureCounter = 0;
}

KeyMgr::ConfigureResult KeyMgr::FinishConfigure(u32 newKey) {
if (newKey == 0) {
mConfigureCounter = 0;
return ConfigureResult::Pending;
}
if (mConfigureCounter < 30) {
mConfigureCounter++;
return ConfigureResult::Pending;
}

ClearHold();
if (newKey == 0) {
mpConfiguringKey = nullptr;
return ConfigureResult::FailEmpty;
}
*mpConfiguringKey = newKey;
mpConfiguringKey = nullptr;
infof("New combo: %x", newKey);
return ConfigureResult::Success;
}

void KeyMgr::Save(fs::ConfigFile& file) const {
file.WriteInteger(named(mKeySave));
file.WriteInteger(named(mKeySaveFile));
file.WriteInteger(named(mKeyRestore));
file.WriteInteger(named(mKeyRestoreFile));
}

void KeyMgr::Load(fs::ConfigFile& file) {
file.ReadInteger(&mKeySave);
file.ReadInteger(&mKeySaveFile);
file.ReadInteger(&mKeyRestore);
file.ReadInteger(&mKeyRestoreFile);
}

} // namespace botwsavs::core
Loading

0 comments on commit faf8486

Please sign in to comment.