mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-09-28 01:37:58 +03:00
Scheduler: Yield based on scenario address
Now it yields execution when the device state is checked multiple times from the same scenario address.
This commit is contained in:
@@ -74,7 +74,6 @@ static void ntmain(struct _scoadr inadr) {
|
||||
}
|
||||
sys_getInputInfo();
|
||||
sdl_wait_vsync();
|
||||
scheduler_on_event(SCHEDULER_EVENT_NEW_FRAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1035,7 +1035,6 @@ static void va_update() {
|
||||
if (!proceeding) {
|
||||
nact->is_va_animation = FALSE;
|
||||
}
|
||||
scheduler_on_event(SCHEDULER_EVENT_VA_UPDATE);
|
||||
}
|
||||
|
||||
void va_reset(void) {
|
||||
|
||||
@@ -121,7 +121,6 @@ void nact_main() {
|
||||
nact->callback(); // Async in emscripten
|
||||
sys_getInputInfo();
|
||||
sdl_wait_vsync();
|
||||
scheduler_on_event(SCHEDULER_EVENT_NEW_FRAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+37
-37
@@ -17,11 +17,19 @@
|
||||
*
|
||||
*/
|
||||
#include "scheduler.h"
|
||||
#include "scenario.h"
|
||||
#include "nact.h"
|
||||
|
||||
bool scheduler_yield_requested;
|
||||
int scheduler_cmd_count;
|
||||
|
||||
#define BLOOM_FILTER_HASHES 4
|
||||
|
||||
// Knuth's multiplicative hash.
|
||||
static uint32_t hash(uint32_t x, int s) {
|
||||
return (x * 2654435761ULL) >> s;
|
||||
}
|
||||
|
||||
/*
|
||||
* System 3.x games are basically driven by busy loops that repeatedly check
|
||||
* the state of input devices or timers until their state changes. On modern
|
||||
@@ -30,54 +38,46 @@ int scheduler_cmd_count;
|
||||
* loops and schedules a yield.
|
||||
*/
|
||||
void scheduler_on_event(enum scheduler_event event) {
|
||||
static int frame_count = 0;
|
||||
static int cmd_count_of_prev_input = -1;
|
||||
static int timer_check_frame = -1;
|
||||
static int timer_check_count = 0;
|
||||
static int audio_check_frame = -1;
|
||||
static int va_status_check_count;
|
||||
static int prev_cmd_count = -1;
|
||||
static uint64_t bloom = 0;
|
||||
|
||||
switch (event) {
|
||||
case SCHEDULER_EVENT_NEW_FRAME:
|
||||
frame_count++;
|
||||
case SCHEDULER_EVENT_SLEEP:
|
||||
scheduler_yield_requested = false;
|
||||
bloom = 0;
|
||||
scheduler_cmd_count = 0;
|
||||
prev_cmd_count = -1;
|
||||
break;
|
||||
|
||||
case SCHEDULER_EVENT_INPUT_CHECK_MISS:
|
||||
if (scheduler_cmd_count != cmd_count_of_prev_input)
|
||||
scheduler_yield_requested = true;
|
||||
break;
|
||||
|
||||
case SCHEDULER_EVENT_INPUT_CHECK_HIT:
|
||||
cmd_count_of_prev_input = scheduler_cmd_count;
|
||||
break;
|
||||
|
||||
case SCHEDULER_EVENT_TIMER_CHECK:
|
||||
// Allow up to 10 timer checks in single animation frame.
|
||||
if (frame_count == timer_check_frame) {
|
||||
if (++timer_check_count >= 10)
|
||||
scheduler_yield_requested = true;
|
||||
} else {
|
||||
timer_check_frame = frame_count;
|
||||
timer_check_count = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCHEDULER_EVENT_AUDIO_CHECK:
|
||||
if (frame_count == audio_check_frame)
|
||||
scheduler_yield_requested = true;
|
||||
audio_check_frame = frame_count;
|
||||
break;
|
||||
|
||||
case SCHEDULER_EVENT_VA_STATUS_CHECK:
|
||||
if (++va_status_check_count > 1) {
|
||||
va_status_check_count = 0;
|
||||
scheduler_yield_requested = true;
|
||||
}
|
||||
break;
|
||||
// A single Sys3x command may generate multiple scheduler events.
|
||||
// Deduplicate them.
|
||||
if (prev_cmd_count == scheduler_cmd_count)
|
||||
break;
|
||||
prev_cmd_count = scheduler_cmd_count;
|
||||
|
||||
case SCHEDULER_EVENT_VA_UPDATE:
|
||||
va_status_check_count = 0;
|
||||
if (event == SCHEDULER_EVENT_INPUT_CHECK_HIT) {
|
||||
// There are new input events. Let's process them without delay.
|
||||
bloom = 0;
|
||||
} else {
|
||||
uint32_t h1 = hash(sl_getPage(), 7);
|
||||
uint32_t h2 = hash(sl_getIndex(), 15);
|
||||
uint64_t bits = 0;
|
||||
for (int i = 0; i < BLOOM_FILTER_HASHES; i++) {
|
||||
uint32_t h = (h1 + (i + 1) * h2) % 64;
|
||||
bits |= 1ULL << h;
|
||||
}
|
||||
if ((bloom & bits) == bits) {
|
||||
request_yield();
|
||||
bloom = 0;
|
||||
} else {
|
||||
bloom |= bits;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-5
@@ -22,13 +22,12 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
enum scheduler_event {
|
||||
SCHEDULER_EVENT_NEW_FRAME,
|
||||
SCHEDULER_EVENT_SLEEP,
|
||||
SCHEDULER_EVENT_INPUT_CHECK_MISS,
|
||||
SCHEDULER_EVENT_INPUT_CHECK_HIT,
|
||||
SCHEDULER_EVENT_TIMER_CHECK,
|
||||
SCHEDULER_EVENT_AUDIO_CHECK,
|
||||
SCHEDULER_EVENT_VA_STATUS_CHECK,
|
||||
SCHEDULER_EVENT_VA_UPDATE,
|
||||
};
|
||||
void scheduler_on_event(enum scheduler_event event);
|
||||
|
||||
@@ -39,10 +38,8 @@ static inline bool is_yield_requested(void) { return scheduler_yield_requested;
|
||||
|
||||
extern int scheduler_cmd_count;
|
||||
static inline void scheduler_on_command(void) {
|
||||
if (++scheduler_cmd_count >= 10000) {
|
||||
if (++scheduler_cmd_count >= 10000)
|
||||
request_yield();
|
||||
scheduler_cmd_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __SCHEDULER__
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "system.h"
|
||||
#include "sdl_core.h"
|
||||
#include "sdl_private.h"
|
||||
#include "scheduler.h"
|
||||
#include "font.h"
|
||||
#include "ags.h"
|
||||
#include "image.h"
|
||||
@@ -77,6 +78,7 @@ void sdl_sleep(int msec) {
|
||||
#else
|
||||
SDL_Delay(msec);
|
||||
#endif
|
||||
scheduler_on_event(SCHEDULER_EVENT_SLEEP);
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
@@ -98,6 +100,7 @@ void sdl_wait_vsync() {
|
||||
#else
|
||||
SDL_Delay(16);
|
||||
#endif
|
||||
scheduler_on_event(SCHEDULER_EVENT_SLEEP);
|
||||
}
|
||||
|
||||
/* off-screen の指定領域を Main Window へ転送 */
|
||||
|
||||
Reference in New Issue
Block a user