#define LINUX #define SOUNDDEVICE "/dev/dsp" #define quiet 0 #define error(x) fprintf(stderr,"%s\n",x) #define NEXTBYTE ((unsigned char)MMF[MMF_OFF++]) #define NEXTUL MMF[MMF_OFF]|(MMF[MMF_OFF+1]<<8)|(MMF[MMF_OFF+2]<<16)|(MMF[MMF_OFF+3]<<24);MMF_OFF+=4; #define NEXTBLOCK(dest,bytes) memcpy((dest),&MMF[MMF_OFF],(bytes));MMF_OFF+=(bytes); #define THROWAWAY(bytes) MMF_OFF+=bytes; #define WRITEBLOCK(destfp,bytes) write((destfp),&MMF[MMF_OFF],bytes);MMF_OFF+=(bytes); #define FWRITEBLOCK(destfp,bytes) fwrite(&MMF[MMF_OFF],bytes,1,destfp);MMF_OFF+=(bytes); /* 0=not rotated, 1=table lookup, 2=blit-rotate */ #define rotated 1 #define cachesound 0 #define dirtyrect 0 #define sound 1 #define debug 0 #define deb if (debug) printf #include #include #include #include #include #include #include #include #include #include #include #include #ifndef LINUX #error THIS PROGRAM REQUIRES LINUX #endif #include int ifd; int bufferstep=0; unsigned short int pagesize; unsigned char *MMF; unsigned long int MMF_OFF=0; unsigned long FSIZE; char *buf; unsigned short int palrange=1; unsigned short int trans[64000]; #define _ANSI_ARGS_(x) x unsigned long pix[256]; XColor pal[256]; unsigned char *bbuf; unsigned char *fbuf; unsigned char *fbuf1; unsigned char *fbuf2; /*unsigned char *scrollin;*/ unsigned long int pmr; int wwidth=320,wheight=200; int bwidth,bheight; Colormap cmap; static Display *display; static Window window; static GC gc; static XImage *ximage; #include #include #include static int HandleXError _ANSI_ARGS_((Display *dpy, XErrorEvent *event)); static void InstallXErrorHandler _ANSI_ARGS_((void)); static void DeInstallXErrorHandler _ANSI_ARGS_((void)); static int shmem_flag=1; static XShmSegmentInfo shminfo1; static int gXErrorFlag; static int CompletionType = -1; int speed=22050; int bits=AFMT_U8; int stereo=0; /*int frag=0x00020009; /* 2 fragments of 2^9=512 bytes */ /*int frag=0x0002000f; /* 2 fragments of 2^15=32k bytes */ /*int frag=0x0004000e; /* 2 fragments of 2^15=32k bytes */ /*int frag=0x0008000d; /* 2 fragments of 2^15=32k bytes */ int frag=0x00100009; /* 16 fragments of 2^12=4096 bytes */ int ffd; int c1,c2,c3,c4; long int remaining; unsigned char twoseconds[55000]; /*unsigned char modexbuf[64000];*/ unsigned long int nextblock; static int HandleXError(dpy, event) Display *dpy; XErrorEvent *event; { gXErrorFlag = 1; return 0; } static void InstallXErrorHandler() { XSetErrorHandler(HandleXError); XFlush(display); } static void DeInstallXErrorHandler() { XSetErrorHandler(NULL); XFlush(display); } void init_display(name) char *name; { int crv, cbu, cgu, cgv; int y, u, v, r, g, b; int i; char dummy; int screen; int private; XColor xcolor; unsigned int fg, bg; char *hello = "Space Ace"; XSizeHints hint; XVisualInfo vinfo; XEvent xev; unsigned long tmp_pixel; XWindowAttributes xwa; display = XOpenDisplay(name); if (display == NULL) error("Cannot open display\n"); screen = DefaultScreen(display); hint.x = 200; hint.y = 200; hint.width = wwidth; hint.height = wheight; hint.flags = PSize; /* Get some colors */ /* bg = WhitePixel (display, screen); fg = BlackPixel (display, screen);*/ /* Make the window */ if (!XMatchVisualInfo(display, screen, 8, PseudoColor, &vinfo)) { if (!XMatchVisualInfo(display, screen, 8, GrayScale, &vinfo)) error("requires 8 bit display\n"); } window = XCreateSimpleWindow (display, DefaultRootWindow (display), hint.x, hint.y, hint.width, hint.height, 0, 0, 0); XSelectInput(display, window, StructureNotifyMask); /* Tell other applications about this window */ XSetStandardProperties (display, window, hello, hello, None, NULL, 0, &hint); /* Map window. */ XMapWindow(display, window); /* Wait for map. */ do { XNextEvent(display, &xev); } while (xev.type != MapNotify || xev.xmap.event != window); XSelectInput(display, window, NoEventMask); /* allocate colors */ gc = DefaultGC(display, screen); cmap = DefaultColormap(display, screen); /* create private colormap */ XGetWindowAttributes(display, window, &xwa); cmap = XCreateColormap(display, window, xwa.visual, AllocNone); XSetWindowColormap(display, window, cmap); if (XAllocColorCells(display, cmap, False, &pmr, 0, pix, 256)==0) { printf("** XAllocColorCells FAILED **"); }; for (i=0;i<256;i++) { pal[i].flags|=DoRed|DoGreen|DoBlue; pal[i].pixel=pix[i]; } /* for (i=0;i<256;i++) { xcolor.red=i<<8; xcolor.green=i<<8; xcolor.blue=i<<8; XAllocColor(display, cmap, &xcolor); mapping[i]=xcolor.pixel; }*/ if (XShmQueryExtension(display)) shmem_flag = 1; else { shmem_flag = 0; if (!quiet) fprintf(stderr, "Shared memory not supported\nReverting to normal Xlib\n") ; } } void createshm(int width,int height) { if (shmem_flag) CompletionType = XShmGetEventBase(display) + ShmCompletion; InstallXErrorHandler(); if (shmem_flag) { ximage = XShmCreateImage(display, None, 8, ZPixmap, NULL, &shminfo1, width, height); /* If no go, then revert to normal Xlib calls. */ if (ximage==NULL) { if (!quiet) fprintf(stderr, "Shared memory error, disabling (Ximage error)\n"); } /* Success here, continue. */ shminfo1.shmid = shmget(IPC_PRIVATE, width*height, IPC_CREAT | 0777); if (shminfo1.shmid<0) { perror("shmget"); XDestroyImage(ximage); if (!quiet) fprintf(stderr, "Shared memory error, disabling (seg id error)\n"); } shminfo1.shmaddr = (char *) shmat(shminfo1.shmid, 0, 0); if (shminfo1.shmaddr==((char *) -1)) { XDestroyImage(ximage); if (!quiet) { fprintf(stderr, "Shared memory error, disabling (address error)\n"); } } shminfo1.readOnly = False; XShmAttach(display, &shminfo1); shmctl(shminfo1.shmid, IPC_RMID, 0 ); buf = ximage->data = shminfo1.shmaddr; XSync(display, False); if (gXErrorFlag) { /* Ultimate failure here. */ XDestroyImage(ximage); shmdt(shminfo1.shmaddr); if (!quiet) fprintf(stderr, "Shared memory error, disabling.\n"); gXErrorFlag = 0; } else { shmctl(shminfo1.shmid, IPC_RMID, 0); } if (!quiet) { fprintf(stderr, "Sharing memory. [ %d x %d ]\n",width,height); } } /* else { shmemerror: shmem_flag = 0; ximage = XCreateImage(display,None,8,ZPixmap,0,&dummy, coded_picture_width,coded_picture_height,8,0); if (!(dithered_image = (unsigned char *)malloc(coded_picture_width* coded_picture_height))) error("malloc failed"); }*/ DeInstallXErrorHandler(); } void destroyshm() { XShmDetach(display, &shminfo1); XDestroyImage(ximage); shmdt(shminfo1.shmaddr); } void doPalette(void) { // XStoreColors(display, cmap, &pal[0], 256); int i; for (i=0;i<256;i++) { vga_setpalette(i, (pal[i].red)/(65535/63), pal[i].green/(65535/63), pal[i].blue/(65535/63)); } vga_waitretrace(); } void getPalette(void) { int i,j; char fn[100]; FILE *im; deb("\t- Palette [ "); c1=NEXTBYTE; palrange=NEXTBYTE; for (i=0;i<5;i++) { j=NEXTBYTE; deb("%ld ",j); } deb("]\n"); if (palrange==0) palrange=256; for (i=0;ic1;j--) { bbuf[i]=(unsigned char)c2; i++; if (!(i<(bwidth*bheight))) break; } } else { NEXTBLOCK(&bbuf[i],c1); i+=c1; } } memcpy(fbuf1,bbuf,bwidth*bheight); memcpy(fbuf2,bbuf,bwidth*bheight); deb("[%ldx%ld]\n",bheight,bwidth);fflush(stdout); /* XPutImage(display, window, gc, ximage, 0, 0, 0, 0, bheight, bwidth);*/ /* sprintf(fn,"back%ld.img",position); printf("\t- Background image (dumping to %s)\n",fn); im = fopen(fn,"wb"); for (i=0;idata[i]=fbuf[trans[i]]; } // XShmPutImage(display, window, gc, ximage, // 0, 0, 0, 0, bwidth, bheight,True); { static unsigned char *poo=NULL; if (!poo) poo = vga_getgraphmem(); memcpy(poo, ximage->data, 320*200); } } } else if (rotated==0) { if (debug) { memcpy(ximage->data,fbuf,bwidth*bheight); XShmPutImage(display, window, gc, ximage, 0, 0, 200, 0, bheight, bwidth,True); memcpy(ximage->data,bbuf,bwidth*bheight); XShmPutImage(display, window, gc, ximage, 0, 0, 400, 0, bheight, bwidth,True); if (0) { memcpy(&fbuf[pagesize],fbuf,pagesize); memcpy(&fbuf[pagesize*2],fbuf,pagesize); memcpy(&fbuf[pagesize*3],fbuf,pagesize); } } k=bwidth/4; j=k; for (i=0;idata[(j*4+3)*bheight]),&fbuf[i*bheight],bheight); memcpy(&(ximage->data[(j*4+2)*bheight]),&fbuf[(i+bwidth/4)*bheight],bheight); memcpy(&(ximage->data[(j*4+1)*bheight]),&fbuf[(i+bwidth/2)*bheight],bheight); memcpy(&(ximage->data[(j*4)*bheight]),&fbuf[(i+3*(bwidth/4))*bheight],bheight);*/ } /* XPutImage(display, window, gc, ximage, 0, 0, 0, 0, bheight, bwidth);*/ XShmPutImage(display,window,gc,ximage,0,0,0,0,bheight,bwidth,True); } } void doForeground(void) { int j,lastpix,nwidth,nheight,k,page,p1,p2,p3,p4,p5,p6; unsigned long int i,ix,iy; unsigned long int xx; char fn[100]; FILE *im; unsigned char tab[128]; deb("\t- Foreground ("); if (1) { THROWAWAY(5); remaining-=5; /* for (i=0;i<5;i++) printf("%ld.",NEXTBYTE);*/ xx=NEXTUL; remaining-=4; /* deb("*%ld*",xx);*/ i=NEXTUL; remaining-=4; /* deb("*%ld*",i);*/ if ((i-xx)!=134) deb("--XXXXXXX--%ld--",i-xx); } /* XSetForeground(display, gc, pix[255]); XFillRectangle(display,window,gc,0,330,640,480); XSetForeground(display, gc, pix[63]);*/ #define ww 41 #define ix ((i/ww)*8) #define iy ((i%ww)*2) #define copyback {\ p4=iy*bheight+ix;\ for (p1=0;p1<8;p1++)\ {\ for (p2=0;p2<2;p2++)\ {\ p5=p4+p1+(p2*bheight);\ fbuf[p5]=bbuf[p5];\ p5+=pagesize;\ fbuf[p5]=bbuf[p5];\ p5+=pagesize;\ fbuf[p5]=bbuf[p5];\ p5+=pagesize;\ fbuf[p5]=bbuf[p5];\ }\ }\ } i=0; for (j=0;j<134;j++) { c1=NEXTBYTE; if ((c1!=0)&&(j<128)) { if (c1&128) copyback; i++; if (c1&64) copyback; i++; if (c1&32) copyback; i++; if (c1&16) copyback; i++; if (c1&8) copyback; i++; if (c1&4) copyback; i++; if (c1&2) copyback; i++; if (c1&1) copyback; i++; } else i+=8; } j=lastpix=0; i=page=0; if (1) { while ((i<((bwidth*bheight)))/*&&(remaining>0)*/) { c1 = NEXTBYTE;/* remaining--;*/ /* printf("** - %3d %3d\n",c1&0xC0,c1); fflush(stdout);*/ if (c1==0x81) /* next line */ { i=i/bheight; i++; i=i*bheight; } else if (c1==0x80) /* next page */ { deb("'@%ld,",i); page++; i=pagesize*page; deb("%ld'",i); } else if (c1 > 129) /* runlength piece, 0 transparent */ { c2=NEXTBYTE;/*remaining--;*/ if (c2!=0) memset(&fbuf[i],c2,256-c1); i+=256-c1; } else /* raw block, 0 transparent */ { if (c1>63) {deb("`*'");fflush(stdout);} /* if (c1==0) printf("<0length>\n");fflush(stdout);*/ for (j=0;j "); if (up==128<<24) printf("UP! "); if (down==128<<24) printf("DOWN! "); if (left==128<<24) printf("LEFT! "); if (right==128<<24) printf("RIGHT! "); if (fire==128<<24) printf("FIRE! "); if (nothing==128<<24) printf("(nothing) "); printf("\n"); } void main(int argc, char **argv) { int i,j; unsigned char blocktype; struct stat fi; init_display(":0"); vga_init(); vga_setmode(G320x200x256); XSetForeground(display, gc, pix[64]); /* fairly constant black */ XFillRectangle(display, window, gc, 0, 0, wwidth,wheight); fbuf1=malloc(320*200); fbuf2=malloc(320*200); if (bufferstep) fbuf=fbuf1; else fbuf=fbuf2; bbuf=malloc(320*200); if (rotated==1) createshm(320,200); else createshm(200,320); bwidth=320; bheight=200; pagesize=16000; if (sound) { if ((ifd=open(SOUNDDEVICE,O_WRONLY))==-1) { fprintf(stderr,"warning: %s: ",SOUNDDEVICE); perror(SOUNDDEVICE); /* exit(-1);*/ } } if (rotated==1) gentrans(); #ifdef LINUX if (sound) { ioctl(ifd, SNDCTL_DSP_SETFRAGMENT, &frag); ioctl(ifd,SNDCTL_DSP_RESET); ioctl(ifd,SNDCTL_DSP_SPEED,&speed); printf("Speed: %dHz (desired: 22050Hz)\n",speed); ioctl(ifd,SNDCTL_DSP_SAMPLESIZE,&bits); printf("Bits: %d (desired: %d)\n",bits,AFMT_U8); ioctl(ifd,SNDCTL_DSP_STEREO,&stereo); printf("Stereo: %d (desired: 0)\n",stereo); ioctl(ifd,SNDCTL_DSP_SYNC); } #endif ffd = open(argv[1],O_RDONLY); if (ffd==-1) { perror("open"); exit(0); } fstat(ffd, &fi); FSIZE=fi.st_size; if ((MMF=(unsigned char *)mmap(NULL,FSIZE,PROT_READ,MAP_PRIVATE,ffd,0))==(unsigned char *)-1) { perror("mmap"); exit(0); } /* for (i=0;i=FSIZE) { deb("EOF\n"); goto finish; break; } blocktype=NEXTBYTE; /* get block type */ if (nextblock==128<<24) /* freaky next-block-address */ { deb("\n-----------------------SCENE END <%d> - skipping over marker...\n",blocktype); THROWAWAY(3); nextblock=NEXTUL; if (MMF_OFF>=FSIZE) { deb("EOF\n"); goto finish; break; } blocktype=NEXTBYTE; /* get block type */ } remaining=nextblock-MMF_OFF; deb("%ld\t%ld:\t%ld\t%ld",MMF_OFF,blocktype,remaining,nextblock); fflush(stdout); switch(blocktype) /* BLOCK TYPE */ { case 0: /* BACKGROUND */ { doBackground(); break; } case 1: /* FOREGROUND */ { doForeground(); break; } case 2: /* AUDIO BLOCK */ { if (sound) doAudio(); break; } case 3: /* ACTION BLOCK */ { deb("\t- ACTION - "); doAction(); break; } case 4: /* DISPOSE BACKGROUND? */ { deb("\t- cut!"); memset(bbuf,0,bwidth*bheight); while (remaining--) deb(" %d",NEXTBYTE); deb("\n"); break; } case 5: /* SYNC BLOCK */ { deb("\t- SYNC"); for (i=0;i<5;i++) deb(" %d",NEXTBYTE); deb("\n"); doPalette(); show(); XFlush(display); /* XSync(display,False);*/ /* fgetc(stdin);*/ if (bufferstep) fbuf=fbuf1; else fbuf=fbuf2; bufferstep=!bufferstep; /* swap buffers */ break; } case 6: /* PALETTE */ { getPalette(); break; } case 7: /* SEQ ID */ { deb("\t- Seq ID = "); for (i=0;i<3;i++) deb("%d ",NEXTBYTE); deb("\n"); break; } default: { printf("\tUNKNOWN <%ld>",blocktype); printf("\n"); break; } } MMF_OFF=nextblock; } finish: XSync(display,False); destroyshm(); if (sound) ioctl(ifd,SNDCTL_DSP_SYNC); /* XShmPutImage(display, window, gc, ximage, 0, 0, 0, 0, width, height, False); XPutImage(display, window, gc, ximage, 0, 0, 0, 0, width, height); XFlush(display); write(ifd,ximage->data,64000); fread(twoseconds,42000,1,fp); write(ifd,twoseconds,42000);*/ }