X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fbsod.c;h=84f5f312a1a1a47f4fa4039b0bcc361069febc34;hp=9e5c9da0bc3f87c2fb77c3e1df312168199f58be;hb=96a411663168b0ba5432b407a83be55f3df0c802;hpb=bbd0773f2adde4927a6196361d4061e70bf48cd9 diff --git a/hacks/bsod.c b/hacks/bsod.c index 9e5c9da0..84f5f312 100644 --- a/hacks/bsod.c +++ b/hacks/bsod.c @@ -16,6 +16,7 @@ #include #include "screenhack.h" #include "xpm-pixmap.h" +#include "apple2.h" #include #include #include @@ -293,12 +294,54 @@ windows (Display *dpy, Window window, int delay, int which) const char *wmeb = (" System halted."); +# ifdef __GNUC__ + __extension__ /* don't warn about "string length is greater than the + length ISO C89 compilers are required to support" + in the following string constant... */ +# endif + + const char *wxpa = /* From Wm. Rhodes */ + ("A problem has been detected and windows has been shut down to prevent " + "damage\n" + "to your computer.\n" + "\n" + "If this is the first time you've seen this Stop error screen,\n" + "restart your computer. If this screen appears again, follow\n" + "these steps:\n" + "\n" + "Check to be sure you have adequate disk space. If a driver is\n" + "identified in the Stop message, disable the driver or check\n" + "with the manufacturer for driver updates. Try changing video\n" + "adapters.\n" + "\n" + "Check with you hardware vendor for any BIOS updates. Disable\n" + "BIOS memory options such as caching or shadowing. If you need\n" + "to use Safe Mode to remove or disable compinents, restart your\n" + "computer, press F8 to select Advanced Startup Options, and then\n" + "select Safe Mode.\n" + "\n" + "Technical information:\n" + "\n" + "*** STOP: 0x0000007E (0xC0000005,0xF88FF190,0x0xF8975BA0,0xF89758A0)\n" + "\n" + "\n" + "*** EPUSBDSK.sys - Address F88FF190 base at FF88FE000, datestamp " + "3b9f3248\n" + "\n" + "Beginning dump of physical memory\n"); + const char *wxpb = + ("Physical memory dump complete.\n" + "Contact your system administrator or technical support group for " + "further\n" + "assitance.\n" + ); + if (which < 0 || which > 2) abort(); - /* kludge to lump Win2K and WinME together; seems silly to add another - preference/command line option just for this little one. */ + /* kludge to lump Win2K, WinME, and WinXP together; seems silly to add + another preference/command line option just for these little ones. */ if (which == 2 && (random() % 2)) - which = 3; + which = 3 + (random() % 2); XGetWindowAttributes (dpy, window, &xgwa); @@ -354,6 +397,16 @@ windows (Display *dpy, Window window, int delay, int which) draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, w2kb, 750); } else if (which == 3) + { + int line_height = font->ascent + font->descent + 1; + int x = 4; + int y = 4; + draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, wxpa, 750); + y += line_height * 26; + bsod_sleep(dpy, 4); + draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, wxpb, 750); + } + else if (which == 4) { int line_height = font->ascent + font->descent; int x = 0; @@ -1453,7 +1506,7 @@ blitdamage (Display *dpy, Window window, int delay) XGetWindowAttributes(dpy, window, &xwa); - load_random_image (xwa.screen, window, window); + load_random_image (xwa.screen, window, window, NULL); w = xwa.width; h = xwa.height; @@ -1587,7 +1640,7 @@ make_scrolling_window (Display *dpy, Window window, if (!grab_screen_p) ts->sub_height += ts->sub_y, ts->sub_y = 0; if (grab_screen_p) - load_random_image (xgwa.screen, window, window); + load_random_image (xgwa.screen, window, window, NULL); sprintf (buf1, "%.50s.background", name); sprintf (buf2, "%.50s.Background", name); @@ -2319,6 +2372,71 @@ vms (Display *dpy, Window window, int delay) } +/* HVX (formerly GCOS6) and TPS6 crash + by Brian Garratt + + GCOS6 is a Unix-like operating system developed by Honeywell in the + 1970s in collaboration with MIT and AT&T (who called their version + UNIX). Both are very much like MULTICS which Honeywell got from GE. + + HVX ("High-performance Virtual System on Unix") is an AIX application + which emulates GCOS6 hardware on RS6000-like machines. + */ +static void +hvx (Display *dpy, Window window, int delay) +{ + XWindowAttributes xgwa; + scrolling_window *ts; + + int delay1 = 10000; + int delay2 = 100000; + const char *hvx_panic_1 = + ("(TP) Trap no E Effective address 00000000 Instruction D7DE\n" + "(TP) Registers :\n" + "(TP) B1 -> B7 03801B02 00000000 03880D45 038BABDB 0388AFFD" + " 0389B3F8 03972317\n" + "(TP) R1 -> R7 0001 0007 F10F 090F 0020 0106 0272\n" + "(TP) P I Z M1 0388A18B 3232 0000 FF00\n" + "(TP) Program counter is at offset 0028 from string YTPAD\n" + "(TP) User id of task which trapped is LT 626\n" + "(TP)?\n" + ); + const char *hvx_panic_2 = + ("\n" + "(TP)?\n" + "Core dumps initiated for selected HVX processes ...\n" + "Core dumps complete.\n" + "Fri Jul 19 15:53:09 2002\n" + "Live registers for cp 0:\n" + " P = 7de3 IW=0000 I=32 CI=30000000 S=80006013" + " IV=aa0 Level=13\n" + " R1-7 = 1f 913 13 4 8 0 0\n" + " B1-7 = 64e71b a93 50e 64e73c 6c2c 7000 b54\n" + "Memory dump starting to file /var/hvx/dp01/diag/Level2 ...\n" + "Memory dump complete.\n" + ); + + XGetWindowAttributes (dpy, window, &xgwa); + ts = make_scrolling_window (dpy, window, "HVX", False); + XClearWindow(dpy, window); + + scrolling_puts (ts, hvx_panic_1, delay1); + if (bsod_sleep(dpy, 1)) goto DONE; + scrolling_puts (ts, " TP CLOSE ALL", delay2); + scrolling_puts (ts, "\n(TP)?\n", delay1); + if (bsod_sleep(dpy, 1)) goto DONE; + scrolling_puts (ts, " TP ABORT -LT ALL", delay2); + scrolling_puts (ts, "\n(TP)?\n", delay1); + if (bsod_sleep(dpy, 1)) goto DONE; + scrolling_puts (ts, " TP STOP KILL", delay2); + scrolling_puts (ts, hvx_panic_2, delay1); + + bsod_sleep(dpy, delay); + DONE: + XClearWindow(dpy, window); +} + + /* HPUX panic, by Tobias Klausmann @@ -2562,83 +2680,20 @@ DONE: /* - * Simulate various Apple II crashes. The memory map encouraged many - * programs to use the primary hi-res video page for various storage, - * and the secondary hi-res page for active display. When it crashed - * into Applesoft or the monitor, it would revert to the primary page - * and you'd see memory garbage on the screen. Also, it was common for - * copy-protected games to use the primary text page for important - * code, because that made it really hard to reverse-engineer them. The - * result often looked like what this generates. - * - * Sometimes an imaginary user types some of the standard commands to - * recover from crashes. You can turn off BSOD*apple2SimulateUser to - * prevent this. - * - * It simulates the following characteristics of standard television - * monitors: + * Simulate various Apple ][ crashes. The memory map encouraged many programs + * to use the primary hi-res video page for various storage, and the secondary + * hi-res page for active display. When it crashed into Applesoft or the + * monitor, it would revert to the primary page and you'd see memory garbage on + * the screen. Also, it was common for copy-protected games to use the primary + * text page for important code, because that made it really hard to + * reverse-engineer them. The result often looked like what this generates. * - * - Realistic rendering of a composite video signal - * - Compression & brightening on the right, as the scan gets truncated - * because of saturation in the flyback transformer - * - Blooming of the picture dependent on brightness - * - Overscan, cutting off a few pixels on the left side. - * - Colored text in mixed graphics/text modes - * - * It's amazing how much it makes your high-end monitor look like at - * large late-70s TV. All you need is to put a big "Solid State" logo - * in curly script on it and you'd be set. + * The Apple ][ logic and video hardware is in apple2.c. The TV is emulated by + * analogtv.c for maximum realism * * Trevor Blackwell */ -/* - * Implementation notes: - * - * There are roughly 3 parts to this hack: - * - * - emulation of A2 Basic and Monitor. Not much more than printing random - * plausible messages. Here we work in the A2 memory space. - * - * - emulation of the A2's video output section, which shifted bits out of main - * memory at a 14 MHz dot clock rate, sort of. You could only read one byte - * per MHz, so there were various schemes for turning 8 bits into 14 screen - * pixels. - * - * - simulation of an NTSC television, which turned the bits into colored - * graphics and text. - * - * The A2 had 3 display modes: text, lores, and hires. Text was 40x24, and it - * disabled color in the TV. Lores gave you 40x48 graphics blocks, using the - * same memory as the text screen. Each could be one of 16 colors. Hires gave - * you 280x192 pixels. Odd pixels were blue or purple, and even pixels were - * orange or green depending on the setting of the high bit in each byte. - * - * The graphics modes could also have 4 lines of text at the bottom. This was - * fairly unreadable if you had a color monitor. - * - * Each mode had 2 different screens using different memory space. In hires - * mode this was sometimes used for double buffering, but more often the lower - * screen was full of code/data and the upper screen was used for display, so - * you got random garbage on the screen. - * - * In DirectColor or TrueColor modes, it generates pixel values directly from - * RGB values it calculates across each scan line. In PseudoColor mode, it - * consider each possible pattern of 5 preceding bit values in each possible - * position modulo 4 and allocates a color for each. A few things, like the - * brightening on the right side as the horizontal trace slows down, aren't - * done in PseudoColor. - * - * The text font is based on X's standard 6x10 font, with a few tweaks like - * putting a slash across the zero. - * - * I'd like to add a bit of visible retrace, but it conflicts with being able - * to bitcopy the image when fast scrolling. After another couple of CPU - * generations, we could probably regenerate the whole image from scratch every - * time. On a P4 2 GHz it can manage this fine for blinking text, but scrolling - * looks too slow. - */ - static char * apple2_basic_errors[]={ "BREAK", "NEXT WITHOUT FOR", @@ -2653,6 +2708,12 @@ static char * apple2_basic_errors[]={ "FORMULA TOO COMPLEX", "UNDEF'D FUNCTION", "OUT OF DATA" +#if 0 + , + "DEFAULT ARGUMENTS ARE NOT ALLOWED IN DECLARATION OF FRIEND " + "TEMPLATE SPECIALIZATION" +#endif + }; static char * apple2_dos_errors[]={ "VOLUME MISMATCH", @@ -2662,1403 +2723,223 @@ static char * apple2_dos_errors[]={ "PROGRAM TOO LARGE", }; -struct apple2_state { - char hireslines[192][40]; - char textlines[24][40]; - int gr_text; - enum { - A2_GR_FULL=1, - A2_GR_LORES=2, - A2_GR_HIRES=4 - } gr_mode; - int cursx; - int cursy; - int blink; - int rowimage[24]; -}; - -enum { - A2_SP_ROWMASK=1023, - A2_SP_PUT=1024, - A2_SP_COPY=2048 -}; - -static void -a2_scroll(struct apple2_state *st) +void a2controller_crash(apple2_sim_t *sim, int *stepno, + double *next_actiontime) { + apple2_state_t *st=sim->st; + char *s; int i; - int top=(st->gr_mode&(A2_GR_LORES|A2_GR_HIRES)) ? 20 : 0; - if ((st->gr_mode&A2_GR_FULL) && (st->gr_mode&A2_GR_HIRES)) return; - if (st->gr_mode&A2_GR_FULL) top=0; - for (i=top; i<23; i++) { - if (memcmp(st->textlines[i],st->textlines[i+1],40)) { - memcpy(st->textlines[i],st->textlines[i+1],40); - st->rowimage[i]=st->rowimage[i+1]; - } - } - memset(st->textlines[23],0xe0,40); - st->rowimage[23]=-1; -} -static void -a2_printc(struct apple2_state *st, char c) -{ - st->textlines[st->cursy][st->cursx] |= 0xc0; /* turn off blink */ - if (c=='\n') { - if (st->cursy==23) { - a2_scroll(st); - } else { - st->rowimage[st->cursy]=-1; - st->cursy++; - st->rowimage[st->cursy]=-1; - } - st->cursx=0; - } else { - st->textlines[st->cursy][st->cursx]=c ^ 0xc0; - st->rowimage[st->cursy]=-1; - st->cursx++; - if (st->cursx==40) { - if (st->cursy==23) { - a2_scroll(st); - } else { - st->rowimage[st->cursy]=-1; - st->cursy++; - st->rowimage[st->cursy]=-1; - } - st->cursx=0; - } - } - st->textlines[st->cursy][st->cursx] &= 0x7f; /* turn on blink */ -} + struct mydata { + int fillptr; + int fillbyte; + } *mine; -static void -a2_goto(struct apple2_state *st, int r, int c) -{ - st->textlines[st->cursy][st->cursx] |= 0xc0; /* turn off blink */ - st->cursy=r; - st->cursx=c; - st->textlines[st->cursy][st->cursx] &= 0x7f; /* turn on blink */ -} - -static void -a2_cls(struct apple2_state *st) -{ - int i; - for (i=0; i<24; i++) { - memset(st->textlines[i],0xe0,40); - st->rowimage[i]=-1; - } -} - -static void -a2_invalidate(struct apple2_state *st) -{ - int i; - for (i=0; i<24; i++) { - st->rowimage[i]=-1; - } -} - -static void -a2_poke(struct apple2_state *st, int addr, int val) -{ + if (!sim->controller_data) + sim->controller_data = calloc(sizeof(struct mydata),1); + mine=(struct mydata *) sim->controller_data; - if (addr>=0x400 && addr<0x800) { - /* text memory */ - int row=((addr&0x380)/0x80) + ((addr&0x7f)/0x28)*8; - int col=(addr&0x7f)%0x28; - if (row<24 && col<40) { - st->textlines[row][col]=val; - if (!(st->gr_mode&(A2_GR_HIRES)) || - (!(st->gr_mode&(A2_GR_FULL)) && row>=20)) { - st->rowimage[row]=-1; - } - } - } - else if (addr>=0x2000 && addr<0x4000) { - int row=(((addr&0x1c00) / 0x400) * 1 + - ((addr&0x0380) / 0x80) * 8 + - ((addr&0x0078) / 0x28) * 64); - int col=((addr&0x07f)%0x28); - if (row<192 && col<40) { - st->hireslines[row][col]=val; - if (st->gr_mode&A2_GR_HIRES) { - st->rowimage[row/8]=-1; - } - } - } -} - -/* This table lists fixes for characters that differ from the standard 6x10 - font. Each encodes a pixel, as (charindex*7 + x) + (y<<10) + (value<<15) - where value is 0 for white and 1 for black. */ -static unsigned short a2_fixfont[] = { - /* Fix $ */ 0x8421, 0x941d, - /* Fix % */ 0x8024, 0x0028, 0x8425, 0x0426, 0x0825, 0x1027, 0x1426, 0x9427, - 0x1824, 0x9828, - /* Fix * */ 0x8049, 0x8449, 0x8849, 0x0c47, 0x0c48, 0x0c4a, 0x0c4b, 0x9049, - 0x9449, 0x9849, - /* Fix , */ 0x9057, 0x1458, 0x9856, 0x1857, 0x1c56, - /* Fix . */ 0x1465, 0x1864, 0x1866, 0x1c65, - /* Fix / */ 0x006e, 0x186a, - /* Fix 0 */ 0x8874, 0x8c73, 0x9072, - /* Fix 1 */ 0x0878, 0x1878, 0x187c, - /* Fix 5 */ 0x8895, 0x0c94, 0x0c95, - /* Fix 6 */ 0x809f, 0x8c9c, 0x109c, - /* Fix 7 */ 0x8ca4, 0x0ca5, 0x90a3, 0x10a4, - /* Fix 9 */ 0x08b3, 0x8cb3, 0x98b0, - /* Fix : */ 0x04b9, 0x08b8, 0x08ba, 0x0cb9, 0x90b9, 0x14b9, 0x18b8, 0x18b9, - 0x18ba, 0x1cb9, - /* Fix ; */ 0x04c0, 0x08bf, 0x08c1, 0x0cc0, 0x90c0, 0x14c1, 0x98bf, 0x18c0, - 0x1cbf, - /* Fix < */ 0x80c8, 0x00c9, 0x84c7, 0x04c8, 0x88c6, 0x08c7, 0x8cc5, 0x0cc6, - 0x90c6, 0x10c7, - 0x94c7, 0x14c8, 0x98c8, 0x18c9, - /* Fix > */ 0x80d3, 0x00d4, 0x84d4, 0x04d5, 0x88d5, 0x08d6, 0x8cd6, 0x0cd7, - 0x90d5, 0x10d6, - 0x94d4, 0x14d5, 0x98d3, 0x18d4, - /* Fix @ */ 0x88e3, 0x08e4, 0x8ce4, 0x98e5, - /* Fix B */ 0x84ef, 0x04f0, 0x88ef, 0x08f0, 0x8cef, 0x90ef, 0x10f0, 0x94ef, - 0x14f0, - /* Fix D */ 0x84fd, 0x04fe, 0x88fd, 0x08fe, 0x8cfd, 0x0cfe, 0x90fd, 0x10fe, - 0x94fd, 0x14fe, - /* Fix G */ 0x8116, 0x0516, 0x9916, - /* Fix J */ 0x0129, 0x012a, 0x052a, 0x852b, 0x092a, 0x892b, 0x0d2a, 0x8d2b, - 0x112a, 0x912b, - 0x152a, 0x952b, 0x992a, - /* Fix M */ 0x853d, 0x853f, 0x093d, 0x893e, 0x093f, - /* Fix Q */ 0x915a, 0x155a, 0x955b, 0x155c, 0x195b, 0x995c, 0x1d5c, - /* Fix V */ 0x8d7b, 0x0d7c, 0x0d7e, 0x8d7f, 0x917b, 0x117c, 0x117e, 0x917f, - /* Fix [ */ 0x819e, 0x81a2, 0x859e, 0x899e, 0x8d9e, 0x919e, 0x959e, 0x999e, - 0x99a2, - /* Fix \ */ 0x01a5, 0x19a9, - /* Fix ] */ 0x81ac, 0x81b0, 0x85b0, 0x89b0, 0x8db0, 0x91b0, 0x95b0, 0x99ac, - 0x99b0, - /* Fix ^ */ 0x01b5, 0x05b4, 0x05b6, 0x09b3, 0x89b5, 0x09b7, 0x8db4, 0x8db6, - 0x91b3, 0x91b7, - /* Fix _ */ 0x9db9, 0x9dbf, - 0, -}; - -struct ntsc_dec { - char pattern[600]; - int ntscy[600]; - int ntsci[600]; - int ntscq[600]; - int multi[600]; - int multq[600]; - int brightness_control; -}; - -/* - First generate the I and Q reference signals, which we'll multiply by the - input signal to accomplish the demodulation. Normally they are shifted 33 - degrees from the colorburst. I think this was convenient for - inductor-capacitor-vacuum tube implementation. - - The tint control, FWIW, just adds a phase shift to the chroma signal, and - the color control controls the amplitude. - - In text modes (colormode==0) the system disabled the color burst, and no - color was detected by the monitor. - - freq_error gives a mismatch between the built-in oscillator and the TV's - colorbust. Older II Plus machines seemed to occasionally get instability - problems -- the crystal oscillator was a single transistor if I remember - correctly -- and the frequency would vary enough that the tint would change - across the width of the screen. The left side would be in correct tint - because it had just gotten resynchronized with the color burst. -*/ -static void -ntsc_set_demod(struct ntsc_dec *it, double tint_control, - double color_control, double brightness_control, - double freq_error, - int colormode) -{ - int i; - - it->brightness_control=(int)(1024.0*brightness_control); - - for (i=0; i<600; i++) { - double phase=90.0-90.0*i + freq_error*i/600.0 + tint_control; - it->multi[i]=(int)(-cos(3.1415926/180.0*(phase-303)) * 65536.0 * - color_control * colormode * 4); - it->multq[i]=(int)(cos(3.1415926/180.0*(phase-33)) * 65536.0 * - color_control * colormode * 4); - } -} - -/* Here we model the analog circuitry of an NTSC television. Basically, it - splits the signal into 3 signals: Y, I and Q. Y corresponds to luminance, - and you get it by low-pass filtering the input signal to below 3.57 MHz. - - I and Q are the in-phase and quadrature components of the 3.57 MHz - subcarrier. We get them by multiplying by cos(3.57 MHz*t) and sin(3.57 - MHz*t), and low-pass filtering. Because the eye has less resolution in some - colors than others, the I component gets low-pass filtered at 1.5 MHz and - the Q at 0.5 MHz. The I component is approximately orange-blue, and Q is - roughly purple-green. See http://www.ntsc-tv.com for details. - */ -static void -ntsc_to_yiq(struct ntsc_dec *it) -{ - int i; - int fyx[10],fyy[10]; - int fix[10],fiy[10]; - int fqx[10],fqy[10]; - int pixghost; - int iny,ini,inq,pix,blank; - - for (i=0; i<10; i++) fyx[i]=fyy[i]=fix[i]=fiy[i]=fqx[i]=fqy[i]=0.0; - pixghost=0; - for (i=0; i<600; i++) { - /* Get the video out signal, and add a teeny bit of ghosting, typical of RF - monitor cables. This corresponds to a pretty long cable, but looks right - to me. */ - pix=it->pattern[i]*1024; - if (i>=20) pixghost += it->pattern[i-20]*15; - if (i>=30) pixghost -= it->pattern[i-30]*15; - pix += pixghost; - - /* Get Y, I, Q before filtering */ - iny=pix; - ini=(pix*it->multi[i])>>16; - inq=(pix*it->multq[i])>>16; - - blank = (i>=7 && i<596 ? it->brightness_control : -200); - - /* Now filter them. These are infinite impulse response filters calculated - by the script at http://www-users.cs.york.ac.uk/~fisher/mkfilter. This - is fixed-point integer DSP, son. No place for wimps. We do it in integer - because you can count on integer being faster on most CPUs. We care - about speed because we need to recalculate every time we blink text, and - when we spew random bytes into screen memory. This is roughly 16.16 - fixed point arithmetic, but we scale some filter values up by a few bits - to avoid some nasty precision errors. */ - - /* Filter y at with a 4-pole low-pass Butterworth filter at 3.5 MHz - with an extra zero at 3.5 MHz, from - mkfilter -Bu -Lp -o 4 -a 2.1428571429e-01 0 -Z 2.5e-01 -l - Delay about 2 */ - - fyx[0] = fyx[1]; fyx[1] = fyx[2]; fyx[2] = fyx[3]; - fyx[3] = fyx[4]; fyx[4] = fyx[5]; fyx[5] = fyx[6]; - fyx[6] = (iny * 1897) >> 13; - fyy[0] = fyy[1]; fyy[1] = fyy[2]; fyy[2] = fyy[3]; - fyy[3] = fyy[4]; fyy[4] = fyy[5]; fyy[5] = fyy[6]; - fyy[6] = (fyx[0]+fyx[6]) + 4*(fyx[1]+fyx[5]) + 7*(fyx[2]+fyx[4]) + 8*fyx[3] - + ((-151*fyy[2] + 8115*fyy[3] - 38312*fyy[4] + 36586*fyy[5]) >> 16); - if (i>=2) it->ntscy[i-2] = blank + (fyy[6]>>3); - - /* Filter I and Q at 1.5 MHz. 3 pole Butterworth from - mkfilter -Bu -Lp -o 3 -a 1.0714285714e-01 0 - Delay about 3. - - The NTSC spec says the Q value should be filtered at 0.5 MHz at the - transmit end, But the Apple's video circuitry doesn't any such thing. - AFAIK, oldish televisions (before comb filters) simply applied a 1.5 MHz - filter to both after the demodulator. - */ - - fix[0] = fix[1]; fix[1] = fix[2]; fix[2] = fix[3]; - fix[3] = (ini * 1413) >> 14; - fiy[0] = fiy[1]; fiy[1] = fiy[2]; fiy[2] = fiy[3]; - fiy[3] = (fix[0]+fix[3]) + 3*(fix[1]+fix[2]) - + ((16559*fiy[0] - 72008*fiy[1] + 109682*fiy[2]) >> 16); - if (i>=3) it->ntsci[i-3] = fiy[3]>>2; - - fqx[0] = fqx[1]; fqx[1] = fqx[2]; fqx[2] = fqx[3]; - fqx[3] = (inq * 1413) >> 14; - fqy[0] = fqy[1]; fqy[1] = fqy[2]; fqy[2] = fqy[3]; - fqy[3] = (fqx[0]+fqx[3]) + 3*(fqx[1]+fqx[2]) - + ((16559*fqy[0] - 72008*fqy[1] + 109682*fqy[2]) >> 16); - if (i>=3) it->ntscq[i-3] = fqy[3]>>2; - - } - for (; i<610; i++) { - if (i-2<600) it->ntscy[i-2]=0; - if (i-3<600) it->ntsci[i-3]=0; - if (i-9<600) it->ntscq[i-9]=0; - } -} - -enum { - A2_CMAP_HISTBITS=5, - A2_CMAP_LEVELS=2, - A2_CMAP_OFFSETS=4 -}; - -#define A2_CMAP_INDEX(COLORMODE, LEVEL, HIST, OFFSET) \ -((((COLORMODE)*A2_CMAP_LEVELS+(LEVEL))<class; - red_shift=red_invprec=green_shift=green_invprec=blue_shift=blue_invprec=-1; - if (visclass == TrueColor || xgwa.visual->class == DirectColor) { - use_cmap=0; - use_color=!mono_p; - } - else if (visclass == PseudoColor || visclass == StaticColor) { - use_cmap=1; - use_color=!mono_p; - } - else { - use_cmap=1; - use_color=0; - } - - /* The Apple II screen was 280x192, sort of. We expand the width to 300 - pixels to allow for overscan. We then pick a size within the window - that's an integer multiple of 300x192. The small case happens when - we're displaying in a subwindow. Then it ends up showing the center - of the screen, which is OK. */ - w=xgwa.width; - h = (xgwa.height/192)*192; - if (w<300) w=300; - if (h==0) h=192; - - dec=(struct ntsc_dec *)malloc(sizeof(struct ntsc_dec)); - - if (use_cmap) { - int hist,offset,level; - int colorprec=8; - - cmap_again: - n_colors=0; - /* Typically allocates 214 distinct colors, but will scale back its - ambitions pretty far if it can't get them */ - for (colormode=0; colormode<=use_color; colormode++) { - ntsc_set_demod(dec, tint_control, color_control, brightness_control, - 0.0, colormode); - for (level=0; level<2; level++) { - for (hist=0; hist<(1<dec->powerup = 1000.0; - for (i=0; i<600; i++) dec->pattern[i]=0; - for (i=0; ipattern[64+offset-i]=(hist>>i)&1; - } - - ntsc_to_yiq(dec); - interpy=dec->ntscy[63+offset]; - interpi=dec->ntsci[63+offset]; - interpq=dec->ntscq[63+offset]; - - r=(interpy + ((+68128*interpi+40894*interpq)>>16))*levelmult; - g=(interpy + ((-18087*interpi-41877*interpq)>>16))*levelmult; - b=(interpy + ((-72417*interpi+113312*interpq)>>16))*levelmult; - if (r<0) r=0; - if (r>65535) r=65535; - if (g<0) g=0; - if (g>65535) g=65535; - if (b<0) b=0; - if (b>65535) b=65535; - - col.red=r & precmask; - col.green=g & precmask; - col.blue=b & precmask; - col.pixel=0; - if (!XAllocColor(dpy, xgwa.colormap, &col)) { - XFreeColors(dpy, xgwa.colormap, colors, n_colors, 0L); - n_colors=0; - colorprec--; - if (colorprec<3) { - goto bailout; - } - goto cmap_again; - } - colors[n_colors++]=col.pixel; - } - } - } + if (random()%3==0) { + st->gr_mode=0; + *next_actiontime+=0.4; + *stepno=100; } - } else { - /* Is there a standard way to do this? Does this handle all cases? */ - int shift, prec; - for (shift=0; shift<32; shift++) { - for (prec=1; prec<16 && prec<32-shift; prec++) { - unsigned long mask=(0xffffUL>>(16-prec)) << shift; - if (red_shift<0 && mask==xgwa.visual->red_mask) - red_shift=shift, red_invprec=16-prec; - if (green_shift<0 && mask==xgwa.visual->green_mask) - green_shift=shift, green_invprec=16-prec; - if (blue_shift<0 && mask==xgwa.visual->blue_mask) - blue_shift=shift, blue_invprec=16-prec; - } + else if (random()%4==0) { + st->gr_mode=A2_GR_LORES; + if (random()%3==0) st->gr_mode |= A2_GR_FULL; + *next_actiontime+=0.4; + *stepno=100; } - if (red_shift<0 || green_shift<0 || blue_shift<0) { - if (0) fprintf(stderr,"Can't figure out color space\n"); - goto bailout; + else if (random()%2==0) { + st->gr_mode=A2_GR_HIRES; + *stepno=300; } - raw_rgb=(short *)calloc(w*3, sizeof(short)); - } - - gcv.background=0; - gc = XCreateGC(dpy, window, GCBackground, &gcv); - XSetWindowBackground(dpy, window, gcv.background); - XClearWindow(dpy,window); - - screen_xo=(xgwa.width-w)/2; - screen_yo=(xgwa.height-h)/2; - - if (use_shm) { -#ifdef HAVE_XSHM_EXTENSION - image = create_xshm_image (dpy, xgwa.visual, xgwa.depth, ZPixmap, 0, - &shm_info, w, h); -#endif - if (!image) { - fprintf(stderr, "create_xshm_image failed\n"); - use_shm=0; + else { + st->gr_mode=A2_GR_HIRES; + *next_actiontime+=0.4; + *stepno=100; } - } - if (!image) { - image = XCreateImage(dpy, xgwa.visual, xgwa.depth, ZPixmap, 0, 0, - w, h, 8, 0); - image->data = (char *)calloc(image->height, image->bytes_per_line); - } - - st=(struct apple2_state *)calloc(1,sizeof(struct apple2_state)); - - /* - Generate the font. It used a 5x7 font which looks a lot like the standard X - 6x10 font, with a few differences. So we render up all the uppercase - letters of 6x10, and make a few tweaks (like putting a slash across the - zero) according to fixfont. - */ - { - const char *def_font="6x10"; - XFontStruct *font; - Pixmap text_pm; - GC gc; - - font = XLoadQueryFont (dpy, def_font); - if (!font) { - fprintf(stderr,"Can't load font %s\n",def_font); - goto bailout; - } - - text_pm=XCreatePixmap(dpy, window, 64*7, 8, xgwa.depth); - - gcv.foreground=1; - gcv.background=0; - gcv.font=font->fid; - gc=XCreateGC(dpy, text_pm, GCFont|GCBackground|GCForeground, &gcv); - - XSetForeground(dpy, gc, 0); - XFillRectangle(dpy, text_pm, gc, 0, 0, 64*7, 8); - XSetForeground(dpy, gc, 1); - for (i=0; i<64; i++) { - char c=32+i; - int x=7*i+1; - int y=7; - if (c=='0') { - c='O'; - XDrawString(dpy, text_pm, gc, x, y, &c, 1); + break; + + case 100: + /* An illegal instruction or a reset caused it to drop into the + assembly language monitor, where you could disassemble code & view + data in hex. */ + if (random()%3==0) { + char ibytes[128]; + char itext[128]; + int addr=0xd000+random()%0x3000; + sprintf(ibytes, + "%02X",random()%0xff); + sprintf(itext, + "???"); + sprintf(sim->printing_buf, + "\n\n" + "%04X: %-15s %s\n" + " A=%02X X=%02X Y=%02X S=%02X F=%02X\n" + "*", + addr,ibytes,itext, + random()%0xff, random()%0xff, + random()%0xff, random()%0xff, + random()%0xff); + sim->printing=sim->printing_buf; + a2_goto(st,23,1); + if (st->gr_mode) { + *stepno=180; } else { - XDrawString(dpy, text_pm, gc, x, y, &c, 1); + *stepno=200; } + sim->prompt='*'; + *next_actiontime += 2.0 + (random()%1000)*0.0002; } - text_im = XGetImage(dpy, text_pm, 0, 0, 64*7, 8, ~0L, ZPixmap); - XFreeGC(dpy, gc); - XFreePixmap(dpy, text_pm); - - for (i=0; a2_fixfont[i]; i++) { - XPutPixel(text_im, a2_fixfont[i]&0x3ff, - (a2_fixfont[i]>>10)&0xf, - (a2_fixfont[i]>>15)&1); - } - } - - /* - Simulate plausible initial memory contents. - */ - { - int addr=0; - while (addr<0x4000) { - int n; - - switch (random()%4) { - case 0: - case 1: - n=random()%500; - for (i=0; iwidth); - for (i=0; i<100; i++) { - for (y=0; y<8; y++) { - c=0; - for (j=0; j<8; j++) { - c |= XGetPixel(text_im, (x+j)%text_im->width, y)<width); - } - break; - - case 3: - if (addr>0x2000) { - n=random()%200; - for (i=0; iprinting_buf, + "\n" + "\n" + "\n" + "?%s IN %d\n" + "\001]", + apple2_basic_errors[random() % + (sizeof(apple2_basic_errors) + /sizeof(char *))], + (1000*(random()%(random()%59+1)) + + 100*(random()%(random()%9+1)) + + 5*(random()%(random()%199+1)) + + 1*(random()%(random()%(random()%2+1)+1)))); + sim->printing=sim->printing_buf; + a2_goto(st,23,1); + *stepno=110; + sim->prompt=']'; + *next_actiontime += 2.0 + (random()%1000)*0.0002; } - } - - if (random()%4==0 && - !use_cmap && use_color && - xgwa.visual->bits_per_rgb>=8) { - flutter_tint=1; - } - else if (random()%3==0) { - flutter_horiz_desync=1; - } - - crtload[0]=0.0; - stepno=0; - a2_goto(st,23,0); - gettimeofday(&basetime_tv, NULL); - if (random()%2==0) basetime_tv.tv_sec -= 1; /* random blink phase */ - next_actiontime=0.0; - fillptr=fillbyte=0; - while (1) { - double curtime,blinkphase; - int startdisplayrow=0; - int cheapdisplay=0; - int nodelay=0; - { - struct timeval curtime_tv; - gettimeofday(&curtime_tv, NULL); - curtime=(curtime_tv.tv_sec - basetime_tv.tv_sec) + - 0.000001*(curtime_tv.tv_usec - basetime_tv.tv_usec); + break; + + case 110: + if (random()%3==0) { + /* This was how you reset the Basic interpreter. The sort of + incantation you'd have on a little piece of paper taped to the + side of your machine */ + sim->typing="CALL -1370"; + *stepno=120; } - if (curtime>delay) goto finished; - - if (bsod_sleep(dpy,0)) goto finished; - - if (flutter_tint && st->gr_mode && !printing) { - /* Oscillator instability. Look for freq_error below. We should only do - this with color depth>=8, since otherwise you see pixels changing. */ - freq_error_inc += (-0.10*freq_error_inc - + ((int)(random()&0xff)-0x80) * 0.01); - freq_error += freq_error_inc; - a2_invalidate(st); - nodelay=1; + else if (random()%2==0) { + sim->typing="CATALOG\n"; + *stepno=170; } - else if (flutter_horiz_desync) { - /* Horizontal sync during vertical sync instability. */ - horiz_desync += (-0.10*(horiz_desync-3.0) + - ((int)(random()&0xff)-0x80) * - ((int)(random()&0xff)-0x80) * - ((int)(random()&0xff)-0x80) * 0.0000003); - for (i=0; i<3; i++) st->rowimage[i]=-1; - nodelay=1; - } - - /* It's super-important to get the cursor/text flash out at exactly the - right time, or it looks wrong. So if we're almost due for a blink, wait - for it so we don't miss it in the middle of a screen update. */ - blinkphase=curtime/0.8; - if (blinkphase-floor(blinkphase)>0.7 && !printing && !nodelay) { - /* We're about to blink */ - int delay = ((1.0-(blinkphase-floor(blinkphase)))*0.8) * 1000000; - if (delay<1000) delay=1000; - usleep(delay); - continue; + else { + *next_actiontime+=1.0; + *stepno=999; } - - /* The blinking rate was controlled by 555 timer with a resistor/capacitor - time constant. Because the capacitor was electrolytic, the flash rate - varied somewhat between machines. I'm guessing 1.6 seconds/cycle was - reasonable. (I soldered a resistor in mine to make it blink faster.) */ - i=st->blink; - st->blink=((int)blinkphase)&1; - if (st->blink!=i && !(st->gr_mode&A2_GR_FULL)) { - int downcounter=0; - /* For every row with blinking text, set the changed flag. This basically - works great except with random screen garbage in text mode, when we - end up redrawing the whole screen every second */ - for (row=(st->gr_mode ? 20 : 0); row<24; row++) { - for (col=0; col<40; col++) { - c=st->textlines[row][col]; - if ((c & 0xc0) == 0x40) { - downcounter=4; - break; - } - } - if (downcounter>0) { - st->rowimage[row]=-1; - downcounter--; - } - } - st->rowimage[st->cursy]=-1; - startdisplayrow=random()%24; - } - else if (next_actiontime > curtime && !printing && !nodelay) { - int delay = (next_actiontime-curtime)*1000000; - - if (delay>100000) delay=100000; - if (delay<1000) delay=1000; - usleep(delay); - continue; + break; + + case 120: + *stepno=130; + *next_actiontime += 0.5; + break; + + case 130: + st->gr_mode=0; + a2_cls(st); + a2_goto(st,0,16); + for (s="APPLE ]["; *s; s++) a2_printc(st,*s); + a2_goto(st,23,0); + a2_printc(st,']'); + *next_actiontime+=1.0; + *stepno=999; + break; + + case 170: + if (random()%50==0) { + sprintf(sim->printing_buf, + "\nDISK VOLUME 254\n\n" + " A 002 HELLO\n" + "\n" + "]"); + sim->printing=sim->printing_buf; } - - if (printing) { - cheapdisplay=1; - while (*printing) { - if (*printing=='\001') { /* pause */ - printing++; - for (i=20; i<24; i++) st->rowimage[i]=-1; - break; - } - else if (*printing=='\n') { - a2_printc(st,*printing); - printing++; - break; - } - else { - a2_printc(st,*printing); - printing++; - } - } - if (!*printing) printing=NULL; + else { + sprintf(sim->printing_buf,"\n?%s\n]", + apple2_dos_errors[random()% + (sizeof(apple2_dos_errors) / + sizeof(char *))]); + sim->printing=sim->printing_buf; } - else if (curtime >= next_actiontime) { - if (typing) { - /* If we're in the midst of typing a string, emit a character with - random timing. */ - a2_printc(st, *typing); - if (*typing=='\n') { - next_actiontime = curtime; - } else { - next_actiontime = curtime + (random()%1000)*0.0003 + 0.3; - } - typing++; - - if (!*typing) typing=NULL; - - } - else { - next_actiontime=curtime; - - switch(stepno) { - case 0: - a2_invalidate(st); - if (0) { - /* - For testing color rendering. The spec is: - red grn blu - 0 black 0 0 0 - 1 red 227 30 96 - 2 dk blue 96 78 189 - 3 purple 255 68 253 - 4 dk green 0 163 96 - 5 gray 156 156 156 - 6 med blue 20 207 253 - 7 lt blue 208 195 255 - 8 brown 96 114 3 - 9 orange 255 106 60 - 10 grey 156 156 156 - 11 pink 255 160 208 - 12 lt green 20 245 60 - 13 yellow 208 221 141 - 14 aqua 114 255 208 - 15 white 255 255 255 - */ - st->gr_mode=A2_GR_LORES; - for (row=0; row<24; row++) { - for (col=0; col<40; col++) { - st->textlines[row][col]=(row&15)*17; - } - } - next_actiontime+=0.4; - stepno=88; - } - else if (random()%3==0) { - st->gr_mode=0; - next_actiontime+=0.4; - stepno=88; - } - else if (random()%4==0) { - st->gr_mode=A2_GR_LORES; - if (random()%3==0) st->gr_mode |= A2_GR_FULL; - next_actiontime+=0.4; - stepno=88; - } - else if (random()%2==0) { - st->gr_mode=A2_GR_HIRES; - stepno=73; - } - else { - st->gr_mode=A2_GR_HIRES; - next_actiontime+=0.4; - stepno=88; - } - break; - - case 88: - /* An illegal instruction or a reset caused it to drop into the - assembly language monitor, where you could disassemble code & view - data in hex. */ - if (random()%3==0) { - char ibytes[128]; - char itext[128]; - int addr=0xd000+random()%0x3000; - sprintf(ibytes, - "%02X",random()%0xff); - sprintf(itext, - "???"); - sprintf(printbuf, - "\n\n" - "%04X: %-15s %s\n" - " A=%02X X=%02X Y=%02X S=%02X F=%02X\n" - "*", - addr,ibytes,itext, - random()%0xff, random()%0xff, - random()%0xff, random()%0xff, - random()%0xff); - printing=printbuf; - a2_goto(st,23,1); - if (st->gr_mode) { - stepno=11; - } else { - stepno=13; - } - prompt='*'; - next_actiontime += 2.0 + (random()%1000)*0.0002; - } - else { - /* Lots of programs had at least their main functionality in - Applesoft Basic, which had a lot of limits (memory, string - length, etc) and would sometimes crash unexpectedly. */ - sprintf(printbuf, - "\n" - "\n" - "\n" - "?%s IN %d\n" - "\001]", - apple2_basic_errors[random() % - (sizeof(apple2_basic_errors) - /sizeof(char *))], - (1000*(random()%(random()%59+1)) + - 100*(random()%(random()%9+1)) + - 5*(random()%(random()%199+1)) + - 1*(random()%(random()%(random()%2+1)+1)))); - printing=printbuf; - a2_goto(st,23,1); - stepno=1; - prompt=']'; - next_actiontime += 2.0 + (random()%1000)*0.0002; - } - break; - - case 1: - if (simulate_user && random()%3==0) { - /* This was how you reset the Basic interpreter. The sort of - incantation you'd have on a little piece of paper taped to the - side of your machine */ - typing="CALL -1370"; - stepno=2; - } - else if (simulate_user && random()%2==0) { - typing="CATALOG\n"; - stepno=22; - } - else { - next_actiontime+=1.0; - stepno=6; - } - break; - - case 2: - stepno=3; - next_actiontime += 0.5; - break; - - case 3: - st->gr_mode=0; - a2_cls(st); - a2_goto(st,0,16); - for (s="APPLE ]["; *s; s++) a2_printc(st,*s); - a2_goto(st,23,0); - a2_printc(st,']'); - next_actiontime+=1.0; - stepno=6; - break; - - case 6: - if (simulate_user && random()%50==0 && 0) { /* disabled, too goofy */ - typing="10 PRINT \"TRS-80S SUCK!!!\"\n" - "]20 GOTO 10\n" - "]RUN"; - stepno=7; - } - else { - stepno=8; - next_actiontime += delay; - } - break; - - case 7: - for (i=0; i<30; i++) { - for (s="\nTRS-80S SUCK"; *s; s++) a2_printc(st,*s); - } - stepno=8; - next_actiontime+=delay; - - case 8: - break; - - case 22: - if (random()%50==0) { - sprintf(printbuf,"\nDISK VOLUME 254\n\n" - " A 002 HELLO\n" - "\n" - "]"); - printing=printbuf; - } - else { - sprintf(printbuf,"\n?%s\n]", - apple2_dos_errors[random()% - (sizeof(apple2_dos_errors) / - sizeof(char *))]); - printing=printbuf; - } - stepno=6; - next_actiontime+=1.0; - break; - - case 11: - if (simulate_user && random()%2==0) { - /* This was how you went back to text mode in the monitor */ - typing="FB4BG"; - stepno=12; - } else { - next_actiontime+=1.0; - stepno=6; - } - break; - - case 12: - st->gr_mode=0; - a2_invalidate(st); - a2_printc(st,'\n'); - a2_printc(st,'*'); - stepno=13; - next_actiontime+=2.0; - break; - - case 13: - /* This reset things into Basic */ - if (simulate_user && random()%2==0) { - typing="FAA6G"; - stepno=2; - } - else { - stepno=8; - next_actiontime+=delay; - } - break; - - case 73: - for (i=0; i<1500; i++) { - a2_poke(st, fillptr, fillbyte); - fillptr++; - fillbyte = (fillbyte+1)&0xff; - } - next_actiontime += 0.08; - /* When you hit c000, it changed video settings */ - if (fillptr>=0xc000) { - a2_invalidate(st); - st->gr_mode=0; - } - /* And it seemed to reset around here, I dunno why */ - if (fillptr>=0xcf00) stepno=3; - break; - } - } + *stepno=999; + *next_actiontime+=1.0; + break; + + case 180: + if (random()%2==0) { + /* This was how you went back to text mode in the monitor */ + sim->typing="FB4BG"; + *stepno=190; + } else { + *next_actiontime+=1.0; + *stepno=999; } - - /* Now, we turn the data in the Apple II video into a screen display. This - is interesting because of the interaction with the NTSC color decoding - in a color television. */ - - colormode=use_color && st->gr_mode!=0; - if (!use_cmap) { - ntsc_set_demod(dec, tint_control, color_control, brightness_control, - freq_error, colormode); + break; + + case 190: + st->gr_mode=0; + a2_invalidate(st); + a2_printc(st,'\n'); + a2_printc(st,'*'); + *stepno=200; + *next_actiontime+=2.0; + break; + + case 200: + /* This reset things into Basic */ + if (random()%2==0) { + sim->typing="FAA6G"; + *stepno=120; } - imgrow=0; - for (textrow=0; textrow<24; textrow++) { - if (st->rowimage[textrow] == textrow) { - screen_plan[textrow]=0; - } - else if (cheapdisplay && st->rowimage[textrow]>=0 && - textrow<21 && st->rowimage[textrow]<21 && - st->rowimage[textrow]>=2 && textrow>=2 && - (st->rowimage[textrow]+1)*h/24 + screen_xo <= xgwa.height) { - screen_plan[textrow]= A2_SP_COPY | st->rowimage[textrow]; - for (i=0; i<8; i++) { - crtload[textrow*8+i]=crtload[st->rowimage[textrow]*8+i]; - } - startdisplayrow=0; - } - else { - st->rowimage[textrow]=imgrow; - screen_plan[textrow]=imgrow | A2_SP_PUT; - - for (row=textrow*8; rowpattern,0,sizeof(dec->pattern)); - pp=dec->pattern+20; - - if ((st->gr_mode&A2_GR_HIRES) && (row<160 || - (st->gr_mode&A2_GR_FULL))) { - - /* Emulate the mysterious pink line, due to a bit getting - stuck in a shift register between the end of the last - row and the beginning of this one. */ - if ((st->hireslines[row][0] & 0x80) && - (st->hireslines[row][39]&0x40)) { - pp[-1]=1; - } - - for (col=0; col<40; col++) { - u_char b=st->hireslines[row][col]; - int shift=(b&0x80)?0:1; - - /* Each of the low 7 bits in hires mode corresponded to 2 dot - clocks, shifted by one if the high bit was set. */ - for (i=0; i<7; i++) { - pp[shift+1] = pp[shift] =(b>>i)&1; - pp+=2; - } - } - } - else if ((st->gr_mode&A2_GR_LORES) && (row<160 || - (st->gr_mode&A2_GR_FULL))) { - for (col=0; col<40; col++) { - u_char nib=(st->textlines[textrow][col] >> (((row/4)&1)*4))&0xf; - /* The low or high nybble was shifted out one bit at a time. */ - for (i=0; i<14; i++) { - *pp = (nib>>((col*14+i)&3))&1; - pp++; - } - } - } - else { - for (col=0; col<40; col++) { - int rev; - c=st->textlines[textrow][col]; - /* hi bits control inverse/blink as follows: - 0x00: inverse - 0x40: blink - 0x80: normal - 0xc0: normal */ - rev=!(c&0x80) && (!(c&0x40) || st->blink); - - for (i=0; i<7; i++) { - for (i=0; i<7; i++) { - unsigned long pix=XGetPixel(text_im, - ((c&0x3f)^0x20)*7+i, row%8); - pp[1] = pp[2] = pix^rev; - pp+=2; - } - } - } - } - - /* - Interpolate the 600-dotclock line into however many horizontal - screen pixels we're using, and convert to RGB. - - We add some 'bloom', variations in the horizontal scan width with - the amount of brightness, extremely common on period TV sets. They - had a single oscillator which generated both the horizontal scan - and (during the horizontal retrace interval) the high voltage for - the electron beam. More brightness meant more load on the - oscillator, which caused an decrease in horizontal deflection. Look - for (bloomthisrow). - - Also, the A2 did a bad job of generating horizontal sync pulses - during the vertical blanking interval. This, and the fact that the - horizontal frequency was a bit off meant that TVs usually went a - bit out of sync during the vertical retrace, and the top of the - screen would be bent a bit to the left or right. Look for - (shiftthisrow). - - We also add a teeny bit of left overscan, just enough to be - annoying, but you can still read the left column of text. - - We also simulate compression & brightening on the right side of the - screen. Most TVs do this, but you don't notice because they - overscan so it's off the right edge of the CRT. But the A2 video - system used so much of the horizontal scan line that you had to - crank the horizontal width down in order to not lose the right few - characters, and you'd see the compression on the right - edge. Associated with compression is brightening; since the - electron beam was scanning slower, the same drive signal hit the - phosphor harder. Look for (squishright_i) and (squishdiv). - */ - - for (i=j=0; i<600; i++) { - j += dec->pattern[i]; - } - crtload[row] = (crtload[row>1 ? row-1 : 0]) * 0.98 + 0.02*(j/600.0) + - (row>180 ? (row-180)*(row-180)*0.0005 : 0.0); - bloomthisrow = -10.0 * crtload[row]; - shiftthisrow=((row<18) ? ((18-row)*(18-row)* 0.002 + (18-row)*0.05) - * horiz_desync : 0.0); - - scanstart_i=(int)((bloomthisrow+shiftthisrow+18.0)*65536.0); - if (scanstart_i<0) scanstart_i=0; - if (scanstart_i>30*65536) scanstart_i=30*65536; - scanend_i=599*65536; - squishright_i=scanstart_i + 530*65536; - squishdiv=w/15; - pixrate=(int)((560.0-2.0*bloomthisrow)*65536.0/w); - - if (use_cmap) { - for (y=ytop; y=3) && - !(y==ybot-1 && ybot-ytop>=5)); - int hist=0; - int histi=0; - - pixmultinc=pixrate; - for (x=0, i=scanstart_i; - x>16); - int offset=pati&3; - while (pati>=histi) { - hist=(((hist<<1) & ((1<pattern[histi]); - histi++; - } - XPutPixel(image, x, y, - colors[A2_CMAP_INDEX(colormode,level,hist,offset)]); - if (i >= squishright_i) { - pixmultinc += pixmultinc/squishdiv; - } - } - for ( ; x>16; - int r,g,b; - - int interpy=((dec->ntscy[pati]*invpixfrac + - dec->ntscy[pati+1]*pixfrac)>>16); - int interpi=((dec->ntsci[pati]*invpixfrac + - dec->ntsci[pati+1]*pixfrac)>>16); - int interpq=((dec->ntscq[pati]*invpixfrac + - dec->ntscq[pati+1]*pixfrac)>>16); - - /* - According to the NTSC spec, Y,I,Q are generated as: - - y=0.30 r + 0.59 g + 0.11 b - i=0.60 r - 0.28 g - 0.32 b - q=0.21 r - 0.52 g + 0.31 b - - So if you invert the implied 3x3 matrix you get what standard - televisions implement with a bunch of resistors (or directly in - the CRT -- don't ask): - - r = y + 0.948 i + 0.624 q - g = y - 0.276 i - 0.639 q - b = y - 1.105 i + 1.729 q - - These coefficients are below in 16.16 format. - */ - - r=((interpy + ((+68128*interpi+40894*interpq)>>16))*pixbright) - >>16; - g=((interpy + ((-18087*interpi-41877*interpq)>>16))*pixbright) - >>16; - b=((interpy + ((-72417*interpi+113312*interpq)>>16))*pixbright) - >>16; - if (r<0) r=0; - if (g<0) g=0; - if (b<0) b=0; - rrp[0]=r; - rrp[1]=g; - rrp[2]=b; - - if (i>=squishright_i) { - pixmultinc += pixmultinc/squishdiv; - pixbright += pixbright/squishdiv; - } - } - for ( ; xformat==ZPixmap && image->bits_per_pixel==32 && - sizeof(unsigned long)==4 && - image->byte_order==localbyteorder) { - unsigned long *pixelptr = - (unsigned long *) (image->data + y * image->bytes_per_line); - for (x=0, rrp=raw_rgb; x65535) ntscri=65535; - if (ntscgi>65535) ntscgi=65535; - if (ntscbi>65535) ntscbi=65535; - *pixelptr++ = ((ntscri>>red_invprec)<>green_invprec)<>blue_invprec)<format==ZPixmap && image->bits_per_pixel==16 && - sizeof(unsigned short)==2 && - image->byte_order==localbyteorder) { - unsigned short *pixelptr = - (unsigned short *)(image->data + y*image->bytes_per_line); - for (x=0, rrp=raw_rgb; x65535) ntscri=65535; - if (ntscgi>65535) ntscgi=65535; - if (ntscbi>65535) ntscbi=65535; - *pixelptr++ = ((ntscri>>red_invprec)<>green_invprec)<>blue_invprec)<65535) ntscri=65535; - if (ntscgi>65535) ntscgi=65535; - if (ntscbi>65535) ntscbi=65535; - pixel = ((ntscri>>red_invprec)<>green_invprec)<>blue_invprec)<delay; } + break; - /* For just the the rows which changed, blit the image to the screen. */ - for (textrow=0; textrow<24; ) { - int top,bot,srcrow,srctop,nrows; - - nrows=1; - while (textrow+nrows < 24 && - screen_plan[textrow+nrows] == screen_plan[textrow]+nrows) - nrows++; - - top=h*textrow/24; - bot=h*(textrow+nrows)/24; - srcrow=screen_plan[textrow]&A2_SP_ROWMASK; - srctop=srcrow*h/24; - - if (screen_plan[textrow] & A2_SP_COPY) { - if (0) printf("Copy %d screenrows %d to %d\n", nrows, srcrow, textrow); - XCopyArea(dpy, window, window, gc, - screen_xo, screen_yo + srctop, - w, bot-top, - screen_xo, screen_yo + top); - } - else if (screen_plan[textrow] & A2_SP_PUT) { - if (0) printf("Draw %d imgrows %d to %d\n", nrows, srcrow, textrow); - if (use_shm) { -#ifdef HAVE_XSHM_EXTENSION - XShmPutImage(dpy, window, gc, image, - 0, srctop, screen_xo, screen_yo + top, - w, bot-top, False); -#endif - } else { - XPutImage(dpy, window, gc, image, - 0, srctop, - screen_xo, screen_yo + top, - w, bot-top); - } - } - textrow += nrows; + case 300: + for (i=0; i<1500; i++) { + a2_poke(st, mine->fillptr, mine->fillbyte); + mine->fillptr++; + mine->fillbyte = (mine->fillbyte+1)&0xff; } - XSync(dpy,0); - - for (textrow=0; textrow<24; textrow++) { - st->rowimage[textrow]=textrow; + *next_actiontime += 0.08; + /* When you hit c000, it changed video settings */ + if (mine->fillptr>=0xc000) { + a2_invalidate(st); + st->gr_mode=0; } - } + /* And it seemed to reset around here, I dunno why */ + if (mine->fillptr>=0xcf00) *stepno=130; + break; - finished: - XSync(dpy,False); - XClearWindow(dpy, window); - goto cleanup; - - bailout: - ; + case 999: + break; - cleanup: - if (image) { - if (use_shm) { -#ifdef HAVE_XSHM_EXTENSION - destroy_xshm_image(dpy, image, &shm_info); -#endif - } else { - XDestroyImage(image); - } - image=NULL; + case A2CONTROLLER_FREE: + free(mine); + break; } - if (text_im) XDestroyImage(text_im); - if (gc) XFreeGC(dpy, gc); - if (st) free(st); - if (raw_rgb) free(raw_rgb); - if (dec) free(dec); - if (n_colors) XFreeColors(dpy, xgwa.colormap, colors, n_colors, 0L); } +static void +apple2crash (Display* dpy, Window window, int delay) +{ + apple2 (dpy, window, delay, a2controller_crash); +} - char *progclass = "BSOD"; char *defaults [] = { @@ -4084,6 +2965,7 @@ char *defaults [] = { "*doApple2: True", "*doOS390: True", "*doVMS: True", + "*doHVX: True", ".Windows.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*", ".Windows.font2: -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*", @@ -4124,6 +3006,11 @@ char *defaults [] = { ".SCO.foreground: White", ".SCO.background: Black", + ".HVX.font: -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*", + ".HVX.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", + ".HVX.foreground: White", + ".HVX.background: Black", + ".Linux.font: 9x15bold", ".Linux.font2: -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*", ".Linux.foreground: White", @@ -4168,6 +3055,8 @@ char *defaults [] = { ".VMS.foreground: White", ".VMS.background: Black", + ANALOGTV_DEFAULTS + #ifdef HAVE_XSHM_EXTENSION "*useSHM: True", #endif @@ -4199,6 +3088,8 @@ XrmOptionDescRec options [] = { { "-no-apple2", ".doApple2", XrmoptionNoArg, "False" }, { "-sco", ".doSCO", XrmoptionNoArg, "True" }, { "-no-sco", ".doSCO", XrmoptionNoArg, "False" }, + { "-hvx", ".doHVX", XrmoptionNoArg, "True" }, + { "-no-hvx", ".doHVX", XrmoptionNoArg, "False" }, { "-bsd", ".doBSD", XrmoptionNoArg, "True" }, { "-no-bsd", ".doBSD", XrmoptionNoArg, "False" }, { "-linux", ".doLinux", XrmoptionNoArg, "True" }, @@ -4215,6 +3106,7 @@ XrmOptionDescRec options [] = { { "-no-os390", ".doOS390", XrmoptionNoArg, "False" }, { "-vms", ".doVMS", XrmoptionNoArg, "True" }, { "-no-vms", ".doVMS", XrmoptionNoArg, "False" }, + ANALOGTV_OPTIONS { 0, 0, 0, 0 } }; @@ -4224,14 +3116,15 @@ static struct { void (*fn) (Display *, Window, int delay); } all_modes[] = { { "Windows", windows_31 }, - { "Nt", windows_nt }, - { "2k", windows_2k }, + { "NT", windows_nt }, + { "Win2K", windows_2k }, { "Amiga", amiga }, { "Mac", mac }, { "MacsBug", macsbug }, { "Mac1", mac1 }, { "MacX", macx }, { "SCO", sco }, + { "HVX", hvx }, { "SparcLinux", sparc_linux }, { "BSD", bsd }, { "Atari", atari }, @@ -4240,7 +3133,7 @@ static struct { { "Linux", linux_fsck }, { "HPUX", hpux }, { "OS390", os390 }, - { "Apple2", apple2 }, + { "Apple2", apple2crash }, { "VMS", vms }, }; @@ -4277,7 +3170,8 @@ screenhack (Display *dpy, Window window) XWindowAttributes xgwa; XGetWindowAttributes (dpy, window, &xgwa); XSelectInput (dpy, window, - xgwa.your_event_mask | KeyPressMask | ButtonPressMask); + xgwa.your_event_mask | + KeyPressMask | ButtonPressMask | ExposureMask); } while (1)