Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/RSDKv5/RSDK/Graphics/DX9/DX9RenderDevice.cpp
1163 views
1
#include "resource.h"
2
#if !RETRO_USE_ORIGINAL_CODE
3
#include <D3Dcompiler.h>
4
#endif
5
6
#include "Ks.h" // used for KSCATEGORY_AUDIO
7
#include "Ksmedia.h" // used for KSCATEGORY_AUDIO
8
9
// for some reason this seems to be applying "thick frame" instead of thin frame (intended)
10
// it is for this reason that I'm unable to get the cool mini window toolbar that og mania has :(
11
// tldr: microsoft sucks again
12
#define DX9_WINDOWFLAGS_BORDERED (WS_POPUP | (WS_BORDER | WS_DLGFRAME) | (WS_SYSMENU | WS_GROUP))
13
14
#define DX9_WINDOWFLAGS_BORDERLESS (WS_POPUP)
15
16
HWND RenderDevice::windowHandle;
17
18
HDEVNOTIFY RenderDevice::deviceNotif = 0;
19
PAINTSTRUCT RenderDevice::Paint;
20
21
IDirect3D9 *RenderDevice::dx9Context;
22
IDirect3DDevice9 *RenderDevice::dx9Device;
23
UINT RenderDevice::dxAdapter;
24
IDirect3DVertexDeclaration9 *RenderDevice::dx9VertexDeclare;
25
IDirect3DVertexBuffer9 *RenderDevice::dx9VertexBuffer;
26
IDirect3DTexture9 *RenderDevice::screenTextures[SCREEN_COUNT];
27
IDirect3DTexture9 *RenderDevice::imageTexture;
28
D3DVIEWPORT9 RenderDevice::dx9ViewPort;
29
30
int32 RenderDevice::adapterCount = 0;
31
RECT RenderDevice::monitorDisplayRect;
32
GUID RenderDevice::deviceIdentifier;
33
34
bool RenderDevice::useFrequency = false;
35
36
LARGE_INTEGER RenderDevice::performanceCount;
37
LARGE_INTEGER RenderDevice::frequency;
38
LARGE_INTEGER RenderDevice::initialFrequency;
39
LARGE_INTEGER RenderDevice::curFrequency;
40
41
// WinMain args
42
HINSTANCE RenderDevice::hInstance;
43
HINSTANCE RenderDevice::hPrevInstance;
44
INT RenderDevice::nShowCmd;
45
46
bool RenderDevice::Init()
47
{
48
#if _UNICODE
49
// shoddy workaround to get the title into wide chars in UNICODE mode
50
std::string str = gameVerInfo.gameTitle;
51
std::wstring temp = std::wstring(str.begin(), str.end());
52
LPCWSTR gameTitle = temp.c_str();
53
#else
54
std::string str = gameVerInfo.gameTitle;
55
LPCSTR gameTitle = str.c_str();
56
#endif
57
58
HMODULE handle = GetModuleHandle(NULL);
59
60
WNDCLASS wndClass = {};
61
wndClass.style = CS_VREDRAW | CS_HREDRAW;
62
wndClass.lpfnWndProc = WindowEventCallback;
63
wndClass.cbClsExtra = 0;
64
wndClass.cbWndExtra = sizeof(LONG);
65
wndClass.hInstance = hInstance;
66
wndClass.hIcon = LoadIcon(handle, IDI_APPLICATION);
67
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
68
wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
69
wndClass.lpszMenuName = NULL;
70
wndClass.lpszClassName = gameTitle;
71
if (!RegisterClass(&wndClass))
72
return false;
73
74
ShowCursor(false);
75
76
tagRECT winRect;
77
if (videoSettings.windowed) {
78
winRect.left = (GetSystemMetrics(SM_CXSCREEN) - videoSettings.windowWidth) / 2;
79
winRect.top = (GetSystemMetrics(SM_CYSCREEN) - videoSettings.windowHeight) / 2;
80
winRect.right = winRect.left + videoSettings.windowWidth;
81
winRect.bottom = winRect.top + videoSettings.windowHeight;
82
}
83
else if (videoSettings.fsWidth <= 0 || videoSettings.fsHeight <= 0) {
84
winRect.left = 0;
85
winRect.top = 0;
86
winRect.right = GetSystemMetrics(SM_CXSCREEN);
87
winRect.bottom = GetSystemMetrics(SM_CYSCREEN);
88
}
89
else {
90
winRect.left = (GetSystemMetrics(SM_CXSCREEN) - videoSettings.fsWidth) / 2;
91
winRect.top = (GetSystemMetrics(SM_CYSCREEN) - videoSettings.fsHeight) / 2;
92
winRect.right = winRect.left + videoSettings.fsWidth;
93
winRect.bottom = winRect.top + videoSettings.fsHeight;
94
}
95
96
uint32 windowFlags = 0;
97
if (videoSettings.bordered && videoSettings.windowed)
98
windowFlags = DX9_WINDOWFLAGS_BORDERED;
99
else
100
windowFlags = DX9_WINDOWFLAGS_BORDERLESS;
101
102
AdjustWindowRect(&winRect, windowFlags, false);
103
windowHandle = CreateWindowEx(WS_EX_LEFT, gameTitle, gameTitle, windowFlags, winRect.left, winRect.top, winRect.right - winRect.left,
104
winRect.bottom - winRect.top, NULL, NULL, hInstance, NULL);
105
106
PrintLog(PRINT_NORMAL, "w: %d h: %d windowed: %d", winRect.right - winRect.left, winRect.bottom - winRect.top, videoSettings.windowed);
107
108
if (!windowHandle)
109
return false;
110
111
ShowWindow(windowHandle, nShowCmd);
112
UpdateWindow(windowHandle);
113
114
if (!SetupRendering() || !AudioDevice::Init())
115
return false;
116
117
InitInputDevices();
118
return true;
119
}
120
121
void RenderDevice::CopyFrameBuffer()
122
{
123
dx9Device->SetTexture(0, NULL);
124
125
for (int32 s = 0; s < videoSettings.screenCount; ++s) {
126
D3DLOCKED_RECT rect;
127
128
if (SUCCEEDED(screenTextures[s]->LockRect(0, &rect, NULL, D3DLOCK_DISCARD))) {
129
WORD *pixels = (WORD *)rect.pBits;
130
uint16 *frameBuffer = screens[s].frameBuffer;
131
132
int32 screenPitch = screens[s].pitch;
133
int32 pitch = (rect.Pitch >> 1) - screenPitch;
134
135
for (int32 y = 0; y < SCREEN_YSIZE; ++y) {
136
int32 pixelCount = screenPitch >> 4;
137
for (int32 x = 0; x < pixelCount; ++x) {
138
pixels[0] = frameBuffer[0];
139
pixels[1] = frameBuffer[1];
140
pixels[2] = frameBuffer[2];
141
pixels[3] = frameBuffer[3];
142
pixels[4] = frameBuffer[4];
143
pixels[5] = frameBuffer[5];
144
pixels[6] = frameBuffer[6];
145
pixels[7] = frameBuffer[7];
146
pixels[8] = frameBuffer[8];
147
pixels[9] = frameBuffer[9];
148
pixels[10] = frameBuffer[10];
149
pixels[11] = frameBuffer[11];
150
pixels[12] = frameBuffer[12];
151
pixels[13] = frameBuffer[13];
152
pixels[14] = frameBuffer[14];
153
pixels[15] = frameBuffer[15];
154
155
frameBuffer += 16;
156
pixels += 16;
157
}
158
159
pixels += pitch;
160
}
161
162
screenTextures[s]->UnlockRect(0);
163
}
164
}
165
}
166
167
void RenderDevice::FlipScreen()
168
{
169
if (windowRefreshDelay > 0) {
170
if (!--windowRefreshDelay)
171
UpdateGameWindow();
172
173
return;
174
}
175
176
dx9Device->SetViewport(&displayInfo.viewport);
177
dx9Device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
178
dx9Device->SetViewport(&dx9ViewPort);
179
180
if (SUCCEEDED(dx9Device->BeginScene())) {
181
// reload shader if needed
182
if (lastShaderID != videoSettings.shaderID) {
183
lastShaderID = videoSettings.shaderID;
184
185
if (shaderList[videoSettings.shaderID].linear) {
186
dx9Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
187
dx9Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
188
}
189
else {
190
dx9Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
191
dx9Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
192
}
193
194
if (videoSettings.shaderSupport) {
195
dx9Device->SetVertexShader(shaderList[videoSettings.shaderID].vertexShaderObject);
196
dx9Device->SetPixelShader(shaderList[videoSettings.shaderID].pixelShaderObject);
197
dx9Device->SetVertexDeclaration(dx9VertexDeclare);
198
dx9Device->SetStreamSource(0, dx9VertexBuffer, 0, sizeof(RenderVertex));
199
}
200
else {
201
dx9Device->SetStreamSource(0, dx9VertexBuffer, 0, sizeof(RenderVertex));
202
dx9Device->SetFVF(D3DFVF_TEX1 | D3DFVF_DIFFUSE | D3DFVF_XYZ);
203
}
204
}
205
206
if (videoSettings.shaderSupport) {
207
float2 screenDim = { videoSettings.dimMax * videoSettings.dimPercent, 0 };
208
209
dx9Device->SetPixelShaderConstantF(0, &pixelSize.x, 1); // pixelSize
210
dx9Device->SetPixelShaderConstantF(1, &textureSize.x, 1); // textureSize
211
dx9Device->SetPixelShaderConstantF(2, &viewSize.x, 1); // viewSize
212
dx9Device->SetPixelShaderConstantF(3, &screenDim.x, 1); // screenDim
213
}
214
215
int32 startVert = 0;
216
switch (videoSettings.screenCount) {
217
default:
218
case 0:
219
#if RETRO_REV02
220
startVert = 54;
221
#else
222
startVert = 18;
223
#endif
224
dx9Device->SetTexture(0, imageTexture);
225
dx9Device->DrawPrimitive(D3DPT_TRIANGLELIST, startVert, 2);
226
dx9Device->EndScene();
227
break;
228
229
case 1:
230
dx9Device->SetTexture(0, screenTextures[0]);
231
dx9Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
232
break;
233
234
case 2:
235
#if RETRO_REV02
236
startVert = startVertex_2P[0];
237
#else
238
startVert = 6;
239
#endif
240
dx9Device->SetTexture(0, screenTextures[0]);
241
dx9Device->DrawPrimitive(D3DPT_TRIANGLELIST, startVert, 2);
242
243
#if RETRO_REV02
244
startVert = startVertex_2P[1];
245
#else
246
startVert = 12;
247
#endif
248
dx9Device->SetTexture(0, screenTextures[1]);
249
dx9Device->DrawPrimitive(D3DPT_TRIANGLELIST, startVert, 2);
250
break;
251
252
#if RETRO_REV02
253
case 3:
254
dx9Device->SetTexture(0, screenTextures[0]);
255
dx9Device->DrawPrimitive(D3DPT_TRIANGLELIST, startVertex_3P[0], 2);
256
257
dx9Device->SetTexture(0, screenTextures[1]);
258
dx9Device->DrawPrimitive(D3DPT_TRIANGLELIST, startVertex_3P[1], 2);
259
260
dx9Device->SetTexture(0, screenTextures[2]);
261
dx9Device->DrawPrimitive(D3DPT_TRIANGLELIST, startVertex_3P[2], 2);
262
break;
263
264
case 4:
265
dx9Device->SetTexture(0, screenTextures[0]);
266
dx9Device->DrawPrimitive(D3DPT_TRIANGLELIST, 30, 2);
267
268
dx9Device->SetTexture(0, screenTextures[1]);
269
dx9Device->DrawPrimitive(D3DPT_TRIANGLELIST, 36, 2);
270
271
dx9Device->SetTexture(0, screenTextures[2]);
272
dx9Device->DrawPrimitive(D3DPT_TRIANGLELIST, 42, 2);
273
274
dx9Device->SetTexture(0, screenTextures[3]);
275
dx9Device->DrawPrimitive(D3DPT_TRIANGLELIST, 48, 2);
276
break;
277
#endif
278
}
279
280
dx9Device->EndScene();
281
}
282
283
if (FAILED(dx9Device->Present(NULL, NULL, NULL, NULL)))
284
windowRefreshDelay = 8;
285
}
286
287
void RenderDevice::Release(bool32 isRefresh)
288
{
289
if (videoSettings.shaderSupport) {
290
for (int32 i = 0; i < shaderCount; ++i) {
291
if (shaderList[i].vertexShaderObject)
292
shaderList[i].vertexShaderObject->Release();
293
shaderList[i].vertexShaderObject = NULL;
294
295
if (shaderList[i].pixelShaderObject)
296
shaderList[i].pixelShaderObject->Release();
297
shaderList[i].pixelShaderObject = NULL;
298
}
299
300
shaderCount = 0;
301
#if RETRO_USE_MOD_LOADER
302
userShaderCount = 0;
303
#endif
304
}
305
306
if (imageTexture) {
307
imageTexture->Release();
308
imageTexture = NULL;
309
}
310
311
for (int32 i = 0; i < SCREEN_COUNT; ++i) {
312
if (screenTextures[i])
313
screenTextures[i]->Release();
314
315
screenTextures[i] = NULL;
316
}
317
318
if (!isRefresh && displayInfo.displays) {
319
free(displayInfo.displays);
320
displayInfo.displays = NULL;
321
}
322
323
if (dx9VertexBuffer) {
324
dx9VertexBuffer->Release();
325
dx9VertexBuffer = NULL;
326
}
327
328
if (isRefresh && dx9VertexDeclare) {
329
dx9VertexDeclare->Release();
330
dx9VertexDeclare = NULL;
331
}
332
333
if (dx9Device) {
334
dx9Device->Release();
335
dx9Device = NULL;
336
}
337
338
if (!isRefresh && dx9Context) {
339
dx9Context->Release();
340
dx9Context = NULL;
341
}
342
343
if (!isRefresh && scanlines) {
344
free(scanlines);
345
scanlines = NULL;
346
}
347
}
348
349
void RenderDevice::RefreshWindow()
350
{
351
videoSettings.windowState = WINDOWSTATE_UNINITIALIZED;
352
353
Release(true);
354
355
ShowWindow(windowHandle, SW_HIDE);
356
357
if (videoSettings.windowed && videoSettings.bordered)
358
SetWindowLong(windowHandle, GWL_STYLE, DX9_WINDOWFLAGS_BORDERED);
359
else
360
SetWindowLong(windowHandle, GWL_STYLE, DX9_WINDOWFLAGS_BORDERLESS);
361
362
Sleep(250); // zzzz.. mimimimi..
363
364
GetDisplays();
365
366
tagRECT rect;
367
if (videoSettings.windowed || !videoSettings.exclusiveFS) {
368
tagRECT winRect;
369
GetClientRect(windowHandle, &winRect);
370
371
tagPOINT topLeft, bottomRight;
372
topLeft.x = winRect.left;
373
topLeft.y = winRect.top;
374
bottomRight.x = winRect.right;
375
bottomRight.y = winRect.bottom;
376
377
ClientToScreen(windowHandle, &topLeft);
378
ClientToScreen(windowHandle, &bottomRight);
379
380
if (videoSettings.windowed) {
381
D3DDISPLAYMODE displayMode;
382
dx9Context->GetAdapterDisplayMode(dxAdapter, &displayMode);
383
384
if (videoSettings.windowWidth >= displayMode.Width || videoSettings.windowHeight >= displayMode.Height) {
385
videoSettings.windowWidth = (displayMode.Height / 480 * videoSettings.pixWidth);
386
videoSettings.windowHeight = displayMode.Height / 480 * videoSettings.pixHeight;
387
}
388
389
rect.left = (topLeft.x + bottomRight.x) / 2 - videoSettings.windowWidth / 2;
390
rect.top = (topLeft.y + bottomRight.y) / 2 - videoSettings.windowHeight / 2;
391
rect.right = (topLeft.x + bottomRight.x) / 2 + videoSettings.windowWidth / 2;
392
rect.bottom = (topLeft.y + bottomRight.y) / 2 + videoSettings.windowHeight / 2;
393
394
if (videoSettings.bordered)
395
AdjustWindowRect(&rect, DX9_WINDOWFLAGS_BORDERED, false);
396
else
397
AdjustWindowRect(&rect, DX9_WINDOWFLAGS_BORDERLESS, false);
398
399
if (rect.left < monitorDisplayRect.left || rect.right > monitorDisplayRect.right || rect.top < monitorDisplayRect.top
400
|| rect.bottom > monitorDisplayRect.bottom) {
401
rect.left = (monitorDisplayRect.right + monitorDisplayRect.left) / 2 - videoSettings.windowWidth / 2;
402
rect.top = (monitorDisplayRect.top + monitorDisplayRect.bottom) / 2 - videoSettings.windowHeight / 2;
403
rect.right = (monitorDisplayRect.right + monitorDisplayRect.left) / 2 + videoSettings.windowWidth / 2;
404
rect.bottom = (monitorDisplayRect.top + monitorDisplayRect.bottom) / 2 + videoSettings.windowHeight / 2;
405
406
if (videoSettings.bordered)
407
AdjustWindowRect(&rect, DX9_WINDOWFLAGS_BORDERED, false);
408
else
409
AdjustWindowRect(&rect, DX9_WINDOWFLAGS_BORDERLESS, false);
410
}
411
}
412
else {
413
rect = monitorDisplayRect;
414
AdjustWindowRect(&monitorDisplayRect, DX9_WINDOWFLAGS_BORDERLESS, 0);
415
}
416
417
SetWindowPos(windowHandle, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_SHOWWINDOW);
418
}
419
420
ShowWindow(windowHandle, SW_SHOW);
421
RedrawWindow(windowHandle, NULL, NULL, RDW_UPDATENOW | RDW_INVALIDATE);
422
423
if (!InitGraphicsAPI() || !InitShaders())
424
return;
425
426
videoSettings.windowState = WINDOWSTATE_ACTIVE;
427
}
428
429
void RenderDevice::InitFPSCap()
430
{
431
if (QueryPerformanceFrequency(&frequency)) {
432
useFrequency = true;
433
initialFrequency.QuadPart = frequency.QuadPart / videoSettings.refreshRate;
434
QueryPerformanceCounter(&performanceCount);
435
}
436
else {
437
useFrequency = false;
438
performanceCount.QuadPart = timeGetTime();
439
}
440
}
441
bool RenderDevice::CheckFPSCap()
442
{
443
if (useFrequency)
444
QueryPerformanceCounter(&curFrequency);
445
else
446
curFrequency.QuadPart = timeGetTime();
447
448
if (curFrequency.QuadPart > performanceCount.QuadPart)
449
return true;
450
451
return false;
452
}
453
void RenderDevice::UpdateFPSCap() { performanceCount.QuadPart = curFrequency.QuadPart + initialFrequency.LowPart; }
454
455
void RenderDevice::InitVertexBuffer()
456
{
457
RenderVertex vertBuffer[sizeof(rsdkVertexBuffer) / sizeof(RenderVertex)];
458
memcpy(vertBuffer, rsdkVertexBuffer, sizeof(rsdkVertexBuffer));
459
460
float x = 0.5 / (float)viewSize.x;
461
float y = 0.5 / (float)viewSize.y;
462
463
// ignore the last 6 verts, they're scaled to the 1024x512 textures already!
464
int32 vertCount = (RETRO_REV02 ? 60 : 24) - 6;
465
for (int32 v = 0; v < vertCount; ++v) {
466
RenderVertex *vertex = &vertBuffer[v];
467
vertex->pos.x = vertex->pos.x - x;
468
vertex->pos.y = vertex->pos.y + y;
469
470
if (vertex->tex.x)
471
vertex->tex.x = screens[0].size.x * (1.0 / textureSize.x);
472
473
if (vertex->tex.y)
474
vertex->tex.y = screens[0].size.y * (1.0 / textureSize.y);
475
}
476
477
RenderVertex *vertBufferPtr;
478
if (SUCCEEDED(dx9VertexBuffer->Lock(0, 0, (void **)&vertBufferPtr, 0))) {
479
memcpy(vertBufferPtr, vertBuffer, sizeof(vertBuffer));
480
dx9VertexBuffer->Unlock();
481
}
482
}
483
484
bool RenderDevice::InitGraphicsAPI()
485
{
486
videoSettings.shaderSupport = false;
487
488
D3DCAPS9 pCaps;
489
if (SUCCEEDED(dx9Context->GetDeviceCaps(0, D3DDEVTYPE_HAL, &pCaps)) && (pCaps.PixelShaderVersion & 0xFF00) >= 0x300)
490
videoSettings.shaderSupport = true;
491
492
viewSize.x = 0;
493
viewSize.y = 0;
494
495
D3DPRESENT_PARAMETERS presentParams;
496
ZeroMemory(&presentParams, sizeof(presentParams));
497
if (videoSettings.windowed || !videoSettings.exclusiveFS) {
498
presentParams.BackBufferWidth = 0;
499
presentParams.BackBufferHeight = 0;
500
presentParams.BackBufferFormat = D3DFMT_UNKNOWN;
501
presentParams.BackBufferCount = 1;
502
503
presentParams.MultiSampleType = D3DMULTISAMPLE_NONE;
504
presentParams.MultiSampleQuality = 0;
505
506
presentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
507
presentParams.hDeviceWindow = windowHandle;
508
presentParams.Windowed = true;
509
presentParams.EnableAutoDepthStencil = false;
510
presentParams.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
511
presentParams.Flags = 0;
512
513
presentParams.FullScreen_RefreshRateInHz = 0;
514
presentParams.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
515
516
if (videoSettings.windowed) {
517
viewSize.x = (float)videoSettings.windowWidth;
518
viewSize.y = (float)videoSettings.windowHeight;
519
}
520
else {
521
viewSize.x = (float)displayWidth[dxAdapter];
522
viewSize.y = (float)displayHeight[dxAdapter];
523
}
524
}
525
else {
526
int32 bufferWidth = videoSettings.fsWidth;
527
int32 bufferHeight = videoSettings.fsHeight;
528
if (videoSettings.fsWidth <= 0 || videoSettings.fsHeight <= 0) {
529
bufferWidth = displayWidth[dxAdapter];
530
bufferHeight = displayHeight[dxAdapter];
531
}
532
533
presentParams.BackBufferWidth = bufferWidth;
534
presentParams.BackBufferHeight = bufferHeight;
535
// for some reason this seems to force the window to have permanent top focus after coming out of fullscreen
536
// despite this being 1:1 with the original code and it not having that behaviour
537
// tldr: microsoft sucks
538
presentParams.BackBufferFormat = D3DFMT_X8R8G8B8;
539
presentParams.BackBufferCount = videoSettings.tripleBuffered ? 2 : 1;
540
541
presentParams.MultiSampleType = D3DMULTISAMPLE_NONE;
542
presentParams.MultiSampleQuality = 0;
543
544
presentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
545
presentParams.hDeviceWindow = windowHandle;
546
presentParams.Windowed = false;
547
presentParams.EnableAutoDepthStencil = false;
548
presentParams.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
549
presentParams.Flags = 0;
550
551
presentParams.FullScreen_RefreshRateInHz = videoSettings.refreshRate;
552
presentParams.PresentationInterval = videoSettings.vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
553
554
viewSize.x = (float)bufferWidth;
555
viewSize.y = (float)bufferHeight;
556
}
557
558
if (FAILED(dx9Context->CreateDevice(dxAdapter, D3DDEVTYPE_HAL, windowHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParams, &dx9Device)))
559
return false;
560
561
if (videoSettings.shaderSupport) {
562
D3DVERTEXELEMENT9 elements[4];
563
564
elements[0].Type = D3DDECLTYPE_FLOAT3;
565
elements[0].Method = 0;
566
elements[0].Stream = 0;
567
elements[0].Offset = 0;
568
elements[0].Usage = D3DDECLUSAGE_POSITION;
569
elements[0].UsageIndex = 0;
570
571
elements[1].Type = D3DDECLTYPE_D3DCOLOR;
572
elements[1].Method = 0;
573
elements[1].Stream = 0;
574
elements[1].Offset = offsetof(RenderVertex, color);
575
elements[1].Usage = D3DDECLUSAGE_COLOR;
576
elements[1].UsageIndex = 0;
577
578
elements[2].Type = D3DDECLTYPE_FLOAT2;
579
elements[2].Method = 0;
580
elements[2].Stream = 0;
581
elements[2].Offset = offsetof(RenderVertex, tex);
582
elements[2].Usage = D3DDECLUSAGE_TEXCOORD;
583
elements[2].UsageIndex = 0;
584
585
elements[3].Type = D3DDECLTYPE_UNUSED;
586
elements[3].Method = 0;
587
elements[3].Stream = 0xFF;
588
elements[3].Offset = 0;
589
elements[3].Usage = 0;
590
elements[3].UsageIndex = 0;
591
592
if (FAILED(dx9Device->CreateVertexDeclaration(elements, &dx9VertexDeclare)))
593
return false;
594
595
if (FAILED(dx9Device->CreateVertexBuffer(sizeof(rsdkVertexBuffer), 0, 0, D3DPOOL_DEFAULT, &dx9VertexBuffer, NULL)))
596
return false;
597
}
598
else {
599
if (FAILED(dx9Device->CreateVertexBuffer(sizeof(rsdkVertexBuffer), 0, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, D3DPOOL_DEFAULT,
600
&dx9VertexBuffer, NULL)))
601
return false;
602
}
603
604
int32 maxPixHeight = 0;
605
#if !RETRO_USE_ORIGINAL_CODE
606
int32 screenWidth = 0;
607
#endif
608
for (int32 s = 0; s < SCREEN_COUNT; ++s) {
609
if (videoSettings.pixHeight > maxPixHeight)
610
maxPixHeight = videoSettings.pixHeight;
611
612
screens[s].size.y = videoSettings.pixHeight;
613
614
float viewAspect = viewSize.x / viewSize.y;
615
#if !RETRO_USE_ORIGINAL_CODE
616
screenWidth = (int32)((viewAspect * videoSettings.pixHeight) + 3) & 0xFFFFFFFC;
617
#else
618
int32 screenWidth = (int32)((viewAspect * videoSettings.pixHeight) + 3) & 0xFFFFFFFC;
619
#endif
620
if (screenWidth < videoSettings.pixWidth)
621
screenWidth = videoSettings.pixWidth;
622
623
#if !RETRO_USE_ORIGINAL_CODE
624
if (customSettings.maxPixWidth && screenWidth > customSettings.maxPixWidth)
625
screenWidth = customSettings.maxPixWidth;
626
#else
627
if (screenWidth > DEFAULT_PIXWIDTH)
628
screenWidth = DEFAULT_PIXWIDTH;
629
#endif
630
631
memset(&screens[s].frameBuffer, 0, sizeof(screens[s].frameBuffer));
632
SetScreenSize(s, screenWidth, screens[s].size.y);
633
}
634
635
pixelSize.x = (float)screens[0].size.x;
636
pixelSize.y = (float)screens[0].size.y;
637
float pixAspect = pixelSize.x / pixelSize.y;
638
639
dx9Device->GetViewport(&displayInfo.viewport);
640
dx9ViewPort = displayInfo.viewport;
641
642
if ((viewSize.x / viewSize.y) <= ((pixelSize.x / pixelSize.y) + 0.1)) {
643
if ((pixAspect - 0.1) > (viewSize.x / viewSize.y)) {
644
viewSize.y = (pixelSize.y / pixelSize.x) * viewSize.x;
645
dx9ViewPort.Y = (DWORD)((displayInfo.viewport.Height >> 1) - (viewSize.y * 0.5));
646
dx9ViewPort.Height = (DWORD)viewSize.y;
647
648
dx9Device->SetViewport(&dx9ViewPort);
649
}
650
}
651
else {
652
viewSize.x = pixAspect * viewSize.y;
653
dx9ViewPort.X = (DWORD)((displayInfo.viewport.Width >> 1) - (viewSize.x * 0.5));
654
dx9ViewPort.Width = (DWORD)viewSize.x;
655
656
dx9Device->SetViewport(&dx9ViewPort);
657
}
658
659
#if !RETRO_USE_ORIGINAL_CODE
660
if (screenWidth <= 512 && maxPixHeight <= 256) {
661
#else
662
if (maxPixHeight <= 256) {
663
#endif
664
textureSize.x = 512.0;
665
textureSize.y = 256.0;
666
}
667
else {
668
textureSize.x = 1024.0;
669
textureSize.y = 512.0;
670
}
671
672
for (int32 s = 0; s < SCREEN_COUNT; ++s) {
673
if (FAILED(dx9Device->CreateTexture((UINT)textureSize.x, (UINT)textureSize.y, 1, D3DUSAGE_DYNAMIC, D3DFMT_R5G6B5, D3DPOOL_DEFAULT,
674
&screenTextures[s], NULL)))
675
return false;
676
}
677
678
if (FAILED(dx9Device->CreateTexture(RETRO_VIDEO_TEXTURE_W, RETRO_VIDEO_TEXTURE_H, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
679
&imageTexture, NULL)))
680
return false;
681
682
lastShaderID = -1;
683
InitVertexBuffer();
684
engine.inFocus = 1;
685
videoSettings.viewportX = (float)dx9ViewPort.X;
686
videoSettings.viewportY = (float)dx9ViewPort.Y;
687
videoSettings.viewportW = 1.0 / viewSize.x;
688
videoSettings.viewportH = 1.0 / viewSize.y;
689
690
return true;
691
}
692
693
void RenderDevice::LoadShader(const char *fileName, bool32 linear)
694
{
695
char fullFilePath[0x100];
696
FileInfo info;
697
698
for (int32 i = 0; i < shaderCount; ++i) {
699
if (strcmp(shaderList[i].name, fileName) == 0)
700
return;
701
}
702
703
if (shaderCount == SHADER_COUNT)
704
return;
705
706
ShaderEntry *shader = &shaderList[shaderCount];
707
shader->linear = linear;
708
sprintf_s(shader->name, sizeof(shader->name), "%s", fileName);
709
710
const D3D_SHADER_MACRO defines[] = {
711
#if RETRO_REV02
712
{ "RETRO_REV02" },
713
{ "1" },
714
#endif
715
{ NULL },
716
{ NULL }
717
};
718
719
#if !RETRO_USE_ORIGINAL_CODE
720
// Try to compile the vertex shader source if it exists
721
sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Shaders/DX9/%s.hlsl", fileName);
722
InitFileInfo(&info);
723
if (LoadFile(&info, fullFilePath, FMODE_RB)) {
724
uint8 *fileData = NULL;
725
AllocateStorage((void **)&fileData, info.fileSize, DATASET_TMP, false);
726
ReadBytes(&info, fileData, info.fileSize);
727
CloseFile(&info);
728
729
UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;
730
if (engine.devMenu) {
731
flags |= D3DCOMPILE_DEBUG;
732
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0;
733
flags |= D3DCOMPILE_WARNINGS_ARE_ERRORS;
734
}
735
else {
736
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
737
}
738
739
ID3DBlob *shaderBlob = nullptr;
740
ID3DBlob *errorBlob = nullptr;
741
HRESULT result = D3DCompile(fileData, info.fileSize, fullFilePath, defines, NULL, "VSMain", "vs_3_0", flags, 0, &shaderBlob, &errorBlob);
742
743
RemoveStorageEntry((void **)&fileData);
744
745
if (FAILED(result)) {
746
if (errorBlob) {
747
PrintLog(PRINT_NORMAL, "ERROR COMPILING VERTEX SHADER: %s", (char *)errorBlob->GetBufferPointer());
748
errorBlob->Release();
749
}
750
751
if (shaderBlob)
752
shaderBlob->Release();
753
754
return;
755
}
756
else {
757
PrintLog(PRINT_NORMAL, "Successfully compiled vertex shader!");
758
if (errorBlob)
759
PrintLog(PRINT_NORMAL, "Vertex shader warnings:\n%s", (char *)errorBlob->GetBufferPointer());
760
761
if (FAILED(dx9Device->CreateVertexShader((DWORD *)shaderBlob->GetBufferPointer(), &shader->vertexShaderObject))) {
762
if (shader->vertexShaderObject) {
763
shader->vertexShaderObject->Release();
764
shader->vertexShaderObject = NULL;
765
}
766
767
return;
768
}
769
}
770
}
771
else {
772
#endif
773
// if the vertex shader source doesn't exist, fall back and try to load the vertex shader bytecode
774
sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Shaders/CSO-DX9/%s.vso", fileName);
775
InitFileInfo(&info);
776
if (LoadFile(&info, fullFilePath, FMODE_RB)) {
777
uint8 *fileData = NULL;
778
AllocateStorage((void **)&fileData, info.fileSize, DATASET_TMP, false);
779
ReadBytes(&info, fileData, info.fileSize);
780
CloseFile(&info);
781
782
if (FAILED(dx9Device->CreateVertexShader((DWORD *)fileData, &shader->vertexShaderObject))) {
783
if (shader->vertexShaderObject) {
784
shader->vertexShaderObject->Release();
785
shader->vertexShaderObject = NULL;
786
}
787
788
RemoveStorageEntry((void **)&fileData);
789
return;
790
}
791
792
RemoveStorageEntry((void **)&fileData);
793
}
794
795
#if !RETRO_USE_ORIGINAL_CODE
796
}
797
#endif
798
799
#if !RETRO_USE_ORIGINAL_CODE
800
// Try to compile the pixel shader source if it exists
801
sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Shaders/DX9/%s.hlsl", fileName);
802
InitFileInfo(&info);
803
if (LoadFile(&info, fullFilePath, FMODE_RB)) {
804
uint8 *fileData = NULL;
805
AllocateStorage((void **)&fileData, info.fileSize, DATASET_TMP, false);
806
ReadBytes(&info, fileData, info.fileSize);
807
CloseFile(&info);
808
809
UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;
810
if (engine.devMenu) {
811
flags |= D3DCOMPILE_DEBUG;
812
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0;
813
flags |= D3DCOMPILE_WARNINGS_ARE_ERRORS;
814
}
815
else {
816
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
817
}
818
819
ID3DBlob *shaderBlob = nullptr;
820
ID3DBlob *errorBlob = nullptr;
821
HRESULT result = D3DCompile(fileData, info.fileSize, fullFilePath, defines, NULL, "PSMain", "ps_3_0", flags, 0, &shaderBlob, &errorBlob);
822
823
RemoveStorageEntry((void **)&fileData);
824
825
if (FAILED(result)) {
826
if (errorBlob) {
827
PrintLog(PRINT_NORMAL, "ERROR COMPILING PIXEL SHADER:\n%s", (char *)errorBlob->GetBufferPointer());
828
errorBlob->Release();
829
}
830
831
if (shaderBlob)
832
shaderBlob->Release();
833
}
834
else {
835
PrintLog(PRINT_NORMAL, "Successfully compiled pixel shader!");
836
if (errorBlob)
837
PrintLog(PRINT_NORMAL, "Pixel shader warnings:\n%s", (char *)errorBlob->GetBufferPointer());
838
839
if (FAILED(dx9Device->CreatePixelShader((DWORD *)shaderBlob->GetBufferPointer(), &shader->pixelShaderObject))) {
840
if (shader->vertexShaderObject) {
841
shader->vertexShaderObject->Release();
842
shader->vertexShaderObject = NULL;
843
}
844
845
return;
846
}
847
}
848
}
849
else {
850
#endif
851
// if the pixel shader source doesn't exist, fall back and try to load the pixel shader bytecode
852
sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Shaders/CSO-DX9/%s.fso", fileName);
853
InitFileInfo(&info);
854
if (LoadFile(&info, fullFilePath, FMODE_RB)) {
855
uint8 *fileData = NULL;
856
AllocateStorage((void **)&fileData, info.fileSize, DATASET_TMP, false);
857
ReadBytes(&info, fileData, info.fileSize);
858
CloseFile(&info);
859
860
if (FAILED(dx9Device->CreatePixelShader((DWORD *)fileData, &shader->pixelShaderObject))) {
861
if (shader->pixelShaderObject) {
862
shader->pixelShaderObject->Release();
863
shader->pixelShaderObject = NULL;
864
}
865
866
RemoveStorageEntry((void **)&fileData);
867
return;
868
}
869
870
RemoveStorageEntry((void **)&fileData);
871
}
872
873
#if !RETRO_USE_ORIGINAL_CODE
874
}
875
#endif
876
877
shaderCount++;
878
}
879
880
bool RenderDevice::InitShaders()
881
{
882
dx9Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
883
dx9Device->SetRenderState(D3DRS_LIGHTING, false);
884
dx9Device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
885
dx9Device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
886
dx9Device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
887
dx9Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
888
dx9Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
889
dx9Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
890
891
int32 maxShaders = 0;
892
#if RETRO_USE_MOD_LOADER
893
// this causes small memleaks here and in other render devices, as we never close the existing shaders
894
// TODO: fix? 🤨
895
shaderCount = 0;
896
#endif
897
if (videoSettings.shaderSupport) {
898
LoadShader("None", false);
899
LoadShader("Clean", true);
900
LoadShader("CRT-Yeetron", true);
901
LoadShader("CRT-Yee64", true);
902
903
#if RETRO_USE_MOD_LOADER
904
// a place for mods to load custom shaders
905
RunModCallbacks(MODCB_ONSHADERLOAD, NULL);
906
userShaderCount = shaderCount;
907
#endif
908
909
LoadShader("YUV-420", true);
910
LoadShader("YUV-422", true);
911
LoadShader("YUV-444", true);
912
LoadShader("RGB-Image", true);
913
maxShaders = shaderCount;
914
}
915
else {
916
for (int32 s = 0; s < SHADER_COUNT; ++s) shaderList[s].linear = true;
917
918
shaderList[0].linear = videoSettings.windowed ? false : shaderList[0].linear;
919
maxShaders = 1;
920
shaderCount = 1;
921
}
922
923
// no shaders == no support
924
if (!maxShaders) {
925
videoSettings.shaderSupport = false;
926
927
for (int32 s = 0; s < SHADER_COUNT; ++s) shaderList[s].linear = true;
928
929
shaderList[0].linear = videoSettings.windowed ? false : shaderList[0].linear;
930
maxShaders = 1;
931
shaderCount = 1;
932
}
933
934
videoSettings.shaderID = videoSettings.shaderID >= maxShaders ? 0 : videoSettings.shaderID;
935
936
if (shaderList[videoSettings.shaderID].linear || videoSettings.screenCount > 1) {
937
dx9Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
938
dx9Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
939
}
940
else {
941
dx9Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
942
dx9Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
943
}
944
945
dx9Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
946
947
return true;
948
}
949
950
bool RenderDevice::SetupRendering()
951
{
952
dx9Context = Direct3DCreate9(D3D_SDK_VERSION);
953
if (!dx9Context)
954
return false;
955
956
ZeroMemory(&deviceIdentifier, sizeof(deviceIdentifier));
957
958
GetDisplays();
959
960
if (!InitGraphicsAPI() || !InitShaders())
961
return false;
962
963
int32 size = videoSettings.pixWidth >= SCREEN_YSIZE ? videoSettings.pixWidth : SCREEN_YSIZE;
964
scanlines = (ScanlineInfo *)malloc(size * sizeof(ScanlineInfo));
965
memset(scanlines, 0, size * sizeof(ScanlineInfo));
966
967
videoSettings.windowState = WINDOWSTATE_ACTIVE;
968
videoSettings.dimMax = 1.0;
969
videoSettings.dimPercent = 1.0;
970
971
return true;
972
}
973
974
void RenderDevice::GetDisplays()
975
{
976
adapterCount = dx9Context->GetAdapterCount();
977
978
UINT prevAdapter = dxAdapter;
979
980
HMONITOR windowMonitor = MonitorFromWindow(windowHandle, MONITOR_DEFAULTTOPRIMARY);
981
dxAdapter = 0;
982
for (int32 a = 0; a < adapterCount; ++a) {
983
D3DDISPLAYMODE displayMode;
984
985
HMONITOR monitor = dx9Context->GetAdapterMonitor(a);
986
dx9Context->GetAdapterDisplayMode(a, &displayMode);
987
displayWidth[a] = displayMode.Width;
988
displayHeight[a] = displayMode.Height;
989
990
if (windowMonitor == monitor) {
991
MONITORINFO lpmi;
992
ZeroMemory(&lpmi, sizeof(lpmi));
993
lpmi.cbSize = sizeof(MONITORINFO);
994
995
GetMonitorInfo(windowMonitor, &lpmi);
996
dxAdapter = a;
997
monitorDisplayRect = lpmi.rcMonitor;
998
}
999
}
1000
1001
D3DADAPTER_IDENTIFIER9 adapterIdentifier;
1002
ZeroMemory(&adapterIdentifier, sizeof(adapterIdentifier));
1003
dx9Context->GetAdapterIdentifier(dxAdapter, 0, &adapterIdentifier);
1004
1005
// no change, don't reload anything
1006
if (memcmp(&deviceIdentifier, &adapterIdentifier.DeviceIdentifier, sizeof(deviceIdentifier)) == 0 && dxAdapter == prevAdapter)
1007
return;
1008
1009
deviceIdentifier = adapterIdentifier.DeviceIdentifier;
1010
1011
displayCount = dx9Context->GetAdapterModeCount(dxAdapter, D3DFMT_X8R8G8B8);
1012
if (displayInfo.displays)
1013
free(displayInfo.displays);
1014
1015
displayInfo.displays = (decltype(displayInfo.displays))malloc(sizeof(D3DDISPLAYMODE) * displayCount);
1016
int32 newDisplayCount = 0;
1017
bool32 foundFullScreenDisplay = false;
1018
1019
for (int32 d = 0; d < displayCount; ++d) {
1020
dx9Context->EnumAdapterModes(dxAdapter, D3DFMT_X8R8G8B8, d, &displayInfo.displays[newDisplayCount].internal);
1021
1022
int32 refreshRate = displayInfo.displays[newDisplayCount].refresh_rate;
1023
if (refreshRate >= 59 && (refreshRate <= 60 || refreshRate >= 120) && displayInfo.displays[newDisplayCount].height >= (SCREEN_YSIZE * 2)) {
1024
if (d && refreshRate == 60 && displayInfo.displays[newDisplayCount - 1].refresh_rate == 59) {
1025
memcpy(&displayInfo.displays[newDisplayCount - 1], &displayInfo.displays[newDisplayCount], sizeof(displayInfo.displays[0]));
1026
--newDisplayCount;
1027
}
1028
1029
if (videoSettings.fsWidth == displayInfo.displays[newDisplayCount].width
1030
&& videoSettings.fsHeight == displayInfo.displays[newDisplayCount].height)
1031
foundFullScreenDisplay = true;
1032
1033
++newDisplayCount;
1034
}
1035
}
1036
1037
displayCount = newDisplayCount;
1038
if (!foundFullScreenDisplay) {
1039
videoSettings.fsWidth = 0;
1040
videoSettings.fsHeight = 0;
1041
videoSettings.refreshRate = 60; // 0;
1042
}
1043
}
1044
1045
void RenderDevice::GetWindowSize(int32 *width, int32 *height)
1046
{
1047
D3DDISPLAYMODE display;
1048
dx9Context->GetAdapterDisplayMode(dxAdapter, &display);
1049
1050
if (width)
1051
*width = display.Width;
1052
1053
if (height)
1054
*height = display.Height;
1055
}
1056
1057
void RenderDevice::ProcessEvent(MSG Msg)
1058
{
1059
bool handledMsg = false;
1060
1061
switch (Msg.message) {
1062
case WM_QUIT:
1063
isRunning = false;
1064
handledMsg = true;
1065
break;
1066
1067
// called when holding "ALT" down
1068
case WM_SYSKEYDOWN: {
1069
WPARAM activeButtons = Msg.wParam;
1070
switch (Msg.wParam) {
1071
// shift key
1072
case VK_SHIFT:
1073
activeButtons = MapVirtualKey(((Msg.lParam >> 16) & 0xFF), MAPVK_VSC_TO_VK_EX);
1074
break;
1075
1076
// CTRL key
1077
case VK_CONTROL:
1078
activeButtons = VK_LCONTROL + (((Msg.lParam >> 24) & 0xFF) & 1);
1079
break;
1080
1081
// ALT key
1082
case VK_MENU: activeButtons = VK_LMENU + (((Msg.lParam >> 24) & 0xFF) & 1); break;
1083
}
1084
1085
switch (Msg.wParam) {
1086
default:
1087
#if RETRO_INPUTDEVICE_KEYBOARD
1088
SKU::UpdateKeyState(activeButtons);
1089
handledMsg = true;
1090
#endif
1091
break;
1092
1093
case VK_RETURN: // alt + enter
1094
if (GetAsyncKeyState(VK_MENU)) {
1095
videoSettings.windowed ^= 1;
1096
UpdateGameWindow();
1097
changedVideoSettings = false;
1098
handledMsg = true;
1099
}
1100
1101
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1102
RSDK::SKU::specialKeyStates[1] = true;
1103
#endif
1104
break;
1105
1106
case VK_F4: // alt + f4
1107
if (GetAsyncKeyState(VK_MENU))
1108
isRunning = false;
1109
1110
handledMsg = true;
1111
break;
1112
}
1113
}
1114
1115
// regular keydown
1116
case WM_KEYDOWN: {
1117
WPARAM activeButtons = Msg.wParam;
1118
switch (Msg.wParam) {
1119
// shift key
1120
case VK_SHIFT:
1121
activeButtons = MapVirtualKey(((Msg.lParam >> 16) & 0xFF), MAPVK_VSC_TO_VK_EX);
1122
break;
1123
1124
// CTRL key
1125
case VK_CONTROL:
1126
activeButtons = VK_LCONTROL + (((Msg.lParam >> 24) & 0xFF) & 1);
1127
break;
1128
1129
// ALT key
1130
case VK_MENU: activeButtons = VK_LMENU + (((Msg.lParam >> 24) & 0xFF) & 1); break;
1131
}
1132
1133
// handledMsg = true;
1134
switch (Msg.wParam) {
1135
default:
1136
#if RETRO_INPUTDEVICE_KEYBOARD
1137
SKU::UpdateKeyState(activeButtons);
1138
#endif
1139
break;
1140
1141
case VK_BACK:
1142
if (engine.devMenu) {
1143
engine.gameSpeed = engine.fastForwardSpeed;
1144
1145
handledMsg = true;
1146
}
1147
break;
1148
1149
case VK_ESCAPE:
1150
if (engine.devMenu) {
1151
#if RETRO_REV0U
1152
if (sceneInfo.state == ENGINESTATE_DEVMENU || RSDK::Legacy::gameMode == RSDK::Legacy::ENGINE_DEVMENU)
1153
#else
1154
if (sceneInfo.state == ENGINESTATE_DEVMENU)
1155
#endif
1156
CloseDevMenu();
1157
else
1158
OpenDevMenu();
1159
1160
handledMsg = true;
1161
}
1162
else {
1163
#if RETRO_INPUTDEVICE_KEYBOARD
1164
SKU::UpdateKeyState(activeButtons);
1165
#endif
1166
}
1167
1168
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1169
RSDK::SKU::specialKeyStates[0] = true;
1170
#endif
1171
break;
1172
1173
#if !RETRO_USE_ORIGINAL_CODE
1174
case VK_F1:
1175
if (engine.devMenu) {
1176
sceneInfo.listPos--;
1177
while (sceneInfo.listPos < sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart
1178
|| sceneInfo.listPos > sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd
1179
|| !sceneInfo.listCategory[sceneInfo.activeCategory].sceneCount) {
1180
sceneInfo.activeCategory--;
1181
if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {
1182
sceneInfo.activeCategory = sceneInfo.categoryCount - 1;
1183
}
1184
sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd;
1185
}
1186
1187
#if RETRO_REV0U
1188
switch (engine.version) {
1189
default: break;
1190
case 5: LoadScene(); break;
1191
case 4:
1192
case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;
1193
}
1194
#else
1195
LoadScene();
1196
#endif
1197
1198
handledMsg = true;
1199
}
1200
break;
1201
1202
case VK_F2:
1203
if (engine.devMenu) {
1204
sceneInfo.listPos++;
1205
while (sceneInfo.listPos < sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart
1206
|| sceneInfo.listPos > sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd
1207
|| !sceneInfo.listCategory[sceneInfo.activeCategory].sceneCount) {
1208
sceneInfo.activeCategory++;
1209
if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {
1210
sceneInfo.activeCategory = 0;
1211
}
1212
sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart;
1213
}
1214
1215
#if RETRO_REV0U
1216
switch (engine.version) {
1217
default: break;
1218
case 5: LoadScene(); break;
1219
case 4:
1220
case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;
1221
}
1222
#else
1223
LoadScene();
1224
#endif
1225
1226
handledMsg = true;
1227
}
1228
break;
1229
#endif
1230
1231
case VK_F3:
1232
if (userShaderCount) {
1233
videoSettings.shaderID = (videoSettings.shaderID + 1) % userShaderCount;
1234
1235
handledMsg = true;
1236
}
1237
break;
1238
1239
#if !RETRO_USE_ORIGINAL_CODE
1240
case VK_F4:
1241
if (engine.devMenu) {
1242
engine.showEntityInfo ^= 1;
1243
1244
handledMsg = true;
1245
}
1246
break;
1247
1248
case VK_F5:
1249
if (engine.devMenu) {
1250
// Quick-Reload
1251
#if RETRO_USE_MOD_LOADER
1252
if (GetAsyncKeyState(VK_CONTROL))
1253
RefreshModFolders();
1254
#endif
1255
1256
#if RETRO_REV0U
1257
switch (engine.version) {
1258
default: break;
1259
case 5: LoadScene(); break;
1260
case 4:
1261
case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;
1262
}
1263
#else
1264
LoadScene();
1265
#endif
1266
1267
handledMsg = true;
1268
}
1269
break;
1270
1271
case VK_F6:
1272
if (engine.devMenu && videoSettings.screenCount > 1) {
1273
videoSettings.screenCount--;
1274
1275
handledMsg = true;
1276
}
1277
break;
1278
1279
case VK_F7:
1280
if (engine.devMenu && videoSettings.screenCount < SCREEN_COUNT) {
1281
videoSettings.screenCount++;
1282
1283
handledMsg = true;
1284
}
1285
break;
1286
1287
case VK_F8:
1288
if (engine.devMenu) {
1289
engine.showUpdateRanges ^= 1;
1290
1291
handledMsg = true;
1292
}
1293
break;
1294
1295
case VK_F9:
1296
if (engine.devMenu) {
1297
showHitboxes ^= 1;
1298
1299
handledMsg = true;
1300
}
1301
break;
1302
1303
case VK_F10:
1304
if (engine.devMenu) {
1305
engine.showPaletteOverlay ^= 1;
1306
1307
handledMsg = true;
1308
}
1309
break;
1310
#endif
1311
1312
case VK_INSERT:
1313
case VK_F11:
1314
if (engine.devMenu) {
1315
engine.frameStep = true;
1316
1317
handledMsg = true;
1318
}
1319
break;
1320
1321
case VK_PAUSE:
1322
case VK_F12:
1323
if (engine.devMenu) {
1324
#if RETRO_REV0U
1325
switch (engine.version) {
1326
default: break;
1327
case 5:
1328
if (sceneInfo.state != ENGINESTATE_NONE)
1329
sceneInfo.state ^= ENGINESTATE_STEPOVER;
1330
break;
1331
case 4:
1332
case 3:
1333
if (RSDK::Legacy::stageMode != ENGINESTATE_NONE)
1334
RSDK::Legacy::stageMode ^= RSDK::Legacy::STAGEMODE_STEPOVER;
1335
break;
1336
}
1337
#else
1338
if (sceneInfo.state != ENGINESTATE_NONE)
1339
sceneInfo.state ^= ENGINESTATE_STEPOVER;
1340
#endif
1341
1342
handledMsg = true;
1343
}
1344
break;
1345
}
1346
break;
1347
}
1348
1349
case WM_KEYUP:
1350
case WM_SYSKEYUP: {
1351
WPARAM activeButtons = Msg.wParam;
1352
switch (Msg.wParam) {
1353
case VK_SHIFT: activeButtons = MapVirtualKey(((Msg.lParam >> 16) & 0xFF), MAPVK_VSC_TO_VK_EX); break;
1354
1355
case VK_CONTROL: activeButtons = VK_LCONTROL + ((Msg.lParam >> 24) & 1); break;
1356
1357
case VK_MENU: // ALT key
1358
activeButtons = VK_LMENU + ((Msg.lParam >> 24) & 1);
1359
break;
1360
}
1361
1362
switch (Msg.wParam) {
1363
default:
1364
#if RETRO_INPUTDEVICE_KEYBOARD
1365
SKU::ClearKeyState(activeButtons);
1366
#endif
1367
break;
1368
1369
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1370
case VK_ESCAPE:
1371
RSDK::SKU::specialKeyStates[0] = false;
1372
SKU::ClearKeyState(activeButtons);
1373
break;
1374
1375
case VK_RETURN:
1376
RSDK::SKU::specialKeyStates[1] = false;
1377
SKU::ClearKeyState(activeButtons);
1378
break;
1379
#endif
1380
1381
case VK_BACK:
1382
engine.gameSpeed = 1;
1383
1384
handledMsg = true;
1385
break;
1386
}
1387
1388
break;
1389
}
1390
1391
case WM_LBUTTONDOWN: touchInfo.down[0] = 1; touchInfo.count = 1;
1392
1393
#if !RETRO_REV02
1394
RSDK::SKU::buttonDownCount++;
1395
#endif
1396
1397
handledMsg = true;
1398
break;
1399
1400
case WM_LBUTTONUP: touchInfo.down[0] = 0; touchInfo.count = 0;
1401
1402
#if !RETRO_REV02
1403
RSDK::SKU::buttonDownCount--;
1404
#endif
1405
1406
handledMsg = true;
1407
break;
1408
1409
case WM_MBUTTONDOWN: handledMsg = true; break;
1410
1411
case WM_RBUTTONDOWN: handledMsg = true;
1412
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1413
RSDK::SKU::specialKeyStates[3] = true;
1414
RSDK::SKU::buttonDownCount++;
1415
#endif
1416
break;
1417
1418
case WM_RBUTTONUP: handledMsg = true;
1419
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1420
RSDK::SKU::specialKeyStates[3] = false;
1421
RSDK::SKU::buttonDownCount--;
1422
#endif
1423
break;
1424
}
1425
1426
if (!handledMsg)
1427
DispatchMessage(&Msg);
1428
}
1429
1430
bool RenderDevice::ProcessEvents()
1431
{
1432
MSG Msg = {};
1433
while (PeekMessage(&Msg, NULL, 0, 0, true)) {
1434
ProcessEvent(Msg);
1435
1436
if (!isRunning)
1437
return false;
1438
}
1439
1440
return isRunning;
1441
}
1442
1443
LRESULT CALLBACK RenderDevice::WindowEventCallback(HWND hRecipient, UINT message, WPARAM wParam, LPARAM lParam)
1444
{
1445
bool32 forceExit = false;
1446
GUID deviceGUID = KSCATEGORY_AUDIO;
1447
1448
switch (message) {
1449
case WM_CREATE: {
1450
if (deviceNotif)
1451
return 0;
1452
1453
DEV_BROADCAST_DEVICEINTERFACE filter;
1454
filter.dbcc_name[0] = 0;
1455
filter.dbcc_reserved = 0;
1456
filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
1457
filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
1458
filter.dbcc_classguid = deviceGUID;
1459
1460
deviceNotif = RegisterDeviceNotification(hRecipient, &filter, DEVICE_NOTIFY_WINDOW_HANDLE);
1461
1462
forceExit = true;
1463
break;
1464
}
1465
1466
case WM_DESTROY:
1467
if (deviceNotif) {
1468
UnregisterDeviceNotification(deviceNotif);
1469
deviceNotif = 0;
1470
}
1471
1472
isRunning = false;
1473
forceExit = true;
1474
break;
1475
1476
case WM_MOVE:
1477
case WM_SIZE: forceExit = true; break;
1478
1479
case WM_ACTIVATE:
1480
if (wParam) {
1481
if (!videoSettings.windowState)
1482
return 0;
1483
1484
if (AudioDevice::audioFocus == 1) {
1485
AudioDevice::audioFocus = 0;
1486
if (AudioDevice::sourceVoice)
1487
AudioDevice::sourceVoice->Start(0, 0);
1488
}
1489
1490
GetDisplays();
1491
videoSettings.windowState = WINDOWSTATE_ACTIVE;
1492
}
1493
else {
1494
touchInfo.down[0] = false;
1495
touchInfo.count = 0;
1496
if (!videoSettings.windowState)
1497
return 0;
1498
#if !RETRO_USE_ORIGINAL_CODE
1499
if (customSettings.disableFocusPause)
1500
return 0;
1501
#endif
1502
1503
if (!AudioDevice::audioFocus) {
1504
AudioDevice::audioFocus = 1;
1505
if (AudioDevice::sourceVoice)
1506
AudioDevice::sourceVoice->Stop(0, 0);
1507
}
1508
1509
videoSettings.windowState = WINDOWSTATE_INACTIVE;
1510
}
1511
1512
forceExit = true;
1513
break;
1514
1515
case WM_PAINT:
1516
BeginPaint(hRecipient, &Paint);
1517
EndPaint(hRecipient, &Paint);
1518
1519
forceExit = true;
1520
break;
1521
1522
case WM_DEVICECHANGE: {
1523
DEV_BROADCAST_DEVICEINTERFACE *deviceInterace = (DEV_BROADCAST_DEVICEINTERFACE *)lParam;
1524
1525
if ((wParam == DBT_DEVICEARRIVAL || wParam == DBT_DEVICEREMOVECOMPLETE) && deviceInterace
1526
&& deviceInterace->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
1527
1528
if (memcmp(&deviceInterace->dbcc_classguid, &deviceGUID, sizeof(deviceGUID)) == 0) {
1529
AudioDevice::audioState = 30;
1530
}
1531
}
1532
1533
#if RETRO_INPUTDEVICE_XINPUT
1534
SKU::UpdateXInputDevices();
1535
#endif
1536
1537
#if RETRO_INPUTDEVICE_RAWINPUT
1538
SKU::InitHIDAPI();
1539
#endif
1540
1541
#if RETRO_INPUTDEVICE_XINPUT
1542
SKU::InitXInputAPI();
1543
#endif
1544
1545
forceExit = true;
1546
break;
1547
}
1548
1549
#if RETRO_INPUTDEVICE_RAWINPUT
1550
case WM_INPUT:
1551
SKU::UpdateHIDButtonStates((HRAWINPUT)lParam);
1552
1553
forceExit = true;
1554
break;
1555
#endif
1556
1557
case WM_SYSCOMMAND: {
1558
int32 param = wParam & 0xFFF0;
1559
if (param == SC_MINIMIZE) {
1560
touchInfo.down[0] = 0;
1561
touchInfo.count = 0;
1562
if (videoSettings.windowState) {
1563
PauseSound();
1564
videoSettings.windowState = WINDOWSTATE_INACTIVE;
1565
}
1566
}
1567
else if (param == SC_MAXIMIZE && videoSettings.windowState != WINDOWSTATE_UNINITIALIZED) {
1568
ResumeSound();
1569
videoSettings.windowState = WINDOWSTATE_ACTIVE;
1570
}
1571
1572
break;
1573
}
1574
1575
case WM_MENUSELECT:
1576
case WM_ENTERSIZEMOVE:
1577
touchInfo.down[0] = 0;
1578
touchInfo.count = 0;
1579
1580
forceExit = true;
1581
break;
1582
1583
case WM_EXITSIZEMOVE:
1584
GetDisplays();
1585
1586
forceExit = true;
1587
break;
1588
1589
default: break;
1590
}
1591
1592
if (forceExit)
1593
return 0;
1594
else
1595
return DefWindowProc(hRecipient, message, wParam, lParam);
1596
}
1597
1598
void RenderDevice::SetupImageTexture(int32 width, int32 height, uint8 *imagePixels)
1599
{
1600
if (!imagePixels)
1601
return;
1602
1603
dx9Device->SetTexture(0, NULL);
1604
1605
D3DLOCKED_RECT rect;
1606
if (imageTexture->LockRect(0, &rect, NULL, D3DLOCK_DISCARD) == 0) {
1607
DWORD *pixels = (DWORD *)rect.pBits;
1608
int32 pitch = (rect.Pitch >> 2) - width;
1609
1610
uint32 *imagePixels32 = (uint32 *)imagePixels;
1611
for (int32 y = 0; y < height; ++y) {
1612
for (int32 x = 0; x < width; ++x) {
1613
*pixels++ = *imagePixels32++;
1614
}
1615
1616
pixels += pitch;
1617
}
1618
1619
imageTexture->UnlockRect(0);
1620
}
1621
}
1622
1623
void RenderDevice::SetupVideoTexture_YUV420(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,
1624
int32 strideV)
1625
{
1626
dx9Device->SetTexture(0, NULL);
1627
1628
D3DLOCKED_RECT rect;
1629
if (imageTexture->LockRect(0, &rect, NULL, D3DLOCK_DISCARD) == 0) {
1630
DWORD *pixels = (DWORD *)rect.pBits;
1631
int32 pitch = (rect.Pitch >> 2) - width;
1632
1633
if (videoSettings.shaderSupport) {
1634
// Shaders are supported! lets watch this video in full color!
1635
for (int32 y = 0; y < height; ++y) {
1636
for (int32 x = 0; x < width; ++x) {
1637
*pixels++ = (yPlane[x] << 16) | 0xFF000000;
1638
}
1639
1640
pixels += pitch;
1641
yPlane += strideY;
1642
}
1643
1644
pixels = (DWORD *)rect.pBits;
1645
pitch = (rect.Pitch >> 2) - (width >> 1);
1646
for (int32 y = 0; y < (height >> 1); ++y) {
1647
for (int32 x = 0; x < (width >> 1); ++x) {
1648
*pixels++ |= (vPlane[x] << 0) | (uPlane[x] << 8) | 0xFF000000;
1649
}
1650
1651
pixels += pitch;
1652
uPlane += strideU;
1653
vPlane += strideV;
1654
}
1655
}
1656
else {
1657
// No shader support means no YUV support! at least use the brightness to show it in grayscale!
1658
for (int32 y = 0; y < height; ++y) {
1659
for (int32 x = 0; x < width; ++x) {
1660
int32 brightness = yPlane[x];
1661
*pixels++ = (brightness << 0) | (brightness << 8) | (brightness << 16) | 0xFF000000;
1662
}
1663
1664
pixels += pitch;
1665
yPlane += strideY;
1666
}
1667
}
1668
1669
imageTexture->UnlockRect(0);
1670
}
1671
}
1672
void RenderDevice::SetupVideoTexture_YUV422(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,
1673
int32 strideV)
1674
{
1675
dx9Device->SetTexture(0, NULL);
1676
1677
D3DLOCKED_RECT rect;
1678
if (imageTexture->LockRect(0, &rect, NULL, D3DLOCK_DISCARD) == 0) {
1679
DWORD *pixels = (DWORD *)rect.pBits;
1680
int32 pitch = (rect.Pitch >> 2) - width;
1681
1682
if (videoSettings.shaderSupport) {
1683
// Shaders are supported! lets watch this video in full color!
1684
for (int32 y = 0; y < height; ++y) {
1685
for (int32 x = 0; x < width; ++x) {
1686
*pixels++ = (yPlane[x] << 16) | 0xFF000000;
1687
}
1688
1689
pixels += pitch;
1690
yPlane += strideY;
1691
}
1692
1693
pixels = (DWORD *)rect.pBits;
1694
pitch = (rect.Pitch >> 2) - (width >> 1);
1695
for (int32 y = 0; y < height; ++y) {
1696
for (int32 x = 0; x < (width >> 1); ++x) {
1697
*pixels++ |= (vPlane[x] << 0) | (uPlane[x] << 8) | 0xFF000000;
1698
}
1699
1700
pixels += pitch;
1701
uPlane += strideU;
1702
vPlane += strideV;
1703
}
1704
}
1705
else {
1706
// No shader support means no YUV support! at least use the brightness to show it in grayscale!
1707
for (int32 y = 0; y < height; ++y) {
1708
for (int32 x = 0; x < width; ++x) {
1709
int32 brightness = yPlane[x];
1710
*pixels++ = (brightness << 0) | (brightness << 8) | (brightness << 16) | 0xFF000000;
1711
}
1712
1713
pixels += pitch;
1714
yPlane += strideY;
1715
}
1716
}
1717
1718
imageTexture->UnlockRect(0);
1719
}
1720
}
1721
void RenderDevice::SetupVideoTexture_YUV444(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,
1722
int32 strideV)
1723
{
1724
dx9Device->SetTexture(0, NULL);
1725
1726
D3DLOCKED_RECT rect;
1727
if (imageTexture->LockRect(0, &rect, NULL, D3DLOCK_DISCARD) == 0) {
1728
DWORD *pixels = (DWORD *)rect.pBits;
1729
int32 pitch = (rect.Pitch >> 2) - width;
1730
1731
if (videoSettings.shaderSupport) {
1732
// Shaders are supported! lets watch this video in full color!
1733
for (int32 y = 0; y < height; ++y) {
1734
int32 pos1 = yPlane - vPlane;
1735
int32 pos2 = uPlane - vPlane;
1736
uint8 *pixV = vPlane;
1737
for (int32 x = 0; x < width; ++x) {
1738
*pixels++ = pixV[0] | (pixV[pos2] << 8) | (pixV[pos1] << 16) | 0xFF000000;
1739
pixV++;
1740
}
1741
1742
pixels += pitch;
1743
yPlane += strideY;
1744
uPlane += strideU;
1745
vPlane += strideV;
1746
}
1747
}
1748
else {
1749
// No shader support means no YUV support! at least use the brightness to show it in grayscale!
1750
for (int32 y = 0; y < height; ++y) {
1751
for (int32 x = 0; x < width; ++x) {
1752
int32 brightness = yPlane[x];
1753
*pixels++ = (brightness << 0) | (brightness << 8) | (brightness << 16) | 0xFF000000;
1754
}
1755
1756
pixels += pitch;
1757
yPlane += strideY;
1758
}
1759
}
1760
1761
imageTexture->UnlockRect(0);
1762
}
1763
}
1764