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

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

unix.superglobalmegacorp.com

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