rumble_init.c (7374B)
1 #include "config.h" 2 3 #if ENABLE_RUMBLE 4 5 #include <ultra64.h> 6 #include <PR/os.h> 7 #include "macros.h" 8 9 #include "buffers/buffers.h" 10 #include "main.h" 11 #include "rumble_init.h" 12 13 FORCE_BSS OSThread gRumblePakThread; 14 15 FORCE_BSS OSPfs gRumblePakPfs; 16 17 FORCE_BSS OSMesg gRumblePakSchedulerMesgBuf; 18 FORCE_BSS OSMesgQueue gRumblePakSchedulerMesgQueue; 19 FORCE_BSS OSMesg gRumbleThreadVIMesgBuf; 20 FORCE_BSS OSMesgQueue gRumbleThreadVIMesgQueue; 21 22 FORCE_BSS struct RumbleData gRumbleDataQueue[3]; 23 FORCE_BSS struct StructSH8031D9B0 gCurrRumbleSettings; 24 25 s32 sRumblePakThreadActive = FALSE; 26 s32 sRumblePakActive = FALSE; 27 s32 sRumblePakErrorCount = 0; 28 s32 gRumblePakTimer = 0; 29 30 void init_rumble_pak_scheduler_queue(void) { 31 osCreateMesgQueue(&gRumblePakSchedulerMesgQueue, &gRumblePakSchedulerMesgBuf, 1); 32 osSendMesg(&gRumblePakSchedulerMesgQueue, (OSMesg) 0, OS_MESG_NOBLOCK); 33 } 34 35 void block_until_rumble_pak_free(void) { 36 OSMesg msg; 37 osRecvMesg(&gRumblePakSchedulerMesgQueue, &msg, OS_MESG_BLOCK); 38 } 39 40 void release_rumble_pak_control(void) { 41 osSendMesg(&gRumblePakSchedulerMesgQueue, (OSMesg) 0, OS_MESG_NOBLOCK); 42 } 43 44 static void start_rumble(void) { 45 if (!sRumblePakActive) { 46 return; 47 } 48 49 block_until_rumble_pak_free(); 50 51 #ifdef VERSION_CN 52 if (!__osMotorAccess(&gRumblePakPfs, MOTOR_START)) { 53 #else 54 if (!osMotorStart(&gRumblePakPfs)) { 55 #endif 56 sRumblePakErrorCount = 0; 57 } else { 58 sRumblePakErrorCount++; 59 } 60 61 release_rumble_pak_control(); 62 } 63 64 static void stop_rumble(void) { 65 if (!sRumblePakActive) { 66 return; 67 } 68 69 block_until_rumble_pak_free(); 70 71 #ifdef VERSION_CN 72 if (!__osMotorAccess(&gRumblePakPfs, MOTOR_STOP)) { 73 #else 74 if (!osMotorStop(&gRumblePakPfs)) { 75 #endif 76 sRumblePakErrorCount = 0; 77 } else { 78 sRumblePakErrorCount++; 79 } 80 81 release_rumble_pak_control(); 82 } 83 84 static void update_rumble_pak(void) { 85 if (gResetTimer > 0) { 86 stop_rumble(); 87 return; 88 } 89 90 if (gCurrRumbleSettings.unk08 > 0) { 91 gCurrRumbleSettings.unk08--; 92 start_rumble(); 93 } else if (gCurrRumbleSettings.unk04 > 0) { 94 gCurrRumbleSettings.unk04--; 95 96 gCurrRumbleSettings.unk02 -= gCurrRumbleSettings.unk0E; 97 if (gCurrRumbleSettings.unk02 < 0) { 98 gCurrRumbleSettings.unk02 = 0; 99 } 100 101 if (gCurrRumbleSettings.unk00 == 1) { 102 start_rumble(); 103 } else if (gCurrRumbleSettings.unk06 >= 0x100) { 104 gCurrRumbleSettings.unk06 -= 0x100; 105 start_rumble(); 106 } else { 107 gCurrRumbleSettings.unk06 += 108 ((gCurrRumbleSettings.unk02 * gCurrRumbleSettings.unk02 * gCurrRumbleSettings.unk02) / (1 << 9)) + 4; 109 110 stop_rumble(); 111 } 112 } else { 113 gCurrRumbleSettings.unk04 = 0; 114 115 if (gCurrRumbleSettings.unk0A >= 5) { 116 start_rumble(); 117 } else if ((gCurrRumbleSettings.unk0A >= 2) && (gNumVblanks % gCurrRumbleSettings.unk0C == 0)) { 118 start_rumble(); 119 } else { 120 stop_rumble(); 121 } 122 } 123 124 if (gCurrRumbleSettings.unk0A > 0) { 125 gCurrRumbleSettings.unk0A--; 126 } 127 } 128 129 static void update_rumble_data_queue(void) { 130 if (gRumbleDataQueue[0].unk00) { 131 gCurrRumbleSettings.unk06 = 0; 132 gCurrRumbleSettings.unk08 = 4; 133 gCurrRumbleSettings.unk00 = gRumbleDataQueue[0].unk00; 134 gCurrRumbleSettings.unk04 = gRumbleDataQueue[0].unk02; 135 gCurrRumbleSettings.unk02 = gRumbleDataQueue[0].unk01; 136 gCurrRumbleSettings.unk0E = gRumbleDataQueue[0].unk04; 137 } 138 139 gRumbleDataQueue[0] = gRumbleDataQueue[1]; 140 gRumbleDataQueue[1] = gRumbleDataQueue[2]; 141 142 gRumbleDataQueue[2].unk00 = 0; 143 } 144 145 void queue_rumble_data(s16 a0, s16 a1) { 146 if (gCurrDemoInput != NULL) { 147 return; 148 } 149 150 if (a1 > 70) { 151 gRumbleDataQueue[2].unk00 = 1; 152 } else { 153 gRumbleDataQueue[2].unk00 = 2; 154 } 155 156 gRumbleDataQueue[2].unk01 = a1; 157 gRumbleDataQueue[2].unk02 = a0; 158 gRumbleDataQueue[2].unk04 = 0; 159 } 160 161 void func_sh_8024C89C(s16 a0) { 162 gRumbleDataQueue[2].unk04 = a0; 163 } 164 165 u8 is_rumble_finished_and_queue_empty(void) { 166 if (gCurrRumbleSettings.unk08 + gCurrRumbleSettings.unk04 >= 4) { 167 return FALSE; 168 } 169 170 if (gRumbleDataQueue[0].unk00 != 0) { 171 return FALSE; 172 } 173 174 if (gRumbleDataQueue[1].unk00 != 0) { 175 return FALSE; 176 } 177 178 if (gRumbleDataQueue[2].unk00 != 0) { 179 return FALSE; 180 } 181 182 return TRUE; 183 } 184 185 void reset_rumble_timers(void) { 186 if (gCurrDemoInput != NULL) { 187 return; 188 } 189 190 if (gCurrRumbleSettings.unk0A == 0) { 191 gCurrRumbleSettings.unk0A = 7; 192 } 193 194 if (gCurrRumbleSettings.unk0A < 4) { 195 gCurrRumbleSettings.unk0A = 4; 196 } 197 198 gCurrRumbleSettings.unk0C = 7; 199 } 200 201 void reset_rumble_timers_2(s32 a0) { 202 if (gCurrDemoInput != NULL) { 203 return; 204 } 205 206 if (gCurrRumbleSettings.unk0A == 0) { 207 gCurrRumbleSettings.unk0A = 7; 208 } 209 210 if (gCurrRumbleSettings.unk0A < 4) { 211 gCurrRumbleSettings.unk0A = 4; 212 } 213 214 if (a0 == 4) { 215 gCurrRumbleSettings.unk0C = 1; 216 } 217 218 if (a0 == 3) { 219 gCurrRumbleSettings.unk0C = 2; 220 } 221 222 if (a0 == 2) { 223 gCurrRumbleSettings.unk0C = 3; 224 } 225 226 if (a0 == 1) { 227 gCurrRumbleSettings.unk0C = 4; 228 } 229 230 if (a0 == 0) { 231 gCurrRumbleSettings.unk0C = 5; 232 } 233 } 234 235 void func_sh_8024CA04(void) { 236 if (gCurrDemoInput != NULL) { 237 return; 238 } 239 240 gCurrRumbleSettings.unk0A = 4; 241 gCurrRumbleSettings.unk0C = 4; 242 } 243 244 static void thread6_rumble_loop(UNUSED void *a0) { 245 OSMesg msg; 246 247 CN_DEBUG_PRINTF(("start motor thread\n")); 248 249 cancel_rumble(); 250 sRumblePakThreadActive = TRUE; 251 252 CN_DEBUG_PRINTF(("go motor thread\n")); 253 254 while (TRUE) { 255 // Block until VI 256 osRecvMesg(&gRumbleThreadVIMesgQueue, &msg, OS_MESG_BLOCK); 257 258 update_rumble_data_queue(); 259 update_rumble_pak(); 260 261 if (sRumblePakActive) { 262 if (sRumblePakErrorCount >= 30) { 263 sRumblePakActive = FALSE; 264 } 265 } else if (gNumVblanks % 60 == 0) { 266 sRumblePakActive = osMotorInit(&gSIEventMesgQueue, &gRumblePakPfs, gPlayer1Controller->port) == 0; 267 sRumblePakErrorCount = 0; 268 } 269 270 if (gRumblePakTimer > 0) { 271 gRumblePakTimer--; 272 } 273 } 274 } 275 276 void cancel_rumble(void) { 277 sRumblePakActive = osMotorInit(&gSIEventMesgQueue, &gRumblePakPfs, gPlayer1Controller->port) == 0; 278 279 if (sRumblePakActive) { 280 #ifdef VERSION_CN 281 __osMotorAccess(&gRumblePakPfs, MOTOR_STOP); 282 #else 283 osMotorStop(&gRumblePakPfs); 284 #endif 285 } 286 287 gRumbleDataQueue[0].unk00 = 0; 288 gRumbleDataQueue[1].unk00 = 0; 289 gRumbleDataQueue[2].unk00 = 0; 290 291 gCurrRumbleSettings.unk04 = 0; 292 gCurrRumbleSettings.unk0A = 0; 293 294 gRumblePakTimer = 0; 295 } 296 297 void create_thread_6(void) { 298 osCreateMesgQueue(&gRumbleThreadVIMesgQueue, &gRumbleThreadVIMesgBuf, 1); 299 osCreateThread(&gRumblePakThread, 6, thread6_rumble_loop, NULL, gThread6Stack + 0x2000, 30); 300 osStartThread(&gRumblePakThread); 301 } 302 303 void rumble_thread_update_vi(void) { 304 if (!sRumblePakThreadActive) { 305 return; 306 } 307 308 #pragma GCC diagnostic push 309 #pragma GCC diagnostic ignored "-Wmultichar" 310 osSendMesg(&gRumbleThreadVIMesgQueue, (OSMesg) 'VRTC', OS_MESG_NOBLOCK); 311 #pragma GCC diagnostic pop 312 } 313 314 #endif