/* HAR format loader */ #include #include #include #include #define LINE_SIZE 320 #define TOT_LINES 200 #define VGA_MEM 0xa0000000 #define BIOSVID 0x10 #define VGA256 0x13 #define TEXT 0x3 #define SETMODE 0 /* Declare a variable type that holds the image information */ typedef struct { char identsize; char colormaptype; char imagetype; unsigned int colormapstart; unsigned int colormaplength; char colormapbits; unsigned int xstart; unsigned int ystart; unsigned int width, depth; char bits; char descriptor; } TGAHEAD; /* Function declarations */ void graphics (void); void text (void); void decode (FILE *fp); void paletteset (char *buffer); void putline(char *p, unsigned int n, int width); void getline(char *p, unsigned int n, int width); void error (char *message); void main(int argc, char *argv[]) { FILE *fp; /* Make sure a filename was entered */ if(argc > 1) { /* Open the file */ if((fp = fopen (argv[argc - 1], "rb")) != NULL) { /* Go into graphics mode */ graphics(); /* Read and display the file */ decode(fp); /* Close the file */ fclose(fp); /* Wait for a keypress */ while(!kbhit()); /* Return to text mode */ text(); } else printf("Error opening %s\n", argv[argc - 1]); } else puts("Must specify a filename\n"); } /* The graphics function puts the screen in graphics mode */ void graphics (void) { union REGS regs; regs.h.ah = 0; regs.h.al = 0x13; int86(0x10, ®s, ®s); } /* The text function returns the screen to text mode */ void text (void) { union REGS regs; regs.h.ah = 0; regs.h.al = 3; int86(0x10, ®s, ®s); } /* The decode function reads and displays the TGA file */ void decode (FILE *fp) { TGAHEAD tga; char *ptr; char buffer[768], buffer2[320], buffer3[320]; char temp; int bytes, i, n, startline, endline, incline; /* Read the header for the file */ if (fread((char *)&tga, 1, sizeof(TGAHEAD), fp)==sizeof(TGAHEAD)) { /* Read until the beginning of the image is reached */ fseek(fp, (long)tga.identsize, SEEK_CUR); /* See if the file has an invalid number of colors */ if(tga.colormaptype) { switch(tga.colormapbits) { case 24: for(i = tga.colormapstart; i < tga.colormaplength; i++) { if(i >= 256) break; buffer[i*3+2] = fgetc(fp); buffer[i*3+1] = fgetc(fp); buffer[i*3] = fgetc(fp); } break; case 16: for(i = tga.colormapstart; i < tga.colormaplength; i++) { if(i >= 256) break; n = ((fgetc(fp) & 0xff) + ((fgetc(fp) & 0xff) << 8)); buffer[i*3+2] = ((n >> 10) & 0x1f) << 3; buffer[i*3+1] = ((n >> 5 ) & 0x1f) << 3; buffer[i*3] = (n & 0x1f) << 3; } break; } paletteset(buffer); } else { if(tga.imagetype==3) { for(i=0; i<=255; i++) { buffer[i * 3] = i; buffer[i * 3 + 1] = i; buffer[i * 3 + 2] = i; } paletteset(buffer); } else { error("Image must be greyscale or have a palette."); } } /* Set up which parts of the file are to be displayed */ startline = 0; endline = tga.depth; incline = 4; /* Read the level 1 image and display it */ for(i = startline; i < endline; i += incline) { fread(&buffer, 1, tga.width, fp); putline(buffer, i, tga.width); putline(buffer, i + 1, tga.width); putline(buffer, i + 2, tga.width); putline(buffer, i + 3, tga.width); } /* Read the level 2 image and display it */ for(i = startline; i < endline; i += incline) { fread(&buffer, 1, tga.width, fp); getline(buffer2, i, tga.width); getline(buffer3, i + 2, tga.width); for(n = 0; n < tga.width; n++) { buffer2[n] = buffer2[n] + buffer[n] / 2; buffer3[n] = buffer3[n] - buffer[n] / 2; if(buffer[n] & 1) if(buffer[n] < 0) buffer3[n]++; else buffer2[n]++; } putline(buffer2, i, tga.width); putline(buffer2, i + 1, tga.width); putline(buffer3, i + 2, tga.width); putline(buffer3, i + 3, tga.width); } for(i = startline; i < endline; i += incline) { fread(&buffer, 1, tga.width, fp); getline(buffer2, i, tga.width); getline(buffer3, i + 1, tga.width); for(n = 0; n < tga.width; n++) { buffer2[n] = buffer2[n] + buffer[n] / 2; buffer3[n] = buffer3[n] - buffer[n] / 2; if(buffer[n] & 1) if(buffer[n] < 0) buffer3[n]++; else buffer2[n]++; } putline(buffer2, i, tga.width); putline(buffer3, i + 1, tga.width); } for(i = startline; i < endline; i += incline) { fread(&buffer, 1, tga.width, fp); getline(buffer2, i + 2, tga.width); getline(buffer3, i + 3, tga.width); for(n = 0; n < tga.width; n++) { buffer2[n] = buffer2[n] + buffer[n] / 2; buffer3[n] = buffer3[n] - buffer[n] / 2; if(buffer[n] & 1) if(buffer[n] < 0) buffer3[n]++; else buffer2[n]++; } putline(buffer2, i + 2, tga.width); putline(buffer3, i + 3, tga.width); } } } /* The paletteset function sets the color palette */ void paletteset (char *buffer) { union REGS regs; int i; outp(0x3c6, 0xff); for(i = 0; i < 255; i++) { outp(0x3c8, i); outp(0x3c9, (*buffer++) >> 2); outp(0x3c9, (*buffer++) >> 2); outp(0x3c9, (*buffer++) >> 2); } } /* The putline function displays one line of the image */ void putline(char *buffer, unsigned int n, int width) { char far *ScreenMemory = (char far *)(VGA_MEM + n * LINE_SIZE); int j; for(j = 0; j < width; j++) *(ScreenMemory+j) = buffer[j]; } /* The getline function reads a line of the image from screen memory */ void getline(char *buffer, unsigned int n, int width) { char far *ScreenMemory = (char far *)(VGA_MEM + n * LINE_SIZE); int j; for(j = 0; j < width; j++) *(buffer + j) = *(ScreenMemory + j); } /* The error function displays an error message and halts the program */ void error (char *message) { text(); puts(message); exit(1); }