Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-1-2-2013-Decompilation
Path: blob/main/RSDKv4/Scene.cpp
817 views
1
#include "RetroEngine.hpp"
2
3
int stageListCount[STAGELIST_MAX];
4
char stageListNames[STAGELIST_MAX][0x20] = {
5
"Presentation Stages",
6
"Regular Stages",
7
"Bonus Stages",
8
"Special Stages",
9
};
10
SceneInfo stageList[STAGELIST_MAX][0x100];
11
12
int stageMode = STAGEMODE_LOAD;
13
14
int cameraTarget = -1;
15
int cameraStyle = CAMERASTYLE_FOLLOW;
16
int cameraEnabled = 0;
17
int cameraAdjustY = 0;
18
int xScrollOffset = 0;
19
int yScrollOffset = 0;
20
int cameraXPos = 0;
21
int cameraYPos = 0;
22
int cameraShift = 0;
23
int cameraLockedY = 0;
24
int cameraShakeX = 0;
25
int cameraShakeY = 0;
26
int cameraLag = 0;
27
int cameraLagStyle = 0;
28
29
int curXBoundary1 = 0;
30
int newXBoundary1 = 0;
31
int curYBoundary1 = 0;
32
int newYBoundary1 = 0;
33
int curXBoundary2 = 0;
34
int curYBoundary2 = 0;
35
int waterLevel = 0;
36
int waterDrawPos = 0;
37
int newXBoundary2 = 0;
38
int newYBoundary2 = 0;
39
40
int SCREEN_SCROLL_LEFT = SCREEN_CENTERX - 8;
41
int SCREEN_SCROLL_RIGHT = SCREEN_CENTERX + 8;
42
43
int lastYSize = -1;
44
int lastXSize = -1;
45
46
bool pauseEnabled = true;
47
bool timeEnabled = true;
48
bool debugMode = false;
49
int frameCounter = 0;
50
int stageMilliseconds = 0;
51
int stageSeconds = 0;
52
int stageMinutes = 0;
53
54
// Category and Scene IDs
55
int activeStageList = 0;
56
int stageListPosition = 0;
57
char currentStageFolder[0x100];
58
int actID = 0;
59
60
char titleCardText[0x100];
61
byte titleCardWord2 = 0;
62
63
byte activeTileLayers[4];
64
byte tLayerMidPoint;
65
TileLayer stageLayouts[LAYER_COUNT];
66
67
int bgDeformationData0[DEFORM_COUNT];
68
int bgDeformationData1[DEFORM_COUNT];
69
int bgDeformationData2[DEFORM_COUNT];
70
int bgDeformationData3[DEFORM_COUNT];
71
72
LineScroll hParallax;
73
LineScroll vParallax;
74
75
Tiles128x128 tiles128x128;
76
CollisionMasks collisionMasks[2];
77
78
byte tilesetGFXData[TILESET_SIZE];
79
80
ushort tile3DFloorBuffer[0x100 * 0x100];
81
bool drawStageGFXHQ = false;
82
83
#if RETRO_USE_MOD_LOADER
84
bool loadGlobalScripts = false; // stored here so I can use it later
85
int globalObjCount = 0;
86
#endif
87
88
void InitFirstStage(void)
89
{
90
xScrollOffset = 0;
91
yScrollOffset = 0;
92
StopMusic(true);
93
StopAllSfx();
94
ReleaseStageSfx();
95
fadeMode = 0;
96
ClearGraphicsData();
97
ClearAnimationData();
98
activePalette = fullPalette[0];
99
activePalette32 = fullPalette32[0];
100
stageMode = STAGEMODE_LOAD;
101
Engine.gameMode = ENGINE_MAINGAME;
102
activeStageList = 0;
103
stageListPosition = 0;
104
}
105
106
void InitStartingStage(int list, int stage, int player)
107
{
108
xScrollOffset = 0;
109
yScrollOffset = 0;
110
StopMusic(true);
111
StopAllSfx();
112
ReleaseStageSfx();
113
fadeMode = 0;
114
playerListPos = player;
115
ClearGraphicsData();
116
ClearAnimationData();
117
ResetCurrentStageFolder();
118
activeStageList = list;
119
activePalette = fullPalette[0];
120
activePalette32 = fullPalette32[0];
121
stageMode = STAGEMODE_LOAD;
122
Engine.gameMode = ENGINE_MAINGAME;
123
stageListPosition = stage;
124
}
125
126
void ProcessStage(void)
127
{
128
#if !RETRO_USE_ORIGINAL_CODE
129
debugHitboxCount = 0;
130
#endif
131
132
switch (stageMode) {
133
case STAGEMODE_LOAD: // Startup
134
SetActivePalette(0, 0, 256);
135
gameMenu[0].visibleRowOffset = 0;
136
gameMenu[1].alignment = 0;
137
gameMenu[1].selectionCount = 0;
138
fadeMode = 0;
139
cameraEnabled = true;
140
cameraTarget = -1;
141
cameraShift = 0;
142
cameraStyle = CAMERASTYLE_FOLLOW;
143
cameraXPos = 0;
144
cameraYPos = 0;
145
cameraLockedY = 0;
146
cameraAdjustY = 0;
147
xScrollOffset = 0;
148
yScrollOffset = 0;
149
cameraShakeX = 0;
150
cameraShakeY = 0;
151
vertexCount = 0;
152
faceCount = 0;
153
frameCounter = 0;
154
pauseEnabled = false;
155
timeEnabled = false;
156
stageMilliseconds = 0;
157
stageSeconds = 0;
158
stageMinutes = 0;
159
stageMode = STAGEMODE_NORMAL;
160
161
#if RSDK_AUTOBUILD
162
// Prevent playing as Amy if on autobuilds
163
if (GetGlobalVariableByName("PLAYER_AMY") && playerListPos == GetGlobalVariableByName("PLAYER_AMY"))
164
playerListPos = 0;
165
else if (GetGlobalVariableByName("PLAYER_AMY_TAILS") && playerListPos == GetGlobalVariableByName("PLAYER_AMY_TAILS"))
166
playerListPos = 0;
167
#endif
168
169
#if RETRO_USE_MOD_LOADER
170
for (int m = 0; m < modList.size(); ++m) ScanModFolder(&modList[m]);
171
#endif
172
ResetBackgroundSettings();
173
LoadStageFiles();
174
175
#if RETRO_HARDWARE_RENDER
176
texBufferMode = 0;
177
for (int i = 0; i < LAYER_COUNT; i++) {
178
if (stageLayouts[i].type == LAYER_3DSKY)
179
texBufferMode = 1;
180
}
181
for (int i = 0; i < hParallax.entryCount; i++) {
182
if (hParallax.deform[i])
183
texBufferMode = 1;
184
}
185
186
if (tilesetGFXData[0x32002] > 0)
187
texBufferMode = 0;
188
189
if (texBufferMode) {
190
for (int i = 0; i < TILEUV_SIZE; i += 4) {
191
tileUVArray[i + 0] = (i >> 2) % 28 * 18 + 1;
192
tileUVArray[i + 1] = (i >> 2) / 28 * 18 + 1;
193
tileUVArray[i + 2] = tileUVArray[i + 0] + 16;
194
tileUVArray[i + 3] = tileUVArray[i + 1] + 16;
195
}
196
tileUVArray[TILEUV_SIZE - 4] = 487.0f;
197
tileUVArray[TILEUV_SIZE - 3] = 487.0f;
198
tileUVArray[TILEUV_SIZE - 2] = 503.0f;
199
tileUVArray[TILEUV_SIZE - 1] = 503.0f;
200
}
201
else {
202
for (int i = 0; i < TILEUV_SIZE; i += 4) {
203
tileUVArray[i + 0] = (i >> 2 & 31) * 16;
204
tileUVArray[i + 1] = (i >> 2 >> 5) * 16;
205
tileUVArray[i + 2] = tileUVArray[i + 0] + 16;
206
tileUVArray[i + 3] = tileUVArray[i + 1] + 16;
207
}
208
}
209
210
UpdateHardwareTextures();
211
gfxIndexSize = 0;
212
gfxVertexSize = 0;
213
gfxIndexSizeOpaque = 0;
214
gfxVertexSizeOpaque = 0;
215
#endif
216
break;
217
218
case STAGEMODE_NORMAL:
219
drawStageGFXHQ = false;
220
if (fadeMode > 0)
221
fadeMode--;
222
223
lastXSize = -1;
224
lastYSize = -1;
225
CheckKeyDown(&keyDown);
226
CheckKeyPress(&keyPress);
227
if (pauseEnabled && keyPress.start) {
228
stageMode = STAGEMODE_NORMAL_STEP;
229
PauseSound();
230
}
231
232
if (timeEnabled) {
233
if (++frameCounter == 60) {
234
frameCounter = 0;
235
if (++stageSeconds > 59) {
236
stageSeconds = 0;
237
if (++stageMinutes > 59)
238
stageMinutes = 0;
239
}
240
}
241
stageMilliseconds = 100 * frameCounter / 60;
242
}
243
else {
244
frameCounter = 60 * stageMilliseconds / 100;
245
}
246
247
// Update
248
ProcessObjects();
249
250
if (cameraTarget > -1) {
251
if (cameraEnabled == 1) {
252
switch (cameraStyle) {
253
case CAMERASTYLE_FOLLOW: SetPlayerScreenPosition(&objectEntityList[cameraTarget]); break;
254
case CAMERASTYLE_EXTENDED:
255
case CAMERASTYLE_EXTENDED_OFFSET_L:
256
case CAMERASTYLE_EXTENDED_OFFSET_R: SetPlayerScreenPositionCDStyle(&objectEntityList[cameraTarget]); break;
257
case CAMERASTYLE_HLOCKED: SetPlayerHLockedScreenPosition(&objectEntityList[cameraTarget]); break;
258
default: break;
259
}
260
}
261
else {
262
SetPlayerLockedScreenPosition(&objectEntityList[cameraTarget]);
263
}
264
}
265
266
ProcessParallaxAutoScroll();
267
DrawStageGFX();
268
break;
269
270
case STAGEMODE_PAUSED:
271
drawStageGFXHQ = false;
272
if (fadeMode > 0)
273
fadeMode--;
274
275
lastXSize = -1;
276
lastYSize = -1;
277
CheckKeyDown(&keyDown);
278
CheckKeyPress(&keyPress);
279
280
if (pauseEnabled && keyPress.start) {
281
stageMode = STAGEMODE_PAUSED_STEP;
282
PauseSound();
283
}
284
285
// Update
286
ProcessPausedObjects();
287
288
#if RETRO_HARDWARE_RENDER
289
gfxIndexSize = 0;
290
gfxVertexSize = 0;
291
gfxIndexSizeOpaque = 0;
292
gfxVertexSizeOpaque = 0;
293
#endif
294
295
DrawObjectList(0);
296
DrawObjectList(1);
297
DrawObjectList(2);
298
DrawObjectList(3);
299
DrawObjectList(4);
300
DrawObjectList(5);
301
#if RETRO_REV03
302
#if !RETRO_USE_ORIGINAL_CODE
303
// Hacky fix for Tails Object not working properly in special stages on non-Origins bytecode
304
if (forceUseScripts || Engine.usingOrigins)
305
#endif
306
DrawObjectList(7);
307
#endif
308
DrawObjectList(6);
309
310
#if !RETRO_USE_ORIGINAL_CODE
311
DrawDebugOverlays();
312
#endif
313
break;
314
315
case STAGEMODE_FROZEN:
316
drawStageGFXHQ = false;
317
if (fadeMode > 0)
318
fadeMode--;
319
320
lastXSize = -1;
321
lastYSize = -1;
322
CheckKeyDown(&keyDown);
323
CheckKeyPress(&keyPress);
324
325
// Update
326
ProcessFrozenObjects();
327
328
if (cameraTarget > -1) {
329
if (cameraEnabled == 1) {
330
switch (cameraStyle) {
331
case CAMERASTYLE_FOLLOW: SetPlayerScreenPosition(&objectEntityList[cameraTarget]); break;
332
case CAMERASTYLE_EXTENDED:
333
case CAMERASTYLE_EXTENDED_OFFSET_L:
334
case CAMERASTYLE_EXTENDED_OFFSET_R: SetPlayerScreenPositionCDStyle(&objectEntityList[cameraTarget]); break;
335
case CAMERASTYLE_HLOCKED: SetPlayerHLockedScreenPosition(&objectEntityList[cameraTarget]); break;
336
default: break;
337
}
338
}
339
else {
340
SetPlayerLockedScreenPosition(&objectEntityList[cameraTarget]);
341
}
342
}
343
344
DrawStageGFX();
345
break;
346
347
#if !RETRO_REV00
348
case STAGEMODE_2P:
349
drawStageGFXHQ = false;
350
if (fadeMode > 0)
351
fadeMode--;
352
353
lastXSize = -1;
354
lastYSize = -1;
355
CheckKeyDown(&keyDown);
356
CheckKeyPress(&keyPress);
357
if (pauseEnabled && keyPress.start) {
358
stageMode = STAGEMODE_2P_STEP;
359
PauseSound();
360
}
361
362
if (timeEnabled) {
363
if (++frameCounter == 60) {
364
frameCounter = 0;
365
if (++stageSeconds > 59) {
366
stageSeconds = 0;
367
if (++stageMinutes > 59)
368
stageMinutes = 0;
369
}
370
}
371
stageMilliseconds = 100 * frameCounter / 60;
372
}
373
else {
374
frameCounter = 60 * stageMilliseconds / 100;
375
}
376
377
// Update
378
Process2PObjects();
379
380
if (cameraTarget > -1) {
381
if (cameraEnabled == 1) {
382
switch (cameraStyle) {
383
case CAMERASTYLE_FOLLOW: SetPlayerScreenPosition(&objectEntityList[cameraTarget]); break;
384
case CAMERASTYLE_EXTENDED:
385
case CAMERASTYLE_EXTENDED_OFFSET_L:
386
case CAMERASTYLE_EXTENDED_OFFSET_R: SetPlayerScreenPositionCDStyle(&objectEntityList[cameraTarget]); break;
387
case CAMERASTYLE_HLOCKED: SetPlayerHLockedScreenPosition(&objectEntityList[cameraTarget]); break;
388
default: break;
389
}
390
}
391
else {
392
SetPlayerLockedScreenPosition(&objectEntityList[cameraTarget]);
393
}
394
}
395
396
ProcessParallaxAutoScroll();
397
DrawStageGFX();
398
break;
399
#endif
400
401
case STAGEMODE_NORMAL_STEP:
402
drawStageGFXHQ = false;
403
if (fadeMode > 0)
404
fadeMode--;
405
406
lastXSize = -1;
407
lastYSize = -1;
408
CheckKeyDown(&keyDown);
409
CheckKeyPress(&keyPress);
410
411
if (keyPress.C) {
412
keyPress.C = false;
413
414
if (timeEnabled) {
415
if (++frameCounter == 60) {
416
frameCounter = 0;
417
if (++stageSeconds > 59) {
418
stageSeconds = 0;
419
if (++stageMinutes > 59)
420
stageMinutes = 0;
421
}
422
}
423
stageMilliseconds = 100 * frameCounter / 60;
424
}
425
else {
426
frameCounter = 60 * stageMilliseconds / 100;
427
}
428
429
ProcessObjects();
430
if (cameraTarget > -1) {
431
if (cameraEnabled == 1) {
432
switch (cameraStyle) {
433
case CAMERASTYLE_FOLLOW: SetPlayerScreenPosition(&objectEntityList[cameraTarget]); break;
434
case CAMERASTYLE_EXTENDED:
435
case CAMERASTYLE_EXTENDED_OFFSET_L:
436
case CAMERASTYLE_EXTENDED_OFFSET_R: SetPlayerScreenPositionCDStyle(&objectEntityList[cameraTarget]); break;
437
case CAMERASTYLE_HLOCKED: SetPlayerHLockedScreenPosition(&objectEntityList[cameraTarget]); break;
438
default: break;
439
}
440
}
441
else {
442
SetPlayerLockedScreenPosition(&objectEntityList[cameraTarget]);
443
}
444
}
445
446
DrawStageGFX();
447
ProcessParallaxAutoScroll();
448
}
449
450
if (pauseEnabled && keyPress.start) {
451
stageMode = STAGEMODE_NORMAL;
452
ResumeSound();
453
}
454
break;
455
456
case STAGEMODE_PAUSED_STEP:
457
drawStageGFXHQ = false;
458
if (fadeMode > 0)
459
fadeMode--;
460
461
lastXSize = -1;
462
lastYSize = -1;
463
CheckKeyDown(&keyDown);
464
CheckKeyPress(&keyPress);
465
466
if (keyPress.C) {
467
#if RETRO_HARDWARE_RENDER
468
gfxIndexSize = 0;
469
gfxVertexSize = 0;
470
gfxIndexSizeOpaque = 0;
471
gfxVertexSizeOpaque = 0;
472
#endif
473
474
keyPress.C = false;
475
ProcessPausedObjects();
476
DrawObjectList(0);
477
DrawObjectList(1);
478
DrawObjectList(2);
479
DrawObjectList(3);
480
DrawObjectList(4);
481
DrawObjectList(5);
482
#if RETRO_REV03
483
#if !RETRO_USE_ORIGINAL_CODE
484
// Hacky fix for Tails Object not working properly in special stages on non-Origins bytecode
485
if (forceUseScripts || Engine.usingOrigins)
486
#endif
487
DrawObjectList(7);
488
#endif
489
DrawObjectList(6);
490
491
#if !RETRO_USE_ORIGINAL_CODE
492
DrawDebugOverlays();
493
#endif
494
}
495
496
if (pauseEnabled && keyPress.start) {
497
stageMode = STAGEMODE_PAUSED;
498
ResumeSound();
499
}
500
break;
501
502
case STAGEMODE_FROZEN_STEP:
503
drawStageGFXHQ = false;
504
if (fadeMode > 0)
505
fadeMode--;
506
507
lastXSize = -1;
508
lastYSize = -1;
509
CheckKeyDown(&keyDown);
510
CheckKeyPress(&keyPress);
511
512
if (keyPress.C) {
513
keyPress.C = false;
514
515
// Update
516
ProcessFrozenObjects();
517
518
if (cameraTarget > -1) {
519
if (cameraEnabled == 1) {
520
switch (cameraStyle) {
521
case CAMERASTYLE_FOLLOW: SetPlayerScreenPosition(&objectEntityList[cameraTarget]); break;
522
case CAMERASTYLE_EXTENDED:
523
case CAMERASTYLE_EXTENDED_OFFSET_L:
524
case CAMERASTYLE_EXTENDED_OFFSET_R: SetPlayerScreenPositionCDStyle(&objectEntityList[cameraTarget]); break;
525
case CAMERASTYLE_HLOCKED: SetPlayerHLockedScreenPosition(&objectEntityList[cameraTarget]); break;
526
default: break;
527
}
528
}
529
else {
530
SetPlayerLockedScreenPosition(&objectEntityList[cameraTarget]);
531
}
532
}
533
534
DrawStageGFX();
535
}
536
if (pauseEnabled && keyPress.start) {
537
stageMode = STAGEMODE_FROZEN;
538
ResumeSound();
539
}
540
break;
541
542
#if !RETRO_REV00
543
case STAGEMODE_2P_STEP:
544
drawStageGFXHQ = false;
545
if (fadeMode > 0)
546
fadeMode--;
547
548
lastXSize = -1;
549
lastYSize = -1;
550
CheckKeyDown(&keyDown);
551
CheckKeyPress(&keyPress);
552
if (keyPress.C) {
553
keyPress.C = false;
554
555
if (timeEnabled) {
556
if (++frameCounter == 60) {
557
frameCounter = 0;
558
if (++stageSeconds > 59) {
559
stageSeconds = 0;
560
if (++stageMinutes > 59)
561
stageMinutes = 0;
562
}
563
}
564
stageMilliseconds = 100 * frameCounter / 60;
565
}
566
else {
567
frameCounter = 60 * stageMilliseconds / 100;
568
}
569
570
// Update
571
Process2PObjects();
572
573
if (cameraTarget > -1) {
574
if (cameraEnabled == 1) {
575
switch (cameraStyle) {
576
case CAMERASTYLE_FOLLOW: SetPlayerScreenPosition(&objectEntityList[cameraTarget]); break;
577
case CAMERASTYLE_EXTENDED:
578
case CAMERASTYLE_EXTENDED_OFFSET_L:
579
case CAMERASTYLE_EXTENDED_OFFSET_R: SetPlayerScreenPositionCDStyle(&objectEntityList[cameraTarget]); break;
580
case CAMERASTYLE_HLOCKED: SetPlayerHLockedScreenPosition(&objectEntityList[cameraTarget]); break;
581
default: break;
582
}
583
}
584
else {
585
SetPlayerLockedScreenPosition(&objectEntityList[cameraTarget]);
586
}
587
}
588
589
DrawStageGFX();
590
ProcessParallaxAutoScroll();
591
}
592
593
if (pauseEnabled && keyPress.start) {
594
stageMode = STAGEMODE_2P;
595
ResumeSound();
596
}
597
break;
598
#endif
599
}
600
}
601
602
void ProcessParallaxAutoScroll()
603
{
604
for (int i = 0; i < hParallax.entryCount; ++i) hParallax.scrollPos[i] += hParallax.scrollSpeed[i];
605
for (int i = 0; i < vParallax.entryCount; ++i) vParallax.scrollPos[i] += vParallax.scrollSpeed[i];
606
}
607
608
void LoadStageFiles(void)
609
{
610
FileInfo infoStore;
611
FileInfo info;
612
byte fileBuffer = 0;
613
byte fileBuffer2 = 0;
614
int scriptID = 1;
615
char strBuffer[0x100];
616
617
StopAllSfx();
618
if (!CheckCurrentStageFolder(stageListPosition)) {
619
PrintLog("Loading Scene %s - %s", stageListNames[activeStageList], stageList[activeStageList][stageListPosition].name);
620
ReleaseStageSfx();
621
ClearScriptData();
622
for (int i = SURFACE_COUNT; i > 0; i--) RemoveGraphicsFile((char *)"", i - 1);
623
624
#if RETRO_USE_MOD_LOADER
625
loadGlobalScripts = false;
626
#else
627
bool loadGlobalScripts = false;
628
#endif
629
if (LoadStageFile("StageConfig.bin", stageListPosition, &info)) {
630
byte buf = 0;
631
FileRead(&buf, 1);
632
loadGlobalScripts = buf;
633
CloseFile();
634
}
635
636
if (loadGlobalScripts && LoadFile("Data/Game/GameConfig.bin", &info)) {
637
FileRead(&fileBuffer, 1);
638
FileRead(&strBuffer, fileBuffer);
639
FileRead(&fileBuffer, 1);
640
FileRead(&strBuffer, fileBuffer);
641
642
byte buf[3];
643
for (int c = 0; c < 0x60; ++c) {
644
FileRead(buf, 3);
645
SetPaletteEntry(-1, c, buf[0], buf[1], buf[2]);
646
}
647
648
byte globalObjectCount = 0;
649
FileRead(&globalObjectCount, 1);
650
for (byte i = 0; i < globalObjectCount; ++i) {
651
FileRead(&fileBuffer2, 1);
652
FileRead(strBuffer, fileBuffer2);
653
strBuffer[fileBuffer2] = 0;
654
SetObjectTypeName(strBuffer, scriptID + i);
655
}
656
657
#if RETRO_USE_MOD_LOADER && RETRO_USE_COMPILER
658
for (byte i = 0; i < modObjCount && loadGlobalScripts; ++i) {
659
SetObjectTypeName(modTypeNames[i], globalObjectCount + i + 1);
660
}
661
#endif
662
663
#if RETRO_USE_COMPILER
664
#if !RETRO_USE_ORIGINAL_CODE
665
bool bytecodeExists = false;
666
FileInfo bytecodeInfo;
667
GetFileInfo(&bytecodeInfo);
668
CloseFile();
669
if (LoadFile("Bytecode/GlobalCode.bin", &info)) {
670
bytecodeExists = true;
671
CloseFile();
672
}
673
SetFileInfo(&bytecodeInfo);
674
675
if (bytecodeExists && !forceUseScripts) {
676
#else
677
if (Engine.usingBytecode) {
678
#endif
679
GetFileInfo(&infoStore);
680
CloseFile();
681
LoadBytecode(4, scriptID);
682
scriptID += globalObjectCount;
683
SetFileInfo(&infoStore);
684
}
685
else {
686
for (byte i = 0; i < globalObjectCount; ++i) {
687
FileRead(&fileBuffer2, 1);
688
FileRead(strBuffer, fileBuffer2);
689
strBuffer[fileBuffer2] = 0;
690
GetFileInfo(&infoStore);
691
CloseFile();
692
ParseScriptFile(strBuffer, scriptID++);
693
SetFileInfo(&infoStore);
694
if (Engine.gameMode == ENGINE_SCRIPTERROR)
695
return;
696
}
697
}
698
#else
699
GetFileInfo(&infoStore);
700
CloseFile();
701
LoadBytecode(4, scriptID);
702
scriptID += globalObjectCount;
703
SetFileInfo(&infoStore);
704
#endif
705
CloseFile();
706
707
#if RETRO_USE_MOD_LOADER
708
Engine.LoadXMLPalettes();
709
#endif
710
711
#if RETRO_USE_MOD_LOADER && RETRO_USE_COMPILER
712
globalObjCount = globalObjectCount;
713
for (byte i = 0; i < modObjCount && loadGlobalScripts; ++i) {
714
SetObjectTypeName(modTypeNames[i], scriptID);
715
716
GetFileInfo(&infoStore);
717
CloseFile();
718
ParseScriptFile(modScriptPaths[i], scriptID++);
719
SetFileInfo(&infoStore);
720
if (Engine.gameMode == ENGINE_SCRIPTERROR)
721
return;
722
}
723
#endif
724
}
725
726
if (LoadStageFile("StageConfig.bin", stageListPosition, &info)) {
727
FileRead(&fileBuffer, 1); // Load Globals
728
729
byte clr[3];
730
for (int i = 0x60; i < 0x80; ++i) {
731
FileRead(&clr, 3);
732
SetPaletteEntry(-1, i, clr[0], clr[1], clr[2]);
733
}
734
735
FileRead(&fileBuffer, 1);
736
stageSFXCount = fileBuffer;
737
for (byte i = 0; i < stageSFXCount; ++i) {
738
FileRead(&fileBuffer2, 1);
739
FileRead(strBuffer, fileBuffer2);
740
strBuffer[fileBuffer2] = 0;
741
742
SetSfxName(strBuffer, i + globalSFXCount);
743
}
744
for (byte i = 0; i < stageSFXCount; ++i) {
745
FileRead(&fileBuffer2, 1);
746
FileRead(strBuffer, fileBuffer2);
747
strBuffer[fileBuffer2] = 0;
748
GetFileInfo(&infoStore);
749
CloseFile();
750
LoadSfx(strBuffer, globalSFXCount + i);
751
SetFileInfo(&infoStore);
752
}
753
754
byte stageObjectCount = 0;
755
FileRead(&stageObjectCount, 1);
756
for (byte i = 0; i < stageObjectCount; ++i) {
757
FileRead(&fileBuffer2, 1);
758
FileRead(strBuffer, fileBuffer2);
759
strBuffer[fileBuffer2] = 0;
760
SetObjectTypeName(strBuffer, scriptID + i);
761
}
762
763
#if RETRO_USE_COMPILER
764
#if !RETRO_USE_ORIGINAL_CODE
765
char scriptPath[0x40];
766
switch (activeStageList) {
767
case STAGELIST_PRESENTATION:
768
case STAGELIST_REGULAR:
769
case STAGELIST_BONUS:
770
case STAGELIST_SPECIAL:
771
StrCopy(scriptPath, "Bytecode/");
772
StrAdd(scriptPath, stageList[activeStageList][stageListPosition].folder);
773
StrAdd(scriptPath, ".bin");
774
break;
775
default: break;
776
}
777
bool bytecodeExists = false;
778
FileInfo bytecodeInfo;
779
GetFileInfo(&bytecodeInfo);
780
CloseFile();
781
if (LoadFile(scriptPath, &info)) {
782
bytecodeExists = true;
783
CloseFile();
784
}
785
SetFileInfo(&bytecodeInfo);
786
787
if (bytecodeExists && !forceUseScripts) {
788
#else
789
if (Engine.usingBytecode) {
790
#endif
791
for (byte i = 0; i < stageObjectCount; ++i) {
792
FileRead(&fileBuffer2, 1);
793
FileRead(strBuffer, fileBuffer2);
794
strBuffer[fileBuffer2] = 0;
795
}
796
GetFileInfo(&infoStore);
797
CloseFile();
798
LoadBytecode(activeStageList, scriptID);
799
SetFileInfo(&infoStore);
800
}
801
else {
802
for (byte i = 0; i < stageObjectCount; ++i) {
803
FileRead(&fileBuffer2, 1);
804
FileRead(strBuffer, fileBuffer2);
805
strBuffer[fileBuffer2] = 0;
806
GetFileInfo(&infoStore);
807
CloseFile();
808
ParseScriptFile(strBuffer, scriptID + i);
809
SetFileInfo(&infoStore);
810
if (Engine.gameMode == ENGINE_SCRIPTERROR)
811
return;
812
}
813
}
814
#else
815
for (byte i = 0; i < stageObjectCount; ++i) {
816
FileRead(&fileBuffer2, 1);
817
FileRead(strBuffer, fileBuffer2);
818
strBuffer[fileBuffer2] = 0;
819
}
820
GetFileInfo(&infoStore);
821
CloseFile();
822
LoadBytecode(activeStageList, scriptID);
823
SetFileInfo(&infoStore);
824
#endif
825
CloseFile();
826
}
827
828
LoadStageGIFFile(stageListPosition);
829
LoadStageCollisions();
830
LoadStageBackground();
831
}
832
else {
833
PrintLog("Reloading Scene %s - %s", stageListNames[activeStageList], stageList[activeStageList][stageListPosition].name);
834
}
835
LoadStageChunks();
836
for (int i = 0; i < TRACK_COUNT; ++i) SetMusicTrack("", i, false, 0);
837
838
memset(objectEntityList, 0, ENTITY_COUNT * sizeof(Entity));
839
for (int i = 0; i < ENTITY_COUNT; ++i) {
840
objectEntityList[i].drawOrder = 3;
841
objectEntityList[i].scale = 512;
842
objectEntityList[i].objectInteractions = true;
843
objectEntityList[i].visible = true;
844
objectEntityList[i].tileCollisions = true;
845
}
846
LoadActLayout();
847
Init3DFloorBuffer(0);
848
ProcessStartupObjects();
849
}
850
int LoadActFile(const char *ext, int stageID, FileInfo *info)
851
{
852
char dest[0x40];
853
854
StrCopy(dest, "Data/Stages/");
855
StrAdd(dest, stageList[activeStageList][stageID].folder);
856
StrAdd(dest, "/Act");
857
StrAdd(dest, stageList[activeStageList][stageID].id);
858
StrAdd(dest, ext);
859
860
ConvertStringToInteger(stageList[activeStageList][stageID].id, &actID);
861
862
return LoadFile(dest, info);
863
}
864
int LoadStageFile(const char *filePath, int stageID, FileInfo *info)
865
{
866
char dest[0x40];
867
868
StrCopy(dest, "Data/Stages/");
869
StrAdd(dest, stageList[activeStageList][stageID].folder);
870
StrAdd(dest, "/");
871
StrAdd(dest, filePath);
872
return LoadFile(dest, info);
873
}
874
void LoadActLayout()
875
{
876
FileInfo info;
877
for (int a = 0; a < 4; ++a) activeTileLayers[a] = 9; // disables missing scenes from rendering
878
879
if (LoadActFile(".bin", stageListPosition, &info)) {
880
byte fileBuffer[4];
881
882
byte length = 0;
883
FileRead(&length, 1);
884
titleCardWord2 = (byte)length;
885
for (int i = 0; i < length; ++i) {
886
FileRead(&titleCardText[i], 1);
887
if (titleCardText[i] == '-')
888
titleCardWord2 = (byte)(i + 1);
889
}
890
titleCardText[length] = '\0';
891
892
// READ TILELAYER
893
FileRead(activeTileLayers, 4);
894
FileRead(&tLayerMidPoint, 1);
895
896
FileRead(&stageLayouts[0].xsize, 1);
897
FileRead(fileBuffer, 1); // Unused
898
899
FileRead(&stageLayouts[0].ysize, 1);
900
FileRead(fileBuffer, 1); // Unused
901
curXBoundary1 = 0;
902
newXBoundary1 = 0;
903
curYBoundary1 = 0;
904
newYBoundary1 = 0;
905
curXBoundary2 = stageLayouts[0].xsize << 7;
906
curYBoundary2 = stageLayouts[0].ysize << 7;
907
waterLevel = curYBoundary2 + 128;
908
newXBoundary2 = stageLayouts[0].xsize << 7;
909
newYBoundary2 = stageLayouts[0].ysize << 7;
910
911
memset(stageLayouts[0].tiles, 0, TILELAYER_CHUNK_COUNT * sizeof(ushort));
912
memset(stageLayouts[0].lineScroll, 0, 0x7FFF);
913
914
for (int y = 0; y < stageLayouts[0].ysize; ++y) {
915
ushort *tiles = &stageLayouts[0].tiles[(y * TILELAYER_CHUNK_H)];
916
for (int x = 0; x < stageLayouts[0].xsize; ++x) {
917
FileRead(&fileBuffer[0], 1);
918
tiles[x] = fileBuffer[0];
919
FileRead(&fileBuffer[0], 1);
920
tiles[x] |= fileBuffer[0] << 8;
921
}
922
}
923
924
// READ OBJECTS
925
FileRead(&fileBuffer[0], 2);
926
int objectCount = fileBuffer[0] + (fileBuffer[1] << 8);
927
#if !RETRO_USE_ORIGINAL_CODE
928
if (objectCount > 0x400)
929
PrintLog("WARNING: object count %d exceeds the object limit", objectCount);
930
#endif
931
932
#if RETRO_USE_MOD_LOADER
933
int offsetCount = 0;
934
for (int m = 0; m < modObjCount; ++m)
935
if (modScriptFlags[m])
936
++offsetCount;
937
#endif
938
Entity *object = &objectEntityList[32];
939
for (int i = 0; i < objectCount; ++i) {
940
FileRead(fileBuffer, 2);
941
ushort attribs = (fileBuffer[1] << 8) + fileBuffer[0];
942
943
FileRead(fileBuffer, 1);
944
object->type = fileBuffer[0];
945
946
#if RETRO_USE_MOD_LOADER
947
if (loadGlobalScripts && offsetCount && object->type > globalObjCount)
948
object->type += offsetCount; // offset it by our mod count
949
#endif
950
951
FileRead(fileBuffer, 1);
952
object->propertyValue = fileBuffer[0];
953
954
FileRead(&fileBuffer, 4);
955
object->xpos = (fileBuffer[3] << 24) + (fileBuffer[2] << 16) + (fileBuffer[1] << 8) + fileBuffer[0];
956
957
FileRead(&fileBuffer, 4);
958
object->ypos = (fileBuffer[3] << 24) + (fileBuffer[2] << 16) + (fileBuffer[1] << 8) + fileBuffer[0];
959
960
if (attribs & 0x1) {
961
FileRead(&fileBuffer, 4);
962
object->state = (fileBuffer[3] << 24) + (fileBuffer[2] << 16) + (fileBuffer[1] << 8) + fileBuffer[0];
963
}
964
if (attribs & 0x2) {
965
FileRead(fileBuffer, 1);
966
object->direction = fileBuffer[0];
967
}
968
if (attribs & 0x4) {
969
FileRead(&fileBuffer, 4);
970
object->scale = (fileBuffer[3] << 24) + (fileBuffer[2] << 16) + (fileBuffer[1] << 8) + fileBuffer[0];
971
}
972
if (attribs & 0x8) {
973
FileRead(&fileBuffer, 4);
974
object->rotation = (fileBuffer[3] << 24) + (fileBuffer[2] << 16) + (fileBuffer[1] << 8) + fileBuffer[0];
975
}
976
if (attribs & 0x10) {
977
FileRead(fileBuffer, 1);
978
object->drawOrder = fileBuffer[0];
979
}
980
if (attribs & 0x20) {
981
FileRead(fileBuffer, 1);
982
object->priority = fileBuffer[0];
983
}
984
if (attribs & 0x40) {
985
FileRead(fileBuffer, 1);
986
object->alpha = fileBuffer[0];
987
}
988
if (attribs & 0x80) {
989
FileRead(fileBuffer, 1);
990
object->animation = fileBuffer[0];
991
}
992
if (attribs & 0x100) {
993
FileRead(&fileBuffer, 4);
994
object->animationSpeed = (fileBuffer[3] << 24) + (fileBuffer[2] << 16) + (fileBuffer[1] << 8) + fileBuffer[0];
995
}
996
if (attribs & 0x200) {
997
FileRead(fileBuffer, 1);
998
object->frame = fileBuffer[0];
999
}
1000
if (attribs & 0x400) {
1001
FileRead(fileBuffer, 1);
1002
object->inkEffect = fileBuffer[0];
1003
}
1004
if (attribs & 0x800) {
1005
FileRead(&fileBuffer, 4);
1006
object->values[0] = (fileBuffer[3] << 24) + (fileBuffer[2] << 16) + (fileBuffer[1] << 8) + fileBuffer[0];
1007
}
1008
if (attribs & 0x1000) {
1009
FileRead(&fileBuffer, 4);
1010
object->values[1] = (fileBuffer[3] << 24) + (fileBuffer[2] << 16) + (fileBuffer[1] << 8) + fileBuffer[0];
1011
}
1012
if (attribs & 0x2000) {
1013
FileRead(&fileBuffer, 4);
1014
object->values[2] = (fileBuffer[3] << 24) + (fileBuffer[2] << 16) + (fileBuffer[1] << 8) + fileBuffer[0];
1015
}
1016
if (attribs & 0x4000) {
1017
FileRead(&fileBuffer, 4);
1018
object->values[3] = (fileBuffer[3] << 24) + (fileBuffer[2] << 16) + (fileBuffer[1] << 8) + fileBuffer[0];
1019
}
1020
1021
++object;
1022
}
1023
}
1024
stageLayouts[0].type = LAYER_HSCROLL;
1025
CloseFile();
1026
}
1027
void LoadStageBackground()
1028
{
1029
for (int i = 0; i < LAYER_COUNT; ++i) {
1030
stageLayouts[i].type = LAYER_NOSCROLL;
1031
stageLayouts[i].deformationOffset = 0;
1032
stageLayouts[i].deformationOffsetW = 0;
1033
}
1034
for (int i = 0; i < PARALLAX_COUNT; ++i) {
1035
hParallax.scrollPos[i] = 0;
1036
vParallax.scrollPos[i] = 0;
1037
}
1038
1039
FileInfo info;
1040
if (LoadStageFile("Backgrounds.bin", stageListPosition, &info)) {
1041
byte fileBuffer = 0;
1042
byte layerCount = 0;
1043
FileRead(&layerCount, 1);
1044
FileRead(&hParallax.entryCount, 1);
1045
for (byte i = 0; i < hParallax.entryCount; ++i) {
1046
FileRead(&fileBuffer, 1);
1047
hParallax.parallaxFactor[i] = fileBuffer;
1048
FileRead(&fileBuffer, 1);
1049
hParallax.parallaxFactor[i] |= fileBuffer << 8;
1050
1051
FileRead(&fileBuffer, 1);
1052
hParallax.scrollSpeed[i] = fileBuffer << 10;
1053
1054
hParallax.scrollPos[i] = 0;
1055
1056
FileRead(&hParallax.deform[i], 1);
1057
}
1058
1059
FileRead(&vParallax.entryCount, 1);
1060
for (byte i = 0; i < vParallax.entryCount; ++i) {
1061
FileRead(&fileBuffer, 1);
1062
vParallax.parallaxFactor[i] = fileBuffer;
1063
FileRead(&fileBuffer, 1);
1064
vParallax.parallaxFactor[i] |= fileBuffer << 8;
1065
1066
FileRead(&fileBuffer, 1);
1067
vParallax.scrollSpeed[i] = fileBuffer << 10;
1068
1069
vParallax.scrollPos[i] = 0;
1070
1071
FileRead(&vParallax.deform[i], 1);
1072
}
1073
1074
for (byte i = 1; i < layerCount + 1; ++i) {
1075
FileRead(&fileBuffer, 1);
1076
stageLayouts[i].xsize = fileBuffer;
1077
FileRead(&fileBuffer, 1); // Unused (???)
1078
FileRead(&fileBuffer, 1);
1079
stageLayouts[i].ysize = fileBuffer;
1080
FileRead(&fileBuffer, 1); // Unused (???)
1081
FileRead(&fileBuffer, 1);
1082
stageLayouts[i].type = fileBuffer;
1083
FileRead(&fileBuffer, 1);
1084
stageLayouts[i].parallaxFactor = fileBuffer;
1085
FileRead(&fileBuffer, 1);
1086
stageLayouts[i].parallaxFactor |= fileBuffer << 8;
1087
FileRead(&fileBuffer, 1);
1088
stageLayouts[i].scrollSpeed = fileBuffer << 10;
1089
stageLayouts[i].scrollPos = 0;
1090
1091
memset(stageLayouts[i].tiles, 0, TILELAYER_CHUNK_COUNT * sizeof(ushort));
1092
byte *lineScrollPtr = stageLayouts[i].lineScroll;
1093
memset(stageLayouts[i].lineScroll, 0, 0x7FFF);
1094
1095
// Read Line Scroll
1096
byte buf[3];
1097
int pos = 0;
1098
while (true) {
1099
FileRead(&buf[0], 1);
1100
if (buf[0] == 0xFF) {
1101
FileRead(&buf[1], 1);
1102
if (buf[1] == 0xFF) {
1103
break;
1104
}
1105
else {
1106
FileRead(&buf[2], 1);
1107
int index = buf[1];
1108
int cnt = buf[2] - 1;
1109
for (int c = 0; c < cnt; ++c) *lineScrollPtr++ = index;
1110
}
1111
}
1112
else {
1113
*lineScrollPtr++ = buf[0];
1114
}
1115
}
1116
1117
// Read Layout
1118
for (int y = 0; y < stageLayouts[i].ysize; ++y) {
1119
ushort *chunks = &stageLayouts[i].tiles[y * TILELAYER_CHUNK_H];
1120
for (int x = 0; x < stageLayouts[i].xsize; ++x) {
1121
FileRead(&fileBuffer, 1);
1122
*chunks = fileBuffer;
1123
FileRead(&fileBuffer, 1);
1124
*chunks |= fileBuffer << 8;
1125
++chunks;
1126
}
1127
}
1128
}
1129
1130
CloseFile();
1131
}
1132
}
1133
void LoadStageChunks()
1134
{
1135
FileInfo info;
1136
byte entry[3];
1137
1138
if (LoadStageFile("128x128Tiles.bin", stageListPosition, &info)) {
1139
for (int i = 0; i < CHUNKTILE_COUNT; ++i) {
1140
FileRead(&entry, 3);
1141
entry[0] -= (byte)((entry[0] >> 6) << 6);
1142
1143
tiles128x128.visualPlane[i] = (byte)(entry[0] >> 4);
1144
entry[0] -= 16 * (entry[0] >> 4);
1145
1146
tiles128x128.direction[i] = (byte)(entry[0] >> 2);
1147
entry[0] -= 4 * (entry[0] >> 2);
1148
1149
tiles128x128.tileIndex[i] = entry[1] + (entry[0] << 8);
1150
#if RETRO_SOFTWARE_RENDER
1151
tiles128x128.gfxDataPos[i] = tiles128x128.tileIndex[i] << 8;
1152
#endif
1153
#if RETRO_HARDWARE_RENDER
1154
tiles128x128.gfxDataPos[i] = tiles128x128.tileIndex[i] << 2;
1155
#endif
1156
1157
tiles128x128.collisionFlags[0][i] = entry[2] >> 4;
1158
tiles128x128.collisionFlags[1][i] = entry[2] - ((entry[2] >> 4) << 4);
1159
}
1160
CloseFile();
1161
}
1162
}
1163
void LoadStageCollisions()
1164
{
1165
FileInfo info;
1166
if (LoadStageFile("CollisionMasks.bin", stageListPosition, &info)) {
1167
1168
byte fileBuffer = 0;
1169
int tileIndex = 0;
1170
for (int t = 0; t < TILE_COUNT; ++t) {
1171
for (int p = 0; p < CPATH_COUNT; ++p) {
1172
FileRead(&fileBuffer, 1);
1173
bool isCeiling = fileBuffer >> 4;
1174
collisionMasks[p].flags[t] = fileBuffer & 0xF;
1175
FileRead(&fileBuffer, 1);
1176
collisionMasks[p].angles[t] = fileBuffer;
1177
FileRead(&fileBuffer, 1);
1178
collisionMasks[p].angles[t] |= fileBuffer << 8;
1179
FileRead(&fileBuffer, 1);
1180
collisionMasks[p].angles[t] |= fileBuffer << 16;
1181
FileRead(&fileBuffer, 1);
1182
collisionMasks[p].angles[t] |= fileBuffer << 24;
1183
1184
if (isCeiling) // Ceiling Tile
1185
{
1186
for (int c = 0; c < TILE_SIZE; c += 2) {
1187
FileRead(&fileBuffer, 1);
1188
collisionMasks[p].roofMasks[c + tileIndex] = fileBuffer >> 4;
1189
collisionMasks[p].roofMasks[c + tileIndex + 1] = fileBuffer & 0xF;
1190
}
1191
1192
// Has Collision (Pt 1)
1193
FileRead(&fileBuffer, 1);
1194
int id = 1;
1195
for (int c = 0; c < TILE_SIZE / 2; ++c) {
1196
if (fileBuffer & id) {
1197
collisionMasks[p].floorMasks[c + tileIndex + 8] = 0;
1198
}
1199
else {
1200
collisionMasks[p].floorMasks[c + tileIndex + 8] = 0x40;
1201
collisionMasks[p].roofMasks[c + tileIndex + 8] = -0x40;
1202
}
1203
id <<= 1;
1204
}
1205
1206
// Has Collision (Pt 2)
1207
FileRead(&fileBuffer, 1);
1208
id = 1;
1209
for (int c = 0; c < TILE_SIZE / 2; ++c) {
1210
if (fileBuffer & id) {
1211
collisionMasks[p].floorMasks[c + tileIndex] = 0;
1212
}
1213
else {
1214
collisionMasks[p].floorMasks[c + tileIndex] = 0x40;
1215
collisionMasks[p].roofMasks[c + tileIndex] = -0x40;
1216
}
1217
id <<= 1;
1218
}
1219
1220
// LWall rotations
1221
for (int c = 0; c < TILE_SIZE; ++c) {
1222
int h = 0;
1223
while (h > -1) {
1224
if (h == TILE_SIZE) {
1225
collisionMasks[p].lWallMasks[c + tileIndex] = 0x40;
1226
h = -1;
1227
}
1228
else if (c > collisionMasks[p].roofMasks[h + tileIndex]) {
1229
++h;
1230
}
1231
else {
1232
collisionMasks[p].lWallMasks[c + tileIndex] = h;
1233
h = -1;
1234
}
1235
}
1236
}
1237
1238
// RWall rotations
1239
for (int c = 0; c < TILE_SIZE; ++c) {
1240
int h = TILE_SIZE - 1;
1241
while (h < TILE_SIZE) {
1242
if (h == -1) {
1243
collisionMasks[p].rWallMasks[c + tileIndex] = -0x40;
1244
h = TILE_SIZE;
1245
}
1246
else if (c > collisionMasks[p].roofMasks[h + tileIndex]) {
1247
--h;
1248
}
1249
else {
1250
collisionMasks[p].rWallMasks[c + tileIndex] = h;
1251
h = TILE_SIZE;
1252
}
1253
}
1254
}
1255
}
1256
else // Regular Tile
1257
{
1258
for (int c = 0; c < TILE_SIZE; c += 2) {
1259
FileRead(&fileBuffer, 1);
1260
collisionMasks[p].floorMasks[c + tileIndex] = fileBuffer >> 4;
1261
collisionMasks[p].floorMasks[c + tileIndex + 1] = fileBuffer & 0xF;
1262
}
1263
FileRead(&fileBuffer, 1);
1264
int id = 1;
1265
for (int c = 0; c < TILE_SIZE / 2; ++c) // HasCollision
1266
{
1267
if (fileBuffer & id) {
1268
collisionMasks[p].roofMasks[c + tileIndex + 8] = 0xF;
1269
}
1270
else {
1271
collisionMasks[p].floorMasks[c + tileIndex + 8] = 0x40;
1272
collisionMasks[p].roofMasks[c + tileIndex + 8] = -0x40;
1273
}
1274
id <<= 1;
1275
}
1276
1277
FileRead(&fileBuffer, 1);
1278
id = 1;
1279
for (int c = 0; c < TILE_SIZE / 2; ++c) // HasCollision (pt 2)
1280
{
1281
if (fileBuffer & id) {
1282
collisionMasks[p].roofMasks[c + tileIndex] = 0xF;
1283
}
1284
else {
1285
collisionMasks[p].floorMasks[c + tileIndex] = 0x40;
1286
collisionMasks[p].roofMasks[c + tileIndex] = -0x40;
1287
}
1288
id <<= 1;
1289
}
1290
1291
// LWall rotations
1292
for (int c = 0; c < TILE_SIZE; ++c) {
1293
int h = 0;
1294
while (h > -1) {
1295
if (h == TILE_SIZE) {
1296
collisionMasks[p].lWallMasks[c + tileIndex] = 0x40;
1297
h = -1;
1298
}
1299
else if (c < collisionMasks[p].floorMasks[h + tileIndex]) {
1300
++h;
1301
}
1302
else {
1303
collisionMasks[p].lWallMasks[c + tileIndex] = h;
1304
h = -1;
1305
}
1306
}
1307
}
1308
1309
// RWall rotations
1310
for (int c = 0; c < TILE_SIZE; ++c) {
1311
int h = TILE_SIZE - 1;
1312
while (h < TILE_SIZE) {
1313
if (h == -1) {
1314
collisionMasks[p].rWallMasks[c + tileIndex] = -0x40;
1315
h = TILE_SIZE;
1316
}
1317
else if (c < collisionMasks[p].floorMasks[h + tileIndex]) {
1318
--h;
1319
}
1320
else {
1321
collisionMasks[p].rWallMasks[c + tileIndex] = h;
1322
h = TILE_SIZE;
1323
}
1324
}
1325
}
1326
}
1327
}
1328
tileIndex += 16;
1329
}
1330
CloseFile();
1331
}
1332
}
1333
void LoadStageGIFFile(int stageID)
1334
{
1335
FileInfo info;
1336
if (LoadStageFile("16x16Tiles.gif", stageID, &info)) {
1337
byte fileBuffer = 0;
1338
1339
SetFilePosition(6); // GIF89a
1340
FileRead(&fileBuffer, 1);
1341
int width = fileBuffer;
1342
FileRead(&fileBuffer, 1);
1343
width |= (fileBuffer << 8);
1344
FileRead(&fileBuffer, 1);
1345
int height = fileBuffer;
1346
FileRead(&fileBuffer, 1);
1347
height |= (fileBuffer << 8);
1348
1349
FileRead(&fileBuffer, 1); // Palette Size (thrown away) :/
1350
FileRead(&fileBuffer, 1); // BG Color index (thrown away)
1351
FileRead(&fileBuffer, 1); // idk actually (still thrown away)
1352
1353
byte clr[3];
1354
for (int c = 0; c < 0x80; ++c) FileRead(clr, 3);
1355
for (int c = 0x80; c < 0x100; ++c) {
1356
FileRead(clr, 3);
1357
SetPaletteEntry(-1, c, clr[0], clr[1], clr[2]);
1358
}
1359
1360
FileRead(&fileBuffer, 1);
1361
while (fileBuffer != ',') FileRead(&fileBuffer, 1); // gif image start identifier
1362
1363
ushort fileBuffer2 = 0;
1364
FileRead(&fileBuffer2, 2);
1365
FileRead(&fileBuffer2, 2);
1366
FileRead(&fileBuffer2, 2);
1367
FileRead(&fileBuffer2, 2);
1368
FileRead(&fileBuffer, 1);
1369
bool interlaced = (fileBuffer & 0x40) >> 6;
1370
if ((unsigned int)fileBuffer >> 7 == 1) {
1371
int c = 128;
1372
do {
1373
++c;
1374
FileRead(&fileBuffer, 3);
1375
} while (c != 256);
1376
}
1377
1378
ReadGifPictureData(width, height, interlaced, tilesetGFXData, 0);
1379
1380
byte transparent = tilesetGFXData[0];
1381
for (int i = 0; i < TILESET_SIZE; ++i) {
1382
if (tilesetGFXData[i] == transparent)
1383
tilesetGFXData[i] = 0;
1384
}
1385
1386
CloseFile();
1387
}
1388
}
1389
1390
void ResetBackgroundSettings()
1391
{
1392
for (int i = 0; i < LAYER_COUNT; ++i) {
1393
stageLayouts[i].deformationOffset = 0;
1394
stageLayouts[i].deformationOffsetW = 0;
1395
stageLayouts[i].scrollPos = 0;
1396
}
1397
1398
for (int i = 0; i < PARALLAX_COUNT; ++i) {
1399
hParallax.scrollPos[i] = 0;
1400
vParallax.scrollPos[i] = 0;
1401
}
1402
1403
for (int i = 0; i < DEFORM_COUNT; ++i) {
1404
bgDeformationData0[i] = 0;
1405
bgDeformationData1[i] = 0;
1406
bgDeformationData2[i] = 0;
1407
bgDeformationData3[i] = 0;
1408
}
1409
}
1410
1411
void SetLayerDeformation(int selectedDef, int waveLength, int waveWidth, int waveType, int YPos, int waveSize)
1412
{
1413
int *deformPtr = nullptr;
1414
switch (selectedDef) {
1415
case DEFORM_FG: deformPtr = bgDeformationData0; break;
1416
case DEFORM_FG_WATER: deformPtr = bgDeformationData1; break;
1417
case DEFORM_BG: deformPtr = bgDeformationData2; break;
1418
case DEFORM_BG_WATER: deformPtr = bgDeformationData3; break;
1419
default: break;
1420
}
1421
1422
#if RETRO_SOFTWARE_RENDER
1423
int shift = 9;
1424
#endif
1425
1426
#if RETRO_HARDWARE_RENDER
1427
int shift = 5;
1428
#endif
1429
1430
int id = 0;
1431
if (waveType == 1) {
1432
id = YPos;
1433
for (int i = 0; i < waveSize; ++i) {
1434
deformPtr[id] = waveWidth * sin512LookupTable[(i << 9) / waveLength & 0x1FF] >> shift;
1435
++id;
1436
}
1437
}
1438
else {
1439
for (int i = 0; i < 0x200 * 0x100; i += 0x200) {
1440
int val = waveWidth * sin512LookupTable[i / waveLength & 0x1FF] >> shift;
1441
deformPtr[id] = val;
1442
#if RETRO_SOFTWARE_RENDER
1443
if (deformPtr[id] >= waveWidth)
1444
deformPtr[id] = waveWidth - 1;
1445
#endif
1446
++id;
1447
}
1448
}
1449
1450
switch (selectedDef) {
1451
case DEFORM_FG:
1452
for (int i = DEFORM_STORE; i < DEFORM_COUNT; ++i) bgDeformationData0[i] = bgDeformationData0[i - DEFORM_STORE];
1453
break;
1454
case DEFORM_FG_WATER:
1455
for (int i = DEFORM_STORE; i < DEFORM_COUNT; ++i) bgDeformationData1[i] = bgDeformationData1[i - DEFORM_STORE];
1456
break;
1457
case DEFORM_BG:
1458
for (int i = DEFORM_STORE; i < DEFORM_COUNT; ++i) bgDeformationData2[i] = bgDeformationData2[i - DEFORM_STORE];
1459
break;
1460
case DEFORM_BG_WATER:
1461
for (int i = DEFORM_STORE; i < DEFORM_COUNT; ++i) bgDeformationData3[i] = bgDeformationData3[i - DEFORM_STORE];
1462
break;
1463
default: break;
1464
}
1465
}
1466
1467
void SetPlayerScreenPosition(Entity *target)
1468
{
1469
int targetX = target->xpos >> 16;
1470
int targetY = cameraAdjustY + (target->ypos >> 16);
1471
if (newYBoundary1 > curYBoundary1) {
1472
if (newYBoundary1 >= yScrollOffset)
1473
curYBoundary1 = yScrollOffset;
1474
else
1475
curYBoundary1 = newYBoundary1;
1476
}
1477
if (newYBoundary1 < curYBoundary1) {
1478
if (curYBoundary1 >= yScrollOffset)
1479
--curYBoundary1;
1480
else
1481
curYBoundary1 = newYBoundary1;
1482
}
1483
if (newYBoundary2 < curYBoundary2) {
1484
if (curYBoundary2 <= yScrollOffset + SCREEN_YSIZE || newYBoundary2 >= yScrollOffset + SCREEN_YSIZE)
1485
--curYBoundary2;
1486
else
1487
curYBoundary2 = yScrollOffset + SCREEN_YSIZE;
1488
}
1489
if (newYBoundary2 > curYBoundary2) {
1490
if (yScrollOffset + SCREEN_YSIZE >= curYBoundary2) {
1491
++curYBoundary2;
1492
if (target->yvel > 0) {
1493
int buf = curYBoundary2 + (target->yvel >> 16);
1494
if (newYBoundary2 < buf) {
1495
curYBoundary2 = newYBoundary2;
1496
}
1497
else {
1498
curYBoundary2 += target->yvel >> 16;
1499
}
1500
}
1501
}
1502
else
1503
curYBoundary2 = newYBoundary2;
1504
}
1505
if (newXBoundary1 > curXBoundary1) {
1506
if (xScrollOffset <= newXBoundary1)
1507
curXBoundary1 = xScrollOffset;
1508
else
1509
curXBoundary1 = newXBoundary1;
1510
}
1511
if (newXBoundary1 < curXBoundary1) {
1512
if (xScrollOffset <= curXBoundary1) {
1513
--curXBoundary1;
1514
if (target->xvel < 0) {
1515
curXBoundary1 += target->xvel >> 16;
1516
if (curXBoundary1 < newXBoundary1)
1517
curXBoundary1 = newXBoundary1;
1518
}
1519
}
1520
else {
1521
curXBoundary1 = newXBoundary1;
1522
}
1523
}
1524
if (newXBoundary2 < curXBoundary2) {
1525
if (newXBoundary2 > SCREEN_XSIZE + xScrollOffset)
1526
curXBoundary2 = newXBoundary2;
1527
else
1528
curXBoundary2 = SCREEN_XSIZE + xScrollOffset;
1529
}
1530
if (newXBoundary2 > curXBoundary2) {
1531
if (SCREEN_XSIZE + xScrollOffset >= curXBoundary2) {
1532
++curXBoundary2;
1533
if (target->xvel > 0) {
1534
curXBoundary2 += target->xvel >> 16;
1535
if (curXBoundary2 > newXBoundary2)
1536
curXBoundary2 = newXBoundary2;
1537
}
1538
}
1539
else {
1540
curXBoundary2 = newXBoundary2;
1541
}
1542
}
1543
1544
int xPosDif = targetX - cameraXPos;
1545
if (targetX > cameraXPos) {
1546
xPosDif -= 8;
1547
if (xPosDif >= 0) {
1548
if (xPosDif >= 17)
1549
xPosDif = 16;
1550
}
1551
else {
1552
xPosDif = 0;
1553
}
1554
}
1555
else {
1556
xPosDif += 8;
1557
if (xPosDif > 0) {
1558
xPosDif = 0;
1559
}
1560
else if (xPosDif <= -17) {
1561
xPosDif = -16;
1562
}
1563
}
1564
1565
int centeredXBound1 = cameraXPos + xPosDif;
1566
cameraXPos = centeredXBound1;
1567
if (centeredXBound1 < SCREEN_CENTERX + curXBoundary1) {
1568
cameraXPos = SCREEN_CENTERX + curXBoundary1;
1569
centeredXBound1 = SCREEN_CENTERX + curXBoundary1;
1570
}
1571
1572
int centeredXBound2 = curXBoundary2 - SCREEN_CENTERX;
1573
if (centeredXBound2 < centeredXBound1) {
1574
cameraXPos = centeredXBound2;
1575
centeredXBound1 = centeredXBound2;
1576
}
1577
1578
int yPosDif = 0;
1579
if (target->scrollTracking) {
1580
if (targetY <= cameraYPos) {
1581
yPosDif = (targetY - cameraYPos) + 32;
1582
if (yPosDif <= 0) {
1583
if (yPosDif <= -17)
1584
yPosDif = -16;
1585
}
1586
else
1587
yPosDif = 0;
1588
}
1589
else {
1590
yPosDif = (targetY - cameraYPos) - 32;
1591
if (yPosDif >= 0) {
1592
if (yPosDif >= 17)
1593
yPosDif = 16;
1594
}
1595
else
1596
yPosDif = 0;
1597
}
1598
cameraLockedY = false;
1599
}
1600
else if (cameraLockedY) {
1601
yPosDif = 0;
1602
cameraYPos = targetY;
1603
}
1604
else if (targetY <= cameraYPos) {
1605
yPosDif = targetY - cameraYPos;
1606
if (targetY - cameraYPos <= 0) {
1607
if (yPosDif >= -32 && abs(target->yvel) <= 0x60000) {
1608
if (yPosDif < -6) {
1609
yPosDif = -6;
1610
}
1611
}
1612
else if (yPosDif < -16) {
1613
yPosDif = -16;
1614
}
1615
}
1616
else {
1617
yPosDif = 0;
1618
cameraLockedY = true;
1619
}
1620
}
1621
else {
1622
yPosDif = targetY - cameraYPos;
1623
if (targetY - cameraYPos < 0) {
1624
yPosDif = 0;
1625
cameraLockedY = true;
1626
}
1627
else if (yPosDif > 32 || abs(target->yvel) > 0x60000) {
1628
if (yPosDif > 16) {
1629
yPosDif = 16;
1630
}
1631
else {
1632
cameraLockedY = true;
1633
}
1634
}
1635
else {
1636
if (yPosDif <= 6) {
1637
cameraLockedY = true;
1638
}
1639
else {
1640
yPosDif = 6;
1641
}
1642
}
1643
}
1644
1645
int newCamY = cameraYPos + yPosDif;
1646
if (newCamY <= curYBoundary1 + (SCREEN_SCROLL_UP - 1))
1647
newCamY = curYBoundary1 + SCREEN_SCROLL_UP;
1648
cameraYPos = newCamY;
1649
if (curYBoundary2 - (SCREEN_SCROLL_DOWN - 1) <= newCamY) {
1650
cameraYPos = curYBoundary2 - SCREEN_SCROLL_DOWN;
1651
}
1652
1653
xScrollOffset = cameraShakeX + centeredXBound1 - SCREEN_CENTERX;
1654
1655
int pos = cameraYPos + target->lookPosY - SCREEN_SCROLL_UP;
1656
if (pos < curYBoundary1) {
1657
yScrollOffset = curYBoundary1;
1658
}
1659
else {
1660
yScrollOffset = cameraYPos + target->lookPosY - SCREEN_SCROLL_UP;
1661
}
1662
1663
int y = curYBoundary2 - SCREEN_YSIZE;
1664
if (curYBoundary2 - (SCREEN_YSIZE - 1) > yScrollOffset)
1665
y = yScrollOffset;
1666
yScrollOffset = cameraShakeY + y;
1667
1668
if (cameraShakeX) {
1669
if (cameraShakeX <= 0) {
1670
cameraShakeX = ~cameraShakeX;
1671
}
1672
else {
1673
cameraShakeX = -cameraShakeX;
1674
}
1675
}
1676
1677
if (cameraShakeY) {
1678
if (cameraShakeY <= 0) {
1679
cameraShakeY = ~cameraShakeY;
1680
}
1681
else {
1682
cameraShakeY = -cameraShakeY;
1683
}
1684
}
1685
}
1686
void SetPlayerScreenPositionCDStyle(Entity *target)
1687
{
1688
int targetX = target->xpos >> 16;
1689
int targetY = cameraAdjustY + (target->ypos >> 16);
1690
if (newYBoundary1 > curYBoundary1) {
1691
if (newYBoundary1 >= yScrollOffset)
1692
curYBoundary1 = yScrollOffset;
1693
else
1694
curYBoundary1 = newYBoundary1;
1695
}
1696
if (newYBoundary1 < curYBoundary1) {
1697
if (curYBoundary1 >= yScrollOffset)
1698
--curYBoundary1;
1699
else
1700
curYBoundary1 = newYBoundary1;
1701
}
1702
if (newYBoundary2 < curYBoundary2) {
1703
if (curYBoundary2 <= yScrollOffset + SCREEN_YSIZE || newYBoundary2 >= yScrollOffset + SCREEN_YSIZE)
1704
--curYBoundary2;
1705
else
1706
curYBoundary2 = yScrollOffset + SCREEN_YSIZE;
1707
}
1708
if (newYBoundary2 > curYBoundary2) {
1709
if (yScrollOffset + SCREEN_YSIZE >= curYBoundary2) {
1710
++curYBoundary2;
1711
if (target->yvel > 0) {
1712
int buf = curYBoundary2 + (target->yvel >> 16);
1713
if (newYBoundary2 < buf) {
1714
curYBoundary2 = newYBoundary2;
1715
}
1716
else {
1717
curYBoundary2 += target->yvel >> 16;
1718
}
1719
}
1720
}
1721
else
1722
curYBoundary2 = newYBoundary2;
1723
}
1724
if (newXBoundary1 > curXBoundary1) {
1725
if (xScrollOffset <= newXBoundary1)
1726
curXBoundary1 = xScrollOffset;
1727
else
1728
curXBoundary1 = newXBoundary1;
1729
}
1730
if (newXBoundary1 < curXBoundary1) {
1731
if (xScrollOffset <= curXBoundary1) {
1732
--curXBoundary1;
1733
if (target->xvel < 0) {
1734
curXBoundary1 += target->xvel >> 16;
1735
if (curXBoundary1 < newXBoundary1)
1736
curXBoundary1 = newXBoundary1;
1737
}
1738
}
1739
else {
1740
curXBoundary1 = newXBoundary1;
1741
}
1742
}
1743
if (newXBoundary2 < curXBoundary2) {
1744
if (newXBoundary2 > SCREEN_XSIZE + xScrollOffset)
1745
curXBoundary2 = newXBoundary2;
1746
else
1747
curXBoundary2 = SCREEN_XSIZE + xScrollOffset;
1748
}
1749
if (newXBoundary2 > curXBoundary2) {
1750
if (SCREEN_XSIZE + xScrollOffset >= curXBoundary2) {
1751
++curXBoundary2;
1752
if (target->xvel > 0) {
1753
curXBoundary2 += target->xvel >> 16;
1754
if (curXBoundary2 > newXBoundary2)
1755
curXBoundary2 = newXBoundary2;
1756
}
1757
}
1758
else {
1759
curXBoundary2 = newXBoundary2;
1760
}
1761
}
1762
1763
if (!target->gravity) {
1764
if (target->direction) {
1765
if (cameraStyle == CAMERASTYLE_EXTENDED_OFFSET_R || target->speed < -0x5F5C2) {
1766
cameraShift = 2;
1767
if (target->lookPosX <= 63) {
1768
target->lookPosX += 2;
1769
}
1770
}
1771
else {
1772
cameraShift = 0;
1773
if (target->lookPosX < 0) {
1774
target->lookPosX += 2;
1775
}
1776
1777
if (target->lookPosX > 0) {
1778
target->lookPosX -= 2;
1779
}
1780
}
1781
}
1782
else {
1783
if (cameraStyle == CAMERASTYLE_EXTENDED_OFFSET_L || target->speed > 0x5F5C2) {
1784
cameraShift = 1;
1785
if (target->lookPosX >= -63) {
1786
target->lookPosX -= 2;
1787
}
1788
}
1789
else {
1790
cameraShift = 0;
1791
if (target->lookPosX < 0) {
1792
target->lookPosX += 2;
1793
}
1794
1795
if (target->lookPosX > 0) {
1796
target->lookPosX -= 2;
1797
}
1798
}
1799
}
1800
}
1801
else {
1802
if (cameraShift == 1) {
1803
if (target->lookPosX >= -63) {
1804
target->lookPosX -= 2;
1805
}
1806
}
1807
else if (cameraShift < 1) {
1808
if (target->lookPosX < 0) {
1809
target->lookPosX += 2;
1810
}
1811
if (target->lookPosX > 0) {
1812
target->lookPosX -= 2;
1813
}
1814
}
1815
else if (cameraShift == 2) {
1816
if (target->lookPosX <= 63) {
1817
target->lookPosX += 2;
1818
}
1819
}
1820
}
1821
cameraXPos = targetX - target->lookPosX;
1822
1823
if (!target->scrollTracking) {
1824
if (cameraLockedY) {
1825
cameraYPos = targetY;
1826
if (cameraYPos < curYBoundary1 + SCREEN_SCROLL_UP) {
1827
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1828
}
1829
}
1830
else if (targetY > cameraYPos) {
1831
int dif = targetY - cameraYPos;
1832
if (targetY - cameraYPos < 0) {
1833
cameraLockedY = true;
1834
if (cameraYPos < curYBoundary1 + SCREEN_SCROLL_UP) {
1835
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1836
}
1837
}
1838
else {
1839
if (dif > 32 || abs(target->yvel) > 0x60000) {
1840
if (dif > 16) {
1841
dif = 16;
1842
if (cameraYPos + dif >= curYBoundary1 + SCREEN_SCROLL_UP) {
1843
cameraYPos += dif;
1844
}
1845
else {
1846
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1847
}
1848
}
1849
else {
1850
cameraLockedY = true;
1851
if (cameraYPos + dif >= curYBoundary1 + SCREEN_SCROLL_UP) {
1852
cameraYPos += dif;
1853
}
1854
else {
1855
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1856
}
1857
}
1858
}
1859
else if (dif > 6) {
1860
dif = 6;
1861
if (cameraYPos + dif >= curYBoundary1 + SCREEN_SCROLL_UP) {
1862
cameraYPos += dif;
1863
}
1864
else {
1865
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1866
}
1867
}
1868
else {
1869
cameraLockedY = true;
1870
if (cameraYPos + dif >= curYBoundary1 + SCREEN_SCROLL_UP) {
1871
cameraYPos += dif;
1872
}
1873
else {
1874
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1875
}
1876
}
1877
}
1878
}
1879
else {
1880
int dif = targetY - cameraYPos;
1881
if (targetY - cameraYPos <= 0) {
1882
if (dif < -32 || abs(target->yvel) > 0x60000) {
1883
if (dif < -16) {
1884
dif = -16;
1885
if (cameraYPos + dif >= curYBoundary1 + SCREEN_SCROLL_UP) {
1886
cameraYPos += dif;
1887
}
1888
else {
1889
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1890
}
1891
}
1892
else {
1893
cameraLockedY = true;
1894
if (cameraYPos + dif >= curYBoundary1 + SCREEN_SCROLL_UP) {
1895
cameraYPos += dif;
1896
}
1897
else {
1898
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1899
}
1900
}
1901
}
1902
else if (dif < -6) {
1903
dif = -6;
1904
if (cameraYPos + dif >= curYBoundary1 + SCREEN_SCROLL_UP) {
1905
cameraYPos += dif;
1906
}
1907
else {
1908
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1909
}
1910
}
1911
}
1912
else {
1913
dif = 0;
1914
if (abs(target->yvel) > 0x60000) {
1915
cameraLockedY = true;
1916
if (cameraYPos + dif >= curYBoundary1 + SCREEN_SCROLL_UP) {
1917
cameraYPos += dif;
1918
}
1919
else {
1920
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1921
}
1922
}
1923
else {
1924
cameraLockedY = true;
1925
if (cameraYPos + dif >= curYBoundary1 + SCREEN_SCROLL_UP) {
1926
cameraYPos += dif;
1927
}
1928
else {
1929
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1930
}
1931
}
1932
}
1933
}
1934
}
1935
else {
1936
int dif = targetY - cameraYPos;
1937
int difY = 0;
1938
if (targetY > cameraYPos) {
1939
difY = dif - 32;
1940
if (difY >= 0) {
1941
if (difY >= 17)
1942
difY = 16;
1943
1944
cameraLockedY = false;
1945
if (cameraYPos + difY >= curYBoundary1 + SCREEN_SCROLL_UP) {
1946
cameraYPos += difY;
1947
}
1948
else {
1949
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1950
}
1951
}
1952
else {
1953
cameraLockedY = false;
1954
if (cameraYPos < curYBoundary1 + SCREEN_SCROLL_UP) {
1955
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1956
}
1957
}
1958
}
1959
else {
1960
difY = dif + 32;
1961
if (difY > 0) {
1962
difY = 0;
1963
1964
cameraLockedY = false;
1965
if (cameraYPos < curYBoundary1 + SCREEN_SCROLL_UP) {
1966
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1967
}
1968
}
1969
else if (difY <= -17) {
1970
difY = -16;
1971
1972
cameraLockedY = false;
1973
if (cameraYPos + difY >= curYBoundary1 + SCREEN_SCROLL_UP) {
1974
cameraYPos += difY;
1975
}
1976
else {
1977
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1978
}
1979
}
1980
else {
1981
cameraLockedY = false;
1982
if (cameraYPos + difY >= curYBoundary1 + SCREEN_SCROLL_UP) {
1983
cameraYPos += difY;
1984
}
1985
else {
1986
cameraYPos = curYBoundary1 + SCREEN_SCROLL_UP;
1987
}
1988
}
1989
}
1990
}
1991
1992
if (cameraYPos >= curYBoundary2 - SCREEN_SCROLL_DOWN - 1) {
1993
cameraYPos = curYBoundary2 - SCREEN_SCROLL_DOWN;
1994
}
1995
1996
xScrollOffset = cameraXPos - SCREEN_CENTERX;
1997
yScrollOffset = target->lookPosY + cameraYPos - SCREEN_SCROLL_UP;
1998
1999
int x = curXBoundary1;
2000
if (x <= xScrollOffset)
2001
x = xScrollOffset;
2002
else
2003
xScrollOffset = x;
2004
2005
if (x > curXBoundary2 - SCREEN_XSIZE) {
2006
x = curXBoundary2 - SCREEN_XSIZE;
2007
xScrollOffset = curXBoundary2 - SCREEN_XSIZE;
2008
}
2009
2010
int y = curYBoundary1;
2011
if (yScrollOffset >= y)
2012
y = yScrollOffset;
2013
else
2014
yScrollOffset = y;
2015
2016
if (curYBoundary2 - SCREEN_YSIZE - 1 <= y)
2017
y = curYBoundary2 - SCREEN_YSIZE;
2018
2019
xScrollOffset = cameraShakeX + x;
2020
yScrollOffset = cameraShakeY + y;
2021
2022
if (cameraShakeX) {
2023
if (cameraShakeX <= 0) {
2024
cameraShakeX = ~cameraShakeX;
2025
}
2026
else {
2027
cameraShakeX = -cameraShakeX;
2028
}
2029
}
2030
2031
if (cameraShakeY) {
2032
if (cameraShakeY <= 0) {
2033
cameraShakeY = ~cameraShakeY;
2034
}
2035
else {
2036
cameraShakeY = -cameraShakeY;
2037
}
2038
}
2039
}
2040
void SetPlayerHLockedScreenPosition(Entity *target)
2041
{
2042
int targetY = cameraAdjustY + (target->ypos >> 16);
2043
2044
if (newYBoundary1 <= curYBoundary1) {
2045
if (curYBoundary1 > yScrollOffset)
2046
--curYBoundary1;
2047
else
2048
curYBoundary1 = newYBoundary1;
2049
}
2050
else {
2051
if (newYBoundary1 >= yScrollOffset)
2052
curYBoundary1 = yScrollOffset;
2053
else
2054
curYBoundary1 = newYBoundary1;
2055
}
2056
2057
if (newYBoundary2 < curYBoundary2) {
2058
if (curYBoundary2 <= yScrollOffset + SCREEN_YSIZE || newYBoundary2 >= yScrollOffset + SCREEN_YSIZE)
2059
--curYBoundary2;
2060
else
2061
curYBoundary2 = yScrollOffset + SCREEN_YSIZE;
2062
}
2063
if (newYBoundary2 > curYBoundary2) {
2064
if (yScrollOffset + SCREEN_YSIZE >= curYBoundary2) {
2065
++curYBoundary2;
2066
if (target->yvel > 0) {
2067
if (newYBoundary2 < curYBoundary2 + (target->yvel >> 16)) {
2068
curYBoundary2 = newYBoundary2;
2069
}
2070
else {
2071
curYBoundary2 += target->yvel >> 16;
2072
}
2073
}
2074
}
2075
else
2076
curYBoundary2 = newYBoundary2;
2077
}
2078
2079
if (newXBoundary1 > curXBoundary1) {
2080
if (xScrollOffset <= newXBoundary1)
2081
curXBoundary1 = xScrollOffset;
2082
else
2083
curXBoundary1 = newXBoundary1;
2084
}
2085
if (newXBoundary1 < curXBoundary1) {
2086
if (xScrollOffset <= curXBoundary1) {
2087
--curXBoundary1;
2088
if (target->xvel < 0) {
2089
curXBoundary1 += target->xvel >> 16;
2090
if (curXBoundary1 < newXBoundary1)
2091
curXBoundary1 = newXBoundary1;
2092
}
2093
}
2094
else {
2095
curXBoundary1 = newXBoundary1;
2096
}
2097
}
2098
if (newXBoundary2 < curXBoundary2) {
2099
if (newXBoundary2 > SCREEN_XSIZE + xScrollOffset)
2100
curXBoundary2 = newXBoundary2;
2101
else
2102
curXBoundary2 = SCREEN_XSIZE + xScrollOffset;
2103
}
2104
if (newXBoundary2 > curXBoundary2) {
2105
if (SCREEN_XSIZE + xScrollOffset >= curXBoundary2) {
2106
++curXBoundary2;
2107
if (target->xvel > 0) {
2108
curXBoundary2 += target->xvel >> 16;
2109
if (curXBoundary2 > newXBoundary2)
2110
curXBoundary2 = newXBoundary2;
2111
}
2112
}
2113
else {
2114
curXBoundary2 = newXBoundary2;
2115
}
2116
}
2117
2118
int camScroll = 0;
2119
if (target->scrollTracking) {
2120
if (targetY <= cameraYPos) {
2121
camScroll = targetY - cameraYPos + 32;
2122
if (camScroll <= 0) {
2123
if (camScroll <= -17)
2124
camScroll = -16;
2125
}
2126
else
2127
camScroll = 0;
2128
}
2129
else {
2130
camScroll = targetY - cameraYPos - 32;
2131
if (camScroll >= 0) {
2132
if (camScroll >= 17)
2133
camScroll = 16;
2134
}
2135
else
2136
camScroll = 0;
2137
}
2138
cameraLockedY = false;
2139
}
2140
else if (cameraLockedY) {
2141
camScroll = 0;
2142
cameraYPos = targetY;
2143
}
2144
else if (targetY > cameraYPos) {
2145
camScroll = targetY - cameraYPos;
2146
if (camScroll >= 0) {
2147
if (camScroll > 32 || abs(target->yvel) > 0x60000) {
2148
if (camScroll > 16) {
2149
camScroll = 16;
2150
}
2151
else {
2152
cameraLockedY = true;
2153
}
2154
}
2155
else if (camScroll > 6) {
2156
camScroll = 6;
2157
}
2158
else {
2159
cameraLockedY = true;
2160
}
2161
}
2162
else {
2163
camScroll = 0;
2164
cameraLockedY = true;
2165
}
2166
}
2167
else {
2168
camScroll = targetY - cameraYPos;
2169
if (camScroll > 0) {
2170
camScroll = 0;
2171
cameraLockedY = true;
2172
}
2173
else if (camScroll < -32 || abs(target->yvel) > 0x60000) {
2174
if (camScroll < -16) {
2175
camScroll = -16;
2176
}
2177
else {
2178
cameraLockedY = true;
2179
}
2180
}
2181
else {
2182
if (camScroll >= -6)
2183
cameraLockedY = true;
2184
else
2185
camScroll = -6;
2186
}
2187
}
2188
2189
int newCamY = cameraYPos + camScroll;
2190
if (newCamY <= curYBoundary1 + (SCREEN_SCROLL_UP - 1))
2191
newCamY = curYBoundary1 + SCREEN_SCROLL_UP;
2192
cameraYPos = newCamY;
2193
if (curYBoundary2 - (SCREEN_SCROLL_DOWN - 1) <= newCamY) {
2194
newCamY = curYBoundary2 - SCREEN_SCROLL_DOWN;
2195
cameraYPos = curYBoundary2 - SCREEN_SCROLL_DOWN;
2196
}
2197
2198
xScrollOffset = cameraShakeX + cameraXPos - SCREEN_CENTERX;
2199
2200
int pos = newCamY + target->lookPosY - SCREEN_SCROLL_UP;
2201
if (pos < curYBoundary1) {
2202
yScrollOffset = curYBoundary1;
2203
}
2204
else {
2205
yScrollOffset = newCamY + target->lookPosY - SCREEN_SCROLL_UP;
2206
}
2207
int y1 = curYBoundary2 - (SCREEN_YSIZE - 1);
2208
int y2 = curYBoundary2 - SCREEN_YSIZE;
2209
if (y1 > yScrollOffset)
2210
y2 = yScrollOffset;
2211
yScrollOffset = cameraShakeY + y2;
2212
2213
if (cameraShakeX) {
2214
if (cameraShakeX <= 0) {
2215
cameraShakeX = ~cameraShakeX;
2216
}
2217
else {
2218
cameraShakeX = -cameraShakeX;
2219
}
2220
}
2221
2222
if (cameraShakeY) {
2223
if (cameraShakeY <= 0) {
2224
cameraShakeY = ~cameraShakeY;
2225
}
2226
else {
2227
cameraShakeY = -cameraShakeY;
2228
}
2229
}
2230
}
2231
void SetPlayerLockedScreenPosition(Entity *target)
2232
{
2233
if (newYBoundary1 > curYBoundary1) {
2234
if (yScrollOffset <= newYBoundary1)
2235
curYBoundary1 = yScrollOffset;
2236
else
2237
curYBoundary1 = newYBoundary1;
2238
}
2239
if (newYBoundary1 < curYBoundary1) {
2240
if (yScrollOffset <= curYBoundary1)
2241
--curYBoundary1;
2242
else
2243
curYBoundary1 = newYBoundary1;
2244
}
2245
if (newYBoundary2 < curYBoundary2) {
2246
if (curYBoundary2 <= yScrollOffset + SCREEN_YSIZE || newYBoundary2 >= yScrollOffset + SCREEN_YSIZE)
2247
--curYBoundary2;
2248
else
2249
curYBoundary2 = yScrollOffset + SCREEN_YSIZE;
2250
}
2251
if (newYBoundary2 > curYBoundary2) {
2252
if (yScrollOffset + SCREEN_YSIZE >= curYBoundary2)
2253
++curYBoundary2;
2254
else
2255
curYBoundary2 = newYBoundary2;
2256
}
2257
if (newXBoundary1 > curXBoundary1) {
2258
if (xScrollOffset <= newXBoundary1)
2259
curXBoundary1 = xScrollOffset;
2260
else
2261
curXBoundary1 = newXBoundary1;
2262
}
2263
if (newXBoundary1 < curXBoundary1) {
2264
if (xScrollOffset <= curXBoundary1) {
2265
--curXBoundary1;
2266
if (target->xvel < 0) {
2267
curXBoundary1 += target->xvel >> 16;
2268
if (curXBoundary1 < newXBoundary1)
2269
curXBoundary1 = newXBoundary1;
2270
}
2271
}
2272
else {
2273
curXBoundary1 = newXBoundary1;
2274
}
2275
}
2276
if (newXBoundary2 < curXBoundary2) {
2277
if (newXBoundary2 > SCREEN_XSIZE + xScrollOffset)
2278
curXBoundary2 = newXBoundary2;
2279
else
2280
curXBoundary2 = SCREEN_XSIZE + xScrollOffset;
2281
}
2282
if (newXBoundary2 > curXBoundary2) {
2283
if (SCREEN_XSIZE + xScrollOffset >= curXBoundary2) {
2284
++curXBoundary2;
2285
if (target->xvel > 0) {
2286
curXBoundary2 += target->xvel >> 16;
2287
if (curXBoundary2 > newXBoundary2)
2288
curXBoundary2 = newXBoundary2;
2289
}
2290
}
2291
else {
2292
curXBoundary2 = newXBoundary2;
2293
}
2294
}
2295
2296
if (cameraShakeX) {
2297
if (cameraShakeX <= 0) {
2298
cameraShakeX = ~cameraShakeX;
2299
}
2300
else {
2301
cameraShakeX = -cameraShakeX;
2302
}
2303
}
2304
2305
if (cameraShakeY) {
2306
if (cameraShakeY <= 0) {
2307
cameraShakeY = ~cameraShakeY;
2308
}
2309
else {
2310
cameraShakeY = -cameraShakeY;
2311
}
2312
}
2313
}
2314
// Completely unused in both Sonic 1 & Sonic 2
2315
void SetPlayerScreenPositionFixed(Entity *target)
2316
{
2317
int targetX = target->xpos >> 16;
2318
int targetY = cameraAdjustY + (target->ypos >> 16);
2319
if (newYBoundary1 > curYBoundary1) {
2320
if (newYBoundary1 >= yScrollOffset)
2321
curYBoundary1 = yScrollOffset;
2322
else
2323
curYBoundary1 = newYBoundary1;
2324
}
2325
if (newYBoundary1 < curYBoundary1) {
2326
if (curYBoundary1 >= yScrollOffset)
2327
--curYBoundary1;
2328
else
2329
curYBoundary1 = newYBoundary1;
2330
}
2331
if (newYBoundary2 < curYBoundary2) {
2332
if (curYBoundary2 <= yScrollOffset + SCREEN_YSIZE || newYBoundary2 >= yScrollOffset + SCREEN_YSIZE)
2333
--curYBoundary2;
2334
else
2335
curYBoundary2 = yScrollOffset + SCREEN_YSIZE;
2336
}
2337
if (newYBoundary2 > curYBoundary2) {
2338
if (yScrollOffset + SCREEN_YSIZE >= curYBoundary2) {
2339
++curYBoundary2;
2340
if (target->yvel > 0) {
2341
int buf = curYBoundary2 + (target->yvel >> 16);
2342
if (newYBoundary2 < buf) {
2343
curYBoundary2 = newYBoundary2;
2344
}
2345
else {
2346
curYBoundary2 += target->yvel >> 16;
2347
}
2348
}
2349
}
2350
else
2351
curYBoundary2 = newYBoundary2;
2352
}
2353
if (newXBoundary1 > curXBoundary1) {
2354
if (xScrollOffset <= newXBoundary1)
2355
curXBoundary1 = xScrollOffset;
2356
else
2357
curXBoundary1 = newXBoundary1;
2358
}
2359
if (newXBoundary1 < curXBoundary1) {
2360
if (xScrollOffset <= curXBoundary1) {
2361
--curXBoundary1;
2362
if (target->xvel < 0) {
2363
curXBoundary1 += target->xvel >> 16;
2364
if (curXBoundary1 < newXBoundary1)
2365
curXBoundary1 = newXBoundary1;
2366
}
2367
}
2368
else {
2369
curXBoundary1 = newXBoundary1;
2370
}
2371
}
2372
if (newXBoundary2 < curXBoundary2) {
2373
if (newXBoundary2 > SCREEN_XSIZE + xScrollOffset)
2374
curXBoundary2 = newXBoundary2;
2375
else
2376
curXBoundary2 = SCREEN_XSIZE + xScrollOffset;
2377
}
2378
if (newXBoundary2 > curXBoundary2) {
2379
if (SCREEN_XSIZE + xScrollOffset >= curXBoundary2) {
2380
++curXBoundary2;
2381
if (target->xvel > 0) {
2382
curXBoundary2 += target->xvel >> 16;
2383
if (curXBoundary2 > newXBoundary2)
2384
curXBoundary2 = newXBoundary2;
2385
}
2386
}
2387
else {
2388
curXBoundary2 = newXBoundary2;
2389
}
2390
}
2391
2392
cameraXPos = targetX;
2393
if (targetX < SCREEN_CENTERX + curXBoundary1) {
2394
targetX = SCREEN_CENTERX + curXBoundary1;
2395
cameraXPos = SCREEN_CENTERX + curXBoundary1;
2396
}
2397
int boundX2 = curXBoundary2 - SCREEN_CENTERX;
2398
if (boundX2 < targetX) {
2399
targetX = boundX2;
2400
cameraXPos = boundX2;
2401
}
2402
2403
if (targetY <= curYBoundary1 + 119) {
2404
targetY = curYBoundary1 + 120;
2405
cameraYPos = curYBoundary1 + 120;
2406
}
2407
else {
2408
cameraYPos = targetY;
2409
}
2410
if (curYBoundary2 - 119 <= targetY) {
2411
targetY = curYBoundary2 - 120;
2412
cameraYPos = curYBoundary2 - 120;
2413
}
2414
2415
xScrollOffset = cameraShakeX + targetX - SCREEN_CENTERX;
2416
int camY = targetY + target->lookPosY - SCREEN_CENTERY;
2417
if (curYBoundary1 > camY) {
2418
yScrollOffset = curYBoundary1;
2419
}
2420
else {
2421
yScrollOffset = targetY + target->lookPosY - SCREEN_CENTERY;
2422
}
2423
2424
int newCamY = curYBoundary2 - SCREEN_YSIZE;
2425
if (curYBoundary2 - (SCREEN_YSIZE - 1) > yScrollOffset)
2426
newCamY = yScrollOffset;
2427
yScrollOffset = cameraShakeY + newCamY;
2428
2429
if (cameraShakeX) {
2430
if (cameraShakeX <= 0) {
2431
cameraShakeX = ~cameraShakeX;
2432
}
2433
else {
2434
cameraShakeX = -cameraShakeX;
2435
}
2436
}
2437
2438
if (cameraShakeY) {
2439
if (cameraShakeY <= 0) {
2440
cameraShakeY = ~cameraShakeY;
2441
}
2442
else {
2443
cameraShakeY = -cameraShakeY;
2444
}
2445
}
2446
}
2447
2448