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

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

unix.superglobalmegacorp.com

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