From 419a247584803825a22274381047cf197d11e231 Mon Sep 17 00:00:00 2001 From: Ulysse Cura Date: Fri, 21 Aug 2026 22:57:55 +0200 Subject: [PATCH] Changed way asset builder works. --- SDL3_Core | 2 +- assets/Makefile | 28 +- assets/asset_builder/README.md | 51 +- assets/asset_builder/src/Makefile | 3 +- assets/asset_builder/src/asset_file.c | 92 ---- assets/asset_builder/src/headers/asset_file.h | 25 - assets/asset_builder/src/headers/errors.h | 27 +- assets/asset_builder/src/headers/image.h | 6 +- assets/asset_builder/src/headers/map.h | 6 +- assets/asset_builder/src/headers/object.h | 8 + assets/asset_builder/src/headers/utils.h | 10 + assets/asset_builder/src/image.c | 180 ++----- assets/asset_builder/src/main.c | 265 +++++++--- assets/asset_builder/src/map.c | 456 ++++++------------ assets/asset_builder/src/object.c | 50 ++ assets/asset_builder/src/utils.c | 27 ++ 16 files changed, 544 insertions(+), 692 deletions(-) delete mode 100644 assets/asset_builder/src/asset_file.c delete mode 100644 assets/asset_builder/src/headers/asset_file.h create mode 100644 assets/asset_builder/src/headers/object.h create mode 100644 assets/asset_builder/src/headers/utils.h create mode 100644 assets/asset_builder/src/object.c create mode 100644 assets/asset_builder/src/utils.c diff --git a/SDL3_Core b/SDL3_Core index 8d021e5..2a0803d 160000 --- a/SDL3_Core +++ b/SDL3_Core @@ -1 +1 @@ -Subproject commit 8d021e517a6ccbdce9021deffe1f7179f27057ca +Subproject commit 2a0803d4c4e15048fced7d3c402b76fc782e0d85 diff --git a/assets/Makefile b/assets/Makefile index 05b8601..7a5051d 100644 --- a/assets/Makefile +++ b/assets/Makefile @@ -11,20 +11,36 @@ ASSETS := \ ASSETS := $(addprefix $(ASSETS_DIR)/,$(ASSETS)) +ASSETS_OBJECTS = $(ASSETS:%=$(BUILD_DIR)/%.o) + + ASSET_BUILDER_DIR = $(ASSETS_DIR)/asset_builder/src - ASSET_BUILDER_OUTPUT = $(BUILD_DIR)/$(ASSETS_DIR)/asset_builder/asset_builder - -build_assets: setup_asset build_asset_builder asset_end - include $(ASSET_BUILDER_DIR)/Makefile +build_assets: setup_asset build_asset_builder count_assets_build asset_end + +# Current file nb to process +CURRENT_ASSET_FILE := 0 + +# Count nb of files to build +count_assets_build: + $(eval export TOTAL_ASSETS_FILES := $(shell echo $$(($$(make -n $(ASSETS_OBJECTS) 2>/dev/null | grep -c "Building") + 1)))) + setup_asset: @echo "Building $(notdir $(ASSET_OUTPUT))" + $(Q)mkdir -p $(dir $(ASSETS_OBJECTS)) -$(ASSET_OUTPUT): $(ASSET_BUILDER_OUTPUT) $(ASSETS) +$(ASSET_OUTPUT): $(ASSETS_OBJECTS) $(ASSET_BUILDER_OUTPUT) @echo -e "[100%] $(YELLOW)Building $(notdir $(ASSET_OUTPUT))$(RESET)" - $(Q)$(ASSET_BUILDER_OUTPUT) $@ $(ASSETS) + $(Q)$(ASSET_BUILDER_OUTPUT) $@ $(ASSETS_OBJECTS) + +# Build .o files +$(BUILD_DIR)/$(ASSETS_DIR)/%.o: $(ASSETS_DIR)/% $(ASSET_BUILDER_OUTPUT) + $(eval CURRENT_ASSET_FILE := $(shell echo $$(($(CURRENT_ASSET_FILE)+1)))) + $(eval PERCENTAGE := $(shell echo $$(($(CURRENT_ASSET_FILE)*100/$(TOTAL_ASSETS_FILES))))) + @echo -e "[$(PERCENTAGE)%] $(GREEN)Building ASSET object $@$(RESET)" + $(Q)$(ASSET_BUILDER_OUTPUT) $@ -c $< asset_end: $(ASSET_OUTPUT) @echo "Built target $(notdir $(ASSET_OUTPUT))" diff --git a/assets/asset_builder/README.md b/assets/asset_builder/README.md index 23672d8..088d9d8 100644 --- a/assets/asset_builder/README.md +++ b/assets/asset_builder/README.md @@ -7,42 +7,35 @@ The supported file formats are : The different files format are deduced from the extensions only. -The code has some optimisation problems but here is the main idea : +-------- -First calculate header wich consists of : +To build objects files, they are analised and written in an output file wich content depend on asset type. -| Description | Length | -| :---------------- | :------------------------------------------------ | -| Assets number | unsigned int (32 bits) | -| ... | | -| Asset name | const char [] (variable length, ends with '\00') | -| Asset start index | unsigned int (32 bits) | -| ... | | +Their structure will be : -This calculation needs to analse the content of inputs files to calculate the start offsets in the file. +| Description | Length | +| :---------------- | :-----------------------| +| Asset size | unsigned int (32 bits) | +| Asset data | depends on asset type | -Then write the content of each file in the same order as they were analysed for header calculations. - -For the moment each input file is openend and analized 2 times. - -## Image (.png) +#### Image (.png) Convert png's RGBA8888 to custom RGB565 with #0001 in RGB565 as the transparent color. If png's alpha is null then the color of the pixel will be replaced with this. -### Image asset data structure +##### Image asset data structure | Description | Length | | :---------------- | :------------------------------------------ | -| Image width | unsigned int (32 bits) | -| Image height | unsigned int (32 bits) | +| Image width | unsigned short (16 bits) | +| Image height | unsigned short (16 bits) | | Image data | depend on image size, pixel short (16 bits) | -## Maps (.map) +#### Maps (.map) Convert from json to custom format. -### Maps asset data structure +##### Maps asset data structure | Description | Length | | :-------------------------- | :---------------------------------------------------- | @@ -58,7 +51,7 @@ Convert from json to custom format. | Entity ID | unsigned int (32 bits) | | Entity components number | unsigned short (16 bits) | | ... | | -| Component type | unsigned int (32 bits) | +| Component type | unsigned short (16 bits) | | ... | | | Component attributes | depend on attribute type | | int | unsigned int (32 bits) | @@ -67,3 +60,19 @@ Convert from json to custom format. | str | const char [] (variable length, ends with '\00') | | ... | | | ... | | + +-------- + +To build asset file : + +First calculate header wich consists of : + +| Description | Length | +| :---------------- | :------------------------------------------------ | +| Assets number | unsigned int (32 bits) | +| ... | | +| Asset name | const char [] (variable length, ends with '\00') | +| Asset start index | unsigned int (32 bits) | +| ... | | + +And then write content of each input files. diff --git a/assets/asset_builder/src/Makefile b/assets/asset_builder/src/Makefile index 3f0e5f1..7d71f70 100644 --- a/assets/asset_builder/src/Makefile +++ b/assets/asset_builder/src/Makefile @@ -1,8 +1,9 @@ # Source files ASSET_BUILDER_SOURCES := \ - asset_file.c \ + object.c \ image.c \ map.c \ + utils.c \ main.c # Compiler and flags diff --git a/assets/asset_builder/src/asset_file.c b/assets/asset_builder/src/asset_file.c deleted file mode 100644 index 7e2e0f1..0000000 --- a/assets/asset_builder/src/asset_file.c +++ /dev/null @@ -1,92 +0,0 @@ -#include "asset_file.h" - -#include -#include -#include "image.h" -#include "map.h" -#include "errors.h" - -int parse_file_for_header(const char *input_file_name, asset_header_def_t *asset_header_def) -{ - const char *file_name_dot = strrchr(input_file_name, '.'); - - if(!file_name_dot) - { - error_printf("File does not have an extension."); - return EXIT_FAILURE; - } - - const char *file_name_ext = file_name_dot + 1; - - if(!strcmp(file_name_ext, "png")) - { - if(parse_png_for_header(input_file_name, asset_header_def)) return_failure_int; - } - else if(!strcmp(file_name_ext, "map")) - { - if(parse_map_for_header(input_file_name, asset_header_def)) return_failure_int; - } - else - { - error_printf("Extension unsupported : %s", file_name_dot); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} - -int write_header_to_file(asset_file_header_t *asset_file_header, FILE *output_file) -{ - if(fwrite(&asset_file_header->assets_number, sizeof(asset_file_header->assets_number), 1, output_file) != 1) - { - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; - } - - for(uint32_t i = 0; i < asset_file_header->assets_number; i++) - { - size_t name_length = strlen(asset_file_header->assets_header_def[i].name) + 1; - if(fwrite(asset_file_header->assets_header_def[i].name, sizeof(unsigned char), name_length, output_file) != name_length) - { - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; - } - - if(fwrite(&asset_file_header->assets_header_def[i].start, sizeof(asset_file_header->assets_header_def[i].start), 1, output_file) != 1) - { - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; - } - } - - return EXIT_SUCCESS; -} - -int parse_file_for_content_and_write(const char *input_file_name, FILE *output_file) -{ - const char *file_name_dot = strrchr(input_file_name, '.'); - - if(!file_name_dot) - { - error_printf("File does not have an extension."); - return EXIT_FAILURE; - } - - const char *file_name_ext = file_name_dot + 1; - - if(!strcmp(file_name_ext, "png")) - { - if(parse_png_for_content_and_write(input_file_name, output_file)) return_failure_int; - } - else if(!strcmp(file_name_ext, "map")) - { - if(parse_map_for_content_and_write(input_file_name, output_file)) return_failure_int; - } - else - { - error_printf("Extension unsupported : %s", file_name_dot); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/assets/asset_builder/src/headers/asset_file.h b/assets/asset_builder/src/headers/asset_file.h deleted file mode 100644 index de391c8..0000000 --- a/assets/asset_builder/src/headers/asset_file.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef ASSET_FILE_H -#define ASSET_FILE_H - -#include -#include - -typedef struct asset_header_def_t { - char *name; - uint32_t start, end; -} asset_header_def_t; - -typedef struct asset_file_header_t { - uint32_t assets_number; - asset_header_def_t *assets_header_def; - - size_t header_size; -} asset_file_header_t; - -int parse_file_for_header(const char *input_file_name, asset_header_def_t *asset_header_def); - -int write_header_to_file(asset_file_header_t *asset_file_header, FILE *output_file); - -int parse_file_for_content_and_write(const char *input_file_name, FILE *output_file); - -#endif // ASSET_FILE_H \ No newline at end of file diff --git a/assets/asset_builder/src/headers/errors.h b/assets/asset_builder/src/headers/errors.h index 4844914..0e68cc6 100644 --- a/assets/asset_builder/src/headers/errors.h +++ b/assets/asset_builder/src/headers/errors.h @@ -15,8 +15,23 @@ fprintf(stderr, "\033[32mINFO\033[m: " __VA_ARGS__); \ fputc('\n', stderr); \ } while (0) + +#define return_failure_int \ + do { \ + fprintf(stderr, "\tin %s:%d:%s()\n", __FILE__, __LINE__, __func__); \ + return EXIT_FAILURE; \ + } while (0); + +#define return_failure_ptr \ + do { \ + fprintf(stderr, "\tin %s:%d:%s()\n", __FILE__, __LINE__, __func__); \ + return NULL; \ + } while (0); #else #define debug_printf(...) + +#define return_failure_int return EXIT_FAILURE; +#define return_failure_ptr return NULL; #endif #define warning_printf(...) \ @@ -32,16 +47,4 @@ fputc('\n', stderr); \ } while (0) -#define return_failure_int \ - do { \ - fprintf(stderr, " in %s:%d:%s()\n", __FILE__, __LINE__, __func__); \ - return EXIT_FAILURE; \ - } while (0); - -#define return_failure_ptr \ - do { \ - fprintf(stderr, " in %s:%d:%s()\n", __FILE__, __LINE__, __func__); \ - return NULL; \ - } while (0); - #endif // ERRORS_H \ No newline at end of file diff --git a/assets/asset_builder/src/headers/image.h b/assets/asset_builder/src/headers/image.h index 477dc9b..30a1869 100644 --- a/assets/asset_builder/src/headers/image.h +++ b/assets/asset_builder/src/headers/image.h @@ -1,9 +1,9 @@ #ifndef IMAGE_H #define IMAGE_H -#include "asset_file.h" +#include +#include -int parse_png_for_header(const char *input_file_name, asset_header_def_t *asset_header_def); -int parse_png_for_content_and_write(const char *input_file_name, FILE *output_file); +int build_image(const char *input_file_name, FILE *output_file, uint32_t *asset_size); #endif // IMAGE_H \ No newline at end of file diff --git a/assets/asset_builder/src/headers/map.h b/assets/asset_builder/src/headers/map.h index e940b13..5aec6f3 100644 --- a/assets/asset_builder/src/headers/map.h +++ b/assets/asset_builder/src/headers/map.h @@ -1,9 +1,9 @@ #ifndef MAP_H #define MAP_H -#include "asset_file.h" +#include +#include -int parse_map_for_header(const char *input_file_name, asset_header_def_t *asset_header_def); -int parse_map_for_content_and_write(const char *input_file_name, FILE *output_file); +int build_map(const char *input_file_name, FILE *output_file, uint32_t *asset_size); #endif // MAP_H \ No newline at end of file diff --git a/assets/asset_builder/src/headers/object.h b/assets/asset_builder/src/headers/object.h new file mode 100644 index 0000000..74bef79 --- /dev/null +++ b/assets/asset_builder/src/headers/object.h @@ -0,0 +1,8 @@ +#ifndef OBJECT_H +#define OBJECT_H + +#include + +int build_object(const char *input_file_path, FILE *output_file); + +#endif // OBJECT_H \ No newline at end of file diff --git a/assets/asset_builder/src/headers/utils.h b/assets/asset_builder/src/headers/utils.h new file mode 100644 index 0000000..0a75cb1 --- /dev/null +++ b/assets/asset_builder/src/headers/utils.h @@ -0,0 +1,10 @@ +#ifndef UTILS_H +#define UTILS_H + +#include + +int file_read(void *ptr, size_t size, size_t nb, FILE *file); + +int file_write(const void *ptr, size_t size, size_t nb, FILE *file); + +#endif // UTILS_H \ No newline at end of file diff --git a/assets/asset_builder/src/image.c b/assets/asset_builder/src/image.c index 1e41dbc..421550d 100644 --- a/assets/asset_builder/src/image.c +++ b/assets/asset_builder/src/image.c @@ -2,96 +2,10 @@ #include #include -#include "asset_file.h" +#include "utils.h" #include "errors.h" -int parse_png_for_header(const char *file_name, asset_header_def_t *asset_header_def) -{ - FILE *input_file = fopen(file_name, "rb"); - - if(!input_file) - { - error_printf("Failed to open input file."); - return EXIT_FAILURE; - } - - // Check png autenticity. - unsigned char sig[8]; - if(fread(sig, sizeof(unsigned char), 8, input_file) != 8) - { - fclose(input_file); - error_printf("Failed to read input file."); - return EXIT_FAILURE; - } - - if(!png_check_sig(sig, 8)) - { - fclose(input_file); - error_printf("Png file is not valid."); - return EXIT_FAILURE; - } - - // PNG structs. - png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if(!png_ptr) - { - fclose(input_file); - error_printf("Failed to allocate png ptr."); - return EXIT_FAILURE; - } - - png_infop info_ptr = png_create_info_struct(png_ptr); - if(!info_ptr) - { - png_destroy_read_struct(&png_ptr, NULL, NULL); - fclose(input_file); - error_printf("Failed to allocate png info."); - return EXIT_FAILURE; - } - - // Fill structs and load data. - png_init_io(png_ptr, input_file); - png_set_sig_bytes(png_ptr, 8); - png_read_info(png_ptr, info_ptr); - - uint32_t width = png_get_image_width(png_ptr, info_ptr); - uint32_t height = png_get_image_height(png_ptr, info_ptr); - uint8_t bit_depth = png_get_bit_depth(png_ptr, info_ptr); - uint8_t color_type = png_get_color_type(png_ptr, info_ptr); - - // Verify png attributes. - if(bit_depth != 8) - { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(input_file); - error_printf("Png bit depth not supported."); - return EXIT_FAILURE; - } - - switch(color_type) - { - case PNG_COLOR_TYPE_RGB: - case PNG_COLOR_TYPE_RGB_ALPHA: - break; - - default: - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(input_file); - error_printf("Png color type not supported."); - return EXIT_FAILURE; - } - - // Fill asset def. - asset_header_def->start = 0; - asset_header_def->end = sizeof(width) + sizeof(height) + height * width * sizeof(uint16_t); - - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(input_file); - - return EXIT_SUCCESS; -} - -int parse_png_for_content_and_write(const char *input_file_name, FILE *output_file) +int build_image(const char *input_file_name, FILE *output_file, uint32_t *asset_size) { FILE *input_file = fopen(input_file_name, "rb"); @@ -102,18 +16,13 @@ int parse_png_for_content_and_write(const char *input_file_name, FILE *output_fi } // Check png autenticity. - unsigned char sig[8]; - if(fread(sig, sizeof(unsigned char), 8, input_file) != 8) - { - fclose(input_file); - error_printf("Failed to read input file."); - return EXIT_FAILURE; - } - + png_byte sig[8]; + if(file_read(sig, sizeof(png_byte), sizeof(sig), input_file)) return_failure_int; if(!png_check_sig(sig, 8)) { - fclose(input_file); error_printf("Png file is not valid."); + if(fclose(input_file)) + error_printf("Failed to close input file : %d", errno); return EXIT_FAILURE; } @@ -121,17 +30,19 @@ int parse_png_for_content_and_write(const char *input_file_name, FILE *output_fi png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) { - fclose(input_file); error_printf("Failed to allocate png ptr."); + if(fclose(input_file)) + error_printf("Failed to close input file : %d", errno); return EXIT_FAILURE; } png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { - png_destroy_read_struct(&png_ptr, NULL, NULL); - fclose(input_file); error_printf("Failed to allocate png info."); + png_destroy_read_struct(&png_ptr, NULL, NULL); + if(fclose(input_file)) + error_printf("Failed to close input file : %d", errno); return EXIT_FAILURE; } @@ -140,27 +51,31 @@ int parse_png_for_content_and_write(const char *input_file_name, FILE *output_fi png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); - uint32_t width = png_get_image_width(png_ptr, info_ptr); - uint32_t height = png_get_image_height(png_ptr, info_ptr); + uint16_t width = png_get_image_width(png_ptr, info_ptr); + uint16_t height = png_get_image_height(png_ptr, info_ptr); size_t row_length = png_get_rowbytes(png_ptr, info_ptr); // Write image size. - if(fwrite(&width, sizeof(width), 1, output_file) != 1) + if(file_write(&width, sizeof(width), 1, output_file)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(input_file); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; + if(fclose(input_file)) + error_printf("Failed to close input file : %d", errno); + return_failure_int; } - if(fwrite(&height, sizeof(height), 1, output_file) != 1) + *asset_size += sizeof(width); + + if(file_write(&height, sizeof(height), 1, output_file)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(input_file); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; + if(fclose(input_file)) + error_printf("Failed to close input file : %d", errno); + return_failure_int; } + *asset_size += sizeof(height); + // Prepare storage. png_byte src_pixels[height * row_length]; png_bytep src_row_ptrs[height]; @@ -170,46 +85,43 @@ int parse_png_for_content_and_write(const char *input_file_name, FILE *output_fi // Read pixels. png_read_image(png_ptr, src_row_ptrs); - uint16_t dst_pixels[width * height * sizeof(uint16_t)]; + uint16_t dst_pixels[width * height]; - for(uint32_t i = 0; i < height; i++) + for(uint16_t i = 0; i < height; i++) { - for(uint32_t j = 0; j < width; j += 1) + for(uint16_t j = 0; j < width; j += 1) { - uint8_t r, g, b; - if(src_pixels[i * row_length + j * 4 + 3]) { - r = src_pixels[i * row_length + j * 4] >> 3; - g = src_pixels[i * row_length + j * 4 + 1] >> 2; - b = src_pixels[i * row_length + j * 4 + 2] >> 3; + uint8_t r = src_pixels[i * row_length + j * 4] >> 3; + uint8_t g = src_pixels[i * row_length + j * 4 + 1] >> 2; + uint8_t b = src_pixels[i * row_length + j * 4 + 2] >> 3; + + dst_pixels[i * width + j] = ((r) << 11) | ((g) << 5) | b; } else { - r = 0x00; - g = 0x00; - b = 0x01; + dst_pixels[i * width + j] = 0x0001; } - - uint16_t pixel = ((r) << 11) | ((g) << 5) | b; - - dst_pixels[i * width + j] = pixel; - -// printf("\033[48;2;%d;%d;%dm ", r << 3, g << 2, b << 3); } -// puts("\033[m"); } - if(fwrite(&dst_pixels, sizeof(uint16_t), width * height, output_file) != width * height) + if(file_write(&dst_pixels, sizeof(*dst_pixels), width * height, output_file)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(input_file); - error_printf("Failed to write to output file : %d", errno); + if(fclose(input_file)) + error_printf("Failed to close input file : %d", errno); + return_failure_int; + } + + *asset_size += sizeof(dst_pixels); + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + if(fclose(input_file)) + { + error_printf("Failed to close input file : %d", errno); return EXIT_FAILURE; } - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(input_file); - return EXIT_SUCCESS; } diff --git a/assets/asset_builder/src/main.c b/assets/asset_builder/src/main.c index 920fa83..6512ba8 100644 --- a/assets/asset_builder/src/main.c +++ b/assets/asset_builder/src/main.c @@ -1,101 +1,212 @@ #include #include #include -#include "asset_file.h" +#include +#include "object.h" +#include "utils.h" #include "errors.h" +typedef enum build_function_t { + BUILD_OBJECT, + BUILD_ASSET_FILE +} build_function_t; + +void print_usage(void) +{ + puts("\033[33musage\033[m:"); + puts("\tasset_builder output_object_file -c input_file"); + puts("\tasset_builder output_asset_file input_object_file [input_object_file2 ...]"); +} + int main(int argc, char *argv[]) { - int exit_status = EXIT_FAILURE; - - FILE *output_asset_file = NULL; - - // Verify arguments minimum number. + // Parse args if(argc < 3) { - puts("\033[33musage\033[m: asset_builder output_file input_file [input_file_2 ...]"); - goto end; + print_usage(); + return EXIT_FAILURE; } - // Header size and content. - asset_file_header_t asset_file_header; - asset_file_header.assets_number = argc - 2; - asset_file_header.header_size = sizeof(asset_file_header.assets_number) + sizeof(uint32_t) * asset_file_header.assets_number; - asset_file_header.assets_header_def = calloc(asset_file_header.assets_number, sizeof(asset_header_def_t)); - if(!asset_file_header.assets_header_def) + const build_function_t build_function = strcmp(argv[2], "-c") ? BUILD_ASSET_FILE : BUILD_OBJECT; + + const char *output_file_path = argv[1]; + FILE *output_file = fopen(output_file_path, "wb"); + + if(!output_file) { - error_printf("Failed to allocate memory."); - goto end; + error_printf("Failed to open output file : %d", errno); + return EXIT_FAILURE; } - // Set assets name. - for(uint32_t i = 0; i < asset_file_header.assets_number; i++) + if(build_function == BUILD_OBJECT) { - const char *file_name = argv[i + 2]; - - const char *file_name_last_slash = strrchr(file_name, '/'); - const char *file_base_name = file_name_last_slash ? file_name_last_slash + 1 : file_name; - - const char *file_name_dot = strrchr(file_name, '.'); - const char *file_name_ext = file_name_dot ? file_name_dot + 1 : file_name; - - size_t asset_name_length = strlen(file_base_name) - strlen(file_name_ext); - - asset_file_header.assets_header_def[i].name = malloc(asset_name_length); - asset_file_header.assets_header_def[i].name[asset_name_length - 1] = '\0'; - strncpy(asset_file_header.assets_header_def[i].name, file_base_name, asset_name_length - 1); - - // Update header size. - asset_file_header.header_size += asset_name_length; - } - - // Parse input files to create header structure and fill output file. - output_asset_file = fopen(argv[1], "wb"); - if(!output_asset_file) - { - error_printf("could not create output file."); - goto end; - } - - for(uint32_t i = 0; i < asset_file_header.assets_number; i++) - { - if(parse_file_for_header(argv[i + 2], &asset_file_header.assets_header_def[i])) return_failure_int; - - // Calculate absolute position of assets in the file. - if(i) asset_file_header.assets_header_def[i].start = asset_file_header.assets_header_def[i - 1].end; - else asset_file_header.assets_header_def[0].start = asset_file_header.header_size; - asset_file_header.assets_header_def[i].end += asset_file_header.assets_header_def[i].start; - } - - if(write_header_to_file(&asset_file_header, output_asset_file)) - { - error_printf("Failed to write to output file : %d", errno); - goto end; - } - - for(uint32_t i = 0; i < asset_file_header.assets_number; i++) - { - if(parse_file_for_content_and_write(argv[i + 2], output_asset_file)) return_failure_int; - } - - exit_status = EXIT_SUCCESS; - -end: - if(asset_file_header.assets_header_def) - { - for(uint32_t i = 0; i < asset_file_header.assets_number; i++) + if(argc != 4) { - if(asset_file_header.assets_header_def[i].name) + print_usage(); + return EXIT_FAILURE; + } + + const char *input_file_path = argv[3]; + + if(build_object(input_file_path, output_file)) + { + if(fclose(output_file)) + error_printf("Failed to close output file : %d", errno); + + return_failure_int; + } + } + else if(build_function == BUILD_ASSET_FILE) + { + uint32_t header_size = 0; + + const int nb_input_object_files = argc - 2; + + if(file_write(&nb_input_object_files, sizeof(nb_input_object_files), 1, output_file)) + { + if(fclose(output_file)) + error_printf("Failed to close output file : %d", errno); + + return_failure_int; + } + header_size += sizeof(nb_input_object_files); + + FILE *input_object_files[nb_input_object_files]; + + uint32_t input_object_files_sizes[nb_input_object_files]; + uint32_t input_object_files_offsets[nb_input_object_files]; + + for(int i = 0; i < nb_input_object_files; i++) + { + const char *input_object_file_path = argv[i + 2]; + + input_object_files[i] = fopen(input_object_file_path, "rb"); + + if(!input_object_files[i]) { - free(asset_file_header.assets_header_def[i].name); + error_printf("Failed to open input object file : %d", errno); + + for(; i >= 0; i--) + if(fclose(input_object_files[i])) + error_printf("Failed to close input object file : %d", errno); + + if(fclose(output_file)) + error_printf("Failed to close output file : %d", errno); + + return EXIT_FAILURE; + } + + if(file_read(&input_object_files_sizes[i], sizeof(*input_object_files_sizes), 1, input_object_files[i])) + { + for(; i >= 0; i--) + if(fclose(input_object_files[i])) + error_printf("Failed to close input object file : %d", errno); + + if(fclose(output_file)) + error_printf("Failed to close output file : %d", errno); + + return_failure_int + } + + const char *input_object_file_slash = strrchr(input_object_file_path, '/'); + const char *input_object_file_name = input_object_file_slash ? input_object_file_slash + 1 : input_object_file_path; + const char *input_object_file_ext = strchr(input_object_file_path, '.'); + uint32_t input_object_file_base_name_length = strlen(input_object_file_name) - strlen(input_object_file_ext) + 1; + + header_size += input_object_file_base_name_length * sizeof(*input_object_file_name); + header_size += sizeof(*input_object_files_offsets); + } + + input_object_files_offsets[0] = header_size; + + for(int i = 0; i < nb_input_object_files; i++) + { + if(i) input_object_files_offsets[i] = input_object_files_offsets[i - 1] + input_object_files_sizes[i - 1]; + + char *input_object_file_path = argv[i + 2]; + const char *input_object_file_slash = strrchr(input_object_file_path, '/'); + const char *input_object_file_name = input_object_file_slash ? input_object_file_slash + 1 : input_object_file_path; + char *input_object_file_ext = strchr(input_object_file_path, '.'); + input_object_file_ext[0] = '\00'; + uint32_t input_object_file_base_name_length = strlen(input_object_file_name) - strlen(input_object_file_ext) + 1; + + if(file_write(input_object_file_name, sizeof(*input_object_file_name), input_object_file_base_name_length, output_file)) + { + for(i = 0; i < nb_input_object_files; i++) + if(fclose(input_object_files[i])) + error_printf("Failed to close input object file : %d", errno); + + if(fclose(output_file)) + error_printf("Failed to close output file : %d", errno); + + return_failure_int; + } + + if(file_write(&input_object_files_offsets[i], sizeof(*input_object_files_offsets), 1, output_file)) + { + for(i = 0; i < nb_input_object_files; i++) + if(fclose(input_object_files[i])) + error_printf("Failed to close input object file : %d", errno); + + if(fclose(output_file)) + error_printf("Failed to close output file : %d", errno); + + return_failure_int; } } - free(asset_file_header.assets_header_def); + for(int i = 0; i < nb_input_object_files; i++) + { + char buffer[input_object_files_sizes[i]]; + + if(file_read(buffer, sizeof(*buffer), input_object_files_sizes[i], input_object_files[i])) + { + for(i = 0; i < nb_input_object_files; i++) + if(fclose(input_object_files[i])) + error_printf("Failed to close input object file : %d", errno); + + if(fclose(output_file)) + error_printf("Failed to close output file : %d", errno); + + return_failure_int; + } + + if(file_write(buffer, sizeof(*buffer), input_object_files_sizes[i], output_file)) + { + for(i = 0; i < nb_input_object_files; i++) + if(fclose(input_object_files[i])) + error_printf("Failed to close input object file : %d", errno); + + if(fclose(output_file)) + error_printf("Failed to close output file : %d", errno); + + return_failure_int; + } + } + + for(int i = 0; i < nb_input_object_files; i++) + { + if(fclose(input_object_files[i])) + { + error_printf("Failed to close input object file : %d", errno); + + for(i++; i < nb_input_object_files; i++) + if(fclose(input_object_files[i])) + error_printf("Failed to close input object file : %d", errno); + + if(fclose(output_file)) + error_printf("Failed to close output file : %d", errno); + + return EXIT_FAILURE; + } + } } - if(output_asset_file) - fclose(output_asset_file); + if(fclose(output_file)) + { + error_printf("Failed to close output file : %d", errno); + return EXIT_FAILURE; + } - return exit_status; + return EXIT_SUCCESS; } diff --git a/assets/asset_builder/src/map.c b/assets/asset_builder/src/map.c index e7b3d60..56298ef 100644 --- a/assets/asset_builder/src/map.c +++ b/assets/asset_builder/src/map.c @@ -4,171 +4,42 @@ #include #include #include -#include "asset_file.h" +#include "utils.h" #include "errors.h" -int parse_map_for_header(const char *input_file_name, asset_header_def_t *asset_header_def) +static int json_get_object_of_type(const json_object *obj, const char *key, json_type type, json_object **result) { - json_object *root = json_object_from_file(input_file_name); - if (!root) + if(!json_object_object_get_ex(obj, key, result)) { - error_printf("Failed to load input file."); + error_printf("Object doesn't contain key \"%s\".", key); return EXIT_FAILURE; } - if(json_object_object_length(root) != 8) + if(!json_object_is_type(*result, type)) { - json_object_put(root); - error_printf("Map file doesn't contain 8 elements at its root."); + error_printf("Key \"%s\" is not of type %s.", key, json_type_to_name(type)); return EXIT_FAILURE; } - json_object *tmp_obj; + return EXIT_SUCCESS; +} - if(!json_object_object_get_ex(root, "MapWidth", &tmp_obj)) +static inline int json_get_idx_of_type(const json_object *obj, size_t idx, json_type type, json_object **result) +{ + *result = json_object_array_get_idx(obj, idx); + + if(!*result) { - json_object_put(root); - error_printf("Map file doesn't contain key \"MapWidth\"."); + error_printf("Array index out of range : %lu.", idx); return EXIT_FAILURE; } - if(!json_object_is_type(tmp_obj, json_type_int)) + if(!json_object_is_type(*result, type)) { - error_printf("Map key \"MapWidth\" is not of type int."); + error_printf("Result is not of type %s.", json_type_to_name(type)); return EXIT_FAILURE; } - int map_width = json_object_get_int(tmp_obj); - - if(!json_object_object_get_ex(root, "MapHeight", &tmp_obj)) - { - json_object_put(root); - error_printf("Map file doesn't contain key \"MapHeight\"."); - return EXIT_FAILURE; - } - - if(!json_object_is_type(tmp_obj, json_type_int)) - { - error_printf("Map key \"MapHeight\" is not of type int."); - return EXIT_FAILURE; - } - - int map_height = json_object_get_int(tmp_obj); - - json_object *entities; - - if(!json_object_object_get_ex(root, "Entities", &entities)) - { - json_object_put(root); - error_printf("Map file doesn't contain key \"Entities\"."); - return EXIT_FAILURE; - } - - if(!json_object_is_type(entities, json_type_array)) - { - json_object_put(root); - error_printf("Map object \"Entities\" is not an array."); - return EXIT_FAILURE; - } - - uint32_t entities_nb = json_object_array_length(entities); - - asset_header_def->start = 0; - asset_header_def->end = sizeof(map_width) + sizeof(map_height) - + map_width * map_height * sizeof(uint16_t) * 4 - + map_width * map_height * sizeof(uint8_t) - + sizeof(entities_nb); - - for(uint32_t i = 0; i < entities_nb; i++) - { - json_object *entity = json_object_array_get_idx(entities, i); - - if(!json_object_is_type(entity, json_type_object)) - { - error_printf("Map entity is not of type object."); - return EXIT_FAILURE; - } - - asset_header_def->end += sizeof(uint32_t); - - json_object *components; - - if(!json_object_object_get_ex(entity, "Components", &components)) - { - error_printf("Entity doesn't have key \"Components\"."); - return EXIT_FAILURE; - } - - if(!json_object_is_type(components, json_type_array)) - { - error_printf("Component is not of type array."); - return EXIT_FAILURE; - } - - uint32_t components_nb = json_object_array_length(components); - - asset_header_def->end += sizeof(components_nb); - - for(uint32_t j = 0; j < components_nb; j++) - { - json_object *component = json_object_array_get_idx(components, j); - - if(!json_object_is_type(component, json_type_object)) - { - error_printf("Entity component is not of type object."); - return EXIT_FAILURE; - } - - asset_header_def->end += sizeof(uint32_t); - - json_object *attributes; - - if(!json_object_object_get_ex(component, "Attributes", &attributes)) - { - error_printf("Component doesn't have key \"Attributes\"."); - return EXIT_FAILURE; - } - - if(!json_object_is_type(attributes, json_type_array)) - { - error_printf("Attributes is not of type array."); - return EXIT_FAILURE; - } - - uint32_t attributes_nb = json_object_array_length(attributes); - - for(uint32_t k = 0; k < attributes_nb; k++) - { - json_object *attribute = json_object_array_get_idx(attributes, k); - - switch(json_object_get_type(attribute)) - { - case json_type_int: - asset_header_def->end += sizeof(uint32_t); - break; - - case json_type_double: - asset_header_def->end += sizeof(float); - break; - - case json_type_boolean: - asset_header_def->end += sizeof(bool); - break; - - case json_type_string: - asset_header_def->end += json_object_get_string_len(attribute) + 1; - break; - - default: - error_printf("Attribute type is not supported : %s", json_type_to_name(json_object_get_type(attribute))); - return EXIT_FAILURE; - } - } - } - } - - json_object_put(root); - return EXIT_SUCCESS; } @@ -177,7 +48,7 @@ typedef enum component_type_t { #include "components.def" } component_type_t; -int parse_map_for_content_and_write(const char *input_file_name, FILE *output_file) +int build_map(const char *input_file_name, FILE *output_file, uint32_t *asset_size) { json_object *root = json_object_from_file(input_file_name); if (!root) @@ -188,283 +59,233 @@ int parse_map_for_content_and_write(const char *input_file_name, FILE *output_fi json_object *tmp_obj; - if(!json_object_object_get_ex(root, "MapWidth", &tmp_obj)) + if(json_get_object_of_type(root, "MapWidth", json_type_int, &tmp_obj)) { json_object_put(root); - error_printf("Map file doesn't contain key \"MapWidth\"."); - return EXIT_FAILURE; + return_failure_int; } - int map_width = json_object_get_int(tmp_obj); + uint16_t map_width = json_object_get_int(tmp_obj); - if(fwrite(&map_width, sizeof(map_width), 1, output_file) != 1) + if(json_get_object_of_type(root, "MapHeight", json_type_int, &tmp_obj)) { json_object_put(root); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; + return_failure_int; } - if(!json_object_object_get_ex(root, "MapHeight", &tmp_obj)) + uint16_t map_height = json_object_get_int(tmp_obj); + + if(file_write(&map_width, sizeof(map_width), 1, output_file)) { json_object_put(root); - error_printf("Map file doesn't contain key \"MapHeight\"."); - return EXIT_FAILURE; + return_failure_int; } - int map_height = json_object_get_int(tmp_obj); + *asset_size += sizeof(map_width); - if(fwrite(&map_height, sizeof(map_height), 1, output_file) != 1) + if(file_write(&map_height, sizeof(map_height), 1, output_file)) { json_object_put(root); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; + return_failure_int; } - // Background Layer 1 - if(!json_object_object_get_ex(root, "BackgroundLayer1", &tmp_obj)) + *asset_size += sizeof(map_height); + + // BackgroundLayers + json_object *backgroundlayers; + if(json_get_object_of_type(root, "BackgroundLayers", json_type_array, &backgroundlayers)) { json_object_put(root); - error_printf("Map file doesn't contain key \"BackgroundLayer1\"."); - return EXIT_FAILURE; + return_failure_int; } - if(!json_object_is_type(tmp_obj, json_type_array)) + uint8_t layer_count = json_object_array_length(backgroundlayers); + + if(file_write(&layer_count, sizeof(layer_count), 1, output_file)) { json_object_put(root); - error_printf("Map background layer 1 is not of type array."); - return EXIT_FAILURE; + return_failure_int; } - uint16_t layer_data[map_width * map_height]; + *asset_size += sizeof(layer_count); - for(size_t i = 0; i < (size_t)map_width * (size_t)map_height; i++) - { - json_object *tile = json_object_array_get_idx(tmp_obj, i); - layer_data[i] = json_object_get_int(tile); - } + uint16_t layer_data[(size_t)map_width * (size_t)map_height]; - if(fwrite(&layer_data, sizeof(uint16_t), map_width * map_height, output_file) != (size_t)map_width * (size_t)map_height) + for(uint8_t i = 0; i < layer_count; i++) { - json_object_put(root); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; - } + json_object *backgroundlayer; + if(json_get_idx_of_type(backgroundlayers, i, json_type_array, &backgroundlayer)) + { + json_object_put(root); + return_failure_int; + } - // Background Layer 2 - if(!json_object_object_get_ex(root, "BackgroundLayer2", &tmp_obj)) - { - json_object_put(root); - error_printf("Map file doesn't contain key \"BackgroundLayer2\"."); - return EXIT_FAILURE; - } + for(size_t j = 0; j < (size_t)map_width * (size_t)map_height; j++) + { + if(json_get_idx_of_type(backgroundlayer, j, json_type_int, &tmp_obj)) + { + json_object_put(root); + return_failure_int; + } + layer_data[j] = json_object_get_int(tmp_obj); + } - if(!json_object_is_type(tmp_obj, json_type_array)) - { - json_object_put(root); - error_printf("Map background layer 1 is not of type array."); - return EXIT_FAILURE; - } + if(file_write(&layer_data, sizeof(*layer_data), (size_t)map_width * (size_t)map_height, output_file)) + { + json_object_put(root); + return_failure_int; + } - for(size_t i = 0; i < (size_t)map_width * (size_t)map_height; i++) - { - json_object *tile = json_object_array_get_idx(tmp_obj, i); - layer_data[i] = json_object_get_int(tile); - } - - if(fwrite(&layer_data, sizeof(uint16_t), map_width * map_height, output_file) != (size_t)map_width * (size_t)map_height) - { - json_object_put(root); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; - } - - // Background Layer 3 - if(!json_object_object_get_ex(root, "BackgroundLayer3", &tmp_obj)) - { - json_object_put(root); - error_printf("Map file doesn't contain key \"BackgroundLayer3\"."); - return EXIT_FAILURE; - } - - if(!json_object_is_type(tmp_obj, json_type_array)) - { - json_object_put(root); - error_printf("Map background layer 1 is not of type array."); - return EXIT_FAILURE; - } - - for(size_t i = 0; i < (size_t)map_width * (size_t)map_height; i++) - { - json_object *tile = json_object_array_get_idx(tmp_obj, i); - layer_data[i] = json_object_get_int(tile); - } - - if(fwrite(&layer_data, sizeof(uint16_t), map_width * map_height, output_file) != (size_t)map_width * (size_t)map_height) - { - json_object_put(root); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; + *asset_size += sizeof(layer_data); } // Foreground - if(!json_object_object_get_ex(root, "Foreground", &tmp_obj)) + json_object *foregroundlayer; + if(json_get_object_of_type(root, "ForegroundLayer", json_type_array, &foregroundlayer)) { json_object_put(root); - error_printf("Map file doesn't contain key \"Foreground\"."); - return EXIT_FAILURE; - } - - if(!json_object_is_type(tmp_obj, json_type_array)) - { - json_object_put(root); - error_printf("Map background layer 1 is not of type array."); - return EXIT_FAILURE; + return_failure_int; } for(size_t i = 0; i < (size_t)map_width * (size_t)map_height; i++) { - json_object *tile = json_object_array_get_idx(tmp_obj, i); - layer_data[i] = json_object_get_int(tile); + if(json_get_idx_of_type(foregroundlayer, i, json_type_int, &tmp_obj)) + { + json_object_put(root); + return_failure_int; + } + layer_data[i] = json_object_get_int(tmp_obj); } - if(fwrite(&layer_data, sizeof(uint16_t), map_width * map_height, output_file) != (size_t)map_width * (size_t)map_height) + if(file_write(&layer_data, sizeof(*layer_data), (size_t)map_width * (size_t)map_height, output_file)) { json_object_put(root); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; + return_failure_int; } + *asset_size += sizeof(layer_data); + // Hitboxes - if(!json_object_object_get_ex(root, "Hitboxes", &tmp_obj)) + json_object *hitboxes; + if(json_get_object_of_type(root, "Hitboxes", json_type_array, &hitboxes)) { json_object_put(root); - error_printf("Map file doesn't contain key \"Hitboxes\"."); - return EXIT_FAILURE; + return_failure_int; } - if(!json_object_is_type(tmp_obj, json_type_array)) - { - json_object_put(root); - error_printf("Map background layer 1 is not of type array."); - return EXIT_FAILURE; - } - - uint8_t hitboxes_layer[map_width * map_height]; + uint8_t hitboxes_layer_data[(size_t)map_width * (size_t)map_height]; for(size_t i = 0; i < (size_t)map_width * (size_t)map_height; i++) { - json_object *tile = json_object_array_get_idx(tmp_obj, i); - hitboxes_layer[i] = json_object_get_int(tile); + if(json_get_idx_of_type(hitboxes, i, json_type_int, &tmp_obj)) + { + json_object_put(root); + return_failure_int; + } + hitboxes_layer_data[i] = json_object_get_int(tmp_obj); } - if(fwrite(&hitboxes_layer, sizeof(uint8_t), map_width * map_height, output_file) != (size_t)map_width * (size_t)map_height) + if(file_write(&hitboxes_layer_data, sizeof(*hitboxes_layer_data), (size_t)map_width * (size_t)map_height, output_file)) { json_object_put(root); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; + return_failure_int; } + *asset_size += sizeof(hitboxes_layer_data); + + // Entities json_object *entities; - if(!json_object_object_get_ex(root, "Entities", &entities)) + if(json_get_object_of_type(root, "Entities", json_type_array, &entities)) { json_object_put(root); - error_printf("Map file doesn't contain key \"Entities\"."); - return EXIT_FAILURE; + return_failure_int; } - uint32_t entities_nb = json_object_array_length(entities); + uint16_t entities_nb = json_object_array_length(entities); - if(fwrite(&entities_nb, sizeof(entities_nb), 1, output_file) != 1) + if(file_write(&entities_nb, sizeof(entities_nb), 1, output_file)) { json_object_put(root); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; + return_failure_int; } + *asset_size += sizeof(entities_nb); + for(uint32_t i = 0; i < entities_nb; i++) { json_object *entity = json_object_array_get_idx(entities, i); - if(!json_object_object_get_ex(entity, "ID", &tmp_obj)) + if(json_get_object_of_type(entity, "ID", json_type_int, &tmp_obj)) { json_object_put(root); - error_printf("Entity doesn't have key \"ID\"."); - return EXIT_FAILURE; - } - - if(!json_object_is_type(tmp_obj, json_type_int)) - { - json_object_put(root); - error_printf("Entity ID is not of type int."); - return EXIT_FAILURE; + return_failure_int; } uint32_t entity_id = json_object_get_int(tmp_obj); - if(fwrite(&entity_id, sizeof(entity_id), 1, output_file) != 1) + if(file_write(&entity_id, sizeof(entity_id), 1, output_file)) { json_object_put(root); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; + return_failure_int; } + *asset_size += sizeof(entity_id); + json_object *components; - if(!json_object_object_get_ex(entity, "Components", &components)) + if(json_get_object_of_type(entity, "Components", json_type_array, &components)) { json_object_put(root); - error_printf("Entity doesn't have key \"Components\"."); - return EXIT_FAILURE; + return_failure_int; } - uint32_t components_nb = json_object_array_length(components); + uint16_t components_nb = json_object_array_length(components); - if(fwrite(&components_nb, sizeof(components_nb), 1, output_file) != 1) + if(file_write(&components_nb, sizeof(components_nb), 1, output_file)) { json_object_put(root); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; + return_failure_int; } + *asset_size += sizeof(components_nb); + for(uint32_t j = 0; j < components_nb; j++) { - json_object *component = json_object_array_get_idx(components, j); + json_object *component; + if(json_get_idx_of_type(components, j, json_type_object, &component)) + { + json_object_put(root); + return_failure_int; + } json_object *attributes; - if(!json_object_object_get_ex(component, "Type", &tmp_obj)) + if(json_get_object_of_type(component, "Type", json_type_string, &tmp_obj)) { json_object_put(root); - error_printf("Component doesn't have key \"Type\"."); - return EXIT_FAILURE; + return_failure_int; } - if(!json_object_is_type(tmp_obj, json_type_string)) - { - json_object_put(root); - error_printf("Component type is not of type string."); - return EXIT_FAILURE; - } + uint16_t component_type; - component_type_t component_type; #define COMPONENT(NAME, ...) \ if(!strcmp(#NAME, json_object_get_string(tmp_obj))) \ component_type = NAME; #include "components.def" - if(fwrite(&component_type, sizeof(uint32_t), 1, output_file) != 1) + if(file_write(&component_type, sizeof(component_type), 1, output_file)) { json_object_put(root); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; + return_failure_int; } - if(!json_object_object_get_ex(component, "Attributes", &attributes)) + *asset_size += sizeof(component_type); + + if(json_get_object_of_type(component, "Attributes", json_type_array, &attributes)) { json_object_put(root); - error_printf("Component doesn't have key \"Attributes\"."); - return EXIT_FAILURE; + return_failure_int; } uint32_t attributes_nb = json_object_array_length(attributes); @@ -477,53 +298,54 @@ int parse_map_for_content_and_write(const char *input_file_name, FILE *output_fi { case json_type_int: { - int value = json_object_get_int(attribute); - if(fwrite(&value, sizeof(value), 1, output_file) != 1) + uint32_t value = json_object_get_int(attribute); + if(file_write(&value, sizeof(value), 1, output_file)) { json_object_put(root); - error_printf("Failed to write to output file : %d", errno); return EXIT_FAILURE; } + *asset_size += sizeof(value); break; } case json_type_double: { float value = json_object_get_double(attribute); - if(fwrite(&value, sizeof(value), 1, output_file) != 1) + if(file_write(&value, sizeof(value), 1, output_file)) { json_object_put(root); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; + return_failure_int; } + *asset_size += sizeof(value); break; } case json_type_boolean: { bool value = json_object_get_boolean(attribute); - if(fwrite(&value, sizeof(value), 1, output_file) != 1) + if(file_write(&value, sizeof(value), 1, output_file)) { json_object_put(root); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; + return_failure_int; } + *asset_size += sizeof(value); break; } case json_type_string: { const char *str = json_object_get_string(attribute); - if(fwrite(str, sizeof(char), strlen(str) + 1, output_file) != strlen(str) + 1) + if(file_write(str, sizeof(*str), strlen(str) + 1, output_file)) { json_object_put(root); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; + return_failure_int; } + *asset_size += (strlen(str) + 1) * sizeof(*str); break; } default: + error_printf("Component attribute of type %s is not handled.", json_type_to_name(json_object_get_type(attribute))); return EXIT_FAILURE; } } diff --git a/assets/asset_builder/src/object.c b/assets/asset_builder/src/object.c new file mode 100644 index 0000000..35e3bc4 --- /dev/null +++ b/assets/asset_builder/src/object.c @@ -0,0 +1,50 @@ +#include "object.h" + +#include +#include +#include +#include +#include "utils.h" +#include "image.h" +#include "map.h" +#include "errors.h" + +int build_object(const char *input_file_path, FILE *output_file) +{ + // Reserve space to write asset_size + uint32_t asset_size = 0; + if(file_write(&asset_size, sizeof(asset_size), 1, output_file)) return_failure_int; + + const char *input_file_dot = strrchr(input_file_path, '.'); + if(!input_file_dot) + { + error_printf("Input file \"%s\" doesn't have an extension.", input_file_path); + return EXIT_FAILURE; + } + + const char *input_file_ext = input_file_dot + 1; + + if(!strcmp(input_file_ext, "png")) + { + if(build_image(input_file_path, output_file, &asset_size)) return_failure_int; + } + else if(!strcmp(input_file_ext, "map")) + { + if(build_map(input_file_path, output_file, &asset_size)) return_failure_int; + } + else + { + error_printf("Extension \"%s\" not supported.", input_file_ext); + return EXIT_FAILURE; + } + + if(fseek(output_file, 0, SEEK_SET)) + { + error_printf("Failed to seek in output file : %d", errno); + return EXIT_FAILURE; + } + + if(file_write(&asset_size, sizeof(asset_size), 1, output_file)) return_failure_int; + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/assets/asset_builder/src/utils.c b/assets/asset_builder/src/utils.c new file mode 100644 index 0000000..32f9546 --- /dev/null +++ b/assets/asset_builder/src/utils.c @@ -0,0 +1,27 @@ +#include "utils.h" + +#include +#include +#include "errors.h" + +inline int file_read(void *ptr, size_t size, size_t nb, FILE *file) +{ + if(fread(ptr, size, nb, file) != nb) + { + error_printf("Failed to read output file : %d", errno); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +inline int file_write(const void *ptr, size_t size, size_t nb, FILE *file) +{ + if(fwrite(ptr, size, nb, file) != nb) + { + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +}