Annotation of generator/main/ui-console.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.