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