a-game

2D platformer written from scratch.
git clone git://git.amin.space/a-game.git
Log | Files | Refs | README | LICENSE

commit 27962884cc72f5136c74fb125d8c97e8c9e04ebc
parent ccdb9723373b4dfee6cb0b97aef5392a07cc973a
Author: amin <dev@aminmesbah.com>
Date:   Fri,  5 Jul 2019 23:07:54 +0000

Clean up image loading code

FossilOrigin-Name: 0fb7a63c65b43f90dc500f21d3fd7d387760ecf8cb48387da0372d467d55b04b
Diffstat:
Msrc/game.c | 78++++++++++++++++++++++++++++++++++++++++++++----------------------------------
1 file changed, 44 insertions(+), 34 deletions(-)

diff --git a/src/game.c b/src/game.c @@ -31,7 +31,7 @@ struct ImgTgaHeader #pragma pack(pop) static_assert(sizeof(struct ImgTgaHeader) == 18, ""); -void img_tga_header_print(struct ImgTgaHeader h) +internal void img_tga_header_print(struct ImgTgaHeader h) { printf("id_length: %u\n", h.id_length); printf("color_map_type: %u\n", h.color_map_type); @@ -47,13 +47,25 @@ void img_tga_header_print(struct ImgTgaHeader h) printf("image_descriptor: %u\n", h.image_descriptor); } +internal u8 img_consume_byte(u8 **buffer, uintptr_t end_address) +{ + u8 byte = 0; + if ((uintptr_t)*buffer < end_address) + { + byte = **buffer; + (*buffer)++; + } + return byte; +} + internal u8 *img_load_from_memory(u8 *buffer, size_t len, i32 *out_width, i32 *out_height, struct StackAllocator *allocator) { assert(buffer); - u8 *one_past_last = buffer + (len * sizeof(u8)); + uintptr_t buf_end = (uintptr_t)buffer + (len * sizeof(u8)); assert(len >= sizeof(struct ImgTgaHeader)); struct ImgTgaHeader h = *(struct ImgTgaHeader *)buffer; + buffer += sizeof(struct ImgTgaHeader); img_tga_header_print(h); // Image descriptor not currently accounted for @@ -62,6 +74,7 @@ internal u8 *img_load_from_memory(u8 *buffer, size_t len, i32 *out_width, i32 *o assert(h.color_map_type == 0); // Only RGB is supported assert(h.data_type_code == 2 || h.data_type_code == 10); + assert(h.bits_per_pixel <= 32); if (out_width) { @@ -72,74 +85,71 @@ internal u8 *img_load_from_memory(u8 *buffer, size_t len, i32 *out_width, i32 *o *out_height = h.height; } - buffer += sizeof(struct ImgTgaHeader); - u8 bytes_per_pixel = h.bits_per_pixel / 8; - size_t pixel_buffer_length = h.width * h.height * bytes_per_pixel; - u8 *pixels = mem_st_alloc_buffer(allocator, u8, pixel_buffer_length); - assert(pixels); + size_t bytes_per_row = h.width * bytes_per_pixel; + size_t img_data_buf_len = h.height * bytes_per_row; + u8 *img_data = mem_st_alloc_buffer(allocator, u8, img_data_buf_len); + assert(img_data); if (h.data_type_code == 2) { - for (size_t i = 0; i < pixel_buffer_length; i++) + // uncompressed RGB + for (size_t b = 0; b < img_data_buf_len; b++) { - pixels[i] = *buffer++; + img_data[b] = img_consume_byte(&buffer, buf_end); } } else if (h.data_type_code == 10) { - size_t pixel_bytes_read = 0; - while (pixel_bytes_read < pixel_buffer_length) + // Run Length Encoded RGB + size_t img_bytes_read = 0; + while (img_bytes_read < img_data_buf_len) { - u8 packet_header = *buffer++; - printf("h: %X --- ", packet_header); - + u8 packet_header = img_consume_byte(&buffer, buf_end); u8 run_length_header_bit = packet_header >> 7; - u8 run_count = (packet_header & (~(1 << 7))) + 1; + u32 run_count = (packet_header & (~(1 << 7))) + 1; assert(run_count <= 128); - printf("run_count: %u\n", run_count); + u32 run_length_in_bytes = run_count * bytes_per_pixel; + if (run_length_header_bit) { - printf("rl\n"); u8 pixel[4] = {0}; - for (u8 i = 0; i < bytes_per_pixel; i++) + for (u32 b = 0; b < bytes_per_pixel; b++) { - pixel[i] = *buffer++; + pixel[b] = img_consume_byte(&buffer, buf_end); } - for (u8 i = 0; i < run_count * bytes_per_pixel; i++) + for (u32 b = 0; b < run_length_in_bytes; b++) { - pixels[pixel_bytes_read + i] = pixel[i % bytes_per_pixel]; + img_data[img_bytes_read + b] = pixel[b % bytes_per_pixel]; } - pixel_bytes_read += run_count * bytes_per_pixel; + img_bytes_read += run_length_in_bytes; } else { - printf("raw\n"); - for (u8 i = 0; i < run_count * bytes_per_pixel; i++) + for (u32 b = 0; b < run_length_in_bytes; b++) { - pixels[pixel_bytes_read + i] = *buffer++; + img_data[img_bytes_read + b] = img_consume_byte(&buffer, buf_end); } - pixel_bytes_read += run_count * bytes_per_pixel; + img_bytes_read += run_length_in_bytes; } } } - u32 bytes_per_row = h.width * bytes_per_pixel; // NOTE(amin): Intentional truncating division. If height is odd, we want // our last row offset to be 1 less than the middle row. u32 half_height = h.height / 2; for (size_t row_offset = 0; row_offset < half_height; row_offset++) { - u8 *top_row = &pixels[row_offset * bytes_per_row]; - u8 *bot_row = &pixels[(h.height - row_offset - 1) * bytes_per_row]; - for (size_t i = 0; i < bytes_per_row; i++) + u8 *top_row = &img_data[row_offset * bytes_per_row]; + u8 *bot_row = &img_data[(h.height - row_offset - 1) * bytes_per_row]; + for (size_t b = 0; b < bytes_per_row; b++) { - u8 temp = top_row[i]; - top_row[i] = bot_row[i]; - bot_row[i] = temp; + u8 temp = top_row[b]; + top_row[b] = bot_row[b]; + bot_row[b] = temp; } } - return pixels; + return img_data; } internal void move_mode_print(enum MoveMode s)