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

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

unix.superglobalmegacorp.com

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