Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/RSDKv5/RSDK/Graphics/GLFW/GLFWRenderDevice.cpp
1163 views
1
#ifndef _GLVERSION
2
#define _GLVERSION 20
3
//#define _GLVERSION 33
4
#endif
5
6
#if _GLVERSION > 30
7
#define _GLSLVERSION "#version 130\n#define in_V in\n#define in_F in\n"
8
#else
9
#define _GLSLVERSION "#version 110\n#define in_V attribute\n#define out varying\n#define in_F varying\n"
10
#endif
11
12
#if RETRO_REV02
13
#define _GLDEFINE "#define RETRO_REV02 (1)\n"
14
#else
15
#define _GLDEFINE "\n"
16
#endif
17
18
const GLchar *backupVertex = R"aa(
19
in_V vec3 in_pos;
20
in_V vec2 in_UV;
21
out vec4 ex_color;
22
out vec2 ex_UV;
23
24
void main()
25
{
26
gl_Position = vec4(in_pos, 1.0);
27
ex_color = vec4(1.0);
28
ex_UV = in_UV;
29
}
30
)aa";
31
32
const GLchar *backupFragment = R"aa(
33
in_F vec2 ex_UV;
34
in_F vec4 ex_color;
35
36
uniform sampler2D texDiffuse;
37
38
void main()
39
{
40
gl_FragColor = texture2D(texDiffuse, ex_UV);
41
}
42
)aa";
43
44
GLFWwindow *RenderDevice::window;
45
GLuint RenderDevice::VAO;
46
GLuint RenderDevice::VBO;
47
48
GLuint RenderDevice::screenTextures[SCREEN_COUNT];
49
GLuint RenderDevice::imageTexture;
50
51
double RenderDevice::lastFrame;
52
double RenderDevice::targetFreq;
53
54
int32 RenderDevice::monitorIndex;
55
56
uint32 *RenderDevice::videoBuffer;
57
58
// Creates a window using the video settings
59
GLFWwindow *RenderDevice::CreateGLFWWindow(void)
60
{
61
GLFWwindow *win;
62
GLFWmonitor *monitor = NULL;
63
int32 w, h;
64
65
glfwWindowHint(GLFW_DECORATED, videoSettings.bordered);
66
67
if (videoSettings.windowed) {
68
w = videoSettings.windowWidth;
69
h = videoSettings.windowHeight;
70
}
71
else if (videoSettings.fsWidth <= 0 || videoSettings.fsHeight <= 0) {
72
monitor = glfwGetPrimaryMonitor();
73
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
74
w = mode->width;
75
h = mode->height;
76
}
77
else {
78
monitor = glfwGetPrimaryMonitor();
79
w = videoSettings.fsWidth;
80
h = videoSettings.fsHeight;
81
}
82
83
win = glfwCreateWindow(w, h, gameVerInfo.gameTitle, monitor, NULL);
84
if (!win) {
85
PrintLog(PRINT_NORMAL, "ERROR: [GLFW] window creation failed");
86
return NULL;
87
}
88
if (videoSettings.windowed) {
89
// Center the window
90
monitor = glfwGetPrimaryMonitor();
91
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
92
int x, y;
93
glfwGetMonitorPos(monitor, &x, &y);
94
// Get scaling for HiDPI screens
95
float xscale, yscale;
96
glfwGetMonitorContentScale(monitor, &xscale, &yscale);
97
int xpos = x + (mode->width - (int)((float)videoSettings.windowWidth * xscale)) / 2;
98
int ypos = y + (mode->height - (int)((float)videoSettings.windowHeight * yscale)) / 2;
99
glfwSetWindowPos(win, xpos, ypos);
100
}
101
glfwShowWindow(win);
102
PrintLog(PRINT_NORMAL, "w: %d h: %d windowed: %d", w, h, videoSettings.windowed);
103
104
glfwSetKeyCallback(win, ProcessKeyEvent);
105
glfwSetMouseButtonCallback(win, ProcessMouseEvent);
106
glfwSetWindowFocusCallback(win, ProcessFocusEvent);
107
glfwSetWindowMaximizeCallback(win, ProcessMaximizeEvent);
108
109
return win;
110
}
111
112
bool RenderDevice::Init()
113
{
114
glfwInit();
115
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, _GLVERSION / 10);
116
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, _GLVERSION % 10);
117
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
118
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
119
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
120
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); // HiDPI scaling support
121
#if GLFW_VERSION_MAJOR >= 3 && GLFW_VERSION_MINOR >= 4
122
// Disable framebuffer scaling which (surprisingly) makes the framebuffer scale correctly on Wayland
123
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_FALSE);
124
#endif
125
126
if ((window = CreateGLFWWindow()) == NULL)
127
return false;
128
129
glfwSetJoystickCallback(ProcessJoystickEvent);
130
131
if (!SetupRendering() || !AudioDevice::Init())
132
return false;
133
134
InitInputDevices();
135
return true;
136
}
137
138
bool RenderDevice::SetupRendering()
139
{
140
glfwMakeContextCurrent(window);
141
GLenum err = glewInit();
142
// Wayland workaround, see https://github.com/nigels-com/glew/issues/172
143
if (err != GLEW_OK && err != GLEW_ERROR_NO_GLX_DISPLAY) {
144
PrintLog(PRINT_NORMAL, "ERROR: failed to initialize GLEW: %s", glewGetErrorString(err));
145
return false;
146
}
147
148
glfwSwapInterval(videoSettings.vsync ? 1 : 0);
149
150
GetDisplays();
151
152
if (!InitGraphicsAPI() || !InitShaders())
153
return false;
154
155
int32 size = videoSettings.pixWidth >= SCREEN_YSIZE ? videoSettings.pixWidth : SCREEN_YSIZE;
156
scanlines = (ScanlineInfo *)malloc(size * sizeof(ScanlineInfo));
157
memset(scanlines, 0, size * sizeof(ScanlineInfo));
158
159
videoSettings.windowState = WINDOWSTATE_ACTIVE;
160
videoSettings.dimMax = 1.0;
161
videoSettings.dimPercent = 1.0;
162
163
return true;
164
}
165
166
void RenderDevice::GetDisplays()
167
{
168
GLFWmonitor *monitor = glfwGetWindowMonitor(window);
169
if (!monitor)
170
monitor = glfwGetPrimaryMonitor();
171
const GLFWvidmode *displayMode = glfwGetVideoMode(monitor);
172
int32 monitorCount;
173
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
174
175
for (int32 m = 0; m < monitorCount; ++m) {
176
const GLFWvidmode *vidMode = glfwGetVideoMode(monitors[m]);
177
displayWidth[m] = vidMode->width;
178
displayHeight[m] = vidMode->height;
179
if (!memcmp(vidMode, displayMode, sizeof(GLFWvidmode))) {
180
monitorIndex = m;
181
}
182
}
183
184
const GLFWvidmode *displayModes = glfwGetVideoModes(monitor, &displayCount);
185
if (displayInfo.displays)
186
free(displayInfo.displays);
187
188
displayInfo.displays = (decltype(displayInfo.displays))malloc(sizeof(GLFWvidmode) * displayCount);
189
int32 newDisplayCount = 0;
190
bool32 foundFullScreenDisplay = false;
191
192
for (int32 d = 0; d < displayCount; ++d) {
193
memcpy(&displayInfo.displays[newDisplayCount].internal, &displayModes[d], sizeof(GLFWvidmode));
194
195
int32 refreshRate = displayInfo.displays[newDisplayCount].refresh_rate;
196
if (refreshRate >= 59 && (refreshRate <= 60 || refreshRate >= 120) && displayInfo.displays[newDisplayCount].height >= (SCREEN_YSIZE * 2)) {
197
if (d && refreshRate == 60 && displayInfo.displays[newDisplayCount - 1].refresh_rate == 59)
198
--newDisplayCount;
199
200
if (videoSettings.fsWidth == displayInfo.displays[newDisplayCount].width
201
&& videoSettings.fsHeight == displayInfo.displays[newDisplayCount].height)
202
foundFullScreenDisplay = true;
203
204
++newDisplayCount;
205
}
206
}
207
208
displayCount = newDisplayCount;
209
if (!foundFullScreenDisplay) {
210
videoSettings.fsWidth = 0;
211
videoSettings.fsHeight = 0;
212
videoSettings.refreshRate = 60; // 0;
213
}
214
}
215
216
bool RenderDevice::InitGraphicsAPI()
217
{
218
glClearColor(0.0, 0.0, 0.0, 1.0);
219
glDisable(GL_DEPTH_TEST);
220
glDisable(GL_DITHER);
221
glDisable(GL_BLEND);
222
glDisable(GL_SCISSOR_TEST);
223
glDisable(GL_CULL_FACE);
224
225
// setup buffers
226
227
#if _GLVERSION > 30
228
glGenVertexArrays(1, &VAO);
229
glBindVertexArray(VAO);
230
#endif
231
232
glGenBuffers(1, &VBO);
233
glBindBuffer(GL_ARRAY_BUFFER, VBO);
234
glBufferData(GL_ARRAY_BUFFER, sizeof(RenderVertex) * (!RETRO_REV02 ? 24 : 60), NULL, GL_DYNAMIC_DRAW);
235
236
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(RenderVertex), 0);
237
glEnableVertexAttribArray(0);
238
// glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(RenderVertex), (void *)offsetof(RenderVertex, color));
239
// glEnableVertexAttribArray(1);
240
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(RenderVertex), (void *)offsetof(RenderVertex, tex));
241
glEnableVertexAttribArray(1);
242
243
if (videoSettings.windowed || !videoSettings.exclusiveFS) {
244
if (videoSettings.windowed) {
245
viewSize.x = videoSettings.windowWidth;
246
viewSize.y = videoSettings.windowHeight;
247
}
248
else {
249
viewSize.x = displayWidth[monitorIndex];
250
viewSize.y = displayHeight[monitorIndex];
251
}
252
}
253
else {
254
int32 bufferWidth = videoSettings.fsWidth;
255
int32 bufferHeight = videoSettings.fsHeight;
256
if (videoSettings.fsWidth <= 0 || videoSettings.fsHeight <= 0) {
257
bufferWidth = displayWidth[monitorIndex];
258
bufferHeight = displayHeight[monitorIndex];
259
}
260
viewSize.x = bufferWidth;
261
viewSize.y = bufferHeight;
262
}
263
264
int32 maxPixHeight = 0;
265
#if !RETRO_USE_ORIGINAL_CODE
266
int32 screenWidth = 0;
267
#endif
268
for (int32 s = 0; s < SCREEN_COUNT; ++s) {
269
if (videoSettings.pixHeight > maxPixHeight)
270
maxPixHeight = videoSettings.pixHeight;
271
272
screens[s].size.y = videoSettings.pixHeight;
273
274
float viewAspect = viewSize.x / viewSize.y;
275
#if !RETRO_USE_ORIGINAL_CODE
276
screenWidth = (int32)((viewAspect * videoSettings.pixHeight) + 3) & 0xFFFFFFFC;
277
#else
278
int32 screenWidth = (int32)((viewAspect * videoSettings.pixHeight) + 3) & 0xFFFFFFFC;
279
#endif
280
if (screenWidth < videoSettings.pixWidth)
281
screenWidth = videoSettings.pixWidth;
282
283
#if !RETRO_USE_ORIGINAL_CODE
284
if (customSettings.maxPixWidth && screenWidth > customSettings.maxPixWidth)
285
screenWidth = customSettings.maxPixWidth;
286
#else
287
if (screenWidth > DEFAULT_PIXWIDTH)
288
screenWidth = DEFAULT_PIXWIDTH;
289
#endif
290
291
memset(&screens[s].frameBuffer, 0, sizeof(screens[s].frameBuffer));
292
SetScreenSize(s, screenWidth, screens[s].size.y);
293
}
294
295
pixelSize.x = screens[0].size.x;
296
pixelSize.y = screens[0].size.y;
297
float pixAspect = pixelSize.x / pixelSize.y;
298
299
Vector2 viewportPos{};
300
Vector2 lastViewSize;
301
302
glfwGetWindowSize(window, &lastViewSize.x, &lastViewSize.y);
303
Vector2 viewportSize = lastViewSize;
304
305
if ((viewSize.x / viewSize.y) <= ((pixelSize.x / pixelSize.y) + 0.1)) {
306
if ((pixAspect - 0.1) > (viewSize.x / viewSize.y)) {
307
viewSize.y = (pixelSize.y / pixelSize.x) * viewSize.x;
308
viewportPos.y = (lastViewSize.y >> 1) - (viewSize.y * 0.5);
309
viewportSize.y = viewSize.y;
310
}
311
}
312
else {
313
viewSize.x = pixAspect * viewSize.y;
314
viewportPos.x = (lastViewSize.x >> 1) - ((pixAspect * viewSize.y) * 0.5);
315
viewportSize.x = (pixAspect * viewSize.y);
316
}
317
318
#if !RETRO_USE_ORIGINAL_CODE
319
if (screenWidth <= 512 && maxPixHeight <= 256) {
320
#else
321
if (maxPixHeight <= 256) {
322
#endif
323
textureSize.x = 512.0;
324
textureSize.y = 256.0;
325
}
326
else {
327
textureSize.x = 1024.0;
328
textureSize.y = 512.0;
329
}
330
331
glViewport(viewportPos.x, viewportPos.y, viewportSize.x, viewportSize.y);
332
333
glActiveTexture(GL_TEXTURE0);
334
glGenTextures(SCREEN_COUNT, screenTextures);
335
336
for (int32 i = 0; i < SCREEN_COUNT; ++i) {
337
glBindTexture(GL_TEXTURE_2D, screenTextures[i]);
338
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureSize.x, textureSize.y, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
339
340
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
341
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
342
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
343
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
344
}
345
glGenTextures(1, &imageTexture);
346
glBindTexture(GL_TEXTURE_2D, imageTexture);
347
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, RETRO_VIDEO_TEXTURE_W, RETRO_VIDEO_TEXTURE_H, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
348
349
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
350
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
351
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
352
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
353
354
videoBuffer = new uint32[RETRO_VIDEO_TEXTURE_W * RETRO_VIDEO_TEXTURE_H];
355
356
lastShaderID = -1;
357
InitVertexBuffer();
358
engine.inFocus = 1;
359
videoSettings.viewportX = viewportPos.x;
360
videoSettings.viewportY = viewportPos.y;
361
videoSettings.viewportW = 1.0 / viewSize.x;
362
videoSettings.viewportH = 1.0 / viewSize.y;
363
364
return true;
365
}
366
367
// CUSTOM BUFFER FOR SHENANIGAN PURPOSES
368
// GL hates us and it's coordinate system is reverse of DX
369
// for shader output equivalency, we havee to flip everything
370
// X and Y are negated, some verts are specifically moved to match
371
// U and V are 0/1s and flipped from what it was originally
372
// clang-format off
373
#if RETRO_REV02
374
const RenderVertex rsdkGLVertexBuffer[60] = {
375
// 1 Screen (0)
376
{ { +1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
377
{ { +1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
378
{ { -1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
379
{ { +1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
380
{ { -1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
381
{ { -1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
382
383
// 2 Screens - Bordered (Top Screen) (6)
384
{ { +0.5, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
385
{ { +0.5, +1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
386
{ { -0.5, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
387
{ { +0.5, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
388
{ { -0.5, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
389
{ { -0.5, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
390
391
// 2 Screens - Bordered (Bottom Screen) (12)
392
{ { +0.5, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
393
{ { +0.5, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
394
{ { -0.5, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
395
{ { +0.5, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
396
{ { -0.5, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
397
{ { -0.5, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
398
399
// 2 Screens - Stretched (Top Screen) (18)
400
{ { +1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
401
{ { +1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
402
{ { -1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
403
{ { +1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
404
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
405
{ { -1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
406
407
// 2 Screens - Stretched (Bottom Screen) (24)
408
{ { +1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
409
{ { +1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
410
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
411
{ { +1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
412
{ { -1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
413
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
414
415
// 4 Screens (Top-Left) (30)
416
{ { 0.0, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
417
{ { 0.0, +1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
418
{ { -1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
419
{ { 0.0, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
420
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
421
{ { -1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
422
423
// 4 Screens (Top-Right) (36)
424
{ { +1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
425
{ { +1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
426
{ { 0.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
427
{ { +1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
428
{ { 0.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
429
{ { 0.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
430
431
// 4 Screens (Bottom-Right) (42)
432
{ { 0.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
433
{ { 0.0, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
434
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
435
{ { 0.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
436
{ { -1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
437
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
438
439
// 4 Screens (Bottom-Left) (48)
440
{ { +1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
441
{ { +1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
442
{ { 0.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
443
{ { +1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
444
{ { 0.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
445
{ { 0.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
446
447
// Image/Video (54)
448
{ { +1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
449
{ { +1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
450
{ { -1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
451
{ { +1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
452
{ { -1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
453
{ { -1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } }
454
};
455
#else
456
const RenderVertex rsdkGLVertexBuffer[24] =
457
{
458
// 1 Screen (0)
459
{ { +1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
460
{ { +1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
461
{ { -1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
462
{ { +1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
463
{ { -1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
464
{ { -1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
465
466
// 2 Screens - Stretched (Top Screen) (6)
467
{ { +1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
468
{ { +1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
469
{ { -1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
470
{ { +1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
471
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
472
{ { -1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
473
474
// 2 Screens - Stretched (Bottom Screen) (12)
475
{ { +1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
476
{ { +1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
477
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
478
{ { +1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
479
{ { -1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
480
{ { -1.0, 0.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
481
482
// Image/Video (18)
483
{ { +1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
484
{ { +1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 0.0 } },
485
{ { -1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } },
486
{ { +1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 1.0, 1.0 } },
487
{ { -1.0, -1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 1.0 } },
488
{ { -1.0, +1.0, 1.0 }, 0xFFFFFFFF, { 0.0, 0.0 } }
489
};
490
#endif
491
492
493
void RenderDevice::InitVertexBuffer()
494
{
495
RenderVertex vertBuffer[sizeof(rsdkGLVertexBuffer) / sizeof(RenderVertex)];
496
memcpy(vertBuffer, rsdkGLVertexBuffer, sizeof(rsdkGLVertexBuffer));
497
498
float x = 0.5 / (float)viewSize.x;
499
float y = 0.5 / (float)viewSize.y;
500
501
// ignore the last 6 verts, they're scaled to the 1024x512 textures already!
502
int32 vertCount = (RETRO_REV02 ? 60 : 24) - 6;
503
for (int32 v = 0; v < vertCount; ++v) {
504
RenderVertex *vertex = &vertBuffer[v];
505
vertex->pos.x = vertex->pos.x + x;
506
vertex->pos.y = vertex->pos.y - y;
507
508
if (vertex->tex.x)
509
vertex->tex.x = screens[0].size.x * (1.0 / textureSize.x);
510
511
if (vertex->tex.y)
512
vertex->tex.y = screens[0].size.y * (1.0 / textureSize.y);
513
}
514
515
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(RenderVertex) * (!RETRO_REV02 ? 24 : 60), vertBuffer);
516
}
517
518
void RenderDevice::InitFPSCap()
519
{
520
lastFrame = glfwGetTime();
521
targetFreq = 1.0 / videoSettings.refreshRate;
522
}
523
bool RenderDevice::CheckFPSCap()
524
{
525
if (lastFrame + targetFreq < glfwGetTime())
526
return true;
527
528
return false;
529
}
530
void RenderDevice::UpdateFPSCap() { lastFrame = glfwGetTime(); }
531
532
void RenderDevice::CopyFrameBuffer()
533
{
534
for (int32 s = 0; s < videoSettings.screenCount; ++s) {
535
glBindTexture(GL_TEXTURE_2D, screenTextures[s]);
536
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, screens[s].pitch, SCREEN_YSIZE, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, screens[s].frameBuffer);
537
}
538
}
539
540
bool RenderDevice::ProcessEvents()
541
{
542
glfwPollEvents();
543
if (glfwWindowShouldClose(window))
544
isRunning = false;
545
return false;
546
}
547
548
void RenderDevice::FlipScreen()
549
{
550
if (lastShaderID != videoSettings.shaderID) {
551
lastShaderID = videoSettings.shaderID;
552
553
SetLinear(shaderList[videoSettings.shaderID].linear);
554
555
if (videoSettings.shaderSupport)
556
glUseProgram(shaderList[videoSettings.shaderID].programID);
557
}
558
559
if (windowRefreshDelay > 0) {
560
windowRefreshDelay--;
561
if (!windowRefreshDelay)
562
UpdateGameWindow();
563
return;
564
}
565
566
glClear(GL_COLOR_BUFFER_BIT);
567
if (videoSettings.shaderSupport) {
568
glUniform2fv(glGetUniformLocation(shaderList[videoSettings.shaderID].programID, "textureSize"), 1, &textureSize.x);
569
glUniform2fv(glGetUniformLocation(shaderList[videoSettings.shaderID].programID, "pixelSize"), 1, &pixelSize.x);
570
glUniform2fv(glGetUniformLocation(shaderList[videoSettings.shaderID].programID, "viewSize"), 1, &viewSize.x);
571
glUniform1f(glGetUniformLocation(shaderList[videoSettings.shaderID].programID, "screenDim"), videoSettings.dimMax * videoSettings.dimPercent);
572
}
573
574
int32 startVert = 0;
575
switch (videoSettings.screenCount) {
576
default:
577
case 0:
578
#if RETRO_REV02
579
startVert = 54;
580
#else
581
startVert = 18;
582
#endif
583
glBindTexture(GL_TEXTURE_2D, imageTexture);
584
glDrawArrays(GL_TRIANGLES, startVert, 6);
585
586
break;
587
588
case 1:
589
glBindTexture(GL_TEXTURE_2D, screenTextures[0]);
590
glDrawArrays(GL_TRIANGLES, 0, 6);
591
break;
592
593
case 2:
594
#if RETRO_REV02
595
startVert = startVertex_2P[0];
596
#else
597
startVert = 6;
598
#endif
599
glBindTexture(GL_TEXTURE_2D, screenTextures[0]);
600
glDrawArrays(GL_TRIANGLES, startVert, 6);
601
602
#if RETRO_REV02
603
startVert = startVertex_2P[1];
604
#else
605
startVert = 12;
606
#endif
607
glBindTexture(GL_TEXTURE_2D, screenTextures[1]);
608
glDrawArrays(GL_TRIANGLES, startVert, 6);
609
break;
610
611
#if RETRO_REV02
612
case 3:
613
// also flipped
614
glBindTexture(GL_TEXTURE_2D, screenTextures[0]);
615
glDrawArrays(GL_TRIANGLES, startVertex_3P[0], 6);
616
617
glBindTexture(GL_TEXTURE_2D, screenTextures[1]);
618
glDrawArrays(GL_TRIANGLES, startVertex_3P[1], 6);
619
620
glBindTexture(GL_TEXTURE_2D, screenTextures[2]);
621
glDrawArrays(GL_TRIANGLES, startVertex_3P[2], 6);
622
break;
623
624
case 4:
625
// this too
626
glBindTexture(GL_TEXTURE_2D, screenTextures[0]);
627
glDrawArrays(GL_TRIANGLES, 30, 6);
628
glBindTexture(GL_TEXTURE_2D, screenTextures[1]);
629
glDrawArrays(GL_TRIANGLES, 36, 6);
630
631
glBindTexture(GL_TEXTURE_2D, screenTextures[2]);
632
glDrawArrays(GL_TRIANGLES, 42, 6);
633
634
glBindTexture(GL_TEXTURE_2D, screenTextures[3]);
635
glDrawArrays(GL_TRIANGLES, 48, 6);
636
break;
637
#endif
638
}
639
640
glFlush();
641
glfwSwapBuffers(window);
642
}
643
644
void RenderDevice::Release(bool32 isRefresh)
645
{
646
glDeleteTextures(SCREEN_COUNT, screenTextures);
647
glDeleteTextures(1, &imageTexture);
648
if (videoBuffer)
649
delete[] videoBuffer;
650
for (int32 i = 0; i < shaderCount; ++i) {
651
glDeleteProgram(shaderList[i].programID);
652
}
653
654
#if _GLVERSION > 30
655
glDeleteVertexArrays(1, &VAO);
656
glDeleteBuffers(1, &VBO);
657
#endif
658
659
shaderCount = 0;
660
#if RETRO_USE_MOD_LOADER
661
userShaderCount = 0;
662
#endif
663
664
glfwDestroyWindow(window);
665
666
if (!isRefresh) {
667
if (displayInfo.displays)
668
free(displayInfo.displays);
669
displayInfo.displays = NULL;
670
671
if (scanlines)
672
free(scanlines);
673
scanlines = NULL;
674
675
glfwTerminate();
676
}
677
}
678
679
bool RenderDevice::InitShaders()
680
{
681
videoSettings.shaderSupport = true;
682
int32 maxShaders = 0;
683
#if RETRO_USE_MOD_LOADER
684
shaderCount = 0;
685
#endif
686
687
LoadShader("None", false);
688
LoadShader("Clean", true);
689
LoadShader("CRT-Yeetron", true);
690
LoadShader("CRT-Yee64", true);
691
692
#if RETRO_USE_MOD_LOADER
693
// a place for mods to load custom shaders
694
RunModCallbacks(MODCB_ONSHADERLOAD, NULL);
695
userShaderCount = shaderCount;
696
#endif
697
698
LoadShader("YUV-420", true);
699
LoadShader("YUV-422", true);
700
LoadShader("YUV-444", true);
701
LoadShader("RGB-Image", true);
702
maxShaders = shaderCount;
703
704
// no shaders == no support
705
if (!maxShaders) {
706
ShaderEntry *shader = &shaderList[0];
707
videoSettings.shaderSupport = false;
708
709
// let's load
710
maxShaders = 1;
711
shaderCount = 1;
712
713
GLint success;
714
char infoLog[0x1000];
715
716
717
GLuint vert, frag;
718
const GLchar *vchar[] = { _GLSLVERSION, _GLDEFINE, backupVertex };
719
vert = glCreateShader(GL_VERTEX_SHADER);
720
glShaderSource(vert, 3, vchar, NULL);
721
glCompileShader(vert);
722
723
const GLchar *fchar[] = { _GLSLVERSION, _GLDEFINE, backupFragment };
724
frag = glCreateShader(GL_FRAGMENT_SHADER);
725
glShaderSource(frag, 3, fchar, NULL);
726
glCompileShader(frag);
727
728
glGetShaderiv(vert, GL_COMPILE_STATUS, &success);
729
if (!success) {
730
glGetShaderInfoLog(vert, 0x1000, NULL, infoLog);
731
PrintLog(PRINT_NORMAL, "BACKUP vertex shader compiling failed:\n%s", infoLog);
732
}
733
734
glGetShaderiv(frag, GL_COMPILE_STATUS, &success);
735
if (!success) {
736
glGetShaderInfoLog(frag, 0x1000, NULL, infoLog);
737
PrintLog(PRINT_NORMAL, "BACKUP fragment shader compiling failed:\n%s", infoLog);
738
}
739
shader->programID = glCreateProgram();
740
glAttachShader(shader->programID, vert);
741
glAttachShader(shader->programID, frag);
742
743
glBindAttribLocation(shader->programID, 0, "in_pos");
744
//glBindAttribLocation(shader->programID, 1, "in_color");
745
glBindAttribLocation(shader->programID, 1, "in_UV");
746
747
glLinkProgram(shader->programID);
748
glDeleteShader(vert);
749
glDeleteShader(frag);
750
751
glUseProgram(shader->programID);
752
753
shader->linear = videoSettings.windowed ? false : shader->linear;
754
}
755
756
videoSettings.shaderID = MAX(videoSettings.shaderID >= maxShaders ? 0 : videoSettings.shaderID, 0);
757
SetLinear(shaderList[videoSettings.shaderID].linear || videoSettings.screenCount > 1);
758
759
return true;
760
}
761
762
void RenderDevice::LoadShader(const char *fileName, bool32 linear)
763
{
764
char fullFilePath[0x100];
765
FileInfo info;
766
767
for (int32 i = 0; i < shaderCount; ++i) {
768
if (strcmp(shaderList[i].name, fileName) == 0)
769
return;
770
}
771
772
if (shaderCount == SHADER_COUNT)
773
return;
774
775
ShaderEntry *shader = &shaderList[shaderCount];
776
sprintf_s(shader->name, sizeof(shader->name), "%s", fileName);
777
778
GLint success;
779
char infoLog[0x1000];
780
GLuint vert, frag;
781
sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Shaders/OGL/None.vs");
782
InitFileInfo(&info);
783
if (LoadFile(&info, fullFilePath, FMODE_RB)) {
784
uint8 *fileData = NULL;
785
AllocateStorage((void **)&fileData, info.fileSize + 1, DATASET_TMP, false);
786
ReadBytes(&info, fileData, info.fileSize);
787
fileData[info.fileSize] = 0;
788
CloseFile(&info);
789
790
const GLchar *glchar[] = { _GLSLVERSION, _GLDEFINE, (const GLchar *)fileData };
791
vert = glCreateShader(GL_VERTEX_SHADER);
792
glShaderSource(vert, 3, glchar, NULL);
793
glCompileShader(vert);
794
RemoveStorageEntry((void **)&fileData);
795
796
glGetShaderiv(vert, GL_COMPILE_STATUS, &success);
797
if (!success) {
798
glGetShaderInfoLog(vert, 0x1000, NULL, infoLog);
799
PrintLog(PRINT_NORMAL, "Vertex shader compiling failed:\n%s", infoLog);
800
return;
801
}
802
}
803
else
804
return;
805
806
sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Shaders/OGL/%s.fs", fileName);
807
InitFileInfo(&info);
808
if (LoadFile(&info, fullFilePath, FMODE_RB)) {
809
uint8 *fileData = NULL;
810
AllocateStorage((void **)&fileData, info.fileSize + 1, DATASET_TMP, false);
811
ReadBytes(&info, fileData, info.fileSize);
812
fileData[info.fileSize] = 0;
813
CloseFile(&info);
814
815
const GLchar *glchar[] = { _GLSLVERSION, _GLDEFINE, (const GLchar *)fileData };
816
frag = glCreateShader(GL_FRAGMENT_SHADER);
817
glShaderSource(frag, 3, glchar, NULL);
818
glCompileShader(frag);
819
RemoveStorageEntry((void **)&fileData);
820
821
glGetShaderiv(frag, GL_COMPILE_STATUS, &success);
822
if (!success) {
823
glGetShaderInfoLog(frag, 0x1000, NULL, infoLog);
824
PrintLog(PRINT_NORMAL, "Fragment shader compiling failed:\n%s", infoLog);
825
return;
826
}
827
}
828
else
829
return;
830
831
shader->linear = linear;
832
833
shader->programID = glCreateProgram();
834
glAttachShader(shader->programID, vert);
835
glAttachShader(shader->programID, frag);
836
837
glBindAttribLocation(shader->programID, 0, "in_pos");
838
//glBindAttribLocation(shader->programID, 1, "in_color");
839
glBindAttribLocation(shader->programID, 1, "in_UV");
840
841
glLinkProgram(shader->programID);
842
glGetProgramiv(shader->programID, GL_LINK_STATUS, &success);
843
if (!success) {
844
glGetProgramInfoLog(shader->programID, 0x1000, NULL, infoLog);
845
PrintLog(PRINT_NORMAL, "OpenGL shader linking failed:\n%s", infoLog);
846
return;
847
}
848
glDeleteShader(vert);
849
glDeleteShader(frag);
850
851
shaderCount++;
852
};
853
854
void RenderDevice::RefreshWindow()
855
{
856
videoSettings.windowState = WINDOWSTATE_UNINITIALIZED;
857
858
Release(true);
859
860
if ((window = CreateGLFWWindow()) == NULL)
861
return;
862
863
glfwMakeContextCurrent(window);
864
865
if (!InitGraphicsAPI() || !InitShaders())
866
return;
867
868
videoSettings.windowState = WINDOWSTATE_ACTIVE;
869
}
870
871
void RenderDevice::GetWindowSize(int32 *width, int32 *height)
872
{
873
int32 widest = 0, highest = 0, count = 0;
874
GLFWmonitor **monitors = glfwGetMonitors(&count);
875
for (int32 i = 0; i < count; i++) {
876
const GLFWvidmode *mode = glfwGetVideoMode(monitors[i]);
877
if (mode->height > highest) {
878
highest = mode->height;
879
widest = mode->width;
880
}
881
}
882
if (width)
883
*width = widest;
884
if (height)
885
*height = highest;
886
}
887
888
void RenderDevice::SetupImageTexture(int32 width, int32 height, uint8 *imagePixels)
889
{
890
if (imagePixels) {
891
glBindTexture(GL_TEXTURE_2D, imageTexture);
892
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, imagePixels);
893
}
894
}
895
896
void RenderDevice::SetupVideoTexture_YUV420(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,
897
int32 strideV)
898
{
899
uint32 *pixels = videoBuffer;
900
uint32 *preY = pixels;
901
int32 pitch = RETRO_VIDEO_TEXTURE_W - width;
902
903
if (videoSettings.shaderSupport) {
904
for (int32 y = 0; y < height; ++y) {
905
for (int32 x = 0; x < width; ++x) {
906
*pixels++ = (yPlane[x] << 16) | 0xFF000000;
907
}
908
909
pixels += pitch;
910
yPlane += strideY;
911
}
912
913
pixels = preY;
914
pitch = RETRO_VIDEO_TEXTURE_W - (width >> 1);
915
for (int32 y = 0; y < (height >> 1); ++y) {
916
for (int32 x = 0; x < (width >> 1); ++x) {
917
*pixels++ |= (vPlane[x] << 0) | (uPlane[x] << 8) | 0xFF000000;
918
}
919
920
pixels += pitch;
921
uPlane += strideU;
922
vPlane += strideV;
923
}
924
}
925
else {
926
// No shader support means no YUV support! at least use the brightness to show it in grayscale!
927
for (int32 y = 0; y < height; ++y) {
928
for (int32 x = 0; x < width; ++x) {
929
int32 brightness = yPlane[x];
930
*pixels++ = (brightness << 0) | (brightness << 8) | (brightness << 16) | 0xFF000000;
931
}
932
933
pixels += pitch;
934
yPlane += strideY;
935
}
936
}
937
glBindTexture(GL_TEXTURE_2D, imageTexture);
938
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, RETRO_VIDEO_TEXTURE_W, RETRO_VIDEO_TEXTURE_H, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, videoBuffer);
939
}
940
941
void RenderDevice::SetupVideoTexture_YUV422(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,
942
int32 strideV)
943
{
944
uint32 *pixels = videoBuffer;
945
uint32 *preY = pixels;
946
int32 pitch = RETRO_VIDEO_TEXTURE_W - width;
947
948
if (videoSettings.shaderSupport) {
949
for (int32 y = 0; y < height; ++y) {
950
for (int32 x = 0; x < width; ++x) {
951
*pixels++ = (yPlane[x] << 16) | 0xFF000000;
952
}
953
954
pixels += pitch;
955
yPlane += strideY;
956
}
957
958
pixels = preY;
959
pitch = RETRO_VIDEO_TEXTURE_W - (width >> 1);
960
for (int32 y = 0; y < height; ++y) {
961
for (int32 x = 0; x < (width >> 1); ++x) {
962
*pixels++ |= (vPlane[x] << 0) | (uPlane[x] << 8) | 0xFF000000;
963
}
964
965
pixels += pitch;
966
uPlane += strideU;
967
vPlane += strideV;
968
}
969
}
970
else {
971
// No shader support means no YUV support! at least use the brightness to show it in grayscale!
972
for (int32 y = 0; y < height; ++y) {
973
for (int32 x = 0; x < width; ++x) {
974
int32 brightness = yPlane[x];
975
*pixels++ = (brightness << 0) | (brightness << 8) | (brightness << 16) | 0xFF000000;
976
}
977
978
pixels += pitch;
979
yPlane += strideY;
980
}
981
}
982
983
glBindTexture(GL_TEXTURE_2D, imageTexture);
984
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, RETRO_VIDEO_TEXTURE_W, RETRO_VIDEO_TEXTURE_H, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, videoBuffer);
985
}
986
void RenderDevice::SetupVideoTexture_YUV444(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,
987
int32 strideV)
988
{
989
uint32 *pixels = videoBuffer;
990
int32 pitch = RETRO_VIDEO_TEXTURE_W - width;
991
992
if (videoSettings.shaderSupport) {
993
for (int32 y = 0; y < height; ++y) {
994
int32 pos1 = yPlane - vPlane;
995
int32 pos2 = uPlane - vPlane;
996
uint8 *pixV = vPlane;
997
for (int32 x = 0; x < width; ++x) {
998
*pixels++ = pixV[0] | (pixV[pos2] << 8) | (pixV[pos1] << 16) | 0xFF000000;
999
pixV++;
1000
}
1001
1002
pixels += pitch;
1003
yPlane += strideY;
1004
uPlane += strideU;
1005
vPlane += strideV;
1006
}
1007
}
1008
else {
1009
// No shader support means no YUV support! at least use the brightness to show it in grayscale!
1010
for (int32 y = 0; y < height; ++y) {
1011
for (int32 x = 0; x < width; ++x) {
1012
int32 brightness = yPlane[x];
1013
*pixels++ = (brightness << 0) | (brightness << 8) | (brightness << 16) | 0xFF000000;
1014
}
1015
1016
pixels += pitch;
1017
yPlane += strideY;
1018
}
1019
}
1020
glBindTexture(GL_TEXTURE_2D, imageTexture);
1021
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, RETRO_VIDEO_TEXTURE_W, RETRO_VIDEO_TEXTURE_H, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, videoBuffer);
1022
}
1023
1024
void RenderDevice::ProcessKeyEvent(GLFWwindow *, int32 key, int32 scancode, int32 action, int32 mods)
1025
{
1026
switch (action) {
1027
case GLFW_PRESS: {
1028
#if !RETRO_REV02
1029
++RSDK::SKU::buttonDownCount;
1030
#endif
1031
switch (key) {
1032
case GLFW_KEY_ENTER:
1033
if (mods & GLFW_MOD_ALT) {
1034
videoSettings.windowed ^= 1;
1035
UpdateGameWindow();
1036
changedVideoSettings = false;
1037
break;
1038
}
1039
1040
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1041
RSDK::SKU::specialKeyStates[1] = true;
1042
#endif
1043
1044
// [fallthrough]
1045
1046
default:
1047
#if RETRO_INPUTDEVICE_KEYBOARD
1048
SKU::UpdateKeyState(key);
1049
#endif
1050
break;
1051
1052
case GLFW_KEY_ESCAPE:
1053
if (engine.devMenu) {
1054
#if RETRO_REV0U
1055
if (sceneInfo.state == ENGINESTATE_DEVMENU || RSDK::Legacy::gameMode == RSDK::Legacy::ENGINE_DEVMENU)
1056
#else
1057
if (sceneInfo.state == ENGINESTATE_DEVMENU)
1058
#endif
1059
CloseDevMenu();
1060
else
1061
OpenDevMenu();
1062
}
1063
else {
1064
#if RETRO_INPUTDEVICE_KEYBOARD
1065
SKU::UpdateKeyState(key);
1066
#endif
1067
}
1068
1069
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1070
RSDK::SKU::specialKeyStates[0] = true;
1071
#endif
1072
break;
1073
1074
#if !RETRO_USE_ORIGINAL_CODE
1075
case GLFW_KEY_F1:
1076
if (engine.devMenu) {
1077
sceneInfo.listPos--;
1078
while (sceneInfo.listPos < sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart
1079
|| sceneInfo.listPos > sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd
1080
|| !sceneInfo.listCategory[sceneInfo.activeCategory].sceneCount) {
1081
sceneInfo.activeCategory--;
1082
if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {
1083
sceneInfo.activeCategory = sceneInfo.categoryCount - 1;
1084
}
1085
sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd - 1;
1086
}
1087
1088
#if RETRO_REV0U
1089
switch (engine.version) {
1090
default: break;
1091
case 5: LoadScene(); break;
1092
case 4:
1093
case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;
1094
}
1095
#else
1096
LoadScene();
1097
#endif
1098
}
1099
break;
1100
1101
case GLFW_KEY_F2:
1102
if (engine.devMenu) {
1103
sceneInfo.listPos++;
1104
while (sceneInfo.listPos < sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart
1105
|| sceneInfo.listPos > sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd
1106
|| !sceneInfo.listCategory[sceneInfo.activeCategory].sceneCount) {
1107
sceneInfo.activeCategory++;
1108
if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {
1109
sceneInfo.activeCategory = 0;
1110
}
1111
sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart;
1112
}
1113
1114
#if RETRO_REV0U
1115
switch (engine.version) {
1116
default: break;
1117
case 5: LoadScene(); break;
1118
case 4:
1119
case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;
1120
}
1121
#else
1122
LoadScene();
1123
#endif
1124
}
1125
break;
1126
#endif
1127
1128
case GLFW_KEY_F3:
1129
if (userShaderCount)
1130
videoSettings.shaderID = (videoSettings.shaderID + 1) % userShaderCount;
1131
break;
1132
1133
#if !RETRO_USE_ORIGINAL_CODE
1134
case GLFW_KEY_F4:
1135
if (engine.devMenu)
1136
engine.showEntityInfo ^= 1;
1137
break;
1138
1139
case GLFW_KEY_F5:
1140
if (engine.devMenu) {
1141
// Quick-Reload
1142
#if RETRO_USE_MOD_LOADER
1143
if (mods & GLFW_MOD_CONTROL)
1144
RefreshModFolders();
1145
#endif
1146
1147
#if RETRO_REV0U
1148
switch (engine.version) {
1149
default: break;
1150
case 5: LoadScene(); break;
1151
case 4:
1152
case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;
1153
}
1154
#else
1155
LoadScene();
1156
#endif
1157
}
1158
break;
1159
1160
case GLFW_KEY_F6:
1161
if (engine.devMenu && videoSettings.screenCount > 1)
1162
videoSettings.screenCount--;
1163
break;
1164
1165
case GLFW_KEY_F7:
1166
if (engine.devMenu && videoSettings.screenCount < SCREEN_COUNT)
1167
videoSettings.screenCount++;
1168
break;
1169
1170
case GLFW_KEY_F8:
1171
if (engine.devMenu)
1172
engine.showUpdateRanges ^= 1;
1173
break;
1174
1175
case GLFW_KEY_F9:
1176
if (engine.devMenu)
1177
showHitboxes ^= 1;
1178
break;
1179
1180
case GLFW_KEY_F10:
1181
if (engine.devMenu)
1182
engine.showPaletteOverlay ^= 1;
1183
break;
1184
#endif
1185
case GLFW_KEY_BACKSPACE:
1186
if (engine.devMenu)
1187
engine.gameSpeed = engine.fastForwardSpeed;
1188
break;
1189
1190
case GLFW_KEY_F11:
1191
case GLFW_KEY_INSERT:
1192
if (engine.devMenu)
1193
engine.frameStep = true;
1194
break;
1195
1196
case GLFW_KEY_F12:
1197
case GLFW_KEY_PAUSE:
1198
if (engine.devMenu) {
1199
#if RETRO_REV0U
1200
switch (engine.version) {
1201
default: break;
1202
case 5:
1203
if (sceneInfo.state != ENGINESTATE_NONE)
1204
sceneInfo.state ^= ENGINESTATE_STEPOVER;
1205
break;
1206
case 4:
1207
case 3:
1208
if (RSDK::Legacy::stageMode != ENGINESTATE_NONE)
1209
RSDK::Legacy::stageMode ^= RSDK::Legacy::STAGEMODE_STEPOVER;
1210
break;
1211
}
1212
#else
1213
if (sceneInfo.state != ENGINESTATE_NONE)
1214
sceneInfo.state ^= ENGINESTATE_STEPOVER;
1215
#endif
1216
}
1217
break;
1218
}
1219
break;
1220
}
1221
case GLFW_RELEASE: {
1222
#if !RETRO_REV02
1223
--RSDK::SKU::buttonDownCount;
1224
#endif
1225
switch (key) {
1226
default:
1227
#if RETRO_INPUTDEVICE_KEYBOARD
1228
SKU::ClearKeyState(key);
1229
#endif
1230
break;
1231
1232
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1233
case GLFW_KEY_ESCAPE:
1234
RSDK::SKU::specialKeyStates[0] = false;
1235
SKU::ClearKeyState(key);
1236
break;
1237
1238
case GLFW_KEY_ENTER:
1239
RSDK::SKU::specialKeyStates[1] = false;
1240
SKU::ClearKeyState(key);
1241
break;
1242
#endif
1243
case GLFW_KEY_BACKSPACE: engine.gameSpeed = 1; break;
1244
}
1245
break;
1246
}
1247
}
1248
}
1249
void RenderDevice::ProcessFocusEvent(GLFWwindow *, int32 focused)
1250
{
1251
if (!focused) {
1252
#if RETRO_REV02
1253
SKU::userCore->focusState = 1;
1254
#endif
1255
}
1256
else {
1257
#if RETRO_REV02
1258
SKU::userCore->focusState = 0;
1259
#endif
1260
}
1261
}
1262
void RenderDevice::ProcessMouseEvent(GLFWwindow *, int32 button, int32 action, int32 mods)
1263
{
1264
switch (action) {
1265
case GLFW_PRESS: {
1266
switch (button) {
1267
case GLFW_MOUSE_BUTTON_LEFT: touchInfo.down[0] = true; touchInfo.count = 1;
1268
#if !RETRO_REV02
1269
RSDK::SKU::buttonDownCount++;
1270
#endif
1271
break;
1272
1273
case GLFW_MOUSE_BUTTON_RIGHT:
1274
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1275
RSDK::SKU::specialKeyStates[3] = true;
1276
RSDK::SKU::buttonDownCount++;
1277
#endif
1278
break;
1279
}
1280
break;
1281
}
1282
1283
case GLFW_RELEASE: {
1284
switch (button) {
1285
case GLFW_MOUSE_BUTTON_LEFT: touchInfo.down[0] = false; touchInfo.count = 0;
1286
#if !RETRO_REV02
1287
RSDK::SKU::buttonDownCount--;
1288
#endif
1289
break;
1290
1291
case GLFW_MOUSE_BUTTON_RIGHT:
1292
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1293
RSDK::SKU::specialKeyStates[3] = false;
1294
RSDK::SKU::buttonDownCount--;
1295
#endif
1296
break;
1297
}
1298
break;
1299
}
1300
}
1301
}
1302
void RenderDevice::ProcessJoystickEvent(int32 ID, int32 event)
1303
{
1304
#if RETRO_INPUTDEVICE_GLFW
1305
if (!glfwJoystickIsGamepad(ID))
1306
return;
1307
uint32 hash;
1308
char idBuffer[0x20];
1309
sprintf_s(idBuffer, sizeof(idBuffer), "%s%d", "GLFWDevice", ID);
1310
GenerateHashCRC(&hash, idBuffer);
1311
1312
if (event == GLFW_CONNECTED)
1313
SKU::InitGLFWInputDevice(hash, ID);
1314
else
1315
RemoveInputDevice(InputDeviceFromID(hash));
1316
#endif
1317
}
1318
void RenderDevice::ProcessMaximizeEvent(GLFWwindow *, int32 maximized)
1319
{
1320
// i don't know why this is a thing
1321
if (maximized) {
1322
// set fullscreen idk about the specifics rn
1323
}
1324
}
1325
1326
void RenderDevice::SetLinear(bool32 linear)
1327
{
1328
for (int32 i = 0; i < SCREEN_COUNT; ++i) {
1329
glBindTexture(GL_TEXTURE_2D, screenTextures[i]);
1330
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST);
1331
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST);
1332
}
1333
}
1334
1335