Refactoring to enable future time scaling, coordinated clocks, etc.
This commit is contained in:
parent
05f2577fb7
commit
8244409501
|
@ -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" />
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(
|
||||||
×tamp_timer_, nullptr,
|
×tamp_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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue