Refactoring to enable future time scaling, coordinated clocks, etc.

This commit is contained in:
Ben Vanik 2015-05-26 22:20:46 -07:00
parent 05f2577fb7
commit 8244409501
19 changed files with 213 additions and 57 deletions

View File

@ -25,6 +25,7 @@
<ClCompile Include="src\xenia\apu\xaudio2\xaudio2_audio_driver.cc" /> <ClCompile Include="src\xenia\apu\xaudio2\xaudio2_audio_driver.cc" />
<ClCompile Include="src\xenia\apu\xaudio2\xaudio2_audio_system.cc" /> <ClCompile Include="src\xenia\apu\xaudio2\xaudio2_audio_system.cc" />
<ClCompile Include="src\xenia\base\arena.cc" /> <ClCompile Include="src\xenia\base\arena.cc" />
<ClCompile Include="src\xenia\base\clock.cc" />
<ClCompile Include="src\xenia\base\debugging_win.cc" /> <ClCompile Include="src\xenia\base\debugging_win.cc" />
<ClCompile Include="src\xenia\base\fs.cc" /> <ClCompile Include="src\xenia\base\fs.cc" />
<ClCompile Include="src\xenia\base\fs_win.cc" /> <ClCompile Include="src\xenia\base\fs_win.cc" />
@ -217,6 +218,7 @@
<ClInclude Include="src\xenia\base\assert.h" /> <ClInclude Include="src\xenia\base\assert.h" />
<ClInclude Include="src\xenia\base\atomic.h" /> <ClInclude Include="src\xenia\base\atomic.h" />
<ClInclude Include="src\xenia\base\byte_order.h" /> <ClInclude Include="src\xenia\base\byte_order.h" />
<ClInclude Include="src\xenia\base\clock.h" />
<ClInclude Include="src\xenia\base\debugging.h" /> <ClInclude Include="src\xenia\base\debugging.h" />
<ClInclude Include="src\xenia\base\delegate.h" /> <ClInclude Include="src\xenia\base\delegate.h" />
<ClInclude Include="src\xenia\base\fs.h" /> <ClInclude Include="src\xenia\base\fs.h" />

View File

@ -706,6 +706,9 @@
<ClCompile Include="src\xenia\apu\audio_decoder.cc"> <ClCompile Include="src\xenia\apu\audio_decoder.cc">
<Filter>src\xenia\apu</Filter> <Filter>src\xenia\apu</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\xenia\base\clock.cc">
<Filter>src\xenia\base</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="src\xenia\emulator.h"> <ClInclude Include="src\xenia\emulator.h">
@ -1362,6 +1365,9 @@
<ClInclude Include="src\xenia\base\mutex.h"> <ClInclude Include="src\xenia\base\mutex.h">
<Filter>src\xenia\base</Filter> <Filter>src\xenia\base</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\xenia\base\clock.h">
<Filter>src\xenia\base</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="src\xenia\cpu\backend\x64\x64_sequence.inl"> <None Include="src\xenia\cpu\backend\x64\x64_sequence.inl">

96
src/xenia/base/clock.cc Normal file
View File

@ -0,0 +1,96 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/base/clock.h"
#include "xenia/base/platform.h"
namespace xe {
double guest_time_scalar_ = 1.0;
uint64_t guest_tick_frequency_ = Clock::host_tick_frequency();
uint64_t guest_system_time_base_ = Clock::QueryHostSystemTime();
uint64_t Clock::host_tick_frequency() {
static LARGE_INTEGER frequency = {0};
if (!frequency.QuadPart) {
QueryPerformanceFrequency(&frequency);
}
return frequency.QuadPart;
}
uint64_t Clock::QueryHostTickCount() {
LARGE_INTEGER counter;
uint64_t time = 0;
if (QueryPerformanceCounter(&counter)) {
time = counter.QuadPart;
}
return time;
}
uint64_t Clock::QueryHostSystemTime() {
FILETIME t;
GetSystemTimeAsFileTime(&t);
return (uint64_t(t.dwHighDateTime) << 32) | t.dwLowDateTime;
}
uint32_t Clock::QueryHostUptimeMillis() { return ::GetTickCount(); }
double Clock::guest_time_scalar() { return guest_time_scalar_; }
void Clock::set_guest_time_scalar(double scalar) {
guest_time_scalar_ = scalar;
}
uint64_t Clock::guest_tick_frequency() { return guest_tick_frequency_; }
void Clock::set_guest_tick_frequency(uint64_t frequency) {
guest_tick_frequency_ = frequency;
}
uint64_t Clock::guest_system_time_base() { return guest_system_time_base_; }
void Clock::set_guest_system_time_base(uint64_t time_base) {
guest_system_time_base_ = time_base;
}
uint64_t Clock::QueryGuestTickCount() {
// TODO(benvanik): adjust.
return QueryHostTickCount();
}
uint64_t Clock::QueryGuestSystemTime() {
// TODO(benvanik): adjust.
return QueryHostSystemTime();
}
uint32_t Clock::QueryGuestUptimeMillis() {
// TODO(benvanik): adjust.
return QueryHostUptimeMillis();
}
uint32_t Clock::ScaleGuestDurationMillis(uint32_t guest_ms) {
// TODO(benvanik): adjust.
// if -1, return -1
// if 0, return 0
return guest_ms;
}
int64_t Clock::ScaleGuestDurationFileTime(int64_t guest_file_time) {
// TODO(benvanik): adjust.
// negative = relative times
// positive = absolute times
return guest_file_time;
}
void Clock::ScaleGuestDurationTimeval(long* tv_sec, long* tv_usec) {
// TODO(benvanik): adjust.
}
} // namespace xe

60
src/xenia/base/clock.h Normal file
View File

@ -0,0 +1,60 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_BASE_CLOCK_H_
#define XENIA_BASE_CLOCK_H_
#include <cstdint>
namespace xe {
class Clock {
public:
// Host ticks-per-second.
static uint64_t host_tick_frequency();
// Queries the current host tick count.
static uint64_t QueryHostTickCount();
// Host time, in FILETIME format.
static uint64_t QueryHostSystemTime();
// Queries the milliseconds since the host began.
static uint32_t QueryHostUptimeMillis();
// Guest time scalar.
static double guest_time_scalar();
// Sets the guest time scalar, adjusting tick and wall clock speed.
// Ex: 1x=normal, 2x=double speed, 1/2x=half speed.
static void set_guest_time_scalar(double scalar);
// Guest ticks-per-second.
static uint64_t guest_tick_frequency();
// Sets the guest ticks-per-second.
static void set_guest_tick_frequency(uint64_t frequency);
// Time based used for the guest system time.
static uint64_t guest_system_time_base();
// Sets the guest time base, used for computing the system time.
// By default this is the current system time.
static void set_guest_system_time_base(uint64_t time_base);
// Queries the current guest tick count, accounting for frequency adjustment
// and scaling.
static uint64_t QueryGuestTickCount();
// Queries the guest time, in FILETIME format, accounting for scaling.
static uint64_t QueryGuestSystemTime();
// Queries the milliseconds since the guest began, accounting for scaling.
static uint32_t QueryGuestUptimeMillis();
// Scales a time duration in milliseconds, from guest time.
static uint32_t ScaleGuestDurationMillis(uint32_t guest_ms);
// Scales a time duration in 100ns ticks like FILETIME, from guest time.
static int64_t ScaleGuestDurationFileTime(int64_t guest_file_time);
// Scales a time duration represented as a timeval, from guest time.
static void ScaleGuestDurationTimeval(long* tv_sec, long* tv_usec);
};
} // namespace xe
#endif // XENIA_BASE_CLOCK_H_

View File

@ -43,10 +43,6 @@ class Fence {
std::atomic<bool> signaled_; std::atomic<bool> signaled_;
}; };
// Gets the current high-performance tick count.
uint64_t ticks();
uint64_t ticks_per_second();
// TODO(benvanik): processor info API. // TODO(benvanik): processor info API.
// Gets a stable thread-specific ID, but may not be. Use for informative // Gets a stable thread-specific ID, but may not be. Use for informative

View File

@ -14,23 +14,6 @@
namespace xe { namespace xe {
namespace threading { namespace threading {
uint64_t ticks() {
LARGE_INTEGER counter;
uint64_t time = 0;
if (QueryPerformanceCounter(&counter)) {
time = counter.QuadPart;
}
return time;
}
uint64_t ticks_per_second() {
static LARGE_INTEGER freq = {0};
if (!freq.QuadPart) {
QueryPerformanceFrequency(&freq);
}
return freq.QuadPart;
}
uint32_t current_thread_id() { uint32_t current_thread_id() {
return static_cast<uint32_t>(GetCurrentThreadId()); return static_cast<uint32_t>(GetCurrentThreadId());
} }

View File

@ -25,6 +25,7 @@
#include "xenia/cpu/backend/x64/x64_sequences.h" #include "xenia/cpu/backend/x64/x64_sequences.h"
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/clock.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/threading.h" #include "xenia/base/threading.h"
#include "xenia/cpu/backend/x64/x64_emitter.h" #include "xenia/cpu/backend/x64/x64_emitter.h"
@ -1086,7 +1087,7 @@ EMITTER(LOAD_CLOCK, MATCH(I<OPCODE_LOAD_CLOCK, I64<>>)) {
e.mov(i.dest, e.rax); e.mov(i.dest, e.rax);
} }
static uint64_t LoadClock(void* raw_context) { static uint64_t LoadClock(void* raw_context) {
return xe::threading::ticks(); return Clock::QueryGuestTickCount();
} }
}; };
EMITTER_OPCODE_TABLE( EMITTER_OPCODE_TABLE(

View File

@ -9,8 +9,11 @@
#include "xenia/emulator.h" #include "xenia/emulator.h"
#include <gflags/gflags.h>
#include "xenia/apu/apu.h" #include "xenia/apu/apu.h"
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/clock.h"
#include "xenia/base/string.h" #include "xenia/base/string.h"
#include "xenia/cpu/cpu.h" #include "xenia/cpu/cpu.h"
#include "xenia/gpu/gpu.h" #include "xenia/gpu/gpu.h"
@ -22,6 +25,9 @@
#include "xenia/memory.h" #include "xenia/memory.h"
#include "xenia/ui/main_window.h" #include "xenia/ui/main_window.h"
DEFINE_double(time_scalar, 1.0,
"Scalar used to speed or slow time (1x, 2x, 1/2x, etc).");
namespace xe { namespace xe {
using namespace xe::apu; using namespace xe::apu;
@ -64,6 +70,16 @@ Emulator::~Emulator() {
X_STATUS Emulator::Setup() { X_STATUS Emulator::Setup() {
X_STATUS result = X_STATUS_UNSUCCESSFUL; X_STATUS result = X_STATUS_UNSUCCESSFUL;
// Initialize clock.
// 360 uses a 50MHz clock.
// Clock::set_guest_tick_frequency(50000000);
// We could reset this with save state data/constant value to help replays.
Clock::set_guest_system_time_base(Clock::QueryHostSystemTime());
// This can be adjusted dynamically, as well.
Clock::set_guest_time_scalar(FLAGS_time_scalar);
// Before we can set thread affinity we must enable the process to use all
// logical processors.
HANDLE process_handle = GetCurrentProcess(); HANDLE process_handle = GetCurrentProcess();
DWORD_PTR process_affinity_mask; DWORD_PTR process_affinity_mask;
DWORD_PTR system_affinity_mask; DWORD_PTR system_affinity_mask;

View File

@ -59,7 +59,6 @@ CommandProcessor::CommandProcessor(GL4GraphicsSystem* graphics_system)
trace_state_(TraceState::kDisabled), trace_state_(TraceState::kDisabled),
worker_running_(true), worker_running_(true),
swap_mode_(SwapMode::kNormal), swap_mode_(SwapMode::kNormal),
time_base_(0),
counter_(0), counter_(0),
primary_buffer_ptr_(0), primary_buffer_ptr_(0),
primary_buffer_size_(0), primary_buffer_size_(0),
@ -83,19 +82,10 @@ CommandProcessor::CommandProcessor(GL4GraphicsSystem* graphics_system)
draw_index_count_(0), draw_index_count_(0),
draw_batcher_(graphics_system_->register_file()), draw_batcher_(graphics_system_->register_file()),
scratch_buffer_(kScratchBufferCapacity, kScratchBufferAlignment) { scratch_buffer_(kScratchBufferCapacity, kScratchBufferAlignment) {
LARGE_INTEGER perf_counter;
QueryPerformanceCounter(&perf_counter);
time_base_ = perf_counter.QuadPart;
} }
CommandProcessor::~CommandProcessor() { CloseHandle(write_ptr_index_event_); } CommandProcessor::~CommandProcessor() { CloseHandle(write_ptr_index_event_); }
uint64_t CommandProcessor::QueryTime() {
LARGE_INTEGER perf_counter;
QueryPerformanceCounter(&perf_counter);
return perf_counter.QuadPart - time_base_;
}
bool CommandProcessor::Initialize(std::unique_ptr<GLContext> context) { bool CommandProcessor::Initialize(std::unique_ptr<GLContext> context) {
context_ = std::move(context); context_ = std::move(context);

View File

@ -62,7 +62,6 @@ class CommandProcessor {
typedef std::function<void(const SwapParameters& params)> SwapHandler; typedef std::function<void(const SwapParameters& params)> SwapHandler;
void set_swap_handler(SwapHandler fn) { swap_handler_ = fn; } void set_swap_handler(SwapHandler fn) { swap_handler_ = fn; }
uint64_t QueryTime();
uint32_t counter() const { return counter_; } uint32_t counter() const { return counter_; }
void increment_counter() { counter_++; } void increment_counter() { counter_++; }
@ -243,7 +242,6 @@ class CommandProcessor {
SwapMode swap_mode_; SwapMode swap_mode_;
uint64_t time_base_;
uint32_t counter_; uint32_t counter_;
uint32_t primary_buffer_ptr_; uint32_t primary_buffer_ptr_;

View File

@ -9,6 +9,7 @@
#include "xenia/gpu/gl4/gl4_graphics_system.h" #include "xenia/gpu/gl4/gl4_graphics_system.h"
#include "xenia/base/clock.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/threading.h" #include "xenia/base/threading.h"
#include "xenia/cpu/processor.h" #include "xenia/cpu/processor.h"
@ -86,11 +87,11 @@ X_STATUS GL4GraphicsSystem::Setup(cpu::Processor* processor,
kernel::object_ref<kernel::XHostThread>(new kernel::XHostThread( kernel::object_ref<kernel::XHostThread>(new kernel::XHostThread(
emulator()->kernel_state(), 128 * 1024, 0, [this]() { emulator()->kernel_state(), 128 * 1024, 0, [this]() {
uint64_t vsync_duration = FLAGS_vsync ? 16 : 1; uint64_t vsync_duration = FLAGS_vsync ? 16 : 1;
uint64_t last_frame_time = xe::threading::ticks(); uint64_t last_frame_time = Clock::QueryGuestTickCount();
while (worker_running_) { while (worker_running_) {
uint64_t current_time = xe::threading::ticks(); uint64_t current_time = Clock::QueryGuestTickCount();
uint64_t elapsed = (current_time - last_frame_time) / uint64_t elapsed = (current_time - last_frame_time) /
(xe::threading::ticks_per_second() / 1000); (Clock::guest_tick_frequency() / 1000);
if (elapsed >= vsync_duration) { if (elapsed >= vsync_duration) {
MarkVblank(); MarkVblank();
last_frame_time = current_time; last_frame_time = current_time;

View File

@ -11,6 +11,7 @@
#include "third_party/imgui/imgui.h" #include "third_party/imgui/imgui.h"
#include "xenia/base/clock.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/main.h" #include "xenia/base/main.h"
#include "xenia/base/mapped_memory.h" #include "xenia/base/mapped_memory.h"
@ -2272,10 +2273,10 @@ int trace_viewer_main(std::vector<std::wstring>& args) {
imgui_setup = true; imgui_setup = true;
} }
auto& io = ImGui::GetIO(); auto& io = ImGui::GetIO();
auto current_ticks = xe::threading::ticks(); auto current_ticks = Clock::QueryHostTickCount();
static uint64_t last_ticks = 0; static uint64_t last_ticks = 0;
io.DeltaTime = (current_ticks - last_ticks) / io.DeltaTime =
float(xe::threading::ticks_per_second()); (current_ticks - last_ticks) / float(Clock::host_tick_frequency());
last_ticks = current_ticks; last_ticks = current_ticks;
io.DisplaySize = io.DisplaySize =

View File

@ -11,6 +11,7 @@
#include <gflags/gflags.h> #include <gflags/gflags.h>
#include "xenia/base/clock.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/base/mutex.h" #include "xenia/base/mutex.h"
@ -236,10 +237,7 @@ X_STATUS XThread::Create() {
xe::store_and_swap<uint32_t>(p + 0x09C, 0xFDFFD7FF); xe::store_and_swap<uint32_t>(p + 0x09C, 0xFDFFD7FF);
xe::store_and_swap<uint32_t>( xe::store_and_swap<uint32_t>(
p + 0x0D0, thread_state_->stack_address() + thread_state_->stack_size()); p + 0x0D0, thread_state_->stack_address() + thread_state_->stack_size());
FILETIME t; xe::store_and_swap<uint64_t>(p + 0x130, Clock::QueryGuestSystemTime());
GetSystemTimeAsFileTime(&t);
xe::store_and_swap<uint64_t>(
p + 0x130, ((uint64_t)t.dwHighDateTime << 32) | t.dwLowDateTime);
xe::store_and_swap<uint32_t>(p + 0x144, thread_state_address_ + 0x144); xe::store_and_swap<uint32_t>(p + 0x144, thread_state_address_ + 0x144);
xe::store_and_swap<uint32_t>(p + 0x148, thread_state_address_ + 0x144); xe::store_and_swap<uint32_t>(p + 0x148, thread_state_address_ + 0x144);
xe::store_and_swap<uint32_t>(p + 0x14C, thread_id_); xe::store_and_swap<uint32_t>(p + 0x14C, thread_id_);
@ -621,6 +619,7 @@ X_STATUS XThread::Delay(uint32_t processor_mode, uint32_t alertable,
} else { } else {
timeout_ms = 0; timeout_ms = 0;
} }
timeout_ms = Clock::ScaleGuestDurationMillis(timeout_ms);
DWORD result = SleepEx(timeout_ms, alertable ? TRUE : FALSE); DWORD result = SleepEx(timeout_ms, alertable ? TRUE : FALSE);
switch (result) { switch (result) {
case 0: case 0:

View File

@ -9,6 +9,7 @@
#include "xenia/kernel/objects/xtimer.h" #include "xenia/kernel/objects/xtimer.h"
#include "xenia/base/clock.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/cpu/processor.h" #include "xenia/cpu/processor.h"
@ -49,6 +50,9 @@ X_STATUS XTimer::SetTimer(int64_t due_time, uint32_t period_ms,
current_routine_ = routine; current_routine_ = routine;
current_routine_arg_ = routine_arg; current_routine_arg_ = routine_arg;
due_time = Clock::ScaleGuestDurationFileTime(due_time);
period_ms = Clock::ScaleGuestDurationMillis(period_ms);
LARGE_INTEGER due_time_li; LARGE_INTEGER due_time_li;
due_time_li.QuadPart = due_time; due_time_li.QuadPart = due_time;
BOOL result = BOOL result =

View File

@ -10,6 +10,7 @@
#define _WINSOCK_DEPRECATED_NO_WARNINGS // inet_addr #define _WINSOCK_DEPRECATED_NO_WARNINGS // inet_addr
#include <winsock2.h> #include <winsock2.h>
#include "xenia/base/clock.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/kernel/kernel_state.h" #include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/util/shim_utils.h"
@ -373,6 +374,7 @@ SHIM_CALL NetDll_select_shim(PPCContext* ppc_state, KernelState* state) {
if (timeout_ptr) { if (timeout_ptr) {
timeout = {static_cast<long>(SHIM_MEM_32(timeout_ptr + 0)), timeout = {static_cast<long>(SHIM_MEM_32(timeout_ptr + 0)),
static_cast<long>(SHIM_MEM_32(timeout_ptr + 4))}; static_cast<long>(SHIM_MEM_32(timeout_ptr + 4))};
Clock::ScaleGuestDurationTimeval(&timeout.tv_sec, &timeout.tv_usec);
timeout_in = &timeout; timeout_in = &timeout;
} }
int ret = select(nfds, readfds_ptr ? &readfds : nullptr, int ret = select(nfds, readfds_ptr ? &readfds : nullptr,

View File

@ -11,6 +11,7 @@
#include <gflags/gflags.h> #include <gflags/gflags.h>
#include "xenia/base/clock.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/emulator.h" #include "xenia/emulator.h"
@ -133,13 +134,15 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
"xboxkrnl.exe", ordinals::KeTimeStampBundle, pKeTimeStampBundle); "xboxkrnl.exe", ordinals::KeTimeStampBundle, pKeTimeStampBundle);
xe::store_and_swap<uint64_t>(lpKeTimeStampBundle + 0, 0); xe::store_and_swap<uint64_t>(lpKeTimeStampBundle + 0, 0);
xe::store_and_swap<uint64_t>(lpKeTimeStampBundle + 8, 0); xe::store_and_swap<uint64_t>(lpKeTimeStampBundle + 8, 0);
xe::store_and_swap<uint32_t>(lpKeTimeStampBundle + 16, GetTickCount()); xe::store_and_swap<uint32_t>(lpKeTimeStampBundle + 16,
Clock::QueryGuestUptimeMillis());
xe::store_and_swap<uint32_t>(lpKeTimeStampBundle + 20, 0); xe::store_and_swap<uint32_t>(lpKeTimeStampBundle + 20, 0);
CreateTimerQueueTimer( CreateTimerQueueTimer(
&timestamp_timer_, nullptr, &timestamp_timer_, nullptr,
[](PVOID param, BOOLEAN timer_or_wait_fired) { [](PVOID param, BOOLEAN timer_or_wait_fired) {
auto timestamp_bundle = reinterpret_cast<uint8_t*>(param); auto timestamp_bundle = reinterpret_cast<uint8_t*>(param);
xe::store_and_swap<uint32_t>(timestamp_bundle + 16, GetTickCount()); xe::store_and_swap<uint32_t>(timestamp_bundle + 16,
Clock::QueryGuestUptimeMillis());
}, },
lpKeTimeStampBundle, 0, lpKeTimeStampBundle, 0,
1, // 1ms 1, // 1ms

View File

@ -8,6 +8,7 @@
*/ */
#include "xenia/base/atomic.h" #include "xenia/base/atomic.h"
#include "xenia/base/clock.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/mutex.h" #include "xenia/base/mutex.h"
#include "xenia/cpu/processor.h" #include "xenia/cpu/processor.h"
@ -312,13 +313,7 @@ SHIM_CALL KeQueryPerformanceFrequency_shim(PPCContext* ppc_state,
// XELOGD( // XELOGD(
// "KeQueryPerformanceFrequency()"); // "KeQueryPerformanceFrequency()");
// TODO(benvanik): return fixed 50000000? uint64_t result = Clock::guest_tick_frequency();
uint64_t result = 0;
LARGE_INTEGER frequency;
if (QueryPerformanceFrequency(&frequency)) {
result = frequency.QuadPart;
}
SHIM_SET_RETURN_64(result); SHIM_SET_RETURN_64(result);
} }
@ -351,9 +346,7 @@ SHIM_CALL KeQuerySystemTime_shim(PPCContext* ppc_state, KernelState* state) {
XELOGD("KeQuerySystemTime(%.8X)", time_ptr); XELOGD("KeQuerySystemTime(%.8X)", time_ptr);
FILETIME t; uint64_t time = Clock::QueryGuestSystemTime();
GetSystemTimeAsFileTime(&t);
uint64_t time = ((uint64_t)t.dwHighDateTime << 32) | t.dwLowDateTime;
if (time_ptr) { if (time_ptr) {
SHIM_SET_MEM_64(time_ptr, time); SHIM_SET_MEM_64(time_ptr, time);

View File

@ -9,6 +9,7 @@
#include "xenia/kernel/xobject.h" #include "xenia/kernel/xobject.h"
#include "xenia/base/clock.h"
#include "xenia/kernel/kernel_state.h" #include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/objects/xevent.h" #include "xenia/kernel/objects/xevent.h"
#include "xenia/kernel/objects/xmutant.h" #include "xenia/kernel/objects/xmutant.h"
@ -109,6 +110,7 @@ X_STATUS XObject::Wait(uint32_t wait_reason, uint32_t processor_mode,
} }
DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE; DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE;
timeout_ms = Clock::ScaleGuestDurationMillis(timeout_ms);
DWORD result = WaitForSingleObjectEx(wait_handle, timeout_ms, alertable); DWORD result = WaitForSingleObjectEx(wait_handle, timeout_ms, alertable);
switch (result) { switch (result) {
@ -131,6 +133,7 @@ X_STATUS XObject::SignalAndWait(XObject* signal_object, XObject* wait_object,
uint32_t wait_reason, uint32_t processor_mode, uint32_t wait_reason, uint32_t processor_mode,
uint32_t alertable, uint64_t* opt_timeout) { uint32_t alertable, uint64_t* opt_timeout) {
DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE; DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE;
timeout_ms = Clock::ScaleGuestDurationMillis(timeout_ms);
DWORD result = SignalObjectAndWait(signal_object->GetWaitHandle(), DWORD result = SignalObjectAndWait(signal_object->GetWaitHandle(),
wait_object->GetWaitHandle(), timeout_ms, wait_object->GetWaitHandle(), timeout_ms,
@ -150,6 +153,7 @@ X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects,
} }
DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE; DWORD timeout_ms = opt_timeout ? TimeoutTicksToMs(*opt_timeout) : INFINITE;
timeout_ms = Clock::ScaleGuestDurationMillis(timeout_ms);
DWORD result = WaitForMultipleObjectsEx( DWORD result = WaitForMultipleObjectsEx(
count, wait_handles, wait_type ? FALSE : TRUE, timeout_ms, alertable); count, wait_handles, wait_type ? FALSE : TRUE, timeout_ms, alertable);

View File

@ -14,6 +14,7 @@
#include <algorithm> #include <algorithm>
#include <mutex> #include <mutex>
#include "xenia/base/clock.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/base/threading.h" #include "xenia/base/threading.h"
@ -114,7 +115,7 @@ Memory::~Memory() {
int Memory::Initialize() { int Memory::Initialize() {
wchar_t file_name[256]; wchar_t file_name[256];
wsprintf(file_name, L"Local\\xenia_memory_%p", xe::threading::ticks()); wsprintf(file_name, L"Local\\xenia_memory_%p", Clock::QueryHostTickCount());
file_name_ = file_name; file_name_ = file_name;
// Create main page file-backed mapping. This is all reserved but // Create main page file-backed mapping. This is all reserved but