Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-1-2-2013-Decompilation
Path: blob/main/RSDKv4/Drawing.cpp
817 views
1
#include "RetroEngine.hpp"
2
3
ushort blendLookupTable[0x20 * 0x100];
4
ushort subtractLookupTable[0x20 * 0x100];
5
ushort tintLookupTable[0x10000];
6
7
// Extras used in blending
8
#define maxVal(a, b) (a >= b ? a : b)
9
#define minVal(a, b) (a <= b ? a : b)
10
11
bool windowCreated = false;
12
13
int SCREEN_XSIZE_CONFIG = 424;
14
int SCREEN_XSIZE = 424;
15
int SCREEN_CENTERX = 424 / 2;
16
17
float SCREEN_XSIZE_F = 424;
18
float SCREEN_CENTERX_F = 424 / 2;
19
20
float SCREEN_YSIZE_F = SCREEN_YSIZE;
21
float SCREEN_CENTERY_F = SCREEN_YSIZE / 2;
22
23
int touchWidth = SCREEN_XSIZE;
24
int touchHeight = SCREEN_YSIZE;
25
float touchWidthF = SCREEN_XSIZE;
26
float touchHeightF = SCREEN_YSIZE;
27
28
DrawListEntry drawListEntries[DRAWLAYER_COUNT];
29
30
int gfxDataPosition = 0;
31
GFXSurface gfxSurface[SURFACE_COUNT];
32
byte graphicData[GFXDATA_SIZE];
33
34
DisplaySettings displaySettings;
35
bool convertTo32Bit = false;
36
bool mixFiltersOnJekyll = false;
37
38
#if RETRO_USING_OPENGL
39
GLint defaultFramebuffer = -1;
40
GLuint framebufferHiRes = -1;
41
GLuint renderbufferHiRes = -1;
42
#endif
43
44
#if !RETRO_USE_ORIGINAL_CODE
45
// enable integer scaling, which is a modification of enhanced scaling
46
bool integerScaling = false;
47
// allows me to disable it to prevent blur on resolutions that match only on 1 axis
48
bool disableEnhancedScaling = false;
49
// enable bilinear scaling, which just disables the fancy upscaling that enhanced scaling does.
50
bool bilinearScaling = false;
51
#endif
52
53
int InitRenderDevice()
54
{
55
char gameTitle[0x40];
56
57
sprintf(gameTitle, "%s%s", Engine.gameWindowText, Engine.usingDataFile_Config ? "" : " (Using Data Folder)");
58
59
#if !RETRO_USE_ORIGINAL_CODE
60
#if RETRO_USING_SDL2
61
SDL_Init(SDL_INIT_EVERYTHING);
62
63
SDL_DisableScreenSaver();
64
65
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
66
SDL_SetHint(SDL_HINT_RENDER_VSYNC, Engine.vsync ? "1" : "0");
67
68
byte flags = 0;
69
#if RETRO_USING_OPENGL
70
flags |= SDL_WINDOW_OPENGL;
71
72
#if RETRO_PLATFORM != RETRO_OSX // dude idk either you just gotta trust that this works
73
#if RETRO_PLATFORM != RETRO_ANDROID
74
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
75
#else
76
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
77
#endif
78
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
79
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
80
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
81
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
82
#endif
83
#endif
84
#if RETRO_DEVICETYPE == RETRO_MOBILE
85
Engine.startFullScreen = true;
86
87
SDL_DisplayMode dm;
88
SDL_GetDesktopDisplayMode(0, &dm);
89
90
bool landscape = dm.h < dm.w;
91
int h = landscape ? dm.w : dm.h;
92
int w = landscape ? dm.h : dm.w;
93
94
SCREEN_XSIZE = ((float)SCREEN_YSIZE * h / w);
95
if (SCREEN_XSIZE % 2)
96
++SCREEN_XSIZE;
97
#endif
98
99
SCREEN_CENTERX = SCREEN_XSIZE / 2;
100
Engine.window = SDL_CreateWindow(gameTitle, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_XSIZE * Engine.windowScale,
101
SCREEN_YSIZE * Engine.windowScale, SDL_WINDOW_ALLOW_HIGHDPI | flags);
102
103
if (!Engine.window) {
104
PrintLog("ERROR: failed to create window!");
105
return 0;
106
}
107
108
#if !RETRO_USING_OPENGL
109
Engine.renderer = SDL_CreateRenderer(Engine.window, -1, SDL_RENDERER_ACCELERATED);
110
111
if (!Engine.renderer) {
112
PrintLog("ERROR: failed to create renderer!");
113
return 0;
114
}
115
116
SDL_RenderSetLogicalSize(Engine.renderer, SCREEN_XSIZE, SCREEN_YSIZE);
117
SDL_SetRenderDrawBlendMode(Engine.renderer, SDL_BLENDMODE_BLEND);
118
119
#if RETRO_SOFTWARE_RENDER
120
Engine.screenBuffer = SDL_CreateTexture(Engine.renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, SCREEN_XSIZE, SCREEN_YSIZE);
121
122
if (!Engine.screenBuffer) {
123
PrintLog("ERROR: failed to create screen buffer!\nerror msg: %s", SDL_GetError());
124
return 0;
125
}
126
127
Engine.screenBuffer2x =
128
SDL_CreateTexture(Engine.renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, SCREEN_XSIZE * 2, SCREEN_YSIZE * 2);
129
130
if (!Engine.screenBuffer2x) {
131
PrintLog("ERROR: failed to create screen buffer HQ!\nerror msg: %s", SDL_GetError());
132
return 0;
133
}
134
#endif
135
#endif
136
137
if (Engine.borderless) {
138
SDL_RestoreWindow(Engine.window);
139
SDL_SetWindowBordered(Engine.window, SDL_FALSE);
140
}
141
142
SDL_DisplayMode disp;
143
if (SDL_GetDisplayMode(0, 0, &disp) == 0) {
144
Engine.screenRefreshRate = disp.refresh_rate;
145
}
146
147
#endif
148
149
#if RETRO_USING_SDL1
150
SDL_Init(SDL_INIT_EVERYTHING);
151
152
byte flags = 0;
153
#if RETRO_USING_OPENGL
154
flags |= SDL_OPENGL;
155
#endif
156
157
Engine.windowSurface = SDL_SetVideoMode(SCREEN_XSIZE * Engine.windowScale, SCREEN_YSIZE * Engine.windowScale, 32, SDL_SWSURFACE | flags);
158
if (!Engine.windowSurface) {
159
PrintLog("ERROR: failed to create window!\nerror msg: %s", SDL_GetError());
160
return 0;
161
}
162
// Set the window caption
163
SDL_WM_SetCaption(gameTitle, NULL);
164
165
Engine.screenBuffer =
166
SDL_CreateRGBSurface(0, SCREEN_XSIZE * Engine.windowScale, SCREEN_YSIZE * Engine.windowScale, 16, 0xF800, 0x7E0, 0x1F, 0x00);
167
168
if (!Engine.screenBuffer) {
169
PrintLog("ERROR: failed to create screen buffer!\nerror msg: %s", SDL_GetError());
170
return 0;
171
}
172
173
/*Engine.screenBuffer2x = SDL_SetVideoMode(SCREEN_XSIZE * 2, SCREEN_YSIZE * 2, 16, SDL_SWSURFACE | flags);
174
if (!Engine.screenBuffer2x) {
175
PrintLog("ERROR: failed to create screen buffer HQ!\nerror msg: %s", SDL_GetError());
176
return 0;
177
}*/
178
179
if (Engine.startFullScreen) {
180
Engine.windowSurface =
181
SDL_SetVideoMode(SCREEN_XSIZE * Engine.windowScale, SCREEN_YSIZE * Engine.windowScale, 16, SDL_SWSURFACE | SDL_FULLSCREEN | flags);
182
SDL_ShowCursor(SDL_FALSE);
183
Engine.isFullScreen = true;
184
}
185
186
// TODO: not supported in 1.2?
187
if (Engine.borderless) {
188
// SDL_RestoreWindow(Engine.window);
189
// SDL_SetWindowBordered(Engine.window, SDL_FALSE);
190
}
191
192
// SDL_SetWindowPosition(Engine.window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
193
194
Engine.useHQModes = false; // disabled
195
Engine.borderless = false; // disabled
196
#endif
197
198
#if RETRO_USING_OPENGL
199
200
// Init GL
201
Engine.glContext = SDL_GL_CreateContext(Engine.window);
202
203
SDL_GL_SetSwapInterval(Engine.vsync ? 1 : 0);
204
205
#if RETRO_PLATFORM != RETRO_ANDROID && RETRO_PLATFORM != RETRO_OSX
206
GLenum err = glewInit();
207
if (err != GLEW_OK && err != GLEW_ERROR_NO_GLX_DISPLAY) {
208
PrintLog("glew init error:");
209
PrintLog((const char *)glewGetErrorString(err));
210
return false;
211
}
212
#endif
213
214
displaySettings.unknown2 = 0;
215
216
glClearColor(0.0, 0.0, 0.0, 1.0);
217
218
glDisable(GL_LIGHTING);
219
glEnable(GL_TEXTURE_2D);
220
glDisable(GL_DEPTH_TEST);
221
glDisable(GL_DITHER);
222
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
223
glDisable(GL_BLEND);
224
glEnable(GL_CULL_FACE);
225
226
glMatrixMode(GL_PROJECTION);
227
glLoadIdentity();
228
229
#if RETRO_PLATFORM == RETRO_ANDROID
230
Engine.windowScale = 1;
231
displaySettings.width = SCREEN_XSIZE;
232
displaySettings.height = SCREEN_YSIZE;
233
#else
234
displaySettings.width = SCREEN_XSIZE_CONFIG * Engine.windowScale;
235
displaySettings.height = SCREEN_YSIZE * Engine.windowScale;
236
#endif
237
238
textureList[0].id = -1;
239
SetupViewport();
240
241
ResetRenderStates();
242
SetupDrawIndexList();
243
244
for (int c = 0; c < 0x10000; ++c) {
245
int r = (c & 0b1111100000000000) >> 8;
246
int g = (c & 0b0000011111100000) >> 3;
247
int b = (c & 0b0000000000011111) << 3;
248
gfxPalette16to32[c] = (0xFF << 24) | (b << 16) | (g << 8) | (r << 0);
249
}
250
251
float lightAmbient[4] = { 2.0, 2.0, 2.0, 1.0 };
252
float lightDiffuse[4] = { 1.0, 1.0, 1.0, 1.0 };
253
float lightPos[4] = { 0.0, 0.0, 0.0, 1.0 };
254
255
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
256
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
257
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
258
glEnable(GL_LIGHT0);
259
260
#if RETRO_PLATFORM == RETRO_ANDROID
261
Engine.startFullScreen = true;
262
#endif
263
#endif
264
265
#if RETRO_PLATFORM != RETRO_ANDROID
266
SetScreenDimensions(SCREEN_XSIZE_CONFIG * Engine.windowScale, SCREEN_YSIZE * Engine.windowScale);
267
#else
268
SetScreenDimensions(SCREEN_XSIZE, SCREEN_YSIZE);
269
#endif
270
271
#if RETRO_SOFTWARE_RENDER
272
Engine.frameBuffer = new ushort[GFX_LINESIZE * SCREEN_YSIZE];
273
Engine.frameBuffer2x = new ushort[GFX_LINESIZE_DOUBLE * (SCREEN_YSIZE * 2)];
274
memset(Engine.frameBuffer, 0, (GFX_LINESIZE * SCREEN_YSIZE) * sizeof(ushort));
275
memset(Engine.frameBuffer2x, 0, GFX_LINESIZE_DOUBLE * (SCREEN_YSIZE * 2) * sizeof(ushort));
276
#endif
277
Engine.texBuffer = new uint[GFX_LINESIZE * SCREEN_YSIZE];
278
memset(Engine.texBuffer, 0, (GFX_LINESIZE * SCREEN_YSIZE) * sizeof(uint));
279
280
#endif
281
282
if (Engine.startFullScreen) {
283
SetFullScreen(true);
284
}
285
286
OBJECT_BORDER_X2 = SCREEN_XSIZE + 0x80;
287
// OBJECT_BORDER_Y2 = SCREEN_YSIZE + 0x100;
288
OBJECT_BORDER_X4 = SCREEN_XSIZE + 0x20;
289
// OBJECT_BORDER_Y4 = SCREEN_YSIZE + 0x80;
290
291
InitInputDevices();
292
293
return 1;
294
}
295
void FlipScreen()
296
{
297
#if !RETRO_USE_ORIGINAL_CODE
298
float dimAmount = 1.0;
299
if ((!Engine.masterPaused || Engine.frameStep) && !drawStageGFXHQ) {
300
if (Engine.dimTimer < Engine.dimLimit) {
301
if (Engine.dimPercent < 1.0) {
302
Engine.dimPercent += 0.05;
303
if (Engine.dimPercent > 1.0)
304
Engine.dimPercent = 1.0;
305
}
306
}
307
else if (Engine.dimPercent > 0.25 && Engine.dimLimit >= 0) {
308
Engine.dimPercent *= 0.9;
309
}
310
311
dimAmount = Engine.dimMax * Engine.dimPercent;
312
}
313
314
#if RETRO_SOFTWARE_RENDER && !RETRO_USING_OPENGL
315
#if RETRO_USING_SDL2
316
SDL_Rect destScreenPos_scaled;
317
SDL_Texture *texTarget = NULL;
318
319
switch (Engine.scalingMode) {
320
// reset to default if value is invalid.
321
default: Engine.scalingMode = 0; break;
322
case 0: break; // nearest
323
case 1: integerScaling = true; break; // integer scaling
324
case 2: break; // sharp bilinear
325
case 3: bilinearScaling = true; break; // regular old bilinear
326
}
327
328
SDL_GetWindowSize(Engine.window, &Engine.windowXSize, &Engine.windowYSize);
329
float screenxsize = SCREEN_XSIZE;
330
float screenysize = SCREEN_YSIZE;
331
332
// check if enhanced scaling is even necessary to be calculated by checking if the screen size is close enough on one axis
333
// unfortunately it has to be "close enough" because of floating point precision errors. dang it
334
if (Engine.scalingMode == 2) {
335
bool cond1 = std::round((Engine.windowXSize / screenxsize) * 24) / 24 == std::floor(Engine.windowXSize / screenxsize);
336
bool cond2 = std::round((Engine.windowYSize / screenysize) * 24) / 24 == std::floor(Engine.windowYSize / screenysize);
337
if (cond1 || cond2)
338
disableEnhancedScaling = true;
339
}
340
341
// get 2x resolution if HQ is enabled.
342
if (drawStageGFXHQ) {
343
screenxsize *= 2;
344
screenysize *= 2;
345
}
346
347
if (Engine.scalingMode != 0 && !disableEnhancedScaling) {
348
// set up integer scaled texture, which is scaled to the largest integer scale of the screen buffer
349
// before you make a texture that's larger than the window itself. This texture will then be scaled
350
// up to the actual screen size using linear interpolation. This makes even window/screen scales
351
// nice and sharp, and uneven scales as sharp as possible without creating wonky pixel scales,
352
// creating a nice image.
353
354
// get integer scale
355
float scale = 1;
356
if (!bilinearScaling) {
357
scale =
358
std::fminf(std::floor((float)Engine.windowXSize / (float)SCREEN_XSIZE), std::floor((float)Engine.windowYSize / (float)SCREEN_YSIZE));
359
}
360
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); // set interpolation to linear
361
// create texture that's integer scaled.
362
texTarget = SDL_CreateTexture(Engine.renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_TARGET, SCREEN_XSIZE * scale, SCREEN_YSIZE * scale);
363
364
// keep aspect
365
float aspectScale = std::fminf(Engine.windowYSize / screenysize, Engine.windowXSize / screenxsize);
366
if (integerScaling) {
367
aspectScale = std::floor(aspectScale);
368
}
369
float xoffset = (Engine.windowXSize - (screenxsize * aspectScale)) / 2;
370
float yoffset = (Engine.windowYSize - (screenysize * aspectScale)) / 2;
371
destScreenPos_scaled.x = std::round(xoffset);
372
destScreenPos_scaled.y = std::round(yoffset);
373
destScreenPos_scaled.w = std::round(screenxsize * aspectScale);
374
destScreenPos_scaled.h = std::round(screenysize * aspectScale);
375
// fill the screen with the texture, making lerp work.
376
SDL_RenderSetLogicalSize(Engine.renderer, Engine.windowXSize, Engine.windowYSize);
377
}
378
379
int pitch = 0;
380
SDL_SetRenderTarget(Engine.renderer, texTarget);
381
382
// Clear the screen. This is needed to keep the
383
// pillarboxes in fullscreen from displaying garbage data.
384
SDL_RenderClear(Engine.renderer);
385
386
ushort *pixels = NULL;
387
if (!drawStageGFXHQ) {
388
SDL_LockTexture(Engine.screenBuffer, NULL, (void **)&pixels, &pitch);
389
ushort *frameBufferPtr = Engine.frameBuffer;
390
for (int y = 0; y < SCREEN_YSIZE; ++y) {
391
memcpy(pixels, frameBufferPtr, SCREEN_XSIZE * sizeof(ushort));
392
frameBufferPtr += GFX_LINESIZE;
393
pixels += pitch / sizeof(ushort);
394
}
395
// memcpy(pixels, Engine.frameBuffer, pitch * SCREEN_YSIZE); //faster but produces issues with odd numbered screen sizes
396
SDL_UnlockTexture(Engine.screenBuffer);
397
398
SDL_RenderCopy(Engine.renderer, Engine.screenBuffer, NULL, NULL);
399
}
400
else {
401
int w = 0, h = 0;
402
SDL_QueryTexture(Engine.screenBuffer2x, NULL, NULL, &w, &h);
403
SDL_LockTexture(Engine.screenBuffer2x, NULL, (void **)&pixels, &pitch);
404
405
ushort *framebufferPtr = Engine.frameBuffer;
406
for (int y = 0; y < (SCREEN_YSIZE / 2) + 12; ++y) {
407
for (int x = 0; x < GFX_LINESIZE; ++x) {
408
*pixels = *framebufferPtr;
409
pixels++;
410
*pixels = *framebufferPtr;
411
pixels++;
412
framebufferPtr++;
413
}
414
415
framebufferPtr -= GFX_LINESIZE;
416
for (int x = 0; x < GFX_LINESIZE; ++x) {
417
*pixels = *framebufferPtr;
418
pixels++;
419
*pixels = *framebufferPtr;
420
pixels++;
421
framebufferPtr++;
422
}
423
}
424
425
framebufferPtr = Engine.frameBuffer2x;
426
for (int y = 0; y < ((SCREEN_YSIZE / 2) - 12) * 2; ++y) {
427
for (int x = 0; x < GFX_LINESIZE; ++x) {
428
*pixels = *framebufferPtr;
429
framebufferPtr++;
430
pixels++;
431
432
*pixels = *framebufferPtr;
433
framebufferPtr++;
434
pixels++;
435
}
436
}
437
SDL_UnlockTexture(Engine.screenBuffer2x);
438
SDL_RenderCopy(Engine.renderer, Engine.screenBuffer2x, NULL, NULL);
439
}
440
441
if (Engine.scalingMode != 0 && !disableEnhancedScaling) {
442
// set render target back to the screen.
443
SDL_SetRenderTarget(Engine.renderer, NULL);
444
// clear the screen itself now, for same reason as above
445
SDL_RenderClear(Engine.renderer);
446
// copy texture to screen with lerp
447
SDL_RenderCopy(Engine.renderer, texTarget, NULL, &destScreenPos_scaled);
448
// Apply dimming
449
SDL_SetRenderDrawColor(Engine.renderer, 0, 0, 0, 0xFF - (dimAmount * 0xFF));
450
if (dimAmount < 1.0)
451
SDL_RenderFillRect(Engine.renderer, NULL);
452
// finally present it
453
SDL_RenderPresent(Engine.renderer);
454
// reset everything just in case
455
SDL_RenderSetLogicalSize(Engine.renderer, SCREEN_XSIZE, SCREEN_YSIZE);
456
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
457
// putting some FLEX TAPE� on that memory leak
458
SDL_DestroyTexture(texTarget);
459
}
460
else {
461
// Apply dimming
462
SDL_SetRenderDrawColor(Engine.renderer, 0, 0, 0, 0xFF - (dimAmount * 0xFF));
463
if (dimAmount < 1.0)
464
SDL_RenderFillRect(Engine.renderer, NULL);
465
// no change here
466
SDL_RenderPresent(Engine.renderer);
467
}
468
SDL_ShowWindow(Engine.window);
469
#endif
470
471
#if RETRO_USING_SDL1
472
ushort *px = (ushort *)Engine.screenBuffer->pixels;
473
int w = SCREEN_XSIZE * Engine.windowScale;
474
int h = SCREEN_YSIZE * Engine.windowScale;
475
476
if (Engine.windowScale == 1) {
477
ushort *frameBufferPtr = Engine.frameBuffer;
478
for (int y = 0; y < SCREEN_YSIZE; ++y) {
479
for (int x = 0; x < SCREEN_XSIZE; ++x) {
480
pixels[x] = frameBufferPtr[x];
481
}
482
frameBufferPtr += GFX_LINESIZE;
483
px += Engine.screenBuffer->pitch / sizeof(ushort);
484
}
485
// memcpy(Engine.screenBuffer->pixels, Engine.frameBuffer, Engine.screenBuffer->pitch * SCREEN_YSIZE);
486
}
487
else {
488
// TODO: this better, I really dont know how to use SDL1.2 well lol
489
int dx = 0, dy = 0;
490
do {
491
do {
492
int x = (int)(dx * (1.0f / Engine.windowScale));
493
int y = (int)(dy * (1.0f / Engine.windowScale));
494
495
px[dx + (dy * w)] = Engine.frameBuffer[x + (y * GFX_LINESIZE)];
496
497
dx++;
498
} while (dx < w);
499
dy++;
500
dx = 0;
501
} while (dy < h);
502
}
503
504
// Apply image to screen
505
SDL_BlitSurface(Engine.screenBuffer, NULL, Engine.windowSurface, NULL);
506
507
// Update Screen
508
SDL_Flip(Engine.windowSurface);
509
#endif
510
511
#endif // !RETRO_SOFTWARE_RENDER
512
513
#endif
514
}
515
void ReleaseRenderDevice(bool refresh)
516
{
517
if (!refresh) {
518
ClearMeshData();
519
ClearTextures(false);
520
}
521
522
#if !RETRO_USE_ORIGINAL_CODE
523
#if RETRO_SOFTWARE_RENDER
524
if (Engine.frameBuffer)
525
delete[] Engine.frameBuffer;
526
if (Engine.frameBuffer2x)
527
delete[] Engine.frameBuffer2x;
528
#if RETRO_USING_SDL2 && !RETRO_USING_OPENGL
529
SDL_DestroyTexture(Engine.screenBuffer);
530
Engine.screenBuffer = NULL;
531
#endif
532
if (Engine.texBuffer)
533
delete[] Engine.texBuffer;
534
535
#if RETRO_USING_SDL1
536
SDL_FreeSurface(Engine.screenBuffer);
537
#endif
538
#endif
539
540
#if RETRO_USING_OPENGL
541
if (Engine.glContext)
542
SDL_GL_DeleteContext(Engine.glContext);
543
#endif
544
545
#if RETRO_USING_SDL2
546
#if !RETRO_USING_OPENGL
547
SDL_DestroyRenderer(Engine.renderer);
548
#endif
549
SDL_DestroyWindow(Engine.window);
550
#endif
551
#endif
552
}
553
554
void GenerateBlendLookupTable(void)
555
{
556
for (int y = 0; y < 0x100; y++) {
557
for (int x = 0; x < 0x20; x++) {
558
blendLookupTable[x + (0x20 * y)] = y * x >> 8;
559
subtractLookupTable[x + (0x20 * y)] = y * (0x1F - x) >> 8;
560
}
561
}
562
563
for (int i = 0; i < 0x10000; i++) {
564
int tintValue = ((i & 0x1F) + ((i & 0x7E0) >> 6) + ((i & 0xF800) >> 11)) / 3 + 6;
565
tintLookupTable[i] = 0x841 * minVal(tintValue, 0x1F);
566
}
567
}
568
569
void ClearScreen(byte index)
570
{
571
#if RETRO_SOFTWARE_RENDER
572
ushort color = activePalette[index];
573
ushort *framebuffer = Engine.frameBuffer;
574
int cnt = GFX_LINESIZE * SCREEN_YSIZE;
575
while (cnt--) {
576
*framebuffer = color;
577
++framebuffer;
578
}
579
#endif
580
}
581
582
void SetScreenDimensions(int width, int height)
583
{
584
touchWidth = width;
585
touchHeight = height;
586
displaySettings.width = width;
587
displaySettings.height = height;
588
touchWidthF = width;
589
displaySettings.unknown1 = 16;
590
touchHeightF = height;
591
// displaySettings.maxWidth = 424;
592
double aspect = (((width >> 16) * 65536.0) + width) / (((height >> 16) * 65536.0) + height);
593
SCREEN_XSIZE_F = SCREEN_YSIZE * aspect;
594
SCREEN_CENTERX_F = aspect * SCREEN_CENTERY;
595
SetPerspectiveMatrix(SCREEN_YSIZE * aspect, SCREEN_YSIZE_F, 0.0, 1000.0);
596
#if RETRO_USING_OPENGL
597
glViewport(0, 0, displaySettings.width, displaySettings.height);
598
#endif
599
600
Engine.useHighResAssets = displaySettings.height > (SCREEN_YSIZE * 2);
601
int displayWidth = aspect * SCREEN_YSIZE;
602
// if (val > displaySettings.maxWidth)
603
// val = displaySettings.maxWidth;
604
#if !RETRO_USE_ORIGINAL_CODE
605
SetScreenSize(displayWidth, (displayWidth + 9) & -0x8);
606
#else
607
SetScreenSize(displayWidth, (displayWidth + 9) & -0x10);
608
#endif
609
610
int width2 = 0;
611
int wBuf = GFX_LINESIZE - 1;
612
while (wBuf > 0) {
613
width2++;
614
wBuf >>= 1;
615
}
616
int height2 = 0;
617
int hBuf = SCREEN_YSIZE - 1;
618
while (hBuf > 0) {
619
height2++;
620
hBuf >>= 1;
621
}
622
int texWidth = 1 << width2;
623
int texHeight = 1 << height2;
624
625
textureList[0].widthN = 1.0f / texWidth;
626
textureList[0].heightN = 1.0f / texHeight;
627
628
float w = (SCREEN_XSIZE * textureList[0].widthN);
629
float w2 = (GFX_LINESIZE * textureList[0].widthN);
630
float h = (SCREEN_YSIZE * textureList[0].heightN);
631
632
retroVertexList[0] = -SCREEN_CENTERX_F;
633
retroVertexList[1] = SCREEN_CENTERY_F;
634
retroVertexList[2] = 160.0;
635
retroVertexList[6] = 0.0;
636
retroVertexList[7] = 0.0;
637
638
retroVertexList[9] = SCREEN_CENTERX_F;
639
retroVertexList[10] = SCREEN_CENTERY_F;
640
retroVertexList[11] = 160.0;
641
retroVertexList[15] = w;
642
retroVertexList[16] = 0.0;
643
644
retroVertexList[18] = -SCREEN_CENTERX_F;
645
retroVertexList[19] = -SCREEN_CENTERY_F;
646
retroVertexList[20] = 160.0;
647
retroVertexList[24] = 0.0;
648
retroVertexList[25] = h;
649
650
retroVertexList[27] = SCREEN_CENTERX_F;
651
retroVertexList[28] = -SCREEN_CENTERY_F;
652
retroVertexList[29] = 160.0;
653
retroVertexList[33] = w;
654
retroVertexList[34] = h;
655
656
screenBufferVertexList[0] = -1.0;
657
screenBufferVertexList[1] = 1.0;
658
screenBufferVertexList[2] = 1.0;
659
screenBufferVertexList[6] = 0.0;
660
screenBufferVertexList[7] = h;
661
662
screenBufferVertexList[9] = 1.0;
663
screenBufferVertexList[10] = 1.0;
664
screenBufferVertexList[11] = 1.0;
665
screenBufferVertexList[15] = w2;
666
screenBufferVertexList[16] = h;
667
668
screenBufferVertexList[18] = -1.0;
669
screenBufferVertexList[19] = -1.0;
670
screenBufferVertexList[20] = 1.0;
671
screenBufferVertexList[24] = 0.0;
672
screenBufferVertexList[25] = 0.0;
673
674
screenBufferVertexList[27] = 1.0;
675
screenBufferVertexList[28] = -1.0;
676
screenBufferVertexList[29] = 1.0;
677
screenBufferVertexList[33] = w2;
678
screenBufferVertexList[34] = 0.0;
679
}
680
681
void SetScreenSize(int width, int lineSize)
682
{
683
SCREEN_XSIZE = width;
684
SCREEN_CENTERX = width / 2;
685
SCREEN_SCROLL_LEFT = SCREEN_CENTERX - 8;
686
SCREEN_SCROLL_RIGHT = SCREEN_CENTERX + 8;
687
OBJECT_BORDER_X2 = width + 0x80;
688
OBJECT_BORDER_X4 = width + 0x20;
689
690
GFX_LINESIZE = lineSize;
691
GFX_LINESIZE_MINUSONE = lineSize - 1;
692
GFX_LINESIZE_DOUBLE = 2 * lineSize;
693
GFX_FRAMEBUFFERSIZE = SCREEN_YSIZE * lineSize;
694
GFX_FBUFFERMINUSONE = SCREEN_YSIZE * lineSize - 1;
695
}
696
697
#if RETRO_SOFTWARE_RENDER
698
void CopyFrameOverlay2x()
699
{
700
ushort *frameBuffer = &Engine.frameBuffer[((SCREEN_YSIZE / 2) + 12) * GFX_LINESIZE];
701
ushort *frameBuffer2x = Engine.frameBuffer2x;
702
703
for (int y = 0; y < (SCREEN_YSIZE / 2) - 12; ++y) {
704
for (int x = 0; x < GFX_LINESIZE; ++x) {
705
if (*frameBuffer == 0xF81F) { // magenta
706
frameBuffer2x += 2;
707
}
708
else {
709
*frameBuffer2x = *frameBuffer;
710
frameBuffer2x++;
711
*frameBuffer2x = *frameBuffer;
712
frameBuffer2x++;
713
}
714
++frameBuffer;
715
}
716
717
frameBuffer -= GFX_LINESIZE;
718
for (int x = 0; x < GFX_LINESIZE; ++x) {
719
if (*frameBuffer == 0xF81F) { // magenta
720
frameBuffer2x += 2;
721
}
722
else {
723
*frameBuffer2x = *frameBuffer;
724
frameBuffer2x++;
725
*frameBuffer2x = *frameBuffer;
726
frameBuffer2x++;
727
}
728
++frameBuffer;
729
}
730
}
731
}
732
#endif
733
734
void SetupViewport()
735
{
736
double aspect = displaySettings.width / (double)displaySettings.height;
737
SCREEN_XSIZE_F = SCREEN_YSIZE * aspect;
738
SCREEN_CENTERX_F = aspect * SCREEN_CENTERY;
739
740
#if RETRO_USING_OPENGL
741
glScalef(320.0f / (SCREEN_YSIZE * aspect), 1.0, 1.0);
742
#endif
743
744
SetPerspectiveMatrix(90.0, 0.75, 1.0, 5000.0);
745
746
#if RETRO_USING_OPENGL
747
glViewport(displaySettings.offsetX, 0, displaySettings.width, displaySettings.height);
748
#endif
749
int displayWidth = aspect * SCREEN_YSIZE;
750
#if !RETRO_USE_ORIGINAL_CODE
751
SetScreenSize(displayWidth, (displayWidth + 9) & -0x8);
752
#else
753
SetScreenSize(displayWidth, (displayWidth + 9) & -0x10);
754
#endif
755
756
Engine.useHighResAssets = displaySettings.height > (SCREEN_YSIZE * 2);
757
758
#if RETRO_USING_OPENGL
759
glMatrixMode(GL_MODELVIEW);
760
glLoadIdentity();
761
#endif
762
763
int width2 = 0;
764
int wBuf = GFX_LINESIZE - 1;
765
while (wBuf > 0) {
766
width2++;
767
wBuf >>= 1;
768
}
769
int height2 = 0;
770
int hBuf = SCREEN_YSIZE - 1;
771
while (hBuf > 0) {
772
height2++;
773
hBuf >>= 1;
774
}
775
int texWidth = 1 << width2;
776
int texHeight = 1 << height2;
777
778
float w = (SCREEN_XSIZE * textureList[0].widthN);
779
float w2 = (GFX_LINESIZE * textureList[0].widthN);
780
float h = (SCREEN_YSIZE * textureList[0].heightN);
781
782
retroVertexList[0] = -SCREEN_CENTERX_F;
783
retroVertexList[1] = SCREEN_CENTERY_F;
784
retroVertexList[2] = 160.0;
785
retroVertexList[6] = 0.0;
786
retroVertexList[7] = 0.0;
787
788
retroVertexList[9] = SCREEN_CENTERX_F;
789
retroVertexList[10] = SCREEN_CENTERY_F;
790
retroVertexList[11] = 160.0;
791
retroVertexList[15] = w;
792
retroVertexList[16] = 0.0;
793
794
retroVertexList[18] = -SCREEN_CENTERX_F;
795
retroVertexList[19] = -SCREEN_CENTERY_F;
796
retroVertexList[20] = 160.0;
797
retroVertexList[24] = 0.0;
798
retroVertexList[25] = h;
799
800
retroVertexList[27] = SCREEN_CENTERX_F;
801
retroVertexList[28] = -SCREEN_CENTERY_F;
802
retroVertexList[29] = 160.0;
803
retroVertexList[33] = w;
804
retroVertexList[34] = h;
805
806
screenBufferVertexList[0] = -1.0;
807
screenBufferVertexList[1] = 1.0;
808
screenBufferVertexList[2] = 1.0;
809
screenBufferVertexList[6] = 0.0;
810
screenBufferVertexList[7] = h;
811
812
screenBufferVertexList[9] = 1.0;
813
screenBufferVertexList[10] = 1.0;
814
screenBufferVertexList[11] = 1.0;
815
screenBufferVertexList[15] = w2;
816
screenBufferVertexList[16] = h;
817
818
screenBufferVertexList[18] = -1.0;
819
screenBufferVertexList[19] = -1.0;
820
screenBufferVertexList[20] = 1.0;
821
screenBufferVertexList[24] = 0.0;
822
screenBufferVertexList[25] = 0.0;
823
824
screenBufferVertexList[27] = 1.0;
825
screenBufferVertexList[28] = -1.0;
826
screenBufferVertexList[29] = 1.0;
827
screenBufferVertexList[33] = w2;
828
screenBufferVertexList[34] = 0.0;
829
830
StrCopy(textureList[0].fileName, "RetroBuffer");
831
textureList[0].width = texWidth;
832
textureList[0].height = texHeight;
833
textureList[0].format = TEXFMT_RETROBUFFER;
834
textureList[0].widthN = 1.0f / texWidth;
835
textureList[0].heightN = 1.0f / texHeight;
836
837
if (Engine.useHighResAssets) {
838
#if RETRO_USING_OPENGL
839
if (framebufferHiRes != -1)
840
glDeleteFramebuffers(1, &framebufferHiRes);
841
if (renderbufferHiRes != -1)
842
glDeleteTextures(1, &renderbufferHiRes);
843
framebufferHiRes = -1;
844
renderbufferHiRes = -1;
845
846
glGenFramebuffers(1, &framebufferHiRes);
847
glBindFramebuffer(GL_FRAMEBUFFER, framebufferHiRes);
848
glGenTextures(1, &renderbufferHiRes);
849
glBindTexture(GL_TEXTURE_2D, renderbufferHiRes);
850
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Engine.scalingMode ? GL_LINEAR : GL_NEAREST);
851
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Engine.scalingMode ? GL_LINEAR : GL_NEAREST);
852
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
853
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
854
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth << 1, texHeight << 1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
855
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderbufferHiRes, 0);
856
glBindFramebuffer(GL_FRAMEBUFFER, 0);
857
glBindTexture(GL_TEXTURE_2D, 0);
858
#endif
859
860
float w = (((((GFX_LINESIZE >> 16) * 65536.0) + GFX_LINESIZE) + 0.5) * textureList[0].widthN) - 0.001;
861
float h = (SCREEN_YSIZE * textureList[0].heightN) - 0.001;
862
screenBufferVertexList[0] = -1.0;
863
screenBufferVertexList[1] = 1.0;
864
screenBufferVertexList[2] = 1.0;
865
screenBufferVertexList[6] = 0.0;
866
screenBufferVertexList[9] = 1.0;
867
screenBufferVertexList[10] = 1.0;
868
screenBufferVertexList[11] = 1.0;
869
screenBufferVertexList[7] = h;
870
screenBufferVertexList[16] = h;
871
screenBufferVertexList[18] = -1.0;
872
screenBufferVertexList[19] = -1.0;
873
screenBufferVertexList[20] = 1.0;
874
screenBufferVertexList[24] = 0.0;
875
screenBufferVertexList[25] = 0.0;
876
screenBufferVertexList[27] = 1.0;
877
screenBufferVertexList[28] = -1.0;
878
screenBufferVertexList[29] = 1.0;
879
screenBufferVertexList[15] = w;
880
screenBufferVertexList[34] = 0.0;
881
screenBufferVertexList[33] = w;
882
}
883
else {
884
#if RETRO_USING_OPENGL
885
if (framebufferHiRes != -1)
886
glDeleteFramebuffers(1, &framebufferHiRes);
887
if (renderbufferHiRes != -1)
888
glDeleteTextures(1, &renderbufferHiRes);
889
glBindFramebuffer(GL_FRAMEBUFFER, 0);
890
891
framebufferHiRes = -1;
892
renderbufferHiRes = -1;
893
#endif
894
}
895
896
bool transfer = false;
897
#if RETRO_USING_OPENGL
898
if (textureList[0].id != -1) {
899
glDeleteTextures(1, &textureList[0].id);
900
transfer = true;
901
}
902
glGenTextures(1, &textureList[0].id);
903
glBindTexture(GL_TEXTURE_2D, textureList[0].id);
904
#endif
905
906
convertTo32Bit = true;
907
#if RETRO_USING_OPENGL
908
if (displaySettings.height > 720) {
909
convertTo32Bit = true;
910
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
911
}
912
else if (convertTo32Bit)
913
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
914
else
915
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 0);
916
917
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Engine.scalingMode ? GL_LINEAR : GL_NEAREST);
918
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Engine.scalingMode ? GL_LINEAR : GL_NEAREST);
919
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
920
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
921
glBindTexture(GL_TEXTURE_2D, 0);
922
#endif
923
924
mixFiltersOnJekyll = Engine.useHighResAssets;
925
926
if (transfer && Engine.frameBuffer)
927
TransferRetroBuffer();
928
}
929
930
void SetFullScreen(bool fs)
931
{
932
if (fs) {
933
#if RETRO_USING_SDL1
934
Engine.windowSurface =
935
SDL_SetVideoMode(SCREEN_XSIZE * Engine.windowScale, SCREEN_YSIZE * Engine.windowScale, 16, SDL_SWSURFACE | SDL_FULLSCREEN);
936
SDL_ShowCursor(SDL_FALSE);
937
#elif RETRO_USING_SDL2
938
SDL_RestoreWindow(Engine.window);
939
SDL_SetWindowFullscreen(Engine.window, SDL_WINDOW_FULLSCREEN_DESKTOP);
940
SDL_ShowCursor(SDL_FALSE);
941
942
#if RETRO_USING_OPENGL
943
SDL_DisplayMode mode;
944
SDL_GetDesktopDisplayMode(0, &mode);
945
946
int w = mode.w;
947
int h = mode.h;
948
if (mode.h > mode.w) {
949
w = mode.h;
950
h = mode.w;
951
}
952
953
#if RETRO_PLATFORM != RETRO_iOS && RETRO_PLATFORM != RETRO_ANDROID
954
float aspect = SCREEN_XSIZE_CONFIG / (float)SCREEN_YSIZE;
955
displaySettings.height = h;
956
displaySettings.width = aspect * displaySettings.height;
957
displaySettings.offsetX = abs(w - displaySettings.width) / 2;
958
if (displaySettings.width > w) {
959
displaySettings.offsetX = 0;
960
displaySettings.width = w;
961
}
962
963
SetupViewport();
964
#else
965
displaySettings.height = h;
966
displaySettings.width = w;
967
glViewport(0, 0, displaySettings.width, displaySettings.height);
968
#endif
969
#endif
970
#endif
971
}
972
else {
973
#if RETRO_USING_SDL1
974
Engine.windowSurface = SDL_SetVideoMode(SCREEN_XSIZE * Engine.windowScale, SCREEN_YSIZE * Engine.windowScale, 16, SDL_SWSURFACE);
975
SDL_ShowCursor(SDL_TRUE);
976
#elif RETRO_USING_SDL2
977
SDL_SetWindowFullscreen(Engine.window, false);
978
SDL_ShowCursor(SDL_TRUE);
979
SDL_SetWindowSize(Engine.window, SCREEN_XSIZE_CONFIG * Engine.windowScale, SCREEN_YSIZE * Engine.windowScale);
980
SDL_SetWindowPosition(Engine.window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
981
SDL_RestoreWindow(Engine.window);
982
983
displaySettings.width = SCREEN_XSIZE_CONFIG * Engine.windowScale;
984
displaySettings.height = SCREEN_YSIZE * Engine.windowScale;
985
displaySettings.offsetX = 0;
986
SetupViewport();
987
#endif
988
}
989
Engine.isFullScreen = fs;
990
}
991
992
void DrawObjectList(int Layer)
993
{
994
int size = drawListEntries[Layer].listSize;
995
for (int i = 0; i < size; ++i) {
996
objectEntityPos = drawListEntries[Layer].entityRefs[i];
997
int type = objectEntityList[objectEntityPos].type;
998
if (type) {
999
if (scriptCode[objectScriptList[type].eventDraw.scriptCodePtr] > 0)
1000
ProcessScript(objectScriptList[type].eventDraw.scriptCodePtr, objectScriptList[type].eventDraw.jumpTablePtr, EVENT_DRAW);
1001
}
1002
}
1003
}
1004
void DrawStageGFX()
1005
{
1006
waterDrawPos = waterLevel - yScrollOffset;
1007
1008
#if RETRO_SOFTWARE_RENDER
1009
if (waterDrawPos < 0)
1010
waterDrawPos = 0;
1011
1012
if (waterDrawPos > SCREEN_YSIZE)
1013
waterDrawPos = SCREEN_YSIZE;
1014
#endif
1015
1016
if (tLayerMidPoint < 3) {
1017
DrawObjectList(0);
1018
1019
if (activeTileLayers[0] < LAYER_COUNT) {
1020
switch (stageLayouts[activeTileLayers[0]].type) {
1021
case LAYER_HSCROLL: DrawHLineScrollLayer(0); break;
1022
1023
case LAYER_VSCROLL: DrawVLineScrollLayer(0); break;
1024
1025
case LAYER_3DFLOOR:
1026
#if RETRO_SOFTWARE_RENDER
1027
drawStageGFXHQ = false;
1028
#endif
1029
Draw3DFloorLayer(0);
1030
break;
1031
1032
case LAYER_3DSKY:
1033
#if RETRO_SOFTWARE_RENDER
1034
#if !RETRO_USE_ORIGINAL_CODE
1035
if (Engine.useHQModes)
1036
#endif
1037
drawStageGFXHQ = true;
1038
1039
Draw3DSkyLayer(0);
1040
#endif
1041
break;
1042
1043
default: break;
1044
}
1045
}
1046
1047
DrawObjectList(1);
1048
1049
if (activeTileLayers[1] < LAYER_COUNT) {
1050
switch (stageLayouts[activeTileLayers[1]].type) {
1051
case LAYER_HSCROLL: DrawHLineScrollLayer(1); break;
1052
1053
case LAYER_VSCROLL: DrawVLineScrollLayer(1); break;
1054
1055
case LAYER_3DFLOOR:
1056
#if RETRO_SOFTWARE_RENDER
1057
drawStageGFXHQ = false;
1058
#endif
1059
Draw3DFloorLayer(1);
1060
break;
1061
1062
case LAYER_3DSKY:
1063
#if RETRO_SOFTWARE_RENDER
1064
#if !RETRO_USE_ORIGINAL_CODE
1065
if (Engine.useHQModes)
1066
#endif
1067
drawStageGFXHQ = true;
1068
1069
Draw3DSkyLayer(1);
1070
#endif
1071
break;
1072
1073
default: break;
1074
}
1075
}
1076
1077
DrawObjectList(2);
1078
DrawObjectList(3);
1079
DrawObjectList(4);
1080
1081
if (activeTileLayers[2] < LAYER_COUNT) {
1082
switch (stageLayouts[activeTileLayers[2]].type) {
1083
case LAYER_HSCROLL: DrawHLineScrollLayer(2); break;
1084
1085
case LAYER_VSCROLL: DrawVLineScrollLayer(2); break;
1086
1087
case LAYER_3DFLOOR:
1088
#if RETRO_SOFTWARE_RENDER
1089
drawStageGFXHQ = false;
1090
#endif
1091
Draw3DFloorLayer(2);
1092
break;
1093
1094
case LAYER_3DSKY:
1095
#if RETRO_SOFTWARE_RENDER
1096
#if !RETRO_USE_ORIGINAL_CODE
1097
if (Engine.useHQModes)
1098
#endif
1099
drawStageGFXHQ = true;
1100
1101
Draw3DSkyLayer(2);
1102
#endif
1103
break;
1104
1105
default: break;
1106
}
1107
}
1108
}
1109
else if (tLayerMidPoint < 6) {
1110
DrawObjectList(0);
1111
1112
if (activeTileLayers[0] < LAYER_COUNT) {
1113
switch (stageLayouts[activeTileLayers[0]].type) {
1114
case LAYER_HSCROLL: DrawHLineScrollLayer(0); break;
1115
1116
case LAYER_VSCROLL: DrawVLineScrollLayer(0); break;
1117
1118
case LAYER_3DFLOOR:
1119
#if RETRO_SOFTWARE_RENDER
1120
drawStageGFXHQ = false;
1121
#endif
1122
Draw3DFloorLayer(0);
1123
break;
1124
1125
case LAYER_3DSKY:
1126
#if RETRO_SOFTWARE_RENDER
1127
#if !RETRO_USE_ORIGINAL_CODE
1128
if (Engine.useHQModes)
1129
#endif
1130
drawStageGFXHQ = true;
1131
1132
Draw3DSkyLayer(0);
1133
#endif
1134
break;
1135
1136
default: break;
1137
}
1138
}
1139
1140
DrawObjectList(1);
1141
1142
if (activeTileLayers[1] < LAYER_COUNT) {
1143
switch (stageLayouts[activeTileLayers[1]].type) {
1144
case LAYER_HSCROLL: DrawHLineScrollLayer(1); break;
1145
1146
case LAYER_VSCROLL: DrawVLineScrollLayer(1); break;
1147
1148
case LAYER_3DFLOOR:
1149
#if RETRO_SOFTWARE_RENDER
1150
drawStageGFXHQ = false;
1151
#endif
1152
Draw3DFloorLayer(1);
1153
break;
1154
1155
case LAYER_3DSKY:
1156
#if RETRO_SOFTWARE_RENDER
1157
#if !RETRO_USE_ORIGINAL_CODE
1158
if (Engine.useHQModes)
1159
#endif
1160
drawStageGFXHQ = true;
1161
1162
Draw3DSkyLayer(1);
1163
#endif
1164
break;
1165
1166
default: break;
1167
}
1168
}
1169
1170
DrawObjectList(2);
1171
1172
if (activeTileLayers[2] < LAYER_COUNT) {
1173
switch (stageLayouts[activeTileLayers[2]].type) {
1174
case LAYER_HSCROLL: DrawHLineScrollLayer(2); break;
1175
case LAYER_VSCROLL: DrawVLineScrollLayer(2); break;
1176
case LAYER_3DFLOOR:
1177
#if RETRO_SOFTWARE_RENDER
1178
drawStageGFXHQ = false;
1179
#endif
1180
Draw3DFloorLayer(2);
1181
break;
1182
case LAYER_3DSKY:
1183
#if RETRO_SOFTWARE_RENDER
1184
#if !RETRO_USE_ORIGINAL_CODE
1185
if (Engine.useHQModes)
1186
#endif
1187
drawStageGFXHQ = true;
1188
1189
Draw3DSkyLayer(2);
1190
#endif
1191
break;
1192
default: break;
1193
}
1194
}
1195
1196
DrawObjectList(3);
1197
DrawObjectList(4);
1198
}
1199
1200
if (tLayerMidPoint < 6) {
1201
if (activeTileLayers[3] < LAYER_COUNT) {
1202
switch (stageLayouts[activeTileLayers[3]].type) {
1203
case LAYER_HSCROLL: DrawHLineScrollLayer(3); break;
1204
1205
case LAYER_VSCROLL: DrawVLineScrollLayer(3); break;
1206
1207
case LAYER_3DFLOOR:
1208
#if RETRO_SOFTWARE_RENDER
1209
drawStageGFXHQ = false;
1210
#endif
1211
Draw3DFloorLayer(3);
1212
break;
1213
1214
case LAYER_3DSKY:
1215
#if RETRO_SOFTWARE_RENDER
1216
#if !RETRO_USE_ORIGINAL_CODE
1217
if (Engine.useHQModes)
1218
#endif
1219
drawStageGFXHQ = true;
1220
1221
Draw3DSkyLayer(3);
1222
#endif
1223
break;
1224
default: break;
1225
}
1226
}
1227
1228
DrawObjectList(5);
1229
#if RETRO_REV03
1230
#if !RETRO_USE_ORIGINAL_CODE
1231
// Hacky fix for Tails Object not working properly in special stages on non-Origins bytecode
1232
if (forceUseScripts || Engine.usingOrigins)
1233
#endif
1234
DrawObjectList(7);
1235
#endif
1236
DrawObjectList(6);
1237
}
1238
1239
#if !RETRO_USE_ORIGINAL_CODE
1240
if (drawStageGFXHQ)
1241
DrawDebugOverlays();
1242
#endif
1243
1244
#if RETRO_SOFTWARE_RENDER
1245
if (drawStageGFXHQ) {
1246
CopyFrameOverlay2x();
1247
1248
if (fadeMode > 0) {
1249
DrawRectangle(0, 0, SCREEN_XSIZE, SCREEN_YSIZE, fadeR, fadeG, fadeB, fadeA);
1250
SetFadeHQ(fadeR, fadeG, fadeB, fadeA);
1251
}
1252
}
1253
else {
1254
if (fadeMode > 0) {
1255
DrawRectangle(0, 0, SCREEN_XSIZE, SCREEN_YSIZE, fadeR, fadeG, fadeB, fadeA);
1256
}
1257
}
1258
#endif
1259
1260
#if !RETRO_USE_ORIGINAL_CODE
1261
if (!drawStageGFXHQ)
1262
DrawDebugOverlays();
1263
#endif
1264
}
1265
1266
#if !RETRO_USE_ORIGINAL_CODE
1267
void DrawDebugOverlays()
1268
{
1269
if (showHitboxes) {
1270
for (int i = 0; i < debugHitboxCount; ++i) {
1271
DebugHitboxInfo *info = &debugHitboxList[i];
1272
int x = info->xpos + (info->left << 16);
1273
int y = info->ypos + (info->top << 16);
1274
int w = abs((info->xpos + (info->right << 16)) - x) >> 16;
1275
int h = abs((info->ypos + (info->bottom << 16)) - y) >> 16;
1276
x = (x >> 16) - xScrollOffset;
1277
y = (y >> 16) - yScrollOffset;
1278
1279
switch (info->type) {
1280
case H_TYPE_TOUCH:
1281
if (showHitboxes & 1)
1282
DrawRectangle(x, y, w, h, info->collision ? 0x80 : 0xFF, info->collision ? 0x80 : 0x00, 0x00, 0x60);
1283
break;
1284
1285
case H_TYPE_BOX:
1286
if (showHitboxes & 1) {
1287
DrawRectangle(x, y, w, h, 0x00, 0x00, 0xFF, 0x60);
1288
if (info->collision & 1) // top
1289
DrawRectangle(x, y, w, 1, 0xFF, 0xFF, 0x00, 0xC0);
1290
if (info->collision & 8) // bottom
1291
DrawRectangle(x, y + h, w, 1, 0xFF, 0xFF, 0x00, 0xC0);
1292
if (info->collision & 2) { // left
1293
int sy = y;
1294
int sh = h;
1295
if (info->collision & 1) {
1296
sy++;
1297
sh--;
1298
}
1299
if (info->collision & 8)
1300
sh--;
1301
DrawRectangle(x, sy, 1, sh, 0xFF, 0xFF, 0x00, 0xC0);
1302
}
1303
if (info->collision & 4) { // right
1304
int sy = y;
1305
int sh = h;
1306
if (info->collision & 1) {
1307
sy++;
1308
sh--;
1309
}
1310
if (info->collision & 8)
1311
sh--;
1312
DrawRectangle(x + w, sy, 1, sh, 0xFF, 0xFF, 0x00, 0xC0);
1313
}
1314
}
1315
break;
1316
1317
case H_TYPE_PLAT:
1318
if (showHitboxes & 1) {
1319
DrawRectangle(x, y, w, h, 0x00, 0xFF, 0x00, 0x60);
1320
if (info->collision & 1) // top
1321
DrawRectangle(x, y, w, 1, 0xFF, 0xFF, 0x00, 0xC0);
1322
if (info->collision & 8) // bottom
1323
DrawRectangle(x, y + h, w, 1, 0xFF, 0xFF, 0x00, 0xC0);
1324
}
1325
break;
1326
1327
case H_TYPE_FINGER:
1328
if (showHitboxes & 2)
1329
DrawRectangle(x + xScrollOffset, y + yScrollOffset, w, h, 0xF0, 0x00, 0xF0, 0x60);
1330
break;
1331
}
1332
}
1333
}
1334
1335
if (Engine.showPaletteOverlay) {
1336
for (int p = 0; p < PALETTE_COUNT; ++p) {
1337
int x = (SCREEN_XSIZE - (0x10 << 3));
1338
int y = (SCREEN_YSIZE - (0x10 << 2));
1339
for (int c = 0; c < PALETTE_COLOR_COUNT; ++c) {
1340
int g = fullPalette32[p][c].g;
1341
// HQ mode overrides any magenta px, so slightly change the g channel since it has the most bits to make it "not quite magenta"
1342
if (drawStageGFXHQ && fullPalette32[p][c].r == 0xFF && fullPalette32[p][c].g == 0x00 && fullPalette32[p][c].b == 0xFF)
1343
g += 8;
1344
1345
DrawRectangle(x + ((c & 0xF) << 1) + ((p % (PALETTE_COUNT / 2)) * (2 * 16)),
1346
y + ((c >> 4) << 1) + ((p / (PALETTE_COUNT / 2)) * (2 * 16)), 2, 2, fullPalette32[p][c].r, g, fullPalette32[p][c].b,
1347
0xFF);
1348
}
1349
}
1350
}
1351
}
1352
#endif
1353
1354
void DrawHLineScrollLayer(int layerID)
1355
{
1356
TileLayer *layer = &stageLayouts[activeTileLayers[layerID]];
1357
if (!layer->xsize || !layer->ysize)
1358
return;
1359
1360
#if RETRO_SOFTWARE_RENDER
1361
int screenwidth16 = (GFX_LINESIZE >> 4) - 1;
1362
int layerwidth = layer->xsize;
1363
int layerheight = layer->ysize;
1364
bool aboveMidPoint = layerID >= tLayerMidPoint;
1365
1366
byte *lineScroll;
1367
int *deformationData;
1368
int *deformationDataW;
1369
1370
int yscrollOffset = 0;
1371
if (activeTileLayers[layerID]) { // BG Layer
1372
int yScroll = yScrollOffset * layer->parallaxFactor >> 8;
1373
int fullheight = layerheight << 7;
1374
layer->scrollPos += layer->scrollSpeed;
1375
if (layer->scrollPos > fullheight << 16)
1376
layer->scrollPos -= fullheight << 16;
1377
yscrollOffset = (yScroll + (layer->scrollPos >> 16)) % fullheight;
1378
layerheight = fullheight >> 7;
1379
lineScroll = layer->lineScroll;
1380
deformationData = &bgDeformationData2[(byte)(yscrollOffset + layer->deformationOffset)];
1381
deformationDataW = &bgDeformationData3[(byte)(yscrollOffset + waterDrawPos + layer->deformationOffsetW)];
1382
}
1383
else { // FG Layer
1384
lastXSize = layer->xsize;
1385
yscrollOffset = yScrollOffset;
1386
lineScroll = layer->lineScroll;
1387
for (int i = 0; i < PARALLAX_COUNT; ++i) hParallax.linePos[i] = xScrollOffset;
1388
deformationData = &bgDeformationData0[(byte)(yscrollOffset + layer->deformationOffset)];
1389
deformationDataW = &bgDeformationData1[(byte)(yscrollOffset + waterDrawPos + layer->deformationOffsetW)];
1390
}
1391
1392
if (layer->type == LAYER_HSCROLL) {
1393
if (lastXSize != layerwidth) {
1394
int fullLayerwidth = layerwidth << 7;
1395
for (int i = 0; i < hParallax.entryCount; ++i) {
1396
hParallax.linePos[i] = xScrollOffset * hParallax.parallaxFactor[i] >> 8;
1397
if (hParallax.scrollPos[i] > fullLayerwidth << 16)
1398
hParallax.scrollPos[i] -= fullLayerwidth << 16;
1399
if (hParallax.scrollPos[i] < 0)
1400
hParallax.scrollPos[i] += fullLayerwidth << 16;
1401
hParallax.linePos[i] += hParallax.scrollPos[i] >> 16;
1402
hParallax.linePos[i] %= fullLayerwidth;
1403
}
1404
}
1405
int w = -1;
1406
if (activeTileLayers[layerID])
1407
w = layerwidth;
1408
lastXSize = w;
1409
}
1410
1411
ushort *frameBufferPtr = Engine.frameBuffer;
1412
byte *lineBuffer = gfxLineBuffer;
1413
int tileYPos = yscrollOffset % (layerheight << 7);
1414
if (tileYPos < 0)
1415
tileYPos += layerheight << 7;
1416
byte *scrollIndex = &lineScroll[tileYPos];
1417
int tileY16 = tileYPos & 0xF;
1418
int chunkY = tileYPos >> 7;
1419
int tileY = (tileYPos & 0x7F) >> 4;
1420
1421
// Draw Above Water (if applicable)
1422
int drawableLines[2] = { waterDrawPos, SCREEN_YSIZE - waterDrawPos };
1423
for (int i = 0; i < 2; ++i) {
1424
while (drawableLines[i]--) {
1425
activePalette = fullPalette[*lineBuffer];
1426
activePalette32 = fullPalette32[*lineBuffer];
1427
lineBuffer++;
1428
int chunkX = hParallax.linePos[*scrollIndex];
1429
if (i == 0) {
1430
if (hParallax.deform[*scrollIndex])
1431
chunkX += *deformationData;
1432
++deformationData;
1433
}
1434
else {
1435
if (hParallax.deform[*scrollIndex])
1436
chunkX += *deformationDataW;
1437
++deformationDataW;
1438
}
1439
++scrollIndex;
1440
1441
int fullLayerwidth = layerwidth << 7;
1442
if (chunkX < 0)
1443
chunkX += fullLayerwidth;
1444
if (chunkX >= fullLayerwidth)
1445
chunkX -= fullLayerwidth;
1446
1447
int chunkXPos = chunkX >> 7;
1448
int tilePxXPos = chunkX & 0xF;
1449
int tileXPxRemain = TILE_SIZE - tilePxXPos;
1450
int chunk = (layer->tiles[(chunkX >> 7) + (chunkY << 8)] << 6) + ((chunkX & 0x7F) >> 4) + 8 * tileY;
1451
int tileOffsetY = TILE_SIZE * tileY16;
1452
int tileOffsetYFlipX = TILE_SIZE * tileY16 + 0xF;
1453
int tileOffsetYFlipY = TILE_SIZE * (0xF - tileY16);
1454
int tileOffsetYFlipXY = TILE_SIZE * (0xF - tileY16) + 0xF;
1455
int lineRemain = GFX_LINESIZE;
1456
1457
byte *gfxDataPtr = NULL;
1458
int tilePxLineCnt = tileXPxRemain;
1459
1460
// Draw the first tile to the left
1461
if (tiles128x128.visualPlane[chunk] == (byte)aboveMidPoint) {
1462
lineRemain -= tilePxLineCnt;
1463
switch (tiles128x128.direction[chunk]) {
1464
case FLIP_NONE:
1465
gfxDataPtr = &tilesetGFXData[tileOffsetY + tiles128x128.gfxDataPos[chunk] + tilePxXPos];
1466
while (tilePxLineCnt--) {
1467
if (*gfxDataPtr > 0)
1468
*frameBufferPtr = activePalette[*gfxDataPtr];
1469
++frameBufferPtr;
1470
++gfxDataPtr;
1471
}
1472
break;
1473
case FLIP_X:
1474
1475
gfxDataPtr = &tilesetGFXData[tileOffsetYFlipX + tiles128x128.gfxDataPos[chunk] - tilePxXPos];
1476
while (tilePxLineCnt--) {
1477
if (*gfxDataPtr > 0)
1478
*frameBufferPtr = activePalette[*gfxDataPtr];
1479
++frameBufferPtr;
1480
--gfxDataPtr;
1481
}
1482
break;
1483
1484
case FLIP_Y:
1485
gfxDataPtr = &tilesetGFXData[tileOffsetYFlipY + tiles128x128.gfxDataPos[chunk] + tilePxXPos];
1486
while (tilePxLineCnt--) {
1487
if (*gfxDataPtr > 0)
1488
*frameBufferPtr = activePalette[*gfxDataPtr];
1489
++frameBufferPtr;
1490
++gfxDataPtr;
1491
}
1492
break;
1493
1494
case FLIP_XY:
1495
gfxDataPtr = &tilesetGFXData[tileOffsetYFlipXY + tiles128x128.gfxDataPos[chunk] - tilePxXPos];
1496
while (tilePxLineCnt--) {
1497
if (*gfxDataPtr > 0)
1498
*frameBufferPtr = activePalette[*gfxDataPtr];
1499
++frameBufferPtr;
1500
--gfxDataPtr;
1501
}
1502
break;
1503
default: break;
1504
}
1505
}
1506
else {
1507
frameBufferPtr += tilePxLineCnt;
1508
lineRemain -= tilePxLineCnt;
1509
}
1510
1511
// Draw the bulk of the tiles
1512
int chunkTileX = ((chunkX & 0x7F) >> 4) + 1;
1513
int tilesPerLine = screenwidth16;
1514
while (tilesPerLine--) {
1515
if (chunkTileX < 8) {
1516
++chunk;
1517
}
1518
else {
1519
if (++chunkXPos == layerwidth)
1520
chunkXPos = 0;
1521
1522
chunkTileX = 0;
1523
chunk = (layer->tiles[chunkXPos + (chunkY << 8)] << 6) + 8 * tileY;
1524
}
1525
lineRemain -= TILE_SIZE;
1526
1527
// Loop Unrolling (faster but messier code)
1528
if (tiles128x128.visualPlane[chunk] == (byte)aboveMidPoint) {
1529
switch (tiles128x128.direction[chunk]) {
1530
case FLIP_NONE:
1531
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetY];
1532
if (*gfxDataPtr > 0)
1533
*frameBufferPtr = activePalette[*gfxDataPtr];
1534
++frameBufferPtr;
1535
++gfxDataPtr;
1536
1537
if (*gfxDataPtr > 0)
1538
*frameBufferPtr = activePalette[*gfxDataPtr];
1539
++frameBufferPtr;
1540
++gfxDataPtr;
1541
1542
if (*gfxDataPtr > 0)
1543
*frameBufferPtr = activePalette[*gfxDataPtr];
1544
++frameBufferPtr;
1545
++gfxDataPtr;
1546
1547
if (*gfxDataPtr > 0)
1548
*frameBufferPtr = activePalette[*gfxDataPtr];
1549
++frameBufferPtr;
1550
++gfxDataPtr;
1551
1552
if (*gfxDataPtr > 0)
1553
*frameBufferPtr = activePalette[*gfxDataPtr];
1554
++frameBufferPtr;
1555
++gfxDataPtr;
1556
1557
if (*gfxDataPtr > 0)
1558
*frameBufferPtr = activePalette[*gfxDataPtr];
1559
++frameBufferPtr;
1560
++gfxDataPtr;
1561
1562
if (*gfxDataPtr > 0)
1563
*frameBufferPtr = activePalette[*gfxDataPtr];
1564
++frameBufferPtr;
1565
++gfxDataPtr;
1566
1567
if (*gfxDataPtr > 0)
1568
*frameBufferPtr = activePalette[*gfxDataPtr];
1569
++frameBufferPtr;
1570
++gfxDataPtr;
1571
1572
if (*gfxDataPtr > 0)
1573
*frameBufferPtr = activePalette[*gfxDataPtr];
1574
++frameBufferPtr;
1575
++gfxDataPtr;
1576
1577
if (*gfxDataPtr > 0)
1578
*frameBufferPtr = activePalette[*gfxDataPtr];
1579
++frameBufferPtr;
1580
++gfxDataPtr;
1581
1582
if (*gfxDataPtr > 0)
1583
*frameBufferPtr = activePalette[*gfxDataPtr];
1584
++frameBufferPtr;
1585
++gfxDataPtr;
1586
1587
if (*gfxDataPtr > 0)
1588
*frameBufferPtr = activePalette[*gfxDataPtr];
1589
++frameBufferPtr;
1590
++gfxDataPtr;
1591
1592
if (*gfxDataPtr > 0)
1593
*frameBufferPtr = activePalette[*gfxDataPtr];
1594
++frameBufferPtr;
1595
++gfxDataPtr;
1596
1597
if (*gfxDataPtr > 0)
1598
*frameBufferPtr = activePalette[*gfxDataPtr];
1599
++frameBufferPtr;
1600
++gfxDataPtr;
1601
1602
if (*gfxDataPtr > 0)
1603
*frameBufferPtr = activePalette[*gfxDataPtr];
1604
++frameBufferPtr;
1605
++gfxDataPtr;
1606
1607
if (*gfxDataPtr > 0)
1608
*frameBufferPtr = activePalette[*gfxDataPtr];
1609
++frameBufferPtr;
1610
break;
1611
1612
case FLIP_X:
1613
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetYFlipX];
1614
if (*gfxDataPtr > 0)
1615
*frameBufferPtr = activePalette[*gfxDataPtr];
1616
++frameBufferPtr;
1617
--gfxDataPtr;
1618
1619
if (*gfxDataPtr > 0)
1620
*frameBufferPtr = activePalette[*gfxDataPtr];
1621
++frameBufferPtr;
1622
--gfxDataPtr;
1623
1624
if (*gfxDataPtr > 0)
1625
*frameBufferPtr = activePalette[*gfxDataPtr];
1626
++frameBufferPtr;
1627
--gfxDataPtr;
1628
1629
if (*gfxDataPtr > 0)
1630
*frameBufferPtr = activePalette[*gfxDataPtr];
1631
++frameBufferPtr;
1632
--gfxDataPtr;
1633
1634
if (*gfxDataPtr > 0)
1635
*frameBufferPtr = activePalette[*gfxDataPtr];
1636
++frameBufferPtr;
1637
--gfxDataPtr;
1638
1639
if (*gfxDataPtr > 0)
1640
*frameBufferPtr = activePalette[*gfxDataPtr];
1641
++frameBufferPtr;
1642
--gfxDataPtr;
1643
1644
if (*gfxDataPtr > 0)
1645
*frameBufferPtr = activePalette[*gfxDataPtr];
1646
++frameBufferPtr;
1647
--gfxDataPtr;
1648
1649
if (*gfxDataPtr > 0)
1650
*frameBufferPtr = activePalette[*gfxDataPtr];
1651
++frameBufferPtr;
1652
--gfxDataPtr;
1653
1654
if (*gfxDataPtr > 0)
1655
*frameBufferPtr = activePalette[*gfxDataPtr];
1656
++frameBufferPtr;
1657
--gfxDataPtr;
1658
1659
if (*gfxDataPtr > 0)
1660
*frameBufferPtr = activePalette[*gfxDataPtr];
1661
++frameBufferPtr;
1662
--gfxDataPtr;
1663
1664
if (*gfxDataPtr > 0)
1665
*frameBufferPtr = activePalette[*gfxDataPtr];
1666
++frameBufferPtr;
1667
--gfxDataPtr;
1668
1669
if (*gfxDataPtr > 0)
1670
*frameBufferPtr = activePalette[*gfxDataPtr];
1671
++frameBufferPtr;
1672
--gfxDataPtr;
1673
1674
if (*gfxDataPtr > 0)
1675
*frameBufferPtr = activePalette[*gfxDataPtr];
1676
++frameBufferPtr;
1677
--gfxDataPtr;
1678
1679
if (*gfxDataPtr > 0)
1680
*frameBufferPtr = activePalette[*gfxDataPtr];
1681
++frameBufferPtr;
1682
--gfxDataPtr;
1683
1684
if (*gfxDataPtr > 0)
1685
*frameBufferPtr = activePalette[*gfxDataPtr];
1686
++frameBufferPtr;
1687
--gfxDataPtr;
1688
1689
if (*gfxDataPtr > 0)
1690
*frameBufferPtr = activePalette[*gfxDataPtr];
1691
++frameBufferPtr;
1692
break;
1693
1694
case FLIP_Y:
1695
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetYFlipY];
1696
if (*gfxDataPtr > 0)
1697
*frameBufferPtr = activePalette[*gfxDataPtr];
1698
++frameBufferPtr;
1699
++gfxDataPtr;
1700
1701
if (*gfxDataPtr > 0)
1702
*frameBufferPtr = activePalette[*gfxDataPtr];
1703
++frameBufferPtr;
1704
++gfxDataPtr;
1705
1706
if (*gfxDataPtr > 0)
1707
*frameBufferPtr = activePalette[*gfxDataPtr];
1708
++frameBufferPtr;
1709
++gfxDataPtr;
1710
1711
if (*gfxDataPtr > 0)
1712
*frameBufferPtr = activePalette[*gfxDataPtr];
1713
++frameBufferPtr;
1714
++gfxDataPtr;
1715
1716
if (*gfxDataPtr > 0)
1717
*frameBufferPtr = activePalette[*gfxDataPtr];
1718
++frameBufferPtr;
1719
++gfxDataPtr;
1720
1721
if (*gfxDataPtr > 0)
1722
*frameBufferPtr = activePalette[*gfxDataPtr];
1723
++frameBufferPtr;
1724
++gfxDataPtr;
1725
1726
if (*gfxDataPtr > 0)
1727
*frameBufferPtr = activePalette[*gfxDataPtr];
1728
++frameBufferPtr;
1729
++gfxDataPtr;
1730
1731
if (*gfxDataPtr > 0)
1732
*frameBufferPtr = activePalette[*gfxDataPtr];
1733
++frameBufferPtr;
1734
++gfxDataPtr;
1735
1736
if (*gfxDataPtr > 0)
1737
*frameBufferPtr = activePalette[*gfxDataPtr];
1738
++frameBufferPtr;
1739
++gfxDataPtr;
1740
1741
if (*gfxDataPtr > 0)
1742
*frameBufferPtr = activePalette[*gfxDataPtr];
1743
++frameBufferPtr;
1744
++gfxDataPtr;
1745
1746
if (*gfxDataPtr > 0)
1747
*frameBufferPtr = activePalette[*gfxDataPtr];
1748
++frameBufferPtr;
1749
++gfxDataPtr;
1750
1751
if (*gfxDataPtr > 0)
1752
*frameBufferPtr = activePalette[*gfxDataPtr];
1753
++frameBufferPtr;
1754
++gfxDataPtr;
1755
1756
if (*gfxDataPtr > 0)
1757
*frameBufferPtr = activePalette[*gfxDataPtr];
1758
++frameBufferPtr;
1759
++gfxDataPtr;
1760
1761
if (*gfxDataPtr > 0)
1762
*frameBufferPtr = activePalette[*gfxDataPtr];
1763
++frameBufferPtr;
1764
++gfxDataPtr;
1765
1766
if (*gfxDataPtr > 0)
1767
*frameBufferPtr = activePalette[*gfxDataPtr];
1768
++frameBufferPtr;
1769
++gfxDataPtr;
1770
1771
if (*gfxDataPtr > 0)
1772
*frameBufferPtr = activePalette[*gfxDataPtr];
1773
++frameBufferPtr;
1774
break;
1775
1776
case FLIP_XY:
1777
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetYFlipXY];
1778
if (*gfxDataPtr > 0)
1779
*frameBufferPtr = activePalette[*gfxDataPtr];
1780
++frameBufferPtr;
1781
--gfxDataPtr;
1782
1783
if (*gfxDataPtr > 0)
1784
*frameBufferPtr = activePalette[*gfxDataPtr];
1785
++frameBufferPtr;
1786
--gfxDataPtr;
1787
1788
if (*gfxDataPtr > 0)
1789
*frameBufferPtr = activePalette[*gfxDataPtr];
1790
++frameBufferPtr;
1791
--gfxDataPtr;
1792
1793
if (*gfxDataPtr > 0)
1794
*frameBufferPtr = activePalette[*gfxDataPtr];
1795
++frameBufferPtr;
1796
--gfxDataPtr;
1797
1798
if (*gfxDataPtr > 0)
1799
*frameBufferPtr = activePalette[*gfxDataPtr];
1800
++frameBufferPtr;
1801
--gfxDataPtr;
1802
1803
if (*gfxDataPtr > 0)
1804
*frameBufferPtr = activePalette[*gfxDataPtr];
1805
++frameBufferPtr;
1806
--gfxDataPtr;
1807
1808
if (*gfxDataPtr > 0)
1809
*frameBufferPtr = activePalette[*gfxDataPtr];
1810
++frameBufferPtr;
1811
--gfxDataPtr;
1812
1813
if (*gfxDataPtr > 0)
1814
*frameBufferPtr = activePalette[*gfxDataPtr];
1815
++frameBufferPtr;
1816
--gfxDataPtr;
1817
1818
if (*gfxDataPtr > 0)
1819
*frameBufferPtr = activePalette[*gfxDataPtr];
1820
++frameBufferPtr;
1821
--gfxDataPtr;
1822
1823
if (*gfxDataPtr > 0)
1824
*frameBufferPtr = activePalette[*gfxDataPtr];
1825
++frameBufferPtr;
1826
--gfxDataPtr;
1827
1828
if (*gfxDataPtr > 0)
1829
*frameBufferPtr = activePalette[*gfxDataPtr];
1830
++frameBufferPtr;
1831
--gfxDataPtr;
1832
1833
if (*gfxDataPtr > 0)
1834
*frameBufferPtr = activePalette[*gfxDataPtr];
1835
++frameBufferPtr;
1836
--gfxDataPtr;
1837
1838
if (*gfxDataPtr > 0)
1839
*frameBufferPtr = activePalette[*gfxDataPtr];
1840
++frameBufferPtr;
1841
--gfxDataPtr;
1842
1843
if (*gfxDataPtr > 0)
1844
*frameBufferPtr = activePalette[*gfxDataPtr];
1845
++frameBufferPtr;
1846
--gfxDataPtr;
1847
1848
if (*gfxDataPtr > 0)
1849
*frameBufferPtr = activePalette[*gfxDataPtr];
1850
++frameBufferPtr;
1851
--gfxDataPtr;
1852
1853
if (*gfxDataPtr > 0)
1854
*frameBufferPtr = activePalette[*gfxDataPtr];
1855
++frameBufferPtr;
1856
break;
1857
}
1858
}
1859
else {
1860
frameBufferPtr += TILE_SIZE;
1861
}
1862
++chunkTileX;
1863
}
1864
1865
// Draw any remaining tiles
1866
while (lineRemain > 0) {
1867
if (chunkTileX++ < 8) {
1868
++chunk;
1869
}
1870
else {
1871
chunkTileX = 0;
1872
if (++chunkXPos == layerwidth)
1873
chunkXPos = 0;
1874
1875
chunk = (layer->tiles[chunkXPos + (chunkY << 8)] << 6) + 8 * tileY;
1876
}
1877
1878
tilePxLineCnt = lineRemain >= TILE_SIZE ? TILE_SIZE : lineRemain;
1879
lineRemain -= tilePxLineCnt;
1880
if (tiles128x128.visualPlane[chunk] == (byte)aboveMidPoint) {
1881
switch (tiles128x128.direction[chunk]) {
1882
case FLIP_NONE:
1883
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetY];
1884
while (tilePxLineCnt--) {
1885
if (*gfxDataPtr > 0)
1886
*frameBufferPtr = activePalette[*gfxDataPtr];
1887
++frameBufferPtr;
1888
++gfxDataPtr;
1889
}
1890
break;
1891
1892
case FLIP_X:
1893
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetYFlipX];
1894
while (tilePxLineCnt--) {
1895
if (*gfxDataPtr > 0)
1896
*frameBufferPtr = activePalette[*gfxDataPtr];
1897
++frameBufferPtr;
1898
--gfxDataPtr;
1899
}
1900
break;
1901
1902
case FLIP_Y:
1903
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetYFlipY];
1904
while (tilePxLineCnt--) {
1905
if (*gfxDataPtr > 0)
1906
*frameBufferPtr = activePalette[*gfxDataPtr];
1907
++frameBufferPtr;
1908
++gfxDataPtr;
1909
}
1910
break;
1911
1912
case FLIP_XY:
1913
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetYFlipXY];
1914
while (tilePxLineCnt--) {
1915
if (*gfxDataPtr > 0)
1916
*frameBufferPtr = activePalette[*gfxDataPtr];
1917
++frameBufferPtr;
1918
--gfxDataPtr;
1919
}
1920
break;
1921
1922
default: break;
1923
}
1924
}
1925
else {
1926
frameBufferPtr += tilePxLineCnt;
1927
}
1928
}
1929
1930
if (++tileY16 >= TILE_SIZE) {
1931
tileY16 = 0;
1932
++tileY;
1933
}
1934
1935
if (tileY >= 8) {
1936
if (++chunkY == layerheight) {
1937
chunkY = 0;
1938
scrollIndex -= 0x80 * layerheight;
1939
}
1940
tileY = 0;
1941
}
1942
}
1943
}
1944
#endif
1945
}
1946
void DrawVLineScrollLayer(int layerID)
1947
{
1948
TileLayer *layer = &stageLayouts[activeTileLayers[layerID]];
1949
if (!layer->xsize || !layer->ysize)
1950
return;
1951
#if RETRO_SOFTWARE_RENDER
1952
int layerwidth = layer->xsize;
1953
int layerheight = layer->ysize;
1954
bool aboveMidPoint = layerID >= tLayerMidPoint;
1955
1956
byte *lineScroll;
1957
int *deformationData;
1958
1959
int xscrollOffset = 0;
1960
if (activeTileLayers[layerID]) { // BG Layer
1961
int xScroll = xScrollOffset * layer->parallaxFactor >> 8;
1962
int fullLayerwidth = layerwidth << 7;
1963
layer->scrollPos += layer->scrollSpeed;
1964
if (layer->scrollPos > fullLayerwidth << 16)
1965
layer->scrollPos -= fullLayerwidth << 16;
1966
xscrollOffset = (xScroll + (layer->scrollPos >> 16)) % fullLayerwidth;
1967
layerwidth = fullLayerwidth >> 7;
1968
lineScroll = layer->lineScroll;
1969
deformationData = &bgDeformationData2[(byte)(xscrollOffset + layer->deformationOffset)];
1970
}
1971
else { // FG Layer
1972
lastYSize = layer->ysize;
1973
xscrollOffset = xScrollOffset;
1974
lineScroll = layer->lineScroll;
1975
vParallax.linePos[0] = yScrollOffset;
1976
vParallax.deform[0] = true;
1977
deformationData = &bgDeformationData0[(byte)(xScrollOffset + layer->deformationOffset)];
1978
}
1979
1980
if (layer->type == LAYER_VSCROLL) {
1981
if (lastYSize != layerheight) {
1982
int fullLayerheight = layerheight << 7;
1983
for (int i = 0; i < vParallax.entryCount; ++i) {
1984
vParallax.linePos[i] = yScrollOffset * vParallax.parallaxFactor[i] >> 8;
1985
1986
vParallax.scrollPos[i] += vParallax.scrollPos[i] << 16;
1987
if (vParallax.scrollPos[i] > fullLayerheight << 16)
1988
vParallax.scrollPos[i] -= fullLayerheight << 16;
1989
1990
vParallax.linePos[i] += vParallax.scrollPos[i] >> 16;
1991
vParallax.linePos[i] %= fullLayerheight;
1992
}
1993
layerheight = fullLayerheight >> 7;
1994
}
1995
lastYSize = layerheight;
1996
}
1997
1998
ushort *frameBufferPtr = Engine.frameBuffer;
1999
activePalette = fullPalette[gfxLineBuffer[0]];
2000
activePalette32 = fullPalette32[gfxLineBuffer[0]];
2001
int tileXPos = xscrollOffset % (layerheight << 7);
2002
if (tileXPos < 0)
2003
tileXPos += layerheight << 7;
2004
byte *scrollIndex = &lineScroll[tileXPos];
2005
int chunkX = tileXPos >> 7;
2006
int tileX16 = tileXPos & 0xF;
2007
int tileX = (tileXPos & 0x7F) >> 4;
2008
2009
// Draw Above Water (if applicable)
2010
int drawableLines = SCREEN_XSIZE;
2011
while (drawableLines--) {
2012
int chunkY = vParallax.linePos[*scrollIndex];
2013
if (vParallax.deform[*scrollIndex])
2014
chunkY += *deformationData;
2015
++deformationData;
2016
++scrollIndex;
2017
2018
int fullLayerHeight = layerheight << 7;
2019
if (chunkY < 0)
2020
chunkY += fullLayerHeight;
2021
if (chunkY >= fullLayerHeight)
2022
chunkY -= fullLayerHeight;
2023
2024
int chunkYPos = chunkY >> 7;
2025
int tileY = chunkY & 0xF;
2026
int tileYPxRemain = TILE_SIZE - tileY;
2027
int chunk = (layer->tiles[chunkX + (chunkY >> 7 << 8)] << 6) + tileX + 8 * ((chunkY & 0x7F) >> 4);
2028
int tileOffsetXFlipX = 0xF - tileX16;
2029
int tileOffsetXFlipY = tileX16 + SCREEN_YSIZE;
2030
int tileOffsetXFlipXY = 0xFF - tileX16;
2031
int lineRemain = SCREEN_YSIZE;
2032
2033
byte *gfxDataPtr = NULL;
2034
int tilePxLineCnt = tileYPxRemain;
2035
2036
// Draw the first tile to the left
2037
if (tiles128x128.visualPlane[chunk] == (byte)aboveMidPoint) {
2038
lineRemain -= tilePxLineCnt;
2039
switch (tiles128x128.direction[chunk]) {
2040
case FLIP_NONE:
2041
gfxDataPtr = &tilesetGFXData[TILE_SIZE * tileY + tileX16 + tiles128x128.gfxDataPos[chunk]];
2042
while (tilePxLineCnt--) {
2043
if (*gfxDataPtr > 0)
2044
*frameBufferPtr = activePalette[*gfxDataPtr];
2045
frameBufferPtr += GFX_LINESIZE;
2046
gfxDataPtr += TILE_SIZE;
2047
}
2048
break;
2049
2050
case FLIP_X:
2051
gfxDataPtr = &tilesetGFXData[TILE_SIZE * tileY + tileOffsetXFlipX + tiles128x128.gfxDataPos[chunk]];
2052
while (tilePxLineCnt--) {
2053
if (*gfxDataPtr > 0)
2054
*frameBufferPtr = activePalette[*gfxDataPtr];
2055
frameBufferPtr += GFX_LINESIZE;
2056
gfxDataPtr += TILE_SIZE;
2057
}
2058
break;
2059
2060
case FLIP_Y:
2061
gfxDataPtr = &tilesetGFXData[tileOffsetXFlipY + tiles128x128.gfxDataPos[chunk] - TILE_SIZE * tileY];
2062
while (tilePxLineCnt--) {
2063
if (*gfxDataPtr > 0)
2064
*frameBufferPtr = activePalette[*gfxDataPtr];
2065
frameBufferPtr += GFX_LINESIZE;
2066
gfxDataPtr -= TILE_SIZE;
2067
}
2068
break;
2069
2070
case FLIP_XY:
2071
gfxDataPtr = &tilesetGFXData[tileOffsetXFlipXY + tiles128x128.gfxDataPos[chunk] - TILE_SIZE * tileY];
2072
while (tilePxLineCnt--) {
2073
if (*gfxDataPtr > 0)
2074
*frameBufferPtr = activePalette[*gfxDataPtr];
2075
frameBufferPtr += GFX_LINESIZE;
2076
gfxDataPtr -= TILE_SIZE;
2077
}
2078
break;
2079
2080
default: break;
2081
}
2082
}
2083
else {
2084
frameBufferPtr += GFX_LINESIZE * tileYPxRemain;
2085
lineRemain -= tilePxLineCnt;
2086
}
2087
2088
// Draw the bulk of the tiles
2089
int chunkTileY = ((chunkY & 0x7F) >> 4) + 1;
2090
int tilesPerLine = (SCREEN_YSIZE >> 4) - 1;
2091
2092
while (tilesPerLine--) {
2093
if (chunkTileY < 8) {
2094
chunk += 8;
2095
}
2096
else {
2097
if (++chunkYPos == layerheight)
2098
chunkYPos = 0;
2099
2100
chunkTileY = 0;
2101
chunk = (layer->tiles[chunkX + (chunkYPos << 8)] << 6) + tileX;
2102
}
2103
lineRemain -= TILE_SIZE;
2104
2105
// Loop Unrolling (faster but messier code)
2106
if (tiles128x128.visualPlane[chunk] == (byte)aboveMidPoint) {
2107
switch (tiles128x128.direction[chunk]) {
2108
case FLIP_NONE:
2109
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileX16];
2110
if (*gfxDataPtr > 0)
2111
*frameBufferPtr = activePalette[*gfxDataPtr];
2112
frameBufferPtr += GFX_LINESIZE;
2113
gfxDataPtr += TILE_SIZE;
2114
2115
if (*gfxDataPtr > 0)
2116
*frameBufferPtr = activePalette[*gfxDataPtr];
2117
frameBufferPtr += GFX_LINESIZE;
2118
gfxDataPtr += TILE_SIZE;
2119
2120
if (*gfxDataPtr > 0)
2121
*frameBufferPtr = activePalette[*gfxDataPtr];
2122
frameBufferPtr += GFX_LINESIZE;
2123
gfxDataPtr += TILE_SIZE;
2124
2125
if (*gfxDataPtr > 0)
2126
*frameBufferPtr = activePalette[*gfxDataPtr];
2127
frameBufferPtr += GFX_LINESIZE;
2128
gfxDataPtr += TILE_SIZE;
2129
2130
if (*gfxDataPtr > 0)
2131
*frameBufferPtr = activePalette[*gfxDataPtr];
2132
frameBufferPtr += GFX_LINESIZE;
2133
gfxDataPtr += TILE_SIZE;
2134
2135
if (*gfxDataPtr > 0)
2136
*frameBufferPtr = activePalette[*gfxDataPtr];
2137
frameBufferPtr += GFX_LINESIZE;
2138
gfxDataPtr += TILE_SIZE;
2139
2140
if (*gfxDataPtr > 0)
2141
*frameBufferPtr = activePalette[*gfxDataPtr];
2142
frameBufferPtr += GFX_LINESIZE;
2143
gfxDataPtr += TILE_SIZE;
2144
2145
if (*gfxDataPtr > 0)
2146
*frameBufferPtr = activePalette[*gfxDataPtr];
2147
frameBufferPtr += GFX_LINESIZE;
2148
gfxDataPtr += TILE_SIZE;
2149
2150
if (*gfxDataPtr > 0)
2151
*frameBufferPtr = activePalette[*gfxDataPtr];
2152
frameBufferPtr += GFX_LINESIZE;
2153
gfxDataPtr += TILE_SIZE;
2154
2155
if (*gfxDataPtr > 0)
2156
*frameBufferPtr = activePalette[*gfxDataPtr];
2157
frameBufferPtr += GFX_LINESIZE;
2158
gfxDataPtr += TILE_SIZE;
2159
2160
if (*gfxDataPtr > 0)
2161
*frameBufferPtr = activePalette[*gfxDataPtr];
2162
frameBufferPtr += GFX_LINESIZE;
2163
gfxDataPtr += TILE_SIZE;
2164
2165
if (*gfxDataPtr > 0)
2166
*frameBufferPtr = activePalette[*gfxDataPtr];
2167
frameBufferPtr += GFX_LINESIZE;
2168
gfxDataPtr += TILE_SIZE;
2169
2170
if (*gfxDataPtr > 0)
2171
*frameBufferPtr = activePalette[*gfxDataPtr];
2172
frameBufferPtr += GFX_LINESIZE;
2173
gfxDataPtr += TILE_SIZE;
2174
2175
if (*gfxDataPtr > 0)
2176
*frameBufferPtr = activePalette[*gfxDataPtr];
2177
frameBufferPtr += GFX_LINESIZE;
2178
gfxDataPtr += TILE_SIZE;
2179
2180
if (*gfxDataPtr > 0)
2181
*frameBufferPtr = activePalette[*gfxDataPtr];
2182
frameBufferPtr += GFX_LINESIZE;
2183
gfxDataPtr += TILE_SIZE;
2184
2185
if (*gfxDataPtr > 0)
2186
*frameBufferPtr = activePalette[*gfxDataPtr];
2187
frameBufferPtr += GFX_LINESIZE;
2188
break;
2189
2190
case FLIP_X:
2191
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetXFlipX];
2192
if (*gfxDataPtr > 0)
2193
*frameBufferPtr = activePalette[*gfxDataPtr];
2194
frameBufferPtr += GFX_LINESIZE;
2195
gfxDataPtr += TILE_SIZE;
2196
2197
if (*gfxDataPtr > 0)
2198
*frameBufferPtr = activePalette[*gfxDataPtr];
2199
frameBufferPtr += GFX_LINESIZE;
2200
gfxDataPtr += TILE_SIZE;
2201
2202
if (*gfxDataPtr > 0)
2203
*frameBufferPtr = activePalette[*gfxDataPtr];
2204
frameBufferPtr += GFX_LINESIZE;
2205
gfxDataPtr += TILE_SIZE;
2206
2207
if (*gfxDataPtr > 0)
2208
*frameBufferPtr = activePalette[*gfxDataPtr];
2209
frameBufferPtr += GFX_LINESIZE;
2210
gfxDataPtr += TILE_SIZE;
2211
2212
if (*gfxDataPtr > 0)
2213
*frameBufferPtr = activePalette[*gfxDataPtr];
2214
frameBufferPtr += GFX_LINESIZE;
2215
gfxDataPtr += TILE_SIZE;
2216
2217
if (*gfxDataPtr > 0)
2218
*frameBufferPtr = activePalette[*gfxDataPtr];
2219
frameBufferPtr += GFX_LINESIZE;
2220
gfxDataPtr += TILE_SIZE;
2221
2222
if (*gfxDataPtr > 0)
2223
*frameBufferPtr = activePalette[*gfxDataPtr];
2224
frameBufferPtr += GFX_LINESIZE;
2225
gfxDataPtr += TILE_SIZE;
2226
2227
if (*gfxDataPtr > 0)
2228
*frameBufferPtr = activePalette[*gfxDataPtr];
2229
frameBufferPtr += GFX_LINESIZE;
2230
gfxDataPtr += TILE_SIZE;
2231
2232
if (*gfxDataPtr > 0)
2233
*frameBufferPtr = activePalette[*gfxDataPtr];
2234
frameBufferPtr += GFX_LINESIZE;
2235
gfxDataPtr += TILE_SIZE;
2236
2237
if (*gfxDataPtr > 0)
2238
*frameBufferPtr = activePalette[*gfxDataPtr];
2239
frameBufferPtr += GFX_LINESIZE;
2240
gfxDataPtr += TILE_SIZE;
2241
2242
if (*gfxDataPtr > 0)
2243
*frameBufferPtr = activePalette[*gfxDataPtr];
2244
frameBufferPtr += GFX_LINESIZE;
2245
gfxDataPtr += TILE_SIZE;
2246
2247
if (*gfxDataPtr > 0)
2248
*frameBufferPtr = activePalette[*gfxDataPtr];
2249
frameBufferPtr += GFX_LINESIZE;
2250
gfxDataPtr += TILE_SIZE;
2251
2252
if (*gfxDataPtr > 0)
2253
*frameBufferPtr = activePalette[*gfxDataPtr];
2254
frameBufferPtr += GFX_LINESIZE;
2255
gfxDataPtr += TILE_SIZE;
2256
2257
if (*gfxDataPtr > 0)
2258
*frameBufferPtr = activePalette[*gfxDataPtr];
2259
frameBufferPtr += GFX_LINESIZE;
2260
gfxDataPtr += TILE_SIZE;
2261
2262
if (*gfxDataPtr > 0)
2263
*frameBufferPtr = activePalette[*gfxDataPtr];
2264
frameBufferPtr += GFX_LINESIZE;
2265
gfxDataPtr += TILE_SIZE;
2266
2267
if (*gfxDataPtr > 0)
2268
*frameBufferPtr = activePalette[*gfxDataPtr];
2269
frameBufferPtr += GFX_LINESIZE;
2270
break;
2271
2272
case FLIP_Y:
2273
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetXFlipY];
2274
if (*gfxDataPtr > 0)
2275
*frameBufferPtr = activePalette[*gfxDataPtr];
2276
frameBufferPtr += GFX_LINESIZE;
2277
gfxDataPtr -= TILE_SIZE;
2278
2279
if (*gfxDataPtr > 0)
2280
*frameBufferPtr = activePalette[*gfxDataPtr];
2281
frameBufferPtr += GFX_LINESIZE;
2282
gfxDataPtr -= TILE_SIZE;
2283
2284
if (*gfxDataPtr > 0)
2285
*frameBufferPtr = activePalette[*gfxDataPtr];
2286
frameBufferPtr += GFX_LINESIZE;
2287
gfxDataPtr -= TILE_SIZE;
2288
2289
if (*gfxDataPtr > 0)
2290
*frameBufferPtr = activePalette[*gfxDataPtr];
2291
frameBufferPtr += GFX_LINESIZE;
2292
gfxDataPtr -= TILE_SIZE;
2293
2294
if (*gfxDataPtr > 0)
2295
*frameBufferPtr = activePalette[*gfxDataPtr];
2296
frameBufferPtr += GFX_LINESIZE;
2297
gfxDataPtr -= TILE_SIZE;
2298
2299
if (*gfxDataPtr > 0)
2300
*frameBufferPtr = activePalette[*gfxDataPtr];
2301
frameBufferPtr += GFX_LINESIZE;
2302
gfxDataPtr -= TILE_SIZE;
2303
2304
if (*gfxDataPtr > 0)
2305
*frameBufferPtr = activePalette[*gfxDataPtr];
2306
frameBufferPtr += GFX_LINESIZE;
2307
gfxDataPtr -= TILE_SIZE;
2308
2309
if (*gfxDataPtr > 0)
2310
*frameBufferPtr = activePalette[*gfxDataPtr];
2311
frameBufferPtr += GFX_LINESIZE;
2312
gfxDataPtr -= TILE_SIZE;
2313
2314
if (*gfxDataPtr > 0)
2315
*frameBufferPtr = activePalette[*gfxDataPtr];
2316
frameBufferPtr += GFX_LINESIZE;
2317
gfxDataPtr -= TILE_SIZE;
2318
2319
if (*gfxDataPtr > 0)
2320
*frameBufferPtr = activePalette[*gfxDataPtr];
2321
frameBufferPtr += GFX_LINESIZE;
2322
gfxDataPtr -= TILE_SIZE;
2323
2324
if (*gfxDataPtr > 0)
2325
*frameBufferPtr = activePalette[*gfxDataPtr];
2326
frameBufferPtr += GFX_LINESIZE;
2327
gfxDataPtr -= TILE_SIZE;
2328
2329
if (*gfxDataPtr > 0)
2330
*frameBufferPtr = activePalette[*gfxDataPtr];
2331
frameBufferPtr += GFX_LINESIZE;
2332
gfxDataPtr -= TILE_SIZE;
2333
2334
if (*gfxDataPtr > 0)
2335
*frameBufferPtr = activePalette[*gfxDataPtr];
2336
frameBufferPtr += GFX_LINESIZE;
2337
gfxDataPtr -= TILE_SIZE;
2338
2339
if (*gfxDataPtr > 0)
2340
*frameBufferPtr = activePalette[*gfxDataPtr];
2341
frameBufferPtr += GFX_LINESIZE;
2342
gfxDataPtr -= TILE_SIZE;
2343
2344
if (*gfxDataPtr > 0)
2345
*frameBufferPtr = activePalette[*gfxDataPtr];
2346
frameBufferPtr += GFX_LINESIZE;
2347
gfxDataPtr -= TILE_SIZE;
2348
2349
if (*gfxDataPtr > 0)
2350
*frameBufferPtr = activePalette[*gfxDataPtr];
2351
frameBufferPtr += GFX_LINESIZE;
2352
break;
2353
2354
case FLIP_XY:
2355
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetXFlipXY];
2356
if (*gfxDataPtr > 0)
2357
*frameBufferPtr = activePalette[*gfxDataPtr];
2358
frameBufferPtr += GFX_LINESIZE;
2359
gfxDataPtr -= TILE_SIZE;
2360
2361
if (*gfxDataPtr > 0)
2362
*frameBufferPtr = activePalette[*gfxDataPtr];
2363
frameBufferPtr += GFX_LINESIZE;
2364
gfxDataPtr -= TILE_SIZE;
2365
2366
if (*gfxDataPtr > 0)
2367
*frameBufferPtr = activePalette[*gfxDataPtr];
2368
frameBufferPtr += GFX_LINESIZE;
2369
gfxDataPtr -= TILE_SIZE;
2370
2371
if (*gfxDataPtr > 0)
2372
*frameBufferPtr = activePalette[*gfxDataPtr];
2373
frameBufferPtr += GFX_LINESIZE;
2374
gfxDataPtr -= TILE_SIZE;
2375
2376
if (*gfxDataPtr > 0)
2377
*frameBufferPtr = activePalette[*gfxDataPtr];
2378
frameBufferPtr += GFX_LINESIZE;
2379
gfxDataPtr -= TILE_SIZE;
2380
2381
if (*gfxDataPtr > 0)
2382
*frameBufferPtr = activePalette[*gfxDataPtr];
2383
frameBufferPtr += GFX_LINESIZE;
2384
gfxDataPtr -= TILE_SIZE;
2385
2386
if (*gfxDataPtr > 0)
2387
*frameBufferPtr = activePalette[*gfxDataPtr];
2388
frameBufferPtr += GFX_LINESIZE;
2389
gfxDataPtr -= TILE_SIZE;
2390
2391
if (*gfxDataPtr > 0)
2392
*frameBufferPtr = activePalette[*gfxDataPtr];
2393
frameBufferPtr += GFX_LINESIZE;
2394
gfxDataPtr -= TILE_SIZE;
2395
2396
if (*gfxDataPtr > 0)
2397
*frameBufferPtr = activePalette[*gfxDataPtr];
2398
frameBufferPtr += GFX_LINESIZE;
2399
gfxDataPtr -= TILE_SIZE;
2400
2401
if (*gfxDataPtr > 0)
2402
*frameBufferPtr = activePalette[*gfxDataPtr];
2403
frameBufferPtr += GFX_LINESIZE;
2404
gfxDataPtr -= TILE_SIZE;
2405
2406
if (*gfxDataPtr > 0)
2407
*frameBufferPtr = activePalette[*gfxDataPtr];
2408
frameBufferPtr += GFX_LINESIZE;
2409
gfxDataPtr -= TILE_SIZE;
2410
2411
if (*gfxDataPtr > 0)
2412
*frameBufferPtr = activePalette[*gfxDataPtr];
2413
frameBufferPtr += GFX_LINESIZE;
2414
gfxDataPtr -= TILE_SIZE;
2415
2416
if (*gfxDataPtr > 0)
2417
*frameBufferPtr = activePalette[*gfxDataPtr];
2418
frameBufferPtr += GFX_LINESIZE;
2419
gfxDataPtr -= TILE_SIZE;
2420
2421
if (*gfxDataPtr > 0)
2422
*frameBufferPtr = activePalette[*gfxDataPtr];
2423
frameBufferPtr += GFX_LINESIZE;
2424
gfxDataPtr -= TILE_SIZE;
2425
2426
if (*gfxDataPtr > 0)
2427
*frameBufferPtr = activePalette[*gfxDataPtr];
2428
frameBufferPtr += GFX_LINESIZE;
2429
gfxDataPtr -= TILE_SIZE;
2430
2431
if (*gfxDataPtr > 0)
2432
*frameBufferPtr = activePalette[*gfxDataPtr];
2433
frameBufferPtr += GFX_LINESIZE;
2434
break;
2435
}
2436
}
2437
else {
2438
frameBufferPtr += GFX_LINESIZE * TILE_SIZE;
2439
}
2440
++chunkTileY;
2441
}
2442
2443
// Draw any remaining tiles
2444
while (lineRemain > 0) {
2445
if (chunkTileY < 8) {
2446
chunk += 8;
2447
}
2448
else {
2449
if (++chunkYPos == layerheight)
2450
chunkYPos = 0;
2451
2452
chunkTileY = 0;
2453
chunk = (layer->tiles[chunkX + (chunkYPos << 8)] << 6) + tileX;
2454
}
2455
2456
tilePxLineCnt = lineRemain >= TILE_SIZE ? TILE_SIZE : lineRemain;
2457
lineRemain -= tilePxLineCnt;
2458
2459
if (tiles128x128.visualPlane[chunk] == (byte)aboveMidPoint) {
2460
switch (tiles128x128.direction[chunk]) {
2461
case FLIP_NONE:
2462
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileX16];
2463
while (tilePxLineCnt--) {
2464
if (*gfxDataPtr > 0)
2465
*frameBufferPtr = activePalette[*gfxDataPtr];
2466
frameBufferPtr += GFX_LINESIZE;
2467
gfxDataPtr += TILE_SIZE;
2468
}
2469
break;
2470
2471
case FLIP_X:
2472
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetXFlipX];
2473
while (tilePxLineCnt--) {
2474
if (*gfxDataPtr > 0)
2475
*frameBufferPtr = activePalette[*gfxDataPtr];
2476
frameBufferPtr += GFX_LINESIZE;
2477
gfxDataPtr += TILE_SIZE;
2478
}
2479
break;
2480
2481
case FLIP_Y:
2482
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetXFlipY];
2483
while (tilePxLineCnt--) {
2484
if (*gfxDataPtr > 0)
2485
*frameBufferPtr = activePalette[*gfxDataPtr];
2486
frameBufferPtr += GFX_LINESIZE;
2487
gfxDataPtr -= TILE_SIZE;
2488
}
2489
break;
2490
2491
case FLIP_XY:
2492
gfxDataPtr = &tilesetGFXData[tiles128x128.gfxDataPos[chunk] + tileOffsetXFlipXY];
2493
while (tilePxLineCnt--) {
2494
if (*gfxDataPtr > 0)
2495
*frameBufferPtr = activePalette[*gfxDataPtr];
2496
frameBufferPtr += GFX_LINESIZE;
2497
gfxDataPtr -= TILE_SIZE;
2498
}
2499
break;
2500
2501
default: break;
2502
}
2503
}
2504
else {
2505
frameBufferPtr += GFX_LINESIZE * tilePxLineCnt;
2506
}
2507
chunkTileY++;
2508
}
2509
2510
if (++tileX16 >= TILE_SIZE) {
2511
tileX16 = 0;
2512
++tileX;
2513
}
2514
2515
if (tileX >= 8) {
2516
if (++chunkX == layerwidth) {
2517
chunkX = 0;
2518
scrollIndex -= 0x80 * layerwidth;
2519
}
2520
tileX = 0;
2521
}
2522
2523
frameBufferPtr -= GFX_FBUFFERMINUSONE;
2524
}
2525
#endif
2526
}
2527
void Draw3DFloorLayer(int layerID)
2528
{
2529
TileLayer *layer = &stageLayouts[activeTileLayers[layerID]];
2530
if (!layer->xsize || !layer->ysize)
2531
return;
2532
2533
#if RETRO_SOFTWARE_RENDER
2534
int layerWidth = layer->xsize << 7;
2535
int layerHeight = layer->ysize << 7;
2536
int layerYPos = layer->ypos;
2537
int layerZPos = layer->zpos;
2538
int sinValue = sinM7LookupTable[layer->angle];
2539
int cosValue = cosM7LookupTable[layer->angle];
2540
byte *gfxLineBufferPtr = &gfxLineBuffer[(SCREEN_YSIZE / 2) + 12];
2541
ushort *frameBufferPtr = &Engine.frameBuffer[((SCREEN_YSIZE / 2) + 12) * GFX_LINESIZE];
2542
int layerXPos = layer->xpos >> 4;
2543
int ZBuffer = layerZPos >> 4;
2544
for (int i = 4; i < 112; ++i) {
2545
if (!(i & 1)) {
2546
activePalette = fullPalette[*gfxLineBufferPtr];
2547
activePalette32 = fullPalette32[*gfxLineBufferPtr];
2548
gfxLineBufferPtr++;
2549
}
2550
int XBuffer = layerYPos / (i << 9) * -cosValue >> 8;
2551
int YBuffer = sinValue * (layerYPos / (i << 9)) >> 8;
2552
int XPos = layerXPos + (3 * sinValue * (layerYPos / (i << 9)) >> 2) - XBuffer * SCREEN_CENTERX;
2553
int YPos = ZBuffer + (3 * cosValue * (layerYPos / (i << 9)) >> 2) - YBuffer * SCREEN_CENTERX;
2554
int lineBuffer = 0;
2555
while (lineBuffer < GFX_LINESIZE) {
2556
int tileX = XPos >> 12;
2557
int tileY = YPos >> 12;
2558
if (tileX > -1 && tileX < layerWidth && tileY > -1 && tileY < layerHeight) {
2559
int chunk = tile3DFloorBuffer[(YPos >> 16 << 8) + (XPos >> 16)];
2560
byte *tilePixel = &tilesetGFXData[tiles128x128.gfxDataPos[chunk]];
2561
switch (tiles128x128.direction[chunk]) {
2562
case FLIP_NONE: tilePixel += 16 * (tileY & 0xF) + (tileX & 0xF); break;
2563
case FLIP_X: tilePixel += 16 * (tileY & 0xF) + 15 - (tileX & 0xF); break;
2564
case FLIP_Y: tilePixel += (tileX & 0xF) + SCREEN_YSIZE - 16 * (tileY & 0xF); break;
2565
case FLIP_XY: tilePixel += 15 - (tileX & 0xF) + SCREEN_YSIZE - 16 * (tileY & 0xF); break;
2566
default: break;
2567
}
2568
2569
if (*tilePixel > 0)
2570
*frameBufferPtr = activePalette[*tilePixel];
2571
}
2572
++frameBufferPtr;
2573
++lineBuffer;
2574
XPos += XBuffer;
2575
YPos += YBuffer;
2576
}
2577
}
2578
#endif
2579
}
2580
void Draw3DSkyLayer(int layerID)
2581
{
2582
TileLayer *layer = &stageLayouts[activeTileLayers[layerID]];
2583
if (!layer->xsize || !layer->ysize)
2584
return;
2585
2586
#if RETRO_SOFTWARE_RENDER
2587
int layerWidth = layer->xsize << 7;
2588
int layerHeight = layer->ysize << 7;
2589
int layerYPos = layer->ypos;
2590
int sinValue = sinM7LookupTable[layer->angle & 0x1FF];
2591
int cosValue = cosM7LookupTable[layer->angle & 0x1FF];
2592
ushort *frameBufferPtr = &Engine.frameBuffer[((SCREEN_YSIZE / 2) + 12) * GFX_LINESIZE];
2593
ushort *bufferPtr = Engine.frameBuffer2x;
2594
if (!drawStageGFXHQ)
2595
bufferPtr = &Engine.frameBuffer[((SCREEN_YSIZE / 2) + 12) * GFX_LINESIZE];
2596
byte *gfxLineBufferPtr = &gfxLineBuffer[((SCREEN_YSIZE / 2) + 12)];
2597
int layerXPos = layer->xpos >> 4;
2598
int layerZPos = layer->zpos >> 4;
2599
for (int i = TILE_SIZE / 2; i < SCREEN_YSIZE - TILE_SIZE; ++i) {
2600
if (!(i & 1)) {
2601
activePalette = fullPalette[*gfxLineBufferPtr];
2602
activePalette32 = fullPalette32[*gfxLineBufferPtr];
2603
gfxLineBufferPtr++;
2604
}
2605
int xBuffer = layerYPos / (i << 8) * -cosValue >> 9;
2606
int yBuffer = sinValue * (layerYPos / (i << 8)) >> 9;
2607
int XPos = layerXPos + (3 * sinValue * (layerYPos / (i << 8)) >> 2) - xBuffer * GFX_LINESIZE;
2608
int YPos = layerZPos + (3 * cosValue * (layerYPos / (i << 8)) >> 2) - yBuffer * GFX_LINESIZE;
2609
int lineBuffer = 0;
2610
while (lineBuffer < GFX_LINESIZE * 2) {
2611
int tileX = XPos >> 12;
2612
int tileY = YPos >> 12;
2613
if (tileX > -1 && tileX < layerWidth && tileY > -1 && tileY < layerHeight) {
2614
int chunk = tile3DFloorBuffer[(YPos >> 16 << 8) + (XPos >> 16)];
2615
byte *tilePixel = &tilesetGFXData[tiles128x128.gfxDataPos[chunk]];
2616
switch (tiles128x128.direction[chunk]) {
2617
case FLIP_NONE: tilePixel += TILE_SIZE * (tileY & 0xF) + (tileX & 0xF); break;
2618
case FLIP_X: tilePixel += TILE_SIZE * (tileY & 0xF) + 0xF - (tileX & 0xF); break;
2619
case FLIP_Y: tilePixel += (tileX & 0xF) + SCREEN_YSIZE - TILE_SIZE * (tileY & 0xF); break;
2620
case FLIP_XY: tilePixel += 0xF - (tileX & 0xF) + SCREEN_YSIZE - TILE_SIZE * (tileY & 0xF); break;
2621
default: break;
2622
}
2623
2624
if (*tilePixel > 0)
2625
*bufferPtr = activePalette[*tilePixel];
2626
else if (drawStageGFXHQ)
2627
*bufferPtr = *frameBufferPtr;
2628
}
2629
else if (drawStageGFXHQ) {
2630
*bufferPtr = *frameBufferPtr;
2631
}
2632
2633
if (lineBuffer & 1)
2634
++frameBufferPtr;
2635
2636
if (drawStageGFXHQ)
2637
bufferPtr++;
2638
else if (lineBuffer & 1)
2639
++bufferPtr;
2640
2641
lineBuffer++;
2642
XPos += xBuffer;
2643
YPos += yBuffer;
2644
}
2645
2646
if (!(i & 1))
2647
frameBufferPtr -= GFX_LINESIZE;
2648
2649
if (!(i & 1) && !drawStageGFXHQ)
2650
bufferPtr -= GFX_LINESIZE;
2651
}
2652
2653
if (drawStageGFXHQ) {
2654
frameBufferPtr = &Engine.frameBuffer[((SCREEN_YSIZE / 2) + 12) * GFX_LINESIZE];
2655
int cnt = ((SCREEN_YSIZE / 2) - 12) * GFX_LINESIZE;
2656
while (cnt--) *frameBufferPtr++ = 0xF81F; // Magenta
2657
}
2658
#endif
2659
}
2660
2661
void DrawRectangle(int XPos, int YPos, int width, int height, int R, int G, int B, int A)
2662
{
2663
if (A > 0xFF)
2664
A = 0xFF;
2665
#if RETRO_SOFTWARE_RENDER
2666
if (width + XPos > GFX_LINESIZE)
2667
width = GFX_LINESIZE - XPos;
2668
if (XPos < 0) {
2669
width += XPos;
2670
XPos = 0;
2671
}
2672
2673
if (height + YPos > SCREEN_YSIZE)
2674
height = SCREEN_YSIZE - YPos;
2675
if (YPos < 0) {
2676
height += YPos;
2677
YPos = 0;
2678
}
2679
if (width <= 0 || height <= 0 || A <= 0)
2680
return;
2681
int pitch = GFX_LINESIZE - width;
2682
ushort *frameBufferPtr = &Engine.frameBuffer[XPos + GFX_LINESIZE * YPos];
2683
ushort clr = PACK_RGB888(R, G, B);
2684
if (A == 0xFF) {
2685
int h = height;
2686
while (h--) {
2687
int w = width;
2688
while (w--) {
2689
*frameBufferPtr = clr;
2690
++frameBufferPtr;
2691
}
2692
frameBufferPtr += pitch;
2693
}
2694
}
2695
else {
2696
ushort *fbufferBlend = &blendLookupTable[0x20 * (0xFF - A)];
2697
ushort *pixelBlend = &blendLookupTable[0x20 * A];
2698
2699
int h = height;
2700
while (h--) {
2701
int w = width;
2702
while (w--) {
2703
int R = (fbufferBlend[(*frameBufferPtr & 0xF800) >> 11] + pixelBlend[(clr & 0xF800) >> 11]) << 11;
2704
int G = (fbufferBlend[(*frameBufferPtr & 0x7E0) >> 6] + pixelBlend[(clr & 0x7E0) >> 6]) << 6;
2705
int B = fbufferBlend[*frameBufferPtr & 0x1F] + pixelBlend[clr & 0x1F];
2706
2707
*frameBufferPtr = R | G | B;
2708
++frameBufferPtr;
2709
}
2710
frameBufferPtr += pitch;
2711
}
2712
}
2713
#endif
2714
}
2715
2716
void SetFadeHQ(int R, int G, int B, int A)
2717
{
2718
#if RETRO_SOFTWARE_RENDER
2719
if (A <= 0)
2720
return;
2721
if (A > 0xFF)
2722
A = 0xFF;
2723
int pitch = GFX_LINESIZE * 2;
2724
ushort *frameBufferPtr = Engine.frameBuffer2x;
2725
ushort clr = PACK_RGB888(R, G, B);
2726
if (A == 0xFF) {
2727
int h = SCREEN_YSIZE;
2728
while (h--) {
2729
int w = pitch;
2730
while (w--) {
2731
*frameBufferPtr = clr;
2732
++frameBufferPtr;
2733
}
2734
}
2735
}
2736
else {
2737
ushort *fbufferBlend = &blendLookupTable[0x20 * (0xFF - A)];
2738
ushort *pixelBlend = &blendLookupTable[0x20 * A];
2739
2740
int h = SCREEN_YSIZE;
2741
while (h--) {
2742
int w = pitch;
2743
while (w--) {
2744
int R = (fbufferBlend[(*frameBufferPtr & 0xF800) >> 11] + pixelBlend[(clr & 0xF800) >> 11]) << 11;
2745
int G = (fbufferBlend[(*frameBufferPtr & 0x7E0) >> 6] + pixelBlend[(clr & 0x7E0) >> 6]) << 6;
2746
int B = fbufferBlend[*frameBufferPtr & 0x1F] + pixelBlend[clr & 0x1F];
2747
2748
*frameBufferPtr = R | G | B;
2749
++frameBufferPtr;
2750
}
2751
}
2752
}
2753
#endif
2754
}
2755
2756
void DrawTintRectangle(int XPos, int YPos, int width, int height)
2757
{
2758
#if RETRO_SOFTWARE_RENDER
2759
if (width + XPos > GFX_LINESIZE)
2760
width = GFX_LINESIZE - XPos;
2761
if (XPos < 0) {
2762
width += XPos;
2763
XPos = 0;
2764
}
2765
2766
if (height + YPos > SCREEN_YSIZE)
2767
height = SCREEN_YSIZE - YPos;
2768
if (YPos < 0) {
2769
height += YPos;
2770
YPos = 0;
2771
}
2772
2773
if (width < 0 || height < 0)
2774
return;
2775
2776
int yOffset = GFX_LINESIZE - width;
2777
for (ushort *frameBufferPtr = &Engine.frameBuffer[XPos + GFX_LINESIZE * YPos];; frameBufferPtr += yOffset) {
2778
height--;
2779
if (height < 0)
2780
break;
2781
int w = width;
2782
while (w--) {
2783
*frameBufferPtr = tintLookupTable[*frameBufferPtr];
2784
++frameBufferPtr;
2785
}
2786
}
2787
#endif
2788
}
2789
void DrawScaledTintMask(int direction, int XPos, int YPos, int pivotX, int pivotY, int scaleX, int scaleY, int width, int height, int sprX, int sprY,
2790
int sheetID)
2791
{
2792
#if RETRO_SOFTWARE_RENDER
2793
int roundedYPos = 0;
2794
int roundedXPos = 0;
2795
int truescaleX = 4 * scaleX;
2796
int truescaleY = 4 * scaleY;
2797
int widthM1 = width - 1;
2798
int trueXPos = XPos - (truescaleX * pivotX >> 11);
2799
width = truescaleX * width >> 11;
2800
int trueYPos = YPos - (truescaleY * pivotY >> 11);
2801
height = truescaleY * height >> 11;
2802
int finalscaleX = (signed int)(float)((float)(2048.0 / (float)truescaleX) * 2048.0);
2803
int finalscaleY = (signed int)(float)((float)(2048.0 / (float)truescaleY) * 2048.0);
2804
if (width + trueXPos > GFX_LINESIZE) {
2805
width = GFX_LINESIZE - trueXPos;
2806
}
2807
2808
if (direction) {
2809
if (trueXPos < 0) {
2810
widthM1 -= trueXPos * -finalscaleX >> 11;
2811
roundedXPos = (ushort)trueXPos * -(short)finalscaleX & 0x7FF;
2812
width += trueXPos;
2813
trueXPos = 0;
2814
}
2815
}
2816
else if (trueXPos < 0) {
2817
sprX += trueXPos * -finalscaleX >> 11;
2818
roundedXPos = (ushort)trueXPos * -(short)finalscaleX & 0x7FF;
2819
width += trueXPos;
2820
trueXPos = 0;
2821
}
2822
2823
if (height + trueYPos > SCREEN_YSIZE) {
2824
height = SCREEN_YSIZE - trueYPos;
2825
}
2826
if (trueYPos < 0) {
2827
sprY += trueYPos * -finalscaleY >> 11;
2828
roundedYPos = (ushort)trueYPos * -(short)finalscaleY & 0x7FF;
2829
height += trueYPos;
2830
trueYPos = 0;
2831
}
2832
2833
if (width <= 0 || height <= 0)
2834
return;
2835
2836
GFXSurface *surface = &gfxSurface[sheetID];
2837
int pitch = GFX_LINESIZE - width;
2838
int gfxwidth = surface->width;
2839
// byte *lineBuffer = &gfxLineBuffer[trueYPos];
2840
byte *gfxData = &graphicData[sprX + surface->width * sprY + surface->dataPosition];
2841
ushort *frameBufferPtr = &Engine.frameBuffer[trueXPos + GFX_LINESIZE * trueYPos];
2842
if (direction == FLIP_X) {
2843
byte *gfxDataPtr = &gfxData[widthM1];
2844
int gfxPitch = 0;
2845
while (height--) {
2846
int roundXPos = roundedXPos;
2847
int w = width;
2848
while (w--) {
2849
if (*gfxDataPtr > 0)
2850
*frameBufferPtr = tintLookupTable[*frameBufferPtr];
2851
int offsetX = finalscaleX + roundXPos;
2852
gfxDataPtr -= offsetX >> 11;
2853
gfxPitch += offsetX >> 11;
2854
roundXPos = offsetX & 0x7FF;
2855
++frameBufferPtr;
2856
}
2857
frameBufferPtr += pitch;
2858
int offsetY = finalscaleY + roundedYPos;
2859
gfxDataPtr += gfxPitch + (offsetY >> 11) * gfxwidth;
2860
roundedYPos = offsetY & 0x7FF;
2861
gfxPitch = 0;
2862
}
2863
}
2864
else {
2865
int gfxPitch = 0;
2866
int h = height;
2867
while (h--) {
2868
int roundXPos = roundedXPos;
2869
int w = width;
2870
while (w--) {
2871
if (*gfxData > 0)
2872
*frameBufferPtr = tintLookupTable[*frameBufferPtr];
2873
int offsetX = finalscaleX + roundXPos;
2874
gfxData += offsetX >> 11;
2875
gfxPitch += offsetX >> 11;
2876
roundXPos = offsetX & 0x7FF;
2877
++frameBufferPtr;
2878
}
2879
frameBufferPtr += pitch;
2880
int offsetY = finalscaleY + roundedYPos;
2881
gfxData += (offsetY >> 11) * gfxwidth - gfxPitch;
2882
roundedYPos = offsetY & 0x7FF;
2883
gfxPitch = 0;
2884
}
2885
}
2886
#endif
2887
}
2888
2889
void DrawSprite(int XPos, int YPos, int width, int height, int sprX, int sprY, int sheetID)
2890
{
2891
#if RETRO_SOFTWARE_RENDER
2892
if (width + XPos > GFX_LINESIZE)
2893
width = GFX_LINESIZE - XPos;
2894
if (XPos < 0) {
2895
sprX -= XPos;
2896
width += XPos;
2897
XPos = 0;
2898
}
2899
if (height + YPos > SCREEN_YSIZE)
2900
height = SCREEN_YSIZE - YPos;
2901
if (YPos < 0) {
2902
sprY -= YPos;
2903
height += YPos;
2904
YPos = 0;
2905
}
2906
if (width <= 0 || height <= 0)
2907
return;
2908
2909
GFXSurface *surface = &gfxSurface[sheetID];
2910
int pitch = GFX_LINESIZE - width;
2911
int gfxPitch = surface->width - width;
2912
byte *lineBuffer = &gfxLineBuffer[YPos];
2913
byte *gfxDataPtr = &graphicData[sprX + surface->width * sprY + surface->dataPosition];
2914
ushort *frameBufferPtr = &Engine.frameBuffer[XPos + GFX_LINESIZE * YPos];
2915
while (height--) {
2916
activePalette = fullPalette[*lineBuffer];
2917
activePalette32 = fullPalette32[*lineBuffer];
2918
lineBuffer++;
2919
int w = width;
2920
while (w--) {
2921
if (*gfxDataPtr > 0)
2922
*frameBufferPtr = activePalette[*gfxDataPtr];
2923
++gfxDataPtr;
2924
++frameBufferPtr;
2925
}
2926
frameBufferPtr += pitch;
2927
gfxDataPtr += gfxPitch;
2928
}
2929
#endif
2930
}
2931
2932
#if RETRO_REV00
2933
void DrawSpriteClipped(int XPos, int YPos, int width, int height, int sprX, int sprY, int sheetID, int clipY)
2934
{
2935
if (width + XPos > GFX_LINESIZE)
2936
width = GFX_LINESIZE - XPos;
2937
if (XPos < 0) {
2938
sprX -= XPos;
2939
width += XPos;
2940
XPos = 0;
2941
}
2942
if (height + YPos > clipY)
2943
height = clipY - YPos;
2944
if (YPos < 0) {
2945
sprY -= YPos;
2946
height += YPos;
2947
YPos = 0;
2948
}
2949
if (width <= 0 || height <= 0)
2950
return;
2951
2952
GFXSurface *surface = &gfxSurface[sheetID];
2953
int pitch = GFX_LINESIZE - width;
2954
int gfxPitch = surface->width - width;
2955
byte *lineBuffer = &gfxLineBuffer[YPos];
2956
byte *gfxDataPtr = &graphicData[sprX + surface->width * sprY + surface->dataPosition];
2957
ushort *frameBufferPtr = &Engine.frameBuffer[XPos + GFX_LINESIZE * YPos];
2958
while (height--) {
2959
activePalette = fullPalette[*lineBuffer];
2960
activePalette32 = fullPalette32[*lineBuffer];
2961
lineBuffer++;
2962
int w = width;
2963
while (w--) {
2964
if (*gfxDataPtr > 0)
2965
*frameBufferPtr = activePalette[*gfxDataPtr];
2966
++gfxDataPtr;
2967
++frameBufferPtr;
2968
}
2969
frameBufferPtr += pitch;
2970
gfxDataPtr += gfxPitch;
2971
}
2972
}
2973
#endif
2974
2975
void DrawSpriteFlipped(int XPos, int YPos, int width, int height, int sprX, int sprY, int direction, int sheetID)
2976
{
2977
#if RETRO_SOFTWARE_RENDER
2978
int widthFlip = width;
2979
int heightFlip = height;
2980
2981
if (width + XPos > GFX_LINESIZE) {
2982
width = GFX_LINESIZE - XPos;
2983
}
2984
if (XPos < 0) {
2985
sprX -= XPos;
2986
width += XPos;
2987
widthFlip += XPos + XPos;
2988
XPos = 0;
2989
}
2990
if (height + YPos > SCREEN_YSIZE) {
2991
height = SCREEN_YSIZE - YPos;
2992
}
2993
if (YPos < 0) {
2994
sprY -= YPos;
2995
height += YPos;
2996
heightFlip += YPos + YPos;
2997
YPos = 0;
2998
}
2999
if (width <= 0 || height <= 0)
3000
return;
3001
3002
GFXSurface *surface = &gfxSurface[sheetID];
3003
int pitch;
3004
int gfxPitch;
3005
byte *lineBuffer;
3006
byte *gfxData;
3007
ushort *frameBufferPtr;
3008
switch (direction) {
3009
case FLIP_NONE:
3010
pitch = GFX_LINESIZE - width;
3011
gfxPitch = surface->width - width;
3012
lineBuffer = &gfxLineBuffer[YPos];
3013
gfxData = &graphicData[sprX + surface->width * sprY + surface->dataPosition];
3014
frameBufferPtr = &Engine.frameBuffer[XPos + GFX_LINESIZE * YPos];
3015
3016
while (height--) {
3017
activePalette = fullPalette[*lineBuffer];
3018
activePalette32 = fullPalette32[*lineBuffer];
3019
lineBuffer++;
3020
int w = width;
3021
while (w--) {
3022
if (*gfxData > 0)
3023
*frameBufferPtr = activePalette[*gfxData];
3024
++gfxData;
3025
++frameBufferPtr;
3026
}
3027
frameBufferPtr += pitch;
3028
gfxData += gfxPitch;
3029
}
3030
break;
3031
case FLIP_X:
3032
pitch = GFX_LINESIZE - width;
3033
gfxPitch = width + surface->width;
3034
lineBuffer = &gfxLineBuffer[YPos];
3035
gfxData = &graphicData[widthFlip - 1 + sprX + surface->width * sprY + surface->dataPosition];
3036
frameBufferPtr = &Engine.frameBuffer[XPos + GFX_LINESIZE * YPos];
3037
while (height--) {
3038
activePalette = fullPalette[*lineBuffer];
3039
activePalette32 = fullPalette32[*lineBuffer];
3040
lineBuffer++;
3041
int w = width;
3042
while (w--) {
3043
if (*gfxData > 0)
3044
*frameBufferPtr = activePalette[*gfxData];
3045
--gfxData;
3046
++frameBufferPtr;
3047
}
3048
frameBufferPtr += pitch;
3049
gfxData += gfxPitch;
3050
}
3051
break;
3052
case FLIP_Y:
3053
pitch = GFX_LINESIZE - width;
3054
gfxPitch = width + surface->width;
3055
lineBuffer = &gfxLineBuffer[YPos];
3056
gfxData = &graphicData[sprX + surface->width * (sprY + heightFlip - 1) + surface->dataPosition];
3057
frameBufferPtr = &Engine.frameBuffer[XPos + GFX_LINESIZE * YPos];
3058
while (height--) {
3059
activePalette = fullPalette[*lineBuffer];
3060
activePalette32 = fullPalette32[*lineBuffer];
3061
lineBuffer++;
3062
int w = width;
3063
while (w--) {
3064
if (*gfxData > 0)
3065
*frameBufferPtr = activePalette[*gfxData];
3066
++gfxData;
3067
++frameBufferPtr;
3068
}
3069
frameBufferPtr += pitch;
3070
gfxData -= gfxPitch;
3071
}
3072
break;
3073
case FLIP_XY:
3074
pitch = GFX_LINESIZE - width;
3075
gfxPitch = surface->width - width;
3076
lineBuffer = &gfxLineBuffer[YPos];
3077
gfxData = &graphicData[widthFlip - 1 + sprX + surface->width * (sprY + heightFlip - 1) + surface->dataPosition];
3078
frameBufferPtr = &Engine.frameBuffer[XPos + GFX_LINESIZE * YPos];
3079
while (height--) {
3080
activePalette = fullPalette[*lineBuffer];
3081
activePalette32 = fullPalette32[*lineBuffer];
3082
lineBuffer++;
3083
int w = width;
3084
while (w--) {
3085
if (*gfxData > 0)
3086
*frameBufferPtr = activePalette[*gfxData];
3087
--gfxData;
3088
++frameBufferPtr;
3089
}
3090
frameBufferPtr += pitch;
3091
gfxData -= gfxPitch;
3092
}
3093
break;
3094
default: break;
3095
}
3096
#endif
3097
}
3098
void DrawSpriteScaled(int direction, int XPos, int YPos, int pivotX, int pivotY, int scaleX, int scaleY, int width, int height, int sprX, int sprY,
3099
int sheetID)
3100
{
3101
#if RETRO_SOFTWARE_RENDER
3102
int roundedYPos = 0;
3103
int roundedXPos = 0;
3104
int truescaleX = 4 * scaleX;
3105
int truescaleY = 4 * scaleY;
3106
int widthM1 = width - 1;
3107
int trueXPos = XPos - (truescaleX * pivotX >> 11);
3108
width = truescaleX * width >> 11;
3109
int trueYPos = YPos - (truescaleY * pivotY >> 11);
3110
height = truescaleY * height >> 11;
3111
int finalscaleX = (signed int)(float)((float)(2048.0 / (float)truescaleX) * 2048.0);
3112
int finalscaleY = (signed int)(float)((float)(2048.0 / (float)truescaleY) * 2048.0);
3113
if (width + trueXPos > GFX_LINESIZE) {
3114
width = GFX_LINESIZE - trueXPos;
3115
}
3116
3117
if (direction) {
3118
if (trueXPos < 0) {
3119
widthM1 -= trueXPos * -finalscaleX >> 11;
3120
roundedXPos = (ushort)trueXPos * -(short)finalscaleX & 0x7FF;
3121
width += trueXPos;
3122
trueXPos = 0;
3123
}
3124
}
3125
else if (trueXPos < 0) {
3126
sprX += trueXPos * -finalscaleX >> 11;
3127
roundedXPos = (ushort)trueXPos * -(short)finalscaleX & 0x7FF;
3128
width += trueXPos;
3129
trueXPos = 0;
3130
}
3131
3132
if (height + trueYPos > SCREEN_YSIZE) {
3133
height = SCREEN_YSIZE - trueYPos;
3134
}
3135
if (trueYPos < 0) {
3136
sprY += trueYPos * -finalscaleY >> 11;
3137
roundedYPos = (ushort)trueYPos * -(short)finalscaleY & 0x7FF;
3138
height += trueYPos;
3139
trueYPos = 0;
3140
}
3141
3142
if (width <= 0 || height <= 0)
3143
return;
3144
3145
GFXSurface *surface = &gfxSurface[sheetID];
3146
int pitch = GFX_LINESIZE - width;
3147
int gfxwidth = surface->width;
3148
byte *lineBuffer = &gfxLineBuffer[trueYPos];
3149
byte *gfxData = &graphicData[sprX + surface->width * sprY + surface->dataPosition];
3150
ushort *frameBufferPtr = &Engine.frameBuffer[trueXPos + GFX_LINESIZE * trueYPos];
3151
if (direction == FLIP_X) {
3152
byte *gfxDataPtr = &gfxData[widthM1];
3153
int gfxPitch = 0;
3154
while (height--) {
3155
activePalette = fullPalette[*lineBuffer];
3156
activePalette32 = fullPalette32[*lineBuffer];
3157
lineBuffer++;
3158
int roundXPos = roundedXPos;
3159
int w = width;
3160
while (w--) {
3161
if (*gfxDataPtr > 0)
3162
*frameBufferPtr = activePalette[*gfxDataPtr];
3163
int offsetX = finalscaleX + roundXPos;
3164
gfxDataPtr -= offsetX >> 11;
3165
gfxPitch += offsetX >> 11;
3166
roundXPos = offsetX & 0x7FF;
3167
++frameBufferPtr;
3168
}
3169
frameBufferPtr += pitch;
3170
int offsetY = finalscaleY + roundedYPos;
3171
gfxDataPtr += gfxPitch + (offsetY >> 11) * gfxwidth;
3172
roundedYPos = offsetY & 0x7FF;
3173
gfxPitch = 0;
3174
}
3175
}
3176
else {
3177
int gfxPitch = 0;
3178
int h = height;
3179
while (h--) {
3180
activePalette = fullPalette[*lineBuffer];
3181
activePalette32 = fullPalette32[*lineBuffer];
3182
lineBuffer++;
3183
int roundXPos = roundedXPos;
3184
int w = width;
3185
while (w--) {
3186
if (*gfxData > 0)
3187
*frameBufferPtr = activePalette[*gfxData];
3188
int offsetX = finalscaleX + roundXPos;
3189
gfxData += offsetX >> 11;
3190
gfxPitch += offsetX >> 11;
3191
roundXPos = offsetX & 0x7FF;
3192
++frameBufferPtr;
3193
}
3194
frameBufferPtr += pitch;
3195
int offsetY = finalscaleY + roundedYPos;
3196
gfxData += (offsetY >> 11) * gfxwidth - gfxPitch;
3197
roundedYPos = offsetY & 0x7FF;
3198
gfxPitch = 0;
3199
}
3200
}
3201
#endif
3202
}
3203
#if !RETRO_REV02
3204
void DrawScaledChar(int direction, int XPos, int YPos, int pivotX, int pivotY, int scaleX, int scaleY, int width, int height, int sprX, int sprY,
3205
int sheetID)
3206
{
3207
#if RETRO_SOFTWARE_RENDER
3208
// Not avaliable in SW Render mode
3209
#endif
3210
}
3211
#endif
3212
void DrawSpriteRotated(int direction, int XPos, int YPos, int pivotX, int pivotY, int sprX, int sprY, int width, int height, int rotation,
3213
int sheetID)
3214
{
3215
#if RETRO_SOFTWARE_RENDER
3216
int sprXPos = (pivotX + sprX) << 9;
3217
int sprYPos = (pivotY + sprY) << 9;
3218
int fullwidth = width + sprX;
3219
int fullheight = height + sprY;
3220
int angle = rotation & 0x1FF;
3221
if (angle < 0)
3222
angle += 0x200;
3223
if (angle)
3224
angle = 0x200 - angle;
3225
int sine = sin512LookupTable[angle];
3226
int cosine = cos512LookupTable[angle];
3227
int xPositions[4];
3228
int yPositions[4];
3229
3230
if (direction == FLIP_X) {
3231
xPositions[0] = XPos + ((sine * (-pivotY - 2) + cosine * (pivotX + 2)) >> 9);
3232
yPositions[0] = YPos + ((cosine * (-pivotY - 2) - sine * (pivotX + 2)) >> 9);
3233
xPositions[1] = XPos + ((sine * (-pivotY - 2) + cosine * (pivotX - width - 2)) >> 9);
3234
yPositions[1] = YPos + ((cosine * (-pivotY - 2) - sine * (pivotX - width - 2)) >> 9);
3235
xPositions[2] = XPos + ((sine * (height - pivotY + 2) + cosine * (pivotX + 2)) >> 9);
3236
yPositions[2] = YPos + ((cosine * (height - pivotY + 2) - sine * (pivotX + 2)) >> 9);
3237
int a = pivotX - width - 2;
3238
int b = height - pivotY + 2;
3239
xPositions[3] = XPos + ((sine * b + cosine * a) >> 9);
3240
yPositions[3] = YPos + ((cosine * b - sine * a) >> 9);
3241
}
3242
else {
3243
xPositions[0] = XPos + ((sine * (-pivotY - 2) + cosine * (-pivotX - 2)) >> 9);
3244
yPositions[0] = YPos + ((cosine * (-pivotY - 2) - sine * (-pivotX - 2)) >> 9);
3245
xPositions[1] = XPos + ((sine * (-pivotY - 2) + cosine * (width - pivotX + 2)) >> 9);
3246
yPositions[1] = YPos + ((cosine * (-pivotY - 2) - sine * (width - pivotX + 2)) >> 9);
3247
xPositions[2] = XPos + ((sine * (height - pivotY + 2) + cosine * (-pivotX - 2)) >> 9);
3248
yPositions[2] = YPos + ((cosine * (height - pivotY + 2) - sine * (-pivotX - 2)) >> 9);
3249
int a = width - pivotX + 2;
3250
int b = height - pivotY + 2;
3251
xPositions[3] = XPos + ((sine * b + cosine * a) >> 9);
3252
yPositions[3] = YPos + ((cosine * b - sine * a) >> 9);
3253
}
3254
3255
int left = GFX_LINESIZE;
3256
for (int i = 0; i < 4; ++i) {
3257
if (xPositions[i] < left)
3258
left = xPositions[i];
3259
}
3260
if (left < 0)
3261
left = 0;
3262
3263
int right = 0;
3264
for (int i = 0; i < 4; ++i) {
3265
if (xPositions[i] > right)
3266
right = xPositions[i];
3267
}
3268
if (right > GFX_LINESIZE)
3269
right = GFX_LINESIZE;
3270
int maxX = right - left;
3271
3272
int top = SCREEN_YSIZE;
3273
for (int i = 0; i < 4; ++i) {
3274
if (yPositions[i] < top)
3275
top = yPositions[i];
3276
}
3277
if (top < 0)
3278
top = 0;
3279
3280
int bottom = 0;
3281
for (int i = 0; i < 4; ++i) {
3282
if (yPositions[i] > bottom)
3283
bottom = yPositions[i];
3284
}
3285
if (bottom > SCREEN_YSIZE)
3286
bottom = SCREEN_YSIZE;
3287
int maxY = bottom - top;
3288
3289
if (maxX <= 0 || maxY <= 0)
3290
return;
3291
3292
GFXSurface *surface = &gfxSurface[sheetID];
3293
int pitch = GFX_LINESIZE - maxX;
3294
int lineSize = surface->widthShift;
3295
ushort *frameBufferPtr = &Engine.frameBuffer[left + GFX_LINESIZE * top];
3296
byte *lineBuffer = &gfxLineBuffer[top];
3297
int startX = left - XPos;
3298
int startY = top - YPos;
3299
int shiftPivot = (sprX << 9) - 1;
3300
fullwidth <<= 9;
3301
int shiftheight = (sprY << 9) - 1;
3302
fullheight <<= 9;
3303
byte *gfxData = &graphicData[surface->dataPosition];
3304
if (cosine < 0 || sine < 0)
3305
sprYPos += sine + cosine;
3306
3307
if (direction == FLIP_X) {
3308
int drawX = sprXPos - (cosine * startX - sine * startY) - 0x100;
3309
int drawY = cosine * startY + sprYPos + sine * startX;
3310
while (maxY--) {
3311
activePalette = fullPalette[*lineBuffer];
3312
activePalette32 = fullPalette32[*lineBuffer];
3313
lineBuffer++;
3314
int finalX = drawX;
3315
int finalY = drawY;
3316
int w = maxX;
3317
while (w--) {
3318
if (finalX > shiftPivot && finalX < fullwidth && finalY > shiftheight && finalY < fullheight) {
3319
byte index = gfxData[(finalY >> 9 << lineSize) + (finalX >> 9)];
3320
if (index > 0)
3321
*frameBufferPtr = activePalette[index];
3322
}
3323
++frameBufferPtr;
3324
finalX -= cosine;
3325
finalY += sine;
3326
}
3327
drawX += sine;
3328
drawY += cosine;
3329
frameBufferPtr += pitch;
3330
}
3331
}
3332
else {
3333
int drawX = sprXPos + cosine * startX - sine * startY;
3334
int drawY = cosine * startY + sprYPos + sine * startX;
3335
while (maxY--) {
3336
activePalette = fullPalette[*lineBuffer];
3337
activePalette32 = fullPalette32[*lineBuffer];
3338
lineBuffer++;
3339
int finalX = drawX;
3340
int finalY = drawY;
3341
int w = maxX;
3342
while (w--) {
3343
if (finalX > shiftPivot && finalX < fullwidth && finalY > shiftheight && finalY < fullheight) {
3344
byte index = gfxData[(finalY >> 9 << lineSize) + (finalX >> 9)];
3345
if (index > 0)
3346
*frameBufferPtr = activePalette[index];
3347
}
3348
++frameBufferPtr;
3349
finalX += cosine;
3350
finalY += sine;
3351
}
3352
drawX -= sine;
3353
drawY += cosine;
3354
frameBufferPtr += pitch;
3355
}
3356
}
3357
#endif
3358
}
3359
3360
void DrawSpriteRotozoom(int direction, int XPos, int YPos, int pivotX, int pivotY, int sprX, int sprY, int width, int height, int rotation, int scale,
3361
int sheetID)
3362
{
3363
#if RETRO_SOFTWARE_RENDER
3364
if (scale == 0)
3365
return;
3366
3367
int sprXPos = (pivotX + sprX) << 9;
3368
int sprYPos = (pivotY + sprY) << 9;
3369
int fullwidth = width + sprX;
3370
int fullheight = height + sprY;
3371
int angle = rotation & 0x1FF;
3372
if (angle < 0)
3373
angle += 0x200;
3374
if (angle)
3375
angle = 0x200 - angle;
3376
int sine = scale * sin512LookupTable[angle] >> 9;
3377
int cosine = scale * cos512LookupTable[angle] >> 9;
3378
int xPositions[4];
3379
int yPositions[4];
3380
3381
if (direction == FLIP_X) {
3382
xPositions[0] = XPos + ((sine * (-pivotY - 2) + cosine * (pivotX + 2)) >> 9);
3383
yPositions[0] = YPos + ((cosine * (-pivotY - 2) - sine * (pivotX + 2)) >> 9);
3384
xPositions[1] = XPos + ((sine * (-pivotY - 2) + cosine * (pivotX - width - 2)) >> 9);
3385
yPositions[1] = YPos + ((cosine * (-pivotY - 2) - sine * (pivotX - width - 2)) >> 9);
3386
xPositions[2] = XPos + ((sine * (height - pivotY + 2) + cosine * (pivotX + 2)) >> 9);
3387
yPositions[2] = YPos + ((cosine * (height - pivotY + 2) - sine * (pivotX + 2)) >> 9);
3388
int a = pivotX - width - 2;
3389
int b = height - pivotY + 2;
3390
xPositions[3] = XPos + ((sine * b + cosine * a) >> 9);
3391
yPositions[3] = YPos + ((cosine * b - sine * a) >> 9);
3392
}
3393
else {
3394
xPositions[0] = XPos + ((sine * (-pivotY - 2) + cosine * (-pivotX - 2)) >> 9);
3395
yPositions[0] = YPos + ((cosine * (-pivotY - 2) - sine * (-pivotX - 2)) >> 9);
3396
xPositions[1] = XPos + ((sine * (-pivotY - 2) + cosine * (width - pivotX + 2)) >> 9);
3397
yPositions[1] = YPos + ((cosine * (-pivotY - 2) - sine * (width - pivotX + 2)) >> 9);
3398
xPositions[2] = XPos + ((sine * (height - pivotY + 2) + cosine * (-pivotX - 2)) >> 9);
3399
yPositions[2] = YPos + ((cosine * (height - pivotY + 2) - sine * (-pivotX - 2)) >> 9);
3400
int a = width - pivotX + 2;
3401
int b = height - pivotY + 2;
3402
xPositions[3] = XPos + ((sine * b + cosine * a) >> 9);
3403
yPositions[3] = YPos + ((cosine * b - sine * a) >> 9);
3404
}
3405
int truescale = (signed int)(float)((float)(512.0 / (float)scale) * 512.0);
3406
sine = truescale * sin512LookupTable[angle] >> 9;
3407
cosine = truescale * cos512LookupTable[angle] >> 9;
3408
3409
int left = GFX_LINESIZE;
3410
for (int i = 0; i < 4; ++i) {
3411
if (xPositions[i] < left)
3412
left = xPositions[i];
3413
}
3414
if (left < 0)
3415
left = 0;
3416
3417
int right = 0;
3418
for (int i = 0; i < 4; ++i) {
3419
if (xPositions[i] > right)
3420
right = xPositions[i];
3421
}
3422
if (right > GFX_LINESIZE)
3423
right = GFX_LINESIZE;
3424
int maxX = right - left;
3425
3426
int top = SCREEN_YSIZE;
3427
for (int i = 0; i < 4; ++i) {
3428
if (yPositions[i] < top)
3429
top = yPositions[i];
3430
}
3431
if (top < 0)
3432
top = 0;
3433
3434
int bottom = 0;
3435
for (int i = 0; i < 4; ++i) {
3436
if (yPositions[i] > bottom)
3437
bottom = yPositions[i];
3438
}
3439
if (bottom > SCREEN_YSIZE)
3440
bottom = SCREEN_YSIZE;
3441
int maxY = bottom - top;
3442
3443
if (maxX <= 0 || maxY <= 0)
3444
return;
3445
3446
GFXSurface *surface = &gfxSurface[sheetID];
3447
int pitch = GFX_LINESIZE - maxX;
3448
int lineSize = surface->widthShift;
3449
ushort *frameBufferPtr = &Engine.frameBuffer[left + GFX_LINESIZE * top];
3450
byte *lineBuffer = &gfxLineBuffer[top];
3451
int startX = left - XPos;
3452
int startY = top - YPos;
3453
int shiftPivot = (sprX << 9) - 1;
3454
fullwidth <<= 9;
3455
int shiftheight = (sprY << 9) - 1;
3456
fullheight <<= 9;
3457
byte *gfxData = &graphicData[surface->dataPosition];
3458
if (cosine < 0 || sine < 0)
3459
sprYPos += sine + cosine;
3460
3461
if (direction == FLIP_X) {
3462
int drawX = sprXPos - (cosine * startX - sine * startY) - (truescale >> 1);
3463
int drawY = cosine * startY + sprYPos + sine * startX;
3464
while (maxY--) {
3465
activePalette = fullPalette[*lineBuffer];
3466
activePalette32 = fullPalette32[*lineBuffer];
3467
lineBuffer++;
3468
int finalX = drawX;
3469
int finalY = drawY;
3470
int w = maxX;
3471
while (w--) {
3472
if (finalX > shiftPivot && finalX < fullwidth && finalY > shiftheight && finalY < fullheight) {
3473
byte index = gfxData[(finalY >> 9 << lineSize) + (finalX >> 9)];
3474
if (index > 0)
3475
*frameBufferPtr = activePalette[index];
3476
}
3477
++frameBufferPtr;
3478
finalX -= cosine;
3479
finalY += sine;
3480
}
3481
drawX += sine;
3482
drawY += cosine;
3483
frameBufferPtr += pitch;
3484
}
3485
}
3486
else {
3487
int drawX = sprXPos + cosine * startX - sine * startY;
3488
int drawY = cosine * startY + sprYPos + sine * startX;
3489
while (maxY--) {
3490
activePalette = fullPalette[*lineBuffer];
3491
activePalette32 = fullPalette32[*lineBuffer];
3492
lineBuffer++;
3493
int finalX = drawX;
3494
int finalY = drawY;
3495
int w = maxX;
3496
while (w--) {
3497
if (finalX > shiftPivot && finalX < fullwidth && finalY > shiftheight && finalY < fullheight) {
3498
byte index = gfxData[(finalY >> 9 << lineSize) + (finalX >> 9)];
3499
if (index > 0)
3500
*frameBufferPtr = activePalette[index];
3501
}
3502
++frameBufferPtr;
3503
finalX += cosine;
3504
finalY += sine;
3505
}
3506
drawX -= sine;
3507
drawY += cosine;
3508
frameBufferPtr += pitch;
3509
}
3510
}
3511
#endif
3512
}
3513
3514
void DrawBlendedSprite(int XPos, int YPos, int width, int height, int sprX, int sprY, int sheetID)
3515
{
3516
#if RETRO_SOFTWARE_RENDER
3517
if (width + XPos > GFX_LINESIZE)
3518
width = GFX_LINESIZE - XPos;
3519
if (XPos < 0) {
3520
sprX -= XPos;
3521
width += XPos;
3522
XPos = 0;
3523
}
3524
if (height + YPos > SCREEN_YSIZE)
3525
height = SCREEN_YSIZE - YPos;
3526
if (YPos < 0) {
3527
sprY -= YPos;
3528
height += YPos;
3529
YPos = 0;
3530
}
3531
if (width <= 0 || height <= 0)
3532
return;
3533
3534
GFXSurface *surface = &gfxSurface[sheetID];
3535
int pitch = GFX_LINESIZE - width;
3536
int gfxPitch = surface->width - width;
3537
byte *lineBuffer = &gfxLineBuffer[YPos];
3538
byte *gfxData = &graphicData[sprX + surface->width * sprY + surface->dataPosition];
3539
ushort *frameBufferPtr = &Engine.frameBuffer[XPos + GFX_LINESIZE * YPos];
3540
while (height--) {
3541
activePalette = fullPalette[*lineBuffer];
3542
activePalette32 = fullPalette32[*lineBuffer];
3543
lineBuffer++;
3544
int w = width;
3545
while (w--) {
3546
if (*gfxData > 0)
3547
*frameBufferPtr = ((activePalette[*gfxData] & 0xF7DE) >> 1) + ((*frameBufferPtr & 0xF7DE) >> 1);
3548
++gfxData;
3549
++frameBufferPtr;
3550
}
3551
frameBufferPtr += pitch;
3552
gfxData += gfxPitch;
3553
}
3554
#endif
3555
}
3556
void DrawAlphaBlendedSprite(int XPos, int YPos, int width, int height, int sprX, int sprY, int alpha, int sheetID)
3557
{
3558
if (alpha > 0xFF)
3559
alpha = 0xFF;
3560
#if RETRO_SOFTWARE_RENDER
3561
if (width + XPos > GFX_LINESIZE)
3562
width = GFX_LINESIZE - XPos;
3563
if (XPos < 0) {
3564
sprX -= XPos;
3565
width += XPos;
3566
XPos = 0;
3567
}
3568
if (height + YPos > SCREEN_YSIZE)
3569
height = SCREEN_YSIZE - YPos;
3570
if (YPos < 0) {
3571
sprY -= YPos;
3572
height += YPos;
3573
YPos = 0;
3574
}
3575
if (width <= 0 || height <= 0 || alpha <= 0)
3576
return;
3577
3578
GFXSurface *surface = &gfxSurface[sheetID];
3579
int pitch = GFX_LINESIZE - width;
3580
int gfxPitch = surface->width - width;
3581
byte *lineBuffer = &gfxLineBuffer[YPos];
3582
byte *gfxData = &graphicData[sprX + surface->width * sprY + surface->dataPosition];
3583
ushort *frameBufferPtr = &Engine.frameBuffer[XPos + GFX_LINESIZE * YPos];
3584
if (alpha == 0xFF) {
3585
while (height--) {
3586
activePalette = fullPalette[*lineBuffer];
3587
activePalette32 = fullPalette32[*lineBuffer];
3588
lineBuffer++;
3589
int w = width;
3590
while (w--) {
3591
if (*gfxData > 0)
3592
*frameBufferPtr = activePalette[*gfxData];
3593
++gfxData;
3594
++frameBufferPtr;
3595
}
3596
frameBufferPtr += pitch;
3597
gfxData += gfxPitch;
3598
}
3599
}
3600
else {
3601
ushort *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
3602
ushort *pixelBlend = &blendLookupTable[0x20 * alpha];
3603
3604
while (height--) {
3605
activePalette = fullPalette[*lineBuffer];
3606
activePalette32 = fullPalette32[*lineBuffer];
3607
lineBuffer++;
3608
int w = width;
3609
while (w--) {
3610
if (*gfxData > 0) {
3611
ushort color = activePalette[*gfxData];
3612
3613
int R = (fbufferBlend[(*frameBufferPtr & 0xF800) >> 11] + pixelBlend[(color & 0xF800) >> 11]) << 11;
3614
int G = (fbufferBlend[(*frameBufferPtr & 0x7E0) >> 6] + pixelBlend[(color & 0x7E0) >> 6]) << 6;
3615
int B = fbufferBlend[*frameBufferPtr & 0x1F] + pixelBlend[color & 0x1F];
3616
3617
*frameBufferPtr = R | G | B;
3618
}
3619
++gfxData;
3620
++frameBufferPtr;
3621
}
3622
frameBufferPtr += pitch;
3623
gfxData += gfxPitch;
3624
}
3625
}
3626
#endif
3627
}
3628
void DrawAdditiveBlendedSprite(int XPos, int YPos, int width, int height, int sprX, int sprY, int alpha, int sheetID)
3629
{
3630
if (alpha > 0xFF)
3631
alpha = 0xFF;
3632
#if RETRO_SOFTWARE_RENDER
3633
if (width + XPos > GFX_LINESIZE)
3634
width = GFX_LINESIZE - XPos;
3635
if (XPos < 0) {
3636
sprX -= XPos;
3637
width += XPos;
3638
XPos = 0;
3639
}
3640
if (height + YPos > SCREEN_YSIZE)
3641
height = SCREEN_YSIZE - YPos;
3642
if (YPos < 0) {
3643
sprY -= YPos;
3644
height += YPos;
3645
YPos = 0;
3646
}
3647
if (width <= 0 || height <= 0 || alpha <= 0)
3648
return;
3649
3650
ushort *blendTablePtr = &blendLookupTable[0x20 * alpha];
3651
GFXSurface *surface = &gfxSurface[sheetID];
3652
int pitch = GFX_LINESIZE - width;
3653
int gfxPitch = surface->width - width;
3654
byte *lineBuffer = &gfxLineBuffer[YPos];
3655
byte *gfxData = &graphicData[sprX + surface->width * sprY + surface->dataPosition];
3656
ushort *frameBufferPtr = &Engine.frameBuffer[XPos + GFX_LINESIZE * YPos];
3657
3658
while (height--) {
3659
activePalette = fullPalette[*lineBuffer];
3660
activePalette32 = fullPalette32[*lineBuffer];
3661
lineBuffer++;
3662
int w = width;
3663
while (w--) {
3664
if (*gfxData > 0) {
3665
ushort color = activePalette[*gfxData];
3666
3667
int R = minVal((blendTablePtr[(color & 0xF800) >> 11] << 11) + (*frameBufferPtr & 0xF800), 0xF800);
3668
int G = minVal((blendTablePtr[(color & 0x7E0) >> 6] << 6) + (*frameBufferPtr & 0x7E0), 0x7E0);
3669
int B = minVal(blendTablePtr[color & 0x1F] + (*frameBufferPtr & 0x1F), 0x1F);
3670
3671
*frameBufferPtr = R | G | B;
3672
}
3673
++gfxData;
3674
++frameBufferPtr;
3675
}
3676
frameBufferPtr += pitch;
3677
gfxData += gfxPitch;
3678
}
3679
#endif
3680
}
3681
void DrawSubtractiveBlendedSprite(int XPos, int YPos, int width, int height, int sprX, int sprY, int alpha, int sheetID)
3682
{
3683
if (alpha > 0xFF)
3684
alpha = 0xFF;
3685
3686
#if RETRO_SOFTWARE_RENDER
3687
if (width + XPos > GFX_LINESIZE)
3688
width = GFX_LINESIZE - XPos;
3689
if (XPos < 0) {
3690
sprX -= XPos;
3691
width += XPos;
3692
XPos = 0;
3693
}
3694
if (height + YPos > SCREEN_YSIZE)
3695
height = SCREEN_YSIZE - YPos;
3696
if (YPos < 0) {
3697
sprY -= YPos;
3698
height += YPos;
3699
YPos = 0;
3700
}
3701
if (width <= 0 || height <= 0 || alpha <= 0)
3702
return;
3703
3704
ushort *subBlendTable = &subtractLookupTable[0x20 * alpha];
3705
GFXSurface *surface = &gfxSurface[sheetID];
3706
int pitch = GFX_LINESIZE - width;
3707
int gfxPitch = surface->width - width;
3708
byte *lineBuffer = &gfxLineBuffer[YPos];
3709
byte *gfxData = &graphicData[sprX + surface->width * sprY + surface->dataPosition];
3710
ushort *frameBufferPtr = &Engine.frameBuffer[XPos + GFX_LINESIZE * YPos];
3711
3712
while (height--) {
3713
activePalette = fullPalette[*lineBuffer];
3714
activePalette32 = fullPalette32[*lineBuffer];
3715
lineBuffer++;
3716
int w = width;
3717
while (w--) {
3718
if (*gfxData > 0) {
3719
ushort color = activePalette[*gfxData];
3720
3721
int R = maxVal((*frameBufferPtr & 0xF800) - (subBlendTable[(color & 0xF800) >> 11] << 11), 0);
3722
int G = maxVal((*frameBufferPtr & 0x7E0) - (subBlendTable[(color & 0x7E0) >> 6] << 6), 0);
3723
int B = maxVal((*frameBufferPtr & 0x1F) - subBlendTable[color & 0x1F], 0);
3724
3725
*frameBufferPtr = R | G | B;
3726
}
3727
++gfxData;
3728
++frameBufferPtr;
3729
}
3730
frameBufferPtr += pitch;
3731
gfxData += gfxPitch;
3732
}
3733
#endif
3734
}
3735
3736
void DrawObjectAnimation(void *objScr, void *ent, int XPos, int YPos)
3737
{
3738
ObjectScript *objectScript = (ObjectScript *)objScr;
3739
Entity *entity = (Entity *)ent;
3740
SpriteAnimation *sprAnim = &animationList[objectScript->animFile->aniListOffset + entity->animation];
3741
SpriteFrame *frame = &animFrames[sprAnim->frameListOffset + entity->frame];
3742
int rotation = 0;
3743
3744
switch (sprAnim->rotationStyle) {
3745
case ROTSTYLE_NONE:
3746
switch (entity->direction) {
3747
case FLIP_NONE:
3748
DrawSpriteFlipped(frame->pivotX + XPos, frame->pivotY + YPos, frame->width, frame->height, frame->sprX, frame->sprY, FLIP_NONE,
3749
frame->sheetID);
3750
break;
3751
3752
case FLIP_X:
3753
DrawSpriteFlipped(XPos - frame->width - frame->pivotX, frame->pivotY + YPos, frame->width, frame->height, frame->sprX,
3754
frame->sprY, FLIP_X, frame->sheetID);
3755
break;
3756
case FLIP_Y:
3757
3758
DrawSpriteFlipped(frame->pivotX + XPos, YPos - frame->height - frame->pivotY, frame->width, frame->height, frame->sprX,
3759
frame->sprY, FLIP_Y, frame->sheetID);
3760
break;
3761
3762
case FLIP_XY:
3763
DrawSpriteFlipped(XPos - frame->width - frame->pivotX, YPos - frame->height - frame->pivotY, frame->width, frame->height,
3764
frame->sprX, frame->sprY, FLIP_XY, frame->sheetID);
3765
break;
3766
3767
default: break;
3768
}
3769
break;
3770
3771
case ROTSTYLE_FULL:
3772
DrawSpriteRotated(entity->direction, XPos, YPos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY, frame->width, frame->height,
3773
entity->rotation, frame->sheetID);
3774
break;
3775
3776
case ROTSTYLE_45DEG:
3777
if (entity->rotation >= 0x100)
3778
DrawSpriteRotated(entity->direction, XPos, YPos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY, frame->width,
3779
frame->height, 0x200 - ((0x214 - entity->rotation) >> 6 << 6), frame->sheetID);
3780
else
3781
DrawSpriteRotated(entity->direction, XPos, YPos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY, frame->width,
3782
frame->height, (entity->rotation + 20) >> 6 << 6, frame->sheetID);
3783
break;
3784
3785
case ROTSTYLE_STATICFRAMES: {
3786
if (entity->rotation >= 0x100)
3787
rotation = 8 - ((532 - entity->rotation) >> 6);
3788
else
3789
rotation = (entity->rotation + 20) >> 6;
3790
int frameID = entity->frame;
3791
switch (rotation) {
3792
case 0: // 0 deg
3793
case 8: // 360 deg
3794
rotation = 0x00;
3795
break;
3796
3797
case 1: // 45 deg
3798
frameID += sprAnim->frameCount;
3799
if (entity->direction)
3800
rotation = 0;
3801
else
3802
rotation = 0x80;
3803
break;
3804
3805
case 2: // 90 deg
3806
rotation = 0x80;
3807
break;
3808
3809
case 3: // 135 deg
3810
frameID += sprAnim->frameCount;
3811
if (entity->direction)
3812
rotation = 0x80;
3813
else
3814
rotation = 0x100;
3815
break;
3816
3817
case 4: // 180 deg
3818
rotation = 0x100;
3819
break;
3820
3821
case 5: // 225 deg
3822
frameID += sprAnim->frameCount;
3823
if (entity->direction)
3824
rotation = 0x100;
3825
else
3826
rotation = 384;
3827
break;
3828
3829
case 6: // 270 deg
3830
rotation = 384;
3831
break;
3832
3833
case 7: // 315 deg
3834
frameID += sprAnim->frameCount;
3835
if (entity->direction)
3836
rotation = 384;
3837
else
3838
rotation = 0;
3839
break;
3840
3841
default: break;
3842
}
3843
3844
frame = &animFrames[sprAnim->frameListOffset + frameID];
3845
DrawSpriteRotated(entity->direction, XPos, YPos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY, frame->width, frame->height,
3846
rotation, frame->sheetID);
3847
// DrawSpriteRotozoom(entity->direction, XPos, YPos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY, frame->width,
3848
// frame->height,
3849
// rotation, entity->scale, frame->sheetID);
3850
break;
3851
}
3852
3853
default: break;
3854
}
3855
}
3856
3857
void DrawFace(void *v, uint color)
3858
{
3859
Vertex *verts = (Vertex *)v;
3860
int alpha = (color & 0x7F000000) >> 23;
3861
if (alpha < 1)
3862
return;
3863
3864
if (alpha > 0xFF)
3865
alpha = 0xFF;
3866
3867
if (verts[0].x < 0 && verts[1].x < 0 && verts[2].x < 0 && verts[3].x < 0)
3868
return;
3869
3870
if (verts[0].x > GFX_LINESIZE && verts[1].x > GFX_LINESIZE && verts[2].x > GFX_LINESIZE && verts[3].x > GFX_LINESIZE)
3871
return;
3872
3873
if (verts[0].y < 0 && verts[1].y < 0 && verts[2].y < 0 && verts[3].y < 0)
3874
return;
3875
3876
if (verts[0].y > SCREEN_YSIZE && verts[1].y > SCREEN_YSIZE && verts[2].y > SCREEN_YSIZE && verts[3].y > SCREEN_YSIZE)
3877
return;
3878
3879
if (verts[0].x == verts[1].x && verts[1].x == verts[2].x && verts[2].x == verts[3].x)
3880
return;
3881
3882
if (verts[0].y == verts[1].y && verts[1].y == verts[2].y && verts[2].y == verts[3].y)
3883
return;
3884
3885
#if RETRO_SOFTWARE_RENDER
3886
int vertexA = 0;
3887
int vertexB = 1;
3888
int vertexC = 2;
3889
int vertexD = 3;
3890
if (verts[1].y < verts[0].y) {
3891
vertexA = 1;
3892
vertexB = 0;
3893
}
3894
if (verts[2].y < verts[vertexA].y) {
3895
int temp = vertexA;
3896
vertexA = 2;
3897
vertexC = temp;
3898
}
3899
if (verts[3].y < verts[vertexA].y) {
3900
int temp = vertexA;
3901
vertexA = 3;
3902
vertexD = temp;
3903
}
3904
if (verts[vertexC].y < verts[vertexB].y) {
3905
int temp = vertexB;
3906
vertexB = vertexC;
3907
vertexC = temp;
3908
}
3909
if (verts[vertexD].y < verts[vertexB].y) {
3910
int temp = vertexB;
3911
vertexB = vertexD;
3912
vertexD = temp;
3913
}
3914
if (verts[vertexD].y < verts[vertexC].y) {
3915
int temp = vertexC;
3916
vertexC = vertexD;
3917
vertexD = temp;
3918
}
3919
3920
int faceTop = verts[vertexA].y;
3921
int faceBottom = verts[vertexD].y;
3922
if (faceTop < 0)
3923
faceTop = 0;
3924
if (faceBottom > SCREEN_YSIZE)
3925
faceBottom = SCREEN_YSIZE;
3926
for (int i = faceTop; i < faceBottom; ++i) {
3927
faceLineStart[i] = 100000;
3928
faceLineEnd[i] = -100000;
3929
}
3930
3931
ProcessScanEdge(&verts[vertexA], &verts[vertexB]);
3932
ProcessScanEdge(&verts[vertexA], &verts[vertexC]);
3933
ProcessScanEdge(&verts[vertexA], &verts[vertexD]);
3934
ProcessScanEdge(&verts[vertexB], &verts[vertexC]);
3935
ProcessScanEdge(&verts[vertexC], &verts[vertexD]);
3936
ProcessScanEdge(&verts[vertexB], &verts[vertexD]);
3937
3938
ushort color16 = PACK_RGB888(((color >> 16) & 0xFF), ((color >> 8) & 0xFF), ((color >> 0) & 0xFF));
3939
3940
ushort *frameBufferPtr = &Engine.frameBuffer[GFX_LINESIZE * faceTop];
3941
if (alpha == 255) {
3942
while (faceTop < faceBottom) {
3943
int startX = faceLineStart[faceTop];
3944
int endX = faceLineEnd[faceTop];
3945
if (startX >= GFX_LINESIZE || endX <= 0) {
3946
frameBufferPtr += GFX_LINESIZE;
3947
}
3948
else {
3949
if (startX < 0)
3950
startX = 0;
3951
if (endX > GFX_LINESIZE_MINUSONE)
3952
endX = GFX_LINESIZE_MINUSONE;
3953
ushort *fbPtr = &frameBufferPtr[startX];
3954
frameBufferPtr += GFX_LINESIZE;
3955
int vertexwidth = endX - startX + 1;
3956
while (vertexwidth--) {
3957
*fbPtr = color16;
3958
++fbPtr;
3959
}
3960
}
3961
++faceTop;
3962
}
3963
}
3964
else {
3965
ushort *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
3966
ushort *pixelBlend = &blendLookupTable[0x20 * alpha];
3967
3968
while (faceTop < faceBottom) {
3969
int startX = faceLineStart[faceTop];
3970
int endX = faceLineEnd[faceTop];
3971
if (startX >= GFX_LINESIZE || endX <= 0) {
3972
frameBufferPtr += GFX_LINESIZE;
3973
}
3974
else {
3975
if (startX < 0)
3976
startX = 0;
3977
if (endX > GFX_LINESIZE_MINUSONE)
3978
endX = GFX_LINESIZE_MINUSONE;
3979
ushort *fbPtr = &frameBufferPtr[startX];
3980
frameBufferPtr += GFX_LINESIZE;
3981
int vertexwidth = endX - startX + 1;
3982
while (vertexwidth--) {
3983
int R = (fbufferBlend[(*fbPtr & 0xF800) >> 11] + pixelBlend[(color16 & 0xF800) >> 11]) << 11;
3984
int G = (fbufferBlend[(*fbPtr & 0x7E0) >> 6] + pixelBlend[(color16 & 0x7E0) >> 6]) << 6;
3985
int B = fbufferBlend[*fbPtr & 0x1F] + pixelBlend[color16 & 0x1F];
3986
3987
*fbPtr = R | G | B;
3988
++fbPtr;
3989
}
3990
}
3991
++faceTop;
3992
}
3993
}
3994
#endif
3995
}
3996
void DrawFadedFace(void *v, uint color, uint fogColor, int alpha)
3997
{
3998
Vertex *verts = (Vertex *)v;
3999
if (alpha > 0xFF)
4000
alpha = 0xFF;
4001
4002
if (alpha < 1)
4003
return;
4004
4005
if (verts[0].x < 0 && verts[1].x < 0 && verts[2].x < 0 && verts[3].x < 0)
4006
return;
4007
4008
if (verts[0].x > GFX_LINESIZE && verts[1].x > GFX_LINESIZE && verts[2].x > GFX_LINESIZE && verts[3].x > GFX_LINESIZE)
4009
return;
4010
4011
if (verts[0].y < 0 && verts[1].y < 0 && verts[2].y < 0 && verts[3].y < 0)
4012
return;
4013
4014
if (verts[0].y > SCREEN_YSIZE && verts[1].y > SCREEN_YSIZE && verts[2].y > SCREEN_YSIZE && verts[3].y > SCREEN_YSIZE)
4015
return;
4016
4017
if (verts[0].x == verts[1].x && verts[1].x == verts[2].x && verts[2].x == verts[3].x)
4018
return;
4019
4020
if (verts[0].y == verts[1].y && verts[1].y == verts[2].y && verts[2].y == verts[3].y)
4021
return;
4022
4023
#if RETRO_SOFTWARE_RENDER
4024
int vertexA = 0;
4025
int vertexB = 1;
4026
int vertexC = 2;
4027
int vertexD = 3;
4028
if (verts[1].y < verts[0].y) {
4029
vertexA = 1;
4030
vertexB = 0;
4031
}
4032
if (verts[2].y < verts[vertexA].y) {
4033
int temp = vertexA;
4034
vertexA = 2;
4035
vertexC = temp;
4036
}
4037
if (verts[3].y < verts[vertexA].y) {
4038
int temp = vertexA;
4039
vertexA = 3;
4040
vertexD = temp;
4041
}
4042
if (verts[vertexC].y < verts[vertexB].y) {
4043
int temp = vertexB;
4044
vertexB = vertexC;
4045
vertexC = temp;
4046
}
4047
if (verts[vertexD].y < verts[vertexB].y) {
4048
int temp = vertexB;
4049
vertexB = vertexD;
4050
vertexD = temp;
4051
}
4052
if (verts[vertexD].y < verts[vertexC].y) {
4053
int temp = vertexC;
4054
vertexC = vertexD;
4055
vertexD = temp;
4056
}
4057
4058
int faceTop = verts[vertexA].y;
4059
int faceBottom = verts[vertexD].y;
4060
if (faceTop < 0)
4061
faceTop = 0;
4062
if (faceBottom > SCREEN_YSIZE)
4063
faceBottom = SCREEN_YSIZE;
4064
for (int i = faceTop; i < faceBottom; ++i) {
4065
faceLineStart[i] = 100000;
4066
faceLineEnd[i] = -100000;
4067
}
4068
4069
ProcessScanEdge(&verts[vertexA], &verts[vertexB]);
4070
ProcessScanEdge(&verts[vertexA], &verts[vertexC]);
4071
ProcessScanEdge(&verts[vertexA], &verts[vertexD]);
4072
ProcessScanEdge(&verts[vertexB], &verts[vertexC]);
4073
ProcessScanEdge(&verts[vertexC], &verts[vertexD]);
4074
ProcessScanEdge(&verts[vertexB], &verts[vertexD]);
4075
4076
ushort color16 = PACK_RGB888(((color >> 16) & 0xFF), ((color >> 8) & 0xFF), ((color >> 0) & 0xFF));
4077
ushort fogColor16 = PACK_RGB888(((fogColor >> 16) & 0xFF), ((fogColor >> 8) & 0xFF), ((fogColor >> 0) & 0xFF));
4078
4079
ushort *frameBufferPtr = &Engine.frameBuffer[GFX_LINESIZE * faceTop];
4080
ushort *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)];
4081
ushort *pixelBlend = &blendLookupTable[0x20 * alpha];
4082
4083
while (faceTop < faceBottom) {
4084
int startX = faceLineStart[faceTop];
4085
int endX = faceLineEnd[faceTop];
4086
if (startX >= GFX_LINESIZE || endX <= 0) {
4087
frameBufferPtr += GFX_LINESIZE;
4088
}
4089
else {
4090
if (startX < 0)
4091
startX = 0;
4092
if (endX > GFX_LINESIZE_MINUSONE)
4093
endX = GFX_LINESIZE_MINUSONE;
4094
ushort *fbPtr = &frameBufferPtr[startX];
4095
frameBufferPtr += GFX_LINESIZE;
4096
int vertexwidth = endX - startX + 1;
4097
while (vertexwidth--) {
4098
int R = (fbufferBlend[(fogColor16 & 0xF800) >> 11] + pixelBlend[(color16 & 0xF800) >> 11]) << 11;
4099
int G = (fbufferBlend[(fogColor16 & 0x7E0) >> 6] + pixelBlend[(color16 & 0x7E0) >> 6]) << 6;
4100
int B = fbufferBlend[fogColor16 & 0x1F] + pixelBlend[color16 & 0x1F];
4101
4102
*fbPtr = R | G | B;
4103
++fbPtr;
4104
}
4105
}
4106
++faceTop;
4107
}
4108
#endif
4109
}
4110
void DrawTexturedFace(void *v, byte sheetID)
4111
{
4112
Vertex *verts = (Vertex *)v;
4113
4114
if (verts[0].x < 0 && verts[1].x < 0 && verts[2].x < 0 && verts[3].x < 0)
4115
return;
4116
if (verts[0].x > GFX_LINESIZE && verts[1].x > GFX_LINESIZE && verts[2].x > GFX_LINESIZE && verts[3].x > GFX_LINESIZE)
4117
return;
4118
if (verts[0].y < 0 && verts[1].y < 0 && verts[2].y < 0 && verts[3].y < 0)
4119
return;
4120
if (verts[0].y > SCREEN_YSIZE && verts[1].y > SCREEN_YSIZE && verts[2].y > SCREEN_YSIZE && verts[3].y > SCREEN_YSIZE)
4121
return;
4122
if (verts[0].x == verts[1].x && verts[1].x == verts[2].x && verts[2].x == verts[3].x)
4123
return;
4124
if (verts[0].y == verts[1].y && verts[1].y == verts[2].y && verts[2].y == verts[3].y)
4125
return;
4126
4127
#if RETRO_SOFTWARE_RENDER
4128
int vertexA = 0;
4129
int vertexB = 1;
4130
int vertexC = 2;
4131
int vertexD = 3;
4132
if (verts[1].y < verts[0].y) {
4133
vertexA = 1;
4134
vertexB = 0;
4135
}
4136
if (verts[2].y < verts[vertexA].y) {
4137
int temp = vertexA;
4138
vertexA = 2;
4139
vertexC = temp;
4140
}
4141
if (verts[3].y < verts[vertexA].y) {
4142
int temp = vertexA;
4143
vertexA = 3;
4144
vertexD = temp;
4145
}
4146
if (verts[vertexC].y < verts[vertexB].y) {
4147
int temp = vertexB;
4148
vertexB = vertexC;
4149
vertexC = temp;
4150
}
4151
if (verts[vertexD].y < verts[vertexB].y) {
4152
int temp = vertexB;
4153
vertexB = vertexD;
4154
vertexD = temp;
4155
}
4156
if (verts[vertexD].y < verts[vertexC].y) {
4157
int temp = vertexC;
4158
vertexC = vertexD;
4159
vertexD = temp;
4160
}
4161
4162
int faceTop = verts[vertexA].y;
4163
int faceBottom = verts[vertexD].y;
4164
if (faceTop < 0)
4165
faceTop = 0;
4166
if (faceBottom > SCREEN_YSIZE)
4167
faceBottom = SCREEN_YSIZE;
4168
for (int i = faceTop; i < faceBottom; ++i) {
4169
faceLineStart[i] = 100000;
4170
faceLineEnd[i] = -100000;
4171
}
4172
4173
ProcessScanEdgeUV(&verts[vertexA], &verts[vertexB]);
4174
ProcessScanEdgeUV(&verts[vertexA], &verts[vertexC]);
4175
ProcessScanEdgeUV(&verts[vertexA], &verts[vertexD]);
4176
ProcessScanEdgeUV(&verts[vertexB], &verts[vertexC]);
4177
ProcessScanEdgeUV(&verts[vertexC], &verts[vertexD]);
4178
ProcessScanEdgeUV(&verts[vertexB], &verts[vertexD]);
4179
4180
ushort *frameBufferPtr = &Engine.frameBuffer[GFX_LINESIZE * faceTop];
4181
byte *sheetPtr = &graphicData[gfxSurface[sheetID].dataPosition];
4182
int shiftwidth = gfxSurface[sheetID].widthShift;
4183
byte *lineBuffer = &gfxLineBuffer[faceTop];
4184
while (faceTop < faceBottom) {
4185
activePalette = fullPalette[*lineBuffer];
4186
activePalette32 = fullPalette32[*lineBuffer];
4187
lineBuffer++;
4188
int startX = faceLineStart[faceTop];
4189
int endX = faceLineEnd[faceTop];
4190
int UPos = faceLineStartU[faceTop];
4191
int VPos = faceLineStartV[faceTop];
4192
if (startX >= GFX_LINESIZE || endX <= 0) {
4193
frameBufferPtr += GFX_LINESIZE;
4194
}
4195
else {
4196
int posDifference = endX - startX;
4197
int bufferedUPos = 0;
4198
int bufferedVPos = 0;
4199
if (endX == startX) {
4200
bufferedUPos = 0;
4201
bufferedVPos = 0;
4202
}
4203
else {
4204
bufferedUPos = (faceLineEndU[faceTop] - UPos) / posDifference;
4205
bufferedVPos = (faceLineEndV[faceTop] - VPos) / posDifference;
4206
}
4207
if (endX > GFX_LINESIZE_MINUSONE)
4208
posDifference = GFX_LINESIZE_MINUSONE - startX;
4209
if (startX < 0) {
4210
posDifference += startX;
4211
UPos -= startX * bufferedUPos;
4212
VPos -= startX * bufferedVPos;
4213
startX = 0;
4214
}
4215
ushort *fbPtr = &frameBufferPtr[startX];
4216
frameBufferPtr += GFX_LINESIZE;
4217
#if RETRO_REV02
4218
int counter = posDifference;
4219
#else
4220
int counter = posDifference + 1;
4221
#endif
4222
while (counter--) {
4223
if (UPos < 0)
4224
UPos = 0;
4225
if (VPos < 0)
4226
VPos = 0;
4227
ushort index = sheetPtr[(VPos >> 16 << shiftwidth) + (UPos >> 16)];
4228
if (index > 0)
4229
*fbPtr = activePalette[index];
4230
fbPtr++;
4231
UPos += bufferedUPos;
4232
VPos += bufferedVPos;
4233
}
4234
}
4235
++faceTop;
4236
}
4237
#endif
4238
}
4239
void DrawTexturedFaceBlended(void *v, byte sheetID)
4240
{
4241
Vertex *verts = (Vertex *)v;
4242
if (verts[0].x < 0 && verts[1].x < 0 && verts[2].x < 0 && verts[3].x < 0)
4243
return;
4244
4245
if (verts[0].x > GFX_LINESIZE && verts[1].x > GFX_LINESIZE && verts[2].x > GFX_LINESIZE && verts[3].x > GFX_LINESIZE)
4246
return;
4247
4248
if (verts[0].y < 0 && verts[1].y < 0 && verts[2].y < 0 && verts[3].y < 0)
4249
return;
4250
4251
if (verts[0].y > SCREEN_YSIZE && verts[1].y > SCREEN_YSIZE && verts[2].y > SCREEN_YSIZE && verts[3].y > SCREEN_YSIZE)
4252
return;
4253
4254
if (verts[0].x == verts[1].x && verts[1].x == verts[2].x && verts[2].x == verts[3].x)
4255
return;
4256
4257
if (verts[0].y == verts[1].y && verts[1].y == verts[2].y && verts[2].y == verts[3].y)
4258
return;
4259
4260
#if RETRO_SOFTWARE_RENDER
4261
int vertexA = 0;
4262
int vertexB = 1;
4263
int vertexC = 2;
4264
int vertexD = 3;
4265
if (verts[1].y < verts[0].y) {
4266
vertexA = 1;
4267
vertexB = 0;
4268
}
4269
if (verts[2].y < verts[vertexA].y) {
4270
int temp = vertexA;
4271
vertexA = 2;
4272
vertexC = temp;
4273
}
4274
if (verts[3].y < verts[vertexA].y) {
4275
int temp = vertexA;
4276
vertexA = 3;
4277
vertexD = temp;
4278
}
4279
if (verts[vertexC].y < verts[vertexB].y) {
4280
int temp = vertexB;
4281
vertexB = vertexC;
4282
vertexC = temp;
4283
}
4284
if (verts[vertexD].y < verts[vertexB].y) {
4285
int temp = vertexB;
4286
vertexB = vertexD;
4287
vertexD = temp;
4288
}
4289
if (verts[vertexD].y < verts[vertexC].y) {
4290
int temp = vertexC;
4291
vertexC = vertexD;
4292
vertexD = temp;
4293
}
4294
4295
int faceTop = verts[vertexA].y;
4296
int faceBottom = verts[vertexD].y;
4297
if (faceTop < 0)
4298
faceTop = 0;
4299
if (faceBottom > SCREEN_YSIZE)
4300
faceBottom = SCREEN_YSIZE;
4301
for (int i = faceTop; i < faceBottom; ++i) {
4302
faceLineStart[i] = 100000;
4303
faceLineEnd[i] = -100000;
4304
}
4305
4306
ProcessScanEdgeUV(&verts[vertexA], &verts[vertexB]);
4307
ProcessScanEdgeUV(&verts[vertexA], &verts[vertexC]);
4308
ProcessScanEdgeUV(&verts[vertexA], &verts[vertexD]);
4309
ProcessScanEdgeUV(&verts[vertexB], &verts[vertexC]);
4310
ProcessScanEdgeUV(&verts[vertexC], &verts[vertexD]);
4311
ProcessScanEdgeUV(&verts[vertexB], &verts[vertexD]);
4312
4313
ushort *frameBufferPtr = &Engine.frameBuffer[GFX_LINESIZE * faceTop];
4314
byte *sheetPtr = &graphicData[gfxSurface[sheetID].dataPosition];
4315
int shiftwidth = gfxSurface[sheetID].widthShift;
4316
byte *lineBuffer = &gfxLineBuffer[faceTop];
4317
while (faceTop < faceBottom) {
4318
activePalette = fullPalette[*lineBuffer];
4319
activePalette32 = fullPalette32[*lineBuffer];
4320
lineBuffer++;
4321
int startX = faceLineStart[faceTop];
4322
int endX = faceLineEnd[faceTop];
4323
int UPos = faceLineStartU[faceTop];
4324
int VPos = faceLineStartV[faceTop];
4325
if (startX >= GFX_LINESIZE || endX <= 0) {
4326
frameBufferPtr += GFX_LINESIZE;
4327
}
4328
else {
4329
int posDifference = endX - startX;
4330
int bufferedUPos = 0;
4331
int bufferedVPos = 0;
4332
if (endX == startX) {
4333
bufferedUPos = 0;
4334
bufferedVPos = 0;
4335
}
4336
else {
4337
bufferedUPos = (faceLineEndU[faceTop] - UPos) / posDifference;
4338
bufferedVPos = (faceLineEndV[faceTop] - VPos) / posDifference;
4339
}
4340
if (endX > GFX_LINESIZE_MINUSONE)
4341
posDifference = GFX_LINESIZE_MINUSONE - startX;
4342
if (startX < 0) {
4343
posDifference += startX;
4344
UPos -= startX * bufferedUPos;
4345
VPos -= startX * bufferedVPos;
4346
startX = 0;
4347
}
4348
ushort *fbPtr = &frameBufferPtr[startX];
4349
frameBufferPtr += GFX_LINESIZE;
4350
#if RETRO_REV02
4351
int counter = posDifference;
4352
#else
4353
int counter = posDifference + 1;
4354
#endif
4355
while (counter--) {
4356
if (UPos < 0)
4357
UPos = 0;
4358
if (VPos < 0)
4359
VPos = 0;
4360
ushort index = sheetPtr[(VPos >> 16 << shiftwidth) + (UPos >> 16)];
4361
if (index > 0)
4362
*fbPtr = ((activePalette[index] & 0xF7BC) >> 1) + ((*fbPtr & 0xF7BC) >> 1);
4363
fbPtr++;
4364
UPos += bufferedUPos;
4365
VPos += bufferedVPos;
4366
}
4367
}
4368
++faceTop;
4369
}
4370
#endif
4371
}
4372
4373
#if !RETRO_REV02
4374
void DrawBitmapText(void *menu, int XPos, int YPos, int scale, int spacing, int rowStart, int rowCount)
4375
{
4376
TextMenu *tMenu = (TextMenu *)menu;
4377
int Y = YPos << 9;
4378
if (rowCount < 0)
4379
rowCount = tMenu->rowCount;
4380
if (rowStart + rowCount > tMenu->rowCount)
4381
rowCount = tMenu->rowCount - rowStart;
4382
4383
while (rowCount > 0) {
4384
int X = XPos << 9;
4385
for (int i = 0; i < tMenu->entrySize[rowStart]; ++i) {
4386
ushort c = tMenu->textData[tMenu->entryStart[rowStart] + i];
4387
FontCharacter *fChar = &fontCharacterList[c];
4388
#if RETRO_SOFTWARE_RENDER
4389
DrawSpriteScaled(FLIP_NONE, X >> 9, Y >> 9, -fChar->pivotX, -fChar->pivotY, scale, scale, fChar->width, fChar->height, fChar->srcX,
4390
fChar->srcY, textMenuSurfaceNo);
4391
#endif
4392
X += fChar->xAdvance * scale;
4393
}
4394
Y += spacing * scale;
4395
rowStart++;
4396
rowCount--;
4397
}
4398
}
4399
#endif
4400
4401
void DrawTextMenuEntry(void *menu, int rowID, int XPos, int YPos, int textHighlight)
4402
{
4403
TextMenu *tMenu = (TextMenu *)menu;
4404
int id = tMenu->entryStart[rowID];
4405
for (int i = 0; i < tMenu->entrySize[rowID]; ++i) {
4406
DrawSprite(XPos + (i << 3) - (((tMenu->entrySize[rowID] % 2) & (tMenu->alignment == 2)) * 4), YPos, 8, 8, ((tMenu->textData[id] & 0xF) << 3),
4407
((tMenu->textData[id] >> 4) << 3) + textHighlight, textMenuSurfaceNo);
4408
id++;
4409
}
4410
}
4411
void DrawStageTextEntry(void *menu, int rowID, int XPos, int YPos, int textHighlight)
4412
{
4413
TextMenu *tMenu = (TextMenu *)menu;
4414
int id = tMenu->entryStart[rowID];
4415
for (int i = 0; i < tMenu->entrySize[rowID]; ++i) {
4416
if (i == tMenu->entrySize[rowID] - 1) {
4417
DrawSprite(XPos + (i << 3), YPos, 8, 8, ((tMenu->textData[id] & 0xF) << 3), ((tMenu->textData[id] >> 4) << 3), textMenuSurfaceNo);
4418
}
4419
else {
4420
DrawSprite(XPos + (i << 3), YPos, 8, 8, ((tMenu->textData[id] & 0xF) << 3), ((tMenu->textData[id] >> 4) << 3) + textHighlight,
4421
textMenuSurfaceNo);
4422
}
4423
id++;
4424
}
4425
}
4426
void DrawBlendedTextMenuEntry(void *menu, int rowID, int XPos, int YPos, int textHighlight)
4427
{
4428
TextMenu *tMenu = (TextMenu *)menu;
4429
int id = tMenu->entryStart[rowID];
4430
for (int i = 0; i < tMenu->entrySize[rowID]; ++i) {
4431
DrawBlendedSprite(XPos + (i << 3), YPos, 8, 8, ((tMenu->textData[id] & 0xF) << 3), ((tMenu->textData[id] >> 4) << 3) + textHighlight,
4432
textMenuSurfaceNo);
4433
id++;
4434
}
4435
}
4436
void DrawTextMenu(void *menu, int XPos, int YPos)
4437
{
4438
TextMenu *tMenu = (TextMenu *)menu;
4439
int cnt = 0;
4440
4441
if (tMenu->visibleRowCount > 0) {
4442
cnt = (int)(tMenu->visibleRowCount + tMenu->visibleRowOffset);
4443
}
4444
else {
4445
tMenu->visibleRowOffset = 0;
4446
cnt = (int)tMenu->rowCount;
4447
}
4448
4449
if (tMenu->selectionCount == 3) {
4450
tMenu->selection2 = -1;
4451
for (int i = 0; i <= tMenu->selection1; ++i) {
4452
if (tMenu->entryHighlight[i]) {
4453
tMenu->selection2 = i;
4454
}
4455
}
4456
}
4457
4458
switch (tMenu->alignment) {
4459
case 0:
4460
for (int i = (int)tMenu->visibleRowOffset; i < cnt; ++i) {
4461
switch (tMenu->selectionCount) {
4462
case 1:
4463
if (i == tMenu->selection1)
4464
DrawTextMenuEntry(tMenu, i, XPos, YPos, 128);
4465
else
4466
DrawTextMenuEntry(tMenu, i, XPos, YPos, 0);
4467
break;
4468
4469
case 2:
4470
if (i == tMenu->selection1 || i == tMenu->selection2)
4471
DrawTextMenuEntry(tMenu, i, XPos, YPos, 128);
4472
else
4473
DrawTextMenuEntry(tMenu, i, XPos, YPos, 0);
4474
break;
4475
4476
case 3:
4477
if (i == tMenu->selection1)
4478
DrawTextMenuEntry(tMenu, i, XPos, YPos, 128);
4479
else
4480
DrawTextMenuEntry(tMenu, i, XPos, YPos, 0);
4481
4482
if (i == tMenu->selection2 && i != tMenu->selection1)
4483
DrawStageTextEntry(tMenu, i, XPos, YPos, 128);
4484
break;
4485
}
4486
YPos += 8;
4487
}
4488
break;
4489
4490
case 1:
4491
for (int i = (int)tMenu->visibleRowOffset; i < cnt; ++i) {
4492
int entryX = XPos - (tMenu->entrySize[i] << 3);
4493
switch (tMenu->selectionCount) {
4494
case 1:
4495
if (i == tMenu->selection1)
4496
DrawTextMenuEntry(tMenu, i, entryX, YPos, 128);
4497
else
4498
DrawTextMenuEntry(tMenu, i, entryX, YPos, 0);
4499
break;
4500
4501
case 2:
4502
if (i == tMenu->selection1 || i == tMenu->selection2)
4503
DrawTextMenuEntry(tMenu, i, entryX, YPos, 128);
4504
else
4505
DrawTextMenuEntry(tMenu, i, entryX, YPos, 0);
4506
break;
4507
4508
case 3:
4509
if (i == tMenu->selection1)
4510
DrawTextMenuEntry(tMenu, i, entryX, YPos, 128);
4511
else
4512
DrawTextMenuEntry(tMenu, i, entryX, YPos, 0);
4513
4514
if (i == tMenu->selection2 && i != tMenu->selection1)
4515
DrawStageTextEntry(tMenu, i, entryX, YPos, 128);
4516
break;
4517
}
4518
YPos += 8;
4519
}
4520
break;
4521
4522
case 2:
4523
for (int i = (int)tMenu->visibleRowOffset; i < cnt; ++i) {
4524
int entryX = XPos - (tMenu->entrySize[i] >> 1 << 3);
4525
switch (tMenu->selectionCount) {
4526
case 1:
4527
if (i == tMenu->selection1)
4528
DrawTextMenuEntry(tMenu, i, entryX, YPos, 128);
4529
else
4530
DrawTextMenuEntry(tMenu, i, entryX, YPos, 0);
4531
break;
4532
case 2:
4533
if (i == tMenu->selection1 || i == tMenu->selection2)
4534
DrawTextMenuEntry(tMenu, i, entryX, YPos, 128);
4535
else
4536
DrawTextMenuEntry(tMenu, i, entryX, YPos, 0);
4537
break;
4538
case 3:
4539
if (i == tMenu->selection1)
4540
DrawTextMenuEntry(tMenu, i, entryX, YPos, 128);
4541
else
4542
DrawTextMenuEntry(tMenu, i, entryX, YPos, 0);
4543
4544
if (i == tMenu->selection2 && i != tMenu->selection1)
4545
DrawStageTextEntry(tMenu, i, entryX, YPos, 128);
4546
break;
4547
}
4548
YPos += 8;
4549
}
4550
break;
4551
4552
default: break;
4553
}
4554
}
4555
4556