2 This are just a few usefull routines for emulators on unix systems,
3 they can be used for games on unix in general.
4 Current implement stuff:
14 #include <sys/types.h>
19 #ifdef HAVE_GETTIMEOFDAY
21 #define UCLOCKS_PER_SEC 2000
23 /* Standard UNIX clock() is based on CPU time, not real time.
24 Here is a real-time drop in replacement for UNIX systems that have the
25 gettimeofday() routine. This results in much more accurate timing for
30 static long init_sec
= 0;
36 return (((tv
.tv_sec
- init_sec
) * 2000) + (tv
.tv_usec
/ 500));
41 #if (CLOCKS_PER_SEC < 1000)
42 /* the resolution of the normal clock() call isn't good enough, unless the
43 framerate is a division of 100, so we fake a higher resolution */
44 #define clock() (clock() << 5)
45 #define UCLOCKS_PER_SEC (CLOCKS_PER_SEC << 5)
47 #define UCLOCKS_PER_SEC CLOCKS_PER_SEC
50 #endif /* ifdef HAVE_GETTIMEOFDAY */
52 static clock_t clocks_per_refresh
;
53 static clock_t next_refresh
; /* the time the next refresh should occur */
54 static clock_t init_time
; /* the time slowdown_init was called */
55 static clock_t pause_time
; /* the time the emulation was paused */
56 static clock_t sleep_time
; /* total time the emulation has been inactive */
57 static int pause_count
; /* the no of times slowdown_pause has been called,
58 since nested pause - resume pairs can occur */
60 /* You should call this function before using slowdown, it calculates the
61 number of uclocks per screenrefresh.
62 Arguments: frames per second the emulation should be slowed to.
64 void slowdown_init(int frames_per_sec
)
66 clocks_per_refresh
= UCLOCKS_PER_SEC
/ frames_per_sec
;
68 next_refresh
= init_time
+ clocks_per_refresh
;
74 /* When called once every frame update this function slowsdown the emulation
75 to the number of frames / sec given to init_slowdown.
76 it's return value can be used to automaticly skip frames, it returns:
77 1 if it actually slowed the emulation
78 0 if the emulation is too slow.
79 So if this function returns 1 draw the next frame. If it returns 0 skip the
80 next frame, to catch up speed.
82 int slowdown_slow(void)
88 /* Under certain conditions new_time while wrap around before next_refresh.
89 To stop infinite looping, we have to check this here ;( */
90 if ((new_time
< -1073741824) && (next_refresh
> 1073741824))
91 next_refresh
= new_time
;
94 /* If the system has a good USLEEP, we can try to sleep the
95 time away instead of polling - always nice on a *NIX system.
96 We sleep for a tenth of the amount of time remaining for this
97 frame - this is an attempt to avoid oversleeping. */
98 if (new_time
< next_refresh
)
99 usleep( ((next_refresh
- new_time
)*(100000/CLOCKS_PER_SEC
)));
101 } while (next_refresh
> new_time
);
103 next_refresh
+= clocks_per_refresh
;
105 if (next_refresh
> new_time
) return 1;
107 /* this codes automagically corrects for pause, and being suspended.
108 But it only works if the emulation is capable of running at full speed
109 (with or without frameskip). Therefore it's disabled and slowdown_pause
110 and slowdown_resume should be used instead */
112 /* if the emulation is too slow, and behind more then 1 sec, the emulation,
113 probably has been suspended without calling slowdown_pause/resume */
114 if ((new_time
- next_refresh
) > UCLOCKS_PER_SEC
)
116 sleep_time
+= new_time
- next_refresh
;
117 next_refresh
= new_time
+ clocks_per_refresh
;
125 /* This function should be called every time the emulation is stopped for
126 any reason at all. The slowdown routine's use this function together with
127 slowdown_resume to recalibrate there timing.
128 This function should be used in conjunction with slowdown_resume.
130 void slowdown_pause(void)
132 if (pause_count
==0) pause_time
= clock();
136 /* This function should be called every time the emulation is resumed after
137 being stopped for any reason at all. This function should be used in
138 conjunction with slowdown_pause.
140 void slowdown_resume(void)
142 clock_t sleeping_time
;
146 sleeping_time
= clock() - pause_time
;
147 next_refresh
+= sleeping_time
;
148 sleep_time
+= sleeping_time
;
153 /* This function returns the number of seconds the emulation is running.
154 Not counting the seconds the emulation has been paused by slowdown_pause.
156 int slowdown_seconds_running(void)
160 seconds_running
= ((clock() - init_time
) - sleep_time
) / UCLOCKS_PER_SEC
;
161 if (seconds_running
== 0)
164 return seconds_running
;
169 #include <linux/joystick.h>
170 int j0_fd
=-1; /* joystick device */
172 int j0_max_left
, j0_max_right
, j0_max_up
, j0_max_down
; /* calibration data */
173 int j1_max_left
, j1_max_right
, j1_max_up
, j1_max_down
;
174 int nr_of_joysticks
=0;
176 /* This function initialises all joystick related stuff,
177 it returns the nr of joysticks detected */
178 int joystick_init(void)
181 struct JS_DATA_TYPE js_data
={0,0,0};
183 j0_fd
= open ("/dev/js0", O_RDONLY
);
184 if (j0_fd
< 0) return 0;
185 status
= read(j0_fd
, &js_data
, JS_RETURN
);
186 if (status
!= JS_RETURN
)
192 j0_max_left
=js_data
.x
-100;
193 j0_max_right
=js_data
.x
+100;
194 j0_max_up
=js_data
.y
-100;
195 j0_max_down
=js_data
.y
+100;
198 j1_fd
= open ("/dev/js1", O_RDONLY
);
199 if (j1_fd
< 0) return 1;
200 status
= read(j1_fd
, &js_data
, JS_RETURN
);
201 if (status
!= JS_RETURN
)
207 j1_max_left
=js_data
.x
-100;
208 j1_max_right
=js_data
.x
+100;
209 j1_max_up
=js_data
.y
-100;
210 j1_max_down
=js_data
.y
+100;
216 /* This functions cleans up all joystick related stuff */
217 void joystick_close(void)
219 if (j0_fd
> -1) close(j0_fd
);
220 if (j1_fd
> -1) close(j1_fd
);
223 /* This function reads the current joystick values and stores
224 them in the joydata structs which are given.
225 joy0 is mandatory, joy1 is optional and maybe NULL.
226 This functions returns:
228 1 if reading for joy0 failed
229 2 if reading for joy1 failed
231 The data stored in the structs is only valid when this functions
232 returns 0! The call will fail when joy2 is not NULL and only
233 one joystick is detected. (although the data in joy0 will still
235 int joystick_read(struct joy_data
*joy0
, struct joy_data
*joy1
)
238 struct JS_DATA_TYPE js_data
={0,0,0};
240 if (nr_of_joysticks
< 1 || joy0
== NULL
) return 1;
241 if ((status
= read (j0_fd
, &js_data
, JS_RETURN
)) != JS_RETURN
) return 1;
242 memset(joy0
, 0, sizeof(struct joy_data
));
244 if (js_data
.x
< j0_max_left
) j0_max_left
=js_data
.x
;
245 if (js_data
.x
> j0_max_right
) j0_max_right
=js_data
.x
;
246 if (js_data
.y
< j0_max_up
) j0_max_up
=js_data
.y
;
247 if (js_data
.y
> j0_max_down
) j0_max_down
=js_data
.y
;
249 if (js_data
.x
< (j0_max_right
-j0_max_left
)*.25+j0_max_left
) joy0
->left
=1;
250 else if (js_data
.x
> (j0_max_right
-j0_max_left
)*.75+j0_max_left
) joy0
->right
=1;
251 if (js_data
.y
< (j0_max_down
-j0_max_up
)*.25+j0_max_up
) joy0
->up
=1;
252 else if (js_data
.y
> (j0_max_down
-j0_max_up
)*.75+j0_max_up
) joy0
->down
=1;
254 if (js_data
.buttons
& 0x01) joy0
->buttons
[0] = 1;
255 if (js_data
.buttons
& 0x02) joy0
->buttons
[1] = 1;
256 if (js_data
.buttons
& 0x04) joy0
->buttons
[2] = 1;
257 if (js_data
.buttons
& 0x08) joy0
->buttons
[3] = 1;
259 if (joy1
== NULL
) return 0;
260 if (nr_of_joysticks
< 2) return 2;
261 if ((status
= read (j1_fd
, &js_data
, JS_RETURN
)) != JS_RETURN
) return 2;
262 memset(joy1
, 0, sizeof(struct joy_data
));
264 if (js_data
.x
< j1_max_left
) j1_max_left
=js_data
.x
;
265 if (js_data
.x
> j1_max_right
) j1_max_right
=js_data
.x
;
266 if (js_data
.y
< j1_max_up
) j1_max_up
=js_data
.y
;
267 if (js_data
.y
> j1_max_down
) j1_max_down
=js_data
.y
;
269 if (js_data
.x
< (j1_max_right
-j1_max_left
)*.25+j1_max_left
) joy1
->left
=1;
270 else if (js_data
.x
> (j1_max_right
-j1_max_left
)*.75+j1_max_left
) joy1
->right
=1;
271 if (js_data
.y
< (j1_max_down
-j1_max_up
)*.25+j1_max_up
) joy1
->up
=1;
272 else if (js_data
.y
> (j1_max_down
-j1_max_up
)*.75+j1_max_up
) joy1
->down
=1;
274 if (js_data
.buttons
& 0x01) joy1
->buttons
[0] = 1;
275 if (js_data
.buttons
& 0x02) joy1
->buttons
[1] = 1;
276 if (js_data
.buttons
& 0x04) joy1
->buttons
[2] = 1;
277 if (js_data
.buttons
& 0x08) joy1
->buttons
[3] = 1;