dos-vga-arena-shooter-game/bmp_loader.c

136 lines
3.4 KiB
C

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <dos.h>
#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;
}
}