|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.