#include #include #include #include #include "bmp_loader.h" #include "pc_stuff.h" #include "vga.h" int readBMPHeader(FILE *fh, struct BMPImage *info) { int sizeOfHeader; unsigned int numberOfUsedColors; if ((fgetc(fh) != 'B') || (fgetc(fh) != 'M')) { printf("Not a BMP file\n"); return 1; } fseek(fh, 12, SEEK_CUR); fread(&sizeOfHeader, sizeof(int), 1, fh); fread(&info->width, sizeof(int), 1, fh); fread(&info->height, sizeof(int), 1, fh); fseek(fh, 2, SEEK_CUR); fread(&info->bpp, sizeof(word), 1, fh); // for gimp, you need to add colors to the color map until it hits // 16 colors, then the image will be a 256 color, 8 bpp image // // https://www.gimp-forum.net/Thread-indexing-into-8-bit?pid=13233#pid13233 if (info->bpp != 8) return 1; fseek(fh, 16, SEEK_CUR); fread(&numberOfUsedColors, sizeof(unsigned int), 1, fh); if (numberOfUsedColors > 256) return 1; // get down to color data fseek(fh, 14 + sizeOfHeader, SEEK_SET); fread(info->colors, sizeof(struct BMPColor), numberOfUsedColors, fh); return 0; } int readBMPIntoMemory(FILE *fh, struct BMPImage *info) { int x, y, plane; int result; byte *currentPointer; result = readBMPHeader(fh, info); if (result) return result; currentPointer = info->memoryStart; for (y = 0; y < info->height; ++y) { for (x = 0; x < info->width; ++x) { currentPointer[(info->height - 1 - y) * info->width + x] = fgetc(fh); } } return 0; } int readBMPIntoUnchainedMemory(FILE *fh, struct BMPImage* info) { int x, y, plane; int writeX, writeY, offset; int unchainedLineWidth; int result; byte *rowHolder; result = readBMPHeader(fh, info); if (result) return result; unchainedLineWidth = info->width / 4; // reserve a row's worth of data // read the bitmap data into the row, interleaving for planes // for each plane, memcpy the data to the plane for (y = 0; y < info->height; ++y) { writeY = ((info->height - 1) - y) * unchainedLineWidth; for (x = 0; x < info->width; ++x) { plane = x & 0x03; writeX = (x >> 2); offset = plane * (unchainedLineWidth * info->height); info->memoryStart[offset + writeY + writeX] = fgetc(fh); } } return 0; } int readBMPIntoUnchainedVGAMemory(FILE *fh, struct BMPImage* info) { int x, y, plane; int unchainedLineWidth; int result; byte *rowHolder; result = readBMPHeader(fh, info); if (result) return result; rowHolder = malloc(info->width); unchainedLineWidth = info->width / 4; // reserve a row's worth of data // read the bitmap data into the row, interleaving for planes // for each plane, memcpy the data to the plane for (y = 0; y < info->height; ++y) { for (x = 0; x < info->width; ++x) { rowHolder[((x & 3) * 80) + (x >> 2)] = fgetc(fh); } for (plane = 0; plane < 4; ++plane) { setActiveVGAMemoryPlanes(1 << plane); memcpy(info->memoryStart + ((info->height - 1) - y) * info->width / 4, rowHolder + unchainedLineWidth * plane, unchainedLineWidth); } } free(rowHolder); return 0; } void bmp256ColorPaletteToVGAColorPalette(struct BMPImage* bmpImage, struct VGAColor colors[]) { int i; for (i = 0; i < 256; ++i) { colors[i].red = bmpImage->colors[i].red >> 2; colors[i].green = bmpImage->colors[i].green >> 2; colors[i].blue = bmpImage->colors[i].blue >> 2; } }