a-game

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

commit 8184b6442df94646fac162fab217abff111cf7b0
parent 27962884cc72f5136c74fb125d8c97e8c9e04ebc
Author: amin <dev@aminmesbah.com>
Date:   Sat,  6 Jul 2019 00:35:03 +0000

Move image code to separate files

FossilOrigin-Name: a8bcff94c7abec8b72ae58607c4423c38d5283288a2a56fea3512ad813a2df5e
Diffstat:
Msrc/game.c | 142+------------------------------------------------------------------------------
Msrc/game.h | 2++
Asrc/image.c | 120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/image.h | 19+++++++++++++++++++
4 files changed, 142 insertions(+), 141 deletions(-)

diff --git a/src/game.c b/src/game.c @@ -10,147 +10,7 @@ #include "render.c" #include "world.c" #include "input.c" - -#pragma pack(push, 1) -struct ImgTgaHeader -{ - // http://paulbourke.net/dataformats/tga/ - u8 id_length; - u8 color_map_type; - u8 data_type_code; - u16 color_map_origin; - u16 color_map_length; - u8 color_map_depth; - u16 x_origin; - u16 y_origin; - u16 width; - u16 height; - u8 bits_per_pixel; - u8 image_descriptor; -}; -#pragma pack(pop) -static_assert(sizeof(struct ImgTgaHeader) == 18, ""); - -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); - printf("data_type_code: %u\n", h.data_type_code); - printf("color_map_origin: %u\n", h.color_map_origin); - printf("color_map_length: %u\n", h.color_map_length); - printf("color_map_depth: %u\n", h.color_map_depth); - printf("x_origin: %u\n", h.x_origin); - printf("y_origin: %u\n", h.y_origin); - printf("width: %u\n", h.width); - printf("height: %u\n", h.height); - printf("bits_per_pixel: %u\n", h.bits_per_pixel); - 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); - 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 - assert(h.id_length == 0); - // Color maps not currently supported - 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) - { - *out_width = h.width; - } - if (out_height) - { - *out_height = h.height; - } - - u8 bytes_per_pixel = h.bits_per_pixel / 8; - 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) - { - // uncompressed RGB - for (size_t b = 0; b < img_data_buf_len; b++) - { - img_data[b] = img_consume_byte(&buffer, buf_end); - } - } - else if (h.data_type_code == 10) - { - // Run Length Encoded RGB - size_t img_bytes_read = 0; - while (img_bytes_read < img_data_buf_len) - { - u8 packet_header = img_consume_byte(&buffer, buf_end); - u8 run_length_header_bit = packet_header >> 7; - u32 run_count = (packet_header & (~(1 << 7))) + 1; - assert(run_count <= 128); - u32 run_length_in_bytes = run_count * bytes_per_pixel; - - if (run_length_header_bit) - { - u8 pixel[4] = {0}; - for (u32 b = 0; b < bytes_per_pixel; b++) - { - pixel[b] = img_consume_byte(&buffer, buf_end); - } - for (u32 b = 0; b < run_length_in_bytes; b++) - { - img_data[img_bytes_read + b] = pixel[b % bytes_per_pixel]; - } - img_bytes_read += run_length_in_bytes; - } - else - { - for (u32 b = 0; b < run_length_in_bytes; b++) - { - img_data[img_bytes_read + b] = img_consume_byte(&buffer, buf_end); - } - img_bytes_read += run_length_in_bytes; - } - } - } - - // 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 = &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[b]; - top_row[b] = bot_row[b]; - bot_row[b] = temp; - } - } - return img_data; -} +#include "image.c" internal void move_mode_print(enum MoveMode s) { diff --git a/src/game.h b/src/game.h @@ -81,6 +81,8 @@ void *memmove(void *dst, const void *src, size_t n) #include "render.h" #include "world.h" #include "input.h" +#include "image.h" + #include "platform.h" static_assert(-1 == ~0, "Implementation doesn't use two's complement"); diff --git a/src/image.c b/src/image.c @@ -0,0 +1,120 @@ +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); + printf("data_type_code: %u\n", h.data_type_code); + printf("color_map_origin: %u\n", h.color_map_origin); + printf("color_map_length: %u\n", h.color_map_length); + printf("color_map_depth: %u\n", h.color_map_depth); + printf("x_origin: %u\n", h.x_origin); + printf("y_origin: %u\n", h.y_origin); + printf("width: %u\n", h.width); + printf("height: %u\n", h.height); + printf("bits_per_pixel: %u\n", h.bits_per_pixel); + 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); + 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 + assert(h.id_length == 0); + // Color maps not currently supported + 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) + { + *out_width = h.width; + } + if (out_height) + { + *out_height = h.height; + } + + u8 bytes_per_pixel = h.bits_per_pixel / 8; + 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) + { + // uncompressed RGB + for (size_t b = 0; b < img_data_buf_len; b++) + { + img_data[b] = img_consume_byte(&buffer, buf_end); + } + } + else if (h.data_type_code == 10) + { + // Run Length Encoded RGB + size_t img_bytes_read = 0; + while (img_bytes_read < img_data_buf_len) + { + u8 packet_header = img_consume_byte(&buffer, buf_end); + u8 run_length_header_bit = packet_header >> 7; + u32 run_count = (packet_header & (~(1 << 7))) + 1; + assert(run_count <= 128); + u32 run_length_in_bytes = run_count * bytes_per_pixel; + + if (run_length_header_bit) + { + u8 pixel[4] = {0}; + for (u32 b = 0; b < bytes_per_pixel; b++) + { + pixel[b] = img_consume_byte(&buffer, buf_end); + } + for (u32 b = 0; b < run_length_in_bytes; b++) + { + img_data[img_bytes_read + b] = pixel[b % bytes_per_pixel]; + } + img_bytes_read += run_length_in_bytes; + } + else + { + for (u32 b = 0; b < run_length_in_bytes; b++) + { + img_data[img_bytes_read + b] = img_consume_byte(&buffer, buf_end); + } + img_bytes_read += run_length_in_bytes; + } + } + } + + // 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 = &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[b]; + top_row[b] = bot_row[b]; + bot_row[b] = temp; + } + } + return img_data; +} diff --git a/src/image.h b/src/image.h @@ -0,0 +1,19 @@ +#pragma pack(push, 1) +struct ImgTgaHeader +{ + // http://paulbourke.net/dataformats/tga/ + u8 id_length; + u8 color_map_type; + u8 data_type_code; + u16 color_map_origin; + u16 color_map_length; + u8 color_map_depth; + u16 x_origin; + u16 y_origin; + u16 width; + u16 height; + u8 bits_per_pixel; + u8 image_descriptor; +}; +#pragma pack(pop) +static_assert(sizeof(struct ImgTgaHeader) == 18, "");