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