#include #include #include #include #include #define VGA_WIDTH_PIXELS 640 #define VGA_HEIGHT_SCAN_LINES 480 typedef struct _BITMAPFILEHEADER { USHORT bfType; ULONG bfSize; USHORT bfReserved1; USHORT bfReserved2; ULONG bfOffBits; } BITMAPFILEHEADER; typedef struct _BITMAPINFOHEADER{ ULONG biSize; long biWidth; long biHeight; USHORT biPlanes; USHORT biBitCount; ULONG biCompression; ULONG biSizeImage; long biXPelsPerMeter; long biYPelsPerMeter; ULONG biClrUsed; ULONG biClrImportant; } BITMAPINFOHEADER; BITMAPFILEHEADER FileHeader; BITMAPINFOHEADER InfoHeader; // // Pixel maps. This is set up so that when bitmaps using the standard // Windows VGA palette are displayed from a file, monochrome ones have // a dark blue foreground and black background. Color bitmaps use the // dark blue index as the background; pixels that are dark blue are // assigned to be background and not placed into the video buffer. // BYTE PixMapMono[2] = { VGAPIX_BLACK, VGAPIX_BLUE }; BYTE PixMapColor[16] = { VGAPIX_BLACK, VGAPIX_RED, VGAPIX_GREEN, VGAPIX_YELLOW, VGAPIX_BLUE, VGAPIX_MAGENTA, VGAPIX_CYAN, VGAPIX_LIGHT_GRAY, VGAPIX_DARK_GRAY, VGAPIX_LIGHT_RED, VGAPIX_LIGHT_GREEN, VGAPIX_LIGHT_YELLOW, VGAPIX_LIGHT_BLUE, VGAPIX_TRANSPARENT, VGAPIX_LIGHT_CYAN, VGAPIX_WHITE }; BOOL _far VgaDisplayBitmapFromFile( IN FPCHAR Filename, IN USHORT x, IN USHORT y, IN FPVOID ScratchBuffer, IN UINT ScratchBufferSize ) { unsigned FileHandle; unsigned Count; unsigned BytesPerLine; unsigned MaxLines; unsigned Lines; unsigned Bottom; BOOL b = FALSE; // // Open the file. // if(_dos_open(Filename,SH_DENYWR,&FileHandle)) { goto c0; } // // Read the bitmap file header and validate it. // if(_dos_read(FileHandle,&FileHeader,sizeof(BITMAPFILEHEADER),&Count) || (Count != sizeof(BITMAPFILEHEADER)) || (FileHeader.bfType != 0x4d42)) { goto c1; } // // Read the bitmap info header and validate it. // if(_dos_read(FileHandle,&InfoHeader,sizeof(BITMAPINFOHEADER),&Count) || (Count != sizeof(BITMAPINFOHEADER)) || (InfoHeader.biSize != sizeof(BITMAPINFOHEADER)) || (InfoHeader.biHeight < 0) || ((y + InfoHeader.biHeight) > VGA_HEIGHT_SCAN_LINES) || ((x + InfoHeader.biWidth) > VGA_WIDTH_PIXELS) || (InfoHeader.biPlanes != 1) || ((InfoHeader.biBitCount != 1) && (InfoHeader.biBitCount != 4)) || InfoHeader.biCompression) { goto c1; } // // Calculate the number of bytes per line. Rows are padded to // dword boundary. // Count = 8 / InfoHeader.biBitCount; BytesPerLine = (unsigned)(InfoHeader.biWidth / Count); if(InfoHeader.biWidth % Count) { BytesPerLine++; } BytesPerLine = (BytesPerLine+3) & 0xfffc; // // Ignore the color table for now. Seek to the start of the // actual bits. // if(DosSeek(FileHandle,FileHeader.bfOffBits,DOSSEEK_START) != FileHeader.bfOffBits) { goto c1; } // // Figure out how many lines fit into the buffer we were given. // MaxLines = ScratchBufferSize / BytesPerLine; Bottom = (y + (USHORT)InfoHeader.biHeight) - 1; while(InfoHeader.biHeight) { Lines = (unsigned)InfoHeader.biHeight; if(Lines > MaxLines) { Lines = MaxLines; } if(_dos_read(FileHandle,ScratchBuffer,Lines*BytesPerLine,&Count) || (Count != (Lines*BytesPerLine))) { goto c1; } VgaBitBlt( x, Bottom, (unsigned)InfoHeader.biWidth, -Lines, BytesPerLine, InfoHeader.biBitCount != 1, (InfoHeader.biBitCount != 1) ? PixMapColor : PixMapMono, ScratchBuffer ); InfoHeader.biHeight -= Lines; Bottom -= Lines; } b = TRUE; c1: _dos_close(FileHandle); c0: return(b); }