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

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

unix.superglobalmegacorp.com

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