HLE : Configurable viewport scaling (as a hack)
This commit is contained in:
parent
7ac82d5de1
commit
ccd82a8e0f
BIN
resource/Cxbx.rc
BIN
resource/Cxbx.rc
Binary file not shown.
|
@ -135,6 +135,7 @@
|
|||
#define ID_HACKS_UNCAPFRAMERATE 40097
|
||||
#define ID_HACKS_RUNXBOXTHREADSONALLCORES 40098
|
||||
#define ID_HACKS_PATCHCPUFREQUENCY 40099
|
||||
#define ID_HACKS_SCALEVIEWPORT 40100
|
||||
#define IDC_STATIC -1
|
||||
|
||||
// Next default values for new objects
|
||||
|
|
|
@ -113,7 +113,7 @@ void WndMain::InitializeSettings() {
|
|||
#define TIMERID_FPS 0
|
||||
#define TIMERID_LED 1
|
||||
|
||||
void WndMain::ResizeWindow(bool bForGUI)
|
||||
void WndMain::ResizeWindow(HWND hwnd, bool bForGUI)
|
||||
{
|
||||
RECT desktopRect;
|
||||
RECT windowRect;
|
||||
|
@ -149,9 +149,9 @@ void WndMain::ResizeWindow(bool bForGUI)
|
|||
|
||||
// Resize the window so it's client area can contain the requested resolution
|
||||
windowRect = { m_x, m_y, m_x + m_w, m_y + m_h };
|
||||
AdjustWindowRectEx(&windowRect, GetWindowLong(m_hwnd, GWL_STYLE), GetMenu(m_hwnd) != NULL, GetWindowLong(m_hwnd, GWL_EXSTYLE));
|
||||
AdjustWindowRectEx(&windowRect, GetWindowLong(hwnd, GWL_STYLE), GetMenu(hwnd) != NULL, GetWindowLong(hwnd, GWL_EXSTYLE));
|
||||
// TODO : For DPI screens, replace AdjustWindowRectEx by DwmGetWindowAttribute using DWMWA_EXTENDED_FRAME_BOUNDS
|
||||
SetWindowPos(m_hwnd, 0,
|
||||
SetWindowPos(hwnd, 0,
|
||||
windowRect.left,
|
||||
windowRect.top,
|
||||
windowRect.right - windowRect.left,
|
||||
|
@ -230,6 +230,12 @@ WndMain::WndMain(HINSTANCE x_hInstance) :
|
|||
m_PatchCpuFrequency = 0;
|
||||
}
|
||||
|
||||
dwType = REG_DWORD; dwSize = sizeof(DWORD);
|
||||
result = RegQueryValueEx(hKey, "HackScaleViewport", NULL, &dwType, (PBYTE)&m_ScaleViewport, &dwSize);
|
||||
if (result != ERROR_SUCCESS) {
|
||||
m_ScaleViewport = 0;
|
||||
}
|
||||
|
||||
dwType = REG_DWORD; dwSize = sizeof(DWORD);
|
||||
result = RegQueryValueEx(hKey, "CxbxDebug", NULL, &dwType, (PBYTE)&m_CxbxDebug, &dwSize);
|
||||
if (result != ERROR_SUCCESS) {
|
||||
|
@ -392,6 +398,9 @@ WndMain::~WndMain()
|
|||
dwType = REG_DWORD; dwSize = sizeof(DWORD);
|
||||
RegSetValueEx(hKey, "HackPatchCpuFrequency", 0, dwType, (PBYTE)&m_PatchCpuFrequency, dwSize);
|
||||
|
||||
dwType = REG_DWORD; dwSize = sizeof(DWORD);
|
||||
RegSetValueEx(hKey, "HackScaleViewport", 0, dwType, (PBYTE)&m_ScaleViewport, dwSize);
|
||||
|
||||
dwType = REG_DWORD; dwSize = sizeof(DWORD);
|
||||
RegSetValueEx(hKey, "CxbxDebug", 0, dwType, (PBYTE)&m_CxbxDebug, dwSize);
|
||||
|
||||
|
@ -435,8 +444,7 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
}
|
||||
|
||||
// Set window size to GUI dimensions
|
||||
m_hwnd = hwnd; // Needed inside ResizeWindow (will be set to the same value later wayway)
|
||||
ResizeWindow(/*bForGUI=*/true);
|
||||
ResizeWindow(hwnd, /*bForGUI=*/true);
|
||||
|
||||
// initialize back buffer
|
||||
{
|
||||
|
@ -1363,6 +1371,11 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
RefreshMenus();
|
||||
break;
|
||||
|
||||
case ID_HACKS_SCALEVIEWPORT:
|
||||
m_ScaleViewport = !m_ScaleViewport;
|
||||
RefreshMenus();
|
||||
break;
|
||||
|
||||
case ID_HELP_ABOUT:
|
||||
{
|
||||
ShowAboutDialog(hwnd);
|
||||
|
@ -1793,6 +1806,9 @@ void WndMain::RefreshMenus()
|
|||
|
||||
chk_flag = (m_PatchCpuFrequency) ? MF_CHECKED : MF_UNCHECKED;
|
||||
CheckMenuItem(settings_menu, ID_HACKS_PATCHCPUFREQUENCY, chk_flag);
|
||||
|
||||
chk_flag = (m_ScaleViewport) ? MF_CHECKED : MF_UNCHECKED;
|
||||
CheckMenuItem(settings_menu, ID_HACKS_SCALEVIEWPORT, chk_flag);
|
||||
}
|
||||
|
||||
// emulation menu
|
||||
|
@ -2167,9 +2183,18 @@ void WndMain::StartEmulation(HWND hwndParent, DebuggerState LocalDebuggerState /
|
|||
g_EmuShared->SetUncapFramerate(&m_UncapFramerate);
|
||||
g_EmuShared->SetUseAllCores(&m_UseAllCores);
|
||||
g_EmuShared->SetPatchCpuFrequency(&m_PatchCpuFrequency);
|
||||
g_EmuShared->SetScaleViewport(&m_ScaleViewport);
|
||||
|
||||
// Set the window size to emulation dimensions
|
||||
ResizeWindow(/*bForGUI*/false);
|
||||
if (m_ScaleViewport) {
|
||||
// Set the window size to emulation dimensions
|
||||
// Note : Doing this here assures the emulation process will use
|
||||
// the configured dimensions (because if done inside the emulation
|
||||
// process, that doesn't resize correctly sometimes)
|
||||
// TODO : Instead of doing the resize before launch, move it
|
||||
// towards CreateDevice emulation, using Xbox-requested dimensions
|
||||
// (and fix the issue of incorrect resizing)
|
||||
ResizeWindow(m_hwnd, /*bForGUI*/false);
|
||||
}
|
||||
|
||||
// shell exe
|
||||
{
|
||||
|
@ -2240,7 +2265,7 @@ void WndMain::StopEmulation()
|
|||
UpdateCaption();
|
||||
RefreshMenus();
|
||||
// Set the window size back to it's GUI dimensions
|
||||
ResizeWindow(/*bForGUI=*/true);
|
||||
ResizeWindow(m_hwnd, /*bForGUI=*/true);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ class WndMain : public Wnd
|
|||
// ******************************************************************
|
||||
// * resize the main window for either GUI or emulation
|
||||
// ******************************************************************
|
||||
void ResizeWindow(bool bForGUI);
|
||||
void ResizeWindow(HWND hwnd, bool bForGUI);
|
||||
|
||||
// ******************************************************************
|
||||
// * after an xbe is loaded, some things must be updated
|
||||
|
@ -222,6 +222,7 @@ class WndMain : public Wnd
|
|||
int m_UncapFramerate;
|
||||
int m_UseAllCores;
|
||||
int m_PatchCpuFrequency;
|
||||
int m_ScaleViewport;
|
||||
|
||||
// ******************************************************************
|
||||
// * debug output filenames
|
||||
|
|
|
@ -583,6 +583,7 @@ void PrintCurrentConfigurationLog()
|
|||
printf("Uncap Framerate: %s\n", g_UncapFramerate == 1 ? "On" : "Off");
|
||||
printf("Run Xbox threads on all cores: %s\n", g_UseAllCores == 1 ? "On" : "Off");
|
||||
printf("Patch CPU Frequency (rdtsc): %s\n", g_PatchCpuFrequency == 1 ? "On" : "Off");
|
||||
printf("Scale Xbox to host viewport (and back): %s\n", g_ScaleViewport == 1 ? "On" : "Off");
|
||||
}
|
||||
|
||||
printf("------------------------- END OF CONFIG LOG ------------------------\n");
|
||||
|
@ -1102,6 +1103,8 @@ __declspec(noreturn) void CxbxKrnlInit
|
|||
g_UseAllCores = !!HackEnabled;
|
||||
g_EmuShared->GetPatchCpuFrequency(&HackEnabled);
|
||||
g_PatchCpuFrequency = !!HackEnabled;
|
||||
g_EmuShared->GetScaleViewport(&HackEnabled);
|
||||
g_ScaleViewport = !!HackEnabled;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_PRINT_CURRENT_CONF
|
||||
|
|
|
@ -68,6 +68,7 @@ bool g_DisablePixelShaders = false;
|
|||
bool g_UncapFramerate = false;
|
||||
bool g_UseAllCores = false;
|
||||
bool g_PatchCpuFrequency = false;
|
||||
bool g_ScaleViewport = false;
|
||||
|
||||
// Delta added to host SystemTime, used in xboxkrnl::KeQuerySystemTime and xboxkrnl::NtSetSystemTime
|
||||
LARGE_INTEGER HostSystemTimeDelta = {};
|
||||
|
|
|
@ -111,4 +111,5 @@ extern bool g_DisablePixelShaders;
|
|||
extern bool g_UncapFramerate;
|
||||
extern bool g_UseAllCores;
|
||||
extern bool g_PatchCpuFrequency;
|
||||
extern bool g_ScaleViewport;
|
||||
#endif
|
||||
|
|
|
@ -3209,36 +3209,37 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetViewport)
|
|||
|
||||
LOG_FUNC_ONE_ARG(pViewport);
|
||||
|
||||
D3DVIEWPORT HostViewPort = *pViewport;
|
||||
|
||||
if (g_ScaleViewport) {
|
||||
#if 0 // Disabled for now, as the Xbox code triggers an error-code 6 in uc_emu_start()
|
||||
// Use a trampoline here, so GetViewport can be unpatched
|
||||
XB_trampoline(VOID, WINAPI, D3DDevice_SetViewport, (CONST X_D3DVIEWPORT8 *));
|
||||
XB_D3DDevice_SetViewport(pViewport);
|
||||
// Use a trampoline here, so GetViewport can be unpatched
|
||||
XB_trampoline(VOID, WINAPI, D3DDevice_SetViewport, (CONST X_D3DVIEWPORT8 *));
|
||||
XB_D3DDevice_SetViewport(pViewport);
|
||||
#endif
|
||||
|
||||
// Get current Xbox render target dimensions
|
||||
DWORD XboxRenderTarget_Width = GetPixelContainerWidth(g_pXboxRenderTarget);
|
||||
DWORD XboxRenderTarget_Height = GetPixelContainerHeigth(g_pXboxRenderTarget);
|
||||
// Get current Xbox render target dimensions
|
||||
DWORD XboxRenderTarget_Width = GetPixelContainerWidth(g_pXboxRenderTarget);
|
||||
DWORD XboxRenderTarget_Height = GetPixelContainerHeigth(g_pXboxRenderTarget);
|
||||
|
||||
// Get current host render target dimensions
|
||||
DWORD HostRenderTarget_Width;
|
||||
DWORD HostRenderTarget_Height;
|
||||
// Get current host render target dimensions
|
||||
DWORD HostRenderTarget_Width;
|
||||
DWORD HostRenderTarget_Height;
|
||||
|
||||
D3DVIEWPORT HostViewPort;
|
||||
if (GetHostRenderTargetDimensions(&HostRenderTarget_Width, &HostRenderTarget_Height)) {
|
||||
|
||||
if (GetHostRenderTargetDimensions(&HostRenderTarget_Width, &HostRenderTarget_Height)) {
|
||||
|
||||
// Scale Xbox to host dimensions (avoiding hard-coding 640 x 480)
|
||||
HostViewPort.X = ScaleDWORD(pViewport->X, XboxRenderTarget_Width, HostRenderTarget_Width);
|
||||
HostViewPort.Y = ScaleDWORD(pViewport->Y, XboxRenderTarget_Height, HostRenderTarget_Height);
|
||||
HostViewPort.Width = ScaleDWORD(pViewport->Width, XboxRenderTarget_Width, HostRenderTarget_Width);
|
||||
HostViewPort.Height = ScaleDWORD(pViewport->Height, XboxRenderTarget_Height, HostRenderTarget_Height);
|
||||
// TODO : Fix test-case Shenmue 2 (which halves height, leaving the bottom half unused)
|
||||
HostViewPort.MinZ = pViewport->MinZ; // No need scale Z for now
|
||||
HostViewPort.MaxZ = pViewport->MaxZ;
|
||||
}
|
||||
else {
|
||||
HostViewPort = *pViewport;
|
||||
EmuWarning("GetHostRenderTargetDimensions failed - SetViewport sets Xbox viewport instead!");
|
||||
// Scale Xbox to host dimensions (avoiding hard-coding 640 x 480)
|
||||
HostViewPort.X = ScaleDWORD(pViewport->X, XboxRenderTarget_Width, HostRenderTarget_Width);
|
||||
HostViewPort.Y = ScaleDWORD(pViewport->Y, XboxRenderTarget_Height, HostRenderTarget_Height);
|
||||
HostViewPort.Width = ScaleDWORD(pViewport->Width, XboxRenderTarget_Width, HostRenderTarget_Width);
|
||||
HostViewPort.Height = ScaleDWORD(pViewport->Height, XboxRenderTarget_Height, HostRenderTarget_Height);
|
||||
// TODO : Fix test-case Shenmue 2 (which halves height, leaving the bottom half unused)
|
||||
HostViewPort.MinZ = pViewport->MinZ; // No need scale Z for now
|
||||
HostViewPort.MaxZ = pViewport->MaxZ;
|
||||
}
|
||||
else {
|
||||
EmuWarning("GetHostRenderTargetDimensions failed - SetViewport sets Xbox viewport instead!");
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT hRet = g_pD3DDevice->SetViewport(&HostViewPort);
|
||||
|
@ -3257,38 +3258,43 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_GetViewport)
|
|||
|
||||
LOG_FUNC_ONE_ARG(pViewport);
|
||||
|
||||
// Note : We cannot return the Xbox viewport as set in EMUPATCH(D3DDevice_SetViewport)
|
||||
// because various Xbox D3D functions reset the Xbox viewport. Since we call comparable
|
||||
// functions on host D3D, the host viewport is better suited as a return value;
|
||||
// We just need to scale the host viewport back to Xbox dimensions - the exact opposite
|
||||
// operation from the up-scaling that happens in EMUPATCH(D3DDevice_SetViewport).
|
||||
|
||||
D3DVIEWPORT HostViewPort;
|
||||
|
||||
HRESULT hRet = g_pD3DDevice->GetViewport(&HostViewPort);
|
||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->GetViewport");
|
||||
|
||||
// Get current host render target dimensions
|
||||
DWORD HostRenderTarget_Width;
|
||||
DWORD HostRenderTarget_Height;
|
||||
|
||||
if (GetHostRenderTargetDimensions(&HostRenderTarget_Width, &HostRenderTarget_Height)) {
|
||||
|
||||
// Get current Xbox render target dimensions
|
||||
DWORD XboxRenderTarget_Width = GetPixelContainerWidth(g_pXboxRenderTarget);
|
||||
DWORD XboxRenderTarget_Height = GetPixelContainerHeigth(g_pXboxRenderTarget);
|
||||
|
||||
// Scale host back to Xbox dimensions (avoiding hard-coding 640 x 480)
|
||||
pViewport->X = ScaleDWORD(HostViewPort.X, HostRenderTarget_Width, XboxRenderTarget_Width);
|
||||
pViewport->Y = ScaleDWORD(HostViewPort.Y, HostRenderTarget_Height, XboxRenderTarget_Height);
|
||||
pViewport->Width = ScaleDWORD(HostViewPort.Width, HostRenderTarget_Width, XboxRenderTarget_Width);
|
||||
pViewport->Height = ScaleDWORD(HostViewPort.Height, HostRenderTarget_Height, XboxRenderTarget_Height);
|
||||
pViewport->MinZ = HostViewPort.MinZ; // No need scale Z for now
|
||||
pViewport->MaxZ = HostViewPort.MaxZ;
|
||||
if (!g_ScaleViewport) {
|
||||
*pViewport = HostViewPort;
|
||||
}
|
||||
else {
|
||||
*pViewport = HostViewPort;
|
||||
EmuWarning("GetHostRenderTargetDimensions failed - GetViewport returns host viewport instead!");
|
||||
// Note : We cannot return the Xbox viewport as set in EMUPATCH(D3DDevice_SetViewport)
|
||||
// because various Xbox D3D functions reset the Xbox viewport. Since we call comparable
|
||||
// functions on host D3D, the host viewport is better suited as a return value;
|
||||
// We just need to scale the host viewport back to Xbox dimensions - the exact opposite
|
||||
// operation from the up-scaling that happens in EMUPATCH(D3DDevice_SetViewport).
|
||||
|
||||
// Get current host render target dimensions
|
||||
DWORD HostRenderTarget_Width;
|
||||
DWORD HostRenderTarget_Height;
|
||||
|
||||
if (GetHostRenderTargetDimensions(&HostRenderTarget_Width, &HostRenderTarget_Height)) {
|
||||
|
||||
// Get current Xbox render target dimensions
|
||||
DWORD XboxRenderTarget_Width = GetPixelContainerWidth(g_pXboxRenderTarget);
|
||||
DWORD XboxRenderTarget_Height = GetPixelContainerHeigth(g_pXboxRenderTarget);
|
||||
|
||||
// Scale host back to Xbox dimensions (avoiding hard-coding 640 x 480)
|
||||
pViewport->X = ScaleDWORD(HostViewPort.X, HostRenderTarget_Width, XboxRenderTarget_Width);
|
||||
pViewport->Y = ScaleDWORD(HostViewPort.Y, HostRenderTarget_Height, XboxRenderTarget_Height);
|
||||
pViewport->Width = ScaleDWORD(HostViewPort.Width, HostRenderTarget_Width, XboxRenderTarget_Width);
|
||||
pViewport->Height = ScaleDWORD(HostViewPort.Height, HostRenderTarget_Height, XboxRenderTarget_Height);
|
||||
pViewport->MinZ = HostViewPort.MinZ; // No need scale Z for now
|
||||
pViewport->MaxZ = HostViewPort.MaxZ;
|
||||
}
|
||||
else {
|
||||
*pViewport = HostViewPort;
|
||||
EmuWarning("GetHostRenderTargetDimensions failed - GetViewport returns host viewport instead!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,8 @@ class EmuShared : public Mutex
|
|||
void SetUseAllCores(int* value) { Lock(); m_UseAllCores = *value; Unlock(); }
|
||||
void GetPatchCpuFrequency(int* value) { Lock(); *value = m_PatchCpuFrequeny; Unlock(); }
|
||||
void SetPatchCpuFrequency(int* value) { Lock(); m_PatchCpuFrequeny = *value; Unlock(); }
|
||||
void GetScaleViewport(int* value) { Lock(); *value = m_ScaleViewport; Unlock(); }
|
||||
void SetScaleViewport(int* value) { Lock(); m_ScaleViewport = *value; Unlock(); }
|
||||
|
||||
// ******************************************************************
|
||||
// * MSpF/Benchmark values Accessors
|
||||
|
@ -202,6 +204,7 @@ class EmuShared : public Mutex
|
|||
bool m_bMultiXbeFlag;
|
||||
bool m_bDebugging;
|
||||
int m_LedSequence[4];
|
||||
int m_ScaleViewport;
|
||||
};
|
||||
|
||||
// ******************************************************************
|
||||
|
|
Loading…
Reference in New Issue