Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/RSDKv5/RSDK/Core/RetroEngine.cpp
1162 views
1
#include "RSDK/Core/RetroEngine.hpp"
2
3
using namespace RSDK;
4
5
#if RETRO_REV0U
6
#include "Legacy/RetroEngineLegacy.cpp"
7
#endif
8
9
LogicLinkHandle RSDK::linkGameLogic = NULL;
10
11
Link::Handle gameLogicHandle = NULL;
12
13
#if RETRO_PLATFORM == RETRO_ANDROID
14
#include <jni.h>
15
#include <unistd.h>
16
#endif
17
18
int32 *RSDK::globalVarsPtr = NULL;
19
#if RETRO_REV0U
20
void (*RSDK::globalVarsInitCB)(void *globals) = NULL;
21
#endif
22
23
RetroEngine RSDK::engine = RetroEngine();
24
25
int32 RSDK::RunRetroEngine(int32 argc, char *argv[])
26
{
27
ParseArguments(argc, argv);
28
29
if (engine.consoleEnabled)
30
InitConsole();
31
RenderDevice::isRunning = false;
32
33
if (InitStorage()) {
34
SKU::InitUserCore();
35
LoadSettingsINI();
36
37
#if !RETRO_USE_ORIGINAL_CODE
38
// temp fix till i properly figure out what exactly went wrong here
39
#if RETRO_REV02
40
SKU::curSKU.platform = SKU::userCore->GetUserPlatform();
41
#else
42
if (gameVerInfo.platform == PLATFORM_PC)
43
gameVerInfo.platform = engine.devMenu ? PLATFORM_DEV : PLATFORM_PC;
44
#endif
45
#endif
46
47
#if RETRO_USE_MOD_LOADER
48
// do it early so we can render funny little loading bar for mods
49
int32 shader = videoSettings.shaderID;
50
strcpy(gameVerInfo.gameTitle, "RSDK" ENGINE_V_NAME);
51
if (RenderDevice::Init()) {
52
RenderDevice::isRunning = true;
53
currentScreen = &screens[0];
54
videoSettings.screenCount = 1;
55
}
56
else {
57
// No render device, throw a "QUIT" msg onto the message loop and call it a day :)
58
SendQuitMsg();
59
}
60
#if RETRO_PLATFORM == RETRO_ANDROID
61
// wait until we have a window
62
while (!RenderDevice::window) {
63
RenderDevice::ProcessEvents();
64
}
65
#endif
66
67
#if RETRO_REV0U
68
engine.version = 0;
69
InitModAPI(true); // check for versions
70
engine.version = 5;
71
#endif
72
#endif
73
74
#if RETRO_REV0U
75
DetectEngineVersion();
76
#endif
77
78
// By Default we use the dummy system so this'll never be false
79
// its used in cases like steam where it gives the "Steam must be running to play this game" message and closes
80
#if RETRO_REV02
81
if (!SKU::userCore->CheckAPIInitialized()) {
82
#else
83
if (false) { // it's more hardcoded in rev01, so lets pretend it's here
84
#endif
85
// popup a message box saying the API failed to validate or something
86
// on steam this is the "steam must be running to play this game" message
87
return 0;
88
}
89
90
InitEngine();
91
#if RETRO_USE_MOD_LOADER
92
// we confirmed the game actually is valid & running, lets start some callbacks
93
videoSettings.shaderID = shader;
94
RenderDevice::InitShaders();
95
RenderDevice::SetWindowTitle();
96
RenderDevice::lastShaderID = -1;
97
#else
98
if (RenderDevice::Init()) {
99
RenderDevice::isRunning = true;
100
}
101
else {
102
// No render device, throw a "QUIT" msg onto the message loop and call it a day :)
103
SendQuitMsg();
104
}
105
#endif
106
}
107
108
RenderDevice::InitFPSCap();
109
110
while (RenderDevice::isRunning) {
111
RenderDevice::ProcessEvents();
112
113
if (!RenderDevice::isRunning)
114
break;
115
116
if (RenderDevice::CheckFPSCap()) {
117
RenderDevice::UpdateFPSCap();
118
119
AudioDevice::FrameInit();
120
121
#if RETRO_REV02
122
SKU::userCore->FrameInit();
123
124
if (SKU::userCore->CheckEnginePause())
125
continue;
126
127
// Focus Checks
128
#if !RETRO_USE_ORIGINAL_CODE
129
if (customSettings.disableFocusPause)
130
engine.focusState = 0;
131
else if (SKU::userCore->CheckFocusLost()) {
132
#else
133
if (SKU::userCore->CheckFocusLost()) {
134
#endif
135
if (!(engine.focusState & 1)) {
136
engine.focusState = 1;
137
138
#if !RETRO_USE_ORIGINAL_CODE
139
for (int32 c = 0; c < CHANNEL_COUNT; ++c) {
140
engine.focusPausedChannel[c] = false;
141
if (!(channels[c].state & CHANNEL_PAUSED)) {
142
PauseChannel(c);
143
engine.focusPausedChannel[c] = true;
144
}
145
}
146
#else
147
PauseSound();
148
#endif
149
}
150
}
151
else if (engine.focusState) {
152
engine.focusState = 0;
153
154
#if !RETRO_USE_ORIGINAL_CODE
155
for (int32 c = 0; c < CHANNEL_COUNT; ++c) {
156
if (engine.focusPausedChannel[c])
157
ResumeChannel(c);
158
engine.focusPausedChannel[c] = false;
159
}
160
#else
161
ResumeSound();
162
#endif
163
}
164
#endif
165
166
if (!engine.initialized || (engine.focusState & 1)) {
167
if (videoSettings.windowState != WINDOWSTATE_ACTIVE)
168
continue;
169
}
170
else {
171
if (!engine.hardPause) {
172
// common stuff
173
foreachStackPtr = foreachStackList;
174
#if !RETRO_USE_ORIGINAL_CODE
175
debugHitboxCount = 0;
176
#endif
177
178
#if RETRO_USE_MOD_LOADER
179
#if RETRO_REV0U
180
if (((engine.version == 5 && sceneInfo.state != ENGINESTATE_DEVMENU)
181
|| (engine.version != 5 && RSDK::Legacy::gameMode != RSDK::Legacy::ENGINE_DEVMENU))
182
&& devMenu.modsChanged) {
183
engine.version = 0;
184
#else
185
if (sceneInfo.state != ENGINESTATE_DEVMENU && devMenu.modsChanged) {
186
#endif
187
devMenu.modsChanged = false;
188
SaveMods();
189
RefreshModFolders(true);
190
LoadModSettings();
191
for (int32 c = 0; c < CHANNEL_COUNT; ++c) StopChannel(c);
192
#if RETRO_REV02
193
forceHardReset = true;
194
#endif
195
196
#if RETRO_REV0U
197
int32 preVersion = engine.version;
198
199
DetectEngineVersion();
200
if (!engine.version)
201
engine.version = preVersion;
202
203
SceneInfo pre = sceneInfo;
204
int32 preGameMode = RSDK::Legacy::gameMode;
205
int32 preStageMode = RSDK::Legacy::stageMode;
206
207
// Clear some stuff
208
sceneInfo.listData = NULL;
209
sceneInfo.listCategory = NULL;
210
211
globalVarsPtr = NULL;
212
globalVarsInitCB = NULL;
213
214
dataStorage[DATASET_STG].entryCount = 0;
215
dataStorage[DATASET_STG].usedStorage = 0;
216
dataStorage[DATASET_SFX].entryCount = 0;
217
dataStorage[DATASET_SFX].usedStorage = 0;
218
219
for (int32 o = 0; o < objectClassCount; ++o) {
220
if (objectClassList[o].staticVars && *objectClassList[o].staticVars)
221
(*objectClassList[o].staticVars) = NULL;
222
}
223
224
InitEngine();
225
226
switch (engine.version) {
227
default:
228
case 5:
229
sceneInfo.classCount = pre.classCount;
230
if (pre.state == ENGINESTATE_LOAD) {
231
sceneInfo.activeCategory = pre.activeCategory;
232
sceneInfo.listPos = pre.listPos;
233
}
234
break;
235
case 4:
236
case 3:
237
if (preGameMode == RSDK::Legacy::ENGINE_MAINGAME && preStageMode == RSDK::Legacy::STAGEMODE_LOAD) {
238
sceneInfo.activeCategory = pre.activeCategory;
239
sceneInfo.listPos = pre.listPos;
240
}
241
break;
242
}
243
244
#else
245
SceneInfo pre = sceneInfo;
246
InitEngine();
247
sceneInfo.classCount = pre.classCount;
248
if (pre.state == ENGINESTATE_LOAD) {
249
sceneInfo.activeCategory = pre.activeCategory;
250
sceneInfo.listPos = pre.listPos;
251
}
252
#endif
253
RenderDevice::SetWindowTitle();
254
sceneInfo.state = ENGINESTATE_LOAD;
255
}
256
#endif
257
258
// update device states and other stuff
259
ProcessInputDevices();
260
261
if (engine.devMenu)
262
ProcessDebugCommands();
263
264
#if RETRO_REV0U
265
switch (engine.version) {
266
default:
267
case 5: ProcessEngine(); break;
268
case 4: Legacy::v4::ProcessEngine(); break;
269
case 3: Legacy::v3::ProcessEngine(); break;
270
}
271
#else
272
ProcessEngine();
273
#endif
274
}
275
276
#if RETRO_PLATFORM == RETRO_ANDROID
277
HideLoadingIcon(); // best spot to do it
278
#endif
279
280
if (videoSettings.windowState != WINDOWSTATE_ACTIVE)
281
continue;
282
283
#if !RETRO_USE_ORIGINAL_CODE
284
for (int32 t = 0; t < touchInfo.count; ++t) {
285
if (touchInfo.down[t]) {
286
int32 tx = (int32)(touchInfo.x[t] * screens->size.x);
287
int32 ty = (int32)(touchInfo.y[t] * screens->size.y);
288
289
if (tx <= 32 && ty <= 32) {
290
if (engine.devMenu) {
291
#if RETRO_REV0U
292
if (sceneInfo.state != ENGINESTATE_DEVMENU && RSDK::Legacy::gameMode != RSDK::Legacy::ENGINE_DEVMENU)
293
#else
294
if (sceneInfo.state != ENGINESTATE_DEVMENU)
295
#endif
296
OpenDevMenu();
297
}
298
}
299
}
300
}
301
#endif
302
if (engine.inFocus == 1) {
303
// Uncomment this code to add the build number to dev menu
304
// overrides the game subtitle, used in switch dev menu
305
if (currentScreen && sceneInfo.state == ENGINESTATE_DEVMENU) {
306
// Switch 1.00 build # is 17051, 1.04 is 18403
307
// char buffer[0x40];
308
// sprintf(buffer, "Build #%d", 18403);
309
// DrawRectangle(currentScreen->center.x - 128, currentScreen->center.y - 48, 256, 8, 0x008000, 0xFF, INK_NONE, true);
310
// DrawDevString(buffer, currentScreen->center.x, currentScreen->center.y - 48, 1, 0xF0F0F0);
311
}
312
313
RenderDevice::CopyFrameBuffer();
314
}
315
}
316
317
if ((engine.focusState & 1) || engine.inFocus == 1)
318
RenderDevice::ProcessDimming();
319
320
RenderDevice::FlipScreen();
321
}
322
}
323
324
// Shutdown
325
326
ReleaseInputDevices();
327
AudioDevice::Release();
328
RenderDevice::Release(false);
329
SaveSettingsINI(false);
330
SKU::ReleaseUserCore();
331
ReleaseStorage();
332
#if RETRO_USE_MOD_LOADER
333
UnloadMods();
334
#endif
335
336
Link::Close(gameLogicHandle);
337
gameLogicHandle = NULL;
338
339
if (engine.consoleEnabled)
340
ReleaseConsole();
341
342
return 0;
343
}
344
345
void RSDK::ProcessEngine()
346
{
347
switch (sceneInfo.state) {
348
default: break;
349
350
case ENGINESTATE_LOAD:
351
if (!sceneInfo.listData) {
352
sceneInfo.state = ENGINESTATE_NONE;
353
}
354
else {
355
#if RETRO_USE_MOD_LOADER
356
if (devMenu.modsChanged)
357
RefreshModFolders();
358
#endif
359
LoadSceneFolder();
360
LoadSceneAssets();
361
InitObjects();
362
363
#if RETRO_REV02
364
#if !RETRO_USE_ORIGINAL_CODE
365
AddViewableVariable("Show Hitboxes", &showHitboxes, VIEWVAR_BOOL, false, true);
366
AddViewableVariable("Show Palettes", &engine.showPaletteOverlay, VIEWVAR_BOOL, false, true);
367
AddViewableVariable("Show Obj Range", &engine.showUpdateRanges, VIEWVAR_UINT8, 0, 2);
368
AddViewableVariable("Show Obj Info", &engine.showEntityInfo, VIEWVAR_UINT8, 0, 2);
369
#endif
370
SKU::userCore->StageLoad();
371
for (int32 v = 0; v < DRAWGROUP_COUNT; ++v)
372
AddViewableVariable(drawGroupNames[v], &engine.drawGroupVisible[v], VIEWVAR_BOOL, false, true);
373
#endif
374
375
// dim after 5 mins
376
videoSettings.dimLimit = (5 * 60) * videoSettings.refreshRate;
377
ProcessInput();
378
ProcessObjects();
379
#if RETRO_VER_EGS || RETRO_USE_DUMMY_ACHIEVEMENTS
380
SKU::LoadAchievementAssets();
381
#endif
382
}
383
384
break;
385
386
case ENGINESTATE_REGULAR:
387
ProcessInput();
388
ProcessSceneTimer();
389
ProcessObjects();
390
ProcessParallaxAutoScroll();
391
392
for (int32 i = 1; i < engine.gameSpeed; ++i) {
393
if (sceneInfo.state != ENGINESTATE_REGULAR)
394
break;
395
396
ProcessSceneTimer();
397
ProcessObjects();
398
ProcessParallaxAutoScroll();
399
}
400
401
#if RETRO_VER_EGS || RETRO_USE_DUMMY_ACHIEVEMENTS
402
SKU::ProcessAchievements();
403
#endif
404
ProcessObjectDrawLists();
405
406
break;
407
408
case ENGINESTATE_PAUSED:
409
ProcessInput();
410
ProcessPausedObjects();
411
412
for (int32 i = 1; i < engine.gameSpeed; ++i) {
413
if (sceneInfo.state != ENGINESTATE_PAUSED)
414
break;
415
416
ProcessPausedObjects();
417
}
418
419
#if RETRO_VER_EGS || RETRO_USE_DUMMY_ACHIEVEMENTS
420
SKU::ProcessAchievements();
421
#endif
422
ProcessObjectDrawLists();
423
break;
424
425
case ENGINESTATE_FROZEN:
426
ProcessInput();
427
ProcessFrozenObjects();
428
429
for (int32 i = 1; i < engine.gameSpeed; ++i) {
430
if (sceneInfo.state != ENGINESTATE_FROZEN)
431
break;
432
433
ProcessFrozenObjects();
434
}
435
436
#if RETRO_VER_EGS || RETRO_USE_DUMMY_ACHIEVEMENTS
437
SKU::ProcessAchievements();
438
#endif
439
ProcessObjectDrawLists();
440
break;
441
442
case ENGINESTATE_LOAD | ENGINESTATE_STEPOVER:
443
#if RETRO_USE_MOD_LOADER
444
if (devMenu.modsChanged)
445
RefreshModFolders();
446
#endif
447
LoadSceneFolder();
448
LoadSceneAssets();
449
InitObjects();
450
451
#if RETRO_REV02
452
#if !RETRO_USE_ORIGINAL_CODE
453
AddViewableVariable("Show Hitboxes", &showHitboxes, VIEWVAR_BOOL, false, true);
454
AddViewableVariable("Show Palettes", &engine.showPaletteOverlay, VIEWVAR_BOOL, false, true);
455
AddViewableVariable("Show Obj Range", &engine.showUpdateRanges, VIEWVAR_UINT8, 0, 2);
456
AddViewableVariable("Show Obj Info", &engine.showEntityInfo, VIEWVAR_UINT8, 0, 2);
457
#endif
458
SKU::userCore->StageLoad();
459
for (int32 v = 0; v < DRAWGROUP_COUNT; ++v)
460
AddViewableVariable(drawGroupNames[v], &engine.drawGroupVisible[v], VIEWVAR_BOOL, false, true);
461
#endif
462
463
ProcessInput();
464
ProcessObjects();
465
sceneInfo.state = ENGINESTATE_REGULAR | ENGINESTATE_STEPOVER;
466
#if RETRO_VER_EGS || RETRO_USE_DUMMY_ACHIEVEMENTS
467
SKU::LoadAchievementAssets();
468
#endif
469
break;
470
471
case ENGINESTATE_REGULAR | ENGINESTATE_STEPOVER:
472
ProcessInput();
473
474
if (engine.frameStep) {
475
ProcessSceneTimer();
476
ProcessObjects();
477
ProcessParallaxAutoScroll();
478
#if RETRO_VER_EGS || RETRO_USE_DUMMY_ACHIEVEMENTS
479
SKU::ProcessAchievements();
480
#endif
481
ProcessObjectDrawLists();
482
engine.frameStep = false;
483
}
484
break;
485
486
case ENGINESTATE_PAUSED | ENGINESTATE_STEPOVER:
487
ProcessInput();
488
489
if (engine.frameStep) {
490
ProcessPausedObjects();
491
#if RETRO_VER_EGS || RETRO_USE_DUMMY_ACHIEVEMENTS
492
SKU::ProcessAchievements();
493
#endif
494
ProcessObjectDrawLists();
495
engine.frameStep = false;
496
}
497
break;
498
499
case ENGINESTATE_FROZEN | ENGINESTATE_STEPOVER:
500
ProcessInput();
501
502
if (engine.frameStep) {
503
ProcessFrozenObjects();
504
#if RETRO_VER_EGS || RETRO_USE_DUMMY_ACHIEVEMENTS
505
SKU::ProcessAchievements();
506
#endif
507
ProcessObjectDrawLists();
508
engine.frameStep = false;
509
}
510
break;
511
512
case ENGINESTATE_DEVMENU:
513
ProcessInput();
514
currentScreen = &screens[0];
515
516
if (devMenu.state)
517
devMenu.state();
518
break;
519
520
case ENGINESTATE_VIDEOPLAYBACK:
521
ProcessInput();
522
ProcessVideo();
523
break;
524
525
case ENGINESTATE_SHOWIMAGE:
526
ProcessInput();
527
528
if (engine.imageFadeSpeed <= 0.0 || videoSettings.dimMax >= 1.0) {
529
if (engine.displayTime <= 0.0) {
530
videoSettings.dimMax += engine.imageFadeSpeed;
531
if (videoSettings.dimMax <= 0.0) {
532
videoSettings.shaderID = engine.storedShaderID;
533
videoSettings.screenCount = 1;
534
sceneInfo.state = engine.storedState;
535
videoSettings.dimMax = 1.0;
536
}
537
}
538
else {
539
engine.displayTime -= (1.0 / 60.0); // deltaTime frame-step;
540
#if RETRO_USE_MOD_LOADER
541
RunModCallbacks(MODCB_ONVIDEOSKIPCB, (void *)engine.skipCallback);
542
#endif
543
if (engine.skipCallback && engine.skipCallback()) {
544
engine.displayTime = 0.0;
545
}
546
}
547
}
548
else {
549
videoSettings.dimMax += engine.imageFadeSpeed;
550
if (videoSettings.dimMax >= 1.0) {
551
engine.imageFadeSpeed = -engine.imageFadeSpeed;
552
videoSettings.dimMax = 1.0;
553
}
554
}
555
break;
556
557
#if RETRO_REV02
558
case ENGINESTATE_ERRORMSG: {
559
ProcessInput();
560
561
if (controller[0].keyStart.down)
562
sceneInfo.state = engine.storedState;
563
564
currentScreen = &screens[0];
565
int32 yOff = DevOutput_GetStringYSize(outputString);
566
DrawRectangle(0, currentScreen->center.y - (yOff >> 1), currentScreen->size.x, yOff, 128, 255, INK_NONE, true);
567
DrawDevString(outputString, 8, currentScreen->center.y - (yOff >> 1) + 8, 0, 0xF0F0F0);
568
break;
569
}
570
case ENGINESTATE_ERRORMSG_FATAL: {
571
ProcessInput();
572
573
if (controller[0].keyStart.down)
574
RenderDevice::isRunning = false;
575
576
currentScreen = &screens[0];
577
int32 yOff = DevOutput_GetStringYSize(outputString);
578
DrawRectangle(0, currentScreen->center.y - (yOff >> 1), currentScreen->size.x, yOff, 0xF00000, 255, INK_NONE, true);
579
DrawDevString(outputString, 8, currentScreen->center.y - (yOff >> 1) + 8, 0, 0xF0F0F0);
580
break;
581
}
582
#endif
583
}
584
}
585
586
void RSDK::ParseArguments(int32 argc, char *argv[])
587
{
588
memset(currentSceneFolder, 0, sizeof(currentSceneFolder));
589
memset(currentSceneID, 0, sizeof(currentSceneID));
590
#if RETRO_REV02
591
sceneInfo.filter = 0;
592
#endif
593
594
for (int32 a = 0; a < argc; ++a) {
595
const char *find = "";
596
597
find = strstr(argv[a], "stage=");
598
if (find) {
599
int32 b = 0;
600
int32 c = 6;
601
while (find[c] && find[c] != ';') currentSceneFolder[b++] = find[c++];
602
currentSceneFolder[b] = 0;
603
}
604
605
find = strstr(argv[a], "scene=");
606
if (find) {
607
int32 b = 0;
608
int32 c = 6;
609
while (find[c] && find[c] != ';') currentSceneID[b++] = find[c++];
610
currentSceneID[b] = 0;
611
}
612
613
#if RETRO_REV02
614
find = strstr(argv[a], "filter=");
615
if (find) {
616
char buf[0x10];
617
618
int32 b = 0;
619
int32 c = 7;
620
while (argv[a][c] && find[c] != ';') buf[b++] = find[c++];
621
buf[b] = 0;
622
sceneInfo.filter = atoi(buf);
623
}
624
#endif
625
626
#if !RETRO_DISABLE_LOG
627
find = strstr(argv[a], "console=true");
628
if (find) {
629
engine.consoleEnabled = true;
630
engine.devMenu = true;
631
}
632
#endif
633
}
634
}
635
636
void RSDK::InitEngine()
637
{
638
#if RETRO_PLATFORM == RETRO_ANDROID
639
ShowLoadingIcon(); // if valid
640
#endif
641
642
#if RETRO_REV0U
643
switch (engine.version) {
644
case 5:
645
#endif
646
StartGameObjects();
647
#if RETRO_REV0U
648
break;
649
650
case 4:
651
devMenu.state = DevMenu_MainMenu;
652
SetupFunctionTables();
653
654
Legacy::CalculateTrigAnglesM7();
655
656
engine.gamePlatform = (RETRO_DEVICETYPE == RETRO_STANDARD ? "STANDARD" : "MOBILE");
657
engine.gameRenderType = "SW_RENDERING";
658
engine.gameHapticSetting = "NO_F_FEEDBACK";
659
#if !RETRO_USE_ORIGINAL_CODE
660
engine.releaseType = (engine.gameReleaseID ? "USE_ORIGINS" : "USE_STANDALONE");
661
662
Legacy::deviceType = RETRO_DEVICETYPE;
663
if (SKU::curSKU.language <= LANGUAGE_JP)
664
Legacy::language = SKU::curSKU.language;
665
else {
666
switch (SKU::curSKU.language) {
667
default: Legacy::language = Legacy::LEGACY_LANGUAGE_EN; break;
668
case LANGUAGE_KO: Legacy::language = Legacy::LEGACY_LANGUAGE_KO; break;
669
case LANGUAGE_SC: Legacy::language = Legacy::LEGACY_LANGUAGE_ZS; break;
670
case LANGUAGE_TC: Legacy::language = Legacy::LEGACY_LANGUAGE_ZH; break;
671
}
672
}
673
#endif
674
675
Legacy::v4::LoadGameConfig("Data/Game/GameConfig.bin");
676
if (!useDataPack)
677
strcat(gameVerInfo.gameTitle, " (Using Data Folder)");
678
strcpy(gameVerInfo.version, "Legacy v4 Mode");
679
680
RSDK::GenerateBlendLookupTable();
681
Legacy::GenerateBlendLookupTable();
682
Legacy::v4::InitFirstStage();
683
Legacy::ResetCurrentStageFolder();
684
Legacy::v4::ClearScriptData();
685
break;
686
687
case 3:
688
devMenu.state = DevMenu_MainMenu;
689
SetupFunctionTables();
690
691
Legacy::CalculateTrigAnglesM7();
692
693
engine.gamePlatform = (RETRO_DEVICETYPE == RETRO_STANDARD ? "Standard" : "Mobile");
694
engine.gameRenderType = "SW_Rendering";
695
engine.gameHapticSetting = "No_Haptics";
696
#if !RETRO_USE_ORIGINAL_CODE
697
engine.releaseType = (engine.gameReleaseID ? "Use_Origins" : "Use_Standalone");
698
699
Legacy::deviceType = RETRO_DEVICETYPE;
700
switch (RETRO_PLATFORM) {
701
default:
702
case RETRO_WIN: Legacy::gamePlatformID = Legacy::LEGACY_RETRO_WIN; break;
703
case RETRO_OSX: Legacy::gamePlatformID = Legacy::LEGACY_RETRO_OSX; break;
704
case RETRO_iOS: Legacy::gamePlatformID = Legacy::LEGACY_RETRO_iOS; break;
705
case RETRO_XB1: Legacy::gamePlatformID = Legacy::LEGACY_RETRO_XBOX_360; break;
706
case RETRO_PS4: Legacy::gamePlatformID = Legacy::LEGACY_RETRO_PS3; break;
707
case RETRO_ANDROID: Legacy::gamePlatformID = Legacy::LEGACY_RETRO_ANDROID; break;
708
}
709
710
if (SKU::curSKU.language <= LANGUAGE_JP)
711
Legacy::language = SKU::curSKU.language;
712
else
713
Legacy::language = Legacy::LEGACY_LANGUAGE_EN;
714
#endif
715
716
Legacy::v3::LoadGameConfig("Data/Game/GameConfig.bin");
717
if (!useDataPack)
718
strcat(gameVerInfo.gameTitle, " (Using Data Folder)");
719
strcpy(gameVerInfo.version, "Legacy v3 Mode");
720
721
RSDK::GenerateBlendLookupTable();
722
Legacy::GenerateBlendLookupTable();
723
Legacy::v3::InitFirstStage();
724
Legacy::ResetCurrentStageFolder();
725
Legacy::v3::ClearScriptData();
726
break;
727
}
728
#endif
729
engine.initialized = true;
730
engine.hardPause = false;
731
#if RETRO_PLATFORM == RETRO_ANDROID
732
SetLoadingIcon();
733
#endif
734
735
#if RETRO_USE_MOD_LOADER
736
RunModCallbacks(MODCB_ONGAMESTARTUP, NULL); // rerun those callbacks
737
#endif
738
}
739
740
void RSDK::StartGameObjects()
741
{
742
#if RETRO_USE_MOD_LOADER
743
// ObjectClass is a non-POD struct because of std::function, we can't memset(0) or it would overwrite vtable data
744
for (int i = 0; i < OBJECT_COUNT; ++i) {
745
objectClassList[i] = {};
746
}
747
#else
748
memset(&objectClassList, 0, sizeof(objectClassList));
749
#endif
750
751
sceneInfo.classCount = 0;
752
sceneInfo.activeCategory = 0;
753
sceneInfo.listPos = 0;
754
sceneInfo.state = ENGINESTATE_LOAD;
755
sceneInfo.inEditor = false;
756
sceneInfo.debugMode = engine.devMenu;
757
devMenu.state = DevMenu_MainMenu;
758
759
for (int32 l = 0; l < DRAWGROUP_COUNT; ++l) engine.drawGroupVisible[l] = true;
760
761
SetupFunctionTables();
762
InitGameLink();
763
LoadGameConfig();
764
}
765
766
#if RETRO_USE_MOD_LOADER
767
void RSDK::LoadGameXML(bool pal)
768
{
769
FileInfo info;
770
SortMods();
771
for (int32 m = 0; m < modList.size(); ++m) {
772
if (!modList[m].active)
773
break;
774
SetActiveMod(m);
775
InitFileInfo(&info);
776
if (LoadFile(&info, "Data/Game/Game.xml", FMODE_RB)) {
777
tinyxml2::XMLDocument *doc = new tinyxml2::XMLDocument;
778
779
char *xmlData = new char[info.fileSize + 1];
780
ReadBytes(&info, xmlData, info.fileSize);
781
xmlData[info.fileSize] = 0;
782
CloseFile(&info);
783
784
doc->Parse(xmlData);
785
const tinyxml2::XMLElement *gameElement = doc->FirstChildElement("game"); // gameElement is nullptr if parse failure
786
787
if (gameElement) {
788
if (pal)
789
LoadXMLPalettes(gameElement);
790
else {
791
LoadXMLWindowText(gameElement);
792
LoadXMLObjects(gameElement);
793
LoadXMLSoundFX(gameElement);
794
LoadXMLStages(gameElement);
795
}
796
}
797
else {
798
PrintLog(PRINT_NORMAL, "[MOD] Failed to parse Game.xml file for mod %s", modList[m].id.c_str());
799
}
800
801
delete[] xmlData;
802
delete doc;
803
}
804
}
805
SetActiveMod(-1);
806
}
807
808
void RSDK::LoadXMLWindowText(const tinyxml2::XMLElement *gameElement)
809
{
810
const tinyxml2::XMLElement *titleElement = gameElement->FirstChildElement("title");
811
if (titleElement) {
812
const tinyxml2::XMLAttribute *nameAttr = titleElement->FindAttribute("name");
813
if (nameAttr)
814
strcpy(gameVerInfo.gameTitle, nameAttr->Value());
815
}
816
}
817
818
void RSDK::LoadXMLPalettes(const tinyxml2::XMLElement *gameElement)
819
{
820
const tinyxml2::XMLElement *paletteElement = gameElement->FirstChildElement("palette");
821
if (paletteElement) {
822
for (const tinyxml2::XMLElement *clrElement = paletteElement->FirstChildElement("color"); clrElement;
823
clrElement = clrElement->NextSiblingElement("color")) {
824
const tinyxml2::XMLAttribute *bankAttr = clrElement->FindAttribute("bank");
825
int32 bank = 0;
826
if (bankAttr)
827
bank = bankAttr->IntValue();
828
829
const tinyxml2::XMLAttribute *indAttr = clrElement->FindAttribute("index");
830
int32 index = 0;
831
if (indAttr)
832
index = indAttr->IntValue();
833
834
const tinyxml2::XMLAttribute *rAttr = clrElement->FindAttribute("r");
835
int32 r = 0;
836
if (rAttr)
837
r = rAttr->IntValue();
838
839
const tinyxml2::XMLAttribute *gAttr = clrElement->FindAttribute("g");
840
int32 g = 0;
841
if (gAttr)
842
g = gAttr->IntValue();
843
844
const tinyxml2::XMLAttribute *bAttr = clrElement->FindAttribute("b");
845
int32 b = 0;
846
if (bAttr)
847
b = bAttr->IntValue();
848
849
SetPaletteEntry(bank, index, (r << 16) | (g << 8) | b);
850
}
851
852
for (const tinyxml2::XMLElement *clrsElement = paletteElement->FirstChildElement("colors"); clrsElement;
853
clrsElement = clrsElement->NextSiblingElement("colors")) {
854
const tinyxml2::XMLAttribute *bankAttr = clrsElement->FindAttribute("bank");
855
int32 bank = 0;
856
if (bankAttr)
857
bank = bankAttr->IntValue();
858
859
const tinyxml2::XMLAttribute *indAttr = clrsElement->FindAttribute("start");
860
int32 index = 0;
861
if (indAttr)
862
index = indAttr->IntValue();
863
864
std::string text = clrsElement->GetText();
865
// working: AABBFF #FFaaFF (12,32,34) (145 53 234)
866
std::regex search(R"((?:#?([0-9A-F]{6}))|(?:\((\d+),?\s*(\d+),?\s*(\d+)\)))",
867
std::regex_constants::icase | std::regex_constants::ECMAScript);
868
std::smatch match;
869
while (std::regex_search(text, match, search)) {
870
int32 color;
871
if (match[1].matched) {
872
// we have hex, just set color directly lol
873
color = std::stoi(match[1].str(), nullptr, 16);
874
}
875
else {
876
// triplet
877
int32 r = std::stoi(match[2 + 0].str(), nullptr, 10);
878
int32 g = std::stoi(match[2 + 1].str(), nullptr, 10);
879
int32 b = std::stoi(match[2 + 2].str(), nullptr, 10);
880
color = (r << 16) | (g << 8) | b;
881
}
882
883
SetPaletteEntry(bank, index++, color);
884
text = match.suffix();
885
}
886
}
887
}
888
}
889
890
void RSDK::LoadXMLObjects(const tinyxml2::XMLElement *gameElement)
891
{
892
const tinyxml2::XMLElement *objectsElement = gameElement->FirstChildElement("objects");
893
if (objectsElement) {
894
for (const tinyxml2::XMLElement *objElement = objectsElement->FirstChildElement("object"); objElement;
895
objElement = objElement->NextSiblingElement("object")) {
896
const tinyxml2::XMLAttribute *nameAttr = objElement->FindAttribute("name");
897
const char *objName = "unknownObject";
898
if (nameAttr)
899
objName = nameAttr->Value();
900
901
RETRO_HASH_MD5(hash);
902
GEN_HASH_MD5(objName, hash);
903
globalObjectIDs[globalObjectCount] = 0;
904
for (int32 objID = 0; objID < objectClassCount; ++objID) {
905
if (HASH_MATCH_MD5(hash, objectClassList[objID].hash)) {
906
globalObjectIDs[globalObjectCount] = objID;
907
globalObjectCount++;
908
}
909
}
910
}
911
}
912
}
913
914
void RSDK::LoadXMLSoundFX(const tinyxml2::XMLElement *gameElement)
915
{
916
const tinyxml2::XMLElement *soundsElement = gameElement->FirstChildElement("sounds");
917
if (soundsElement) {
918
for (const tinyxml2::XMLElement *sfxElement = soundsElement->FirstChildElement("soundfx"); sfxElement;
919
sfxElement = sfxElement->NextSiblingElement("soundfx")) {
920
const tinyxml2::XMLAttribute *valAttr = sfxElement->FindAttribute("path");
921
const char *sfxPath = "unknownSFX.wav";
922
if (valAttr)
923
sfxPath = valAttr->Value();
924
925
const tinyxml2::XMLAttribute *playsAttr = sfxElement->FindAttribute("maxConcurrentPlays");
926
int32 maxConcurrentPlays = 0;
927
if (playsAttr)
928
maxConcurrentPlays = playsAttr->IntValue();
929
930
LoadSfx((char *)sfxPath, maxConcurrentPlays, SCOPE_GLOBAL);
931
}
932
}
933
}
934
935
#if !RETRO_REV0U
936
std::vector<SceneListEntry> listData;
937
std::vector<SceneListInfo> listCategory;
938
#endif
939
940
void RSDK::LoadXMLStages(const tinyxml2::XMLElement *gameElement)
941
{
942
943
for (const tinyxml2::XMLElement *listElement = gameElement->FirstChildElement("category"); listElement;
944
listElement = listElement->NextSiblingElement("category")) {
945
SceneListInfo *list = nullptr;
946
int32 listID;
947
948
const tinyxml2::XMLAttribute *nameAttr = listElement->FindAttribute("name");
949
const char *lstName = "unknown list";
950
if (nameAttr)
951
lstName = nameAttr->Value();
952
RETRO_HASH_MD5(hash);
953
GEN_HASH_MD5(lstName, hash);
954
955
for (int l = 0; l < listCategory.size(); ++l) {
956
if (HASH_MATCH_MD5(hash, listCategory[l].hash)) {
957
list = &listCategory[l];
958
listID = l;
959
}
960
}
961
962
if (!list) {
963
listCategory.emplace_back();
964
list = &listCategory.back();
965
sprintf_s(list->name, sizeof(list->name), "%s", lstName);
966
HASH_COPY_MD5(list->hash, hash);
967
968
list->sceneOffsetStart = listData.size();
969
list->sceneOffsetEnd = listData.size();
970
list->sceneCount = 0;
971
sceneInfo.categoryCount++;
972
}
973
974
for (const tinyxml2::XMLElement *stgElement = listElement->FirstChildElement("stage"); stgElement;
975
stgElement = stgElement->NextSiblingElement("stage")) {
976
const tinyxml2::XMLAttribute *nameAttr = stgElement->FindAttribute("name");
977
const char *stgName = "unknownStage";
978
if (nameAttr)
979
stgName = nameAttr->Value();
980
981
const tinyxml2::XMLAttribute *folderAttr = stgElement->FindAttribute("folder");
982
const char *stgFolder = "unknownStageFolder";
983
if (folderAttr)
984
stgFolder = folderAttr->Value();
985
986
const tinyxml2::XMLAttribute *idAttr = stgElement->FindAttribute("id");
987
const char *stgID = "unknownStageID";
988
if (idAttr)
989
stgID = idAttr->Value();
990
991
#if RETRO_REV02
992
const tinyxml2::XMLAttribute *filterAttr = stgElement->FindAttribute("filter");
993
int32 stgFilter = 0;
994
if (stgFilter)
995
stgFilter = filterAttr->IntValue();
996
#endif
997
listData.emplace(listData.begin() + list->sceneOffsetEnd);
998
SceneListEntry *scene = &listData[list->sceneOffsetEnd];
999
1000
sprintf_s(scene->name, sizeof(scene->name), "%s", stgName);
1001
GEN_HASH_MD5(scene->name, scene->hash);
1002
sprintf_s(scene->folder, sizeof(scene->folder), "%s", stgFolder);
1003
sprintf_s(scene->id, sizeof(scene->id), "%s", stgID);
1004
1005
#if RETRO_REV02
1006
scene->filter = stgFilter;
1007
if (scene->filter == 0x00)
1008
scene->filter = 0xFF;
1009
#endif
1010
list->sceneCount++;
1011
list->sceneOffsetEnd++;
1012
for (int32 l = listID + 1; l < listCategory.size(); ++l) listCategory[l].sceneOffsetStart++;
1013
}
1014
}
1015
sceneInfo.listData = listData.data();
1016
sceneInfo.listCategory = listCategory.data();
1017
}
1018
#endif
1019
1020
void RSDK::LoadGameConfig()
1021
{
1022
FileInfo info;
1023
InitFileInfo(&info);
1024
1025
if (LoadFile(&info, "Data/Game/GameConfig.bin", FMODE_RB)) {
1026
char buffer[0x100];
1027
uint32 sig = ReadInt32(&info, false);
1028
1029
if (sig != RSDK_SIGNATURE_CFG) {
1030
CloseFile(&info);
1031
return;
1032
}
1033
1034
ReadString(&info, gameVerInfo.gameTitle);
1035
if (!useDataPack)
1036
strcat(gameVerInfo.gameTitle, " (Data Folder)");
1037
ReadString(&info, gameVerInfo.gameSubtitle);
1038
ReadString(&info, gameVerInfo.version);
1039
1040
sceneInfo.activeCategory = ReadInt8(&info);
1041
int32 startScene = ReadInt16(&info);
1042
1043
uint8 objCnt = ReadInt8(&info);
1044
globalObjectCount = TYPE_DEFAULT_COUNT;
1045
for (int32 i = 0; i < objCnt; ++i) {
1046
ReadString(&info, textBuffer);
1047
1048
RETRO_HASH_MD5(hash);
1049
GEN_HASH_MD5_BUFFER(textBuffer, hash);
1050
1051
if (objectClassCount > 0) {
1052
globalObjectIDs[globalObjectCount] = 0;
1053
for (int32 objID = 0; objID < objectClassCount; ++objID) {
1054
if (HASH_MATCH_MD5(hash, objectClassList[objID].hash)) {
1055
globalObjectIDs[globalObjectCount] = objID;
1056
globalObjectCount++;
1057
}
1058
}
1059
}
1060
}
1061
1062
for (int32 i = 0; i < PALETTE_BANK_COUNT; ++i) {
1063
activeGlobalRows[i] = ReadInt16(&info);
1064
for (int32 r = 0; r < 0x10; ++r) {
1065
if ((activeGlobalRows[i] >> r & 1)) {
1066
for (int32 c = 0; c < 0x10; ++c) {
1067
uint8 red = ReadInt8(&info);
1068
uint8 green = ReadInt8(&info);
1069
uint8 blue = ReadInt8(&info);
1070
globalPalette[i][(r << 4) + c] = rgb32To16_B[blue] | rgb32To16_G[green] | rgb32To16_R[red];
1071
}
1072
}
1073
else {
1074
for (int32 c = 0; c < 0x10; ++c) globalPalette[i][(r << 4) + c] = 0;
1075
}
1076
}
1077
}
1078
1079
uint8 sfxCnt = ReadInt8(&info);
1080
for (int32 i = 0; i < sfxCnt; ++i) {
1081
ReadString(&info, buffer);
1082
uint8 maxConcurrentPlays = ReadInt8(&info);
1083
LoadSfx(buffer, maxConcurrentPlays, SCOPE_GLOBAL);
1084
}
1085
1086
uint16 totalSceneCount = ReadInt16(&info);
1087
1088
if (!totalSceneCount)
1089
totalSceneCount = 1;
1090
1091
if (strlen(currentSceneFolder) && strlen(currentSceneID)) {
1092
#if RETRO_USE_MOD_LOADER
1093
listData.resize(totalSceneCount + 1);
1094
sceneInfo.listData = listData.data();
1095
#else
1096
AllocateStorage((void **)&sceneInfo.listData, sizeof(SceneListEntry) * (totalSceneCount + 1), DATASET_STG, false);
1097
#endif
1098
SceneListEntry *scene = &sceneInfo.listData[totalSceneCount];
1099
strcpy(scene->name, "_RSDK_SCENE");
1100
strcpy(scene->folder, currentSceneFolder);
1101
strcpy(scene->id, currentSceneID);
1102
#if RETRO_REV02
1103
scene->filter = sceneInfo.filter;
1104
#endif
1105
GEN_HASH_MD5(scene->name, scene->hash);
1106
1107
// Override existing values
1108
sceneInfo.activeCategory = 0;
1109
startScene = totalSceneCount;
1110
currentSceneFolder[0] = 0;
1111
currentSceneID[0] = 0;
1112
}
1113
else {
1114
#if RETRO_USE_MOD_LOADER
1115
listData.resize(totalSceneCount);
1116
sceneInfo.listData = listData.data();
1117
#else
1118
AllocateStorage((void **)&sceneInfo.listData, sizeof(SceneListEntry) * totalSceneCount, DATASET_STG, false);
1119
#endif
1120
}
1121
1122
sceneInfo.categoryCount = ReadInt8(&info);
1123
sceneInfo.listPos = 0;
1124
1125
int32 categoryCount = sceneInfo.categoryCount;
1126
1127
if (!categoryCount)
1128
categoryCount = 1;
1129
1130
#if RETRO_USE_MOD_LOADER
1131
listCategory.resize(categoryCount);
1132
sceneInfo.listCategory = listCategory.data();
1133
#else
1134
AllocateStorage((void **)&sceneInfo.listCategory, sizeof(SceneListInfo) * categoryCount, DATASET_STG, false);
1135
#endif
1136
sceneInfo.listPos = 0;
1137
1138
int32 sceneID = 0;
1139
for (int32 i = 0; i < sceneInfo.categoryCount; ++i) {
1140
SceneListInfo *category = &sceneInfo.listCategory[i];
1141
ReadString(&info, category->name);
1142
GEN_HASH_MD5(category->name, category->hash);
1143
1144
category->sceneOffsetStart = sceneID;
1145
category->sceneCount = ReadInt8(&info);
1146
for (int32 s = 0; s < category->sceneCount; ++s) {
1147
SceneListEntry *scene = &sceneInfo.listData[sceneID + s];
1148
ReadString(&info, scene->name);
1149
GEN_HASH_MD5(scene->name, scene->hash);
1150
1151
ReadString(&info, scene->folder);
1152
ReadString(&info, scene->id);
1153
1154
#if RETRO_REV02
1155
scene->filter = ReadInt8(&info);
1156
if (scene->filter == 0x00)
1157
scene->filter = 0xFF;
1158
#endif
1159
}
1160
category->sceneOffsetEnd = category->sceneCount ? category->sceneOffsetStart + category->sceneCount - 1 : 0;
1161
sceneID += category->sceneCount;
1162
}
1163
1164
uint8 varCount = ReadInt8(&info);
1165
for (int32 i = 0; i < varCount; ++i) {
1166
#if RETRO_REV0U
1167
// v5U Ditches this in favour of the InitVarsCB method
1168
ReadInt32(&info, false);
1169
int32 count = ReadInt32(&info, false);
1170
for (int32 v = 0; v < count; ++v) ReadInt32(&info, false);
1171
#else
1172
if (!globalVarsPtr)
1173
break;
1174
// standard v5 loads variables directly into the struct
1175
int32 offset = ReadInt32(&info, false);
1176
int32 count = ReadInt32(&info, false);
1177
for (int32 v = 0; v < count; ++v) {
1178
globalVarsPtr[offset + v] = ReadInt32(&info, false);
1179
}
1180
#endif
1181
}
1182
1183
CloseFile(&info);
1184
#if RETRO_USE_MOD_LOADER
1185
LoadGameXML();
1186
#endif
1187
1188
#if RETRO_REV0U
1189
if (globalVarsInitCB)
1190
globalVarsInitCB(globalVarsPtr);
1191
#endif
1192
1193
sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart + startScene;
1194
}
1195
}
1196
1197
void RSDK::InitGameLink()
1198
{
1199
#if RETRO_USE_MOD_LOADER
1200
objectClassCount = 0;
1201
memset(globalObjectIDs, 0, sizeof(globalObjectIDs));
1202
memset(objectEntityList, 0, sizeof(objectEntityList));
1203
editableVarCount = 0;
1204
foreachStackPtr = foreachStackList;
1205
currentMod = NULL;
1206
#endif
1207
1208
#if RETRO_REV0U
1209
RegisterObject((Object **)&DefaultObject, ":DefaultObject:", sizeof(EntityBase), sizeof(ObjectDefaultObject), DefaultObject_Update,
1210
DefaultObject_LateUpdate, DefaultObject_StaticUpdate, DefaultObject_Draw, DefaultObject_Create, DefaultObject_StageLoad,
1211
DefaultObject_EditorLoad, DefaultObject_EditorDraw, DefaultObject_Serialize, (void (*)(Object *))DefaultObject_StaticLoad);
1212
1213
RegisterObject((Object **)&DevOutput, ":DevOutput:", sizeof(EntityDevOutput), sizeof(ObjectDevOutput), DevOutput_Update, DevOutput_LateUpdate,
1214
DevOutput_StaticUpdate, DevOutput_Draw, DevOutput_Create, DevOutput_StageLoad, DevOutput_EditorLoad, DevOutput_EditorDraw,
1215
DevOutput_Serialize, (void (*)(Object *))DevOutput_StaticLoad);
1216
#elif RETRO_REV02
1217
RegisterObject((Object **)&DefaultObject, ":DefaultObject:", sizeof(EntityBase), sizeof(ObjectDefaultObject), DefaultObject_Update,
1218
DefaultObject_LateUpdate, DefaultObject_StaticUpdate, DefaultObject_Draw, DefaultObject_Create, DefaultObject_StageLoad,
1219
DefaultObject_EditorLoad, DefaultObject_EditorDraw, DefaultObject_Serialize);
1220
1221
RegisterObject((Object **)&DevOutput, ":DevOutput:", sizeof(EntityDevOutput), sizeof(ObjectDevOutput), DevOutput_Update, DevOutput_LateUpdate,
1222
DevOutput_StaticUpdate, DevOutput_Draw, DevOutput_Create, DevOutput_StageLoad, DevOutput_EditorLoad, DevOutput_EditorDraw,
1223
DevOutput_Serialize);
1224
#else // RETRO_REV01
1225
RegisterObject((Object **)&DefaultObject, ":DefaultObject:", sizeof(EntityDefaultObject), sizeof(ObjectDefaultObject), DefaultObject_Update,
1226
DefaultObject_LateUpdate, DefaultObject_StaticUpdate, DefaultObject_Draw, DefaultObject_Create, DefaultObject_StageLoad,
1227
DefaultObject_EditorLoad, DefaultObject_EditorDraw, DefaultObject_Serialize);
1228
#endif
1229
1230
globalObjectIDs[0] = TYPE_DEFAULTOBJECT;
1231
#if RETRO_REV02
1232
globalObjectIDs[1] = TYPE_DEVOUTPUT;
1233
#endif
1234
1235
globalObjectCount = TYPE_DEFAULT_COUNT;
1236
1237
#if RETRO_REV02
1238
EngineInfo info;
1239
1240
info.functionTable = RSDKFunctionTable;
1241
info.APITable = APIFunctionTable;
1242
1243
info.currentSKU = &SKU::curSKU;
1244
info.gameInfo = &gameVerInfo;
1245
info.sceneInfo = &sceneInfo;
1246
1247
info.controller = controller;
1248
info.stickL = stickL;
1249
info.stickR = stickR;
1250
info.triggerL = triggerL;
1251
info.triggerR = triggerR;
1252
info.touchMouse = &touchInfo;
1253
1254
info.unknown = &SKU::unknownInfo;
1255
1256
info.screenInfo = screens;
1257
1258
#if RETRO_USE_MOD_LOADER
1259
info.modTable = modFunctionTable;
1260
#endif
1261
#else
1262
EngineInfo info;
1263
1264
info.functionTable = RSDKFunctionTable;
1265
1266
info.gameInfo = &gameVerInfo;
1267
info.sceneInfo = &sceneInfo;
1268
1269
info.controllerInfo = controller;
1270
info.stickInfo = stickL;
1271
info.touchInfo = &touchInfo;
1272
1273
info.screenInfo = screens;
1274
1275
#if RETRO_USE_MOD_LOADER
1276
info.modTable = modFunctionTable;
1277
#endif
1278
#endif
1279
1280
bool32 linked = false;
1281
1282
#if RETRO_USE_MOD_LOADER
1283
if (!modSettings.disableGameLogic) {
1284
#endif
1285
if (engine.useExternalCode) {
1286
char buffer[0x100];
1287
#if RETRO_PLATFORM == RETRO_WIN
1288
strcpy_s(buffer, 0x100, gameLogicName);
1289
#else
1290
sprintf(buffer, "%s%s", SKU::userFileDir, gameLogicName);
1291
#endif
1292
if (!gameLogicHandle)
1293
gameLogicHandle = Link::Open(buffer);
1294
1295
if (gameLogicHandle) {
1296
bool32 canLink = true;
1297
#if !RETRO_USE_ORIGINAL_CODE
1298
int32 *RSDKRevision = (int32 *)Link::GetSymbol(gameLogicHandle, "RSDKRevision");
1299
if (RSDKRevision) {
1300
canLink = *RSDKRevision == RETRO_REVISION;
1301
if (!canLink)
1302
PrintLog(PRINT_NORMAL, "ERROR: Game Logic RSDK Revision doesn't match Engine RSDK Revision!");
1303
}
1304
#endif
1305
1306
LogicLinkHandle linkGameLogic = (LogicLinkHandle)Link::GetSymbol(gameLogicHandle, "LinkGameLogicDLL");
1307
if (canLink && linkGameLogic) {
1308
#if RETRO_REV02
1309
linkGameLogic(&info);
1310
#else
1311
linkGameLogic(info);
1312
#endif
1313
linked = true;
1314
}
1315
else if (canLink && !linkGameLogic) {
1316
PrintLog(PRINT_ERROR, "ERROR: Failed to find 'LinkGameLogicDLL' -> %s", Link::GetError());
1317
}
1318
}
1319
else {
1320
PrintLog(PRINT_ERROR, "ERROR: Failed to open game logic file -> %s", Link::GetError());
1321
}
1322
1323
if (!linked)
1324
PrintLog(PRINT_NORMAL, "ERROR: Failed to link game logic!");
1325
}
1326
else {
1327
#if RETRO_REV02
1328
linkGameLogic(&info);
1329
#else
1330
linkGameLogic(info);
1331
#endif
1332
}
1333
#if RETRO_USE_MOD_LOADER
1334
}
1335
1336
for (int32 m = 0; m < modList.size(); ++m) {
1337
currentMod = &modList[m];
1338
if (!currentMod->active)
1339
break;
1340
for (modLinkSTD linkModLogic : modList[m].linkModLogic) {
1341
if (!linkModLogic(&info, modList[m].id.c_str())) {
1342
modList[m].active = false;
1343
PrintLog(PRINT_ERROR, "[MOD] Failed to link logic for mod %s!", modList[m].id.c_str());
1344
}
1345
}
1346
}
1347
1348
currentMod = NULL;
1349
#endif
1350
}
1351
1352
void RSDK::ProcessDebugCommands()
1353
{
1354
#if !RETRO_USE_ORIGINAL_CODE
1355
if (!customSettings.enableControllerDebugging)
1356
return;
1357
#endif
1358
1359
if (controller[CONT_P1].keySelect.press) {
1360
#if RETRO_REV0U
1361
if (sceneInfo.state == ENGINESTATE_DEVMENU || RSDK::Legacy::gameMode == RSDK::Legacy::ENGINE_DEVMENU)
1362
#else
1363
if (sceneInfo.state == ENGINESTATE_DEVMENU)
1364
#endif
1365
CloseDevMenu();
1366
else
1367
OpenDevMenu();
1368
}
1369
1370
#if RETRO_REV0U
1371
int32 state = engine.version == 5 ? sceneInfo.state : Legacy::stageMode;
1372
const int32 stepOver = engine.version == 5 ? (int32)ENGINESTATE_STEPOVER : (int32)Legacy::STAGEMODE_STEPOVER;
1373
#else
1374
uint8 state = sceneInfo.state;
1375
const uint8 stepOver = ENGINESTATE_STEPOVER;
1376
#endif
1377
1378
bool32 framePaused = (state & stepOver) == stepOver;
1379
1380
#if RETRO_REV02
1381
if (triggerL[CONT_P1].keyBumper.down) {
1382
if (triggerL[CONT_P1].keyTrigger.down || triggerL[CONT_P1].triggerDelta >= 0.3) {
1383
if (!framePaused)
1384
state ^= stepOver;
1385
}
1386
else {
1387
if (framePaused)
1388
state ^= stepOver;
1389
}
1390
1391
framePaused = (state & stepOver) == stepOver;
1392
1393
if (framePaused) {
1394
if (triggerR[CONT_P1].keyBumper.press)
1395
engine.frameStep = true;
1396
}
1397
else {
1398
engine.gameSpeed = (triggerR[CONT_P1].keyTrigger.down || triggerR[CONT_P1].triggerDelta >= 0.3) ? 8 : 1;
1399
}
1400
}
1401
else {
1402
if (engine.gameSpeed == 8)
1403
engine.gameSpeed = 1;
1404
1405
if (framePaused)
1406
state ^= stepOver;
1407
}
1408
1409
#if RETRO_REV0U
1410
if (engine.version != 5)
1411
Legacy::stageMode = state;
1412
else
1413
#endif
1414
sceneInfo.state = state;
1415
#else
1416
if (controller[CONT_P1].keyBumperL.down) {
1417
if (controller[CONT_P1].keyTriggerL.down || stickL[CONT_P1].triggerDeltaL >= 0.3) {
1418
if (!framePaused)
1419
sceneInfo.state ^= ENGINESTATE_STEPOVER;
1420
}
1421
else {
1422
if (framePaused)
1423
sceneInfo.state ^= ENGINESTATE_STEPOVER;
1424
}
1425
1426
framePaused = (sceneInfo.state >> 2) & 1;
1427
if (framePaused) {
1428
if (controller[CONT_P1].keyBumperR.press)
1429
engine.frameStep = true;
1430
}
1431
else {
1432
engine.gameSpeed = (controller[CONT_P1].keyTriggerR.down || stickL[CONT_P1].triggerDeltaR >= 0.3) ? 8 : 1;
1433
}
1434
}
1435
else {
1436
if (engine.gameSpeed == 8)
1437
engine.gameSpeed = 1;
1438
1439
if (framePaused)
1440
sceneInfo.state ^= ENGINESTATE_STEPOVER;
1441
}
1442
#endif
1443
}
1444
1445
#ifdef __SWITCH__
1446
#include <switch.h>
1447
#include <stdlib.h>
1448
#include <stdio.h>
1449
#include <string.h>
1450
#include <sys/socket.h>
1451
#include <sys/errno.h>
1452
#include <arpa/inet.h>
1453
#include <unistd.h>
1454
#include "RetroEngine.hpp"
1455
1456
static int32 s_nxlinkSock = -1;
1457
1458
static void initNxLink()
1459
{
1460
if (R_FAILED(socketInitializeDefault()))
1461
return;
1462
1463
s_nxlinkSock = nxlinkStdio();
1464
if (s_nxlinkSock >= 0)
1465
printf("printf output now goes to nxlink server\n");
1466
else
1467
socketExit();
1468
}
1469
#endif
1470
1471
void RSDK::InitCoreAPI()
1472
{
1473
#if RETRO_RENDERDEVICE_DIRECTX9 || RETRO_RENDERDEVICE_DIRECTX11
1474
MSG Msg;
1475
PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE);
1476
InitCommonControls();
1477
#endif
1478
1479
#ifdef __SWITCH__
1480
Result res;
1481
if (R_FAILED(res = dynInitialize()))
1482
diagAbortWithResult(res);
1483
#endif
1484
1485
#if RETRO_RENDERDEVICE_SDL2 || RETRO_AUDIODEVICE_SDL2 || RETRO_INPUTDEVICE_SDL2
1486
SDL_Init(0);
1487
#endif
1488
}
1489
void RSDK::ReleaseCoreAPI()
1490
{
1491
#if RETRO_RENDERDEVICE_SDL2 || RETRO_AUDIODEVICE_SDL2 || RETRO_INPUTDEVICE_SDL2
1492
SDL_Quit();
1493
#endif
1494
1495
#ifdef __SWITCH__
1496
dynExit();
1497
#endif
1498
}
1499
1500
void RSDK::InitConsole()
1501
{
1502
#if RETRO_PLATFORM == RETRO_WIN
1503
AllocConsole();
1504
AttachConsole(GetCurrentProcessId());
1505
1506
freopen("CON", "w", stdout);
1507
#endif
1508
1509
#if RETRO_PLATFORM == RETRO_SWITCH
1510
consoleInit(NULL);
1511
#endif
1512
}
1513
void RSDK::ReleaseConsole()
1514
{
1515
#if RETRO_PLATFORM == RETRO_WIN
1516
FreeConsole();
1517
#endif
1518
}
1519
1520
void RSDK::SendQuitMsg()
1521
{
1522
#if RETRO_RENDERDEVICE_DIRECTX9 || RETRO_RENDERDEVICE_DIRECTX11
1523
PostQuitMessage(0);
1524
#endif
1525
}
1526
1527