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