145 lines
4.5 KiB
C
145 lines
4.5 KiB
C
#include "texture_map.h"
|
|
#include <errno.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
struct TextureMap {
|
|
uint32_t* data;
|
|
size_t width;
|
|
size_t height;
|
|
};
|
|
|
|
TextureMap* texture_map_new(const char* filename)
|
|
{
|
|
TextureMap* result;
|
|
|
|
FILE* file = fopen(filename, "rb");
|
|
if (!file) {
|
|
fprintf(
|
|
stderr,
|
|
"error: could not open texture map file \"%s\": %s\n",
|
|
filename,
|
|
strerror(errno));
|
|
return NULL;
|
|
}
|
|
|
|
constexpr size_t header_size = 18;
|
|
uint8_t header[header_size];
|
|
size_t header_read = fread(header, 1, 18, file);
|
|
if (header_read != header_size) {
|
|
fprintf(
|
|
stderr,
|
|
"error: could not read texture map TGA header of file \"%s\"\n",
|
|
filename);
|
|
|
|
result = nullptr;
|
|
goto exit_close_file;
|
|
}
|
|
|
|
const uint8_t* header_iter = header;
|
|
|
|
uint8_t id_length = *header_iter++;
|
|
uint8_t color_map_type = *header_iter++;
|
|
uint8_t image_type = *header_iter++;
|
|
uint8_t cm_spec[5];
|
|
for (size_t i = 0; i < 5; ++i)
|
|
cm_spec[i] = *header_iter++;
|
|
uint8_t image_spec[10];
|
|
for (size_t i = 0; i < 10; ++i)
|
|
image_spec[i] = *header_iter++;
|
|
|
|
uint16_t first_entry_index = (uint16_t)(cm_spec[1] << 8 | cm_spec[0]);
|
|
uint16_t cm_length = (cm_spec[2] << 8 | cm_spec[3]) & 0xffff;
|
|
uint8_t cm_entry_size = cm_spec[4];
|
|
|
|
uint16_t x_origin = (uint16_t)(image_spec[1] << 8 | image_spec[0]);
|
|
uint16_t y_origin = (uint16_t)(image_spec[3] << 8 | image_spec[2]);
|
|
uint16_t image_width = (uint16_t)(image_spec[5] << 8 | image_spec[4]);
|
|
uint16_t image_height = (uint16_t)(image_spec[7] << 8 | image_spec[6]);
|
|
uint8_t pixel_depth = image_spec[8];
|
|
uint8_t image_desc = image_spec[9];
|
|
|
|
uint8_t alpha_channel_depth = image_desc & 0b1111;
|
|
bool right_to_left_ordering = image_desc >> 4 & 0x1;
|
|
bool top_to_bottom_ordering = image_desc >> 5 & 0x1;
|
|
|
|
if (!(id_length == 0 && color_map_type == 0 && image_type == 2
|
|
&& first_entry_index == 0 && cm_length == 0 && cm_entry_size == 0
|
|
&& x_origin == 0 && y_origin == 128 && image_width == 128
|
|
&& image_height == 128 && pixel_depth == 32 && image_desc == 40
|
|
&& alpha_channel_depth == 8 && right_to_left_ordering == 0
|
|
&& top_to_bottom_ordering == 1)) {
|
|
fprintf(stderr, "error: invalid texture map \"%s\"\n", filename);
|
|
printf("id length: %d\n", id_length);
|
|
printf("color map type: %d\n", color_map_type);
|
|
printf("image type: %d\n", image_type);
|
|
printf("first entry index: %d\n", first_entry_index);
|
|
printf("color map length: %d\n", cm_length);
|
|
printf("color map entry size: %d\n", cm_entry_size);
|
|
printf("x_origin: %d\n", x_origin);
|
|
printf("y_origin: %d\n", y_origin);
|
|
printf("image_width: %d\n", image_width);
|
|
printf("image_height: %d\n", image_height);
|
|
printf("pixel_depth: %d\n", pixel_depth);
|
|
printf("image_desc: %d\n", image_desc);
|
|
printf("alpha_channel_depth: %d\n", alpha_channel_depth);
|
|
printf("right_to_left_ordering: %d\n", right_to_left_ordering);
|
|
printf("top_to_bottom_ordering: %d\n", top_to_bottom_ordering);
|
|
|
|
result = nullptr;
|
|
goto exit_close_file;
|
|
}
|
|
|
|
uint32_t* data = malloc(sizeof(uint32_t) * image_width * image_height);
|
|
size_t data_read
|
|
= fread(data, sizeof(uint32_t), image_width * image_height, file);
|
|
if (data_read != image_width * image_height) {
|
|
printf("data_bytes_read: %ld\n", data_read);
|
|
printf(
|
|
"expected: %ld\n", sizeof(uint32_t) * image_width * image_height);
|
|
fprintf(
|
|
stderr,
|
|
"error: could not read texture map TGA data of file \"%s\"\n",
|
|
filename);
|
|
|
|
result = nullptr;
|
|
goto exit_free_data;
|
|
}
|
|
|
|
result = malloc(sizeof(TextureMap));
|
|
*result = (TextureMap) {
|
|
.data = data,
|
|
.width = image_width,
|
|
.height = image_height,
|
|
};
|
|
|
|
fclose(file);
|
|
return result;
|
|
|
|
exit_free_data:
|
|
free(data);
|
|
exit_close_file:
|
|
fclose(file);
|
|
return result;
|
|
}
|
|
|
|
void texture_map_free(TextureMap* map)
|
|
{
|
|
free(map->data);
|
|
free(map);
|
|
}
|
|
|
|
void texture_map_read_texture(TextureMap* map, uint32_t* data, int id)
|
|
{
|
|
for (size_t y = 0; y < 8; ++y) {
|
|
for (size_t x = 0; x < 8; ++x) {
|
|
size_t oy = (size_t)(id / 8) + y;
|
|
size_t ox = (size_t)(id % 8) + x;
|
|
data[y * 8 + x] = map->data[oy * map->width + ox];
|
|
}
|
|
}
|
|
}
|