1fa2 /* 2FASTNC Converts compressed IFF file to fast loading MCGA format */ /* This version does not save the palette, only width and height */ /* use C O M P A C T MODE!!! */ #include #include #include FILE* f; union REGS regs; #define FORM 0x464f524dL #define ILBM 0x494c424dL #define BMHD 0x424d4844L #define CMAP 0x434d4150L #define BODY 0x424f4459L unsigned char far *screen; unsigned char palbuf[768]; unsigned char planes,compress; int width,height; unsigned char red[256],green[256],blue[256]; long read32bit(); long to32bit(); unsigned char fname[80]; unsigned char fastfname[80]; main(int argc, char **argv) { if(! (f = fopen(argv[1],"rb"))) { printf("Couldn't find %s!\n",argv[1]); exit(1); } strcpy(fname,argv[1]); setpal(); if(compress == 1) load_comp(); else load_uncompx(); getch(); if(argc > 2) strcpy(fastfname,argv[2]); else strcpy(fastfname,""); save_fastformat(fastfname); set_text(); } load_comp() { unsigned int i,plane,scrstart; unsigned int addr,scan,nextline; unsigned char byte,b; for(scan=0;scan < height;scan++) { for(plane=0;plane < planes; plane++) /* 8 bitplanes */ { addr = 320*scan; nextline = addr + width; do { byte = (unsigned char)getc(f); if(byte < 128) { for(i=0;i < byte+1; i++) { b = (unsigned char)getc(f); screen[addr++] |= (b >> 7 & 1) << plane; screen[addr++] |= (b >> 6 & 1) << plane; screen[addr++] |= (b >> 5 & 1) << plane; screen[addr++] |= (b >> 4 & 1) << plane; screen[addr++] |= (b >> 3 & 1) << plane; screen[addr++] |= (b >> 2 & 1) << plane; screen[addr++] |= (b >> 1 & 1) << plane; screen[addr++] |= (b & 1) << plane; } } else if(byte > 128) { b = (unsigned char)getc(f); for(i=0;i < (256-byte)+1; i++) { screen[addr++] |= (b >> 7 & 1) << plane; screen[addr++] |= (b >> 6 & 1) << plane; screen[addr++] |= (b >> 5 & 1) << plane; screen[addr++] |= (b >> 4 & 1) << plane; screen[addr++] |= (b >> 3 & 1) << plane; screen[addr++] |= (b >> 2 & 1) << plane; screen[addr++] |= (b >> 1 & 1) << plane; screen[addr++] |= (b & 1) << plane; } } } while(addr < nextline); } } fclose(f); } load_uncompx() { int scan; for(scan = 0;scan> 7 & 1) << plane; screen[addr++] |= (b >> 6 & 1) << plane; screen[addr++] |= (b >> 5 & 1) << plane; screen[addr++] |= (b >> 4 & 1) << plane; screen[addr++] |= (b >> 3 & 1) << plane; screen[addr++] |= (b >> 2 & 1) << plane; screen[addr++] |= (b >> 1 & 1) << plane; screen[addr++] |= (b & 1) << plane; } } } while(addr < nextline); } fclose(f); } setpal() { int i; unsigned char trash[10]; unsigned long id,length; id = read32bit(); if(id != FORM) error("Not an IFF/LBM file!"); length = read32bit(); id = read32bit(); if(id != ILBM) error("Not an IFF/LBM file!"); while(1) { id = read32bit(); length = read32bit(); if(id == BMHD) break; fseek(f,length,SEEK_CUR); } width = read16bit(); height = read16bit(); fseek(f,4L,SEEK_CUR); planes = (unsigned char)getc(f); /* no of bitplanes */ getc(f); compress = (unsigned char)getc(f); /* compress flag */ fseek(f,9L,SEEK_CUR); while(1) { id = read32bit(); length = read32bit(); if(id == CMAP) break; fseek(f,length,SEEK_CUR); } screen = MK_FP(0xA000,0); set_mcga(); fread(palbuf,768,1,f); for (i=0;i<768;i++) palbuf[i] >>= 2; regs.h.ah = 0x10; regs.h.al = 0x12; regs.x.bx = 0; regs.x.cx = 256; regs.x.dx = (unsigned)palbuf; int86(0x10,®s,®s); while(1) { id = read32bit(); length = read32bit(); if(id == BODY) break; fseek(f,length,SEEK_CUR); } } save_fastformat(unsigned char *fastfname) { FILE* f; int i,scan; if(strlen(fastfname) == 0) { strcpy(fastfname,fname); fastfname[strchr(fastfname,'.')-fastfname] = 0; strcat(fastfname,".FST"); } f = fopen(fastfname,"wb"); fwrite(&width,2,1,f); fwrite(&height,2,1,f); scan = 0; do { fwrite(&screen[scan*320],width,1,f); scan++; } while(scan < height); fclose(f); } error(char *errmsg) { printf("Error: %s\n",errmsg); fclose(f); exit(1); } int read16bit() { int c1, c2; c1 = getc(f); c2 = getc(f); return to16bit(c1,c2); } int to16bit(c1,c2) int c1, c2; { return ((c1 & 0xff ) << 8) + (c2 & 0xff); } long read32bit() { int c1, c2, c3, c4; c1 = getc(f); c2 = getc(f); c3 = getc(f); c4 = getc(f); return to32bit(c1,c2,c3,c4); } long to32bit(c1,c2,c3,c4) { long value = 0L; value = (c1 & 0xff); value = (value<<8) + (c2 & 0xff); value = (value<<8) + (c3 & 0xff); value = (value<<8) + (c4 & 0xff); return (value); } set_mcga() { regs.h.ah = 0; regs.h.al = 0x13; int86(0x10,®s,®s); } set_text() { regs.h.ah = 0; regs.h.al = 3; int86(0x10,®s,®s); } /* *.IFF 4 bytes "FORM" (FORM chunk ID) 1 long length of file that follows 4 bytes "ILBM" (InterLeaved BitMap file ID) 4 bytes "BMHD" (BitMap HeaDer chunk ID) 1 long length of chunk [20] 20 bytes 1 word = image width in pixels 1 word = image height in lines 1 word = image x-offset [usually 0] 1 word = image y-offset [usually 0] 1 byte = # bitplanes 1 byte = mask (0=no, 1=impl., 2=transparent, 3=lasso) 1 byte = compressed [1] or uncompressed [0] 1 byte = unused [0] 1 word = transparent color (for mask=2) 1 byte = x-aspect [5=640x200, 10=320x200/640x400, 20=320x400] 1 byte = y-aspect [11] 1 word = page width (usually the same as image width) 1 word = page height (usually the same as image height) 4 bytes "CMAP" (ColorMAP chunk ID) 1 long length of chunk [3*n where n is the # colors] 3n bytes 3 bytes per RGB color. Each color value is a byte and the actual color value is left-justified in the byte such that the most significant bit of the value is the MSB of the byte. (ie. a color value of 15 ($0F) is stored as $F0) The bytes are stored in R,G,B order. 4 bytes "CRNG" (Color RaNGe chunk ID) 1 long length of chunk [8] 8 bytes 1 word = reserved [0] 1 word = animation speed (16384 = 60 steps per second) 1 word = active [1] or inactive [0] 1 byte = left/lower color animation limit 1 byte = right/upper color animation limit 4 bytes "CAMG" (Commodore AMiGa viewport mode chunk ID) 1 long length of chunk [4] 1 long viewport mode bits (bit 11 = HAM, bit 3 = interlaced) 4 bytes "BODY" (BODY chunk ID) 1 long length of chunk [# bytes of image data that follow] ? bytes actual image data NOTES: Some of these chunks may not be present in every IFF file, and may not be in this order. You should always look for the ID bytes to find a certain chunk. All chunk IDs are followed by a long value that tells the size of the chunk (note that "ILBM" is not a chunk ID). This is the number of bytes that FOLLOW the 4 ID bytes and size longword. The exception to this is the FORM chunk. The size longword that follows the FORM ID is the size of the remainder of the file. The FORM chunk must always be the first chunk in an IFF file. */ . 0