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

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

unix.superglobalmegacorp.com

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