Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/RSDKv5/RSDK/Graphics/DX11/DX11RenderDevice.cpp
1163 views
1
#include "resource.h"
2
3
#if !RETRO_USE_ORIGINAL_CODE
4
#include <D3Dcompiler.h>
5
#include "BackupShaders.hpp"
6
#endif
7
8
#include <atlbase.h>
9
10
#include "Ks.h" // used for KSCATEGORY_AUDIO
11
#include "Ksmedia.h" // used for KSCATEGORY_AUDIO
12
13
#define DX11_WINDOWFLAGS_BORDERED (WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_GROUP)
14
#define DX11_WINDOWFLAGS_BORDERLESS (WS_POPUP)
15
16
HWND RenderDevice::windowHandle;
17
18
HDEVNOTIFY RenderDevice::deviceNotif = 0;
19
PAINTSTRUCT RenderDevice::Paint;
20
21
ID3D11DeviceContext *RenderDevice::dx11Context;
22
ID3D11Device *RenderDevice::dx11Device;
23
UINT RenderDevice::dxAdapter;
24
ID3D11Buffer *RenderDevice::dx11VertexBuffer;
25
ID3D11Texture2D *RenderDevice::screenTextures[SCREEN_COUNT];
26
ID3D11Texture2D *RenderDevice::imageTexture;
27
ID3D11ShaderResourceView *RenderDevice::screenTextureViews[SCREEN_COUNT];
28
ID3D11ShaderResourceView *RenderDevice::imageTextureView;
29
D3D11_VIEWPORT RenderDevice::dx11ViewPort;
30
IDXGISwapChain *RenderDevice::swapChain;
31
ID3D11RenderTargetView *RenderDevice::renderView;
32
33
ID3D11RasterizerState *RenderDevice::rasterState;
34
ID3D11SamplerState *RenderDevice::samplerPoint;
35
ID3D11SamplerState *RenderDevice::samplerLinear;
36
ID3D11Buffer *RenderDevice::psConstBuffer = NULL;
37
38
int32 RenderDevice::adapterCount = 0;
39
RECT RenderDevice::monitorDisplayRect;
40
LUID RenderDevice::deviceIdentifier;
41
42
D3D_DRIVER_TYPE RenderDevice::driverType = D3D_DRIVER_TYPE_NULL;
43
D3D_FEATURE_LEVEL RenderDevice::featureLevel = D3D_FEATURE_LEVEL_11_0;
44
45
bool RenderDevice::useFrequency = false;
46
47
LARGE_INTEGER RenderDevice::performanceCount;
48
LARGE_INTEGER RenderDevice::frequency;
49
LARGE_INTEGER RenderDevice::initialFrequency;
50
LARGE_INTEGER RenderDevice::curFrequency;
51
52
// WinMain args
53
HINSTANCE RenderDevice::hInstance;
54
HINSTANCE RenderDevice::hPrevInstance;
55
INT RenderDevice::nShowCmd;
56
57
struct ShaderConstants {
58
float2 pixelSize;
59
float2 textureSize;
60
float2 viewSize;
61
float2 screenDim;
62
};
63
64
bool RenderDevice::Init()
65
{
66
#if _UNICODE
67
// shit workaround since windows is BEGGING me to use wide strs
68
std::string str = gameVerInfo.gameTitle;
69
std::wstring temp = std::wstring(str.begin(), str.end());
70
LPCWSTR gameTitle = temp.c_str();
71
#else
72
std::string str = gameVerInfo.gameTitle;
73
LPCSTR gameTitle = str.c_str();
74
#endif
75
76
HMODULE handle = GetModuleHandle(NULL);
77
78
WNDCLASS wndClass;
79
wndClass.style = CS_VREDRAW | CS_HREDRAW;
80
wndClass.lpfnWndProc = WindowEventCallback;
81
wndClass.cbClsExtra = 0;
82
wndClass.cbWndExtra = sizeof(LONG);
83
wndClass.hInstance = hInstance;
84
wndClass.hIcon = LoadIcon(handle, IDI_APPLICATION);
85
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
86
wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
87
wndClass.lpszMenuName = NULL;
88
wndClass.lpszClassName = gameTitle;
89
if (!RegisterClass(&wndClass))
90
return false;
91
92
ShowCursor(false);
93
94
tagRECT winRect;
95
if (videoSettings.windowed) {
96
winRect.left = (GetSystemMetrics(SM_CXSCREEN) - videoSettings.windowWidth) / 2;
97
winRect.top = (GetSystemMetrics(SM_CYSCREEN) - videoSettings.windowHeight) / 2;
98
winRect.right = winRect.left + videoSettings.windowWidth;
99
winRect.bottom = winRect.top + videoSettings.windowHeight;
100
}
101
else if (videoSettings.fsWidth <= 0 || videoSettings.fsHeight <= 0) {
102
winRect.left = 0;
103
winRect.top = 0;
104
winRect.right = GetSystemMetrics(SM_CXSCREEN);
105
winRect.bottom = GetSystemMetrics(SM_CYSCREEN);
106
}
107
else {
108
winRect.left = (GetSystemMetrics(SM_CXSCREEN) - videoSettings.fsWidth) / 2;
109
winRect.top = (GetSystemMetrics(SM_CYSCREEN) - videoSettings.fsHeight) / 2;
110
winRect.right = winRect.left + videoSettings.fsWidth;
111
winRect.bottom = winRect.top + videoSettings.fsHeight;
112
}
113
114
uint32 windowFlags = 0;
115
if (videoSettings.bordered && videoSettings.windowed)
116
windowFlags = DX11_WINDOWFLAGS_BORDERED;
117
else
118
windowFlags = DX11_WINDOWFLAGS_BORDERLESS;
119
120
AdjustWindowRect(&winRect, windowFlags, false);
121
windowHandle = CreateWindowEx(WS_EX_LEFT, gameTitle, gameTitle, windowFlags, winRect.left, winRect.top, winRect.right - winRect.left,
122
winRect.bottom - winRect.top, NULL, NULL, hInstance, NULL);
123
124
PrintLog(PRINT_NORMAL, "w: %d h: %d windowed: %d\n", winRect.right - winRect.left, winRect.bottom - winRect.top, videoSettings.windowed);
125
126
if (!windowHandle)
127
return false;
128
129
ShowWindow(windowHandle, nShowCmd);
130
UpdateWindow(windowHandle);
131
132
if (!SetupRendering() || !AudioDevice::Init())
133
return false;
134
135
InitInputDevices();
136
return true;
137
}
138
139
void RenderDevice::CopyFrameBuffer()
140
{
141
for (int32 s = 0; s < videoSettings.screenCount; ++s) {
142
D3D11_MAPPED_SUBRESOURCE mappedResource;
143
if (SUCCEEDED(dx11Context->Map(screenTextures[s], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))) {
144
WORD *pixels = (WORD *)mappedResource.pData;
145
uint16 *frameBuffer = screens[s].frameBuffer;
146
147
int32 screenPitch = screens[s].pitch;
148
int32 pitch = (mappedResource.RowPitch >> 1) - screenPitch;
149
150
for (int32 y = 0; y < SCREEN_YSIZE; ++y) {
151
int32 pixelCount = screenPitch >> 4;
152
for (int32 x = 0; x < pixelCount; ++x) {
153
pixels[0] = frameBuffer[0];
154
pixels[1] = frameBuffer[1];
155
pixels[2] = frameBuffer[2];
156
pixels[3] = frameBuffer[3];
157
pixels[4] = frameBuffer[4];
158
pixels[5] = frameBuffer[5];
159
pixels[6] = frameBuffer[6];
160
pixels[7] = frameBuffer[7];
161
pixels[8] = frameBuffer[8];
162
pixels[9] = frameBuffer[9];
163
pixels[10] = frameBuffer[10];
164
pixels[11] = frameBuffer[11];
165
pixels[12] = frameBuffer[12];
166
pixels[13] = frameBuffer[13];
167
pixels[14] = frameBuffer[14];
168
pixels[15] = frameBuffer[15];
169
170
frameBuffer += 16;
171
pixels += 16;
172
}
173
174
pixels += pitch;
175
}
176
177
dx11Context->Unmap(screenTextures[s], 0);
178
}
179
}
180
}
181
182
void RenderDevice::FlipScreen()
183
{
184
if (windowRefreshDelay > 0) {
185
if (!--windowRefreshDelay)
186
UpdateGameWindow();
187
188
return;
189
}
190
191
const FLOAT clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
192
193
dx11Context->RSSetViewports(1, &displayInfo.viewport);
194
dx11Context->ClearRenderTargetView(renderView, clearColor);
195
dx11Context->RSSetViewports(1, &dx11ViewPort);
196
197
dx11Context->OMSetRenderTargets(1, &renderView, nullptr);
198
dx11Context->RSSetState(rasterState);
199
200
if (true) {
201
// reload shader if needed
202
if (lastShaderID != videoSettings.shaderID) {
203
lastShaderID = videoSettings.shaderID;
204
205
dx11Context->PSSetSamplers(0, 1, shaderList[videoSettings.shaderID].linear ? &samplerLinear : &samplerPoint);
206
207
dx11Context->IASetInputLayout(shaderList[videoSettings.shaderID].vertexDeclare);
208
if (videoSettings.shaderSupport) {
209
dx11Context->VSSetShader(shaderList[videoSettings.shaderID].vertexShaderObject, nullptr, 0);
210
dx11Context->PSSetShader(shaderList[videoSettings.shaderID].pixelShaderObject, nullptr, 0);
211
}
212
}
213
214
if (videoSettings.shaderSupport) {
215
ShaderConstants constants[] = { pixelSize, textureSize, viewSize, { videoSettings.dimMax * videoSettings.dimPercent, 0 } };
216
217
D3D11_MAPPED_SUBRESOURCE mappedResource;
218
ZeroMemory(&mappedResource, sizeof(mappedResource));
219
dx11Context->Map(psConstBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
220
memcpy(mappedResource.pData, &constants, sizeof(ShaderConstants));
221
dx11Context->Unmap(psConstBuffer, 0);
222
223
dx11Context->PSSetConstantBuffers(0, 1, &psConstBuffer);
224
}
225
226
int32 startVert = 0;
227
ID3D11Texture2D *const tex = screenTextures[0];
228
229
switch (videoSettings.screenCount) {
230
default:
231
case 0:
232
#if RETRO_REV02
233
startVert = 54;
234
#else
235
startVert = 18;
236
#endif
237
dx11Context->PSSetShaderResources(0, 1, &imageTextureView);
238
dx11Context->Draw(6, startVert);
239
break;
240
241
case 1:
242
dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[0]);
243
dx11Context->Draw(6, 0);
244
break;
245
246
case 2:
247
#if RETRO_REV02
248
startVert = startVertex_2P[0];
249
#else
250
startVert = 6;
251
#endif
252
dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[0]);
253
dx11Context->Draw(6, startVert);
254
255
#if RETRO_REV02
256
startVert = startVertex_2P[1];
257
#else
258
startVert = 12;
259
#endif
260
dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[1]);
261
dx11Context->Draw(6, startVert);
262
break;
263
264
#if RETRO_REV02
265
case 3:
266
dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[0]);
267
dx11Context->Draw(6, startVertex_3P[0]);
268
269
dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[1]);
270
dx11Context->Draw(6, startVertex_3P[1]);
271
272
dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[2]);
273
dx11Context->Draw(6, startVertex_3P[2]);
274
break;
275
276
case 4:
277
dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[0]);
278
dx11Context->Draw(startVert, 30);
279
280
dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[1]);
281
dx11Context->Draw(startVert, 36);
282
283
dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[2]);
284
dx11Context->Draw(startVert, 42);
285
286
dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[3]);
287
dx11Context->Draw(startVert, 48);
288
break;
289
#endif
290
}
291
}
292
293
if (FAILED(swapChain->Present(videoSettings.vsync ? 1 : 0, 0)))
294
windowRefreshDelay = 8;
295
}
296
297
void RenderDevice::Release(bool32 isRefresh)
298
{
299
if (dx11Context)
300
dx11Context->ClearState();
301
302
if (videoSettings.shaderSupport) {
303
for (int32 i = 0; i < shaderCount; ++i) {
304
if (shaderList[i].vertexShaderObject)
305
shaderList[i].vertexShaderObject->Release();
306
shaderList[i].vertexShaderObject = NULL;
307
308
if (shaderList[i].pixelShaderObject)
309
shaderList[i].pixelShaderObject->Release();
310
shaderList[i].pixelShaderObject = NULL;
311
312
if (shaderList[i].vertexDeclare)
313
shaderList[i].vertexDeclare->Release();
314
shaderList[i].vertexDeclare = NULL;
315
}
316
317
shaderCount = 0;
318
#if RETRO_USE_MOD_LOADER
319
userShaderCount = 0;
320
#endif
321
}
322
323
if (imageTexture) {
324
imageTexture->Release();
325
imageTexture = NULL;
326
}
327
328
if (imageTextureView) {
329
imageTextureView->Release();
330
imageTextureView = NULL;
331
}
332
333
for (int32 i = 0; i < SCREEN_COUNT; ++i) {
334
if (screenTextures[i])
335
screenTextures[i]->Release();
336
337
screenTextures[i] = NULL;
338
339
if (screenTextureViews[i])
340
screenTextureViews[i]->Release();
341
342
screenTextureViews[i] = NULL;
343
}
344
345
if (renderView) {
346
renderView->Release();
347
renderView = NULL;
348
}
349
350
if (psConstBuffer) {
351
psConstBuffer->Release();
352
psConstBuffer = NULL;
353
}
354
355
if (samplerPoint) {
356
samplerPoint->Release();
357
samplerPoint = NULL;
358
}
359
360
if (samplerLinear) {
361
samplerLinear->Release();
362
samplerLinear = NULL;
363
}
364
365
if (rasterState) {
366
rasterState->Release();
367
rasterState = NULL;
368
}
369
370
if (!isRefresh && displayInfo.displays) {
371
free(displayInfo.displays);
372
displayInfo.displays = NULL;
373
}
374
375
if (dx11VertexBuffer) {
376
dx11VertexBuffer->Release();
377
dx11VertexBuffer = NULL;
378
}
379
380
if (swapChain) {
381
DXGI_SWAP_CHAIN_DESC desc;
382
swapChain->GetDesc(&desc);
383
// it's not a good idea to release it while in fullscreen so, lets not!
384
if (!desc.Windowed)
385
swapChain->SetFullscreenState(FALSE, NULL);
386
387
swapChain->Release();
388
swapChain = NULL;
389
}
390
391
if (!isRefresh && dx11Device) {
392
dx11Device->Release();
393
dx11Device = NULL;
394
}
395
396
if (!isRefresh && dx11Context) {
397
dx11Context->Release();
398
dx11Context = NULL;
399
}
400
401
if (!isRefresh && scanlines) {
402
free(scanlines);
403
scanlines = NULL;
404
}
405
}
406
407
void RenderDevice::RefreshWindow()
408
{
409
videoSettings.windowState = WINDOWSTATE_UNINITIALIZED;
410
411
Release(true);
412
413
ShowWindow(windowHandle, SW_HIDE);
414
415
if (videoSettings.windowed && videoSettings.bordered)
416
SetWindowLong(windowHandle, GWL_STYLE, DX11_WINDOWFLAGS_BORDERED);
417
else
418
SetWindowLong(windowHandle, GWL_STYLE, DX11_WINDOWFLAGS_BORDERLESS);
419
420
Sleep(250); // zzzz.. mimimimi..
421
422
GetDisplays();
423
424
tagRECT rect;
425
if (videoSettings.windowed || !videoSettings.exclusiveFS) {
426
tagRECT winRect;
427
GetClientRect(windowHandle, &winRect);
428
429
tagPOINT topLeft, bottomRight;
430
topLeft.x = winRect.left;
431
topLeft.y = winRect.top;
432
bottomRight.x = winRect.right;
433
bottomRight.y = winRect.bottom;
434
435
ClientToScreen(windowHandle, &topLeft);
436
ClientToScreen(windowHandle, &bottomRight);
437
438
if (videoSettings.windowed) {
439
std::vector<IDXGIAdapter *> adapterList = GetAdapterList();
440
441
IDXGIOutput *pOutput;
442
if (SUCCEEDED(adapterList[dxAdapter]->EnumOutputs(0, &pOutput))) {
443
DXGI_OUTPUT_DESC outputDesc;
444
pOutput->GetDesc(&outputDesc);
445
446
int32 displayWidth = outputDesc.DesktopCoordinates.right - outputDesc.DesktopCoordinates.left;
447
int32 displayHeight = outputDesc.DesktopCoordinates.bottom - outputDesc.DesktopCoordinates.top;
448
449
if (videoSettings.windowWidth >= displayWidth || videoSettings.windowHeight >= displayHeight) {
450
videoSettings.windowWidth = (displayHeight / 480 * videoSettings.pixWidth);
451
videoSettings.windowHeight = displayHeight / 480 * videoSettings.pixHeight;
452
}
453
}
454
455
rect.left = (bottomRight.x + topLeft.x) / 2 - videoSettings.windowWidth / 2;
456
rect.top = (bottomRight.y + topLeft.y) / 2 - videoSettings.windowHeight / 2;
457
rect.right = (bottomRight.x + topLeft.x) / 2 + videoSettings.windowWidth / 2;
458
rect.bottom = (bottomRight.y + topLeft.y) / 2 + videoSettings.windowHeight / 2;
459
460
if (videoSettings.bordered)
461
AdjustWindowRect(&rect, DX11_WINDOWFLAGS_BORDERED, false);
462
else
463
AdjustWindowRect(&rect, DX11_WINDOWFLAGS_BORDERLESS, false);
464
465
if (rect.left < monitorDisplayRect.left || rect.right > monitorDisplayRect.right || rect.top < monitorDisplayRect.top
466
|| rect.bottom > monitorDisplayRect.bottom) {
467
rect.left = (monitorDisplayRect.right + monitorDisplayRect.left) / 2 - videoSettings.windowWidth / 2;
468
rect.top = (monitorDisplayRect.top + monitorDisplayRect.bottom) / 2 - videoSettings.windowHeight / 2;
469
rect.right = (monitorDisplayRect.right + monitorDisplayRect.left) / 2 + videoSettings.windowWidth / 2;
470
rect.bottom = (monitorDisplayRect.top + monitorDisplayRect.bottom) / 2 + videoSettings.windowHeight / 2;
471
472
if (videoSettings.bordered)
473
AdjustWindowRect(&rect, DX11_WINDOWFLAGS_BORDERED, false);
474
else
475
AdjustWindowRect(&rect, DX11_WINDOWFLAGS_BORDERLESS, false);
476
}
477
}
478
else {
479
rect = monitorDisplayRect;
480
AdjustWindowRect(&monitorDisplayRect, DX11_WINDOWFLAGS_BORDERLESS, 0);
481
}
482
483
SetWindowPos(windowHandle, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_SHOWWINDOW);
484
}
485
486
ShowWindow(windowHandle, SW_SHOW);
487
RedrawWindow(windowHandle, NULL, NULL, RDW_UPDATENOW | RDW_INVALIDATE);
488
489
if (!InitGraphicsAPI() || !InitShaders())
490
return;
491
492
videoSettings.windowState = WINDOWSTATE_ACTIVE;
493
}
494
495
void RenderDevice::InitFPSCap()
496
{
497
if (QueryPerformanceFrequency(&frequency)) {
498
useFrequency = true;
499
initialFrequency.QuadPart = frequency.QuadPart / videoSettings.refreshRate;
500
QueryPerformanceCounter(&performanceCount);
501
}
502
else {
503
useFrequency = false;
504
performanceCount.QuadPart = timeGetTime();
505
}
506
}
507
bool RenderDevice::CheckFPSCap()
508
{
509
if (useFrequency)
510
QueryPerformanceCounter(&curFrequency);
511
else
512
curFrequency.QuadPart = timeGetTime();
513
514
if (curFrequency.QuadPart > performanceCount.QuadPart)
515
return true;
516
517
return false;
518
}
519
void RenderDevice::UpdateFPSCap() { performanceCount.QuadPart = curFrequency.QuadPart + initialFrequency.LowPart; }
520
521
void RenderDevice::InitVertexBuffer()
522
{
523
RenderVertex vertBuffer[sizeof(rsdkVertexBuffer) / sizeof(RenderVertex)];
524
memcpy(vertBuffer, rsdkVertexBuffer, sizeof(rsdkVertexBuffer));
525
526
float x = 0.5 / (float)viewSize.x;
527
float y = 0.5 / (float)viewSize.y;
528
529
// ignore the last 6 verts, they're scaled to the 1024x512 textures already!
530
int32 vertCount = (RETRO_REV02 ? 60 : 24) - 6;
531
for (int32 v = 0; v < vertCount; ++v) {
532
RenderVertex *vertex = &vertBuffer[v];
533
vertex->pos.x = vertex->pos.x - x;
534
vertex->pos.y = vertex->pos.y + y;
535
536
if (vertex->tex.x)
537
vertex->tex.x = screens[0].size.x * (1.0 / textureSize.x);
538
539
if (vertex->tex.y)
540
vertex->tex.y = screens[0].size.y * (1.0 / textureSize.y);
541
}
542
543
D3D11_MAPPED_SUBRESOURCE resource;
544
if (SUCCEEDED(dx11Context->Map(dx11VertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource))) {
545
memcpy(resource.pData, vertBuffer, sizeof(vertBuffer));
546
dx11Context->Unmap(dx11VertexBuffer, 0);
547
}
548
549
// Set/Update vertex buffer
550
UINT stride = sizeof(RenderVertex);
551
UINT offset = 0;
552
dx11Context->IASetVertexBuffers(0, 1, &dx11VertexBuffer, &stride, &offset);
553
554
// Init pixel shader constants
555
D3D11_BUFFER_DESC cbDesc = {};
556
cbDesc.Usage = D3D11_USAGE_DYNAMIC;
557
cbDesc.ByteWidth = sizeof(ShaderConstants);
558
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
559
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
560
cbDesc.MiscFlags = 0;
561
cbDesc.StructureByteStride = 0;
562
563
dx11Device->CreateBuffer(&cbDesc, NULL, &psConstBuffer);
564
}
565
566
bool RenderDevice::InitGraphicsAPI()
567
{
568
videoSettings.shaderSupport = false;
569
if (featureLevel >= D3D_FEATURE_LEVEL_11_0) {
570
videoSettings.shaderSupport = true;
571
}
572
else {
573
PrintLog(PRINT_NORMAL, "ERROR: HLSL shader model 5 support not detected. shader support is required for the DX11 backend!\nIf this issue "
574
"persists, try using the DX9 backend instead?");
575
return false; // unlike DX9, DX11 doesn't support shaderless rendering, so just kill it here
576
}
577
578
HRESULT hr = 0;
579
580
// Obtain DXGI factory from device (since we used nullptr for pAdapter above)
581
IDXGIFactory1 *dxgiFactory = nullptr;
582
{
583
IDXGIDevice *dxgiDevice = nullptr;
584
hr = dx11Device->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
585
if (SUCCEEDED(hr)) {
586
IDXGIAdapter *adapter = nullptr;
587
hr = dxgiDevice->GetAdapter(&adapter);
588
if (SUCCEEDED(hr)) {
589
hr = adapter->GetParent(__uuidof(IDXGIFactory1), (void **)&dxgiFactory);
590
adapter->Release();
591
}
592
dxgiDevice->Release();
593
}
594
}
595
596
if (FAILED(hr))
597
return false;
598
599
if (videoSettings.windowed || !videoSettings.exclusiveFS) {
600
if (videoSettings.windowed) {
601
viewSize.x = videoSettings.windowWidth;
602
viewSize.y = videoSettings.windowHeight;
603
}
604
else {
605
viewSize.x = displayWidth[dxAdapter];
606
viewSize.y = displayHeight[dxAdapter];
607
}
608
}
609
else {
610
int32 bufferWidth = videoSettings.fsWidth;
611
int32 bufferHeight = videoSettings.fsHeight;
612
if (videoSettings.fsWidth <= 0 || videoSettings.fsHeight <= 0) {
613
bufferWidth = displayWidth[dxAdapter];
614
bufferHeight = displayHeight[dxAdapter];
615
}
616
617
viewSize.x = bufferWidth;
618
viewSize.y = bufferHeight;
619
}
620
621
// Create swap chain
622
IDXGIFactory2 *dxgiFactory2 = nullptr;
623
hr = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), (void **)&dxgiFactory2);
624
if (dxgiFactory2) {
625
// DirectX 11.1 or later
626
hr = dx11Device->QueryInterface(__uuidof(ID3D11Device1), (void **)&dx11Device);
627
if (SUCCEEDED(hr))
628
dx11Context->QueryInterface(__uuidof(ID3D11DeviceContext1), (void **)&dx11Context);
629
630
DXGI_SWAP_CHAIN_DESC1 swapDesc = {};
631
swapDesc.Width = viewSize.x;
632
swapDesc.Height = viewSize.y;
633
swapDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
634
swapDesc.Stereo = FALSE;
635
swapDesc.SampleDesc.Count = 1;
636
swapDesc.SampleDesc.Quality = 0;
637
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
638
swapDesc.BufferCount = 2;
639
swapDesc.Scaling = DXGI_SCALING_STRETCH;
640
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
641
swapDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
642
swapDesc.Flags = 0;
643
644
DXGI_SWAP_CHAIN_FULLSCREEN_DESC fsDesc = {};
645
646
fsDesc.RefreshRate.Numerator = videoSettings.refreshRate;
647
fsDesc.RefreshRate.Denominator = 1;
648
fsDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
649
fsDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
650
fsDesc.Windowed = videoSettings.windowed || !videoSettings.exclusiveFS;
651
652
CComPtr<IDXGISwapChain1> swapChain1;
653
hr = dxgiFactory2->CreateSwapChainForHwnd(dx11Device, windowHandle, &swapDesc, &fsDesc, nullptr, &swapChain1);
654
if (SUCCEEDED(hr))
655
hr = swapChain1->QueryInterface(__uuidof(IDXGISwapChain), (void **)&swapChain);
656
657
dxgiFactory2->Release();
658
}
659
else {
660
// DirectX 11.0 systems
661
DXGI_SWAP_CHAIN_DESC swapDesc = {};
662
swapDesc.BufferCount = 1;
663
swapDesc.BufferDesc.Width = viewSize.x;
664
swapDesc.BufferDesc.Height = viewSize.y;
665
swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
666
swapDesc.BufferDesc.RefreshRate.Numerator = videoSettings.refreshRate;
667
swapDesc.BufferDesc.RefreshRate.Denominator = 1;
668
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
669
swapDesc.OutputWindow = windowHandle;
670
swapDesc.SampleDesc.Count = 2;
671
swapDesc.SampleDesc.Quality = 0;
672
swapDesc.Windowed = videoSettings.windowed || !videoSettings.exclusiveFS;
673
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
674
675
hr = dxgiFactory->CreateSwapChain(dx11Device, &swapDesc, &swapChain);
676
}
677
678
dxgiFactory->Release();
679
680
// disable the api handling ALT+Return (we handle it ourselves)
681
IDXGIFactory1 *pFactory = NULL;
682
if (SUCCEEDED(swapChain->GetParent(__uuidof(IDXGIFactory1), (void **)&pFactory))) {
683
pFactory->MakeWindowAssociation(windowHandle, DXGI_MWA_NO_ALT_ENTER);
684
pFactory->Release();
685
}
686
687
// Create a render target view
688
ID3D11Texture2D *pBackBuffer = nullptr;
689
hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)&pBackBuffer);
690
if (FAILED(hr))
691
return false;
692
693
hr = dx11Device->CreateRenderTargetView(pBackBuffer, nullptr, &renderView);
694
pBackBuffer->Release();
695
if (FAILED(hr))
696
return false;
697
698
dx11Context->OMSetRenderTargets(1, &renderView, nullptr);
699
700
dx11Context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
701
702
{
703
D3D11_BUFFER_DESC desc = {};
704
desc.Usage = D3D11_USAGE_DYNAMIC;
705
desc.ByteWidth = sizeof(RenderVertex) * ARRAYSIZE(rsdkVertexBuffer);
706
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
707
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
708
709
hr = dx11Device->CreateBuffer(&desc, NULL, &dx11VertexBuffer);
710
if (FAILED(hr))
711
return false;
712
}
713
714
int32 maxPixHeight = 0;
715
#if !RETRO_USE_ORIGINAL_CODE
716
int32 screenWidth = 0;
717
#endif
718
for (int32 s = 0; s < SCREEN_COUNT; ++s) {
719
if (videoSettings.pixHeight > maxPixHeight)
720
maxPixHeight = videoSettings.pixHeight;
721
722
screens[s].size.y = videoSettings.pixHeight;
723
724
float viewAspect = viewSize.x / viewSize.y;
725
#if !RETRO_USE_ORIGINAL_CODE
726
screenWidth = (int32)((viewAspect * videoSettings.pixHeight) + 3) & 0xFFFFFFFC;
727
#else
728
int32 screenWidth = (int32)((viewAspect * videoSettings.pixHeight) + 3) & 0xFFFFFFFC;
729
#endif
730
if (screenWidth < videoSettings.pixWidth)
731
screenWidth = videoSettings.pixWidth;
732
733
#if !RETRO_USE_ORIGINAL_CODE
734
if (customSettings.maxPixWidth && screenWidth > customSettings.maxPixWidth)
735
screenWidth = customSettings.maxPixWidth;
736
#else
737
if (screenWidth > DEFAULT_PIXWIDTH)
738
screenWidth = DEFAULT_PIXWIDTH;
739
#endif
740
741
memset(&screens[s].frameBuffer, 0, sizeof(screens[s].frameBuffer));
742
SetScreenSize(s, screenWidth, screens[s].size.y);
743
}
744
745
pixelSize.x = screens[0].size.x;
746
pixelSize.y = screens[0].size.y;
747
float pixAspect = pixelSize.x / pixelSize.y;
748
749
UINT viewportCount = 0;
750
dx11Context->RSGetViewports(&viewportCount, NULL);
751
if (viewportCount) {
752
D3D11_VIEWPORT *viewports = new D3D11_VIEWPORT[viewportCount];
753
dx11Context->RSGetViewports(&viewportCount, viewports);
754
displayInfo.viewport = viewports[0];
755
dx11ViewPort = displayInfo.viewport;
756
757
delete[] viewports;
758
}
759
else {
760
displayInfo.viewport.TopLeftX = 0;
761
displayInfo.viewport.TopLeftY = 0;
762
displayInfo.viewport.Width = viewSize.x;
763
displayInfo.viewport.Height = viewSize.y;
764
displayInfo.viewport.MinDepth = 0;
765
displayInfo.viewport.MaxDepth = 1;
766
767
dx11ViewPort = displayInfo.viewport;
768
769
dx11Context->RSSetViewports(1, &dx11ViewPort);
770
}
771
772
if ((viewSize.x / viewSize.y) <= ((pixelSize.x / pixelSize.y) + 0.1)) {
773
if ((pixAspect - 0.1) > (viewSize.x / viewSize.y)) {
774
viewSize.y = (pixelSize.y / pixelSize.x) * viewSize.x;
775
dx11ViewPort.TopLeftY = (displayInfo.viewport.Height * 0.5) - (viewSize.y * 0.5);
776
dx11ViewPort.Height = viewSize.y;
777
778
dx11Context->RSSetViewports(1, &dx11ViewPort);
779
}
780
}
781
else {
782
viewSize.x = pixAspect * viewSize.y;
783
dx11ViewPort.TopLeftX = (displayInfo.viewport.Width * 0.5) - (viewSize.x * 0.5);
784
dx11ViewPort.Width = viewSize.x;
785
786
dx11Context->RSSetViewports(1, &dx11ViewPort);
787
}
788
789
#if !RETRO_USE_ORIGINAL_CODE
790
if (screenWidth <= 512 && maxPixHeight <= 256) {
791
#else
792
if (maxPixHeight <= 256) {
793
#endif
794
textureSize.x = 512.0;
795
textureSize.y = 256.0;
796
}
797
else {
798
textureSize.x = 1024.0;
799
textureSize.y = 512.0;
800
}
801
802
for (int32 s = 0; s < SCREEN_COUNT; ++s) {
803
D3D11_TEXTURE2D_DESC desc = {};
804
desc.Width = textureSize.x;
805
desc.Height = textureSize.y;
806
desc.MipLevels = desc.ArraySize = 1;
807
desc.Format = DXGI_FORMAT_B5G6R5_UNORM;
808
desc.SampleDesc.Quality = 0;
809
desc.SampleDesc.Count = 1;
810
desc.Usage = D3D11_USAGE_DYNAMIC;
811
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
812
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
813
desc.MiscFlags = 0;
814
815
if (FAILED(dx11Device->CreateTexture2D(&desc, NULL, &screenTextures[s])))
816
return false;
817
818
D3D11_SHADER_RESOURCE_VIEW_DESC resDesc;
819
resDesc.Format = desc.Format;
820
resDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
821
resDesc.Texture2D.MostDetailedMip = 0;
822
resDesc.Texture2D.MipLevels = 1;
823
824
if (FAILED(dx11Device->CreateShaderResourceView(screenTextures[s], &resDesc, &screenTextureViews[s])))
825
return false;
826
}
827
828
D3D11_TEXTURE2D_DESC desc = {};
829
desc.Width = RETRO_VIDEO_TEXTURE_W;
830
desc.Height = RETRO_VIDEO_TEXTURE_H;
831
desc.MipLevels = desc.ArraySize = 1;
832
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
833
desc.SampleDesc.Quality = 0;
834
desc.SampleDesc.Count = 1;
835
desc.Usage = D3D11_USAGE_DYNAMIC;
836
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
837
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
838
desc.MiscFlags = 0;
839
if (FAILED(dx11Device->CreateTexture2D(&desc, NULL, &imageTexture)))
840
return false;
841
842
D3D11_SHADER_RESOURCE_VIEW_DESC resDesc;
843
resDesc.Format = desc.Format;
844
resDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
845
resDesc.Texture2D.MostDetailedMip = 0;
846
resDesc.Texture2D.MipLevels = 1;
847
848
if (FAILED(dx11Device->CreateShaderResourceView(imageTexture, &resDesc, &imageTextureView)))
849
return false;
850
851
lastShaderID = -1;
852
InitVertexBuffer();
853
engine.inFocus = 1;
854
videoSettings.viewportX = dx11ViewPort.TopLeftX;
855
videoSettings.viewportY = dx11ViewPort.TopLeftY;
856
videoSettings.viewportW = 1.0 / viewSize.x;
857
videoSettings.viewportH = 1.0 / viewSize.y;
858
859
return true;
860
}
861
862
void RenderDevice::LoadShader(const char *fileName, bool32 linear)
863
{
864
char fullFilePath[0x100];
865
FileInfo info;
866
867
for (int32 i = 0; i < shaderCount; ++i) {
868
if (strcmp(shaderList[i].name, fileName) == 0)
869
return;
870
}
871
872
if (shaderCount == SHADER_COUNT)
873
return;
874
875
ShaderEntry *shader = &shaderList[shaderCount];
876
shader->linear = linear;
877
sprintf_s(shader->name, sizeof(shader->name), "%s", fileName);
878
879
const D3D_SHADER_MACRO defines[] = {
880
#if RETRO_REV02
881
"RETRO_REV02",
882
"1",
883
#endif
884
NULL,
885
NULL
886
};
887
888
#if !RETRO_USE_ORIGINAL_CODE
889
void *bytecode = NULL;
890
size_t bytecodeSize = 0;
891
892
// Try to compile the vertex shader source if it exists
893
sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Shaders/DX11/%s.hlsl", fileName);
894
InitFileInfo(&info);
895
if (LoadFile(&info, fullFilePath, FMODE_RB)) {
896
uint8 *fileData = NULL;
897
AllocateStorage((void **)&fileData, info.fileSize, DATASET_TMP, false);
898
ReadBytes(&info, fileData, info.fileSize);
899
CloseFile(&info);
900
901
UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;
902
if (engine.devMenu) {
903
flags |= D3DCOMPILE_DEBUG;
904
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0;
905
flags |= D3DCOMPILE_WARNINGS_ARE_ERRORS;
906
}
907
else {
908
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
909
}
910
911
ID3DBlob *shaderBlob = nullptr;
912
ID3DBlob *errorBlob = nullptr;
913
HRESULT result = D3DCompile(fileData, info.fileSize, fullFilePath, defines, NULL, "VSMain", "vs_5_0", flags, 0, &shaderBlob, &errorBlob);
914
915
RemoveStorageEntry((void **)&fileData);
916
917
if (FAILED(result)) {
918
if (errorBlob) {
919
PrintLog(PRINT_NORMAL, "ERROR COMPILING VERTEX SHADER: %s", (char *)errorBlob->GetBufferPointer());
920
errorBlob->Release();
921
}
922
923
if (shaderBlob)
924
shaderBlob->Release();
925
926
return;
927
}
928
else {
929
PrintLog(PRINT_NORMAL, "Successfully compiled vertex shader!");
930
if (errorBlob)
931
PrintLog(PRINT_NORMAL, "Vertex shader warnings:\n%s", (char *)errorBlob->GetBufferPointer());
932
933
if (FAILED(dx11Device->CreateVertexShader((DWORD *)shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), NULL,
934
&shader->vertexShaderObject))) {
935
if (shader->vertexShaderObject) {
936
shader->vertexShaderObject->Release();
937
shader->vertexShaderObject = NULL;
938
}
939
940
return;
941
}
942
#pragma comment( lib, "dxguid.lib")
943
shader->vertexShaderObject->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(fileName), fileName);
944
}
945
946
bytecode = shaderBlob->GetBufferPointer();
947
bytecodeSize = shaderBlob->GetBufferSize();
948
}
949
else {
950
#endif
951
// if the vertex shader source doesn't exist, fall back and try to load the vertex shader bytecode
952
sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Shaders/CSO-DX11/%s.vso", fileName);
953
InitFileInfo(&info);
954
if (LoadFile(&info, fullFilePath, FMODE_RB)) {
955
uint8 *fileData = NULL;
956
AllocateStorage((void **)&fileData, info.fileSize, DATASET_TMP, false);
957
ReadBytes(&info, fileData, info.fileSize);
958
CloseFile(&info);
959
960
if (FAILED(dx11Device->CreateVertexShader((DWORD *)fileData, info.fileSize, NULL, &shader->vertexShaderObject))) {
961
if (shader->vertexShaderObject) {
962
shader->vertexShaderObject->Release();
963
shader->vertexShaderObject = NULL;
964
}
965
966
RemoveStorageEntry((void **)&fileData);
967
return;
968
}
969
970
bytecode = fileData;
971
bytecodeSize = info.fileSize;
972
RemoveStorageEntry((void **)&fileData);
973
}
974
975
#if !RETRO_USE_ORIGINAL_CODE
976
else {
977
PrintLog(PRINT_NORMAL, "Could not find vertex shader for '%s', aborting", fileName);
978
return;
979
}
980
}
981
#endif
982
983
// create the vertex layout stuff using the vertex shader
984
{
985
D3D11_INPUT_ELEMENT_DESC elements[2];
986
987
elements[0].SemanticName = "SV_POSITION";
988
elements[0].SemanticIndex = 0;
989
elements[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
990
elements[0].InputSlot = 0;
991
elements[0].AlignedByteOffset = offsetof(RenderVertex, pos);
992
elements[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
993
elements[0].InstanceDataStepRate = 0;
994
995
elements[1].SemanticName = "TEXCOORD";
996
elements[1].SemanticIndex = 0;
997
elements[1].Format = DXGI_FORMAT_R32G32_FLOAT;
998
elements[1].InputSlot = 0;
999
elements[1].AlignedByteOffset = offsetof(RenderVertex, tex);
1000
elements[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
1001
elements[1].InstanceDataStepRate = 0;
1002
1003
// elements[2].SemanticName = "COLOR";
1004
// elements[2].SemanticIndex = 0;
1005
// elements[2].Format = DXGI_FORMAT_R32G32B32_UINT;
1006
// elements[2].InputSlot = 0;
1007
// elements[2].AlignedByteOffset = offsetof(RenderVertex, color);
1008
// elements[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
1009
// elements[2].InstanceDataStepRate = 0;
1010
1011
HRESULT res = dx11Device->CreateInputLayout(elements, ARRAYSIZE(elements), bytecode, bytecodeSize, &shader->vertexDeclare);
1012
if (FAILED(res))
1013
return;
1014
}
1015
1016
#if !RETRO_USE_ORIGINAL_CODE
1017
// Try to compile the pixel shader source if it exists
1018
sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Shaders/DX11/%s.hlsl", fileName);
1019
InitFileInfo(&info);
1020
if (LoadFile(&info, fullFilePath, FMODE_RB)) {
1021
uint8 *fileData = NULL;
1022
AllocateStorage((void **)&fileData, info.fileSize, DATASET_TMP, false);
1023
ReadBytes(&info, fileData, info.fileSize);
1024
CloseFile(&info);
1025
1026
UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;
1027
if (engine.devMenu) {
1028
flags |= D3DCOMPILE_DEBUG;
1029
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0;
1030
flags |= D3DCOMPILE_WARNINGS_ARE_ERRORS;
1031
}
1032
else {
1033
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
1034
}
1035
1036
ID3DBlob *shaderBlob = nullptr;
1037
ID3DBlob *errorBlob = nullptr;
1038
HRESULT result = D3DCompile(fileData, info.fileSize, fullFilePath, defines, NULL, "PSMain", "ps_5_0", flags, 0, &shaderBlob, &errorBlob);
1039
1040
if (FAILED(result)) {
1041
if (errorBlob) {
1042
PrintLog(PRINT_NORMAL, "ERROR COMPILING PIXEL SHADER:\n%s", (char *)errorBlob->GetBufferPointer());
1043
errorBlob->Release();
1044
}
1045
1046
if (shaderBlob)
1047
shaderBlob->Release();
1048
}
1049
else {
1050
PrintLog(PRINT_NORMAL, "Successfully compiled pixel shader!");
1051
if (errorBlob)
1052
PrintLog(PRINT_NORMAL, "Pixel shader warnings:\n%s", (char *)errorBlob->GetBufferPointer());
1053
1054
if (FAILED(dx11Device->CreatePixelShader((DWORD *)shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), NULL,
1055
&shader->pixelShaderObject))) {
1056
if (shader->vertexShaderObject) {
1057
shader->vertexShaderObject->Release();
1058
shader->vertexShaderObject = NULL;
1059
}
1060
1061
RemoveStorageEntry((void **)&fileData);
1062
return;
1063
}
1064
}
1065
1066
RemoveStorageEntry((void **)&fileData);
1067
}
1068
else {
1069
#endif
1070
// if the pixel shader source doesn't exist, fall back and try to load the pixel shader bytecode
1071
sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Shaders/CSO-DX11/%s.fso", fileName);
1072
InitFileInfo(&info);
1073
if (LoadFile(&info, fullFilePath, FMODE_RB)) {
1074
uint8 *fileData = NULL;
1075
AllocateStorage((void **)&fileData, info.fileSize, DATASET_TMP, false);
1076
ReadBytes(&info, fileData, info.fileSize);
1077
CloseFile(&info);
1078
1079
if (FAILED(dx11Device->CreatePixelShader((DWORD *)fileData, info.fileSize, NULL, &shader->pixelShaderObject))) {
1080
if (shader->pixelShaderObject) {
1081
shader->pixelShaderObject->Release();
1082
shader->pixelShaderObject = NULL;
1083
}
1084
1085
RemoveStorageEntry((void **)&fileData);
1086
return;
1087
}
1088
1089
RemoveStorageEntry((void **)&fileData);
1090
}
1091
1092
#if !RETRO_USE_ORIGINAL_CODE
1093
}
1094
#endif
1095
1096
shaderCount++;
1097
}
1098
1099
bool RenderDevice::LoadBackupShader()
1100
{
1101
ShaderEntry *shader = &shaderList[0];
1102
sprintf_s(shader->name, sizeof(shader->name), "%s", "BACKUP");
1103
1104
const D3D_SHADER_MACRO defines[] = {
1105
#if RETRO_REV02
1106
"RETRO_REV02", "1",
1107
#endif
1108
NULL, NULL
1109
};
1110
1111
void *bytecode = NULL;
1112
size_t bytecodeSize = 0;
1113
1114
// Try to compile the vertex shader source
1115
UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;
1116
if (engine.devMenu) {
1117
flags |= D3DCOMPILE_DEBUG;
1118
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0;
1119
flags |= D3DCOMPILE_WARNINGS_ARE_ERRORS;
1120
}
1121
else {
1122
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
1123
}
1124
1125
ID3DBlob *shaderBlob = nullptr;
1126
ID3DBlob *errorBlob = nullptr;
1127
HRESULT result = D3DCompile(backupHLSL, strlen(backupHLSL), "BACKUP", defines, NULL, "VSMain", "vs_5_0", flags, 0, &shaderBlob, &errorBlob);
1128
1129
if (FAILED(result)) {
1130
if (errorBlob) {
1131
PrintLog(PRINT_NORMAL, "ERROR COMPILING VERTEX SHADER: %s", (char *)errorBlob->GetBufferPointer());
1132
errorBlob->Release();
1133
}
1134
1135
if (shaderBlob)
1136
shaderBlob->Release();
1137
1138
return false;
1139
}
1140
else {
1141
PrintLog(PRINT_NORMAL, "Successfully compiled vertex shader!");
1142
if (errorBlob)
1143
PrintLog(PRINT_NORMAL, "Vertex shader warnings:\n%s", (char *)errorBlob->GetBufferPointer());
1144
1145
if (FAILED(dx11Device->CreateVertexShader((DWORD *)shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), NULL,
1146
&shader->vertexShaderObject))) {
1147
if (shader->vertexShaderObject) {
1148
shader->vertexShaderObject->Release();
1149
shader->vertexShaderObject = NULL;
1150
}
1151
1152
return false;
1153
}
1154
#pragma comment(lib, "dxguid.lib")
1155
shader->vertexShaderObject->SetPrivateData(WKPDID_D3DDebugObjectName, strlen("BACKUP"), "BACKUP");
1156
}
1157
1158
bytecode = shaderBlob->GetBufferPointer();
1159
bytecodeSize = shaderBlob->GetBufferSize();
1160
1161
// create the vertex layout stuff using the vertex shader
1162
{
1163
D3D11_INPUT_ELEMENT_DESC elements[2];
1164
1165
elements[0].SemanticName = "SV_POSITION";
1166
elements[0].SemanticIndex = 0;
1167
elements[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
1168
elements[0].InputSlot = 0;
1169
elements[0].AlignedByteOffset = offsetof(RenderVertex, pos);
1170
elements[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
1171
elements[0].InstanceDataStepRate = 0;
1172
1173
elements[1].SemanticName = "TEXCOORD";
1174
elements[1].SemanticIndex = 0;
1175
elements[1].Format = DXGI_FORMAT_R32G32_FLOAT;
1176
elements[1].InputSlot = 0;
1177
elements[1].AlignedByteOffset = offsetof(RenderVertex, tex);
1178
elements[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
1179
elements[1].InstanceDataStepRate = 0;
1180
1181
// elements[2].SemanticName = "COLOR";
1182
// elements[2].SemanticIndex = 0;
1183
// elements[2].Format = DXGI_FORMAT_R32G32B32_UINT;
1184
// elements[2].InputSlot = 0;
1185
// elements[2].AlignedByteOffset = offsetof(RenderVertex, color);
1186
// elements[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
1187
// elements[2].InstanceDataStepRate = 0;
1188
1189
HRESULT res = dx11Device->CreateInputLayout(elements, ARRAYSIZE(elements), bytecode, bytecodeSize, &shader->vertexDeclare);
1190
if (FAILED(res))
1191
return false;
1192
}
1193
1194
// Try to compile the pixel shader source
1195
{
1196
UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;
1197
if (engine.devMenu) {
1198
flags |= D3DCOMPILE_DEBUG;
1199
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0;
1200
flags |= D3DCOMPILE_WARNINGS_ARE_ERRORS;
1201
}
1202
else {
1203
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
1204
}
1205
1206
ID3DBlob *shaderBlob = nullptr;
1207
ID3DBlob *errorBlob = nullptr;
1208
HRESULT result = D3DCompile(backupHLSL, strlen(backupHLSL), "BACKUP", defines, NULL, "PSMain", "ps_5_0", flags, 0, &shaderBlob, &errorBlob);
1209
1210
if (FAILED(result)) {
1211
if (errorBlob) {
1212
PrintLog(PRINT_NORMAL, "ERROR COMPILING PIXEL SHADER:\n%s", (char *)errorBlob->GetBufferPointer());
1213
errorBlob->Release();
1214
}
1215
1216
if (shaderBlob)
1217
shaderBlob->Release();
1218
}
1219
else {
1220
PrintLog(PRINT_NORMAL, "Successfully compiled pixel shader!");
1221
if (errorBlob)
1222
PrintLog(PRINT_NORMAL, "Pixel shader warnings:\n%s", (char *)errorBlob->GetBufferPointer());
1223
1224
if (FAILED(dx11Device->CreatePixelShader((DWORD *)shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), NULL,
1225
&shader->pixelShaderObject))) {
1226
if (shader->vertexShaderObject) {
1227
shader->vertexShaderObject->Release();
1228
shader->vertexShaderObject = NULL;
1229
}
1230
1231
return false;
1232
}
1233
}
1234
}
1235
1236
shader->linear = videoSettings.windowed ? false : shader->linear;
1237
return true;
1238
}
1239
1240
bool RenderDevice::InitShaders()
1241
{
1242
D3D11_RASTERIZER_DESC rDesc = {};
1243
1244
D3D11_SAMPLER_DESC sPointDesc = {};
1245
D3D11_SAMPLER_DESC sLinearDesc = {};
1246
1247
// init
1248
rDesc.FillMode = D3D11_FILL_SOLID;
1249
rDesc.CullMode = D3D11_CULL_NONE;
1250
rDesc.FrontCounterClockwise = FALSE;
1251
rDesc.DepthBias = D3D11_DEFAULT_DEPTH_BIAS;
1252
rDesc.DepthBiasClamp = D3D11_DEFAULT_DEPTH_BIAS_CLAMP;
1253
rDesc.SlopeScaledDepthBias = D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
1254
rDesc.DepthClipEnable = TRUE;
1255
rDesc.ScissorEnable = FALSE;
1256
rDesc.MultisampleEnable = FALSE;
1257
rDesc.AntialiasedLineEnable = FALSE;
1258
1259
// init
1260
sPointDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
1261
sPointDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
1262
sPointDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
1263
sPointDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
1264
sPointDesc.MipLODBias = 0;
1265
sPointDesc.MaxAnisotropy = 1;
1266
sPointDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
1267
sPointDesc.BorderColor[0] = 1.0f;
1268
sPointDesc.BorderColor[1] = 1.0f;
1269
sPointDesc.BorderColor[2] = 1.0f;
1270
sPointDesc.BorderColor[3] = 1.0f;
1271
sPointDesc.MinLOD = -FLT_MAX;
1272
sPointDesc.MaxLOD = FLT_MAX;
1273
1274
sLinearDesc = sPointDesc;
1275
sLinearDesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
1276
1277
if (FAILED(dx11Device->CreateRasterizerState(&rDesc, &rasterState))) {
1278
// uh oh...
1279
}
1280
1281
if (FAILED(dx11Device->CreateSamplerState(&sPointDesc, &samplerPoint))) {
1282
// uh oh...
1283
}
1284
1285
if (FAILED(dx11Device->CreateSamplerState(&sLinearDesc, &samplerLinear))) {
1286
// uh oh...
1287
}
1288
1289
int32 maxShaders = 0;
1290
#if RETRO_USE_MOD_LOADER
1291
shaderCount = 0;
1292
#endif
1293
1294
if (videoSettings.shaderSupport) {
1295
LoadShader("None", false);
1296
LoadShader("Clean", true);
1297
LoadShader("CRT-Yeetron", true);
1298
LoadShader("CRT-Yee64", true);
1299
1300
#if RETRO_USE_MOD_LOADER
1301
// a place for mods to load custom shaders
1302
RunModCallbacks(MODCB_ONSHADERLOAD, NULL);
1303
userShaderCount = shaderCount;
1304
#endif
1305
1306
LoadShader("YUV-420", true);
1307
LoadShader("YUV-422", true);
1308
LoadShader("YUV-444", true);
1309
LoadShader("RGB-Image", true);
1310
maxShaders = shaderCount;
1311
}
1312
else {
1313
for (int32 s = 0; s < SHADER_COUNT; ++s) shaderList[s].linear = true;
1314
1315
shaderList[0].linear = videoSettings.windowed ? false : shaderList[0].linear;
1316
maxShaders = 1;
1317
shaderCount = 1;
1318
}
1319
1320
// Load backup shader if no shaders have been found
1321
if (!maxShaders) {
1322
PrintLog(PRINT_NORMAL, "[DX11] No shaders loaded correctly, attempting backup");
1323
maxShaders = 1;
1324
shaderCount = 1;
1325
if (!LoadBackupShader())
1326
PrintLog(PRINT_NORMAL, "[DX11] Failed to load backup shaders!");
1327
1328
}
1329
1330
videoSettings.shaderID = videoSettings.shaderID >= maxShaders ? 0 : videoSettings.shaderID;
1331
1332
return true;
1333
}
1334
1335
bool RenderDevice::SetupRendering()
1336
{
1337
// Init DX11 context & device
1338
UINT createDeviceFlags = 0;
1339
#ifdef _DEBUG
1340
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
1341
#endif
1342
1343
D3D_DRIVER_TYPE driverTypes[] = {
1344
D3D_DRIVER_TYPE_HARDWARE,
1345
D3D_DRIVER_TYPE_WARP,
1346
D3D_DRIVER_TYPE_REFERENCE,
1347
};
1348
UINT numDriverTypes = ARRAYSIZE(driverTypes);
1349
1350
D3D_FEATURE_LEVEL featureLevels[] = {
1351
D3D_FEATURE_LEVEL_11_1,
1352
D3D_FEATURE_LEVEL_11_0,
1353
D3D_FEATURE_LEVEL_10_1,
1354
D3D_FEATURE_LEVEL_10_0,
1355
};
1356
UINT numFeatureLevels = ARRAYSIZE(featureLevels);
1357
1358
HRESULT hr = 0;
1359
for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) {
1360
driverType = driverTypes[driverTypeIndex];
1361
hr = D3D11CreateDevice(nullptr, driverType, nullptr, createDeviceFlags, featureLevels, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION,
1362
&dx11Device, &featureLevel, &dx11Context);
1363
1364
if (hr == E_INVALIDARG) {
1365
// DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it
1366
hr = D3D11CreateDevice(nullptr, driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1, D3D11_SDK_VERSION,
1367
&dx11Device, &featureLevel, &dx11Context);
1368
}
1369
1370
if (SUCCEEDED(hr))
1371
break;
1372
}
1373
1374
if (FAILED(hr))
1375
return false;
1376
1377
ZeroMemory(&deviceIdentifier, sizeof(deviceIdentifier));
1378
1379
GetDisplays();
1380
1381
if (!InitGraphicsAPI() || !InitShaders())
1382
return false;
1383
1384
int32 size = videoSettings.pixWidth >= SCREEN_YSIZE ? videoSettings.pixWidth : SCREEN_YSIZE;
1385
scanlines = (ScanlineInfo *)malloc(size * sizeof(ScanlineInfo));
1386
memset(scanlines, 0, size * sizeof(ScanlineInfo));
1387
1388
videoSettings.windowState = WINDOWSTATE_ACTIVE;
1389
videoSettings.dimMax = 1.0;
1390
videoSettings.dimPercent = 1.0;
1391
1392
return true;
1393
}
1394
1395
void RenderDevice::GetDisplays()
1396
{
1397
std::vector<IDXGIAdapter *> adapterList = GetAdapterList();
1398
adapterCount = (int32)adapterList.size();
1399
1400
uint32 prevAdapter = dxAdapter;
1401
1402
HMONITOR windowMonitor = MonitorFromWindow(windowHandle, MONITOR_DEFAULTTOPRIMARY);
1403
for (int32 a = 0; a < adapterCount; ++a) {
1404
IDXGIOutput *pOutput;
1405
if (SUCCEEDED(adapterList[a]->EnumOutputs(0, &pOutput))) {
1406
DXGI_OUTPUT_DESC outputDesc;
1407
pOutput->GetDesc(&outputDesc);
1408
HMONITOR monitor = outputDesc.Monitor;
1409
1410
UINT modeCount;
1411
pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &modeCount, nullptr);
1412
1413
DXGI_MODE_DESC *descArr = new DXGI_MODE_DESC[modeCount];
1414
pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &modeCount, descArr);
1415
1416
std::vector<DXGI_MODE_DESC> adapterModeList;
1417
for (UINT i = 0; i < modeCount; i++) adapterModeList.push_back(descArr[i]);
1418
pOutput->Release();
1419
1420
displayWidth[a] = outputDesc.DesktopCoordinates.right - outputDesc.DesktopCoordinates.left;
1421
displayHeight[a] = outputDesc.DesktopCoordinates.bottom - outputDesc.DesktopCoordinates.top;
1422
1423
if (windowMonitor == monitor) {
1424
MONITORINFO lpmi;
1425
ZeroMemory(&lpmi, sizeof(lpmi));
1426
lpmi.cbSize = sizeof(MONITORINFO);
1427
1428
GetMonitorInfo(windowMonitor, &lpmi);
1429
dxAdapter = a;
1430
monitorDisplayRect = lpmi.rcMonitor;
1431
}
1432
1433
delete[] descArr;
1434
}
1435
}
1436
1437
DXGI_ADAPTER_DESC adapterIdentifier;
1438
ZeroMemory(&adapterIdentifier, sizeof(adapterIdentifier));
1439
adapterList[dxAdapter]->GetDesc(&adapterIdentifier);
1440
1441
// no change, don't reload anything
1442
if (memcmp(&deviceIdentifier, &adapterIdentifier.AdapterLuid, sizeof(deviceIdentifier)) == 0 && dxAdapter == prevAdapter)
1443
return;
1444
1445
deviceIdentifier = adapterIdentifier.AdapterLuid;
1446
1447
IDXGIOutput *pOutput;
1448
adapterList[dxAdapter]->EnumOutputs(0, &pOutput);
1449
1450
pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, (UINT *)&displayCount, nullptr);
1451
if (displayInfo.displays)
1452
free(displayInfo.displays);
1453
1454
DXGI_MODE_DESC *descArr = new DXGI_MODE_DESC[displayCount];
1455
pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, (UINT *)&displayCount, descArr);
1456
1457
displayInfo.displays = (decltype(displayInfo.displays))malloc(sizeof(DXGI_MODE_DESC) * displayCount);
1458
int32 newDisplayCount = 0;
1459
bool32 foundFullScreenDisplay = false;
1460
1461
for (int32 d = 0; d < displayCount; ++d) {
1462
memcpy(&displayInfo.displays[newDisplayCount].internal, &descArr[d], sizeof(DXGI_MODE_DESC));
1463
1464
int32 refreshRate = 0;
1465
1466
DXGI_RATIONAL *rate = &displayInfo.displays[newDisplayCount].refresh_rate;
1467
if (rate->Numerator > 0 && rate->Denominator > 0)
1468
refreshRate = rate->Numerator / rate->Denominator;
1469
1470
if (refreshRate >= 59 && (refreshRate <= 60 || refreshRate >= 120) && displayInfo.displays[newDisplayCount].height >= (SCREEN_YSIZE * 2)) {
1471
int32 prevRefreshRate = 0;
1472
if (d) {
1473
rate = &displayInfo.displays[newDisplayCount - 1].refresh_rate;
1474
1475
if (rate->Numerator > 0 && rate->Denominator > 0)
1476
prevRefreshRate = rate->Numerator / rate->Denominator;
1477
}
1478
1479
// remove duplicates
1480
if (d && displayInfo.displays[newDisplayCount].width == displayInfo.displays[newDisplayCount - 1].width
1481
&& displayInfo.displays[newDisplayCount].height == displayInfo.displays[newDisplayCount - 1].height
1482
&& refreshRate == prevRefreshRate) {
1483
memcpy(&displayInfo.displays[newDisplayCount - 1], &displayInfo.displays[newDisplayCount], sizeof(displayInfo.displays[0]));
1484
--newDisplayCount;
1485
}
1486
// remove "duds"
1487
else if (d && refreshRate == 60 && prevRefreshRate == 59) {
1488
memcpy(&displayInfo.displays[newDisplayCount - 1], &displayInfo.displays[newDisplayCount], sizeof(displayInfo.displays[0]));
1489
--newDisplayCount;
1490
}
1491
1492
if (videoSettings.fsWidth == displayInfo.displays[newDisplayCount].width
1493
&& videoSettings.fsHeight == displayInfo.displays[newDisplayCount].height)
1494
foundFullScreenDisplay = true;
1495
1496
++newDisplayCount;
1497
}
1498
}
1499
1500
delete[] descArr;
1501
1502
displayCount = newDisplayCount;
1503
if (!foundFullScreenDisplay) {
1504
videoSettings.fsWidth = 0;
1505
videoSettings.fsHeight = 0;
1506
videoSettings.refreshRate = 60; // 0;
1507
}
1508
}
1509
1510
void RenderDevice::GetWindowSize(int32 *width, int32 *height)
1511
{
1512
std::vector<IDXGIAdapter *> adapterList = GetAdapterList();
1513
1514
IDXGIOutput *pOutput;
1515
if (FAILED(adapterList[dxAdapter]->EnumOutputs(0, &pOutput))) {
1516
if (width)
1517
*width = 0;
1518
1519
if (height)
1520
*height = 0;
1521
1522
return;
1523
}
1524
1525
DXGI_OUTPUT_DESC outputDesc;
1526
pOutput->GetDesc(&outputDesc);
1527
1528
if (width)
1529
*width = outputDesc.DesktopCoordinates.right - outputDesc.DesktopCoordinates.left;
1530
1531
if (height)
1532
*height = outputDesc.DesktopCoordinates.bottom - outputDesc.DesktopCoordinates.top;
1533
}
1534
1535
void RenderDevice::ProcessEvent(MSG Msg)
1536
{
1537
bool handledMsg = false;
1538
1539
switch (Msg.message) {
1540
case WM_QUIT: isRunning = false; break;
1541
1542
// called when holding "ALT" down
1543
case WM_SYSKEYDOWN: {
1544
WPARAM activeButtons = Msg.wParam;
1545
switch (Msg.wParam) {
1546
// shift key
1547
case VK_SHIFT:
1548
activeButtons = MapVirtualKey(((Msg.lParam >> 16) & 0xFF), MAPVK_VSC_TO_VK_EX);
1549
break;
1550
1551
// CTRL key
1552
case VK_CONTROL:
1553
activeButtons = VK_LCONTROL + (((Msg.lParam >> 24) & 0xFF) & 1);
1554
break;
1555
1556
// ALT key
1557
case VK_MENU: activeButtons = VK_LMENU + (((Msg.lParam >> 24) & 0xFF) & 1); break;
1558
}
1559
1560
switch (Msg.wParam) {
1561
default:
1562
#if RETRO_INPUTDEVICE_KEYBOARD
1563
SKU::UpdateKeyState(activeButtons);
1564
handledMsg = true;
1565
#endif
1566
break;
1567
1568
case VK_RETURN: // alt + enter
1569
if (GetAsyncKeyState(VK_MENU)) {
1570
videoSettings.windowed ^= 1;
1571
UpdateGameWindow();
1572
changedVideoSettings = false;
1573
handledMsg = true;
1574
}
1575
1576
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1577
RSDK::SKU::specialKeyStates[1] = true;
1578
#endif
1579
break;
1580
1581
case VK_F4: // alt + f4
1582
if (GetAsyncKeyState(VK_MENU))
1583
isRunning = false;
1584
handledMsg = true;
1585
break;
1586
1587
case VK_F10:
1588
if (engine.devMenu)
1589
engine.showPaletteOverlay ^= 1;
1590
handledMsg = true;
1591
break;
1592
}
1593
1594
break;
1595
}
1596
1597
// regular keydown
1598
case WM_KEYDOWN: {
1599
WPARAM activeButtons = Msg.wParam;
1600
switch (Msg.wParam) {
1601
// shift key
1602
case VK_SHIFT:
1603
activeButtons = MapVirtualKey(((Msg.lParam >> 16) & 0xFF), MAPVK_VSC_TO_VK_EX);
1604
break;
1605
1606
// CTRL key
1607
case VK_CONTROL:
1608
activeButtons = VK_LCONTROL + (((Msg.lParam >> 24) & 0xFF) & 1);
1609
break;
1610
1611
// ALT key
1612
case VK_MENU: activeButtons = VK_LMENU + (((Msg.lParam >> 24) & 0xFF) & 1); break;
1613
}
1614
1615
// handledMsg = true;
1616
switch (Msg.wParam) {
1617
default:
1618
#if RETRO_INPUTDEVICE_KEYBOARD
1619
SKU::UpdateKeyState(activeButtons);
1620
handledMsg = false;
1621
#endif
1622
break;
1623
1624
case VK_BACK:
1625
if (engine.devMenu) {
1626
engine.gameSpeed = engine.fastForwardSpeed;
1627
handledMsg = true;
1628
}
1629
break;
1630
1631
case VK_ESCAPE:
1632
if (engine.devMenu) {
1633
#if RETRO_REV0U
1634
if (sceneInfo.state == ENGINESTATE_DEVMENU || RSDK::Legacy::gameMode == RSDK::Legacy::ENGINE_DEVMENU)
1635
#else
1636
if (sceneInfo.state == ENGINESTATE_DEVMENU)
1637
#endif
1638
CloseDevMenu();
1639
else
1640
OpenDevMenu();
1641
}
1642
else {
1643
#if RETRO_INPUTDEVICE_KEYBOARD
1644
SKU::UpdateKeyState(activeButtons);
1645
handledMsg = false;
1646
#endif
1647
}
1648
1649
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1650
RSDK::SKU::specialKeyStates[0] = true;
1651
#endif
1652
break;
1653
1654
#if !RETRO_USE_ORIGINAL_CODE
1655
case VK_F1:
1656
if (engine.devMenu) {
1657
sceneInfo.listPos--;
1658
while (sceneInfo.listPos < sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart
1659
|| sceneInfo.listPos > sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd
1660
|| !sceneInfo.listCategory[sceneInfo.activeCategory].sceneCount) {
1661
sceneInfo.activeCategory--;
1662
if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {
1663
sceneInfo.activeCategory = sceneInfo.categoryCount - 1;
1664
}
1665
sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd - 1;
1666
}
1667
1668
#if RETRO_REV0U
1669
switch (engine.version) {
1670
default: break;
1671
case 5: LoadScene(); break;
1672
case 4:
1673
case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;
1674
}
1675
#else
1676
LoadScene();
1677
#endif
1678
}
1679
break;
1680
1681
case VK_F2:
1682
if (engine.devMenu) {
1683
sceneInfo.listPos++;
1684
while (sceneInfo.listPos < sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart
1685
|| sceneInfo.listPos > sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd
1686
|| !sceneInfo.listCategory[sceneInfo.activeCategory].sceneCount) {
1687
sceneInfo.activeCategory++;
1688
if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {
1689
sceneInfo.activeCategory = 0;
1690
}
1691
sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart;
1692
}
1693
1694
#if RETRO_REV0U
1695
switch (engine.version) {
1696
default: break;
1697
case 5: LoadScene(); break;
1698
case 4:
1699
case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;
1700
}
1701
#else
1702
LoadScene();
1703
#endif
1704
}
1705
break;
1706
#endif
1707
1708
case VK_F3:
1709
if (userShaderCount) {
1710
videoSettings.shaderID = (videoSettings.shaderID + 1) % userShaderCount;
1711
handledMsg = true;
1712
}
1713
break;
1714
1715
#if !RETRO_USE_ORIGINAL_CODE
1716
case VK_F4:
1717
if (engine.devMenu) {
1718
engine.showEntityInfo ^= 1;
1719
1720
handledMsg = true;
1721
}
1722
break;
1723
1724
case VK_F5:
1725
if (engine.devMenu) {
1726
// Quick-Reload
1727
#if RETRO_USE_MOD_LOADER
1728
if (GetAsyncKeyState(VK_CONTROL))
1729
RefreshModFolders();
1730
#endif
1731
1732
#if RETRO_REV0U
1733
switch (engine.version) {
1734
default: break;
1735
case 5: LoadScene(); break;
1736
case 4:
1737
case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;
1738
}
1739
#else
1740
LoadScene();
1741
#endif
1742
}
1743
break;
1744
1745
case VK_F6:
1746
if (engine.devMenu && videoSettings.screenCount > 1)
1747
videoSettings.screenCount--;
1748
break;
1749
1750
case VK_F7:
1751
if (engine.devMenu && videoSettings.screenCount < SCREEN_COUNT)
1752
videoSettings.screenCount++;
1753
break;
1754
1755
case VK_F8:
1756
if (engine.devMenu) {
1757
engine.showUpdateRanges ^= 1;
1758
1759
handledMsg = true;
1760
}
1761
break;
1762
1763
case VK_F9:
1764
if (engine.devMenu) {
1765
showHitboxes ^= 1;
1766
1767
handledMsg = true;
1768
}
1769
break;
1770
1771
case VK_F10:
1772
if (engine.devMenu)
1773
engine.showPaletteOverlay ^= 1;
1774
break;
1775
#endif
1776
1777
case VK_INSERT:
1778
case VK_F11:
1779
if (engine.devMenu) {
1780
engine.frameStep = true;
1781
handledMsg = true;
1782
}
1783
break;
1784
1785
case VK_PAUSE:
1786
case VK_F12:
1787
if (engine.devMenu) {
1788
#if RETRO_REV0U
1789
switch (engine.version) {
1790
default: break;
1791
case 5:
1792
if (sceneInfo.state != ENGINESTATE_NONE)
1793
sceneInfo.state ^= ENGINESTATE_STEPOVER;
1794
break;
1795
case 4:
1796
case 3:
1797
if (RSDK::Legacy::stageMode != ENGINESTATE_NONE)
1798
RSDK::Legacy::stageMode ^= RSDK::Legacy::STAGEMODE_STEPOVER;
1799
break;
1800
}
1801
#else
1802
if (sceneInfo.state != ENGINESTATE_NONE)
1803
sceneInfo.state ^= ENGINESTATE_STEPOVER;
1804
#endif
1805
}
1806
break;
1807
}
1808
break;
1809
}
1810
1811
case WM_KEYUP:
1812
case WM_SYSKEYUP: {
1813
WPARAM activeButtons = Msg.wParam;
1814
switch (Msg.wParam) {
1815
case VK_SHIFT: activeButtons = MapVirtualKey(((Msg.lParam >> 16) & 0xFF), MAPVK_VSC_TO_VK_EX); break;
1816
1817
case VK_CONTROL: activeButtons = VK_LCONTROL + ((Msg.lParam >> 24) & 1); break;
1818
1819
case VK_MENU: // ALT key
1820
activeButtons = VK_LMENU + ((Msg.lParam >> 24) & 1);
1821
break;
1822
}
1823
1824
switch (Msg.wParam) {
1825
default:
1826
#if RETRO_INPUTDEVICE_KEYBOARD
1827
SKU::ClearKeyState(activeButtons);
1828
#endif
1829
break;
1830
1831
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1832
case VK_ESCAPE:
1833
RSDK::SKU::specialKeyStates[0] = false;
1834
SKU::ClearKeyState(activeButtons);
1835
break;
1836
1837
case VK_RETURN:
1838
RSDK::SKU::specialKeyStates[1] = false;
1839
SKU::ClearKeyState(activeButtons);
1840
break;
1841
#endif
1842
1843
case VK_BACK:
1844
engine.gameSpeed = 1;
1845
handledMsg = true;
1846
break;
1847
}
1848
1849
break;
1850
}
1851
1852
case WM_LBUTTONDOWN: touchInfo.down[0] = 1; touchInfo.count = 1;
1853
1854
#if !RETRO_REV02
1855
RSDK::SKU::buttonDownCount++;
1856
#endif
1857
1858
handledMsg = true;
1859
break;
1860
1861
case WM_LBUTTONUP: touchInfo.down[0] = 0; touchInfo.count = 0;
1862
1863
#if !RETRO_REV02
1864
RSDK::SKU::buttonDownCount--;
1865
#endif
1866
1867
handledMsg = true;
1868
break;
1869
1870
case WM_MBUTTONDOWN: handledMsg = true; break;
1871
1872
case WM_RBUTTONDOWN: handledMsg = true;
1873
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1874
RSDK::SKU::specialKeyStates[3] = true;
1875
RSDK::SKU::buttonDownCount++;
1876
#endif
1877
break;
1878
1879
case WM_RBUTTONUP: handledMsg = true;
1880
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
1881
RSDK::SKU::specialKeyStates[3] = false;
1882
RSDK::SKU::buttonDownCount--;
1883
#endif
1884
break;
1885
}
1886
1887
if (!handledMsg)
1888
DispatchMessage(&Msg);
1889
}
1890
1891
bool RenderDevice::ProcessEvents()
1892
{
1893
MSG Msg = {};
1894
while (PeekMessage(&Msg, NULL, 0, 0, true)) {
1895
ProcessEvent(Msg);
1896
1897
if (!isRunning)
1898
return false;
1899
}
1900
1901
return isRunning;
1902
}
1903
1904
LRESULT CALLBACK RenderDevice::WindowEventCallback(HWND hRecipient, UINT message, WPARAM wParam, LPARAM lParam)
1905
{
1906
bool32 forceExit = false;
1907
GUID deviceGUID = KSCATEGORY_AUDIO;
1908
1909
switch (message) {
1910
case WM_CREATE: {
1911
if (deviceNotif)
1912
return 0;
1913
1914
DEV_BROADCAST_DEVICEINTERFACE filter;
1915
filter.dbcc_name[0] = 0;
1916
filter.dbcc_reserved = 0;
1917
filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
1918
filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
1919
filter.dbcc_classguid = deviceGUID;
1920
1921
deviceNotif = RegisterDeviceNotification(hRecipient, &filter, DEVICE_NOTIFY_WINDOW_HANDLE);
1922
1923
forceExit = true;
1924
break;
1925
}
1926
1927
case WM_DESTROY:
1928
if (deviceNotif) {
1929
UnregisterDeviceNotification(deviceNotif);
1930
deviceNotif = 0;
1931
}
1932
1933
isRunning = false;
1934
forceExit = true;
1935
break;
1936
1937
case WM_MOVE:
1938
case WM_SIZE: forceExit = true; break;
1939
1940
case WM_ACTIVATE:
1941
if (wParam) {
1942
if (!videoSettings.windowState)
1943
return 0;
1944
1945
if (AudioDevice::audioFocus == 1) {
1946
AudioDevice::audioFocus = 0;
1947
if (AudioDevice::sourceVoice)
1948
AudioDevice::sourceVoice->Start(0, 0);
1949
}
1950
1951
GetDisplays();
1952
videoSettings.windowState = WINDOWSTATE_ACTIVE;
1953
}
1954
else {
1955
touchInfo.down[0] = false;
1956
touchInfo.count = 0;
1957
if (!videoSettings.windowState)
1958
return 0;
1959
#if !RETRO_USE_ORIGINAL_CODE
1960
if (customSettings.disableFocusPause)
1961
return 0;
1962
#endif
1963
1964
if (!AudioDevice::audioFocus) {
1965
AudioDevice::audioFocus = 1;
1966
if (AudioDevice::sourceVoice)
1967
AudioDevice::sourceVoice->Stop(0, 0);
1968
}
1969
1970
videoSettings.windowState = WINDOWSTATE_INACTIVE;
1971
}
1972
1973
forceExit = true;
1974
break;
1975
1976
case WM_PAINT:
1977
BeginPaint(hRecipient, &Paint);
1978
EndPaint(hRecipient, &Paint);
1979
1980
forceExit = true;
1981
break;
1982
1983
case WM_DEVICECHANGE: {
1984
DEV_BROADCAST_DEVICEINTERFACE *deviceInterace = (DEV_BROADCAST_DEVICEINTERFACE *)lParam;
1985
1986
if ((wParam == DBT_DEVICEARRIVAL || wParam == DBT_DEVICEREMOVECOMPLETE) && deviceInterace
1987
&& deviceInterace->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
1988
1989
if (memcmp(&deviceInterace->dbcc_classguid, &deviceGUID, sizeof(deviceGUID)) == 0) {
1990
AudioDevice::audioState = 30;
1991
}
1992
}
1993
1994
#if RETRO_INPUTDEVICE_XINPUT
1995
SKU::UpdateXInputDevices();
1996
#endif
1997
1998
#if RETRO_INPUTDEVICE_RAWINPUT
1999
SKU::InitHIDAPI();
2000
#endif
2001
2002
#if RETRO_INPUTDEVICE_XINPUT
2003
SKU::InitXInputAPI();
2004
#endif
2005
2006
forceExit = true;
2007
break;
2008
}
2009
2010
#if RETRO_INPUTDEVICE_RAWINPUT
2011
case WM_INPUT:
2012
SKU::UpdateHIDButtonStates((HRAWINPUT)lParam);
2013
2014
forceExit = true;
2015
break;
2016
#endif
2017
2018
case WM_SYSCOMMAND: {
2019
int32 param = wParam & 0xFFF0;
2020
if (param == SC_MINIMIZE) {
2021
touchInfo.down[0] = 0;
2022
touchInfo.count = 0;
2023
if (videoSettings.windowState) {
2024
PauseSound();
2025
videoSettings.windowState = WINDOWSTATE_INACTIVE;
2026
}
2027
}
2028
else if (param == SC_MAXIMIZE && videoSettings.windowState != WINDOWSTATE_UNINITIALIZED) {
2029
ResumeSound();
2030
videoSettings.windowState = WINDOWSTATE_ACTIVE;
2031
}
2032
2033
break;
2034
}
2035
2036
case WM_MENUSELECT:
2037
case WM_ENTERSIZEMOVE:
2038
touchInfo.down[0] = 0;
2039
touchInfo.count = 0;
2040
2041
forceExit = true;
2042
break;
2043
2044
case WM_EXITSIZEMOVE:
2045
GetDisplays();
2046
2047
forceExit = true;
2048
break;
2049
2050
default: break;
2051
}
2052
2053
if (forceExit)
2054
return 0;
2055
else
2056
return DefWindowProc(hRecipient, message, wParam, lParam);
2057
}
2058
2059
void RenderDevice::SetupImageTexture(int32 width, int32 height, uint8 *imagePixels)
2060
{
2061
if (!imagePixels)
2062
return;
2063
2064
D3D11_MAPPED_SUBRESOURCE mappedResource;
2065
if (SUCCEEDED(dx11Context->Map(imageTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))) {
2066
DWORD *pixels = (DWORD *)mappedResource.pData;
2067
int32 pitch = (mappedResource.RowPitch >> 2) - width;
2068
2069
uint32 *imagePixels32 = (uint32 *)imagePixels;
2070
for (int32 y = 0; y < height; ++y) {
2071
for (int32 x = 0; x < width; ++x) {
2072
*pixels++ = *imagePixels32++;
2073
}
2074
2075
pixels += pitch;
2076
}
2077
2078
dx11Context->Unmap(imageTexture, 0);
2079
}
2080
}
2081
2082
void RenderDevice::SetupVideoTexture_YUV420(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,
2083
int32 strideV)
2084
{
2085
D3D11_MAPPED_SUBRESOURCE mappedResource;
2086
if (SUCCEEDED(dx11Context->Map(imageTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))) {
2087
DWORD *pixels = (DWORD *)mappedResource.pData;
2088
int32 pitch = (mappedResource.RowPitch >> 2) - width;
2089
2090
if (videoSettings.shaderSupport) {
2091
// Shaders are supported! lets watch this video in full color!
2092
for (int32 y = 0; y < height; ++y) {
2093
for (int32 x = 0; x < width; ++x) {
2094
*pixels++ = (yPlane[x] << 16) | 0xFF000000;
2095
}
2096
2097
pixels += pitch;
2098
yPlane += strideY;
2099
}
2100
2101
pixels = (DWORD *)mappedResource.pData;
2102
pitch = (mappedResource.RowPitch >> 2) - (width >> 1);
2103
for (int32 y = 0; y < (height >> 1); ++y) {
2104
for (int32 x = 0; x < (width >> 1); ++x) {
2105
*pixels++ |= (vPlane[x] << 0) | (uPlane[x] << 8) | 0xFF000000;
2106
}
2107
2108
pixels += pitch;
2109
uPlane += strideU;
2110
vPlane += strideV;
2111
}
2112
}
2113
else {
2114
// No shader support means no YUV support! at least use the brightness to show it in grayscale!
2115
for (int32 y = 0; y < height; ++y) {
2116
for (int32 x = 0; x < width; ++x) {
2117
int32 brightness = yPlane[x];
2118
*pixels++ = (brightness << 0) | (brightness << 8) | (brightness << 16) | 0xFF000000;
2119
}
2120
2121
pixels += pitch;
2122
yPlane += strideY;
2123
}
2124
}
2125
2126
dx11Context->Unmap(imageTexture, 0);
2127
}
2128
}
2129
void RenderDevice::SetupVideoTexture_YUV422(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,
2130
int32 strideV)
2131
{
2132
D3D11_MAPPED_SUBRESOURCE mappedResource;
2133
if (SUCCEEDED(dx11Context->Map(imageTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))) {
2134
DWORD *pixels = (DWORD *)mappedResource.pData;
2135
int32 pitch = (mappedResource.RowPitch >> 2) - width;
2136
2137
if (videoSettings.shaderSupport) {
2138
// Shaders are supported! lets watch this video in full color!
2139
for (int32 y = 0; y < height; ++y) {
2140
for (int32 x = 0; x < width; ++x) {
2141
*pixels++ = (yPlane[x] << 16) | 0xFF000000;
2142
}
2143
2144
pixels += pitch;
2145
yPlane += strideY;
2146
}
2147
2148
pixels = (DWORD *)mappedResource.pData;
2149
pitch = (mappedResource.RowPitch >> 2) - (width >> 1);
2150
for (int32 y = 0; y < height; ++y) {
2151
for (int32 x = 0; x < (width >> 1); ++x) {
2152
*pixels++ |= (vPlane[x] << 0) | (uPlane[x] << 8) | 0xFF000000;
2153
}
2154
2155
pixels += pitch;
2156
uPlane += strideU;
2157
vPlane += strideV;
2158
}
2159
}
2160
else {
2161
// No shader support means no YUV support! at least use the brightness to show it in grayscale!
2162
for (int32 y = 0; y < height; ++y) {
2163
for (int32 x = 0; x < width; ++x) {
2164
int32 brightness = yPlane[x];
2165
*pixels++ = (brightness << 0) | (brightness << 8) | (brightness << 16) | 0xFF000000;
2166
}
2167
2168
pixels += pitch;
2169
yPlane += strideY;
2170
}
2171
}
2172
2173
dx11Context->Unmap(imageTexture, 0);
2174
}
2175
}
2176
void RenderDevice::SetupVideoTexture_YUV444(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,
2177
int32 strideV)
2178
{
2179
D3D11_MAPPED_SUBRESOURCE mappedResource;
2180
if (SUCCEEDED(dx11Context->Map(imageTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))) {
2181
DWORD *pixels = (DWORD *)mappedResource.pData;
2182
int32 pitch = (mappedResource.RowPitch >> 2) - width;
2183
2184
if (videoSettings.shaderSupport) {
2185
// Shaders are supported! lets watch this video in full color!
2186
for (int32 y = 0; y < height; ++y) {
2187
int32 pos1 = yPlane - vPlane;
2188
int32 pos2 = uPlane - vPlane;
2189
uint8 *pixV = vPlane;
2190
for (int32 x = 0; x < width; ++x) {
2191
*pixels++ = pixV[0] | (pixV[pos2] << 8) | (pixV[pos1] << 16) | 0xFF000000;
2192
pixV++;
2193
}
2194
2195
pixels += pitch;
2196
yPlane += strideY;
2197
uPlane += strideU;
2198
vPlane += strideV;
2199
}
2200
}
2201
else {
2202
// No shader support means no YUV support! at least use the brightness to show it in grayscale!
2203
for (int32 y = 0; y < height; ++y) {
2204
for (int32 x = 0; x < width; ++x) {
2205
int32 brightness = yPlane[x];
2206
*pixels++ = (brightness << 0) | (brightness << 8) | (brightness << 16) | 0xFF000000;
2207
}
2208
2209
pixels += pitch;
2210
yPlane += strideY;
2211
}
2212
}
2213
2214
dx11Context->Unmap(imageTexture, 0);
2215
}
2216
}
2217
2218