#include "texture_map.h" #include #include #include #include #include #include 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]; } } }