rev |
line source |
nuclear@0
|
1 /* This file implements all calls made to dos-specific code using SDL
|
nuclear@0
|
2 * Don't ask why ...
|
nuclear@0
|
3 */
|
nuclear@0
|
4
|
nuclear@0
|
5 #include <stdlib.h>
|
nuclear@0
|
6 #include <assert.h>
|
nuclear@0
|
7 #include <SDL.h>
|
nuclear@38
|
8 #include <imago2.h>
|
nuclear@24
|
9 #include "wvga.h"
|
nuclear@0
|
10 #include "conio.h"
|
nuclear@0
|
11 #include "mouse.h"
|
nuclear@34
|
12 #include "keyb.h"
|
nuclear@0
|
13 #include "timer.h"
|
nuclear@0
|
14
|
nuclear@0
|
15 static void proc_events(void);
|
nuclear@38
|
16 static void capture_frame(unsigned char *frame);
|
nuclear@0
|
17
|
nuclear@34
|
18 static void init_sdl()
|
nuclear@34
|
19 {
|
nuclear@35
|
20 const SDL_version *ver;
|
nuclear@35
|
21
|
nuclear@34
|
22 if(!SDL_WasInit(SDL_INIT_EVERYTHING)) {
|
nuclear@34
|
23 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
nuclear@35
|
24
|
nuclear@35
|
25 if((ver = SDL_Linked_Version())) {
|
nuclear@35
|
26 printf("SDL %d.%d.%d initialized\n", ver->major, ver->minor, ver->patch);
|
nuclear@35
|
27 }
|
nuclear@34
|
28 }
|
nuclear@34
|
29 }
|
nuclear@34
|
30
|
nuclear@24
|
31 /* ----- graphics (wvga.c implementation) ----- */
|
nuclear@0
|
32 static SDL_Surface *fbsurf;
|
nuclear@35
|
33 static int scale = 3;
|
nuclear@38
|
34 static int frames_to_capture;
|
nuclear@38
|
35
|
nuclear@38
|
36 static struct {
|
nuclear@38
|
37 unsigned char r, g, b;
|
nuclear@38
|
38 } palette[256];
|
nuclear@38
|
39
|
nuclear@0
|
40
|
nuclear@24
|
41 int set_video_mode(int mode)
|
nuclear@0
|
42 {
|
nuclear@0
|
43 int resx = 320, resy = 200;
|
nuclear@9
|
44 unsigned int sdl_flags = SDL_HWPALETTE;
|
nuclear@28
|
45 char *env;
|
nuclear@0
|
46
|
nuclear@0
|
47 if(getenv("DOSEMU_DOUBLESIZE")) {
|
nuclear@28
|
48 scale = 2;
|
nuclear@0
|
49 }
|
nuclear@0
|
50
|
nuclear@28
|
51 if((env = getenv("DOSEMU_SCALE"))) {
|
nuclear@28
|
52 int n = atoi(env);
|
nuclear@28
|
53 if(n > 0) {
|
nuclear@28
|
54 scale = n;
|
nuclear@28
|
55 }
|
nuclear@28
|
56 }
|
nuclear@28
|
57 resx *= scale;
|
nuclear@28
|
58 resy *= scale;
|
nuclear@28
|
59
|
nuclear@9
|
60 if(getenv("DOSEMU_FULLSCREEN")) {
|
nuclear@9
|
61 sdl_flags |= SDL_FULLSCREEN;
|
nuclear@9
|
62 }
|
nuclear@9
|
63
|
nuclear@34
|
64 init_sdl();
|
nuclear@34
|
65
|
nuclear@0
|
66 switch(mode) {
|
nuclear@0
|
67 case 0x13:
|
nuclear@9
|
68 if(!(fbsurf = SDL_SetVideoMode(resx, resy, 8, sdl_flags))) {
|
nuclear@0
|
69 fprintf(stderr, "failed to set video mode\n");
|
nuclear@0
|
70 abort();
|
nuclear@0
|
71 }
|
nuclear@25
|
72 SDL_WM_SetCaption("Deepstone", 0);
|
nuclear@28
|
73 /*SDL_ShowCursor(0);*/
|
nuclear@34
|
74 /*SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);*/
|
nuclear@0
|
75 break;
|
nuclear@0
|
76
|
nuclear@0
|
77 case 3:
|
nuclear@0
|
78 SDL_ShowCursor(1);
|
nuclear@11
|
79 SDL_EnableKeyRepeat(0, 0);
|
nuclear@0
|
80 SDL_Quit();
|
nuclear@0
|
81 break;
|
nuclear@0
|
82
|
nuclear@0
|
83 default:
|
nuclear@0
|
84 break;
|
nuclear@0
|
85 }
|
nuclear@24
|
86
|
nuclear@24
|
87 return 0;
|
nuclear@0
|
88 }
|
nuclear@0
|
89
|
nuclear@24
|
90 void set_palette(int idx, int *col, int count)
|
nuclear@24
|
91 {
|
nuclear@24
|
92 int i;
|
nuclear@24
|
93
|
nuclear@24
|
94 for(i=0; i<count; i++) {
|
nuclear@24
|
95 set_pal_entry(idx + i, col[0], col[1], col[2]);
|
nuclear@24
|
96 col += 3;
|
nuclear@24
|
97 }
|
nuclear@24
|
98 }
|
nuclear@24
|
99
|
nuclear@24
|
100 void set_pal_entry(int idx, int r, int g, int b)
|
nuclear@0
|
101 {
|
nuclear@0
|
102 SDL_Color col;
|
nuclear@0
|
103 col.r = r;
|
nuclear@0
|
104 col.g = g;
|
nuclear@0
|
105 col.b = b;
|
nuclear@0
|
106
|
nuclear@24
|
107 if(SDL_SetPalette(fbsurf, SDL_LOGPAL | SDL_PHYSPAL, &col, idx, 1) != 1) {
|
nuclear@0
|
108 fprintf(stderr, "set_palette failed to set the required color\n");
|
nuclear@0
|
109 }
|
nuclear@38
|
110
|
nuclear@38
|
111 palette[idx].r = r;
|
nuclear@38
|
112 palette[idx].g = g;
|
nuclear@38
|
113 palette[idx].b = b;
|
nuclear@0
|
114 }
|
nuclear@0
|
115
|
nuclear@24
|
116 void copy_frame(void *pixels)
|
nuclear@0
|
117 {
|
nuclear@24
|
118 unsigned char *frame = (unsigned char*)pixels;
|
nuclear@24
|
119
|
nuclear@0
|
120 if(SDL_MUSTLOCK(fbsurf)) {
|
nuclear@0
|
121 SDL_LockSurface(fbsurf);
|
nuclear@0
|
122 }
|
nuclear@0
|
123
|
nuclear@28
|
124 if(scale > 1) {
|
nuclear@28
|
125 int i, j, xsz, ysz;
|
nuclear@28
|
126 unsigned char *dest = fbsurf->pixels;
|
nuclear@0
|
127
|
nuclear@28
|
128 xsz = 320 * scale;
|
nuclear@28
|
129 ysz = 200 * scale;
|
nuclear@28
|
130
|
nuclear@28
|
131 for(i=0; i<ysz; i++) {
|
nuclear@28
|
132 for(j=0; j<xsz; j++) {
|
nuclear@28
|
133 *dest++ = frame[(i / scale) * 320 + (j / scale)];
|
nuclear@0
|
134 }
|
nuclear@0
|
135 }
|
nuclear@0
|
136 } else {
|
nuclear@0
|
137 memcpy(fbsurf->pixels, frame, 64000);
|
nuclear@0
|
138 }
|
nuclear@0
|
139
|
nuclear@0
|
140 if(SDL_MUSTLOCK(fbsurf)) {
|
nuclear@0
|
141 SDL_UnlockSurface(fbsurf);
|
nuclear@0
|
142 }
|
nuclear@0
|
143 SDL_Flip(fbsurf);
|
nuclear@34
|
144
|
nuclear@38
|
145 if(frames_to_capture > 0) {
|
nuclear@38
|
146 capture_frame(pixels);
|
nuclear@38
|
147 --frames_to_capture;
|
nuclear@38
|
148 }
|
nuclear@34
|
149
|
nuclear@34
|
150 /* also print fps every second ... */
|
nuclear@34
|
151 {
|
nuclear@34
|
152 static long prev_fps, num_frames;
|
nuclear@34
|
153 long msec, dt;
|
nuclear@34
|
154
|
nuclear@34
|
155 msec = get_msec();
|
nuclear@34
|
156 dt = msec - prev_fps;
|
nuclear@34
|
157 if(dt >= 1000) {
|
nuclear@34
|
158 float fps = (float)num_frames / ((float)dt / 1000.0f);
|
nuclear@34
|
159 printf("framerate: %.1f \r", fps);
|
nuclear@34
|
160 fflush(stdout);
|
nuclear@34
|
161 num_frames = 0;
|
nuclear@34
|
162 prev_fps = msec;
|
nuclear@34
|
163 } else {
|
nuclear@34
|
164 num_frames++;
|
nuclear@34
|
165 }
|
nuclear@34
|
166 }
|
nuclear@0
|
167 }
|
nuclear@0
|
168
|
nuclear@38
|
169 #define spin_delay(ms) \
|
nuclear@38
|
170 do { \
|
nuclear@38
|
171 unsigned int end = SDL_GetTicks() + ms; \
|
nuclear@38
|
172 while((prev_msec = SDL_GetTicks()) < end); \
|
nuclear@38
|
173 } while(0)
|
nuclear@38
|
174
|
nuclear@38
|
175 #define FRAME_INTERVAL (1000/70)
|
nuclear@0
|
176 void wait_vsync(void)
|
nuclear@0
|
177 {
|
nuclear@38
|
178 static int prev_msec;
|
nuclear@38
|
179 int msec, dt, tleft;
|
nuclear@38
|
180
|
nuclear@38
|
181 msec = SDL_GetTicks();
|
nuclear@38
|
182
|
nuclear@38
|
183 dt = msec - prev_msec;
|
nuclear@38
|
184
|
nuclear@38
|
185 tleft = FRAME_INTERVAL - dt;
|
nuclear@38
|
186 if(tleft > 0) {
|
nuclear@38
|
187 int coarse = tleft & 0xfffffff8;
|
nuclear@38
|
188 tleft = tleft & 7;
|
nuclear@38
|
189
|
nuclear@38
|
190 if(coarse) {
|
nuclear@38
|
191 SDL_Delay(coarse);
|
nuclear@38
|
192 }
|
nuclear@38
|
193 if(tleft) {
|
nuclear@38
|
194 spin_delay(tleft);
|
nuclear@38
|
195 } else {
|
nuclear@38
|
196 prev_msec = SDL_GetTicks();
|
nuclear@38
|
197 }
|
nuclear@38
|
198 } else {
|
nuclear@38
|
199 prev_msec = msec;
|
nuclear@38
|
200 }
|
nuclear@0
|
201 }
|
nuclear@0
|
202
|
nuclear@38
|
203 static int cap_count = 0;
|
nuclear@38
|
204 void begin_capture(int frames)
|
nuclear@38
|
205 {
|
nuclear@38
|
206 frames_to_capture = frames;
|
nuclear@38
|
207 }
|
nuclear@38
|
208
|
nuclear@38
|
209 void end_capture(void)
|
nuclear@38
|
210 {
|
nuclear@38
|
211 cap_count = 0;
|
nuclear@38
|
212 frames_to_capture = 0;
|
nuclear@38
|
213 }
|
nuclear@38
|
214
|
nuclear@38
|
215 #define NUMPIX (320 * 200)
|
nuclear@38
|
216 static void capture_frame(unsigned char *frame)
|
nuclear@38
|
217 {
|
nuclear@38
|
218 static unsigned char rgbpix[NUMPIX * 4];
|
nuclear@38
|
219 char fname[32];
|
nuclear@38
|
220 int i;
|
nuclear@38
|
221 unsigned char *src, *dest;
|
nuclear@38
|
222
|
nuclear@38
|
223 sprintf(fname, "frame%04d.png", cap_count++);
|
nuclear@38
|
224
|
nuclear@38
|
225 src = frame;
|
nuclear@38
|
226 dest = rgbpix;
|
nuclear@38
|
227
|
nuclear@38
|
228 for(i=0; i<NUMPIX; i++) {
|
nuclear@38
|
229 unsigned char c = *src++;
|
nuclear@38
|
230 *dest++ = palette[c].r;
|
nuclear@38
|
231 *dest++ = palette[c].g;
|
nuclear@38
|
232 *dest++ = palette[c].b;
|
nuclear@38
|
233 *dest++ = 255;
|
nuclear@38
|
234 }
|
nuclear@38
|
235
|
nuclear@38
|
236 img_save_pixels(fname, rgbpix, 320, 200, IMG_FMT_RGBA32);
|
nuclear@38
|
237 }
|
nuclear@38
|
238
|
nuclear@38
|
239
|
nuclear@0
|
240 /* ----- event handling (conio.h) ----- */
|
nuclear@0
|
241 static SDL_Event *keybev;
|
nuclear@0
|
242 static int mousex, mousey, bnmask;
|
nuclear@0
|
243
|
nuclear@34
|
244 static int keystate[256];
|
nuclear@34
|
245 static int num_pressed;
|
nuclear@34
|
246
|
nuclear@0
|
247 int kbhit(void)
|
nuclear@0
|
248 {
|
nuclear@0
|
249 if(!keybev) {
|
nuclear@0
|
250 proc_events();
|
nuclear@0
|
251 }
|
nuclear@0
|
252 return keybev != 0;
|
nuclear@0
|
253 }
|
nuclear@0
|
254
|
nuclear@9
|
255 int getch(void)
|
nuclear@0
|
256 {
|
nuclear@9
|
257 int res;
|
nuclear@0
|
258
|
nuclear@0
|
259 while(!keybev) {
|
nuclear@0
|
260 SDL_Event ev;
|
nuclear@0
|
261 SDL_WaitEvent(&ev);
|
nuclear@0
|
262 SDL_PushEvent(&ev);
|
nuclear@0
|
263 proc_events();
|
nuclear@0
|
264 }
|
nuclear@0
|
265 res = keybev->key.keysym.sym;
|
nuclear@0
|
266 keybev = 0;
|
nuclear@0
|
267 return res;
|
nuclear@0
|
268 }
|
nuclear@0
|
269
|
nuclear@34
|
270 /* ----- improved event handling (keyb.h) ---- */
|
nuclear@34
|
271
|
nuclear@34
|
272 int kb_init(int bufsz)
|
nuclear@34
|
273 {
|
nuclear@34
|
274 init_sdl();
|
nuclear@34
|
275
|
nuclear@34
|
276 return 0;
|
nuclear@34
|
277 }
|
nuclear@34
|
278
|
nuclear@34
|
279 void kb_shutdown(void)
|
nuclear@34
|
280 {
|
nuclear@34
|
281 }
|
nuclear@34
|
282
|
nuclear@34
|
283 int kb_getkey(void)
|
nuclear@34
|
284 {
|
nuclear@34
|
285 int res = -1;
|
nuclear@34
|
286
|
nuclear@34
|
287 proc_events();
|
nuclear@34
|
288 if(keybev) {
|
nuclear@34
|
289 res = keybev->key.keysym.sym;
|
nuclear@34
|
290 keybev = 0;
|
nuclear@34
|
291 }
|
nuclear@34
|
292 return res;
|
nuclear@34
|
293 }
|
nuclear@34
|
294
|
nuclear@34
|
295 int kb_isdown(int key)
|
nuclear@34
|
296 {
|
nuclear@34
|
297 if(key == KB_ANY) {
|
nuclear@34
|
298 return num_pressed;
|
nuclear@34
|
299 }
|
nuclear@34
|
300 return keystate[key];
|
nuclear@34
|
301 }
|
nuclear@34
|
302
|
nuclear@0
|
303 /* mouse handling (mouse.c implementation) */
|
nuclear@34
|
304 static unsigned long last_mouse_hide_time;
|
nuclear@34
|
305
|
nuclear@0
|
306 int have_mouse(void)
|
nuclear@0
|
307 {
|
nuclear@0
|
308 return 1;
|
nuclear@0
|
309 }
|
nuclear@0
|
310
|
nuclear@34
|
311 void set_mouse(int x, int y)
|
nuclear@34
|
312 {
|
nuclear@36
|
313 SDL_ShowCursor(0);
|
nuclear@36
|
314 last_mouse_hide_time = get_msec();
|
nuclear@34
|
315
|
nuclear@34
|
316 SDL_WarpMouse(x * scale, y * scale);
|
nuclear@34
|
317 mousex = x;
|
nuclear@34
|
318 mousey = y;
|
nuclear@34
|
319 }
|
nuclear@34
|
320
|
nuclear@0
|
321 int read_mouse(int *xp, int *yp)
|
nuclear@0
|
322 {
|
nuclear@0
|
323 if(xp) *xp = mousex;
|
nuclear@0
|
324 if(yp) *yp = mousey;
|
nuclear@0
|
325 return bnmask;
|
nuclear@0
|
326 }
|
nuclear@0
|
327
|
nuclear@0
|
328 static void proc_events(void)
|
nuclear@0
|
329 {
|
nuclear@0
|
330 static SDL_Event ev;
|
nuclear@0
|
331
|
nuclear@34
|
332 if(last_mouse_hide_time > 0 && get_msec() - last_mouse_hide_time > 3000) {
|
nuclear@34
|
333 last_mouse_hide_time = 0;
|
nuclear@34
|
334 SDL_ShowCursor(1);
|
nuclear@34
|
335 }
|
nuclear@34
|
336
|
nuclear@0
|
337 while(SDL_PollEvent(&ev)) {
|
nuclear@0
|
338 switch(ev.type) {
|
nuclear@0
|
339 case SDL_KEYDOWN:
|
nuclear@34
|
340 {
|
nuclear@34
|
341 int key = ev.key.keysym.sym;
|
nuclear@34
|
342
|
nuclear@34
|
343 if(!keybev) {
|
nuclear@34
|
344 keybev = &ev;
|
nuclear@34
|
345 }
|
nuclear@34
|
346
|
nuclear@34
|
347 if(!keystate[key]) {
|
nuclear@34
|
348 keystate[key] = 1;
|
nuclear@34
|
349 num_pressed++;
|
nuclear@34
|
350 }
|
nuclear@34
|
351 }
|
nuclear@34
|
352 break;
|
nuclear@34
|
353
|
nuclear@34
|
354 case SDL_KEYUP:
|
nuclear@34
|
355 {
|
nuclear@34
|
356 int key = ev.key.keysym.sym;
|
nuclear@34
|
357
|
nuclear@34
|
358 if(keystate[key]) {
|
nuclear@34
|
359 keystate[key] = 0;
|
nuclear@34
|
360 if(--num_pressed < 0) {
|
nuclear@34
|
361 num_pressed = 0;
|
nuclear@34
|
362 }
|
nuclear@34
|
363 }
|
nuclear@34
|
364 }
|
nuclear@34
|
365 break;
|
nuclear@0
|
366
|
nuclear@0
|
367 case SDL_MOUSEMOTION:
|
nuclear@28
|
368 mousex = ev.motion.x / scale;
|
nuclear@28
|
369 mousey = ev.motion.y / scale;
|
nuclear@0
|
370 break;
|
nuclear@0
|
371
|
nuclear@0
|
372 case SDL_MOUSEBUTTONDOWN:
|
nuclear@0
|
373 case SDL_MOUSEBUTTONUP:
|
nuclear@0
|
374 {
|
nuclear@0
|
375 int mask = 0;
|
nuclear@0
|
376 switch(ev.button.button) {
|
nuclear@0
|
377 case SDL_BUTTON_LEFT:
|
nuclear@0
|
378 mask = MOUSE_LEFT;
|
nuclear@0
|
379 break;
|
nuclear@0
|
380 case SDL_BUTTON_MIDDLE:
|
nuclear@0
|
381 mask = MOUSE_MIDDLE;
|
nuclear@0
|
382 break;
|
nuclear@0
|
383 case SDL_BUTTON_RIGHT:
|
nuclear@0
|
384 mask = MOUSE_RIGHT;
|
nuclear@0
|
385 default:
|
nuclear@0
|
386 break;
|
nuclear@0
|
387 }
|
nuclear@0
|
388 if(!mask) {
|
nuclear@0
|
389 break;
|
nuclear@0
|
390 }
|
nuclear@0
|
391
|
nuclear@0
|
392 if(ev.button.state == SDL_PRESSED) {
|
nuclear@0
|
393 bnmask |= mask;
|
nuclear@0
|
394 } else {
|
nuclear@0
|
395 bnmask &= ~mask;
|
nuclear@0
|
396 }
|
nuclear@0
|
397 }
|
nuclear@0
|
398 break;
|
nuclear@0
|
399
|
nuclear@0
|
400 default:
|
nuclear@0
|
401 break;
|
nuclear@0
|
402 }
|
nuclear@0
|
403 }
|
nuclear@0
|
404 }
|
nuclear@0
|
405
|
nuclear@0
|
406 /* ---- timer.c implementation ---- */
|
nuclear@0
|
407 static Uint32 start_time;
|
nuclear@0
|
408
|
nuclear@0
|
409 void init_timer(int res_hz)
|
nuclear@0
|
410 {
|
nuclear@34
|
411 init_sdl();
|
nuclear@0
|
412 reset_timer();
|
nuclear@0
|
413 }
|
nuclear@0
|
414
|
nuclear@0
|
415 void reset_timer(void)
|
nuclear@0
|
416 {
|
nuclear@0
|
417 start_time = SDL_GetTicks();
|
nuclear@34
|
418 printf("resetting timer: %u, %lu\n", start_time, get_msec());
|
nuclear@0
|
419 }
|
nuclear@0
|
420
|
nuclear@0
|
421 unsigned long get_msec(void)
|
nuclear@0
|
422 {
|
nuclear@34
|
423 Uint32 ticks = SDL_GetTicks();
|
nuclear@34
|
424 return (unsigned long)(ticks - start_time);
|
nuclear@0
|
425 }
|