http://www.jwz.org/xscreensaver/xscreensaver-5.14.tar.gz
[xscreensaver] / hacks / bsod.c
1 /* xscreensaver, Copyright (c) 1998-2011 Jamie Zawinski <jwz@jwz.org>
2  *
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 
9  * implied warranty.
10  *
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.
14  * Mostly rewritten by jwz, 20-Feb-2006.
15  */
16
17
18 /* To add a new mode:
19
20     - Define a function `new_os(dpy,win)' that returns a `bsod_state' struct.
21     - Draw on the window to set up its frame-zero state.  This must be fast:
22       no sleeping or long loops!
23     - Populate the bsod_state structure with additional actions to take by
24       using the various BSOD_ macros.  Note that you can control the delays
25       when printing text on a per-character or per-line basis.
26     - Insert your function in the `all_modes' table.
27     - Add a `doXXX' entry to `bsod_defaults'.
28     - Add fonts or colors to `bsod_defaults' if necessary.
29
30    Look at windows_31() for a simple example.
31
32    Look at linux_fsck() for a more complicated example with random behavior.
33
34    Or, you can bypass all that: look at nvidia() for a really hairy example.
35  */
36
37
38 #include "screenhack.h"
39 #include "xpm-pixmap.h"
40 #include "apple2.h"
41
42 #include <ctype.h>
43
44 #ifdef HAVE_XSHM_EXTENSION
45 #include "xshm.h"
46 #endif
47
48 #ifdef HAVE_UNAME
49 # include <sys/utsname.h>
50 #endif /* HAVE_UNAME */
51
52 #if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) || defined(HAVE_COCOA)
53 # define DO_XPM
54 #endif
55
56 #ifdef DO_XPM
57 # include "images/amiga.xpm"
58 # include "images/hmac.xpm"
59 # include "images/osx_10_2.xpm"
60 # include "images/osx_10_3.xpm"
61 #endif
62 #include "images/atari.xbm"
63 #include "images/mac.xbm"
64 #include "images/macbomb.xbm"
65 #include "images/atm.xbm"
66
67 #undef countof
68 #define countof(x) (sizeof((x))/sizeof((*x)))
69
70 #undef EOF
71 typedef enum { EOF=0, 
72                LEFT, CENTER, RIGHT, 
73                LEFT_FULL, CENTER_FULL, RIGHT_FULL, 
74                COLOR, INVERT, MOVETO, MARGINS,
75                CURSOR_BLOCK, CURSOR_LINE, RECT, COPY, PIXMAP, IMG,
76                PAUSE, CHAR_DELAY, LINE_DELAY,
77                LOOP, RESET
78 } bsod_event_type;
79
80 struct bsod_event {
81   bsod_event_type type;
82   void *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
83 };
84
85 struct bsod_state {
86   Display *dpy;
87   Window window;
88   XWindowAttributes xgwa;
89   XFontStruct *font;
90   unsigned long fg, bg;
91   GC gc;
92   int left_margin, right_margin;        /* for text wrapping */
93   int top_margin, bottom_margin;        /* for text scrolling */
94   Bool wrap_p;
95   Bool scroll_p;
96
97   Pixmap pixmap;                /* Source image used by BSOD_PIXMAP */
98
99   int x, y;                     /* current text-drawing position */
100   int current_left;             /* don't use this */
101
102   int pos;                      /* position in queue */
103   int queue_size;
104   struct bsod_event *queue;
105
106   unsigned long char_delay;     /* delay between printing characters */
107   unsigned long line_delay;     /* delay between printing lines */
108
109   Bool macx_eol_kludge;
110
111   void *closure;
112   int  (*draw_cb) (struct bsod_state *);
113   void (*free_cb) (struct bsod_state *);
114
115   async_load_state *img_loader;
116 };
117
118
119 # if !defined(__GNUC__) && !defined(__extension__)
120   /* don't warn about "string length is greater than the length ISO C89
121      compilers are required to support" in these string constants... */
122 #  define  __extension__ /**/
123 # endif
124
125
126 /* Draw text at the current position; align is LEFT, CENTER, RIGHT, or *_FULL
127    (meaning to clear the whole line margin to margin).
128  */
129 #define BSOD_TEXT(bst,align,string) do { \
130   ensure_queue (bst); \
131   (bst)->queue[(bst)->pos].type = (align); \
132   (bst)->queue[(bst)->pos].arg1 = (void *) strdup (__extension__ (string)); \
133   (bst)->queue[(bst)->pos].arg2 = (bst)->queue[(bst)->pos].arg1; \
134   (bst)->queue[(bst)->pos].arg3 = (void *) 0; \
135   (bst)->pos++; \
136   } while (0)
137
138 /* Flip the foreground and background colors
139  */
140 #define BSOD_INVERT(bst) do { \
141   ensure_queue (bst); \
142   (bst)->queue[(bst)->pos].type = INVERT; \
143   (bst)->pos++; \
144   } while (0)
145
146 /* Set the foreground and background colors to the given pixels
147  */
148 #define BSOD_COLOR(bst,fg,bg) do { \
149   ensure_queue (bst); \
150   (bst)->queue[(bst)->pos].type = COLOR; \
151   (bst)->queue[(bst)->pos].arg1 = (void *) fg; \
152   (bst)->queue[(bst)->pos].arg2 = (void *) bg; \
153   (bst)->pos++; \
154   } while (0)
155
156 /* Set the position of the next text.
157    Note that this is the baseline: lower left corner of next char printed.
158  */
159 #define BSOD_MOVETO(bst,x,y) do { \
160   ensure_queue (bst); \
161   (bst)->queue[(bst)->pos].type = MOVETO; \
162   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (x)); \
163   (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (y)); \
164   (bst)->pos++; \
165   } while (0)
166
167 /* Delay for at least the given number of microseconds.
168  */
169 #define BSOD_PAUSE(bst,usec) do { \
170   ensure_queue (bst); \
171   (bst)->queue[(bst)->pos].type = PAUSE; \
172   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (usec)); \
173   (bst)->pos++; \
174   } while (0)
175
176 /* Set the delay after each character is printed.
177  */
178 #define BSOD_CHAR_DELAY(bst,usec) do { \
179   ensure_queue (bst); \
180   (bst)->queue[(bst)->pos].type = CHAR_DELAY; \
181   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (usec)); \
182   (bst)->pos++; \
183   } while (0)
184
185 /* Set the delay after each newline.
186  */
187 #define BSOD_LINE_DELAY(bst,usec) do { \
188   ensure_queue (bst); \
189   (bst)->queue[(bst)->pos].type = LINE_DELAY; \
190   (bst)->queue[(bst)->pos].arg1 = (void *) (usec); \
191   (bst)->pos++; \
192   } while (0)
193
194 /* Set the prevailing left/right margins (used when strings have
195    embedded newlines, and when centering or right-justifying text.)
196  */
197 #define BSOD_MARGINS(bst,left,right) do { \
198   ensure_queue (bst); \
199   (bst)->queue[(bst)->pos].type = MARGINS; \
200   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (left)); \
201   (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (right)); \
202   (bst)->pos++; \
203   } while (0)
204
205 /* Draw a blinking cursor; type is CURSOR_BLOCK or CURSOR_LINE.
206    usec is how long 1/2 of a cycle is.  count is how many times to blink.
207    (You can pass a gigantic number if this is the last thing in your mode.)
208  */
209 #define BSOD_CURSOR(bst,ctype,usec,count) do { \
210   ensure_queue (bst); \
211   (bst)->queue[(bst)->pos].type = (ctype); \
212   (bst)->queue[(bst)->pos].arg1 = (void *) (usec); \
213   (bst)->queue[(bst)->pos].arg2 = (void *) (count); \
214   (bst)->pos++; \
215   } while (0)
216
217 /* Draw or fill a rectangle.  You can set line-width in the GC.
218  */
219 #define BSOD_RECT(bst,fill,x,y,w,h) do { \
220   ensure_queue (bst); \
221   (bst)->queue[(bst)->pos].type = RECT; \
222   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (fill)); \
223   (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (x)); \
224   (bst)->queue[(bst)->pos].arg3 = (void *) ((long) (y)); \
225   (bst)->queue[(bst)->pos].arg4 = (void *) ((long) (w)); \
226   (bst)->queue[(bst)->pos].arg5 = (void *) ((long) (h)); \
227   (bst)->pos++; \
228   } while (0)
229
230 /* Copy a rect from the window, to the window.
231  */
232 #define BSOD_COPY(bst,srcx,srcy,w,h,tox,toy) do { \
233   ensure_queue (bst); \
234   (bst)->queue[(bst)->pos].type = COPY; \
235   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (srcx)); \
236   (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (srcy)); \
237   (bst)->queue[(bst)->pos].arg3 = (void *) ((long) (w)); \
238   (bst)->queue[(bst)->pos].arg4 = (void *) ((long) (h)); \
239   (bst)->queue[(bst)->pos].arg5 = (void *) ((long) (tox)); \
240   (bst)->queue[(bst)->pos].arg6 = (void *) ((long) (toy)); \
241   (bst)->pos++; \
242   } while (0)
243
244 /* Copy a rect from bst->pixmap to the window.
245  */
246 #define BSOD_PIXMAP(bst,srcx,srcy,w,h,tox,toy) do { \
247   BSOD_COPY(bst,srcx,srcy,w,h,tox,toy); \
248   (bst)->queue[(bst)->pos-1].type = PIXMAP; \
249   } while (0)
250
251 /* Load a random image (or the desktop) onto the window.
252  */
253 #define BSOD_IMG(bst) do { \
254   ensure_queue (bst); \
255   (bst)->queue[(bst)->pos].type = IMG; \
256   (bst)->pos++; \
257   } while (0)
258
259 /* Jump around in the state table.  You can use this as the last thing 
260    in your state table to repeat the last N elements forever.
261  */
262 #define BSOD_LOOP(bst,off) do { \
263   ensure_queue (bst); \
264   (bst)->queue[(bst)->pos].type = LOOP; \
265   (bst)->queue[(bst)->pos].arg1 = (void *) (off); \
266   (bst)->pos++; \
267   } while (0)
268
269 /* Restart the whole thing from the beginning.
270  */
271 #define BSOD_RESET(bst) do { \
272   ensure_queue (bst); \
273   (bst)->queue[(bst)->pos].type = RESET; \
274   (bst)->pos++; \
275   } while (0)
276
277
278 static void
279 ensure_queue (struct bsod_state *bst)
280 {
281   int n;
282   if (bst->pos + 1 < bst->queue_size)
283     return;
284
285   n = bst->queue_size + 10;
286   if (n < 100) n *= 2;
287   n *= 1.2;
288
289   bst->queue = (struct bsod_event *) 
290     realloc (bst->queue, n * sizeof(*bst->queue));
291   if (!bst->queue) abort();
292   memset (bst->queue + bst->queue_size, 0, 
293           (n - bst->queue_size) * sizeof(*bst->queue));
294   bst->queue_size = n;
295 }
296
297
298 static void
299 position_for_text (struct bsod_state *bst, const char *line)
300 {
301   int max_width = 0;
302
303   const char *start = line;
304
305   if (bst->queue[bst->pos].type != LEFT &&
306       bst->queue[bst->pos].type != LEFT_FULL)
307     while (*start)
308       {
309         int dir, ascent, descent;
310         XCharStruct ov;
311         const char *end = start;
312         while (*end && *end != '\r' && *end != '\n')
313           end++;
314
315         XTextExtents (bst->font, start, end-start,
316                       &dir, &ascent, &descent, &ov);
317         if (ov.width > max_width)
318           max_width = ov.width;
319         if (!*end) break;
320         start = end+1;
321       }
322
323   switch (bst->queue[bst->pos].type) {
324   case LEFT:
325   case LEFT_FULL:
326     bst->current_left = bst->left_margin;
327     break;
328   case RIGHT:
329   case RIGHT_FULL:
330     bst->x = max_width - bst->right_margin;
331     bst->current_left = bst->x;
332     break;
333   case CENTER:
334   case CENTER_FULL:
335     {
336       int w = (bst->xgwa.width - bst->left_margin - bst->right_margin -
337                max_width);
338       if (w < 0) w = 0;
339       bst->x = bst->left_margin + (w / 2);
340       bst->current_left = bst->x;
341       break;
342     }
343   default:
344     abort();
345   }
346 }
347
348
349 static void
350 bst_crlf (struct bsod_state *bst)
351 {
352   int lh = bst->font->ascent + bst->font->descent;
353   bst->x = bst->current_left;
354   if (!bst->scroll_p ||
355       bst->y + lh < bst->xgwa.height - bst->bottom_margin)
356     bst->y += lh;
357   else
358     {
359       int w = bst->xgwa.width  - bst->right_margin - bst->left_margin;
360       int h = bst->xgwa.height - bst->top_margin - bst->bottom_margin;
361       XCopyArea (bst->dpy, bst->window, bst->window, bst->gc,
362                  bst->left_margin,
363                  bst->top_margin + lh,
364                  w, h - lh,
365                  bst->left_margin,
366                  bst->top_margin);
367       XClearArea (bst->dpy, bst->window,
368                   bst->left_margin, bst->top_margin + h - lh, w, lh, False);
369     }
370 }
371
372
373 static void
374 draw_char (struct bsod_state *bst, char c)
375 {
376   if (!c)
377     abort();
378   else if (c == '\r')
379     {
380       bst->x = bst->current_left;
381     }
382   else if (c == '\n')
383     {
384       if (bst->macx_eol_kludge)
385         {
386           /* Special case for the weird way OSX crashes print newlines... */
387           XDrawImageString (bst->dpy, bst->window, bst->gc, 
388                             bst->x, bst->y, " ", 1);
389           XDrawImageString (bst->dpy, bst->window, bst->gc, 
390                             bst->x, 
391                             bst->y + bst->font->ascent + bst->font->descent,
392                             " ", 1);
393         }
394       bst_crlf (bst);
395     }
396   else if (c == '\b')   /* backspace */
397     {
398       int cw = (bst->font->per_char
399                 ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
400                 : bst->font->min_bounds.width);
401       bst->x -= cw;
402       if (bst->x < bst->left_margin)
403         bst->x = bst->left_margin;
404     }
405   else
406     {
407       int dir, ascent, descent;
408       XCharStruct ov;
409       XTextExtents (bst->font, &c, 1, &dir, &ascent, &descent, &ov);
410
411       if (bst->wrap_p && 
412           bst->x + ov.width > bst->xgwa.width - bst->right_margin)
413         bst_crlf (bst);
414
415       XDrawImageString (bst->dpy, bst->window, bst->gc, 
416                         bst->x, bst->y, &c, 1);
417       bst->x += ov.width;
418     }
419 }
420
421
422 static long
423 bsod_pop (struct bsod_state *bst)
424 {
425   bsod_event_type type = bst->queue[bst->pos].type;
426
427   if (bst->draw_cb)
428     return bst->draw_cb (bst);
429
430   if (bst->pos < 0)   /* already done */
431     abort();
432
433   switch (type) {
434
435   case LEFT:   case LEFT_FULL:
436   case CENTER: case CENTER_FULL:
437   case RIGHT:  case RIGHT_FULL:
438     {
439       const char *s = (const char *) bst->queue[bst->pos].arg2;
440       char c;
441
442       if (! *s)
443         {
444           long delay = bst->line_delay;
445           bst->pos++;
446           bst->current_left = bst->left_margin;
447           return delay;
448         }
449
450       if (! bst->queue[bst->pos].arg3)    /* "done once" */
451         {
452           position_for_text (bst, s);
453           bst->queue[bst->pos].arg4 = (void *) bst->queue[bst->pos].type;
454           bst->queue[bst->pos].type = LEFT;
455
456           if (type == CENTER_FULL ||
457               type == LEFT_FULL ||
458               type == RIGHT_FULL)
459             {
460               XSetForeground (bst->dpy, bst->gc, bst->bg);
461               XFillRectangle (bst->dpy, bst->window, bst->gc,
462                               0,
463                               bst->y - bst->font->ascent,
464                               bst->xgwa.width,
465                               bst->font->ascent + bst->font->descent);
466               XSetForeground (bst->dpy, bst->gc, bst->fg);
467             }
468         }
469
470       c = *s++;
471       draw_char (bst, c);
472       bst->queue[bst->pos].arg2 = (void *) s;
473       bst->queue[bst->pos].arg3 = (void *) 1;  /* "done once" */
474
475       return (c == '\r' || c == '\n'
476               ? bst->line_delay
477               : bst->char_delay);
478     }
479   case INVERT:
480     {
481       unsigned long swap = bst->fg;
482       bst->fg = bst->bg;
483       bst->bg = swap;
484       XSetForeground (bst->dpy, bst->gc, bst->fg);
485       XSetBackground (bst->dpy, bst->gc, bst->bg);
486       bst->pos++;
487       return 0;
488     }
489   case COLOR:
490     {
491       bst->fg = (unsigned long) bst->queue[bst->pos].arg1;
492       bst->bg = (unsigned long) bst->queue[bst->pos].arg2;
493       XSetForeground (bst->dpy, bst->gc, bst->fg);
494       XSetBackground (bst->dpy, bst->gc, bst->bg);
495       bst->pos++;
496       return 0;
497     }
498   case MOVETO:
499     {
500       bst->x = (long) bst->queue[bst->pos].arg1;
501       bst->y = (long) bst->queue[bst->pos].arg2;
502       bst->pos++;
503       return 0;
504     }
505   case RECT:
506     {
507       int f = (long) bst->queue[bst->pos].arg1;
508       int x = (long) bst->queue[bst->pos].arg2;
509       int y = (long) bst->queue[bst->pos].arg3;
510       int w = (long) bst->queue[bst->pos].arg4;
511       int h = (long) bst->queue[bst->pos].arg5;
512       if (f)
513         XFillRectangle (bst->dpy, bst->window, bst->gc, x, y, w, h);
514       else
515         XDrawRectangle (bst->dpy, bst->window, bst->gc, x, y, w, h);
516       bst->pos++;
517       return 0;
518     }
519   case COPY:
520   case PIXMAP:
521     {
522       int srcx = (long) bst->queue[bst->pos].arg1;
523       int srcy = (long) bst->queue[bst->pos].arg2;
524       int w    = (long) bst->queue[bst->pos].arg3;
525       int h    = (long) bst->queue[bst->pos].arg4;
526       int tox  = (long) bst->queue[bst->pos].arg5;
527       int toy  = (long) bst->queue[bst->pos].arg6;
528       XCopyArea (bst->dpy, 
529                  (type == PIXMAP ? bst->pixmap : bst->window), 
530                  bst->window, bst->gc,
531                  srcx, srcy, w, h, tox, toy);
532       bst->pos++;
533       return 0;
534     }
535   case IMG:
536     {
537       if (bst->img_loader) abort();
538       bst->img_loader = load_image_async_simple (0, bst->xgwa.screen, 
539                                                  bst->window, bst->window,
540                                                  0, 0);
541       bst->pos++;
542       return 0;
543     }
544   case PAUSE:
545     {
546       long delay = (long) bst->queue[bst->pos].arg1;
547       bst->pos++;
548       return delay;
549     }
550   case CHAR_DELAY:
551     {
552       bst->char_delay = (long) bst->queue[bst->pos].arg1;
553       bst->pos++;
554       return 0;
555     }
556   case LINE_DELAY:
557     {
558       bst->line_delay = (long) bst->queue[bst->pos].arg1;
559       bst->pos++;
560       return 0;
561     }
562   case MARGINS:
563     {
564       bst->left_margin  = (long) bst->queue[bst->pos].arg1;
565       bst->right_margin = (long) bst->queue[bst->pos].arg2;
566       bst->pos++;
567       return 0;
568     }
569   case CURSOR_BLOCK:
570   case CURSOR_LINE:
571     {
572       long delay = (long) bst->queue[bst->pos].arg1;
573       long count = (long) bst->queue[bst->pos].arg2;
574       int ox = bst->x;
575
576       if (type == CURSOR_BLOCK)
577         {
578           unsigned long swap = bst->fg;
579           bst->fg = bst->bg;
580           bst->bg = swap;
581           XSetForeground (bst->dpy, bst->gc, bst->fg);
582           XSetBackground (bst->dpy, bst->gc, bst->bg);
583           draw_char (bst, ' ');
584         }
585       else
586         {
587           draw_char (bst, (count & 1 ? ' ' : '_'));
588           draw_char (bst, ' ');
589         }
590
591       bst->x = ox;
592
593       count--;
594       bst->queue[bst->pos].arg2 = (void *) count;
595       if (count <= 0)
596         bst->pos++;
597
598       return delay;
599     }
600   case LOOP:
601     {
602       long off = (long) bst->queue[bst->pos].arg1;
603       bst->pos += off;
604       if (bst->pos < 0 || bst->pos >= bst->queue_size)
605         abort();
606       return 0;
607     }
608   case RESET:
609     {
610       int i;
611       for (i = 0; i < bst->queue_size; i++)
612         switch (bst->queue[i].type) {
613         case LEFT:   case LEFT_FULL:
614         case CENTER: case CENTER_FULL:
615         case RIGHT:  case RIGHT_FULL:
616           bst->queue[i].arg2 = bst->queue[i].arg1;
617           bst->queue[i].arg3 = 0;
618           bst->queue[i].type = (bsod_event_type) bst->queue[i].arg4;
619           break;
620         default: break;
621         }
622       bst->pos = 0;
623       return 0;
624     }
625   case EOF:
626     {
627       bst->pos = -1;
628       return -1;
629     }
630   default:
631     break;
632   }
633   abort();
634 }
635
636
637 static struct bsod_state *
638 make_bsod_state (Display *dpy, Window window,
639                  const char *name, const char *class)
640 {
641   XGCValues gcv;
642   struct bsod_state *bst;
643   char buf1[1024], buf2[1024];
644   char buf3[1024], buf4[1024];
645   const char *font1, *font2;
646
647   bst = (struct bsod_state *) calloc (1, sizeof (*bst));
648   bst->queue_size = 10;
649   bst->queue = (struct bsod_event *) calloc (bst->queue_size,
650                                              sizeof (*bst->queue));
651   bst->dpy = dpy;
652   bst->window = window;
653   XGetWindowAttributes (dpy, window, &bst->xgwa);
654
655   /* If the window is small:
656        use ".font" if it is loadable, else use ".font2".
657
658      If the window is big:
659        use ".bigFont" if it is loadable, else use ".bigFont2".
660    */
661   if (bst->xgwa.height < 640)
662     {
663       sprintf (buf1, "%.100s.font", name);
664       sprintf (buf2, "%.100s.font", class);
665       sprintf (buf3, "%.100s.font2", name);
666       sprintf (buf4, "%.100s.font2", class);
667     }
668   else
669     {
670       sprintf (buf1, "%.100s.bigFont", name);
671       sprintf (buf2, "%.100s.bigFont", class);
672       sprintf (buf3, "%.100s.bigFont2", name);
673       sprintf (buf4, "%.100s.bigFont2", class);
674     }
675
676   font1 = get_string_resource (dpy, buf1, buf2);
677   font2 = get_string_resource (dpy, buf3, buf4);
678
679   if (font1)
680     bst->font = XLoadQueryFont (dpy, font1);
681   if (! bst->font && font2)
682     bst->font = XLoadQueryFont (dpy, font2);
683
684   /* If neither of those worked, try some defaults. */
685
686   if (! bst->font)
687     bst->font = XLoadQueryFont (dpy,"-*-courier-bold-r-*-*-*-120-*-*-m-*-*-*");
688   if (! bst->font)
689     bst->font = XLoadQueryFont (dpy, "fixed");
690   if (! bst->font)
691     abort();
692
693   gcv.font = bst->font->fid;
694
695   sprintf (buf1, "%.100s.foreground", name);
696   sprintf (buf2, "%.100s.Foreground", class);
697   bst->fg = gcv.foreground = get_pixel_resource (dpy, bst->xgwa.colormap,
698                                                  buf1, buf2);
699   sprintf (buf1, "%.100s.background", name);
700   sprintf (buf2, "%.100s.Background", class);
701   bst->bg = gcv.background = get_pixel_resource (dpy, bst->xgwa.colormap,
702                                                  buf1, buf2);
703   bst->gc = XCreateGC (dpy, window, GCFont|GCForeground|GCBackground, &gcv);
704
705 #ifdef HAVE_COCOA
706   jwxyz_XSetAntiAliasing (dpy, bst->gc, False);
707 #endif
708
709   bst->left_margin = bst->right_margin = 10;
710   bst->x = bst->left_margin;
711   bst->y = bst->font->ascent + bst->left_margin;
712
713   XSetWindowBackground (dpy, window, gcv.background);
714   return bst;
715 }
716
717
718 static void
719 free_bsod_state (struct bsod_state *bst)
720 {
721   int i;
722
723   if (bst->free_cb)
724     bst->free_cb (bst);
725   if (bst->pixmap)
726     XFreePixmap(bst->dpy, bst->pixmap);
727
728   XFreeFont (bst->dpy, bst->font);
729   XFreeGC (bst->dpy, bst->gc);
730
731   for (i = 0; i < bst->queue_size; i++)
732     switch (bst->queue[i].type) {
733     case LEFT:   case LEFT_FULL:
734     case RIGHT:  case RIGHT_FULL:
735     case CENTER: case CENTER_FULL:
736       free ((char *) bst->queue[i].arg1);
737       break;
738     default:
739       break;
740     }
741
742   free (bst->queue);
743   free (bst);
744 }
745
746
747 static Pixmap
748 double_pixmap (Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap,
749                int pix_w, int pix_h)
750 {
751   int x, y;
752   Pixmap p2 = XCreatePixmap(dpy, pixmap, pix_w*2, pix_h*2, depth);
753   XImage *i1 = XGetImage(dpy, pixmap, 0, 0, pix_w, pix_h, ~0L, ZPixmap);
754   XImage *i2 = XCreateImage(dpy, visual, depth, ZPixmap, 0, 0,
755                             pix_w*2, pix_h*2, 8, 0);
756   i2->data = (char *) calloc(i2->height, i2->bytes_per_line);
757   for (y = 0; y < pix_h; y++)
758     for (x = 0; x < pix_w; x++)
759       {
760         unsigned long p = XGetPixel(i1, x, y);
761         XPutPixel(i2, x*2,   y*2,   p);
762         XPutPixel(i2, x*2+1, y*2,   p);
763         XPutPixel(i2, x*2,   y*2+1, p);
764         XPutPixel(i2, x*2+1, y*2+1, p);
765       }
766   free(i1->data); i1->data = 0;
767   XDestroyImage(i1);
768   XPutImage(dpy, p2, gc, i2, 0, 0, 0, 0, i2->width, i2->height);
769   free(i2->data); i2->data = 0;
770   XDestroyImage(i2);
771   XFreePixmap(dpy, pixmap);
772   return p2;
773 }
774
775
776 /*****************************************************************************
777  *****************************************************************************/
778
779 static struct bsod_state *
780 windows_31 (Display *dpy, Window window)
781 {
782   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
783   BSOD_INVERT (bst);
784   BSOD_TEXT   (bst, CENTER, "Windows\n");
785   BSOD_INVERT (bst);
786   BSOD_TEXT   (bst, CENTER,
787                "A fatal exception 0E has occured at F0AD:42494C4C\n"
788                "the current application will be terminated.\n"
789                "\n"
790                "* Press any key to terminate the current application.\n"
791                "* Press CTRL+ALT+DELETE again to restart your computer.\n"
792                "  You will lose any unsaved information in all applications.\n"
793                "\n"
794                "\n");
795   BSOD_TEXT   (bst, CENTER, "Press any key to continue");
796
797   bst->y = ((bst->xgwa.height -
798              ((bst->font->ascent + bst->font->descent) * 9))
799             / 2);
800
801   XClearWindow (dpy, window);
802   return bst;
803 }
804
805
806 static struct bsod_state *
807 windows_nt (Display *dpy, Window window)
808 {
809   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
810
811   BSOD_TEXT (bst, LEFT,
812    "*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n"
813    "Unhandled Kernel exception c0000047 from fa8418b4 (8025ea21,fd6829e8)\n"
814    "\n"
815    "Dll Base Date Stamp - Name             Dll Base Date Stamp - Name\n"
816    "80100000 2be154c9 - ntoskrnl.exe       80400000 2bc153b0 - hal.dll\n"
817    "80258000 2bd49628 - ncrc710.sys        8025c000 2bd49688 - SCSIPORT.SYS \n"
818    "80267000 2bd49683 - scsidisk.sys       802a6000 2bd496b9 - Fastfat.sys\n"
819    "fa800000 2bd49666 - Floppy.SYS         fa810000 2bd496db - Hpfs_Rec.SYS\n"
820    "fa820000 2bd49676 - Null.SYS           fa830000 2bd4965a - Beep.SYS\n"
821    "fa840000 2bdaab00 - i8042prt.SYS       fa850000 2bd5a020 - SERMOUSE.SYS\n"
822    "fa860000 2bd4966f - kbdclass.SYS       fa870000 2bd49671 - MOUCLASS.SYS\n"
823    "fa880000 2bd9c0be - Videoprt.SYS       fa890000 2bd49638 - NCC1701E.SYS\n"
824    "fa8a0000 2bd4a4ce - Vga.SYS            fa8b0000 2bd496d0 - Msfs.SYS\n"
825    "fa8c0000 2bd496c3 - Npfs.SYS           fa8e0000 2bd496c9 - Ntfs.SYS\n"
826    "fa940000 2bd496df - NDIS.SYS           fa930000 2bd49707 - wdlan.sys\n"
827    "fa970000 2bd49712 - TDI.SYS            fa950000 2bd5a7fb - nbf.sys\n"
828    "fa980000 2bd72406 - streams.sys        fa9b0000 2bd4975f - ubnb.sys\n"
829    "fa9c0000 2bd5bfd7 - usbser.sys         fa9d0000 2bd4971d - netbios.sys\n"
830    "fa9e0000 2bd49678 - Parallel.sys       fa9f0000 2bd4969f - serial.SYS\n"
831    "faa00000 2bd49739 - mup.sys            faa40000 2bd4971f - SMBTRSUP.SYS\n"
832    "faa10000 2bd6f2a2 - srv.sys            faa50000 2bd4971a - afd.sys\n"
833    "faa60000 2bd6fd80 - rdr.sys            faaa0000 2bd49735 - bowser.sys\n"
834    "\n"
835    "Address dword dump Dll Base                                      - Name\n"
836    "801afc20 80106fc0 80106fc0 00000000 00000000 80149905 : "
837      "fa840000 - i8042prt.SYS\n"
838    "801afc24 80149905 80149905 ff8e6b8c 80129c2c ff8e6b94 : "
839      "8025c000 - SCSIPORT.SYS\n"
840    "801afc2c 80129c2c 80129c2c ff8e6b94 00000000 ff8e6b94 : "
841      "80100000 - ntoskrnl.exe\n"
842    "801afc34 801240f2 80124f02 ff8e6df4 ff8e6f60 ff8e6c58 : "
843      "80100000 - ntoskrnl.exe\n"
844    "801afc54 80124f16 80124f16 ff8e6f60 ff8e6c3c 8015ac7e : "
845      "80100000 - ntoskrnl.exe\n"
846    "801afc64 8015ac7e 8015ac7e ff8e6df4 ff8e6f60 ff8e6c58 : "
847      "80100000 - ntoskrnl.exe\n"
848    "801afc70 80129bda 80129bda 00000000 80088000 80106fc0 : "
849      "80100000 - ntoskrnl.exe\n"
850    "\n"
851    "Kernel Debugger Using: COM2 (Port 0x2f8, Baud Rate 19200)\n"
852    "Restart and set the recovery options in the system control panel\n"
853    "or the /CRASHDEBUG system start option. If this message reappears,\n"
854    "contact your system administrator or technical support group."
855    );
856
857   bst->line_delay = 750;
858
859   XClearWindow (dpy, window);
860   return bst;
861 }
862
863
864 static struct bsod_state *
865 windows_2k (Display *dpy, Window window)
866 {
867   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
868
869   BSOD_TEXT (bst, LEFT,
870     "*** STOP: 0x000000D1 (0xE1D38000,0x0000001C,0x00000000,0xF09D42DA)\n"
871     "DRIVER_IRQL_NOT_LESS_OR_EQUAL \n"
872     "\n"
873     "*** Address F09D42DA base at F09D4000, DateStamp 39f459ff - CRASHDD.SYS\n"
874     "\n"
875     "Beginning dump of physical memory\n");
876   BSOD_PAUSE (bst, 4000000);
877   BSOD_TEXT (bst, LEFT,
878     "Physical memory dump complete. Contact your system administrator or\n"
879     "technical support group.\n");
880
881   bst->left_margin = 40;
882   bst->y = (bst->font->ascent + bst->font->descent) * 10;
883   bst->line_delay = 750;
884
885   XClearWindow (dpy, window);
886   return bst;
887 }
888
889
890 static struct bsod_state *
891 windows_me (Display *dpy, Window window)
892 {
893   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
894
895   BSOD_TEXT (bst, LEFT,
896     "Windows protection error.  You need to restart your computer.\n\n"
897     "System halted.");
898   BSOD_CURSOR (bst, CURSOR_LINE, 120000, 999999);
899
900   bst->left_margin = 40;
901   bst->y = ((bst->xgwa.height -
902              ((bst->font->ascent + bst->font->descent) * 3))
903             / 2);
904
905   XClearWindow (dpy, window);
906   return bst;
907 }
908
909
910 static struct bsod_state *
911 windows_xp (Display *dpy, Window window)
912 {
913   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
914
915   BSOD_TEXT (bst, LEFT,  /* From Wm. Rhodes <xscreensaver@27.org> */
916       "A problem has been detected and windows has been shut down to prevent "
917       "damage\n"
918       "to your computer.\n"
919       "\n"
920       "If this is the first time you've seen this Stop error screen,\n"
921       "restart your computer. If this screen appears again, follow\n"
922       "these steps:\n"
923       "\n"
924       "Check to be sure you have adequate disk space. If a driver is\n"
925       "identified in the Stop message, disable the driver or check\n"
926       "with the manufacturer for driver updates. Try changing video\n"
927       "adapters.\n"
928       "\n"
929       "Check with your hardware vendor for any BIOS updates. Disable\n"
930       "BIOS memory options such as caching or shadowing. If you need\n"
931       "to use Safe Mode to remove or disable components, restart your\n"
932       "computer, press F8 to select Advanced Startup Options, and then\n"
933       "select Safe Mode.\n"
934       "\n"
935       "Technical information:\n"
936       "\n"
937       "*** STOP: 0x0000007E (0xC0000005,0xF88FF190,0x0xF8975BA0,0xF89758A0)\n"
938       "\n"
939       "\n"
940       "***  EPUSBDSK.sys - Address F88FF190 base at FF88FE000, datestamp "
941       "3b9f3248\n"
942       "\n"
943       "Beginning dump of physical memory\n");
944   BSOD_PAUSE (bst, 4000000);
945   BSOD_TEXT (bst, LEFT,
946       "Physical memory dump complete.\n"
947       "Contact your system administrator or technical support group for "
948       "further\n"
949       "assistance.\n");
950
951   XClearWindow (dpy, window);
952   return bst;
953 }
954
955
956 static struct bsod_state *
957 windows_lh (Display *dpy, Window window)
958 {
959   struct bsod_state *bst = 
960     make_bsod_state (dpy, window, "windowslh", "WindowsLH");
961
962   unsigned long fg = bst->fg;
963   unsigned long bg = bst->bg;
964   unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
965                                           "windowslh.background2",
966                                           "WindowsLH.Background");
967
968   /* The "RSOD" that appeared with "Windows Longhorn 5048.050401-0536_x86fre"
969      As reported by http://joi.ito.com/RedScreen.jpg
970    */
971   BSOD_COLOR (bst, bg, bg2);
972   BSOD_TEXT (bst, CENTER_FULL, "Windows Boot Error\n");
973   BSOD_COLOR (bst, fg, bg);
974   BSOD_TEXT (bst, CENTER,
975      "\n"
976      "Windows Boot Manager has experienced a problem.\n"
977      "\n"
978      "\n"
979      "    Status: 0xc000000f\n"
980      "\n"
981      "\n"
982      "\n"
983      "    Info: An error occurred transferring exectuion."  /* (sic) */
984      "\n"
985      "\n"
986      "\n"
987      "You can try to recover the system with the Microsoft Windows "
988      "System Recovery\n"
989      "Tools. (You might need to restart the system manually.)\n"
990      "\n"
991      "If the problem continues, please contact your system administrator "
992      "or computer\n"
993      "manufacturer.\n"
994      );
995   BSOD_MOVETO (bst, bst->left_margin, bst->xgwa.height - bst->font->descent);
996   BSOD_COLOR (bst, bg, bg2);
997   BSOD_TEXT (bst, LEFT_FULL, " SPACE=Continue\n");
998
999   bst->y = bst->font->ascent;
1000
1001   XClearWindow (dpy, window);
1002   return bst;
1003 }
1004
1005
1006 static struct bsod_state *
1007 windows_other (Display *dpy, Window window)
1008 {
1009   /* Lump all of the 2K-ish crashes together and select them randomly...
1010    */
1011   int which = (random() % 4);
1012   switch (which) {
1013   case 0: return windows_2k (dpy, window); break;
1014   case 1: return windows_me (dpy, window); break;
1015   case 2: return windows_xp (dpy, window); break;
1016   case 3: return windows_lh (dpy, window); break;
1017   default: abort(); break;
1018   }
1019 }
1020
1021
1022 /* As seen in Portal 2.  By jwz.
1023  */
1024 static struct bsod_state *
1025 glados (Display *dpy, Window window)
1026 {
1027   struct bsod_state *bst = make_bsod_state (dpy, window, "glaDOS", "GlaDOS");
1028   const char * panicstr[] = {
1029     "\n",
1030     "MOLTEN CORE WARNING\n",
1031     "\n",
1032     "An operator error exception has occurred at FISSREAC0020093:09\n",
1033     "FISSREAC0020077:14 FISSREAC0020023:17 FISSREAC0020088:22\n",
1034     "neutron multiplication rate at spikevalue 99999999\n",
1035     "\n",
1036     "* Press any keep to vent radiological emissions into atmosphere.\n",
1037     "* Consult reactor core manual for instructions on proper reactor core\n",
1038     "maintenance and repair.\n",
1039     "\n",
1040     "Press any key to continue\n",
1041   };
1042
1043   int i;
1044
1045   bst->y = ((bst->xgwa.height -
1046              ((bst->font->ascent + bst->font->descent) * countof(panicstr)))
1047             / 2);
1048
1049   BSOD_MOVETO (bst, 0, bst->y);
1050   BSOD_INVERT (bst);
1051   BSOD_TEXT   (bst,  CENTER, "OPERATOR ERROR\n");
1052   BSOD_INVERT (bst);
1053   for (i = 0; i < countof(panicstr); i++)
1054     BSOD_TEXT (bst, CENTER, panicstr[i]);
1055   BSOD_PAUSE (bst, 1000000);
1056   BSOD_INVERT (bst);
1057   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
1058   BSOD_INVERT (bst);
1059   BSOD_PAUSE (bst, 250000);
1060   BSOD_RESET (bst);
1061
1062   XClearWindow (dpy, window);
1063   return bst;
1064 }
1065
1066
1067
1068 /* SCO OpenServer 5 panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
1069  */
1070 static struct bsod_state *
1071 sco (Display *dpy, Window window)
1072 {
1073   struct bsod_state *bst = make_bsod_state (dpy, window, "sco", "SCO");
1074
1075   BSOD_TEXT (bst, LEFT,
1076      "Unexpected trap in kernel mode:\n"
1077      "\n"
1078      "cr0 0x80010013     cr2  0x00000014     cr3 0x00000000  tlb  0x00000000\n"
1079      "ss  0x00071054    uesp  0x00012055     efl 0x00080888  ipl  0x00000005\n"
1080      "cs  0x00092585     eip  0x00544a4b     err 0x004d4a47  trap 0x0000000E\n"
1081      "eax 0x0045474b     ecx  0x0042544b     edx 0x57687920  ebx  0x61726520\n"
1082      "esp 0x796f7520     ebp  0x72656164     esi 0x696e6720  edi  0x74686973\n"
1083      "ds  0x3f000000     es   0x43494c48     fs  0x43525343  gs   0x4f4d4b53\n"
1084      "\n"
1085      "PANIC: k_trap - kernel mode trap type 0x0000000E\n"
1086      "Trying to dump 5023 pages to dumpdev hd (1/41), 63 pages per '.'\n"
1087     );
1088   BSOD_CHAR_DELAY (bst, 100000);
1089   BSOD_TEXT (bst, LEFT,
1090     "................................................................."
1091     "..............\n"
1092     );
1093   BSOD_CHAR_DELAY (bst, 0);
1094   BSOD_TEXT (bst, LEFT,
1095      "5023 pages dumped\n"
1096      "\n"
1097      "\n"
1098      );
1099   BSOD_PAUSE (bst, 2000000);
1100   BSOD_TEXT (bst, LEFT,
1101      "**   Safe to Power Off   **\n"
1102      "           - or -\n"
1103      "** Press Any Key to Reboot **\n"
1104     );
1105
1106   bst->y = ((bst->xgwa.height -
1107              ((bst->font->ascent + bst->font->descent) * 18)));
1108
1109   XClearWindow (dpy, window);
1110   return bst;
1111 }
1112
1113
1114 /* Linux (sparc) panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
1115  */
1116 static struct bsod_state *
1117 sparc_linux (Display *dpy, Window window)
1118 {
1119   struct bsod_state *bst = make_bsod_state (dpy, window, "sco", "SCO");
1120   bst->scroll_p = True;
1121   bst->y = bst->xgwa.height - bst->font->ascent - bst->font->descent;
1122
1123   BSOD_TEXT (bst, LEFT,
1124         "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
1125         "Unable to handle kernel paging request at virtual address f0d4a000\n"
1126         "tsk->mm->context = 00000014\n"
1127         "tsk->mm->pgd = f26b0000\n"
1128         "              \\|/ ____ \\|/\n"
1129         "              \"@'/ ,. \\`@\"\n"
1130         "              /_| \\__/ |_\\\n"
1131         "                 \\__U_/\n"
1132         "gawk(22827): Oops\n"
1133         "PSR: 044010c1 PC: f001c2cc NPC: f001c2d0 Y: 00000000\n"
1134         "g0: 00001000 g1: fffffff7 g2: 04401086 g3: 0001eaa0\n"
1135         "g4: 000207dc g5: f0130400 g6: f0d4a018 g7: 00000001\n"
1136         "o0: 00000000 o1: f0d4a298 o2: 00000040 o3: f1380718\n"
1137         "o4: f1380718 o5: 00000200 sp: f1b13f08 ret_pc: f001c2a0\n"
1138         "l0: efffd880 l1: 00000001 l2: f0d4a230 l3: 00000014\n"
1139         "l4: 0000ffff l5: f0131550 l6: f012c000 l7: f0130400\n"
1140         "i0: f1b13fb0 i1: 00000001 i2: 00000002 i3: 0007c000\n"
1141         "i4: f01457c0 i5: 00000004 i6: f1b13f70 i7: f0015360\n"
1142         "Instruction DUMP:\n"
1143     );
1144
1145   XClearWindow (dpy, window);
1146   return bst;
1147 }
1148
1149
1150 /* BSD Panic by greywolf@starwolf.com - modeled after the Linux panic above.
1151    By Grey Wolf <greywolf@siteROCK.com>
1152  */
1153 static struct bsod_state *
1154 bsd (Display *dpy, Window window)
1155 {
1156   struct bsod_state *bst = make_bsod_state (dpy, window, "bsd", "BSD");
1157
1158   const char * const panicstr[] = {
1159     "panic: ifree: freeing free inode\n",
1160     "panic: blkfree: freeing free block\n",
1161     "panic: improbability coefficient below zero\n",
1162     "panic: cgsixmmap\n",
1163     "panic: crazy interrupts\n",
1164     "panic: nmi\n",
1165     "panic: attempted windows install\n",
1166     "panic: don't\n",
1167     "panic: free inode isn't\n",
1168     "panic: cpu_fork: curproc\n",
1169     "panic: malloc: out of space in kmem_map\n",
1170     "panic: vogon starship detected\n",
1171     "panic: teleport chamber: out of order\n",
1172     "panic: Brain fried - core dumped\n"
1173    };
1174   int i, n, b;
1175   char syncing[80], bbuf[5];
1176
1177   for (i = 0; i < sizeof(syncing); i++)
1178     syncing[i] = 0;
1179
1180   i = (random() % (sizeof(panicstr) / sizeof(*panicstr)));
1181   BSOD_TEXT (bst, LEFT, panicstr[i]);
1182   BSOD_TEXT (bst, LEFT, "Syncing disks: ");
1183
1184   b = (random() % 40);
1185   for (n = 0; (n < 20) && (b > 0); n++)
1186     {
1187       if (i)
1188         {
1189           i = (random() & 0x7);
1190           b -= (random() & 0xff) % 20;
1191           if (b < 0)
1192             b = 0;
1193         }
1194       sprintf (bbuf, "%d ", b);
1195       BSOD_TEXT (bst, LEFT, bbuf);
1196       BSOD_PAUSE (bst, 1000000);
1197     }
1198
1199   BSOD_TEXT (bst, LEFT, "\n");
1200   BSOD_TEXT (bst, LEFT, (b ? "damn!" : "sunk!"));
1201   BSOD_TEXT (bst, LEFT, "\nRebooting\n");
1202
1203   bst->y = ((bst->xgwa.height -
1204              ((bst->font->ascent + bst->font->descent) * 4)));
1205
1206   XClearWindow (dpy, window);
1207   return bst;
1208 }
1209
1210
1211 static struct bsod_state *
1212 amiga (Display *dpy, Window window)
1213 {
1214   struct bsod_state *bst = make_bsod_state (dpy, window, "amiga", "Amiga");
1215
1216   Pixmap pixmap = 0;
1217   int pix_w = 0, pix_h = 0;
1218   int height;
1219   int lw = 10;
1220
1221   unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
1222                                           "amiga.background2",
1223                                           "Amiga.Background");
1224
1225 # ifdef DO_XPM
1226   pixmap = xpm_data_to_pixmap (dpy, window, (char **) amiga_hand,
1227                                &pix_w, &pix_h, 0);
1228 # endif /* DO_XPM */
1229
1230   if (pixmap && bst->xgwa.height > 600) /* scale up the bitmap */
1231     {
1232       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
1233                               pixmap, pix_w, pix_h);
1234       pix_w *= 2;
1235       pix_h *= 2;
1236     }
1237
1238   XSetLineAttributes (dpy, bst->gc, lw, LineSolid, CapButt, JoinMiter);
1239
1240   height = (bst->font->ascent + bst->font->descent) * 6;
1241
1242   BSOD_PAUSE (bst, 2000000);
1243   BSOD_COPY (bst, 0, 0, bst->xgwa.width, bst->xgwa.height - height, 0, height);
1244
1245   BSOD_INVERT (bst);
1246   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, height);
1247   BSOD_INVERT (bst);
1248   BSOD_TEXT (bst, CENTER,
1249              "\n"
1250              "Software failure.  Press left mouse button to continue.\n"
1251              "Guru Meditation #00000003.00C01570"
1252              );
1253   BSOD_RECT (bst, False, lw/2, lw/2, bst->xgwa.width - lw, height);
1254   BSOD_PAUSE (bst, 1000000);
1255   BSOD_INVERT (bst);
1256   BSOD_LOOP (bst, -3);
1257
1258   XSetWindowBackground (dpy, window, bg2);
1259   XClearWindow (dpy, window);
1260   XSetWindowBackground (dpy, window, bst->bg);
1261
1262   if (pixmap)
1263     {
1264       int x = (bst->xgwa.width - pix_w) / 2;
1265       int y = ((bst->xgwa.height - pix_h) / 2);
1266       XCopyArea (dpy, pixmap, bst->window, bst->gc, 0, 0, pix_w, pix_h, x, y);
1267     }
1268
1269   bst->y += lw;
1270
1271   return bst;
1272 }
1273
1274
1275
1276 /* Atari ST, by Marcus Herbert <rhoenie@nobiscum.de>
1277    Marcus had this to say:
1278
1279         Though I still have my Atari somewhere, I hardly remember
1280         the meaning of the bombs. I think 9 bombs was "bus error" or
1281         something like that.  And you often had a few bombs displayed
1282         quickly and then the next few ones coming up step by step.
1283         Perhaps somebody else can tell you more about it..  its just
1284         a quick hack :-}
1285  */
1286 static struct bsod_state *
1287 atari (Display *dpy, Window window)
1288 {
1289   struct bsod_state *bst = make_bsod_state (dpy, window, "atari", "Atari");
1290
1291   Pixmap pixmap = 0;
1292   int pix_w = atari_width;
1293   int pix_h = atari_height;
1294   int offset;
1295   int i, x, y;
1296
1297   pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) atari_bits,
1298                                         pix_w, pix_h,
1299                                         bst->fg, bst->bg, bst->xgwa.depth);
1300   pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
1301                           pixmap, pix_w, pix_h);
1302   pix_w *= 2;
1303   pix_h *= 2;
1304
1305   offset = pix_w;
1306   x = 0;
1307   y = bst->xgwa.height/2;
1308   if (y < 0) y = 0;
1309
1310   for (i = 1; i< 7; i++)
1311     BSOD_COPY (bst, x, y, pix_w, pix_h, (x + (i*offset)), y);
1312
1313   for (; i< 10; i++) 
1314     {
1315       BSOD_PAUSE (bst, 1000000);
1316       BSOD_COPY (bst, x, y, pix_w, pix_h, (x + (i*offset)), y);
1317     }
1318
1319   XClearWindow (dpy, window);
1320   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
1321   XFreePixmap (dpy, pixmap);
1322
1323   return bst;
1324 }
1325
1326
1327 static struct bsod_state *
1328 mac (Display *dpy, Window window)
1329 {
1330   struct bsod_state *bst = make_bsod_state (dpy, window, "mac", "Mac");
1331
1332   Pixmap pixmap = 0;
1333   int pix_w = mac_width;
1334   int pix_h = mac_height;
1335   int offset = mac_height * 4;
1336   int i;
1337
1338   const char *string = ("0 0 0 0 0 0 0 F\n"
1339                         "0 0 0 0 0 0 0 3");
1340
1341   pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) mac_bits,
1342                                        mac_width, mac_height,
1343                                        bst->fg, bst->bg, bst->xgwa.depth);
1344
1345   for (i = 0; i < 2; i++)
1346     {
1347       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
1348                               pixmap, pix_w, pix_h);
1349       pix_w *= 2; pix_h *= 2;
1350     }
1351
1352   bst->x = (bst->xgwa.width - pix_w) / 2;
1353   bst->y = (((bst->xgwa.height + offset) / 2) -
1354             pix_h -
1355             (bst->font->ascent + bst->font->descent) * 2);
1356   if (bst->y < 0) bst->y = 0;
1357
1358   XClearWindow (dpy, window);
1359   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, bst->x, bst->y);
1360   XFreePixmap (dpy, pixmap);
1361
1362   bst->y += offset + bst->font->ascent + bst->font->descent;
1363   BSOD_TEXT (bst, CENTER, string);
1364
1365   return bst;
1366 }
1367
1368
1369 static struct bsod_state *
1370 macsbug (Display *dpy, Window window)
1371 {
1372   struct bsod_state *bst = make_bsod_state (dpy, window, "macsbug", "MacsBug");
1373
1374   __extension__
1375   const char *left = ("    SP     \n"
1376                       " 04EB0A58  \n"
1377                       "58 00010000\n"
1378                       "5C 00010000\n"
1379                       "   ........\n"
1380                       "60 00000000\n"
1381                       "64 000004EB\n"
1382                       "   ........\n"
1383                       "68 0000027F\n"
1384                       "6C 2D980035\n"
1385                       "   ....-..5\n"
1386                       "70 00000054\n"
1387                       "74 0173003E\n"
1388                       "   ...T.s.>\n"
1389                       "78 04EBDA76\n"
1390                       "7C 04EBDA8E\n"
1391                       "   .S.L.a.U\n"
1392                       "80 00000000\n"
1393                       "84 000004EB\n"
1394                       "   ........\n"
1395                       "88 00010000\n"
1396                       "8C 00010000\n"
1397                       "   ...{3..S\n"
1398                       "\n"
1399                       "\n"
1400                       " CurApName \n"
1401                       "  Finder   \n"
1402                       "\n"
1403                       " 32-bit VM \n"
1404                       "SR Smxnzvc0\n"
1405                       "D0 04EC0062\n"
1406                       "D1 00000053\n"
1407                       "D2 FFFF0100\n"
1408                       "D3 00010000\n"
1409                       "D4 00010000\n"
1410                       "D5 04EBDA76\n"
1411                       "D6 04EBDA8E\n"
1412                       "D7 00000001\n"
1413                       "\n"
1414                       "A0 04EBDA76\n"
1415                       "A1 04EBDA8E\n"
1416                       "A2 A0A00060\n"
1417                       "A3 027F2D98\n"
1418                       "A4 027F2E58\n"
1419                       "A5 04EC04F0\n"
1420                       "A6 04EB0A86\n"
1421                       "A7 04EB0A58");
1422   const char *bottom = ("  _A09D\n"
1423                         "     +00884    40843714     #$0700,SR         "
1424                         "                  ; A973        | A973\n"
1425                         "     +00886    40843765     *+$0400           "
1426                         "                                | 4A1F\n"
1427                         "     +00888    40843718     $0004(A7),([0,A7[)"
1428                         "                  ; 04E8D0AE    | 66B8");
1429   __extension__
1430   const char * body = ("PowerPC unmapped memory exception at 003AFDAC "
1431                                                 "BowelsOfTheMemoryMgr+04F9C\n"
1432                       " Calling chain using A6/R1 links\n"
1433                       "  Back chain  ISA  Caller\n"
1434                       "  00000000    PPC  28C5353C  __start+00054\n"
1435                       "  24DB03C0    PPC  28B9258C  main+0039C\n"
1436                       "  24DB0350    PPC  28B9210C  MainEvent+00494\n"
1437                       "  24DB02B0    PPC  28B91B40  HandleEvent+00278\n"
1438                       "  24DB0250    PPC  28B83DAC  DoAppleEvent+00020\n"
1439                       "  24DB0210    PPC  FFD3E5D0  "
1440                                                 "AEProcessAppleEvent+00020\n"
1441                       "  24DB0132    68K  00589468\n"
1442                       "  24DAFF8C    68K  00589582\n"
1443                       "  24DAFF26    68K  00588F70\n"
1444                       "  24DAFEB3    PPC  00307098  "
1445                                                 "EmToNatEndMoveParams+00014\n"
1446                       "  24DAFE40    PPC  28B9D0B0  DoScript+001C4\n"
1447                       "  24DAFDD0    PPC  28B9C35C  RunScript+00390\n"
1448                       "  24DAFC60    PPC  28BA36D4  run_perl+000E0\n"
1449                       "  24DAFC10    PPC  28BC2904  perl_run+002CC\n"
1450                       "  24DAFA80    PPC  28C18490  Perl_runops+00068\n"
1451                       "  24DAFA30    PPC  28BE6CC0  Perl_pp_backtick+000FC\n"
1452                       "  24DAF9D0    PPC  28BA48B8  Perl_my_popen+00158\n"
1453                       "  24DAF980    PPC  28C5395C  sfclose+00378\n"
1454                       "  24DAF930    PPC  28BA568C  free+0000C\n"
1455                       "  24DAF8F0    PPC  28BA6254  pool_free+001D0\n"
1456                       "  24DAF8A0    PPC  FFD48F14  DisposePtr+00028\n"
1457                       "  24DAF7C9    PPC  00307098  "
1458                                                 "EmToNatEndMoveParams+00014\n"
1459                       "  24DAF780    PPC  003AA180  __DisposePtr+00010");
1460
1461   const char *s;
1462   int body_lines = 1;
1463
1464   int char_width, line_height;
1465   int col_right, row_top, row_bottom, page_right, page_bottom, body_top;
1466   int xoff, yoff;
1467
1468   unsigned long fg = bst->fg;
1469   unsigned long bg = bst->bg;
1470   unsigned long bc = get_pixel_resource (dpy, bst->xgwa.colormap,
1471                                          "macsbug.borderColor",
1472                                          "MacsBug.BorderColor");
1473
1474   for (s = body; *s; s++) if (*s == '\n') body_lines++;
1475
1476   char_width = (bst->font->per_char
1477                 ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
1478                 : bst->font->min_bounds.width);
1479   line_height = bst->font->ascent + bst->font->descent;
1480
1481   col_right   = char_width  * 12;  /* number of columns in `left' */
1482   page_bottom = line_height * 47;  /* number of lines in `left'   */
1483
1484   if (page_bottom > bst->xgwa.height) 
1485     page_bottom = bst->xgwa.height;
1486
1487   row_bottom = page_bottom - line_height;
1488   row_top    = row_bottom - (line_height * 4);
1489   page_right = col_right + (char_width * 88);
1490   body_top   = row_top - (line_height * body_lines);
1491
1492   page_bottom += 2;
1493   row_bottom += 2;
1494   body_top -= 4;
1495
1496   if (body_top > 4)
1497     body_top = 4;
1498
1499   xoff = (bst->xgwa.width  - page_right)  / 2;
1500   yoff = (bst->xgwa.height - page_bottom) / 2;
1501
1502   if (xoff < 0) xoff = 0;
1503   if (yoff < 0) yoff = 0;
1504
1505   BSOD_MARGINS (bst, xoff, yoff);
1506
1507   BSOD_COLOR (bst, bc, bg);
1508   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
1509   BSOD_COLOR (bst, bg, bg);
1510   BSOD_RECT (bst, True, xoff-2, yoff, page_right+4, page_bottom);
1511   BSOD_COLOR (bst, fg, bg);
1512
1513   BSOD_MOVETO (bst, xoff, yoff + line_height);
1514   BSOD_TEXT (bst, LEFT, left);
1515   BSOD_MOVETO (bst, xoff+col_right, yoff + row_top + line_height);
1516   BSOD_TEXT (bst, LEFT, bottom);
1517
1518   BSOD_RECT (bst, True, xoff + col_right, yoff, 2, page_bottom);
1519   BSOD_RECT (bst, True, xoff + col_right, yoff + row_top, 
1520              page_right - col_right, 1);
1521   BSOD_RECT (bst, True, xoff + col_right, yoff + row_bottom, 
1522              page_right - col_right, 1);
1523   BSOD_RECT (bst, False, xoff-2, yoff, page_right+4, page_bottom);
1524
1525   BSOD_LINE_DELAY (bst, 500);
1526   BSOD_MOVETO (bst, 
1527                xoff + col_right + char_width, 
1528                yoff + body_top + line_height);
1529   BSOD_MARGINS (bst, xoff + col_right + char_width, yoff);
1530   BSOD_TEXT (bst, LEFT, body);
1531
1532   BSOD_RECT (bst, False, xoff-2, yoff, page_right+4, page_bottom); /* again */
1533
1534   BSOD_RECT (bst, False,
1535              xoff + col_right + (char_width/2)+2,
1536              yoff + row_bottom + 2,
1537              0,
1538              page_bottom - row_bottom - 4);
1539
1540   BSOD_PAUSE (bst, 666666);
1541   BSOD_INVERT (bst);
1542   BSOD_LOOP (bst, -3);
1543
1544   XClearWindow (dpy, window);
1545   return bst;
1546 }
1547
1548
1549 static struct bsod_state *
1550 mac1 (Display *dpy, Window window)
1551 {
1552   struct bsod_state *bst = make_bsod_state (dpy, window, "mac1", "Mac1");
1553
1554   Pixmap pixmap = 0;
1555   int pix_w = macbomb_width;
1556   int pix_h = macbomb_height;
1557   int x, y;
1558
1559   pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) macbomb_bits,
1560                                         macbomb_width, macbomb_height,
1561                                         bst->fg, bst->bg, bst->xgwa.depth);
1562
1563   x = (bst->xgwa.width - pix_w) / 2;
1564   y = (bst->xgwa.height - pix_h) / 2;
1565   if (y < 0) y = 0;
1566
1567   XClearWindow (dpy, window);
1568   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
1569
1570   return bst;
1571 }
1572
1573
1574 /* This is what kernel panics looked like on MacOS X 10.0 through 10.1.5.
1575    In later releases, it's a graphic of a power button with text in
1576    English, French, German, and Japanese overlayed transparently.
1577  */
1578 static struct bsod_state *
1579 macx_10_0 (Display *dpy, Window window)
1580 {
1581   struct bsod_state *bst = make_bsod_state (dpy, window, "macx", "MacX");
1582
1583   XClearWindow (dpy, window);
1584   XSetForeground (dpy, bst->gc,
1585                   get_pixel_resource (dpy, bst->xgwa.colormap,
1586                                       "macx.textForeground",
1587                                       "MacX.TextForeground"));
1588   XSetBackground (dpy, bst->gc,
1589                   get_pixel_resource (dpy, bst->xgwa.colormap,
1590                                       "macx.textBackground",
1591                                       "MacX.TextBackground"));
1592
1593 # ifdef DO_XPM
1594   {
1595     Pixmap pixmap = 0;
1596     Pixmap mask = 0;
1597     int x, y, pix_w, pix_h;
1598     pixmap = xpm_data_to_pixmap (dpy, window, (char **) happy_mac,
1599                                  &pix_w, &pix_h, &mask);
1600
1601     x = (bst->xgwa.width - pix_w) / 2;
1602     y = (bst->xgwa.height - pix_h) / 2;
1603     if (y < 0) y = 0;
1604     XSetClipMask (dpy, bst->gc, mask);
1605     XSetClipOrigin (dpy, bst->gc, x, y);
1606     XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
1607     XSetClipMask (dpy, bst->gc, None);
1608     XFreePixmap (dpy, pixmap);
1609   }
1610 #endif /* DO_XPM */
1611
1612   bst->left_margin = 0;
1613   bst->right_margin = 0;
1614   bst->y = bst->font->ascent;
1615   bst->macx_eol_kludge = True;
1616   bst->wrap_p = True;
1617
1618   BSOD_PAUSE (bst, 3000000);
1619   BSOD_TEXT (bst, LEFT,
1620     "panic(cpu 0): Unable to find driver for this platform: "
1621     "\"PowerMac 3,5\".\n"
1622     "\n"
1623     "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c "
1624     "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n"
1625     "\n"
1626     "\n"
1627     "\n"
1628     "No debugger configured - dumping debug information\n"
1629     "\n"
1630     "version string : Darwin Kernel Version 1.3:\n"
1631     "Thu Mar  1 06:56:40 PST 2001; root:xnu/xnu-123.5.obj~1/RELEASE_PPC\n"
1632     "\n"
1633     "\n"
1634     "\n"
1635     "\n"
1636     "DBAT0: 00000000 00000000\n"
1637     "DBAT1: 00000000 00000000\n"
1638     "DBAT2: 80001FFE 8000003A\n"
1639     "DBAT3: 90001FFE 9000003A\n"
1640     "MSR=00001030\n"
1641     "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c "
1642     "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n"
1643     "\n"
1644     "panic: We are hanging here...\n");
1645
1646   return bst;
1647 }
1648
1649
1650 # ifdef DO_XPM
1651 static struct bsod_state *
1652 macx_10_2 (Display *dpy, Window window, Bool v10_3_p)
1653 {
1654   struct bsod_state *bst = make_bsod_state (dpy, window, "macx", "MacX");
1655
1656   Pixmap pixmap = 0;
1657   int pix_w = 0, pix_h = 0;
1658   int x, y;
1659
1660   pixmap = xpm_data_to_pixmap (dpy, window, 
1661                                (char **) (v10_3_p ? osx_10_3 : osx_10_2),
1662                                &pix_w, &pix_h, 0);
1663   if (! pixmap) abort();
1664
1665 #if 0
1666   if (bst->xgwa.height > 600)   /* scale up the bitmap */
1667     {
1668       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
1669                               pixmap, pix_w, pix_h);
1670       if (! pixmap) abort();
1671       pix_w *= 2;
1672       pix_h *= 2;
1673     }
1674 #endif
1675
1676   BSOD_IMG (bst);
1677   BSOD_PAUSE (bst, 2000000);
1678
1679   bst->pixmap = pixmap;
1680
1681   x = (bst->xgwa.width - pix_w) / 2;
1682   y = ((bst->xgwa.height - pix_h) / 2);
1683   BSOD_PIXMAP (bst, 0, 0, pix_w, pix_h, x, y);
1684
1685   return bst;
1686 }
1687 # endif /* DO_XPM */
1688
1689
1690 static struct bsod_state *
1691 macx (Display *dpy, Window window)
1692 {
1693 # ifdef DO_XPM
1694   switch (random() % 3) {
1695   case 0: return macx_10_0 (dpy, window);        break;
1696   case 1: return macx_10_2 (dpy, window, False); break;
1697   case 2: return macx_10_2 (dpy, window, True);  break;
1698   default: abort();
1699   }
1700 # else  /* !DO_XPM */
1701   return macx_10_0 (dpy, window);
1702 # endif /* !DO_XPM */
1703 }
1704
1705
1706 #ifndef HAVE_COCOA /* #### I have no idea how to implement this without
1707                            real plane-masks.  I don't think it would look
1708                            right if done with alpha-transparency... */
1709 /* blit damage
1710  *
1711  * by Martin Pool <mbp@samba.org>, Feb 2000.
1712  *
1713  * This is meant to look like the preferred failure mode of NCD
1714  * Xterms.  The parameters for choosing what to copy where might not
1715  * be quite right, but it looks about ugly enough.
1716  */
1717 static struct bsod_state *
1718 blitdamage (Display *dpy, Window window)
1719 {
1720   struct bsod_state *bst = 
1721     make_bsod_state (dpy, window, "blitdamage", "BlitDamage");
1722
1723   int i;
1724   int delta_x = 0, delta_y = 0;
1725   int w, h;
1726   int chunk_h, chunk_w;
1727   int steps;
1728   long gc_mask = 0;
1729   int src_x, src_y;
1730   int x, y;
1731   
1732   w = bst->xgwa.width;
1733   h = bst->xgwa.height;
1734
1735   gc_mask = GCForeground;
1736   
1737   XSetPlaneMask (dpy, bst->gc, random());
1738
1739   steps = 50;
1740   chunk_w = w / (random() % 1 + 1);
1741   chunk_h = h / (random() % 1 + 1);
1742   if (random() & 0x1000) 
1743     delta_y = random() % 600;
1744   if (!delta_y || (random() & 0x2000))
1745     delta_x = random() % 600;
1746   src_x = 0; 
1747   src_y = 0; 
1748   x = 0;
1749   y = 0;
1750   
1751   BSOD_IMG (bst);
1752   for (i = 0; i < steps; i++) {
1753     if (x + chunk_w > w) 
1754       x -= w;
1755     else
1756       x += delta_x;
1757     
1758     if (y + chunk_h > h)
1759       y -= h;
1760     else
1761       y += delta_y;
1762     
1763     BSOD_COPY (bst, src_x, src_y, chunk_w, chunk_h, x, y);
1764     BSOD_PAUSE (bst, 1000);
1765   }
1766
1767   return bst;
1768 }
1769 #endif /* !HAVE_COCOA */
1770
1771
1772 /*
1773  * OS/2 panics, by Knut St. Osmundsen <bird-xscreensaver@anduin.net>
1774  *
1775  * All but one messages are real ones, some are from my test machines
1776  * and system dumps, others are reconstructed from google results.
1777  * Please, don't be to hard if the formatting of the earlier systems
1778  * aren't 100% correct.
1779  */
1780 static struct bsod_state *
1781 os2 (Display *dpy, Window window)
1782 {
1783   struct bsod_state *bst = make_bsod_state (dpy, window, "os2", "OS2");
1784
1785   __extension__
1786   static const char * const os2_panics[] =
1787     { /* OS/2 2.0 trap - details are bogus (CR0++). */
1788       "TRAP 0002       ERRCD=0000  ERACC=****  ERLIM=********\n"
1789       "EAX=7d240a58  EBX=ff202fdc  ECX=00064423  EDX=00003624\n"
1790       "ESI=fff3272c  EDI=7d240004  EBP=00004a44  FLG=00003202\n"
1791       "CS:EIP=0160:fff702a6  CSACC=c09d  CSLIM=ffffffff\n"
1792       "SS:ESP=0030:00004a38  SSACC=1097  SSLIM=00003fff\n"
1793       "DS=0158  DSACC=c0f3  DSLIM=ffffffff  CR0=fffffffb\n"
1794       "ES=0158  ESACC=c0f3  ESLIM=ffffffff  CR2=1a060014\n"
1795       "FS=0000  FSACC=****  FSLIM=********\n"
1796       "GS=0000  GSACC=****  GSLIM=********\n"
1797       "\n"
1798       "The system detected an internal processing error\n"
1799       "at location ##0160:fff6453f - 000d:a53f\n"
1800       "60000, 9084\n"
1801       "\n"
1802       "038600d1\n"
1803       "Internal revision 6.307, 92/03/01\n"
1804       "\n",
1805
1806       /* warp 3 (early) */
1807       "TRAP 000e       ERRCD=0000  ERACC=****  ERLIM=********\n"
1808       "EAX=ff050c20  EBX=000000bb  ECX=ffff00c1  EDx=fff379b8\n"
1809       "ESI=ffe55a3c  EDI=00000000  EBP=00004eb8  FLG=00013282\n"
1810       "CS:EIP=0160:fff8dbb8  CSACC=c09b  CSLIM=ffffffff\n"
1811       "SS:EIP=0030:00004eb4  SSACC=1097  SSLIM=00003fff\n"
1812       "DS=0158  DSACC=c0f3  DSLIM=ffffffff  CR0=8001001b\n"
1813       "ES=0158  DSACC=c0f3  DSLIM=ffffffff  CR2=000000c7\n"
1814       "FS=0000  FSACC=****  FSLIM=********\n"
1815       "GS=0000  GSACC=****  GSLIM=********\n"
1816       "\n"
1817       "The system detected an internal processing error\n"
1818       "at location ##0160:fff66bf0 - 000d:9bf0.\n"
1819       "60000, 9084\n"
1820       "\n"
1821       "048600b4\n"
1822       "Internal revision 8.125, 94/02/16\n"
1823       "\n"
1824       "The system is stopped.  Record the location number of the error\n"
1825       "and contact your service representative.\n",
1826
1827       /* warp 3 */
1828       "TRAP 000e       ERRCD=0002  ERACC=****  ERLIM=********\n"
1829       "EAX=00000000  EBX=fdef1e0c  ECX=00003824  EDX=0000edf9\n"
1830       "ESI=fdf30e80  EDI=fc8b0000  EBP=00005658  FLG=00012246\n"
1831       "CS:EIP=0160:fff8ada3  CSACC=c09b  CSLIM=ffffffff\n"
1832       "SS:ESP=0030:000055d4  SSACC=1097  SSLIM=0000480f\n"
1833       "DS=0158  DSACC=c093  DSLIM=ffffffff  CR0=8001001b\n"
1834       "ES=0158  ESACC=c093  ESLIM=ffffffff  CR2=fc8b0000\n"
1835       "FS=03b8  FSACC=0093  FSLIM=00000023\n"
1836       "GS=0000  GSACC=****  GSLIM=********\n"
1837       "\n"
1838       "The system detected an internal processing error\n"
1839       "at location ##0160:fff5c364 - 000d:a364.\n"
1840       "60000, 9084\n"
1841       "\n"
1842       "05860526\n"
1843       "Internal revision 8200,94/11/07\n"
1844       "\n"
1845       "The system is stopped. Record all of the above information and\n"
1846       "contact your service representative.\n",
1847
1848       /* warp 3 (late) */
1849       "TRAP 000d       ERRCD=2200  ERACC=1092  ERLIM=00010fff\n"
1850       "EAX=0000802e  EBX=fff001c8  ECX=9bd80000  EDX=00000000\n"
1851       "ESI=fff09bd8  EDI=fdeb001b  EBP=00000000  FLG=00012012\n"
1852       "CS:EIP=0168:fff480a2  CSACC=c09b  CSLIM=ffffffff\n"
1853       "SS:ESP=00e8:00001f32  SSACC=0093  SSLIM=00001fff\n"
1854       "DS=0940  DSACC=0093  DSLIM=00000397  CR0=8001001b\n"
1855       "ES=00e8  ESACC=0093  ESLIM=00001fff  CR2=15760008\n"
1856       "FS=0000  FSACC=****  FSLIM=****\n"
1857       "GS=0000  GSACC=****  GSLIM=****\n"
1858       "\n"
1859       "The system detected an internal processing error\n"
1860       "at location ##0168:fff4b06e - 000e:c06e\n"
1861       "60000, 9084\n"
1862       "\n"
1863       "06860652\n"
1864       "Internal revision 8.259_uni,98/01/07\n"
1865       "\n"
1866       "The system is stopped. Record all of the above information and\n"
1867       "contact your service representative.\n",
1868
1869       /* Warp 4.52+ - the official r0trap.exe from the debugging classes */
1870       "Exception in module: OS2KRNL\n"
1871       "TRAP 000e       ERRCD=0002  ERACC=****  ERLIM=********\n"
1872       "EAX=00000001  EBX=80010002  ECX=ffed4638  EDX=0003f17b\n"
1873       "ESI=00000001  EDI=00000002  EBP=00005408  FLG=00012202\n"
1874       "CS:EIP=0168:fff3cd2e  CSACC=c09b  CSLIM=ffffffff\n"
1875       "SS:ESP=0030:000053ec  SSACC=1097  SSLIM=000044ff\n"
1876       "DS=0160  DSACC=c093  DSLIM=ffffffff  CR0=8001001b\n"
1877       "ES=0160  ESACC=c093  ESLIM=ffffffff  CR2=00000001\n"
1878       "FS=0000  FSACC=****  FSLIM=********\n"
1879       "GS=0000  GSACC=****  GSLIM=********\n"
1880       "\n"
1881       "The system detected an internal processing error at\n"
1882       "location ##0168:fff1e3f3 - 000e:c3f3.\n"
1883       "60000, 9084\n"
1884       "\n"
1885       "068606a0\n"
1886       "Internal revision 14.097_UNI\n"
1887       "\n"
1888       "The system is stopped. Record all of the above information and\n"
1889       "contact your service representative.\n",
1890
1891       /* Warp 4.52+, typical JFS problem. */
1892       "Exeption in module: JFS\n"
1893       "TRAP 0003       ERRCD=0000  ERACC=****  ERLIM=********\n"
1894       "EAX=00000000  EBX=ffffff05  ECX=00000001  EDX=f5cd8010\n"
1895       "ESI=000000e6  EDI=000000e7  EBP=f9c7378e  FLG=00002296\n"
1896       "CS:EIP=0168:f8df3250  CSACC=c09b  CSLIM=ffffffff\n"
1897       "SS:ESP=1550:fdc73778  SSACC=c093  SSLIM=ffffffff\n"
1898       "DS=0160  DSACC=c093  DSLIM=ffffffff  CR0=80010016\n"
1899       "ES=0160  ESACC=c093  DSLIM=ffffffff  CR2=05318000\n"
1900       "FS=03c0  FSACC=0093  DSLIM=00000023\n"
1901       "GS=0160  GSACC=c093  DSLIM=ffffffff\n"
1902       "\n"
1903       "The system detected an internal processing error\n"
1904       "at location ##0168:fff1e2ab - 000e:c2ab.\n"
1905       "60000, 9084\n"
1906       "\n"
1907       "07860695\n"
1908       "\n"
1909       "Internal revision 14.100c_UNI\n"
1910       "\n"
1911       "The system is stopped. Record all of the above information and\n"
1912       "contact your service representative.\n"
1913     };
1914
1915   BSOD_TEXT (bst, LEFT, os2_panics[random() % countof(os2_panics)]);
1916   BSOD_CURSOR (bst, CURSOR_LINE, 240000, 999999);
1917
1918   XClearWindow (dpy, window);
1919   return bst;
1920 }
1921
1922
1923 /* SPARC Solaris panic. Should look pretty authentic on Solaris boxes.
1924  * Anton Solovyev <solovam@earthlink.net>
1925  */ 
1926 static struct bsod_state *
1927 sparc_solaris (Display *dpy, Window window)
1928 {
1929   struct bsod_state *bst = make_bsod_state (dpy, window, "solaris", "Solaris");
1930   int i;
1931
1932   bst->scroll_p = True;
1933   bst->wrap_p = True;
1934   bst->left_margin = bst->right_margin = bst->xgwa.width  * 0.07;
1935   bst->top_margin = bst->bottom_margin = bst->xgwa.height * 0.07;
1936   bst->y = bst->top_margin + bst->font->ascent;
1937
1938   BSOD_IMG (bst);
1939   BSOD_PAUSE (bst, 3000000);
1940
1941   BSOD_INVERT(bst);
1942   BSOD_RECT (bst, True, 
1943              bst->left_margin, bst->top_margin,
1944              bst->xgwa.width - bst->left_margin - bst->right_margin,
1945              bst->xgwa.height - bst->top_margin - bst->bottom_margin);
1946   BSOD_INVERT(bst);
1947
1948   BSOD_TEXT (bst, LEFT,
1949     "BAD TRAP: cpu=0 type=0x31 rp=0x2a10043b5e0 addr=0xf3880 mmu_fsr=0x0\n"
1950     "BAD TRAP occurred in module \"unix\" due to an illegal access to a"
1951     " user address.\n"
1952     "adb: trap type = 0x31\n"
1953     "addr=0xf3880\n"
1954     "pid=307, pc=0x100306e4, sp=0x2a10043ae81, tstate=0x4480001602,"
1955     " context=0x87f\n"
1956     "g1-g7: 1045b000, 32f, 10079440, 180, 300000ebde8, 0, 30000953a20\n"
1957     "Begin traceback... sp = 2a10043ae81\n"
1958     "Called from 100bd060, fp=2a10043af31, args=f3700 300008cc988 f3880 0"
1959     " 1 300000ebde0.\n"
1960     "Called from 101fe1bc, fp=2a10043b011, args=3000045a240 104465a0"
1961     " 300008e47d0 300008e48fa 300008ae350 300008ae410\n"
1962     "Called from 1007c520, fp=2a10043b0c1, args=300008e4878 300003596e8 0"
1963     " 3000045a320 0 3000045a220\n"
1964     "Called from 1007c498, fp=2a10043b171, args=1045a000 300007847f0 20"
1965     " 3000045a240 1 0\n"
1966     "Called from 1007972c, fp=2a10043b221, args=1 300009517c0 30000951e58 1"
1967     " 300007847f0 0\n"
1968     "Called from 10031e10, fp=2a10043b2d1, args=3000095b0c8 0 300009396a8"
1969     " 30000953a20 0 1\n"
1970     "Called from 10000bdd8, fp=ffffffff7ffff1c1, args=0 57 100131480"
1971     " 100131480 10012a6e0 0\n"
1972     "End traceback...\n"
1973     "panic[cpu0]/thread=30000953a20: trap\n"
1974     "syncing file systems...");
1975
1976   BSOD_PAUSE (bst, 3000000);
1977
1978   BSOD_TEXT (bst, LEFT, " 1 done\n");
1979   BSOD_TEXT (bst, LEFT, "dumping to /dev/dsk/c0t0d0s3, offset 26935296\n");
1980   BSOD_PAUSE (bst, 2000000);
1981
1982
1983   for (i = 1; i <= 100; ++i)
1984     {
1985       char buf[100];
1986       sprintf (buf, "\b\b\b\b\b\b\b\b\b\b\b%3d%% done", i);
1987       BSOD_TEXT (bst, LEFT, buf);
1988       BSOD_PAUSE (bst, 100000);
1989     }
1990
1991   BSOD_TEXT (bst, LEFT,
1992     ": 2803 pages dumped, compression ratio 2.88, dump succeeded\n");
1993   BSOD_PAUSE (bst, 2000000);
1994
1995   BSOD_TEXT (bst, LEFT,
1996     "rebooting...\n"
1997     "Resetting ...");
1998
1999   return bst;
2000 }
2001
2002
2003 /* Linux panic and fsck, by jwz
2004  */
2005 static struct bsod_state *
2006 linux_fsck (Display *dpy, Window window)
2007 {
2008   struct bsod_state *bst = make_bsod_state (dpy, window, "linux", "Linux");
2009
2010   int i;
2011   const char *sysname;
2012   char buf[1024];
2013
2014   const char *linux_panic[] = {
2015    " kernel: Unable to handle kernel paging request at virtual "
2016      "address 0000f0ad\n",
2017    " kernel:  printing eip:\n",
2018    " kernel: c01becd7\n",
2019    " kernel: *pde = 00000000\n",
2020    " kernel: Oops: 0000\n",
2021    " kernel: CPU:    0\n",
2022    " kernel: EIP:    0010:[<c01becd7>]    Tainted: P \n",
2023    " kernel: EFLAGS: 00010286\n",
2024    " kernel: eax: 0000ff00   ebx: ca6b7e00   ecx: ce1d7a60   edx: ce1d7a60\n",
2025    " kernel: esi: ca6b7ebc   edi: 00030000   ebp: d3655ca0   esp: ca6b7e5c\n",
2026    " kernel: ds: 0018   es: 0018   ss: 0018\n",
2027    " kernel: Process crond (pid: 1189, stackpage=ca6b7000)\n",
2028    " kernel: Stack: d3655ca0 ca6b7ebc 00030054 ca6b7e7c c01c1e5b "
2029        "00000287 00000020 c01c1fbf \n",
2030    "",
2031    " kernel:        00005a36 000000dc 000001f4 00000000 00000000 "
2032        "ce046d40 00000001 00000000 \n",
2033    "", "", "",
2034    " kernel:        ffffffff d3655ca0 d3655b80 00030054 c01bef93 "
2035        "d3655ca0 ca6b7ebc 00030054 \n",
2036    "", "", "",
2037    " kernel: Call Trace:    [<c01c1e5b>] [<c01c1fbf>] [<c01bef93>] "
2038        "[<c01bf02b>] [<c0134c4f>]\n",
2039    "", "", "",
2040    " kernel:   [<c0142562>] [<c0114f8c>] [<c0134de3>] [<c010891b>]\n",
2041    " kernel: \n",
2042    " kernel: Code: 2a 00 75 08 8b 44 24 2c 85 c0 74 0c 8b 44 24 58 83 48 18 "
2043       "08 \n",
2044    0
2045   };
2046
2047   bst->scroll_p = True;
2048   bst->wrap_p = True;
2049   bst->left_margin = bst->right_margin = 10;
2050   bst->top_margin = bst->bottom_margin = 10;
2051
2052   sysname = "linux";
2053 # ifdef HAVE_UNAME
2054   {
2055     struct utsname uts;
2056     char *s;
2057     if (uname (&uts) >= 0)
2058       sysname = uts.nodename;
2059     s = strchr (sysname, '.');
2060     if (s) *s = 0;
2061   }
2062 # endif /* !HAVE_UNAME */
2063
2064
2065   BSOD_TEXT (bst, LEFT, "waiting for X server to shut down ");
2066   BSOD_PAUSE (bst, 100000);
2067   BSOD_TEXT (bst, LEFT,
2068              "XIO:  fatal IO error 2 (broken pipe) on X server \":0.0\"\n"
2069              "        after 339471 requests (339471 known processed) "
2070              "with 0 events remaining\n");
2071   BSOD_CHAR_DELAY (bst, 300000);
2072   BSOD_TEXT (bst, LEFT, ".........\n");
2073   BSOD_CHAR_DELAY (bst, 0);
2074   BSOD_TEXT (bst, LEFT, 
2075              "xinit:  X server slow to shut down, sending KILL signal.\n"
2076              "waiting for server to die ");
2077   BSOD_CHAR_DELAY (bst, 300000);
2078   BSOD_TEXT (bst, LEFT, "...\n");
2079   BSOD_CHAR_DELAY (bst, 0);
2080   BSOD_TEXT (bst, LEFT, "xinit:  Can't kill server\n");
2081   BSOD_PAUSE (bst, 2000000);
2082
2083   sprintf (buf, "\n%s Login: ", sysname);
2084   BSOD_TEXT (bst, LEFT, buf);
2085   BSOD_PAUSE (bst, 1000000);
2086   BSOD_TEXT (bst, LEFT,
2087     "\n\n"
2088     "Parallelizing fsck version 1.22 (22-Jun-2001)\n"
2089     "e2fsck 1.22, 22-Jun-2001 for EXT2 FS 0.5b, 95/08/09\n"
2090     "Warning!  /dev/hda1 is mounted.\n"
2091     "/dev/hda1 contains a file system with errors, check forced.\n");
2092   BSOD_PAUSE (bst, 1000000);
2093
2094   if (0 == random() % 2)
2095     BSOD_TEXT (bst, LEFT,
2096      "Couldn't find ext2 superblock, trying backup blocks...\n"
2097      "The filesystem size (according to the superblock) is 3644739 blocks\n"
2098      "The physical size of the device is 3636706 blocks\n"
2099      "Either the superblock or the partition table is likely to be corrupt!\n"
2100      "Abort<y>? no\n");
2101   BSOD_PAUSE (bst, 1000000);
2102
2103  AGAIN:
2104
2105   BSOD_TEXT (bst, LEFT, "Pass 1: Checking inodes, blocks, and sizes\n");
2106   BSOD_PAUSE (bst, 2000000);
2107
2108   i = (random() % 60) - 20;
2109   while (--i > 0)
2110     {
2111       int b = random() % 0xFFFF;
2112       sprintf (buf, "Deleted inode %d has zero dtime.  Fix<y>? yes\n\n", b);
2113       BSOD_TEXT (bst, LEFT, buf);
2114       BSOD_PAUSE (bst, 1000);
2115     }
2116
2117   i = (random() % 40) - 10;
2118   if (i > 0)
2119     {
2120       int g = random() % 0xFFFF;
2121       int b = random() % 0xFFFFFFF;
2122
2123       BSOD_PAUSE (bst, 1000000);
2124
2125       sprintf (buf, "Warning: Group %d's copy of the group descriptors "
2126                "has a bad block (%d).\n", g, b);
2127       BSOD_TEXT (bst, LEFT, buf);
2128
2129       b = random() % 0x3FFFFF;
2130       while (--i > 0)
2131         {
2132           b += random() % 0xFFFF;
2133           sprintf (buf,
2134                    "Error reading block %d (Attempt to read block "
2135                    "from filesystem resulted in short read) while doing "
2136                    "inode scan.  Ignore error<y>?",
2137                    b);
2138           BSOD_TEXT (bst, LEFT, buf);
2139           BSOD_PAUSE (bst, 10000);
2140           BSOD_TEXT (bst, LEFT, " yes\n\n");
2141         }
2142     }
2143
2144   if (0 == (random() % 10))
2145     {
2146       BSOD_PAUSE (bst, 1000000);
2147
2148       i = 3 + (random() % 10);
2149       while (--i > 0)
2150         {
2151           BSOD_TEXT (bst, LEFT,
2152                      "Could not allocate 256 block(s) for inode table: "
2153                      "No space left on device\n");
2154           BSOD_PAUSE (bst, 1000);
2155         }
2156       BSOD_TEXT (bst, LEFT, "Restarting e2fsck from the beginning...\n");
2157       BSOD_PAUSE (bst, 2000000);
2158
2159       goto AGAIN;
2160     }
2161
2162   i = (random() % 20) - 5;
2163
2164   if (i > 0)
2165     BSOD_PAUSE (bst, 1000000);
2166
2167   while (--i > 0)
2168     {
2169       int j = 5 + (random() % 10);
2170       int w = random() % 4;
2171
2172       while (--j > 0)
2173         {
2174           int b = random() % 0xFFFFF;
2175           int g = random() % 0xFFF;
2176
2177           if (0 == (random() % 10))
2178             b = 0;
2179           else if (0 == (random() % 10))
2180             b = -1;
2181
2182           if (w == 0)
2183             sprintf (buf,
2184                      "Inode table for group %d not in group.  (block %d)\n"
2185                      "WARNING: SEVERE DATA LOSS POSSIBLE.\n"
2186                      "Relocate<y>?",
2187                      g, b);
2188           else if (w == 1)
2189             sprintf (buf,
2190                      "Block bitmap for group %d not in group.  (block %d)\n"
2191                      "Relocate<y>?",
2192                      g, b);
2193           else if (w == 2)
2194             sprintf (buf,
2195                      "Inode bitmap %d for group %d not in group.\n"
2196                      "Continue<y>?",
2197                      b, g);
2198           else /* if (w == 3) */
2199             sprintf (buf,
2200                      "Bad block %d in group %d's inode table.\n"
2201                      "WARNING: SEVERE DATA LOSS POSSIBLE.\n"
2202                      "Relocate<y>?",
2203                      b, g);
2204
2205           BSOD_TEXT (bst, LEFT, buf);
2206           BSOD_TEXT (bst, LEFT, " yes\n\n");
2207           BSOD_PAUSE (bst, 1000);
2208         }
2209     }
2210
2211
2212   if (0 == random() % 10) goto PANIC;
2213   BSOD_TEXT (bst, LEFT, "Pass 2: Checking directory structure\n");
2214   BSOD_PAUSE (bst, 2000000);
2215
2216   i = (random() % 20) - 5;
2217   while (--i > 0)
2218     {
2219       int n = random() % 0xFFFFF;
2220       int o = random() % 0xFFF;
2221       sprintf (buf, "Directory inode %d, block 0, offset %d: "
2222                "directory corrupted\n"
2223                "Salvage<y>? ",
2224                n, o);
2225       BSOD_TEXT (bst, LEFT, buf);
2226       BSOD_PAUSE (bst, 1000);
2227       BSOD_TEXT (bst, LEFT, " yes\n\n");
2228
2229       if (0 == (random() % 100))
2230         {
2231           sprintf (buf, "Missing '.' in directory inode %d.\nFix<y>?", n);
2232           BSOD_TEXT (bst, LEFT, buf);
2233           BSOD_PAUSE (bst, 1000);
2234           BSOD_TEXT (bst, LEFT, " yes\n\n");
2235         }
2236     }
2237
2238   if (0 == random() % 10)
2239     goto PANIC;
2240
2241   BSOD_TEXT (bst, LEFT, 
2242              "Pass 3: Checking directory connectivity\n"
2243              "/lost+found not found.  Create? yes\n");
2244   BSOD_PAUSE (bst, 2000000);
2245
2246   /* Unconnected directory inode 4949 (/var/spool/squid/06/???)
2247      Connect to /lost+found<y>? yes
2248
2249      '..' in /var/spool/squid/06/08 (20351) is <The NULL inode> (0), should be 
2250      /var/spool/squid/06 (20350).
2251      Fix<y>? yes
2252
2253      Unconnected directory inode 128337 (/var/spool/squid/06/???)
2254      Connect to /lost+found<y>? yes
2255    */
2256
2257
2258   if (0 == random() % 10) goto PANIC;
2259   BSOD_TEXT (bst, LEFT,  "Pass 4: Checking reference counts\n");
2260   BSOD_PAUSE (bst, 2000000);
2261
2262   /* Inode 2 ref count is 19, should be 20.  Fix<y>? yes
2263
2264      Inode 4949 ref count is 3, should be 2.  Fix<y>? yes
2265
2266         ...
2267
2268      Inode 128336 ref count is 3, should be 2.  Fix<y>? yes
2269
2270      Inode 128337 ref count is 3, should be 2.  Fix<y>? yes
2271
2272    */
2273
2274
2275   if (0 == random() % 10) goto PANIC;
2276   BSOD_TEXT (bst, LEFT,  "Pass 5: Checking group summary information\n");
2277   BSOD_PAUSE (bst, 2000000);
2278
2279   i = (random() % 200) - 50;
2280   if (i > 0)
2281     {
2282       BSOD_TEXT (bst, LEFT,  "Block bitmap differences: ");
2283       while (--i > 0)
2284         {
2285           sprintf (buf, " %d", -(random() % 0xFFF));
2286           BSOD_TEXT (bst, LEFT, buf);
2287           BSOD_PAUSE (bst, 1000);
2288         }
2289       BSOD_TEXT (bst, LEFT, "\nFix? yes\n\n");
2290     }
2291
2292
2293   i = (random() % 100) - 50;
2294   if (i > 0)
2295     {
2296       BSOD_TEXT (bst, LEFT,  "Inode bitmap differences: ");
2297       while (--i > 0)
2298         {
2299           sprintf (buf, " %d", -(random() % 0xFFF));
2300           BSOD_TEXT (bst, LEFT, buf);
2301           BSOD_PAUSE (bst, 1000);
2302         }
2303       BSOD_TEXT (bst, LEFT,  "\nFix? yes\n\n");
2304     }
2305
2306   i = (random() % 20) - 5;
2307   while (--i > 0)
2308     {
2309       int g = random() % 0xFFFF;
2310       int c = random() % 0xFFFF;
2311       sprintf (buf,
2312                "Free blocks count wrong for group #0 (%d, counted=%d).\nFix? ",
2313                g, c);
2314       BSOD_TEXT (bst, LEFT, buf);
2315       BSOD_PAUSE (bst, 1000);
2316       BSOD_TEXT (bst, LEFT,  " yes\n\n");
2317     }
2318
2319  PANIC:
2320
2321   i = 0;
2322   BSOD_TEXT (bst, LEFT,  "\n\n");
2323   while (linux_panic[i])
2324     {
2325       time_t t = time ((time_t *) 0);
2326       struct tm *tm = localtime (&t);
2327       char prefix[100];
2328
2329       if (*linux_panic[i])
2330         {
2331           strftime (prefix, sizeof(prefix)-1, "%b %d %H:%M:%S ", tm);
2332           BSOD_TEXT (bst, LEFT,  prefix);
2333           BSOD_TEXT (bst, LEFT,  sysname);
2334           BSOD_TEXT (bst, LEFT,  linux_panic[i]);
2335           BSOD_PAUSE (bst, 1000);
2336         }
2337       else
2338         BSOD_PAUSE (bst, 300000);
2339
2340       i++;
2341     }
2342   BSOD_PAUSE (bst, 4000000);
2343
2344   XClearWindow(dpy, window);
2345   return bst;
2346 }
2347
2348
2349 /*
2350  * Linux (hppa) panic, by Stuart Brady <sdbrady@ntlworld.com>
2351  * Output courtesy of M. Grabert
2352  */
2353 static struct bsod_state *
2354 hppa_linux (Display *dpy, Window window)
2355 {
2356   struct bsod_state *bst = 
2357     make_bsod_state (dpy, window, "hppalinux", "HPPALinux");
2358
2359   int i = 0;
2360   const char *release, *sysname, *gccversion, *version;
2361   long int linedelay = 0;
2362
2363   __extension__
2364   struct { long int delay; const char *string; } linux_panic[] =
2365     {{ 0, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
2366           "\n\n\n\n\n\n\n\n\n\n\n\n\n" },
2367      { 0, "Linux version %s (root@%s) (gcc version %s) %s\n" },
2368      { 4000, "FP[0] enabled: Rev 1 Model 16\n" },
2369      { 10, "The 32-bit Kernel has started...\n" },
2370      { -1, "Determining PDC firmware type: System Map.\n" },
2371      { -1, "model 00005bb0 00000481 00000000 00000002 7778df9f 100000f0 "
2372            "00000008 000000b2 000000b2\n" },
2373      { -1, "vers  00000203\n" },
2374      { -1, "CPUID vers 17 rev 7 (0x00000227)\n" },
2375      { -1, "capabilities 0x3\n" },
2376      { -1, "model 9000/785/C3000\n" },
2377      { -1, "Total Memory: 1024 Mb\n" },
2378      { -1, "On node 0 totalpages: 262144\n" },
2379      { -1, "  DMA zone: 262144 pages, LIFO batch:16\n" },
2380      { -1, "  Normal zone: 0 pages, LIFO batch:1\n" },
2381      { -1, "  HighMem zone: 0 pages, LIFO batch:1\n" },
2382      { -1, "LCD display at f05d0008,f05d0000 registered\n" },
2383      { -1, "Building zonelist for node : 0\n" },
2384      { -1, "Kernel command line: ide=nodma root=/dev/sda3 HOME=/ ip=off "
2385            "console=ttyS0 TERM=vt102 palo_kernel=2/vmlinux-2.6\n" },
2386      { -1, "ide_setup: ide=nodmaIDE: Prevented DMA\n" },
2387      { -1, "PID hash table entries: 16 (order 4: 128 bytes)\n" },
2388      {500, "Console: colour dummy device 160x64\n" },
2389      { 10, "Memory: 1034036k available\n" },
2390      { -1, "Calibrating delay loop... 796.67 BogoMIPS\n" },
2391      { -1, "Dentry cache hash table entries: 131072 (order: 7, 524288 "
2392            "bytes)\n" },
2393      { -1, "Inode-cache hash table entries: 65536 (order: 6, 262144 "
2394            "bytes)\n" },
2395      { -1, "Mount-cache hash table entries: 512 (order: 0, 4096 bytes)\n" },
2396      { -1, "POSIX conformance testing by UNIFIX\n" },
2397      { -1, "NET: Registered protocol family 16\n" },
2398      { 100, "Searching for devices...\n" },
2399      { 25, "Found devices:\n" },
2400      { 10, "1. Astro BC Runway Port at 0xfed00000 [10] "
2401            "{ 12, 0x0, 0x582, 0x0000b }\n" },
2402      { -1, "2. Elroy PCI Bridge at 0xfed30000 [10/0] "
2403            "{ 13, 0x0, 0x782, 0x0000a }\n" },
2404      { -1, "3. Elroy PCI Bridge at 0xfed32000 [10/1] "
2405            "{ 13, 0x0, 0x782, 0x0000a }\n" },
2406      { -1, "4. Elroy PCI Bridge at 0xfed38000 [10/4] "
2407            "{ 13, 0x0, 0x782, 0x0000a }\n" },
2408      { -1, "5. Elroy PCI Bridge at 0xfed3c000 [10/6] "
2409            "{ 13, 0x0, 0x782, 0x0000a }\n" },
2410      { -1, "6. AllegroHigh W at 0xfffa0000 [32] "
2411            "{ 0, 0x0, 0x5bb, 0x00004 }\n" },
2412      { -1, "7. Memory at 0xfed10200 [49] { 1, 0x0, 0x086, 0x00009 }\n" },
2413      { -1, "CPU(s): 1 x PA8500 (PCX-W) at 400.000000 MHz\n" },
2414      { -1, "SBA found Astro 2.1 at 0xfed00000\n" },
2415      { -1, "lba version TR2.1 (0x2) found at 0xfed30000\n" },
2416      { -1, "lba version TR2.1 (0x2) found at 0xfed32000\n" },
2417      { -1, "lba version TR2.1 (0x2) found at 0xfed38000\n" },
2418      { -1, "lba version TR2.1 (0x2) found at 0xfed3c000\n" },
2419      { 100, "SCSI subsystem initialized\n" },
2420      { 10, "drivers/usb/core/usb.c: registered new driver usbfs\n" },
2421      { -1, "drivers/usb/core/usb.c: registered new driver hub\n" },
2422      { -1, "ikconfig 0.7 with /proc/config*\n" },
2423      { -1, "Initializing Cryptographic API\n" },
2424      { 250, "SuperIO: probe of 0000:00:0e.0 failed with error -1\n" },
2425      { 20, "SuperIO: Found NS87560 Legacy I/O device at 0000:00:0e.1 "
2426            "(IRQ 64)\n" },
2427      { -1, "SuperIO: Serial port 1 at 0x3f8\n" },
2428      { -1, "SuperIO: Serial port 2 at 0x2f8\n" },
2429      { -1, "SuperIO: Parallel port at 0x378\n" },
2430      { -1, "SuperIO: Floppy controller at 0x3f0\n" },
2431      { -1, "SuperIO: ACPI at 0x7e0\n" },
2432      { -1, "SuperIO: USB regulator enabled\n" },
2433      { -1, "SuperIO: probe of 0000:00:0e.2 failed with error -1\n" },
2434      { -1, "Soft power switch enabled, polling @ 0xf0400804.\n" },
2435      { -1, "pty: 256 Unix98 ptys configured\n" },
2436      { -1, "Generic RTC Driver v1.07\n" },
2437      { -1, "Serial: 8250/16550 driver $Revision: 1.94 $ 13 ports, "
2438            "IRQ sharing disabled\n" },
2439      { -1, "ttyS0 at I/O 0x3f8 (irq = 0) is a 16550A\n" },
2440      { -1, "ttyS1 at I/O 0x2f8 (irq = 0) is a 16550A\n" },
2441      { -1, "Linux Tulip driver version 1.1.13 (May 11, 2002)\n" },
2442      { 150, "tulip0: no phy info, aborting mtable build\n" },
2443      { 10, "tulip0:  MII transceiver #1 config 1000 status 782d "
2444            "advertising 01e1.\n" },
2445      { -1, "eth0: Digital DS21143 Tulip rev 65 at 0xf4008000, "
2446            "00:10:83:F9:B4:34, IRQ 66.\n" },
2447      { -1, "Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2\n" },
2448      { -1, "ide: Assuming 33MHz system bus speed for PIO modes; "
2449            "override with idebus=xx\n" },
2450      { 100, "SiI680: IDE controller at PCI slot 0000:01:06.0\n" },
2451      { 10, "SiI680: chipset revision 2\n" },
2452      { -1, "SiI680: BASE CLOCK == 133\n" },
2453      { -1, "SiI680: 100% native mode on irq 128\n" },
2454      { -1, "    ide0: MMIO-DMA at 0xf4800000-0xf4800007 -- "
2455            "Error, MMIO ports already in use.\n" },
2456      { -1, "    ide1: MMIO-DMA at 0xf4800008-0xf480000f -- "
2457            "Error, MMIO ports already in use.\n" },
2458      { 5, "hda: TS130220A2, ATA DISK drive\n" },
2459      { -1, "      _______________________________\n" },
2460      { -1, "     < Your System ate a SPARC! Gah! >\n" },
2461      { -1, "      -------------------------------\n" },
2462      { -1, "             \\   ^__^\n" },
2463      { -1, "              \\  (xx)\\_______\n" },
2464      { -1, "                 (__)\\       )\\/\\\n" },
2465      { -1, "                  U  ||----w |\n" },
2466      { -1, "                     ||     ||\n" },
2467      { -1, "swapper (pid 1): Breakpoint (code 0)\n" },
2468      { -1, "\n" },
2469      { -1, "     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n" },
2470      { -1, "PSW: 00000000000001001111111100001111 Not tainted\n" },
2471      { -1, "r00-03  4d6f6f21 1032f010 10208f34 103fc2e0\n" },
2472      { -1, "r04-07  103fc230 00000001 00000001 0000000f\n" },
2473      { -1, "r08-11  103454f8 000f41fa 372d3980 103ee404\n" },
2474      { -1, "r12-15  3ccbf700 10344810 103ee010 f0400004\n" },
2475      { -1, "r16-19  f00008c4 f000017c f0000174 00000000\n" },
2476      { -1, "r20-23  fed32840 fed32800 00000000 0000000a\n" },
2477      { -1, "r24-27  0000ffa0 000000ff 103fc2e0 10326010\n" },
2478      { -1, "r28-31  00000000 00061a80 4ff98340 10208f34\n" },
2479      { -1, "sr0-3   00000000 00000000 00000000 00000000\n" },
2480      { -1, "sr4-7   00000000 00000000 00000000 00000000\n" },
2481      { -1, "\n" },
2482      { -1, "IASQ: 00000000 00000000 IAOQ: 00000000 00000004\n" },
2483      { -1, " IIR: 00000000    ISR: 00000000  IOR: 00000000\n" },
2484      { -1, " CPU:        0   CR30: 4ff98000 CR31: 1037c000\n" },
2485      { -1, " ORIG_R28: 55555555\n" },
2486      { -1, " IAOQ[0]: 0x0\n" },
2487      { -1, " IAOQ[1]: 0x4\n" },
2488      { -1, " RP(r2): probe_hwif+0x218/0x44c\n" },
2489      { -1, "Kernel panic: Attempted to kill init!\n" },
2490      { 0, NULL }};
2491
2492   bst->scroll_p = True;
2493   bst->wrap_p = True;
2494   bst->left_margin = bst->right_margin = 10;
2495   bst->top_margin = bst->bottom_margin = 10;
2496
2497   release = "2.6.0-test11-pa2";
2498   sysname = "hppa";
2499   version = "#2 Mon Dec 8 06:09:27 GMT 2003";
2500 # ifdef HAVE_UNAME
2501   {
2502     struct utsname uts;
2503     char *s;
2504     if (uname (&uts) >= 0)
2505       {
2506         sysname = uts.nodename;
2507         if (!strcmp (uts.sysname, "Linux"))
2508           {
2509             release = uts.release;
2510             version = uts.version;
2511           }
2512       }
2513     s = strchr (sysname, '.');
2514     if (s) *s = 0;
2515   }
2516 # endif /* !HAVE_UNAME */
2517
2518 # if (defined (__GNUC__) && defined (__VERSION__))
2519   gccversion = __VERSION__;
2520 # else /* !(defined (__GNUC__) && defined (__VERSION__)) */
2521   gccversion = "3.3.2 (Debian)";
2522 # endif /* !(defined (__GNUC__) && defined (__VERSION__)) */
2523
2524   /* Insert current host name into banner on line 2 */
2525   {
2526     char ss[1024];
2527     snprintf (ss, 1024, linux_panic[1].string, 
2528               release, sysname, gccversion, version);
2529     linux_panic[1].string = ss;
2530   }
2531
2532   BSOD_PAUSE (bst, 100000);
2533   while (linux_panic[i].string)
2534     {
2535       if (linux_panic[i].delay != -1)
2536         linedelay = linux_panic[i].delay * 1000;
2537       BSOD_PAUSE (bst, linedelay);
2538       BSOD_TEXT (bst, LEFT, linux_panic[i].string);
2539       i++;
2540     }
2541
2542   bst->y = bst->xgwa.height - bst->font->ascent - bst->font->descent;
2543
2544   XClearWindow(dpy, window);
2545   return bst;
2546 }
2547
2548
2549 /* VMS by jwz (text sent by Roland Barmettler <roli@barmettler.net>)
2550  */
2551 static struct bsod_state *
2552 vms (Display *dpy, Window window)
2553 {
2554   struct bsod_state *bst = make_bsod_state (dpy, window, "vms", "VMS");
2555
2556   const char *sysname;
2557   int char_delay = 0;
2558   int dot_delay = 40000;
2559   int chunk_delay = 500000;
2560   char *s, *s1;
2561   int i;
2562   int arg_count;
2563
2564   __extension__
2565
2566   const char *lines[] = {
2567     "%CNXMAN,  Lost connection to system #\n"
2568     "%SHADOW-I-VOLPROC, DSA0: shadow master has changed.  "
2569     "Dump file WILL be written if system crashes.\n"
2570     "\n",
2571     "",
2572
2573     "%CNXMAN,  Quorum lost, blocking activity\n"
2574     "%CNXMAN,  Timed-out lost connection to system #\n"
2575     "%CNXMAN,  Timed-out lost connection to system #\n"
2576     "%CNXMAN,  Timed-out lost connection to system #\n"
2577     "%CNXMAN,  Proposing reconfiguration of the VMScluster\n",
2578     "",
2579
2580     "%CNXMAN,  Removed from VMScluster system #\n"
2581     "%CNXMAN,  Removed from VMScluster system #\n"
2582     "%CNXMAN,  Removed from VMScluster system #\n"
2583     "%CNXMAN,  Completing VMScluster state transition\n",
2584
2585     "\n"
2586     "**** OpenVMS (TM) Alpha Operating system V7.3-1   - BUGCHECK ****\n"
2587     "\n"
2588     "** Bugcheck code = 000005DC: CLUEXIT, Node voluntarily exiting "
2589     "VMScluster\n"
2590     "** Crash CPU: 00    Primary CPU: 00    Active CPUs: 00000001\n"
2591     "** Current Process = NULL\n"
2592     "** Current PSB ID = 00000001\n"
2593     "** Image Name =\n"
2594     "\n"
2595     "** Dumping error log buffers to HBVS unit 0\n"
2596     "**** Unable to dump error log buffers to remaining shadow set members\n"
2597     "** Error log buffers not dumped to HBVS unit 200\n"
2598     "\n"
2599     "** Dumping memory to HBVS unit 0\n"
2600     "**** Starting compressed selective memory dump at #...\n",
2601
2602     "...",
2603
2604     "\n"
2605     "**** Memory dump complete - not all processes or global pages saved\n",
2606
2607     "\n"
2608     "halted CPU 0\n",
2609     "",
2610
2611     "\n"
2612     "halt code = 5\n"
2613     "HALT instruction executed\n"
2614     "PC = ffffffff800c3884\n",
2615
2616     "\n"
2617     "CPU 0 booting\n",
2618
2619     "\n"
2620     "resetting all I/O buses\n"
2621     "\n"
2622     "\n"
2623     };
2624   char *args[8];
2625   int ids[3];
2626
2627   bst->scroll_p = True;
2628   bst->wrap_p = True;
2629   bst->left_margin = bst->right_margin = 10;
2630   bst->top_margin = bst->bottom_margin = 10;
2631
2632   sysname = "VMS001";
2633 # ifdef HAVE_UNAME
2634   {
2635     struct utsname uts;
2636     if (uname (&uts) >= 0)
2637       sysname = uts.nodename;
2638     s = strchr (sysname, '.');
2639     if (s) *s = 0;
2640   }
2641 # endif /* !HAVE_UNAME */
2642
2643   args[0] = malloc (strlen(sysname) + 7);
2644   strcpy (args[0], sysname);
2645   args[0][5] = 0;
2646
2647   /* Pick three numbers, 1-9, no overlaps. */
2648   ids[0] = 1 + (random() % 9);
2649   do { ids[1] = 1 + (random() % 9); } while (ids[1]==ids[0]);
2650   do { ids[2] = 1 + (random() % 9); } while (ids[2]==ids[0] || ids[2]==ids[1]);
2651
2652   i = strlen(args[0])-1;
2653   if (i < 6) i++;
2654   args[0][i] = '0' + ids[0];
2655   args[0][i+1] = 0;
2656
2657   for (s = args[0]; *s; s++)
2658     if (isalpha(*s)) *s = toupper (*s);
2659
2660   args[1] = strdup (args[0]);
2661   args[2] = strdup (args[0]); args[2][i] = '0' + ids[1];
2662   args[3] = strdup (args[0]); args[3][i] = '0' + ids[2];
2663
2664   args[4] = strdup (args[1]);
2665   args[5] = strdup (args[2]);
2666   args[6] = strdup (args[3]);
2667
2668   {
2669     time_t t = time ((time_t *) 0);
2670     struct tm *tm = localtime (&t);
2671     args[7] = malloc (30);
2672     strftime (args[7], 29, "%d-%b-%Y %H:%M", tm);
2673     for (s = args[7]; *s; s++)
2674       if (isalpha(*s)) *s = toupper (*s);
2675   }
2676
2677   arg_count = 0;
2678   for (i = 0; i < countof(lines); i++)
2679     {
2680       const char *fmt = lines[i];
2681       if (! strcmp (fmt, "..."))
2682         {
2683           int steps = 180 + (random() % 60);
2684           while (--steps >= 0)
2685             {
2686               BSOD_TEXT (bst, LEFT, ".");
2687               BSOD_PAUSE (bst, dot_delay);
2688             }
2689         }
2690       else
2691         {
2692           char *fmt2 = malloc (strlen (fmt) * 2 + 1);
2693           for (s = (char *) fmt, s1 = fmt2; *s; s++)
2694             {
2695               if (*s == '#')
2696                 {
2697                   strcpy (s1, args[arg_count++]);
2698                   s1 += strlen(s1);
2699                 }
2700               else
2701                 *s1++ = *s;
2702             }
2703           *s1 = 0;
2704           BSOD_CHAR_DELAY (bst, char_delay);
2705           BSOD_TEXT (bst, LEFT, fmt2);
2706           free (fmt2);
2707           BSOD_CHAR_DELAY (bst, 0);
2708           BSOD_PAUSE (bst, chunk_delay);
2709         }
2710     }
2711
2712   for (i = 0; i < countof (args); i++)
2713     free (args[i]);
2714
2715   XClearWindow(dpy, window);
2716   return bst;
2717 }
2718
2719
2720 /* HVX (formerly GCOS6) and TPS6 crash
2721    by Brian Garratt <brian-m.garratt@bull.co.uk>
2722
2723    GCOS6 is a Unix-like operating system developed by Honeywell in the
2724    1970s in collaboration with MIT and AT&T (who called their version
2725    UNIX).  Both are very much like MULTICS which Honeywell got from GE.
2726
2727    HVX ("High-performance Virtual System on Unix") is an AIX application
2728    which emulates GCOS6 hardware on RS6000-like machines.
2729  */
2730 static struct bsod_state *
2731 hvx (Display *dpy, Window window)
2732 {
2733   struct bsod_state *bst = make_bsod_state (dpy, window, "hvx", "HVX");
2734
2735   bst->scroll_p = True;
2736   bst->wrap_p = True;
2737   bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent;
2738
2739   BSOD_CHAR_DELAY (bst, 10000);
2740   BSOD_TEXT (bst, LEFT,
2741      "(TP) Trap no E   Effective address 00000000   Instruction D7DE\n"
2742      "(TP)  Registers :\n"
2743      "(TP)  B1 -> B7  03801B02  00000000  03880D45  038BABDB  0388AFFD"
2744      "  0389B3F8  03972317\n"
2745      "(TP)  R1 -> R7  0001  0007  F10F  090F  0020  0106  0272\n"
2746      "(TP)  P I Z M1  0388A18B  3232  0000 FF00\n"
2747      "(TP) Program counter is at offset 0028 from string YTPAD\n"
2748      "(TP) User id of task which trapped is LT 626\n"
2749      "(TP)?\n"
2750      );
2751   BSOD_PAUSE (bst, 1000000);
2752
2753   BSOD_CHAR_DELAY (bst, 100000);
2754   BSOD_TEXT (bst, LEFT, " TP CLOSE ALL");
2755
2756   BSOD_CHAR_DELAY (bst, 10000);
2757   BSOD_TEXT (bst, LEFT, "\n(TP)?\n");
2758   BSOD_PAUSE (bst, 1000000);
2759
2760   BSOD_CHAR_DELAY (bst, 100000);
2761   BSOD_TEXT (bst, LEFT, " TP ABORT -LT ALL");
2762
2763   BSOD_CHAR_DELAY (bst, 10000);
2764   BSOD_TEXT (bst, LEFT, "\n(TP)?\n");
2765   BSOD_PAUSE (bst, 1000000);
2766
2767   BSOD_CHAR_DELAY (bst, 100000);
2768   BSOD_TEXT (bst, LEFT, "  TP STOP KILL");
2769
2770   BSOD_CHAR_DELAY (bst, 10000);
2771   BSOD_TEXT (bst, LEFT,
2772      "\n"
2773      "(TP)?\n"
2774      "Core dumps initiated for selected HVX processes ...\n"
2775      "Core dumps complete.\n"
2776      "Fri Jul 19 15:53:09 2002\n"
2777      "Live registers for cp 0:\n"
2778      " P    =     7de3  IW=0000     I=32    CI=30000000   S=80006013"
2779      "   IV=aa0      Level=13\n"
2780      " R1-7 =       1f      913       13        4        8        0        0\n"
2781      " B1-7 =   64e71b      a93      50e   64e73c     6c2c     7000      b54\n"
2782      "Memory dump starting to file /var/hvx/dp01/diag/Level2 ...\n"
2783      "Memory dump complete.\n"
2784     );
2785
2786   XClearWindow(dpy, window);
2787   return bst;
2788 }
2789
2790
2791 /* HPUX panic, by Tobias Klausmann <klausman@schwarzvogel.de>
2792  */
2793 static struct bsod_state *
2794 hpux (Display *dpy, Window window)
2795 {
2796   struct bsod_state *bst = make_bsod_state (dpy, window, "hvx", "HVX");
2797   const char *sysname;
2798   char buf[2048];
2799
2800   bst->scroll_p = True;
2801   bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent;
2802
2803   sysname = "HPUX";
2804 # ifdef HAVE_UNAME
2805   {
2806     struct utsname uts;
2807     char *s;
2808     if (uname (&uts) >= 0)
2809       sysname = uts.nodename;
2810     s = strchr (sysname, '.');
2811     if (s) *s = 0;
2812   }
2813 # endif /* !HAVE_UNAME */
2814
2815   BSOD_TEXT (bst, LEFT,
2816              "                                                       "
2817              "                                                       "
2818              "                                                       \n");
2819   sprintf (buf, "%.100s [HP Release B.11.00] (see /etc/issue)\n", sysname);
2820   BSOD_TEXT (bst, LEFT, buf);
2821   BSOD_PAUSE (bst, 1000000);
2822   BSOD_TEXT (bst, LEFT,
2823    "Console Login:\n"
2824    "\n"
2825    "     ******* Unexpected HPMC/TOC. Processor HPA FFFFFFFF'"
2826    "FFFA0000 *******\n"
2827    "                              GENERAL REGISTERS:\n"
2828    "r00/03 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2829    "006C76C0\n"
2830    "r04/07 00000000'00000001 00000000'0126E328 00000000'00000000 00000000'"
2831    "0122B640\n"
2832    "r08/11 00000000'00000000 00000000'0198CFC0 00000000'000476FE 00000000'"
2833    "00000001\n"
2834    "r12/15 00000000'40013EE8 00000000'08000080 00000000'4002530C 00000000'"
2835    "4002530C\n"
2836    "r16/19 00000000'7F7F2A00 00000000'00000001 00000000'00000000 00000000'"
2837    "00000000\n"
2838    "r20/23 00000000'006C8048 00000000'00000001 00000000'00000000 00000000'"
2839    "00000000\n"
2840    "r24/27 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2841    "00744378\n"
2842    "r28/31 00000000'00000000 00000000'007DD628 00000000'0199F2B0 00000000'"
2843    "00000000\n"
2844    "                              CONTROL REGISTERS:\n"
2845    "sr0/3  00000000'0F3B4000 00000000'0C2A2000 00000000'016FF800 00000000'"
2846    "00000000\n"
2847    "sr4/7  00000000'00000000 00000000'016FF800 00000000'0DBF1400 00000000'"
2848    "00000000\n"
2849    "pcq =  00000000'00000000.00000000'00104950 00000000'00000000.00000000'"
2850    "00104A14\n"
2851    "isr =  00000000'10240006 ior = 00000000'67D9E220 iir = 08000240 rctr = "
2852    "7FF10BB6\n"
2853    "\n"
2854    "pid reg cr8/cr9    00007700'0000B3A9 00000000'0000C5D8\n"
2855    "pid reg cr12/cr13  00000000'00000000 00000000'00000000\n"
2856    "ipsw = 000000FF'080CFF1F iva = 00000000'0002C000 sar = 3A ccr = C0\n"
2857    "tr0/3  00000000'006C76C0 00000000'00000001 00000000'00000000 00000000'"
2858    "7F7CE000\n"
2859    "tr4/7  00000000'03790000 0000000C'4FB68340 00000000'C07EE13F 00000000'"
2860    "0199F2B0\n"
2861    "eiem = FFFFFFF0'FFFFFFFF eirr = 80000000'00000000 itmr = 0000000C'"
2862    "4FD8EDE1\n"
2863    "cr1/4  00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
2864    "00000000\n"
2865    "cr5/7  00000000'00000000 00000000'00000000 00000000'"
2866    "00000000\n"
2867    "                           MACHINE CHECK PARAMETERS:\n"
2868    "Check Type = 00000000 CPU STATE = 9E000001 Cache Check = 00000000\n"
2869    "TLB Check = 00000000 Bus Check = 00000000 PIM State = ? SIU "
2870    "Status = ????????\n"
2871    "Assists = 00000000 Processor = 00000000\n"
2872    "Slave Addr = 00000000'00000000 Master Addr = 00000000'00000000\n"
2873    "\n"
2874    "\n"
2875    "TOC,    pcsq.pcoq = 0'0.0'104950   , isr.ior = 0'10240006.0'67d9e220\n"
2876    "@(#)B2352B/9245XB HP-UX (B.11.00) #1: Wed Nov  5 22:38:19 PST 1997\n"
2877    "Transfer of control: (display==0xd904, flags==0x0)\n"
2878    "\n"
2879    "\n"
2880    "\n"
2881    "*** A system crash has occurred.  (See the above messages for details.)\n"
2882    "*** The system is now preparing to dump physical memory to disk, for use\n"
2883    "*** in debugging the crash.\n"
2884    "\n"
2885    "*** The dump will be a SELECTIVE dump:  40 of 256 megabytes.\n"
2886    "*** To change this dump type, press any key within 10 seconds.\n"
2887    "*** Proceeding with selective dump.\n"
2888    "\n"
2889    "*** The dump may be aborted at any time by pressing ESC.\n");
2890
2891   {
2892     int i;
2893     int steps = 11;
2894     int size = 40;
2895     for (i = 0; i <= steps; i++)
2896       {
2897         if (i > steps) i = steps;
2898         sprintf (buf, 
2899                "*** Dumping: %3d%% complete (%d of 40 MB) (device 64:0x2)\r",
2900                  i * 100 / steps,
2901                  i * size / steps);
2902         BSOD_TEXT (bst, LEFT, buf);
2903         BSOD_PAUSE (bst, 1500000);
2904       }
2905   }
2906
2907   BSOD_TEXT (bst, LEFT, "\n*** System rebooting.\n");
2908
2909   XClearWindow(dpy, window);
2910   return bst;
2911 }
2912
2913
2914 /* IBM OS/390 aka MVS aka z/OS.
2915    Text from Dan Espen <dane@mk.telcordia.com>.
2916    Apparently this isn't actually a crash, just a random session...
2917    But who can tell.
2918  */
2919 static struct bsod_state *
2920 os390 (Display *dpy, Window window)
2921 {
2922   struct bsod_state *bst = make_bsod_state (dpy, window, "os390", "OS390");
2923
2924   bst->scroll_p = True;
2925   bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent;
2926
2927   BSOD_LINE_DELAY (bst, 100000);
2928   BSOD_TEXT (bst, LEFT,
2929    "\n*** System rebooting.\n"
2930    "* ISPF Subtask abend *\n"
2931    "SPF      ENDED DUE TO ERROR+\n"
2932    "READY\n"
2933    "\n"
2934    "IEA995I SYMPTOM DUMP OUTPUT\n"
2935    "  USER COMPLETION CODE=0222\n"
2936    " TIME=23.00.51  SEQ=03210  CPU=0000  ASID=00AE\n"
2937    " PSW AT TIME OF ERROR  078D1000   859DAF18  ILC 2  INTC 0D\n"
2938    "   NO ACTIVE MODULE FOUND\n"
2939    "   NAME=UNKNOWN\n"
2940    "   DATA AT PSW  059DAF12 - 00181610  0A0D9180  70644710\n"
2941    "   AR/GR 0: 00000000/80000000   1: 00000000/800000DE\n"
2942    "         2: 00000000/196504DC   3: 00000000/00037A78\n"
2943    "         4: 00000000/00037B78   5: 00000000/0003351C\n"
2944    "         6: 00000000/0000F0AD   7: 00000000/00012000\n"
2945    "         8: 00000000/059DAF10   9: 00000000/0002D098\n"
2946    "         A: 00000000/059D9F10   B: 00000000/059D8F10\n"
2947    "         C: 00000000/859D7F10   D: 00000000/00032D60\n"
2948    "         E: 00000000/00033005   F: 01000002/00000041\n"
2949    " END OF SYMPTOM DUMP\n"
2950    "ISPS014 - ** Logical screen request failed - abend 0000DE **\n"
2951    "ISPS015 - ** Contact your system programmer or dialog developer.**\n"
2952    "*** ISPF Main task abend ***\n"
2953    "IEA995I SYMPTOM DUMP OUTPUT\n"
2954    "  USER COMPLETION CODE=0222\n"
2955    " TIME=23.00.52  SEQ=03211  CPU=0000  ASID=00AE\n"
2956    " PSW AT TIME OF ERROR  078D1000   8585713C  ILC 2  INTC 0D\n"
2957    "   ACTIVE LOAD MODULE           ADDRESS=05855000  OFFSET=0000213C\n"
2958    "   NAME=ISPMAIN\n"
2959    "   DATA AT PSW  05857136 - 00181610  0A0D9180  D3304770\n"
2960    "   GR 0: 80000000   1: 800000DE\n"
2961    "      2: 00015260   3: 00000038\n"
2962    "      4: 00012508   5: 00000000\n"
2963    "      6: 000173AC   7: FFFFFFF8\n"
2964    "      8: 05858000   9: 00012CA0\n"
2965    "      A: 05857000   B: 05856000\n"
2966    "      C: 85855000   D: 00017020\n"
2967    "      E: 85857104   F: 00000000\n"
2968    " END OF SYMPTOM DUMP\n"
2969    "READY\n"
2970    "***");
2971   BSOD_CURSOR (bst, CURSOR_LINE, 240000, 999999);
2972
2973   XClearWindow(dpy, window);
2974   return bst;
2975 }
2976
2977
2978 /* Compaq Tru64 Unix panic, by jwz as described by
2979    Tobias Klausmann <klausman@schwarzvogel.de>
2980  */
2981 static struct bsod_state *
2982 tru64 (Display *dpy, Window window)
2983 {
2984   struct bsod_state *bst = make_bsod_state (dpy, window, "tru64", "Tru64");
2985   const char *sysname;
2986   char buf[2048];
2987
2988   bst->scroll_p = True;
2989   bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent;
2990
2991   sysname = "127.0.0.1";
2992 # ifdef HAVE_UNAME
2993   {
2994     struct utsname uts;
2995     if (uname (&uts) >= 0)
2996       sysname = uts.nodename;
2997   }
2998 # endif /* !HAVE_UNAME */
2999
3000   sprintf (buf,
3001            "Compaq Tru64 UNIX V5.1B (Rev. 2650) (%.100s) console\n"
3002            "\n"
3003            "login: ",
3004            sysname);
3005   BSOD_TEXT (bst, LEFT, buf);
3006   BSOD_PAUSE (bst, 6000000);
3007
3008   BSOD_TEXT (bst, LEFT,
3009     "panic (cpu 0): trap: illegal instruction\n"
3010     "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n"
3011     "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n"
3012     "                                                                   \n"
3013     "DUMP: blocks available:  1571600\n"
3014     "DUMP: blocks wanted:      100802 (partial compressed dump) [OKAY]\n"
3015     "DUMP: Device     Disk Blocks Available\n"
3016     "DUMP: ------     ---------------------\n"
3017     "DUMP: 0x1300023  1182795 - 1571597 (of 1571598) [primary swap]\n"
3018     "DUMP.prom: Open: dev 0x5100041, block 2102016: SCSI 0 11 0 2 200 0 0\n"
3019     "DUMP: Writing header... [1024 bytes at dev 0x1300023, block 1571598]\n"
3020     "DUMP: Writing data");
3021
3022   {
3023     int i;
3024     int steps = 4 + (random() % 8);
3025     BSOD_CHAR_DELAY (bst, 1000000);
3026     for (i = 0; i < steps; i++)
3027       BSOD_TEXT (bst, LEFT, ".");
3028     BSOD_CHAR_DELAY (bst, 0);
3029     sprintf (buf, "[%dMB]\n", steps);
3030     BSOD_TEXT (bst, LEFT, buf);
3031   }
3032
3033   BSOD_TEXT (bst, LEFT,
3034     "DUMP: Writing header... [1024 bytes at dev 0x1300023, block 1571598]\n"
3035     "DUMP: crash dump complete.\n"
3036     "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n"
3037     "                                                                   \n"
3038     "DUMP: second crash dump skipped: 'dump_savecnt' enforced.\n");
3039   BSOD_PAUSE (bst, 4000000);
3040
3041   BSOD_TEXT (bst, LEFT,
3042     "\n"
3043     "halted CPU 0\n"
3044     "\n"
3045     "halt code = 5\n"
3046     "HALT instruction executed\n"
3047     "PC = fffffc00005863b0\n");
3048   BSOD_PAUSE (bst, 3000000);
3049
3050   BSOD_TEXT (bst, LEFT,
3051     "\n"   
3052     "CPU 0 booting\n"
3053     "\n"
3054     "\n"
3055     "\n");
3056
3057   XClearWindow(dpy, window);
3058   return bst;
3059 }
3060
3061
3062 /* MS-DOS, by jwz
3063  */
3064 static struct bsod_state *
3065 msdos (Display *dpy, Window window)
3066 {
3067   struct bsod_state *bst = make_bsod_state (dpy, window, "msdos", "MSDOS");
3068
3069   BSOD_CHAR_DELAY (bst, 10000);
3070   BSOD_TEXT (bst, LEFT, "C:\\WINDOWS>");
3071   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 8);
3072
3073   BSOD_CHAR_DELAY (bst, 200000);
3074   BSOD_TEXT (bst, LEFT, "dir a:");
3075   BSOD_PAUSE (bst, 1000000);
3076
3077   BSOD_CHAR_DELAY (bst, 10000);
3078   BSOD_TEXT (bst, LEFT, "\nNot ready reading drive A\nAbort, Retry, Fail?");
3079
3080   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 10);
3081   BSOD_CHAR_DELAY (bst, 200000);
3082   BSOD_TEXT (bst, LEFT, "f");
3083   BSOD_PAUSE (bst, 1000000);
3084
3085   BSOD_CHAR_DELAY (bst, 10000);
3086   BSOD_TEXT (bst, LEFT,
3087              "\n\n\nNot ready reading drive A\nAbort, Retry, Fail?");
3088
3089   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 10);
3090   BSOD_CHAR_DELAY (bst, 200000);
3091   BSOD_TEXT (bst, LEFT, "f");
3092   BSOD_PAUSE (bst, 1000000);
3093
3094   BSOD_CHAR_DELAY (bst, 10000);
3095   BSOD_TEXT (bst, LEFT, "\nVolume in drive A has no label\n\n"
3096                   "Not ready reading drive A\nAbort, Retry, Fail?");
3097
3098   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 12);
3099   BSOD_CHAR_DELAY (bst, 200000);
3100   BSOD_TEXT (bst, LEFT, "a");
3101   BSOD_PAUSE (bst, 1000000);
3102
3103   BSOD_CHAR_DELAY (bst, 10000);
3104   BSOD_TEXT (bst, LEFT, "\n\nC:\\WINDOWS>");
3105
3106   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 999999);
3107
3108   XClearWindow(dpy, window);
3109   return bst;
3110 }
3111
3112
3113 /* nvidia, by jwz.
3114  *
3115  * This is what happens if an Nvidia card goes into some crazy text mode.
3116  * Most often seen on the second screen of a dual-head system when the
3117  * proper driver isn't loaded.
3118  */
3119 typedef struct { int fg; int bg; int bit; Bool blink; } nvcell;
3120
3121 static void
3122 nvspatter (nvcell *grid, int rows, int cols, int ncolors, int nbits,
3123            Bool fill_p)
3124 {
3125   int max = rows * cols;
3126   int from = fill_p ?   0 : random() % (max - 1);
3127   int len  = fill_p ? max : random() % (cols * 4);
3128   int to = from + len;
3129   int i;
3130   Bool noisy = ((random() % 4) == 0);
3131   Bool diag = (noisy || fill_p) ? 0 : ((random() % 4) == 0);
3132
3133   int fg = random() % ncolors;
3134   int bg = random() % ncolors;
3135   int blink = ((random() % 4) == 0);
3136   int bit = (random() % nbits);
3137
3138   if (to > max) to = max;
3139
3140   if (diag)
3141     {
3142       int src = random() % (rows * cols);
3143       int len2 = (cols / 2) - (random() % 5);
3144       int j = src;
3145       for (i = from; i < to; i++, j++)
3146         {
3147           if (j > src + len2 || j >= max)
3148             j = src;
3149           if (i >= max) abort();
3150           if (j >= max) abort();
3151           grid[j] = grid[i];
3152         }
3153     }
3154   else
3155     for (i = from; i < to; i++)
3156       {
3157         nvcell *cell = &grid[i];
3158         cell->fg = fg;
3159         cell->bg = bg;
3160         cell->bit = bit;
3161         cell->blink = blink;
3162
3163         if (noisy)
3164           {
3165             fg = random() % ncolors;
3166             bg = random() % ncolors;
3167             blink = ((random() % 8) == 0);
3168           }
3169       }
3170 }
3171
3172 typedef struct {
3173   struct bsod_state *bst;
3174   GC gc1;
3175   Pixmap bits[5];
3176   int rows, cols;
3177   int cellw, cellh;
3178   nvcell *grid;
3179   int ncolors;
3180   unsigned long colors[256];
3181   int tick;
3182 } nvstate;
3183
3184
3185 static void
3186 nvidia_free (struct bsod_state *bst)
3187 {
3188   nvstate *nvs = (nvstate *) bst->closure;
3189   int i;
3190   XFreeColors (bst->dpy, bst->xgwa.colormap, nvs->colors, nvs->ncolors, 0);
3191   for (i = 0; i < countof(nvs->bits); i++)
3192     XFreePixmap (bst->dpy, nvs->bits[i]);
3193   XFreeGC (bst->dpy, nvs->gc1);
3194   free (nvs->grid);
3195   free (nvs);
3196 }
3197
3198 static int
3199 nvidia_draw (struct bsod_state *bst)
3200 {
3201   nvstate *nvs = (nvstate *) bst->closure;
3202   int x, y;
3203
3204   for (y = 0; y < nvs->rows; y++)
3205     for (x = 0; x < nvs->cols; x++)
3206       {
3207         nvcell *cell = &nvs->grid[y * nvs->cols + x];
3208         unsigned long fg = nvs->colors[cell->fg];
3209         unsigned long bg = nvs->colors[cell->bg];
3210         Bool flip = cell->blink && (nvs->tick & 1);
3211         XSetForeground (bst->dpy, bst->gc, flip ? fg : bg);
3212         XSetBackground (bst->dpy, bst->gc, flip ? bg : fg);
3213         XCopyPlane (bst->dpy, nvs->bits[cell->bit], bst->window, bst->gc,
3214                     0, 0, nvs->cellw, nvs->cellh,
3215                     x * nvs->cellw, y * nvs->cellh, 1L);
3216       }
3217
3218   nvs->tick++;
3219   if ((random() % 5) == 0)    /* change the display */
3220     nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors, 
3221                countof(nvs->bits), False);
3222
3223   return 250000;
3224 }
3225
3226
3227 static struct bsod_state *
3228 nvidia (Display *dpy, Window window)
3229 {
3230   struct bsod_state *bst = make_bsod_state (dpy, window, "nvidia", "nVidia");
3231   nvstate *nvs = (nvstate *) calloc (1, sizeof (*nvs));
3232
3233   XGCValues gcv;
3234   int i;
3235
3236   nvs->bst = bst;
3237   bst->closure = nvs;
3238   bst->draw_cb = nvidia_draw;
3239   bst->free_cb = nvidia_free;
3240
3241   nvs->cols = 80;
3242   nvs->rows = 25;
3243   nvs->cellw = bst->xgwa.width  / nvs->cols;
3244   nvs->cellh = bst->xgwa.height / nvs->rows;
3245   if (nvs->cellw < 8 || nvs->cellh < 18)
3246     nvs->cellw = 8, nvs->cellh = 18;
3247   nvs->cols = (bst->xgwa.width  / nvs->cellw) + 1;
3248   nvs->rows = (bst->xgwa.height / nvs->cellh) + 1;
3249
3250   nvs->grid = (nvcell *) calloc (sizeof(*nvs->grid), nvs->rows * nvs->cols);
3251
3252   /* Allocate colors
3253    */
3254   nvs->ncolors = 16;
3255   for (i = 0; i < nvs->ncolors; i++)
3256     {
3257       XColor c;
3258       c.red   = random() & 0xFFFF;
3259       c.green = random() & 0xFFFF;
3260       c.blue  = random() & 0xFFFF;
3261       c.flags = DoRed|DoGreen|DoBlue;
3262       XAllocColor (dpy, bst->xgwa.colormap, &c);
3263       nvs->colors[i] = c.pixel;
3264     }
3265
3266   /* Construct corrupted character bitmaps
3267    */
3268   for (i = 0; i < countof(nvs->bits); i++)
3269     {
3270       int j;
3271
3272       nvs->bits[i] = XCreatePixmap (dpy, window, nvs->cellw, nvs->cellh, 1);
3273       if (!nvs->gc1) nvs->gc1 = XCreateGC (dpy, nvs->bits[i], 0, &gcv);
3274
3275       XSetForeground (dpy, nvs->gc1, 0);
3276       XFillRectangle (dpy, nvs->bits[i], nvs->gc1, 0, 0, 
3277                       nvs->cellw, nvs->cellh);
3278       XSetForeground (dpy, nvs->gc1, 1);
3279
3280       if ((random() % 40) != 0)
3281         for (j = 0; j < ((nvs->cellw * nvs->cellh) / 16); j++)
3282           XFillRectangle (dpy, nvs->bits[i], nvs->gc1,
3283                           (random() % (nvs->cellw-2)) & ~1,
3284                           (random() % (nvs->cellh-2)) & ~1,
3285                           2, 2);
3286     }
3287
3288   /* Randomize the grid
3289    */
3290   nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors, 
3291              countof(nvs->bits), True);
3292   for (i = 0; i < 20; i++)
3293     nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors, 
3294                countof(nvs->bits), False);
3295
3296   return bst;
3297 }
3298
3299
3300 /*
3301  * Simulate various Apple ][ crashes. The memory map encouraged many programs
3302  * to use the primary hi-res video page for various storage, and the secondary
3303  * hi-res page for active display. When it crashed into Applesoft or the
3304  * monitor, it would revert to the primary page and you'd see memory garbage on
3305  * the screen. Also, it was common for copy-protected games to use the primary
3306  * text page for important code, because that made it really hard to
3307  * reverse-engineer them. The result often looked like what this generates.
3308  *
3309  * The Apple ][ logic and video hardware is in apple2.c. The TV is emulated by
3310  * analogtv.c for maximum realism
3311  *
3312  * Trevor Blackwell <tlb@tlb.org> 
3313  */
3314
3315 static const char * const apple2_basic_errors[]={
3316   "BREAK",
3317   "NEXT WITHOUT FOR",
3318   "SYNTAX ERROR",
3319   "RETURN WITHOUT GOSUB",
3320   "ILLEGAL QUANTITY",
3321   "OVERFLOW",
3322   "OUT OF MEMORY",
3323   "BAD SUBSCRIPT ERROR",
3324   "DIVISION BY ZERO",
3325   "STRING TOO LONG",
3326   "FORMULA TOO COMPLEX",
3327   "UNDEF'D FUNCTION",
3328   "OUT OF DATA"
3329 #if 0
3330   ,
3331   "DEFAULT ARGUMENTS ARE NOT ALLOWED IN DECLARATION OF FRIEND "
3332   "TEMPLATE SPECIALIZATION"
3333 #endif
3334
3335 };
3336 static const char * const apple2_dos_errors[]={
3337   "VOLUME MISMATCH",
3338   "I/O ERROR",
3339   "DISK FULL",
3340   "NO BUFFERS AVAILABLE",
3341   "PROGRAM TOO LARGE",
3342 };
3343
3344 static void a2controller_crash(apple2_sim_t *sim, int *stepno,
3345                                double *next_actiontime)
3346 {
3347   apple2_state_t *st=sim->st;
3348   char *s;
3349   int i;
3350
3351   struct mydata {
3352     int fillptr;
3353     int fillbyte;
3354   } *mine;
3355
3356   if (!sim->controller_data)
3357     sim->controller_data = calloc(sizeof(struct mydata),1);
3358   mine=(struct mydata *) sim->controller_data;
3359   
3360   switch(*stepno) {
3361   case 0:
3362     
3363     a2_init_memory_active(sim);
3364     sim->dec->powerup = 1000.0;
3365
3366     if (random()%3==0) {
3367       st->gr_mode=0;
3368       *next_actiontime+=0.4;
3369       *stepno=100;
3370     }
3371     else if (random()%4==0) {
3372       st->gr_mode=A2_GR_LORES;
3373       if (random()%3==0) st->gr_mode |= A2_GR_FULL;
3374       *next_actiontime+=0.4;
3375       *stepno=100;
3376     }
3377     else if (random()%2==0) {
3378       st->gr_mode=A2_GR_HIRES;
3379       *stepno=300;
3380     }
3381     else {
3382       st->gr_mode=A2_GR_HIRES;
3383       *next_actiontime+=0.4;
3384       *stepno=100;
3385     }
3386     break;
3387
3388   case 100:
3389     /* An illegal instruction or a reset caused it to drop into the
3390        assembly language monitor, where you could disassemble code & view
3391        data in hex. */
3392     if (random()%3==0) {
3393       char ibytes[128];
3394       char itext[128];
3395       int addr=0xd000+random()%0x3000;
3396       sprintf(ibytes,
3397               "%02X",random()%0xff);
3398       sprintf(itext,
3399               "???");
3400       sprintf(sim->printing_buf,
3401               "\n\n"
3402               "%04X: %-15s %s\n"
3403               " A=%02X X=%02X Y=%02X S=%02X F=%02X\n"
3404               "*",
3405               addr,ibytes,itext,
3406               random()%0xff, random()%0xff,
3407               random()%0xff, random()%0xff,
3408               random()%0xff);
3409       sim->printing=sim->printing_buf;
3410       a2_goto(st,23,1);
3411       if (st->gr_mode) {
3412         *stepno=180;
3413       } else {
3414         *stepno=200;
3415       }
3416       sim->prompt='*';
3417       *next_actiontime += 2.0 + (random()%1000)*0.0002;
3418     }
3419     else {
3420       /* Lots of programs had at least their main functionality in
3421          Applesoft Basic, which had a lot of limits (memory, string
3422          length, etc) and would sometimes crash unexpectedly. */
3423       sprintf(sim->printing_buf,
3424               "\n"
3425               "\n"
3426               "\n"
3427               "?%s IN %d\n"
3428               "\001]",
3429               apple2_basic_errors[random() %
3430                                   (sizeof(apple2_basic_errors)
3431                                    /sizeof(char *))],
3432               (1000*(random()%(random()%59+1)) +
3433                100*(random()%(random()%9+1)) +
3434                5*(random()%(random()%199+1)) +
3435                1*(random()%(random()%(random()%2+1)+1))));
3436       sim->printing=sim->printing_buf;
3437       a2_goto(st,23,1);
3438       *stepno=110;
3439       sim->prompt=']';
3440       *next_actiontime += 2.0 + (random()%1000)*0.0002;
3441     }
3442     break;
3443
3444   case 110:
3445     if (random()%3==0) {
3446       /* This was how you reset the Basic interpreter. The sort of
3447          incantation you'd have on a little piece of paper taped to the
3448          side of your machine */
3449       sim->typing="CALL -1370";
3450       *stepno=120;
3451     }
3452     else if (random()%2==0) {
3453       sim->typing="CATALOG\n";
3454       *stepno=170;
3455     }
3456     else {
3457       *next_actiontime+=1.0;
3458       *stepno=999;
3459     }
3460     break;
3461
3462   case 120:
3463     *stepno=130;
3464     *next_actiontime += 0.5;
3465     break;
3466
3467   case 130:
3468     st->gr_mode=0;
3469     a2_cls(st);
3470     a2_goto(st,0,16);
3471     for (s="APPLE ]["; *s; s++) a2_printc(st,*s);
3472     a2_goto(st,23,0);
3473     a2_printc(st,']');
3474     *next_actiontime+=1.0;
3475     *stepno=999;
3476     break;
3477
3478   case 170:
3479     if (random()%50==0) {
3480       sprintf(sim->printing_buf,
3481               "\nDISK VOLUME 254\n\n"
3482               " A 002 HELLO\n"
3483               "\n"
3484               "]");
3485       sim->printing=sim->printing_buf;
3486     }
3487     else {
3488       sprintf(sim->printing_buf,"\n?%s\n]",
3489               apple2_dos_errors[random()%
3490                                 (sizeof(apple2_dos_errors) /
3491                                  sizeof(char *))]);
3492       sim->printing=sim->printing_buf;
3493     }
3494     *stepno=999;
3495     *next_actiontime+=1.0;
3496     break;
3497
3498   case 180:
3499     if (random()%2==0) {
3500       /* This was how you went back to text mode in the monitor */
3501       sim->typing="FB4BG";
3502       *stepno=190;
3503     } else {
3504       *next_actiontime+=1.0;
3505       *stepno=999;
3506     }
3507     break;
3508
3509   case 190:
3510     st->gr_mode=0;
3511     a2_invalidate(st);
3512     a2_printc(st,'\n');
3513     a2_printc(st,'*');
3514     *stepno=200;
3515     *next_actiontime+=2.0;
3516     break;
3517
3518   case 200:
3519     /* This reset things into Basic */
3520     if (random()%2==0) {
3521       sim->typing="FAA6G";
3522       *stepno=120;
3523     }
3524     else {
3525       *stepno=999;
3526       *next_actiontime+=sim->delay;
3527     }
3528     break;
3529
3530   case 300:
3531     for (i=0; i<1500; i++) {
3532       a2_poke(st, mine->fillptr, mine->fillbyte);
3533       mine->fillptr++;
3534       mine->fillbyte = (mine->fillbyte+1)&0xff;
3535     }
3536     *next_actiontime += 0.08;
3537     /* When you hit c000, it changed video settings */
3538     if (mine->fillptr>=0xc000) {
3539       a2_invalidate(st);
3540       st->gr_mode=0;
3541     }
3542     /* And it seemed to reset around here, I dunno why */
3543     if (mine->fillptr>=0xcf00) *stepno=130;
3544     break;
3545
3546   case 999:
3547     break;
3548
3549   case A2CONTROLLER_FREE:
3550     free(mine);
3551     mine = 0;
3552     break;
3553   }
3554 }
3555
3556 static int
3557 a2_draw (struct bsod_state *bst)
3558 {
3559   apple2_sim_t *sim = (apple2_sim_t *) bst->closure;
3560   if (! sim) {
3561     sim = apple2_start (bst->dpy, bst->window, 9999999, a2controller_crash);
3562     bst->closure = sim;
3563   }
3564
3565   if (! apple2_one_frame (sim)) {
3566     bst->closure = 0;
3567   }
3568
3569   return 10000;
3570 }
3571
3572 static void
3573 a2_free (struct bsod_state *bst)
3574 {
3575   apple2_sim_t *sim = (apple2_sim_t *) bst->closure;
3576   if (sim) {
3577     sim->stepno = A2CONTROLLER_DONE;
3578     a2_draw (bst);              /* finish up */
3579     if (bst->closure) abort();  /* should have been freed by now */
3580   }
3581 }
3582
3583
3584 static struct bsod_state *
3585 apple2crash (Display *dpy, Window window)
3586 {
3587   struct bsod_state *bst = make_bsod_state (dpy, window, "apple2", "Apple2");
3588   bst->draw_cb = a2_draw;
3589   bst->free_cb = a2_free;
3590   return bst;
3591 }
3592
3593
3594 /* A crash spotted on a cash machine circa 2006, by jwz.  I didn't note
3595    what model it was; probably a Tranax Mini-Bank 1000 or similar vintage.
3596  */
3597 static struct bsod_state *
3598 atm (Display *dpy, Window window)
3599 {
3600   struct bsod_state *bst = make_bsod_state (dpy, window, "atm", "ATM");
3601
3602   Pixmap pixmap = 0;
3603   int pix_w = atm_width;
3604   int pix_h = atm_height;
3605   int x, y, i = 0;
3606   float scale = 0.48;
3607
3608   XClearWindow (dpy, window);
3609
3610   pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) atm_bits,
3611                                         atm_width, atm_height,
3612                                         bst->fg, bst->bg, bst->xgwa.depth);
3613
3614   while (pix_w <= bst->xgwa.width  * scale && 
3615          pix_h <= bst->xgwa.height * scale)
3616     {
3617       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
3618                               pixmap, pix_w, pix_h);
3619       pix_w *= 2;
3620       pix_h *= 2;
3621       i++;
3622     }
3623
3624   x = (bst->xgwa.width  - pix_w) / 2;
3625   y = (bst->xgwa.height - pix_h) / 2;
3626   if (y < 0) y = 0;
3627
3628   if (i > 0)
3629     {
3630       int j;
3631       XSetForeground (dpy, bst->gc,
3632                       get_pixel_resource (dpy, bst->xgwa.colormap,
3633                                           "atm.background",
3634                                           "ATM.Background"));
3635       for (j = -1; j < pix_w; j += i+1)
3636         XDrawLine (bst->dpy, pixmap, bst->gc, j, 0, j, pix_h);
3637       for (j = -1; j < pix_h; j += i+1)
3638         XDrawLine (bst->dpy, pixmap, bst->gc, 0, j, pix_w, j);
3639     }
3640
3641   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
3642
3643   XFreePixmap (dpy, pixmap);
3644
3645   return bst;
3646 }
3647
3648
3649 /*****************************************************************************
3650  *****************************************************************************/
3651
3652
3653 static const struct {
3654   const char *name;
3655   struct bsod_state * (*fn) (Display *, Window);
3656 } all_modes[] = {
3657   { "Windows",          windows_31 },
3658   { "NT",               windows_nt },
3659   { "Win2K",            windows_other },
3660   { "Amiga",            amiga },
3661   { "Mac",              mac },
3662   { "MacsBug",          macsbug },
3663   { "Mac1",             mac1 },
3664   { "MacX",             macx },
3665   { "SCO",              sco },
3666   { "HVX",              hvx },
3667   { "HPPALinux",        hppa_linux },
3668   { "SparcLinux",       sparc_linux },
3669   { "BSD",              bsd },
3670   { "Atari",            atari },
3671 #ifndef HAVE_COCOA
3672   { "BlitDamage",       blitdamage },
3673 #endif
3674   { "Solaris",          sparc_solaris },
3675   { "Linux",            linux_fsck },
3676   { "HPUX",             hpux },
3677   { "OS390",            os390 },
3678   { "Tru64",            tru64 },
3679   { "VMS",              vms },
3680   { "OS2",              os2 },
3681   { "MSDOS",            msdos },
3682   { "Nvidia",           nvidia },
3683   { "Apple2",           apple2crash },
3684   { "ATM",              atm },
3685   { "GLaDOS",           glados },
3686 };
3687
3688
3689 struct driver_state {
3690   const char *name;
3691   int only, which;
3692   int delay;
3693   time_t start;
3694   Bool debug_p, cycle_p;
3695   struct bsod_state *bst;
3696 };
3697
3698
3699 static void
3700 hack_title (struct driver_state *dst)
3701 {
3702 # ifndef HAVE_COCOA
3703   char *oname = 0;
3704   XFetchName (dst->bst->dpy, dst->bst->window, &oname);
3705   if (oname && !strncmp (oname, "BSOD: ", 6)) {
3706     char *tail = oname + 4;
3707     char *s = strchr (tail+1, ':');
3708     char *nname;
3709     if (s) tail = s;
3710     nname = malloc (strlen (tail) + strlen (dst->name) + 20);
3711     sprintf (nname, "BSOD: %s%s", dst->name, tail);
3712     XStoreName (dst->bst->dpy, dst->bst->window, nname);
3713     free (nname);
3714   }
3715 # endif /* !HAVE_COCOA */
3716 }
3717
3718 static void *
3719 bsod_init (Display *dpy, Window window)
3720 {
3721   struct driver_state *dst = (struct driver_state *) calloc (1, sizeof(*dst));
3722   char *s;
3723
3724   dst->delay = get_integer_resource (dpy, "delay", "Integer");
3725   if (dst->delay < 3) dst->delay = 3;
3726
3727   dst->debug_p = get_boolean_resource (dpy, "debug", "Boolean");
3728
3729   dst->only = -1;
3730   s = get_string_resource(dpy, "doOnly", "DoOnly");
3731   if (s && !strcasecmp (s, "cycle"))
3732     {
3733       dst->which = -1;
3734       dst->cycle_p = True;
3735     }
3736   else if (s && *s)
3737     {
3738       int count = countof(all_modes);
3739       for (dst->only = 0; dst->only < count; dst->only++)
3740         if (!strcasecmp (s, all_modes[dst->only].name))
3741           break;
3742       if (dst->only >= count)
3743         {
3744           fprintf (stderr, "%s: unknown -only mode: \"%s\"\n", progname, s);
3745           dst->only = -1;
3746         }
3747     }
3748   if (s) free (s);
3749
3750   dst->name = "none";
3751   dst->which = -1;
3752   return dst;
3753 }
3754
3755
3756 static unsigned long
3757 bsod_draw (Display *dpy, Window window, void *closure)
3758 {
3759   struct driver_state *dst = (struct driver_state *) closure;
3760   time_t now;
3761   int time_left;
3762
3763  AGAIN:
3764   now = time ((time_t *) 0);
3765   time_left = dst->start + dst->delay - now;
3766
3767   if (dst->bst && dst->bst->img_loader)   /* still loading */
3768     {
3769       dst->bst->img_loader = 
3770         load_image_async_simple (dst->bst->img_loader, 0, 0, 0, 0, 0);
3771       return 100000;
3772     }
3773
3774   if (! dst->bst && time_left > 0)      /* run completed; wait out the delay */
3775     {
3776       if (dst->debug_p)
3777         fprintf (stderr, "%s: %s: %d left\n", progname, dst->name, time_left);
3778       return 500000;
3779     }
3780
3781   else if (dst->bst)                    /* sub-mode currently running */
3782     {
3783       int this_delay = -1;
3784
3785       if (time_left > 0)
3786         this_delay = bsod_pop (dst->bst);
3787
3788       /* XSync (dpy, False);  slows down char drawing too much on HAVE_COCOA */
3789
3790       if (this_delay == 0)
3791         goto AGAIN;                     /* no delay, not expired: stay here */
3792       else if (this_delay >= 0)
3793         return this_delay;              /* return; time to sleep */
3794       else
3795         {                               /* sub-mode run completed or expired */
3796           if (dst->debug_p)
3797             fprintf (stderr, "%s: %s: done\n", progname, dst->name);
3798           free_bsod_state (dst->bst);
3799           dst->bst = 0;
3800           return 0;
3801         }
3802     }
3803   else                                  /* launch a new sub-mode */
3804     {
3805       if (dst->cycle_p)
3806         dst->which = (dst->which + 1) % countof(all_modes);
3807       else if (dst->only >= 0)
3808         dst->which = dst->only;
3809       else
3810         {
3811           int count = countof(all_modes);
3812           int i;
3813
3814           for (i = 0; i < 200; i++)
3815             {
3816               char name[100], class[100];
3817               int new_mode = (random() & 0xFF) % count;
3818
3819               if (i < 100 && new_mode == dst->which)
3820                 continue;
3821
3822               sprintf (name,  "do%s", all_modes[new_mode].name);
3823               sprintf (class, "Do%s", all_modes[new_mode].name);
3824
3825               if (get_boolean_resource (dpy, name, class))
3826                 {
3827                   dst->which = new_mode;
3828                   break;
3829                 }
3830             }
3831
3832           if (i >= 200)
3833             {
3834               fprintf (stderr, "%s: no display modes enabled?\n", progname);
3835               /* exit (-1); */
3836               dst->which = dst->only = 0;
3837             }
3838         }
3839           
3840       if (dst->debug_p)
3841         fprintf (stderr, "%s: %s: launch\n", progname, 
3842                  all_modes[dst->which].name);
3843
3844       /* Run the mode setup routine...
3845        */
3846       if (dst->bst) abort();
3847       dst->name  = all_modes[dst->which].name;
3848       dst->bst   = all_modes[dst->which].fn (dpy, window);
3849       dst->start = (dst->bst ? time ((time_t *) 0) : 0);
3850
3851       /* Reset the structure run state to the beginning,
3852          and do some sanitization of the cursor position
3853          before the first run.
3854        */
3855       if (dst->bst)
3856         {
3857           if (dst->debug_p)
3858             fprintf (stderr, "%s: %s: queue size: %d (%d)\n", progname, 
3859                      dst->name, dst->bst->pos, dst->bst->queue_size);
3860
3861           hack_title (dst);
3862           dst->bst->pos = 0;
3863           dst->bst->x = dst->bst->current_left = dst->bst->left_margin;
3864
3865           if (dst->bst->y < dst->bst->top_margin + dst->bst->font->ascent)
3866             dst->bst->y = dst->bst->top_margin + dst->bst->font->ascent;
3867         }
3868     }
3869
3870   return 0;
3871 }
3872
3873
3874 static void
3875 bsod_reshape (Display *dpy, Window window, void *closure, 
3876               unsigned int w, unsigned int h)
3877 {
3878   struct driver_state *dst = (struct driver_state *) closure;
3879
3880   if (dst->bst &&
3881       w == dst->bst->xgwa.width &&
3882       h == dst->bst->xgwa.height)
3883     return;
3884
3885   if (dst->debug_p)
3886     fprintf (stderr, "%s: %s: reshape reset\n", progname, dst->name);
3887
3888   /* just pick a new mode and restart when the window is resized. */
3889   if (dst->bst)
3890     free_bsod_state (dst->bst);
3891   dst->bst = 0;
3892   dst->start = 0;
3893   dst->name = "none";
3894   XClearWindow (dpy, window);
3895 }
3896
3897
3898 static Bool
3899 bsod_event (Display *dpy, Window window, void *closure, XEvent *event)
3900 {
3901   struct driver_state *dst = (struct driver_state *) closure;
3902   Bool reset_p = False;
3903
3904   /* pick a new mode and restart when mouse clicked, or certain keys typed. */
3905
3906   if (event->type == ButtonPress)
3907     reset_p = True;
3908   else if (event->type == KeyPress)
3909     {
3910       KeySym keysym;
3911       char c = 0;
3912       XLookupString (&event->xkey, &c, 1, &keysym, 0);
3913       if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
3914         reset_p = True;
3915     }
3916
3917   if (reset_p)
3918     {
3919       if (dst->debug_p)
3920         fprintf (stderr, "%s: %s: manual reset\n", progname, dst->name);
3921       if (dst->bst)
3922         free_bsod_state (dst->bst);
3923       dst->bst = 0;
3924       dst->start = 0;
3925       dst->name = "none";
3926       XClearWindow (dpy, window);
3927       return True;
3928     }
3929   else
3930     return False;
3931 }
3932
3933
3934 static void
3935 bsod_free (Display *dpy, Window window, void *closure)
3936 {
3937   struct driver_state *dst = (struct driver_state *) closure;
3938   if (dst->bst)
3939     free_bsod_state (dst->bst);
3940   free (dst);
3941 }
3942
3943
3944 static const char *bsod_defaults [] = {
3945   "*delay:                 30",
3946   "*debug:                 False",
3947
3948   "*doOnly:                ",
3949   "*doWindows:             True",
3950   "*doNT:                  True",
3951   "*doWin2K:               True",
3952   "*doAmiga:               True",
3953   "*doMac:                 True",
3954   "*doMacsBug:             True",
3955   "*doMac1:                True",
3956   "*doMacX:                True",
3957   "*doSCO:                 True",
3958   "*doAtari:               False",      /* boring */
3959   "*doBSD:                 False",      /* boring */
3960   "*doLinux:               True",
3961   "*doSparcLinux:          False",      /* boring */
3962   "*doHPPALinux:           True",
3963   "*doBlitDamage:          True",
3964   "*doSolaris:             True",
3965   "*doHPUX:                True",
3966   "*doTru64:               True",
3967   "*doApple2:              True",
3968   "*doOS390:               True",
3969   "*doVMS:                 True",
3970   "*doHVX:                 True",
3971   "*doMSDOS:               True",
3972   "*doOS2:                 True",
3973   "*doNvidia:              True",
3974   "*doATM:                 True",
3975   "*doGLaDOS:              True",
3976
3977   "*font:                  9x15bold",
3978   "*font2:                 -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
3979   "*bigFont:               -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
3980   "*bigFont2:              -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
3981
3982   ".foreground:            White",
3983   ".background:            Black",
3984
3985   ".windows.foreground:    White",
3986   ".windows.background:    #0000AA",    /* EGA color 0x01. */
3987
3988   ".windowslh.foreground:  White",
3989   ".windowslh.background:  #AA0000",    /* EGA color 0x04. */
3990   ".windowslh.background2: #AAAAAA",    /* EGA color 0x07. */
3991
3992   ".glaDOS.foreground:     White",
3993   ".glaDOS.background:     #0000AA",    /* EGA color 0x01. */
3994
3995   ".amiga.foreground:      #FF0000",
3996   ".amiga.background:      Black",
3997   ".amiga.background2:     White",
3998
3999   ".mac.foreground:        #BBFFFF",
4000   ".mac.background:        Black",
4001
4002   ".atari.foreground:      Black",
4003   ".atari.background:      White",
4004
4005   ".macsbug.font:          -*-courier-medium-r-*-*-*-80-*-*-m-*-*-*",
4006   ".macsbug.bigFont:       -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4007   ".macsbug.foreground:    Black",
4008   ".macsbug.background:    White",
4009   ".macsbug.borderColor:   #AAAAAA",
4010
4011   ".mac1.foreground:       Black",
4012   ".mac1.background:       White",
4013
4014   ".macx.foreground:       White",
4015   ".macx.textForeground:   White",
4016   ".macx.textBackground:   Black",
4017   ".macx.background:       #888888",
4018
4019   ".sco.font:              -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4020   ".sco.foreground:        White",
4021   ".sco.background:        Black",
4022
4023   ".hvx.font:              -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4024   ".hvx.foreground:        White",
4025   ".hvx.background:        Black",
4026
4027   ".linux.foreground:      White",
4028   ".linux.background:      Black",
4029
4030   ".hppalinux.bigFont:     -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4031   ".hppalinux.foreground:  White",
4032   ".hppalinux.background:  Black",
4033
4034   ".sparclinux.bigFont:    -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4035   ".sparclinux.foreground: White",
4036   ".sparclinux.background: Black",
4037
4038   ".bsd.font:              vga",
4039   ".bsd.bigFont:           -sun-console-medium-r-*-*-22-*-*-*-m-*-*-*",
4040   ".bsd.bigFont2:          -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4041   ".bsd.foreground:        #c0c0c0",
4042   ".bsd.background:        Black",
4043
4044   ".solaris.font:          -sun-gallant-*-*-*-*-19-*-*-*-*-120-*-*",
4045   ".solaris.foreground:    Black",
4046   ".solaris.background:    White",
4047
4048   ".hpux.bigFont:          -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4049   ".hpux.foreground:       White",
4050   ".hpux.background:       Black",
4051
4052   ".os390.bigFont:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4053   ".os390.background:      Black",
4054   ".os390.foreground:      Red",
4055
4056   ".tru64.bigFont:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4057   ".tru64.foreground:      White",
4058   ".tru64.background:      #0000AA",    /* EGA color 0x01. */
4059
4060   ".vms.bigFont:           -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4061   ".vms.foreground:        White",
4062   ".vms.background:        Black",
4063
4064   ".msdos.bigFont:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4065   ".msdos.foreground:      White",
4066   ".msdos.background:      Black",
4067
4068   ".os2.foreground:        White",
4069   ".os2.background:        Black",
4070
4071   ".atm.foreground:        Black",
4072   ".atm.background:        #FF6600",
4073
4074   "*dontClearRoot:         True",
4075
4076   "*apple2TVColor:         50",
4077   "*apple2TVTint:          5",
4078   "*apple2TVBrightness:    10",
4079   "*apple2TVContrast:      90",
4080   "*apple2SimulateUser:    True",
4081
4082   ANALOGTV_DEFAULTS
4083
4084 #ifdef HAVE_XSHM_EXTENSION
4085   "*useSHM:                True",
4086 #endif
4087   0
4088 };
4089
4090 static const XrmOptionDescRec bsod_options [] = {
4091   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
4092   { "-only",            ".doOnly",              XrmoptionSepArg, 0 },
4093   { "-debug",           ".debug",               XrmoptionNoArg,  "True"  },
4094   { "-windows",         ".doWindows",           XrmoptionNoArg,  "True"  },
4095   { "-no-windows",      ".doWindows",           XrmoptionNoArg,  "False" },
4096   { "-nt",              ".doNT",                XrmoptionNoArg,  "True"  },
4097   { "-no-nt",           ".doNT",                XrmoptionNoArg,  "False" },
4098   { "-2k",              ".doWin2K",             XrmoptionNoArg,  "True"  },
4099   { "-no-2k",           ".doWin2K",             XrmoptionNoArg,  "False" },
4100   { "-amiga",           ".doAmiga",             XrmoptionNoArg,  "True"  },
4101   { "-no-amiga",        ".doAmiga",             XrmoptionNoArg,  "False" },
4102   { "-mac",             ".doMac",               XrmoptionNoArg,  "True"  },
4103   { "-no-mac",          ".doMac",               XrmoptionNoArg,  "False" },
4104   { "-mac1",            ".doMac1",              XrmoptionNoArg,  "True"  },
4105   { "-no-mac1",         ".doMac1",              XrmoptionNoArg,  "False" },
4106   { "-macx",            ".doMacX",              XrmoptionNoArg,  "True"  },
4107   { "-no-macx",         ".doMacX",              XrmoptionNoArg,  "False" },
4108   { "-atari",           ".doAtari",             XrmoptionNoArg,  "True"  },
4109   { "-no-atari",        ".doAtari",             XrmoptionNoArg,  "False" },
4110   { "-macsbug",         ".doMacsBug",           XrmoptionNoArg,  "True"  },
4111   { "-no-macsbug",      ".doMacsBug",           XrmoptionNoArg,  "False" },
4112   { "-apple2",          ".doApple2",            XrmoptionNoArg,  "True"  },
4113   { "-no-apple2",       ".doApple2",            XrmoptionNoArg,  "False" },
4114   { "-sco",             ".doSCO",               XrmoptionNoArg,  "True"  },
4115   { "-no-sco",          ".doSCO",               XrmoptionNoArg,  "False" },
4116   { "-hvx",             ".doHVX",               XrmoptionNoArg,  "True"  },
4117   { "-no-hvx",          ".doHVX",               XrmoptionNoArg,  "False" },
4118   { "-bsd",             ".doBSD",               XrmoptionNoArg,  "True"  },
4119   { "-no-bsd",          ".doBSD",               XrmoptionNoArg,  "False" },
4120   { "-linux",           ".doLinux",             XrmoptionNoArg,  "True"  },
4121   { "-no-linux",        ".doLinux",             XrmoptionNoArg,  "False" },
4122   { "-hppalinux",       ".doHPPALinux",         XrmoptionNoArg,  "True"  },
4123   { "-no-hppalinux",    ".doHPPALinux",         XrmoptionNoArg,  "False" },
4124   { "-sparclinux",      ".doSparcLinux",        XrmoptionNoArg,  "True"  },
4125   { "-no-sparclinux",   ".doSparcLinux",        XrmoptionNoArg,  "False" },
4126   { "-blitdamage",      ".doBlitDamage",        XrmoptionNoArg,  "True"  },
4127   { "-no-blitdamage",   ".doBlitDamage",        XrmoptionNoArg,  "False" },
4128   { "-nvidia",          ".doNvidia",            XrmoptionNoArg,  "True"  },
4129   { "-no-nvidia",       ".doNvidia",            XrmoptionNoArg,  "False" },
4130   { "-solaris",         ".doSolaris",           XrmoptionNoArg,  "True"  },
4131   { "-no-solaris",      ".doSolaris",           XrmoptionNoArg,  "False" },
4132   { "-hpux",            ".doHPUX",              XrmoptionNoArg,  "True"  },
4133   { "-no-hpux",         ".doHPUX",              XrmoptionNoArg,  "False" },
4134   { "-os390",           ".doOS390",             XrmoptionNoArg,  "True"  },
4135   { "-no-os390",        ".doOS390",             XrmoptionNoArg,  "False" },
4136   { "-tru64",           ".doHPUX",              XrmoptionNoArg,  "True"  },
4137   { "-no-tru64",        ".doTru64",             XrmoptionNoArg,  "False" },
4138   { "-vms",             ".doVMS",               XrmoptionNoArg,  "True"  },
4139   { "-no-vms",          ".doVMS",               XrmoptionNoArg,  "False" },
4140   { "-msdos",           ".doMSDOS",             XrmoptionNoArg,  "True"  },
4141   { "-no-msdos",        ".doMSDOS",             XrmoptionNoArg,  "False" },
4142   { "-os2",             ".doOS2",               XrmoptionNoArg,  "True"  },
4143   { "-no-os2",          ".doOS2",               XrmoptionNoArg,  "False" },
4144   { "-atm",             ".doATM",               XrmoptionNoArg,  "True"  },
4145   { "-no-atm",          ".doATM",               XrmoptionNoArg,  "False" },
4146   { "-glados",          ".doGLaDOS",            XrmoptionNoArg,  "True"  },
4147   { "-no-glados",       ".doGLaDOS",            XrmoptionNoArg,  "False" },
4148   ANALOGTV_OPTIONS
4149   { 0, 0, 0, 0 }
4150 };
4151
4152
4153 XSCREENSAVER_MODULE ("BSOD", bsod)