|
|
1.1 root 1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
2:
3: /* generic 640x480 console mode */
4:
5: /* I call the first field the even field and the second field the odd field,
6: sorry - I counted lines from 0 when I wrote the code... strictly speaking
7: this is confusing... (it confuses me) */
8:
1.1.1.2 root 9: /* there must be a uip-xxx.c file to go with this user interface - all
10: platform dependent calls are in the uip file - see uip.h for the calls
11: required */
12:
1.1 root 13: #include <sys/types.h>
14: #include <sys/stat.h>
15: #include <fcntl.h>
16: #include <stdlib.h>
17: #include <stdio.h>
18: #include <stdarg.h>
19: #include <time.h>
20: #include <string.h>
21: #include <unistd.h>
22: #include <errno.h>
23:
24: #include "generator.h"
25: #include "snprintf.h"
26:
27: #include "cpu68k.h"
28: #include "cpuz80.h"
29: #include "ui.h"
30: #include "vdp.h"
31: #include "event.h"
32: #include "gensound.h"
33: #include "mem68k.h"
34: #include "logo.h"
35: #include "font.h"
36: #include "uip.h"
37: #include "ui-console.h"
38: #include "state.h"
1.1.1.3 ! root 39: #include "uiplot.h"
1.1 root 40:
41: #define UI_LOGLINESIZE 128
42: #define UI_LOGLINES 64
43:
44: uint32 ui_fkeys = 0;
45:
1.1.1.2 root 46: uint8 ui_vdpsimple = 0; /* 0=raster, 1=cell based plotter */
47: uint8 ui_clearnext = 0; /* flag indicating redraw required */
48: uint8 ui_fullscreen = 0; /* does the user want full screen or not */
49: uint8 ui_info = 1; /* does the user want info onscreen or not */
50: uint8 ui_vsync = 0; /* does the user want us to wait for vsync */
51: t_binding ui_bindings[2]; /* keyboard/joystick bindings for players */
52:
53: t_interlace ui_interlace = DEINTERLACE_WEAVEFILTER;
1.1 root 54:
55: /*** forward reference declarations ***/
56:
57: static void ui_usage(void);
58: void ui_exithandler(void);
59: void ui_newframe(void);
60: void ui_plotsprite_acorn(uint16 *logo, uint16 width, uint16 height,
1.1.1.2 root 61: uint16 x, uint16 y);
1.1 root 62: int ui_unpackfont(void);
63: uint16 ui_plotstring(const char *text, uint16 xpos, uint16 ypos);
64: uint16 ui_plotint2(uint8 num, uint16 xpos, uint16 ypos);
65: void ui_plotsettings(void);
66: void ui_drawbox(uint16 colour, uint16 x, uint16 y, uint16 width,
67: uint16 height);
68: void ui_rendertoscreen(void);
69: void ui_basicbits(void);
70: void ui_licensescreen(void);
71: void ui_imagescreen(void);
72: void ui_imagescreen_main(void);
73: void ui_statescreen(void);
74: void ui_statescreen_main(void);
75: int ui_statescreen_loadsavestate(int save);
76: void ui_resetscreen(void);
77: void ui_resetscreen_main(void);
78: int ui_saveimage(const char *type, char *filename, int buflen,
79: int *xsize, int *ysize);
80: int ui_setcolourbits(const char *str);
1.1.1.2 root 81: int ui_setcontrollers(const char *str);
1.1 root 82:
1.1.1.3 ! root 83: static void ui_simpleplot(void);
! 84:
1.1 root 85: /* we store up log lines and dump them right at the end for allegro */
86: #ifdef ALLEGRO
87: void ui_printlog(void);
1.1.1.3 ! root 88: static uint32 ui_logline = 0;
! 89: static char ui_loglines[UI_LOGLINES][UI_LOGLINESIZE];
! 90: static uint16 ui_logcount = 0; /* log counter */
1.1 root 91: #endif
92:
93: /*** static variables ***/
94:
1.1.1.2 root 95: static uint8 ui_vga = 0; /* flag for whether in VGA more or not */
96: static uint8 ui_frameskip = 0; /* 0 for dynamic */
97: static uint8 ui_actualskip = 0; /* the last skip we did (1..) */
98: static uint8 ui_state = 0; /* 0=stop, 1=paused, 2=play */
99: static char *ui_initload = NULL; /* filename to load on init */
100: static uint8 ui_plotfield = 0; /* flag indicating plotting this field */
101: static uint8 ui_plotprevfield = 0; /* did we plot the previous field? */
102: static uint16 *ui_font; /* unpacked font */
103: static uint8 bigbuffer[8192]; /* stupid no-vsnprintf platforms */
104: static t_uipinfo ui_uipinfo; /* uipinfo filled in by uip 'sub-system' */
105: static uint16 *ui_screen0; /* pointer to screen block for bank 0 */
106: static uint16 *ui_screen1; /* pointer to screen block for bank 1 */
107: static uint16 *ui_newscreen; /* pointer to new screen block */
108: static int ui_saverom; /* flag to save rom and quit */
109: static int ui_joysticks = 0; /* number of joysticks */
1.1 root 110:
1.1.1.3 ! root 111: static uint16 ui_screen[3][320 * 240]; /* screen buffers */
1.1 root 112:
113: /*** Program entry point ***/
114:
115: int ui_init(int argc, char *argv[])
116: {
117: int i;
118: int ch;
119:
1.1.1.2 root 120: ui_bindings[0].joystick = -1; /* -1 = use keyboard */
121: ui_bindings[0].keyboard = 0; /* 0 = main keyboard */
122: ui_bindings[1].joystick = -1; /* -1 = use keyboard */
123: ui_bindings[1].keyboard = -1; /* -1 = no keyboard */
124:
1.1.1.3 ! root 125: i = 0; /* supress warning */
! 126: #ifdef ALLEGRO
1.1.1.2 root 127: for (i = 0; i < UI_LOGLINES; i++)
1.1 root 128: ui_loglines[i][0] = '\0';
1.1.1.3 ! root 129: #endif
1.1 root 130: if (ui_unpackfont() == -1) {
131: fprintf(stderr, "Failed to unpack font, out of memory?\n");
132: return 1;
133: }
1.1.1.2 root 134: while ((ch = getopt(argc, argv, "i:c:w:f:sd:v:l:j:k:")) != -1) {
1.1 root 135: switch (ch) {
1.1.1.2 root 136: case 'c': /* set colour bit positions */
137: if (ui_setcolourbits(optarg)) {
138: fprintf(stderr, "-c option not understood, must be "
139: "'red,green,blue'\n");
140: return 1;
141: }
142: break;
143: case 'i': /* de-interlacing mode */
144: if (!strcasecmp(optarg, "bob")) {
145: ui_interlace = DEINTERLACE_BOB;
146: } else if (!strcasecmp(optarg, "weave")) {
147: ui_interlace = DEINTERLACE_WEAVE;
148: } else if (!strcasecmp(optarg, "weave-filter")) {
149: ui_interlace = DEINTERLACE_WEAVEFILTER;
150: } else {
151: fprintf(stderr, "-i option not understood, must be "
152: "bob|weave|weave-filter\n");
153: return 1;
154: }
155: break;
156: case 'd': /* enable sound debug mode */
157: /* re-write this to cope with comma separated items later */
158: if (!strcasecmp(optarg, "sound"))
159: sound_debug = 1;
160: break;
161: case 'j': /* configure keyboard bindings */
162: if (ui_setcontrollers(optarg)) {
163: fprintf(stderr, "-j option not understood\n");
164: return 1;
165: }
166: break;
167: case 's': /* save raw format rom */
168: ui_saverom = 1;
169: break;
170: case 'l': /* set min fields / audio latency */
171: sound_minfields = atoi(optarg);
172: break;
173: case 'f': /* set max fields / audio fragments */
174: sound_maxfields = atoi(optarg);
175: break;
176: case 'k': /* set frame skip */
177: ui_frameskip = atoi(optarg);
178: break;
179: case 'v': /* set log verbosity level */
180: gen_loglevel = atoi(optarg);
181: break;
182: case 'w': /* saved game work dir */
183: chdir(optarg); /* for the moment this will do */
184: break;
185: case '?':
186: default:
187: ui_usage();
1.1 root 188: }
189: }
1.1.1.2 root 190: argc -= optind;
191: argv += optind;
192:
1.1 root 193: if (argc < 1 || argc > 3)
194: ui_usage();
1.1.1.2 root 195: if ((ui_initload = malloc(strlen(argv[0]) + 1)) == NULL) {
1.1 root 196: fprintf(stderr, "Out of memory\n");
197: return 1;
198: }
199: strcpy(ui_initload, argv[0]);
200:
201: if (atexit(ui_exithandler) == -1) {
202: LOG_CRITICAL(("Failed to set exit handler"));
203: return 1;
204: }
205: if (uip_init(&ui_uipinfo)) {
206: LOG_CRITICAL(("Failed to initialise platform dependent UI"));
207: return 1;
208: }
1.1.1.2 root 209: ui_joysticks = uip_initjoysticks();
210: LOG_VERBOSE(("%d joysticks detected", ui_joysticks));
211:
212: if (ui_bindings[0].joystick >= ui_joysticks) {
213: LOG_CRITICAL(("Invalid joystick selected for first player"));
214: return 1;
215: }
216: if (ui_bindings[1].joystick >= ui_joysticks) {
217: LOG_CRITICAL(("Invalid joystick selected for second player"));
218: return 1;
219: }
220: if (ui_bindings[0].joystick == ui_bindings[1].joystick &&
221: ui_bindings[0].joystick >= 0) {
222: LOG_CRITICAL(("The same joystick was selected for both players!"));
223: return 1;
224: }
225: if (ui_bindings[0].joystick == -1 && ui_bindings[0].joystick == -1) {
226: if (ui_bindings[0].keyboard == ui_bindings[1].keyboard) {
227: LOG_CRITICAL(("The same keyboard position was selected for "
228: "both players!"));
229: return 1;
230: }
231: if ((ui_bindings[0].keyboard == 0 && ui_bindings[1].keyboard != -1) ||
232: (ui_bindings[1].keyboard == 0 && ui_bindings[0].keyboard != -1)) {
233: LOG_CRITICAL(("Invalid keyboard configuration"));
234: return 1;
235: }
236: }
1.1 root 237: /* ui_newscreen is where the emulation data is rendered to - it is
238: then compared with ui_screen0 or ui_screen1 depending on which
239: screen bank it is being written to, and the delta changes are sent
240: to screen memory. The ui_screenX and ui_newscreen pointers are then
241: switched, and the next frame/field begins... */
242: memset(ui_screen[0], 0, sizeof(ui_screen[0]));
243: memset(ui_screen[1], 0, sizeof(ui_screen[1]));
244: ui_screen0 = ui_screen[0];
245: ui_screen1 = ui_screen[1];
246: ui_newscreen = ui_screen[2];
247: return 0;
248: }
249:
250: void ui_usage(void)
251: {
252: fprintf(stderr, "Generator is (c) James Ponder 1997-2001, all rights "
1.1.1.3 ! root 253: "reserved. " VERSION "\n\n");
1.1 root 254: fprintf(stderr, "generator [options] <rom>\n\n");
255: fprintf(stderr, " -v <verbose level> can be: 0 = none, 1 = critical, "
1.1.1.2 root 256: "2 = normal, 3 = verbose\n");
1.1 root 257: fprintf(stderr, " -d sound - turns on debug mode for sound\n");
258: fprintf(stderr, " -l <sound latency> is the number of video fields worth "
1.1.1.2 root 259: "of sound to\n try to keep buffered (default 5)\n");
1.1 root 260: fprintf(stderr, " -f <sound fragments> is the number of video fields worth "
1.1.1.2 root 261: "of sound to\n allow buffered (approx) (default 10)\n");
1.1 root 262: fprintf(stderr, " -w <work dir> indicates where saved games are stored "
1.1.1.2 root 263: "(default is current dir)\n");
1.1 root 264: fprintf(stderr, " -c [<r>,<g>,<b>] sets the colour bit positions of where "
1.1.1.2 root 265: "red, green and blue\n 5-bit values should be shifted "
266: "to (default 10,5,0 for 15-bit modes)\n");
1.1 root 267: fprintf(stderr, " -i <mode> selects de-interlace mode, one of: bob "
1.1.1.2 root 268: "weave weave-filter\n");
1.1 root 269: fprintf(stderr, " -k <x> forces the frame step (1=all frames, 2=every other,"
1.1.1.2 root 270: " etc.)\n");
271: fprintf(stderr, " -j <pad1>,<pad2> sets the input device for each joypad "
272: "(default key0,none)\n");
1.1 root 273: fprintf(stderr, " -s will save the ROM to the work directory in raw "
1.1.1.2 root 274: "format\n\n");
1.1 root 275: fprintf(stderr, " ROM types supported: .rom or .smd interleaved "
1.1.1.2 root 276: "(autodetected)\n");
1.1 root 277: fprintf(stderr, " Sound latency will be kept between -l and -a values. "
1.1.1.2 root 278: "If you are having sound\n problems try -l 20 -f 30\n");
1.1 root 279: exit(1);
280: }
281:
282: #ifdef ALLEGRO
283: void ui_printlog(void)
284: {
285: unsigned int i;
286: char *p;
287:
288: printf("**** Last lines logged:\n");
1.1.1.2 root 289: for (i = ui_logline; i < (UI_LOGLINES + ui_logline); i++) {
290: p = ui_loglines[(i < UI_LOGLINES) ? i : (i - UI_LOGLINES)];
1.1 root 291: if (*p)
292: printf("%s\n", p);
293: }
294: printf("**** END\n");
295: }
296: #endif
297:
298: void ui_exithandler(void)
299: {
300: if (ui_vga)
301: uip_textmode();
302: ui_vga = 0;
303: #ifdef ALLEGRO
304: ui_printlog();
305: #endif
306: }
307:
308: void ui_final(void)
309: {
310: if (ui_vga)
311: uip_textmode();
312: ui_vga = 0;
313: #ifdef ALLEGRO
314: ui_printlog();
315: #endif
316: }
317:
318: int ui_setcolourbits(const char *str)
319: {
320: char *green, *blue;
321: char s[32];
322: int r, g, b;
323:
324: snprintf(s, sizeof(s), "%s", str);
325:
1.1.1.2 root 326: if ((green = strchr(s, ',')) == NULL)
1.1 root 327: return -1;
328: *green++ = '\0';
329: if ((blue = strchr(green, ',')) == NULL)
330: return -1;
1.1.1.2 root 331: *blue++ = '\0';
1.1 root 332: if ((r = atoi(s)) < 0 || r > 15 ||
1.1.1.2 root 333: (g = atoi(green)) < 0 || g > 15 || (b = atoi(blue)) < 0 || b > 15)
1.1 root 334: return -1;
335: if (uip_setcolourbits(r, g, b))
336: return -1;
337: return 0;
338: }
339:
1.1.1.2 root 340: /* set controllers for input device from user setting.
341: usage: <player1>,<player2>
342: where either can be: joy0, joy1, joy2, joy3 - joypad number
343: key0 - main keyboard
344: key1 - left side of keyboard
345: key2 - right side of keyboard
346: none - no keyboard
347: */
348:
349: int ui_setcontrollers(const char *str)
350: {
351: char *cont0, *cont1;
352: char s[32];
353: int i;
354: char *p;
355:
356: snprintf(s, sizeof(s), "%s", str);
357: cont0 = s;
358: if ((cont1 = strchr(s, ',')) == NULL)
359: return -1;
360: *cont1++ = '\0';
361:
362: for (i = 0; i < 2; i++) {
363: p = (i == 0 ? cont0 : cont1);
364: if (!strncasecmp(p, "key", 3)) {
365: if (p[3] < '0' || p[3] > '2')
366: return -1;
367: if (p[4])
368: return -1;
369: ui_bindings[i].joystick = -1;
370: ui_bindings[i].keyboard = p[3] - '0';
371: } else if (!strncasecmp(p, "joy", 3)) {
372: if (p[3] < '0' || p[3] > '1')
373: return -1;
374: if (p[4])
375: return -1;
376: ui_bindings[i].joystick = p[3] - '0';
377: ui_bindings[i].keyboard = -1;
378: } else if (!strcasecmp(p, "none")) {
379: ui_bindings[i].joystick = -1;
380: ui_bindings[i].keyboard = -1;
381: } else {
382: return -1;
383: }
384: }
385: return 0;
386: }
387:
1.1 root 388: /*** ui_drawbox - plot a box ***/
389:
390: void ui_drawbox(uint16 colour, uint16 x, uint16 y, uint16 width,
391: uint16 height)
392: {
393: uint16 *p, *q;
394: unsigned int i;
395:
1.1.1.2 root 396: p = (uint16 *)(ui_uipinfo.screenmem_w + y * ui_uipinfo.linewidth + x * 2);
397: q = (uint16 *)((uint8 *)p + (height - 1) * ui_uipinfo.linewidth);
1.1 root 398: for (i = 0; i < width; i++)
399: *p++ = *q++ = colour;
1.1.1.2 root 400: p = (uint16 *)(ui_uipinfo.screenmem_w + y * ui_uipinfo.linewidth + x * 2);
1.1 root 401: for (i = 0; i < height; i++) {
402: p[0] = colour;
1.1.1.2 root 403: p[width - 1] = colour;
404: p = (uint16 *)((uint8 *)p + ui_uipinfo.linewidth);
1.1 root 405: }
406: }
407:
408: /*** ui_unpackfont - unpack the font file ***/
409:
410: int ui_unpackfont(void)
411: {
412: unsigned int c, y, x;
413: unsigned char packed;
414: uint16 *cdata;
415:
1.1.1.3 ! root 416: /* 128 chars, 6x, 10y, 16bit */
! 417: if ((ui_font = malloc(128 * 6 * 10 * 2)) == NULL)
1.1 root 418: return -1;
1.1.1.2 root 419: for (c = 0; c < 128; c++) { /* 128 characters */
420: cdata = ui_font + c * 6 * 10;
421: for (y = 0; y < 10; y++) { /* 10 pixels height */
422: packed = generator_font[c * 10 + y];
1.1 root 423: for (x = 0; x < 6; x++) { /* 6 pixels width */
1.1.1.2 root 424: *cdata++ = (packed & 1 << (7 - x)) ? 0xffff : 0;
1.1 root 425: }
426: }
427: }
428: return 0;
429: }
1.1.1.2 root 430:
1.1 root 431: /*** ui_plotint2 - plot a 2-char wide integer ***/
432:
433: uint16 ui_plotint2(uint8 num, uint16 xpos, uint16 ypos)
434: {
435: char buf[3];
436:
437: buf[0] = '0' + (num / 10) % 10;
438: buf[1] = '0' + (num % 10);
439: buf[2] = '\0';
440: return ui_plotstring(buf, xpos, ypos);
441: }
442:
443: /*** ui_plotstring - plot a string ***/
444:
445: uint16 ui_plotstring(const char *text, uint16 xpos, uint16 ypos)
446: {
447: const unsigned char *p;
448: const uint16 *cdata;
1.1.1.2 root 449: unsigned int x, y;
1.1 root 450: uint16 *scr;
451:
452: for (p = text; *p; p++) {
453: if (*p > 128)
1.1.1.2 root 454: cdata = ui_font + '.' * 6 * 10;
1.1 root 455: else
1.1.1.2 root 456: cdata = ui_font + (*p) * 6 * 10;
1.1 root 457: for (y = 0; y < 10; y++) {
1.1.1.2 root 458: scr =
459: (uint16 *)(ui_uipinfo.screenmem_w +
460: (ypos + y) * ui_uipinfo.linewidth + xpos * 2);
1.1 root 461: for (x = 0; x < 6; x++)
462: *scr++ = *cdata++;
463: }
1.1.1.2 root 464: xpos += 6;
1.1 root 465: }
466: return xpos;
467: }
468:
469: /*** ui_plotsprite - plot a sprite ***/
470:
471: void ui_plotsprite_acorn(uint16 *logo, uint16 width, uint16 height,
1.1.1.2 root 472: uint16 x, uint16 y)
1.1 root 473: {
474: uint16 a, b;
1.1.1.3 ! root 475: uint16 *p;
1.1 root 476: uint16 word;
477: uint8 red, green, blue;
478:
479: for (b = 0; b < height; b++) {
1.1.1.2 root 480: p =
481: (uint16 *)(ui_uipinfo.screenmem_w + (y + b) * ui_uipinfo.linewidth +
482: x * 2);
1.1 root 483: for (a = 0; a < width; a++) {
1.1.1.2 root 484: word = (((uint8 *)logo)[1] << 8) | ((uint8 *)logo)[0];
485: green = (word >> 5) & 0x1f;
1.1 root 486: red = word & 0x1f;
1.1.1.2 root 487: blue = (word >> 10) & 0x1f;
488: *p++ = red << ui_uipinfo.redshift | green << ui_uipinfo.greenshift |
489: blue << ui_uipinfo.blueshift;
1.1 root 490: logo++;
491: }
492: }
493: }
494:
495: /*** ui_setupscreen - plot borders and stuff ***/
496:
497: void ui_setupscreen(void)
498: {
1.1.1.2 root 499: uint16 grey = 24 << ui_uipinfo.redshift | 24 << ui_uipinfo.greenshift |
500: 24 << ui_uipinfo.blueshift;
501: uint16 red = 24 << ui_uipinfo.redshift;
1.1 root 502:
503: if (!ui_info) {
504: if (!ui_fullscreen) {
505: ui_drawbox(red, 140, 100, 360, 280);
506: ui_drawbox(grey, 141, 101, 358, 278);
507: }
508: return;
509: }
510: if (ui_fullscreen) {
511: ui_plotstring(":", 622, 470);
512: return;
513: }
514: ui_drawbox(red, 140, 100, 360, 280);
515: ui_drawbox(grey, 141, 101, 358, 278);
516: ui_plotsprite_acorn((uint16 *)logo, 282, 40, 179, 80);
517: ui_plotsprite_acorn((uint16 *)logo, 282, 40, 179, 360);
518: ui_drawbox(red, 0, 415, 640, 1);
519: ui_drawbox(grey, 0, 416, 640, 1);
520: ui_drawbox(red, 0, 65, 640, 1);
521: ui_drawbox(grey, 0, 66, 640, 1);
522: ;
523: /* draw marker for 320x224 box */
524: // ui_drawbox(grey, 160, 128, 320, 224);
525: /* draw marker for 320x240 box */
526: // ui_drawbox(grey, 160, 120, 320, 240);
527: /* draw marker for 256x224 box */
528: // ui_drawbox(grey, 192, 128, 256, 224);
529: /* draw marker for 256x240 box */
530: // ui_drawbox(grey, 192, 120, 256, 240);
531: ;
532: ui_plotstring("Generator is (c) James Ponder 1997-2001, "
533: "all rights reserved.", 0, 0);
1.1.1.3 ! root 534: ui_plotstring(VERSION, 640 - (strlen(VERSION) * 6), 0);
1.1 root 535: ;
1.1.1.2 root 536: if (ui_bindings[0].joystick != -1) {
537: ui_plotstring("Joystick", 0, 420);
538: } else {
539: if (ui_bindings[0].keyboard == 0) {
540: ui_plotstring("[A] A button", 0, 420);
541: ui_plotstring("[S] B button", 0, 430);
542: ui_plotstring("[D] C button", 0, 440);
543: ui_plotstring("[RETURN] Start", 0, 450);
544: ui_plotstring("[ARROWS] D-pad", 0, 460);
545: ui_plotstring("[ESCAPE] QUIT", 0, 470);
546: } else {
1.1.1.3 ! root 547: ui_plotstring("[ZXC] 1) A B C", 0, 420);
1.1.1.2 root 548: ui_plotstring("[DGRF] 1) D-pad", 0, 430);
549: ui_plotstring("[V] 1) Start", 0, 440);
550: ui_plotstring("[,./] 2) A B C", 0, 450);
551: ui_plotstring("[ARROWS] 2) D-pad", 0, 460);
552: ui_plotstring("[RETURN] 2) Start", 0, 470);
553: }
554: }
1.1 root 555: ;
556: ui_plotstring("FPS: 00", 120, 420);
557: ui_plotstring("Skip: 00", 120, 430);
558: ui_plotstring(":", 622, 470);
559: ;
560: ui_plotstring("[F1] License", 0, 20);
561: ui_plotstring("[F2] Load/Save state", 0, 30);
562: ui_plotstring("[F3] -", 0, 40);
563: ui_plotstring("[F4] Save image", 0, 50);
564: ;
565: ui_plotstring("[F5] Toggle info:", 216, 20);
566: ui_plotstring("[F6] Toggle video:", 216, 30);
567: ui_plotstring("[F7] Toggle country:", 216, 40);
568: ui_plotstring("[F8] Toggle plotter:", 216, 50);
569: ;
570: ui_plotstring("[F9] Toggle vsync:", 432, 20);
571: ui_plotstring("[F10] Full screen", 432, 30);
572: ui_plotstring("[F11] -", 432, 40);
573: ui_plotstring("[F12] Reset", 432, 50);
574: ;
575: ui_plotsettings();
576: ;
577: sprintf(bigbuffer, "%s %X %s", gen_cartinfo.version,
578: gen_cartinfo.checksum, gen_cartinfo.country);
579: ui_plotstring(bigbuffer, 216, 420);
580: ui_plotstring(gen_cartinfo.name_domestic, 216, 430);
581: ui_plotstring(gen_cartinfo.name_overseas, 216, 440);
582: }
583:
584: void ui_plotsettings(void)
585: {
1.1.1.2 root 586: ui_plotstring(ui_info ? "On " : "Off", 216 + 126, 20);
587: ui_plotstring(vdp_pal ? "Pal " : "NTSC", 216 + 126, 30);
588: ui_plotstring(vdp_overseas ? "USA/Europe" : "Japan ", 216 + 126, 40);
589: ui_plotstring(ui_vdpsimple ? "Cell (fast) " : "Raster (slow)", 216 + 126,
590: 50);
591: ui_plotstring(ui_vsync ? "On " : "Off", 216 + 342, 20);
1.1 root 592: }
593:
594: /*** ui_loop - main UI loop ***/
595:
596: int ui_loop(void)
597: {
598: char *p;
599: int f;
600:
601: if (ui_initload) {
602: p = gen_loadimage(ui_initload);
603: if (p) {
604: LOG_CRITICAL(("Failed to load ROM image: %s", p));
605: return 1;
606: }
607: if (ui_saverom) {
1.1.1.2 root 608: snprintf(bigbuffer, sizeof(bigbuffer) - 1, "%s (%X-%s)",
609: gen_cartinfo.name_overseas, gen_cartinfo.checksum,
610: gen_cartinfo.country);
611: if ((f = open(bigbuffer, O_CREAT | O_EXCL | O_WRONLY, 0777)) == -1
612: || write(f, cpu68k_rom, cpu68k_romlen) == -1 || close(f) == -1) {
1.1 root 613: fprintf(stderr, "Failed to write file: %s\n", strerror(errno));
614: }
615: printf("Successfully wrote: %s\n", bigbuffer);
616: gen_quit = 1;
617: return 0;
618: }
619: ui_state = 2;
620: } else {
621: LOG_CRITICAL(("You must specify a ROM to load"));
622: return 1;
623: }
624: if (uip_vgamode()) {
625: LOG_CRITICAL(("Failed to start VGA mode"));
626: return 1;
627: }
1.1.1.3 ! root 628: uiplot_setshifts(ui_uipinfo.redshift, ui_uipinfo.greenshift,
! 629: ui_uipinfo.blueshift);
1.1 root 630: gen_quit = 0;
1.1.1.2 root 631: while (!uip_checkkeyboard()) {
632: switch (ui_state) {
633: case 0: /* stopped */
1.1 root 634: break;
1.1.1.2 root 635: case 1: /* paused */
1.1 root 636: break;
1.1.1.2 root 637: case 2: /* playing */
638: if (ui_fkeys & 1 << 1)
1.1 root 639: ui_licensescreen();
1.1.1.2 root 640: if (ui_fkeys & 1 << 2)
1.1 root 641: ui_statescreen();
1.1.1.2 root 642: if (ui_fkeys & 1 << 4)
1.1 root 643: ui_imagescreen();
1.1.1.2 root 644: if (ui_fkeys & 1 << 5) {
645: ui_info ^= 1;
1.1 root 646: ui_clearnext = 2;
647: }
1.1.1.2 root 648: if (ui_fkeys & 1 << 6) {
649: vdp_pal ^= 1;
1.1 root 650: vdp_setupvideo();
651: ui_clearnext = 2;
652: }
1.1.1.2 root 653: if (ui_fkeys & 1 << 7) {
654: vdp_overseas ^= 1;
1.1 root 655: ui_clearnext = 2;
656: }
1.1.1.2 root 657: if (ui_fkeys & 1 << 8) {
658: ui_vdpsimple ^= 1;
1.1 root 659: ui_clearnext = 2;
660: }
1.1.1.2 root 661: if (ui_fkeys & 1 << 9) {
662: ui_vsync ^= 1;
1.1 root 663: ui_clearnext = 2;
664: }
1.1.1.2 root 665: if (ui_fkeys & 1 << 10) {
666: ui_fullscreen ^= 1;
1.1 root 667: ui_clearnext = 2;
668: }
1.1.1.2 root 669: if (ui_fkeys & 1 << 12)
1.1 root 670: ui_resetscreen();
671: ui_fkeys = 0;
672: ui_newframe();
673: event_doframe();
674: break;
675: }
676: }
677: return 0;
678: }
679:
680: void ui_newframe(void)
681: {
682: static int hmode = 0;
683: static int skipcount = 0;
1.1.1.2 root 684: static char frameplots[60]; /* 60 for NTSC, 50 for PAL */
1.1 root 685: static unsigned int frameplots_i = 0;
686: unsigned int i;
687: int fps;
688: time_t t = time(NULL);
689: struct tm *tm_p = localtime(&t);
690:
691: /* we store whether we plotted the previous field as this is important
692: for doing weave interlacing - we don't want to weave two distant fields */
693: ui_plotprevfield = ui_plotfield;
694:
695: if (frameplots_i > vdp_framerate)
696: frameplots_i = 0;
697: if (((vdp_reg[12] >> 1) & 3) && vdp_oddframe) {
698: /* interlace mode, and we're about to do an odd field - we always leave
699: ui_plotfield alone so we do fields in pairs */
700: } else {
701: ui_plotfield = 0;
702: if (ui_frameskip == 0) {
703: if (sound_feedback != -1)
704: ui_plotfield = 1;
705: } else {
706: if (cpu68k_frames % ui_frameskip == 0)
707: ui_plotfield = 1;
708: }
709: }
710: if (!ui_plotfield) {
711: skipcount++;
712: frameplots[frameplots_i++] = 0;
713: return;
714: }
1.1.1.2 root 715: if (hmode != (vdp_reg[12] & 1))
1.1 root 716: ui_clearnext = 2;
717: if (ui_clearnext) {
718: /* horizontal size has changed, so clear whole screen and setup
719: borders etc again */
720: ui_clearnext--;
721: hmode = vdp_reg[12] & 1;
1.1.1.2 root 722: memset(uip_whichbank()? ui_screen1 : ui_screen0, 0, sizeof(ui_screen[0]));
1.1 root 723: uip_clearscreen();
724: ui_setupscreen();
725: }
726: /* count the frames we've plotted in the last vdp_framerate real frames */
727: fps = 0;
728: for (i = 0; i < vdp_framerate; i++) {
729: if (frameplots[i])
730: fps++;
731: }
732: frameplots[frameplots_i++] = 1;
733: if (!ui_info)
734: return;
735: if (ui_fullscreen) {
736: ui_plotint2(fps, 0, 470);
737: } else {
738: ui_plotint2(fps, 156, 420);
1.1.1.2 root 739: ui_plotint2(skipcount + 1, 156, 430);
1.1 root 740: skipcount = 0;
741: }
742: ui_plotint2(tm_p->tm_hour, 610, 470);
743: ui_plotint2(tm_p->tm_min, 628, 470);
744: /*
1.1.1.2 root 745: if (!ui_fullscreen) {
746: int y, i, s;
747: for (i = 0; i < 8; i++) {
748: for (s = 0; s < 4; s++) {
749: ui_plotstring((sound_keys[i] & (1<<s)) ? "*" : ".",
750: 510+(5*s), 200+10*i);
751: }
752: }
753: }
754: */
1.1 root 755: }
756:
1.1.1.3 ! root 757: /*** ui_line - it is time to render a line ***/
1.1 root 758:
1.1.1.3 ! root 759: void ui_line(int line)
1.1 root 760: {
1.1.1.3 ! root 761: static uint8 gfx[320];
! 762: unsigned int width = (vdp_reg[12] & 1) ? 320 : 256;
1.1 root 763:
1.1.1.3 ! root 764: if (!ui_plotfield)
! 765: return;
! 766: if (line < 0 || line >= (int)vdp_vislines)
! 767: return;
! 768: if (ui_vdpsimple) {
! 769: if (line == (int)(vdp_vislines >> 1))
! 770: /* if we're in simple cell-based mode, plot when half way
! 771: * down screen */
! 772: ui_simpleplot();
! 773: return;
1.1 root 774: }
1.1.1.3 ! root 775: /* we are plotting this frame, and we're not doing a simple plot at
! 776: the end of it all */
! 777: switch ((vdp_reg[12] >> 1) & 3) {
! 778: case 0: /* normal */
! 779: case 1: /* interlace simply doubled up */
! 780: case 2: /* invalid */
! 781: vdp_renderline(line, gfx, 0);
! 782: break;
! 783: case 3: /* interlace with double resolution */
! 784: vdp_renderline(line, gfx, vdp_oddframe);
! 785: break;
1.1 root 786: }
1.1.1.3 ! root 787: uiplot_checkpalcache(0);
! 788: uiplot_convertdata16(gfx, ui_newscreen + line * 320, width);
1.1 root 789: }
790:
1.1.1.3 ! root 791: static void ui_simpleplot(void)
1.1.1.2 root 792: {
1.1.1.3 ! root 793: unsigned int line;
1.1 root 794: unsigned int width = (vdp_reg[12] & 1) ? 320 : 256;
1.1.1.3 ! root 795: uint8 gfx[(320 + 16) * (240 + 16)];
1.1 root 796:
1.1.1.3 ! root 797: /* cell mode - entire frame done here */
! 798: uiplot_checkpalcache(0);
! 799: vdp_renderframe(gfx + (8 * (320 + 16)) + 8, 320 + 16); /* plot frame */
! 800: for (line = 0; line < vdp_vislines; line++) {
! 801: uiplot_convertdata16(gfx + 8 + (line + 8) * (320 + 16),
! 802: ui_newscreen + line * 320, width);
1.1 root 803: }
804: }
805:
806: /*** ui_endfield - end of field reached ***/
807:
808: void ui_endfield(void)
809: {
810: static int counter = 0;
811:
812: if (ui_plotfield) {
1.1.1.2 root 813: ui_rendertoscreen(); /* plot ui_newscreen to screen */
1.1 root 814: }
815: if (ui_frameskip == 0) {
816: /* dynamic frame skipping */
817: counter++;
818: if (sound_feedback >= 0) {
819: ui_actualskip = counter;
820: counter = 0;
821: }
822: } else {
823: ui_actualskip = ui_frameskip;
824: }
825: }
826:
827: void ui_rendertoscreen(void)
828: {
1.1.1.2 root 829: uint16 **oldscreenpp = uip_whichbank()? &ui_screen1 : &ui_screen0;
1.1 root 830: uint16 *scrtmp;
831: uint16 *newlinedata, *oldlinedata;
832: unsigned int line;
833: unsigned int nominalwidth = (vdp_reg[12] & 1) ? 320 : 256;
1.1.1.2 root 834: unsigned int yoffset = (vdp_reg[1] & 1 << 3) ? 0 : 8;
1.1 root 835: unsigned int xoffset = (vdp_reg[12] & 1) ? 0 : 32;
836: uint8 *screen;
1.1.1.2 root 837: uint16 *evenscreen; /* interlace: lines 0,2,etc. */
838: uint16 *oddscreen; /* lines 1,3,etc. */
1.1 root 839:
840: for (line = 0; line < vdp_vislines; line++) {
1.1.1.2 root 841: newlinedata = ui_newscreen + line * 320;
842: oldlinedata = *oldscreenpp + line * 320;
1.1 root 843: if (ui_fullscreen) {
1.1.1.2 root 844: screen = (ui_uipinfo.screenmem_w + xoffset * 4 +
845: ui_uipinfo.linewidth * 2 * (line + yoffset));
1.1 root 846: switch ((vdp_reg[12] >> 1) & 3) { /* interlace mode */
847: case 0:
848: case 1:
849: case 2:
1.1.1.3 ! root 850: uiplot_render16_x2h(newlinedata, oldlinedata, screen, nominalwidth);
1.1 root 851: break;
852: case 3:
853: /* work out which buffer contains the odd and even fields */
854: if (vdp_oddframe) {
855: oddscreen = ui_newscreen;
1.1.1.2 root 856: evenscreen = uip_whichbank()? ui_screen0 : ui_screen1;
1.1 root 857: } else {
858: evenscreen = ui_newscreen;
1.1.1.2 root 859: oddscreen = uip_whichbank()? ui_screen0 : ui_screen1;
1.1 root 860: }
861: switch (ui_interlace) {
862: case DEINTERLACE_BOB:
1.1.1.3 ! root 863: uiplot_render16_x2(newlinedata, oldlinedata, screen,
! 864: ui_uipinfo.linewidth, nominalwidth);
1.1 root 865: break;
866: case DEINTERLACE_WEAVE:
1.1.1.3 ! root 867: uiplot_render16_x2h(evenscreen + line * 320, NULL, screen,
! 868: nominalwidth);
! 869: uiplot_render16_x2h(oddscreen + line * 320, NULL,
! 870: screen + ui_uipinfo.linewidth, nominalwidth);
1.1 root 871: break;
872: case DEINTERLACE_WEAVEFILTER:
1.1.1.3 ! root 873: /* lines line+0 and line+1 */
! 874: uiplot_irender16_weavefilter(evenscreen + line * 320,
! 875: oddscreen + line * 320,
! 876: screen, nominalwidth);
! 877: /* lines line+1 and line+2 */
! 878: uiplot_irender16_weavefilter(oddscreen + line * 320,
! 879: evenscreen + line * 320 + 320,
! 880: screen + ui_uipinfo.linewidth,
! 881: nominalwidth);
1.1 root 882: break;
883: }
884: break;
885: }
886: } else {
1.1.1.2 root 887: screen = (ui_uipinfo.screenmem_w + 320 + xoffset * 2 +
888: ui_uipinfo.linewidth * (120 + line + yoffset));
1.1.1.3 ! root 889: uiplot_render16_x1(newlinedata, oldlinedata, screen,
! 890: nominalwidth);
1.1 root 891: }
892: }
893: uip_displaybank(-1);
894: if (ui_vsync)
895: uip_vsync();
896: /* swap ui_screenX and ui_newscreen pointers */
897: scrtmp = *oldscreenpp;
898: *oldscreenpp = ui_newscreen;
899: ui_newscreen = scrtmp;
900: }
901:
902: void ui_basicbits(void)
903: {
1.1.1.2 root 904: uint16 grey = 24 << ui_uipinfo.redshift | 24 << ui_uipinfo.greenshift |
905: 24 << ui_uipinfo.blueshift;
906: uint16 red = 24 << ui_uipinfo.redshift;
1.1 root 907:
908: ui_plotstring("Generator is (c) James Ponder 1997-2001, "
909: "all rights reserved.", 0, 0);
1.1.1.3 ! root 910: ui_plotstring(VERSION, 640 - (strlen(VERSION) * 6), 0);
1.1 root 911: ui_drawbox(red, 140, 100, 360, 280);
912: ui_drawbox(grey, 141, 101, 358, 278);
913: ui_plotsprite_acorn((uint16 *)logo, 282, 40, 179, 80);
914: ui_plotsprite_acorn((uint16 *)logo, 282, 40, 179, 360);
915: }
916:
917: void ui_licensescreen(void)
918: {
919: char c;
920:
921: sound_stop();
922: uip_singlebank();
923: uip_clearscreen();
924: ui_basicbits();
925: /* #01234567890123456789012345678901234567890123456789012 */
926: ui_plotstring("Generator - Sega Genesis (Mega Drive) emulator", 160, 120);
927: ui_plotstring("Copyright (C) 1997-2001 James Ponder", 160, 130);
928: ui_plotstring("YM2612 chip emulation by Tatsuyuki Satoh", 160, 150);
1.1.1.2 root 929: ui_plotstring("SN76496 chip emulation by Nicola Salmoria et al", 160, 160);
930: #ifdef RAZE
931: ui_plotstring("RAZE z80 CPU emulator by Richard Mitton", 160, 170);
932: #else
933: ui_plotstring("Multi-Z80 CPU emulator by Neil Bradley", 160, 170);
934: ui_plotstring(" Portable C version written by Edward Massey", 160, 180);
935: #endif
1.1 root 936: ui_plotstring("This program is free software; you can redistribute", 160,
1.1.1.2 root 937: 200);
938: ui_plotstring("it and/or modify it under the terms of the GNU", 160, 210);
939: ui_plotstring("General Public License version 2 as published by", 160, 220);
940: ui_plotstring("the Free Software Foundation.", 160, 230);
941: ui_plotstring("http://www.squish.net/generator/", 160, 250);
942: ui_plotstring("[0] Return to game", 160, 290);
943: while ((c = uip_getchar()) != '0') {
1.1 root 944: }
945: uip_doublebank();
946: ui_clearnext = 2;
947: sound_start();
948: }
949:
950: void ui_resetscreen(void)
951: {
952: sound_stop();
953: uip_singlebank();
954: uip_clearscreen();
955: ui_basicbits();
956: ui_resetscreen_main();
957: uip_doublebank();
958: ui_clearnext = 2;
1.1.1.2 root 959: sound_start();
1.1 root 960: }
961:
962: void ui_resetscreen_main(void)
963: {
964: char c;
965:
966: for (;;) {
967: uip_clearmiddle();
968: ui_plotstring("Reset menu", 160, 120);
969: ui_plotstring("----------", 160, 130);
970: ui_plotstring("[1] Soft reset", 160, 140);
971: ui_plotstring("[2] Hard reset", 160, 150);
972: ui_plotstring("[0] Return to game", 160, 170);
973: ;
1.1.1.2 root 974: switch ((c = uip_getchar())) {
1.1 root 975: case '0':
976: return;
977: case '1':
978: gen_softreset();
979: return;
980: case '2':
981: gen_reset();
982: return;
983: }
984: }
985: }
986:
987: void ui_statescreen(void)
988: {
989: sound_stop();
990: uip_singlebank();
991: uip_clearscreen();
992: ui_basicbits();
993: ui_statescreen_main();
994: uip_doublebank();
995: ui_clearnext = 2;
996: sound_start();
997: }
998:
999: void ui_statescreen_main(void)
1000: {
1001: char c;
1002:
1003: for (;;) {
1004: uip_clearmiddle();
1005: ui_plotstring("Load / Save state menu", 160, 120);
1006: ui_plotstring("----------------------", 160, 130);
1007: ui_plotstring("[1] Load state", 160, 140);
1008: ui_plotstring("[2] Save state", 160, 150);
1009: ui_plotstring("[0] Return to game", 160, 170);
1010: ;
1.1.1.2 root 1011: switch ((c = uip_getchar())) {
1.1 root 1012: case '0':
1013: return;
1014: case '1':
1015: if (ui_statescreen_loadsavestate(0))
1016: return;
1017: break;
1018: case '2':
1019: if (ui_statescreen_loadsavestate(1))
1020: return;
1021: break;
1022: }
1023: }
1024: }
1025:
1026: int ui_statescreen_loadsavestate(int save)
1027: {
1028: char c;
1029: time_t t;
1030: char buf[64];
1031: int i, y;
1032:
1033: for (;;) {
1034: uip_clearmiddle();
1035: if (save)
1036: ui_plotstring("Save state", 160, 120);
1037: else
1038: ui_plotstring("Load state", 160, 120);
1039: ui_plotstring("----------", 160, 130);
1040: for (i = 1; i <= 9; i++) {
1041: y = 140 + 10 * i;
1042: snprintf(buf, sizeof(buf), "[%d]", i);
1043: ui_plotstring(buf, 160, y);
1044: if ((t = state_date(i)) == 0) {
1.1.1.2 root 1045: ui_plotstring("empty slot", 160 + 4 * 6, y);
1.1 root 1046: } else {
1047: strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&t));
1.1.1.2 root 1048: ui_plotstring(buf, 160 + 4 * 6, y);
1.1 root 1049: }
1050: }
1.1.1.2 root 1051: ui_plotstring("[0] ...back", 160, 140 + 10 * 11);
1.1 root 1052: if ((c = uip_getchar()) == '0')
1053: return 0;
1054: if (c >= '1' && c <= '9') {
1055: /* this is a function call! */
1.1.1.2 root 1056: if ((save ? state_save : state_load) (c - '0') == 0)
1.1 root 1057: return 1;
1058: uip_clearmiddle();
1059: if (save)
1060: ui_plotstring("Failed to save file.", 160, 120);
1061: else
1062: ui_plotstring("Failed to load file.", 160, 120);
1063: ui_plotstring("Press any key to continue", 160, 140);
1064: uip_getchar();
1065: }
1066: }
1067: }
1068:
1069: void ui_imagescreen(void)
1070: {
1071: sound_stop();
1072: uip_singlebank();
1073: uip_clearscreen();
1074: ui_basicbits();
1075: ui_imagescreen_main();
1076: uip_doublebank();
1077: ui_clearnext = 2;
1078: sound_start();
1079: }
1080:
1081: void ui_imagescreen_main(void)
1082: {
1083: char c;
1084: char filename[256];
1085: char buf[256];
1086: int xsize, ysize;
1087:
1088: for (;;) {
1089: uip_clearmiddle();
1090: ui_plotstring("Save screen shot menu", 160, 120);
1091: ui_plotstring("---------------------", 160, 130);
1092: ui_plotstring("[1] Save svga screen (640x480)", 160, 140);
1093: ui_plotstring("[2] Save game screen", 160, 150);
1094: ui_plotstring("[0] Return to game", 160, 170);
1095: ;
1096: c = uip_getchar();
1097: if (c == '0') {
1098: return;
1099: } else if (c == '1' || c == '2') {
1100: if (ui_saveimage(c == '1' ? "svga" : "game", filename, 256,
1101: &xsize, &ysize)) {
1102: uip_clearmiddle();
1103: ui_plotstring("Failed to save image.", 160, 120);
1104: ui_plotstring("Press any key to continue", 160, 140);
1105: uip_getchar();
1106: } else {
1107: uip_clearmiddle();
1108: snprintf(buf, sizeof(buf), "Successfully saved %s", filename);
1109: ui_plotstring(buf, 160, 120);
1.1.1.2 root 1110: snprintf(buf, sizeof(buf), "(%d x %d 24 bit raw image)",
1111: xsize, ysize);
1.1 root 1112: ui_plotstring(buf, 160, 130);
1113: ui_plotstring("Press any key to continue", 160, 150);
1114: uip_getchar();
1115: }
1116: }
1117: }
1118: }
1119:
1120: int ui_saveimage(const char *type, char *filename, int buflen,
1121: int *xsize, int *ysize)
1122: {
1123: int i, y;
1124: int fd = 0;
1125: char out[3];
1126: int count;
1127:
1128: for (i = 1; i <= 9; i++) {
1129: snprintf(filename, buflen, "%s.ss%d", gen_leafname, i);
1130: if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0644)) != -1)
1131: break;
1132: }
1133: if (i < 1 || i > 9) {
1134: *filename = '\0';
1135: LOG_CRITICAL(("Error - there are already 9 saved images"));
1136: return -1;
1137: }
1138: if (!strcasecmp(type, "svga")) {
1139: uint8 *scr;
1140: uint16 *line;
1141: /* get the bank that we're not writing/reading to now */
1142: scr = (ui_uipinfo.screenmem_w == ui_uipinfo.screenmem0) ?
1.1.1.2 root 1143: ui_uipinfo.screenmem1 : ui_uipinfo.screenmem0;
1.1 root 1144: for (y = 0; y < 480; y++) {
1145: line = (uint16 *)(scr + y * ui_uipinfo.linewidth);
1146: for (i = 0; i < 640; i++) {
1.1.1.2 root 1147: out[0] = ((line[i] >> ui_uipinfo.redshift) & 0x1f) << 3;
1148: out[1] = ((line[i] >> ui_uipinfo.greenshift) & 0x1f) << 3;
1149: out[2] = ((line[i] >> ui_uipinfo.blueshift) & 0x1f) << 3;
1.1 root 1150: count = write(fd, out, 3);
1151: if (count == -1) {
1152: LOG_CRITICAL(("Error whilst writing to output image file: %s",
1153: strerror(errno)));
1154: close(fd);
1155: return -1;
1156: } else if (count != 3) {
1157: LOG_CRITICAL(("Short write - wrote 3 bytes, got %d", count));
1158: close(fd);
1159: return -1;
1160: }
1161: }
1162: }
1163: *xsize = 640;
1164: *ysize = 480;
1165: } else if (!strcasecmp(type, "game")) {
1166: uint16 data;
1.1.1.2 root 1167: uint16 *scr = uip_whichbank()? ui_screen0 : ui_screen1;
1.1 root 1168: *xsize = (vdp_reg[12] & 1) ? 320 : 256;
1169: *ysize = vdp_vislines;
1170: for (y = 0; y < *ysize; y++) {
1171: for (i = 0; i < *xsize; i++) {
1.1.1.2 root 1172: data = scr[320 * y + i];
1173: out[0] = ((data >> ui_uipinfo.redshift) & 0x1f) << 3;
1174: out[1] = ((data >> ui_uipinfo.greenshift) & 0x1f) << 3;
1175: out[2] = ((data >> ui_uipinfo.blueshift) & 0x1f) << 3;
1.1 root 1176: count = write(fd, out, 3);
1177: if (count == -1) {
1178: LOG_CRITICAL(("Error whilst writing to output image file: %s",
1179: strerror(errno)));
1180: close(fd);
1181: return -1;
1182: } else if (count != 3) {
1183: LOG_CRITICAL(("Short write - wrote 3 bytes, got %d", count));
1184: close(fd);
1185: return -1;
1186: }
1187: }
1188: }
1189: } else {
1190: LOG_CRITICAL(("Invalid image type '%s' passed to image save routine",
1191: type));
1192: close(fd);
1193: return -1;
1194: }
1195: if (close(fd)) {
1196: LOG_CRITICAL(("Close returned error whilst writing image"));
1197: return -1;
1198: }
1199: return 0;
1200: }
1201:
1202: /*** logging functions ***/
1203:
1204: /* logging is done this way because this was the best I could come up with
1205: whilst battling with macros that can only take fixed numbers of arguments */
1206:
1207: #ifdef ALLEGRO
1208: #define LOG_FUNC(name,level,txt) void ui_log_ ## name ## (const char *text, ...) \
1209: { \
1210: va_list ap; \
1211: char *ll = ui_loglines[ui_logline]; \
1212: char *p = bigbuffer; \
1213: if (gen_loglevel >= level) { \
1214: p+= sprintf(p, "%d ", ui_logcount++); \
1215: p+= sprintf(p, txt); \
1216: va_start(ap, text); \
1217: vsprintf(p, text, ap); \
1218: va_end(ap); \
1219: strncpy(ll, bigbuffer, UI_LOGLINESIZE); \
1220: if (++ui_logline >= UI_LOGLINES) \
1221: ui_logline = 0; \
1222: } \
1223: }
1224: #else
1225: #define LOG_FUNC(name,level,txt) void ui_log_ ## name ## (const char *text, ...) \
1226: { \
1227: va_list ap; \
1228: if (gen_loglevel >= level) { \
1229: printf("[%s] ", txt); \
1230: va_start(ap, text); \
1231: vprintf(text, ap); \
1232: va_end(ap); \
1233: putchar(10); \
1234: } \
1235: }
1236: #endif
1237:
1.1.1.2 root 1238: LOG_FUNC(debug3, 7, "DEBG ");
1239: LOG_FUNC(debug2, 6, "DEBG ");
1240: LOG_FUNC(debug1, 5, "DEBG ");
1241: LOG_FUNC(user, 4, "USER ");
1242: LOG_FUNC(verbose, 3, "---- ");
1243: LOG_FUNC(normal, 2, "---- ");
1.1 root 1244: LOG_FUNC(critical, 1, "CRIT ");
1.1.1.2 root 1245: LOG_FUNC(request, 0, "---- "); /* this generates a warning, such is life */
1.1 root 1246:
1247: /*** ui_err - log error message and quit ***/
1248:
1249: void ui_err(const char *text, ...)
1250: {
1251: va_list ap;
1252:
1253: printf("ERROR: ");
1254:
1255: va_start(ap, text);
1256: vfprintf(stderr, text, ap);
1257: va_end(ap);
1258: putc(10, stderr);
1.1.1.2 root 1259: exit(0); /* don't exit(1) because windows makes an error then! */
1.1 root 1260: }
1261:
1262: /*** ui_topbit - given an integer return the top most bit set ***/
1263:
1264: int ui_topbit(unsigned long int bits)
1265: {
1266: long int bit = 31;
1.1.1.2 root 1267: unsigned long int mask = 1 << 31;
1.1 root 1268:
1.1.1.2 root 1269: for (; bit >= 0; bit--, mask >>= 1) {
1.1 root 1270: if (bits & mask)
1271: return bit;
1272: }
1273: return -1;
1274: }
1.1.1.3 ! root 1275:
! 1276: /*** console version doesn't implement music log yet ***/
! 1277:
! 1278: void ui_musiclog(uint8 *data, unsigned int length)
! 1279: {
! 1280: (void)data;
! 1281: (void)length;
! 1282: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.