diff --git a/general.h b/general.h index 51e0e54e07..6bde38a5a7 100644 --- a/general.h +++ b/general.h @@ -183,6 +183,7 @@ struct settings #ifdef SSNES_CONSOLE struct console_settings { + msg_queue_t *stderr_queue; #ifdef __CELLOS_LV2__ bool custom_bgm_enable; #endif @@ -478,20 +479,35 @@ extern struct console_settings g_console; #if defined(SSNES_CONSOLE) && defined(HAVE_LOGGER) #include "logger_override.h" #else + +#ifdef SSNES_CONSOLE +#define SSNES_LOG_MSG_QUEUE(base, ...) do { \ + char msg[512]; + snprintf(msg, sizeof(msg), base ## __VA_ARGS__); \ + if (g_console.stderr_queue) \ + msg_queue_push_simple(g_console.stderr_queue, msg); \ +} while(0) +#else +#define SSNES_LOG_MSG_QUEUE(base, ...) ((void)0) +#endif + #define SSNES_LOG(...) do { \ if (g_extern.verbose) \ fprintf(stderr, "SSNES: " __VA_ARGS__); \ fflush(stderr); \ + SSNES_LOG_MSG_QUEUE("SSNES: ", __VA_ARGS__); \ } while (0) #define SSNES_ERR(...) do { \ fprintf(stderr, "SSNES [ERROR] :: " __VA_ARGS__); \ fflush(stderr); \ + SSNES_LOG_MSG_QUEUE("SSNES [ERROR]: ", __VA_ARGS__); \ } while (0) #define SSNES_WARN(...) do { \ fprintf(stderr, "SSNES [WARN] :: " __VA_ARGS__); \ fflush(stderr); \ + SSNES_LOG_MSG_QUEUE("SSNES [WARN]: ", __VA_ARGS__); \ } while (0) #endif diff --git a/message.c b/message.c index 24066198d7..f9c3aaea55 100644 --- a/message.c +++ b/message.c @@ -38,6 +38,9 @@ struct msg_queue msg_queue_t *msg_queue_new(size_t size) { + if (size == 0) + return NULL; + msg_queue_t *queue = (msg_queue_t*)calloc(1, sizeof(*queue)); if (!queue) return NULL; @@ -66,7 +69,7 @@ void msg_queue_push(msg_queue_t *queue, const char *msg, unsigned prio, unsigned if (queue->ptr >= queue->size) return; - struct queue_elem *new_elem = (struct queue_elem*)calloc(1, sizeof(struct queue_elem)); + struct queue_elem *new_elem = (struct queue_elem*)calloc(1, sizeof(*new_elem)); new_elem->prio = prio; new_elem->duration = duration; new_elem->msg = msg ? strdup(msg) : NULL; @@ -81,15 +84,50 @@ void msg_queue_push(msg_queue_t *queue, const char *msg, unsigned prio, unsigned if (child->prio <= parent->prio) break; - else - { - queue->elems[tmp_ptr >> 1] = child; - queue->elems[tmp_ptr] = parent; - } + + queue->elems[tmp_ptr >> 1] = child; + queue->elems[tmp_ptr] = parent; tmp_ptr >>= 1; } } +void msg_queue_push_simple(msg_queue_t *queue, const char *msg) +{ + if (queue->ptr >= queue->size) + { + if (queue->elems[1]) + { + free(queue->elems[1]->msg); + free(queue->elems[1]); + } + + queue->ptr--; + memmove(queue->elems, queue->elems + 1, queue->ptr * sizeof(struct queue_elem)); + } + + struct queue_elem *new_elem = (struct queue_elem*)calloc(1, sizeof(*new_elem)); + new_elem->prio = 1; + new_elem->duration = 1; + new_elem->msg = msg ? strdup(msg) : NULL; + + queue->elems[queue->ptr++] = new_elem; +} + +const char *msg_queue_pull_simple(msg_queue_t *queue) +{ + if (queue->ptr == 1) + return NULL; + + free(queue->tmp_msg); + queue->tmp_msg = queue->elems[1]->msg; + queue->elems[1]->msg = NULL; + free(queue->elems[1]); + + queue->ptr--; + memmove(queue->elems, queue->elems + 1, queue->ptr * sizeof(struct queue_elem)); + return queue->tmp_msg; +} + void msg_queue_clear(msg_queue_t *queue) { for (size_t i = 1; i < queue->ptr; i++) @@ -112,48 +150,48 @@ const char *msg_queue_pull(msg_queue_t *queue) return NULL; struct queue_elem *front = queue->elems[1]; + front->duration--; if (front->duration > 0) return front->msg; - else + + free(queue->tmp_msg); + queue->tmp_msg = front->msg; + front->msg = NULL; + + struct queue_elem *last = queue->elems[--queue->ptr]; + queue->elems[1] = last; + free(front); + + size_t tmp_ptr = 1; + for (;;) { - free(queue->tmp_msg); - queue->tmp_msg = front->msg; - front->msg = NULL; + bool left = (tmp_ptr * 2 <= queue->ptr) && (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2]); + bool right = (tmp_ptr * 2 + 1 <= queue->ptr) && (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2 + 1]); - struct queue_elem *front = queue->elems[1]; - struct queue_elem *last = queue->elems[--queue->ptr]; - queue->elems[1] = last; - free(front); + if (!left && !right) + break; - size_t tmp_ptr = 1; - for (;;) + size_t switch_index = tmp_ptr; + if (left && !right) + switch_index <<= 1; + else if (right && !left) + switch_index += switch_index + 1; + else { - bool left = (tmp_ptr * 2 <= queue->ptr) && (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2]); - bool right = (tmp_ptr * 2 + 1 <= queue->ptr) && (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2 + 1]); - - if (!left && !right) - break; - - size_t switch_index = tmp_ptr; - if (left && !right) + if (queue->elems[tmp_ptr * 2] >= queue->elems[tmp_ptr * 2 + 1]) switch_index <<= 1; - else if (right && !left) - switch_index += switch_index + 1; else - { - if (queue->elems[tmp_ptr * 2] >= queue->elems[tmp_ptr * 2 + 1]) - switch_index <<= 1; - else - switch_index += switch_index + 1; - } - struct queue_elem *parent = queue->elems[tmp_ptr]; - struct queue_elem *child = queue->elems[switch_index]; - queue->elems[tmp_ptr] = child; - queue->elems[switch_index] = parent; - tmp_ptr = switch_index; + switch_index += switch_index + 1; } - return queue->tmp_msg; + struct queue_elem *parent = queue->elems[tmp_ptr]; + struct queue_elem *child = queue->elems[switch_index]; + queue->elems[tmp_ptr] = child; + queue->elems[switch_index] = parent; + tmp_ptr = switch_index; } + + return queue->tmp_msg; } + diff --git a/message.h b/message.h index 21395c6bdc..e146fdb780 100644 --- a/message.h +++ b/message.h @@ -32,6 +32,10 @@ void msg_queue_push(msg_queue_t *queue, const char *msg, unsigned prio, unsigned // Pulls highest prio message in queue. Returns NULL if no message in queue. const char *msg_queue_pull(msg_queue_t *queue); +// Pushes and pulls in a FIFO fashion, duration is fixed to one frame, prio doesn't matter. +void msg_queue_push_simple(msg_queue_t *queue, const char *msg); +const char *msg_queue_pull_simple(msg_queue_t *queue); + // Clear out everything in queue. void msg_queue_clear(msg_queue_t *queue); diff --git a/ssnes.c b/ssnes.c index 87d12e32dc..650828a0ec 100644 --- a/ssnes.c +++ b/ssnes.c @@ -1196,12 +1196,22 @@ void ssnes_init_msg_queue(void) { if (!g_extern.msg_queue) ssnes_assert(g_extern.msg_queue = msg_queue_new(8)); + +#ifdef SSNES_CONSOLE + if (!g_console.stderr_queue) + ssnes_assert(g_console.stderr_queue = msg_queue_new(256)); +#endif } static void deinit_msg_queue(void) { if (g_extern.msg_queue) msg_queue_free(g_extern.msg_queue); + +#ifdef SSNES_CONSOLE + if (g_console.stderr_queue) + msg_queue_free(g_console.stderr_queue); +#endif } #ifdef HAVE_XML