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