Digimon World 3 decomp
The European version, SLES_039.36
Loading...
Searching...
No Matches
port.c
Go to the documentation of this file.
1#include "engine/game.h"
2#include <libpad.h>
3
4/*
5 * The libpad state of a port while it can be read (0 otherwise); a stable pad gets its actuators
6 * aligned
7 */
9 u32 p = port;
10 u32 mask;
11 s32 state = PadGetState(p & 0xFF);
12
13 switch (state) {
14 case PadStateDiscon:
15 case PadStateFindPad:
16 /* meant to drop the slot's mode lock, but masks with the slot's
17 index rather than its bit */
18 mask = ~(((p >> 2) & 0x3C) | (p & 3)); PAD.flags = PAD.flags & mask & ~(PAD_FLAG_ALIGNING | PAD_FLAG_VIBRATION);
19 return 0;
20 case PadStateStable:
21 if (!(PAD.flags & PAD_FLAG_VIBRATION)) {
24 } else if (alignActuators(p & 0xFF)) {
26 }
27 }
28 return state;
29 case PadStateFindCTP1:
30 return state;
31 case PadStateFindCTP2:
32 case PadStateReqInfo:
33 case PadStateExecCmd:
34 default:
35 return 0;
36 }
37}
38
39/* Builds held/pressed/repeated from the raw data (the demo record replaces all but Start) */
40void readPadButtons(s32 port, PadData *data, PadData *record) {
41 u32 id = port & 0xFF;
42 s32 mode = PadInfoMode(id, InfoModeCurExID, 0);
43 u32 pad = (id >> 4) & 1;
44 PadSlot *slot = &PAD.slots[(u8)pad][port & 3];
45 s16 buttons;
46 s16 i;
47 u16 b;
48 s16 circle, cross, triangle;
49
50 if ((PAD.flags & PAD_FLAG_DEMO_PLAYBACK) && PAD.demoPad == ((port & 3) | pad)) {
51 buttons = (~data->buttons & 1 << PAD_START) | (~record->buttons & ~(1 << PAD_START));
52 if (mode == PAD_ID_ANALOG) {
53 /* not record->analog[i], which adds the index the other way round */
54 for (i = 0; i < 4; i++) {
55 slot->analog[i] = *(record->analog + i);
56 }
57 }
58 } else {
59#if VERSION_US
60 b = ~data->buttons;
61 circle = (b >> RAW_CIRCLE) & 1;
62 cross = (b >> RAW_CROSS) & 1;
63 triangle = (b >> RAW_TRIANGLE) & 1;
64 buttons = ~data->buttons & ~FACE_BUTTONS;
65 if (cross) {
66 buttons |= 1 << PAD_CROSS;
67 }
68 if (triangle) {
69 buttons |= 1 << PAD_TRIANGLE;
70 }
71 if (circle) {
72 buttons |= 1 << PAD_CIRCLE;
73 }
74#elif VERSION_EU || VERSION_JP
75 /* the Japanese language keeps the buttons as they are (the Japanese
76 version's only one, LANGUAGE 0) */
77 buttons = ~data->buttons;
78 if (LANGUAGE != 0) {
79 b = buttons;
80 circle = (b >> RAW_CIRCLE) & 1;
81 cross = (b >> RAW_CROSS) & 1;
82 triangle = (b >> RAW_TRIANGLE) & 1;
83 buttons &= ~FACE_BUTTONS;
84 if (cross) {
85 buttons |= 1 << PAD_CROSS;
86 }
87 if (triangle) {
88 buttons |= 1 << PAD_TRIANGLE;
89 }
90 if (circle) {
91 buttons |= 1 << PAD_CIRCLE;
92 }
93 }
94#endif
95 if (mode == PAD_ID_ANALOG) {
96 /* as above, not data->analog[i] */
97 for (i = 0; i < 4; i++) {
98 slot->analog[i] = *(data->analog + i);
99 }
100 }
101 }
102 if (mode == PAD_ID_ANALOG) {
103 if (slot->analog[2] <= STICK_LOW) {
104 buttons |= 1 << PAD_LEFT;
105 } else if (slot->analog[2] >= STICK_HIGH) {
106 buttons |= 1 << PAD_RIGHT;
107 }
108 if (slot->analog[3] <= STICK_LOW) {
109 buttons |= 1 << PAD_UP;
110 } else if (slot->analog[3] >= STICK_HIGH) {
111 buttons |= 1 << PAD_DOWN;
112 }
113 }
114 i = 0;
115 slot->repeated = 0;
116 for (; i < 16; i++) {
117 u8 bit = slot->buttonMap[i];
118 s32 *time = &slot->repeatTime[bit];
119 u8 *count = &slot->repeatCount[bit];
120
121 if ((buttons >> bit) & 1) {
122 if (PAD.repeatRate > 0) {
123 if ((GFX.funcs.getTime() - *time + *count) / PAD.repeatRate != 0) {
124 *count += 10;
125 if (*count >= 12) {
126 *count = 12;
127 }
128 *time = GFX.funcs.getTime();
129 slot->repeated |= 1 << slot->buttonMap[i];
130 }
131 }
132 } else {
133 *time = GFX.funcs.getTime();
134 *count = 0;
135 }
136 }
137 b = slot->held;
138 slot->held = buttons;
139 slot->prevHeld = b;
140 slot->pressed = buttons & (b ^ buttons);
141}
142
143/* Reads one pad (vibration included), or clears its buttons when it is missing */
144s32 readPad(u16 port, PadData *data) {
145 u8 id = port;
146 s32 mode;
147
148 if (data->status != 0 || pollPadState(id & 0xFF) == 0) {
149 PAD.slots[(id >> 4) & 1][port & 3].pressed = 0;
150 PAD.slots[(id >> 4) & 1][port & 3].repeated = 0;
151 PAD.slots[(id >> 4) & 1][port & 3].held = 0;
152 return 0;
153 }
154 mode = PadInfoMode(id & 0xFF, InfoModeCurExID, 0);
155 if (mode == PAD_ID_DIGITAL || mode == PAD_ID_ANALOG) {
156 updateVibration(id & 0xFF);
157 }
158 readPadButtons(id & 0xFF, data, NULL);
159 return 1;
160}
161
162/* Locks or unlocks the analog button of a DualShock, keeping its current mode */
163s32 lockPadMode(s32 port, s32 lock) {
164 u32 id = port & 0xFF;
165 s32 mode;
166 s32 bit;
167
168 if (pollPadState(id) != 0) {
169 mode = PadInfoMode(id, InfoModeCurExID, 0);
170 if (mode == PAD_ID_DIGITAL || mode == PAD_ID_ANALOG) {
171 bit = ((id >> 4) << 2) | (port & 3);
172 if (lock != 0) {
173 PAD.flags |= 1 << bit;
174 PadSetMainMode(id, PadInfoMode(id, InfoModeCurExOffs, 0), PAD_MODE_LOCKED);
175 } else {
176 PAD.flags &= ~(1 << bit);
177 PadSetMainMode(id, PadInfoMode(id, InfoModeCurExOffs, 0), PAD_MODE_UNLOCKED);
178 }
180 return 1;
181 }
182 }
183 return 0;
184}
185
186/* Sends a DualShock its actuator alignment, so setVibration can drive the motors */
188 u32 id = (u8)port;
189 s32 count = PadInfoAct(id, -1, 0);
190 s32 i;
191 s32 act;
192
193 for (i = 0; i < count; i++) {
194 act = PadInfoAct(id, i, InfoActSub);
195 if (act != 0) {
196 PAD.act[id >> 4][i] = act & 1;
197 }
198 }
199 return PadSetActAlign(port & 0xFF, PAD.act[(port & 0xFF) >> 4]);
200}
201
202/* Counts down a pad's vibration timers and stops each motor whose time is up */
204 u8 id = port;
205 s32 i;
206 PadSlot *slot = &PAD.slots[id >> 4][port & 3];
207
208 for (i = 0; i < 2; i++) {
209 if (slot->vibrationTimers[i] != 0) {
210 if ((slot->vibrationTimers[i] -= GFX.funcs.getFrameTime()) <= 0) {
211 slot->vibrationTimers[i] = 0;
212 PAD.act[id >> 4][i] = 0;
213 }
214 PadSetAct(port & 0xFF, PAD.act[id >> 4], 2);
215 }
216 }
217}
#define NULL
Definition common.h:17
signed int s32
Definition common.h:11
unsigned int u32
Definition common.h:12
signed short s16
Definition common.h:9
unsigned short u16
Definition common.h:10
unsigned char u8
Definition common.h:8
GfxState GFX
GFX: the graphics state and its methods.
Definition display.c:209
s32 LANGUAGE
The European version's settings, in the small data (.sdata) between file/file_table....
Definition eu_settings.c:13
PadState PAD
Controller input: cleared by initPad, then the methods.
Definition pad.c:168
#define STICK_HIGH
Definition pad.h:54
#define PAD_CROSS
Definition pad.h:31
#define PAD_START
Definition pad.h:21
#define STICK_LOW
A stick at or below LOW, or at or above HIGH, also presses the d-pad.
Definition pad.h:53
#define PAD_MODE_LOCKED
Definition pad.h:44
#define RAW_CROSS
Definition pad.h:49
#define PAD_CIRCLE
Definition pad.h:30
#define PAD_MODE_UNLOCKED
PadSetMainMode's lock: the analog button may change the mode, or not.
Definition pad.h:43
#define PAD_DOWN
Definition pad.h:24
#define PAD_RIGHT
Definition pad.h:23
#define RAW_CIRCLE
Definition pad.h:48
#define PAD_TRIANGLE
Definition pad.h:32
#define PAD_ID_ANALOG
Definition pad.h:37
#define RAW_TRIANGLE
Raw bits of circle, cross and triangle, which readPadButtons rotates.
Definition pad.h:47
#define PAD_FLAG_VIBRATION
the actuators are aligned
Definition pad.h:96
#define PAD_FLAG_DEMO_PLAYBACK
PadState.flags: bits 0-7 hold the mode lock of each port/slot (lockPadMode), the rest are these.
Definition pad.h:93
#define PAD_FLAG_ALIGNING
PadSetActAlign sent, not yet stable.
Definition pad.h:95
#define PAD_ID_DIGITAL
PadInfoMode(InfoModeCurExID) of a DualShock in digital and analog mode.
Definition pad.h:36
#define PAD_UP
Definition pad.h:22
#define PAD_LEFT
Definition pad.h:25
s32 pollPadState(u32 port)
The libpad state of a port while it can be read (0 otherwise); a stable pad gets its actuators aligne...
Definition port.c:8
s32 readPad(u16 port, PadData *data)
Reads one pad (vibration included), or clears its buttons when it is missing.
Definition port.c:144
void updateVibration(u16 port)
Counts down a pad's vibration timers and stops each motor whose time is up.
Definition port.c:203
void readPadButtons(s32 port, PadData *data, PadData *record)
Builds held/pressed/repeated from the raw data (the demo record replaces all but Start)
Definition port.c:40
s32 lockPadMode(s32 port, s32 lock)
Locks or unlocks the analog button of a DualShock, keeping its current mode.
Definition port.c:163
s32 alignActuators(u16 port)
Sends a DualShock its actuator alignment, so setVibration can drive the motors.
Definition port.c:187
s32(* getFrameTime)(void)
Definition gfx.h:32
s32(* getTime)(void)
Definition gfx.h:31
GfxFuncs funcs
Definition gfx.h:77
What a pad sends (libpad's receive buffer)
Definition pad.h:57
u16 buttons
raw: a bit is clear while its button is pressed
Definition pad.h:60
u8 analog[4]
Definition pad.h:61
u8 status
0: it answered
Definition pad.h:58
One controller: a port, or one of the four multitap slots behind it.
Definition pad.h:77
u8 repeatCount[16]
Definition pad.h:84
u16 repeated
pressed, or held long enough to repeat
Definition pad.h:79
u16 prevHeld
Definition pad.h:80
u16 held
Definition pad.h:81
u16 pressed
this frame
Definition pad.h:78
s16 vibrationTimers[2]
Definition pad.h:86
u8 analog[4]
Definition pad.h:82
s32 repeatTime[16]
Definition pad.h:83
u8 buttonMap[16]
Definition pad.h:85
s32 flags
Definition pad.h:112
u8 act[2][6]
Definition pad.h:115
s16 repeatRate
vsyncs
Definition pad.h:116
PadSlot slots[2][4]
Definition pad.h:114
s16 demoPad
Definition pad.h:117