1 /* xscreensaver, Copyright (c) 1998 Jamie Zawinski <jwz@netscape.com>
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.
16 * - Should have a "macsbug" mode.
17 * - Should simulate a Unix kernel panic and reboot.
18 * - Making various boot noises would be fun, too.
19 * - Maybe scatter some random bits across the screen,
20 * to simulate corruption of video ram?
21 * - Should randomize the various hex numbers printed.
24 #include "screenhack.h"
26 #include <X11/Xutil.h>
30 # include "images/amiga.xpm"
33 #include "images/mac.xbm"
37 draw_string (Display *dpy, Window window, GC gc, XGCValues *gcv,
40 int win_width, int win_height,
41 const char *string, int delay)
44 int width = 0, height = 0, cw = 0;
45 int char_width, line_height;
47 const char *s = string;
48 const char *se = string;
50 /* This pretty much assumes fixed-width fonts */
51 char_width = (font->per_char
52 ? font->per_char['n'-font->min_char_or_byte2].width
53 : font->min_bounds.width);
54 line_height = font->ascent + font->descent + 1;
58 if (*s == '\n' || !*s)
61 if (cw > width) width = cw;
70 x = (win_width - (width * char_width)) / 2;
71 y = (win_height - (height * line_height)) / 2;
82 if (*s == '\n' || !*s)
87 if (*se == '@' || *se == '_')
89 if (*se == '@') flip = True;
91 off = (char_width * (width - (s - se))) / 2;
96 XSetForeground(dpy, gc, gcv->background);
97 XSetBackground(dpy, gc, gcv->foreground);
101 XDrawImageString(dpy, window, gc, x+off, y+font->ascent, se, s-se);
105 XSetForeground(dpy, gc, gcv->foreground);
106 XSetBackground(dpy, gc, gcv->background);
126 double_pixmap(Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap,
127 int pix_w, int pix_h)
130 Pixmap p2 = XCreatePixmap(dpy, pixmap, pix_w*2, pix_h*2, depth);
131 XImage *i1 = XGetImage(dpy, pixmap, 0, 0, pix_w, pix_h, ~0L, ZPixmap);
132 XImage *i2 = XCreateImage(dpy, visual, depth, ZPixmap, 0, 0,
133 pix_w*2, pix_h*2, 8, 0);
134 i2->data = (unsigned char *) calloc(i2->height, i2->bytes_per_line);
135 for (y = 0; y < pix_h; y++)
136 for (x = 0; x < pix_w; x++)
138 unsigned long p = XGetPixel(i1, x, y);
139 XPutPixel(i2, x*2, y*2, p);
140 XPutPixel(i2, x*2+1, y*2, p);
141 XPutPixel(i2, x*2, y*2+1, p);
142 XPutPixel(i2, x*2+1, y*2+1, p);
144 free(i1->data); i1->data = 0;
146 XPutImage(dpy, p2, gc, i2, 0, 0, 0, 0, i2->width, i2->height);
147 free(i2->data); i2->data = 0;
149 XFreePixmap(dpy, pixmap);
154 /* Sleep for N seconds and return False. But if a key or mouse event is
155 seen, discard all pending key or mouse events, and return True.
158 bsod_sleep(Display *dpy, int seconds)
162 int mask = KeyPressMask|ButtonPressMask;
166 if (XCheckMaskEvent(dpy, mask, &event))
168 while (XCheckMaskEvent(dpy, mask, &event))
185 windows (Display *dpy, Window window, int delay, Bool w95p)
188 XWindowAttributes xgwa;
190 const char *def_font = "fixed";
196 "A fatal exception 0E has occured at F0AD:42494C4C\n"
197 "the current application will be terminated.\n"
199 "* Press any key to terminate the current application.\n"
200 "* Press CTRL+ALT+DELETE again to restart your computer.\n"
201 " You will lose any unsaved information in all applications.\n"
204 "_Press any key to continue");
207 ("*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n"
208 "Unhandled Kernel exception c0000047 from fa8418b4 (8025ea21,fd6829e8)\n"
210 "Dll Base Date Stamp - Name Dll Base Date Stamp - Name\n"
211 "80100000 2be154c9 - ntoskrnl.exe 80400000 2bc153b0 - hal.dll\n"
212 "80258000 2bd49628 - ncrc710.sys 8025c000 2bd49688 - SCSIPORT.SYS \n"
213 "80267000 2bd49683 - scsidisk.sys 802a6000 2bd496b9 - Fastfat.sys\n"
214 "fa800000 2bd49666 - Floppy.SYS fa810000 2bd496db - Hpfs_Rec.SYS\n"
215 "fa820000 2bd49676 - Null.SYS fa830000 2bd4965a - Beep.SYS\n"
216 "fa840000 2bdaab00 - i8042prt.SYS fa850000 2bd5a020 - SERMOUSE.SYS\n"
217 "fa860000 2bd4966f - kbdclass.SYS fa870000 2bd49671 - MOUCLASS.SYS\n"
218 "fa880000 2bd9c0be - Videoprt.SYS fa890000 2bd49638 - NCC1701E.SYS\n"
219 "fa8a0000 2bd4a4ce - Vga.SYS fa8b0000 2bd496d0 - Msfs.SYS\n"
220 "fa8c0000 2bd496c3 - Npfs.SYS fa8e0000 2bd496c9 - Ntfs.SYS\n"
221 "fa940000 2bd496df - NDIS.SYS fa930000 2bd49707 - wdlan.sys\n"
222 "fa970000 2bd49712 - TDI.SYS fa950000 2bd5a7fb - nbf.sys\n"
223 "fa980000 2bd72406 - streams.sys fa9b0000 2bd4975f - ubnb.sys\n"
224 "fa9c0000 2bd5bfd7 - usbser.sys fa9d0000 2bd4971d - netbios.sys\n"
225 "fa9e0000 2bd49678 - Parallel.sys fa9f0000 2bd4969f - serial.SYS\n"
226 "faa00000 2bd49739 - mup.sys faa40000 2bd4971f - SMBTRSUP.SYS\n"
227 "faa10000 2bd6f2a2 - srv.sys faa50000 2bd4971a - afd.sys\n"
228 "faa60000 2bd6fd80 - rdr.sys faaa0000 2bd49735 - bowser.sys\n"
230 "Address dword dump Dll Base - Name\n"
231 "801afc20 80106fc0 80106fc0 00000000 00000000 80149905 : "
232 "fa840000 - i8042prt.SYS\n"
233 "801afc24 80149905 80149905 ff8e6b8c 80129c2c ff8e6b94 : "
234 "8025c000 - SCSIPORT.SYS\n"
235 "801afc2c 80129c2c 80129c2c ff8e6b94 00000000 ff8e6b94 : "
236 "80100000 - ntoskrnl.exe\n"
237 "801afc34 801240f2 80124f02 ff8e6df4 ff8e6f60 ff8e6c58 : "
238 "80100000 - ntoskrnl.exe\n"
239 "801afc54 80124f16 80124f16 ff8e6f60 ff8e6c3c 8015ac7e : "
240 "80100000 - ntoskrnl.exe\n"
241 "801afc64 8015ac7e 8015ac7e ff8e6df4 ff8e6f60 ff8e6c58 : "
242 "80100000 - ntoskrnl.exe\n"
243 "801afc70 80129bda 80129bda 00000000 80088000 80106fc0 : "
244 "80100000 - ntoskrnl.exe\n"
246 "Kernel Debugger Using: COM2 (Port 0x2f8, Baud Rate 19200)\n"
247 "Restart and set the recovery options in the system control panel\n"
248 "or the /CRASHDEBUG system start option. If this message reappears,\n"
249 "contact your system administrator or technical support group."
252 XGetWindowAttributes (dpy, window, &xgwa);
254 fontname = get_string_resource ((xgwa.height > 600
260 : "windowsNT.font")),
262 if (!fontname || !*fontname) fontname = (char *)def_font;
263 font = XLoadQueryFont (dpy, fontname);
264 if (!font) font = XLoadQueryFont (dpy, def_font);
266 if (fontname && fontname != def_font)
269 gcv.font = font->fid;
270 gcv.foreground = get_pixel_resource((w95p
271 ? "windows95.foreground"
272 : "windowsNT.foreground"),
273 "Windows.Foreground",
275 gcv.background = get_pixel_resource((w95p
276 ? "windows95.background"
277 : "windowsNT.background"),
278 "Windows.Background",
280 XSetWindowBackground(dpy, window, gcv.background);
281 XClearWindow(dpy, window);
283 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
286 draw_string(dpy, window, gc, &gcv, font,
287 0, 0, xgwa.width, xgwa.height, w95, 0);
289 draw_string(dpy, window, gc, &gcv, font, 0, 0, 10, 10, wnt, 750);
293 bsod_sleep(dpy, delay);
294 XClearWindow(dpy, window);
295 XFreeFont(dpy, font);
299 amiga (Display *dpy, Window window, int delay)
302 XWindowAttributes xgwa;
304 const char *def_font = "fixed";
308 unsigned long fg, bg, bg2;
313 ("_Software failure. Press left mouse button to continue.\n"
314 "_Guru Meditation #00000003.00C01570");
316 XGetWindowAttributes (dpy, window, &xgwa);
318 fontname = get_string_resource ((xgwa.height > 600
319 ? "amiga.font2" : "amiga.font"),
321 if (!fontname || !*fontname) fontname = (char *)def_font;
322 font = XLoadQueryFont (dpy, fontname);
323 if (!font) font = XLoadQueryFont (dpy, def_font);
325 if (fontname && fontname != def_font)
328 gcv.font = font->fid;
329 fg = gcv.foreground = get_pixel_resource("amiga.foreground",
332 bg = gcv.background = get_pixel_resource("amiga.background",
335 bg2 = get_pixel_resource("amiga.background2", "Amiga.Background",
337 XSetWindowBackground(dpy, window, bg2);
338 XClearWindow(dpy, window);
340 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
341 gcv.background = fg; gcv.foreground = bg;
342 gc2 = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
344 height = (font->ascent + font->descent) * 6;
348 XpmAttributes xpmattrs;
350 xpmattrs.valuemask = 0;
353 xpmattrs.valuemask |= XpmCloseness;
354 xpmattrs.closeness = 40000;
357 xpmattrs.valuemask |= XpmVisual;
358 xpmattrs.visual = xgwa.visual;
361 xpmattrs.valuemask |= XpmDepth;
362 xpmattrs.depth = xgwa.depth;
365 xpmattrs.valuemask |= XpmColormap;
366 xpmattrs.colormap = xgwa.colormap;
369 result = XpmCreatePixmapFromData(dpy, window, amiga_hand,
370 &pixmap, 0 /* mask */, &xpmattrs);
371 if (!pixmap || (result != XpmSuccess && result != XpmColorError))
373 pix_w = xpmattrs.width;
374 pix_h = xpmattrs.height;
376 #endif /* HAVE_XPM */
378 if (pixmap && xgwa.height > 600) /* scale up the bitmap */
380 pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
381 pixmap, pix_w, pix_h);
388 int x = (xgwa.width - pix_w) / 2;
389 int y = ((xgwa.height - pix_h) / 2);
390 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
395 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y + height);
396 XClearArea(dpy, window, 0, 0, xgwa.width, y + height, False);
397 XFreePixmap(dpy, pixmap);
400 XFillRectangle(dpy, window, gc2, 0, 0, xgwa.width, height);
401 draw_string(dpy, window, gc, &gcv, font, 0, 0, xgwa.width, height, string,0);
407 XFillRectangle(dpy, window, gca, 0, 0, xgwa.width, font->ascent);
408 XFillRectangle(dpy, window, gca, 0, 0, font->ascent, height);
409 XFillRectangle(dpy, window, gca, xgwa.width-font->ascent, 0,
410 font->ascent, height);
411 XFillRectangle(dpy, window, gca, 0, height-font->ascent, xgwa.width,
413 gca = (gca == gc ? gc2 : gc);
415 if (bsod_sleep(dpy, 1))
424 XClearWindow(dpy, window);
425 XFreeFont(dpy, font);
430 mac (Display *dpy, Window window, int delay)
433 XWindowAttributes xgwa;
435 const char *def_font = "fixed";
439 int pix_w = mac_width;
440 int pix_h = mac_height;
441 int offset = mac_height * 4;
444 const char *string = ("0 0 0 0 0 0 0 F\n"
447 XGetWindowAttributes (dpy, window, &xgwa);
449 fontname = get_string_resource ("mac.font", "Mac.Font");
450 if (!fontname || !*fontname) fontname = (char *)def_font;
451 font = XLoadQueryFont (dpy, fontname);
452 if (!font) font = XLoadQueryFont (dpy, def_font);
454 if (fontname && fontname != def_font)
457 gcv.font = font->fid;
458 gcv.foreground = get_pixel_resource("mac.foreground", "Mac.Foreground",
460 gcv.background = get_pixel_resource("mac.background", "Mac.Background",
462 XSetWindowBackground(dpy, window, gcv.background);
463 XClearWindow(dpy, window);
465 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
467 pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) mac_bits,
468 mac_width, mac_height,
473 draw_string(dpy, window, gc, &gcv, font, 0, 0,
474 xgwa.width, xgwa.height + offset, string, 0);
476 for(i = 0; i < 2; i++)
478 pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
479 pixmap, pix_w, pix_h);
480 pix_w *= 2; pix_h *= 2;
484 int x = (xgwa.width - pix_w) / 2;
485 int y = (((xgwa.height + offset) / 2) -
487 (font->ascent + font->descent) * 2);
489 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
490 XFreePixmap(dpy, pixmap);
495 bsod_sleep(dpy, delay);
496 XClearWindow(dpy, window);
497 XFreeFont(dpy, font);
501 macsbug (Display *dpy, Window window, int delay)
504 XWindowAttributes xgwa;
506 const char *def_font = "fixed";
510 int char_width, line_height;
511 int col_right, row_top, row_bottom, page_right, page_bottom, body_top;
514 const char *left = (" SP \n"
561 const char *bottom = (" _A09D\n"
562 " +00884 40843714 #$0700,SR "
564 " +00886 40843765 *+$0400 "
566 " +00888 40843718 $0004(A7),([0,A7[)"
567 " ; 04E8D0AE | 66B8");
568 const char *body = ("Bus Error at 4BF6D6CC\n"
569 "while reading word from 4BF6D6CC in User data space\n"
570 " Unable to access that address\n"
572 " Frame Type: B008");
576 for (s = body; *s; s++) if (*s == '\n') body_lines++;
578 XGetWindowAttributes (dpy, window, &xgwa);
580 fontname = get_string_resource ((xgwa.height > 850
586 if (!fontname || !*fontname) fontname = (char *)def_font;
587 font = XLoadQueryFont (dpy, fontname);
588 if (!font) font = XLoadQueryFont (dpy, def_font);
590 if (fontname && fontname != def_font)
593 gcv.font = font->fid;
594 gcv.foreground = get_pixel_resource("macsbug.foreground",
595 "MacsBug.Foreground",
597 gcv.background = get_pixel_resource("macsbug.background",
598 "MacsBug.Background",
601 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
603 gcv.foreground = gcv.background;
604 gc2 = XCreateGC(dpy, window, GCForeground, &gcv);
606 XSetWindowBackground(dpy, window,
607 get_pixel_resource("macsbug.borderColor",
608 "MacsBug.BorderColor",
609 dpy, xgwa.colormap));
610 XClearWindow(dpy, window);
612 char_width = (font->per_char
613 ? font->per_char['n'-font->min_char_or_byte2].width
614 : font->min_bounds.width);
615 line_height = font->ascent + font->descent + 1;
617 col_right = char_width * 12;
618 page_bottom = line_height * 47;
620 if (page_bottom > xgwa.height) page_bottom = xgwa.height;
622 row_bottom = page_bottom - line_height;
623 row_top = row_bottom - (line_height * 4);
624 page_right = col_right + (char_width * 88);
625 body_top = row_top - (line_height * body_lines);
631 xoff = (xgwa.width - page_right) / 2;
632 yoff = (xgwa.height - page_bottom) / 2;
633 if (xoff < 0) xoff = 0;
634 if (yoff < 0) yoff = 0;
636 XFillRectangle(dpy, window, gc2, xoff, yoff, page_right, page_bottom);
638 draw_string(dpy, window, gc, &gcv, font, xoff, yoff, 10, 10, left, 0);
639 draw_string(dpy, window, gc, &gcv, font, xoff+col_right, yoff+row_top,
641 draw_string(dpy, window, gc, &gcv, font,
642 xoff + col_right + char_width, yoff + body_top, 10, 10, body, 0);
644 XFillRectangle(dpy, window, gc, xoff + col_right, yoff, 2, page_bottom);
645 XDrawLine(dpy, window, gc,
646 xoff+col_right, yoff+row_top, xoff+page_right, yoff+row_top);
647 XDrawLine(dpy, window, gc,
648 xoff+col_right, yoff+row_bottom, xoff+page_right, yoff+row_bottom);
649 XDrawRectangle(dpy, window, gc, xoff, yoff, page_right, page_bottom);
653 XDrawLine(dpy, window, gc,
654 xoff+col_right+(char_width/2)+2, yoff+row_bottom+3,
655 xoff+col_right+(char_width/2)+2, yoff+page_bottom-3);
658 XDrawLine(dpy, window, gc2,
659 xoff+col_right+(char_width/2)+2, yoff+row_bottom+3,
660 xoff+col_right+(char_width/2)+2, yoff+page_bottom-3);
663 if (bsod_sleep(dpy, 0))
670 XClearWindow(dpy, window);
671 XFreeFont(dpy, font);
676 char *progclass = "BSOD";
678 char *defaults [] = {
681 ".Windows.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
682 ".Windows.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
683 ".Windows.foreground: White",
684 ".Windows.background: Blue",
686 ".Amiga.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
687 ".Amiga.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
688 ".Amiga.foreground: Red",
689 ".Amiga.background: Black",
690 ".Amiga.background2: White",
692 ".Mac.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
693 ".Mac.foreground: PaleTurquoise1",
694 ".Mac.background: Black",
696 ".MacsBug.font: -*-courier-medium-r-*-*-*-100-*-*-m-*-*-*",
697 ".MacsBug.font2: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
698 ".MacsBug.font3: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
699 ".MacsBug.foreground: Black",
700 ".MacsBug.background: White",
701 ".MacsBug.borderColor: #AAAAAA",
705 XrmOptionDescRec options [] = {
706 { "-delay", ".delay", XrmoptionSepArg, 0 },
711 screenhack (Display *dpy, Window window)
715 int delay = get_integer_resource ("delay", "Integer");
716 if (delay < 3) delay = 3;
718 if (!get_boolean_resource ("root", "Boolean"))
719 XSelectInput(dpy, window, KeyPressMask|ButtonPressMask);
723 while (i == j) i = random() % 5;
728 case 0: windows(dpy, window, delay, True); break;
729 case 1: windows(dpy, window, delay, False); break;
730 case 2: amiga(dpy, window, delay); break;
731 case 3: mac(dpy, window, delay); break;
732 case 4: macsbug(dpy, window, delay); break;
733 default: abort(); break;