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