Annotation of generator/main/ui-console.c, revision 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.