Changed way asset builder works.
This commit is contained in:
parent
53e5e82976
commit
419a247584
|
|
@ -1 +1 @@
|
|||
Subproject commit 8d021e517a6ccbdce9021deffe1f7179f27057ca
|
||||
Subproject commit 2a0803d4c4e15048fced7d3c402b76fc782e0d85
|
||||
|
|
@ -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))"
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
#include "asset_file.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#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;
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
#ifndef ASSET_FILE_H
|
||||
#define ASSET_FILE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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
|
||||
|
|
@ -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
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
#ifndef IMAGE_H
|
||||
#define IMAGE_H
|
||||
|
||||
#include "asset_file.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
#ifndef MAP_H
|
||||
#define MAP_H
|
||||
|
||||
#include "asset_file.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef OBJECT_H
|
||||
#define OBJECT_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int build_object(const char *input_file_path, FILE *output_file);
|
||||
|
||||
#endif // OBJECT_H
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
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
|
||||
|
|
@ -2,96 +2,10 @@
|
|||
|
||||
#include <png.h>
|
||||
#include <stdlib.h>
|
||||
#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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,101 +1,212 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "asset_file.h"
|
||||
#include <stdint.h>
|
||||
#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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,171 +4,42 @@
|
|||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
#include "object.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#include "utils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#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;
|
||||
}
|
||||
Loading…
Reference in New Issue