1 /***********************************************************************
2  * ��������Ĵ������ (�����ƥ��¸)
3  *
4  *	�ܺ٤ϡ� wait.h ����
5  ************************************************************************/
6 
7 /* select, usleep, nanosleep �Τ����줫�Υ����ƥॳ�������Ѥ���Τǡ�
8    �ʲ��Τɤ줫��Ĥ�Ĥ��ơ�¾�ϥ����ȥ����Ȥ��� */
9 
10 #define USE_SELECT
11 /* #define USE_USLEEP */
12 /* #define USE_NANOSLEEP */
13 
14 
15 #include <stdio.h>
16 
17 #include <sys/types.h>		/* select                        */
18 #include <sys/time.h>		/* select           gettimeofday */
19 #include <unistd.h>		/* select usleep                 */
20 #include <time.h>		/*        nanosleep clock        */
21 
22 #include "quasi88.h"
23 #include "initval.h"
24 #include "wait.h"
25 #include "suspend.h"
26 #include "event.h"		/* quasi88_is_exec		*/
27 
28 #include "intr.h"		/* test */
29 #include "screen.h"		/* test */
30 #include "graph.h"		/* test */
31 
32 
33 /*---------------------------------------------------------------------------*/
34 static	int	wait_do_sleep;			/* idle���� sleep ����       */
35 	int	wait_sleep_min_us = 100;	/* �Ĥ� idle���֤����� us�ʲ���
36 						   ���ϡ� sleep �������Ԥġ�
37 						   (MAX 1�� = 1,000,000us) */
38 
39 static	int	wait_counter = 0;		/* Ϣ³������֥����С�������*/
40 static	int	wait_count_max = 10;		/* ����ʾ�Ϣ³�����С�������
41 						   ��ö,����Ĵ������������ */
42 
43 	int	show_fps;			/* test */
44 static	void	display_fps(void);		/* test */
45 
46 /* �������Ȥ˻��Ѥ�����֤�����ɽ���ϡ� usñ�̤Ȥ��롣 (ms�������٤��㤤�Τ�)
47 
48    ��������ؿ� (gettimeofday() �ʤ�) �Ǽ������������ us ���Ѵ����ơ�
49    long long �����ݻ����뤳�Ȥˤ��褦�� */
50 
51 #ifdef	HAVE_LONG_LONG
52 typedef	long long	T_WAIT_TICK;
53 #else
54 typedef	long		T_WAIT_TICK;
55 #endif
56 
57 static	T_WAIT_TICK	next_time;		/* ���ե졼��λ��� */
58 static	T_WAIT_TICK	delta_time;		/* 1 �ե졼��λ��� */
59 
60 static	T_WAIT_TICK	sleep_min_time = 100;	/* sleep ��ǽ�ʺǾ����� */
61 
62 
63 
64 /* ---- ���ꤵ�줿���� (usecñ��) sleep ���� ---- */
65 
delay_usec(unsigned int usec)66 INLINE	void	delay_usec(unsigned int usec)
67 {
68 #if	defined(USE_SELECT)		/* select ��Ȥ� */
69 
70     struct timeval tv;
71     tv.tv_sec  = 0;
72     tv.tv_usec = usec;
73     select(0, NULL, NULL, NULL, &tv);
74 
75 #elif	defined(USE_USLEEP)		/* usleep ��Ȥ� */
76 
77     usleep(usec);
78 
79 #elif	defined(USE_NANOSLEEP)		/* nanosleep ��Ȥ� */
80 
81     struct timespec ts;
82     ts.tv_sec = 0;
83     ts.tv_nsec = usec * 1000;
84     nanosleep(&ts, NULL);
85 
86 #else					/* �ɤ��Ȥ��ʤ� ! */
87     wait_do_sleep = FALSE; /* X_X; */
88 #endif
89 }
90 
91 
92 
93 /* ---- ���߻����������� (usecñ��) ---- */
94 static int tick_error = FALSE;
95 
96 
97 #ifdef  HAVE_GETTIMEOFDAY		/* gettimeofday() ��Ȥ� */
98 
99 static struct timeval start_tv;
100 
set_tick(void)101 INLINE	void		set_tick(void)
102 {
103     if (gettimeofday(&start_tv, 0)) {
104 	if (verbose_wait) printf("Clock Error\n");
105 	tick_error = TRUE;
106 	start_tv.tv_sec  = 0;
107 	start_tv.tv_usec = 0;
108     }
109 }
110 
get_tick(void)111 INLINE	T_WAIT_TICK	get_tick(void)
112 {
113     struct timeval tv;
114 
115     if (gettimeofday(&tv, 0)) {
116 	if (verbose_wait) { if (tick_error == FALSE) printf("Clock Error\n"); }
117 	tick_error = TRUE;
118 	tv.tv_sec  = 1;
119 	tv.tv_usec = 1;
120     }
121 
122  #if 1
123     return ((T_WAIT_TICK) (tv.tv_sec  - start_tv.tv_sec) * 1000000 +
124 	    (T_WAIT_TICK) (tv.tv_usec - start_tv.tv_usec));
125  #else
126     tv.tv_sec  -= start_tv.tv_sec;
127     tv.tv_usec -= start_tv.tv_usec;
128     if (tv.tv_usec < 0) {
129 	--tv.tv_sec;
130 	tv.tv_usec += 1000000;
131     }
132     return ((T_WAIT_TICK) tv.tv_sec * 1000000 + (T_WAIT_TICK) tv.tv_usec);
133  #endif
134 }
135 
136 #else					/* clock() ��Ȥ� */
137 
138 /* #define CLOCK_SLICE	CLK_TCK */		/* ���줸�����ܡ� */
139 #define	CLOCK_SLICE	CLOCKS_PER_SEC		/* ���ä������� */
140 
set_tick(void)141 INLINE	void		set_tick(void)
142 {
143 }
144 
get_tick(void)145 INLINE	T_WAIT_TICK	get_tick(void)
146 {
147     clock_t t = clock();
148     if (t == (clock_t)-1) {
149 	if (verbose_wait) { if (tick_error == FALSE) printf("Clock Error\n"); }
150 	tick_error = TRUE;
151 	t = CLOCK_SLICE;
152     }
153 
154     return ((T_WAIT_TICK) (t / CLOCK_SLICE) * 1000000 +
155 	    (T_WAIT_TICK)((t % CLOCK_SLICE) * 1000000.0 / CLOCK_SLICE));
156 }
157 
158 #endif
159 
160 
161 
162 
163 
164 /****************************************************************************
165  * ��������Ĵ�������ν��������λ
166  *****************************************************************************/
wait_vsync_init(void)167 int	wait_vsync_init(void)
168 {
169     if (verbose_proc) {
170 #ifdef  HAVE_GETTIMEOFDAY
171 	printf("Timer start (gettimeofday(2) - based)\n");
172 #else
173 	printf("Timer start (clock(3) - based)\n");
174 #endif
175     }
176 
177     return TRUE;
178 }
179 
wait_vsync_exit(void)180 void	wait_vsync_exit(void)
181 {
182 }
183 
184 
185 
186 /****************************************************************************
187  * ��������Ĵ������������
188  *****************************************************************************/
wait_vsync_setup(long vsync_cycle_us,int do_sleep)189 void	wait_vsync_setup(long vsync_cycle_us, int do_sleep)
190 {
191     set_tick();
192 
193     sleep_min_time = wait_sleep_min_us;
194     wait_counter = 0;
195 
196 
197     delta_time = (T_WAIT_TICK) vsync_cycle_us;		/* 1�ե졼����� */
198     next_time  = get_tick() + delta_time;		/* ���ե졼����� */
199 
200     wait_do_sleep = do_sleep;				/* Sleep ̵ͭ */
201 }
202 
203 
204 
205 /****************************************************************************
206  * ��������Ĵ�������μ¹�
207  *****************************************************************************/
wait_vsync_update(void)208 int	wait_vsync_update(void)
209 {
210     int	on_time = FALSE;
211     T_WAIT_TICK	diff_us;
212 
213     /* �¹���ϡ�sleep ���뤫�ɤ����ϡ����ץ����ˤ�뤱�ɡ� */
214     /* ��˥塼�Ǥ�ɬ�� sleep �����뤳�Ȥˤ��롣              */
215     /* (�줤FreeBSD �ǡ��ʤ����ϥ����åפ��뤳�Ȥ�����ġ�) */
216     /* (PAUSE�������ʤ��Τ����ġĤʤ���?                  ) */
217     int need_sleep = (quasi88_is_exec() ? wait_do_sleep : TRUE);
218 
219     diff_us = next_time - get_tick();
220 
221     if (tick_error == FALSE) {
222 
223 	if (diff_us > 0) {	/* �ޤ����֤�;�äƤ���ʤ� */
224 			 	/* diff_us �̥ߥ��å������� */
225 	    if (need_sleep) {		/* ���֤����ޤ� sleep ������ */
226 
227 		/* FreeBSD ���ξ�硢�ʲ��Τ��������ܤ���ˡ�ʳ��ϡ�
228 		   10msñ�̤ǥ��꡼�פ��뤳�Ȥ�Ƚ����
229 		   �Ĥޤꡢ55.4hz�ξ�硢18ms�ǤϤʤ���20ms�Υ��꡼��
230 		   �ˤʤ롣*/
231 
232 #if 1
233 		/* ver 0.6.3 �ޤǤ���ˡ
234 		   �������٤ޤǥ������Ȥ��Ƥ��뤿��㴳�٤줬ȯ������Ϥ���
235 		   ������ɥΥ������װ����� */
236 		if (diff_us < sleep_min_time) {	/* �Ĥ�Ϥ��ʤ�ӥ�����������*/
237 		    while (tick_error == FALSE) {
238 			if (next_time <= get_tick())
239 			    break;
240 		    }
241 		} else {			/* �Ĥ�¿����Хǥ��쥤      */
242 		    delay_usec(diff_us);
243 		}
244 #elif 0
245 		/* 1ms �ʾ���֤�������� 100us �� sleep ��
246 		   1ms ̤���ξ��ϥӥ����������Ȥ��Ƥߤ���XMAME����
247 		   �ӥ����������Ȥ�������٤ǤϤʤ���100us���˽����褦��
248 		   �Ȥ����� 100us �� sleep �� CPU��٤� 100% �᤯�ˤʤ�
249 		   ���Ȥ�Ƚ��������Ϥޤ�������*/
250 		while (tick_error == FALSE) {
251 		    diff_us = next_time - get_tick();
252 		    if (diff_us >= 1000) {
253 			delay_usec(100);
254 		    } else if (diff_us <= 100) {
255 			break;
256 		    }
257 		}
258 #elif 0
259 		/* SDL �� 1ms ñ�̤� sleep �ǡ�CPU��٤�ʤ���������ɤ�
260 		   �Υ������Ǥʤ��Τǡ����Τޤ޿������Ƥߤ褦��*/
261 		if (diff_us >= 1000) {
262 		    delay_usec((diff_us/1000) * 1000);
263 		}
264 #elif 0
265 		/* �������� */
266 		while (tick_error == FALSE) {
267 		    diff_us = next_time - get_tick();
268 		    if (diff_us >= 1100) {
269 			delay_usec(diff_us - 100);
270 		    } else if (diff_us <= 100) {
271 			break;
272 		    }
273 		}
274 #endif
275 	    } else {			/* ���֤����ޤ�Tick ��ƻ뤹���� */
276 
277 		while (tick_error == FALSE) {
278 		    if (next_time <= get_tick())
279 			break;
280 		}
281 	    }
282 
283 	    on_time = TRUE;
284 	}
285     }
286 
287 
288     /* ���ե졼�������� */
289     next_time += delta_time;
290 
291 
292     if (on_time) {			/* ������˽����Ǥ��� */
293 	wait_counter = 0;
294     } else {				/* ������˽����Ǥ��Ƥ��ʤ� */
295 	wait_counter ++;
296 	if (wait_counter >= wait_count_max) {	/* �٤줬�Ҥɤ����� */
297 	    wait_vsync_setup((long) delta_time,	/* �������Ȥ�����   */
298 			     wait_do_sleep);
299 	}
300     }
301 
302 #if 0
303     {
304 	static int x = 0, y = 0;
305 	if (++x == 55) {
306 	    y++;
307 	    x = 0;
308 	    printf("wait %d\n", y);
309 	    fflush(stdout);
310 	}
311     }
312 #endif
313     if (show_fps) {
314 	display_fps();
315     }
316 
317     if (on_time) return WAIT_JUST;
318     else         return WAIT_OVER;
319 }
320 
321 
322 
323 /****************************************************************************
324  *
325  *****************************************************************************/
326 /* Ŭ���� fps �׻� */
display_fps(void)327 static	void	display_fps(void)
328 {
329 #ifdef  HAVE_GETTIMEOFDAY
330     static struct timeval tv0;
331     static int frame_count;
332     static int prev_drawn_count;
333     static int prev_vsync_count;
334 
335     /* ���� tv0 �Ͻ����̤�ʤΤǡ����߻�����å� */
336     if (tv0.tv_sec == 0 &&
337 	tv0.tv_usec == 0) {
338 	gettimeofday(&tv0, 0);
339     }
340 
341     if (quasi88_is_exec()) {
342 
343 	/* ���δؿ��ϡ����������� �� �ե졼����˸ƤӽФ���롣
344 	   60�ե졼���(��1��)�ƤӽФ��줿�顢FPS��׻�����ɽ������ */
345 	if (++ frame_count >= 60) {
346 
347 	    char buf[32];
348 	    struct timeval tv1;
349 	    double dt, fps, hz;
350 	    int now_drawn_count = quasi88_info_draw_count();
351 	    int now_vsync_count = quasi88_info_vsync_count();
352 
353 	    gettimeofday(&tv1, 0);
354 	    dt  = (double)(tv1.tv_sec  - tv0.tv_sec);
355 	    dt += (double)(tv1.tv_usec - tv0.tv_usec) / 1000000.0;
356 
357 	    hz  = (double)(now_vsync_count - prev_vsync_count) / dt;
358 	    fps = (double)(now_drawn_count - prev_drawn_count) / dt;
359 	    sprintf(buf, "FPS: %4.1f (VSYNC %4.1f)", fps, hz);
360 	    graph_set_window_title(buf);
361 
362 
363 	    tv0 = tv1;
364 	    frame_count = 0;
365 	    prev_drawn_count = now_drawn_count;
366 	    prev_vsync_count = now_vsync_count;
367 	}
368 
369     } else {
370 	tv0.tv_sec  = 0;
371 	tv0.tv_usec = 0;
372 	frame_count = 0;
373 	prev_drawn_count = quasi88_info_draw_count();
374 	prev_vsync_count = quasi88_info_vsync_count();
375     }
376 #endif
377 }
378