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
	
	 Mr-Wiseguy
						Mr-Wiseguy