mirror of
https://github.com/N64Recomp/N64ModernRuntime.git
synced 2025-10-30 08:02:29 +00:00
Implement osSetTime and move update screen to before VI update
This commit is contained in:
parent
257b5db9d6
commit
d34934aa7e
4 changed files with 33 additions and 9 deletions
|
|
@ -73,12 +73,21 @@ extern "C" void osGetCount_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||
ctx->r2 = osGetCount();
|
||||
}
|
||||
|
||||
extern "C" void osSetCount_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
osSetCount(ctx->r4);
|
||||
}
|
||||
|
||||
extern "C" void osGetTime_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
uint64_t total_count = osGetTime();
|
||||
ctx->r2 = (int32_t)(total_count >> 32);
|
||||
ctx->r3 = (int32_t)(total_count >> 0);
|
||||
}
|
||||
|
||||
extern "C" void osSetTime_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
uint64_t t = ((uint64_t)(ctx->r4) << 32) | ((ctx->r5) & 0xFFFFFFFFu);
|
||||
osSetTime(t);
|
||||
}
|
||||
|
||||
extern "C" void osSetTimer_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
uint64_t countdown = ((uint64_t)(ctx->r6) << 32) | ((ctx->r7) & 0xFFFFFFFFu);
|
||||
uint64_t interval = load_doubleword(rdram, ctx->r29, 0x10);
|
||||
|
|
|
|||
|
|
@ -290,7 +290,9 @@ void osViSetYScale(float scale);
|
|||
PTR(void) osViGetNextFramebuffer();
|
||||
PTR(void) osViGetCurrentFramebuffer();
|
||||
u32 osGetCount();
|
||||
void osSetCount(u32 count);
|
||||
OSTime osGetTime();
|
||||
void osSetTime(OSTime t);
|
||||
int osSetTimer(RDRAM_ARG PTR(OSTimer) timer, OSTime countdown, OSTime interval, PTR(OSMesgQueue) mq, OSMesg msg);
|
||||
int osStopTimer(RDRAM_ARG PTR(OSTimer) timer);
|
||||
u32 osVirtualToPhysical(PTR(void) addr);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ struct SpTaskAction {
|
|||
};
|
||||
|
||||
struct ScreenUpdateAction {
|
||||
ultramodern::renderer::ViRegs regs;
|
||||
};
|
||||
|
||||
struct UpdateConfigAction {
|
||||
|
|
@ -55,6 +56,7 @@ static struct {
|
|||
int field;
|
||||
ViState states[2];
|
||||
ultramodern::renderer::ViRegs regs;
|
||||
ultramodern::renderer::ViRegs update_screen_regs;
|
||||
|
||||
ViState* get_next_state() {
|
||||
return &states[cur_state ^ 1];
|
||||
|
|
@ -131,7 +133,7 @@ static struct {
|
|||
} events_context{};
|
||||
|
||||
ultramodern::renderer::ViRegs* ultramodern::renderer::get_vi_regs() {
|
||||
return &events_context.vi.regs;
|
||||
return &events_context.vi.update_screen_regs;
|
||||
}
|
||||
|
||||
extern "C" void osSetEventMesg(RDRAM_ARG OSEvent event_id, PTR(OSMesgQueue) mq_, OSMesg msg) {
|
||||
|
|
@ -198,8 +200,9 @@ void vi_thread_func() {
|
|||
next = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
ultramodern::sleep_until(next);
|
||||
auto time_now = ultramodern::time_since_start();
|
||||
// Calculate how many VIs have passed
|
||||
uint64_t new_total_vis = (ultramodern::time_since_start() * (60 * ultramodern::get_speed_multiplier()) / 1000ms) + 1;
|
||||
uint64_t new_total_vis = (time_now * (60 * ultramodern::get_speed_multiplier()) / 1000ms) + 1;
|
||||
if (new_total_vis > total_vis + 1) {
|
||||
//printf("Skipped % " PRId64 " frames in VI interupt thread!\n", new_total_vis - total_vis - 1);
|
||||
}
|
||||
|
|
@ -212,12 +215,13 @@ void vi_thread_func() {
|
|||
odd = !odd;
|
||||
}
|
||||
|
||||
// Queue a screen update for the graphics thread with the current VI register state.
|
||||
// Doing this before the VI update is equivalent to updating the screen after the previous frame's scanout finished.
|
||||
events_context.action_queue.enqueue(ScreenUpdateAction{ events_context.vi.regs });
|
||||
|
||||
// Update VI registers and swap VI modes.
|
||||
events_context.vi.update_vi();
|
||||
|
||||
// Queue a screen update for the graphics thread.
|
||||
events_context.action_queue.enqueue(ScreenUpdateAction{ });
|
||||
|
||||
// If the game has started, handle sending VI and AI events.
|
||||
if (ultramodern::is_game_started()) {
|
||||
remaining_retraces--;
|
||||
|
|
@ -226,13 +230,12 @@ void vi_thread_func() {
|
|||
std::lock_guard lock{ events_context.message_mutex };
|
||||
ViState* cur_state = events_context.vi.get_cur_state();
|
||||
if (remaining_retraces == 0) {
|
||||
remaining_retraces = cur_state->retrace_count;
|
||||
|
||||
if (cur_state->mq != NULLPTR) {
|
||||
if (osSendMesg(PASS_RDRAM cur_state->mq, cur_state->msg, OS_MESG_NOBLOCK) == -1) {
|
||||
//printf("Game skipped a VI frame!\n");
|
||||
}
|
||||
}
|
||||
remaining_retraces = cur_state->retrace_count;
|
||||
}
|
||||
if (events_context.ai.mq != NULLPTR) {
|
||||
if (osSendMesg(PASS_RDRAM events_context.ai.mq, events_context.ai.msg, OS_MESG_NOBLOCK) == -1) {
|
||||
|
|
@ -370,7 +373,7 @@ void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_re
|
|||
// printf("Renderer ProcessDList time: %d us\n", static_cast<u32>(std::chrono::duration_cast<std::chrono::microseconds>(renderer_end - renderer_start).count()));
|
||||
}
|
||||
else if (const auto* screen_update_action = std::get_if<ScreenUpdateAction>(&action)) {
|
||||
(void)screen_update_action;
|
||||
events_context.vi.update_screen_regs = screen_update_action->regs;
|
||||
renderer_context->update_screen();
|
||||
display_refresh_rate = renderer_context->get_display_framerate();
|
||||
resolution_scale = renderer_context->get_resolution_scale();
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
// Start time for the program
|
||||
static std::chrono::high_resolution_clock::time_point start_time = std::chrono::high_resolution_clock::now();
|
||||
// Offset of the duration since program start used to calculate the value for osGetTime.
|
||||
static int64_t ostime_offset = 0;
|
||||
// Game speed multiplier (1 means no speedup)
|
||||
constexpr uint32_t speed_multiplier = 1;
|
||||
// N64 CPU counter ticks per millisecond
|
||||
|
|
@ -162,12 +164,20 @@ extern "C" u32 osGetCount() {
|
|||
return (uint32_t)total_count;
|
||||
}
|
||||
|
||||
extern "C" void osSetCount(u32 count) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
extern "C" OSTime osGetTime() {
|
||||
uint64_t total_count = time_now();
|
||||
uint64_t total_count = time_now() - ostime_offset;
|
||||
|
||||
return total_count;
|
||||
}
|
||||
|
||||
extern "C" void osSetTime(OSTime t) {
|
||||
ostime_offset = time_now() - t;
|
||||
}
|
||||
|
||||
extern "C" int osSetTimer(RDRAM_ARG PTR(OSTimer) t_, OSTime countdown, OSTime interval, PTR(OSMesgQueue) mq, OSMesg msg) {
|
||||
OSTimer* t = TO_PTR(OSTimer, t_);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue