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,
38 XFontStruct *font, int win_width, int win_height,
39 const char *string, int delay)
42 int width = 0, height = 0, cw = 0;
43 int char_width, line_height;
45 const char *s = string;
46 const char *se = string;
48 /* This pretty much assumes fixed-width fonts */
49 char_width = (font->per_char
50 ? font->per_char['n'-font->min_char_or_byte2].width
51 : font->min_bounds.width);
52 line_height = font->ascent + font->descent + 1;
56 if (*s == '\n' || !*s)
59 if (cw > width) width = cw;
68 x = (win_width - (width * char_width)) / 2;
69 y = (win_height - (height * line_height)) / 2;
71 if (x < char_width) x = char_width;
72 if (y < line_height) y = line_height;
77 if (*s == '\n' || !*s)
82 if (*se == '@' || *se == '_')
84 if (*se == '@') flip = True;
86 off = (char_width * (width - (s - se))) / 2;
91 XSetForeground(dpy, gc, gcv->background);
92 XSetBackground(dpy, gc, gcv->foreground);
96 XDrawImageString(dpy, window, gc, x+off, y+font->ascent, se, s-se);
100 XSetForeground(dpy, gc, gcv->foreground);
101 XSetBackground(dpy, gc, gcv->background);
121 double_pixmap(Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap,
122 int pix_w, int pix_h)
125 Pixmap p2 = XCreatePixmap(dpy, pixmap, pix_w*2, pix_h*2, depth);
126 XImage *i1 = XGetImage(dpy, pixmap, 0, 0, pix_w, pix_h, ~0L, ZPixmap);
127 XImage *i2 = XCreateImage(dpy, visual, depth, ZPixmap, 0, 0,
128 pix_w*2, pix_h*2, 8, 0);
129 i2->data = (unsigned char *) calloc(i2->height, i2->bytes_per_line);
130 for (y = 0; y < pix_h; y++)
131 for (x = 0; x < pix_w; x++)
133 unsigned long p = XGetPixel(i1, x, y);
134 XPutPixel(i2, x*2, y*2, p);
135 XPutPixel(i2, x*2+1, y*2, p);
136 XPutPixel(i2, x*2, y*2+1, p);
137 XPutPixel(i2, x*2+1, y*2+1, p);
139 free(i1->data); i1->data = 0;
141 XPutImage(dpy, p2, gc, i2, 0, 0, 0, 0, i2->width, i2->height);
142 free(i2->data); i2->data = 0;
144 XFreePixmap(dpy, pixmap);
149 /* Sleep for N seconds and return False. But if a key or mouse event is
150 seen, discard all pending key or mouse events, and return True.
153 bsod_sleep(Display *dpy, int seconds)
157 int mask = KeyPressMask|ButtonPressMask;
161 if (XCheckMaskEvent(dpy, mask, &event))
163 while (XCheckMaskEvent(dpy, mask, &event))
175 windows (Display *dpy, Window window, int delay, Bool w95p)
178 XWindowAttributes xgwa;
180 const char *def_font = "fixed";
186 "A fatal exception 0E has occured at F0AD:42494C4C\n"
187 "the current application will be terminated.\n"
189 "* Press any key to terminate the current application.\n"
190 "* Press CTRL+ALT+DELETE again to restart your computer.\n"
191 " You will lose any unsaved information in all applications.\n"
194 "_Press any key to continue");
197 ("*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n"
198 "Unhandled Kernel exception c0000047 from fa8418b4 (8025ea21,fd6829e8)\n"
200 "Dll Base Date Stamp - Name Dll Base Date Stamp - Name\n"
201 "80100000 2be154c9 - ntoskrnl.exe 80400000 2bc153b0 - hal.dll\n"
202 "80258000 2bd49628 - ncrc710.sys 8025c000 2bd49688 - SCSIPORT.SYS \n"
203 "80267000 2bd49683 - scsidisk.sys 802a6000 2bd496b9 - Fastfat.sys\n"
204 "fa800000 2bd49666 - Floppy.SYS fa810000 2bd496db - Hpfs_Rec.SYS\n"
205 "fa820000 2bd49676 - Null.SYS fa830000 2bd4965a - Beep.SYS\n"
206 "fa840000 2bdaab00 - i8042prt.SYS fa850000 2bd5a020 - SERMOUSE.SYS\n"
207 "fa860000 2bd4966f - kbdclass.SYS fa870000 2bd49671 - MOUCLASS.SYS\n"
208 "fa880000 2bd9c0be - Videoprt.SYS fa890000 2bd49638 - NCC1701E.SYS\n"
209 "fa8a0000 2bd4a4ce - Vga.SYS fa8b0000 2bd496d0 - Msfs.SYS\n"
210 "fa8c0000 2bd496c3 - Npfs.SYS fa8e0000 2bd496c9 - Ntfs.SYS\n"
211 "fa940000 2bd496df - NDIS.SYS fa930000 2bd49707 - wdlan.sys\n"
212 "fa970000 2bd49712 - TDI.SYS fa950000 2bd5a7fb - nbf.sys\n"
213 "fa980000 2bd72406 - streams.sys fa9b0000 2bd4975f - ubnb.sys\n"
214 "fa9c0000 2bd5bfd7 - usbser.sys fa9d0000 2bd4971d - netbios.sys\n"
215 "fa9e0000 2bd49678 - Parallel.sys fa9f0000 2bd4969f - serial.SYS\n"
216 "faa00000 2bd49739 - mup.sys faa40000 2bd4971f - SMBTRSUP.SYS\n"
217 "faa10000 2bd6f2a2 - srv.sys faa50000 2bd4971a - afd.sys\n"
218 "faa60000 2bd6fd80 - rdr.sys faaa0000 2bd49735 - bowser.sys\n"
220 "Address dword dump Dll Base - Name\n"
221 "801afc20 80106fc0 80106fc0 00000000 00000000 80149905 : "
222 "fa840000 - i8042prt.SYS\n"
223 "801afc24 80149905 80149905 ff8e6b8c 80129c2c ff8e6b94 : "
224 "8025c000 - SCSIPORT.SYS\n"
225 "801afc2c 80129c2c 80129c2c ff8e6b94 00000000 ff8e6b94 : "
226 "80100000 - ntoskrnl.exe\n"
227 "801afc34 801240f2 80124f02 ff8e6df4 ff8e6f60 ff8e6c58 : "
228 "80100000 - ntoskrnl.exe\n"
229 "801afc54 80124f16 80124f16 ff8e6f60 ff8e6c3c 8015ac7e : "
230 "80100000 - ntoskrnl.exe\n"
231 "801afc64 8015ac7e 8015ac7e ff8e6df4 ff8e6f60 ff8e6c58 : "
232 "80100000 - ntoskrnl.exe\n"
233 "801afc70 80129bda 80129bda 00000000 80088000 80106fc0 : "
234 "80100000 - ntoskrnl.exe\n"
236 "Kernel Debugger Using: COM2 (Port 0x2f8, Baud Rate 19200)\n"
237 "Restart and set the recovery options in the system control panel\n"
238 "or the /CRASHDEBUG system start option. If this message reappears,\n"
239 "contact your system administrator or technical support group."
242 XGetWindowAttributes (dpy, window, &xgwa);
244 fontname = get_string_resource ((xgwa.height > 600
250 : "windowsNT.font")),
252 if (!fontname || !*fontname) fontname = (char *)def_font;
253 font = XLoadQueryFont (dpy, fontname);
254 if (!font) font = XLoadQueryFont (dpy, def_font);
256 if (fontname && fontname != def_font)
259 gcv.font = font->fid;
260 gcv.foreground = get_pixel_resource((w95p
261 ? "windows95.foreground"
262 : "windowsNT.foreground"),
263 "Windows.Foreground",
265 gcv.background = get_pixel_resource((w95p
266 ? "windows95.background"
267 : "windowsNT.background"),
268 "Windows.Background",
270 XSetWindowBackground(dpy, window, gcv.background);
271 XClearWindow(dpy, window);
273 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
276 draw_string(dpy, window, gc, &gcv, font, xgwa.width, xgwa.height, w95, 0);
278 draw_string(dpy, window, gc, &gcv, font, 10, 10, wnt, 750);
282 bsod_sleep(dpy, delay);
283 XClearWindow(dpy, window);
284 XFreeFont(dpy, font);
288 amiga (Display *dpy, Window window, int delay)
291 XWindowAttributes xgwa;
293 const char *def_font = "fixed";
297 unsigned long fg, bg, bg2;
302 ("_Software failure. Press left mouse button to continue.\n"
303 "_Guru Meditation #00000003.00C01570");
305 XGetWindowAttributes (dpy, window, &xgwa);
307 fontname = get_string_resource ((xgwa.height > 600
308 ? "amiga.font2" : "amiga.font"),
310 if (!fontname || !*fontname) fontname = (char *)def_font;
311 font = XLoadQueryFont (dpy, fontname);
312 if (!font) font = XLoadQueryFont (dpy, def_font);
314 if (fontname && fontname != def_font)
317 gcv.font = font->fid;
318 fg = gcv.foreground = get_pixel_resource("amiga.foreground",
321 bg = gcv.background = get_pixel_resource("amiga.background",
324 bg2 = get_pixel_resource("amiga.background2", "Amiga.Background",
326 XSetWindowBackground(dpy, window, bg2);
327 XClearWindow(dpy, window);
329 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
330 gcv.background = fg; gcv.foreground = bg;
331 gc2 = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
333 height = (font->ascent + font->descent) * 6;
337 XpmAttributes xpmattrs;
339 xpmattrs.valuemask = 0;
342 xpmattrs.valuemask |= XpmCloseness;
343 xpmattrs.closeness = 40000;
346 xpmattrs.valuemask |= XpmVisual;
347 xpmattrs.visual = xgwa.visual;
350 xpmattrs.valuemask |= XpmDepth;
351 xpmattrs.depth = xgwa.depth;
354 xpmattrs.valuemask |= XpmColormap;
355 xpmattrs.colormap = xgwa.colormap;
358 result = XpmCreatePixmapFromData(dpy, window, amiga_hand,
359 &pixmap, 0 /* mask */, &xpmattrs);
360 if (!pixmap || (result != XpmSuccess && result != XpmColorError))
362 pix_w = xpmattrs.width;
363 pix_h = xpmattrs.height;
365 #endif /* HAVE_XPM */
367 if (pixmap && xgwa.height > 600) /* scale up the bitmap */
369 pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
370 pixmap, pix_w, pix_h);
377 int x = (xgwa.width - pix_w) / 2;
378 int y = ((xgwa.height - pix_h) / 2);
379 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
384 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y + height);
385 XClearArea(dpy, window, 0, 0, xgwa.width, y + height, False);
386 XFreePixmap(dpy, pixmap);
389 XFillRectangle(dpy, window, gc2, 0, 0, xgwa.width, height);
390 draw_string(dpy, window, gc, &gcv, font, xgwa.width, height, string, 0);
396 XFillRectangle(dpy, window, gca, 0, 0, xgwa.width, font->ascent);
397 XFillRectangle(dpy, window, gca, 0, 0, font->ascent, height);
398 XFillRectangle(dpy, window, gca, xgwa.width-font->ascent, 0,
399 font->ascent, height);
400 XFillRectangle(dpy, window, gca, 0, height-font->ascent, xgwa.width,
402 gca = (gca == gc ? gc2 : gc);
404 if (bsod_sleep(dpy, 1))
413 XClearWindow(dpy, window);
414 XFreeFont(dpy, font);
419 mac (Display *dpy, Window window, int delay)
422 XWindowAttributes xgwa;
424 const char *def_font = "fixed";
428 int pix_w = mac_width;
429 int pix_h = mac_height;
430 int offset = mac_height * 4;
433 const char *string = ("0 0 0 0 0 0 0 F\n"
436 XGetWindowAttributes (dpy, window, &xgwa);
438 fontname = get_string_resource ("mac.font", "Mac.Font");
439 if (!fontname || !*fontname) fontname = (char *)def_font;
440 font = XLoadQueryFont (dpy, fontname);
441 if (!font) font = XLoadQueryFont (dpy, def_font);
443 if (fontname && fontname != def_font)
446 gcv.font = font->fid;
447 gcv.foreground = get_pixel_resource("mac.foreground", "Mac.Foreground",
449 gcv.background = get_pixel_resource("mac.background", "Mac.Background",
451 XSetWindowBackground(dpy, window, gcv.background);
452 XClearWindow(dpy, window);
454 gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
456 pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) mac_bits,
457 mac_width, mac_height,
462 draw_string(dpy, window, gc, &gcv, font, xgwa.width, xgwa.height + offset,
465 for(i = 0; i < 2; i++)
467 pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
468 pixmap, pix_w, pix_h);
469 pix_w *= 2; pix_h *= 2;
473 int x = (xgwa.width - pix_w) / 2;
474 int y = (((xgwa.height + offset) / 2) -
476 (font->ascent + font->descent) * 2);
478 XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
479 XFreePixmap(dpy, pixmap);
484 bsod_sleep(dpy, delay);
485 XClearWindow(dpy, window);
486 XFreeFont(dpy, font);
490 char *progclass = "BSOD";
492 char *defaults [] = {
495 "BSOD.Windows.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
496 "BSOD.Windows.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
497 "BSOD.Windows.foreground: White",
498 "BSOD.Windows.background: Blue",
500 "BSOD.Amiga.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
501 "BSOD.Amiga.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
502 "BSOD.Amiga.foreground: Red",
503 "BSOD.Amiga.background: Black",
504 "BSOD.Amiga.background2: White",
506 "BSOD.Mac.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
507 "BSOD.Mac.foreground: PaleTurquoise1",
508 "BSOD.Mac.background: Black",
512 XrmOptionDescRec options [] = {
513 { "-delay", ".delay", XrmoptionSepArg, 0 },
518 screenhack (Display *dpy, Window window)
522 int delay = get_integer_resource ("delay", "Integer");
523 if (delay < 3) delay = 3;
525 if (!get_boolean_resource ("root", "Boolean"))
526 XSelectInput(dpy, window, KeyPressMask|ButtonPressMask);
530 while (i == j) i = random() % 4;
535 case 0: windows(dpy, window, delay, True); break;
536 case 1: windows(dpy, window, delay, False); break;
537 case 2: amiga(dpy, window, delay); break;
538 case 3: mac(dpy, window, delay); break;
539 default: abort(); break;