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"
23 #include <X11/Xutil.h>
25 #ifdef HAVE_XSHM_EXTENSION
30 # include <sys/utsname.h>
31 #endif /* HAVE_UNAME */
33 #include "images/amiga.xpm"
34 #include "images/atari.xbm"
35 #include "images/mac.xbm"
36 #include "images/macbomb.xbm"
37 #include "images/hmac.xpm"
40 #define countof(x) (sizeof((x))/sizeof((*x)))
43 draw_string (Display *dpy, Window window, GC gc, XGCValues *gcv,
46 int win_width, int win_height,
47 const char *string, int delay)
50 int width = 0, height = 0, cw = 0;
51 int char_width, line_height;
53 const char *s = string;
54 const char *se = string;
56 /* This pretty much assumes fixed-width fonts */
57 char_width = (font->per_char
58 ? font->per_char['n'-font->min_char_or_byte2].width
59 : font->min_bounds.width);
60 line_height = font->ascent + font->descent + 1;
64 if (*s == '\n' || !*s)
67 if (cw > width) width = cw;
76 x = (win_width - (width * char_width)) / 2;
77 y = (win_height - (height * line_height)) / 2;
88 if (*s == '\n' || !*s)
93 if (*se == '@' || *se == '_')
95 if (*se == '@') flip = True;
97 off = (char_width * (width - (s - se))) / 2;
102 XSetForeground(dpy, gc, gcv->background);
103 XSetBackground(dpy, gc, gcv->foreground);
107 XDrawImageString(dpy, window, gc, x+off, y+font->ascent, se, s-se);
111 XSetForeground(dpy, gc, gcv->foreground);
112 XSetBackground(dpy, gc, gcv->background);
129 return width * char_width;
134 double_pixmap(Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap,
135 int pix_w, int pix_h)
138 Pixmap p2 = XCreatePixmap(dpy, pixmap, pix_w*2, pix_h*2, depth);
139 XImage *i1 = XGetImage(dpy, pixmap, 0, 0, pix_w, pix_h, ~0L, ZPixmap);
140 XImage *i2 = XCreateImage(dpy, visual, depth, ZPixmap, 0, 0,
141 pix_w*2, pix_h*2, 8, 0);
142 i2->data = (char *) calloc(i2->height, i2->bytes_per_line);
143 for (y = 0; y < pix_h; y++)
144 for (x = 0; x < pix_w; x++)
146 unsigned long p = XGetPixel(i1, x, y);
147 XPutPixel(i2, x*2, y*2, p);
148 XPutPixel(i2, x*2+1, y*2, p);
149 XPutPixel(i2, x*2, y*2+1, p);
150 XPutPixel(i2, x*2+1, y*2+1, p);
152 free(i1->data); i1->data = 0;
154 XPutImage(dpy, p2, gc, i2, 0, 0, 0, 0, i2->width, i2->height);
155 free(i2->data); i2->data = 0;
157 XFreePixmap(dpy, pixmap);
162 /* Sleep for N seconds and return False. But if a key or mouse event is
163 seen, discard all pending key or mouse events, and return True.
166 bsod_sleep(Display *dpy, int seconds)
169 int quantum = 250000;
172 q = 1, quantum = 100000;
177 while (XPending (dpy))
180 XNextEvent (dpy, &event);
181 if (event.xany.type == ButtonPress)
183 if (event.xany.type == KeyPress)
187 XLookupString (&event.xkey, &c, 1, &keysym, 0);
188 if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
191 screenhack_handle_event (dpy, &event);
207 windows (Display *dpy, Window window, int delay, int which)
210 XWindowAttributes xgwa;
212 const char *def_font = "fixed";
218 "A fatal exception 0E has occured at F0AD:42494C4C\n"
219 "the current application will be terminated.\n"
221 "* Press any key to terminate the current application.\n"
222 "* Press CTRL+ALT+DELETE again to restart your computer.\n"
223 " You will lose any unsaved information in all applications.\n"
226 "_Press any key to continue");
229 __extension__ /* don't warn about "string length is greater than the
230 length ISO C89 compilers are required to support"
231 in the following string constant... */
234 const char *wnt = /* from Jim Niemira <urmane@urmane.org> */
235 ("*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n"
236 "Unhandled Kernel exception c0000047 from fa8418b4 (8025ea21,fd6829e8)\n"
238 "Dll Base Date Stamp - Name Dll Base Date Stamp - Name\n"
239 "80100000 2be154c9 - ntoskrnl.exe 80400000 2bc153b0 - hal.dll\n"
240 "80258000 2bd49628 - ncrc710.sys 8025c000 2bd49688 - SCSIPORT.SYS \n"
241 "80267000 2bd49683 - scsidisk.sys 802a6000 2bd496b9 - Fastfat.sys\n"
242 "fa800000 2bd49666 - Floppy.SYS fa810000 2bd496db - Hpfs_Rec.SYS\n"
243 "fa820000 2bd49676 - Null.SYS fa830000 2bd4965a - Beep.SYS\n"
244 "fa840000 2bdaab00 - i8042prt.SYS fa850000 2bd5a020 - SERMOUSE.SYS\n"
245 "fa860000 2bd4966f - kbdclass.SYS fa870000 2bd49671 - MOUCLASS.SYS\n"
246 "fa880000 2bd9c0be - Videoprt.SYS fa890000 2bd49638 - NCC1701E.SYS\n"
247 "fa8a0000 2bd4a4ce - Vga.SYS fa8b0000 2bd496d0 - Msfs.SYS\n"
248 "fa8c0000 2bd496c3 - Npfs.SYS fa8e0000 2bd496c9 - Ntfs.SYS\n"
249 "fa940000 2bd496df - NDIS.SYS fa930000 2bd49707 - wdlan.sys\n"
250 "fa970000 2bd49712 - TDI.SYS fa950000 2bd5a7fb - nbf.sys\n"
251 "fa980000 2bd72406 - streams.sys fa9b0000 2bd4975f - ubnb.sys\n"
252 "fa9c0000 2bd5bfd7 - usbser.sys fa9d0000 2bd4971d - netbios.sys\n"
253 "fa9e0000 2bd49678 - Parallel.sys fa9f0000 2bd4969f - serial.SYS\n"
254 "faa00000 2bd49739 - mup.sys faa40000 2bd4971f - SMBTRSUP.SYS\n"
255 "faa10000 2bd6f2a2 - srv.sys faa50000 2bd4971a - afd.sys\n"
256 "faa60000 2bd6fd80 - rdr.sys faaa0000 2bd49735 - bowser.sys\n"
258 "Address dword dump Dll Base - Name\n"
259 "801afc20 80106fc0 80106fc0 00000000 00000000 80149905 : "
260 "fa840000 - i8042prt.SYS\n"
261 "801afc24 80149905 80149905 ff8e6b8c 80129c2c ff8e6b94 : "
262 "8025c000 - SCSIPORT.SYS\n"
263 "801afc2c 80129c2c 80129c2c ff8e6b94 00000000 ff8e6b94 : "
264 "80100000 - ntoskrnl.exe\n"
265 "801afc34 801240f2 80124f02 ff8e6df4 ff8e6f60 ff8e6c58 : "
266 "80100000 - ntoskrnl.exe\n"
267 "801afc54 80124f16 80124f16 ff8e6f60 ff8e6c3c 8015ac7e : "
268 "80100000 - ntoskrnl.exe\n"
269 "801afc64 8015ac7e 8015ac7e ff8e6df4 ff8e6f60 ff8e6c58 : "
270 "80100000 - ntoskrnl.exe\n"
271 "801afc70 80129bda 80129bda 00000000 80088000 80106fc0 : "
272 "80100000 - ntoskrnl.exe\n"
274 "Kernel Debugger Using: COM2 (Port 0x2f8, Baud Rate 19200)\n"
275 "Restart and set the recovery options in the system control panel\n"
276 "or the /CRASHDEBUG system start option. If this message reappears,\n"
277 "contact your system administrator or technical support group."
281 ("*** STOP: 0x000000D1 (0xE1D38000,0x0000001C,0x00000000,0xF09D42DA)\n"
282 "DRIVER_IRQL_NOT_LESS_OR_EQUAL \n"
284 "*** Address F09D42DA base at F09D4000, DateStamp 39f459ff - CRASHDD.SYS\n"
286 "Beginning dump of physical memory\n");
288 ("Physical memory dump complete. Contact your system administrator or\n"
289 "technical support group.\n");
292 (" Windows protection error. You need to restart your computer.");
296 if (which < 0 || which > 2) abort();
298 /* kludge to lump Win2K and WinME together; seems silly to add another
299 preference/command line option just for this little one. */
300 if (which == 2 && (random() % 2))
303 XGetWindowAttributes (dpy, window, &xgwa);
305 fontname = get_string_resource ((xgwa.height > 600
306 ? (which == 0 ? "windows95.font2" :
307 which == 1 ? "windowsNT.font2" :
308 which == 2 ? "windows2K.font2" :
310 : (which == 0 ? "windows95.font" :
311 which == 1 ? "windowsNT.font" :
312 which == 2 ? "windows2K.font" :
315 if (!fontname || !*fontname) fontname = (char *)def_font;
316 font = XLoadQueryFont (dpy, fontname);
317 if (!font) font = XLoadQueryFont (dpy, def_font);
319 if (fontname && fontname != def_font)
322 gcv.font = font->fid;
323 gcv.foreground = get_pixel_resource((which == 0 ? "windows95.foreground" :
324 which == 1 ? "windowsNT.foreground" :
325 which == 2 ? "windows2K.foreground" :
326 "windowsME.foreground"),
327 "Windows.Foreground",
329 gcv.background = get_pixel_resource((which == 0 ? "windows95.background" :
330 which == 1 ? "windowsNT.background" :
331 which == 2 ? "windows2K.background" :
332 "windowsME.background"),
333 "Windows.Background",
335 XSetWindowBackground(dpy, window, gcv.background);
336 XClearWindow(dpy, window);
338 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
341 draw_string(dpy, window, gc, &gcv, font,
342 0, 0, xgwa.width, xgwa.height, w95, 0);
344 draw_string(dpy, window, gc, &gcv, font, 0, 0, 10, 10, wnt, 750);
347 int line_height = font->ascent + font->descent + 1;
349 int y = (xgwa.height / 4);
351 draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, w2ka, 750);
352 y += line_height * 6;
354 draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, w2kb, 750);
358 int line_height = font->ascent + font->descent;
360 int y = (xgwa.height - line_height * 3) / 2;
361 draw_string (dpy, window, gc, &gcv, font, x, y, 10, 10, wmea, 0);
362 y += line_height * 2;
363 x = draw_string (dpy, window, gc, &gcv, font, x, y, 10, 10, wmeb, 0);
367 XDrawImageString (dpy, window, gc, x, y, "_", 1);
370 XDrawImageString (dpy, window, gc, x, y, " ", 1);
373 if (bsod_sleep(dpy, 0))
384 bsod_sleep(dpy, delay);
385 XClearWindow(dpy, window);
386 XFreeFont(dpy, font);
390 windows_31 (Display *dpy, Window window, int delay)
392 windows (dpy, window, delay, 0);
396 windows_nt (Display *dpy, Window window, int delay)
398 windows (dpy, window, delay, 1);
402 windows_2k (Display *dpy, Window window, int delay)
404 windows (dpy, window, delay, 2);
408 /* SCO OpenServer 5 panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
411 sco (Display *dpy, Window window, int delay)
414 XWindowAttributes xgwa;
416 const char *def_font = "fixed";
419 int lines_1 = 0, lines_2 = 0, lines_3 = 0, lines_4 = 0;
423 __extension__ /* don't warn about "string length is greater than the
424 length ISO C89 compilers are required to support"
425 in the following string constant... */
428 const char *sco_panic_1 =
429 ("Unexpected trap in kernel mode:\n"
431 "cr0 0x80010013 cr2 0x00000014 cr3 0x00000000 tlb 0x00000000\n"
432 "ss 0x00071054 uesp 0x00012055 efl 0x00080888 ipl 0x00000005\n"
433 "cs 0x00092585 eip 0x00544a4b err 0x004d4a47 trap 0x0000000E\n"
434 "eax 0x0045474b ecx 0x0042544b edx 0x57687920 ebx 0x61726520\n"
435 "esp 0x796f7520 ebp 0x72656164 esi 0x696e6720 edi 0x74686973\n"
436 "ds 0x3f000000 es 0x43494c48 fs 0x43525343 gs 0x4f4d4b53\n"
438 "PANIC: k_trap - kernel mode trap type 0x0000000E\n"
439 "Trying to dump 5023 pages to dumpdev hd (1/41), 63 pages per '.'\n"
441 const char *sco_panic_2 =
442 ("................................................................."
445 const char *sco_panic_3 =
446 ("5023 pages dumped\n"
450 const char *sco_panic_4 =
451 ("** Safe to Power Off **\n"
453 "** Press Any Key to Reboot **\n"
456 for (s = sco_panic_1; *s; s++) if (*s == '\n') lines_1++;
457 for (s = sco_panic_2; *s; s++) if (*s == '\n') lines_2++;
458 for (s = sco_panic_3; *s; s++) if (*s == '\n') lines_3++;
459 for (s = sco_panic_4; *s; s++) if (*s == '\n') lines_4++;
461 XGetWindowAttributes (dpy, window, &xgwa);
463 fontname = get_string_resource ((xgwa.height > 600
467 if (!fontname || !*fontname) fontname = (char *)def_font;
468 font = XLoadQueryFont (dpy, fontname);
469 if (!font) font = XLoadQueryFont (dpy, def_font);
471 if (fontname && fontname != def_font)
474 gcv.font = font->fid;
475 gcv.foreground = get_pixel_resource(("sco.foreground"),
478 gcv.background = get_pixel_resource(("sco.background"),
481 XSetWindowBackground(dpy, window, gcv.background);
482 XClearWindow(dpy, window);
484 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
486 draw_string(dpy, window, gc, &gcv, font,
487 10, xgwa.height - ((lines_1 + lines_2 + lines_3 + lines_4 + 1) *
488 (font->ascent + font->descent + 1)),
492 for (s = sco_panic_2; *s; s++)
494 char *ss = strdup(sco_panic_2);
495 ss[s - sco_panic_2] = 0;
496 draw_string(dpy, window, gc, &gcv, font,
497 10, xgwa.height - ((lines_2 + lines_3 + lines_4 + 1) *
498 (font->ascent + font->descent + 1)),
503 if (bsod_sleep (dpy, -1))
507 draw_string(dpy, window, gc, &gcv, font,
508 10, xgwa.height - ((lines_3 + lines_4 + 1) *
509 (font->ascent + font->descent + 1)),
513 if (bsod_sleep(dpy, 1))
515 draw_string(dpy, window, gc, &gcv, font,
516 10, xgwa.height - ((lines_4 + 1) *
517 (font->ascent + font->descent + 1)),
522 bsod_sleep(dpy, delay);
524 XClearWindow(dpy, window);
526 XFreeFont(dpy, font);
530 /* Linux (sparc) panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
533 sparc_linux (Display *dpy, Window window, int delay)
536 XWindowAttributes xgwa;
538 const char *def_font = "fixed";
545 __extension__ /* don't warn about "string length is greater than the
546 length ISO C89 compilers are required to support"
547 in the following string constant... */
550 const char *linux_panic =
551 ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
552 "Unable to handle kernel paging request at virtual address f0d4a000\n"
553 "tsk->mm->context = 00000014\n"
554 "tsk->mm->pgd = f26b0000\n"
559 "gawk(22827): Oops\n"
560 "PSR: 044010c1 PC: f001c2cc NPC: f001c2d0 Y: 00000000\n"
561 "g0: 00001000 g1: fffffff7 g2: 04401086 g3: 0001eaa0\n"
562 "g4: 000207dc g5: f0130400 g6: f0d4a018 g7: 00000001\n"
563 "o0: 00000000 o1: f0d4a298 o2: 00000040 o3: f1380718\n"
564 "o4: f1380718 o5: 00000200 sp: f1b13f08 ret_pc: f001c2a0\n"
565 "l0: efffd880 l1: 00000001 l2: f0d4a230 l3: 00000014\n"
566 "l4: 0000ffff l5: f0131550 l6: f012c000 l7: f0130400\n"
567 "i0: f1b13fb0 i1: 00000001 i2: 00000002 i3: 0007c000\n"
568 "i4: f01457c0 i5: 00000004 i6: f1b13f70 i7: f0015360\n"
569 "Instruction DUMP:\n"
572 for (s = linux_panic; *s; s++) if (*s == '\n') lines++;
574 XGetWindowAttributes (dpy, window, &xgwa);
576 fontname = get_string_resource ((xgwa.height > 600
578 : "sparclinux.font"),
580 if (!fontname || !*fontname) fontname = (char *)def_font;
581 font = XLoadQueryFont (dpy, fontname);
582 if (!font) font = XLoadQueryFont (dpy, def_font);
584 if (fontname && fontname != def_font)
587 gcv.font = font->fid;
588 gcv.foreground = get_pixel_resource(("sparclinux.foreground"),
589 "SparcLinux.Foreground",
591 gcv.background = get_pixel_resource(("sparclinux.background"),
592 "SparcLinux.Background",
594 XSetWindowBackground(dpy, window, gcv.background);
595 XClearWindow(dpy, window);
597 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
599 draw_string(dpy, window, gc, &gcv, font,
600 10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
605 bsod_sleep(dpy, delay);
606 XClearWindow(dpy, window);
607 XFreeFont(dpy, font);
610 /* BSD Panic by greywolf@starwolf.com - modeled after the Linux panic above.
611 By Grey Wolf <greywolf@siteROCK.com>
614 bsd (Display *dpy, Window window, int delay)
617 XWindowAttributes xgwa;
619 const char *def_font = "fixed";
624 const char *rbstr, *panicking;
625 char syncing[80], bbuf[5], *bp;
627 const char *panicstr[] =
628 {"panic: ifree: freeing free inode",
629 "panic: blkfree: freeing free block",
630 "panic: improbability coefficient below zero",
632 "panic: crazy interrupts",
634 "panic: attempted windows install",
636 "panic: free inode isn't",
637 "panic: cpu_fork: curproc",
638 "panic: malloc: out of space in kmem_map",
639 "panic: vogon starship detected",
640 "panic: teleport chamber: out of order",
641 "panic: Brain fried - core dumped"};
643 for (i = 0; i < sizeof(syncing); i++)
646 i = (random() & 0xffff) % (sizeof(panicstr) / sizeof(*panicstr));
648 panicking = panicstr[i];
649 strcpy(syncing, "Syncing disks: ");
651 b = (random() & 0xff) % 40;
652 for (n = 0; (n < 20) && (b > 0); n++)
656 i = (random() & 0x7);
657 b -= (random() & 0xff) % 20;
661 sprintf (bbuf, "%d ", b);
662 strcat (syncing, bbuf);
672 XGetWindowAttributes (dpy, window, &xgwa);
674 fontname = get_string_resource ((xgwa.height > 600
678 if (!fontname || !*fontname) fontname = (char *)def_font;
679 font = XLoadQueryFont (dpy, fontname);
680 if (!font) font = XLoadQueryFont (dpy, def_font);
682 if (fontname && fontname != def_font)
685 gcv.font = font->fid;
686 gcv.foreground = get_pixel_resource(("bsd.foreground"),
689 gcv.background = get_pixel_resource(("bsd.background"),
692 XSetWindowBackground(dpy, window, gcv.background);
693 XClearWindow(dpy, window);
695 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
697 draw_string(dpy, window, gc, &gcv, font,
698 10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
704 for (bp = syncing; *bp;)
706 char *bsd_bufs, oc = 0;
707 for (;*bp && (*bp != ' '); bp++)
714 bsd_bufs = strdup(syncing);
715 draw_string(dpy, window, gc, &gcv, font,
717 xgwa.height - (lines * (font->ascent + font->descent + 1)),
724 if (bsod_sleep(dpy, -1))
731 draw_string(dpy, window, gc, &gcv, font,
732 10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
736 draw_string(dpy, window, gc, &gcv, font,
737 10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
743 bsod_sleep(dpy, delay);
746 XClearWindow(dpy, window);
747 XFreeFont(dpy, font);
751 amiga (Display *dpy, Window window, int delay)
754 XWindowAttributes xgwa;
756 const char *def_font = "fixed";
760 unsigned long fg, bg, bg2;
762 int pix_w = 0, pix_h = 0;
767 ("_Software failure. Press left mouse button to continue.\n"
768 "_Guru Meditation #00000003.00C01570");
770 XGetWindowAttributes (dpy, window, &xgwa);
772 fontname = get_string_resource ((xgwa.height > 600
773 ? "amiga.font2" : "amiga.font"),
775 if (!fontname || !*fontname) fontname = (char *)def_font;
776 font = XLoadQueryFont (dpy, fontname);
777 if (!font) font = XLoadQueryFont (dpy, def_font);
779 if (fontname && fontname != def_font)
782 gcv.font = font->fid;
783 fg = gcv.foreground = get_pixel_resource("amiga.foreground",
786 bg = gcv.background = get_pixel_resource("amiga.background",
789 bg2 = get_pixel_resource("amiga.background2", "Amiga.Background",
791 XSetWindowBackground(dpy, window, bg2);
792 XClearWindow(dpy, window);
794 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
795 gcv.background = fg; gcv.foreground = bg;
796 gc2 = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
798 height = (font->ascent + font->descent) * 6;
800 #if defined(HAVE_GDK_PIXBUF) || defined (HAVE_XPM)
801 pixmap = xpm_data_to_pixmap (dpy, window, (char **) amiga_hand,
803 #endif /* HAVE_GDK_PIXBUF || HAVE_XPM */
805 if (pixmap && xgwa.height > 600) /* scale up the bitmap */
807 pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
808 pixmap, pix_w, pix_h);
815 int x = (xgwa.width - pix_w) / 2;
816 int y = ((xgwa.height - pix_h) / 2);
817 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
822 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y + height);
823 XClearArea(dpy, window, 0, 0, xgwa.width, y + height, False);
824 XFreePixmap(dpy, pixmap);
827 XFillRectangle(dpy, window, gc2, 0, 0, xgwa.width, height);
828 margin = font->ascent;
829 string_width = draw_string(dpy, window, gc, &gcv, font,
831 xgwa.width - (margin * 2), height,
838 XFillRectangle(dpy, window, gca, 0, 0, xgwa.width, margin);
839 XFillRectangle(dpy, window, gca, 0, 0, margin, height);
840 XFillRectangle(dpy, window, gca,
841 0, height - margin, xgwa.width, margin);
842 x2 = margin + string_width;
843 if (x2 < xgwa.width - margin) x2 = xgwa.width - margin;
844 XFillRectangle(dpy, window, gca, x2, 0, margin, height);
846 gca = (gca == gc ? gc2 : gc);
848 if (bsod_sleep(dpy, 1))
857 XClearWindow(dpy, window);
858 XFreeFont(dpy, font);
862 /* Atari ST, by Marcus Herbert <rhoenie@nobiscum.de>
863 Marcus had this to say:
865 Though I still have my Atari somewhere, I hardly remember
866 the meaning of the bombs. I think 9 bombs was "bus error" or
867 something like that. And you often had a few bombs displayed
868 quickly and then the next few ones coming up step by step.
869 Perhaps somebody else can tell you more about it.. its just
873 atari (Display *dpy, Window window, int delay)
877 XWindowAttributes xgwa;
878 const char *def_font = "fixed";
882 int pix_w = atari_width;
883 int pix_h = atari_height;
887 XGetWindowAttributes (dpy, window, &xgwa);
889 font = XLoadQueryFont (dpy, def_font);
892 gcv.font = font->fid;
893 gcv.foreground = get_pixel_resource("atari.foreground", "Atari.Foreground",
895 gcv.background = get_pixel_resource("atari.background", "Atari.Background",
898 XSetWindowBackground(dpy, window, gcv.background);
899 XClearWindow(dpy, window);
901 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
903 pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) atari_bits,
905 gcv.foreground, gcv.background,
907 pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
908 pixmap, pix_w, pix_h);
914 y = (xgwa.height - (xgwa.height / 5));
917 for (i=0 ; i<7 ; i++) {
918 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h,
919 (x + (i*offset)), y);
922 for (i=7 ; i<10 ; i++) {
923 if (bsod_sleep(dpy, 1))
925 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h,
926 (x + (i*offset)), y);
929 bsod_sleep(dpy, delay);
931 XFreePixmap(dpy, pixmap);
934 XClearWindow(dpy, window);
935 XFreeFont(dpy, font);
940 mac (Display *dpy, Window window, int delay)
943 XWindowAttributes xgwa;
945 const char *def_font = "fixed";
949 int pix_w = mac_width;
950 int pix_h = mac_height;
951 int offset = mac_height * 4;
954 const char *string = ("0 0 0 0 0 0 0 F\n"
957 XGetWindowAttributes (dpy, window, &xgwa);
959 fontname = get_string_resource ("mac.font", "Mac.Font");
960 if (!fontname || !*fontname) fontname = (char *)def_font;
961 font = XLoadQueryFont (dpy, fontname);
962 if (!font) font = XLoadQueryFont (dpy, def_font);
964 if (fontname && fontname != def_font)
967 gcv.font = font->fid;
968 gcv.foreground = get_pixel_resource("mac.foreground", "Mac.Foreground",
970 gcv.background = get_pixel_resource("mac.background", "Mac.Background",
972 XSetWindowBackground(dpy, window, gcv.background);
973 XClearWindow(dpy, window);
975 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
977 pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) mac_bits,
978 mac_width, mac_height,
983 for(i = 0; i < 2; i++)
985 pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
986 pixmap, pix_w, pix_h);
987 pix_w *= 2; pix_h *= 2;
991 int x = (xgwa.width - pix_w) / 2;
992 int y = (((xgwa.height + offset) / 2) -
994 (font->ascent + font->descent) * 2);
996 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
997 XFreePixmap(dpy, pixmap);
1000 draw_string(dpy, window, gc, &gcv, font, 0, 0,
1001 xgwa.width, xgwa.height + offset, string, 0);
1005 bsod_sleep(dpy, delay);
1006 XClearWindow(dpy, window);
1007 XFreeFont(dpy, font);
1011 macsbug (Display *dpy, Window window, int delay)
1014 XWindowAttributes xgwa;
1016 const char *def_font = "fixed";
1020 int char_width, line_height;
1021 int col_right, row_top, row_bottom, page_right, page_bottom, body_top;
1025 __extension__ /* don't warn about "string length is greater than the
1026 length ISO C89 compilers are required to support"
1027 in the following string constant... */
1030 const char *left = (" SP \n"
1077 const char *bottom = (" _A09D\n"
1078 " +00884 40843714 #$0700,SR "
1080 " +00886 40843765 *+$0400 "
1082 " +00888 40843718 $0004(A7),([0,A7[)"
1083 " ; 04E8D0AE | 66B8");
1086 const char *body = ("Bus Error at 4BF6D6CC\n"
1087 "while reading word from 4BF6D6CC in User data space\n"
1088 " Unable to access that address\n"
1090 " Frame Type: B008");
1094 __extension__ /* don't warn about "string length is greater than the
1095 length ISO C89 compilers are required to support"
1096 in the following string constant... */
1099 const char * body = ("PowerPC unmapped memory exception at 003AFDAC "
1100 "BowelsOfTheMemoryMgr+04F9C\n"
1101 " Calling chain using A6/R1 links\n"
1102 " Back chain ISA Caller\n"
1103 " 00000000 PPC 28C5353C __start+00054\n"
1104 " 24DB03C0 PPC 28B9258C main+0039C\n"
1105 " 24DB0350 PPC 28B9210C MainEvent+00494\n"
1106 " 24DB02B0 PPC 28B91B40 HandleEvent+00278\n"
1107 " 24DB0250 PPC 28B83DAC DoAppleEvent+00020\n"
1108 " 24DB0210 PPC FFD3E5D0 "
1109 "AEProcessAppleEvent+00020\n"
1110 " 24DB0132 68K 00589468\n"
1111 " 24DAFF8C 68K 00589582\n"
1112 " 24DAFF26 68K 00588F70\n"
1113 " 24DAFEB3 PPC 00307098 "
1114 "EmToNatEndMoveParams+00014\n"
1115 " 24DAFE40 PPC 28B9D0B0 DoScript+001C4\n"
1116 " 24DAFDD0 PPC 28B9C35C RunScript+00390\n"
1117 " 24DAFC60 PPC 28BA36D4 run_perl+000E0\n"
1118 " 24DAFC10 PPC 28BC2904 perl_run+002CC\n"
1119 " 24DAFA80 PPC 28C18490 Perl_runops+00068\n"
1120 " 24DAFA30 PPC 28BE6CC0 Perl_pp_backtick+000FC\n"
1121 " 24DAF9D0 PPC 28BA48B8 Perl_my_popen+00158\n"
1122 " 24DAF980 PPC 28C5395C sfclose+00378\n"
1123 " 24DAF930 PPC 28BA568C free+0000C\n"
1124 " 24DAF8F0 PPC 28BA6254 pool_free+001D0\n"
1125 " 24DAF8A0 PPC FFD48F14 DisposePtr+00028\n"
1126 " 24DAF7C9 PPC 00307098 "
1127 "EmToNatEndMoveParams+00014\n"
1128 " 24DAF780 PPC 003AA180 __DisposePtr+00010");
1134 for (s = body; *s; s++) if (*s == '\n') body_lines++;
1136 XGetWindowAttributes (dpy, window, &xgwa);
1138 fontname = get_string_resource ((xgwa.height > 850
1140 : (xgwa.height > 700
1144 if (!fontname || !*fontname) fontname = (char *)def_font;
1145 font = XLoadQueryFont (dpy, fontname);
1146 if (!font) font = XLoadQueryFont (dpy, def_font);
1147 if (!font) exit(-1);
1148 if (fontname && fontname != def_font)
1151 gcv.font = font->fid;
1152 gcv.foreground = get_pixel_resource("macsbug.foreground",
1153 "MacsBug.Foreground",
1154 dpy, xgwa.colormap);
1155 gcv.background = get_pixel_resource("macsbug.background",
1156 "MacsBug.Background",
1157 dpy, xgwa.colormap);
1159 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
1161 gcv.foreground = gcv.background;
1162 gc2 = XCreateGC(dpy, window, GCForeground, &gcv);
1164 XSetWindowBackground(dpy, window,
1165 get_pixel_resource("macsbug.borderColor",
1166 "MacsBug.BorderColor",
1167 dpy, xgwa.colormap));
1168 XClearWindow(dpy, window);
1170 char_width = (font->per_char
1171 ? font->per_char['n'-font->min_char_or_byte2].width
1172 : font->min_bounds.width);
1173 line_height = font->ascent + font->descent + 1;
1175 col_right = char_width * 12;
1176 page_bottom = line_height * 47;
1178 if (page_bottom > xgwa.height) page_bottom = xgwa.height;
1180 row_bottom = page_bottom - line_height;
1181 row_top = row_bottom - (line_height * 4);
1182 page_right = col_right + (char_width * 88);
1183 body_top = row_top - (line_height * body_lines);
1189 xoff = (xgwa.width - page_right) / 2;
1190 yoff = (xgwa.height - page_bottom) / 2;
1191 if (xoff < 0) xoff = 0;
1192 if (yoff < 0) yoff = 0;
1194 XFillRectangle(dpy, window, gc2, xoff, yoff, page_right, page_bottom);
1196 draw_string(dpy, window, gc, &gcv, font, xoff, yoff, 10, 10, left, 0);
1197 draw_string(dpy, window, gc, &gcv, font, xoff+col_right, yoff+row_top,
1200 XFillRectangle(dpy, window, gc, xoff + col_right, yoff, 2, page_bottom);
1201 XDrawLine(dpy, window, gc,
1202 xoff+col_right, yoff+row_top, xoff+page_right, yoff+row_top);
1203 XDrawLine(dpy, window, gc,
1204 xoff+col_right, yoff+row_bottom, xoff+page_right, yoff+row_bottom);
1205 XDrawRectangle(dpy, window, gc, xoff, yoff, page_right, page_bottom);
1210 draw_string(dpy, window, gc, &gcv, font,
1211 xoff + col_right + char_width, yoff + body_top, 10, 10, body,
1216 XDrawLine(dpy, window, gc,
1217 xoff+col_right+(char_width/2)+2, yoff+row_bottom+3,
1218 xoff+col_right+(char_width/2)+2, yoff+page_bottom-3);
1221 XDrawLine(dpy, window, gc2,
1222 xoff+col_right+(char_width/2)+2, yoff+row_bottom+3,
1223 xoff+col_right+(char_width/2)+2, yoff+page_bottom-3);
1226 if (bsod_sleep(dpy, 0))
1233 XClearWindow(dpy, window);
1234 XFreeFont(dpy, font);
1238 mac1 (Display *dpy, Window window, int delay)
1241 XWindowAttributes xgwa;
1244 int pix_w = macbomb_width;
1245 int pix_h = macbomb_height;
1247 XGetWindowAttributes (dpy, window, &xgwa);
1249 gcv.foreground = get_pixel_resource("mac1.foreground", "Mac.Foreground",
1250 dpy, xgwa.colormap);
1251 gcv.background = get_pixel_resource("mac1.background", "Mac.Background",
1252 dpy, xgwa.colormap);
1253 XSetWindowBackground(dpy, window, gcv.background);
1254 XClearWindow(dpy, window);
1256 gc = XCreateGC(dpy, window, GCForeground|GCBackground, &gcv);
1258 pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) macbomb_bits,
1259 macbomb_width, macbomb_height,
1265 int x = (xgwa.width - pix_w) / 2;
1266 int y = (xgwa.height - pix_h) / 2;
1268 XFillRectangle (dpy, window, gc, 0, 0, xgwa.width, xgwa.height);
1270 if (bsod_sleep(dpy, 1))
1272 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
1277 XFreePixmap(dpy, pixmap);
1279 bsod_sleep(dpy, delay);
1280 XClearWindow(dpy, window);
1285 macx (Display *dpy, Window window, int delay)
1288 XWindowAttributes xgwa;
1290 const char *def_font = "fixed";
1295 __extension__ /* don't warn about "string length is greater than the
1296 length ISO C89 compilers are required to support"
1297 in the following string constant... */
1300 const char *macx_panic =
1301 ("panic(cpu 0): Unable to find driver for this platform: "
1302 "\"PowerMac 3,5\".\n"
1304 "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c "
1305 "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n"
1309 "No debugger configured - dumping debug information\n"
1311 "version string : Darwin Kernel Version 1.3:\n"
1312 "Thu Mar 1 06:56:40 PST 2001; root:xnu/xnu-123.5.obj~1/RELEASE_PPC\n"
1317 "DBAT0: 00000000 00000000\n"
1318 "DBAT1: 00000000 00000000\n"
1319 "DBAT2: 80001FFE 8000003A\n"
1320 "DBAT3: 90001FFE 9000003A\n"
1322 "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c "
1323 "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n"
1325 "panic: We are hanging here...\n");
1327 XGetWindowAttributes (dpy, window, &xgwa);
1329 gcv.background = get_pixel_resource("macX.background",
1331 dpy, xgwa.colormap);
1332 XSetWindowBackground(dpy, window, gcv.background);
1333 XClearWindow(dpy, window);
1335 fontname = get_string_resource ((xgwa.height > 900
1339 if (!fontname || !*fontname) fontname = (char *)def_font;
1340 font = XLoadQueryFont (dpy, fontname);
1341 if (!font) font = XLoadQueryFont (dpy, def_font);
1342 if (!font) exit(-1);
1343 if (fontname && fontname != def_font)
1346 gcv.font = font->fid;
1347 gcv.foreground = get_pixel_resource("macsbug.foreground",
1348 "MacsBug.Foreground",
1349 dpy, xgwa.colormap);
1350 gcv.background = get_pixel_resource("macsbug.background",
1351 "MacsBug.Background",
1352 dpy, xgwa.colormap);
1355 gcv.foreground = get_pixel_resource("macX.textForeground",
1356 "MacX.TextForeground",
1357 dpy, xgwa.colormap);
1358 gcv.background = get_pixel_resource("macX.textBackground",
1359 "MacX.TextBackground",
1360 dpy, xgwa.colormap);
1361 gc = XCreateGC(dpy, window, GCForeground|GCBackground|GCFont, &gcv);
1363 #if defined(HAVE_GDK_PIXBUF) || defined (HAVE_XPM)
1367 int x, y, pix_w, pix_h;
1368 pixmap = xpm_data_to_pixmap (dpy, window, (char **) happy_mac,
1369 &pix_w, &pix_h, &mask);
1371 x = (xgwa.width - pix_w) / 2;
1372 y = (xgwa.height - pix_h) / 2;
1376 XSetClipMask (dpy, gc, mask);
1377 XSetClipOrigin (dpy, gc, x, y);
1378 XCopyArea (dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
1379 XSetClipMask (dpy, gc, None);
1380 XFreePixmap (dpy, pixmap);
1382 #endif /* HAVE_GDK_PIXBUF || HAVE_XPM */
1389 int char_width, line_height;
1390 char_width = (font->per_char
1391 ? font->per_char['n'-font->min_char_or_byte2].width
1392 : font->min_bounds.width);
1393 line_height = font->ascent + font->descent;
1401 if (*s == '\n' || x + char_width >= xgwa.width)
1409 /* Note that to get this goofy effect, they must be actually
1410 emitting LF CR at the end of each line instead of CR LF!
1412 XDrawImageString (dpy, window, gc, ox, oy, " ", 1);
1413 XDrawImageString (dpy, window, gc, ox, y, " ", 1);
1417 XDrawImageString (dpy, window, gc, x, y, s, 1);
1426 bsod_sleep(dpy, delay);
1427 XClearWindow(dpy, window);
1433 * by Martin Pool <mbp@samba.org>, Feb 2000.
1435 * This is meant to look like the preferred failure mode of NCD
1436 * Xterms. The parameters for choosing what to copy where might not
1437 * be quite right, but it looks about ugly enough.
1440 blitdamage (Display *dpy, Window window, int delay)
1443 XWindowAttributes xwa;
1446 int delta_x = 0, delta_y = 0;
1448 int chunk_h, chunk_w;
1454 XGetWindowAttributes(dpy, window, &xwa);
1456 load_random_image (xwa.screen, window, window);
1461 gc_mask = GCForeground;
1463 gcv.plane_mask = random();
1464 gc_mask |= GCPlaneMask;
1466 gc0 = XCreateGC(dpy, window, gc_mask, &gcv);
1469 chunk_w = w / (random() % 1 + 1);
1470 chunk_h = h / (random() % 1 + 1);
1471 if (random() & 0x1000)
1472 delta_y = random() % 600;
1473 if (!delta_y || (random() & 0x2000))
1474 delta_x = random() % 600;
1480 for (i = 0; i < steps; i++) {
1481 if (x + chunk_w > w)
1486 if (y + chunk_h > h)
1491 XCopyArea(dpy, window, window, gc0,
1496 if (bsod_sleep(dpy, 0))
1500 bsod_sleep(dpy, delay);
1508 * SPARC Solaris panic. Should look pretty authentic on Solaris boxes.
1509 * Anton Solovyev <solovam@earthlink.net>
1518 int sub_width; /* Text subwindow width in pixels */
1519 int sub_height; /* Text subwindow height in pixels */
1520 int sub_x; /* upper left corner of the text subwindow */
1521 int sub_y; /* upper left corner of the text subwindow */
1522 int char_width; /* Char width in pixels */
1523 int line_height; /* Line height in pixels */
1524 int columns; /* Number of columns in the text screen */
1525 int x; /* horizontal position of the cursor */
1529 static scrolling_window *
1530 make_scrolling_window (Display *dpy, Window window,
1534 const char *def_font = "fixed";
1535 scrolling_window* ts;
1536 XWindowAttributes xgwa;
1539 char buf1[100], buf2[100];
1541 ts = malloc (sizeof (*ts));
1542 ts->window = window;
1547 XGetWindowAttributes (dpy, window, &xgwa);
1551 ts->sub_width = xgwa.width * 0.8;
1552 ts->sub_height = xgwa.height * 0.8;
1556 ts->sub_width = xgwa.width - 20;
1557 ts->sub_height = xgwa.height - 20;
1558 if (ts->sub_width < 20) ts->sub_width = 20;
1559 if (ts->sub_height < 20) ts->sub_height = 20;
1562 sprintf (buf1, "%.50s.font", name);
1563 sprintf (buf2, "%.50s.Font", name);
1564 fn = get_string_resource (buf1, buf2);
1565 ts->xfs = XLoadQueryFont (dpy, fn);
1568 sprintf (buf1, "%.50s.font2", name);
1569 fn = get_string_resource(buf1, buf2);
1570 ts->xfs = XLoadQueryFont(dpy, fn);
1573 ts->xfs = XLoadQueryFont(dpy, def_font);
1576 gcv.font = ts->xfs->fid;
1577 ts->char_width = (ts->xfs->per_char
1578 ? ts->xfs->per_char['n'-ts->xfs->min_char_or_byte2].width
1579 : ts->xfs->min_bounds.width);
1580 ts->line_height = ts->xfs->ascent + ts->xfs->descent + 1;
1582 ts->columns = ts->sub_width / ts->char_width;
1584 ts->sub_x = (xgwa.width - ts->sub_width) / 2;
1585 ts->sub_y = (xgwa.height - ts->sub_height) / 2;
1587 if (!grab_screen_p) ts->sub_height += ts->sub_y, ts->sub_y = 0;
1590 load_random_image (xgwa.screen, window, window);
1592 sprintf (buf1, "%.50s.background", name);
1593 sprintf (buf2, "%.50s.Background", name);
1594 gcv.background = get_pixel_resource (buf1, buf2, dpy, xgwa.colormap);
1596 sprintf (buf1, "%.50s.foreground", name);
1597 sprintf (buf2, "%.50s.Foreground", name);
1598 gcv.foreground = get_pixel_resource (buf1, buf2, dpy, xgwa.colormap);
1600 ts->gc = XCreateGC (dpy, window,
1601 GCForeground | GCBackground | GCFont,
1603 gcv.foreground = gcv.background;
1604 ts->erase_gc = XCreateGC (dpy, window,
1605 GCForeground | GCBackground,
1607 XSetWindowBackground (dpy, window, gcv.background);
1612 free_scrolling_window (scrolling_window* ts)
1614 XFreeGC (ts->dpy, ts->gc);
1615 XFreeGC (ts->dpy, ts->erase_gc);
1616 XFreeFont (ts->dpy, ts->xfs);
1621 scrolling_putc (scrolling_window* ts, const char aChar)
1627 XCopyArea (ts->dpy, ts->window, ts->window, ts->gc,
1628 ts->sub_x, ts->sub_y + ts->line_height,
1629 ts->sub_width, ts->sub_height,
1630 ts->sub_x, ts->sub_y);
1631 XFillRectangle (ts->dpy, ts->window, ts->erase_gc,
1632 ts->sub_x, ts->sub_y + ts->sub_height - ts->line_height,
1633 ts->sub_width, ts->line_height);
1642 if (ts->x >= ts->columns)
1643 scrolling_putc (ts, '\n');
1644 XDrawImageString (ts->dpy, ts->window, ts->gc,
1646 (ts->x * ts->char_width)
1647 - ts->xfs->min_bounds.lbearing),
1648 (ts->sub_y + ts->sub_height - ts->xfs->descent),
1656 scrolling_puts (scrolling_window *ts, const char* aString, int delay)
1659 for (c = aString; *c; ++c)
1661 scrolling_putc (ts, *c);
1666 if (bsod_sleep (ts->dpy, 0))
1675 sparc_solaris (Display* dpy, Window window, int delay)
1678 __extension__ /* don't warn about "string length is greater than the
1679 length ISO C89 compilers are required to support"
1680 in the following string constant... */
1684 "BAD TRAP: cpu=0 type=0x31 rp=0x2a10043b5e0 addr=0xf3880 mmu_fsr=0x0\n"
1685 "BAD TRAP occured in module \"unix\" due to an illegal access to a"
1687 "adb: trap type = 0x31\n"
1689 "pid=307, pc=0x100306e4, sp=0x2a10043ae81, tstate=0x4480001602,"
1691 "g1-g7: 1045b000, 32f, 10079440, 180, 300000ebde8, 0, 30000953a20\n"
1692 "Begin traceback... sp = 2a10043ae81\n"
1693 "Called from 100bd060, fp=2a10043af31, args=f3700 300008cc988 f3880 0"
1695 "Called from 101fe1bc, fp=2a10043b011, args=3000045a240 104465a0"
1696 " 300008e47d0 300008e48fa 300008ae350 300008ae410\n"
1697 "Called from 1007c520, fp=2a10043b0c1, args=300008e4878 300003596e8 0"
1698 " 3000045a320 0 3000045a220\n"
1699 "Called from 1007c498, fp=2a10043b171, args=1045a000 300007847f0 20"
1700 " 3000045a240 1 0\n"
1701 "Called from 1007972c, fp=2a10043b221, args=1 300009517c0 30000951e58 1"
1703 "Called from 10031e10, fp=2a10043b2d1, args=3000095b0c8 0 300009396a8"
1704 " 30000953a20 0 1\n"
1705 "Called from 10000bdd8, fp=ffffffff7ffff1c1, args=0 57 100131480"
1706 " 100131480 10012a6e0 0\n"
1707 "End traceback...\n"
1708 "panic[cpu0]/thread=30000953a20: trap\n"
1709 "syncing file systems...";
1712 "dumping to /dev/dsk/c0t0d0s3, offset 26935296\n";
1714 ": 2803 pages dumped, compression ratio 2.88, dump succeeded\n";
1719 scrolling_window *ts;
1723 ts = make_scrolling_window (dpy, window, "Solaris", True);
1725 scrolling_puts (ts, msg1, 0);
1726 if (bsod_sleep (dpy, 3))
1729 scrolling_puts (ts, msg2, 0);
1730 if (bsod_sleep (dpy, 2))
1733 for (i = 1; i <= 100; ++i)
1735 sprintf(buf, "\b\b\b\b\b\b\b\b\b\b\b%3d%% done", i);
1736 scrolling_puts (ts, buf, 0);
1737 if (bsod_sleep (dpy, -1))
1741 scrolling_puts (ts, msg3, 0);
1742 if (bsod_sleep (dpy, 2))
1745 scrolling_puts (ts, msg4, 0);
1746 if (bsod_sleep(dpy, 3))
1749 bsod_sleep (dpy, 3);
1752 free_scrolling_window (ts);
1755 /* Linux panic and fsck, by jwz
1758 linux_fsck (Display *dpy, Window window, int delay)
1760 XWindowAttributes xgwa;
1761 scrolling_window *ts;
1763 const char *sysname;
1766 const char *linux_panic[] = {
1767 " kernel: Unable to handle kernel paging request at virtual "
1768 "address 0000f0ad\n",
1769 " kernel: printing eip:\n",
1770 " kernel: c01becd7\n",
1771 " kernel: *pde = 00000000\n",
1772 " kernel: Oops: 0000\n",
1773 " kernel: CPU: 0\n",
1774 " kernel: EIP: 0010:[<c01becd7>] Tainted: P \n",
1775 " kernel: EFLAGS: 00010286\n",
1776 " kernel: eax: 0000ff00 ebx: ca6b7e00 ecx: ce1d7a60 edx: ce1d7a60\n",
1777 " kernel: esi: ca6b7ebc edi: 00030000 ebp: d3655ca0 esp: ca6b7e5c\n",
1778 " kernel: ds: 0018 es: 0018 ss: 0018\n",
1779 " kernel: Process crond (pid: 1189, stackpage=ca6b7000)\n",
1780 " kernel: Stack: d3655ca0 ca6b7ebc 00030054 ca6b7e7c c01c1e5b "
1781 "00000287 00000020 c01c1fbf \n",
1783 " kernel: 00005a36 000000dc 000001f4 00000000 00000000 "
1784 "ce046d40 00000001 00000000 \n",
1786 " kernel: ffffffff d3655ca0 d3655b80 00030054 c01bef93 "
1787 "d3655ca0 ca6b7ebc 00030054 \n",
1789 " kernel: Call Trace: [<c01c1e5b>] [<c01c1fbf>] [<c01bef93>] "
1790 "[<c01bf02b>] [<c0134c4f>]\n",
1792 " kernel: [<c0142562>] [<c0114f8c>] [<c0134de3>] [<c010891b>]\n",
1794 " kernel: Code: 2a 00 75 08 8b 44 24 2c 85 c0 74 0c 8b 44 24 58 83 48 18 "
1799 XGetWindowAttributes (dpy, window, &xgwa);
1800 XSetWindowBackground (dpy, window,
1801 get_pixel_resource("Linux.background",
1803 dpy, xgwa.colormap));
1804 XClearWindow(dpy, window);
1811 if (uname (&uts) >= 0)
1812 sysname = uts.nodename;
1813 s = strchr (sysname, '.');
1816 # endif /* !HAVE_UNAME */
1819 ts = make_scrolling_window (dpy, window, "Linux", False);
1821 scrolling_puts (ts, "waiting for X server to shut down ", 0);
1823 if (bsod_sleep (dpy, 0))
1826 "XIO: fatal IO error 2 (broken pipe) on X server \":0.0\"\n"
1827 " after 339471 requests (339471 known processed) "
1828 "with 0 events remaining\n",
1830 if (scrolling_puts (ts, ".........\n", 300000))
1832 if (bsod_sleep (dpy, 0))
1835 "xinit: X server slow to shut down, sending KILL signal.\n",
1837 scrolling_puts (ts, "waiting for server to die ", 0);
1838 if (scrolling_puts (ts, "...\n", 300000))
1840 if (bsod_sleep (dpy, 0))
1842 scrolling_puts (ts, "xinit: Can't kill server\n", 0);
1844 if (bsod_sleep (dpy, 2))
1847 sprintf (buf, "\n%s Login: ", sysname);
1848 scrolling_puts (ts, buf, 0);
1849 if (bsod_sleep (dpy, 1))
1853 "Parallelizing fsck version 1.22 (22-Jun-2001)\n"
1854 "e2fsck 1.22, 22-Jun-2001 for EXT2 FS 0.5b, 95/08/09\n"
1855 "Warning! /dev/hda1 is mounted.\n"
1856 "/dev/hda1 contains a file system with errors, check forced.\n",
1858 if (bsod_sleep (dpy, 1))
1861 if (0 == random() % 2)
1863 "Couldn't find ext2 superblock, trying backup blocks...\n"
1864 "The filesystem size (according to the superblock) is 3644739 blocks\n"
1865 "The physical size of the device is 3636706 blocks\n"
1866 "Either the superblock or the partition table is likely to be corrupt!\n"
1869 if (bsod_sleep (dpy, 1))
1874 scrolling_puts (ts, "Pass 1: Checking inodes, blocks, and sizes\n", 0);
1875 if (bsod_sleep (dpy, 2))
1878 i = (random() % 60) - 20;
1881 int b = random() % 0xFFFF;
1882 sprintf (buf, "Deleted inode %d has zero dtime. Fix<y>? yes\n\n", b);
1883 scrolling_puts (ts, buf, 0);
1886 i = (random() % 40) - 10;
1889 int g = random() % 0xFFFF;
1890 int b = random() % 0xFFFFFFF;
1892 if (bsod_sleep (dpy, 1))
1895 sprintf (buf, "Warning: Group %d's copy of the group descriptors "
1896 "has a bad block (%d).\n", g, b);
1897 scrolling_puts (ts, buf, 0);
1899 b = random() % 0x3FFFFF;
1902 b += random() % 0xFFFF;
1904 "Error reading block %d (Attempt to read block "
1905 "from filesystem resulted in short read) while doing "
1906 "inode scan. Ignore error<y>?",
1908 scrolling_puts (ts, buf, 0);
1910 scrolling_puts (ts, " yes\n\n", 0);
1914 if (0 == (random() % 10))
1917 if (bsod_sleep (dpy, 1))
1920 i = 3 + (random() % 10);
1922 scrolling_puts (ts, "Could not allocate 256 block(s) for inode table: "
1923 "No space left on device\n", 0);
1924 scrolling_puts (ts, "Restarting e2fsck from the beginning...\n", 0);
1926 if (bsod_sleep (dpy, 2))
1932 i = (random() % 20) - 5;
1935 if (bsod_sleep (dpy, 1))
1940 int j = 5 + (random() % 10);
1941 int w = random() % 4;
1945 int b = random() % 0xFFFFF;
1946 int g = random() % 0xFFF;
1948 if (0 == (random() % 10))
1950 else if (0 == (random() % 10))
1955 "Inode table for group %d not in group. (block %d)\n"
1956 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"
1961 "Block bitmap for group %d not in group. (block %d)\n"
1966 "Inode bitmap %d for group %d not in group.\n"
1969 else /* if (w == 3) */
1971 "Bad block %d in group %d's inode table.\n"
1972 "WARNING: SEVERE DATA LOSS POSSIBLE.\n"
1976 scrolling_puts (ts, buf, 0);
1977 scrolling_puts (ts, " yes\n\n", 0);
1979 if (bsod_sleep (dpy, 0))
1985 if (0 == random() % 10) goto PANIC;
1986 scrolling_puts (ts, "Pass 2: Checking directory structure\n", 0);
1987 if (bsod_sleep (dpy, 2))
1990 i = (random() % 20) - 5;
1993 int n = random() % 0xFFFFF;
1994 int o = random() % 0xFFF;
1995 sprintf (buf, "Directory inode %d, block 0, offset %d: "
1996 "directory corrupted\n"
1999 scrolling_puts (ts, buf, 0);
2001 scrolling_puts (ts, " yes\n\n", 0);
2003 if (0 == (random() % 100))
2005 sprintf (buf, "Missing '.' in directory inode %d.\nFix<y>?", n);
2006 scrolling_puts (ts, buf, 0);
2008 scrolling_puts (ts, " yes\n\n", 0);
2011 if (bsod_sleep (dpy, 0))
2015 if (0 == random() % 10) goto PANIC;
2017 "Pass 3: Checking directory connectivity\n"
2018 "/lost+found not found. Create? yes\n",
2020 if (bsod_sleep (dpy, 2))
2023 /* Unconnected directory inode 4949 (/var/spool/squid/06/???)
2024 Connect to /lost+found<y>? yes
2026 '..' in /var/spool/squid/06/08 (20351) is <The NULL inode> (0), should be
2027 /var/spool/squid/06 (20350).
2030 Unconnected directory inode 128337 (/var/spool/squid/06/???)
2031 Connect to /lost+found<y>? yes
2035 if (0 == random() % 10) goto PANIC;
2036 scrolling_puts (ts, "Pass 4: Checking reference counts\n", 0);
2037 if (bsod_sleep (dpy, 2))
2040 /* Inode 2 ref count is 19, should be 20. Fix<y>? yes
2042 Inode 4949 ref count is 3, should be 2. Fix<y>? yes
2046 Inode 128336 ref count is 3, should be 2. Fix<y>? yes
2048 Inode 128337 ref count is 3, should be 2. Fix<y>? yes
2053 if (0 == random() % 10) goto PANIC;
2054 scrolling_puts (ts, "Pass 5: Checking group summary information\n", 0);
2055 if (bsod_sleep (dpy, 2))
2058 i = (random() % 200) - 50;
2061 scrolling_puts (ts, "Block bitmap differences: ", 0);
2064 sprintf (buf, " %d", -(random() % 0xFFF));
2065 scrolling_puts (ts, buf, 0);
2068 scrolling_puts (ts, "\nFix? yes\n\n", 0);
2072 i = (random() % 100) - 50;
2075 scrolling_puts (ts, "Inode bitmap differences: ", 0);
2078 sprintf (buf, " %d", -(random() % 0xFFF));
2079 scrolling_puts (ts, buf, 0);
2082 scrolling_puts (ts, "\nFix? yes\n\n", 0);
2085 i = (random() % 20) - 5;
2088 int g = random() % 0xFFFF;
2089 int c = random() % 0xFFFF;
2091 "Free blocks count wrong for group #0 (%d, counted=%d).\nFix? ",
2093 scrolling_puts (ts, buf, 0);
2095 scrolling_puts (ts, " yes\n\n", 0);
2096 if (bsod_sleep (dpy, 0))
2103 scrolling_puts (ts, "\n\n", 0);
2104 while (linux_panic[i])
2106 time_t t = time ((time_t *) 0);
2107 struct tm *tm = localtime (&t);
2110 if (*linux_panic[i])
2112 strftime (prefix, sizeof(prefix)-1, "%b %d %H:%M:%S ", tm);
2113 scrolling_puts (ts, prefix, 0);
2114 scrolling_puts (ts, sysname, 0);
2115 scrolling_puts (ts, linux_panic[i], 0);
2122 if (bsod_sleep (dpy, 0))
2127 if (bsod_sleep (dpy, 4))
2132 bsod_sleep(dpy, delay);
2135 free_scrolling_window (ts);
2136 XClearWindow(dpy, window);
2139 /* VMS by jwz (text sent by Roland Barmettler <roli@barmettler.net>)
2142 vms (Display *dpy, Window window, int delay)
2144 XWindowAttributes xgwa;
2145 scrolling_window *ts;
2146 const char *sysname;
2148 int dot_delay = 40000;
2149 int chunk_delay = 500000;
2155 __extension__ /* don't warn about "string length is greater than the
2156 length ISO C89 compilers are required to support"
2157 in the following string constant... */
2160 const char *lines[] = {
2161 "%CNXMAN, Lost connection to system #\n"
2162 "%SHADOW-I-VOLPROC, DSA0: shadow master has changed. "
2163 "Dump file WILL be written if system crashes.\n"
2167 "%CNXMAN, Quorum lost, blocking activity\n"
2168 "%CNXMAN, Timed-out lost connection to system #\n"
2169 "%CNXMAN, Timed-out lost connection to system #\n"
2170 "%CNXMAN, Timed-out lost connection to system #\n"
2171 "%CNXMAN, Proposing reconfiguration of the VMScluster\n",
2174 "%CNXMAN, Removed from VMScluster system #\n"
2175 "%CNXMAN, Removed from VMScluster system #\n"
2176 "%CNXMAN, Removed from VMScluster system #\n"
2177 "%CNXMAN, Completing VMScluster state transition\n",
2180 "**** OpenVMS (TM) Alpha Operating system V7.3-1 - BUGCHECK ****\n"
2182 "** Bugcheck code = 000005DC: CLUEXIT, Node voluntarily exiting "
2184 "** Crash CPU: 00 Primary CPU: 00 Active CPUs: 00000001\n"
2185 "** Current Process = NULL\n"
2186 "** Current PSB ID = 00000001\n"
2189 "** Dumping error log buffers to HBVS unit 0\n"
2190 "**** Unable to dump error log buffers to remaining shadow set members\n"
2191 "** Error log buffers not dumped to HBVS unit 200\n"
2193 "** Dumping memory to HBVS unit 0\n"
2194 "**** Starting compressed selective memory dump at #...\n",
2199 "**** Memory dump complete - not all processes or global pages saved\n",
2207 "HALT instruction executed\n"
2208 "PC = ffffffff800c3884\n",
2214 "resetting all I/O buses\n"
2220 XGetWindowAttributes (dpy, window, &xgwa);
2221 ts = make_scrolling_window (dpy, window, "VMS", False);
2222 XClearWindow(dpy,window);
2225 ts->sub_width = xgwa.width;
2226 ts->sub_height = xgwa.height;
2232 if (uname (&uts) >= 0)
2233 sysname = uts.nodename;
2234 s = strchr (sysname, '.');
2237 # endif /* !HAVE_UNAME */
2239 args[0] = malloc (strlen(sysname) + 7);
2240 strcpy (args[0], sysname);
2243 i = strlen(args[0])-1;
2245 args[0][i] = '1' + (random() % 9);
2248 for (s = args[0]; *s; s++)
2249 if (isalpha(*s)) *s = toupper (*s);
2251 args[1] = strdup (args[0]);
2252 args[2] = strdup (args[0]); args[2][i] = '1' + (random() % 9);
2253 args[3] = strdup (args[0]); args[3][i] = '1' + (random() % 9);
2255 args[4] = strdup (args[1]);
2256 args[5] = strdup (args[2]);
2257 args[6] = strdup (args[3]);
2260 time_t t = time ((time_t *) 0);
2261 struct tm *tm = localtime (&t);
2262 args[7] = malloc (30);
2263 strftime (args[7], 29, "%d-%b-%Y %H:%M", tm);
2264 for (s = args[7]; *s; s++)
2265 if (isalpha(*s)) *s = toupper (*s);
2269 for (i = 0; i < countof(lines); i++)
2271 const char *fmt = lines[i];
2272 if (! strcmp (fmt, "..."))
2274 int steps = 180 + (random() % 60);
2275 while (--steps >= 0)
2277 scrolling_puts (ts, ".", 0);
2280 if (bsod_sleep (dpy, 0))
2286 char *fmt2 = malloc (strlen (fmt) * 2 + 1);
2287 for (s = (char *) fmt, s1 = fmt2; *s; s++)
2291 strcpy (s1, args[arg_count++]);
2298 scrolling_puts (ts, fmt2, char_delay);
2300 usleep (chunk_delay);
2301 if (bsod_sleep (dpy, 0))
2307 bsod_sleep(dpy, delay);
2310 free_scrolling_window (ts);
2311 for (i = 0; i < countof (args); i++)
2318 /* HPUX panic, by Tobias Klausmann <klausman@schwarzvogel.de>
2322 hpux (Display* dpy, Window window, int delay)
2324 XWindowAttributes xgwa;
2325 scrolling_window *ts;
2326 const char *sysname;
2330 __extension__ /* don't warn about "string length is greater than the
2331 length ISO C89 compilers are required to support"
2332 in the following string constant... */
2338 " ******* Unexpected HPMC/TOC. Processor HPA FFFFFFFF'"
2339 "FFFA0000 *******\n"
2340 " GENERAL REGISTERS:\n"
2341 "r00/03 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2343 "r04/07 00000000'00000001 00000000'0126E328 00000000'00000000 00000000'"
2345 "r08/11 00000000'00000000 00000000'0198CFC0 00000000'000476FE 00000000'"
2347 "r12/15 00000000'40013EE8 00000000'08000080 00000000'4002530C 00000000'"
2349 "r16/19 00000000'7F7F2A00 00000000'00000001 00000000'00000000 00000000'"
2351 "r20/23 00000000'006C8048 00000000'00000001 00000000'00000000 00000000'"
2353 "r24/27 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2355 "r28/31 00000000'00000000 00000000'007DD628 00000000'0199F2B0 00000000'"
2357 " CONTROL REGISTERS:\n"
2358 "sr0/3 00000000'0F3B4000 00000000'0C2A2000 00000000'016FF800 00000000'"
2360 "sr4/7 00000000'00000000 00000000'016FF800 00000000'0DBF1400 00000000'"
2362 "pcq = 00000000'00000000.00000000'00104950 00000000'00000000.00000000'"
2364 "isr = 00000000'10240006 ior = 00000000'67D9E220 iir = 08000240 rctr = "
2367 "pid reg cr8/cr9 00007700'0000B3A9 00000000'0000C5D8\n"
2368 "pid reg cr12/cr13 00000000'00000000 00000000'00000000\n"
2369 "ipsw = 000000FF'080CFF1F iva = 00000000'0002C000 sar = 3A ccr = C0\n"
2370 "tr0/3 00000000'006C76C0 00000000'00000001 00000000'00000000 00000000'"
2372 "tr4/7 00000000'03790000 0000000C'4FB68340 00000000'C07EE13F 00000000'"
2374 "eiem = FFFFFFF0'FFFFFFFF eirr = 80000000'00000000 itmr = 0000000C'"
2376 "cr1/4 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2378 "cr5/7 00000000'00000000 00000000'00000000 00000000'"
2380 " MACHINE CHECK PARAMETERS:\n"
2381 "Check Type = 00000000 CPU STATE = 9E000001 Cache Check = 00000000\n"
2382 "TLB Check = 00000000 Bus Check = 00000000 PIM State = ? SIU "
2383 "Status = ????????\n"
2384 "Assists = 00000000 Processor = 00000000\n"
2385 "Slave Addr = 00000000'00000000 Master Addr = 00000000'00000000\n"
2388 "TOC, pcsq.pcoq = 0'0.0'104950 , isr.ior = 0'10240006.0'67d9e220\n"
2389 "@(#)B2352B/9245XB HP-UX (B.11.00) #1: Wed Nov 5 22:38:19 PST 1997\n"
2390 "Transfer of control: (display==0xd904, flags==0x0)\n"
2394 "*** A system crash has occurred. (See the above messages for details.)\n"
2395 "*** The system is now preparing to dump physical memory to disk, for use\n"
2396 "*** in debugging the crash.\n"
2398 "*** The dump will be a SELECTIVE dump: 40 of 256 megabytes.\n"
2399 "*** To change this dump type, press any key within 10 seconds.\n"
2400 "*** Proceeding with selective dump.\n"
2402 "*** The dump may be aborted at any time by pressing ESC.\n";
2404 "\n*** System rebooting.\n";
2406 XGetWindowAttributes (dpy, window, &xgwa);
2407 ts = make_scrolling_window (dpy, window, "HPUX", False);
2408 XClearWindow(dpy,window);
2409 ts->columns = 10000; /* never wrap */
2412 ts->sub_width = xgwa.width;
2413 ts->sub_height = xgwa.height;
2420 if (uname (&uts) >= 0)
2421 sysname = uts.nodename;
2422 s = strchr (sysname, '.');
2425 # endif /* !HAVE_UNAME */
2427 if (bsod_sleep (dpy, 1))
2435 sprintf (buf, "%.100s [HP Release B.11.00] (see /etc/issue)\n", sysname);
2436 scrolling_puts (ts, buf, 0);
2437 if (bsod_sleep (dpy, 1))
2439 scrolling_puts (ts, msg1, 0);
2444 for (i = 0; i <= steps; i++)
2446 if (i > steps) i = steps;
2448 "*** Dumping: %3d%% complete (%d of 40 MB) (device 64:0x2)\r",
2451 scrolling_puts (ts, buf, 0);
2454 if (bsod_sleep (dpy, 0))
2459 scrolling_puts (ts, msg2, 0);
2462 bsod_sleep(dpy, delay);
2465 free_scrolling_window (ts);
2470 /* IBM OS/390 aka MVS aka z/OS.
2471 Text from Dan Espen <dane@mk.telcordia.com>.
2472 Apparently this isn't actually a crash, just a random session...
2477 os390 (Display* dpy, Window window, int delay)
2481 XWindowAttributes xgwa;
2482 scrolling_window *ts;
2485 const char *msg[] = {
2486 "* ISPF Subtask abend *\n",
2487 "SPF ENDED DUE TO ERROR+\n",
2490 "IEA995I SYMPTOM DUMP OUTPUT\n",
2491 " USER COMPLETION CODE=0222\n",
2492 " TIME=23.00.51 SEQ=03210 CPU=0000 ASID=00AE\n",
2493 " PSW AT TIME OF ERROR 078D1000 859DAF18 ILC 2 INTC 0D\n",
2494 " NO ACTIVE MODULE FOUND\n",
2496 " DATA AT PSW 059DAF12 - 00181610 0A0D9180 70644710\n",
2497 " AR/GR 0: 00000000/80000000 1: 00000000/800000DE\n",
2498 " 2: 00000000/196504DC 3: 00000000/00037A78\n",
2499 " 4: 00000000/00037B78 5: 00000000/0003351C\n",
2500 " 6: 00000000/0000F0AD 7: 00000000/00012000\n",
2501 " 8: 00000000/059DAF10 9: 00000000/0002D098\n",
2502 " A: 00000000/059D9F10 B: 00000000/059D8F10\n",
2503 " C: 00000000/859D7F10 D: 00000000/00032D60\n",
2504 " E: 00000000/00033005 F: 01000002/00000041\n",
2505 " END OF SYMPTOM DUMP\n",
2506 "ISPS014 - ** Logical screen request failed - abend 0000DE **\n",
2507 "ISPS015 - ** Contact your system programmer or dialog developer.**\n",
2508 "*** ISPF Main task abend ***\n",
2509 "IEA995I SYMPTOM DUMP OUTPUT\n",
2510 " USER COMPLETION CODE=0222\n",
2511 " TIME=23.00.52 SEQ=03211 CPU=0000 ASID=00AE\n",
2512 " PSW AT TIME OF ERROR 078D1000 8585713C ILC 2 INTC 0D\n",
2513 " ACTIVE LOAD MODULE ADDRESS=05855000 OFFSET=0000213C\n",
2515 " DATA AT PSW 05857136 - 00181610 0A0D9180 D3304770\n",
2516 " GR 0: 80000000 1: 800000DE\n",
2517 " 2: 00015260 3: 00000038\n",
2518 " 4: 00012508 5: 00000000\n",
2519 " 6: 000173AC 7: FFFFFFF8\n",
2520 " 8: 05858000 9: 00012CA0\n",
2521 " A: 05857000 B: 05856000\n",
2522 " C: 85855000 D: 00017020\n",
2523 " E: 85857104 F: 00000000\n",
2524 " END OF SYMPTOM DUMP\n",
2529 XGetWindowAttributes (dpy, window, &xgwa);
2530 ts = make_scrolling_window (dpy, window, "OS390", False);
2531 ts->columns = 10000; /* never wrap */
2534 ts->sub_width = xgwa.width;
2535 ts->sub_height = xgwa.height;
2537 gcv.foreground = get_pixel_resource ("390.background", "390.Background",
2538 dpy, xgwa.colormap);
2539 gc = XCreateGC (dpy, window, GCForeground, &gcv);
2540 XFillRectangle (dpy, window, gc, 0, 0, xgwa.width, xgwa.height);
2543 for (i = 0; i < countof (msg); i++)
2545 scrolling_puts (ts, msg[i], 0);
2547 if (bsod_sleep(dpy, 0)) goto DONE;
2551 bsod_sleep(dpy, delay);
2553 free_scrolling_window (ts);
2559 * Simulate various Apple II crashes. The memory map encouraged many
2560 * programs to use the primary hi-res video page for various storage,
2561 * and the secondary hi-res page for active display. When it crashed
2562 * into Applesoft or the monitor, it would revert to the primary page
2563 * and you'd see memory garbage on the screen. Also, it was common for
2564 * copy-protected games to use the primary text page for important
2565 * code, because that made it really hard to reverse-engineer them. The
2566 * result often looked like what this generates.
2568 * Sometimes an imaginary user types some of the standard commands to
2569 * recover from crashes. You can turn off BSOD*apple2SimulateUser to
2572 * It simulates the following characteristics of standard television
2575 * - Realistic rendering of a composite video signal
2576 * - Compression & brightening on the right, as the scan gets truncated
2577 * because of saturation in the flyback transformer
2578 * - Blooming of the picture dependent on brightness
2579 * - Overscan, cutting off a few pixels on the left side.
2580 * - Colored text in mixed graphics/text modes
2582 * It's amazing how much it makes your high-end monitor look like at
2583 * large late-70s TV. All you need is to put a big "Solid State" logo
2584 * in curly script on it and you'd be set.
2586 * Trevor Blackwell <tlb@tlb.org>
2590 * Implementation notes:
2592 * There are roughly 3 parts to this hack:
2594 * - emulation of A2 Basic and Monitor. Not much more than printing random
2595 * plausible messages. Here we work in the A2 memory space.
2597 * - emulation of the A2's video output section, which shifted bits out of main
2598 * memory at a 14 MHz dot clock rate, sort of. You could only read one byte
2599 * per MHz, so there were various schemes for turning 8 bits into 14 screen
2602 * - simulation of an NTSC television, which turned the bits into colored
2603 * graphics and text.
2605 * The A2 had 3 display modes: text, lores, and hires. Text was 40x24, and it
2606 * disabled color in the TV. Lores gave you 40x48 graphics blocks, using the
2607 * same memory as the text screen. Each could be one of 16 colors. Hires gave
2608 * you 280x192 pixels. Odd pixels were blue or purple, and even pixels were
2609 * orange or green depending on the setting of the high bit in each byte.
2611 * The graphics modes could also have 4 lines of text at the bottom. This was
2612 * fairly unreadable if you had a color monitor.
2614 * Each mode had 2 different screens using different memory space. In hires
2615 * mode this was sometimes used for double buffering, but more often the lower
2616 * screen was full of code/data and the upper screen was used for display, so
2617 * you got random garbage on the screen.
2619 * In DirectColor or TrueColor modes, it generates pixel values directly from
2620 * RGB values it calculates across each scan line. In PseudoColor mode, it
2621 * consider each possible pattern of 5 preceding bit values in each possible
2622 * position modulo 4 and allocates a color for each. A few things, like the
2623 * brightening on the right side as the horizontal trace slows down, aren't
2624 * done in PseudoColor.
2626 * The text font is based on X's standard 6x10 font, with a few tweaks like
2627 * putting a slash across the zero.
2629 * I'd like to add a bit of visible retrace, but it conflicts with being able
2630 * to bitcopy the image when fast scrolling. After another couple of CPU
2631 * generations, we could probably regenerate the whole image from scratch every
2632 * time. On a P4 2 GHz it can manage this fine for blinking text, but scrolling
2636 static char * apple2_basic_errors[]={
2640 "RETURN WITHOUT GOSUB",
2644 "BAD SUBSCRIPT ERROR",
2647 "FORMULA TOO COMPLEX",
2651 static char * apple2_dos_errors[]={
2655 "NO BUFFERS AVAILABLE",
2656 "PROGRAM TOO LARGE",
2659 struct apple2_state {
2660 char hireslines[192][40];
2661 char textlines[24][40];
2681 a2_scroll(struct apple2_state *st)
2684 int top=(st->gr_mode&(A2_GR_LORES|A2_GR_HIRES)) ? 20 : 0;
2685 if ((st->gr_mode&A2_GR_FULL) && (st->gr_mode&A2_GR_HIRES)) return;
2686 if (st->gr_mode&A2_GR_FULL) top=0;
2687 for (i=top; i<23; i++) {
2688 if (memcmp(st->textlines[i],st->textlines[i+1],40)) {
2689 memcpy(st->textlines[i],st->textlines[i+1],40);
2690 st->rowimage[i]=st->rowimage[i+1];
2693 memset(st->textlines[23],0xe0,40);
2694 st->rowimage[23]=-1;
2698 a2_printc(struct apple2_state *st, char c)
2700 st->textlines[st->cursy][st->cursx] |= 0xc0; /* turn off blink */
2702 if (st->cursy==23) {
2705 st->rowimage[st->cursy]=-1;
2707 st->rowimage[st->cursy]=-1;
2711 st->textlines[st->cursy][st->cursx]=c ^ 0xc0;
2712 st->rowimage[st->cursy]=-1;
2714 if (st->cursx==40) {
2715 if (st->cursy==23) {
2718 st->rowimage[st->cursy]=-1;
2720 st->rowimage[st->cursy]=-1;
2725 st->textlines[st->cursy][st->cursx] &= 0x7f; /* turn on blink */
2729 a2_goto(struct apple2_state *st, int r, int c)
2731 st->textlines[st->cursy][st->cursx] |= 0xc0; /* turn off blink */
2734 st->textlines[st->cursy][st->cursx] &= 0x7f; /* turn on blink */
2738 a2_cls(struct apple2_state *st)
2741 for (i=0; i<24; i++) {
2742 memset(st->textlines[i],0xe0,40);
2748 a2_invalidate(struct apple2_state *st)
2751 for (i=0; i<24; i++) {
2757 a2_poke(struct apple2_state *st, int addr, int val)
2760 if (addr>=0x400 && addr<0x800) {
2762 int row=((addr&0x380)/0x80) + ((addr&0x7f)/0x28)*8;
2763 int col=(addr&0x7f)%0x28;
2764 if (row<24 && col<40) {
2765 st->textlines[row][col]=val;
2766 if (!(st->gr_mode&(A2_GR_HIRES)) ||
2767 (!(st->gr_mode&(A2_GR_FULL)) && row>=20)) {
2768 st->rowimage[row]=-1;
2772 else if (addr>=0x2000 && addr<0x4000) {
2773 int row=(((addr&0x1c00) / 0x400) * 1 +
2774 ((addr&0x0380) / 0x80) * 8 +
2775 ((addr&0x0078) / 0x28) * 64);
2776 int col=((addr&0x07f)%0x28);
2777 if (row<192 && col<40) {
2778 st->hireslines[row][col]=val;
2779 if (st->gr_mode&A2_GR_HIRES) {
2780 st->rowimage[row/8]=-1;
2786 /* This table lists fixes for characters that differ from the standard 6x10
2787 font. Each encodes a pixel, as (charindex*7 + x) + (y<<10) + (value<<15)
2788 where value is 0 for white and 1 for black. */
2789 static unsigned short a2_fixfont[] = {
2790 /* Fix $ */ 0x8421, 0x941d,
2791 /* Fix % */ 0x8024, 0x0028, 0x8425, 0x0426, 0x0825, 0x1027, 0x1426, 0x9427,
2793 /* Fix * */ 0x8049, 0x8449, 0x8849, 0x0c47, 0x0c48, 0x0c4a, 0x0c4b, 0x9049,
2795 /* Fix , */ 0x9057, 0x1458, 0x9856, 0x1857, 0x1c56,
2796 /* Fix . */ 0x1465, 0x1864, 0x1866, 0x1c65,
2797 /* Fix / */ 0x006e, 0x186a,
2798 /* Fix 0 */ 0x8874, 0x8c73, 0x9072,
2799 /* Fix 1 */ 0x0878, 0x1878, 0x187c,
2800 /* Fix 5 */ 0x8895, 0x0c94, 0x0c95,
2801 /* Fix 6 */ 0x809f, 0x8c9c, 0x109c,
2802 /* Fix 7 */ 0x8ca4, 0x0ca5, 0x90a3, 0x10a4,
2803 /* Fix 9 */ 0x08b3, 0x8cb3, 0x98b0,
2804 /* Fix : */ 0x04b9, 0x08b8, 0x08ba, 0x0cb9, 0x90b9, 0x14b9, 0x18b8, 0x18b9,
2806 /* Fix ; */ 0x04c0, 0x08bf, 0x08c1, 0x0cc0, 0x90c0, 0x14c1, 0x98bf, 0x18c0,
2808 /* Fix < */ 0x80c8, 0x00c9, 0x84c7, 0x04c8, 0x88c6, 0x08c7, 0x8cc5, 0x0cc6,
2810 0x94c7, 0x14c8, 0x98c8, 0x18c9,
2811 /* Fix > */ 0x80d3, 0x00d4, 0x84d4, 0x04d5, 0x88d5, 0x08d6, 0x8cd6, 0x0cd7,
2813 0x94d4, 0x14d5, 0x98d3, 0x18d4,
2814 /* Fix @ */ 0x88e3, 0x08e4, 0x8ce4, 0x98e5,
2815 /* Fix B */ 0x84ef, 0x04f0, 0x88ef, 0x08f0, 0x8cef, 0x90ef, 0x10f0, 0x94ef,
2817 /* Fix D */ 0x84fd, 0x04fe, 0x88fd, 0x08fe, 0x8cfd, 0x0cfe, 0x90fd, 0x10fe,
2819 /* Fix G */ 0x8116, 0x0516, 0x9916,
2820 /* Fix J */ 0x0129, 0x012a, 0x052a, 0x852b, 0x092a, 0x892b, 0x0d2a, 0x8d2b,
2822 0x152a, 0x952b, 0x992a,
2823 /* Fix M */ 0x853d, 0x853f, 0x093d, 0x893e, 0x093f,
2824 /* Fix Q */ 0x915a, 0x155a, 0x955b, 0x155c, 0x195b, 0x995c, 0x1d5c,
2825 /* Fix V */ 0x8d7b, 0x0d7c, 0x0d7e, 0x8d7f, 0x917b, 0x117c, 0x117e, 0x917f,
2826 /* Fix [ */ 0x819e, 0x81a2, 0x859e, 0x899e, 0x8d9e, 0x919e, 0x959e, 0x999e,
2828 /* Fix \ */ 0x01a5, 0x19a9,
2829 /* Fix ] */ 0x81ac, 0x81b0, 0x85b0, 0x89b0, 0x8db0, 0x91b0, 0x95b0, 0x99ac,
2831 /* Fix ^ */ 0x01b5, 0x05b4, 0x05b6, 0x09b3, 0x89b5, 0x09b7, 0x8db4, 0x8db6,
2833 /* Fix _ */ 0x9db9, 0x9dbf,
2844 int brightness_control;
2848 First generate the I and Q reference signals, which we'll multiply by the
2849 input signal to accomplish the demodulation. Normally they are shifted 33
2850 degrees from the colorburst. I think this was convenient for
2851 inductor-capacitor-vacuum tube implementation.
2853 The tint control, FWIW, just adds a phase shift to the chroma signal, and
2854 the color control controls the amplitude.
2856 In text modes (colormode==0) the system disabled the color burst, and no
2857 color was detected by the monitor.
2859 freq_error gives a mismatch between the built-in oscillator and the TV's
2860 colorbust. Older II Plus machines seemed to occasionally get instability
2861 problems -- the crystal oscillator was a single transistor if I remember
2862 correctly -- and the frequency would vary enough that the tint would change
2863 across the width of the screen. The left side would be in correct tint
2864 because it had just gotten resynchronized with the color burst.
2867 ntsc_set_demod(struct ntsc_dec *it, double tint_control,
2868 double color_control, double brightness_control,
2874 it->brightness_control=(int)(1024.0*brightness_control);
2876 for (i=0; i<600; i++) {
2877 double phase=90.0-90.0*i + freq_error*i/600.0 + tint_control;
2878 it->multi[i]=(int)(-cos(3.1415926/180.0*(phase-303)) * 65536.0 *
2879 color_control * colormode * 4);
2880 it->multq[i]=(int)(cos(3.1415926/180.0*(phase-33)) * 65536.0 *
2881 color_control * colormode * 4);
2885 /* Here we model the analog circuitry of an NTSC television. Basically, it
2886 splits the signal into 3 signals: Y, I and Q. Y corresponds to luminance,
2887 and you get it by low-pass filtering the input signal to below 3.57 MHz.
2889 I and Q are the in-phase and quadrature components of the 3.57 MHz
2890 subcarrier. We get them by multiplying by cos(3.57 MHz*t) and sin(3.57
2891 MHz*t), and low-pass filtering. Because the eye has less resolution in some
2892 colors than others, the I component gets low-pass filtered at 1.5 MHz and
2893 the Q at 0.5 MHz. The I component is approximately orange-blue, and Q is
2894 roughly purple-green. See http://www.ntsc-tv.com for details.
2897 ntsc_to_yiq(struct ntsc_dec *it)
2900 int fyx[10],fyy[10];
2901 int fix[10],fiy[10];
2902 int fqx[10],fqy[10];
2904 int iny,ini,inq,pix,blank;
2906 for (i=0; i<10; i++) fyx[i]=fyy[i]=fix[i]=fiy[i]=fqx[i]=fqy[i]=0.0;
2908 for (i=0; i<600; i++) {
2909 /* Get the video out signal, and add a teeny bit of ghosting, typical of RF
2910 monitor cables. This corresponds to a pretty long cable, but looks right
2912 pix=it->pattern[i]*1024;
2913 if (i>=20) pixghost += it->pattern[i-20]*15;
2914 if (i>=30) pixghost -= it->pattern[i-30]*15;
2917 /* Get Y, I, Q before filtering */
2919 ini=(pix*it->multi[i])>>16;
2920 inq=(pix*it->multq[i])>>16;
2922 blank = (i>=7 && i<596 ? it->brightness_control : -200);
2924 /* Now filter them. These are infinite impulse response filters calculated
2925 by the script at http://www-users.cs.york.ac.uk/~fisher/mkfilter. This
2926 is fixed-point integer DSP, son. No place for wimps. We do it in integer
2927 because you can count on integer being faster on most CPUs. We care
2928 about speed because we need to recalculate every time we blink text, and
2929 when we spew random bytes into screen memory. This is roughly 16.16
2930 fixed point arithmetic, but we scale some filter values up by a few bits
2931 to avoid some nasty precision errors. */
2933 /* Filter y at with a 4-pole low-pass Butterworth filter at 3.5 MHz
2934 with an extra zero at 3.5 MHz, from
2935 mkfilter -Bu -Lp -o 4 -a 2.1428571429e-01 0 -Z 2.5e-01 -l
2938 fyx[0] = fyx[1]; fyx[1] = fyx[2]; fyx[2] = fyx[3];
2939 fyx[3] = fyx[4]; fyx[4] = fyx[5]; fyx[5] = fyx[6];
2940 fyx[6] = (iny * 1897) >> 13;
2941 fyy[0] = fyy[1]; fyy[1] = fyy[2]; fyy[2] = fyy[3];
2942 fyy[3] = fyy[4]; fyy[4] = fyy[5]; fyy[5] = fyy[6];
2943 fyy[6] = (fyx[0]+fyx[6]) + 4*(fyx[1]+fyx[5]) + 7*(fyx[2]+fyx[4]) + 8*fyx[3]
2944 + ((-151*fyy[2] + 8115*fyy[3] - 38312*fyy[4] + 36586*fyy[5]) >> 16);
2945 if (i>=2) it->ntscy[i-2] = blank + (fyy[6]>>3);
2947 /* Filter I and Q at 1.5 MHz. 3 pole Butterworth from
2948 mkfilter -Bu -Lp -o 3 -a 1.0714285714e-01 0
2951 The NTSC spec says the Q value should be filtered at 0.5 MHz at the
2952 transmit end, But the Apple's video circuitry doesn't any such thing.
2953 AFAIK, oldish televisions (before comb filters) simply applied a 1.5 MHz
2954 filter to both after the demodulator.
2957 fix[0] = fix[1]; fix[1] = fix[2]; fix[2] = fix[3];
2958 fix[3] = (ini * 1413) >> 14;
2959 fiy[0] = fiy[1]; fiy[1] = fiy[2]; fiy[2] = fiy[3];
2960 fiy[3] = (fix[0]+fix[3]) + 3*(fix[1]+fix[2])
2961 + ((16559*fiy[0] - 72008*fiy[1] + 109682*fiy[2]) >> 16);
2962 if (i>=3) it->ntsci[i-3] = fiy[3]>>2;
2964 fqx[0] = fqx[1]; fqx[1] = fqx[2]; fqx[2] = fqx[3];
2965 fqx[3] = (inq * 1413) >> 14;
2966 fqy[0] = fqy[1]; fqy[1] = fqy[2]; fqy[2] = fqy[3];
2967 fqy[3] = (fqx[0]+fqx[3]) + 3*(fqx[1]+fqx[2])
2968 + ((16559*fqy[0] - 72008*fqy[1] + 109682*fqy[2]) >> 16);
2969 if (i>=3) it->ntscq[i-3] = fqy[3]>>2;
2972 for (; i<610; i++) {
2973 if (i-2<600) it->ntscy[i-2]=0;
2974 if (i-3<600) it->ntsci[i-3]=0;
2975 if (i-9<600) it->ntscq[i-9]=0;
2985 #define A2_CMAP_INDEX(COLORMODE, LEVEL, HIST, OFFSET) \
2986 ((((COLORMODE)*A2_CMAP_LEVELS+(LEVEL))<<A2_CMAP_HISTBITS)+(HIST))* \
2987 A2_CMAP_OFFSETS+(OFFSET)
2990 apple2(Display *dpy, Window window, int delay)
2992 int w,h,i,j,x,y,textrow,row,col,stepno,colormode,imgrow;
2994 struct timeval basetime_tv;
2995 double next_actiontime;
2996 XWindowAttributes xgwa;
2998 int screen_xo,screen_yo;
3002 XImage *text_im=NULL;
3003 unsigned long colors[A2_CMAP_INDEX(1, A2_CMAP_LEVELS-1,
3004 (1<<A2_CMAP_HISTBITS)-1,
3005 A2_CMAP_OFFSETS-3)+1];
3007 int screen_plan[24];
3008 struct ntsc_dec *dec=NULL;
3009 short *raw_rgb=NULL, *rrp;
3010 struct apple2_state *st=NULL;
3011 char *typing=NULL,*printing=NULL;
3012 char printbuf[1024];
3015 double tint_control,color_control,brightness_control,contrast_control;
3016 double freq_error=0.0,freq_error_inc=0.0;
3017 double horiz_desync=5.0;
3018 int flutter_horiz_desync=0;
3020 double crtload[192];
3021 int red_invprec,red_shift,green_invprec,green_shift,blue_invprec,blue_shift;
3022 int fillptr, fillbyte;
3023 int use_shm,use_cmap,use_color;
3024 /* localbyteorder is 1 if MSB first, 0 otherwise */
3025 unsigned int localbyteorder_loc = MSBFirst<<24;
3026 int localbyteorder=*(char *)&localbyteorder_loc;
3027 #ifdef HAVE_XSHM_EXTENSION
3028 XShmSegmentInfo shm_info;
3031 #ifdef HAVE_XSHM_EXTENSION
3032 use_shm=get_boolean_resource ("useSHM", "Boolean");
3037 /* Model the video controls on a standard television */
3038 tint_control = get_float_resource("apple2TVTint","Apple2TVTint");
3039 color_control = get_float_resource("apple2TVColor","Apple2TVColor")/100.0;
3040 brightness_control = get_float_resource("apple2TVBrightness",
3041 "Apple2TVBrightness") / 100.0;
3042 contrast_control = get_float_resource("apple2TVContrast",
3043 "Apple2TVContrast") / 100.0;
3044 simulate_user = get_boolean_resource("apple2SimulateUser",
3045 "Apple2SimulateUser");
3047 XGetWindowAttributes (dpy, window, &xgwa);
3048 visclass=xgwa.visual->class;
3049 red_shift=red_invprec=green_shift=green_invprec=blue_shift=blue_invprec=-1;
3050 if (visclass == TrueColor || xgwa.visual->class == DirectColor) {
3054 else if (visclass == PseudoColor || visclass == StaticColor) {
3063 /* The Apple II screen was 280x192, sort of. We expand the width to 300
3064 pixels to allow for overscan. We then pick a size within the window
3065 that's an integer multiple of 300x192. The small case happens when
3066 we're displaying in a subwindow. Then it ends up showing the center
3067 of the screen, which is OK. */
3069 h = (xgwa.height/192)*192;
3073 dec=(struct ntsc_dec *)malloc(sizeof(struct ntsc_dec));
3076 int hist,offset,level;
3081 /* Typically allocates 214 distinct colors, but will scale back its
3082 ambitions pretty far if it can't get them */
3083 for (colormode=0; colormode<=use_color; colormode++) {
3084 ntsc_set_demod(dec, tint_control, color_control, brightness_control,
3086 for (level=0; level<2; level++) {
3087 for (hist=0; hist<(1<<A2_CMAP_HISTBITS); hist++) {
3088 for (offset=0; offset<4; offset++) {
3089 int interpy,interpi,interpq,r,g,b;
3090 int levelmult=level ? 64 : 32;
3091 int prec=colormode ? colorprec : (colorprec*2+2)/3;
3092 int precmask=(0xffff<<(16-prec))&0xffff;
3095 if (A2_CMAP_INDEX(colormode,level,hist,offset) != n_colors) {
3096 fprintf(stderr, "apple2: internal colormap allocation error\n");
3100 for (i=0; i<600; i++) dec->pattern[i]=0;
3101 for (i=0; i<A2_CMAP_HISTBITS; i++) {
3102 dec->pattern[64+offset-i]=(hist>>i)&1;
3106 interpy=dec->ntscy[63+offset];
3107 interpi=dec->ntsci[63+offset];
3108 interpq=dec->ntscq[63+offset];
3110 r=(interpy + ((+68128*interpi+40894*interpq)>>16))*levelmult;
3111 g=(interpy + ((-18087*interpi-41877*interpq)>>16))*levelmult;
3112 b=(interpy + ((-72417*interpi+113312*interpq)>>16))*levelmult;
3114 if (r>65535) r=65535;
3116 if (g>65535) g=65535;
3118 if (b>65535) b=65535;
3120 col.red=r & precmask;
3121 col.green=g & precmask;
3122 col.blue=b & precmask;
3124 if (!XAllocColor(dpy, xgwa.colormap, &col)) {
3125 XFreeColors(dpy, xgwa.colormap, colors, n_colors, 0L);
3133 colors[n_colors++]=col.pixel;
3139 /* Is there a standard way to do this? Does this handle all cases? */
3141 for (shift=0; shift<32; shift++) {
3142 for (prec=1; prec<16 && prec<32-shift; prec++) {
3143 unsigned long mask=(0xffffUL>>(16-prec)) << shift;
3144 if (red_shift<0 && mask==xgwa.visual->red_mask)
3145 red_shift=shift, red_invprec=16-prec;
3146 if (green_shift<0 && mask==xgwa.visual->green_mask)
3147 green_shift=shift, green_invprec=16-prec;
3148 if (blue_shift<0 && mask==xgwa.visual->blue_mask)
3149 blue_shift=shift, blue_invprec=16-prec;
3152 if (red_shift<0 || green_shift<0 || blue_shift<0) {
3153 if (0) fprintf(stderr,"Can't figure out color space\n");
3156 raw_rgb=(short *)calloc(w*3, sizeof(short));
3160 gc = XCreateGC(dpy, window, GCBackground, &gcv);
3161 XSetWindowBackground(dpy, window, gcv.background);
3162 XClearWindow(dpy,window);
3164 screen_xo=(xgwa.width-w)/2;
3165 screen_yo=(xgwa.height-h)/2;
3168 #ifdef HAVE_XSHM_EXTENSION
3169 image = create_xshm_image (dpy, xgwa.visual, xgwa.depth, ZPixmap, 0,
3173 fprintf(stderr, "create_xshm_image failed\n");
3178 image = XCreateImage(dpy, xgwa.visual, xgwa.depth, ZPixmap, 0, 0,
3180 image->data = (char *)calloc(image->height, image->bytes_per_line);
3183 st=(struct apple2_state *)calloc(1,sizeof(struct apple2_state));
3186 Generate the font. It used a 5x7 font which looks a lot like the standard X
3187 6x10 font, with a few differences. So we render up all the uppercase
3188 letters of 6x10, and make a few tweaks (like putting a slash across the
3189 zero) according to fixfont.
3192 const char *def_font="6x10";
3197 font = XLoadQueryFont (dpy, def_font);
3199 fprintf(stderr,"Can't load font %s\n",def_font);
3203 text_pm=XCreatePixmap(dpy, window, 64*7, 8, xgwa.depth);
3208 gc=XCreateGC(dpy, text_pm, GCFont|GCBackground|GCForeground, &gcv);
3210 XSetForeground(dpy, gc, 0);
3211 XFillRectangle(dpy, text_pm, gc, 0, 0, 64*7, 8);
3212 XSetForeground(dpy, gc, 1);
3213 for (i=0; i<64; i++) {
3219 XDrawString(dpy, text_pm, gc, x, y, &c, 1);
3221 XDrawString(dpy, text_pm, gc, x, y, &c, 1);
3224 text_im = XGetImage(dpy, text_pm, 0, 0, 64*7, 8, ~0L, ZPixmap);
3226 XFreePixmap(dpy, text_pm);
3228 for (i=0; a2_fixfont[i]; i++) {
3229 XPutPixel(text_im, a2_fixfont[i]&0x3ff,
3230 (a2_fixfont[i]>>10)&0xf,
3231 (a2_fixfont[i]>>15)&1);
3236 Simulate plausible initial memory contents.
3240 while (addr<0x4000) {
3243 switch (random()%4) {
3247 for (i=0; i<n && addr<0x4000; i++) {
3248 u_char rb=((random()%6==0 ? 0 : random()%16) |
3249 ((random()%5==0 ? 0 : random()%16)<<4));
3250 a2_poke(st, addr++, rb);
3255 /* Simulate shapes stored in memory. We use the font since we have it.
3256 Unreadable, since rows of each character are stored in consecutive
3257 bytes. It was typical to store each of the 7 possible shifts of
3258 bitmaps, for fastest blitting to the screen. */
3259 x=random()%(text_im->width);
3260 for (i=0; i<100; i++) {
3261 for (y=0; y<8; y++) {
3263 for (j=0; j<8; j++) {
3264 c |= XGetPixel(text_im, (x+j)%text_im->width, y)<<j;
3266 a2_poke(st, addr++, c);
3268 x=(x+1)%(text_im->width);
3275 for (i=0; i<n && addr<0x4000; i++) {
3276 a2_poke(st, addr++, 0);
3285 if (random()%4==0 &&
3286 !use_cmap && use_color &&
3287 xgwa.visual->bits_per_rgb>=8) {
3290 else if (random()%3==0) {
3291 flutter_horiz_desync=1;
3297 gettimeofday(&basetime_tv, NULL);
3298 if (random()%2==0) basetime_tv.tv_sec -= 1; /* random blink phase */
3299 next_actiontime=0.0;
3302 double curtime,blinkphase;
3303 int startdisplayrow=0;
3307 struct timeval curtime_tv;
3308 gettimeofday(&curtime_tv, NULL);
3309 curtime=(curtime_tv.tv_sec - basetime_tv.tv_sec) +
3310 0.000001*(curtime_tv.tv_usec - basetime_tv.tv_usec);
3312 if (curtime>delay) goto finished;
3314 if (bsod_sleep(dpy,0)) goto finished;
3316 if (flutter_tint && st->gr_mode && !printing) {
3317 /* Oscillator instability. Look for freq_error below. We should only do
3318 this with color depth>=8, since otherwise you see pixels changing. */
3319 freq_error_inc += (-0.10*freq_error_inc
3320 + ((int)(random()&0xff)-0x80) * 0.01);
3321 freq_error += freq_error_inc;
3325 else if (flutter_horiz_desync) {
3326 /* Horizontal sync during vertical sync instability. */
3327 horiz_desync += (-0.10*(horiz_desync-3.0) +
3328 ((int)(random()&0xff)-0x80) *
3329 ((int)(random()&0xff)-0x80) *
3330 ((int)(random()&0xff)-0x80) * 0.0000003);
3331 for (i=0; i<3; i++) st->rowimage[i]=-1;
3335 /* It's super-important to get the cursor/text flash out at exactly the
3336 right time, or it looks wrong. So if we're almost due for a blink, wait
3337 for it so we don't miss it in the middle of a screen update. */
3338 blinkphase=curtime/0.8;
3339 if (blinkphase-floor(blinkphase)>0.7 && !printing && !nodelay) {
3340 /* We're about to blink */
3341 int delay = ((1.0-(blinkphase-floor(blinkphase)))*0.8) * 1000000;
3342 if (delay<1000) delay=1000;
3347 /* The blinking rate was controlled by 555 timer with a resistor/capacitor
3348 time constant. Because the capacitor was electrolytic, the flash rate
3349 varied somewhat between machines. I'm guessing 1.6 seconds/cycle was
3350 reasonable. (I soldered a resistor in mine to make it blink faster.) */
3352 st->blink=((int)blinkphase)&1;
3353 if (st->blink!=i && !(st->gr_mode&A2_GR_FULL)) {
3355 /* For every row with blinking text, set the changed flag. This basically
3356 works great except with random screen garbage in text mode, when we
3357 end up redrawing the whole screen every second */
3358 for (row=(st->gr_mode ? 20 : 0); row<24; row++) {
3359 for (col=0; col<40; col++) {
3360 c=st->textlines[row][col];
3361 if ((c & 0xc0) == 0x40) {
3366 if (downcounter>0) {
3367 st->rowimage[row]=-1;
3371 st->rowimage[st->cursy]=-1;
3372 startdisplayrow=random()%24;
3374 else if (next_actiontime > curtime && !printing && !nodelay) {
3375 int delay = (next_actiontime-curtime)*1000000;
3377 if (delay>100000) delay=100000;
3378 if (delay<1000) delay=1000;
3386 if (*printing=='\001') { /* pause */
3388 for (i=20; i<24; i++) st->rowimage[i]=-1;
3391 else if (*printing=='\n') {
3392 a2_printc(st,*printing);
3397 a2_printc(st,*printing);
3401 if (!*printing) printing=NULL;
3403 else if (curtime >= next_actiontime) {
3405 /* If we're in the midst of typing a string, emit a character with
3407 a2_printc(st, *typing);
3408 if (*typing=='\n') {
3409 next_actiontime = curtime;
3411 next_actiontime = curtime + (random()%1000)*0.0003 + 0.3;
3415 if (!*typing) typing=NULL;
3419 next_actiontime=curtime;
3426 For testing color rendering. The spec is:
3434 6 med blue 20 207 253
3435 7 lt blue 208 195 255
3440 12 lt green 20 245 60
3441 13 yellow 208 221 141
3443 15 white 255 255 255
3445 st->gr_mode=A2_GR_LORES;
3446 for (row=0; row<24; row++) {
3447 for (col=0; col<40; col++) {
3448 st->textlines[row][col]=(row&15)*17;
3451 next_actiontime+=0.4;
3454 else if (random()%3==0) {
3456 next_actiontime+=0.4;
3459 else if (random()%4==0) {
3460 st->gr_mode=A2_GR_LORES;
3461 if (random()%3==0) st->gr_mode |= A2_GR_FULL;
3462 next_actiontime+=0.4;
3465 else if (random()%2==0) {
3466 st->gr_mode=A2_GR_HIRES;
3470 st->gr_mode=A2_GR_HIRES;
3471 next_actiontime+=0.4;
3477 /* An illegal instruction or a reset caused it to drop into the
3478 assembly language monitor, where you could disassemble code & view
3480 if (random()%3==0) {
3483 int addr=0xd000+random()%0x3000;
3485 "%02X",random()%0xff);
3491 " A=%02X X=%02X Y=%02X S=%02X F=%02X\n"
3494 random()%0xff, random()%0xff,
3495 random()%0xff, random()%0xff,
3505 next_actiontime += 2.0 + (random()%1000)*0.0002;
3508 /* Lots of programs had at least their main functionality in
3509 Applesoft Basic, which had a lot of limits (memory, string
3510 length, etc) and would sometimes crash unexpectedly. */
3517 apple2_basic_errors[random() %
3518 (sizeof(apple2_basic_errors)
3520 (1000*(random()%(random()%59+1)) +
3521 100*(random()%(random()%9+1)) +
3522 5*(random()%(random()%199+1)) +
3523 1*(random()%(random()%(random()%2+1)+1))));
3528 next_actiontime += 2.0 + (random()%1000)*0.0002;
3533 if (simulate_user && random()%3==0) {
3534 /* This was how you reset the Basic interpreter. The sort of
3535 incantation you'd have on a little piece of paper taped to the
3536 side of your machine */
3537 typing="CALL -1370";
3540 else if (simulate_user && random()%2==0) {
3545 next_actiontime+=1.0;
3552 next_actiontime += 0.5;
3559 for (s="APPLE ]["; *s; s++) a2_printc(st,*s);
3562 next_actiontime+=1.0;
3567 if (simulate_user && random()%50==0 && 0) { /* disabled, too goofy */
3568 typing="10 PRINT \"TRS-80S SUCK!!!\"\n"
3575 next_actiontime += delay;
3580 for (i=0; i<30; i++) {
3581 for (s="\nTRS-80S SUCK"; *s; s++) a2_printc(st,*s);
3584 next_actiontime+=delay;
3590 if (random()%50==0) {
3591 sprintf(printbuf,"\nDISK VOLUME 254\n\n"
3598 sprintf(printbuf,"\n?%s\n]",
3599 apple2_dos_errors[random()%
3600 (sizeof(apple2_dos_errors) /
3605 next_actiontime+=1.0;
3609 if (simulate_user && random()%2==0) {
3610 /* This was how you went back to text mode in the monitor */
3614 next_actiontime+=1.0;
3625 next_actiontime+=2.0;
3629 /* This reset things into Basic */
3630 if (simulate_user && random()%2==0) {
3636 next_actiontime+=delay;
3641 for (i=0; i<1500; i++) {
3642 a2_poke(st, fillptr, fillbyte);
3644 fillbyte = (fillbyte+1)&0xff;
3646 next_actiontime += 0.08;
3647 /* When you hit c000, it changed video settings */
3648 if (fillptr>=0xc000) {
3652 /* And it seemed to reset around here, I dunno why */
3653 if (fillptr>=0xcf00) stepno=3;
3659 /* Now, we turn the data in the Apple II video into a screen display. This
3660 is interesting because of the interaction with the NTSC color decoding
3661 in a color television. */
3663 colormode=use_color && st->gr_mode!=0;
3665 ntsc_set_demod(dec, tint_control, color_control, brightness_control,
3666 freq_error, colormode);
3669 for (textrow=0; textrow<24; textrow++) {
3670 if (st->rowimage[textrow] == textrow) {
3671 screen_plan[textrow]=0;
3673 else if (cheapdisplay && st->rowimage[textrow]>=0 &&
3674 textrow<21 && st->rowimage[textrow]<21 &&
3675 st->rowimage[textrow]>=2 && textrow>=2 &&
3676 (st->rowimage[textrow]+1)*h/24 + screen_xo <= xgwa.height) {
3677 screen_plan[textrow]= A2_SP_COPY | st->rowimage[textrow];
3678 for (i=0; i<8; i++) {
3679 crtload[textrow*8+i]=crtload[st->rowimage[textrow]*8+i];
3684 st->rowimage[textrow]=imgrow;
3685 screen_plan[textrow]=imgrow | A2_SP_PUT;
3687 for (row=textrow*8; row<textrow*8+8; row++) {
3689 int pixmultinc,pixbright;
3690 int scanstart_i, scanend_i;
3691 int squishright_i, squishdiv;
3693 double bloomthisrow,shiftthisrow;
3694 int ytop=(imgrow*h/24) + ((row-textrow*8) * h/192);
3695 int ybot=ytop+h/192;
3697 /* First we generate the pattern that the video circuitry shifts out
3698 of memory. It has a 14.something MHz dot clock, equal to 4 times
3699 the color burst frequency. So each group of 4 bits defines a
3700 color. Each character position, or byte in hires, defines 14
3701 dots, so odd and even bytes have different color spaces. So,
3702 pattern[0..600] gets the dots for one scan line. */
3704 memset(dec->pattern,0,sizeof(dec->pattern));
3707 if ((st->gr_mode&A2_GR_HIRES) && (row<160 ||
3708 (st->gr_mode&A2_GR_FULL))) {
3710 /* Emulate the mysterious pink line, due to a bit getting
3711 stuck in a shift register between the end of the last
3712 row and the beginning of this one. */
3713 if ((st->hireslines[row][0] & 0x80) &&
3714 (st->hireslines[row][39]&0x40)) {
3718 for (col=0; col<40; col++) {
3719 u_char b=st->hireslines[row][col];
3720 int shift=(b&0x80)?0:1;
3722 /* Each of the low 7 bits in hires mode corresponded to 2 dot
3723 clocks, shifted by one if the high bit was set. */
3724 for (i=0; i<7; i++) {
3725 pp[shift+1] = pp[shift] =(b>>i)&1;
3730 else if ((st->gr_mode&A2_GR_LORES) && (row<160 ||
3731 (st->gr_mode&A2_GR_FULL))) {
3732 for (col=0; col<40; col++) {
3733 u_char nib=(st->textlines[textrow][col] >> (((row/4)&1)*4))&0xf;
3734 /* The low or high nybble was shifted out one bit at a time. */
3735 for (i=0; i<14; i++) {
3736 *pp = (nib>>((col*14+i)&3))&1;
3742 for (col=0; col<40; col++) {
3744 c=st->textlines[textrow][col];
3745 /* hi bits control inverse/blink as follows:
3750 rev=!(c&0x80) && (!(c&0x40) || st->blink);
3752 for (i=0; i<7; i++) {
3753 for (i=0; i<7; i++) {
3754 unsigned long pix=XGetPixel(text_im,
3755 ((c&0x3f)^0x20)*7+i, row%8);
3756 pp[1] = pp[2] = pix^rev;
3764 Interpolate the 600-dotclock line into however many horizontal
3765 screen pixels we're using, and convert to RGB.
3767 We add some 'bloom', variations in the horizontal scan width with
3768 the amount of brightness, extremely common on period TV sets. They
3769 had a single oscillator which generated both the horizontal scan
3770 and (during the horizontal retrace interval) the high voltage for
3771 the electron beam. More brightness meant more load on the
3772 oscillator, which caused an decrease in horizontal deflection. Look
3775 Also, the A2 did a bad job of generating horizontal sync pulses
3776 during the vertical blanking interval. This, and the fact that the
3777 horizontal frequency was a bit off meant that TVs usually went a
3778 bit out of sync during the vertical retrace, and the top of the
3779 screen would be bent a bit to the left or right. Look for
3782 We also add a teeny bit of left overscan, just enough to be
3783 annoying, but you can still read the left column of text.
3785 We also simulate compression & brightening on the right side of the
3786 screen. Most TVs do this, but you don't notice because they
3787 overscan so it's off the right edge of the CRT. But the A2 video
3788 system used so much of the horizontal scan line that you had to
3789 crank the horizontal width down in order to not lose the right few
3790 characters, and you'd see the compression on the right
3791 edge. Associated with compression is brightening; since the
3792 electron beam was scanning slower, the same drive signal hit the
3793 phosphor harder. Look for (squishright_i) and (squishdiv).
3796 for (i=j=0; i<600; i++) {
3797 j += dec->pattern[i];
3799 crtload[row] = (crtload[row>1 ? row-1 : 0]) * 0.98 + 0.02*(j/600.0) +
3800 (row>180 ? (row-180)*(row-180)*0.0005 : 0.0);
3801 bloomthisrow = -10.0 * crtload[row];
3802 shiftthisrow=((row<18) ? ((18-row)*(18-row)* 0.002 + (18-row)*0.05)
3803 * horiz_desync : 0.0);
3805 scanstart_i=(int)((bloomthisrow+shiftthisrow+18.0)*65536.0);
3806 if (scanstart_i<0) scanstart_i=0;
3807 if (scanstart_i>30*65536) scanstart_i=30*65536;
3808 scanend_i=599*65536;
3809 squishright_i=scanstart_i + 530*65536;
3811 pixrate=(int)((560.0-2.0*bloomthisrow)*65536.0/w);
3814 for (y=ytop; y<ybot; y++) {
3815 int level=(!(y==ytop && ybot-ytop>=3) &&
3816 !(y==ybot-1 && ybot-ytop>=5));
3821 for (x=0, i=scanstart_i;
3823 x++, i+=pixmultinc) {
3826 while (pati>=histi) {
3827 hist=(((hist<<1) & ((1<<A2_CMAP_HISTBITS)-1)) |
3828 dec->pattern[histi]);
3831 XPutPixel(image, x, y,
3832 colors[A2_CMAP_INDEX(colormode,level,hist,offset)]);
3833 if (i >= squishright_i) {
3834 pixmultinc += pixmultinc/squishdiv;
3838 XPutPixel(image, x, y, colors[0]);
3845 pixbright=(int)(contrast_control*65536.0);
3847 for (x=0, i=scanstart_i, rrp=raw_rgb;
3849 x++, i+=pixmultinc, rrp+=3) {
3850 int pixfrac=i&0xffff;
3851 int invpixfrac=65536-pixfrac;
3855 int interpy=((dec->ntscy[pati]*invpixfrac +
3856 dec->ntscy[pati+1]*pixfrac)>>16);
3857 int interpi=((dec->ntsci[pati]*invpixfrac +
3858 dec->ntsci[pati+1]*pixfrac)>>16);
3859 int interpq=((dec->ntscq[pati]*invpixfrac +
3860 dec->ntscq[pati+1]*pixfrac)>>16);
3863 According to the NTSC spec, Y,I,Q are generated as:
3865 y=0.30 r + 0.59 g + 0.11 b
3866 i=0.60 r - 0.28 g - 0.32 b
3867 q=0.21 r - 0.52 g + 0.31 b
3869 So if you invert the implied 3x3 matrix you get what standard
3870 televisions implement with a bunch of resistors (or directly in
3871 the CRT -- don't ask):
3873 r = y + 0.948 i + 0.624 q
3874 g = y - 0.276 i - 0.639 q
3875 b = y - 1.105 i + 1.729 q
3877 These coefficients are below in 16.16 format.
3880 r=((interpy + ((+68128*interpi+40894*interpq)>>16))*pixbright)
3882 g=((interpy + ((-18087*interpi-41877*interpq)>>16))*pixbright)
3884 b=((interpy + ((-72417*interpi+113312*interpq)>>16))*pixbright)
3893 if (i>=squishright_i) {
3894 pixmultinc += pixmultinc/squishdiv;
3895 pixbright += pixbright/squishdiv;
3898 for ( ; x<w; x++, rrp+=3) {
3899 rrp[0]=rrp[1]=rrp[2]=0;
3902 for (y=ytop; y<ybot; y++) {
3903 /* levelmult represents the vertical size of scan lines. Each
3904 line is brightest in the middle, and there's a dark band
3907 double levelmult_fp=(y + 0.5 - (ytop+ybot)*0.5) / (ybot-ytop);
3908 levelmult_fp = 1.0-(levelmult_fp*levelmult_fp*levelmult_fp
3909 *levelmult_fp)*16.0;
3910 if (levelmult_fp<0.0) levelmult_fp=0.0;
3911 levelmult = (int)(64.9*levelmult_fp);
3913 /* Fast special cases to avoid the slow XPutPixel. Ugh. It goes
3914 to show why standard graphics sw has to be fast, or else
3915 people will have to work around it and risk incompatibility.
3916 The quickdraw folks understood this. The other answer would
3917 be for X11 to have fewer formats for bitm.. oh, never
3918 mind. If neither of these cases work (they probably cover 99%
3919 of setups) it falls back on the Xlib routines. */
3920 if (image->format==ZPixmap && image->bits_per_pixel==32 &&
3921 sizeof(unsigned long)==4 &&
3922 image->byte_order==localbyteorder) {
3923 unsigned long *pixelptr =
3924 (unsigned long *) (image->data + y * image->bytes_per_line);
3925 for (x=0, rrp=raw_rgb; x<w; x++, rrp+=3) {
3926 unsigned long ntscri, ntscgi, ntscbi;
3927 ntscri=((unsigned long)rrp[0])*levelmult;
3928 ntscgi=((unsigned long)rrp[1])*levelmult;
3929 ntscbi=((unsigned long)rrp[2])*levelmult;
3930 if (ntscri>65535) ntscri=65535;
3931 if (ntscgi>65535) ntscgi=65535;
3932 if (ntscbi>65535) ntscbi=65535;
3933 *pixelptr++ = ((ntscri>>red_invprec)<<red_shift) |
3934 ((ntscgi>>green_invprec)<<green_shift) |
3935 ((ntscbi>>blue_invprec)<<blue_shift);
3938 else if (image->format==ZPixmap && image->bits_per_pixel==16 &&
3939 sizeof(unsigned short)==2 &&
3940 image->byte_order==localbyteorder) {
3941 unsigned short *pixelptr =
3942 (unsigned short *)(image->data + y*image->bytes_per_line);
3943 for (x=0, rrp=raw_rgb; x<w; x++, rrp+=3) {
3944 unsigned long ntscri, ntscgi, ntscbi;
3945 ntscri=((unsigned long)rrp[0])*levelmult;
3946 ntscgi=((unsigned long)rrp[1])*levelmult;
3947 ntscbi=((unsigned long)rrp[2])*levelmult;
3948 if (ntscri>65535) ntscri=65535;
3949 if (ntscgi>65535) ntscgi=65535;
3950 if (ntscbi>65535) ntscbi=65535;
3951 *pixelptr++ = ((ntscri>>red_invprec)<<red_shift) |
3952 ((ntscgi>>green_invprec)<<green_shift) |
3953 ((ntscbi>>blue_invprec)<<blue_shift);
3958 for (x=0, rrp=raw_rgb; x<w; x++, rrp+=3) {
3959 unsigned long pixel, ntscri, ntscgi, ntscbi;
3960 /* Convert to 16-bit color values, with saturation. The ntscr
3961 values are 22.10 fixed point, and levelmult is 24.6, so we
3963 ntscri=((unsigned long)rrp[0])*levelmult;
3964 ntscgi=((unsigned long)rrp[1])*levelmult;
3965 ntscbi=((unsigned long)rrp[2])*levelmult;
3966 if (ntscri>65535) ntscri=65535;
3967 if (ntscgi>65535) ntscgi=65535;
3968 if (ntscbi>65535) ntscbi=65535;
3969 pixel = ((ntscri>>red_invprec)<<red_shift) |
3970 ((ntscgi>>green_invprec)<<green_shift) |
3971 ((ntscbi>>blue_invprec)<<blue_shift);
3972 XPutPixel(image, x, y, pixel);
3982 /* For just the the rows which changed, blit the image to the screen. */
3983 for (textrow=0; textrow<24; ) {
3984 int top,bot,srcrow,srctop,nrows;
3987 while (textrow+nrows < 24 &&
3988 screen_plan[textrow+nrows] == screen_plan[textrow]+nrows)
3992 bot=h*(textrow+nrows)/24;
3993 srcrow=screen_plan[textrow]&A2_SP_ROWMASK;
3996 if (screen_plan[textrow] & A2_SP_COPY) {
3997 if (0) printf("Copy %d screenrows %d to %d\n", nrows, srcrow, textrow);
3998 XCopyArea(dpy, window, window, gc,
3999 screen_xo, screen_yo + srctop,
4001 screen_xo, screen_yo + top);
4003 else if (screen_plan[textrow] & A2_SP_PUT) {
4004 if (0) printf("Draw %d imgrows %d to %d\n", nrows, srcrow, textrow);
4006 #ifdef HAVE_XSHM_EXTENSION
4007 XShmPutImage(dpy, window, gc, image,
4008 0, srctop, screen_xo, screen_yo + top,
4012 XPutImage(dpy, window, gc, image,
4014 screen_xo, screen_yo + top,
4022 for (textrow=0; textrow<24; textrow++) {
4023 st->rowimage[textrow]=textrow;
4029 XClearWindow(dpy, window);
4038 #ifdef HAVE_XSHM_EXTENSION
4039 destroy_xshm_image(dpy, image, &shm_info);
4042 XDestroyImage(image);
4046 if (text_im) XDestroyImage(text_im);
4047 if (gc) XFreeGC(dpy, gc);
4049 if (raw_rgb) free(raw_rgb);
4051 if (n_colors) XFreeColors(dpy, xgwa.colormap, colors, n_colors, 0L);
4056 char *progclass = "BSOD";
4058 char *defaults [] = {
4071 "*doAtari: False", /* boring */
4072 "*doBSD: False", /* boring */
4074 "*doSparcLinux: False", /* boring */
4075 "*doBlitDamage: True",
4082 ".Windows.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4083 ".Windows.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
4084 ".Windows.foreground: White",
4085 ".Windows.background: #0000AA", /* EGA color 0x01. */
4087 ".Amiga.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4088 ".Amiga.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
4089 ".Amiga.foreground: Red",
4090 ".Amiga.background: Black",
4091 ".Amiga.background2: White",
4093 ".Mac.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4094 ".Mac.foreground: PaleTurquoise1",
4095 ".Mac.background: Black",
4097 ".Atari.foreground: Black",
4098 ".Atari.background: White",
4100 ".MacsBug.font: -*-courier-medium-r-*-*-*-100-*-*-m-*-*-*",
4101 ".MacsBug.font2: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4102 ".MacsBug.font3: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4103 ".MacsBug.foreground: Black",
4104 ".MacsBug.background: White",
4105 ".MacsBug.borderColor: #AAAAAA",
4107 ".mac1.foreground: Black",
4108 ".mac1.background: White",
4110 ".macX.textForeground: White",
4111 ".macX.textBackground: Black",
4112 ".macX.background: #888888",
4113 ".macX.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4114 ".macX.font2: -*-courier-bold-r-*-*-*-240-*-*-m-*-*-*",
4116 ".SCO.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4117 ".SCO.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4118 ".SCO.foreground: White",
4119 ".SCO.background: Black",
4121 ".Linux.font: 9x15bold",
4122 ".Linux.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4123 ".Linux.foreground: White",
4124 ".Linux.background: Black",
4126 ".SparcLinux.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4127 ".SparcLinux.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4128 ".SparcLinux.foreground: White",
4129 ".SparcLinux.background: Black",
4132 ".BSD.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4133 ".BSD.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4134 /* ".BSD.font2: -sun-console-medium-r-*-*-22-*-*-*-m-*-*-*", */
4135 ".BSD.foreground: #c0c0c0",
4136 ".BSD.background: Black",
4138 ".Solaris.font: -sun-gallant-*-*-*-*-19-*-*-*-*-120-*-*",
4139 ".Solaris.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4140 ".Solaris.foreground: Black",
4141 ".Solaris.background: White",
4142 "*dontClearRoot: True",
4144 ".HPUX.font: 9x15bold",
4145 ".HPUX.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4146 ".HPUX.foreground: White",
4147 ".HPUX.background: Black",
4149 ".OS390.font: 9x15bold",
4150 ".OS390.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4151 ".OS390.background: Black",
4152 ".OS390.foreground: Red",
4154 "*apple2TVColor: 50",
4156 "*apple2TVBrightness: 10",
4157 "*apple2TVContrast: 90",
4158 "*apple2SimulateUser: True",
4160 ".VMS.font: 9x15bold",
4161 ".VMS.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4162 ".VMS.foreground: White",
4163 ".VMS.background: Black",
4165 #ifdef HAVE_XSHM_EXTENSION
4171 XrmOptionDescRec options [] = {
4172 { "-delay", ".delay", XrmoptionSepArg, 0 },
4173 { "-only", ".doOnly", XrmoptionSepArg, 0 },
4174 { "-windows", ".doWindows", XrmoptionNoArg, "True" },
4175 { "-no-windows", ".doWindows", XrmoptionNoArg, "False" },
4176 { "-nt", ".doNT", XrmoptionNoArg, "True" },
4177 { "-no-nt", ".doNT", XrmoptionNoArg, "False" },
4178 { "-2k", ".doWin2K", XrmoptionNoArg, "True" },
4179 { "-no-2k", ".doWin2K", XrmoptionNoArg, "False" },
4180 { "-amiga", ".doAmiga", XrmoptionNoArg, "True" },
4181 { "-no-amiga", ".doAmiga", XrmoptionNoArg, "False" },
4182 { "-mac", ".doMac", XrmoptionNoArg, "True" },
4183 { "-no-mac", ".doMac", XrmoptionNoArg, "False" },
4184 { "-mac1", ".doMac1", XrmoptionNoArg, "True" },
4185 { "-no-mac1", ".doMac1", XrmoptionNoArg, "False" },
4186 { "-macx", ".doMacX", XrmoptionNoArg, "True" },
4187 { "-no-macx", ".doMacX", XrmoptionNoArg, "False" },
4188 { "-atari", ".doAtari", XrmoptionNoArg, "True" },
4189 { "-no-atari", ".doAtari", XrmoptionNoArg, "False" },
4190 { "-macsbug", ".doMacsBug", XrmoptionNoArg, "True" },
4191 { "-no-macsbug", ".doMacsBug", XrmoptionNoArg, "False" },
4192 { "-apple2", ".doApple2", XrmoptionNoArg, "True" },
4193 { "-no-apple2", ".doApple2", XrmoptionNoArg, "False" },
4194 { "-sco", ".doSCO", XrmoptionNoArg, "True" },
4195 { "-no-sco", ".doSCO", XrmoptionNoArg, "False" },
4196 { "-bsd", ".doBSD", XrmoptionNoArg, "True" },
4197 { "-no-bsd", ".doBSD", XrmoptionNoArg, "False" },
4198 { "-linux", ".doLinux", XrmoptionNoArg, "True" },
4199 { "-no-linux", ".doLinux", XrmoptionNoArg, "False" },
4200 { "-sparclinux", ".doSparcLinux", XrmoptionNoArg, "True" },
4201 { "-no-sparclinux", ".doSparcLinux", XrmoptionNoArg, "False" },
4202 { "-blitdamage", ".doBlitDamage", XrmoptionNoArg, "True" },
4203 { "-no-blitdamage", ".doBlitDamage", XrmoptionNoArg, "False" },
4204 { "-solaris", ".doSolaris", XrmoptionNoArg, "True" },
4205 { "-no-solaris", ".doSolaris", XrmoptionNoArg, "False" },
4206 { "-hpux", ".doHPUX", XrmoptionNoArg, "True" },
4207 { "-no-hpux", ".doHPUX", XrmoptionNoArg, "False" },
4208 { "-os390", ".doOS390", XrmoptionNoArg, "True" },
4209 { "-no-os390", ".doOS390", XrmoptionNoArg, "False" },
4210 { "-vms", ".doVMS", XrmoptionNoArg, "True" },
4211 { "-no-vms", ".doVMS", XrmoptionNoArg, "False" },
4218 void (*fn) (Display *, Window, int delay);
4220 { "Windows", windows_31 },
4221 { "Nt", windows_nt },
4222 { "2k", windows_2k },
4225 { "MacsBug", macsbug },
4229 { "SparcLinux", sparc_linux },
4232 { "BlitDamage", blitdamage },
4233 { "Solaris", sparc_solaris },
4234 { "Linux", linux_fsck },
4237 { "Apple2", apple2 },
4243 screenhack (Display *dpy, Window window)
4249 int delay = get_integer_resource ("delay", "Integer");
4250 if (delay < 3) delay = 3;
4253 char *s = get_string_resource("doOnly", "DoOnly");
4256 int count = countof(all_modes);
4257 for (only = 0; only < count; only++)
4258 if (!strcasecmp (s, all_modes[only].name))
4262 fprintf (stderr, "%s: unknown -only mode: \"%s\"\n", progname, s);
4269 if (!get_boolean_resource ("root", "Boolean"))
4271 XWindowAttributes xgwa;
4272 XGetWindowAttributes (dpy, window, &xgwa);
4273 XSelectInput (dpy, window,
4274 xgwa.your_event_mask | KeyPressMask | ButtonPressMask);
4280 int count = countof(all_modes);
4281 char name[100], class[100];
4286 do { i = (random() & 0xFF) % count; } while (i == j);
4288 sprintf (name, "do%s", all_modes[i].name);
4289 sprintf (class, "Do%s", all_modes[i].name);
4292 if (only > 0 || get_boolean_resource(name, class))
4294 all_modes[i].fn (dpy, window, delay);
4299 if (loop > 100) j = -1;
4302 fprintf (stderr, "%s: no display modes enabled?\n", progname);