Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/RSDKv5/RSDK/Graphics/SDL2/SDL2RenderDevice.cpp
1163 views
1
2
SDL_Window *RenderDevice::window = nullptr;
3
SDL_Renderer *RenderDevice::renderer = nullptr;
4
SDL_Texture *RenderDevice::screenTexture[SCREEN_COUNT];
5
6
SDL_Texture *RenderDevice::imageTexture = nullptr;
7
8
uint32 RenderDevice::displayModeIndex = 0;
9
int32 RenderDevice::displayModeCount = 0;
10
11
unsigned long long RenderDevice::targetFreq = 0;
12
unsigned long long RenderDevice::curTicks = 0;
13
unsigned long long RenderDevice::prevTicks = 0;
14
15
RenderVertex RenderDevice::vertexBuffer[!RETRO_REV02 ? 24 : 60];
16
17
uint8 RenderDevice::lastTextureFormat = -1;
18
19
#define NORMALIZE(val, minVal, maxVal) ((float)(val) - (float)(minVal)) / ((float)(maxVal) - (float)(minVal))
20
21
bool RenderDevice::Init()
22
{
23
const char *gameTitle = gameVerInfo.gameTitle;
24
25
SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
26
27
uint8 flags = 0;
28
29
#if RETRO_PLATFORM == RETRO_ANDROID
30
videoSettings.windowed = false;
31
SDL_DisplayMode dm;
32
SDL_GetDesktopDisplayMode(0, &dm);
33
float hdp = 0, vdp = 0;
34
35
bool landscape = dm.h < dm.w;
36
int32 h = landscape ? dm.w : dm.h;
37
int32 w = landscape ? dm.h : dm.w;
38
39
videoSettings.windowWidth = ((float)SCREEN_YSIZE * h / w);
40
41
#elif RETRO_PLATFORM == RETRO_SWITCH
42
videoSettings.windowed = false;
43
videoSettings.windowWidth = 1920;
44
videoSettings.windowHeight = 1080;
45
flags |= SDL_WINDOW_FULLSCREEN;
46
#endif
47
48
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
49
SDL_SetHint(SDL_HINT_RENDER_VSYNC, videoSettings.vsync ? "1" : "0");
50
51
window = SDL_CreateWindow(gameTitle, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, videoSettings.windowWidth, videoSettings.windowHeight,
52
SDL_WINDOW_ALLOW_HIGHDPI | flags);
53
54
if (!window) {
55
PrintLog(PRINT_NORMAL, "ERROR: failed to create window!");
56
return false;
57
}
58
59
if (!videoSettings.windowed) {
60
SDL_RestoreWindow(window);
61
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
62
SDL_ShowCursor(SDL_FALSE);
63
}
64
65
if (!videoSettings.bordered) {
66
SDL_RestoreWindow(window);
67
SDL_SetWindowBordered(window, SDL_FALSE);
68
}
69
70
PrintLog(PRINT_NORMAL, "w: %d h: %d windowed: %d", videoSettings.windowWidth, videoSettings.windowHeight, videoSettings.windowed);
71
72
if (!SetupRendering() || !AudioDevice::Init())
73
return false;
74
75
InitInputDevices();
76
return true;
77
}
78
79
void RenderDevice::CopyFrameBuffer()
80
{
81
int32 pitch = 0;
82
uint16 *pixels = NULL;
83
84
for (int32 s = 0; s < videoSettings.screenCount; ++s) {
85
SDL_LockTexture(screenTexture[s], NULL, (void **)&pixels, &pitch);
86
87
uint16 *frameBuffer = screens[s].frameBuffer;
88
for (int32 y = 0; y < SCREEN_YSIZE; ++y) {
89
memcpy(pixels, frameBuffer, screens[s].size.x * sizeof(uint16));
90
frameBuffer += screens[s].pitch;
91
pixels += pitch / sizeof(uint16);
92
}
93
94
SDL_UnlockTexture(screenTexture[s]);
95
}
96
}
97
98
void RenderDevice::FlipScreen()
99
{
100
if (windowRefreshDelay > 0) {
101
windowRefreshDelay--;
102
if (!windowRefreshDelay)
103
UpdateGameWindow();
104
return;
105
}
106
107
float dimAmount = videoSettings.dimMax * videoSettings.dimPercent;
108
109
// Clear the screen. This is needed to keep the
110
// pillarboxes in fullscreen from displaying garbage data.
111
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF);
112
SDL_RenderClear(renderer);
113
114
#if (SDL_COMPILEDVERSION >= SDL_VERSIONNUM(2, 0, 18))
115
int32 startVert = 0;
116
switch (videoSettings.screenCount) {
117
default:
118
case 0:
119
#if RETRO_REV02
120
startVert = 54;
121
#else
122
startVert = 18;
123
#endif
124
SDL_RenderGeometryRaw(renderer, imageTexture, &vertexBuffer[startVert].pos.x, sizeof(RenderVertex),
125
(SDL_Color *)&vertexBuffer[startVert].color, sizeof(RenderVertex), &vertexBuffer[startVert].tex.x,
126
sizeof(RenderVertex), 6, NULL, 0, 0);
127
break;
128
129
case 1:
130
startVert = 0;
131
SDL_RenderGeometryRaw(renderer, screenTexture[0], &vertexBuffer[startVert].pos.x, sizeof(RenderVertex),
132
(SDL_Color *)&vertexBuffer[startVert].color, sizeof(RenderVertex), &vertexBuffer[startVert].tex.x,
133
sizeof(RenderVertex), 6, NULL, 0, 0);
134
break;
135
136
case 2:
137
#if RETRO_REV02
138
startVert = startVertex_2P[0];
139
#else
140
startVert = 6;
141
#endif
142
SDL_RenderGeometryRaw(renderer, screenTexture[0], &vertexBuffer[startVert].pos.x, sizeof(RenderVertex),
143
(SDL_Color *)&vertexBuffer[startVert].color, sizeof(RenderVertex), &vertexBuffer[startVert].tex.x,
144
sizeof(RenderVertex), 6, NULL, 0, 0);
145
146
#if RETRO_REV02
147
startVert = startVertex_2P[1];
148
#else
149
startVert = 12;
150
#endif
151
SDL_RenderGeometryRaw(renderer, screenTexture[1], &vertexBuffer[startVert].pos.x, sizeof(RenderVertex),
152
(SDL_Color *)&vertexBuffer[startVert].color, sizeof(RenderVertex), &vertexBuffer[startVert].tex.x,
153
sizeof(RenderVertex), 6, NULL, 0, 0);
154
break;
155
156
#if RETRO_REV02
157
case 3:
158
startVert = startVertex_3P[0];
159
SDL_RenderGeometryRaw(renderer, screenTexture[0], &vertexBuffer[startVert].pos.x, sizeof(RenderVertex),
160
(SDL_Color *)&vertexBuffer[startVert].color, sizeof(RenderVertex), &vertexBuffer[startVert].tex.x,
161
sizeof(RenderVertex), 6, NULL, 0, 0);
162
163
startVert = startVertex_3P[1];
164
SDL_RenderGeometryRaw(renderer, screenTexture[1], &vertexBuffer[startVert].pos.x, sizeof(RenderVertex),
165
(SDL_Color *)&vertexBuffer[startVert].color, sizeof(RenderVertex), &vertexBuffer[startVert].tex.x,
166
sizeof(RenderVertex), 6, NULL, 0, 0);
167
168
startVert = startVertex_3P[2];
169
SDL_RenderGeometryRaw(renderer, screenTexture[2], &vertexBuffer[startVert].pos.x, sizeof(RenderVertex),
170
(SDL_Color *)&vertexBuffer[startVert].color, sizeof(RenderVertex), &vertexBuffer[startVert].tex.x,
171
sizeof(RenderVertex), 6, NULL, 0, 0);
172
break;
173
174
case 4:
175
startVert = 30;
176
SDL_RenderGeometryRaw(renderer, screenTexture[0], &vertexBuffer[startVert].pos.x, sizeof(RenderVertex),
177
(SDL_Color *)&vertexBuffer[startVert].color, sizeof(RenderVertex), &vertexBuffer[startVert].tex.x,
178
sizeof(RenderVertex), 6, NULL, 0, 0);
179
180
startVert = 36;
181
SDL_RenderGeometryRaw(renderer, screenTexture[1], &vertexBuffer[startVert].pos.x, sizeof(RenderVertex),
182
(SDL_Color *)&vertexBuffer[startVert].color, sizeof(RenderVertex), &vertexBuffer[startVert].tex.x,
183
sizeof(RenderVertex), 6, NULL, 0, 0);
184
185
startVert = 42;
186
SDL_RenderGeometryRaw(renderer, screenTexture[2], &vertexBuffer[startVert].pos.x, sizeof(RenderVertex),
187
(SDL_Color *)&vertexBuffer[startVert].color, sizeof(RenderVertex), &vertexBuffer[startVert].tex.x,
188
sizeof(RenderVertex), 6, NULL, 0, 0);
189
190
startVert = 48;
191
SDL_RenderGeometryRaw(renderer, screenTexture[3], &vertexBuffer[startVert].pos.x, sizeof(RenderVertex),
192
(SDL_Color *)&vertexBuffer[startVert].color, sizeof(RenderVertex), &vertexBuffer[startVert].tex.x,
193
sizeof(RenderVertex), 6, NULL, 0, 0);
194
break;
195
#endif
196
}
197
#else
198
int32 startVert = 0;
199
SDL_Rect src, dst;
200
201
// some cheating for today
202
#define _SET_RECTS \
203
dst.x = vertexBuffer[startVert].pos.x; \
204
dst.y = vertexBuffer[startVert].pos.y; \
205
dst.w = vertexBuffer[startVert + 2].pos.x - dst.x; \
206
dst.h = vertexBuffer[startVert + 2].pos.y - dst.y; \
207
src.x = vertexBuffer[startVert].tex.x * textureSize.x; \
208
src.y = vertexBuffer[startVert].tex.y * textureSize.y; \
209
src.w = vertexBuffer[startVert + 2].tex.x * textureSize.x - src.x; \
210
src.h = vertexBuffer[startVert + 2].tex.y * textureSize.y - src.y;
211
212
switch (videoSettings.screenCount) {
213
default:
214
case 0:
215
#if RETRO_REV02
216
startVert = 54;
217
#else
218
startVert = 18;
219
#endif
220
_SET_RECTS;
221
src.w = vertexBuffer[startVert + 2].tex.x * 1024 - src.x;
222
src.h = vertexBuffer[startVert + 2].tex.y * 512 - src.y;
223
SDL_RenderCopy(renderer, imageTexture, &src, &dst);
224
break;
225
226
case 1:
227
startVert = 0;
228
_SET_RECTS;
229
230
SDL_RenderCopy(renderer, screenTexture[0], &src, &dst);
231
break;
232
233
case 2:
234
#if RETRO_REV02
235
startVert = startVertex_2P[0];
236
#else
237
startVert = 6;
238
#endif
239
_SET_RECTS;
240
241
SDL_RenderCopy(renderer, screenTexture[0], &src, &dst);
242
243
#if RETRO_REV02
244
startVert = startVertex_2P[1];
245
#else
246
startVert = 12;
247
#endif
248
_SET_RECTS;
249
250
SDL_RenderCopy(renderer, screenTexture[1], &src, &dst);
251
break;
252
253
#if RETRO_REV02
254
case 3:
255
startVert = startVertex_3P[0];
256
_SET_RECTS;
257
258
SDL_RenderCopy(renderer, screenTexture[0], &src, &dst);
259
260
startVert = startVertex_3P[1];
261
_SET_RECTS;
262
263
SDL_RenderCopy(renderer, screenTexture[1], &src, &dst);
264
265
startVert = startVertex_3P[2];
266
_SET_RECTS;
267
268
SDL_RenderCopy(renderer, screenTexture[2], &src, &dst);
269
270
break;
271
272
case 4:
273
startVert = 30;
274
_SET_RECTS;
275
276
SDL_RenderCopy(renderer, screenTexture[0], &src, &dst);
277
278
startVert = 36;
279
_SET_RECTS;
280
281
SDL_RenderCopy(renderer, screenTexture[1], &src, &dst);
282
283
startVert = 42;
284
_SET_RECTS;
285
286
SDL_RenderCopy(renderer, screenTexture[2], &src, &dst);
287
288
startVert = 48;
289
_SET_RECTS;
290
291
SDL_RenderCopy(renderer, screenTexture[3], &src, &dst);
292
293
break;
294
#endif
295
}
296
#endif
297
if (dimAmount < 1.0f) {
298
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF - (dimAmount * 0xFF));
299
SDL_RenderFillRect(renderer, NULL);
300
}
301
// no change here
302
SDL_RenderPresent(renderer);
303
}
304
305
void RenderDevice::Release(bool32 isRefresh)
306
{
307
for (int32 s = 0; s < SCREEN_COUNT; ++s) {
308
if (screenTexture[s])
309
SDL_DestroyTexture(screenTexture[s]);
310
screenTexture[s] = NULL;
311
}
312
313
if (imageTexture)
314
SDL_DestroyTexture(imageTexture);
315
imageTexture = NULL;
316
317
if (!isRefresh) {
318
if (displayInfo.displays)
319
free(displayInfo.displays);
320
displayInfo.displays = NULL;
321
}
322
323
if (!isRefresh && renderer)
324
SDL_DestroyRenderer(renderer);
325
326
if (!isRefresh && window)
327
SDL_DestroyWindow(window);
328
329
if (!isRefresh)
330
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
331
332
if (!isRefresh) {
333
if (scanlines)
334
free(scanlines);
335
scanlines = NULL;
336
}
337
}
338
339
void RenderDevice::RefreshWindow()
340
{
341
videoSettings.windowState = WINDOWSTATE_UNINITIALIZED;
342
343
Release(true);
344
345
SDL_HideWindow(window);
346
347
if (videoSettings.windowed && videoSettings.bordered)
348
SDL_SetWindowBordered(window, SDL_TRUE);
349
else
350
SDL_SetWindowBordered(window, SDL_FALSE);
351
352
GetDisplays();
353
354
SDL_Rect winRect;
355
winRect.x = SDL_WINDOWPOS_CENTERED;
356
winRect.y = SDL_WINDOWPOS_CENTERED;
357
if (videoSettings.windowed || !videoSettings.exclusiveFS) {
358
int32 currentWindowDisplay = SDL_GetWindowDisplayIndex(window);
359
SDL_DisplayMode displayMode;
360
SDL_GetCurrentDisplayMode(currentWindowDisplay, &displayMode);
361
362
if (videoSettings.windowed) {
363
if (videoSettings.windowWidth >= displayMode.w || videoSettings.windowHeight >= displayMode.h) {
364
videoSettings.windowWidth = (displayMode.h / 480 * videoSettings.pixWidth);
365
videoSettings.windowHeight = displayMode.h / 480 * videoSettings.pixHeight;
366
}
367
368
winRect.w = videoSettings.windowWidth;
369
winRect.h = videoSettings.windowHeight;
370
SDL_SetWindowFullscreen(window, SDL_FALSE);
371
SDL_ShowCursor(SDL_FALSE);
372
}
373
else {
374
winRect.w = displayMode.w;
375
winRect.h = displayMode.h;
376
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
377
SDL_ShowCursor(SDL_TRUE);
378
}
379
380
SDL_SetWindowSize(window, winRect.w, winRect.h);
381
SDL_SetWindowPosition(window, winRect.x, winRect.y);
382
}
383
384
SDL_ShowWindow(window);
385
386
if (!InitGraphicsAPI() || !InitShaders())
387
return;
388
389
videoSettings.windowState = WINDOWSTATE_ACTIVE;
390
}
391
392
void RenderDevice::InitFPSCap()
393
{
394
targetFreq = SDL_GetPerformanceFrequency() / videoSettings.refreshRate;
395
curTicks = 0;
396
prevTicks = 0;
397
}
398
bool RenderDevice::CheckFPSCap()
399
{
400
curTicks = SDL_GetPerformanceCounter();
401
if (curTicks >= prevTicks + targetFreq)
402
return true;
403
404
return false;
405
}
406
void RenderDevice::UpdateFPSCap() { prevTicks = curTicks; }
407
408
void RenderDevice::InitVertexBuffer()
409
{
410
RenderVertex vertBuffer[sizeof(rsdkVertexBuffer) / sizeof(RenderVertex)];
411
memcpy(vertBuffer, rsdkVertexBuffer, sizeof(rsdkVertexBuffer));
412
413
// ignore the last 6 verts, they're scaled to the 1024x512 textures already!
414
int32 vertCount = (RETRO_REV02 ? 60 : 24) - 6;
415
416
// Regular in-game screen de-normalization stuff
417
for (int32 v = 0; v < vertCount; ++v) {
418
RenderVertex *vertex = &vertBuffer[v];
419
vertex->pos.x = NORMALIZE(vertex->pos.x, -1.0, 1.0) * videoSettings.pixWidth;
420
vertex->pos.y = (1.0 - NORMALIZE(vertex->pos.y, -1.0, 1.0)) * SCREEN_YSIZE;
421
422
if (vertex->tex.x)
423
vertex->tex.x = screens[0].size.x * (1.0 / textureSize.x);
424
425
if (vertex->tex.y)
426
vertex->tex.y = screens[0].size.y * (1.0 / textureSize.y);
427
}
428
429
// Fullscreen Image/Video de-normalization stuff
430
for (int32 v = 0; v < 6; ++v) {
431
RenderVertex *vertex = &vertBuffer[vertCount + v];
432
vertex->pos.x = NORMALIZE(vertex->pos.x, -1.0, 1.0) * videoSettings.pixWidth;
433
vertex->pos.y = (1.0 - NORMALIZE(vertex->pos.y, -1.0, 1.0)) * SCREEN_YSIZE;
434
435
// Set the texture to fill the entire screen with all 1024x512 pixels
436
if (vertex->tex.x)
437
vertex->tex.x = 1.0f;
438
439
if (vertex->tex.y)
440
vertex->tex.y = 1.0f;
441
}
442
443
memcpy(vertexBuffer, vertBuffer, sizeof(vertBuffer));
444
}
445
446
bool RenderDevice::InitGraphicsAPI()
447
{
448
videoSettings.shaderSupport = false;
449
450
viewSize.x = 0;
451
viewSize.y = 0;
452
453
if (videoSettings.windowed || !videoSettings.exclusiveFS) {
454
if (videoSettings.windowed) {
455
viewSize.x = videoSettings.windowWidth;
456
viewSize.y = videoSettings.windowHeight;
457
}
458
else {
459
viewSize.x = displayWidth[displayModeIndex];
460
viewSize.y = displayHeight[displayModeIndex];
461
}
462
}
463
else {
464
int32 bufferWidth = videoSettings.fsWidth;
465
int32 bufferHeight = videoSettings.fsHeight;
466
if (videoSettings.fsWidth <= 0 || videoSettings.fsHeight <= 0) {
467
bufferWidth = displayWidth[displayModeIndex];
468
bufferHeight = displayHeight[displayModeIndex];
469
}
470
471
viewSize.x = bufferWidth;
472
viewSize.y = bufferHeight;
473
}
474
475
SDL_SetWindowSize(window, viewSize.x, viewSize.y);
476
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
477
478
int32 maxPixHeight = 0;
479
#if !RETRO_USE_ORIGINAL_CODE
480
int32 screenWidth = 0;
481
#endif
482
for (int32 s = 0; s < 4; ++s) {
483
if (videoSettings.pixHeight > maxPixHeight)
484
maxPixHeight = videoSettings.pixHeight;
485
486
screens[s].size.y = videoSettings.pixHeight;
487
488
float viewAspect = viewSize.x / viewSize.y;
489
#if !RETRO_USE_ORIGINAL_CODE
490
screenWidth = (int32)((viewAspect * videoSettings.pixHeight) + 3) & 0xFFFFFFFC;
491
#else
492
int32 screenWidth = (int32)((viewAspect * videoSettings.pixHeight) + 3) & 0xFFFFFFFC;
493
#endif
494
if (screenWidth < videoSettings.pixWidth)
495
screenWidth = videoSettings.pixWidth;
496
497
#if !RETRO_USE_ORIGINAL_CODE
498
if (customSettings.maxPixWidth && screenWidth > customSettings.maxPixWidth)
499
screenWidth = customSettings.maxPixWidth;
500
#else
501
if (screenWidth > DEFAULT_PIXWIDTH)
502
screenWidth = DEFAULT_PIXWIDTH;
503
#endif
504
505
memset(&screens[s].frameBuffer, 0, sizeof(screens[s].frameBuffer));
506
SetScreenSize(s, screenWidth, screens[s].size.y);
507
}
508
509
pixelSize.x = screens[0].size.x;
510
pixelSize.y = screens[0].size.y;
511
512
SDL_RenderSetLogicalSize(renderer, videoSettings.pixWidth, SCREEN_YSIZE);
513
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
514
515
#if !RETRO_USE_ORIGINAL_CODE
516
if (screenWidth <= 512 && maxPixHeight <= 256) {
517
#else
518
if (maxPixHeight <= 256) {
519
#endif
520
textureSize.x = 512.0;
521
textureSize.y = 256.0;
522
}
523
else {
524
textureSize.x = 1024.0;
525
textureSize.y = 512.0;
526
}
527
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
528
for (int32 s = 0; s < SCREEN_COUNT; ++s) {
529
screenTexture[s] = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, textureSize.x, textureSize.y);
530
531
if (!screenTexture[s]) {
532
PrintLog(PRINT_NORMAL, "ERROR: failed to create screen buffer!\nerror msg: %s", SDL_GetError());
533
return 0;
534
}
535
}
536
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
537
imageTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, RETRO_VIDEO_TEXTURE_W, RETRO_VIDEO_TEXTURE_H);
538
if (!imageTexture)
539
return false;
540
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
541
542
lastShaderID = -1;
543
InitVertexBuffer();
544
engine.inFocus = 1;
545
videoSettings.viewportX = 0;
546
videoSettings.viewportY = 0;
547
videoSettings.viewportW = 1.0 / viewSize.x;
548
videoSettings.viewportH = 1.0 / viewSize.y;
549
550
return true;
551
}
552
553
void RenderDevice::LoadShader(const char *fileName, bool32 linear) { PrintLog(PRINT_NORMAL, "This render device does not support shaders!"); }
554
555
bool RenderDevice::InitShaders()
556
{
557
int32 maxShaders = 0;
558
#if RETRO_USE_MOD_LOADER
559
// who knows maybe SDL3 will have shaders
560
shaderCount = 0;
561
#endif
562
563
if (videoSettings.shaderSupport) {
564
LoadShader("None", false);
565
LoadShader("Clean", true);
566
LoadShader("CRT-Yeetron", true);
567
LoadShader("CRT-Yee64", true);
568
569
#if RETRO_USE_MOD_LOADER
570
// a place for mods to load custom shaders
571
RunModCallbacks(MODCB_ONSHADERLOAD, NULL);
572
userShaderCount = shaderCount;
573
#endif
574
575
LoadShader("YUV-420", true);
576
LoadShader("YUV-422", true);
577
LoadShader("YUV-444", true);
578
LoadShader("RGB-Image", true);
579
maxShaders = shaderCount;
580
}
581
else {
582
for (int32 s = 0; s < SHADER_COUNT; ++s) shaderList[s].linear = true;
583
584
shaderList[0].linear = videoSettings.windowed ? false : shaderList[0].linear;
585
maxShaders = 1;
586
shaderCount = 1;
587
}
588
589
videoSettings.shaderID = videoSettings.shaderID >= maxShaders ? 0 : videoSettings.shaderID;
590
591
return true;
592
}
593
594
bool RenderDevice::SetupRendering()
595
{
596
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
597
598
if (!renderer) {
599
PrintLog(PRINT_NORMAL, "ERROR: failed to create renderer!");
600
return false;
601
}
602
603
GetDisplays();
604
605
if (!InitGraphicsAPI() || !InitShaders())
606
return false;
607
608
int32 size = videoSettings.pixWidth >= SCREEN_YSIZE ? videoSettings.pixWidth : SCREEN_YSIZE;
609
scanlines = (ScanlineInfo *)malloc(size * sizeof(ScanlineInfo));
610
memset(scanlines, 0, size * sizeof(ScanlineInfo));
611
612
videoSettings.windowState = WINDOWSTATE_ACTIVE;
613
videoSettings.dimMax = 1.0;
614
videoSettings.dimPercent = 1.0;
615
616
return true;
617
}
618
619
void RenderDevice::GetDisplays()
620
{
621
int32 currentWindowDisplay = SDL_GetWindowDisplayIndex(window);
622
623
int32 dispCount = SDL_GetNumVideoDisplays();
624
625
SDL_DisplayMode currentDisplay;
626
SDL_GetCurrentDisplayMode(currentWindowDisplay, &currentDisplay);
627
628
displayModeIndex = 0;
629
for (int32 a = 0; a < dispCount; ++a) {
630
SDL_DisplayMode displayMode;
631
632
SDL_GetCurrentDisplayMode(currentWindowDisplay, &displayMode);
633
displayWidth[a] = displayMode.w;
634
displayHeight[a] = displayMode.h;
635
636
if (memcmp(&currentDisplay, &displayMode, sizeof(displayMode)) == 0) {
637
displayModeIndex = a;
638
}
639
}
640
641
displayCount = SDL_GetNumDisplayModes(currentWindowDisplay);
642
if (displayInfo.displays)
643
free(displayInfo.displays);
644
645
displayInfo.displays = (decltype(displayInfo.displays))malloc(sizeof(SDL_DisplayMode) * displayCount);
646
int32 newDisplayCount = 0;
647
bool32 foundFullScreenDisplay = false;
648
649
for (int32 d = displayCount - 1; d >= 0; --d) {
650
SDL_GetDisplayMode(currentWindowDisplay, d, &displayInfo.displays[newDisplayCount].internal);
651
652
int32 refreshRate = displayInfo.displays[newDisplayCount].refresh_rate;
653
if (refreshRate >= 59 && (refreshRate <= 60 || refreshRate >= 120) && displayInfo.displays[newDisplayCount].height >= (SCREEN_YSIZE * 2)) {
654
if (newDisplayCount != 0 && refreshRate == 60 && displayInfo.displays[newDisplayCount - 1].refresh_rate == 59) {
655
memcpy(&displayInfo.displays[newDisplayCount - 1], &displayInfo.displays[newDisplayCount], sizeof(displayInfo.displays[0]));
656
--newDisplayCount;
657
}
658
659
if (videoSettings.fsWidth == displayInfo.displays[newDisplayCount].width
660
&& videoSettings.fsHeight == displayInfo.displays[newDisplayCount].height)
661
foundFullScreenDisplay = true;
662
663
++newDisplayCount;
664
}
665
}
666
667
displayCount = newDisplayCount;
668
if (!foundFullScreenDisplay) {
669
videoSettings.fsWidth = 0;
670
videoSettings.fsHeight = 0;
671
videoSettings.refreshRate = 60; // 0;
672
}
673
}
674
675
void RenderDevice::GetWindowSize(int32 *width, int32 *height)
676
{
677
if (!videoSettings.windowed) {
678
SDL_GetRendererOutputSize(renderer, width, height);
679
}
680
else {
681
int32 currentWindowDisplay = SDL_GetWindowDisplayIndex(window);
682
683
SDL_DisplayMode display;
684
SDL_GetCurrentDisplayMode(currentWindowDisplay, &display);
685
686
if (width)
687
*width = display.w;
688
689
if (height)
690
*height = display.h;
691
}
692
}
693
694
void RenderDevice::ProcessEvent(SDL_Event event)
695
{
696
switch (event.type) {
697
case SDL_WINDOWEVENT:
698
switch (event.window.event) {
699
case SDL_WINDOWEVENT_MAXIMIZED: {
700
SDL_RestoreWindow(window);
701
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
702
SDL_ShowCursor(SDL_FALSE);
703
videoSettings.windowed = false;
704
break;
705
}
706
707
case SDL_WINDOWEVENT_CLOSE: isRunning = false; break;
708
709
case SDL_WINDOWEVENT_FOCUS_GAINED:
710
#if RETRO_REV02
711
SKU::userCore->focusState = 0;
712
#endif
713
break;
714
715
case SDL_WINDOWEVENT_FOCUS_LOST:
716
#if RETRO_REV02
717
SKU::userCore->focusState = 1;
718
#endif
719
break;
720
}
721
break;
722
723
case SDL_CONTROLLERDEVICEADDED: {
724
SDL_GameController *game_controller = SDL_GameControllerOpen(event.cdevice.which);
725
726
if (game_controller != NULL) {
727
uint32 id;
728
char idBuffer[0x20];
729
sprintf_s(idBuffer, sizeof(idBuffer), "SDLDevice%d", SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(game_controller)));
730
GenerateHashCRC(&id, idBuffer);
731
732
if (SKU::InitSDL2InputDevice(id, game_controller) == NULL)
733
SDL_GameControllerClose(game_controller);
734
}
735
736
break;
737
}
738
739
case SDL_CONTROLLERDEVICEREMOVED: {
740
uint32 id;
741
char idBuffer[0x20];
742
sprintf_s(idBuffer, sizeof(idBuffer), "SDLDevice%d", event.cdevice.which);
743
GenerateHashCRC(&id, idBuffer);
744
745
RemoveInputDevice(InputDeviceFromID(id));
746
break;
747
}
748
749
case SDL_APP_WILLENTERFOREGROUND:
750
#if RETRO_REV02
751
SKU::userCore->focusState = 0;
752
#endif
753
break;
754
755
case SDL_APP_WILLENTERBACKGROUND:
756
#if RETRO_REV02
757
SKU::userCore->focusState = 1;
758
#endif
759
break;
760
761
case SDL_APP_TERMINATING: isRunning = false; break;
762
763
case SDL_MOUSEBUTTONDOWN:
764
switch (event.button.button) {
765
case SDL_BUTTON_LEFT: touchInfo.down[0] = true; touchInfo.count = 1;
766
#if !RETRO_REV02
767
RSDK::SKU::buttonDownCount++;
768
#endif
769
break;
770
771
case SDL_BUTTON_RIGHT:
772
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
773
RSDK::SKU::specialKeyStates[3] = true;
774
RSDK::SKU::buttonDownCount++;
775
#endif
776
break;
777
}
778
break;
779
780
case SDL_MOUSEBUTTONUP:
781
switch (event.button.button) {
782
case SDL_BUTTON_LEFT: touchInfo.down[0] = false; touchInfo.count = 0;
783
#if !RETRO_REV02
784
RSDK::SKU::buttonDownCount--;
785
#endif
786
break;
787
788
case SDL_BUTTON_RIGHT:
789
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
790
RSDK::SKU::specialKeyStates[3] = false;
791
RSDK::SKU::buttonDownCount--;
792
#endif
793
break;
794
}
795
break;
796
797
case SDL_FINGERMOTION:
798
case SDL_FINGERDOWN:
799
case SDL_FINGERUP: {
800
int32 count = SDL_GetNumTouchFingers(event.tfinger.touchId);
801
touchInfo.count = 0;
802
for (int32 i = 0; i < count; i++) {
803
SDL_Finger *finger = SDL_GetTouchFinger(event.tfinger.touchId, i);
804
if (finger) {
805
touchInfo.down[touchInfo.count] = true;
806
touchInfo.x[touchInfo.count] = finger->x;
807
touchInfo.y[touchInfo.count] = finger->y;
808
touchInfo.count++;
809
}
810
}
811
break;
812
}
813
814
case SDL_KEYDOWN:
815
#if !RETRO_REV02
816
++RSDK::SKU::buttonDownCount;
817
#endif
818
switch (event.key.keysym.scancode) {
819
case SDL_SCANCODE_RETURN:
820
if (event.key.keysym.mod & KMOD_LALT) {
821
videoSettings.windowed ^= 1;
822
UpdateGameWindow();
823
changedVideoSettings = false;
824
break;
825
}
826
827
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
828
RSDK::SKU::specialKeyStates[1] = true;
829
#endif
830
// [fallthrough]
831
832
default:
833
#if RETRO_INPUTDEVICE_KEYBOARD
834
SKU::UpdateKeyState(event.key.keysym.scancode);
835
#endif
836
break;
837
838
case SDL_SCANCODE_ESCAPE:
839
if (engine.devMenu) {
840
#if RETRO_REV0U
841
if (sceneInfo.state == ENGINESTATE_DEVMENU || RSDK::Legacy::gameMode == RSDK::Legacy::ENGINE_DEVMENU)
842
#else
843
if (sceneInfo.state == ENGINESTATE_DEVMENU)
844
#endif
845
CloseDevMenu();
846
else
847
OpenDevMenu();
848
}
849
else {
850
#if RETRO_INPUTDEVICE_KEYBOARD
851
SKU::UpdateKeyState(event.key.keysym.scancode);
852
#endif
853
}
854
855
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
856
RSDK::SKU::specialKeyStates[0] = true;
857
#endif
858
break;
859
860
#if !RETRO_USE_ORIGINAL_CODE
861
case SDL_SCANCODE_F1:
862
if (engine.devMenu) {
863
sceneInfo.listPos--;
864
while (sceneInfo.listPos < sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart
865
|| sceneInfo.listPos > sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd
866
|| !sceneInfo.listCategory[sceneInfo.activeCategory].sceneCount) {
867
sceneInfo.activeCategory--;
868
if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {
869
sceneInfo.activeCategory = sceneInfo.categoryCount - 1;
870
}
871
sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd - 1;
872
}
873
874
#if RETRO_REV0U
875
switch (engine.version) {
876
default: break;
877
case 5: LoadScene(); break;
878
case 4:
879
case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;
880
}
881
#else
882
LoadScene();
883
#endif
884
}
885
break;
886
887
case SDL_SCANCODE_F2:
888
if (engine.devMenu) {
889
sceneInfo.listPos++;
890
while (sceneInfo.listPos < sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart
891
|| sceneInfo.listPos > sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd
892
|| !sceneInfo.listCategory[sceneInfo.activeCategory].sceneCount) {
893
sceneInfo.activeCategory++;
894
if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {
895
sceneInfo.activeCategory = 0;
896
}
897
sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart;
898
}
899
900
#if RETRO_REV0U
901
switch (engine.version) {
902
default: break;
903
case 5: LoadScene(); break;
904
case 4:
905
case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;
906
}
907
#else
908
LoadScene();
909
#endif
910
}
911
break;
912
#endif
913
914
case SDL_SCANCODE_F3:
915
if (userShaderCount)
916
videoSettings.shaderID = (videoSettings.shaderID + 1) % userShaderCount;
917
break;
918
919
#if !RETRO_USE_ORIGINAL_CODE
920
case SDL_SCANCODE_F4:
921
if (engine.devMenu)
922
engine.showEntityInfo ^= 1;
923
break;
924
925
case SDL_SCANCODE_F5:
926
if (engine.devMenu) {
927
// Quick-Reload
928
#if RETRO_USE_MOD_LOADER
929
if (event.key.keysym.mod & KMOD_LCTRL)
930
RefreshModFolders();
931
#endif
932
933
#if RETRO_REV0U
934
switch (engine.version) {
935
default: break;
936
case 5: LoadScene(); break;
937
case 4:
938
case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;
939
}
940
#else
941
LoadScene();
942
#endif
943
}
944
break;
945
946
case SDL_SCANCODE_F6:
947
if (engine.devMenu && videoSettings.screenCount > 1)
948
videoSettings.screenCount--;
949
break;
950
951
case SDL_SCANCODE_F7:
952
if (engine.devMenu && videoSettings.screenCount < SCREEN_COUNT)
953
videoSettings.screenCount++;
954
break;
955
956
case SDL_SCANCODE_F8:
957
if (engine.devMenu)
958
engine.showUpdateRanges ^= 1;
959
break;
960
961
case SDL_SCANCODE_F9:
962
if (engine.devMenu)
963
showHitboxes ^= 1;
964
break;
965
966
case SDL_SCANCODE_F10:
967
if (engine.devMenu)
968
engine.showPaletteOverlay ^= 1;
969
break;
970
#endif
971
case SDL_SCANCODE_BACKSPACE:
972
if (engine.devMenu)
973
engine.gameSpeed = engine.fastForwardSpeed;
974
break;
975
976
case SDL_SCANCODE_F11:
977
case SDL_SCANCODE_INSERT:
978
if (engine.devMenu)
979
engine.frameStep = true;
980
break;
981
982
case SDL_SCANCODE_F12:
983
case SDL_SCANCODE_PAUSE:
984
if (engine.devMenu) {
985
#if RETRO_REV0U
986
switch (engine.version) {
987
default: break;
988
case 5:
989
if (sceneInfo.state != ENGINESTATE_NONE)
990
sceneInfo.state ^= ENGINESTATE_STEPOVER;
991
break;
992
case 4:
993
case 3:
994
if (RSDK::Legacy::stageMode != ENGINESTATE_NONE)
995
RSDK::Legacy::stageMode ^= RSDK::Legacy::STAGEMODE_STEPOVER;
996
break;
997
}
998
#else
999
if (sceneInfo.state != ENGINESTATE_NONE)
1000
sceneInfo.state ^= ENGINESTATE_STEPOVER;
1001
#endif
1002
}
1003
break;
1004
}
1005
break;
1006
1007
case SDL_KEYUP:
1008
#if !RETRO_REV02
1009
--RSDK::SKU::buttonDownCount;
1010
#endif
1011
switch (event.key.keysym.scancode) {
1012
default:
1013
#if RETRO_INPUTDEVICE_KEYBOARD
1014
SKU::ClearKeyState(event.key.keysym.scancode);
1015
#endif
1016
break;
1017
1018
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1019
case SDL_SCANCODE_ESCAPE:
1020
RSDK::SKU::specialKeyStates[0] = false;
1021
SKU::ClearKeyState(event.key.keysym.scancode);
1022
break;
1023
1024
case SDL_SCANCODE_RETURN:
1025
RSDK::SKU::specialKeyStates[1] = false;
1026
SKU::ClearKeyState(event.key.keysym.scancode);
1027
break;
1028
#endif
1029
case SDL_SCANCODE_BACKSPACE: engine.gameSpeed = 1; break;
1030
}
1031
break;
1032
1033
case SDL_QUIT: isRunning = false; break;
1034
}
1035
}
1036
1037
bool RenderDevice::ProcessEvents()
1038
{
1039
SDL_Event sdlEvent;
1040
1041
while (SDL_PollEvent(&sdlEvent)) {
1042
ProcessEvent(sdlEvent);
1043
1044
if (!isRunning)
1045
return false;
1046
}
1047
1048
return isRunning;
1049
}
1050
1051
void RenderDevice::SetupImageTexture(int32 width, int32 height, uint8 *imagePixels)
1052
{
1053
if (lastTextureFormat != SHADER_RGB_IMAGE) {
1054
if (imageTexture)
1055
SDL_DestroyTexture(imageTexture);
1056
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
1057
1058
imageTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);
1059
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
1060
1061
lastTextureFormat = SHADER_RGB_IMAGE;
1062
}
1063
1064
int32 texPitch = 0;
1065
uint32 *pixels = NULL;
1066
SDL_LockTexture(imageTexture, NULL, (void **)&pixels, &texPitch);
1067
1068
int32 pitch = (texPitch >> 2) - width;
1069
uint32 *imagePixels32 = (uint32 *)imagePixels;
1070
for (int32 y = 0; y < height; ++y) {
1071
for (int32 x = 0; x < width; ++x) {
1072
*pixels++ = *imagePixels32++;
1073
}
1074
1075
pixels += pitch;
1076
}
1077
1078
SDL_UnlockTexture(imageTexture);
1079
}
1080
1081
void RenderDevice::SetupVideoTexture_YUV420(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,
1082
int32 strideV)
1083
{
1084
if (lastTextureFormat != SHADER_YUV_420) {
1085
if (imageTexture)
1086
SDL_DestroyTexture(imageTexture);
1087
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
1088
1089
imageTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, width, height);
1090
1091
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
1092
lastTextureFormat = SHADER_YUV_420;
1093
}
1094
1095
SDL_UpdateYUVTexture(imageTexture, NULL, yPlane, strideY, uPlane, strideU, vPlane, strideV);
1096
}
1097
void RenderDevice::SetupVideoTexture_YUV422(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,
1098
int32 strideV)
1099
{
1100
if (lastTextureFormat != SHADER_YUV_422) {
1101
if (imageTexture)
1102
SDL_DestroyTexture(imageTexture);
1103
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
1104
1105
imageTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, width, height);
1106
1107
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
1108
lastTextureFormat = SHADER_YUV_422;
1109
}
1110
1111
SDL_UpdateYUVTexture(imageTexture, NULL, yPlane, strideY, uPlane, strideU, vPlane, strideV);
1112
}
1113
void RenderDevice::SetupVideoTexture_YUV444(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,
1114
int32 strideV)
1115
{
1116
if (lastTextureFormat != SHADER_YUV_444) {
1117
if (imageTexture)
1118
SDL_DestroyTexture(imageTexture);
1119
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
1120
1121
imageTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, width, height);
1122
1123
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
1124
lastTextureFormat = SHADER_YUV_444;
1125
}
1126
1127
SDL_UpdateYUVTexture(imageTexture, NULL, yPlane, strideY, uPlane, strideU, vPlane, strideV);
1128
}
1129
1130