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"
2221 XGetWindowAttributes (dpy, window, &xgwa);
2222 ts = make_scrolling_window (dpy, window, "VMS", False);
2223 XClearWindow(dpy,window);
2226 ts->sub_width = xgwa.width;
2227 ts->sub_height = xgwa.height;
2233 if (uname (&uts) >= 0)
2234 sysname = uts.nodename;
2235 s = strchr (sysname, '.');
2238 # endif /* !HAVE_UNAME */
2240 args[0] = malloc (strlen(sysname) + 7);
2241 strcpy (args[0], sysname);
2244 /* Pick three numbers, 1-9, no overlaps. */
2245 ids[0] = 1 + (random() % 9);
2246 do { ids[1] = 1 + (random() % 9); } while (ids[1]==ids[0]);
2247 do { ids[2] = 1 + (random() % 9); } while (ids[2]==ids[0] || ids[2]==ids[1]);
2249 i = strlen(args[0])-1;
2251 args[0][i] = '0' + ids[0];
2254 for (s = args[0]; *s; s++)
2255 if (isalpha(*s)) *s = toupper (*s);
2257 args[1] = strdup (args[0]);
2258 args[2] = strdup (args[0]); args[2][i] = '0' + ids[1];
2259 args[3] = strdup (args[0]); args[3][i] = '0' + ids[2];
2261 args[4] = strdup (args[1]);
2262 args[5] = strdup (args[2]);
2263 args[6] = strdup (args[3]);
2266 time_t t = time ((time_t *) 0);
2267 struct tm *tm = localtime (&t);
2268 args[7] = malloc (30);
2269 strftime (args[7], 29, "%d-%b-%Y %H:%M", tm);
2270 for (s = args[7]; *s; s++)
2271 if (isalpha(*s)) *s = toupper (*s);
2275 for (i = 0; i < countof(lines); i++)
2277 const char *fmt = lines[i];
2278 if (! strcmp (fmt, "..."))
2280 int steps = 180 + (random() % 60);
2281 while (--steps >= 0)
2283 scrolling_puts (ts, ".", 0);
2286 if (bsod_sleep (dpy, 0))
2292 char *fmt2 = malloc (strlen (fmt) * 2 + 1);
2293 for (s = (char *) fmt, s1 = fmt2; *s; s++)
2297 strcpy (s1, args[arg_count++]);
2304 scrolling_puts (ts, fmt2, char_delay);
2306 usleep (chunk_delay);
2307 if (bsod_sleep (dpy, 0))
2313 bsod_sleep(dpy, delay);
2316 free_scrolling_window (ts);
2317 for (i = 0; i < countof (args); i++)
2324 /* HPUX panic, by Tobias Klausmann <klausman@schwarzvogel.de>
2328 hpux (Display* dpy, Window window, int delay)
2330 XWindowAttributes xgwa;
2331 scrolling_window *ts;
2332 const char *sysname;
2336 __extension__ /* don't warn about "string length is greater than the
2337 length ISO C89 compilers are required to support"
2338 in the following string constant... */
2344 " ******* Unexpected HPMC/TOC. Processor HPA FFFFFFFF'"
2345 "FFFA0000 *******\n"
2346 " GENERAL REGISTERS:\n"
2347 "r00/03 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2349 "r04/07 00000000'00000001 00000000'0126E328 00000000'00000000 00000000'"
2351 "r08/11 00000000'00000000 00000000'0198CFC0 00000000'000476FE 00000000'"
2353 "r12/15 00000000'40013EE8 00000000'08000080 00000000'4002530C 00000000'"
2355 "r16/19 00000000'7F7F2A00 00000000'00000001 00000000'00000000 00000000'"
2357 "r20/23 00000000'006C8048 00000000'00000001 00000000'00000000 00000000'"
2359 "r24/27 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2361 "r28/31 00000000'00000000 00000000'007DD628 00000000'0199F2B0 00000000'"
2363 " CONTROL REGISTERS:\n"
2364 "sr0/3 00000000'0F3B4000 00000000'0C2A2000 00000000'016FF800 00000000'"
2366 "sr4/7 00000000'00000000 00000000'016FF800 00000000'0DBF1400 00000000'"
2368 "pcq = 00000000'00000000.00000000'00104950 00000000'00000000.00000000'"
2370 "isr = 00000000'10240006 ior = 00000000'67D9E220 iir = 08000240 rctr = "
2373 "pid reg cr8/cr9 00007700'0000B3A9 00000000'0000C5D8\n"
2374 "pid reg cr12/cr13 00000000'00000000 00000000'00000000\n"
2375 "ipsw = 000000FF'080CFF1F iva = 00000000'0002C000 sar = 3A ccr = C0\n"
2376 "tr0/3 00000000'006C76C0 00000000'00000001 00000000'00000000 00000000'"
2378 "tr4/7 00000000'03790000 0000000C'4FB68340 00000000'C07EE13F 00000000'"
2380 "eiem = FFFFFFF0'FFFFFFFF eirr = 80000000'00000000 itmr = 0000000C'"
2382 "cr1/4 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2384 "cr5/7 00000000'00000000 00000000'00000000 00000000'"
2386 " MACHINE CHECK PARAMETERS:\n"
2387 "Check Type = 00000000 CPU STATE = 9E000001 Cache Check = 00000000\n"
2388 "TLB Check = 00000000 Bus Check = 00000000 PIM State = ? SIU "
2389 "Status = ????????\n"
2390 "Assists = 00000000 Processor = 00000000\n"
2391 "Slave Addr = 00000000'00000000 Master Addr = 00000000'00000000\n"
2394 "TOC, pcsq.pcoq = 0'0.0'104950 , isr.ior = 0'10240006.0'67d9e220\n"
2395 "@(#)B2352B/9245XB HP-UX (B.11.00) #1: Wed Nov 5 22:38:19 PST 1997\n"
2396 "Transfer of control: (display==0xd904, flags==0x0)\n"
2400 "*** A system crash has occurred. (See the above messages for details.)\n"
2401 "*** The system is now preparing to dump physical memory to disk, for use\n"
2402 "*** in debugging the crash.\n"
2404 "*** The dump will be a SELECTIVE dump: 40 of 256 megabytes.\n"
2405 "*** To change this dump type, press any key within 10 seconds.\n"
2406 "*** Proceeding with selective dump.\n"
2408 "*** The dump may be aborted at any time by pressing ESC.\n";
2410 "\n*** System rebooting.\n";
2412 XGetWindowAttributes (dpy, window, &xgwa);
2413 ts = make_scrolling_window (dpy, window, "HPUX", False);
2414 XClearWindow(dpy,window);
2415 ts->columns = 10000; /* never wrap */
2418 ts->sub_width = xgwa.width;
2419 ts->sub_height = xgwa.height;
2426 if (uname (&uts) >= 0)
2427 sysname = uts.nodename;
2428 s = strchr (sysname, '.');
2431 # endif /* !HAVE_UNAME */
2433 if (bsod_sleep (dpy, 1))
2441 sprintf (buf, "%.100s [HP Release B.11.00] (see /etc/issue)\n", sysname);
2442 scrolling_puts (ts, buf, 0);
2443 if (bsod_sleep (dpy, 1))
2445 scrolling_puts (ts, msg1, 0);
2450 for (i = 0; i <= steps; i++)
2452 if (i > steps) i = steps;
2454 "*** Dumping: %3d%% complete (%d of 40 MB) (device 64:0x2)\r",
2457 scrolling_puts (ts, buf, 0);
2460 if (bsod_sleep (dpy, 0))
2465 scrolling_puts (ts, msg2, 0);
2468 bsod_sleep(dpy, delay);
2471 free_scrolling_window (ts);
2476 /* IBM OS/390 aka MVS aka z/OS.
2477 Text from Dan Espen <dane@mk.telcordia.com>.
2478 Apparently this isn't actually a crash, just a random session...
2483 os390 (Display* dpy, Window window, int delay)
2487 XWindowAttributes xgwa;
2488 scrolling_window *ts;
2491 const char *msg[] = {
2492 "* ISPF Subtask abend *\n",
2493 "SPF ENDED DUE TO ERROR+\n",
2496 "IEA995I SYMPTOM DUMP OUTPUT\n",
2497 " USER COMPLETION CODE=0222\n",
2498 " TIME=23.00.51 SEQ=03210 CPU=0000 ASID=00AE\n",
2499 " PSW AT TIME OF ERROR 078D1000 859DAF18 ILC 2 INTC 0D\n",
2500 " NO ACTIVE MODULE FOUND\n",
2502 " DATA AT PSW 059DAF12 - 00181610 0A0D9180 70644710\n",
2503 " AR/GR 0: 00000000/80000000 1: 00000000/800000DE\n",
2504 " 2: 00000000/196504DC 3: 00000000/00037A78\n",
2505 " 4: 00000000/00037B78 5: 00000000/0003351C\n",
2506 " 6: 00000000/0000F0AD 7: 00000000/00012000\n",
2507 " 8: 00000000/059DAF10 9: 00000000/0002D098\n",
2508 " A: 00000000/059D9F10 B: 00000000/059D8F10\n",
2509 " C: 00000000/859D7F10 D: 00000000/00032D60\n",
2510 " E: 00000000/00033005 F: 01000002/00000041\n",
2511 " END OF SYMPTOM DUMP\n",
2512 "ISPS014 - ** Logical screen request failed - abend 0000DE **\n",
2513 "ISPS015 - ** Contact your system programmer or dialog developer.**\n",
2514 "*** ISPF Main task abend ***\n",
2515 "IEA995I SYMPTOM DUMP OUTPUT\n",
2516 " USER COMPLETION CODE=0222\n",
2517 " TIME=23.00.52 SEQ=03211 CPU=0000 ASID=00AE\n",
2518 " PSW AT TIME OF ERROR 078D1000 8585713C ILC 2 INTC 0D\n",
2519 " ACTIVE LOAD MODULE ADDRESS=05855000 OFFSET=0000213C\n",
2521 " DATA AT PSW 05857136 - 00181610 0A0D9180 D3304770\n",
2522 " GR 0: 80000000 1: 800000DE\n",
2523 " 2: 00015260 3: 00000038\n",
2524 " 4: 00012508 5: 00000000\n",
2525 " 6: 000173AC 7: FFFFFFF8\n",
2526 " 8: 05858000 9: 00012CA0\n",
2527 " A: 05857000 B: 05856000\n",
2528 " C: 85855000 D: 00017020\n",
2529 " E: 85857104 F: 00000000\n",
2530 " END OF SYMPTOM DUMP\n",
2535 XGetWindowAttributes (dpy, window, &xgwa);
2536 ts = make_scrolling_window (dpy, window, "OS390", False);
2537 ts->columns = 10000; /* never wrap */
2540 ts->sub_width = xgwa.width;
2541 ts->sub_height = xgwa.height;
2543 gcv.foreground = get_pixel_resource ("390.background", "390.Background",
2544 dpy, xgwa.colormap);
2545 gc = XCreateGC (dpy, window, GCForeground, &gcv);
2546 XFillRectangle (dpy, window, gc, 0, 0, xgwa.width, xgwa.height);
2549 for (i = 0; i < countof (msg); i++)
2551 scrolling_puts (ts, msg[i], 0);
2553 if (bsod_sleep(dpy, 0)) goto DONE;
2557 bsod_sleep(dpy, delay);
2559 free_scrolling_window (ts);
2565 * Simulate various Apple II crashes. The memory map encouraged many
2566 * programs to use the primary hi-res video page for various storage,
2567 * and the secondary hi-res page for active display. When it crashed
2568 * into Applesoft or the monitor, it would revert to the primary page
2569 * and you'd see memory garbage on the screen. Also, it was common for
2570 * copy-protected games to use the primary text page for important
2571 * code, because that made it really hard to reverse-engineer them. The
2572 * result often looked like what this generates.
2574 * Sometimes an imaginary user types some of the standard commands to
2575 * recover from crashes. You can turn off BSOD*apple2SimulateUser to
2578 * It simulates the following characteristics of standard television
2581 * - Realistic rendering of a composite video signal
2582 * - Compression & brightening on the right, as the scan gets truncated
2583 * because of saturation in the flyback transformer
2584 * - Blooming of the picture dependent on brightness
2585 * - Overscan, cutting off a few pixels on the left side.
2586 * - Colored text in mixed graphics/text modes
2588 * It's amazing how much it makes your high-end monitor look like at
2589 * large late-70s TV. All you need is to put a big "Solid State" logo
2590 * in curly script on it and you'd be set.
2592 * Trevor Blackwell <tlb@tlb.org>
2596 * Implementation notes:
2598 * There are roughly 3 parts to this hack:
2600 * - emulation of A2 Basic and Monitor. Not much more than printing random
2601 * plausible messages. Here we work in the A2 memory space.
2603 * - emulation of the A2's video output section, which shifted bits out of main
2604 * memory at a 14 MHz dot clock rate, sort of. You could only read one byte
2605 * per MHz, so there were various schemes for turning 8 bits into 14 screen
2608 * - simulation of an NTSC television, which turned the bits into colored
2609 * graphics and text.
2611 * The A2 had 3 display modes: text, lores, and hires. Text was 40x24, and it
2612 * disabled color in the TV. Lores gave you 40x48 graphics blocks, using the
2613 * same memory as the text screen. Each could be one of 16 colors. Hires gave
2614 * you 280x192 pixels. Odd pixels were blue or purple, and even pixels were
2615 * orange or green depending on the setting of the high bit in each byte.
2617 * The graphics modes could also have 4 lines of text at the bottom. This was
2618 * fairly unreadable if you had a color monitor.
2620 * Each mode had 2 different screens using different memory space. In hires
2621 * mode this was sometimes used for double buffering, but more often the lower
2622 * screen was full of code/data and the upper screen was used for display, so
2623 * you got random garbage on the screen.
2625 * In DirectColor or TrueColor modes, it generates pixel values directly from
2626 * RGB values it calculates across each scan line. In PseudoColor mode, it
2627 * consider each possible pattern of 5 preceding bit values in each possible
2628 * position modulo 4 and allocates a color for each. A few things, like the
2629 * brightening on the right side as the horizontal trace slows down, aren't
2630 * done in PseudoColor.
2632 * The text font is based on X's standard 6x10 font, with a few tweaks like
2633 * putting a slash across the zero.
2635 * I'd like to add a bit of visible retrace, but it conflicts with being able
2636 * to bitcopy the image when fast scrolling. After another couple of CPU
2637 * generations, we could probably regenerate the whole image from scratch every
2638 * time. On a P4 2 GHz it can manage this fine for blinking text, but scrolling
2642 static char * apple2_basic_errors[]={
2646 "RETURN WITHOUT GOSUB",
2650 "BAD SUBSCRIPT ERROR",
2653 "FORMULA TOO COMPLEX",
2657 static char * apple2_dos_errors[]={
2661 "NO BUFFERS AVAILABLE",
2662 "PROGRAM TOO LARGE",
2665 struct apple2_state {
2666 char hireslines[192][40];
2667 char textlines[24][40];
2687 a2_scroll(struct apple2_state *st)
2690 int top=(st->gr_mode&(A2_GR_LORES|A2_GR_HIRES)) ? 20 : 0;
2691 if ((st->gr_mode&A2_GR_FULL) && (st->gr_mode&A2_GR_HIRES)) return;
2692 if (st->gr_mode&A2_GR_FULL) top=0;
2693 for (i=top; i<23; i++) {
2694 if (memcmp(st->textlines[i],st->textlines[i+1],40)) {
2695 memcpy(st->textlines[i],st->textlines[i+1],40);
2696 st->rowimage[i]=st->rowimage[i+1];
2699 memset(st->textlines[23],0xe0,40);
2700 st->rowimage[23]=-1;
2704 a2_printc(struct apple2_state *st, char c)
2706 st->textlines[st->cursy][st->cursx] |= 0xc0; /* turn off blink */
2708 if (st->cursy==23) {
2711 st->rowimage[st->cursy]=-1;
2713 st->rowimage[st->cursy]=-1;
2717 st->textlines[st->cursy][st->cursx]=c ^ 0xc0;
2718 st->rowimage[st->cursy]=-1;
2720 if (st->cursx==40) {
2721 if (st->cursy==23) {
2724 st->rowimage[st->cursy]=-1;
2726 st->rowimage[st->cursy]=-1;
2731 st->textlines[st->cursy][st->cursx] &= 0x7f; /* turn on blink */
2735 a2_goto(struct apple2_state *st, int r, int c)
2737 st->textlines[st->cursy][st->cursx] |= 0xc0; /* turn off blink */
2740 st->textlines[st->cursy][st->cursx] &= 0x7f; /* turn on blink */
2744 a2_cls(struct apple2_state *st)
2747 for (i=0; i<24; i++) {
2748 memset(st->textlines[i],0xe0,40);
2754 a2_invalidate(struct apple2_state *st)
2757 for (i=0; i<24; i++) {
2763 a2_poke(struct apple2_state *st, int addr, int val)
2766 if (addr>=0x400 && addr<0x800) {
2768 int row=((addr&0x380)/0x80) + ((addr&0x7f)/0x28)*8;
2769 int col=(addr&0x7f)%0x28;
2770 if (row<24 && col<40) {
2771 st->textlines[row][col]=val;
2772 if (!(st->gr_mode&(A2_GR_HIRES)) ||
2773 (!(st->gr_mode&(A2_GR_FULL)) && row>=20)) {
2774 st->rowimage[row]=-1;
2778 else if (addr>=0x2000 && addr<0x4000) {
2779 int row=(((addr&0x1c00) / 0x400) * 1 +
2780 ((addr&0x0380) / 0x80) * 8 +
2781 ((addr&0x0078) / 0x28) * 64);
2782 int col=((addr&0x07f)%0x28);
2783 if (row<192 && col<40) {
2784 st->hireslines[row][col]=val;
2785 if (st->gr_mode&A2_GR_HIRES) {
2786 st->rowimage[row/8]=-1;
2792 /* This table lists fixes for characters that differ from the standard 6x10
2793 font. Each encodes a pixel, as (charindex*7 + x) + (y<<10) + (value<<15)
2794 where value is 0 for white and 1 for black. */
2795 static unsigned short a2_fixfont[] = {
2796 /* Fix $ */ 0x8421, 0x941d,
2797 /* Fix % */ 0x8024, 0x0028, 0x8425, 0x0426, 0x0825, 0x1027, 0x1426, 0x9427,
2799 /* Fix * */ 0x8049, 0x8449, 0x8849, 0x0c47, 0x0c48, 0x0c4a, 0x0c4b, 0x9049,
2801 /* Fix , */ 0x9057, 0x1458, 0x9856, 0x1857, 0x1c56,
2802 /* Fix . */ 0x1465, 0x1864, 0x1866, 0x1c65,
2803 /* Fix / */ 0x006e, 0x186a,
2804 /* Fix 0 */ 0x8874, 0x8c73, 0x9072,
2805 /* Fix 1 */ 0x0878, 0x1878, 0x187c,
2806 /* Fix 5 */ 0x8895, 0x0c94, 0x0c95,
2807 /* Fix 6 */ 0x809f, 0x8c9c, 0x109c,
2808 /* Fix 7 */ 0x8ca4, 0x0ca5, 0x90a3, 0x10a4,
2809 /* Fix 9 */ 0x08b3, 0x8cb3, 0x98b0,
2810 /* Fix : */ 0x04b9, 0x08b8, 0x08ba, 0x0cb9, 0x90b9, 0x14b9, 0x18b8, 0x18b9,
2812 /* Fix ; */ 0x04c0, 0x08bf, 0x08c1, 0x0cc0, 0x90c0, 0x14c1, 0x98bf, 0x18c0,
2814 /* Fix < */ 0x80c8, 0x00c9, 0x84c7, 0x04c8, 0x88c6, 0x08c7, 0x8cc5, 0x0cc6,
2816 0x94c7, 0x14c8, 0x98c8, 0x18c9,
2817 /* Fix > */ 0x80d3, 0x00d4, 0x84d4, 0x04d5, 0x88d5, 0x08d6, 0x8cd6, 0x0cd7,
2819 0x94d4, 0x14d5, 0x98d3, 0x18d4,
2820 /* Fix @ */ 0x88e3, 0x08e4, 0x8ce4, 0x98e5,
2821 /* Fix B */ 0x84ef, 0x04f0, 0x88ef, 0x08f0, 0x8cef, 0x90ef, 0x10f0, 0x94ef,
2823 /* Fix D */ 0x84fd, 0x04fe, 0x88fd, 0x08fe, 0x8cfd, 0x0cfe, 0x90fd, 0x10fe,
2825 /* Fix G */ 0x8116, 0x0516, 0x9916,
2826 /* Fix J */ 0x0129, 0x012a, 0x052a, 0x852b, 0x092a, 0x892b, 0x0d2a, 0x8d2b,
2828 0x152a, 0x952b, 0x992a,
2829 /* Fix M */ 0x853d, 0x853f, 0x093d, 0x893e, 0x093f,
2830 /* Fix Q */ 0x915a, 0x155a, 0x955b, 0x155c, 0x195b, 0x995c, 0x1d5c,
2831 /* Fix V */ 0x8d7b, 0x0d7c, 0x0d7e, 0x8d7f, 0x917b, 0x117c, 0x117e, 0x917f,
2832 /* Fix [ */ 0x819e, 0x81a2, 0x859e, 0x899e, 0x8d9e, 0x919e, 0x959e, 0x999e,
2834 /* Fix \ */ 0x01a5, 0x19a9,
2835 /* Fix ] */ 0x81ac, 0x81b0, 0x85b0, 0x89b0, 0x8db0, 0x91b0, 0x95b0, 0x99ac,
2837 /* Fix ^ */ 0x01b5, 0x05b4, 0x05b6, 0x09b3, 0x89b5, 0x09b7, 0x8db4, 0x8db6,
2839 /* Fix _ */ 0x9db9, 0x9dbf,
2850 int brightness_control;
2854 First generate the I and Q reference signals, which we'll multiply by the
2855 input signal to accomplish the demodulation. Normally they are shifted 33
2856 degrees from the colorburst. I think this was convenient for
2857 inductor-capacitor-vacuum tube implementation.
2859 The tint control, FWIW, just adds a phase shift to the chroma signal, and
2860 the color control controls the amplitude.
2862 In text modes (colormode==0) the system disabled the color burst, and no
2863 color was detected by the monitor.
2865 freq_error gives a mismatch between the built-in oscillator and the TV's
2866 colorbust. Older II Plus machines seemed to occasionally get instability
2867 problems -- the crystal oscillator was a single transistor if I remember
2868 correctly -- and the frequency would vary enough that the tint would change
2869 across the width of the screen. The left side would be in correct tint
2870 because it had just gotten resynchronized with the color burst.
2873 ntsc_set_demod(struct ntsc_dec *it, double tint_control,
2874 double color_control, double brightness_control,
2880 it->brightness_control=(int)(1024.0*brightness_control);
2882 for (i=0; i<600; i++) {
2883 double phase=90.0-90.0*i + freq_error*i/600.0 + tint_control;
2884 it->multi[i]=(int)(-cos(3.1415926/180.0*(phase-303)) * 65536.0 *
2885 color_control * colormode * 4);
2886 it->multq[i]=(int)(cos(3.1415926/180.0*(phase-33)) * 65536.0 *
2887 color_control * colormode * 4);
2891 /* Here we model the analog circuitry of an NTSC television. Basically, it
2892 splits the signal into 3 signals: Y, I and Q. Y corresponds to luminance,
2893 and you get it by low-pass filtering the input signal to below 3.57 MHz.
2895 I and Q are the in-phase and quadrature components of the 3.57 MHz
2896 subcarrier. We get them by multiplying by cos(3.57 MHz*t) and sin(3.57
2897 MHz*t), and low-pass filtering. Because the eye has less resolution in some
2898 colors than others, the I component gets low-pass filtered at 1.5 MHz and
2899 the Q at 0.5 MHz. The I component is approximately orange-blue, and Q is
2900 roughly purple-green. See http://www.ntsc-tv.com for details.
2903 ntsc_to_yiq(struct ntsc_dec *it)
2906 int fyx[10],fyy[10];
2907 int fix[10],fiy[10];
2908 int fqx[10],fqy[10];
2910 int iny,ini,inq,pix,blank;
2912 for (i=0; i<10; i++) fyx[i]=fyy[i]=fix[i]=fiy[i]=fqx[i]=fqy[i]=0.0;
2914 for (i=0; i<600; i++) {
2915 /* Get the video out signal, and add a teeny bit of ghosting, typical of RF
2916 monitor cables. This corresponds to a pretty long cable, but looks right
2918 pix=it->pattern[i]*1024;
2919 if (i>=20) pixghost += it->pattern[i-20]*15;
2920 if (i>=30) pixghost -= it->pattern[i-30]*15;
2923 /* Get Y, I, Q before filtering */
2925 ini=(pix*it->multi[i])>>16;
2926 inq=(pix*it->multq[i])>>16;
2928 blank = (i>=7 && i<596 ? it->brightness_control : -200);
2930 /* Now filter them. These are infinite impulse response filters calculated
2931 by the script at http://www-users.cs.york.ac.uk/~fisher/mkfilter. This
2932 is fixed-point integer DSP, son. No place for wimps. We do it in integer
2933 because you can count on integer being faster on most CPUs. We care
2934 about speed because we need to recalculate every time we blink text, and
2935 when we spew random bytes into screen memory. This is roughly 16.16
2936 fixed point arithmetic, but we scale some filter values up by a few bits
2937 to avoid some nasty precision errors. */
2939 /* Filter y at with a 4-pole low-pass Butterworth filter at 3.5 MHz
2940 with an extra zero at 3.5 MHz, from
2941 mkfilter -Bu -Lp -o 4 -a 2.1428571429e-01 0 -Z 2.5e-01 -l
2944 fyx[0] = fyx[1]; fyx[1] = fyx[2]; fyx[2] = fyx[3];
2945 fyx[3] = fyx[4]; fyx[4] = fyx[5]; fyx[5] = fyx[6];
2946 fyx[6] = (iny * 1897) >> 13;
2947 fyy[0] = fyy[1]; fyy[1] = fyy[2]; fyy[2] = fyy[3];
2948 fyy[3] = fyy[4]; fyy[4] = fyy[5]; fyy[5] = fyy[6];
2949 fyy[6] = (fyx[0]+fyx[6]) + 4*(fyx[1]+fyx[5]) + 7*(fyx[2]+fyx[4]) + 8*fyx[3]
2950 + ((-151*fyy[2] + 8115*fyy[3] - 38312*fyy[4] + 36586*fyy[5]) >> 16);
2951 if (i>=2) it->ntscy[i-2] = blank + (fyy[6]>>3);
2953 /* Filter I and Q at 1.5 MHz. 3 pole Butterworth from
2954 mkfilter -Bu -Lp -o 3 -a 1.0714285714e-01 0
2957 The NTSC spec says the Q value should be filtered at 0.5 MHz at the
2958 transmit end, But the Apple's video circuitry doesn't any such thing.
2959 AFAIK, oldish televisions (before comb filters) simply applied a 1.5 MHz
2960 filter to both after the demodulator.
2963 fix[0] = fix[1]; fix[1] = fix[2]; fix[2] = fix[3];
2964 fix[3] = (ini * 1413) >> 14;
2965 fiy[0] = fiy[1]; fiy[1] = fiy[2]; fiy[2] = fiy[3];
2966 fiy[3] = (fix[0]+fix[3]) + 3*(fix[1]+fix[2])
2967 + ((16559*fiy[0] - 72008*fiy[1] + 109682*fiy[2]) >> 16);
2968 if (i>=3) it->ntsci[i-3] = fiy[3]>>2;
2970 fqx[0] = fqx[1]; fqx[1] = fqx[2]; fqx[2] = fqx[3];
2971 fqx[3] = (inq * 1413) >> 14;
2972 fqy[0] = fqy[1]; fqy[1] = fqy[2]; fqy[2] = fqy[3];
2973 fqy[3] = (fqx[0]+fqx[3]) + 3*(fqx[1]+fqx[2])
2974 + ((16559*fqy[0] - 72008*fqy[1] + 109682*fqy[2]) >> 16);
2975 if (i>=3) it->ntscq[i-3] = fqy[3]>>2;
2978 for (; i<610; i++) {
2979 if (i-2<600) it->ntscy[i-2]=0;
2980 if (i-3<600) it->ntsci[i-3]=0;
2981 if (i-9<600) it->ntscq[i-9]=0;
2991 #define A2_CMAP_INDEX(COLORMODE, LEVEL, HIST, OFFSET) \
2992 ((((COLORMODE)*A2_CMAP_LEVELS+(LEVEL))<<A2_CMAP_HISTBITS)+(HIST))* \
2993 A2_CMAP_OFFSETS+(OFFSET)
2996 apple2(Display *dpy, Window window, int delay)
2998 int w,h,i,j,x,y,textrow,row,col,stepno,colormode,imgrow;
3000 struct timeval basetime_tv;
3001 double next_actiontime;
3002 XWindowAttributes xgwa;
3004 int screen_xo,screen_yo;
3008 XImage *text_im=NULL;
3009 unsigned long colors[A2_CMAP_INDEX(1, A2_CMAP_LEVELS-1,
3010 (1<<A2_CMAP_HISTBITS)-1,
3011 A2_CMAP_OFFSETS-3)+1];
3013 int screen_plan[24];
3014 struct ntsc_dec *dec=NULL;
3015 short *raw_rgb=NULL, *rrp;
3016 struct apple2_state *st=NULL;
3017 char *typing=NULL,*printing=NULL;
3018 char printbuf[1024];
3021 double tint_control,color_control,brightness_control,contrast_control;
3022 double freq_error=0.0,freq_error_inc=0.0;
3023 double horiz_desync=5.0;
3024 int flutter_horiz_desync=0;
3026 double crtload[192];
3027 int red_invprec,red_shift,green_invprec,green_shift,blue_invprec,blue_shift;
3028 int fillptr, fillbyte;
3029 int use_shm,use_cmap,use_color;
3030 /* localbyteorder is 1 if MSB first, 0 otherwise */
3031 unsigned int localbyteorder_loc = MSBFirst<<24;
3032 int localbyteorder=*(char *)&localbyteorder_loc;
3033 #ifdef HAVE_XSHM_EXTENSION
3034 XShmSegmentInfo shm_info;
3037 #ifdef HAVE_XSHM_EXTENSION
3038 use_shm=get_boolean_resource ("useSHM", "Boolean");
3043 /* Model the video controls on a standard television */
3044 tint_control = get_float_resource("apple2TVTint","Apple2TVTint");
3045 color_control = get_float_resource("apple2TVColor","Apple2TVColor")/100.0;
3046 brightness_control = get_float_resource("apple2TVBrightness",
3047 "Apple2TVBrightness") / 100.0;
3048 contrast_control = get_float_resource("apple2TVContrast",
3049 "Apple2TVContrast") / 100.0;
3050 simulate_user = get_boolean_resource("apple2SimulateUser",
3051 "Apple2SimulateUser");
3053 XGetWindowAttributes (dpy, window, &xgwa);
3054 visclass=xgwa.visual->class;
3055 red_shift=red_invprec=green_shift=green_invprec=blue_shift=blue_invprec=-1;
3056 if (visclass == TrueColor || xgwa.visual->class == DirectColor) {
3060 else if (visclass == PseudoColor || visclass == StaticColor) {
3069 /* The Apple II screen was 280x192, sort of. We expand the width to 300
3070 pixels to allow for overscan. We then pick a size within the window
3071 that's an integer multiple of 300x192. The small case happens when
3072 we're displaying in a subwindow. Then it ends up showing the center
3073 of the screen, which is OK. */
3075 h = (xgwa.height/192)*192;
3079 dec=(struct ntsc_dec *)malloc(sizeof(struct ntsc_dec));
3082 int hist,offset,level;
3087 /* Typically allocates 214 distinct colors, but will scale back its
3088 ambitions pretty far if it can't get them */
3089 for (colormode=0; colormode<=use_color; colormode++) {
3090 ntsc_set_demod(dec, tint_control, color_control, brightness_control,
3092 for (level=0; level<2; level++) {
3093 for (hist=0; hist<(1<<A2_CMAP_HISTBITS); hist++) {
3094 for (offset=0; offset<4; offset++) {
3095 int interpy,interpi,interpq,r,g,b;
3096 int levelmult=level ? 64 : 32;
3097 int prec=colormode ? colorprec : (colorprec*2+2)/3;
3098 int precmask=(0xffff<<(16-prec))&0xffff;
3101 if (A2_CMAP_INDEX(colormode,level,hist,offset) != n_colors) {
3102 fprintf(stderr, "apple2: internal colormap allocation error\n");
3106 for (i=0; i<600; i++) dec->pattern[i]=0;
3107 for (i=0; i<A2_CMAP_HISTBITS; i++) {
3108 dec->pattern[64+offset-i]=(hist>>i)&1;
3112 interpy=dec->ntscy[63+offset];
3113 interpi=dec->ntsci[63+offset];
3114 interpq=dec->ntscq[63+offset];
3116 r=(interpy + ((+68128*interpi+40894*interpq)>>16))*levelmult;
3117 g=(interpy + ((-18087*interpi-41877*interpq)>>16))*levelmult;
3118 b=(interpy + ((-72417*interpi+113312*interpq)>>16))*levelmult;
3120 if (r>65535) r=65535;
3122 if (g>65535) g=65535;
3124 if (b>65535) b=65535;
3126 col.red=r & precmask;
3127 col.green=g & precmask;
3128 col.blue=b & precmask;
3130 if (!XAllocColor(dpy, xgwa.colormap, &col)) {
3131 XFreeColors(dpy, xgwa.colormap, colors, n_colors, 0L);
3139 colors[n_colors++]=col.pixel;
3145 /* Is there a standard way to do this? Does this handle all cases? */
3147 for (shift=0; shift<32; shift++) {
3148 for (prec=1; prec<16 && prec<32-shift; prec++) {
3149 unsigned long mask=(0xffffUL>>(16-prec)) << shift;
3150 if (red_shift<0 && mask==xgwa.visual->red_mask)
3151 red_shift=shift, red_invprec=16-prec;
3152 if (green_shift<0 && mask==xgwa.visual->green_mask)
3153 green_shift=shift, green_invprec=16-prec;
3154 if (blue_shift<0 && mask==xgwa.visual->blue_mask)
3155 blue_shift=shift, blue_invprec=16-prec;
3158 if (red_shift<0 || green_shift<0 || blue_shift<0) {
3159 if (0) fprintf(stderr,"Can't figure out color space\n");
3162 raw_rgb=(short *)calloc(w*3, sizeof(short));
3166 gc = XCreateGC(dpy, window, GCBackground, &gcv);
3167 XSetWindowBackground(dpy, window, gcv.background);
3168 XClearWindow(dpy,window);
3170 screen_xo=(xgwa.width-w)/2;
3171 screen_yo=(xgwa.height-h)/2;
3174 #ifdef HAVE_XSHM_EXTENSION
3175 image = create_xshm_image (dpy, xgwa.visual, xgwa.depth, ZPixmap, 0,
3179 fprintf(stderr, "create_xshm_image failed\n");
3184 image = XCreateImage(dpy, xgwa.visual, xgwa.depth, ZPixmap, 0, 0,
3186 image->data = (char *)calloc(image->height, image->bytes_per_line);
3189 st=(struct apple2_state *)calloc(1,sizeof(struct apple2_state));
3192 Generate the font. It used a 5x7 font which looks a lot like the standard X
3193 6x10 font, with a few differences. So we render up all the uppercase
3194 letters of 6x10, and make a few tweaks (like putting a slash across the
3195 zero) according to fixfont.
3198 const char *def_font="6x10";
3203 font = XLoadQueryFont (dpy, def_font);
3205 fprintf(stderr,"Can't load font %s\n",def_font);
3209 text_pm=XCreatePixmap(dpy, window, 64*7, 8, xgwa.depth);
3214 gc=XCreateGC(dpy, text_pm, GCFont|GCBackground|GCForeground, &gcv);
3216 XSetForeground(dpy, gc, 0);
3217 XFillRectangle(dpy, text_pm, gc, 0, 0, 64*7, 8);
3218 XSetForeground(dpy, gc, 1);
3219 for (i=0; i<64; i++) {
3225 XDrawString(dpy, text_pm, gc, x, y, &c, 1);
3227 XDrawString(dpy, text_pm, gc, x, y, &c, 1);
3230 text_im = XGetImage(dpy, text_pm, 0, 0, 64*7, 8, ~0L, ZPixmap);
3232 XFreePixmap(dpy, text_pm);
3234 for (i=0; a2_fixfont[i]; i++) {
3235 XPutPixel(text_im, a2_fixfont[i]&0x3ff,
3236 (a2_fixfont[i]>>10)&0xf,
3237 (a2_fixfont[i]>>15)&1);
3242 Simulate plausible initial memory contents.
3246 while (addr<0x4000) {
3249 switch (random()%4) {
3253 for (i=0; i<n && addr<0x4000; i++) {
3254 u_char rb=((random()%6==0 ? 0 : random()%16) |
3255 ((random()%5==0 ? 0 : random()%16)<<4));
3256 a2_poke(st, addr++, rb);
3261 /* Simulate shapes stored in memory. We use the font since we have it.
3262 Unreadable, since rows of each character are stored in consecutive
3263 bytes. It was typical to store each of the 7 possible shifts of
3264 bitmaps, for fastest blitting to the screen. */
3265 x=random()%(text_im->width);
3266 for (i=0; i<100; i++) {
3267 for (y=0; y<8; y++) {
3269 for (j=0; j<8; j++) {
3270 c |= XGetPixel(text_im, (x+j)%text_im->width, y)<<j;
3272 a2_poke(st, addr++, c);
3274 x=(x+1)%(text_im->width);
3281 for (i=0; i<n && addr<0x4000; i++) {
3282 a2_poke(st, addr++, 0);
3291 if (random()%4==0 &&
3292 !use_cmap && use_color &&
3293 xgwa.visual->bits_per_rgb>=8) {
3296 else if (random()%3==0) {
3297 flutter_horiz_desync=1;
3303 gettimeofday(&basetime_tv, NULL);
3304 if (random()%2==0) basetime_tv.tv_sec -= 1; /* random blink phase */
3305 next_actiontime=0.0;
3308 double curtime,blinkphase;
3309 int startdisplayrow=0;
3313 struct timeval curtime_tv;
3314 gettimeofday(&curtime_tv, NULL);
3315 curtime=(curtime_tv.tv_sec - basetime_tv.tv_sec) +
3316 0.000001*(curtime_tv.tv_usec - basetime_tv.tv_usec);
3318 if (curtime>delay) goto finished;
3320 if (bsod_sleep(dpy,0)) goto finished;
3322 if (flutter_tint && st->gr_mode && !printing) {
3323 /* Oscillator instability. Look for freq_error below. We should only do
3324 this with color depth>=8, since otherwise you see pixels changing. */
3325 freq_error_inc += (-0.10*freq_error_inc
3326 + ((int)(random()&0xff)-0x80) * 0.01);
3327 freq_error += freq_error_inc;
3331 else if (flutter_horiz_desync) {
3332 /* Horizontal sync during vertical sync instability. */
3333 horiz_desync += (-0.10*(horiz_desync-3.0) +
3334 ((int)(random()&0xff)-0x80) *
3335 ((int)(random()&0xff)-0x80) *
3336 ((int)(random()&0xff)-0x80) * 0.0000003);
3337 for (i=0; i<3; i++) st->rowimage[i]=-1;
3341 /* It's super-important to get the cursor/text flash out at exactly the
3342 right time, or it looks wrong. So if we're almost due for a blink, wait
3343 for it so we don't miss it in the middle of a screen update. */
3344 blinkphase=curtime/0.8;
3345 if (blinkphase-floor(blinkphase)>0.7 && !printing && !nodelay) {
3346 /* We're about to blink */
3347 int delay = ((1.0-(blinkphase-floor(blinkphase)))*0.8) * 1000000;
3348 if (delay<1000) delay=1000;
3353 /* The blinking rate was controlled by 555 timer with a resistor/capacitor
3354 time constant. Because the capacitor was electrolytic, the flash rate
3355 varied somewhat between machines. I'm guessing 1.6 seconds/cycle was
3356 reasonable. (I soldered a resistor in mine to make it blink faster.) */
3358 st->blink=((int)blinkphase)&1;
3359 if (st->blink!=i && !(st->gr_mode&A2_GR_FULL)) {
3361 /* For every row with blinking text, set the changed flag. This basically
3362 works great except with random screen garbage in text mode, when we
3363 end up redrawing the whole screen every second */
3364 for (row=(st->gr_mode ? 20 : 0); row<24; row++) {
3365 for (col=0; col<40; col++) {
3366 c=st->textlines[row][col];
3367 if ((c & 0xc0) == 0x40) {
3372 if (downcounter>0) {
3373 st->rowimage[row]=-1;
3377 st->rowimage[st->cursy]=-1;
3378 startdisplayrow=random()%24;
3380 else if (next_actiontime > curtime && !printing && !nodelay) {
3381 int delay = (next_actiontime-curtime)*1000000;
3383 if (delay>100000) delay=100000;
3384 if (delay<1000) delay=1000;
3392 if (*printing=='\001') { /* pause */
3394 for (i=20; i<24; i++) st->rowimage[i]=-1;
3397 else if (*printing=='\n') {
3398 a2_printc(st,*printing);
3403 a2_printc(st,*printing);
3407 if (!*printing) printing=NULL;
3409 else if (curtime >= next_actiontime) {
3411 /* If we're in the midst of typing a string, emit a character with
3413 a2_printc(st, *typing);
3414 if (*typing=='\n') {
3415 next_actiontime = curtime;
3417 next_actiontime = curtime + (random()%1000)*0.0003 + 0.3;
3421 if (!*typing) typing=NULL;
3425 next_actiontime=curtime;
3432 For testing color rendering. The spec is:
3440 6 med blue 20 207 253
3441 7 lt blue 208 195 255
3446 12 lt green 20 245 60
3447 13 yellow 208 221 141
3449 15 white 255 255 255
3451 st->gr_mode=A2_GR_LORES;
3452 for (row=0; row<24; row++) {
3453 for (col=0; col<40; col++) {
3454 st->textlines[row][col]=(row&15)*17;
3457 next_actiontime+=0.4;
3460 else if (random()%3==0) {
3462 next_actiontime+=0.4;
3465 else if (random()%4==0) {
3466 st->gr_mode=A2_GR_LORES;
3467 if (random()%3==0) st->gr_mode |= A2_GR_FULL;
3468 next_actiontime+=0.4;
3471 else if (random()%2==0) {
3472 st->gr_mode=A2_GR_HIRES;
3476 st->gr_mode=A2_GR_HIRES;
3477 next_actiontime+=0.4;
3483 /* An illegal instruction or a reset caused it to drop into the
3484 assembly language monitor, where you could disassemble code & view
3486 if (random()%3==0) {
3489 int addr=0xd000+random()%0x3000;
3491 "%02X",random()%0xff);
3497 " A=%02X X=%02X Y=%02X S=%02X F=%02X\n"
3500 random()%0xff, random()%0xff,
3501 random()%0xff, random()%0xff,
3511 next_actiontime += 2.0 + (random()%1000)*0.0002;
3514 /* Lots of programs had at least their main functionality in
3515 Applesoft Basic, which had a lot of limits (memory, string
3516 length, etc) and would sometimes crash unexpectedly. */
3523 apple2_basic_errors[random() %
3524 (sizeof(apple2_basic_errors)
3526 (1000*(random()%(random()%59+1)) +
3527 100*(random()%(random()%9+1)) +
3528 5*(random()%(random()%199+1)) +
3529 1*(random()%(random()%(random()%2+1)+1))));
3534 next_actiontime += 2.0 + (random()%1000)*0.0002;
3539 if (simulate_user && random()%3==0) {
3540 /* This was how you reset the Basic interpreter. The sort of
3541 incantation you'd have on a little piece of paper taped to the
3542 side of your machine */
3543 typing="CALL -1370";
3546 else if (simulate_user && random()%2==0) {
3551 next_actiontime+=1.0;
3558 next_actiontime += 0.5;
3565 for (s="APPLE ]["; *s; s++) a2_printc(st,*s);
3568 next_actiontime+=1.0;
3573 if (simulate_user && random()%50==0 && 0) { /* disabled, too goofy */
3574 typing="10 PRINT \"TRS-80S SUCK!!!\"\n"
3581 next_actiontime += delay;
3586 for (i=0; i<30; i++) {
3587 for (s="\nTRS-80S SUCK"; *s; s++) a2_printc(st,*s);
3590 next_actiontime+=delay;
3596 if (random()%50==0) {
3597 sprintf(printbuf,"\nDISK VOLUME 254\n\n"
3604 sprintf(printbuf,"\n?%s\n]",
3605 apple2_dos_errors[random()%
3606 (sizeof(apple2_dos_errors) /
3611 next_actiontime+=1.0;
3615 if (simulate_user && random()%2==0) {
3616 /* This was how you went back to text mode in the monitor */
3620 next_actiontime+=1.0;
3631 next_actiontime+=2.0;
3635 /* This reset things into Basic */
3636 if (simulate_user && random()%2==0) {
3642 next_actiontime+=delay;
3647 for (i=0; i<1500; i++) {
3648 a2_poke(st, fillptr, fillbyte);
3650 fillbyte = (fillbyte+1)&0xff;
3652 next_actiontime += 0.08;
3653 /* When you hit c000, it changed video settings */
3654 if (fillptr>=0xc000) {
3658 /* And it seemed to reset around here, I dunno why */
3659 if (fillptr>=0xcf00) stepno=3;
3665 /* Now, we turn the data in the Apple II video into a screen display. This
3666 is interesting because of the interaction with the NTSC color decoding
3667 in a color television. */
3669 colormode=use_color && st->gr_mode!=0;
3671 ntsc_set_demod(dec, tint_control, color_control, brightness_control,
3672 freq_error, colormode);
3675 for (textrow=0; textrow<24; textrow++) {
3676 if (st->rowimage[textrow] == textrow) {
3677 screen_plan[textrow]=0;
3679 else if (cheapdisplay && st->rowimage[textrow]>=0 &&
3680 textrow<21 && st->rowimage[textrow]<21 &&
3681 st->rowimage[textrow]>=2 && textrow>=2 &&
3682 (st->rowimage[textrow]+1)*h/24 + screen_xo <= xgwa.height) {
3683 screen_plan[textrow]= A2_SP_COPY | st->rowimage[textrow];
3684 for (i=0; i<8; i++) {
3685 crtload[textrow*8+i]=crtload[st->rowimage[textrow]*8+i];
3690 st->rowimage[textrow]=imgrow;
3691 screen_plan[textrow]=imgrow | A2_SP_PUT;
3693 for (row=textrow*8; row<textrow*8+8; row++) {
3695 int pixmultinc,pixbright;
3696 int scanstart_i, scanend_i;
3697 int squishright_i, squishdiv;
3699 double bloomthisrow,shiftthisrow;
3700 int ytop=(imgrow*h/24) + ((row-textrow*8) * h/192);
3701 int ybot=ytop+h/192;
3703 /* First we generate the pattern that the video circuitry shifts out
3704 of memory. It has a 14.something MHz dot clock, equal to 4 times
3705 the color burst frequency. So each group of 4 bits defines a
3706 color. Each character position, or byte in hires, defines 14
3707 dots, so odd and even bytes have different color spaces. So,
3708 pattern[0..600] gets the dots for one scan line. */
3710 memset(dec->pattern,0,sizeof(dec->pattern));
3713 if ((st->gr_mode&A2_GR_HIRES) && (row<160 ||
3714 (st->gr_mode&A2_GR_FULL))) {
3716 /* Emulate the mysterious pink line, due to a bit getting
3717 stuck in a shift register between the end of the last
3718 row and the beginning of this one. */
3719 if ((st->hireslines[row][0] & 0x80) &&
3720 (st->hireslines[row][39]&0x40)) {
3724 for (col=0; col<40; col++) {
3725 u_char b=st->hireslines[row][col];
3726 int shift=(b&0x80)?0:1;
3728 /* Each of the low 7 bits in hires mode corresponded to 2 dot
3729 clocks, shifted by one if the high bit was set. */
3730 for (i=0; i<7; i++) {
3731 pp[shift+1] = pp[shift] =(b>>i)&1;
3736 else if ((st->gr_mode&A2_GR_LORES) && (row<160 ||
3737 (st->gr_mode&A2_GR_FULL))) {
3738 for (col=0; col<40; col++) {
3739 u_char nib=(st->textlines[textrow][col] >> (((row/4)&1)*4))&0xf;
3740 /* The low or high nybble was shifted out one bit at a time. */
3741 for (i=0; i<14; i++) {
3742 *pp = (nib>>((col*14+i)&3))&1;
3748 for (col=0; col<40; col++) {
3750 c=st->textlines[textrow][col];
3751 /* hi bits control inverse/blink as follows:
3756 rev=!(c&0x80) && (!(c&0x40) || st->blink);
3758 for (i=0; i<7; i++) {
3759 for (i=0; i<7; i++) {
3760 unsigned long pix=XGetPixel(text_im,
3761 ((c&0x3f)^0x20)*7+i, row%8);
3762 pp[1] = pp[2] = pix^rev;
3770 Interpolate the 600-dotclock line into however many horizontal
3771 screen pixels we're using, and convert to RGB.
3773 We add some 'bloom', variations in the horizontal scan width with
3774 the amount of brightness, extremely common on period TV sets. They
3775 had a single oscillator which generated both the horizontal scan
3776 and (during the horizontal retrace interval) the high voltage for
3777 the electron beam. More brightness meant more load on the
3778 oscillator, which caused an decrease in horizontal deflection. Look
3781 Also, the A2 did a bad job of generating horizontal sync pulses
3782 during the vertical blanking interval. This, and the fact that the
3783 horizontal frequency was a bit off meant that TVs usually went a
3784 bit out of sync during the vertical retrace, and the top of the
3785 screen would be bent a bit to the left or right. Look for
3788 We also add a teeny bit of left overscan, just enough to be
3789 annoying, but you can still read the left column of text.
3791 We also simulate compression & brightening on the right side of the
3792 screen. Most TVs do this, but you don't notice because they
3793 overscan so it's off the right edge of the CRT. But the A2 video
3794 system used so much of the horizontal scan line that you had to
3795 crank the horizontal width down in order to not lose the right few
3796 characters, and you'd see the compression on the right
3797 edge. Associated with compression is brightening; since the
3798 electron beam was scanning slower, the same drive signal hit the
3799 phosphor harder. Look for (squishright_i) and (squishdiv).
3802 for (i=j=0; i<600; i++) {
3803 j += dec->pattern[i];
3805 crtload[row] = (crtload[row>1 ? row-1 : 0]) * 0.98 + 0.02*(j/600.0) +
3806 (row>180 ? (row-180)*(row-180)*0.0005 : 0.0);
3807 bloomthisrow = -10.0 * crtload[row];
3808 shiftthisrow=((row<18) ? ((18-row)*(18-row)* 0.002 + (18-row)*0.05)
3809 * horiz_desync : 0.0);
3811 scanstart_i=(int)((bloomthisrow+shiftthisrow+18.0)*65536.0);
3812 if (scanstart_i<0) scanstart_i=0;
3813 if (scanstart_i>30*65536) scanstart_i=30*65536;
3814 scanend_i=599*65536;
3815 squishright_i=scanstart_i + 530*65536;
3817 pixrate=(int)((560.0-2.0*bloomthisrow)*65536.0/w);
3820 for (y=ytop; y<ybot; y++) {
3821 int level=(!(y==ytop && ybot-ytop>=3) &&
3822 !(y==ybot-1 && ybot-ytop>=5));
3827 for (x=0, i=scanstart_i;
3829 x++, i+=pixmultinc) {
3832 while (pati>=histi) {
3833 hist=(((hist<<1) & ((1<<A2_CMAP_HISTBITS)-1)) |
3834 dec->pattern[histi]);
3837 XPutPixel(image, x, y,
3838 colors[A2_CMAP_INDEX(colormode,level,hist,offset)]);
3839 if (i >= squishright_i) {
3840 pixmultinc += pixmultinc/squishdiv;
3844 XPutPixel(image, x, y, colors[0]);
3851 pixbright=(int)(contrast_control*65536.0);
3853 for (x=0, i=scanstart_i, rrp=raw_rgb;
3855 x++, i+=pixmultinc, rrp+=3) {
3856 int pixfrac=i&0xffff;
3857 int invpixfrac=65536-pixfrac;
3861 int interpy=((dec->ntscy[pati]*invpixfrac +
3862 dec->ntscy[pati+1]*pixfrac)>>16);
3863 int interpi=((dec->ntsci[pati]*invpixfrac +
3864 dec->ntsci[pati+1]*pixfrac)>>16);
3865 int interpq=((dec->ntscq[pati]*invpixfrac +
3866 dec->ntscq[pati+1]*pixfrac)>>16);
3869 According to the NTSC spec, Y,I,Q are generated as:
3871 y=0.30 r + 0.59 g + 0.11 b
3872 i=0.60 r - 0.28 g - 0.32 b
3873 q=0.21 r - 0.52 g + 0.31 b
3875 So if you invert the implied 3x3 matrix you get what standard
3876 televisions implement with a bunch of resistors (or directly in
3877 the CRT -- don't ask):
3879 r = y + 0.948 i + 0.624 q
3880 g = y - 0.276 i - 0.639 q
3881 b = y - 1.105 i + 1.729 q
3883 These coefficients are below in 16.16 format.
3886 r=((interpy + ((+68128*interpi+40894*interpq)>>16))*pixbright)
3888 g=((interpy + ((-18087*interpi-41877*interpq)>>16))*pixbright)
3890 b=((interpy + ((-72417*interpi+113312*interpq)>>16))*pixbright)
3899 if (i>=squishright_i) {
3900 pixmultinc += pixmultinc/squishdiv;
3901 pixbright += pixbright/squishdiv;
3904 for ( ; x<w; x++, rrp+=3) {
3905 rrp[0]=rrp[1]=rrp[2]=0;
3908 for (y=ytop; y<ybot; y++) {
3909 /* levelmult represents the vertical size of scan lines. Each
3910 line is brightest in the middle, and there's a dark band
3913 double levelmult_fp=(y + 0.5 - (ytop+ybot)*0.5) / (ybot-ytop);
3914 levelmult_fp = 1.0-(levelmult_fp*levelmult_fp*levelmult_fp
3915 *levelmult_fp)*16.0;
3916 if (levelmult_fp<0.0) levelmult_fp=0.0;
3917 levelmult = (int)(64.9*levelmult_fp);
3919 /* Fast special cases to avoid the slow XPutPixel. Ugh. It goes
3920 to show why standard graphics sw has to be fast, or else
3921 people will have to work around it and risk incompatibility.
3922 The quickdraw folks understood this. The other answer would
3923 be for X11 to have fewer formats for bitm.. oh, never
3924 mind. If neither of these cases work (they probably cover 99%
3925 of setups) it falls back on the Xlib routines. */
3926 if (image->format==ZPixmap && image->bits_per_pixel==32 &&
3927 sizeof(unsigned long)==4 &&
3928 image->byte_order==localbyteorder) {
3929 unsigned long *pixelptr =
3930 (unsigned long *) (image->data + y * image->bytes_per_line);
3931 for (x=0, rrp=raw_rgb; x<w; x++, rrp+=3) {
3932 unsigned long ntscri, ntscgi, ntscbi;
3933 ntscri=((unsigned long)rrp[0])*levelmult;
3934 ntscgi=((unsigned long)rrp[1])*levelmult;
3935 ntscbi=((unsigned long)rrp[2])*levelmult;
3936 if (ntscri>65535) ntscri=65535;
3937 if (ntscgi>65535) ntscgi=65535;
3938 if (ntscbi>65535) ntscbi=65535;
3939 *pixelptr++ = ((ntscri>>red_invprec)<<red_shift) |
3940 ((ntscgi>>green_invprec)<<green_shift) |
3941 ((ntscbi>>blue_invprec)<<blue_shift);
3944 else if (image->format==ZPixmap && image->bits_per_pixel==16 &&
3945 sizeof(unsigned short)==2 &&
3946 image->byte_order==localbyteorder) {
3947 unsigned short *pixelptr =
3948 (unsigned short *)(image->data + y*image->bytes_per_line);
3949 for (x=0, rrp=raw_rgb; x<w; x++, rrp+=3) {
3950 unsigned long ntscri, ntscgi, ntscbi;
3951 ntscri=((unsigned long)rrp[0])*levelmult;
3952 ntscgi=((unsigned long)rrp[1])*levelmult;
3953 ntscbi=((unsigned long)rrp[2])*levelmult;
3954 if (ntscri>65535) ntscri=65535;
3955 if (ntscgi>65535) ntscgi=65535;
3956 if (ntscbi>65535) ntscbi=65535;
3957 *pixelptr++ = ((ntscri>>red_invprec)<<red_shift) |
3958 ((ntscgi>>green_invprec)<<green_shift) |
3959 ((ntscbi>>blue_invprec)<<blue_shift);
3964 for (x=0, rrp=raw_rgb; x<w; x++, rrp+=3) {
3965 unsigned long pixel, ntscri, ntscgi, ntscbi;
3966 /* Convert to 16-bit color values, with saturation. The ntscr
3967 values are 22.10 fixed point, and levelmult is 24.6, so we
3969 ntscri=((unsigned long)rrp[0])*levelmult;
3970 ntscgi=((unsigned long)rrp[1])*levelmult;
3971 ntscbi=((unsigned long)rrp[2])*levelmult;
3972 if (ntscri>65535) ntscri=65535;
3973 if (ntscgi>65535) ntscgi=65535;
3974 if (ntscbi>65535) ntscbi=65535;
3975 pixel = ((ntscri>>red_invprec)<<red_shift) |
3976 ((ntscgi>>green_invprec)<<green_shift) |
3977 ((ntscbi>>blue_invprec)<<blue_shift);
3978 XPutPixel(image, x, y, pixel);
3988 /* For just the the rows which changed, blit the image to the screen. */
3989 for (textrow=0; textrow<24; ) {
3990 int top,bot,srcrow,srctop,nrows;
3993 while (textrow+nrows < 24 &&
3994 screen_plan[textrow+nrows] == screen_plan[textrow]+nrows)
3998 bot=h*(textrow+nrows)/24;
3999 srcrow=screen_plan[textrow]&A2_SP_ROWMASK;
4002 if (screen_plan[textrow] & A2_SP_COPY) {
4003 if (0) printf("Copy %d screenrows %d to %d\n", nrows, srcrow, textrow);
4004 XCopyArea(dpy, window, window, gc,
4005 screen_xo, screen_yo + srctop,
4007 screen_xo, screen_yo + top);
4009 else if (screen_plan[textrow] & A2_SP_PUT) {
4010 if (0) printf("Draw %d imgrows %d to %d\n", nrows, srcrow, textrow);
4012 #ifdef HAVE_XSHM_EXTENSION
4013 XShmPutImage(dpy, window, gc, image,
4014 0, srctop, screen_xo, screen_yo + top,
4018 XPutImage(dpy, window, gc, image,
4020 screen_xo, screen_yo + top,
4028 for (textrow=0; textrow<24; textrow++) {
4029 st->rowimage[textrow]=textrow;
4035 XClearWindow(dpy, window);
4044 #ifdef HAVE_XSHM_EXTENSION
4045 destroy_xshm_image(dpy, image, &shm_info);
4048 XDestroyImage(image);
4052 if (text_im) XDestroyImage(text_im);
4053 if (gc) XFreeGC(dpy, gc);
4055 if (raw_rgb) free(raw_rgb);
4057 if (n_colors) XFreeColors(dpy, xgwa.colormap, colors, n_colors, 0L);
4062 char *progclass = "BSOD";
4064 char *defaults [] = {
4077 "*doAtari: False", /* boring */
4078 "*doBSD: False", /* boring */
4080 "*doSparcLinux: False", /* boring */
4081 "*doBlitDamage: True",
4088 ".Windows.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4089 ".Windows.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
4090 ".Windows.foreground: White",
4091 ".Windows.background: #0000AA", /* EGA color 0x01. */
4093 ".Amiga.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4094 ".Amiga.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
4095 ".Amiga.foreground: Red",
4096 ".Amiga.background: Black",
4097 ".Amiga.background2: White",
4099 ".Mac.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4100 ".Mac.foreground: PaleTurquoise1",
4101 ".Mac.background: Black",
4103 ".Atari.foreground: Black",
4104 ".Atari.background: White",
4106 ".MacsBug.font: -*-courier-medium-r-*-*-*-100-*-*-m-*-*-*",
4107 ".MacsBug.font2: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4108 ".MacsBug.font3: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4109 ".MacsBug.foreground: Black",
4110 ".MacsBug.background: White",
4111 ".MacsBug.borderColor: #AAAAAA",
4113 ".mac1.foreground: Black",
4114 ".mac1.background: White",
4116 ".macX.textForeground: White",
4117 ".macX.textBackground: Black",
4118 ".macX.background: #888888",
4119 ".macX.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4120 ".macX.font2: -*-courier-bold-r-*-*-*-240-*-*-m-*-*-*",
4122 ".SCO.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4123 ".SCO.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4124 ".SCO.foreground: White",
4125 ".SCO.background: Black",
4127 ".Linux.font: 9x15bold",
4128 ".Linux.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4129 ".Linux.foreground: White",
4130 ".Linux.background: Black",
4132 ".SparcLinux.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4133 ".SparcLinux.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4134 ".SparcLinux.foreground: White",
4135 ".SparcLinux.background: Black",
4138 ".BSD.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4139 ".BSD.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4140 /* ".BSD.font2: -sun-console-medium-r-*-*-22-*-*-*-m-*-*-*", */
4141 ".BSD.foreground: #c0c0c0",
4142 ".BSD.background: Black",
4144 ".Solaris.font: -sun-gallant-*-*-*-*-19-*-*-*-*-120-*-*",
4145 ".Solaris.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4146 ".Solaris.foreground: Black",
4147 ".Solaris.background: White",
4148 "*dontClearRoot: True",
4150 ".HPUX.font: 9x15bold",
4151 ".HPUX.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4152 ".HPUX.foreground: White",
4153 ".HPUX.background: Black",
4155 ".OS390.font: 9x15bold",
4156 ".OS390.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4157 ".OS390.background: Black",
4158 ".OS390.foreground: Red",
4160 "*apple2TVColor: 50",
4162 "*apple2TVBrightness: 10",
4163 "*apple2TVContrast: 90",
4164 "*apple2SimulateUser: True",
4166 ".VMS.font: 9x15bold",
4167 ".VMS.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4168 ".VMS.foreground: White",
4169 ".VMS.background: Black",
4171 #ifdef HAVE_XSHM_EXTENSION
4177 XrmOptionDescRec options [] = {
4178 { "-delay", ".delay", XrmoptionSepArg, 0 },
4179 { "-only", ".doOnly", XrmoptionSepArg, 0 },
4180 { "-windows", ".doWindows", XrmoptionNoArg, "True" },
4181 { "-no-windows", ".doWindows", XrmoptionNoArg, "False" },
4182 { "-nt", ".doNT", XrmoptionNoArg, "True" },
4183 { "-no-nt", ".doNT", XrmoptionNoArg, "False" },
4184 { "-2k", ".doWin2K", XrmoptionNoArg, "True" },
4185 { "-no-2k", ".doWin2K", XrmoptionNoArg, "False" },
4186 { "-amiga", ".doAmiga", XrmoptionNoArg, "True" },
4187 { "-no-amiga", ".doAmiga", XrmoptionNoArg, "False" },
4188 { "-mac", ".doMac", XrmoptionNoArg, "True" },
4189 { "-no-mac", ".doMac", XrmoptionNoArg, "False" },
4190 { "-mac1", ".doMac1", XrmoptionNoArg, "True" },
4191 { "-no-mac1", ".doMac1", XrmoptionNoArg, "False" },
4192 { "-macx", ".doMacX", XrmoptionNoArg, "True" },
4193 { "-no-macx", ".doMacX", XrmoptionNoArg, "False" },
4194 { "-atari", ".doAtari", XrmoptionNoArg, "True" },
4195 { "-no-atari", ".doAtari", XrmoptionNoArg, "False" },
4196 { "-macsbug", ".doMacsBug", XrmoptionNoArg, "True" },
4197 { "-no-macsbug", ".doMacsBug", XrmoptionNoArg, "False" },
4198 { "-apple2", ".doApple2", XrmoptionNoArg, "True" },
4199 { "-no-apple2", ".doApple2", XrmoptionNoArg, "False" },
4200 { "-sco", ".doSCO", XrmoptionNoArg, "True" },
4201 { "-no-sco", ".doSCO", XrmoptionNoArg, "False" },
4202 { "-bsd", ".doBSD", XrmoptionNoArg, "True" },
4203 { "-no-bsd", ".doBSD", XrmoptionNoArg, "False" },
4204 { "-linux", ".doLinux", XrmoptionNoArg, "True" },
4205 { "-no-linux", ".doLinux", XrmoptionNoArg, "False" },
4206 { "-sparclinux", ".doSparcLinux", XrmoptionNoArg, "True" },
4207 { "-no-sparclinux", ".doSparcLinux", XrmoptionNoArg, "False" },
4208 { "-blitdamage", ".doBlitDamage", XrmoptionNoArg, "True" },
4209 { "-no-blitdamage", ".doBlitDamage", XrmoptionNoArg, "False" },
4210 { "-solaris", ".doSolaris", XrmoptionNoArg, "True" },
4211 { "-no-solaris", ".doSolaris", XrmoptionNoArg, "False" },
4212 { "-hpux", ".doHPUX", XrmoptionNoArg, "True" },
4213 { "-no-hpux", ".doHPUX", XrmoptionNoArg, "False" },
4214 { "-os390", ".doOS390", XrmoptionNoArg, "True" },
4215 { "-no-os390", ".doOS390", XrmoptionNoArg, "False" },
4216 { "-vms", ".doVMS", XrmoptionNoArg, "True" },
4217 { "-no-vms", ".doVMS", XrmoptionNoArg, "False" },
4224 void (*fn) (Display *, Window, int delay);
4226 { "Windows", windows_31 },
4227 { "Nt", windows_nt },
4228 { "2k", windows_2k },
4231 { "MacsBug", macsbug },
4235 { "SparcLinux", sparc_linux },
4238 { "BlitDamage", blitdamage },
4239 { "Solaris", sparc_solaris },
4240 { "Linux", linux_fsck },
4243 { "Apple2", apple2 },
4249 screenhack (Display *dpy, Window window)
4255 int delay = get_integer_resource ("delay", "Integer");
4256 if (delay < 3) delay = 3;
4259 char *s = get_string_resource("doOnly", "DoOnly");
4262 int count = countof(all_modes);
4263 for (only = 0; only < count; only++)
4264 if (!strcasecmp (s, all_modes[only].name))
4268 fprintf (stderr, "%s: unknown -only mode: \"%s\"\n", progname, s);
4275 if (!get_boolean_resource ("root", "Boolean"))
4277 XWindowAttributes xgwa;
4278 XGetWindowAttributes (dpy, window, &xgwa);
4279 XSelectInput (dpy, window,
4280 xgwa.your_event_mask | KeyPressMask | ButtonPressMask);
4286 int count = countof(all_modes);
4287 char name[100], class[100];
4292 do { i = (random() & 0xFF) % count; } while (i == j);
4294 sprintf (name, "do%s", all_modes[i].name);
4295 sprintf (class, "Do%s", all_modes[i].name);
4298 if (only > 0 || get_boolean_resource(name, class))
4300 all_modes[i].fn (dpy, window, delay);
4305 if (loop > 100) j = -1;
4308 fprintf (stderr, "%s: no display modes enabled?\n", progname);