Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions librecomp/src/flash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ extern "C" void osFlashWriteBuffer_recomp(uint8_t * rdram, recomp_context * ctx)
}

// Send the message indicating write completion
osSendMesg(PASS_RDRAM mq, 0, OS_MESG_NOBLOCK);
ultramodern::enqueue_external_message(mq, 0, false, true);

ctx->r2 = 0;
}
Expand Down Expand Up @@ -193,7 +193,7 @@ extern "C" void osFlashReadArray_recomp(uint8_t * rdram, recomp_context * ctx) {
save_read(PASS_RDRAM dramAddr, offset, count);

// Send the message indicating read completion
osSendMesg(PASS_RDRAM mq, 0, OS_MESG_NOBLOCK);
ultramodern::enqueue_external_message(mq, 0, false, true);

ctx->r2 = 0;
}
Expand Down
6 changes: 3 additions & 3 deletions librecomp/src/pi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ void do_dma(RDRAM_ARG PTR(OSMesgQueue) mq, gpr rdram_address, uint32_t physical_
recomp::do_rom_read(rdram, rdram_address, physical_addr, size);

// Send a message to the mq to indicate that the transfer completed
osSendMesg(rdram, mq, 0, OS_MESG_NOBLOCK);
ultramodern::enqueue_external_message(mq, 0, false, true);
} else if (physical_addr >= recomp::sram_base) {
if (!recomp::sram_allowed()) {
ultramodern::error_handling::message_box("Attempted to use SRAM saving with other save type");
Expand All @@ -285,7 +285,7 @@ void do_dma(RDRAM_ARG PTR(OSMesgQueue) mq, gpr rdram_address, uint32_t physical_
save_read(rdram, rdram_address, physical_addr - recomp::sram_base, size);

// Send a message to the mq to indicate that the transfer completed
osSendMesg(rdram, mq, 0, OS_MESG_NOBLOCK);
ultramodern::enqueue_external_message(mq, 0, false, true);
} else {
fprintf(stderr, "[WARN] PI DMA read from unknown region, phys address 0x%08X\n", physical_addr);
}
Expand All @@ -302,7 +302,7 @@ void do_dma(RDRAM_ARG PTR(OSMesgQueue) mq, gpr rdram_address, uint32_t physical_
save_write(rdram, rdram_address, physical_addr - recomp::sram_base, size);

// Send a message to the mq to indicate that the transfer completed
osSendMesg(rdram, mq, 0, OS_MESG_NOBLOCK);
ultramodern::enqueue_external_message(mq, 0, false, true);
} else {
fprintf(stderr, "[WARN] PI DMA write to unknown region, phys address 0x%08X\n", physical_addr);
}
Expand Down
3 changes: 2 additions & 1 deletion ultramodern/include/ultramodern/ultramodern.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ bool thread_queue_empty(RDRAM_ARG PTR(PTR(OSThread)) queue);
PTR(OSThread) thread_queue_peek(RDRAM_ARG PTR(PTR(OSThread)) queue);

// Message queues.
void enqueue_external_message(PTR(OSMesgQueue) mq, OSMesg msg, bool jam, bool requeue_if_blocked);
void wait_for_external_message(RDRAM_ARG1);
void wait_for_external_message_timed(RDRAM_ARG1, u32 millis);

Expand All @@ -77,7 +78,7 @@ PTR(OSThread) this_thread();
void set_main_thread();
bool is_game_thread();
void submit_rsp_task(RDRAM_ARG PTR(OSTask) task);
void send_si_message(RDRAM_ARG1);
void send_si_message();
uint32_t get_speed_multiplier();

// Time
Expand Down
20 changes: 9 additions & 11 deletions ultramodern/src/events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,21 +226,19 @@ void vi_thread_func() {
if (ultramodern::is_game_started()) {
remaining_retraces--;

uint8_t* rdram = events_context.rdram;
std::lock_guard lock{ events_context.message_mutex };
ViState* cur_state = events_context.vi.get_cur_state();
if (remaining_retraces == 0) {
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");
}
// Send a message to the VI queue, and do not set it to be requeued if the queue was full.
// The worst case scenario is that the game misses a VI message and has to wait a little longer for the next.
ultramodern::enqueue_external_message(cur_state->mq, cur_state->msg, false, false);
}
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) {
//printf("Game skipped a AI frame!\n");
}
// Send a message to the VI queue, and do not set it to be requeued if the queue was full for the same reason as the VI message above.
ultramodern::enqueue_external_message(events_context.ai.mq, events_context.ai.msg, false, false);
}
}

Expand All @@ -253,13 +251,13 @@ void vi_thread_func() {
void sp_complete() {
uint8_t* rdram = events_context.rdram;
std::lock_guard lock{ events_context.message_mutex };
osSendMesg(PASS_RDRAM events_context.sp.mq, events_context.sp.msg, OS_MESG_NOBLOCK);
ultramodern::enqueue_external_message(events_context.sp.mq, events_context.sp.msg, false, true);
}

void dp_complete() {
uint8_t* rdram = events_context.rdram;
std::lock_guard lock{ events_context.message_mutex };
osSendMesg(PASS_RDRAM events_context.dp.mq, events_context.dp.msg, OS_MESG_NOBLOCK);
ultramodern::enqueue_external_message(events_context.dp.mq, events_context.dp.msg, false, true);
}

void task_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_ready) {
Expand Down Expand Up @@ -559,8 +557,8 @@ void ultramodern::submit_rsp_task(RDRAM_ARG PTR(OSTask) task_) {
}
}

void ultramodern::send_si_message(RDRAM_ARG1) {
osSendMesg(PASS_RDRAM events_context.si.mq, events_context.si.msg, OS_MESG_NOBLOCK);
void ultramodern::send_si_message() {
ultramodern::enqueue_external_message(events_context.si.mq, events_context.si.msg, false, true);
}

void ultramodern::init_events(RDRAM_ARG ultramodern::renderer::WindowHandle window_handle) {
Expand Down
4 changes: 2 additions & 2 deletions ultramodern/src/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ extern "C" s32 osContReset(RDRAM_ARG PTR(OSMesgQueue) mq, PTR(OSContStatus) data
}

extern "C" s32 osContStartQuery(RDRAM_ARG PTR(OSMesgQueue) mq) {
ultramodern::send_si_message(PASS_RDRAM1);
ultramodern::send_si_message();

return 0;
}
Expand All @@ -109,7 +109,7 @@ extern "C" s32 osContStartReadData(RDRAM_ARG PTR(OSMesgQueue) mq) {
}
update_poll_time();

ultramodern::send_si_message(rdram);
ultramodern::send_si_message();

return 0;
}
Expand Down
27 changes: 19 additions & 8 deletions ultramodern/src/mesgqueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,44 @@ struct QueuedMessage {
PTR(OSMesgQueue) mq;
OSMesg mesg;
bool jam;
bool requeue_if_blocked;
};

static moodycamel::BlockingConcurrentQueue<QueuedMessage> external_messages {};

void enqueue_external_message(PTR(OSMesgQueue) mq, OSMesg msg, bool jam) {
external_messages.enqueue({mq, msg, jam});
void ultramodern::enqueue_external_message(PTR(OSMesgQueue) mq, OSMesg msg, bool jam, bool requeue_if_blocked) {
external_messages.enqueue({mq, msg, jam, requeue_if_blocked});
}

bool do_send(RDRAM_ARG PTR(OSMesgQueue) mq_, OSMesg msg, bool jam, bool block);

void dequeue_external_messages(RDRAM_ARG1) {
QueuedMessage to_send;
std::vector<QueuedMessage> requeued_messages{};
while (external_messages.try_dequeue(to_send)) {
do_send(PASS_RDRAM to_send.mq, to_send.mesg, to_send.jam, false);
if (!do_send(PASS_RDRAM to_send.mq, to_send.mesg, to_send.jam, false) && to_send.requeue_if_blocked) {
requeued_messages.push_back(to_send);
}
}
for (QueuedMessage& cur_mesg : requeued_messages) {
external_messages.enqueue(cur_mesg);
}
}

void ultramodern::wait_for_external_message(RDRAM_ARG1) {
QueuedMessage to_send;
external_messages.wait_dequeue(to_send);
do_send(PASS_RDRAM to_send.mq, to_send.mesg, to_send.jam, false);
if (!do_send(PASS_RDRAM to_send.mq, to_send.mesg, to_send.jam, false) && to_send.requeue_if_blocked) {
external_messages.enqueue(to_send);
}
}

void ultramodern::wait_for_external_message_timed(RDRAM_ARG1, u32 millis) {
void ultramodern::wait_for_external_message_timed(RDRAM_ARG u32 millis) {
QueuedMessage to_send;
if (external_messages.wait_dequeue_timed(to_send, std::chrono::milliseconds{millis})) {
do_send(PASS_RDRAM to_send.mq, to_send.mesg, to_send.jam, false);
if (!do_send(PASS_RDRAM to_send.mq, to_send.mesg, to_send.jam, false) && to_send.requeue_if_blocked) {
external_messages.enqueue(to_send);
}
}
}

Expand Down Expand Up @@ -138,7 +149,7 @@ extern "C" s32 osSendMesg(RDRAM_ARG PTR(OSMesgQueue) mq_, OSMesg msg, s32 flags)

// Don't directly send to the message queue if this isn't a game thread to avoid contention.
if (!ultramodern::is_game_thread()) {
enqueue_external_message(mq_, msg, jam);
ultramodern::enqueue_external_message(mq_, msg, jam, false);
return 0;
}

Expand All @@ -160,7 +171,7 @@ extern "C" s32 osJamMesg(RDRAM_ARG PTR(OSMesgQueue) mq_, OSMesg msg, s32 flags)

// Don't directly send to the message queue if this isn't a game thread to avoid contention.
if (!ultramodern::is_game_thread()) {
enqueue_external_message(mq_, msg, jam);
ultramodern::enqueue_external_message(mq_, msg, jam, false);
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion ultramodern/src/timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ void timer_thread(RDRAM_ARG1) {
}
else {
// Waiting for the timer completed, so send the timer's message to its message queue
osSendMesg(PASS_RDRAM cur_timer->mq, cur_timer->msg, OS_MESG_NOBLOCK);
ultramodern::enqueue_external_message(cur_timer->mq, cur_timer->msg, false, true);
// If the timer has a specified interval then reload it with that value
if (cur_timer->interval != 0) {
cur_timer->timestamp = cur_timer->interval + time_now();
Expand Down
Loading