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