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