mirror of https://github.com/snes9xgit/snes9x.git
win32: Move frame throttle into drivers for precision.
This commit is contained in:
parent
309f9e650d
commit
803125ffe9
|
@ -63,10 +63,10 @@ void ShaderChain::construct_buffer_objects()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto write_size = [&location](float width, float height) {
|
auto write_size = [&location](int width, int height) {
|
||||||
std::array<float, 4> size;
|
std::array<float, 4> size;
|
||||||
size[0] = width;
|
size[0] = (float)width;
|
||||||
size[1] = height;
|
size[1] = (float)height;
|
||||||
size[2] = 1.0f / size[0];
|
size[2] = 1.0f / size[0];
|
||||||
size[3] = 1.0f / size[1];
|
size[3] = 1.0f / size[1];
|
||||||
memcpy(location, size.data(), sizeof(float) * 4);
|
memcpy(location, size.data(), sizeof(float) * 4);
|
||||||
|
@ -104,7 +104,7 @@ void ShaderChain::construct_buffer_objects()
|
||||||
if (uniform.specifier < (int)lookup_textures.size())
|
if (uniform.specifier < (int)lookup_textures.size())
|
||||||
write_size(lookup_textures[uniform.specifier]->image_width, lookup_textures[uniform.specifier]->image_height);
|
write_size(lookup_textures[uniform.specifier]->image_width, lookup_textures[uniform.specifier]->image_height);
|
||||||
else
|
else
|
||||||
write_size(1.0f, 1.0f);
|
write_size(1, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SlangShader::Uniform::MVP:
|
case SlangShader::Uniform::MVP:
|
||||||
|
@ -389,16 +389,18 @@ void ShaderChain::update_descriptor_set(vk::CommandBuffer cmd, int pipe_num, int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderChain::do_frame(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
bool ShaderChain::do_frame(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
||||||
{
|
{
|
||||||
do_frame_without_swap(data, width, height, stride, format, viewport_x, viewport_y, viewport_width, viewport_height);
|
if (!do_frame_without_swap(data, width, height, stride, format, viewport_x, viewport_y, viewport_width, viewport_height))
|
||||||
|
return false;
|
||||||
context->swapchain->swap();
|
context->swapchain->swap();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderChain::do_frame_without_swap(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
bool ShaderChain::do_frame_without_swap(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
||||||
{
|
{
|
||||||
if (!context->swapchain->begin_frame())
|
if (!context->swapchain->begin_frame())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
current_frame_index = context->swapchain->get_current_frame();
|
current_frame_index = context->swapchain->get_current_frame();
|
||||||
|
|
||||||
|
@ -518,6 +520,7 @@ void ShaderChain::do_frame_without_swap(uint8_t *data, int width, int height, in
|
||||||
|
|
||||||
last_frame_index = current_frame_index;
|
last_frame_index = current_frame_index;
|
||||||
frame_count++;
|
frame_count++;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderChain::upload_original(vk::CommandBuffer cmd, uint8_t *data, int width, int height, int stride, vk::Format format)
|
void ShaderChain::upload_original(vk::CommandBuffer cmd, uint8_t *data, int width, int height, int stride, vk::Format format)
|
||||||
|
|
|
@ -19,8 +19,8 @@ class ShaderChain
|
||||||
bool load_shader_preset(std::string filename);
|
bool load_shader_preset(std::string filename);
|
||||||
void update_and_propagate_sizes(int original_width_, int original_height_, int viewport_width_, int viewport_height_);
|
void update_and_propagate_sizes(int original_width_, int original_height_, int viewport_width_, int viewport_height_);
|
||||||
bool load_lookup_textures();
|
bool load_lookup_textures();
|
||||||
void do_frame(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
bool do_frame(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
||||||
void do_frame_without_swap(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
bool do_frame_without_swap(uint8_t *data, int width, int height, int stride, vk::Format format, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
||||||
void upload_original(uint8_t *data, int width, int height, int stride, vk::Format format);
|
void upload_original(uint8_t *data, int width, int height, int stride, vk::Format format);
|
||||||
void upload_original(vk::CommandBuffer cmd, uint8_t *data, int width, int height, int stride, vk::Format format);
|
void upload_original(vk::CommandBuffer cmd, uint8_t *data, int width, int height, int stride, vk::Format format);
|
||||||
void construct_buffer_objects();
|
void construct_buffer_objects();
|
||||||
|
|
|
@ -215,13 +215,13 @@ void SimpleOutput::set_filter(bool on)
|
||||||
filter = on;
|
filter = on;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleOutput::do_frame_without_swap(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
bool SimpleOutput::do_frame_without_swap(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
||||||
{
|
{
|
||||||
if (!context)
|
if (!context)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
if (!swapchain->begin_frame())
|
if (!swapchain->begin_frame())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
auto &tex = textures[swapchain->get_current_frame()];
|
auto &tex = textures[swapchain->get_current_frame()];
|
||||||
auto &cmd = swapchain->get_cmd();
|
auto &cmd = swapchain->get_cmd();
|
||||||
|
@ -253,12 +253,16 @@ void SimpleOutput::do_frame_without_swap(uint8_t *buffer, int width, int height,
|
||||||
|
|
||||||
swapchain->end_render_pass();
|
swapchain->end_render_pass();
|
||||||
swapchain->end_frame_without_swap();
|
swapchain->end_frame_without_swap();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleOutput::do_frame(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
bool SimpleOutput::do_frame(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height)
|
||||||
{
|
{
|
||||||
do_frame_without_swap(buffer, width, height, byte_stride, viewport_x, viewport_y, viewport_width, viewport_height);
|
if (!do_frame_without_swap(buffer, width, height, byte_stride, viewport_x, viewport_y, viewport_width, viewport_height))
|
||||||
|
return false;
|
||||||
swapchain->swap();
|
swapchain->swap();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
|
@ -10,8 +10,8 @@ class SimpleOutput
|
||||||
public:
|
public:
|
||||||
SimpleOutput(Vulkan::Context *context, vk::Format format);
|
SimpleOutput(Vulkan::Context *context, vk::Format format);
|
||||||
~SimpleOutput();
|
~SimpleOutput();
|
||||||
void do_frame(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
bool do_frame(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
||||||
void do_frame_without_swap(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
bool do_frame_without_swap(uint8_t *buffer, int width, int height, int byte_stride, int viewport_x, int viewport_y, int viewport_width, int viewport_height);
|
||||||
void set_filter(bool on);
|
void set_filter(bool on);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -199,14 +199,14 @@ bool Swapchain::begin_frame()
|
||||||
|
|
||||||
auto &frame = frames[current_frame];
|
auto &frame = frames[current_frame];
|
||||||
|
|
||||||
auto result = device.waitForFences(frame.fence.get(), true, 33000000);
|
auto result = device.waitForFences(frame.fence.get(), true, UINT64_MAX);
|
||||||
if (result != vk::Result::eSuccess)
|
if (result != vk::Result::eSuccess)
|
||||||
{
|
{
|
||||||
printf("Failed fence\n");
|
printf("Failed fence\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result_value = device.acquireNextImageKHR(swapchain_object.get(), 33000000, frame.acquire.get());
|
auto result_value = device.acquireNextImageKHR(swapchain_object.get(), UINT64_MAX, frame.acquire.get());
|
||||||
if (result_value.result == vk::Result::eErrorOutOfDateKHR ||
|
if (result_value.result == vk::Result::eErrorOutOfDateKHR ||
|
||||||
result_value.result == vk::Result::eSuboptimalKHR)
|
result_value.result == vk::Result::eSuboptimalKHR)
|
||||||
{
|
{
|
||||||
|
@ -217,7 +217,7 @@ bool Swapchain::begin_frame()
|
||||||
|
|
||||||
if (result_value.result != vk::Result::eSuccess)
|
if (result_value.result != vk::Result::eSuccess)
|
||||||
{
|
{
|
||||||
printf("Timeout waiting for frame. Running too slow.\n");
|
printf("Unable to acquire swapchain image: %s\n", vk::to_string(result_value.result).c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -334,6 +334,7 @@ void CDirect3D::Render(SSurface Src)
|
||||||
pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2);
|
pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2);
|
||||||
pDevice->EndScene();
|
pDevice->EndScene();
|
||||||
|
|
||||||
|
WinThrottleFramerate();
|
||||||
pDevice->Present(NULL, NULL, NULL, NULL);
|
pDevice->Present(NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (GUI.ReduceInputLag)
|
if (GUI.ReduceInputLag)
|
||||||
|
@ -569,7 +570,7 @@ bool CDirect3D::ResetDevice()
|
||||||
pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
|
pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
|
||||||
|
|
||||||
pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
|
pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
|
||||||
|
|
||||||
//recreate the surface
|
//recreate the surface
|
||||||
CreateDrawSurface();
|
CreateDrawSurface();
|
||||||
|
|
||||||
|
|
|
@ -369,6 +369,9 @@ void COpenGL::Render(SSurface Src)
|
||||||
}
|
}
|
||||||
|
|
||||||
glFlush();
|
glFlush();
|
||||||
|
|
||||||
|
WinThrottleFramerate();
|
||||||
|
|
||||||
SwapBuffers(hDC);
|
SwapBuffers(hDC);
|
||||||
if (GUI.ReduceInputLag)
|
if (GUI.ReduceInputLag)
|
||||||
glFinish();
|
glFinish();
|
||||||
|
|
|
@ -61,9 +61,6 @@ void CVulkan::Render(SSurface Src)
|
||||||
if (!context)
|
if (!context)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (GUI.ReduceInputLag)
|
|
||||||
context->wait_idle();
|
|
||||||
|
|
||||||
SSurface Dst{};
|
SSurface Dst{};
|
||||||
|
|
||||||
RECT dstRect = GetFilterOutputSize(Src);
|
RECT dstRect = GetFilterOutputSize(Src);
|
||||||
|
@ -87,14 +84,27 @@ void CVulkan::Render(SSurface Src)
|
||||||
//Get maximum rect respecting AR setting
|
//Get maximum rect respecting AR setting
|
||||||
displayRect = CalculateDisplayRect(Dst.Width, Dst.Height, windowSize.right, windowSize.bottom);
|
displayRect = CalculateDisplayRect(Dst.Width, Dst.Height, windowSize.right, windowSize.bottom);
|
||||||
|
|
||||||
|
bool result;
|
||||||
|
|
||||||
if (shaderchain)
|
if (shaderchain)
|
||||||
{
|
{
|
||||||
shaderchain->do_frame(Dst.Surface, Dst.Width, Dst.Height, Dst.Pitch, vk::Format::eR5G6B5UnormPack16, displayRect.left, displayRect.top, displayRect.right - displayRect.left, displayRect.bottom - displayRect.top);
|
result = shaderchain->do_frame_without_swap(Dst.Surface, Dst.Width, Dst.Height, Dst.Pitch, vk::Format::eR5G6B5UnormPack16, displayRect.left, displayRect.top, displayRect.right - displayRect.left, displayRect.bottom - displayRect.top);
|
||||||
return;
|
}
|
||||||
|
else if (simple_output)
|
||||||
|
{
|
||||||
|
simple_output->set_filter(Settings.BilinearFilter);
|
||||||
|
result = simple_output->do_frame_without_swap(Dst.Surface, Dst.Width, Dst.Height, Dst.Pitch, displayRect.left, displayRect.top, displayRect.right - displayRect.left, displayRect.bottom - displayRect.top);
|
||||||
}
|
}
|
||||||
|
|
||||||
simple_output->set_filter(Settings.BilinearFilter);
|
WinThrottleFramerate();
|
||||||
simple_output->do_frame(Dst.Surface, Dst.Width, Dst.Height, Dst.Pitch, displayRect.left, displayRect.top, displayRect.right - displayRect.left, displayRect.bottom - displayRect.top);
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
context->swapchain->swap();
|
||||||
|
|
||||||
|
if (GUI.ReduceInputLag)
|
||||||
|
context->wait_idle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CVulkan::ChangeRenderSize(unsigned int newWidth, unsigned int newHeight)
|
bool CVulkan::ChangeRenderSize(unsigned int newWidth, unsigned int newHeight)
|
||||||
|
|
|
@ -449,7 +449,6 @@
|
||||||
<ClInclude Include="..\vulkan\vulkan_slang_pipeline.hpp" />
|
<ClInclude Include="..\vulkan\vulkan_slang_pipeline.hpp" />
|
||||||
<ClInclude Include="..\vulkan\vulkan_swapchain.hpp" />
|
<ClInclude Include="..\vulkan\vulkan_swapchain.hpp" />
|
||||||
<ClInclude Include="..\vulkan\vulkan_texture.hpp" />
|
<ClInclude Include="..\vulkan\vulkan_texture.hpp" />
|
||||||
<ClInclude Include="..\vulkan\std_chrono_throttle.hpp" />
|
|
||||||
<ClInclude Include="AVIOutput.h" />
|
<ClInclude Include="AVIOutput.h" />
|
||||||
<ClInclude Include="CCGShader.h" />
|
<ClInclude Include="CCGShader.h" />
|
||||||
<ClInclude Include="CD3DCG.h" />
|
<ClInclude Include="CD3DCG.h" />
|
||||||
|
@ -613,7 +612,6 @@
|
||||||
<ClCompile Include="..\vulkan\vulkan_slang_pipeline.cpp" />
|
<ClCompile Include="..\vulkan\vulkan_slang_pipeline.cpp" />
|
||||||
<ClCompile Include="..\vulkan\vulkan_swapchain.cpp" />
|
<ClCompile Include="..\vulkan\vulkan_swapchain.cpp" />
|
||||||
<ClCompile Include="..\vulkan\vulkan_texture.cpp" />
|
<ClCompile Include="..\vulkan\vulkan_texture.cpp" />
|
||||||
<ClCompile Include="..\vulkan\std_chrono_throttle.cpp" />
|
|
||||||
<ClCompile Include="AVIOutput.cpp" />
|
<ClCompile Include="AVIOutput.cpp" />
|
||||||
<ClCompile Include="CCGShader.cpp" />
|
<ClCompile Include="CCGShader.cpp" />
|
||||||
<ClCompile Include="CD3DCG.cpp" />
|
<ClCompile Include="CD3DCG.cpp" />
|
||||||
|
@ -690,4 +688,4 @@
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -675,6 +675,49 @@ int WinGetAutomaticInputRate(void)
|
||||||
return (int)newInputRate;
|
return (int)newInputRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WinThrottleFramerate()
|
||||||
|
{
|
||||||
|
static HANDLE throttle_timer = nullptr;
|
||||||
|
static int64_t PCBase, PCFrameTime, PCFrameTimeNTSC, PCFrameTimePAL, PCStart, PCEnd;
|
||||||
|
|
||||||
|
if (Settings.SkipFrames != AUTO_FRAMERATE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!throttle_timer)
|
||||||
|
{
|
||||||
|
QueryPerformanceFrequency((LARGE_INTEGER *)&PCBase);
|
||||||
|
|
||||||
|
PCFrameTimeNTSC = (int64_t)(PCBase / NTSC_PROGRESSIVE_FRAME_RATE);
|
||||||
|
PCFrameTimePAL = (int64_t)(PCBase / PAL_PROGRESSIVE_FRAME_RATE);
|
||||||
|
|
||||||
|
throttle_timer = CreateWaitableTimer(NULL, true, NULL);
|
||||||
|
QueryPerformanceCounter((LARGE_INTEGER *)&PCStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Settings.PAL)
|
||||||
|
PCFrameTime = PCBase / PAL_PROGRESSIVE_FRAME_RATE;
|
||||||
|
else
|
||||||
|
PCFrameTime = PCBase / NTSC_PROGRESSIVE_FRAME_RATE;
|
||||||
|
|
||||||
|
QueryPerformanceCounter((LARGE_INTEGER *)&PCEnd);
|
||||||
|
int64_t time_left_us = ((PCFrameTime - (PCEnd - PCStart)) * 1000000) / PCBase;
|
||||||
|
|
||||||
|
int64_t PCFrameTime_us = (int64_t)(PCFrameTime * 1000000.0 / PCBase);
|
||||||
|
if (time_left_us < -PCFrameTime_us / 10)
|
||||||
|
{
|
||||||
|
QueryPerformanceCounter((LARGE_INTEGER *)&PCStart);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (time_left_us > 0)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER li;
|
||||||
|
li.QuadPart = -time_left_us * 10;
|
||||||
|
SetWaitableTimer(throttle_timer, &li, 0, NULL, NULL, false);
|
||||||
|
WaitForSingleObject(throttle_timer, INFINITE);
|
||||||
|
}
|
||||||
|
PCStart += PCFrameTime;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<GLSLParam> *WinGetShaderParameters()
|
std::vector<GLSLParam> *WinGetShaderParameters()
|
||||||
{
|
{
|
||||||
if (GUI.outputMethod == OPENGL)
|
if (GUI.outputMethod == OPENGL)
|
||||||
|
|
|
@ -42,6 +42,7 @@ char *ReadShaderFileContents(const TCHAR *filename);
|
||||||
void ReduceToPath(TCHAR *filename);
|
void ReduceToPath(TCHAR *filename);
|
||||||
double WinGetRefreshRate();
|
double WinGetRefreshRate();
|
||||||
int WinGetAutomaticInputRate();
|
int WinGetAutomaticInputRate();
|
||||||
|
void WinThrottleFramerate();
|
||||||
std::vector<GLSLParam> *WinGetShaderParameters();
|
std::vector<GLSLParam> *WinGetShaderParameters();
|
||||||
std::function<void(const char*)> WinGetShaderSaveFunction();
|
std::function<void(const char*)> WinGetShaderSaveFunction();
|
||||||
|
|
||||||
|
|
|
@ -2802,35 +2802,6 @@ VOID CALLBACK HotkeyTimer( UINT idEvent, UINT uMsg, DWORD dwUser, DWORD dw1, DWO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ThrottleTimer()
|
|
||||||
{
|
|
||||||
bool run_frame = false;
|
|
||||||
do_frame_adjust = false;
|
|
||||||
QueryPerformanceCounter((LARGE_INTEGER*)&PCEnd);
|
|
||||||
|
|
||||||
if (Settings.TurboMode || Settings.FrameAdvance || Settings.SkipFrames != AUTO_FRAMERATE
|
|
||||||
#ifdef NETPLAY_SUPPORT
|
|
||||||
|| Settings.NetPlay
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PCStart = PCEnd;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((PCEnd - PCStart) >= PCFrameTime)
|
|
||||||
{
|
|
||||||
if ((PCEnd - PCStart) >= (PCFrameTime * 2))
|
|
||||||
do_frame_adjust = true;
|
|
||||||
|
|
||||||
run_frame = true;
|
|
||||||
|
|
||||||
PCStart += PCFrameTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
return run_frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void EnsureInputDisplayUpdated()
|
static void EnsureInputDisplayUpdated()
|
||||||
{
|
{
|
||||||
if(GUI.FrameAdvanceJustPressed==1 && Settings.Paused && Settings.DisplayPressedKeys==2 && GUI.ControllerOption != SNES_JOYPAD && GUI.ControllerOption != SNES_MULTIPLAYER5 && GUI.ControllerOption != SNES_MULTIPLAYER8)
|
if(GUI.FrameAdvanceJustPressed==1 && Settings.Paused && Settings.DisplayPressedKeys==2 && GUI.ControllerOption != SNES_JOYPAD && GUI.ControllerOption != SNES_MULTIPLAYER5 && GUI.ControllerOption != SNES_MULTIPLAYER8)
|
||||||
|
@ -3369,8 +3340,6 @@ int WINAPI WinMain(
|
||||||
|
|
||||||
MSG msg;
|
MSG msg;
|
||||||
|
|
||||||
HANDLE throttle_timer = CreateWaitableTimer(NULL, true, NULL);
|
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
EnsureInputDisplayUpdated();
|
EnsureInputDisplayUpdated();
|
||||||
|
@ -3443,43 +3412,32 @@ int WINAPI WinMain(
|
||||||
if(GUI.FrameAdvanceJustPressed)
|
if(GUI.FrameAdvanceJustPressed)
|
||||||
GUI.FrameAdvanceJustPressed--;
|
GUI.FrameAdvanceJustPressed--;
|
||||||
|
|
||||||
if(ThrottleTimer())
|
ProcessInput();
|
||||||
{
|
|
||||||
ProcessInput();
|
|
||||||
|
|
||||||
if(GUI.rewindBufferSize
|
if (GUI.rewindBufferSize
|
||||||
#ifdef NETPLAY_SUPPORT
|
#ifdef NETPLAY_SUPPORT
|
||||||
&&!Settings.NetPlay
|
&& !Settings.NetPlay
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
if(Settings.Rewinding) {
|
if (Settings.Rewinding) {
|
||||||
Settings.Rewinding = stateMan.pop();
|
Settings.Rewinding = stateMan.pop();
|
||||||
} else {
|
}
|
||||||
if(IPPU.TotalEmulatedFrames % GUI.rewindGranularity == 0)
|
else {
|
||||||
stateMan.push();
|
if (IPPU.TotalEmulatedFrames % GUI.rewindGranularity == 0)
|
||||||
}
|
stateMan.push();
|
||||||
}
|
|
||||||
|
|
||||||
S9xMainLoop();
|
|
||||||
GUI.FrameCount++;
|
|
||||||
if (GUI.CursorTimer)
|
|
||||||
{
|
|
||||||
if (--GUI.CursorTimer == 0)
|
|
||||||
{
|
|
||||||
if (GUI.ControllerOption != SNES_SUPERSCOPE && GUI.ControllerOption != SNES_JUSTIFIER && GUI.ControllerOption != SNES_JUSTIFIER_2 && GUI.ControllerOption != SNES_MACSRIFLE)
|
|
||||||
SetCursor(NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
auto time_left = ((PCFrameTime - (PCEnd - PCStart)) * 100000 / PCBase);
|
|
||||||
LARGE_INTEGER li;
|
|
||||||
li.QuadPart = -time_left;
|
|
||||||
SetWaitableTimer(throttle_timer, &li, 0, NULL, NULL, false);
|
|
||||||
WaitForSingleObject(throttle_timer, INFINITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
S9xMainLoop();
|
||||||
|
GUI.FrameCount++;
|
||||||
|
if (GUI.CursorTimer)
|
||||||
|
{
|
||||||
|
if (--GUI.CursorTimer == 0)
|
||||||
|
{
|
||||||
|
if (GUI.ControllerOption != SNES_SUPERSCOPE && GUI.ControllerOption != SNES_JUSTIFIER && GUI.ControllerOption != SNES_JUSTIFIER_2 && GUI.ControllerOption != SNES_MACSRIFLE)
|
||||||
|
SetCursor(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
#ifdef NETPLAY_SUPPORT
|
#ifdef NETPLAY_SUPPORT
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue