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)
2105 XWindowAttributes xgwa;
2106 scrolling_window *ts;
2107 const char *sysname;
2113 " ******* Unexpected HPMC/TOC. Processor HPA FFFFFFFF'"
2114 "FFFA0000 *******\n"
2115 " GENERAL REGISTERS:\n"
2116 "r00/03 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2118 "r04/07 00000000'00000001 00000000'0126E328 00000000'00000000 00000000'"
2120 "r08/11 00000000'00000000 00000000'0198CFC0 00000000'000476FE 00000000'"
2122 "r12/15 00000000'40013EE8 00000000'08000080 00000000'4002530C 00000000'"
2124 "r16/19 00000000'7F7F2A00 00000000'00000001 00000000'00000000 00000000'"
2126 "r20/23 00000000'006C8048 00000000'00000001 00000000'00000000 00000000'"
2128 "r24/27 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2130 "r28/31 00000000'00000000 00000000'007DD628 00000000'0199F2B0 00000000'"
2132 " CONTROL REGISTERS:\n"
2133 "sr0/3 00000000'0F3B4000 00000000'0C2A2000 00000000'016FF800 00000000'"
2135 "sr4/7 00000000'00000000 00000000'016FF800 00000000'0DBF1400 00000000'"
2137 "pcq = 00000000'00000000.00000000'00104950 00000000'00000000.00000000'"
2139 "isr = 00000000'10240006 ior = 00000000'67D9E220 iir = 08000240 rctr = "
2142 "pid reg cr8/cr9 00007700'0000B3A9 00000000'0000C5D8\n"
2143 "pid reg cr12/cr13 00000000'00000000 00000000'00000000\n"
2144 "ipsw = 000000FF'080CFF1F iva = 00000000'0002C000 sar = 3A ccr = C0\n"
2145 "tr0/3 00000000'006C76C0 00000000'00000001 00000000'00000000 00000000'"
2147 "tr4/7 00000000'03790000 0000000C'4FB68340 00000000'C07EE13F 00000000'"
2149 "eiem = FFFFFFF0'FFFFFFFF eirr = 80000000'00000000 itmr = 0000000C'"
2151 "cr1/4 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2153 "cr5/7 00000000'00000000 00000000'00000000 00000000'"
2155 " MACHINE CHECK PARAMETERS:\n"
2156 "Check Type = 00000000 CPU STATE = 9E000001 Cache Check = 00000000\n"
2157 "TLB Check = 00000000 Bus Check = 00000000 PIM State = ? SIU "
2158 "Status = ????????\n"
2159 "Assists = 00000000 Processor = 00000000\n"
2160 "Slave Addr = 00000000'00000000 Master Addr = 00000000'00000000\n"
2163 "TOC, pcsq.pcoq = 0'0.0'104950 , isr.ior = 0'10240006.0'67d9e220\n"
2164 "@(#)B2352B/9245XB HP-UX (B.11.00) #1: Wed Nov 5 22:38:19 PST 1997\n"
2165 "Transfer of control: (display==0xd904, flags==0x0)\n"
2169 "*** A system crash has occurred. (See the above messages for details.)\n"
2170 "*** The system is now preparing to dump physical memory to disk, for use\n"
2171 "*** in debugging the crash.\n"
2173 "*** The dump will be a SELECTIVE dump: 40 of 256 megabytes.\n"
2174 "*** To change this dump type, press any key within 10 seconds.\n"
2175 "*** Proceeding with selective dump.\n"
2177 "*** The dump may be aborted at any time by pressing ESC.\n";
2179 "\n*** System rebooting.\n";
2181 XGetWindowAttributes (dpy, window, &xgwa);
2182 ts = make_scrolling_window (dpy, window, "HPUX", False);
2183 ts->columns = 10000; /* never wrap */
2186 ts->sub_width = xgwa.width;
2187 ts->sub_height = xgwa.height;
2194 if (uname (&uts) >= 0)
2195 sysname = uts.nodename;
2196 s = strchr (sysname, '.');
2199 # endif /* !HAVE_UNAME */
2201 gcv.foreground = get_pixel_resource ("HPUX.foreground", "HPUX.Foreground",
2202 dpy, xgwa.colormap);
2203 gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
2204 XFillRectangle (dpy, window, gc, 0, 0, xgwa.width, xgwa.height);
2205 if (bsod_sleep (dpy, 1))
2213 sprintf (buf, "%.100s [HP Release B.11.00] (see /etc/issue)\n", sysname);
2214 scrolling_puts (ts, buf, 0);
2215 if (bsod_sleep (dpy, 1))
2217 scrolling_puts (ts, msg1, 0);
2222 for (i = 0; i <= steps; i++)
2224 if (i > steps) i = steps;
2226 "*** Dumping: %3d%% complete (%d of 40 MB) (device 64:0x2)\r",
2229 scrolling_puts (ts, buf, 0);
2232 if (bsod_sleep (dpy, 0))
2237 scrolling_puts (ts, msg2, 0);
2240 bsod_sleep(dpy, delay);
2243 free_scrolling_window (ts);
2248 /* IBM OS/390 aka MVS aka z/OS.
2249 Text from Dan Espen <dane@mk.telcordia.com>.
2250 Apparently this isn't actually a crash, just a random session...
2255 os390 (Display* dpy, Window window, int delay)
2259 XWindowAttributes xgwa;
2260 scrolling_window *ts;
2263 const char *msg[] = {
2264 "* ISPF Subtask abend *\n",
2265 "SPF ENDED DUE TO ERROR+\n",
2268 "IEA995I SYMPTOM DUMP OUTPUT\n",
2269 " USER COMPLETION CODE=0222\n",
2270 " TIME=23.00.51 SEQ=03210 CPU=0000 ASID=00AE\n",
2271 " PSW AT TIME OF ERROR 078D1000 859DAF18 ILC 2 INTC 0D\n",
2272 " NO ACTIVE MODULE FOUND\n",
2274 " DATA AT PSW 059DAF12 - 00181610 0A0D9180 70644710\n",
2275 " AR/GR 0: 00000000/80000000 1: 00000000/800000DE\n",
2276 " 2: 00000000/196504DC 3: 00000000/00037A78\n",
2277 " 4: 00000000/00037B78 5: 00000000/0003351C\n",
2278 " 6: 00000000/0000F0AD 7: 00000000/00012000\n",
2279 " 8: 00000000/059DAF10 9: 00000000/0002D098\n",
2280 " A: 00000000/059D9F10 B: 00000000/059D8F10\n",
2281 " C: 00000000/859D7F10 D: 00000000/00032D60\n",
2282 " E: 00000000/00033005 F: 01000002/00000041\n",
2283 " END OF SYMPTOM DUMP\n",
2284 "ISPS014 - ** Logical screen request failed - abend 0000DE **\n",
2285 "ISPS015 - ** Contact your system programmer or dialog developer.**\n",
2286 "*** ISPF Main task abend ***\n",
2287 "IEA995I SYMPTOM DUMP OUTPUT\n",
2288 " USER COMPLETION CODE=0222\n",
2289 " TIME=23.00.52 SEQ=03211 CPU=0000 ASID=00AE\n",
2290 " PSW AT TIME OF ERROR 078D1000 8585713C ILC 2 INTC 0D\n",
2291 " ACTIVE LOAD MODULE ADDRESS=05855000 OFFSET=0000213C\n",
2293 " DATA AT PSW 05857136 - 00181610 0A0D9180 D3304770\n",
2294 " GR 0: 80000000 1: 800000DE\n",
2295 " 2: 00015260 3: 00000038\n",
2296 " 4: 00012508 5: 00000000\n",
2297 " 6: 000173AC 7: FFFFFFF8\n",
2298 " 8: 05858000 9: 00012CA0\n",
2299 " A: 05857000 B: 05856000\n",
2300 " C: 85855000 D: 00017020\n",
2301 " E: 85857104 F: 00000000\n",
2302 " END OF SYMPTOM DUMP\n",
2307 XGetWindowAttributes (dpy, window, &xgwa);
2308 ts = make_scrolling_window (dpy, window, "OS390", False);
2309 ts->columns = 10000; /* never wrap */
2312 ts->sub_width = xgwa.width;
2313 ts->sub_height = xgwa.height;
2315 gcv.foreground = get_pixel_resource ("390.background", "390.Background",
2316 dpy, xgwa.colormap);
2317 gc = XCreateGC (dpy, window, GCForeground, &gcv);
2318 XFillRectangle (dpy, window, gc, 0, 0, xgwa.width, xgwa.height);
2321 for (i = 0; i < countof (msg); i++)
2323 scrolling_puts (ts, msg[i], 0);
2325 if (bsod_sleep(dpy, 0)) goto DONE;
2329 bsod_sleep(dpy, delay);
2331 free_scrolling_window (ts);
2337 * Simulate various Apple II crashes. The memory map encouraged many
2338 * programs to use the primary hi-res video page for various storage,
2339 * and the secondary hi-res page for active display. When it crashed
2340 * into Applesoft or the monitor, it would revert to the primary page
2341 * and you'd see memory garbage on the screen. Also, it was common for
2342 * copy-protected games to use the primary text page for important
2343 * code, because that made it really hard to reverse-engineer them. The
2344 * result often looked like what this generates.
2346 * Sometimes an imaginary user types some of the standard commands to
2347 * recover from crashes. You can turn off BSOD*apple2SimulateUser to
2350 * It simulates the following characteristics of standard television
2353 * - Realistic rendering of a composite video signal
2354 * - Compression & brightening on the right, as the scan gets truncated
2355 * because of saturation in the flyback transformer
2356 * - Blooming of the picture dependent on brightness
2357 * - Overscan, cutting off a few pixels on the left side.
2358 * - Colored text in mixed graphics/text modes
2360 * It's amazing how much it makes your high-end monitor look like at
2361 * large late-70s TV. All you need is to put a big "Solid State" logo
2362 * in curly script on it and you'd be set.
2364 * Trevor Blackwell <tlb@tlb.org>
2368 * Implementation notes:
2370 * There are roughly 3 parts to this hack:
2372 * - emulation of A2 Basic and Monitor. Not much more than printing random
2373 * plausible messages. Here we work in the A2 memory space.
2375 * - emulation of the A2's video output section, which shifted bits out of main
2376 * memory at a 14 MHz dot clock rate, sort of. You could only read one byte
2377 * per MHz, so there were various schemes for turning 8 bits into 14 screen
2380 * - simulation of an NTSC television, which turned the bits into colored
2381 * graphics and text.
2383 * The A2 had 3 display modes: text, lores, and hires. Text was 40x24, and it
2384 * disabled color in the TV. Lores gave you 40x48 graphics blocks, using the
2385 * same memory as the text screen. Each could be one of 16 colors. Hires gave
2386 * you 280x192 pixels. Odd pixels were blue or purple, and even pixels were
2387 * orange or green depending on the setting of the high bit in each byte.
2389 * The graphics modes could also have 4 lines of text at the bottom. This was
2390 * fairly unreadable if you had a color monitor.
2392 * Each mode had 2 different screens using different memory space. In hires
2393 * mode this was sometimes used for double buffering, but more often the lower
2394 * screen was full of code/data and the upper screen was used for display, so
2395 * you got random garbage on the screen.
2397 * In DirectColor or TrueColor modes, it generates pixel values directly from
2398 * RGB values it calculates across each scan line. In PseudoColor mode, it
2399 * consider each possible pattern of 5 preceding bit values in each possible
2400 * position modulo 4 and allocates a color for each. A few things, like the
2401 * brightening on the right side as the horizontal trace slows down, aren't
2402 * done in PseudoColor.
2404 * The text font is based on X's standard 6x10 font, with a few tweaks like
2405 * putting a slash across the zero.
2407 * I'd like to add a bit of visible retrace, but it conflicts with being able
2408 * to bitcopy the image when fast scrolling. After another couple of CPU
2409 * generations, we could probably regenerate the whole image from scratch every
2410 * time. On a P4 2 GHz it can manage this fine for blinking text, but scrolling
2414 static char * apple2_basic_errors[]={
2418 "RETURN WITHOUT GOSUB",
2422 "BAD SUBSCRIPT ERROR",
2425 "FORMULA TOO COMPLEX",
2429 static char * apple2_dos_errors[]={
2433 "NO BUFFERS AVAILABLE",
2434 "PROGRAM TOO LARGE",
2437 struct apple2_state {
2438 char hireslines[192][40];
2439 char textlines[24][40];
2459 a2_scroll(struct apple2_state *st)
2462 int top=(st->gr_mode&(A2_GR_LORES|A2_GR_HIRES)) ? 20 : 0;
2463 if ((st->gr_mode&A2_GR_FULL) && (st->gr_mode&A2_GR_HIRES)) return;
2464 if (st->gr_mode&A2_GR_FULL) top=0;
2465 for (i=top; i<23; i++) {
2466 if (memcmp(st->textlines[i],st->textlines[i+1],40)) {
2467 memcpy(st->textlines[i],st->textlines[i+1],40);
2468 st->rowimage[i]=st->rowimage[i+1];
2471 memset(st->textlines[23],0xe0,40);
2472 st->rowimage[23]=-1;
2476 a2_printc(struct apple2_state *st, char c)
2478 st->textlines[st->cursy][st->cursx] |= 0xc0; /* turn off blink */
2480 if (st->cursy==23) {
2483 st->rowimage[st->cursy]=-1;
2485 st->rowimage[st->cursy]=-1;
2489 st->textlines[st->cursy][st->cursx]=c ^ 0xc0;
2490 st->rowimage[st->cursy]=-1;
2492 if (st->cursx==40) {
2493 if (st->cursy==23) {
2496 st->rowimage[st->cursy]=-1;
2498 st->rowimage[st->cursy]=-1;
2503 st->textlines[st->cursy][st->cursx] &= 0x7f; /* turn on blink */
2507 a2_goto(struct apple2_state *st, int r, int c)
2509 st->textlines[st->cursy][st->cursx] |= 0xc0; /* turn off blink */
2512 st->textlines[st->cursy][st->cursx] &= 0x7f; /* turn on blink */
2516 a2_cls(struct apple2_state *st)
2519 for (i=0; i<24; i++) {
2520 memset(st->textlines[i],0xe0,40);
2526 a2_invalidate(struct apple2_state *st)
2529 for (i=0; i<24; i++) {
2535 a2_poke(struct apple2_state *st, int addr, int val)
2538 if (addr>=0x400 && addr<0x800) {
2540 int row=((addr&0x380)/0x80) + ((addr&0x7f)/0x28)*8;
2541 int col=(addr&0x7f)%0x28;
2542 if (row<24 && col<40) {
2543 st->textlines[row][col]=val;
2544 if (!(st->gr_mode&(A2_GR_HIRES)) ||
2545 (!(st->gr_mode&(A2_GR_FULL)) && row>=20)) {
2546 st->rowimage[row]=-1;
2550 else if (addr>=0x2000 && addr<0x4000) {
2551 int row=(((addr&0x1c00) / 0x400) * 1 +
2552 ((addr&0x0380) / 0x80) * 8 +
2553 ((addr&0x0078) / 0x28) * 64);
2554 int col=((addr&0x07f)%0x28);
2555 if (row<192 && col<40) {
2556 st->hireslines[row][col]=val;
2557 if (st->gr_mode&A2_GR_HIRES) {
2558 st->rowimage[row/8]=-1;
2564 /* This table lists fixes for characters that differ from the standard 6x10
2565 font. Each encodes a pixel, as (charindex*7 + x) + (y<<10) + (value<<15)
2566 where value is 0 for white and 1 for black. */
2567 static unsigned short a2_fixfont[] = {
2568 /* Fix $ */ 0x8421, 0x941d,
2569 /* Fix % */ 0x8024, 0x0028, 0x8425, 0x0426, 0x0825, 0x1027, 0x1426, 0x9427,
2571 /* Fix * */ 0x8049, 0x8449, 0x8849, 0x0c47, 0x0c48, 0x0c4a, 0x0c4b, 0x9049,
2573 /* Fix , */ 0x9057, 0x1458, 0x9856, 0x1857, 0x1c56,
2574 /* Fix . */ 0x1465, 0x1864, 0x1866, 0x1c65,
2575 /* Fix / */ 0x006e, 0x186a,
2576 /* Fix 0 */ 0x8874, 0x8c73, 0x9072,
2577 /* Fix 1 */ 0x0878, 0x1878, 0x187c,
2578 /* Fix 5 */ 0x8895, 0x0c94, 0x0c95,
2579 /* Fix 6 */ 0x809f, 0x8c9c, 0x109c,
2580 /* Fix 7 */ 0x8ca4, 0x0ca5, 0x90a3, 0x10a4,
2581 /* Fix 9 */ 0x08b3, 0x8cb3, 0x98b0,
2582 /* Fix : */ 0x04b9, 0x08b8, 0x08ba, 0x0cb9, 0x90b9, 0x14b9, 0x18b8, 0x18b9,
2584 /* Fix ; */ 0x04c0, 0x08bf, 0x08c1, 0x0cc0, 0x90c0, 0x14c1, 0x98bf, 0x18c0,
2586 /* Fix < */ 0x80c8, 0x00c9, 0x84c7, 0x04c8, 0x88c6, 0x08c7, 0x8cc5, 0x0cc6,
2588 0x94c7, 0x14c8, 0x98c8, 0x18c9,
2589 /* Fix > */ 0x80d3, 0x00d4, 0x84d4, 0x04d5, 0x88d5, 0x08d6, 0x8cd6, 0x0cd7,
2591 0x94d4, 0x14d5, 0x98d3, 0x18d4,
2592 /* Fix @ */ 0x88e3, 0x08e4, 0x8ce4, 0x98e5,
2593 /* Fix B */ 0x84ef, 0x04f0, 0x88ef, 0x08f0, 0x8cef, 0x90ef, 0x10f0, 0x94ef,
2595 /* Fix D */ 0x84fd, 0x04fe, 0x88fd, 0x08fe, 0x8cfd, 0x0cfe, 0x90fd, 0x10fe,
2597 /* Fix G */ 0x8116, 0x0516, 0x9916,
2598 /* Fix J */ 0x0129, 0x012a, 0x052a, 0x852b, 0x092a, 0x892b, 0x0d2a, 0x8d2b,
2600 0x152a, 0x952b, 0x992a,
2601 /* Fix M */ 0x853d, 0x853f, 0x093d, 0x893e, 0x093f,
2602 /* Fix Q */ 0x915a, 0x155a, 0x955b, 0x155c, 0x195b, 0x995c, 0x1d5c,
2603 /* Fix V */ 0x8d7b, 0x0d7c, 0x0d7e, 0x8d7f, 0x917b, 0x117c, 0x117e, 0x917f,
2604 /* Fix [ */ 0x819e, 0x81a2, 0x859e, 0x899e, 0x8d9e, 0x919e, 0x959e, 0x999e,
2606 /* Fix \ */ 0x01a5, 0x19a9,
2607 /* Fix ] */ 0x81ac, 0x81b0, 0x85b0, 0x89b0, 0x8db0, 0x91b0, 0x95b0, 0x99ac,
2609 /* Fix ^ */ 0x01b5, 0x05b4, 0x05b6, 0x09b3, 0x89b5, 0x09b7, 0x8db4, 0x8db6,
2611 /* Fix _ */ 0x9db9, 0x9dbf,
2622 int brightness_control;
2626 First generate the I and Q reference signals, which we'll multiply by the
2627 input signal to accomplish the demodulation. Normally they are shifted 33
2628 degrees from the colorburst. I think this was convenient for
2629 inductor-capacitor-vacuum tube implementation.
2631 The tint control, FWIW, just adds a phase shift to the chroma signal, and
2632 the color control controls the amplitude.
2634 In text modes (colormode==0) the system disabled the color burst, and no
2635 color was detected by the monitor.
2637 freq_error gives a mismatch between the built-in oscillator and the TV's
2638 colorbust. Older II Plus machines seemed to occasionally get instability
2639 problems -- the crystal oscillator was a single transistor if I remember
2640 correctly -- and the frequency would vary enough that the tint would change
2641 across the width of the screen. The left side would be in correct tint
2642 because it had just gotten resynchronized with the color burst.
2645 ntsc_set_demod(struct ntsc_dec *it, double tint_control,
2646 double color_control, double brightness_control,
2652 it->brightness_control=(int)(1024.0*brightness_control);
2654 for (i=0; i<600; i++) {
2655 double phase=90.0-90.0*i + freq_error*i/600.0 + tint_control;
2656 it->multi[i]=(int)(-cos(3.1415926/180.0*(phase-303)) * 65536.0 *
2657 color_control * colormode * 4);
2658 it->multq[i]=(int)(cos(3.1415926/180.0*(phase-33)) * 65536.0 *
2659 color_control * colormode * 4);
2663 /* Here we model the analog circuitry of an NTSC television. Basically, it
2664 splits the signal into 3 signals: Y, I and Q. Y corresponds to luminance,
2665 and you get it by low-pass filtering the input signal to below 3.57 MHz.
2667 I and Q are the in-phase and quadrature components of the 3.57 MHz
2668 subcarrier. We get them by multiplying by cos(3.57 MHz*t) and sin(3.57
2669 MHz*t), and low-pass filtering. Because the eye has less resolution in some
2670 colors than others, the I component gets low-pass filtered at 1.5 MHz and
2671 the Q at 0.5 MHz. The I component is approximately orange-blue, and Q is
2672 roughly purple-green. See http://www.ntsc-tv.com for details.
2675 ntsc_to_yiq(struct ntsc_dec *it)
2678 int fyx[10],fyy[10];
2679 int fix[10],fiy[10];
2680 int fqx[10],fqy[10];
2682 int iny,ini,inq,pix,blank;
2684 for (i=0; i<10; i++) fyx[i]=fyy[i]=fix[i]=fiy[i]=fqx[i]=fqy[i]=0.0;
2686 for (i=0; i<600; i++) {
2687 /* Get the video out signal, and add a teeny bit of ghosting, typical of RF
2688 monitor cables. This corresponds to a pretty long cable, but looks right
2690 pix=it->pattern[i]*1024;
2691 if (i>=20) pixghost += it->pattern[i-20]*15;
2692 if (i>=30) pixghost -= it->pattern[i-30]*15;
2695 /* Get Y, I, Q before filtering */
2697 ini=(pix*it->multi[i])>>16;
2698 inq=(pix*it->multq[i])>>16;
2700 blank = (i>=7 && i<596 ? it->brightness_control : -200);
2702 /* Now filter them. These are infinite impulse response filters calculated
2703 by the script at http://www-users.cs.york.ac.uk/~fisher/mkfilter. This
2704 is fixed-point integer DSP, son. No place for wimps. We do it in integer
2705 because you can count on integer being faster on most CPUs. We care
2706 about speed because we need to recalculate every time we blink text, and
2707 when we spew random bytes into screen memory. This is roughly 16.16
2708 fixed point arithmetic, but we scale some filter values up by a few bits
2709 to avoid some nasty precision errors. */
2711 /* Filter y at with a 4-pole low-pass Butterworth filter at 3.5 MHz
2712 with an extra zero at 3.5 MHz, from
2713 mkfilter -Bu -Lp -o 4 -a 2.1428571429e-01 0 -Z 2.5e-01 -l
2716 fyx[0] = fyx[1]; fyx[1] = fyx[2]; fyx[2] = fyx[3];
2717 fyx[3] = fyx[4]; fyx[4] = fyx[5]; fyx[5] = fyx[6];
2718 fyx[6] = (iny * 1897) >> 13;
2719 fyy[0] = fyy[1]; fyy[1] = fyy[2]; fyy[2] = fyy[3];
2720 fyy[3] = fyy[4]; fyy[4] = fyy[5]; fyy[5] = fyy[6];
2721 fyy[6] = (fyx[0]+fyx[6]) + 4*(fyx[1]+fyx[5]) + 7*(fyx[2]+fyx[4]) + 8*fyx[3]
2722 + ((-151*fyy[2] + 8115*fyy[3] - 38312*fyy[4] + 36586*fyy[5]) >> 16);
2723 if (i>=2) it->ntscy[i-2] = blank + (fyy[6]>>3);
2725 /* Filter I and Q at 1.5 MHz. 3 pole Butterworth from
2726 mkfilter -Bu -Lp -o 3 -a 1.0714285714e-01 0
2729 The NTSC spec says the Q value should be filtered at 0.5 MHz at the
2730 transmit end, But the Apple's video circuitry doesn't any such thing.
2731 AFAIK, oldish televisions (before comb filters) simply applied a 1.5 MHz
2732 filter to both after the demodulator.
2735 fix[0] = fix[1]; fix[1] = fix[2]; fix[2] = fix[3];
2736 fix[3] = (ini * 1413) >> 14;
2737 fiy[0] = fiy[1]; fiy[1] = fiy[2]; fiy[2] = fiy[3];
2738 fiy[3] = (fix[0]+fix[3]) + 3*(fix[1]+fix[2])
2739 + ((16559*fiy[0] - 72008*fiy[1] + 109682*fiy[2]) >> 16);
2740 if (i>=3) it->ntsci[i-3] = fiy[3]>>2;
2742 fqx[0] = fqx[1]; fqx[1] = fqx[2]; fqx[2] = fqx[3];
2743 fqx[3] = (inq * 1413) >> 14;
2744 fqy[0] = fqy[1]; fqy[1] = fqy[2]; fqy[2] = fqy[3];
2745 fqy[3] = (fqx[0]+fqx[3]) + 3*(fqx[1]+fqx[2])
2746 + ((16559*fqy[0] - 72008*fqy[1] + 109682*fqy[2]) >> 16);
2747 if (i>=3) it->ntscq[i-3] = fqy[3]>>2;
2750 for (; i<610; i++) {
2751 if (i-2<600) it->ntscy[i-2]=0;
2752 if (i-3<600) it->ntsci[i-3]=0;
2753 if (i-9<600) it->ntscq[i-9]=0;
2763 #define A2_CMAP_INDEX(COLORMODE, LEVEL, HIST, OFFSET) \
2764 ((((COLORMODE)*A2_CMAP_LEVELS+(LEVEL))<<A2_CMAP_HISTBITS)+(HIST))* \
2765 A2_CMAP_OFFSETS+(OFFSET)
2768 apple2(Display *dpy, Window window, int delay)
2770 int w,h,i,j,x,y,textrow,row,col,stepno,colormode,imgrow;
2772 struct timeval basetime_tv;
2773 double next_actiontime;
2774 XWindowAttributes xgwa;
2776 int screen_xo,screen_yo;
2780 XImage *text_im=NULL;
2781 unsigned long colors[A2_CMAP_INDEX(1, A2_CMAP_LEVELS-1,
2782 (1<<A2_CMAP_HISTBITS)-1,
2783 A2_CMAP_OFFSETS-3)+1];
2785 int screen_plan[24];
2786 struct ntsc_dec *dec=NULL;
2787 short *raw_rgb=NULL, *rrp;
2788 struct apple2_state *st=NULL;
2789 char *typing=NULL,*printing=NULL;
2790 char printbuf[1024];
2793 double tint_control,color_control,brightness_control,contrast_control;
2794 double freq_error=0.0,freq_error_inc=0.0;
2795 double horiz_desync=5.0;
2796 int flutter_horiz_desync=0;
2798 double crtload[192];
2799 int red_invprec,red_shift,green_invprec,green_shift,blue_invprec,blue_shift;
2800 int fillptr, fillbyte;
2801 int use_shm,use_cmap,use_color;
2802 /* localbyteorder is 1 if MSB first, 0 otherwise */
2803 unsigned int localbyteorder_loc = MSBFirst<<24;
2804 int localbyteorder=*(char *)&localbyteorder_loc;
2805 #ifdef HAVE_XSHM_EXTENSION
2806 XShmSegmentInfo shm_info;
2809 #ifdef HAVE_XSHM_EXTENSION
2810 use_shm=get_boolean_resource ("useSHM", "Boolean");
2815 /* Model the video controls on a standard television */
2816 tint_control = get_float_resource("apple2TVTint","Apple2TVTint");
2817 color_control = get_float_resource("apple2TVColor","Apple2TVColor")/100.0;
2818 brightness_control = get_float_resource("apple2TVBrightness",
2819 "Apple2TVBrightness") / 100.0;
2820 contrast_control = get_float_resource("apple2TVContrast",
2821 "Apple2TVContrast") / 100.0;
2822 simulate_user = get_boolean_resource("apple2SimulateUser",
2823 "Apple2SimulateUser");
2825 XGetWindowAttributes (dpy, window, &xgwa);
2826 visclass=xgwa.visual->class;
2827 red_shift=red_invprec=green_shift=green_invprec=blue_shift=blue_invprec=-1;
2828 if (visclass == TrueColor || xgwa.visual->class == DirectColor) {
2832 else if (visclass == PseudoColor || visclass == StaticColor) {
2841 /* The Apple II screen was 280x192, sort of. We expand the width to 300
2842 pixels to allow for overscan. We then pick a size within the window
2843 that's an integer multiple of 300x192. The small case happens when
2844 we're displaying in a subwindow. Then it ends up showing the center
2845 of the screen, which is OK. */
2847 h = (xgwa.height/192)*192;
2851 dec=(struct ntsc_dec *)malloc(sizeof(struct ntsc_dec));
2854 int hist,offset,level;
2859 /* Typically allocates 214 distinct colors, but will scale back its
2860 ambitions pretty far if it can't get them */
2861 for (colormode=0; colormode<=use_color; colormode++) {
2862 ntsc_set_demod(dec, tint_control, color_control, brightness_control,
2864 for (level=0; level<2; level++) {
2865 for (hist=0; hist<(1<<A2_CMAP_HISTBITS); hist++) {
2866 for (offset=0; offset<4; offset++) {
2867 int interpy,interpi,interpq,r,g,b;
2868 int levelmult=level ? 64 : 32;
2869 int prec=colormode ? colorprec : (colorprec*2+2)/3;
2870 int precmask=(0xffff<<(16-prec))&0xffff;
2873 if (A2_CMAP_INDEX(colormode,level,hist,offset) != n_colors) {
2874 fprintf(stderr, "apple2: internal colormap allocation error\n");
2878 for (i=0; i<600; i++) dec->pattern[i]=0;
2879 for (i=0; i<A2_CMAP_HISTBITS; i++) {
2880 dec->pattern[64+offset-i]=(hist>>i)&1;
2884 interpy=dec->ntscy[63+offset];
2885 interpi=dec->ntsci[63+offset];
2886 interpq=dec->ntscq[63+offset];
2888 r=(interpy + ((+68128*interpi+40894*interpq)>>16))*levelmult;
2889 g=(interpy + ((-18087*interpi-41877*interpq)>>16))*levelmult;
2890 b=(interpy + ((-72417*interpi+113312*interpq)>>16))*levelmult;
2892 if (r>65535) r=65535;
2894 if (g>65535) g=65535;
2896 if (b>65535) b=65535;
2898 col.red=r & precmask;
2899 col.green=g & precmask;
2900 col.blue=b & precmask;
2902 if (!XAllocColor(dpy, xgwa.colormap, &col)) {
2903 XFreeColors(dpy, xgwa.colormap, colors, n_colors, 0L);
2911 colors[n_colors++]=col.pixel;
2917 /* Is there a standard way to do this? Does this handle all cases? */
2919 for (shift=0; shift<32; shift++) {
2920 for (prec=1; prec<16 && prec<32-shift; prec++) {
2921 unsigned long mask=(0xffffUL>>(16-prec)) << shift;
2922 if (red_shift<0 && mask==xgwa.visual->red_mask)
2923 red_shift=shift, red_invprec=16-prec;
2924 if (green_shift<0 && mask==xgwa.visual->green_mask)
2925 green_shift=shift, green_invprec=16-prec;
2926 if (blue_shift<0 && mask==xgwa.visual->blue_mask)
2927 blue_shift=shift, blue_invprec=16-prec;
2930 if (red_shift<0 || green_shift<0 || blue_shift<0) {
2931 if (0) fprintf(stderr,"Can't figure out color space\n");
2934 raw_rgb=(short *)calloc(w*3, sizeof(short));
2938 gc = XCreateGC(dpy, window, GCBackground, &gcv);
2939 XSetWindowBackground(dpy, window, gcv.background);
2940 XClearWindow(dpy,window);
2942 screen_xo=(xgwa.width-w)/2;
2943 screen_yo=(xgwa.height-h)/2;
2946 #ifdef HAVE_XSHM_EXTENSION
2947 image = create_xshm_image (dpy, xgwa.visual, xgwa.depth, ZPixmap, 0,
2951 fprintf(stderr, "create_xshm_image failed\n");
2956 image = XCreateImage(dpy, xgwa.visual, xgwa.depth, ZPixmap, 0, 0,
2958 image->data = (char *)calloc(image->height, image->bytes_per_line);
2961 st=(struct apple2_state *)calloc(1,sizeof(struct apple2_state));
2964 Generate the font. It used a 5x7 font which looks a lot like the standard X
2965 6x10 font, with a few differences. So we render up all the uppercase
2966 letters of 6x10, and make a few tweaks (like putting a slash across the
2967 zero) according to fixfont.
2970 const char *def_font="6x10";
2975 font = XLoadQueryFont (dpy, def_font);
2977 fprintf(stderr,"Can't load font %s\n",def_font);
2981 text_pm=XCreatePixmap(dpy, window, 64*7, 8, xgwa.depth);
2986 gc=XCreateGC(dpy, text_pm, GCFont|GCBackground|GCForeground, &gcv);
2988 XSetForeground(dpy, gc, 0);
2989 XFillRectangle(dpy, text_pm, gc, 0, 0, 64*7, 8);
2990 XSetForeground(dpy, gc, 1);
2991 for (i=0; i<64; i++) {
2997 XDrawString(dpy, text_pm, gc, x, y, &c, 1);
2999 XDrawString(dpy, text_pm, gc, x, y, &c, 1);
3002 text_im = XGetImage(dpy, text_pm, 0, 0, 64*7, 8, ~0L, ZPixmap);
3004 XFreePixmap(dpy, text_pm);
3006 for (i=0; a2_fixfont[i]; i++) {
3007 XPutPixel(text_im, a2_fixfont[i]&0x3ff,
3008 (a2_fixfont[i]>>10)&0xf,
3009 (a2_fixfont[i]>>15)&1);
3014 Simulate plausible initial memory contents.
3018 while (addr<0x4000) {
3021 switch (random()%4) {
3025 for (i=0; i<n && addr<0x4000; i++) {
3026 u_char rb=((random()%6==0 ? 0 : random()%16) |
3027 ((random()%5==0 ? 0 : random()%16)<<4));
3028 a2_poke(st, addr++, rb);
3033 /* Simulate shapes stored in memory. We use the font since we have it.
3034 Unreadable, since rows of each character are stored in consecutive
3035 bytes. It was typical to store each of the 7 possible shifts of
3036 bitmaps, for fastest blitting to the screen. */
3037 x=random()%(text_im->width);
3038 for (i=0; i<100; i++) {
3039 for (y=0; y<8; y++) {
3041 for (j=0; j<8; j++) {
3042 c |= XGetPixel(text_im, (x+j)%text_im->width, y)<<j;
3044 a2_poke(st, addr++, c);
3046 x=(x+1)%(text_im->width);
3053 for (i=0; i<n && addr<0x4000; i++) {
3054 a2_poke(st, addr++, 0);
3063 if (random()%4==0 &&
3064 !use_cmap && use_color &&
3065 xgwa.visual->bits_per_rgb>=8) {
3068 else if (random()%3==0) {
3069 flutter_horiz_desync=1;
3075 gettimeofday(&basetime_tv, NULL);
3076 if (random()%2==0) basetime_tv.tv_sec -= 1; /* random blink phase */
3077 next_actiontime=0.0;
3080 double curtime,blinkphase;
3081 int startdisplayrow=0;
3085 struct timeval curtime_tv;
3086 gettimeofday(&curtime_tv, NULL);
3087 curtime=(curtime_tv.tv_sec - basetime_tv.tv_sec) +
3088 0.000001*(curtime_tv.tv_usec - basetime_tv.tv_usec);
3090 if (curtime>delay) goto finished;
3092 if (bsod_sleep(dpy,0)) goto finished;
3094 if (flutter_tint && st->gr_mode && !printing) {
3095 /* Oscillator instability. Look for freq_error below. We should only do
3096 this with color depth>=8, since otherwise you see pixels changing. */
3097 freq_error_inc += (-0.10*freq_error_inc
3098 + ((int)(random()&0xff)-0x80) * 0.01);
3099 freq_error += freq_error_inc;
3103 else if (flutter_horiz_desync) {
3104 /* Horizontal sync during vertical sync instability. */
3105 horiz_desync += (-0.10*(horiz_desync-3.0) +
3106 ((int)(random()&0xff)-0x80) *
3107 ((int)(random()&0xff)-0x80) *
3108 ((int)(random()&0xff)-0x80) * 0.0000003);
3109 for (i=0; i<3; i++) st->rowimage[i]=-1;
3113 /* It's super-important to get the cursor/text flash out at exactly the
3114 right time, or it looks wrong. So if we're almost due for a blink, wait
3115 for it so we don't miss it in the middle of a screen update. */
3116 blinkphase=curtime/0.8;
3117 if (blinkphase-floor(blinkphase)>0.7 && !printing && !nodelay) {
3118 /* We're about to blink */
3119 int delay = ((1.0-(blinkphase-floor(blinkphase)))*0.8) * 1000000;
3120 if (delay<1000) delay=1000;
3125 /* The blinking rate was controlled by 555 timer with a resistor/capacitor
3126 time constant. Because the capacitor was electrolytic, the flash rate
3127 varied somewhat between machines. I'm guessing 1.6 seconds/cycle was
3128 reasonable. (I soldered a resistor in mine to make it blink faster.) */
3130 st->blink=((int)blinkphase)&1;
3131 if (st->blink!=i && !(st->gr_mode&A2_GR_FULL)) {
3133 /* For every row with blinking text, set the changed flag. This basically
3134 works great except with random screen garbage in text mode, when we
3135 end up redrawing the whole screen every second */
3136 for (row=(st->gr_mode ? 20 : 0); row<24; row++) {
3137 for (col=0; col<40; col++) {
3138 c=st->textlines[row][col];
3139 if ((c & 0xc0) == 0x40) {
3144 if (downcounter>0) {
3145 st->rowimage[row]=-1;
3149 st->rowimage[st->cursy]=-1;
3150 startdisplayrow=random()%24;
3152 else if (next_actiontime > curtime && !printing && !nodelay) {
3153 int delay = (next_actiontime-curtime)*1000000;
3155 if (delay>100000) delay=100000;
3156 if (delay<1000) delay=1000;
3164 if (*printing=='\001') { /* pause */
3166 for (i=20; i<24; i++) st->rowimage[i]=-1;
3169 else if (*printing=='\n') {
3170 a2_printc(st,*printing);
3175 a2_printc(st,*printing);
3179 if (!*printing) printing=NULL;
3181 else if (curtime >= next_actiontime) {
3183 /* If we're in the midst of typing a string, emit a character with
3185 a2_printc(st, *typing);
3186 if (*typing=='\n') {
3187 next_actiontime = curtime;
3189 next_actiontime = curtime + (random()%1000)*0.0003 + 0.3;
3193 if (!*typing) typing=NULL;
3197 next_actiontime=curtime;
3204 For testing color rendering. The spec is:
3212 6 med blue 20 207 253
3213 7 lt blue 208 195 255
3218 12 lt green 20 245 60
3219 13 yellow 208 221 141
3221 15 white 255 255 255
3223 st->gr_mode=A2_GR_LORES;
3224 for (row=0; row<24; row++) {
3225 for (col=0; col<40; col++) {
3226 st->textlines[row][col]=(row&15)*17;
3229 next_actiontime+=0.4;
3232 else if (random()%3==0) {
3234 next_actiontime+=0.4;
3237 else if (random()%4==0) {
3238 st->gr_mode=A2_GR_LORES;
3239 if (random()%3==0) st->gr_mode |= A2_GR_FULL;
3240 next_actiontime+=0.4;
3243 else if (random()%2==0) {
3244 st->gr_mode=A2_GR_HIRES;
3248 st->gr_mode=A2_GR_HIRES;
3249 next_actiontime+=0.4;
3255 /* An illegal instruction or a reset caused it to drop into the
3256 assembly language monitor, where you could disassemble code & view
3258 if (random()%3==0) {
3261 int addr=0xd000+random()%0x3000;
3263 "%02X",random()%0xff);
3269 " A=%02X X=%02X Y=%02X S=%02X F=%02X\n"
3272 random()%0xff, random()%0xff,
3273 random()%0xff, random()%0xff,
3283 next_actiontime += 2.0 + (random()%1000)*0.0002;
3286 /* Lots of programs had at least their main functionality in
3287 Applesoft Basic, which had a lot of limits (memory, string
3288 length, etc) and would sometimes crash unexpectedly. */
3295 apple2_basic_errors[random() %
3296 (sizeof(apple2_basic_errors)
3298 (1000*(random()%(random()%59+1)) +
3299 100*(random()%(random()%9+1)) +
3300 5*(random()%(random()%199+1)) +
3301 1*(random()%(random()%(random()%2+1)+1))));
3306 next_actiontime += 2.0 + (random()%1000)*0.0002;
3311 if (simulate_user && random()%3==0) {
3312 /* This was how you reset the Basic interpreter. The sort of
3313 incantation you'd have on a little piece of paper taped to the
3314 side of your machine */
3315 typing="CALL -1370";
3318 else if (simulate_user && random()%2==0) {
3323 next_actiontime+=1.0;
3330 next_actiontime += 0.5;
3337 for (s="APPLE ]["; *s; s++) a2_printc(st,*s);
3340 next_actiontime+=1.0;
3345 if (simulate_user && random()%50==0 && 0) { /* disabled, too goofy */
3346 typing="10 PRINT \"TRS-80S SUCK!!!\"\n"
3353 next_actiontime += delay;
3358 for (i=0; i<30; i++) {
3359 for (s="\nTRS-80S SUCK"; *s; s++) a2_printc(st,*s);
3362 next_actiontime+=delay;
3368 if (random()%50==0) {
3369 sprintf(printbuf,"\nDISK VOLUME 254\n\n"
3376 sprintf(printbuf,"\n?%s\n]",
3377 apple2_dos_errors[random()%
3378 (sizeof(apple2_dos_errors) /
3383 next_actiontime+=1.0;
3387 if (simulate_user && random()%2==0) {
3388 /* This was how you went back to text mode in the monitor */
3392 next_actiontime+=1.0;
3403 next_actiontime+=2.0;
3407 /* This reset things into Basic */
3408 if (simulate_user && random()%2==0) {
3414 next_actiontime+=delay;
3419 for (i=0; i<1500; i++) {
3420 a2_poke(st, fillptr, fillbyte);
3422 fillbyte = (fillbyte+1)&0xff;
3424 next_actiontime += 0.08;
3425 /* When you hit c000, it changed video settings */
3426 if (fillptr>=0xc000) {
3430 /* And it seemed to reset around here, I dunno why */
3431 if (fillptr>=0xcf00) stepno=3;
3437 /* Now, we turn the data in the Apple II video into a screen display. This
3438 is interesting because of the interaction with the NTSC color decoding
3439 in a color television. */
3441 colormode=use_color && st->gr_mode!=0;
3443 ntsc_set_demod(dec, tint_control, color_control, brightness_control,
3444 freq_error, colormode);
3447 for (textrow=0; textrow<24; textrow++) {
3448 if (st->rowimage[textrow] == textrow) {
3449 screen_plan[textrow]=0;
3451 else if (cheapdisplay && st->rowimage[textrow]>=0 &&
3452 textrow<21 && st->rowimage[textrow]<21 &&
3453 st->rowimage[textrow]>=2 && textrow>=2 &&
3454 (st->rowimage[textrow]+1)*h/24 + screen_xo <= xgwa.height) {
3455 screen_plan[textrow]= A2_SP_COPY | st->rowimage[textrow];
3456 for (i=0; i<8; i++) {
3457 crtload[textrow*8+i]=crtload[st->rowimage[textrow]*8+i];
3462 st->rowimage[textrow]=imgrow;
3463 screen_plan[textrow]=imgrow | A2_SP_PUT;
3465 for (row=textrow*8; row<textrow*8+8; row++) {
3467 int pixmultinc,pixbright;
3468 int scanstart_i, scanend_i;
3469 int squishright_i, squishdiv;
3471 double bloomthisrow,shiftthisrow;
3472 int ytop=(imgrow*h/24) + ((row-textrow*8) * h/192);
3473 int ybot=ytop+h/192;
3475 /* First we generate the pattern that the video circuitry shifts out
3476 of memory. It has a 14.something MHz dot clock, equal to 4 times
3477 the color burst frequency. So each group of 4 bits defines a
3478 color. Each character position, or byte in hires, defines 14
3479 dots, so odd and even bytes have different color spaces. So,
3480 pattern[0..600] gets the dots for one scan line. */
3482 memset(dec->pattern,0,sizeof(dec->pattern));
3485 if ((st->gr_mode&A2_GR_HIRES) && (row<160 ||
3486 (st->gr_mode&A2_GR_FULL))) {
3488 /* Emulate the mysterious pink line, due to a bit getting
3489 stuck in a shift register between the end of the last
3490 row and the beginning of this one. */
3491 if ((st->hireslines[row][0] & 0x80) &&
3492 (st->hireslines[row][39]&0x40)) {
3496 for (col=0; col<40; col++) {
3497 u_char b=st->hireslines[row][col];
3498 int shift=(b&0x80)?0:1;
3500 /* Each of the low 7 bits in hires mode corresponded to 2 dot
3501 clocks, shifted by one if the high bit was set. */
3502 for (i=0; i<7; i++) {
3503 pp[shift+1] = pp[shift] =(b>>i)&1;
3508 else if ((st->gr_mode&A2_GR_LORES) && (row<160 ||
3509 (st->gr_mode&A2_GR_FULL))) {
3510 for (col=0; col<40; col++) {
3511 u_char nib=(st->textlines[textrow][col] >> (((row/4)&1)*4))&0xf;
3512 /* The low or high nybble was shifted out one bit at a time. */
3513 for (i=0; i<14; i++) {
3514 *pp = (nib>>((col*14+i)&3))&1;
3520 for (col=0; col<40; col++) {
3522 c=st->textlines[textrow][col];
3523 /* hi bits control inverse/blink as follows:
3528 rev=!(c&0x80) && (!(c&0x40) || st->blink);
3530 for (i=0; i<7; i++) {
3531 for (i=0; i<7; i++) {
3532 unsigned long pix=XGetPixel(text_im,
3533 ((c&0x3f)^0x20)*7+i, row%8);
3534 pp[1] = pp[2] = pix^rev;
3542 Interpolate the 600-dotclock line into however many horizontal
3543 screen pixels we're using, and convert to RGB.
3545 We add some 'bloom', variations in the horizontal scan width with
3546 the amount of brightness, extremely common on period TV sets. They
3547 had a single oscillator which generated both the horizontal scan
3548 and (during the horizontal retrace interval) the high voltage for
3549 the electron beam. More brightness meant more load on the
3550 oscillator, which caused an decrease in horizontal deflection. Look
3553 Also, the A2 did a bad job of generating horizontal sync pulses
3554 during the vertical blanking interval. This, and the fact that the
3555 horizontal frequency was a bit off meant that TVs usually went a
3556 bit out of sync during the vertical retrace, and the top of the
3557 screen would be bent a bit to the left or right. Look for
3560 We also add a teeny bit of left overscan, just enough to be
3561 annoying, but you can still read the left column of text.
3563 We also simulate compression & brightening on the right side of the
3564 screen. Most TVs do this, but you don't notice because they
3565 overscan so it's off the right edge of the CRT. But the A2 video
3566 system used so much of the horizontal scan line that you had to
3567 crank the horizontal width down in order to not lose the right few
3568 characters, and you'd see the compression on the right
3569 edge. Associated with compression is brightening; since the
3570 electron beam was scanning slower, the same drive signal hit the
3571 phosphor harder. Look for (squishright_i) and (squishdiv).
3574 for (i=j=0; i<600; i++) {
3575 j += dec->pattern[i];
3577 crtload[row] = (crtload[row>1 ? row-1 : 0]) * 0.98 + 0.02*(j/600.0) +
3578 (row>180 ? (row-180)*(row-180)*0.0005 : 0.0);
3579 bloomthisrow = -10.0 * crtload[row];
3580 shiftthisrow=((row<18) ? ((18-row)*(18-row)* 0.002 + (18-row)*0.05)
3581 * horiz_desync : 0.0);
3583 scanstart_i=(int)((bloomthisrow+shiftthisrow+18.0)*65536.0);
3584 if (scanstart_i<0) scanstart_i=0;
3585 if (scanstart_i>30*65536) scanstart_i=30*65536;
3586 scanend_i=599*65536;
3587 squishright_i=scanstart_i + 530*65536;
3589 pixrate=(int)((560.0-2.0*bloomthisrow)*65536.0/w);
3592 for (y=ytop; y<ybot; y++) {
3593 int level=(!(y==ytop && ybot-ytop>=3) &&
3594 !(y==ybot-1 && ybot-ytop>=5));
3599 for (x=0, i=scanstart_i;
3601 x++, i+=pixmultinc) {
3604 while (pati>=histi) {
3605 hist=(((hist<<1) & ((1<<A2_CMAP_HISTBITS)-1)) |
3606 dec->pattern[histi]);
3609 XPutPixel(image, x, y,
3610 colors[A2_CMAP_INDEX(colormode,level,hist,offset)]);
3611 if (i >= squishright_i) {
3612 pixmultinc += pixmultinc/squishdiv;
3616 XPutPixel(image, x, y, colors[0]);
3623 pixbright=(int)(contrast_control*65536.0);
3625 for (x=0, i=scanstart_i, rrp=raw_rgb;
3627 x++, i+=pixmultinc, rrp+=3) {
3628 int pixfrac=i&0xffff;
3629 int invpixfrac=65536-pixfrac;
3633 int interpy=((dec->ntscy[pati]*invpixfrac +
3634 dec->ntscy[pati+1]*pixfrac)>>16);
3635 int interpi=((dec->ntsci[pati]*invpixfrac +
3636 dec->ntsci[pati+1]*pixfrac)>>16);
3637 int interpq=((dec->ntscq[pati]*invpixfrac +
3638 dec->ntscq[pati+1]*pixfrac)>>16);
3641 According to the NTSC spec, Y,I,Q are generated as:
3643 y=0.30 r + 0.59 g + 0.11 b
3644 i=0.60 r - 0.28 g - 0.32 b
3645 q=0.21 r - 0.52 g + 0.31 b
3647 So if you invert the implied 3x3 matrix you get what standard
3648 televisions implement with a bunch of resistors (or directly in
3649 the CRT -- don't ask):
3651 r = y + 0.948 i + 0.624 q
3652 g = y - 0.276 i - 0.639 q
3653 b = y - 1.105 i + 1.729 q
3655 These coefficients are below in 16.16 format.
3658 r=((interpy + ((+68128*interpi+40894*interpq)>>16))*pixbright)
3660 g=((interpy + ((-18087*interpi-41877*interpq)>>16))*pixbright)
3662 b=((interpy + ((-72417*interpi+113312*interpq)>>16))*pixbright)
3671 if (i>=squishright_i) {
3672 pixmultinc += pixmultinc/squishdiv;
3673 pixbright += pixbright/squishdiv;
3676 for ( ; x<w; x++, rrp+=3) {
3677 rrp[0]=rrp[1]=rrp[2]=0;
3680 for (y=ytop; y<ybot; y++) {
3681 /* levelmult represents the vertical size of scan lines. Each
3682 line is brightest in the middle, and there's a dark band
3685 double levelmult_fp=(y + 0.5 - (ytop+ybot)*0.5) / (ybot-ytop);
3686 levelmult_fp = 1.0-(levelmult_fp*levelmult_fp*levelmult_fp
3687 *levelmult_fp)*16.0;
3688 if (levelmult_fp<0.0) levelmult_fp=0.0;
3689 levelmult = (int)(64.9*levelmult_fp);
3691 /* Fast special cases to avoid the slow XPutPixel. Ugh. It goes
3692 to show why standard graphics sw has to be fast, or else
3693 people will have to work around it and risk incompatibility.
3694 The quickdraw folks understood this. The other answer would
3695 be for X11 to have fewer formats for bitm.. oh, never
3696 mind. If neither of these cases work (they probably cover 99%
3697 of setups) it falls back on the Xlib routines. */
3698 if (image->format==ZPixmap && image->bits_per_pixel==32 &&
3699 sizeof(unsigned long)==4 &&
3700 image->byte_order==localbyteorder) {
3701 unsigned long *pixelptr =
3702 (unsigned long *) (image->data + y * image->bytes_per_line);
3703 for (x=0, rrp=raw_rgb; x<w; x++, rrp+=3) {
3704 unsigned long ntscri, ntscgi, ntscbi;
3705 ntscri=((unsigned long)rrp[0])*levelmult;
3706 ntscgi=((unsigned long)rrp[1])*levelmult;
3707 ntscbi=((unsigned long)rrp[2])*levelmult;
3708 if (ntscri>65535) ntscri=65535;
3709 if (ntscgi>65535) ntscgi=65535;
3710 if (ntscbi>65535) ntscbi=65535;
3711 *pixelptr++ = ((ntscri>>red_invprec)<<red_shift) |
3712 ((ntscgi>>green_invprec)<<green_shift) |
3713 ((ntscbi>>blue_invprec)<<blue_shift);
3716 else if (image->format==ZPixmap && image->bits_per_pixel==16 &&
3717 sizeof(unsigned short)==2 &&
3718 image->byte_order==localbyteorder) {
3719 unsigned short *pixelptr =
3720 (unsigned short *)(image->data + y*image->bytes_per_line);
3721 for (x=0, rrp=raw_rgb; x<w; x++, rrp+=3) {
3722 unsigned long ntscri, ntscgi, ntscbi;
3723 ntscri=((unsigned long)rrp[0])*levelmult;
3724 ntscgi=((unsigned long)rrp[1])*levelmult;
3725 ntscbi=((unsigned long)rrp[2])*levelmult;
3726 if (ntscri>65535) ntscri=65535;
3727 if (ntscgi>65535) ntscgi=65535;
3728 if (ntscbi>65535) ntscbi=65535;
3729 *pixelptr++ = ((ntscri>>red_invprec)<<red_shift) |
3730 ((ntscgi>>green_invprec)<<green_shift) |
3731 ((ntscbi>>blue_invprec)<<blue_shift);
3736 for (x=0, rrp=raw_rgb; x<w; x++, rrp+=3) {
3737 unsigned long pixel, ntscri, ntscgi, ntscbi;
3738 /* Convert to 16-bit color values, with saturation. The ntscr
3739 values are 22.10 fixed point, and levelmult is 24.6, so we
3741 ntscri=((unsigned long)rrp[0])*levelmult;
3742 ntscgi=((unsigned long)rrp[1])*levelmult;
3743 ntscbi=((unsigned long)rrp[2])*levelmult;
3744 if (ntscri>65535) ntscri=65535;
3745 if (ntscgi>65535) ntscgi=65535;
3746 if (ntscbi>65535) ntscbi=65535;
3747 pixel = ((ntscri>>red_invprec)<<red_shift) |
3748 ((ntscgi>>green_invprec)<<green_shift) |
3749 ((ntscbi>>blue_invprec)<<blue_shift);
3750 XPutPixel(image, x, y, pixel);
3760 /* For just the the rows which changed, blit the image to the screen. */
3761 for (textrow=0; textrow<24; ) {
3762 int top,bot,srcrow,srctop,nrows;
3765 while (textrow+nrows < 24 &&
3766 screen_plan[textrow+nrows] == screen_plan[textrow]+nrows)
3770 bot=h*(textrow+nrows)/24;
3771 srcrow=screen_plan[textrow]&A2_SP_ROWMASK;
3774 if (screen_plan[textrow] & A2_SP_COPY) {
3775 if (0) printf("Copy %d screenrows %d to %d\n", nrows, srcrow, textrow);
3776 XCopyArea(dpy, window, window, gc,
3777 screen_xo, screen_yo + srctop,
3779 screen_xo, screen_yo + top);
3781 else if (screen_plan[textrow] & A2_SP_PUT) {
3782 if (0) printf("Draw %d imgrows %d to %d\n", nrows, srcrow, textrow);
3784 #ifdef HAVE_XSHM_EXTENSION
3785 XShmPutImage(dpy, window, gc, image,
3786 0, srctop, screen_xo, screen_yo + top,
3790 XPutImage(dpy, window, gc, image,
3792 screen_xo, screen_yo + top,
3800 for (textrow=0; textrow<24; textrow++) {
3801 st->rowimage[textrow]=textrow;
3807 XClearWindow(dpy, window);
3816 #ifdef HAVE_XSHM_EXTENSION
3817 destroy_xshm_image(dpy, image, &shm_info);
3820 XDestroyImage(image);
3824 if (text_im) XDestroyImage(text_im);
3825 if (gc) XFreeGC(dpy, gc);
3827 if (raw_rgb) free(raw_rgb);
3829 if (n_colors) XFreeColors(dpy, xgwa.colormap, colors, n_colors, 0L);
3834 char *progclass = "BSOD";
3836 char *defaults [] = {
3849 "*doAtari: False", /* boring */
3850 "*doBSD: False", /* boring */
3852 "*doSparcLinux: False", /* boring */
3853 "*doBlitDamage: True",
3858 ".Windows.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3859 ".Windows.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
3860 ".Windows.foreground: White",
3861 ".Windows.background: #0000AA", /* EGA color 0x01. */
3863 ".Amiga.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3864 ".Amiga.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
3865 ".Amiga.foreground: Red",
3866 ".Amiga.background: Black",
3867 ".Amiga.background2: White",
3869 ".Mac.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3870 ".Mac.foreground: PaleTurquoise1",
3871 ".Mac.background: Black",
3873 ".Atari.foreground: Black",
3874 ".Atari.background: White",
3876 ".MacsBug.font: -*-courier-medium-r-*-*-*-100-*-*-m-*-*-*",
3877 ".MacsBug.font2: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3878 ".MacsBug.font3: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3879 ".MacsBug.foreground: Black",
3880 ".MacsBug.background: White",
3881 ".MacsBug.borderColor: #AAAAAA",
3883 ".mac1.foreground: Black",
3884 ".mac1.background: White",
3886 ".macX.textForeground: White",
3887 ".macX.textBackground: Black",
3888 ".macX.background: #888888",
3889 ".macX.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3890 ".macX.font2: -*-courier-bold-r-*-*-*-240-*-*-m-*-*-*",
3892 ".SCO.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3893 ".SCO.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3894 ".SCO.foreground: White",
3895 ".SCO.background: Black",
3897 ".Linux.font: 9x15bold",
3898 ".Linux.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3899 ".Linux.foreground: White",
3900 ".Linux.background: Black",
3902 ".SparcLinux.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3903 ".SparcLinux.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3904 ".SparcLinux.foreground: White",
3905 ".SparcLinux.background: Black",
3908 ".BSD.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3909 ".BSD.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3910 /* ".BSD.font2: -sun-console-medium-r-*-*-22-*-*-*-m-*-*-*", */
3911 ".BSD.foreground: #c0c0c0",
3912 ".BSD.background: Black",
3914 ".Solaris.font: -sun-gallant-*-*-*-*-19-*-*-*-*-120-*-*",
3915 ".Solaris.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3916 ".Solaris.foreground: Black",
3917 ".Solaris.background: White",
3918 "*dontClearRoot: True",
3920 ".HPUX.font: 9x15bold",
3921 ".HPUX.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3922 ".HPUX.foreground: Black",
3923 ".HPUX.background: White",
3925 ".OS390.font: 9x15bold",
3926 ".OS390.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
3927 ".OS390.background: Black",
3928 ".OS390.foreground: Red",
3930 "*apple2TVColor: 50",
3932 "*apple2TVBrightness: 10",
3933 "*apple2TVContrast: 90",
3934 "*apple2SimulateUser: True",
3936 #ifdef HAVE_XSHM_EXTENSION
3942 XrmOptionDescRec options [] = {
3943 { "-delay", ".delay", XrmoptionSepArg, 0 },
3944 { "-only", ".doOnly", XrmoptionSepArg, 0 },
3945 { "-windows", ".doWindows", XrmoptionNoArg, "True" },
3946 { "-no-windows", ".doWindows", XrmoptionNoArg, "False" },
3947 { "-nt", ".doNT", XrmoptionNoArg, "True" },
3948 { "-no-nt", ".doNT", XrmoptionNoArg, "False" },
3949 { "-2k", ".doWin2K", XrmoptionNoArg, "True" },
3950 { "-no-2k", ".doWin2K", XrmoptionNoArg, "False" },
3951 { "-amiga", ".doAmiga", XrmoptionNoArg, "True" },
3952 { "-no-amiga", ".doAmiga", XrmoptionNoArg, "False" },
3953 { "-mac", ".doMac", XrmoptionNoArg, "True" },
3954 { "-no-mac", ".doMac", XrmoptionNoArg, "False" },
3955 { "-mac1", ".doMac1", XrmoptionNoArg, "True" },
3956 { "-no-mac1", ".doMac1", XrmoptionNoArg, "False" },
3957 { "-macx", ".doMacX", XrmoptionNoArg, "True" },
3958 { "-no-macx", ".doMacX", XrmoptionNoArg, "False" },
3959 { "-atari", ".doAtari", XrmoptionNoArg, "True" },
3960 { "-no-atari", ".doAtari", XrmoptionNoArg, "False" },
3961 { "-macsbug", ".doMacsBug", XrmoptionNoArg, "True" },
3962 { "-no-macsbug", ".doMacsBug", XrmoptionNoArg, "False" },
3963 { "-apple2", ".doApple2", XrmoptionNoArg, "True" },
3964 { "-no-apple2", ".doApple2", XrmoptionNoArg, "False" },
3965 { "-sco", ".doSCO", XrmoptionNoArg, "True" },
3966 { "-no-sco", ".doSCO", XrmoptionNoArg, "False" },
3967 { "-bsd", ".doBSD", XrmoptionNoArg, "True" },
3968 { "-no-bsd", ".doBSD", XrmoptionNoArg, "False" },
3969 { "-linux", ".doLinux", XrmoptionNoArg, "True" },
3970 { "-no-linux", ".doLinux", XrmoptionNoArg, "False" },
3971 { "-sparclinux", ".doSparcLinux", XrmoptionNoArg, "True" },
3972 { "-no-sparclinux", ".doSparcLinux", XrmoptionNoArg, "False" },
3973 { "-blitdamage", ".doBlitDamage", XrmoptionNoArg, "True" },
3974 { "-no-blitdamage", ".doBlitDamage", XrmoptionNoArg, "False" },
3975 { "-solaris", ".doSolaris", XrmoptionNoArg, "True" },
3976 { "-no-solaris", ".doSolaris", XrmoptionNoArg, "False" },
3977 { "-hpux", ".doHPUX", XrmoptionNoArg, "True" },
3978 { "-no-hpux", ".doHPUX", XrmoptionNoArg, "False" },
3979 { "-os390", ".doOS390", XrmoptionNoArg, "True" },
3980 { "-no-os390", ".doOS390", XrmoptionNoArg, "False" },
3987 void (*fn) (Display *, Window, int delay);
3989 { "Windows", windows_31 },
3990 { "Nt", windows_nt },
3991 { "2k", windows_2k },
3994 { "MacsBug", macsbug },
3998 { "SparcLinux", sparc_linux },
4001 { "BlitDamage", blitdamage },
4002 { "Solaris", sparc_solaris },
4003 { "Linux", linux_fsck },
4006 { "Apple2", apple2 },
4011 screenhack (Display *dpy, Window window)
4017 int delay = get_integer_resource ("delay", "Integer");
4018 if (delay < 3) delay = 3;
4021 char *s = get_string_resource("doOnly", "DoOnly");
4024 int count = countof(all_modes);
4025 for (only = 0; only < count; only++)
4026 if (!strcasecmp (s, all_modes[only].name))
4030 fprintf (stderr, "%s: unknown -only mode: \"%s\"\n", progname, s);
4037 if (!get_boolean_resource ("root", "Boolean"))
4039 XWindowAttributes xgwa;
4040 XGetWindowAttributes (dpy, window, &xgwa);
4041 XSelectInput (dpy, window,
4042 xgwa.your_event_mask | KeyPressMask | ButtonPressMask);
4048 int count = countof(all_modes);
4049 char name[100], class[100];
4054 do { i = (random() & 0xFF) % count; } while (i == j);
4056 sprintf (name, "do%s", all_modes[i].name);
4057 sprintf (class, "Do%s", all_modes[i].name);
4060 if (only > 0 || get_boolean_resource(name, class))
4062 all_modes[i].fn (dpy, window, delay);
4067 if (loop > 100) j = -1;
4070 fprintf (stderr, "%s: no display modes enabled?\n", progname);