54 static const int _cpu_speeds[4] = { 4000000, 6000000, 7120000, 10000000 };
55 static int _cpu_speed_index = 0;
56 static int guarded_exit = 0;
57 static unsigned int ticks;
59 static int cpu_cycles_for_dave_sync = 0;
60 static int td_balancer;
61 static Uint64 et_start, et_end;
62 static int td_em_ALL = 0, td_pc_ALL = 0, td_count_ALL = 0;
63 static double balancer;
65 static int sram_ready = 0;
77 #if defined(__EMSCRIPTEN__) || defined(__arm__)
78 return SDL_malloc(
size);
93 #ifdef CONFIG_EPNET_SUPPORT
96 #ifdef CONFIG_EXDOS_SUPPORT
104 #ifdef __EMSCRIPTEN__
113 DEBUGPRINT(
"Closing debug messages log file on exit." NL);
122 static int get_elapsed_time ( Uint64 t_old, Uint64 *t_new, time_t *store_unix_time )
124 #ifdef XEMU_OLD_TIMING
125 #define __TIMING_METHOD_DESC "gettimeofday"
127 gettimeofday(&tv, NULL);
129 *store_unix_time = tv.tv_sec;
130 *t_new = tv.tv_sec * 1000000UL + tv.tv_usec;
131 return *t_new - t_old;
133 #define __TIMING_METHOD_DESC "SDL_GetPerformanceCounter"
135 *store_unix_time = time(NULL);
136 *t_new = SDL_GetPerformanceCounter();
137 return 1000000 * (*t_new - t_old) / SDL_GetPerformanceFrequency();
143 static inline void emu_sleep (
int td )
147 #ifdef __EMSCRIPTEN__
148 #define __SLEEP_METHOD_DESC "emscripten_set_main_loop_timing"
153 emscripten_set_main_loop_timing(EM_TIMING_SETTIMEOUT, td > 999 ? td / 1000 : 1);
154 #elif defined(XEMU_SLEEP_IS_SDL_DELAY)
155 #define __SLEEP_METHOD_DESC "SDL_Delay"
156 SDL_Delay(td / 1000);
157 #elif defined(XEMU_SLEEP_IS_USLEEP)
158 #define __SLEEP_METHOD_DESC "usleep"
161 #define __SLEEP_METHOD_DESC "nanosleep"
162 struct timespec req, rem;
164 req.tv_sec = td / 1000000000UL;
165 req.tv_nsec = td % 1000000000UL;
167 if (nanosleep(&req, &rem)) {
168 if (errno == EINTR) {
169 req.tv_sec = rem.tv_sec;
170 req.tv_nsec = rem.tv_nsec;
172 ERROR_WINDOW(
"Nanosleep() returned with unhandlable error");
183 static void emu_timekeeping_check (
void )
187 int td = get_elapsed_time(et_end, &et_start, &
unix_time);
191 DEBUG(
"TIMING: negative amount of time spent for sleeping?!" NL);
202 static void emu_timekeeping_delay (
int td_em )
204 int td, td_pc = get_elapsed_time(et_start, &et_end, NULL);
206 DEBUG(
"TIMING: negative amount of time spent for an emulation loop?!" NL);
210 DEBUG(
"DELAY: pc=%d em=%d sleep=%d" NL, td_pc, td_em, td);
214 if (td_count_ALL == 50) {
219 td_em_ALL ? (td_pc_ALL * 100 / td_em_ALL) : -1,
231 if (td_balancer > 1000000 || td_balancer < -1000000)
233 DEBUG(
"Balancer = %d" NL, td_balancer);
235 emu_sleep(td_balancer);
245 (void)get_elapsed_time(0, &et_start, &
unix_time);
255 if (hz < 1000000) hz = 1000000;
256 if (hz > 12000000) hz = 12000000;
269 OSD(
"CPU speed: %.2f MHz", hz / 1000000.0);
276 static int emu_one_frame_rasters = -1;
277 static int emu_one_frame_frameskip = 0;
281 emu_one_frame_rasters = rasters;
286 static void __emu_one_frame(
int rasters,
int frameskip)
289 while (SDL_PollEvent(&e) != 0)
291 case SDL_WINDOWEVENT:
292 if (!
is_fullscreen && e.window.event == SDL_WINDOWEVENT_RESIZED) {
293 DEBUG(
"UI: Window is resized to %d x %d" NL,
306 if (e.key.repeat == 0 && (e.key.windowID ==
sdl_winid || e.key.windowID == 0)) {
307 int code =
emu_kbd(e.key.keysym, e.key.state == SDL_PRESSED);
310 else if (code && e.key.state == SDL_PRESSED)
312 #ifndef __EMSCRIPTEN__
325 if (e.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT)) {
332 if (_cpu_speed_index)
336 if (_cpu_speed_index < 3)
344 }
else if (e.key.repeat == 0)
345 DEBUG(
"UI: NOT HANDLED KEY EVENT: repeat = %d windowid = %d [our win = %d]" NL, e.key.repeat, e.key.windowID,
sdl_winid);
347 case SDL_MOUSEMOTION:
354 e.wheel.x, e.wheel.y,
355 e.wheel.direction == SDL_MOUSEWHEEL_FLIPPED
358 case SDL_MOUSEBUTTONDOWN:
359 case SDL_MOUSEBUTTONUP:
377 static void xep128_emulation (
void )
379 emu_timekeeping_check();
385 __emu_one_frame(312, 0);
399 DEBUG(
"CPU: int and accepted = %d" NL, t);
404 cpu_cycles_for_dave_sync += t;
410 balancer += t * SCALER;
412 while (balancer >= 0.5) {
417 emu_one_frame_rasters,
418 emu_one_frame_frameskip
420 emu_one_frame_rasters = -1;
432 int main (
int argc,
char *argv[])
434 const char *snapshot;
437 #ifdef __EMSCRIPTEN__
439 SDL_INIT_EVERYTHING & ~(SDL_INIT_TIMER | SDL_INIT_HAPTIC)
444 ERROR_WINDOW(
"Fatal SDL initialization problem: %s", SDL_GetError());
448 #ifdef __EMSCRIPTEN__
449 ERROR_WINDOW(
"Error with config parsing. Please check the (javascript) console of your browser to learn about the error.");
454 DEBUGPRINT(
"EMU: sleeping = \"%s\", timing = \"%s\"" NL,
458 #ifdef __EMSCRIPTEN__
473 if (ep_pixels == NULL)
475 snapshot = config_getopt_str(
"snapshot");
476 if (strcmp(snapshot,
"none")) {
491 #ifdef CONFIG_SDEXT_SUPPORT
495 #ifdef CONFIG_EXDOS_SUPPORT
499 #ifdef CONFIG_EPNET_SUPPORT
502 ticks = SDL_GetTicks();
507 if (config_getopt_int(
"fullscreen"))
511 if (strcmp(config_getopt_str(
"primo"),
"none") && !snapshot) {
514 OSD(
"Primo Emulator Mode");
519 #ifdef __EMSCRIPTEN__
520 emscripten_set_main_loop(xep128_emulation, 50, 1);
525 printf(
"EXITING FROM main()?!" NL);