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

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

unix.superglobalmegacorp.com

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