--- uae/src/include/events.h 2018/04/24 16:38:39 1.1 +++ uae/src/include/events.h 2018/04/24 17:18:59 1.1.1.14 @@ -2,18 +2,33 @@ * UAE - The Un*x Amiga Emulator * * Events - * - * (c) 1995 Bernd Schmidt + * These are best for low-frequency events. Having too many of them, + * or using them for events that occur too frequently, can cause massive + * slowdown. + * + * Copyright 1995-1998 Bernd Schmidt */ -/* This is tunable. 4 gives good results. */ -#ifdef LINUX_SOUND_SLOW_MACHINE -#define cycles_per_instruction 8 -#else -#define cycles_per_instruction 4 -#endif +typedef unsigned long frame_time_t; + +extern frame_time_t vsynctime, vsyncmintime; +extern frame_time_t gtod_resolution; +extern int vsyncmintime_valid; + +extern frame_time_t first_measured_gtod; +extern unsigned long gtod_secs; +extern unsigned long nr_gtod_to_skip; +extern unsigned long nr_gtod_done, gtod_counter; + +extern int sync_with_sound; +extern int use_gtod; + +extern unsigned long currcycle, nextevent; + +extern int is_lastline; +extern volatile int delaying_for_sound; +extern int active_fs_packets; -extern unsigned long int cycles, nextevent; typedef void (*evfunc)(void); struct ev @@ -23,72 +38,102 @@ struct ev evfunc handler; }; -enum { - ev_hsync, ev_copper, ev_cia, - ev_blitter, ev_diskblk, ev_diskindex, -#ifndef DONT_WANT_SOUND - ev_aud0, ev_aud1, ev_aud2, ev_aud3, - ev_sample, -#endif +enum { + ev_hsync, ev_copper, ev_audio, ev_cia, ev_blitter, ev_disk, ev_max }; extern struct ev eventtab[ev_max]; -static __inline__ void events_schedule(void) +extern void reset_frame_rate_hack (void); +extern void compute_vsynctime (void); +extern void time_vsync (void); + +extern void init_gtod (void); + +STATIC_INLINE frame_time_t get_current_time (int redo_secs) +{ + struct timeval tv; + gettimeofday (&tv, NULL); + if (redo_secs) + gtod_secs = tv.tv_sec; + return tv.tv_usec + (tv.tv_sec - gtod_secs) * 1000000; +} + +STATIC_INLINE void events_schedule (void) { int i; - + unsigned long int mintime = ~0L; - for(i = 0; i < ev_max; i++) { - if (eventtab[i].active) { - unsigned long int eventtime = eventtab[i].evtime - cycles; + for (i = 0; i < ev_max; i++) { + if (eventtab[i].active) { + unsigned long int eventtime = eventtab[i].evtime - currcycle; if (eventtime < mintime) - mintime = eventtime; + mintime = eventtime; } } - nextevent = cycles + mintime; + nextevent = currcycle + mintime; } -static __inline__ void do_cycles_slow(void) +STATIC_INLINE void do_cycles_slow (unsigned long cycles_to_add) { - if ((nextevent - cycles) <= cycles_per_instruction) { - int j; - for(j = 0; j < cycles_per_instruction; j++) { - if (++cycles == nextevent) { - int i; + if (delaying_for_sound) + return; + + if (is_lastline + && eventtab[ev_hsync].evtime - currcycle <= cycles_to_add) + { + static int n_skipped = 0; + frame_time_t curr; + + if (gtod_counter++ < nr_gtod_to_skip) + return; + gtod_counter = 0; + curr = get_current_time (0); - for(i = 0; i < ev_max; i++) { - if (eventtab[i].active && eventtab[i].evtime == cycles) { - (*eventtab[i].handler)(); - } - } - events_schedule(); - } + if ((long int)(curr - vsyncmintime) < 0) { + nr_gtod_done++; + return; } - } else { - cycles += cycles_per_instruction; +#if 0 + printf ("skipped %d times\n", nr_gtod_done); +#endif } -} -static __inline__ void do_cycles_fast(void) -{ - cycles++; - if (nextevent == cycles) { + while ((nextevent - currcycle) <= cycles_to_add) { int i; - - for(i = 0; i < ev_max; i++) { - if (eventtab[i].active && eventtab[i].evtime == cycles) { + cycles_to_add -= (nextevent - currcycle); + currcycle = nextevent; + + for (i = 0; i < ev_max; i++) { + if (eventtab[i].active && eventtab[i].evtime == currcycle) { (*eventtab[i].handler)(); } } events_schedule(); } + currcycle += cycles_to_add; +} +/* This is a special-case function. Normally, all events should lie in the + future; they should only ever be active at the current cycle during + do_cycles. However, a snapshot is saved during do_cycles, and so when + restoring it, we may have other events pending. */ +STATIC_INLINE void handle_active_events (void) +{ + int i; + for (i = 0; i < ev_max; i++) { + if (eventtab[i].active && eventtab[i].evtime == currcycle) { + (*eventtab[i].handler)(); + } + } } -#ifdef FASTER_CPU -#define do_cycles do_cycles_fast -#else +STATIC_INLINE unsigned long get_cycles (void) +{ + return currcycle; +} + +extern void init_eventtab (void); + #define do_cycles do_cycles_slow -#endif