Skip to content

Commit faf8486

Browse files
authored
Configurable key binding and offset (mCount) save/restore (#10)
* working on mcount offset * mcount and configure works * format * extra space
1 parent c2041f5 commit faf8486

36 files changed

+1225
-904
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# CHANGELOG
22

3-
### `1.6.0-SS1.0` `2022-08-26` `LATEST`
3+
### `1.6.0-SS1.1` `2022-09-10` `LATEST`
4+
- Add save and restore offset between pouch item list count (i.e. `mCount`) and actual inventory size to level 3
5+
- Make save and restore key binding configurable
6+
- In setting mode, hold the current key binding for 3 seconds, then hold the new key binding for 3 seconds.
7+
8+
### `1.6.0-SS1.0` `2022-08-26`
49
- Level 3 save and restore
510
- 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
611
- Enable logging (except for debug logging) in ship builds

README.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,13 @@ In setting mode. You can switch between levels of save state.
5656

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

60-
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.
61+
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.
62+
63+
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.
64+
65+
### Levels
6166

6267
There are currently 4 levels:
6368

@@ -101,6 +106,8 @@ Level 3 save state includes everything available, which includes all from Level
101106
- Flame Resist
102107
- Shock Resist
103108
- Stealth
109+
- Inventory offset:
110+
- i.e. the number of broken slots
104111

105112
### Save/Restore with Different Levels
106113
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
@@ -110,7 +117,16 @@ If you save a state with a low level (for example, level 1), then switch to a hi
110117
You need to lower the setting level to restore!
111118
```
112119

113-
### Save State Transfer Script
120+
### Change Key Binding
121+
122+
You can change the key binding for save/restore following these steps:
123+
1. Hold all triggers + whistle for 3 seconds to enter setting mode
124+
2. Hold the current key binding for the one you want to change for 3 seconds
125+
3. Let go of all buttons. You will see a message telling you to hold the new binding for 3 seconds
126+
4. Hold the new binding for 3 seconds and you will see a confirmation message
127+
5. Hold all triggers + whistle for 3 seconds to exit setting mode
128+
129+
### FTP Transfer Script
114130
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.
115131

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

144160
Install these packages
145161
```
146-
python3 -m pip install toml pylint pylint-quotes keystone
162+
python3 -m pip install toml pylint pylint-quotes keystone-engine
147163
```
148164
#### clang-format
149165
clang-format-12 is required. Run this on linux or the mac-equivalent on mac

lib/botw/Game/UI/uiPauseMenuDataMgr.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ class PauseMenuDataMgr {
376376

377377
void grabbedItemStuff(PouchItem* item);
378378

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

415+
// BOTW-SAVE-STATE hack: make these public
416+
public:
415417
sead::OffsetList<PouchItem>& getItems() { return mItemLists.list1; }
416418
const sead::OffsetList<PouchItem>& getItems() const { return mItemLists.list1; }
417-
419+
// BOTW-SAVE-STATE hack end
420+
private:
418421
// FIXME: types
419422
bool useItemFromRecipe(Lists* lists, void* unk, int multiplier, PouchItem* item);
420423

lib/sead/include/container/seadListImpl.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ class ListImpl
3737

3838
bool isEmpty() const { return mCount == 0; }
3939
s32 size() const { return mCount; }
40+
// BOTW-sAVE-STATE hack
41+
void setSize(s32 size) { mCount = size; }
42+
s32 sizeSlow() const {
43+
s32 size = 0;
44+
ListNode* ptr = mStartEnd.mNext;
45+
while(ptr && ptr != &mStartEnd){
46+
ptr = ptr->mNext;
47+
size++;
48+
}
49+
return size;
50+
}
4051

4152
void reverse();
4253
void shuffle();

src/core/Controller.cpp

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@
66

77
namespace botwsavs::core {
88

9-
Controller::~Controller() {
10-
mpController = nullptr;
11-
}
12-
139
bool Controller::TryGetController() {
1410
if (mpController) {
1511
return true;
@@ -27,41 +23,18 @@ bool Controller::TryGetController() {
2723
return false;
2824
}
2925

30-
fs::FileBuffer buf;
31-
buf.SafeAppendF("Found controller instance: %p", pController);
32-
info(buf);
26+
infof("Found controller instance: %p", pController);
3327

3428
mpController = pController;
3529
return true;
3630
}
3731

38-
bool Controller::ShouldSaveState() {
39-
return mpController->isHoldAll(Key::ZL | Key::L | Key::Plus | Key::DpadLeft) &&
40-
!mpController->isHold(Key::RStick);
41-
}
42-
43-
bool Controller::ShouldRestoreState() {
44-
return mpController->isHoldAll(Key::ZL | Key::L | Key::Plus | Key::DpadRight) &&
45-
!mpController->isHold(Key::RStick);
46-
}
47-
48-
bool Controller::ShouldSaveStateToFile() {
49-
return mpController->isHoldAll(Key::ZL | Key::L | Key::Plus | Key::DpadLeft | Key::RStick);
32+
bool Controller::IsOnlyHolding(u32 mask) {
33+
return mpController->isHoldAll(mask) && !mpController->isHold(~mask);
5034
}
5135

52-
bool Controller::ShouldRestoreStateFromFile() {
53-
return mpController->isHoldAll(Key::ZL | Key::L | Key::Plus | Key::DpadRight | Key::RStick);
54-
}
55-
56-
bool Controller::ShouldSwitchMode() {
57-
return mpController->isHoldAll(Key::DpadDown | Key::ZL | Key::ZR | Key::L | Key::R);
58-
}
59-
60-
bool Controller::ShouldIncreaseLevel() {
61-
return mpController->isHold(Key::R);
62-
}
63-
bool Controller::ShouldDecreaseLevel() {
64-
return mpController->isHold(Key::L);
36+
u32 Controller::GetHoldKeys() {
37+
return mpController->getHoldMask();
6538
}
6639

6740
} // namespace botwsavs::core

src/core/Controller.hpp

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,39 +10,20 @@ namespace botwsavs {
1010

1111
namespace core {
1212
class Controller {
13-
public:
14-
enum Key : u32 {
15-
B = 1 << 1,
16-
ZL = 1 << 2,
17-
ZR = 1 << 5,
18-
RStick = 1 << 6,
19-
Plus = 1 << 10,
20-
21-
L = 1 << 13,
22-
R = 1 << 14,
23-
DpadDown = 1 << 17,
24-
DpadLeft = 1 << 18,
25-
DpadRight = 1 << 19
26-
};
27-
2813
public:
2914
Controller() = default;
30-
~Controller();
15+
~Controller() { mpController = nullptr; }
3116

32-
bool isInitialized() {
17+
bool IsInitialized() {
3318
if (!mpController) {
3419
TryGetController();
3520
}
3621
return mpController != nullptr;
3722
}
3823

39-
bool ShouldSaveState();
40-
bool ShouldRestoreState();
41-
bool ShouldSaveStateToFile();
42-
bool ShouldRestoreStateFromFile();
43-
bool ShouldSwitchMode();
44-
bool ShouldIncreaseLevel();
45-
bool ShouldDecreaseLevel();
24+
bool IsOnlyHolding(u32 mask);
25+
26+
u32 GetHoldKeys();
4627

4728
private:
4829
// Return true if controller is cached succesfully

src/core/Key.hpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#pragma once
2+
3+
#include "types.h"
4+
#include "util/StringBuffer.hpp"
5+
6+
namespace botwsavs::core {
7+
enum Key : u32 {
8+
A = 0,
9+
B = 1 << 1,
10+
ZL = 1 << 2,
11+
Y = 1 << 3,
12+
X = 1 << 4,
13+
ZR = 1 << 5,
14+
RStick = 1 << 6,
15+
LStick = 1 << 7,
16+
17+
Minus = (1 << 9) | (1 << 12),
18+
Plus = (1 << 10) | (1 << 11),
19+
20+
L = 1 << 13,
21+
R = 1 << 14,
22+
23+
DpadUp = 1 << 16,
24+
DpadDown = 1 << 17,
25+
DpadLeft = 1 << 18,
26+
DpadRight = 1 << 19
27+
};
28+
29+
namespace key {
30+
template <u32 L>
31+
void GetKeyString(u32 mask, util::StringBuffer<L>& outBuffer) {
32+
static_assert(L >= 100, "Key string buffer length should be at least 100");
33+
outBuffer.Clear();
34+
if (mask == 0) {
35+
return;
36+
}
37+
if (mask & Key::A) {
38+
outBuffer.SafeAppend("A+");
39+
}
40+
if (mask & Key::B) {
41+
outBuffer.SafeAppend("B+");
42+
}
43+
if (mask & Key::X) {
44+
outBuffer.SafeAppend("X+");
45+
}
46+
if (mask & Key::Y) {
47+
outBuffer.SafeAppend("Y+");
48+
}
49+
if (mask & Key::L) {
50+
outBuffer.SafeAppend("L+");
51+
}
52+
if (mask & Key::R) {
53+
outBuffer.SafeAppend("R+");
54+
}
55+
if (mask & Key::ZL) {
56+
outBuffer.SafeAppend("ZL+");
57+
}
58+
if (mask & Key::ZR) {
59+
outBuffer.SafeAppend("ZR+");
60+
}
61+
if (mask & Key::DpadUp) {
62+
outBuffer.SafeAppend("DpadUp+");
63+
}
64+
if (mask & Key::DpadDown) {
65+
outBuffer.SafeAppend("DpadDown+");
66+
}
67+
if (mask & Key::DpadLeft) {
68+
outBuffer.SafeAppend("DpadLeft+");
69+
}
70+
if (mask & Key::DpadRight) {
71+
outBuffer.SafeAppend("DpadRight+");
72+
}
73+
if (mask & Key::Minus) {
74+
outBuffer.SafeAppend("Minus+");
75+
}
76+
if (mask & Key::Plus) {
77+
outBuffer.SafeAppend("Plus+");
78+
}
79+
if (mask & Key::LStick) {
80+
outBuffer.SafeAppend("LStick+");
81+
}
82+
if (mask & Key::RStick) {
83+
outBuffer.SafeAppend("RStick+");
84+
}
85+
outBuffer.SafeDeleteEnd(1);
86+
}
87+
} // namespace key
88+
} // namespace botwsavs::core

src/core/KeyMgr.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#include "KeyMgr.hpp"
2+
#include "fs/ConfigFile.hpp"
3+
#include "fs/Logger.hpp"
4+
5+
namespace botwsavs::core {
6+
7+
bool KeyMgr::DidHoldFor(u32 keys, u32 seconds) {
8+
if (mHoldingKeys != keys) {
9+
mHoldCounter = 0;
10+
mHoldingKeys = keys;
11+
} else {
12+
mHoldCounter++;
13+
}
14+
// 1 tick = 3 frames
15+
// 1s = 30 frames = 10 ticks
16+
u32 ticks = seconds * 10;
17+
if (mHoldCounter >= ticks) {
18+
mHoldCounter = 0;
19+
return true;
20+
}
21+
return false;
22+
}
23+
24+
void KeyMgr::StartConfigure(u32* configureKey) {
25+
info("Configuring key binding");
26+
ClearHold();
27+
mpConfiguringKey = configureKey;
28+
mConfigureCounter = 0;
29+
}
30+
31+
KeyMgr::ConfigureResult KeyMgr::FinishConfigure(u32 newKey) {
32+
if (newKey == 0) {
33+
mConfigureCounter = 0;
34+
return ConfigureResult::Pending;
35+
}
36+
if (mConfigureCounter < 30) {
37+
mConfigureCounter++;
38+
return ConfigureResult::Pending;
39+
}
40+
41+
ClearHold();
42+
if (newKey == 0) {
43+
mpConfiguringKey = nullptr;
44+
return ConfigureResult::FailEmpty;
45+
}
46+
*mpConfiguringKey = newKey;
47+
mpConfiguringKey = nullptr;
48+
infof("New combo: %x", newKey);
49+
return ConfigureResult::Success;
50+
}
51+
52+
void KeyMgr::Save(fs::ConfigFile& file) const {
53+
file.WriteInteger(named(mKeySave));
54+
file.WriteInteger(named(mKeySaveFile));
55+
file.WriteInteger(named(mKeyRestore));
56+
file.WriteInteger(named(mKeyRestoreFile));
57+
}
58+
59+
void KeyMgr::Load(fs::ConfigFile& file) {
60+
file.ReadInteger(&mKeySave);
61+
file.ReadInteger(&mKeySaveFile);
62+
file.ReadInteger(&mKeyRestore);
63+
file.ReadInteger(&mKeyRestoreFile);
64+
}
65+
66+
} // namespace botwsavs::core

0 commit comments

Comments
 (0)