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

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

unix.superglobalmegacorp.com

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