1 /* xscreensaver, Copyright (c) 1998-2003 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
11 * Blue Screen of Death: the finest in personal computer emulation.
12 * Concept cribbed from Stephen Martin <smartin@mks.com>;
13 * this version written by jwz, 4-Jun-98.
17 #include "screenhack.h"
18 #include "xpm-pixmap.h"
22 #include <X11/Xutil.h>
24 #ifdef HAVE_XSHM_EXTENSION
29 # include <sys/utsname.h>
30 #endif /* HAVE_UNAME */
32 #include "images/amiga.xpm"
33 #include "images/atari.xbm"
34 #include "images/mac.xbm"
35 #include "images/macbomb.xbm"
36 #include "images/hmac.xpm"
39 #define countof(x) (sizeof((x))/sizeof((*x)))
42 draw_string (Display *dpy, Window window, GC gc, XGCValues *gcv,
45 int win_width, int win_height,
46 const char *string, int delay)
49 int width = 0, height = 0, cw = 0;
50 int char_width, line_height;
52 const char *s = string;
53 const char *se = string;
55 /* This pretty much assumes fixed-width fonts */
56 char_width = (font->per_char
57 ? font->per_char['n'-font->min_char_or_byte2].width
58 : font->min_bounds.width);
59 line_height = font->ascent + font->descent + 1;
63 if (*s == '\n' || !*s)
66 if (cw > width) width = cw;
75 x = (win_width - (width * char_width)) / 2;
76 y = (win_height - (height * line_height)) / 2;
87 if (*s == '\n' || !*s)
92 if (*se == '@' || *se == '_')
94 if (*se == '@') flip = True;
96 off = (char_width * (width - (s - se))) / 2;
101 XSetForeground(dpy, gc, gcv->background);
102 XSetBackground(dpy, gc, gcv->foreground);
106 XDrawImageString(dpy, window, gc, x+off, y+font->ascent, se, s-se);
110 XSetForeground(dpy, gc, gcv->foreground);
111 XSetBackground(dpy, gc, gcv->background);
128 return width * char_width;
133 double_pixmap(Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap,
134 int pix_w, int pix_h)
137 Pixmap p2 = XCreatePixmap(dpy, pixmap, pix_w*2, pix_h*2, depth);
138 XImage *i1 = XGetImage(dpy, pixmap, 0, 0, pix_w, pix_h, ~0L, ZPixmap);
139 XImage *i2 = XCreateImage(dpy, visual, depth, ZPixmap, 0, 0,
140 pix_w*2, pix_h*2, 8, 0);
141 i2->data = (char *) calloc(i2->height, i2->bytes_per_line);
142 for (y = 0; y < pix_h; y++)
143 for (x = 0; x < pix_w; x++)
145 unsigned long p = XGetPixel(i1, x, y);
146 XPutPixel(i2, x*2, y*2, p);
147 XPutPixel(i2, x*2+1, y*2, p);
148 XPutPixel(i2, x*2, y*2+1, p);
149 XPutPixel(i2, x*2+1, y*2+1, p);
151 free(i1->data); i1->data = 0;
153 XPutImage(dpy, p2, gc, i2, 0, 0, 0, 0, i2->width, i2->height);
154 free(i2->data); i2->data = 0;
156 XFreePixmap(dpy, pixmap);
161 /* Sleep for N seconds and return False. But if a key or mouse event is
162 seen, discard all pending key or mouse events, and return True.
165 bsod_sleep(Display *dpy, int seconds)
168 int quantum = 250000;
171 q = 1, quantum = 100000;
176 while (XPending (dpy))
179 XNextEvent (dpy, &event);
180 if (event.xany.type == ButtonPress)
182 if (event.xany.type == KeyPress)
186 XLookupString (&event.xkey, &c, 1, &keysym, 0);
187 if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
190 screenhack_handle_event (dpy, &event);
206 windows (Display *dpy, Window window, int delay, int which)
209 XWindowAttributes xgwa;
211 const char *def_font = "fixed";
217 "A fatal exception 0E has occured at F0AD:42494C4C\n"
218 "the current application will be terminated.\n"
220 "* Press any key to terminate the current application.\n"
221 "* Press CTRL+ALT+DELETE again to restart your computer.\n"
222 " You will lose any unsaved information in all applications.\n"
225 "_Press any key to continue");
227 const char *wnt = /* from Jim Niemira <urmane@urmane.org> */
228 ("*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n"
229 "Unhandled Kernel exception c0000047 from fa8418b4 (8025ea21,fd6829e8)\n"
231 "Dll Base Date Stamp - Name Dll Base Date Stamp - Name\n"
232 "80100000 2be154c9 - ntoskrnl.exe 80400000 2bc153b0 - hal.dll\n"
233 "80258000 2bd49628 - ncrc710.sys 8025c000 2bd49688 - SCSIPORT.SYS \n"
234 "80267000 2bd49683 - scsidisk.sys 802a6000 2bd496b9 - Fastfat.sys\n"
235 "fa800000 2bd49666 - Floppy.SYS fa810000 2bd496db - Hpfs_Rec.SYS\n"
236 "fa820000 2bd49676 - Null.SYS fa830000 2bd4965a - Beep.SYS\n"
237 "fa840000 2bdaab00 - i8042prt.SYS fa850000 2bd5a020 - SERMOUSE.SYS\n"
238 "fa860000 2bd4966f - kbdclass.SYS fa870000 2bd49671 - MOUCLASS.SYS\n"
239 "fa880000 2bd9c0be - Videoprt.SYS fa890000 2bd49638 - NCC1701E.SYS\n"
240 "fa8a0000 2bd4a4ce - Vga.SYS fa8b0000 2bd496d0 - Msfs.SYS\n"
241 "fa8c0000 2bd496c3 - Npfs.SYS fa8e0000 2bd496c9 - Ntfs.SYS\n"
242 "fa940000 2bd496df - NDIS.SYS fa930000 2bd49707 - wdlan.sys\n"
243 "fa970000 2bd49712 - TDI.SYS fa950000 2bd5a7fb - nbf.sys\n"
244 "fa980000 2bd72406 - streams.sys fa9b0000 2bd4975f - ubnb.sys\n"
245 "fa9c0000 2bd5bfd7 - usbser.sys fa9d0000 2bd4971d - netbios.sys\n"
246 "fa9e0000 2bd49678 - Parallel.sys fa9f0000 2bd4969f - serial.SYS\n"
247 "faa00000 2bd49739 - mup.sys faa40000 2bd4971f - SMBTRSUP.SYS\n"
248 "faa10000 2bd6f2a2 - srv.sys faa50000 2bd4971a - afd.sys\n"
249 "faa60000 2bd6fd80 - rdr.sys faaa0000 2bd49735 - bowser.sys\n"
251 "Address dword dump Dll Base - Name\n"
252 "801afc20 80106fc0 80106fc0 00000000 00000000 80149905 : "
253 "fa840000 - i8042prt.SYS\n"
254 "801afc24 80149905 80149905 ff8e6b8c 80129c2c ff8e6b94 : "
255 "8025c000 - SCSIPORT.SYS\n"
256 "801afc2c 80129c2c 80129c2c ff8e6b94 00000000 ff8e6b94 : "
257 "80100000 - ntoskrnl.exe\n"
258 "801afc34 801240f2 80124f02 ff8e6df4 ff8e6f60 ff8e6c58 : "
259 "80100000 - ntoskrnl.exe\n"
260 "801afc54 80124f16 80124f16 ff8e6f60 ff8e6c3c 8015ac7e : "
261 "80100000 - ntoskrnl.exe\n"
262 "801afc64 8015ac7e 8015ac7e ff8e6df4 ff8e6f60 ff8e6c58 : "
263 "80100000 - ntoskrnl.exe\n"
264 "801afc70 80129bda 80129bda 00000000 80088000 80106fc0 : "
265 "80100000 - ntoskrnl.exe\n"
267 "Kernel Debugger Using: COM2 (Port 0x2f8, Baud Rate 19200)\n"
268 "Restart and set the recovery options in the system control panel\n"
269 "or the /CRASHDEBUG system start option. If this message reappears,\n"
270 "contact your system administrator or technical support group."
274 ("*** STOP: 0x000000D1 (0xE1D38000,0x0000001C,0x00000000,0xF09D42DA)\n"
275 "DRIVER_IRQL_NOT_LESS_OR_EQUAL \n"
277 "*** Address F09D42DA base at F09D4000, DateStamp 39f459ff - CRASHDD.SYS\n"
279 "Beginning dump of physical memory\n");
281 ("Physical memory dump complete. Contact your system administrator or\n"
282 "technical support group.\n");
285 (" Windows protection error. You need to restart your computer.");
289 if (which < 0 || which > 2) abort();
291 /* kludge to lump Win2K and WinME together; seems silly to add another
292 preference/command line option just for this little one. */
293 if (which == 2 && (random() % 2))
296 XGetWindowAttributes (dpy, window, &xgwa);
298 fontname = get_string_resource ((xgwa.height > 600
299 ? (which == 0 ? "windows95.font2" :
300 which == 1 ? "windowsNT.font2" :
301 which == 2 ? "windows2K.font2" :
303 : (which == 0 ? "windows95.font" :
304 which == 1 ? "windowsNT.font" :
305 which == 2 ? "windows2K.font" :
308 if (!fontname || !*fontname) fontname = (char *)def_font;
309 font = XLoadQueryFont (dpy, fontname);
310 if (!font) font = XLoadQueryFont (dpy, def_font);
312 if (fontname && fontname != def_font)
315 gcv.font = font->fid;
316 gcv.foreground = get_pixel_resource((which == 0 ? "windows95.foreground" :
317 which == 1 ? "windowsNT.foreground" :
318 which == 2 ? "windows2K.foreground" :
319 "windowsME.foreground"),
320 "Windows.Foreground",
322 gcv.background = get_pixel_resource((which == 0 ? "windows95.background" :
323 which == 1 ? "windowsNT.background" :
324 which == 2 ? "windows2K.background" :
325 "windowsME.background"),
326 "Windows.Background",
328 XSetWindowBackground(dpy, window, gcv.background);
329 XClearWindow(dpy, window);
331 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
334 draw_string(dpy, window, gc, &gcv, font,
335 0, 0, xgwa.width, xgwa.height, w95, 0);
337 draw_string(dpy, window, gc, &gcv, font, 0, 0, 10, 10, wnt, 750);
340 int line_height = font->ascent + font->descent + 1;
342 int y = (xgwa.height / 4);
344 draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, w2ka, 750);
345 y += line_height * 6;
347 draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, w2kb, 750);
351 int line_height = font->ascent + font->descent;
353 int y = (xgwa.height - line_height * 3) / 2;
354 draw_string (dpy, window, gc, &gcv, font, x, y, 10, 10, wmea, 0);
355 y += line_height * 2;
356 x = draw_string (dpy, window, gc, &gcv, font, x, y, 10, 10, wmeb, 0);
360 XDrawImageString (dpy, window, gc, x, y, "_", 1);
363 XDrawImageString (dpy, window, gc, x, y, " ", 1);
366 if (bsod_sleep(dpy, 0))
377 bsod_sleep(dpy, delay);
378 XClearWindow(dpy, window);
379 XFreeFont(dpy, font);
383 windows_31 (Display *dpy, Window window, int delay)
385 windows (dpy, window, delay, 0);
389 windows_nt (Display *dpy, Window window, int delay)
391 windows (dpy, window, delay, 1);
395 windows_2k (Display *dpy, Window window, int delay)
397 windows (dpy, window, delay, 2);
401 /* SCO OpenServer 5 panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
404 sco (Display *dpy, Window window, int delay)
407 XWindowAttributes xgwa;
409 const char *def_font = "fixed";
412 int lines_1 = 0, lines_2 = 0, lines_3 = 0, lines_4 = 0;
415 const char *sco_panic_1 =
416 ("Unexpected trap in kernel mode:\n"
418 "cr0 0x80010013 cr2 0x00000014 cr3 0x00000000 tlb 0x00000000\n"
419 "ss 0x00071054 uesp 0x00012055 efl 0x00080888 ipl 0x00000005\n"
420 "cs 0x00092585 eip 0x00544a4b err 0x004d4a47 trap 0x0000000E\n"
421 "eax 0x0045474b ecx 0x0042544b edx 0x57687920 ebx 0x61726520\n"
422 "esp 0x796f7520 ebp 0x72656164 esi 0x696e6720 edi 0x74686973\n"
423 "ds 0x3f000000 es 0x43494c48 fs 0x43525343 gs 0x4f4d4b53\n"
425 "PANIC: k_trap - kernel mode trap type 0x0000000E\n"
426 "Trying to dump 5023 pages to dumpdev hd (1/41), 63 pages per '.'\n"
428 const char *sco_panic_2 =
429 ("................................................................."
432 const char *sco_panic_3 =
433 ("5023 pages dumped\n"
437 const char *sco_panic_4 =
438 ("** Safe to Power Off **\n"
440 "** Press Any Key to Reboot **\n"
443 for (s = sco_panic_1; *s; s++) if (*s == '\n') lines_1++;
444 for (s = sco_panic_2; *s; s++) if (*s == '\n') lines_2++;
445 for (s = sco_panic_3; *s; s++) if (*s == '\n') lines_3++;
446 for (s = sco_panic_4; *s; s++) if (*s == '\n') lines_4++;
448 XGetWindowAttributes (dpy, window, &xgwa);
450 fontname = get_string_resource ((xgwa.height > 600
454 if (!fontname || !*fontname) fontname = (char *)def_font;
455 font = XLoadQueryFont (dpy, fontname);
456 if (!font) font = XLoadQueryFont (dpy, def_font);
458 if (fontname && fontname != def_font)
461 gcv.font = font->fid;
462 gcv.foreground = get_pixel_resource(("sco.foreground"),
465 gcv.background = get_pixel_resource(("sco.background"),
468 XSetWindowBackground(dpy, window, gcv.background);
469 XClearWindow(dpy, window);
471 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
473 draw_string(dpy, window, gc, &gcv, font,
474 10, xgwa.height - ((lines_1 + lines_2 + lines_3 + lines_4 + 1) *
475 (font->ascent + font->descent + 1)),
479 for (s = sco_panic_2; *s; s++)
481 char *ss = strdup(sco_panic_2);
482 ss[s - sco_panic_2] = 0;
483 draw_string(dpy, window, gc, &gcv, font,
484 10, xgwa.height - ((lines_2 + lines_3 + lines_4 + 1) *
485 (font->ascent + font->descent + 1)),
490 if (bsod_sleep (dpy, -1))
494 draw_string(dpy, window, gc, &gcv, font,
495 10, xgwa.height - ((lines_3 + lines_4 + 1) *
496 (font->ascent + font->descent + 1)),
500 if (bsod_sleep(dpy, 1))
502 draw_string(dpy, window, gc, &gcv, font,
503 10, xgwa.height - ((lines_4 + 1) *
504 (font->ascent + font->descent + 1)),
509 bsod_sleep(dpy, delay);
511 XClearWindow(dpy, window);
513 XFreeFont(dpy, font);
517 /* Linux (sparc) panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
520 sparc_linux (Display *dpy, Window window, int delay)
523 XWindowAttributes xgwa;
525 const char *def_font = "fixed";
531 const char *linux_panic =
532 ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
533 "Unable to handle kernel paging request at virtual address f0d4a000\n"
534 "tsk->mm->context = 00000014\n"
535 "tsk->mm->pgd = f26b0000\n"
540 "gawk(22827): Oops\n"
541 "PSR: 044010c1 PC: f001c2cc NPC: f001c2d0 Y: 00000000\n"
542 "g0: 00001000 g1: fffffff7 g2: 04401086 g3: 0001eaa0\n"
543 "g4: 000207dc g5: f0130400 g6: f0d4a018 g7: 00000001\n"
544 "o0: 00000000 o1: f0d4a298 o2: 00000040 o3: f1380718\n"
545 "o4: f1380718 o5: 00000200 sp: f1b13f08 ret_pc: f001c2a0\n"
546 "l0: efffd880 l1: 00000001 l2: f0d4a230 l3: 00000014\n"
547 "l4: 0000ffff l5: f0131550 l6: f012c000 l7: f0130400\n"
548 "i0: f1b13fb0 i1: 00000001 i2: 00000002 i3: 0007c000\n"
549 "i4: f01457c0 i5: 00000004 i6: f1b13f70 i7: f0015360\n"
550 "Instruction DUMP:\n"
553 for (s = linux_panic; *s; s++) if (*s == '\n') lines++;
555 XGetWindowAttributes (dpy, window, &xgwa);
557 fontname = get_string_resource ((xgwa.height > 600
559 : "sparclinux.font"),
561 if (!fontname || !*fontname) fontname = (char *)def_font;
562 font = XLoadQueryFont (dpy, fontname);
563 if (!font) font = XLoadQueryFont (dpy, def_font);
565 if (fontname && fontname != def_font)
568 gcv.font = font->fid;
569 gcv.foreground = get_pixel_resource(("sparclinux.foreground"),
570 "SparcLinux.Foreground",
572 gcv.background = get_pixel_resource(("sparclinux.background"),
573 "SparcLinux.Background",
575 XSetWindowBackground(dpy, window, gcv.background);
576 XClearWindow(dpy, window);
578 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
580 draw_string(dpy, window, gc, &gcv, font,
581 10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
586 bsod_sleep(dpy, delay);
587 XClearWindow(dpy, window);
588 XFreeFont(dpy, font);
591 /* BSD Panic by greywolf@starwolf.com - modeled after the Linux panic above.
592 By Grey Wolf <greywolf@siteROCK.com>
595 bsd (Display *dpy, Window window, int delay)
598 XWindowAttributes xgwa;
600 const char *def_font = "fixed";
605 const char *rbstr, *panicking;
606 char syncing[80], bbuf[5], *bp;
608 const char *panicstr[] =
609 {"panic: ifree: freeing free inode",
610 "panic: blkfree: freeing free block",
611 "panic: improbability coefficient below zero",
613 "panic: crazy interrupts",
615 "panic: attempted windows install",
617 "panic: free inode isn't",
618 "panic: cpu_fork: curproc",
619 "panic: malloc: out of space in kmem_map",
620 "panic: vogon starship detected",
621 "panic: teleport chamber: out of order",
622 "panic: Brain fried - core dumped"};
624 for (i = 0; i < sizeof(syncing); i++)
627 i = (random() & 0xffff) % (sizeof(panicstr) / sizeof(*panicstr));
629 panicking = panicstr[i];
630 strcpy(syncing, "Syncing disks: ");
632 b = (random() & 0xff) % 40;
633 for (n = 0; (n < 20) && (b > 0); n++)
637 i = (random() & 0x7);
638 b -= (random() & 0xff) % 20;
642 sprintf (bbuf, "%d ", b);
643 strcat (syncing, bbuf);
653 XGetWindowAttributes (dpy, window, &xgwa);
655 fontname = get_string_resource ((xgwa.height > 600
659 if (!fontname || !*fontname) fontname = (char *)def_font;
660 font = XLoadQueryFont (dpy, fontname);
661 if (!font) font = XLoadQueryFont (dpy, def_font);
663 if (fontname && fontname != def_font)
666 gcv.font = font->fid;
667 gcv.foreground = get_pixel_resource(("bsd.foreground"),
670 gcv.background = get_pixel_resource(("bsd.background"),
673 XSetWindowBackground(dpy, window, gcv.background);
674 XClearWindow(dpy, window);
676 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
678 draw_string(dpy, window, gc, &gcv, font,
679 10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
685 for (bp = syncing; *bp;)
687 char *bsd_bufs, oc = 0;
688 for (;*bp && (*bp != ' '); bp++)
695 bsd_bufs = strdup(syncing);
696 draw_string(dpy, window, gc, &gcv, font,
698 xgwa.height - (lines * (font->ascent + font->descent + 1)),
705 if (bsod_sleep(dpy, -1))
712 draw_string(dpy, window, gc, &gcv, font,
713 10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
717 draw_string(dpy, window, gc, &gcv, font,
718 10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
724 bsod_sleep(dpy, delay);
727 XClearWindow(dpy, window);
728 XFreeFont(dpy, font);
732 amiga (Display *dpy, Window window, int delay)
735 XWindowAttributes xgwa;
737 const char *def_font = "fixed";
741 unsigned long fg, bg, bg2;
743 int pix_w = 0, pix_h = 0;
748 ("_Software failure. Press left mouse button to continue.\n"
749 "_Guru Meditation #00000003.00C01570");
751 XGetWindowAttributes (dpy, window, &xgwa);
753 fontname = get_string_resource ((xgwa.height > 600
754 ? "amiga.font2" : "amiga.font"),
756 if (!fontname || !*fontname) fontname = (char *)def_font;
757 font = XLoadQueryFont (dpy, fontname);
758 if (!font) font = XLoadQueryFont (dpy, def_font);
760 if (fontname && fontname != def_font)
763 gcv.font = font->fid;
764 fg = gcv.foreground = get_pixel_resource("amiga.foreground",
767 bg = gcv.background = get_pixel_resource("amiga.background",
770 bg2 = get_pixel_resource("amiga.background2", "Amiga.Background",
772 XSetWindowBackground(dpy, window, bg2);
773 XClearWindow(dpy, window);
775 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
776 gcv.background = fg; gcv.foreground = bg;
777 gc2 = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
779 height = (font->ascent + font->descent) * 6;
781 #if defined(HAVE_GDK_PIXBUF) || defined (HAVE_XPM)
782 pixmap = xpm_data_to_pixmap (dpy, window, (char **) amiga_hand,
784 #endif /* HAVE_GDK_PIXBUF || HAVE_XPM */
786 if (pixmap && xgwa.height > 600) /* scale up the bitmap */
788 pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
789 pixmap, pix_w, pix_h);
796 int x = (xgwa.width - pix_w) / 2;
797 int y = ((xgwa.height - pix_h) / 2);
798 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
803 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y + height);
804 XClearArea(dpy, window, 0, 0, xgwa.width, y + height, False);
805 XFreePixmap(dpy, pixmap);
808 XFillRectangle(dpy, window, gc2, 0, 0, xgwa.width, height);
809 margin = font->ascent;
810 string_width = draw_string(dpy, window, gc, &gcv, font,
812 xgwa.width - (margin * 2), height,
819 XFillRectangle(dpy, window, gca, 0, 0, xgwa.width, margin);
820 XFillRectangle(dpy, window, gca, 0, 0, margin, height);
821 XFillRectangle(dpy, window, gca,
822 0, height - margin, xgwa.width, margin);
823 x2 = margin + string_width;
824 if (x2 < xgwa.width - margin) x2 = xgwa.width - margin;
825 XFillRectangle(dpy, window, gca, x2, 0, margin, height);
827 gca = (gca == gc ? gc2 : gc);
829 if (bsod_sleep(dpy, 1))
838 XClearWindow(dpy, window);
839 XFreeFont(dpy, font);
843 /* Atari ST, by Marcus Herbert <rhoenie@nobiscum.de>
844 Marcus had this to say:
846 Though I still have my Atari somewhere, I hardly remember
847 the meaning of the bombs. I think 9 bombs was "bus error" or
848 something like that. And you often had a few bombs displayed
849 quickly and then the next few ones coming up step by step.
850 Perhaps somebody else can tell you more about it.. its just
854 atari (Display *dpy, Window window, int delay)
858 XWindowAttributes xgwa;
859 const char *def_font = "fixed";
863 int pix_w = atari_width;
864 int pix_h = atari_height;
868 XGetWindowAttributes (dpy, window, &xgwa);
870 font = XLoadQueryFont (dpy, def_font);
873 gcv.font = font->fid;
874 gcv.foreground = get_pixel_resource("atari.foreground", "Atari.Foreground",
876 gcv.background = get_pixel_resource("atari.background", "Atari.Background",
879 XSetWindowBackground(dpy, window, gcv.background);
880 XClearWindow(dpy, window);
882 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
884 pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) atari_bits,
886 gcv.foreground, gcv.background,
888 pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
889 pixmap, pix_w, pix_h);
895 y = (xgwa.height - (xgwa.height / 5));
898 for (i=0 ; i<7 ; i++) {
899 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h,
900 (x + (i*offset)), y);
903 for (i=7 ; i<10 ; i++) {
904 if (bsod_sleep(dpy, 1))
906 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h,
907 (x + (i*offset)), y);
910 bsod_sleep(dpy, delay);
912 XFreePixmap(dpy, pixmap);
915 XClearWindow(dpy, window);
916 XFreeFont(dpy, font);
921 mac (Display *dpy, Window window, int delay)
924 XWindowAttributes xgwa;
926 const char *def_font = "fixed";
930 int pix_w = mac_width;
931 int pix_h = mac_height;
932 int offset = mac_height * 4;
935 const char *string = ("0 0 0 0 0 0 0 F\n"
938 XGetWindowAttributes (dpy, window, &xgwa);
940 fontname = get_string_resource ("mac.font", "Mac.Font");
941 if (!fontname || !*fontname) fontname = (char *)def_font;
942 font = XLoadQueryFont (dpy, fontname);
943 if (!font) font = XLoadQueryFont (dpy, def_font);
945 if (fontname && fontname != def_font)
948 gcv.font = font->fid;
949 gcv.foreground = get_pixel_resource("mac.foreground", "Mac.Foreground",
951 gcv.background = get_pixel_resource("mac.background", "Mac.Background",
953 XSetWindowBackground(dpy, window, gcv.background);
954 XClearWindow(dpy, window);
956 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
958 pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) mac_bits,
959 mac_width, mac_height,
964 for(i = 0; i < 2; i++)
966 pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
967 pixmap, pix_w, pix_h);
968 pix_w *= 2; pix_h *= 2;
972 int x = (xgwa.width - pix_w) / 2;
973 int y = (((xgwa.height + offset) / 2) -
975 (font->ascent + font->descent) * 2);
977 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
978 XFreePixmap(dpy, pixmap);
981 draw_string(dpy, window, gc, &gcv, font, 0, 0,
982 xgwa.width, xgwa.height + offset, string, 0);
986 bsod_sleep(dpy, delay);
987 XClearWindow(dpy, window);
988 XFreeFont(dpy, font);
992 macsbug (Display *dpy, Window window, int delay)
995 XWindowAttributes xgwa;
997 const char *def_font = "fixed";
1001 int char_width, line_height;
1002 int col_right, row_top, row_bottom, page_right, page_bottom, body_top;
1005 const char *left = (" SP \n"
1052 const char *bottom = (" _A09D\n"
1053 " +00884 40843714 #$0700,SR "
1055 " +00886 40843765 *+$0400 "
1057 " +00888 40843718 $0004(A7),([0,A7[)"
1058 " ; 04E8D0AE | 66B8");
1061 const char *body = ("Bus Error at 4BF6D6CC\n"
1062 "while reading word from 4BF6D6CC in User data space\n"
1063 " Unable to access that address\n"
1065 " Frame Type: B008");
1067 const char * body = ("PowerPC unmapped memory exception at 003AFDAC "
1068 "BowelsOfTheMemoryMgr+04F9C\n"
1069 " Calling chain using A6/R1 links\n"
1070 " Back chain ISA Caller\n"
1071 " 00000000 PPC 28C5353C __start+00054\n"
1072 " 24DB03C0 PPC 28B9258C main+0039C\n"
1073 " 24DB0350 PPC 28B9210C MainEvent+00494\n"
1074 " 24DB02B0 PPC 28B91B40 HandleEvent+00278\n"
1075 " 24DB0250 PPC 28B83DAC DoAppleEvent+00020\n"
1076 " 24DB0210 PPC FFD3E5D0 "
1077 "AEProcessAppleEvent+00020\n"
1078 " 24DB0132 68K 00589468\n"
1079 " 24DAFF8C 68K 00589582\n"
1080 " 24DAFF26 68K 00588F70\n"
1081 " 24DAFEB3 PPC 00307098 "
1082 "EmToNatEndMoveParams+00014\n"
1083 " 24DAFE40 PPC 28B9D0B0 DoScript+001C4\n"
1084 " 24DAFDD0 PPC 28B9C35C RunScript+00390\n"
1085 " 24DAFC60 PPC 28BA36D4 run_perl+000E0\n"
1086 " 24DAFC10 PPC 28BC2904 perl_run+002CC\n"
1087 " 24DAFA80 PPC 28C18490 Perl_runops+00068\n"
1088 " 24DAFA30 PPC 28BE6CC0 Perl_pp_backtick+000FC\n"
1089 " 24DAF9D0 PPC 28BA48B8 Perl_my_popen+00158\n"
1090 " 24DAF980 PPC 28C5395C sfclose+00378\n"
1091 " 24DAF930 PPC 28BA568C free+0000C\n"
1092 " 24DAF8F0 PPC 28BA6254 pool_free+001D0\n"
1093 " 24DAF8A0 PPC FFD48F14 DisposePtr+00028\n"
1094 " 24DAF7C9 PPC 00307098 "
1095 "EmToNatEndMoveParams+00014\n"
1096 " 24DAF780 PPC 003AA180 __DisposePtr+00010");
1102 for (s = body; *s; s++) if (*s == '\n') body_lines++;
1104 XGetWindowAttributes (dpy, window, &xgwa);
1106 fontname = get_string_resource ((xgwa.height > 850
1108 : (xgwa.height > 700
1112 if (!fontname || !*fontname) fontname = (char *)def_font;
1113 font = XLoadQueryFont (dpy, fontname);
1114 if (!font) font = XLoadQueryFont (dpy, def_font);
1115 if (!font) exit(-1);
1116 if (fontname && fontname != def_font)
1119 gcv.font = font->fid;
1120 gcv.foreground = get_pixel_resource("macsbug.foreground",
1121 "MacsBug.Foreground",
1122 dpy, xgwa.colormap);
1123 gcv.background = get_pixel_resource("macsbug.background",
1124 "MacsBug.Background",
1125 dpy, xgwa.colormap);
1127 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
1129 gcv.foreground = gcv.background;
1130 gc2 = XCreateGC(dpy, window, GCForeground, &gcv);
1132 XSetWindowBackground(dpy, window,
1133 get_pixel_resource("macsbug.borderColor",
1134 "MacsBug.BorderColor",
1135 dpy, xgwa.colormap));
1136 XClearWindow(dpy, window);
1138 char_width = (font->per_char
1139 ? font->per_char['n'-font->min_char_or_byte2].width
1140 : font->min_bounds.width);
1141 line_height = font->ascent + font->descent + 1;
1143 col_right = char_width * 12;
1144 page_bottom = line_height * 47;
1146 if (page_bottom > xgwa.height) page_bottom = xgwa.height;
1148 row_bottom = page_bottom - line_height;
1149 row_top = row_bottom - (line_height * 4);
1150 page_right = col_right + (char_width * 88);
1151 body_top = row_top - (line_height * body_lines);
1157 xoff = (xgwa.width - page_right) / 2;
1158 yoff = (xgwa.height - page_bottom) / 2;
1159 if (xoff < 0) xoff = 0;
1160 if (yoff < 0) yoff = 0;
1162 XFillRectangle(dpy, window, gc2, xoff, yoff, page_right, page_bottom);
1164 draw_string(dpy, window, gc, &gcv, font, xoff, yoff, 10, 10, left, 0);
1165 draw_string(dpy, window, gc, &gcv, font, xoff+col_right, yoff+row_top,
1168 XFillRectangle(dpy, window, gc, xoff + col_right, yoff, 2, page_bottom);
1169 XDrawLine(dpy, window, gc,
1170 xoff+col_right, yoff+row_top, xoff+page_right, yoff+row_top);
1171 XDrawLine(dpy, window, gc,
1172 xoff+col_right, yoff+row_bottom, xoff+page_right, yoff+row_bottom);
1173 XDrawRectangle(dpy, window, gc, xoff, yoff, page_right, page_bottom);
1178 draw_string(dpy, window, gc, &gcv, font,
1179 xoff + col_right + char_width, yoff + body_top, 10, 10, body,
1184 XDrawLine(dpy, window, gc,
1185 xoff+col_right+(char_width/2)+2, yoff+row_bottom+3,
1186 xoff+col_right+(char_width/2)+2, yoff+page_bottom-3);
1189 XDrawLine(dpy, window, gc2,
1190 xoff+col_right+(char_width/2)+2, yoff+row_bottom+3,
1191 xoff+col_right+(char_width/2)+2, yoff+page_bottom-3);
1194 if (bsod_sleep(dpy, 0))
1201 XClearWindow(dpy, window);
1202 XFreeFont(dpy, font);
1206 mac1 (Display *dpy, Window window, int delay)
1209 XWindowAttributes xgwa;
1212 int pix_w = macbomb_width;
1213 int pix_h = macbomb_height;
1215 XGetWindowAttributes (dpy, window, &xgwa);
1217 gcv.foreground = get_pixel_resource("mac1.foreground", "Mac.Foreground",
1218 dpy, xgwa.colormap);
1219 gcv.background = get_pixel_resource("mac1.background", "Mac.Background",
1220 dpy, xgwa.colormap);
1221 XSetWindowBackground(dpy, window, gcv.background);
1222 XClearWindow(dpy, window);
1224 gc = XCreateGC(dpy, window, GCForeground|GCBackground, &gcv);
1226 pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) macbomb_bits,
1227 macbomb_width, macbomb_height,
1233 int x = (xgwa.width - pix_w) / 2;
1234 int y = (xgwa.height - pix_h) / 2;
1236 XFillRectangle (dpy, window, gc, 0, 0, xgwa.width, xgwa.height);
1238 if (bsod_sleep(dpy, 1))
1240 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
1245 XFreePixmap(dpy, pixmap);
1247 bsod_sleep(dpy, delay);
1248 XClearWindow(dpy, window);
1253 macx (Display *dpy, Window window, int delay)
1256 XWindowAttributes xgwa;
1258 const char *def_font = "fixed";
1262 const char *macx_panic =
1263 ("panic(cpu 0): Unable to find driver for this platform: "
1264 "\"PowerMac 3,5\".\n"
1266 "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c "
1267 "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n"
1271 "No debugger configured - dumping debug information\n"
1273 "version string : Darwin Kernel Version 1.3:\n"
1274 "Thu Mar 1 06:56:40 PST 2001; root:xnu/xnu-123.5.obj~1/RELEASE_PPC\n"
1279 "DBAT0: 00000000 00000000\n"
1280 "DBAT1: 00000000 00000000\n"
1281 "DBAT2: 80001FFE 8000003A\n"
1282 "DBAT3: 90001FFE 9000003A\n"
1284 "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c "
1285 "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n"
1287 "panic: We are hanging here...\n");
1289 XGetWindowAttributes (dpy, window, &xgwa);
1291 gcv.background = get_pixel_resource("macX.background",
1293 dpy, xgwa.colormap);
1294 XSetWindowBackground(dpy, window, gcv.background);
1295 XClearWindow(dpy, window);
1297 fontname = get_string_resource ((xgwa.height > 900
1301 if (!fontname || !*fontname) fontname = (char *)def_font;
1302 font = XLoadQueryFont (dpy, fontname);
1303 if (!font) font = XLoadQueryFont (dpy, def_font);
1304 if (!font) exit(-1);
1305 if (fontname && fontname != def_font)
1308 gcv.font = font->fid;
1309 gcv.foreground = get_pixel_resource("macsbug.foreground",
1310 "MacsBug.Foreground",
1311 dpy, xgwa.colormap);
1312 gcv.background = get_pixel_resource("macsbug.background",
1313 "MacsBug.Background",
1314 dpy, xgwa.colormap);
1317 gcv.foreground = get_pixel_resource("macX.textForeground",
1318 "MacX.TextForeground",
1319 dpy, xgwa.colormap);
1320 gcv.background = get_pixel_resource("macX.textBackground",
1321 "MacX.TextBackground",
1322 dpy, xgwa.colormap);
1323 gc = XCreateGC(dpy, window, GCForeground|GCBackground|GCFont, &gcv);
1325 #if defined(HAVE_GDK_PIXBUF) || defined (HAVE_XPM)
1329 int x, y, pix_w, pix_h;
1330 pixmap = xpm_data_to_pixmap (dpy, window, (char **) happy_mac,
1331 &pix_w, &pix_h, &mask);
1333 x = (xgwa.width - pix_w) / 2;
1334 y = (xgwa.height - pix_h) / 2;
1338 XSetClipMask (dpy, gc, mask);
1339 XSetClipOrigin (dpy, gc, x, y);
1340 XCopyArea (dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
1341 XSetClipMask (dpy, gc, None);
1342 XFreePixmap (dpy, pixmap);
1344 #endif /* HAVE_GDK_PIXBUF || HAVE_XPM */
1351 int char_width, line_height;
1352 char_width = (font->per_char
1353 ? font->per_char['n'-font->min_char_or_byte2].width
1354 : font->min_bounds.width);
1355 line_height = font->ascent + font->descent;
1363 if (*s == '\n' || x + char_width >= xgwa.width)
1371 /* Note that to get this goofy effect, they must be actually
1372 emitting LF CR at the end of each line instead of CR LF!
1374 XDrawImageString (dpy, window, gc, ox, oy, " ", 1);
1375 XDrawImageString (dpy, window, gc, ox, y, " ", 1);
1379 XDrawImageString (dpy, window, gc, x, y, s, 1);
1388 bsod_sleep(dpy, delay);
1389 XClearWindow(dpy, window);
1395 * by Martin Pool <mbp@samba.org>, Feb 2000.
1397 * This is meant to look like the preferred failure mode of NCD
1398 * Xterms. The parameters for choosing what to copy where might not
1399 * be quite right, but it looks about ugly enough.
1402 blitdamage (Display *dpy, Window window, int delay)
1405 XWindowAttributes xwa;
1408 int delta_x = 0, delta_y = 0;
1410 int chunk_h, chunk_w;
1416 XGetWindowAttributes(dpy, window, &xwa);
1418 load_random_image (xwa.screen, window, window);
1423 gc_mask = GCForeground;
1425 gcv.plane_mask = random();
1426 gc_mask |= GCPlaneMask;
1428 gc0 = XCreateGC(dpy, window, gc_mask, &gcv);
1431 chunk_w = w / (random() % 1 + 1);
1432 chunk_h = h / (random() % 1 + 1);
1433 if (random() & 0x1000)
1434 delta_y = random() % 600;
1435 if (!delta_y || (random() & 0x2000))
1436 delta_x = random() % 600;
1442 for (i = 0; i < steps; i++) {
1443 if (x + chunk_w > w)
1448 if (y + chunk_h > h)
1453 XCopyArea(dpy, window, window, gc0,
1458 if (bsod_sleep(dpy, 0))
1462 bsod_sleep(dpy, delay);
1470 * SPARC Solaris panic. Should look pretty authentic on Solaris boxes.
1471 * Anton Solovyev <solovam@earthlink.net>
1480 int sub_width; /* Text subwindow width in pixels */
1481 int sub_height; /* Text subwindow height in pixels */
1482 int sub_x; /* upper left corner of the text subwindow */
1483 int sub_y; /* upper left corner of the text subwindow */
1484 int char_width; /* Char width in pixels */
1485 int line_height; /* Line height in pixels */
1486 int columns; /* Number of columns in the text screen */
1487 int x; /* horizontal position of the cursor */
1491 static scrolling_window *
1492 make_scrolling_window (Display *dpy, Window window,
1496 const char *def_font = "fixed";
1497 scrolling_window* ts;
1498 XWindowAttributes xgwa;
1501 char buf1[100], buf2[100];
1503 ts = malloc (sizeof (*ts));
1504 ts->window = window;
1509 XGetWindowAttributes (dpy, window, &xgwa);
1513 ts->sub_width = xgwa.width * 0.8;
1514 ts->sub_height = xgwa.height * 0.8;
1518 ts->sub_width = xgwa.width - 20;
1519 ts->sub_height = xgwa.height - 20;
1520 if (ts->sub_width < 20) ts->sub_width = 20;
1521 if (ts->sub_height < 20) ts->sub_height = 20;
1524 sprintf (buf1, "%.50s.font", name);
1525 sprintf (buf2, "%.50s.Font", name);
1526 fn = get_string_resource (buf1, buf2);
1527 ts->xfs = XLoadQueryFont (dpy, fn);
1530 sprintf (buf1, "%.50s.font2", name);
1531 fn = get_string_resource(buf1, buf2);
1532 ts->xfs = XLoadQueryFont(dpy, fn);
1535 ts->xfs = XLoadQueryFont(dpy, def_font);
1538 gcv.font = ts->xfs->fid;
1539 ts->char_width = (ts->xfs->per_char
1540 ? ts->xfs->per_char['n'-ts->xfs->min_char_or_byte2].width
1541 : ts->xfs->min_bounds.width);
1542 ts->line_height = ts->xfs->ascent + ts->xfs->descent + 1;
1544 ts->columns = ts->sub_width / ts->char_width;
1546 ts->sub_x = (xgwa.width - ts->sub_width) / 2;
1547 ts->sub_y = (xgwa.height - ts->sub_height) / 2;
1549 if (!grab_screen_p) ts->sub_height += ts->sub_y, ts->sub_y = 0;
1552 load_random_image (xgwa.screen, window, window);
1554 sprintf (buf1, "%.50s.background", name);
1555 sprintf (buf2, "%.50s.Background", name);
1556 gcv.background = get_pixel_resource (buf1, buf2, dpy, xgwa.colormap);
1558 sprintf (buf1, "%.50s.foreground", name);
1559 sprintf (buf2, "%.50s.Foreground", name);
1560 gcv.foreground = get_pixel_resource (buf1, buf2, dpy, xgwa.colormap);
1562 ts->gc = XCreateGC (dpy, window,
1563 GCForeground | GCBackground | GCFont,
1565 gcv.foreground = gcv.background;
1566 ts->erase_gc = XCreateGC (dpy, window,
1567 GCForeground | GCBackground,
1569 XSetWindowBackground (dpy, window, gcv.background);
1574 free_scrolling_window (scrolling_window* ts)
1576 XFreeGC (ts->dpy, ts->gc);
1577 XFreeGC (ts->dpy, ts->erase_gc);
1578 XFreeFont (ts->dpy, ts->xfs);
1583 scrolling_putc (scrolling_window* ts, const char aChar)
1589 XCopyArea (ts->dpy, ts->window, ts->window, ts->gc,
1590 ts->sub_x, ts->sub_y + ts->line_height,
1591 ts->sub_width, ts->sub_height,
1592 ts->sub_x, ts->sub_y);
1593 XFillRectangle (ts->dpy, ts->window, ts->erase_gc,
1594 ts->sub_x, ts->sub_y + ts->sub_height - ts->line_height,
1595 ts->sub_width, ts->line_height);
1604 if (ts->x >= ts->columns)
1605 scrolling_putc (ts, '\n');
1606 XDrawImageString (ts->dpy, ts->window, ts->gc,
1608 (ts->x * ts->char_width)
1609 - ts->xfs->min_bounds.lbearing),
1610 (ts->sub_y + ts->sub_height - ts->xfs->descent),
1618 scrolling_puts (scrolling_window *ts, const char* aString, int delay)
1621 for (c = aString; *c; ++c)
1623 scrolling_putc (ts, *c);
1628 if (bsod_sleep (ts->dpy, 0))
1637 sparc_solaris (Display* dpy, Window window, int delay)
1640 "BAD TRAP: cpu=0 type=0x31 rp=0x2a10043b5e0 addr=0xf3880 mmu_fsr=0x0\n"
1641 "BAD TRAP occured in module \"unix\" due to an illegal access to a"
1643 "adb: trap type = 0x31\n"
1645 "pid=307, pc=0x100306e4, sp=0x2a10043ae81, tstate=0x4480001602,"
1647 "g1-g7: 1045b000, 32f, 10079440, 180, 300000ebde8, 0, 30000953a20\n"
1648 "Begin traceback... sp = 2a10043ae81\n"
1649 "Called from 100bd060, fp=2a10043af31, args=f3700 300008cc988 f3880 0"
1651 "Called from 101fe1bc, fp=2a10043b011, args=3000045a240 104465a0"
1652 " 300008e47d0 300008e48fa 300008ae350 300008ae410\n"
1653 "Called from 1007c520, fp=2a10043b0c1, args=300008e4878 300003596e8 0"
1654 " 3000045a320 0 3000045a220\n"
1655 "Called from 1007c498, fp=2a10043b171, args=1045a000 300007847f0 20"
1656 " 3000045a240 1 0\n"
1657 "Called from 1007972c, fp=2a10043b221, args=1 300009517c0 30000951e58 1"
1659 "Called from 10031e10, fp=2a10043b2d1, args=3000095b0c8 0 300009396a8"
1660 " 30000953a20 0 1\n"
1661 "Called from 10000bdd8, fp=ffffffff7ffff1c1, args=0 57 100131480"
1662 " 100131480 10012a6e0 0\n"
1663 "End traceback...\n"
1664 "panic[cpu0]/thread=30000953a20: trap\n"
1665 "syncing file systems...";
1668 "dumping to /dev/dsk/c0t0d0s3, offset 26935296\n";
1670 ": 2803 pages dumped, compression ratio 2.88, dump succeeded\n";
1675 scrolling_window *ts;
1679 ts = make_scrolling_window (dpy, window, "Solaris", True);
1681 scrolling_puts (ts, msg1, 0);
1682 if (bsod_sleep (dpy, 3))
1685 scrolling_puts (ts, msg2, 0);
1686 if (bsod_sleep (dpy, 2))
1689 for (i = 1; i <= 100; ++i)
1691 sprintf(buf, "\b\b\b\b\b\b\b\b\b\b\b%3d%% done", i);
1692 scrolling_puts (ts, buf, 0);
1693 if (bsod_sleep (dpy, -1))
1697 scrolling_puts (ts, msg3, 0);
1698 if (bsod_sleep (dpy, 2))
1701 scrolling_puts (ts, msg4, 0);
1702 if (bsod_sleep(dpy, 3))
1705 bsod_sleep (dpy, 3);
1708 free_scrolling_window (ts);
1711 /* Linux panic and fsck, by jwz
1714 linux_fsck (Display *dpy, Window window, int delay)
1716 XWindowAttributes xgwa;
1717 scrolling_window *ts;
1719 const char *sysname;
1722 const char *linux_panic[] = {
1723 " kernel: Unable to handle kernel paging request at virtual "
1724 "address 0000f0ad\n",
1725 " kernel: printing eip:\n",
1726 " kernel: c01becd7\n",
1727 " kernel: *pde = 00000000\n",
1728 " kernel: Oops: 0000\n",
1729 " kernel: CPU: 0\n",
1730 " kernel: EIP: 0010:[<c01becd7>] Tainted: P \n",
1731 " kernel: EFLAGS: 00010286\n",
1732 " kernel: eax: 0000ff00 ebx: ca6b7e00 ecx: ce1d7a60 edx: ce1d7a60\n",
1733 " kernel: esi: ca6b7ebc edi: 00030000 ebp: d3655ca0 esp: ca6b7e5c\n",
1734 " kernel: ds: 0018 es: 0018 ss: 0018\n",
1735 " kernel: Process crond (pid: 1189, stackpage=ca6b7000)\n",
1736 " kernel: Stack: d3655ca0 ca6b7ebc 00030054 ca6b7e7c c01c1e5b "
1737 "00000287 00000020 c01c1fbf \n",
1739 " kernel: 00005a36 000000dc 000001f4 00000000 00000000 "
1740 "ce046d40 00000001 00000000 \n",
1742 " kernel: ffffffff d3655ca0 d3655b80 00030054 c01bef93 "
1743 "d3655ca0 ca6b7ebc 00030054 \n",
1745 " kernel: Call Trace: [<c01c1e5b>] [<c01c1fbf>] [<c01bef93>] "
1746 "[<c01bf02b>] [<c0134c4f>]\n",
1748 " kernel: [<c0142562>] [<c0114f8c>] [<c0134de3>] [<c010891b>]\n",
1750 " kernel: Code: 2a 00 75 08 8b 44 24 2c 85 c0 74 0c 8b 44 24 58 83 48 18 "
1755 XGetWindowAttributes (dpy, window, &xgwa);
1756 XSetWindowBackground (dpy, window,
1757 get_pixel_resource("Linux.background",
1759 dpy, xgwa.colormap));
1760 XClearWindow(dpy, window);
1767 if (uname (&uts) >= 0)
1768 sysname = uts.nodename;
1769 s = strchr (sysname, '.');
1772 # endif /* !HAVE_UNAME */
1775 ts = make_scrolling_window (dpy, window, "Linux", False);
1777 scrolling_puts (ts, "waiting for X server to shut down ", 0);
1779 if (bsod_sleep (dpy, 0))
1782 "XIO: fatal IO error 2 (broken pipe) on X server \":0.0\"\n"
1783 " after 339471 requests (339471 known processed) "
1784 "with 0 events remaining\n",
1786 if (scrolling_puts (ts, ".........\n", 300000))
1788 if (bsod_sleep (dpy, 0))
1791 "xinit: X server slow to shut down, sending KILL signal.\n",
1793 scrolling_puts (ts, "waiting for server to die ", 0);
1794 if (scrolling_puts (ts, "...\n", 300000))
1796 if (bsod_sleep (dpy, 0))
1798 scrolling_puts (ts, "xinit: Can't kill server\n", 0);
1800 if (bsod_sleep (dpy, 2))
1803 sprintf (buf, "\n%s Login: ", sysname);
1804 scrolling_puts (ts, buf, 0);
1805 if (bsod_sleep (dpy, 1))
1809 "Parallelizing fsck version 1.22 (22-Jun-2001)\n"
1810 "e2fsck 1.22, 22-Jun-2001 for EXT2 FS 0.5b, 95/08/09\n"
1811 "Warning! /dev/hda1 is mounted.\n"
1812 "/dev/hda1 contains a file system with errors, check forced.\n",
1814 if (bsod_sleep (dpy, 1))
1817 if (0 == random() % 2)
1819 "Couldn't find ext2 superblock, trying backup blocks...\n"
1820 "The filesystem size (according to the superblock) is 3644739 blocks\n"
1821 "The physical size of the device is 3636706 blocks\n"
1822 "Either the superblock or the partition table is likely to be corrupt!\n"
1825 if (bsod_sleep (dpy, 1))
1830 scrolling_puts (ts, "Pass 1: Checking inodes, blocks, and sizes\n", 0);
1831 if (bsod_sleep (dpy, 2))
1834 i = (random() % 60) - 20;
1837 int b = random() % 0xFFFF;
1838 sprintf (buf, "Deleted inode %d has zero dtime. Fix<y>? yes\n\n", b);
1839 scrolling_puts (ts, buf, 0);
1842 i = (random() % 40) - 10;
1845 int g = random() % 0xFFFF;
1846 int b = random() % 0xFFFFFFF;
1848 if (bsod_sleep (dpy, 1))
1851 sprintf (buf, "Warning: Group %d's copy of the group descriptors "
1852 "has a bad block (%d).\n", g, b);
1853 scrolling_puts (ts, buf, 0);
1855 b = random() % 0x3FFFFF;
1858 b += random() % 0xFFFF;
1860 "Error reading block %d (Attempt to read block "
1861 "from filesystem resulted in short read) while doing "
1862 "inode scan. Ignore error<y>?",
1864 scrolling_puts (ts, buf, 0);
1866 scrolling_puts (ts, " yes\n\n", 0);
1870 if (0 == (random() % 10))
1873 if (bsod_sleep (dpy, 1))
1876 i = 3 + (random() % 10);
1878 scrolling_puts (ts, "Could not allocate 256 block(s) for inode table: "
1879 "No space left on device\n", 0);
1880 scrolling_puts (ts, "Restarting e2fsck from the beginning...\n", 0);
1882 if (bsod_sleep (dpy, 2))
1888 i = (random() % 20) - 5;
1891 if (bsod_sleep (dpy, 1))
1896 int j = 5 + (random() % 10);
1897 int w = random() % 4;
1901 int b = random() % 0xFFFFF;
1902 int g = random() % 0xFFF;
1904 if (0 == (random() % 10))
1906 else if (0 == (random() % 10))
1911 "Inode table for group %d not in group. (block %d)\n"
1912 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"
1917 "Block bitmap for group %d not in group. (block %d)\n"
1922 "Inode bitmap %d for group %d not in group.\n"
1925 else /* if (w == 3) */
1927 "Bad block %d in group %d's inode table.\n"
1928 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"
1932 scrolling_puts (ts, buf, 0);
1933 scrolling_puts (ts, " yes\n\n", 0);
1935 if (bsod_sleep (dpy, 0))
1941 if (0 == random() % 10) goto PANIC;
1942 scrolling_puts (ts, "Pass 2: Checking directory structure\n", 0);
1943 if (bsod_sleep (dpy, 2))
1946 i = (random() % 20) - 5;
1949 int n = random() % 0xFFFFF;
1950 int o = random() % 0xFFF;
1951 sprintf (buf, "Directory inode %d, block 0, offset %d: "
1952 "directory corrupted\n"
1955 scrolling_puts (ts, buf, 0);
1957 scrolling_puts (ts, " yes\n\n", 0);
1959 if (0 == (random() % 100))
1961 sprintf (buf, "Missing '.' in directory inode %d.\nFix<y>?", n);
1962 scrolling_puts (ts, buf, 0);
1964 scrolling_puts (ts, " yes\n\n", 0);
1967 if (bsod_sleep (dpy, 0))
1971 if (0 == random() % 10) goto PANIC;
1973 "Pass 3: Checking directory connectivity\n"
1974 "/lost+found not found. Create? yes\n",
1976 if (bsod_sleep (dpy, 2))
1979 /* Unconnected directory inode 4949 (/var/spool/squid/06/???)
1980 Connect to /lost+found<y>? yes
1982 '..' in /var/spool/squid/06/08 (20351) is <The NULL inode> (0), should be
1983 /var/spool/squid/06 (20350).
1986 Unconnected directory inode 128337 (/var/spool/squid/06/???)
1987 Connect to /lost+found<y>? yes
1991 if (0 == random() % 10) goto PANIC;
1992 scrolling_puts (ts, "Pass 4: Checking reference counts\n", 0);
1993 if (bsod_sleep (dpy, 2))
1996 /* Inode 2 ref count is 19, should be 20. Fix<y>? yes
1998 Inode 4949 ref count is 3, should be 2. Fix<y>? yes
2002 Inode 128336 ref count is 3, should be 2. Fix<y>? yes
2004 Inode 128337 ref count is 3, should be 2. Fix<y>? yes
2009 if (0 == random() % 10) goto PANIC;
2010 scrolling_puts (ts, "Pass 5: Checking group summary information\n", 0);
2011 if (bsod_sleep (dpy, 2))
2014 i = (random() % 200) - 50;
2017 scrolling_puts (ts, "Block bitmap differences: ", 0);
2020 sprintf (buf, " %d", -(random() % 0xFFF));
2021 scrolling_puts (ts, buf, 0);
2024 scrolling_puts (ts, "\nFix? yes\n\n", 0);
2028 i = (random() % 100) - 50;
2031 scrolling_puts (ts, "Inode bitmap differences: ", 0);
2034 sprintf (buf, " %d", -(random() % 0xFFF));
2035 scrolling_puts (ts, buf, 0);
2038 scrolling_puts (ts, "\nFix? yes\n\n", 0);
2041 i = (random() % 20) - 5;
2044 int g = random() % 0xFFFF;
2045 int c = random() % 0xFFFF;
2047 "Free blocks count wrong for group #0 (%d, counted=%d).\nFix? ",
2049 scrolling_puts (ts, buf, 0);
2051 scrolling_puts (ts, " yes\n\n", 0);
2052 if (bsod_sleep (dpy, 0))
2059 scrolling_puts (ts, "\n\n", 0);
2060 while (linux_panic[i])
2062 time_t t = time ((time_t *) 0);
2063 struct tm *tm = localtime (&t);
2066 if (*linux_panic[i])
2068 strftime (prefix, sizeof(prefix)-1, "%b %d %k:%M:%S ", tm);
2069 scrolling_puts (ts, prefix, 0);
2070 scrolling_puts (ts, sysname, 0);
2071 scrolling_puts (ts, linux_panic[i], 0);
2078 if (bsod_sleep (dpy, 0))
2083 if (bsod_sleep (dpy, 4))
2088 bsod_sleep(dpy, delay);
2091 free_scrolling_window (ts);
2092 XClearWindow(dpy, window);
2097 /* HPUX panic, by Tobias Klausmann <klausman@schwarzvogel.de>
2101 hpux (Display* dpy, Window window, int delay)
2103 XWindowAttributes xgwa;
2104 scrolling_window *ts;
2105 const char *sysname;
2111 " ******* Unexpected HPMC/TOC. Processor HPA FFFFFFFF'"
2112 "FFFA0000 *******\n"
2113 " GENERAL REGISTERS:\n"
2114 "r00/03 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2116 "r04/07 00000000'00000001 00000000'0126E328 00000000'00000000 00000000'"
2118 "r08/11 00000000'00000000 00000000'0198CFC0 00000000'000476FE 00000000'"
2120 "r12/15 00000000'40013EE8 00000000'08000080 00000000'4002530C 00000000'"
2122 "r16/19 00000000'7F7F2A00 00000000'00000001 00000000'00000000 00000000'"
2124 "r20/23 00000000'006C8048 00000000'00000001 00000000'00000000 00000000'"
2126 "r24/27 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2128 "r28/31 00000000'00000000 00000000'007DD628 00000000'0199F2B0 00000000'"
2130 " CONTROL REGISTERS:\n"
2131 "sr0/3 00000000'0F3B4000 00000000'0C2A2000 00000000'016FF800 00000000'"
2133 "sr4/7 00000000'00000000 00000000'016FF800 00000000'0DBF1400 00000000'"
2135 "pcq = 00000000'00000000.00000000'00104950 00000000'00000000.00000000'"
2137 "isr = 00000000'10240006 ior = 00000000'67D9E220 iir = 08000240 rctr = "
2140 "pid reg cr8/cr9 00007700'0000B3A9 00000000'0000C5D8\n"
2141 "pid reg cr12/cr13 00000000'00000000 00000000'00000000\n"
2142 "ipsw = 000000FF'080CFF1F iva = 00000000'0002C000 sar = 3A ccr = C0\n"
2143 "tr0/3 00000000'006C76C0 00000000'00000001 00000000'00000000 00000000'"
2145 "tr4/7 00000000'03790000 0000000C'4FB68340 00000000'C07EE13F 00000000'"
2147 "eiem = FFFFFFF0'FFFFFFFF eirr = 80000000'00000000 itmr = 0000000C'"
2149 "cr1/4 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2151 "cr5/7 00000000'00000000 00000000'00000000 00000000'"
2153 " MACHINE CHECK PARAMETERS:\n"
2154 "Check Type = 00000000 CPU STATE = 9E000001 Cache Check = 00000000\n"
2155 "TLB Check = 00000000 Bus Check = 00000000 PIM State = ? SIU "
2156 "Status = ????????\n"
2157 "Assists = 00000000 Processor = 00000000\n"
2158 "Slave Addr = 00000000'00000000 Master Addr = 00000000'00000000\n"
2161 "TOC, pcsq.pcoq = 0'0.0'104950 , isr.ior = 0'10240006.0'67d9e220\n"
2162 "@(#)B2352B/9245XB HP-UX (B.11.00) #1: Wed Nov 5 22:38:19 PST 1997\n"
2163 "Transfer of control: (display==0xd904, flags==0x0)\n"
2167 "*** A system crash has occurred. (See the above messages for details.)\n"
2168 "*** The system is now preparing to dump physical memory to disk, for use\n"
2169 "*** in debugging the crash.\n"
2171 "*** The dump will be a SELECTIVE dump: 40 of 256 megabytes.\n"
2172 "*** To change this dump type, press any key within 10 seconds.\n"
2173 "*** Proceeding with selective dump.\n"
2175 "*** The dump may be aborted at any time by pressing ESC.\n";
2177 "\n*** System rebooting.\n";
2179 XGetWindowAttributes (dpy, window, &xgwa);
2180 ts = make_scrolling_window (dpy, window, "HPUX", False);
2181 XClearWindow(dpy,window);
2182 ts->columns = 10000; /* never wrap */
2185 ts->sub_width = xgwa.width;
2186 ts->sub_height = xgwa.height;
2193 if (uname (&uts) >= 0)
2194 sysname = uts.nodename;
2195 s = strchr (sysname, '.');
2198 # endif /* !HAVE_UNAME */
2200 if (bsod_sleep (dpy, 1))
2208 sprintf (buf, "%.100s [HP Release B.11.00] (see /etc/issue)\n", sysname);
2209 scrolling_puts (ts, buf, 0);
2210 if (bsod_sleep (dpy, 1))
2212 scrolling_puts (ts, msg1, 0);
2217 for (i = 0; i <= steps; i++)
2219 if (i > steps) i = steps;
2221 "*** Dumping: %3d%% complete (%d of 40 MB) (device 64:0x2)\r",
2224 scrolling_puts (ts, buf, 0);
2227 if (bsod_sleep (dpy, 0))
2232 scrolling_puts (ts, msg2, 0);
2235 bsod_sleep(dpy, delay);
2238 free_scrolling_window (ts);
2243 /* IBM OS/390 aka MVS aka z/OS.
2244 Text from Dan Espen <dane@mk.telcordia.com>.
2245 Apparently this isn't actually a crash, just a random session...
2250 os390 (Display* dpy, Window window, int delay)
2254 XWindowAttributes xgwa;
2255 scrolling_window *ts;
2258 const char *msg[] = {
2259 "* ISPF Subtask abend *\n",
2260 "SPF ENDED DUE TO ERROR+\n",
2263 "IEA995I SYMPTOM DUMP OUTPUT\n",
2264 " USER COMPLETION CODE=0222\n",
2265 " TIME=23.00.51 SEQ=03210 CPU=0000 ASID=00AE\n",
2266 " PSW AT TIME OF ERROR 078D1000 859DAF18 ILC 2 INTC 0D\n",
2267 " NO ACTIVE MODULE FOUND\n",
2269 " DATA AT PSW 059DAF12 - 00181610 0A0D9180 70644710\n",
2270 " AR/GR 0: 00000000/80000000 1: 00000000/800000DE\n",
2271 " 2: 00000000/196504DC 3: 00000000/00037A78\n",
2272 " 4: 00000000/00037B78 5: 00000000/0003351C\n",
2273 " 6: 00000000/0000F0AD 7: 00000000/00012000\n",
2274 " 8: 00000000/059DAF10 9: 00000000/0002D098\n",
2275 " A: 00000000/059D9F10 B: 00000000/059D8F10\n",
2276 " C: 00000000/859D7F10 D: 00000000/00032D60\n",
2277 " E: 00000000/00033005 F: 01000002/00000041\n",
2278 " END OF SYMPTOM DUMP\n",
2279 "ISPS014 - ** Logical screen request failed - abend 0000DE **\n",
2280 "ISPS015 - ** Contact your system programmer or dialog developer.**\n",
2281 "*** ISPF Main task abend ***\n",
2282 "IEA995I SYMPTOM DUMP OUTPUT\n",
2283 " USER COMPLETION CODE=0222\n",
2284 " TIME=23.00.52 SEQ=03211 CPU=0000 ASID=00AE\n",
2285 " PSW AT TIME OF ERROR 078D1000 8585713C ILC 2 INTC 0D\n",
2286 " ACTIVE LOAD MODULE ADDRESS=05855000 OFFSET=0000213C\n",
2288 " DATA AT PSW 05857136 - 00181610 0A0D9180 D3304770\n",
2289 " GR 0: 80000000 1: 800000DE\n",
2290 " 2: 00015260 3: 00000038\n",
2291 " 4: 00012508 5: 00000000\n",
2292 " 6: 000173AC 7: FFFFFFF8\n",
2293 " 8: 05858000 9: 00012CA0\n",
2294 " A: 05857000 B: 05856000\n",
2295 " C: 85855000 D: 00017020\n",
2296 " E: 85857104 F: 00000000\n",
2297 " END OF SYMPTOM DUMP\n",
2302 XGetWindowAttributes (dpy, window, &xgwa);
2303 ts = make_scrolling_window (dpy, window, "OS390", False);
2304 ts->columns = 10000; /* never wrap */
2307 ts->sub_width = xgwa.width;
2308 ts->sub_height = xgwa.height;
2310 gcv.foreground = get_pixel_resource ("390.background", "390.Background",
2311 dpy, xgwa.colormap);
2312 gc = XCreateGC (dpy, window, GCForeground, &gcv);
2313 XFillRectangle (dpy, window, gc, 0, 0, xgwa.width, xgwa.height);
2316 for (i = 0; i < countof (msg); i++)
2318 scrolling_puts (ts, msg[i], 0);
2320 if (bsod_sleep(dpy, 0)) goto DONE;
2324 bsod_sleep(dpy, delay);
2326 free_scrolling_window (ts);
2332 * Simulate various Apple II crashes. The memory map encouraged many
2333 * programs to use the primary hi-res video page for various storage,
2334 * and the secondary hi-res page for active display. When it crashed
2335 * into Applesoft or the monitor, it would revert to the primary page
2336 * and you'd see memory garbage on the screen. Also, it was common for
2337 * copy-protected games to use the primary text page for important
2338 * code, because that made it really hard to reverse-engineer them. The
2339 * result often looked like what this generates.
2341 * Sometimes an imaginary user types some of the standard commands to
2342 * recover from crashes. You can turn off BSOD*apple2SimulateUser to
2345 * It simulates the following characteristics of standard television
2348 * - Realistic rendering of a composite video signal
2349 * - Compression & brightening on the right, as the scan gets truncated
2350 * because of saturation in the flyback transformer
2351 * - Blooming of the picture dependent on brightness
2352 * - Overscan, cutting off a few pixels on the left side.
2353 * - Colored text in mixed graphics/text modes
2355 * It's amazing how much it makes your high-end monitor look like at
2356 * large late-70s TV. All you need is to put a big "Solid State" logo
2357 * in curly script on it and you'd be set.
2359 * Trevor Blackwell <tlb@tlb.org>
2363 * Implementation notes:
2365 * There are roughly 3 parts to this hack:
2367 * - emulation of A2 Basic and Monitor. Not much more than printing random
2368 * plausible messages. Here we work in the A2 memory space.
2370 * - emulation of the A2's video output section, which shifted bits out of main
2371 * memory at a 14 MHz dot clock rate, sort of. You could only read one byte
2372 * per MHz, so there were various schemes for turning 8 bits into 14 screen
2375 * - simulation of an NTSC television, which turned the bits into colored
2376 * graphics and text.
2378 * The A2 had 3 display modes: text, lores, and hires. Text was 40x24, and it
2379 * disabled color in the TV. Lores gave you 40x48 graphics blocks, using the
2380 * same memory as the text screen. Each could be one of 16 colors. Hires gave
2381 * you 280x192 pixels. Odd pixels were blue or purple, and even pixels were
2382 * orange or green depending on the setting of the high bit in each byte.
2384 * The graphics modes could also have 4 lines of text at the bottom. This was
2385 * fairly unreadable if you had a color monitor.
2387 * Each mode had 2 different screens using different memory space. In hires
2388 * mode this was sometimes used for double buffering, but more often the lower
2389 * screen was full of code/data and the upper screen was used for display, so
2390 * you got random garbage on the screen.
2392 * In DirectColor or TrueColor modes, it generates pixel values directly from
2393 * RGB values it calculates across each scan line. In PseudoColor mode, it
2394 * consider each possible pattern of 5 preceding bit values in each possible
2395 * position modulo 4 and allocates a color for each. A few things, like the
2396 * brightening on the right side as the horizontal trace slows down, aren't
2397 * done in PseudoColor.
2399 * The text font is based on X's standard 6x10 font, with a few tweaks like
2400 * putting a slash across the zero.
2402 * I'd like to add a bit of visible retrace, but it conflicts with being able
2403 * to bitcopy the image when fast scrolling. After another couple of CPU
2404 * generations, we could probably regenerate the whole image from scratch every
2405 * time. On a P4 2 GHz it can manage this fine for blinking text, but scrolling
2409 static char * apple2_basic_errors[]={
2413 "RETURN WITHOUT GOSUB",
2417 "BAD SUBSCRIPT ERROR",
2420 "FORMULA TOO COMPLEX",
2424 static char * apple2_dos_errors[]={
2428 "NO BUFFERS AVAILABLE",
2429 "PROGRAM TOO LARGE",
2432 struct apple2_state {
2433 char hireslines[192][40];
2434 char textlines[24][40];
2454 a2_scroll(struct apple2_state *st)
2457 int top=(st->gr_mode&(A2_GR_LORES|A2_GR_HIRES)) ? 20 : 0;
2458 if ((st->gr_mode&A2_GR_FULL) && (st->gr_mode&A2_GR_HIRES)) return;
2459 if (st->gr_mode&A2_GR_FULL) top=0;
2460 for (i=top; i<23; i++) {
2461 if (memcmp(st->textlines[i],st->textlines[i+1],40)) {
2462 memcpy(st->textlines[i],st->textlines[i+1],40);
2463 st->rowimage[i]=st->rowimage[i+1];
2466 memset(st->textlines[23],0xe0,40);
2467 st->rowimage[23]=-1;
2471 a2_printc(struct apple2_state *st, char c)
2473 st->textlines[st->cursy][st->cursx] |= 0xc0; /* turn off blink */
2475 if (st->cursy==23) {
2478 st->rowimage[st->cursy]=-1;
2480 st->rowimage[st->cursy]=-1;
2484 st->textlines[st->cursy][st->cursx]=c ^ 0xc0;
2485 st->rowimage[st->cursy]=-1;
2487 if (st->cursx==40) {
2488 if (st->cursy==23) {
2491 st->rowimage[st->cursy]=-1;
2493 st->rowimage[st->cursy]=-1;
2498 st->textlines[st->cursy][st->cursx] &= 0x7f; /* turn on blink */
2502 a2_goto(struct apple2_state *st, int r, int c)
2504 st->textlines[st->cursy][st->cursx] |= 0xc0; /* turn off blink */
2507 st->textlines[st->cursy][st->cursx] &= 0x7f; /* turn on blink */
2511 a2_cls(struct apple2_state *st)
2514 for (i=0; i<24; i++) {
2515 memset(st->textlines[i],0xe0,40);
2521 a2_invalidate(struct apple2_state *st)
2524 for (i=0; i<24; i++) {
2530 a2_poke(struct apple2_state *st, int addr, int val)
2533 if (addr>=0x400 && addr<0x800) {
2535 int row=((addr&0x380)/0x80) + ((addr&0x7f)/0x28)*8;
2536 int col=(addr&0x7f)%0x28;
2537 if (row<24 && col<40) {
2538 st->textlines[row][col]=val;
2539 if (!(st->gr_mode&(A2_GR_HIRES)) ||
2540 (!(st->gr_mode&(A2_GR_FULL)) && row>=20)) {
2541 st->rowimage[row]=-1;
2545 else if (addr>=0x2000 && addr<0x4000) {
2546 int row=(((addr&0x1c00) / 0x400) * 1 +
2547 ((addr&0x0380) / 0x80) * 8 +
2548 ((addr&0x0078) / 0x28) * 64);
2549 int col=((addr&0x07f)%0x28);
2550 if (row<192 && col<40) {
2551 st->hireslines[row][col]=val;
2552 if (st->gr_mode&A2_GR_HIRES) {
2553 st->rowimage[row/8]=-1;
2559 /* This table lists fixes for characters that differ from the standard 6x10
2560 font. Each encodes a pixel, as (charindex*7 + x) + (y<<10) + (value<<15)
2561 where value is 0 for white and 1 for black. */
2562 static unsigned short a2_fixfont[] = {
2563 /* Fix $ */ 0x8421, 0x941d,
2564 /* Fix % */ 0x8024, 0x0028, 0x8425, 0x0426, 0x0825, 0x1027, 0x1426, 0x9427,
2566 /* Fix * */ 0x8049, 0x8449, 0x8849, 0x0c47, 0x0c48, 0x0c4a, 0x0c4b, 0x9049,
2568 /* Fix , */ 0x9057, 0x1458, 0x9856, 0x1857, 0x1c56,
2569 /* Fix . */ 0x1465, 0x1864, 0x1866, 0x1c65,
2570 /* Fix / */ 0x006e, 0x186a,
2571 /* Fix 0 */ 0x8874, 0x8c73, 0x9072,
2572 /* Fix 1 */ 0x0878, 0x1878, 0x187c,
2573 /* Fix 5 */ 0x8895, 0x0c94, 0x0c95,
2574 /* Fix 6 */ 0x809f, 0x8c9c, 0x109c,
2575 /* Fix 7 */ 0x8ca4, 0x0ca5, 0x90a3, 0x10a4,
2576 /* Fix 9 */ 0x08b3, 0x8cb3, 0x98b0,
2577 /* Fix : */ 0x04b9, 0x08b8, 0x08ba, 0x0cb9, 0x90b9, 0x14b9, 0x18b8, 0x18b9,
2579 /* Fix ; */ 0x04c0, 0x08bf, 0x08c1, 0x0cc0, 0x90c0, 0x14c1, 0x98bf, 0x18c0,
2581 /* Fix < */ 0x80c8, 0x00c9, 0x84c7, 0x04c8, 0x88c6, 0x08c7, 0x8cc5, 0x0cc6,
2583 0x94c7, 0x14c8, 0x98c8, 0x18c9,
2584 /* Fix > */ 0x80d3, 0x00d4, 0x84d4, 0x04d5, 0x88d5, 0x08d6, 0x8cd6, 0x0cd7,
2586 0x94d4, 0x14d5, 0x98d3, 0x18d4,
2587 /* Fix @ */ 0x88e3, 0x08e4, 0x8ce4, 0x98e5,
2588 /* Fix B */ 0x84ef, 0x04f0, 0x88ef, 0x08f0, 0x8cef, 0x90ef, 0x10f0, 0x94ef,
2590 /* Fix D */ 0x84fd, 0x04fe, 0x88fd, 0x08fe, 0x8cfd, 0x0cfe, 0x90fd, 0x10fe,
2592 /* Fix G */ 0x8116, 0x0516, 0x9916,
2593 /* Fix J */ 0x0129, 0x012a, 0x052a, 0x852b, 0x092a, 0x892b, 0x0d2a, 0x8d2b,
2595 0x152a, 0x952b, 0x992a,
2596 /* Fix M */ 0x853d, 0x853f, 0x093d, 0x893e, 0x093f,
2597 /* Fix Q */ 0x915a, 0x155a, 0x955b, 0x155c, 0x195b, 0x995c, 0x1d5c,
2598 /* Fix V */ 0x8d7b, 0x0d7c, 0x0d7e, 0x8d7f, 0x917b, 0x117c, 0x117e, 0x917f,
2599 /* Fix [ */ 0x819e, 0x81a2, 0x859e, 0x899e, 0x8d9e, 0x919e, 0x959e, 0x999e,
2601 /* Fix \ */ 0x01a5, 0x19a9,
2602 /* Fix ] */ 0x81ac, 0x81b0, 0x85b0, 0x89b0, 0x8db0, 0x91b0, 0x95b0, 0x99ac,
2604 /* Fix ^ */ 0x01b5, 0x05b4, 0x05b6, 0x09b3, 0x89b5, 0x09b7, 0x8db4, 0x8db6,
2606 /* Fix _ */ 0x9db9, 0x9dbf,
2617 int brightness_control;
2621 First generate the I and Q reference signals, which we'll multiply by the
2622 input signal to accomplish the demodulation. Normally they are shifted 33
2623 degrees from the colorburst. I think this was convenient for
2624 inductor-capacitor-vacuum tube implementation.
2626 The tint control, FWIW, just adds a phase shift to the chroma signal, and
2627 the color control controls the amplitude.
2629 In text modes (colormode==0) the system disabled the color burst, and no
2630 color was detected by the monitor.
2632 freq_error gives a mismatch between the built-in oscillator and the TV's
2633 colorbust. Older II Plus machines seemed to occasionally get instability
2634 problems -- the crystal oscillator was a single transistor if I remember
2635 correctly -- and the frequency would vary enough that the tint would change
2636 across the width of the screen. The left side would be in correct tint
2637 because it had just gotten resynchronized with the color burst.
2640 ntsc_set_demod(struct ntsc_dec *it, double tint_control,
2641 double color_control, double brightness_control,
2647 it->brightness_control=(int)(1024.0*brightness_control);
2649 for (i=0; i<600; i++) {
2650 double phase=90.0-90.0*i + freq_error*i/600.0 + tint_control;
2651 it->multi[i]=(int)(-cos(3.1415926/180.0*(phase-303)) * 65536.0 *
2652 color_control * colormode * 4);
2653 it->multq[i]=(int)(cos(3.1415926/180.0*(phase-33)) * 65536.0 *
2654 color_control * colormode * 4);
2658 /* Here we model the analog circuitry of an NTSC television. Basically, it
2659 splits the signal into 3 signals: Y, I and Q. Y corresponds to luminance,
2660 and you get it by low-pass filtering the input signal to below 3.57 MHz.
2662 I and Q are the in-phase and quadrature components of the 3.57 MHz
2663 subcarrier. We get them by multiplying by cos(3.57 MHz*t) and sin(3.57
2664 MHz*t), and low-pass filtering. Because the eye has less resolution in some
2665 colors than others, the I component gets low-pass filtered at 1.5 MHz and
2666 the Q at 0.5 MHz. The I component is approximately orange-blue, and Q is
2667 roughly purple-green. See http://www.ntsc-tv.com for details.
2670 ntsc_to_yiq(struct ntsc_dec *it)
2673 int fyx[10],fyy[10];
2674 int fix[10],fiy[10];
2675 int fqx[10],fqy[10];
2677 int iny,ini,inq,pix,blank;
2679 for (i=0; i<10; i++) fyx[i]=fyy[i]=fix[i]=fiy[i]=fqx[i]=fqy[i]=0.0;
2681 for (i=0; i<600; i++) {
2682 /* Get the video out signal, and add a teeny bit of ghosting, typical of RF
2683 monitor cables. This corresponds to a pretty long cable, but looks right
2685 pix=it->pattern[i]*1024;
2686 if (i>=20) pixghost += it->pattern[i-20]*15;
2687 if (i>=30) pixghost -= it->pattern[i-30]*15;
2690 /* Get Y, I, Q before filtering */
2692 ini=(pix*it->multi[i])>>16;
2693 inq=(pix*it->multq[i])>>16;
2695 blank = (i>=7 && i<596 ? it->brightness_control : -200);
2697 /* Now filter them. These are infinite impulse response filters calculated
2698 by the script at http://www-users.cs.york.ac.uk/~fisher/mkfilter. This
2699 is fixed-point integer DSP, son. No place for wimps. We do it in integer
2700 because you can count on integer being faster on most CPUs. We care
2701 about speed because we need to recalculate every time we blink text, and
2702 when we spew random bytes into screen memory. This is roughly 16.16
2703 fixed point arithmetic, but we scale some filter values up by a few bits
2704 to avoid some nasty precision errors. */
2706 /* Filter y at with a 4-pole low-pass Butterworth filter at 3.5 MHz
2707 with an extra zero at 3.5 MHz, from
2708 mkfilter -Bu -Lp -o 4 -a 2.1428571429e-01 0 -Z 2.5e-01 -l
2711 fyx[0] = fyx[1]; fyx[1] = fyx[2]; fyx[2] = fyx[3];
2712 fyx[3] = fyx[4]; fyx[4] = fyx[5]; fyx[5] = fyx[6];
2713 fyx[6] = (iny * 1897) >> 13;
2714 fyy[0] = fyy[1]; fyy[1] = fyy[2]; fyy[2] = fyy[3];
2715 fyy[3] = fyy[4]; fyy[4] = fyy[5]; fyy[5] = fyy[6];
2716 fyy[6] = (fyx[0]+fyx[6]) + 4*(fyx[1]+fyx[5]) + 7*(fyx[2]+fyx[4]) + 8*fyx[3]
2717 + ((-151*fyy[2] + 8115*fyy[3] - 38312*fyy[4] + 36586*fyy[5]) >> 16);
2718 if (i>=2) it->ntscy[i-2] = blank + (fyy[6]>>3);
2720 /* Filter I and Q at 1.5 MHz. 3 pole Butterworth from
2721 mkfilter -Bu -Lp -o 3 -a 1.0714285714e-01 0
2724 The NTSC spec says the Q value should be filtered at 0.5 MHz at the
2725 transmit end, But the Apple's video circuitry doesn't any such thing.
2726 AFAIK, oldish televisions (before comb filters) simply applied a 1.5 MHz
2727 filter to both after the demodulator.
2730 fix[0] = fix[1]; fix[1] = fix[2]; fix[2] = fix[3];
2731 fix[3] = (ini * 1413) >> 14;
2732 fiy[0] = fiy[1]; fiy[1] = fiy[2]; fiy[2] = fiy[3];
2733 fiy[3] = (fix[0]+fix[3]) + 3*(fix[1]+fix[2])
2734 + ((16559*fiy[0] - 72008*fiy[1] + 109682*fiy[2]) >> 16);
2735 if (i>=3) it->ntsci[i-3] = fiy[3]>>2;
2737 fqx[0] = fqx[1]; fqx[1] = fqx[2]; fqx[2] = fqx[3];
2738 fqx[3] = (inq * 1413) >> 14;
2739 fqy[0] = fqy[1]; fqy[1] = fqy[2]; fqy[2] = fqy[3];
2740 fqy[3] = (fqx[0]+fqx[3]) + 3*(fqx[1]+fqx[2])
2741 + ((16559*fqy[0] - 72008*fqy[1] + 109682*fqy[2]) >> 16);
2742 if (i>=3) it->ntscq[i-3] = fqy[3]>>2;
2745 for (; i<610; i++) {
2746 if (i-2<600) it->ntscy[i-2]=0;
2747 if (i-3<600) it->ntsci[i-3]=0;
2748 if (i-9<600) it->ntscq[i-9]=0;
2758 #define A2_CMAP_INDEX(COLORMODE, LEVEL, HIST, OFFSET) \
2759 ((((COLORMODE)*A2_CMAP_LEVELS+(LEVEL))<<A2_CMAP_HISTBITS)+(HIST))* \
2760 A2_CMAP_OFFSETS+(OFFSET)
2763 apple2(Display *dpy, Window window, int delay)
2765 int w,h,i,j,x,y,textrow,row,col,stepno,colormode,imgrow;
2767 struct timeval basetime_tv;
2768 double next_actiontime;
2769 XWindowAttributes xgwa;
2771 int screen_xo,screen_yo;
2775 XImage *text_im=NULL;
2776 unsigned long colors[A2_CMAP_INDEX(1, A2_CMAP_LEVELS-1,
2777 (1<<A2_CMAP_HISTBITS)-1,
2778 A2_CMAP_OFFSETS-3)+1];
2780 int screen_plan[24];
2781 struct ntsc_dec *dec=NULL;
2782 short *raw_rgb=NULL, *rrp;
2783 struct apple2_state *st=NULL;
2784 char *typing=NULL,*printing=NULL;
2785 char printbuf[1024];
2788 double tint_control,color_control,brightness_control,contrast_control;
2789 double freq_error=0.0,freq_error_inc=0.0;
2790 double horiz_desync=5.0;
2791 int flutter_horiz_desync=0;
2793 double crtload[192];
2794 int red_invprec,red_shift,green_invprec,green_shift,blue_invprec,blue_shift;
2795 int fillptr, fillbyte;
2796 int use_shm,use_cmap,use_color;
2797 /* localbyteorder is 1 if MSB first, 0 otherwise */
2798 unsigned int localbyteorder_loc = MSBFirst<<24;
2799 int localbyteorder=*(char *)&localbyteorder_loc;
2800 #ifdef HAVE_XSHM_EXTENSION
2801 XShmSegmentInfo shm_info;
2804 #ifdef HAVE_XSHM_EXTENSION
2805 use_shm=get_boolean_resource ("useSHM", "Boolean");
2810 /* Model the video controls on a standard television */
2811 tint_control = get_float_resource("apple2TVTint","Apple2TVTint");
2812 color_control = get_float_resource("apple2TVColor","Apple2TVColor")/100.0;
2813 brightness_control = get_float_resource("apple2TVBrightness",
2814 "Apple2TVBrightness") / 100.0;
2815 contrast_control = get_float_resource("apple2TVContrast",
2816 "Apple2TVContrast") / 100.0;
2817 simulate_user = get_boolean_resource("apple2SimulateUser",
2818 "Apple2SimulateUser");
2820 XGetWindowAttributes (dpy, window, &xgwa);
2821 visclass=xgwa.visual->class;
2822 red_shift=red_invprec=green_shift=green_invprec=blue_shift=blue_invprec=-1;
2823 if (visclass == TrueColor || xgwa.visual->class == DirectColor) {
2827 else if (visclass == PseudoColor || visclass == StaticColor) {
2836 /* The Apple II screen was 280x192, sort of. We expand the width to 300
2837 pixels to allow for overscan. We then pick a size within the window
2838 that's an integer multiple of 300x192. The small case happens when
2839 we're displaying in a subwindow. Then it ends up showing the center
2840 of the screen, which is OK. */
2842 h = (xgwa.height/192)*192;
2846 dec=(struct ntsc_dec *)malloc(sizeof(struct ntsc_dec));
2849 int hist,offset,level;
2854 /* Typically allocates 214 distinct colors, but will scale back its
2855 ambitions pretty far if it can't get them */
2856 for (colormode=0; colormode<=use_color; colormode++) {
2857 ntsc_set_demod(dec, tint_control, color_control, brightness_control,
2859 for (level=0; level<2; level++) {
2860 for (hist=0; hist<(1<<A2_CMAP_HISTBITS); hist++) {
2861 for (offset=0; offset<4; offset++) {
2862 int interpy,interpi,interpq,r,g,b;
2863 int levelmult=level ? 64 : 32;
2864 int prec=colormode ? colorprec : (colorprec*2+2)/3;
2865 int precmask=(0xffff<<(16-prec))&0xffff;
2868 if (A2_CMAP_INDEX(colormode,level,hist,offset) != n_colors) {
2869 fprintf(stderr, "apple2: internal colormap allocation error\n");
2873 for (i=0; i<600; i++) dec->pattern[i]=0;
2874 for (i=0; i<A2_CMAP_HISTBITS; i++) {
2875 dec->pattern[64+offset-i]=(hist>>i)&1;
2879 interpy=dec->ntscy[63+offset];
2880 interpi=dec->ntsci[63+offset];
2881 interpq=dec->ntscq[63+offset];
2883 r=(interpy + ((+68128*interpi+40894*interpq)>>16))*levelmult;
2884 g=(interpy + ((-18087*interpi-41877*interpq)>>16))*levelmult;
2885 b=(interpy + ((-72417*interpi+113312*interpq)>>16))*levelmult;
2887 if (r>65535) r=65535;
2889 if (g>65535) g=65535;
2891 if (b>65535) b=65535;
2893 col.red=r & precmask;
2894 col.green=g & precmask;
2895 col.blue=b & precmask;
2897 if (!XAllocColor(dpy, xgwa.colormap, &col)) {
2898 XFreeColors(dpy, xgwa.colormap, colors, n_colors, 0L);
2906 colors[n_colors++]=col.pixel;
2912 /* Is there a standard way to do this? Does this handle all cases? */
2914 for (shift=0; shift<32; shift++) {
2915 for (prec=1; prec<16 && prec<32-shift; prec++) {
2916 unsigned long mask=(0xffffUL>>(16-prec)) << shift;
2917 if (red_shift<0 && mask==xgwa.visual->red_mask)
2918 red_shift=shift, red_invprec=16-prec;
2919 if (green_shift<0 && mask==xgwa.visual->green_mask)
2920 green_shift=shift, green_invprec=16-prec;
2921 if (blue_shift<0 && mask==xgwa.visual->blue_mask)
2922 blue_shift=shift, blue_invprec=16-prec;
2925 if (red_shift<0 || green_shift<0 || blue_shift<0) {
2926 if (0) fprintf(stderr,"Can't figure out color space\n");
2929 raw_rgb=(short *)calloc(w*3, sizeof(short));
2933 gc = XCreateGC(dpy, window, GCBackground, &gcv);
2934 XSetWindowBackground(dpy, window, gcv.background);
2935 XClearWindow(dpy,window);
2937 screen_xo=(xgwa.width-w)/2;
2938 screen_yo=(xgwa.height-h)/2;
2941 #ifdef HAVE_XSHM_EXTENSION
2942 image = create_xshm_image (dpy, xgwa.visual, xgwa.depth, ZPixmap, 0,
2946 fprintf(stderr, "create_xshm_image failed\n");
2951 image = XCreateImage(dpy, xgwa.visual, xgwa.depth, ZPixmap, 0, 0,
2953 image->data = (char *)calloc(image->height, image->bytes_per_line);
2956 st=(struct apple2_state *)calloc(1,sizeof(struct apple2_state));
2959 Generate the font. It used a 5x7 font which looks a lot like the standard X
2960 6x10 font, with a few differences. So we render up all the uppercase
2961 letters of 6x10, and make a few tweaks (like putting a slash across the
2962 zero) according to fixfont.
2965 const char *def_font="6x10";
2970 font = XLoadQueryFont (dpy, def_font);
2972 fprintf(stderr,"Can't load font %s\n",def_font);
2976 text_pm=XCreatePixmap(dpy, window, 64*7, 8, xgwa.depth);
2981 gc=XCreateGC(dpy, text_pm, GCFont|GCBackground|GCForeground, &gcv);
2983 XSetForeground(dpy, gc, 0);
2984 XFillRectangle(dpy, text_pm, gc, 0, 0, 64*7, 8);
2985 XSetForeground(dpy, gc, 1);
2986 for (i=0; i<64; i++) {
2992 XDrawString(dpy, text_pm, gc, x, y, &c, 1);
2994 XDrawString(dpy, text_pm, gc, x, y, &c, 1);
2997 text_im = XGetImage(dpy, text_pm, 0, 0, 64*7, 8, ~0L, ZPixmap);
2999 XFreePixmap(dpy, text_pm);
3001 for (i=0; a2_fixfont[i]; i++) {
3002 XPutPixel(text_im, a2_fixfont[i]&0x3ff,
3003 (a2_fixfont[i]>>10)&0xf,
3004 (a2_fixfont[i]>>15)&1);
3009 Simulate plausible initial memory contents.
3013 while (addr<0x4000) {
3016 switch (random()%4) {
3020 for (i=0; i<n && addr<0x4000; i++) {
3021 u_char rb=((random()%6==0 ? 0 : random()%16) |
3022 ((random()%5==0 ? 0 : random()%16)<<4));
3023 a2_poke(st, addr++, rb);
3028 /* Simulate shapes stored in memory. We use the font since we have it.
3029 Unreadable, since rows of each character are stored in consecutive
3030 bytes. It was typical to store each of the 7 possible shifts of
3031 bitmaps, for fastest blitting to the screen. */
3032 x=random()%(text_im->width);
3033 for (i=0; i<100; i++) {
3034 for (y=0; y<8; y++) {
3036 for (j=0; j<8; j++) {
3037 c |= XGetPixel(text_im, (x+j)%text_im->width, y)<<j;
3039 a2_poke(st, addr++, c);
3041 x=(x+1)%(text_im->width);
3048 for (i=0; i<n && addr<0x4000; i++) {
3049 a2_poke(st, addr++, 0);
3058 if (random()%4==0 &&
3059 !use_cmap && use_color &&
3060 xgwa.visual->bits_per_rgb>=8) {
3063 else if (random()%3==0) {
3064 flutter_horiz_desync=1;
3070 gettimeofday(&basetime_tv, NULL);
3071 if (random()%2==0) basetime_tv.tv_sec -= 1; /* random blink phase */
3072 next_actiontime=0.0;
3075 double curtime,blinkphase;
3076 int startdisplayrow=0;
3080 struct timeval curtime_tv;
3081 gettimeofday(&curtime_tv, NULL);
3082 curtime=(curtime_tv.tv_sec - basetime_tv.tv_sec) +
3083 0.000001*(curtime_tv.tv_usec - basetime_tv.tv_usec);
3085 if (curtime>delay) goto finished;
3087 if (bsod_sleep(dpy,0)) goto finished;
3089 if (flutter_tint && st->gr_mode && !printing) {
3090 /* Oscillator instability. Look for freq_error below. We should only do
3091 this with color depth>=8, since otherwise you see pixels changing. */
3092 freq_error_inc += (-0.10*freq_error_inc
3093 + ((int)(random()&0xff)-0x80) * 0.01);
3094 freq_error += freq_error_inc;
3098 else if (flutter_horiz_desync) {
3099 /* Horizontal sync during vertical sync instability. */
3100 horiz_desync += (-0.10*(horiz_desync-3.0) +
3101 ((int)(random()&0xff)-0x80) *
3102 ((int)(random()&0xff)-0x80) *
3103 ((int)(random()&0xff)-0x80) * 0.0000003);
3104 for (i=0; i<3; i++) st->rowimage[i]=-1;
3108 /* It's super-important to get the cursor/text flash out at exactly the
3109 right time, or it looks wrong. So if we're almost due for a blink, wait
3110 for it so we don't miss it in the middle of a screen update. */
3111 blinkphase=curtime/0.8;
3112 if (blinkphase-floor(blinkphase)>0.7 && !printing && !nodelay) {
3113 /* We're about to blink */
3114 int delay = ((1.0-(blinkphase-floor(blinkphase)))*0.8) * 1000000;
3115 if (delay<1000) delay=1000;
3120 /* The blinking rate was controlled by 555 timer with a resistor/capacitor
3121 time constant. Because the capacitor was electrolytic, the flash rate
3122 varied somewhat between machines. I'm guessing 1.6 seconds/cycle was
3123 reasonable. (I soldered a resistor in mine to make it blink faster.) */
3125 st->blink=((int)blinkphase)&1;
3126 if (st->blink!=i && !(st->gr_mode&A2_GR_FULL)) {
3128 /* For every row with blinking text, set the changed flag. This basically
3129 works great except with random screen garbage in text mode, when we
3130 end up redrawing the whole screen every second */
3131 for (row=(st->gr_mode ? 20 : 0); row<24; row++) {
3132 for (col=0; col<40; col++) {
3133 c=st->textlines[row][col];
3134 if ((c & 0xc0) == 0x40) {
3139 if (downcounter>0) {
3140 st->rowimage[row]=-1;
3144 st->rowimage[st->cursy]=-1;
3145 startdisplayrow=random()%24;
3147 else if (next_actiontime > curtime && !printing && !nodelay) {
3148 int delay = (next_actiontime-curtime)*1000000;
3150 if (delay>100000) delay=100000;
3151 if (delay<1000) delay=1000;
3159 if (*printing=='\001') { /* pause */
3161 for (i=20; i<24; i++) st->rowimage[i]=-1;
3164 else if (*printing=='\n') {
3165 a2_printc(st,*printing);
3170 a2_printc(st,*printing);
3174 if (!*printing) printing=NULL;
3176 else if (curtime >= next_actiontime) {
3178 /* If we're in the midst of typing a string, emit a character with
3180 a2_printc(st, *typing);
3181 if (*typing=='\n') {
3182 next_actiontime = curtime;
3184 next_actiontime = curtime + (random()%1000)*0.0003 + 0.3;
3188 if (!*typing) typing=NULL;
3192 next_actiontime=curtime;
3199 For testing color rendering. The spec is:
3207 6 med blue 20 207 253
3208 7 lt blue 208 195 255
3213 12 lt green 20 245 60
3214 13 yellow 208 221 141
3216 15 white 255 255 255
3218 st->gr_mode=A2_GR_LORES;
3219 for (row=0; row<24; row++) {
3220 for (col=0; col<40; col++) {
3221 st->textlines[row][col]=(row&15)*17;
3224 next_actiontime+=0.4;
3227 else if (random()%3==0) {
3229 next_actiontime+=0.4;
3232 else if (random()%4==0) {
3233 st->gr_mode=A2_GR_LORES;
3234 if (random()%3==0) st->gr_mode |= A2_GR_FULL;
3235 next_actiontime+=0.4;
3238 else if (random()%2==0) {
3239 st->gr_mode=A2_GR_HIRES;
3243 st->gr_mode=A2_GR_HIRES;
3244 next_actiontime+=0.4;
3250 /* An illegal instruction or a reset caused it to drop into the
3251 assembly language monitor, where you could disassemble code & view
3253 if (random()%3==0) {
3256 int addr=0xd000+random()%0x3000;
3258 "%02X",random()%0xff);
3264 " A=%02X X=%02X Y=%02X S=%02X F=%02X\n"
3267 random()%0xff, random()%0xff,
3268 random()%0xff, random()%0xff,
3278 next_actiontime += 2.0 + (random()%1000)*0.0002;
3281 /* Lots of programs had at least their main functionality in
3282 Applesoft Basic, which had a lot of limits (memory, string
3283 length, etc) and would sometimes crash unexpectedly. */
3290 apple2_basic_errors[random() %
3291 (sizeof(apple2_basic_errors)
3293 (1000*(random()%(random()%59+1)) +
3294 100*(random()%(random()%9+1)) +
3295 5*(random()%(random()%199+1)) +
3296 1*(random()%(random()%(random()%2+1)+1))));
3301 next_actiontime += 2.0 + (random()%1000)*0.0002;
3306 if (simulate_user && random()%3==0) {
3307 /* This was how you reset the Basic interpreter. The sort of
3308 incantation you'd have on a little piece of paper taped to the
3309 side of your machine */
3310 typing="CALL -1370";
3313 else if (simulate_user && random()%2==0) {
3318 next_actiontime+=1.0;
3325 next_actiontime += 0.5;
3332 for (s="APPLE ]["; *s; s++) a2_printc(st,*s);
3335 next_actiontime+=1.0;
3340 if (simulate_user && random()%50==0 && 0) { /* disabled, too goofy */
3341 typing="10 PRINT \"TRS-80S SUCK!!!\"\n"
3348 next_actiontime += delay;
3353 for (i=0; i<30; i++) {
3354 for (s="\nTRS-80S SUCK"; *s; s++) a2_printc(st,*s);
3357 next_actiontime+=delay;
3363 if (random()%50==0) {
3364 sprintf(printbuf,"\nDISK VOLUME 254\n\n"
3371 sprintf(printbuf,"\n?%s\n]",
3372 apple2_dos_errors[random()%
3373 (sizeof(apple2_dos_errors) /
3378 next_actiontime+=1.0;
3382 if (simulate_user && random()%2==0) {
3383 /* This was how you went back to text mode in the monitor */
3387 next_actiontime+=1.0;
3398 next_actiontime+=2.0;
3402 /* This reset things into Basic */
3403 if (simulate_user && random()%2==0) {
3409 next_actiontime+=delay;
3414 for (i=0; i<1500; i++) {
3415 a2_poke(st, fillptr, fillbyte);
3417 fillbyte = (fillbyte+1)&0xff;
3419 next_actiontime += 0.08;
3420 /* When you hit c000, it changed video settings */
3421 if (fillptr>=0xc000) {
3425 /* And it seemed to reset around here, I dunno why */
3426 if (fillptr>=0xcf00) stepno=3;
3432 /* Now, we turn the data in the Apple II video into a screen display. This
3433 is interesting because of the interaction with the NTSC color decoding
3434 in a color television. */
3436 colormode=use_color && st->gr_mode!=0;
3438 ntsc_set_demod(dec, tint_control, color_control, brightness_control,
3439 freq_error, colormode);
3442 for (textrow=0; textrow<24; textrow++) {
3443 if (st->rowimage[textrow] == textrow) {
3444 screen_plan[textrow]=0;
3446 else if (cheapdisplay && st->rowimage[textrow]>=0 &&
3447 textrow<21 && st->rowimage[textrow]<21 &&
3448 st->rowimage[textrow]>=2 && textrow>=2 &&
3449 (st->rowimage[textrow]+1)*h/24 + screen_xo <= xgwa.height) {
3450 screen_plan[textrow]= A2_SP_COPY | st->rowimage[textrow];
3451 for (i=0; i<8; i++) {
3452 crtload[textrow*8+i]=crtload[st->rowimage[textrow]*8+i];
3457 st->rowimage[textrow]=imgrow;
3458 screen_plan[textrow]=imgrow | A2_SP_PUT;
3460 for (row=textrow*8; row<textrow*8+8; row++) {
3462 int pixmultinc,pixbright;
3463 int scanstart_i, scanend_i;
3464 int squishright_i, squishdiv;
3466 double bloomthisrow,shiftthisrow;
3467 int ytop=(imgrow*h/24) + ((row-textrow*8) * h/192);
3468 int ybot=ytop+h/192;
3470 /* First we generate the pattern that the video circuitry shifts out
3471 of memory. It has a 14.something MHz dot clock, equal to 4 times
3472 the color burst frequency. So each group of 4 bits defines a
3473 color. Each character position, or byte in hires, defines 14
3474 dots, so odd and even bytes have different color spaces. So,
3475 pattern[0..600] gets the dots for one scan line. */
3477 memset(dec->pattern,0,sizeof(dec->pattern));
3480 if ((st->gr_mode&A2_GR_HIRES) && (row<160 ||
3481 (st->gr_mode&A2_GR_FULL))) {
3483 /* Emulate the mysterious pink line, due to a bit getting
3484 stuck in a shift register between the end of the last
3485 row and the beginning of this one. */
3486 if ((st->hireslines[row][0] & 0x80) &&
3487 (st->hireslines[row][39]&0x40)) {
3491 for (col=0; col<40; col++) {
3492 u_char b=st->hireslines[row][col];
3493 int shift=(b&0x80)?0:1;
3495 /* Each of the low 7 bits in hires mode corresponded to 2 dot
3496 clocks, shifted by one if the high bit was set. */
3497 for (i=0; i<7; i++) {
3498 pp[shift+1] = pp[shift] =(b>>i)&1;
3503 else if ((st->gr_mode&A2_GR_LORES) && (row<160 ||
3504 (st->gr_mode&A2_GR_FULL))) {
3505 for (col=0; col<40; col++) {
3506 u_char nib=(st->textlines[textrow][col] >> (((row/4)&1)*4))&0xf;
3507 /* The low or high nybble was shifted out one bit at a time. */
3508 for (i=0; i<14; i++) {
3509 *pp = (nib>>((col*14+i)&3))&1;
3515 for (col=0; col<40; col++) {
3517 c=st->textlines[textrow][col];
3518 /* hi bits control inverse/blink as follows:
3523 rev=!(c&0x80) && (!(c&0x40) || st->blink);
3525 for (i=0; i<7; i++) {
3526 for (i=0; i<7; i++) {
3527 unsigned long pix=XGetPixel(text_im,
3528 ((c&0x3f)^0x20)*7+i, row%8);
3529 pp[1] = pp[2] = pix^rev;
3537 Interpolate the 600-dotclock line into however many horizontal
3538 screen pixels we're using, and convert to RGB.
3540 We add some 'bloom', variations in the horizontal scan width with
3541 the amount of brightness, extremely common on period TV sets. They
3542 had a single oscillator which generated both the horizontal scan
3543 and (during the horizontal retrace interval) the high voltage for
3544 the electron beam. More brightness meant more load on the
3545 oscillator, which caused an decrease in horizontal deflection. Look
3548 Also, the A2 did a bad job of generating horizontal sync pulses
3549 during the vertical blanking interval. This, and the fact that the
3550 horizontal frequency was a bit off meant that TVs usually went a
3551 bit out of sync during the vertical retrace, and the top of the
3552 screen would be bent a bit to the left or right. Look for
3555 We also add a teeny bit of left overscan, just enough to be
3556 annoying, but you can still read the left column of text.
3558 We also simulate compression & brightening on the right side of the
3559 screen. Most TVs do this, but you don't notice because they
3560 overscan so it's off the right edge of the CRT. But the A2 video
3561 system used so much of the horizontal scan line that you had to
3562 crank the horizontal width down in order to not lose the right few
3563 characters, and you'd see the compression on the right
3564 edge. Associated with compression is brightening; since the
3565 electron beam was scanning slower, the same drive signal hit the
3566 phosphor harder. Look for (squishright_i) and (squishdiv).
3569 for (i=j=0; i<600; i++) {
3570 j += dec->pattern[i];
3572 crtload[row] = (crtload[row>1 ? row-1 : 0]) * 0.98 + 0.02*(j/600.0) +
3573 (row>180 ? (row-180)*(row-180)*0.0005 : 0.0);
3574 bloomthisrow = -10.0 * crtload[row];
3575 shiftthisrow=((row<18) ? ((18-row)*(18-row)* 0.002 + (18-row)*0.05)
3576 * horiz_desync : 0.0);
3578 scanstart_i=(int)((bloomthisrow+shiftthisrow+18.0)*65536.0);
3579 if (scanstart_i<0) scanstart_i=0;
3580 if (scanstart_i>30*65536) scanstart_i=30*65536;
3581 scanend_i=599*65536;
3582 squishright_i=scanstart_i + 530*65536;
3584 pixrate=(int)((560.0-2.0*bloomthisrow)*65536.0/w);
3587 for (y=ytop; y<ybot; y++) {
3588 int level=(!(y==ytop && ybot-ytop>=3) &&
3589 !(y==ybot-1 && ybot-ytop>=5));
3594 for (x=0, i=scanstart_i;
3596 x++, i+=pixmultinc) {
3599 while (pati>=histi) {
3600 hist=(((hist<<1) & ((1<<A2_CMAP_HISTBITS)-1)) |
3601 dec->pattern[histi]);
3604 XPutPixel(image, x, y,
3605 colors[A2_CMAP_INDEX(colormode,level,hist,offset)]);
3606 if (i >= squishright_i) {
3607 pixmultinc += pixmultinc/squishdiv;
3611 XPutPixel(image, x, y, colors[0]);
3618 pixbright=(int)(contrast_control*65536.0);
3620 for (x=0, i=scanstart_i, rrp=raw_rgb;
3622 x++, i+=pixmultinc, rrp+=3) {
3623 int pixfrac=i&0xffff;
3624 int invpixfrac=65536-pixfrac;
3628 int interpy=((dec->ntscy[pati]*invpixfrac +
3629 dec->ntscy[pati+1]*pixfrac)>>16);
3630 int interpi=((dec->ntsci[pati]*invpixfrac +
3631 dec->ntsci[pati+1]*pixfrac)>>16);
3632 int interpq=((dec->ntscq[pati]*invpixfrac +
3633 dec->ntscq[pati+1]*pixfrac)>>16);
3636 According to the NTSC spec, Y,I,Q are generated as:
3638 y=0.30 r + 0.59 g + 0.11 b
3639 i=0.60 r - 0.28 g - 0.32 b
3640 q=0.21 r - 0.52 g + 0.31 b
3642 So if you invert the implied 3x3 matrix you get what standard
3643 televisions implement with a bunch of resistors (or directly in
3644 the CRT -- don't ask):
3646 r = y + 0.948 i + 0.624 q
3647 g = y - 0.276 i - 0.639 q
3648 b = y - 1.105 i + 1.729 q
3650 These coefficients are below in 16.16 format.
3653 r=((interpy + ((+68128*interpi+40894*interpq)>>16))*pixbright)
3655 g=((interpy + ((-18087*interpi-41877*interpq)>>16))*pixbright)
3657 b=((interpy + ((-72417*interpi+113312*interpq)>>16))*pixbright)
3666 if (i>=squishright_i) {
3667 pixmultinc += pixmultinc/squishdiv;
3668 pixbright += pixbright/squishdiv;
3671 for ( ; x<w; x++, rrp+=3) {
3672 rrp[0]=rrp[1]=rrp[2]=0;
3675 for (y=ytop; y<ybot; y++) {
3676 /* levelmult represents the vertical size of scan lines. Each
3677 line is brightest in the middle, and there's a dark band
3680 double levelmult_fp=(y + 0.5 - (ytop+ybot)*0.5) / (ybot-ytop);
3681 levelmult_fp = 1.0-(levelmult_fp*levelmult_fp*levelmult_fp
3682 *levelmult_fp)*16.0;
3683 if (levelmult_fp<0.0) levelmult_fp=0.0;
3684 levelmult = (int)(64.9*levelmult_fp);
3686 /* Fast special cases to avoid the slow XPutPixel. Ugh. It goes
3687 to show why standard graphics sw has to be fast, or else
3688 people will have to work around it and risk incompatibility.
3689 The quickdraw folks understood this. The other answer would
3690 be for X11 to have fewer formats for bitm.. oh, never
3691 mind. If neither of these cases work (they probably cover 99%
3692 of setups) it falls back on the Xlib routines. */
3693 if (image->format==ZPixmap && image->bits_per_pixel==32 &&
3694 sizeof(unsigned long)==4 &&
3695 image->byte_order==localbyteorder) {
3696 unsigned long *pixelptr =
3697 (unsigned long *) (image->data + y * image->bytes_per_line);
3698 for (x=0, rrp=raw_rgb; x<w; x++, rrp+=3) {
3699 unsigned long ntscri, ntscgi, ntscbi;
3700 ntscri=((unsigned long)rrp[0])*levelmult;
3701 ntscgi=((unsigned long)rrp[1])*levelmult;
3702 ntscbi=((unsigned long)rrp[2])*levelmult;
3703 if (ntscri>65535) ntscri=65535;
3704 if (ntscgi>65535) ntscgi=65535;
3705 if (ntscbi>65535) ntscbi=65535;
3706 *pixelptr++ = ((ntscri>>red_invprec)<<red_shift) |
3707 ((ntscgi>>green_invprec)<<green_shift) |
3708 ((ntscbi>>blue_invprec)<<blue_shift);
3711 else if (image->format==ZPixmap && image->bits_per_pixel==16 &&
3712 sizeof(unsigned short)==2 &&
3713 image->byte_order==localbyteorder) {
3714 unsigned short *pixelptr =
3715 (unsigned short *)(image->data + y*image->bytes_per_line);
3716 for (x=0, rrp=raw_rgb; x<w; x++, rrp+=3) {
3717 unsigned long ntscri, ntscgi, ntscbi;
3718 ntscri=((unsigned long)rrp[0])*levelmult;
3719 ntscgi=((unsigned long)rrp[1])*levelmult;
3720 ntscbi=((unsigned long)rrp[2])*levelmult;
3721 if (ntscri>65535) ntscri=65535;
3722 if (ntscgi>65535) ntscgi=65535;
3723 if (ntscbi>65535) ntscbi=65535;
3724 *pixelptr++ = ((ntscri>>red_invprec)<<red_shift) |
3725 ((ntscgi>>green_invprec)<<green_shift) |
3726 ((ntscbi>>blue_invprec)<<blue_shift);
3731 for (x=0, rrp=raw_rgb; x<w; x++, rrp+=3) {
3732 unsigned long pixel, ntscri, ntscgi, ntscbi;
3733 /* Convert to 16-bit color values, with saturation. The ntscr
3734 values are 22.10 fixed point, and levelmult is 24.6, so we
3736 ntscri=((unsigned long)rrp[0])*levelmult;
3737 ntscgi=((unsigned long)rrp[1])*levelmult;
3738 ntscbi=((unsigned long)rrp[2])*levelmult;
3739 if (ntscri>65535) ntscri=65535;
3740 if (ntscgi>65535) ntscgi=65535;
3741 if (ntscbi>65535) ntscbi=65535;
3742 pixel = ((ntscri>>red_invprec)<<red_shift) |
3743 ((ntscgi>>green_invprec)<<green_shift) |
3744 ((ntscbi>>blue_invprec)<<blue_shift);
3745 XPutPixel(image, x, y, pixel);
3755 /* For just the the rows which changed, blit the image to the screen. */
3756 for (textrow=0; textrow<24; ) {
3757 int top,bot,srcrow,srctop,nrows;
3760 while (textrow+nrows < 24 &&
3761 screen_plan[textrow+nrows] == screen_plan[textrow]+nrows)
3765 bot=h*(textrow+nrows)/24;
3766 srcrow=screen_plan[textrow]&A2_SP_ROWMASK;
3769 if (screen_plan[textrow] & A2_SP_COPY) {
3770 if (0) printf("Copy %d screenrows %d to %d\n", nrows, srcrow, textrow);
3771 XCopyArea(dpy, window, window, gc,
3772 screen_xo, screen_yo + srctop,
3774 screen_xo, screen_yo + top);
3776 else if (screen_plan[textrow] & A2_SP_PUT) {
3777 if (0) printf("Draw %d imgrows %d to %d\n", nrows, srcrow, textrow);
3779 #ifdef HAVE_XSHM_EXTENSION
3780 XShmPutImage(dpy, window, gc, image,
3781 0, srctop, screen_xo, screen_yo + top,
3785 XPutImage(dpy, window, gc, image,
3787 screen_xo, screen_yo + top,
3795 for (textrow=0; textrow<24; textrow++) {
3796 st->rowimage[textrow]=textrow;
3802 XClearWindow(dpy, window);
3811 #ifdef HAVE_XSHM_EXTENSION
3812 destroy_xshm_image(dpy, image, &shm_info);
3815 XDestroyImage(image);
3819 if (text_im) XDestroyImage(text_im);
3820 if (gc) XFreeGC(dpy, gc);
3822 if (raw_rgb) free(raw_rgb);
3824 if (n_colors) XFreeColors(dpy, xgwa.colormap, colors, n_colors, 0L);
3829 char *progclass = "BSOD";
3831 char *defaults [] = {
3844 "*doAtari: False", /* boring */
3845 "*doBSD: False", /* boring */
3847 "*doSparcLinux: False", /* boring */
3848 "*doBlitDamage: True",
3854 ".Windows.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3855 ".Windows.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
3856 ".Windows.foreground: White",
3857 ".Windows.background: #0000AA", /* EGA color 0x01. */
3859 ".Amiga.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3860 ".Amiga.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
3861 ".Amiga.foreground: Red",
3862 ".Amiga.background: Black",
3863 ".Amiga.background2: White",
3865 ".Mac.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3866 ".Mac.foreground: PaleTurquoise1",
3867 ".Mac.background: Black",
3869 ".Atari.foreground: Black",
3870 ".Atari.background: White",
3872 ".MacsBug.font: -*-courier-medium-r-*-*-*-100-*-*-m-*-*-*",
3873 ".MacsBug.font2: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3874 ".MacsBug.font3: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3875 ".MacsBug.foreground: Black",
3876 ".MacsBug.background: White",
3877 ".MacsBug.borderColor: #AAAAAA",
3879 ".mac1.foreground: Black",
3880 ".mac1.background: White",
3882 ".macX.textForeground: White",
3883 ".macX.textBackground: Black",
3884 ".macX.background: #888888",
3885 ".macX.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3886 ".macX.font2: -*-courier-bold-r-*-*-*-240-*-*-m-*-*-*",
3888 ".SCO.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3889 ".SCO.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3890 ".SCO.foreground: White",
3891 ".SCO.background: Black",
3893 ".Linux.font: 9x15bold",
3894 ".Linux.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3895 ".Linux.foreground: White",
3896 ".Linux.background: Black",
3898 ".SparcLinux.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3899 ".SparcLinux.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3900 ".SparcLinux.foreground: White",
3901 ".SparcLinux.background: Black",
3904 ".BSD.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3905 ".BSD.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3906 /* ".BSD.font2: -sun-console-medium-r-*-*-22-*-*-*-m-*-*-*", */
3907 ".BSD.foreground: #c0c0c0",
3908 ".BSD.background: Black",
3910 ".Solaris.font: -sun-gallant-*-*-*-*-19-*-*-*-*-120-*-*",
3911 ".Solaris.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3912 ".Solaris.foreground: Black",
3913 ".Solaris.background: White",
3914 "*dontClearRoot: True",
3916 ".HPUX.font: 9x15bold",
3917 ".HPUX.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3918 ".HPUX.foreground: White",
3919 ".HPUX.background: Black",
3921 ".OS390.font: 9x15bold",
3922 ".OS390.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3923 ".OS390.background: Black",
3924 ".OS390.foreground: Red",
3926 "*apple2TVColor: 50",
3928 "*apple2TVBrightness: 10",
3929 "*apple2TVContrast: 90",
3930 "*apple2SimulateUser: True",
3932 #ifdef HAVE_XSHM_EXTENSION
3938 XrmOptionDescRec options [] = {
3939 { "-delay", ".delay", XrmoptionSepArg, 0 },
3940 { "-only", ".doOnly", XrmoptionSepArg, 0 },
3941 { "-windows", ".doWindows", XrmoptionNoArg, "True" },
3942 { "-no-windows", ".doWindows", XrmoptionNoArg, "False" },
3943 { "-nt", ".doNT", XrmoptionNoArg, "True" },
3944 { "-no-nt", ".doNT", XrmoptionNoArg, "False" },
3945 { "-2k", ".doWin2K", XrmoptionNoArg, "True" },
3946 { "-no-2k", ".doWin2K", XrmoptionNoArg, "False" },
3947 { "-amiga", ".doAmiga", XrmoptionNoArg, "True" },
3948 { "-no-amiga", ".doAmiga", XrmoptionNoArg, "False" },
3949 { "-mac", ".doMac", XrmoptionNoArg, "True" },
3950 { "-no-mac", ".doMac", XrmoptionNoArg, "False" },
3951 { "-mac1", ".doMac1", XrmoptionNoArg, "True" },
3952 { "-no-mac1", ".doMac1", XrmoptionNoArg, "False" },
3953 { "-macx", ".doMacX", XrmoptionNoArg, "True" },
3954 { "-no-macx", ".doMacX", XrmoptionNoArg, "False" },
3955 { "-atari", ".doAtari", XrmoptionNoArg, "True" },
3956 { "-no-atari", ".doAtari", XrmoptionNoArg, "False" },
3957 { "-macsbug", ".doMacsBug", XrmoptionNoArg, "True" },
3958 { "-no-macsbug", ".doMacsBug", XrmoptionNoArg, "False" },
3959 { "-apple2", ".doApple2", XrmoptionNoArg, "True" },
3960 { "-no-apple2", ".doApple2", XrmoptionNoArg, "False" },
3961 { "-sco", ".doSCO", XrmoptionNoArg, "True" },
3962 { "-no-sco", ".doSCO", XrmoptionNoArg, "False" },
3963 { "-bsd", ".doBSD", XrmoptionNoArg, "True" },
3964 { "-no-bsd", ".doBSD", XrmoptionNoArg, "False" },
3965 { "-linux", ".doLinux", XrmoptionNoArg, "True" },
3966 { "-no-linux", ".doLinux", XrmoptionNoArg, "False" },
3967 { "-sparclinux", ".doSparcLinux", XrmoptionNoArg, "True" },
3968 { "-no-sparclinux", ".doSparcLinux", XrmoptionNoArg, "False" },
3969 { "-blitdamage", ".doBlitDamage", XrmoptionNoArg, "True" },
3970 { "-no-blitdamage", ".doBlitDamage", XrmoptionNoArg, "False" },
3971 { "-solaris", ".doSolaris", XrmoptionNoArg, "True" },
3972 { "-no-solaris", ".doSolaris", XrmoptionNoArg, "False" },
3973 { "-hpux", ".doHPUX", XrmoptionNoArg, "True" },
3974 { "-no-hpux", ".doHPUX", XrmoptionNoArg, "False" },
3975 { "-os390", ".doOS390", XrmoptionNoArg, "True" },
3976 { "-no-os390", ".doOS390", XrmoptionNoArg, "False" },
3983 void (*fn) (Display *, Window, int delay);
3985 { "Windows", windows_31 },
3986 { "Nt", windows_nt },
3987 { "2k", windows_2k },
3990 { "MacsBug", macsbug },
3994 { "SparcLinux", sparc_linux },
3997 { "BlitDamage", blitdamage },
3998 { "Solaris", sparc_solaris },
3999 { "Linux", linux_fsck },
4002 { "Apple2", apple2 },
4007 screenhack (Display *dpy, Window window)
4013 int delay = get_integer_resource ("delay", "Integer");
4014 if (delay < 3) delay = 3;
4017 char *s = get_string_resource("doOnly", "DoOnly");
4020 int count = countof(all_modes);
4021 for (only = 0; only < count; only++)
4022 if (!strcasecmp (s, all_modes[only].name))
4026 fprintf (stderr, "%s: unknown -only mode: \"%s\"\n", progname, s);
4033 if (!get_boolean_resource ("root", "Boolean"))
4035 XWindowAttributes xgwa;
4036 XGetWindowAttributes (dpy, window, &xgwa);
4037 XSelectInput (dpy, window,
4038 xgwa.your_event_mask | KeyPressMask | ButtonPressMask);
4044 int count = countof(all_modes);
4045 char name[100], class[100];
4050 do { i = (random() & 0xFF) % count; } while (i == j);
4052 sprintf (name, "do%s", all_modes[i].name);
4053 sprintf (class, "Do%s", all_modes[i].name);
4056 if (only > 0 || get_boolean_resource(name, class))
4058 all_modes[i].fn (dpy, window, delay);
4063 if (loop > 100) j = -1;
4066 fprintf (stderr, "%s: no display modes enabled?\n", progname);