Skip to content

Commit 99ba895

Browse files
committed
Decouple the Button enum from the Pokken controller bitfield. Extend it to all the buttons on the wireless controllers.
1 parent 5e1eded commit 99ba895

File tree

40 files changed

+624
-510
lines changed

40 files changed

+624
-510
lines changed

Common/NintendoSwitch/NintendoSwitch_ControllerDefs.h

Lines changed: 1 addition & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -12,88 +12,8 @@
1212

1313

1414
#ifdef __cplusplus
15-
namespace PokemonAutomation{
16-
namespace NintendoSwitch{
1715

18-
// One second = 125 ticks. Thus each tick is 8 milliseconds.
19-
constexpr uint16_t TICKS_PER_SECOND = 125;
20-
21-
// Buttons
22-
enum Button : uint16_t{
23-
BUTTON_NONE = 0,
24-
BUTTON_Y = ((uint16_t)1 << 0),
25-
BUTTON_B = ((uint16_t)1 << 1),
26-
BUTTON_A = ((uint16_t)1 << 2),
27-
BUTTON_X = ((uint16_t)1 << 3),
28-
BUTTON_L = ((uint16_t)1 << 4),
29-
BUTTON_R = ((uint16_t)1 << 5),
30-
BUTTON_ZL = ((uint16_t)1 << 6),
31-
BUTTON_ZR = ((uint16_t)1 << 7),
32-
BUTTON_MINUS = ((uint16_t)1 << 8),
33-
BUTTON_PLUS = ((uint16_t)1 << 9),
34-
BUTTON_LCLICK = ((uint16_t)1 << 10),
35-
BUTTON_RCLICK = ((uint16_t)1 << 11),
36-
BUTTON_HOME = ((uint16_t)1 << 12),
37-
BUTTON_CAPTURE = ((uint16_t)1 << 13),
38-
};
39-
inline Button operator|(Button x, Button y){
40-
return (Button)((uint16_t)x | (uint16_t)y);
41-
}
42-
inline void operator|=(Button& x, Button y){
43-
x = (Button)((uint16_t)x | (uint16_t)y);
44-
}
45-
#if 0
46-
using Button = uint16_t;
47-
constexpr Button BUTTON_Y = ((uint16_t)1 << 0);
48-
constexpr Button BUTTON_B = ((uint16_t)1 << 1);
49-
constexpr Button BUTTON_A = ((uint16_t)1 << 2);
50-
constexpr Button BUTTON_X = ((uint16_t)1 << 3);
51-
constexpr Button BUTTON_L = ((uint16_t)1 << 4);
52-
constexpr Button BUTTON_R = ((uint16_t)1 << 5);
53-
constexpr Button BUTTON_ZL = ((uint16_t)1 << 6);
54-
constexpr Button BUTTON_ZR = ((uint16_t)1 << 7);
55-
constexpr Button BUTTON_MINUS = ((uint16_t)1 << 8);
56-
constexpr Button BUTTON_PLUS = ((uint16_t)1 << 9);
57-
constexpr Button BUTTON_LCLICK = ((uint16_t)1 << 10);
58-
constexpr Button BUTTON_RCLICK = ((uint16_t)1 << 11);
59-
constexpr Button BUTTON_HOME = ((uint16_t)1 << 12);
60-
constexpr Button BUTTON_CAPTURE = ((uint16_t)1 << 13);
61-
#endif
62-
63-
// Dpad
64-
enum DpadPosition : uint8_t{
65-
DPAD_UP = 0,
66-
DPAD_UP_RIGHT = 1,
67-
DPAD_RIGHT = 2,
68-
DPAD_DOWN_RIGHT = 3,
69-
DPAD_DOWN = 4,
70-
DPAD_DOWN_LEFT = 5,
71-
DPAD_LEFT = 6,
72-
DPAD_UP_LEFT = 7,
73-
DPAD_NONE = 8,
74-
};
75-
76-
#if 0
77-
using DpadPosition = uint8_t;
78-
constexpr DpadPosition DPAD_UP = 0;
79-
constexpr DpadPosition DPAD_UP_RIGHT = 1;
80-
constexpr DpadPosition DPAD_RIGHT = 2;
81-
constexpr DpadPosition DPAD_DOWN_RIGHT = 3;
82-
constexpr DpadPosition DPAD_DOWN = 4;
83-
constexpr DpadPosition DPAD_DOWN_LEFT = 5;
84-
constexpr DpadPosition DPAD_LEFT = 6;
85-
constexpr DpadPosition DPAD_UP_LEFT = 7;
86-
constexpr DpadPosition DPAD_NONE = 8;
87-
#endif
88-
89-
// Joysticks
90-
constexpr uint8_t STICK_MIN = 0x00;
91-
constexpr uint8_t STICK_CENTER = 0x80;
92-
constexpr uint8_t STICK_MAX = 0xff;
93-
94-
95-
}
96-
}
16+
#error "C++ shouldn't include this file."
9717

9818
#else
9919

Common/NintendoSwitch/NintendoSwitch_Protocol_PushButtons.h

Lines changed: 3 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//#include "NativePrograms/NintendoSwitch/Framework/Master.h"
1212
//#endif
1313
#include "Common/Microcontroller/MessageProtocol.h"
14-
#include "Common/NintendoSwitch/NintendoSwitch_ControllerDefs.h"
14+
//#include "Common/NintendoSwitch/NintendoSwitch_ControllerDefs.h"
1515

1616
#if _WIN32
1717
#pragma pack(push, 1)
@@ -27,50 +27,12 @@ namespace NintendoSwitch{
2727
#endif
2828

2929

30-
#define PABB_MSG_COMMAND_PBF_WAIT 0x90
31-
typedef struct{
32-
seqnum_t seqnum;
33-
uint16_t ticks;
34-
} PABB_PACK pabb_pbf_wait;
35-
36-
#define PABB_MSG_COMMAND_PBF_PRESS_BUTTON 0x91
37-
typedef struct{
38-
seqnum_t seqnum;
39-
Button button;
40-
uint16_t hold_ticks;
41-
uint16_t release_ticks;
42-
} PABB_PACK pabb_pbf_press_button;
43-
44-
#define PABB_MSG_COMMAND_PBF_PRESS_DPAD 0x92
45-
typedef struct{
46-
seqnum_t seqnum;
47-
DpadPosition dpad;
48-
uint16_t hold_ticks;
49-
uint16_t release_ticks;
50-
} PABB_PACK pabb_pbf_press_dpad;
51-
52-
#define PABB_MSG_COMMAND_PBF_MOVE_JOYSTICK_L 0x93
53-
#define PABB_MSG_COMMAND_PBF_MOVE_JOYSTICK_R 0x94
54-
typedef struct{
55-
seqnum_t seqnum;
56-
uint8_t x;
57-
uint8_t y;
58-
uint16_t hold_ticks;
59-
uint16_t release_ticks;
60-
} PABB_PACK pabb_pbf_move_joystick;
61-
62-
#define PABB_MSG_COMMAND_MASH_BUTTON 0x95
63-
typedef struct{
64-
seqnum_t seqnum;
65-
Button button;
66-
uint16_t ticks;
67-
} PABB_PACK pabb_pbf_mash_button;
6830

6931
#define PABB_MSG_CONTROLLER_STATE 0x9f
7032
typedef struct{
7133
seqnum_t seqnum;
72-
Button button;
73-
DpadPosition dpad;
34+
uint16_t button;
35+
uint8_t dpad;
7436
uint8_t left_joystick_x;
7537
uint8_t left_joystick_y;
7638
uint8_t right_joystick_x;

Common/PokemonSwSh/PokemonSwSh_Protocol_DaySkippers.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include "NativePrograms/NintendoSwitch/Framework/Master.h"
1414
#endif
1515
#include "Common/Microcontroller/MessageProtocol.h"
16-
#include "Common/NintendoSwitch/NintendoSwitch_ControllerDefs.h"
1716

1817
////////////////////////////////////////////////////////////////////////////////
1918
////////////////////////////////////////////////////////////////////////////////

SerialPrograms/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,8 @@ file(GLOB MAIN_SOURCES
827827
Source/NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h
828828
Source/NintendoSwitch/Commands/NintendoSwitch_Messages_Device.h
829829
Source/NintendoSwitch/Commands/NintendoSwitch_Messages_PushButtons.h
830+
Source/NintendoSwitch/Controllers/NintendoSwitch_ControllerState.cpp
831+
Source/NintendoSwitch/Controllers/NintendoSwitch_ControllerState.h
830832
Source/NintendoSwitch/Controllers/NintendoSwitch_KeyboardMapping.cpp
831833
Source/NintendoSwitch/Controllers/NintendoSwitch_KeyboardMapping.h
832834
Source/NintendoSwitch/Controllers/NintendoSwitch_ProController.cpp

SerialPrograms/SerialPrograms.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ SOURCES += \
407407
Source/NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.cpp \
408408
Source/NintendoSwitch/Commands/NintendoSwitch_Commands_Routines.cpp \
409409
Source/NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.cpp \
410+
Source/NintendoSwitch/Controllers/NintendoSwitch_ControllerState.cpp \
410411
Source/NintendoSwitch/Controllers/NintendoSwitch_KeyboardMapping.cpp \
411412
Source/NintendoSwitch/Controllers/NintendoSwitch_ProController.cpp \
412413
Source/NintendoSwitch/Controllers/NintendoSwitch_ProControllerWithScheduler.cpp \
@@ -1575,6 +1576,7 @@ HEADERS += \
15751576
Source/NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h \
15761577
Source/NintendoSwitch/Commands/NintendoSwitch_Messages_Device.h \
15771578
Source/NintendoSwitch/Commands/NintendoSwitch_Messages_PushButtons.h \
1579+
Source/NintendoSwitch/Controllers/NintendoSwitch_ControllerState.h \
15781580
Source/NintendoSwitch/Controllers/NintendoSwitch_KeyboardMapping.h \
15791581
Source/NintendoSwitch/Controllers/NintendoSwitch_ProController.h \
15801582
Source/NintendoSwitch/Controllers/NintendoSwitch_ProControllerWithScheduler.h \

SerialPrograms/Source/Controllers/Controller.h

Lines changed: 170 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,34 @@
99

1010
#include <string>
1111
#include "Common/Compiler.h"
12+
#include "Common/Cpp/AbstractLogger.h"
1213
#include "Common/Cpp/Time.h"
14+
#include "Common/Cpp/CancellableScope.h"
1315

1416
class QKeyEvent;
1517

1618
namespace PokemonAutomation{
1719

18-
1920
enum class ControllerType;
2021

2122

23+
24+
inline Milliseconds round_up_to_ticksize(Milliseconds ticksize, Milliseconds duration){
25+
if (ticksize == Milliseconds::zero()){
26+
return duration;
27+
}
28+
return (duration + ticksize - Milliseconds(1)) / ticksize * ticksize;
29+
}
30+
31+
32+
33+
2234
class AbstractController{
2335
public:
2436
virtual ~AbstractController() = default;
2537

38+
virtual Logger& logger() = 0;
39+
2640

2741
public:
2842
// Static Information
@@ -45,6 +59,89 @@ class AbstractController{
4559
virtual std::string error_string() const = 0;
4660

4761

62+
public:
63+
//
64+
// Cancellation
65+
//
66+
// These functions will return immediately and are thread-safe with
67+
// everything. The intended use-case is for an inference thread to cancel
68+
// a running sequence of commands on a program thread.
69+
//
70+
71+
// Cancel all commands. This returns the controller to the neutral button
72+
// state and clears the command queue.
73+
// This does not wait for the commands to finish cancelling. This is an
74+
// asynchronous function that merely initiates the cancellation process.
75+
virtual void cancel_all_commands() = 0;
76+
77+
// Same as "cancel_all_commands()", but instead of cancelling the stream,
78+
// it lets it keep running. Then on the next command issued after this
79+
// cancel, it will atomically replace the stream without gapping.
80+
// This lets you do stuff like suddenly change joystick movement in
81+
// response to inference while simultaneously holding a button without
82+
// ever releasing it during the transition.
83+
virtual void replace_on_next_command() = 0;
84+
85+
86+
public:
87+
//
88+
// Superscalar Commands (the "ssf" framework)
89+
//
90+
91+
//
92+
// delay Time to wait before moving onto the next command.
93+
// hold Time to hold the button/stick down for.
94+
// cooldown After the button has been released, prevent it from being
95+
// used again for this much time.
96+
//
97+
// For "normal" use, you should always set (delay == hold + cooldown).
98+
// This is the easiest case to understand and is what the "pbf" interface
99+
// exposes.
100+
//
101+
// If the button is busy (due to still being held down or is waiting out
102+
// the cooldown), the command will wait until the button is ready.
103+
//
104+
// By setting (delay < hold), the command will "return" early and move onto
105+
// the next command while the button is still being held down.
106+
//
107+
// If a command returns before it is finished (delay < hold + cooldown),
108+
// it is considered a "hanging" command.
109+
//
110+
// This allows you to overlap buttons. But is confusing to use because it
111+
// implies a non-trivial controller state with pending button presses that
112+
// are scheduled to be released at a later time.
113+
//
114+
// Each button/stick has its own independent timeline/schedule.
115+
// Users are responsible for understanding the controller state and
116+
// managing the timeline/scheduling.
117+
//
118+
// It is important to remember that the "timeline" here is the timeline
119+
// being fed to the Switch. Thus the timing parameters written in the C++
120+
// code here is what you will get on the console (or as close as possible).
121+
//
122+
// The actual calls to the methods in the class will return or block in an
123+
// unspecified manner as they merely enqueue into a FIFO which is then
124+
// "replayed" to the Switch in an implementation-dependent manner.
125+
//
126+
127+
// Wait for all unfinished commands to finish. This will also wait out
128+
// hanging commands including their cooldown periods.
129+
// This is not a true command function as it waits for the entire queue to
130+
// empty out rather than entering itself into the queue.
131+
// If a cancellation happens inside this function, it will immediately
132+
// throw an OperationCancelledException.
133+
virtual void wait_for_all(const Cancellable* cancellable) = 0;
134+
135+
// Tell the scheduler to wait for all pending commands to finish
136+
// (including cooldowns) before executing further instructions.
137+
// This is used to prevent hanging commands from overlapping with new
138+
// commands issued after this barrier.
139+
virtual void issue_barrier(const Cancellable* cancellable) = 0;
140+
141+
// Do nothing for this much time.
142+
virtual void issue_nop(const Cancellable* cancellable, Milliseconds duration) = 0;
143+
144+
48145
public:
49146
// Keyboard Controls
50147

@@ -56,12 +153,79 @@ class AbstractController{
56153

57154

58155

59-
inline Milliseconds round_up_to_ticksize(Milliseconds ticksize, Milliseconds duration){
60-
if (ticksize == Milliseconds::zero()){
61-
return duration;
156+
//
157+
// The context wrapper to support asynchronous cancel.
158+
//
159+
template <typename Type>
160+
class ControllerContext final : public CancellableScope{
161+
public:
162+
using ControllerType = Type;
163+
164+
public:
165+
ControllerContext(ControllerType& botbase)
166+
: m_controller(botbase)
167+
{}
168+
ControllerContext(CancellableScope& parent, ControllerType& botbase)
169+
: m_controller(botbase)
170+
{
171+
attach(parent);
62172
}
63-
return (duration + ticksize - Milliseconds(1)) / ticksize * ticksize;
64-
}
173+
virtual ~ControllerContext(){
174+
detach();
175+
}
176+
177+
ControllerType* operator->(){
178+
m_lifetime_sanitizer.check_usage();
179+
return &m_controller;
180+
}
181+
182+
operator ControllerType&() const{ return m_controller; }
183+
ControllerType& controller() const{ return m_controller; }
184+
185+
void wait_for_all_requests() const{
186+
auto scope = m_lifetime_sanitizer.check_scope();
187+
m_controller.wait_for_all(this);
188+
}
189+
190+
// Stop all commands in this context now.
191+
void cancel_now(){
192+
auto scope = m_lifetime_sanitizer.check_scope();
193+
CancellableScope::cancel(nullptr);
194+
m_controller.cancel_all_commands();
195+
}
196+
197+
// Stop the commands in this context, but do it lazily.
198+
//
199+
// 1. Stop new commands from being issued to the device from this context.
200+
// 2. Tell the device that the next command that is issued should replace
201+
// the command queue.
202+
//
203+
// This cancel is used when you need continuity from an ongoing
204+
// sequence.
205+
void cancel_lazy(){
206+
auto scope = m_lifetime_sanitizer.check_scope();
207+
CancellableScope::cancel(nullptr);
208+
m_controller.replace_on_next_command();
209+
}
210+
211+
virtual bool cancel(std::exception_ptr exception) noexcept override{
212+
auto scope = m_lifetime_sanitizer.check_scope();
213+
if (CancellableScope::cancel(std::move(exception))){
214+
return true;
215+
}
216+
try{
217+
m_controller.cancel_all_commands();
218+
}catch (...){}
219+
return false;
220+
}
221+
222+
223+
private:
224+
ControllerType& m_controller;
225+
LifetimeSanitizer m_lifetime_sanitizer;
226+
};
227+
228+
65229

66230

67231

0 commit comments

Comments
 (0)