- int visclass;
- int screen_xo,screen_yo;
- XImage *image=NULL;
- XGCValues gcv;
- GC gc=NULL;
- XImage *text_im=NULL;
- unsigned long colors[A2_CMAP_INDEX(1, A2_CMAP_LEVELS-1,
- (1<<A2_CMAP_HISTBITS)-1,
- A2_CMAP_OFFSETS-3)+1];
- int n_colors=0;
- int screen_plan[24];
- struct ntsc_dec *dec=NULL;
- short *raw_rgb=NULL, *rrp;
- struct apple2_state *st=NULL;
- char *typing=NULL,*printing=NULL;
- char printbuf[1024];
- char prompt=']';
- int simulate_user;
- double tint_control,color_control,brightness_control,contrast_control;
- double freq_error=0.0,freq_error_inc=0.0;
- double horiz_desync=5.0;
- int flutter_horiz_desync=0;
- int flutter_tint=0;
- double crtload[192];
- int red_invprec,red_shift,green_invprec,green_shift,blue_invprec,blue_shift;
- int fillptr, fillbyte;
- int use_shm,use_cmap,use_color;
- /* localbyteorder is 1 if MSB first, 0 otherwise */
- unsigned int localbyteorder_loc = MSBFirst<<24;
- int localbyteorder=*(char *)&localbyteorder_loc;
-#ifdef HAVE_XSHM_EXTENSION
- XShmSegmentInfo shm_info;
-#endif
-
-#ifdef HAVE_XSHM_EXTENSION
- use_shm=get_boolean_resource ("useSHM", "Boolean");
-#else
- use_shm=0;
-#endif
-
- /* Model the video controls on a standard television */
- tint_control = get_float_resource("apple2TVTint","Apple2TVTint");
- color_control = get_float_resource("apple2TVColor","Apple2TVColor")/100.0;
- brightness_control = get_float_resource("apple2TVBrightness",
- "Apple2TVBrightness") / 100.0;
- contrast_control = get_float_resource("apple2TVContrast",
- "Apple2TVContrast") / 100.0;
- simulate_user = get_boolean_resource("apple2SimulateUser",
- "Apple2SimulateUser");
-
- XGetWindowAttributes (dpy, window, &xgwa);
- visclass=xgwa.visual->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<<A2_CMAP_HISTBITS); hist++) {
- for (offset=0; offset<4; offset++) {
- int interpy,interpi,interpq,r,g,b;
- int levelmult=level ? 64 : 32;
- int prec=colormode ? colorprec : (colorprec*2+2)/3;
- int precmask=(0xffff<<(16-prec))&0xffff;
- XColor col;
-
- if (A2_CMAP_INDEX(colormode,level,hist,offset) != n_colors) {
- fprintf(stderr, "apple2: internal colormap allocation error\n");
- goto bailout;
- }
-
- for (i=0; i<600; i++) dec->pattern[i]=0;
- for (i=0; i<A2_CMAP_HISTBITS; i++) {
- dec->pattern[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;
- }
- }
- }
- }
- } 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;
- }
- }
- if (red_shift<0 || green_shift<0 || blue_shift<0) {
- if (0) fprintf(stderr,"Can't figure out color space\n");
- goto bailout;
- }
- 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;
- }
- }
- 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);
- } else {
- XDrawString(dpy, text_pm, gc, x, y, &c, 1);
- }
- }
- 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; i<n && addr<0x4000; i++) {
- u_char rb=((random()%6==0 ? 0 : random()%16) |
- ((random()%5==0 ? 0 : random()%16)<<4));
- a2_poke(st, addr++, rb);
- }
- break;
-
- case 2:
- /* Simulate shapes stored in memory. We use the font since we have it.
- Unreadable, since rows of each character are stored in consecutive
- bytes. It was typical to store each of the 7 possible shifts of
- bitmaps, for fastest blitting to the screen. */
- x=random()%(text_im->width);
- 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)<<j;
- }
- a2_poke(st, addr++, c);
- }
- x=(x+1)%(text_im->width);
- }
- break;
-
- case 3:
- if (addr>0x2000) {
- n=random()%200;
- for (i=0; i<n && addr<0x4000; i++) {
- a2_poke(st, addr++, 0);
- }
- }
- break;
-
- }
- }
- }
-
- 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);
- }
- if (curtime>delay) goto finished;