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

1.1       root        1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
                      2: 
                      3: /* user interface for X tcl/tk */
                      4: 
                      5: #include <string.h>
                      6: #include <unistd.h>
                      7: #include <stdlib.h>
                      8: #include <errno.h>
                      9: #include <stdarg.h>
                     10: 
1.1.1.2 ! root       11: #include <sys/types.h>          /* these three are for saving with -save */
1.1       root       12: #include <sys/stat.h>
                     13: #include <fcntl.h>
                     14: 
                     15: #include "generator.h"
                     16: 
                     17: #ifdef HAVE_TCL8_0_H
                     18: #  include <tcl8.0.h>
                     19: #else
                     20: #  include <tcl.h>
                     21: #endif
                     22: 
                     23: #ifdef HAVE_TK8_0_H
                     24: #  include <tk8.0.h>
                     25: #else
                     26: #  include <tk.h>
                     27: #endif
                     28: 
                     29: #include <X11/Xlib.h>
                     30: #include <X11/Xutil.h>
                     31: 
                     32: #include "diss68k.h"
                     33: #include "cpu68k.h"
                     34: #include "cpuz80.h"
                     35: #include "ui.h"
                     36: #include "vdp.h"
                     37: #include "mem68k.h"
                     38: #include "event.h"
                     39: 
                     40: #ifdef XF86DGA
                     41: #include <X11/extensions/xf86dga.h>
                     42: #endif
                     43: 
                     44: /*
                     45: #ifndef XInitImage
                     46: #define XInitImage _XInitImageFuncPtrs
                     47: Status _XInitImageFuncPtrs(XImage *);
                     48: #endif
                     49: */
                     50: 
                     51: #define MAXDEPTHBYTES 4
                     52: 
                     53: /*** forward reference declarations ***/
                     54: 
1.1.1.2 ! root       55: int ui_loadimage(Tcl_Interp * interp, const char *filename);
        !            56: int ui_loadsavepos(Tcl_Interp * interp, const char *filename);
        !            57: int ui_redrawdump(Tcl_Interp * interp, char *textwidget);
1.1       root       58: void ui_updateregs(void);
                     59: void ui_updatestr(char *var, char *val);
                     60: void ui_updateint(char *var, int val);
                     61: int ui_getint(int *cint, char *tclint);
                     62: int ui_setstr(const char *name, const char *value);
1.1.1.2 ! root       63: void ui_keypress(ClientData cd, XEvent * event);
        !            64: void ui_enterleave(ClientData cd, XEvent * event);
1.1       root       65: int ui_topbit(unsigned long int bits);
                     66: void ui_endframe(void);
                     67: void ui_convertdata(uint8 *indata, uint8 *outdata, unsigned int pixels,
1.1.1.2 ! root       68:                     unsigned int lineoffset, unsigned int scale,
        !            69:                     unsigned int depth, unsigned int basepixel);
        !            70: void ui_convertdata_smooth(uint8 *indata, uint8 *outdata,
        !            71:                            unsigned int pixels, unsigned int lineoffset,
        !            72:                            unsigned int depth);
1.1       root       73: 
                     74: #ifdef XF86DGA
                     75: void ui_fullscreen(int onoff);
                     76: #endif
                     77: 
                     78: /*** static variables ***/
                     79: 
                     80: static Tk_Window mainwin;
                     81: static char *display = NULL;
                     82: static Bool xsync = False;
                     83: static Bool save = False;
                     84: static Tcl_Interp *interp;
                     85: static char *imagedata;
                     86: static XImage *image;
                     87: static GC gc = NULL;
                     88: static unsigned int scale = 1;
                     89: static unsigned int smooth = 0;
                     90: static Visual *visual;
                     91: static Colormap cmap;
                     92: static unsigned long visual_bluemask;
                     93: static unsigned long visual_redmask;
                     94: static unsigned long visual_greenmask;
                     95: static int visual_bluepos;
                     96: static int visual_redpos;
                     97: static int visual_greenpos;
                     98: static unsigned int basepixel;
                     99: static unsigned int depth;
                    100: static unsigned int frameskip = 1;
                    101: static Display *ui_display = NULL;
                    102: static Screen *ui_screen = NULL;
                    103: static int ui_screenno = 0;
1.1.1.2 ! root      104: static int ui_dga = 0;          /* enable/disable availability flag */
        !           105: static int ui_dga_state = 0;    /* DGA on/off */
1.1       root      106: static uint32 ui_palcache[192];
1.1.1.2 ! root      107: static int ui_vdpsimple = 1;    /* simple vdp enable/disable */
        !           108: static char *ui_initload = NULL;        /* filename to load on init */
        !           109: static unsigned int state = 0;  /* 0=stop,1=pause,2=play */
1.1       root      110: 
                    111: #ifdef XF86DGA
                    112: static int dga_major, dga_minor;
                    113: static int dga_eventb, dga_errorb;
                    114: static int dga_flags;
                    115: static char *dga_baseaddr;
                    116: static int dga_width, dga_banksize, dga_memsize;
                    117: static int dga_xsize, dga_ysize;
                    118: static char *dga_start;
                    119: #endif
                    120: 
                    121: /*** Define our own arguments for Tk to process ***/
                    122: 
                    123: static Tk_ArgvInfo argtable[] = {
                    124:   /*  { "-display", TK_ARGV_STRING, (char*) NULL, (char*) &display,
1.1.1.2 ! root      125:      "Display to use" }, */
        !           126:   {"-sync", TK_ARGV_CONSTANT, (char *)True, (char *)&xsync,
        !           127:    "Turn on synchronous X"},
        !           128:   {"-save", TK_ARGV_CONSTANT, (char *)True, (char *)&save,
        !           129:    "Save ROM as bin"},
        !           130:   {"", TK_ARGV_END, (char *)NULL, (char *)NULL, (char *)NULL}
1.1       root      131: };
                    132: 
                    133: /*** Error handler for X protocol errors ***/
                    134: 
1.1.1.2 ! root      135: static int errorhandler(ClientData data, XErrorEvent * err)
        !           136: {
1.1       root      137:   ui_err("X error %d, request %d, minor %d", err->error_code,
1.1.1.2 ! root      138:          err->request_code, err->minor_code);
1.1       root      139:   return 0;
                    140: }
                    141: 
                    142: /*** Gen_Load type pathname ***/
                    143: 
1.1.1.2 ! root      144: int
        !           145: Gen_Load(ClientData cdata, Tcl_Interp * interp, int objc,
        !           146:          Tcl_Obj * const objv[])
1.1       root      147: {
                    148:   int i;
                    149: 
                    150:   if (objc != 3) {
1.1.1.2 ! root      151:     Tcl_SetResult(interp,
        !           152:                   "wrong # args: should be \"Gen_Load type pathName\"",
        !           153:                   TCL_STATIC);
1.1       root      154:     return TCL_ERROR;
                    155:   }
                    156:   if (Tcl_GetIntFromObj(interp, objv[1], &i) != TCL_OK)
                    157:     return TCL_ERROR;
                    158:   switch (i) {
                    159:   case 0:
                    160:     return ui_loadimage(interp, Tcl_GetStringFromObj(objv[2], NULL));
                    161:   case 1:
                    162:     return ui_loadsavepos(interp, Tcl_GetStringFromObj(objv[2], NULL));
                    163:   }
                    164:   Tcl_SetResult(interp, "invalid type: should be image (0) or savepos (1)\n",
1.1.1.2 ! root      165:                 TCL_STATIC);
1.1       root      166:   return TCL_ERROR;
                    167: }
                    168: 
                    169: /*** Gen_Save pathname - saves the current state of play in a savegame ***/
                    170: 
1.1.1.2 ! root      171: int
        !           172: Gen_Save(ClientData cdata, Tcl_Interp * interp, int objc,
        !           173:          Tcl_Obj * const objv[])
1.1       root      174: {
                    175:   if (objc != 2) {
                    176:     Tcl_SetResult(interp, "wrong # args: should be \"Gen_Save pathName\"",
1.1.1.2 ! root      177:                   TCL_STATIC);
1.1       root      178:     return TCL_ERROR;
                    179:   }
                    180:   LOG_NORMAL(("Save! %s\n", Tcl_GetStringFromObj(objv[1], NULL)));
                    181:   return TCL_OK;
                    182: }
                    183: 
                    184: /*** Gen_Dump widgetname yview <params from scrollbar> ***/
                    185: 
1.1.1.2 ! root      186: int Gen_Dump(ClientData cdata, Tcl_Interp * interp, int argc, char *argv[])
1.1       root      187: {
                    188:   int si_line, memtype, dumptype, offset, lines;
                    189:   double si_fraction;
                    190:   char tmp[256];
                    191:   Tcl_Obj *varobj, *outobj;
                    192:   Tk_Window window;
                    193:   uint8 *mem_where;
                    194:   unsigned int mem_start, mem_len;
                    195: 
                    196:   if (!cpu68k_rom) {
                    197:     Tcl_SetResult(interp, "Nothing to display", TCL_STATIC);
                    198:     return TCL_ERROR;
                    199:   }
                    200: 
                    201:   window = Tk_NameToWindow(interp, argv[1], Tk_MainWindow(interp));
                    202:   if (!window) {
                    203:     Tcl_SetResult(interp, "bad widget passed to Gen_Dump", TCL_STATIC);
                    204:     return TCL_ERROR;
                    205:   }
                    206: 
                    207:   /* get memtype variable */
                    208:   sprintf(tmp, "%s.memtype", argv[1]);
                    209:   varobj = Tcl_NewStringObj(tmp, -1);
                    210:   Tcl_IncrRefCount(varobj);
                    211:   if (!(outobj = Tcl_ObjGetVar2(interp, varobj, NULL, TCL_GLOBAL_ONLY))) {
                    212:     Tcl_SetResult(interp, ".memtype variable not set", TCL_STATIC);
                    213:     return TCL_ERROR;
                    214:   }
                    215:   Tcl_IncrRefCount(outobj);
                    216:   if (Tcl_GetIntFromObj(interp, outobj, &memtype) != TCL_OK) {
                    217:     return TCL_ERROR;
                    218:   }
                    219:   Tcl_DecrRefCount(varobj);
                    220:   Tcl_DecrRefCount(outobj);
                    221: 
                    222:   /* get dumptype variable */
                    223:   sprintf(tmp, "%s.dumptype", argv[1]);
                    224:   varobj = Tcl_NewStringObj(tmp, -1);
                    225:   Tcl_IncrRefCount(varobj);
                    226:   if (!(outobj = Tcl_ObjGetVar2(interp, varobj, NULL, TCL_GLOBAL_ONLY))) {
                    227:     Tcl_SetResult(interp, ".dumptype variable not set", TCL_STATIC);
                    228:     return TCL_ERROR;
                    229:   }
                    230:   Tcl_IncrRefCount(outobj);
                    231:   if (Tcl_GetIntFromObj(interp, outobj, &dumptype) != TCL_OK) {
                    232:     return TCL_ERROR;
                    233:   }
                    234:   Tcl_DecrRefCount(varobj);
                    235:   Tcl_DecrRefCount(outobj);
                    236: 
                    237:   /* get offset variable */
                    238:   sprintf(tmp, "%s.offset", argv[1]);
                    239:   varobj = Tcl_NewStringObj(tmp, -1);
                    240:   Tcl_IncrRefCount(varobj);
                    241:   if (!(outobj = Tcl_ObjGetVar2(interp, varobj, NULL, TCL_GLOBAL_ONLY))) {
                    242:     Tcl_SetResult(interp, ".offset variable not set", TCL_STATIC);
                    243:     return TCL_ERROR;
                    244:   }
                    245:   Tcl_IncrRefCount(outobj);
                    246:   if (Tcl_GetIntFromObj(interp, outobj, &offset) != TCL_OK) {
                    247:     return TCL_ERROR;
                    248:   }
                    249:   Tcl_DecrRefCount(varobj);
                    250:   Tcl_DecrRefCount(outobj);
                    251: 
                    252:   /* get lines variable */
                    253:   sprintf(tmp, "%s.lines", argv[1]);
                    254:   varobj = Tcl_NewStringObj(tmp, -1);
                    255:   Tcl_IncrRefCount(varobj);
                    256:   if (!(outobj = Tcl_ObjGetVar2(interp, varobj, NULL, TCL_GLOBAL_ONLY))) {
                    257:     Tcl_SetResult(interp, ".lines variable not set", TCL_STATIC);
                    258:     return TCL_ERROR;
                    259:   }
                    260:   Tcl_IncrRefCount(outobj);
                    261:   if (Tcl_GetIntFromObj(interp, outobj, &lines) != TCL_OK) {
                    262:     return TCL_ERROR;
                    263:   }
                    264:   Tcl_DecrRefCount(varobj);
                    265:   Tcl_DecrRefCount(outobj);
                    266: 
1.1.1.2 ! root      267:   switch (memtype) {
1.1       root      268:   case 1:
                    269:     mem_where = cpu68k_ram;
                    270:     mem_start = 0xFF0000;
                    271:     mem_len = 0x10000;
                    272:     break;
                    273:   case 2:
                    274:     mem_where = vdp_vram;
                    275:     mem_start = 0x0;
                    276:     mem_len = LEN_VRAM;
                    277:     break;
                    278:   case 3:
                    279:     mem_where = vdp_cram;
                    280:     mem_start = 0x0;
                    281:     mem_len = LEN_CRAM;
                    282:     break;
                    283:   case 4:
                    284:     mem_where = vdp_vsram;
                    285:     mem_start = 0x0;
                    286:     mem_len = LEN_VSRAM;
                    287:     break;
                    288:   case 5:
                    289:     mem_where = cpuz80_ram;
                    290:     mem_start = 0x0;
                    291:     mem_len = LEN_SRAM;
                    292:     break;
1.1.1.2 ! root      293:   default:                     /* 0 */
1.1       root      294:     mem_where = cpu68k_rom;
                    295:     mem_start = 0;
                    296:     mem_len = cpu68k_romlen;
                    297:     break;
                    298:   }
                    299: 
                    300:   if (!strcasecmp(argv[2], "yview")) {
1.1.1.2 ! root      301:     switch (Tk_GetScrollInfo
        !           302:             (interp, argc - 1, argv + 1, &si_fraction, &si_line)) {
1.1       root      303:     case TK_SCROLL_MOVETO:
1.1.1.2 ! root      304:       offset = (int)(si_fraction * mem_len) & (~1);
1.1       root      305:       break;
                    306:     case TK_SCROLL_UNITS:
                    307:       if (offset < 256 && (si_line > 0)) {
1.1.1.2 ! root      308:         offset = (si_line * 4) + offset;
        !           309:         offset &= ~3;
1.1       root      310:       } else if ((offset <= 256) && (si_line < 0)) {
1.1.1.2 ! root      311:         offset = (si_line * 4) + offset;
        !           312:         offset &= ~3;
1.1       root      313:       } else {
1.1.1.2 ! root      314:         offset = (si_line * 2) + offset;
1.1       root      315:       }
                    316:       break;
                    317:     case TK_SCROLL_PAGES:
1.1.1.2 ! root      318:       offset = si_line * lines * 2 + offset;
1.1       root      319:       break;
                    320:     default:
                    321:       Tcl_SetResult(interp, "unknown yview command parameter", TCL_STATIC);
                    322:       return TCL_ERROR;
                    323:     }
                    324:   } else if (!strcasecmp(argv[2], "redraw")) {
                    325:     return ui_redrawdump(interp, argv[1]);
                    326:   } else {
                    327:     Tcl_SetResult(interp, "unknown command type (must be yview or redraw)",
1.1.1.2 ! root      328:                   TCL_STATIC);
1.1       root      329:     return TCL_ERROR;
1.1.1.2 ! root      330:   }
1.1       root      331:   if (offset >= (signed int)mem_len)
1.1.1.2 ! root      332:     offset = mem_len - 2;
1.1       root      333:   if (offset < 0)
                    334:     offset = 0;
                    335:   sprintf(tmp, "%s.offset", argv[1]);
                    336:   varobj = Tcl_NewStringObj(tmp, -1);
                    337:   Tcl_IncrRefCount(varobj);
                    338:   if (Tcl_ObjSetVar2(interp, varobj, NULL, Tcl_NewIntObj(offset),
1.1.1.2 ! root      339:                      TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG) == NULL) {
1.1       root      340:     return TCL_ERROR;
                    341:   }
                    342:   Tcl_DecrRefCount(varobj);
                    343:   ui_redrawdump(interp, argv[1]);
                    344:   return TCL_OK;
                    345: }
1.1.1.2 ! root      346: 
1.1       root      347: /*** Gen_Step - step through one instruction ***/
                    348: 
1.1.1.2 ! root      349: int
        !           350: Gen_Step(ClientData cdata, Tcl_Interp * interp, int objc,
        !           351:          Tcl_Obj * const objv[])
1.1       root      352: {
                    353:   if (objc != 1) {
1.1.1.2 ! root      354:     Tcl_SetResult(interp, "wrong # args: should be \"Gen_Step\"", TCL_STATIC);
1.1       root      355:     return TCL_ERROR;
                    356:   }
                    357:   event_dostep();
                    358:   ui_updateregs();
                    359:   return TCL_OK;
                    360: }
                    361: 
                    362: /*** Gen_Cont - start executing ***/
                    363: 
1.1.1.2 ! root      364: int
        !           365: Gen_Cont(ClientData cdata, Tcl_Interp * interp, int objc,
        !           366:          Tcl_Obj * const objv[])
1.1       root      367: {
                    368:   char *stopstr;
                    369:   uint32 stopaddr;
                    370:   Tcl_Obj *obj;
                    371:   int i;
                    372: 
                    373:   if (objc != 1) {
1.1.1.2 ! root      374:     Tcl_SetResult(interp, "wrong # args: should be \"Gen_Cont\"", TCL_STATIC);
1.1       root      375:     return TCL_ERROR;
                    376:   }
                    377:   obj = Tcl_ObjGetVar2(interp, Tcl_NewStringObj("regs.stop", -1), NULL,
1.1.1.2 ! root      378:                        TCL_GLOBAL_ONLY);
1.1       root      379:   stopstr = Tcl_GetStringFromObj(obj, NULL);
                    380:   if (!stopstr) {
                    381:     Tcl_SetResult(interp, "Cannot read regs.stop", TCL_STATIC);
                    382:     return TCL_ERROR;
                    383:   }
                    384:   stopaddr = strtol(stopstr, NULL, 16);
                    385:   gen_quit = 0;
                    386:   LOG_NORMAL(("Continuing from %08X", regs.pc));
                    387:   do {
                    388:     while (Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT));
                    389:     for (i = 0; i < 128; i++) {
                    390:       event_dostep();
                    391:       if ((regs.pc & 0xFFFFFF) == stopaddr || gen_quit)
1.1.1.2 ! root      392:         break;
1.1       root      393:     }
1.1.1.2 ! root      394:   }
        !           395:   while ((regs.pc & 0xFFFFFF) != stopaddr && !gen_quit);
1.1       root      396:   LOG_NORMAL(("End of continuation, stopped at %08X", regs.pc));
                    397:   ui_updateregs();
                    398:   if (gen_quit)
                    399:     LOG_NORMAL(("Stopped."));
                    400:   gen_quit = 0;
                    401:   return TCL_OK;
                    402: }
                    403: 
                    404: /*** Gen_FrameStep - step through one frame ***/
                    405: 
1.1.1.2 ! root      406: int
        !           407: Gen_FrameStep(ClientData cdata, Tcl_Interp * interp, int objc,
        !           408:               Tcl_Obj * const objv[])
1.1       root      409: {
                    410:   if (objc != 1) {
                    411:     Tcl_SetResult(interp, "wrong # args: should be \"Gen_FrameStep\"",
1.1.1.2 ! root      412:                   TCL_STATIC);
1.1       root      413:     return TCL_ERROR;
                    414:   }
                    415:   gen_quit = 0;
                    416:   do {
                    417:     event_doframe();
                    418:     while (Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT));
1.1.1.2 ! root      419:   }
        !           420:   while (!gen_quit);
1.1       root      421:   ui_updateregs();
                    422:   if (gen_quit)
                    423:     LOG_NORMAL(("Stopped."));
                    424:   gen_quit = 0;
                    425: 
                    426:   return TCL_OK;
                    427: }
                    428: 
                    429: /*** Gen_SpriteList - print sprite information ***/
                    430: 
1.1.1.2 ! root      431: int
        !           432: Gen_SpriteList(ClientData cdata, Tcl_Interp * interp, int objc,
        !           433:                Tcl_Obj * const objv[])
1.1       root      434: {
                    435:   if (objc != 1) {
                    436:     Tcl_SetResult(interp, "wrong # args: should be \"Gen_SpriteList\"",
1.1.1.2 ! root      437:                   TCL_STATIC);
1.1       root      438:     return TCL_ERROR;
                    439:   }
                    440:   vdp_spritelist();
                    441:   return TCL_OK;
                    442: }
                    443: 
                    444: /*** Gen_Change - there has been a change in parameter ***/
                    445: 
1.1.1.2 ! root      446: int
        !           447: Gen_Change(ClientData cdata, Tcl_Interp * interp, int objc,
        !           448:            Tcl_Obj * const objv[])
1.1       root      449: {
                    450:   Tcl_Obj *varobj, *outobj;
                    451:   unsigned int oldscale = scale;
                    452:   unsigned int newstate;
                    453: 
                    454:   if (objc != 1) {
                    455:     Tcl_SetResult(interp, "wrong # args: should be \"Gen_Change\"",
1.1.1.2 ! root      456:                   TCL_STATIC);
1.1       root      457:     return TCL_ERROR;
                    458:   }
                    459: 
                    460:   ui_getint((int *)&ui_vdpsimple, "vdpsimple");
1.1.1.2 ! root      461:   ui_getint((int *)&vdp_layerB, "layerB");
        !           462:   ui_getint((int *)&vdp_layerBp, "layerBp");
        !           463:   ui_getint((int *)&vdp_layerA, "layerA");
        !           464:   ui_getint((int *)&vdp_layerAp, "layerAp");
        !           465:   ui_getint((int *)&vdp_layerW, "layerW");
        !           466:   ui_getint((int *)&vdp_layerWp, "layerWp");
        !           467:   ui_getint((int *)&vdp_layerH, "layerH");
        !           468:   ui_getint((int *)&vdp_layerS, "layerS");
        !           469:   ui_getint((int *)&vdp_layerSp, "layerSp");
        !           470:   ui_getint((int *)&frameskip, "skip");
        !           471:   ui_getint((int *)&newstate, "state");
1.1       root      472:   ui_getint((int *)&gen_loglevel, "loglevel");
                    473: 
                    474:   ui_getint(&scale, "scale");
                    475:   ui_getint(&smooth, "smooth");
                    476: 
                    477:   if (scale != oldscale) {
                    478:     XDestroyImage(image);
1.1.1.2 ! root      479:     if ((imagedata = malloc(320 * 240 * scale * scale * (depth / 8))) == NULL)
1.1       root      480:       ui_err("%s: Out of memory!");
1.1.1.2 ! root      481:     memset(imagedata, 0, 320 * 240 * scale * scale * (depth / 8));
        !           482:     if ((image =
        !           483:          XCreateImage(ui_display, visual, depth, ZPixmap, 0, imagedata,
        !           484:                       320 * scale, 240 * scale, 8, 0)) == NULL) {
1.1       root      485:       Tcl_SetResult(interp, "unable to create image", TCL_STATIC);
                    486:       return TCL_ERROR;
                    487:     }
                    488:     image->bits_per_pixel = depth;
                    489:     XInitImage(image);
                    490:   }
                    491: #ifdef XF86DGA
1.1.1.2 ! root      492:   dga_start = dga_baseaddr + ((depth / 8) *
        !           493:                               (dga_xsize * ((dga_ysize - (240 * scale)) / 2) +
        !           494:                                ((dga_xsize - (320 * scale)) / 2)));
1.1       root      495: #endif
                    496: 
                    497:   if (newstate != state) {
1.1.1.2 ! root      498:     switch (newstate) {
1.1       root      499:     case 0:
                    500:       /* stop */
                    501:       break;
                    502:     case 1:
                    503:       /* pause */
                    504:       break;
                    505:     case 2:
                    506:       /* play */
                    507:       if (cpu68k_rom == NULL) {
1.1.1.2 ! root      508:         Tcl_SetResult(interp, "No ROM loaded\n", TCL_STATIC);
        !           509:         return TCL_ERROR;
1.1       root      510:       }
                    511:       if (state == 0)
1.1.1.2 ! root      512:         gen_reset();
1.1       root      513:       break;
                    514:     }
                    515:     state = newstate;
                    516:   }
                    517:   return TCL_OK;
                    518: }
                    519: 
                    520: /*** Gen_Initialised ***/
                    521: 
1.1.1.2 ! root      522: int
        !           523: Gen_Initialised(ClientData cdata, Tcl_Interp * interp, int objc,
        !           524:                 Tcl_Obj * const objv[])
1.1       root      525: {
                    526:   char *p;
                    527:   int f;
                    528:   char buffer[256];
                    529: 
                    530:   if (objc != 1) {
                    531:     Tcl_SetResult(interp, "wrong # args: should be \"Gen_Change\"",
1.1.1.2 ! root      532:                   TCL_STATIC);
1.1       root      533:     return TCL_ERROR;
                    534:   }
                    535:   if (ui_initload) {
                    536:     p = gen_loadimage(ui_initload);
                    537:     if (p) {
                    538:       Tcl_SetResult(interp, p, TCL_STATIC);
                    539:       return TCL_ERROR;
                    540:     }
                    541:     ui_updateregs();
                    542:     if (save) {
1.1.1.2 ! root      543:       snprintf(buffer, sizeof(buffer) - 1, "./%s (%X-%s)",
        !           544:                gen_cartinfo.name_overseas, gen_cartinfo.checksum,
        !           545:                gen_cartinfo.country);
1.1       root      546:       f = 0;
1.1.1.2 ! root      547:       if ((f = open(buffer, O_CREAT | O_EXCL | O_WRONLY, 0777)) == -1 ||
        !           548:           write(f, cpu68k_rom, cpu68k_romlen) == -1 || close(f) == -1) {
        !           549:         Tcl_SetResult(interp, strerror(errno), TCL_STATIC);
        !           550:         return TCL_ERROR;
1.1       root      551:       }
                    552:       LOG_REQUEST(("Saved '%s'", buffer));
                    553:     }
                    554:   }
                    555:   return TCL_OK;
                    556: }
                    557: 
                    558: /*** Gen_Reset ***/
                    559: 
1.1.1.2 ! root      560: int
        !           561: Gen_Reset(ClientData cdata, Tcl_Interp * interp, int objc,
        !           562:           Tcl_Obj * const objv[])
1.1       root      563: {
                    564:   int resetitem;
                    565: 
                    566:   if (objc != 2) {
                    567:     Tcl_SetResult(interp, "wrong # args: should be \"Gen_Reset <x>\"",
1.1.1.2 ! root      568:                   TCL_STATIC);
1.1       root      569:     return TCL_ERROR;
                    570:   }
                    571:   Tcl_GetIntFromObj(interp, objv[1], &resetitem);
1.1.1.2 ! root      572:   switch (resetitem) {
        !           573:   case 1:                      /* z80 */
1.1       root      574:     cpuz80_reset();
                    575:     break;
                    576:   default:
                    577:     Tcl_SetResult(interp, "unknown reset item", TCL_STATIC);
                    578:     return TCL_ERROR;
                    579:   }
                    580:   return TCL_OK;
                    581: }
                    582: 
                    583: /*** ui_getint - get a TCL integer into a C int ***/
                    584: 
                    585: int ui_getint(int *cint, char *tclint)
                    586: {
                    587:   Tcl_Obj *valobj, *varobj;
                    588: 
                    589:   varobj = Tcl_NewStringObj(tclint, -1);
                    590:   Tcl_IncrRefCount(varobj);
                    591:   if (!(valobj = Tcl_ObjGetVar2(interp, varobj, NULL, TCL_GLOBAL_ONLY))) {
                    592:     Tcl_SetResult(interp, "variable not set", TCL_STATIC);
                    593:     return TCL_ERROR;
                    594:   }
                    595:   Tcl_IncrRefCount(valobj);
                    596:   if (Tcl_GetIntFromObj(interp, valobj, cint) != TCL_OK) {
                    597:     return TCL_ERROR;
                    598:   }
                    599:   Tcl_DecrRefCount(varobj);
                    600:   Tcl_DecrRefCount(valobj);
                    601:   return TCL_OK;
                    602: }
                    603: 
                    604: /*** ui_setstr - store a string into a TCL variable ***/
                    605: 
                    606: int ui_setstr(const char *name, const char *value)
                    607: {
                    608:   Tcl_Obj *strobj, *varobj, *outobj;
                    609: 
                    610:   varobj = Tcl_NewStringObj((char *)name, -1);
                    611:   Tcl_IncrRefCount(varobj);
                    612:   strobj = Tcl_NewStringObj((char *)value, -1);
                    613:   Tcl_IncrRefCount(strobj);
                    614:   if (!(outobj = Tcl_ObjSetVar2(interp, varobj, NULL, strobj,
1.1.1.2 ! root      615:                                 TCL_GLOBAL_ONLY))) {
1.1       root      616:     return -1;
                    617:   }
                    618:   Tcl_DecrRefCount(varobj);
                    619:   Tcl_DecrRefCount(strobj);
                    620:   return 0;
                    621: }
                    622: 
                    623: /*** Gen_Regs - display registers ***/
                    624: 
1.1.1.2 ! root      625: int
        !           626: Gen_Regs(ClientData cdata, Tcl_Interp * interp, int objc,
        !           627:          Tcl_Obj * const objv[])
1.1       root      628: {
                    629:   if (objc != 1) {
1.1.1.2 ! root      630:     Tcl_SetResult(interp, "wrong # args: should be \"Gen_Regs\"", TCL_STATIC);
1.1       root      631:     return TCL_ERROR;
                    632:   }
                    633:   vdp_showregs();
                    634:   return TCL_OK;
                    635: }
                    636: 
                    637: /*** Gen_VDPDescribe - describe vdp state ***/
                    638: 
1.1.1.2 ! root      639: int
        !           640: Gen_VDPDescribe(ClientData cdata, Tcl_Interp * interp, int objc,
        !           641:                 Tcl_Obj * const objv[])
1.1       root      642: {
                    643:   if (objc != 1) {
                    644:     Tcl_SetResult(interp, "wrong # args: should be \"Gen_VDPDescribe\"",
1.1.1.2 ! root      645:                   TCL_STATIC);
1.1       root      646:     return TCL_ERROR;
                    647:   }
                    648:   vdp_describe();
                    649:   return TCL_OK;
                    650: }
                    651: 
1.1.1.2 ! root      652: int ui_redrawdump(Tcl_Interp * interp, char *textwidget)
1.1       root      653: {
                    654:   int offset, line, listlen, words, i, memtype;
                    655:   char tmp[256], dumpline[128];
                    656:   Tcl_Obj *varobj, *outobj, *paramobj;
                    657:   t_ipc ipc;
                    658:   uint8 *mem_where;
                    659:   unsigned int mem_start, mem_len;
                    660: 
                    661:   /* get offset variable */
                    662:   sprintf(tmp, "%s.offset", textwidget);
                    663:   varobj = Tcl_NewStringObj(tmp, -1);
                    664:   Tcl_IncrRefCount(varobj);
                    665:   if ((outobj = Tcl_ObjGetVar2(interp, varobj, NULL, TCL_GLOBAL_ONLY |
1.1.1.2 ! root      666:                                TCL_LEAVE_ERR_MSG)) == NULL) {
1.1       root      667:     return TCL_ERROR;
                    668:   }
                    669:   Tcl_IncrRefCount(outobj);
                    670:   if (Tcl_GetIntFromObj(interp, outobj, &offset) != TCL_OK) {
                    671:     return TCL_ERROR;
                    672:   }
                    673:   Tcl_DecrRefCount(outobj);
                    674:   Tcl_DecrRefCount(varobj);
                    675: 
                    676:   /* get memtype variable */
                    677:   sprintf(tmp, "%s.memtype", textwidget);
                    678:   varobj = Tcl_NewStringObj(tmp, -1);
                    679:   Tcl_IncrRefCount(varobj);
                    680:   if ((outobj = Tcl_ObjGetVar2(interp, varobj, NULL, TCL_GLOBAL_ONLY |
1.1.1.2 ! root      681:                                TCL_LEAVE_ERR_MSG)) == NULL) {
1.1       root      682:     return TCL_ERROR;
                    683:   }
                    684:   Tcl_IncrRefCount(outobj);
                    685:   if (Tcl_GetIntFromObj(interp, outobj, &memtype) != TCL_OK) {
                    686:     return TCL_ERROR;
                    687:   }
                    688:   Tcl_DecrRefCount(varobj);
                    689:   Tcl_DecrRefCount(outobj);
                    690: 
                    691:   /* clear current text display */
                    692:   sprintf(tmp, "%s.main delete 1.0 end", textwidget);
                    693:   varobj = Tcl_NewStringObj(tmp, -1);
                    694:   Tcl_IncrRefCount(varobj);
                    695:   if (Tcl_EvalObj(interp, varobj) == TCL_ERROR) {
                    696:     return TCL_ERROR;
                    697:   }
                    698:   Tcl_DecrRefCount(varobj);
                    699: 
1.1.1.2 ! root      700:   switch (memtype) {
1.1       root      701:   case 1:
                    702:     mem_where = cpu68k_ram;
                    703:     mem_start = 0xFF0000;
                    704:     mem_len = 0x10000;
                    705:     break;
                    706:   case 2:
                    707:     mem_where = vdp_vram;
                    708:     mem_start = 0x0;
                    709:     mem_len = LEN_VRAM;
                    710:     break;
                    711:   case 3:
                    712:     mem_where = vdp_cram;
                    713:     mem_start = 0x0;
                    714:     mem_len = LEN_CRAM;
                    715:     break;
                    716:   case 4:
                    717:     mem_where = vdp_vsram;
                    718:     mem_start = 0x0;
                    719:     mem_len = LEN_VSRAM;
                    720:     break;
                    721:   case 5:
                    722:     mem_where = cpuz80_ram;
                    723:     mem_start = 0x0;
                    724:     mem_len = LEN_SRAM;
                    725:     break;
1.1.1.2 ! root      726:   default:                     /* 0 */
1.1       root      727:     mem_where = cpu68k_rom;
                    728:     mem_start = 0;
                    729:     mem_len = cpu68k_romlen;
                    730:     break;
                    731:   }
                    732: 
                    733:   line = 1;
1.1.1.2 ! root      734:   while (line <= 100) {         /* do dump loop */
1.1       root      735: 
                    736:     /* first check visibility of line by checking bbox of char 0 on the line */
                    737:     sprintf(tmp, "[%s.main bbox %d.0]", textwidget, line);
                    738:     varobj = Tcl_NewStringObj(tmp, -1);
                    739:     Tcl_IncrRefCount(varobj);
                    740:     if (Tcl_ExprObj(interp, varobj, &outobj) == TCL_ERROR) {
                    741:       return TCL_ERROR;
                    742:     }
                    743:     if (Tcl_ListObjLength(interp, outobj, &listlen) == TCL_ERROR) {
                    744:       return TCL_ERROR;
                    745:     }
                    746:     Tcl_DecrRefCount(outobj);
                    747:     Tcl_DecrRefCount(varobj);
                    748: 
                    749:     if (listlen == 0 || (unsigned int)offset > mem_len) {
                    750:       break;
                    751:     }
                    752: 
                    753:     /* this line is visible so disassemble it */
                    754:     if ((unsigned int)offset == mem_len) {
                    755:       sprintf(dumpline, "---end\n", offset);
                    756:       words = 1;
                    757:     } else {
1.1.1.2 ! root      758:       words = diss68k_getdumpline(mem_start + offset, mem_where + offset,
        !           759:                                   dumpline);
1.1       root      760:     }
                    761: 
                    762:     /* insert line at end of disassembly */
                    763:     sprintf(tmp, "%s.main insert end {%s}", textwidget, dumpline);
                    764:     varobj = Tcl_NewStringObj(tmp, -1);
                    765:     Tcl_IncrRefCount(varobj);
                    766:     if (Tcl_EvalObj(interp, varobj) == TCL_ERROR) {
                    767:       return TCL_ERROR;
                    768:     }
                    769:     Tcl_DecrRefCount(varobj);
                    770: 
                    771:     /* increment address and line number and loop */
1.1.1.2 ! root      772:     offset += words * 2;
1.1       root      773:     line++;
                    774:   }
                    775:   line--;
                    776: 
                    777:   /* update scrollbar */
1.1.1.2 ! root      778:   sprintf(tmp, "%s.bar set %f %f", textwidget, offset / (double)mem_len,
        !           779:           (offset + line * 2) / (double)mem_len);
1.1       root      780:   varobj = Tcl_NewStringObj(tmp, -1);
                    781:   Tcl_IncrRefCount(varobj);
                    782:   if (Tcl_EvalObj(interp, varobj) == TCL_ERROR) {
                    783:     return TCL_ERROR;
                    784:   }
                    785:   Tcl_DecrRefCount(varobj);
                    786: 
                    787:   /* record number of lines for paging function */
                    788:   sprintf(tmp, "%s.lines", textwidget);
                    789:   varobj = Tcl_NewStringObj(tmp, -1);
                    790:   paramobj = Tcl_NewIntObj(line);
                    791:   Tcl_IncrRefCount(varobj);
                    792:   Tcl_IncrRefCount(paramobj);
                    793:   if (Tcl_ObjSetVar2(interp, varobj, NULL, paramobj,
1.1.1.2 ! root      794:                      TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG) == NULL) {
1.1       root      795:     return TCL_ERROR;
                    796:   }
                    797:   Tcl_DecrRefCount(varobj);
                    798:   Tcl_DecrRefCount(paramobj);
                    799:   return TCL_OK;
                    800: }
                    801: 
                    802: /*** Program entry point ***/
                    803: 
                    804: int ui_init(int argc, char *argv[])
                    805: {
                    806:   int i;
                    807:   unsigned int ui;
                    808:   unsigned long plane_masks[1];
                    809:   unsigned long colours[256];
                    810:   XColor xcolor;
                    811: 
                    812:   /* Create tcl interpreter and parse arguments */
                    813:   interp = Tcl_CreateInterp();
                    814:   if (Tk_ParseArgv(interp, NULL, &argc, argv, argtable, 0) != TCL_OK)
                    815:     ui_err("%s: %s", argv[0], Tcl_GetStringResult(interp));
                    816:   if (argc < 1 || argc > 2)
                    817:     ui_err("Usage: %s [<file>]", argv[0]);
                    818: 
                    819:   /* Initialise tcl and tk */
                    820:   if (Tcl_Init(interp) != TCL_OK)
                    821:     ui_err("%s: Tcl_Init failed: %s", argv[0], Tcl_GetStringResult(interp));
                    822:   if (Tk_Init(interp) != TCL_OK)
                    823:     ui_err("%s: Tk_Init failed: %s", argv[0], Tcl_GetStringResult(interp));
                    824:   if ((mainwin = Tk_MainWindow(interp)) == NULL)
                    825:     ui_err("%s: No main window!", argv[0]);
                    826: 
                    827:   ui_display = Tk_Display(mainwin);
                    828:   ui_screen = Tk_Screen(mainwin);
                    829:   ui_screenno = Tk_ScreenNumber(mainwin);
                    830: 
                    831:   /* Configure error handling */
1.1.1.2 ! root      832:   Tk_CreateErrorHandler(ui_display, -1, -1, -1, errorhandler, (char *)NULL);
1.1       root      833:   if (xsync)
                    834:     XSynchronize(ui_display, True);
                    835: 
                    836:   /* Create new Tcl commands */
                    837:   Tcl_CreateObjCommand(interp, "Gen_Load", Gen_Load, NULL, NULL);
                    838:   Tcl_CreateObjCommand(interp, "Gen_Save", Gen_Save, NULL, NULL);
                    839:   Tcl_CreateCommand(interp, "Gen_Dump", Gen_Dump, NULL, NULL);
                    840:   Tcl_CreateObjCommand(interp, "Gen_Step", Gen_Step, NULL, NULL);
                    841:   Tcl_CreateObjCommand(interp, "Gen_FrameStep", Gen_FrameStep, NULL, NULL);
                    842:   Tcl_CreateObjCommand(interp, "Gen_Cont", Gen_Cont, NULL, NULL);
                    843:   Tcl_CreateObjCommand(interp, "Gen_Change", Gen_Change, NULL, NULL);
                    844:   Tcl_CreateObjCommand(interp, "Gen_Regs", Gen_Regs, NULL, NULL);
1.1.1.2 ! root      845:   Tcl_CreateObjCommand(interp, "Gen_VDPDescribe", Gen_VDPDescribe, NULL,
        !           846:                        NULL);
1.1       root      847:   Tcl_CreateObjCommand(interp, "Gen_SpriteList", Gen_SpriteList, NULL, NULL);
1.1.1.2 ! root      848:   Tcl_CreateObjCommand(interp, "Gen_Initialised", Gen_Initialised, NULL,
        !           849:                        NULL);
1.1       root      850:   Tcl_CreateObjCommand(interp, "Gen_Reset", Gen_Reset, NULL, NULL);
                    851: 
                    852:   if ((visual = Tk_GetVisual(interp, mainwin, "truecolor 24", &depth,
1.1.1.2 ! root      853:                              &cmap)) == NULL) {
1.1       root      854:     depth = 0;
                    855:   }
                    856:   LOG_VERBOSE(("Asked for depth 24, got depth %d", depth));
                    857:   if (depth != 16 && depth != 24) {
                    858:     if ((visual = Tk_GetVisual(interp, mainwin, "pseudocolor 8", &depth,
1.1.1.2 ! root      859:                                NULL)) == NULL)
        !           860:       ui_err("%s: GetVisual failed: %s", argv[0],
        !           861:              Tcl_GetStringResult(interp));
1.1       root      862:     if (depth != 8)
1.1.1.2 ! root      863:       ui_err("%s: Depth is %d (we want 8, e.g. 256 colours).", argv[0],
        !           864:              depth);
1.1       root      865:     if ((cmap = Tk_GetColormap(interp, mainwin, "new")) == 0)
                    866:       ui_err("%s: Unable to create new colormap.", argv[0]);
                    867:     if (Tk_SetWindowVisual(mainwin, visual, 8, cmap) != 1)
                    868:       ui_err("%s: Unable to set window visual/colormap.", argv[0]);
                    869:     if (XAllocColorCells(ui_display, cmap, True, plane_masks, 0,
1.1.1.2 ! root      870:                          colours, 32) == 0)
1.1       root      871:       ui_err("%s: Unable to allocate colors.", argv[0]);
                    872:     for (i = 0; i < 32; i++) {
                    873:       xcolor.pixel = i;
                    874:       xcolor.flags = 0;
                    875:       XQueryColor(ui_display, DefaultColormap(ui_display, ui_screenno),
1.1.1.2 ! root      876:                   &xcolor);
1.1       root      877:       XStoreColor(ui_display, cmap, &xcolor);
                    878:     }
                    879:     if (XAllocColorCells(ui_display, cmap, True, plane_masks, 0,
1.1.1.2 ! root      880:                          colours, 64 * 3) == 0)
1.1       root      881:       ui_err("%s: Unable to allocate colors.", argv[0]);
                    882:     basepixel = colours[0];
                    883:     LOG_VERBOSE(("UI: Base pixel %d", basepixel));
                    884:   } else {
                    885:     if (Tk_SetWindowVisual(mainwin, visual, depth, cmap) != 1)
                    886:       ui_err("%s: Unable to set window visual/colormap.", argv[0]);
                    887:   }
                    888: 
1.1.1.2 ! root      889:   if ((imagedata = malloc(320 * 240 * (depth / 8))) == NULL)
1.1       root      890:     ui_err("%s: Out of memory!", argv[0]);
1.1.1.2 ! root      891:   memset(imagedata, 0, 320 * 240 * (depth / 8));
1.1       root      892:   if ((image = XCreateImage(ui_display, visual, depth, ZPixmap, 0,
1.1.1.2 ! root      893:                             imagedata, 320, 240, 8, 0)) == NULL) {
1.1       root      894:     ui_err("%s: Unable to create image.", argv[0]);
                    895:   }
                    896:   /* XCreateImage is broken on my system - force these values */
1.1.1.2 ! root      897:   image->bytes_per_line = 320 * (depth / 8);
1.1       root      898:   image->bits_per_pixel = depth;
                    899:   if (depth != 8) {
                    900:     visual_bluemask = image->blue_mask;
                    901:     visual_redmask = image->red_mask;
                    902:     visual_greenmask = image->green_mask;
                    903:     visual_bluepos = ui_topbit(visual_bluemask) - 2;
                    904:     visual_redpos = ui_topbit(visual_redmask) - 2;
                    905:     visual_greenpos = ui_topbit(visual_greenmask) - 2;
                    906:     if (visual_bluepos == -1 || visual_redpos == -1 || visual_greenpos == -1) {
                    907:       ui_err("%s: Bad colour masks (%x(%d),%x(%d),%x(%d)).",
1.1.1.2 ! root      908:              argv[0], visual_redmask, visual_redpos,
        !           909:              visual_greenmask, visual_greenpos,
        !           910:              visual_bluemask, visual_bluepos);
1.1       root      911:     }
                    912:   }
                    913: 
                    914:   XInitImage(image);
                    915: 
                    916:   /* DGA stuff */
                    917: 
                    918:   ui_dga = 0;
                    919: 
                    920: #ifdef XF86DGA
                    921:   if (geteuid()) {
                    922:     LOG_NORMAL(("%s: You are not root and so DGA is disabled.", argv[0]));
                    923:   } else if (!XF86DGAQueryVersion(ui_display, &dga_major, &dga_minor)) {
                    924:     LOG_NORMAL(("%s: XF86DGAQueryVersion failed", argv[0]));
                    925:   } else if (!XF86DGAQueryExtension(ui_display, &dga_eventb, &dga_errorb)) {
                    926:     LOG_NORMAL(("%s: XF86DGAQueryExtension failed", argv[0]));
                    927:   } else if (!XF86DGAQueryDirectVideo(ui_display, ui_screenno, &dga_flags)) {
                    928:     LOG_NORMAL(("%s: XF86DGAQueryDirectVideo failed", argv[0]));
                    929:   } else if (!(dga_flags & XF86DGADirectPresent)) {
                    930:     LOG_NORMAL(("%s: DGA Direct video support is not present", argv[0]));
                    931:   } else if (!XF86DGAGetVideo(ui_display, ui_screenno, &dga_baseaddr,
1.1.1.2 ! root      932:                               &dga_width, &dga_banksize, &dga_memsize)) {
1.1       root      933:     LOG_NORMAL(("%s: XF86DGAGetVideo failed", argv[0]));
                    934:   } else if (!XF86DGAGetViewPortSize(ui_display, ui_screenno, &dga_xsize,
1.1.1.2 ! root      935:                                      &dga_ysize)) {
1.1       root      936:     LOG_NORMAL(("%s: XF86DGAGetViewPortsize failed", argv[0]));
                    937:   } else {
                    938:     ui_dga = 1;
1.1.1.2 ! root      939:     dga_start = dga_baseaddr + ((depth / 8) *
        !           940:                                 (dga_xsize *
        !           941:                                  ((dga_ysize - (240 * scale)) / 2) +
        !           942:                                  ((dga_xsize - (320 * scale)) / 2)));
1.1       root      943:     LOG_NORMAL(("DGA: Direct full-screen video enabled at "
1.1.1.2 ! root      944:                 "%08X (%d/%d) [%d x %d].", dga_baseaddr, dga_banksize,
        !           945:                 dga_memsize, dga_xsize, dga_ysize));
1.1       root      946:   }
                    947:   if (!ui_dga) {
                    948:     LOG_NORMAL(("DGA has been disabled, no full-screen facilities will "
1.1.1.2 ! root      949:                 "be available."));
1.1       root      950:   }
                    951: #else
                    952:   LOG_VERBOSE(("DGA: Not compiled in."));
                    953: #endif
                    954:   if (setuid(getuid()))
                    955:     ui_err("%s: Failed to setuid: %s", argv[0], strerror(errno));
                    956: 
                    957:   /* end DGA stuff */
                    958: 
                    959:   ui_updateint("debug", gen_debugmode);
                    960: 
                    961:   Tk_CreateEventHandler(mainwin, KeyPressMask | KeyReleaseMask,
1.1.1.2 ! root      962:                         ui_keypress, NULL);
1.1       root      963:   Tk_CreateEventHandler(mainwin, EnterWindowMask | LeaveWindowMask,
1.1.1.2 ! root      964:                         ui_enterleave, NULL);
1.1       root      965: 
                    966:   if (argc == 2) {
1.1.1.2 ! root      967:     if ((ui_initload = malloc(strlen(argv[1]) + 1)) == NULL) {
1.1       root      968:       fprintf(stderr, "Out of memory\n");
                    969:       return 1;
                    970:     }
                    971:     strcpy(ui_initload, argv[1]);
                    972:   }
                    973:   return 0;
                    974: }
                    975: 
                    976: int ui_topbit(unsigned long int bits)
                    977: {
                    978:   long int bit = 31;
1.1.1.2 ! root      979:   unsigned long int mask = 1 << 31;
1.1       root      980: 
1.1.1.2 ! root      981:   for (; bit >= 0; bit--, mask >>= 1) {
1.1       root      982:     if (bits & mask)
                    983:       return bit;
                    984:   }
                    985:   return -1;
                    986: }
                    987: 
                    988: void ui_final(void)
                    989: {
                    990:   XAutoRepeatOn(ui_display);
                    991: }
                    992: 
1.1.1.2 ! root      993: void ui_enterleave(ClientData cd, XEvent * event)
1.1       root      994: {
                    995:   if (event->type == EnterNotify) {
                    996:     XAutoRepeatOff(ui_display);
                    997:   } else {
                    998:     XAutoRepeatOn(ui_display);
                    999:   }
                   1000: }
                   1001: 
1.1.1.2 ! root     1002: void ui_keypress(ClientData cd, XEvent * event)
1.1       root     1003: {
                   1004:   char keysym = XLookupKeysym(&event->xkey, 0);
                   1005:   int type = (event->type == KeyPress);
                   1006: 
                   1007:   LOG_DEBUG3(("KEY %d: %d", type, keysym));
1.1.1.2 ! root     1008:   switch (keysym) {
1.1       root     1009:   case 'a':
                   1010:   case '1':
                   1011:   case 'z':
1.1.1.2 ! root     1012:     mem68k_cont[0].a = type;
1.1       root     1013:     break;
                   1014:   case 'b':
                   1015:   case '2':
                   1016:   case 's':
                   1017:   case 'x':
1.1.1.2 ! root     1018:     mem68k_cont[0].b = type;
1.1       root     1019:     break;
                   1020:   case 'c':
                   1021:   case '3':
                   1022:   case 'd':
1.1.1.2 ! root     1023:     mem68k_cont[0].c = type;
1.1       root     1024:     break;
                   1025:   case 81:
1.1.1.2 ! root     1026:     mem68k_cont[0].left = type;
1.1       root     1027:     break;
                   1028:   case 82:
1.1.1.2 ! root     1029:     mem68k_cont[0].up = type;
1.1       root     1030:     break;
                   1031:   case 83:
1.1.1.2 ! root     1032:     mem68k_cont[0].right = type;
1.1       root     1033:     break;
                   1034:   case 84:
1.1.1.2 ! root     1035:     mem68k_cont[0].down = type;
1.1       root     1036:     break;
                   1037:   case 13:
1.1.1.2 ! root     1038:     mem68k_cont[0].start = type;
1.1       root     1039:     break;
                   1040: #ifdef XF86DGA
                   1041:   case '#':
                   1042:     if (type)
                   1043:       ui_fullscreen(ui_dga_state ^ 1);
                   1044:     break;
                   1045: #endif
                   1046:   default:
                   1047:     break;
                   1048:   }
                   1049: }
                   1050: 
                   1051: /*** ui_updateregs - update register information ***/
                   1052: 
                   1053: void ui_updateregs(void)
                   1054: {
                   1055:   int i, t;
                   1056:   char val[256], var[256];
                   1057: 
                   1058:   for (t = 0; t < 2; t++) {
                   1059:     for (i = 0; i < 8; i++) {
1.1.1.2 ! root     1060:       sprintf(val, "%08X", regs.regs[t * 8 + i]);
1.1       root     1061:       sprintf(var, "regs.%s%d", t ? "a" : "d", i);
                   1062:       ui_updatestr(var, val);
                   1063:     }
                   1064:   }
1.1.1.2 ! root     1065:   sprintf(val, "%08X", regs.pc);
        !          1066:   ui_updatestr("regs.pc", val);
        !          1067:   sprintf(val, "%04X", regs.sr.sr_int);
        !          1068:   ui_updatestr("regs.sr", val);
        !          1069:   sprintf(val, "%08X", regs.sp);
        !          1070:   ui_updatestr("regs.sp", val);
1.1       root     1071:   ui_updateint("regs.s", regs.sr.sr_struct.s);
                   1072:   ui_updateint("regs.x", regs.sr.sr_struct.x);
                   1073:   ui_updateint("regs.n", regs.sr.sr_struct.n);
                   1074:   ui_updateint("regs.z", regs.sr.sr_struct.z);
                   1075:   ui_updateint("regs.v", regs.sr.sr_struct.v);
                   1076:   ui_updateint("regs.c", regs.sr.sr_struct.c);
                   1077:   ui_updateint("regs.frames", cpu68k_frames);
                   1078:   ui_updateint("regs.clocks", cpu68k_clocks);
                   1079: }
                   1080: 
                   1081: void ui_updatestr(char *var, char *val)
                   1082: {
                   1083:   Tcl_Obj *valobj, *varobj;
                   1084: 
                   1085:   valobj = Tcl_NewStringObj(val, -1);
                   1086:   Tcl_IncrRefCount(valobj);
                   1087:   varobj = Tcl_NewStringObj(var, -1);
                   1088:   Tcl_IncrRefCount(varobj);
                   1089: 
                   1090:   if (Tcl_ObjSetVar2(interp, varobj, NULL, valobj,
1.1.1.2 ! root     1091:                      TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG) == NULL) {
1.1       root     1092:     LOG_CRITICAL(("Error setting %s", val));
                   1093:   }
                   1094:   Tcl_DecrRefCount(varobj);
                   1095:   Tcl_DecrRefCount(valobj);
                   1096: }
                   1097: 
                   1098: void ui_updateint(char *var, int val)
                   1099: {
                   1100:   Tcl_Obj *valobj, *varobj;
                   1101: 
                   1102:   valobj = Tcl_NewIntObj(val);
                   1103:   Tcl_IncrRefCount(valobj);
                   1104:   varobj = Tcl_NewStringObj(var, -1);
                   1105:   Tcl_IncrRefCount(varobj);
                   1106: 
                   1107:   if (Tcl_ObjSetVar2(interp, varobj, NULL, valobj,
1.1.1.2 ! root     1108:                      TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG) == NULL) {
1.1       root     1109:     LOG_CRITICAL(("Error setting %s", val));
                   1110:   }
                   1111:   Tcl_DecrRefCount(varobj);
                   1112:   Tcl_DecrRefCount(valobj);
                   1113: }
                   1114: 
                   1115: /*** ui_loop - main UI loop ***/
                   1116: 
                   1117: int ui_loop(void)
                   1118: {
                   1119:   char *trace;
                   1120: 
                   1121:   ui_updateregs();
                   1122: 
                   1123:   /* Run Tcl script */
                   1124:   if (Tcl_EvalFile(interp, FNAME_TCLSCRIPT) != TCL_OK) {
                   1125:     LOG_CRITICAL(("error: %s", Tcl_GetStringResult(interp)));
                   1126:     if ((trace = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY)) != NULL) {
                   1127:       LOG_NORMAL(("TCL TRACE: %s", trace));
                   1128:     }
                   1129:     return 1;
                   1130:   }
                   1131: 
                   1132:   gen_quit = 0;
1.1.1.2 ! root     1133:   while (!gen_quit) {
        !          1134:     switch (state) {
        !          1135:     case 0:                    /* stopped */
1.1       root     1136:       Tcl_DoOneEvent(TCL_ALL_EVENTS);
                   1137:       break;
1.1.1.2 ! root     1138:     case 1:                    /* paused */
1.1       root     1139:       Tcl_DoOneEvent(TCL_ALL_EVENTS);
                   1140:       break;
1.1.1.2 ! root     1141:     case 2:                    /* playing */
1.1       root     1142:       event_doframe();
                   1143:       Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
                   1144:       break;
                   1145:     }
                   1146:   }
                   1147:   return 0;
                   1148: }
                   1149: 
                   1150: /*** ui_loadimage - load ROM image ***/
                   1151: 
1.1.1.2 ! root     1152: int ui_loadimage(Tcl_Interp * interp, const char *filename)
1.1       root     1153: {
                   1154:   char *p;
                   1155: 
                   1156:   p = gen_loadimage(filename);
                   1157:   if (p) {
                   1158:     Tcl_SetResult(interp, p, TCL_STATIC);
                   1159:     return TCL_ERROR;
                   1160:   }
                   1161:   ui_updateregs();
                   1162:   return TCL_OK;
                   1163: }
                   1164: 
                   1165: /*** ui_loadsavepos - load saved position ***/
                   1166: 
1.1.1.2 ! root     1167: int ui_loadsavepos(Tcl_Interp * interp, const char *filename)
1.1       root     1168: {
                   1169:   char *p;
                   1170: 
                   1171:   p = gen_loadsavepos(filename);
                   1172:   if (p) {
                   1173:     Tcl_SetResult(interp, p, TCL_STATIC);
                   1174:     return TCL_ERROR;
                   1175:   }
                   1176:   return TCL_OK;
                   1177: }
                   1178: 
                   1179: /*** ui_setinfo - set information window with name/copyright/etc ***/
                   1180: 
1.1.1.2 ! root     1181: char *ui_setinfo(t_cartinfo * cartinfo)
1.1       root     1182: {
                   1183:   char buffer[128];
                   1184: 
                   1185:   if (ui_setstr("i_console", cartinfo->console) ||
                   1186:       ui_setstr("i_copyright", cartinfo->copyright) ||
                   1187:       ui_setstr("i_name_domestic", cartinfo->name_domestic) ||
                   1188:       ui_setstr("i_name_overseas", cartinfo->name_overseas) ||
                   1189:       ui_setstr("i_version", cartinfo->version) ||
                   1190:       ui_setstr("i_memo", cartinfo->memo))
                   1191:     return "Unable to set tcl variables";
                   1192:   sprintf(buffer, "%x", cartinfo->checksum);
                   1193:   if (ui_setstr("i_checksum", buffer))
                   1194:     return "Unable to set checksum tcl variable";
                   1195:   if (cartinfo->prodtype == pt_game) {
                   1196:     if (ui_setstr("i_prodtype", "Game"))
                   1197:       return "Unable to set checksum tcl variable";
                   1198:   } else if (cartinfo->prodtype == pt_education) {
                   1199:     if (ui_setstr("i_prodtype", "Education"))
                   1200:       return "Unable to set checksum tcl variable";
                   1201:   } else {
                   1202:     if (ui_setstr("i_prodtype", "Unknown"))
                   1203:       return "Unable to set checksum tcl variable";
                   1204:   }
                   1205:   return NULL;
                   1206: }
                   1207: 
                   1208: /*** ui_checkpalcache - make palette cache up-to-date ***/
                   1209: 
                   1210: void ui_checkpalcache(int flag)
                   1211: {
                   1212:   uint32 pal;
                   1213:   unsigned int col;
                   1214:   uint8 *p;
                   1215: 
                   1216:   /* this code requires that there be at least 4 bits per colour, that
                   1217:      is, three bits that come from the console's palette, and one more bit
                   1218:      when we do a dim or bright colour, i.e. this code works with 12bpp
                   1219:      upwards */
                   1220: 
                   1221:   for (col = 0; col < 64; col++) {
                   1222:     if (!flag && !vdp_cramf[col])
                   1223:       continue;
                   1224:     vdp_cramf[col] = 0;
1.1.1.2 ! root     1225:     p = (uint8 *)vdp_cram + 2 * col;
        !          1226:     ui_palcache[col] =
        !          1227:       (((p[0] >> 1) & 7) << visual_bluepos) |
        !          1228:       (((p[1] >> 1) & 7) << visual_redpos) |
        !          1229:       (((p[1] >> 5) & 7) << visual_greenpos);
        !          1230:     ui_palcache[col + 64] =
        !          1231:       (((p[0] >> 1) & 7) << (visual_bluepos - 1)) |
        !          1232:       (((p[1] >> 1) & 7) << (visual_redpos - 1)) |
        !          1233:       (((p[1] >> 5) & 7) << (visual_greenpos - 1)) |
        !          1234:       (4 << visual_bluepos) | (4 << visual_redpos) | (4 << visual_greenpos);
        !          1235:     ui_palcache[col + 128] =
        !          1236:       (((p[0] >> 1) & 7) << (visual_bluepos - 1)) |
        !          1237:       (((p[1] >> 1) & 7) << (visual_redpos - 1)) |
        !          1238:       (((p[1] >> 5) & 7) << (visual_greenpos - 1));
1.1       root     1239:   }
                   1240: }
                   1241: 
                   1242: /*** ui_line - it is time to render a line ***/
                   1243: 
                   1244: void ui_line(unsigned int line)
1.1.1.2 ! root     1245: {
1.1       root     1246:   static uint8 gfx[320];
                   1247:   uint8 *cram = (uint8 *)vdp_cram;
                   1248:   char *p, *pp, *ppp;
                   1249:   int lineoffset;
                   1250: 
                   1251:   if (ui_vdpsimple)
                   1252:     return;
                   1253: 
                   1254: #ifdef XF86DGA
                   1255:   if (ui_dga_state) {
1.1.1.2 ! root     1256:     lineoffset = dga_xsize * (depth / 8);
        !          1257:     p = dga_start + line * lineoffset * scale;
1.1       root     1258:   } else {
1.1.1.2 ! root     1259:     lineoffset = 320 * (depth / 8) * scale;
        !          1260:     p = imagedata + line * lineoffset * scale;
1.1       root     1261:   }
                   1262: #else
1.1.1.2 ! root     1263:   lineoffset = 320 * (depth / 8) * scale;
        !          1264:   p = imagedata + line * lineoffset * scale;
1.1       root     1265: #endif
                   1266: 
                   1267:   if (cpu68k_frames % frameskip != 0)
                   1268:     return;
                   1269: 
                   1270:   LOG_DEBUG2(("line %d: ", line));
1.1.1.2 ! root     1271:   switch ((vdp_reg[12] >> 1) & 3) {
        !          1272:   case 0:                      /* normal */
        !          1273:   case 1:                      /* interlace simply doubled up */
        !          1274:   case 2:                      /* invalid */
1.1       root     1275:     vdp_renderline(line, gfx, 0);
1.1.1.2 ! root     1276:     break;
        !          1277:   case 3:                      /* interlace with double resolution */
        !          1278:     vdp_renderline(line, gfx, vdp_oddframe);
        !          1279:     break;
        !          1280:   }
1.1       root     1281:   if (scale == 2 && smooth) {
                   1282:     ui_convertdata_smooth(gfx, p, 320, lineoffset, depth);
                   1283:   } else {
                   1284:     ui_convertdata(gfx, p, 320, lineoffset, scale, depth, basepixel);
                   1285:   }
                   1286: }
                   1287: 
1.1.1.2 ! root     1288: void
        !          1289: ui_convertdata(uint8 *indata, uint8 *outdata, unsigned int pixels,
        !          1290:                unsigned int lineoffset, unsigned int scale,
        !          1291:                unsigned int depth, unsigned int basepixel)
1.1       root     1292: {
                   1293:   char *p, *pp;
                   1294:   unsigned int ui;
                   1295:   unsigned int t, s;
                   1296:   uint32 data;
                   1297: 
                   1298:   if (depth == 8) {
                   1299:     if (scale == 1) {
1.1.1.2 ! root     1300:       /* not scaled, 8bpp */
        !          1301:       for (ui = 0; ui < pixels; ui++) {
        !          1302:         outdata[ui] = indata[ui] + basepixel;
        !          1303:       }
1.1       root     1304:     } else {
                   1305:       /* scaled, 8bpp */
                   1306:       p = outdata;
1.1.1.2 ! root     1307:       for (ui = 0; ui < pixels; ui++, p += ui * scale) {
        !          1308:         pp = p;
        !          1309:         for (s = 0; s < scale; s++, pp += lineoffset) {
1.1       root     1310:           for (t = 0; t < scale; t++) {
                   1311:             pp[t] = indata[ui] + basepixel;
1.1.1.2 ! root     1312:           }
        !          1313:         }
1.1       root     1314:       }
                   1315:     }
                   1316:   } else {
                   1317:     ui_checkpalcache(0);
                   1318:     if (scale == 1) {
                   1319:       if (depth == 16) {
1.1.1.2 ! root     1320:         /* not scaled, 16bpp */
        !          1321:         for (ui = 0; ui < pixels; ui++) {
        !          1322:           data = ui_palcache[indata[ui]];
        !          1323:           ((uint16 *)outdata)[ui] = data;       /* already in local endian */
        !          1324:         }
1.1       root     1325:       } else if (depth == 24) {
1.1.1.2 ! root     1326:         /* not scaled, 24bpp */
        !          1327:         p = outdata;
        !          1328:         for (ui = 0; ui < pixels; ui++, p += 3) {
        !          1329:           data = ui_palcache[indata[ui]];
1.1       root     1330: #ifdef WORDS_BIGENDIAN
1.1.1.2 ! root     1331:           p[0] = (uint8)(data >> 16);
        !          1332:           p[1] = (uint8)(data >> 8);
        !          1333:           p[2] = (uint8)(data);
1.1       root     1334: #else
1.1.1.2 ! root     1335:           p[0] = (uint8)(data);
        !          1336:           p[1] = (uint8)(data >> 8);
        !          1337:           p[2] = (uint8)(data >> 16);
1.1       root     1338: #endif
1.1.1.2 ! root     1339:         }
1.1       root     1340:       } else {
                   1341:         ui_err("unknown depth %d", depth);
                   1342:       }
                   1343:     } else if (scale == 2) {
                   1344:       if (depth == 16) {
1.1.1.2 ! root     1345:         /* scaled by 2, 16bpp */
        !          1346:         p = outdata;
        !          1347:         for (ui = 0; ui < pixels; ui++, p += 4) {
        !          1348:           data = ui_palcache[indata[ui]];
        !          1349:           ((uint16 *)p)[0] = data;      /* already in local endian */
        !          1350:           ((uint16 *)p)[1] = data;
        !          1351:           ((uint16 *)(p + lineoffset))[0] = data;
        !          1352:           ((uint16 *)(p + lineoffset))[1] = data;
        !          1353:         }
1.1       root     1354:       } else if (depth == 24) {
1.1.1.2 ! root     1355:         /* scaled by 2, 24bpp */
        !          1356:         p = outdata;
        !          1357:         for (ui = 0; ui < pixels; ui++, p += 6) {
        !          1358:           data = ui_palcache[indata[ui]];
1.1       root     1359: #ifdef WORDS_BIGENDIAN
1.1.1.2 ! root     1360:           p[0] = (uint8)(data >> 16);
        !          1361:           p[3] = (uint8)(data >> 16);
        !          1362:           p[lineoffset + 0] = (uint8)(data >> 16);
        !          1363:           p[lineoffset + 3] = (uint8)(data >> 16);
        !          1364:           p[1] = (uint8)(data >> 8);
        !          1365:           p[4] = (uint8)(data >> 8);
        !          1366:           p[lineoffset + 1] = (uint8)(data >> 8);
        !          1367:           p[lineoffset + 4] = (uint8)(data >> 8);
        !          1368:           p[2] = (uint8)(data);
        !          1369:           p[5] = (uint8)(data);
        !          1370:           p[lineoffset + 2] = (uint8)(data);
        !          1371:           p[lineoffset + 5] = (uint8)(data);
1.1       root     1372: #else
1.1.1.2 ! root     1373:           p[0] = (uint8)(data);
        !          1374:           p[3] = (uint8)(data);
        !          1375:           p[lineoffset + 0] = (uint8)(data);
        !          1376:           p[lineoffset + 3] = (uint8)(data);
        !          1377:           p[1] = (uint8)(data >> 8);
        !          1378:           p[4] = (uint8)(data >> 8);
        !          1379:           p[lineoffset + 1] = (uint8)(data >> 8);
        !          1380:           p[lineoffset + 4] = (uint8)(data >> 8);
        !          1381:           p[2] = (uint8)(data >> 16);
        !          1382:           p[5] = (uint8)(data >> 16);
        !          1383:           p[lineoffset + 2] = (uint8)(data >> 16);
        !          1384:           p[lineoffset + 5] = (uint8)(data >> 16);
1.1       root     1385: #endif
1.1.1.2 ! root     1386:         }
1.1       root     1387:       } else {
                   1388:         ui_err("unknown depth %d", depth);
                   1389:       }
                   1390:     } else {
                   1391:       /* scaled by more than 2 */
                   1392:       for (ui = 0; ui < pixels; ui++) {
1.1.1.2 ! root     1393:         data = ui_palcache[indata[ui]];
        !          1394:         p = outdata + ui * (depth / 8) * scale;
        !          1395:         for (s = 0; s < scale; s++, p += lineoffset) {
        !          1396:           for (t = 0; t < scale; t++) {
        !          1397:             if (depth == 16) {
        !          1398:               ((uint16 *)p)[t] = data;  /* already in local endian */
        !          1399:             } else if (depth == 24) {
        !          1400:               pp = p + t * 3;
1.1       root     1401: #ifdef WORDS_BIGENDIAN
1.1.1.2 ! root     1402:               pp[0] = (uint8)(data >> 16);
        !          1403:               pp[1] = (uint8)(data >> 8);
        !          1404:               pp[2] = (uint8)(data);
1.1       root     1405: #else
1.1.1.2 ! root     1406:               pp[0] = (uint8)(data);
        !          1407:               pp[1] = (uint8)(data >> 8);
        !          1408:               pp[2] = (uint8)(data >> 16);
1.1       root     1409: #endif
1.1.1.2 ! root     1410:             } else {
1.1       root     1411:               ui_err("unknown depth %d", depth);
                   1412:             }
1.1.1.2 ! root     1413:           }
        !          1414:         }
1.1       root     1415:       }
                   1416:     }
                   1417:   }
                   1418: }
                   1419: 
1.1.1.2 ! root     1420: void
        !          1421: ui_convertdata_smooth(uint8 *indata, uint8 *outdata, unsigned int pixels,
        !          1422:                       unsigned int lineoffset, unsigned int depth)
1.1       root     1423: {
                   1424:   char *p, *pp;
                   1425:   unsigned int ui;
                   1426:   int t, s;
                   1427:   uint32 data1, data2, datam;
                   1428: 
                   1429:   ui_checkpalcache(0);
                   1430:   if (depth == 16) {
                   1431:     /* scaled by 2, 16bpp */
                   1432:     p = outdata;
                   1433:     data1 = ui_palcache[indata[0]];
1.1.1.2 ! root     1434:     for (ui = 0; ui < pixels - 1; ui++, p += 4) {
        !          1435:       data2 = ui_palcache[indata[ui + 1]];
1.1       root     1436:       datam = (((((data1 & visual_redmask) +
1.1.1.2 ! root     1437:                   (data2 & visual_redmask)) >> 1) & visual_redmask) |
        !          1438:                ((((data1 & visual_greenmask) +
        !          1439:                   (data2 & visual_greenmask)) >> 1) & visual_greenmask) |
        !          1440:                ((((data1 & visual_bluemask) +
        !          1441:                   (data2 & visual_bluemask)) >> 1) & visual_bluemask));
1.1       root     1442:       ((uint16 *)p)[0] = data1; /* already in local endian */
                   1443:       ((uint16 *)p)[1] = datam;
1.1.1.2 ! root     1444:       ((uint16 *)(p + lineoffset))[0] = data1;
        !          1445:       ((uint16 *)(p + lineoffset))[1] = datam;
1.1       root     1446:       data1 = data2;
                   1447:     }
                   1448:   } else {
                   1449:     /* scaled by 2, 24bpp */
                   1450:     p = outdata;
                   1451:     data1 = ui_palcache[indata[0]];
1.1.1.2 ! root     1452:     for (ui = 0; ui < pixels; ui++, p += 6) {
        !          1453:       data2 = ui_palcache[indata[ui + 1]];
1.1       root     1454:       datam = (((((data1 & visual_redmask) +
1.1.1.2 ! root     1455:                   (data2 & visual_redmask)) >> 1) & visual_redmask) |
        !          1456:                ((((data1 & visual_greenmask) +
        !          1457:                   (data2 & visual_greenmask)) >> 1) & visual_greenmask) |
        !          1458:                ((((data1 & visual_bluemask) +
        !          1459:                   (data2 & visual_bluemask)) >> 1) & visual_bluemask));
1.1       root     1460: #ifdef WORDS_BIGENDIAN
1.1.1.2 ! root     1461:       p[0] = (uint8)(data1 >> 16);
        !          1462:       p[lineoffset + 0] = (uint8)(data1 >> 16);
        !          1463:       p[lineoffset + 3] = (uint8)(datam >> 16);
        !          1464:       p[3] = (uint8)(datam >> 16);
        !          1465:       p[1] = (uint8)(data1 >> 8);
        !          1466:       p[lineoffset + 1] = (uint8)(data1 >> 8);
        !          1467:       p[lineoffset + 4] = (uint8)(datam >> 8);
        !          1468:       p[4] = (uint8)(datam >> 8);
        !          1469:       p[2] = (uint8)(data1);
        !          1470:       p[lineoffset + 2] = (uint8)(data1);
        !          1471:       p[lineoffset + 5] = (uint8)(datam);
        !          1472:       p[5] = (uint8)(datam);
1.1       root     1473: #else
1.1.1.2 ! root     1474:       p[0] = (uint8)(data1);
        !          1475:       p[lineoffset + 0] = (uint8)(data1);
        !          1476:       p[lineoffset + 3] = (uint8)(datam);
        !          1477:       p[3] = (uint8)(datam);
        !          1478:       p[1] = (uint8)(data1 >> 8);
        !          1479:       p[lineoffset + 1] = (uint8)(data1 >> 8);
        !          1480:       p[lineoffset + 4] = (uint8)(datam >> 8);
        !          1481:       p[4] = (uint8)(datam >> 8);
        !          1482:       p[2] = (uint8)(data1 >> 16);
        !          1483:       p[lineoffset + 2] = (uint8)(data1 >> 16);
        !          1484:       p[lineoffset + 5] = (uint8)(datam >> 16);
        !          1485:       p[5] = (uint8)(datam >> 16);
1.1       root     1486: #endif
                   1487:       data1 = data2;
                   1488:     }
                   1489:   }
                   1490: }
                   1491: 
                   1492: /*** ui_endfield - end of field reached ***/
                   1493: 
                   1494: void ui_endfield(void)
                   1495: {
                   1496:   ui_endframe();
                   1497: }
                   1498: 
                   1499: /*** ui_endframe - end of frame reached ***/
                   1500: 
                   1501: void ui_endframe(void)
                   1502: {
                   1503:   int y, x, i;
                   1504:   XColor xcolor;
                   1505:   uint16 col;
1.1.1.2 ! root     1506:   static uint8 gfx[(320 + 16) * (240 + 16)];
1.1       root     1507:   char *p, *framestart;
                   1508:   unsigned int lineoffset, line;
                   1509: 
                   1510:   if (cpu68k_frames % frameskip != 0)
                   1511:     return;
                   1512: 
                   1513:   if (ui_vdpsimple) {
                   1514:     /* simple mode - entire frame done here */
1.1.1.2 ! root     1515:     framestart = gfx + (8 * 320) + 8;
        !          1516:     vdp_renderframe(framestart, 320 + 16);      /* plot frame */
1.1       root     1517: #ifdef XF86DGA
                   1518:     if (ui_dga_state) {
1.1.1.2 ! root     1519:       lineoffset = dga_xsize * (depth / 8);
1.1       root     1520:       p = dga_start;
                   1521:     } else {
1.1.1.2 ! root     1522:       lineoffset = 320 * (depth / 8) * scale;
1.1       root     1523:       p = imagedata;
                   1524:     }
                   1525: #else
1.1.1.2 ! root     1526:     lineoffset = 320 * (depth / 8) * scale;
1.1       root     1527:     p = imagedata;
                   1528: #endif
                   1529:     for (line = 0; line < 224; line++) {
                   1530:       if (scale == 2 && smooth) {
1.1.1.2 ! root     1531:         ui_convertdata_smooth(framestart + (320 + 16) * line,
        !          1532:                               p + lineoffset * line * scale, 320,
        !          1533:                               lineoffset, depth);
1.1       root     1534:       } else {
1.1.1.2 ! root     1535:         ui_convertdata(framestart + (320 + 16) * line,
        !          1536:                        p + lineoffset * line * scale, 320, lineoffset,
        !          1537:                        scale, depth, basepixel);
1.1       root     1538:       }
                   1539:     }
                   1540:   }
                   1541:   if (!ui_dga_state) {
                   1542:     /* if ui_dga_state state is set, data has already gone to screen */
                   1543:     if (!gc)
                   1544:       gc = XCreateGC(ui_display, Tk_WindowId(mainwin), 0, NULL);
1.1.1.2 ! root     1545:     XPutImage(ui_display,
        !          1546:               Tk_WindowId(Tk_NameToWindow(interp, ".main", mainwin)),
        !          1547:               gc, image, 0, 0, 0, 0, 320 * scale, 240 * scale);
1.1       root     1548:   }
                   1549:   if (depth == 8) {
                   1550:     for (i = 0; i < 64; i++) {
                   1551:       if (vdp_cramf[i]) {
1.1.1.2 ! root     1552:         xcolor.pixel = basepixel + i;
        !          1553:         xcolor.flags = DoRed | DoGreen | DoBlue;
        !          1554:         xcolor.blue = ((((uint8 *)vdp_cram)[2 * i]) & (7 << 1)) << 12;
        !          1555:         xcolor.red = ((((uint8 *)vdp_cram)[2 * i + 1]) & (7 << 1)) << 12;
        !          1556:         xcolor.green = ((((uint8 *)vdp_cram)[2 * i + 1]) & (7 << 5)) << 8;
        !          1557:         XStoreColor(ui_display, cmap, &xcolor);
        !          1558:         xcolor.pixel = basepixel + i + 64;
        !          1559:         xcolor.blue =
        !          1560:           1 << 15 | ((((uint8 *)vdp_cram)[2 * i]) & (7 << 1)) << 11;
        !          1561:         xcolor.red =
        !          1562:           1 << 15 | ((((uint8 *)vdp_cram)[2 * i + 1]) & (7 << 1)) << 11;
        !          1563:         xcolor.green =
        !          1564:           1 << 15 | ((((uint8 *)vdp_cram)[2 * i + 1]) & (7 << 5)) << 7;
        !          1565:         XStoreColor(ui_display, cmap, &xcolor);
        !          1566:         xcolor.pixel = basepixel + i + 128;
        !          1567:         xcolor.blue = ((((uint8 *)vdp_cram)[2 * i]) & (7 << 1)) << 11;
        !          1568:         xcolor.red = ((((uint8 *)vdp_cram)[2 * i + 1]) & (7 << 1)) << 11;
        !          1569:         xcolor.green = ((((uint8 *)vdp_cram)[2 * i + 1]) & (7 << 5)) << 7;
        !          1570:         XStoreColor(ui_display, cmap, &xcolor);
        !          1571:         vdp_cramf[i] = 0;
1.1       root     1572:       }
                   1573:     }
                   1574:   }
                   1575: }
                   1576: 
                   1577: /*
                   1578: 
                   1579: void ui_run(void)
                   1580: {
                   1581:   gen_quit = 0;
                   1582:   do {
                   1583:     event_doframe();
                   1584:     while (Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT));
                   1585:   } while(!gen_quit);
                   1586:   if (gen_debugmode) {
                   1587:     ui_updateregs();
                   1588:     if (gen_quit)
                   1589:       LOG_NORMAL(("Stopped."));
                   1590:   }
                   1591:   gen_quit = 0;
                   1592: }
                   1593: 
                   1594: */
                   1595: 
                   1596: #ifdef XF86DGA
                   1597: void ui_fullscreen(int onoff)
                   1598: {
                   1599:   static int forkflag = 0;
                   1600:   int i;
                   1601: 
                   1602:   ui_dga_state = 0;
                   1603: 
                   1604:   if (!ui_dga) {
1.1.1.2 ! root     1605:     LOG_CRITICAL(("DGA has been disabled, see error message " "on startup."));
1.1       root     1606:     return;
                   1607:   }
                   1608:   if (onoff) {
                   1609:     if (!XF86DGADirectVideo(ui_display, ui_screenno, XF86DGADirectGraphics)) {
                   1610:       LOG_CRITICAL(("Switch to DGA direct video failed"));
                   1611:       return;
                   1612:     }
                   1613:     if (!XF86DGASetViewPort(ui_display, ui_screenno, 0, 0)) {
                   1614:       LOG_CRITICAL(("Setting of DGA view port failed"));
                   1615:       return;
                   1616:     }
                   1617:     memset(dga_baseaddr, 0, dga_banksize);
                   1618:     ui_dga_state = 1;
                   1619:   } else {
                   1620:     if (!XF86DGADirectVideo(ui_display, ui_screenno, 0)) {
                   1621:       LOG_CRITICAL(("Switch out of DGA mode failed"));
                   1622:       return;
                   1623:     }
                   1624:   }
                   1625: }
                   1626: #endif
                   1627: 
                   1628: /*** logging functions ***/
                   1629: 
                   1630: /* logging is done this way because this was the best I could come up with
                   1631:    whilst battling with macros that can only take fixed numbers of arguments */
                   1632: 
                   1633: #define LOG_FUNC(name,level,txt) void ui_log_ ## name ## (const char *text, ...) \
                   1634: { \
                   1635:   va_list ap; \
                   1636:   if (gen_loglevel >= level) { \
                   1637:     printf("%s (%05X) ", txt, cpu68k_clocks); \
                   1638:     va_start(ap, text); \
                   1639:     vprintf(text, ap); \
                   1640:     va_end(ap); \
                   1641:     putchar(10); \
                   1642:   } \
                   1643: }
                   1644: 
1.1.1.2 ! root     1645: LOG_FUNC(debug3, 7, "DEBG ");
        !          1646: LOG_FUNC(debug2, 6, "DEBG ");
        !          1647: LOG_FUNC(debug1, 5, "DEBG ");
        !          1648: LOG_FUNC(user, 4, "USER ");
        !          1649: LOG_FUNC(verbose, 3, "---- ");
        !          1650: LOG_FUNC(normal, 2, "---- ");
1.1       root     1651: LOG_FUNC(critical, 1, "CRIT ");
1.1.1.2 ! root     1652: LOG_FUNC(request, 0, "---- ");
1.1       root     1653: 
                   1654: /*** ui_err - log error message and quit ***/
                   1655: 
                   1656: void ui_err(const char *text, ...)
                   1657: {
                   1658:   va_list ap;
                   1659: 
                   1660:   printf("ERROR: ");
                   1661: 
                   1662:   va_start(ap, text);
                   1663:   vfprintf(stderr, text, ap);
                   1664:   va_end(ap);
                   1665:   putc(10, stderr);
                   1666:   exit(1);
                   1667: }

unix.superglobalmegacorp.com

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