1#include "controller/seadControllerMgr.h"
2#include "basis/seadNew.h"
3#include "controller/nin/seadNinJoyNpadDevice.h"
4#include "controller/seadControlDevice.h"
5#include "framework/seadTaskID.h"
6#include "prim/seadDelegate.h"
7#include "thread/seadDelegateThread.h"
8
9namespace sead
10{
11SEAD_TASK_SINGLETON_IMPL(ControllerMgr)
12
13// NON_MATCHING: storing too much 00s into stack (for ConstructArg)
14ControllerMgr::ControllerMgr() : CalculateTask(ConstructArg(), "sead::ControllerMgr")
15{
16 mDevices.initOffset(offsetof(ControlDevice, mListNode));
17}
18
19ControllerMgr::ControllerMgr(const TaskConstructArg& arg)
20 : CalculateTask(arg, "sead::ControllerMgr")
21{
22 mDevices.initOffset(offsetof(ControlDevice, mListNode));
23}
24
25ControllerMgr::~ControllerMgr() = default;
26
27void ControllerMgr::prepare()
28{
29 auto* parameter = DynamicCast<Parameter>(obj: mParameter);
30 if (parameter)
31 {
32 initialize(controller_max: parameter->controllerMax, heap: nullptr);
33 if (parameter->proc)
34 parameter->proc->invoke(a1: this);
35 }
36 else
37 {
38 initializeDefault(heap: nullptr);
39 }
40}
41
42void ControllerMgr::initialize(s32 controller_max, Heap* heap)
43{
44 mControllers.allocBuffer(ptrNumMax: controller_max, heap);
45}
46
47void ControllerMgr::finalize()
48{
49 mControllers.freeBuffer();
50}
51
52void ControllerMgr::initializeDefault(Heap* heap)
53{
54 s32 controller_max;
55#ifdef cafe
56 controller_max = 6;
57#elif defined(NNSDK)
58 controller_max = 16;
59#else
60#error "Unknown Platform"
61#endif
62 initialize(controller_max, heap);
63
64#ifdef NNSDK
65 mDevices.pushBack(item: new (heap) NinJoyNpadDevice(this, heap));
66#endif
67}
68
69void ControllerMgr::finalizeDefault()
70{
71#ifdef NNSDK
72 // NON_MATCHING: missing cbz instruction within loop
73 for (auto& device : mDevices)
74 {
75 if (device.getId() == 13)
76 {
77 mDevices.erase(item: &device);
78 delete &device;
79 break;
80 }
81 }
82#endif // cafe
83
84 finalize();
85}
86
87// NON_MATCHING: swapped ldr / ldrsw on second loop check
88void ControllerMgr::calc()
89{
90 for (auto it = mDevices.begin(); it != mDevices.end(); ++it)
91 it->calc();
92
93 for (auto it = mControllers.begin(); it != mControllers.end(); ++it)
94 it->calc();
95}
96
97Controller* ControllerMgr::getControllerByOrder(ControllerDefine::ControllerId id, s32 index) const
98{
99 for (auto& controller : mControllers)
100 {
101 if (controller.mId == id)
102 {
103 if (index == 0)
104 return &controller;
105
106 index--;
107 }
108 }
109
110 return nullptr;
111}
112
113ControlDevice* ControllerMgr::getControlDevice(ControllerDefine::DeviceId id) const
114{
115 for (auto& device : mDevices)
116 {
117 if (device.mId == id)
118 return &device;
119 }
120
121 return nullptr;
122}
123
124ControllerAddon* ControllerMgr::getControllerAddon(s32 index, ControllerDefine::AddonId id) const
125{
126 Controller* controller = mControllers.at(pos: index);
127 if (controller)
128 return controller->getAddon(id);
129
130 return nullptr;
131}
132
133ControllerAddon* ControllerMgr::getControllerAddonByOrder(s32 controller_index,
134 ControllerDefine::AddonId id,
135 s32 addon_index) const
136{
137 Controller* controller = mControllers.at(pos: controller_index);
138 if (controller)
139 return controller->getAddonByOrder(id, index: addon_index);
140
141 return nullptr;
142}
143
144s32 ControllerMgr::findControllerPort(const Controller* controller) const
145{
146 SEAD_ASSERT(controller);
147
148 s32 i = 0;
149 for (auto& controller_it : mControllers)
150 {
151 if (&controller_it == controller)
152 return i;
153 i++;
154 }
155 return -1;
156}
157
158DelegateThread* ControllerMgr::getFramework() const
159{
160 if (mTaskMgr)
161 return mTaskMgr->mPrepareThread;
162 return nullptr;
163}
164
165} // namespace sead
166