Compare commits
No commits in common. "e73b34e87d2422ed9c2c98e1796bd7b5fee2b79d" and "d628de2800a1c68c3a1cabdaac2e1848eae7db2b" have entirely different histories.
e73b34e87d
...
d628de2800
|
|
@ -1 +1 @@
|
||||||
Subproject commit 405ed84cae9b83eba540d7ee319f5ff025a314a1
|
Subproject commit eb01fd4d2b5034228938b5d5b54785111efd4908
|
||||||
2
TODO.md
2
TODO.md
|
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
###### Features
|
###### Features
|
||||||
|
|
||||||
- [ ] Change linked list for each implementation to a macro (iykyk)
|
|
||||||
|
|
||||||
- [ ] Create camera
|
- [ ] Create camera
|
||||||
|
|
||||||
- [ ] Make functionnal hitboxes between entities and map
|
- [ ] Make functionnal hitboxes between entities and map
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,7 @@ ASSETS := \
|
||||||
props_sheets/lever_sheet.png \
|
props_sheets/lever_sheet.png \
|
||||||
props_sheets/barred_door_sheet.png \
|
props_sheets/barred_door_sheet.png \
|
||||||
props_sheets/wooden_door_sheet.png \
|
props_sheets/wooden_door_sheet.png \
|
||||||
tileset/tileset.png \
|
tileset/tileset.png
|
||||||
maps/dungeon_room_1.map
|
|
||||||
|
|
||||||
ASSETS := $(addprefix $(ASSETS_DIR)/,$(ASSETS))
|
ASSETS := $(addprefix $(ASSETS_DIR)/,$(ASSETS))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
# Asset file structure
|
# Asset file structure
|
||||||
|
|
||||||
| Description | Length |
|
| Description | Length |
|
||||||
| :---------------- | :------------------------------------------------ |
|
| :---------------- | :---------------------------------- |
|
||||||
| Assets number | unsigned int (32 bits) |
|
| Assets number | size_t (64 bits) |
|
||||||
| ... | |
|
| ... | |
|
||||||
| Asset name | const char [] (variable length, ends with '\00') |
|
| Asset name | const char * (variable length) |
|
||||||
| Asset start index | unsigned int (32 bits) |
|
| Asset start index | size_t (64 bits) |
|
||||||
| ... | |
|
| Asset end index | size_t (64 bits) |
|
||||||
| Asset data | depend on assets content and number |
|
| ... | |
|
||||||
|
| Asset data | depend on assets content and number |
|
||||||
|
|
||||||
## Image (.png)
|
## Image (.png)
|
||||||
|
|
||||||
|
|
@ -20,8 +21,8 @@ Image data is in RGB 565.
|
||||||
|
|
||||||
| Description | Length |
|
| Description | Length |
|
||||||
| :---------------- | :------------------------------------------ |
|
| :---------------- | :------------------------------------------ |
|
||||||
| Image width | unsigned int (32 bits) |
|
| Image width | size_t (64 bits) |
|
||||||
| Image height | unsigned int (32 bits) |
|
| Image height | size_t (64 bits) |
|
||||||
| Image data | depend on image size, pixel short (16 bits) |
|
| Image data | depend on image size, pixel short (16 bits) |
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -32,26 +33,21 @@ Image data is in RGB 565.
|
||||||
|
|
||||||
### Maps asset data structure
|
### Maps asset data structure
|
||||||
|
|
||||||
| Description | Length |
|
| Description | Length |
|
||||||
| :-------------------------- | :------------------------------------------------ |
|
| :-------------------------- | :-------------------------------------- |
|
||||||
| Map width | unsigned int (32 bits) |
|
| Map width | int (32 bits) |
|
||||||
| Map height | unsigned int (32 bits) |
|
| Map height | int (32 bits) |
|
||||||
| Map background layer 1 data | depend on map size, tile short (16 bits) |
|
| Map background layer 1 data | depend on map size, tile short (16 bit) |
|
||||||
| Map background layer 2 data | depend on map size, tile short (16 bits) |
|
| Map background layer 2 data | depend on map size, tile short (16 bit) |
|
||||||
| Map background layer 3 data | depend on map size, tile short (16 bits) |
|
| Map background layer 3 data | depend on map size, tile short (16 bit) |
|
||||||
| Map foreground layer data | depend on map size, tile short (16 bits) |
|
| Map foreground layer data | depend on map size, tile short (16 bit) |
|
||||||
| Map hitboxes data | depend on map size, tile unsigned char (8 bits) |
|
| Entities number | int (32 bits) |
|
||||||
| Entities number | unsigned int (32 bits) |
|
| ... | |
|
||||||
| ... | |
|
| Entity ID | size_t (64 bits) |
|
||||||
| Entity ID | unsigned int (32 bits) |
|
| Entity component number | int (32 bits) |
|
||||||
| Entity components number | unsigned int (32 bits) |
|
| ... | |
|
||||||
| ... | |
|
| Component type | int (32 bits) |
|
||||||
| Component type | int (32 bits) |
|
| ... | |
|
||||||
| ... | |
|
| Component attributes | depend on attribute type |
|
||||||
| Component attributes | depend on attribute type |
|
| ... | |
|
||||||
| int | int (32 bits) |
|
| ... | |
|
||||||
| float | float (32 bits) |
|
|
||||||
| bool | bool (8 bits) |
|
|
||||||
| str | const char [] (variable length, ends with '\00') |
|
|
||||||
| ... | |
|
|
||||||
| ... | |
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
gcc
|
gcc
|
||||||
# Headers
|
# Headers
|
||||||
-Iassets/asset_builder/src/headers
|
-Iassets/asset_builder/src/headers
|
||||||
-Isrc/components/headers
|
|
||||||
|
|
||||||
# Macros
|
# Macros
|
||||||
-DDEBUG=2
|
-DDEBUG=2
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,17 @@
|
||||||
# Source files
|
# Source files
|
||||||
ASSET_BUILDER_SOURCES := \
|
ASSET_BUILDER_SOURCES := \
|
||||||
|
main.c \
|
||||||
asset_file.c \
|
asset_file.c \
|
||||||
image.c \
|
errors.c
|
||||||
map.c \
|
|
||||||
main.c
|
|
||||||
|
|
||||||
# Compiler and flags
|
# Compiler and flags
|
||||||
ASSET_BUILDER_CC = gcc
|
ASSET_BUILDER_CC = gcc
|
||||||
ifeq ($(RELEASE), 1)
|
ifeq ($(RELEASE), 1)
|
||||||
ASSET_BUILDER_CFLAGS = --std=c17 --pedantic -O3 $(shell pkg-config --cflags libpng json-c) # RELEASE
|
ASSET_BUILDER_CFLAGS = --std=c17 --pedantic -O3 $(shell pkg-config --cflags libpng) # RELEASE
|
||||||
else
|
else
|
||||||
ASSET_BUILDER_CFLAGS = --std=c17 --pedantic -O1 -DDEBUG=1 -g $(shell pkg-config --cflags libpng json-c) \
|
ASSET_BUILDER_CFLAGS = --std=c17 --pedantic -O1 -g $(shell pkg-config --cflags libpng) \
|
||||||
-Wall -Wno-missing-braces -Wextra -Wno-missing-field-initializers \
|
-Wall -Wno-missing-braces -Wextra -Wno-missing-field-initializers \
|
||||||
-Wformat=2 -Wswitch-default -Wswitch -Wcast-align \
|
-Wformat=2 -Wswitch-default -Wswitch-enum -Wcast-align \
|
||||||
-Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 \
|
-Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 \
|
||||||
-Wstrict-prototypes -Winline -Wundef -Wnested-externs \
|
-Wstrict-prototypes -Winline -Wundef -Wnested-externs \
|
||||||
-Wcast-qual -Wshadow -Wunreachable-code -Wlogical-op \
|
-Wcast-qual -Wshadow -Wunreachable-code -Wlogical-op \
|
||||||
|
|
@ -20,10 +19,10 @@ ASSET_BUILDER_CFLAGS = --std=c17 --pedantic -O1 -DDEBUG=1 -g $(shell pkg-config
|
||||||
-Wold-style-definition # DEVELOPEMENT
|
-Wold-style-definition # DEVELOPEMENT
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ASSET_BUILDER_INCLUDE_DIRS = $(ASSET_BUILDER_DIR)/headers $(SOURCE_DIR)/components/headers
|
ASSET_BUILDER_INCLUDE_DIRS = $(ASSET_BUILDER_DIR)/headers
|
||||||
ASSET_BUILDER_INCLUDE_DIRS := $(addprefix -I, $(ASSET_BUILDER_INCLUDE_DIRS))
|
ASSET_BUILDER_INCLUDE_DIRS := $(addprefix -I, $(ASSET_BUILDER_INCLUDE_DIRS))
|
||||||
|
|
||||||
ASSET_BUILDER_LDFLAGS = $(shell pkg-config --libs libpng json-c)
|
ASSET_BUILDER_LDFLAGS = $(shell pkg-config --libs libpng)
|
||||||
|
|
||||||
# Deduce objects
|
# Deduce objects
|
||||||
ASSET_BUILDER_OBJECTS = $(ASSET_BUILDER_SOURCES:%.c=$(BUILD_DIR)/$(ASSET_BUILDER_DIR)/%.o)
|
ASSET_BUILDER_OBJECTS = $(ASSET_BUILDER_SOURCES:%.c=$(BUILD_DIR)/$(ASSET_BUILDER_DIR)/%.o)
|
||||||
|
|
|
||||||
|
|
@ -1,65 +1,48 @@
|
||||||
#include "asset_file.h"
|
#include "asset_file.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <png.h>
|
||||||
#include "image.h"
|
|
||||||
#include "map.h"
|
|
||||||
#include "errors.h"
|
#include "errors.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 parse_file_for_header(const char *input_file_name, asset_header_def_t *asset_header_def)
|
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, '.');
|
const char *file_name_dot = strrchr(input_file_name, '.');
|
||||||
|
|
||||||
if(!file_name_dot)
|
if(!file_name_dot)
|
||||||
{
|
{
|
||||||
error_printf("File does not have an extension.");
|
return NO_EXTENSION;
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *file_name_ext = file_name_dot + 1;
|
const char *file_name_ext = file_name_dot + 1;
|
||||||
|
|
||||||
if(!strcmp(file_name_ext, "png"))
|
if(!strcmp(file_name_ext, "png"))
|
||||||
{
|
{
|
||||||
if(parse_png_for_header(input_file_name, asset_header_def)) return_failure_int;
|
return parse_png_for_header(input_file_name, asset_header_def);
|
||||||
}
|
|
||||||
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;
|
return EXTENSION_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int write_header_to_file(asset_file_header_t *asset_file_header, FILE *output_file)
|
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)
|
if(fwrite(&asset_file_header->assets_number, sizeof(size_t), 1, output_file) != 1)
|
||||||
{
|
return WRITE_FAILED;
|
||||||
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++)
|
for(size_t i = 0; i < asset_file_header->assets_number; i++)
|
||||||
{
|
{
|
||||||
size_t name_length = strlen(asset_file_header->assets_header_def[i].name) + 1;
|
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)
|
if(fwrite(asset_file_header->assets_header_def[i].name, sizeof(unsigned char), name_length, output_file) != name_length)
|
||||||
{
|
return WRITE_FAILED;
|
||||||
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)
|
if(fwrite(&asset_file_header->assets_header_def[i].start, sizeof(size_t), 1, output_file) != 1)
|
||||||
{
|
return WRITE_FAILED;
|
||||||
error_printf("Failed to write to output file : %d", errno);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_file_for_content_and_write(const char *input_file_name, FILE *output_file)
|
int parse_file_for_content_and_write(const char *input_file_name, FILE *output_file)
|
||||||
|
|
@ -68,25 +51,208 @@ int parse_file_for_content_and_write(const char *input_file_name, FILE *output_f
|
||||||
|
|
||||||
if(!file_name_dot)
|
if(!file_name_dot)
|
||||||
{
|
{
|
||||||
error_printf("File does not have an extension.");
|
return NO_EXTENSION;
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *file_name_ext = file_name_dot + 1;
|
const char *file_name_ext = file_name_dot + 1;
|
||||||
|
|
||||||
if(!strcmp(file_name_ext, "png"))
|
if(!strcmp(file_name_ext, "png"))
|
||||||
{
|
{
|
||||||
if(parse_png_for_content_and_write(input_file_name, output_file)) return_failure_int;
|
return parse_png_for_content_and_write(input_file_name, output_file);
|
||||||
}
|
|
||||||
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;
|
return EXTENSION_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// File specific functions.
|
||||||
|
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)
|
||||||
|
return OPEN_FAILED;
|
||||||
|
|
||||||
|
// Check png autenticity.
|
||||||
|
unsigned char sig[8];
|
||||||
|
if(fread(sig, sizeof(unsigned char), 8, input_file) != 8)
|
||||||
|
{
|
||||||
|
fclose(input_file);
|
||||||
|
return READ_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!png_check_sig(sig, 8))
|
||||||
|
{
|
||||||
|
fclose(input_file);
|
||||||
|
return BAD_SIGNATURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PNG structs.
|
||||||
|
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
|
if(!png_ptr)
|
||||||
|
{
|
||||||
|
fclose(input_file);
|
||||||
|
return MEMORY_ALLOC_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if(!info_ptr)
|
||||||
|
{
|
||||||
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||||
|
fclose(input_file);
|
||||||
|
return MEMORY_ALLOC_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
size_t width = png_get_image_width(png_ptr, info_ptr);
|
||||||
|
size_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);
|
||||||
|
return PNG_BIT_DEPTH_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
return PNG_COLOR_TYPE_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill asset def.
|
||||||
|
asset_header_def->start = 0;
|
||||||
|
asset_header_def->end = height * width * sizeof(uint16_t) + sizeof(size_t) * 2;
|
||||||
|
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
fclose(input_file);
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_png_for_content_and_write(const char *input_file_name, FILE *output_file)
|
||||||
|
{
|
||||||
|
FILE *input_file = fopen(input_file_name, "rb");
|
||||||
|
|
||||||
|
if(!input_file)
|
||||||
|
{
|
||||||
|
return OPEN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check png autenticity.
|
||||||
|
unsigned char sig[8];
|
||||||
|
if(fread(sig, sizeof(unsigned char), 8, input_file) != 8)
|
||||||
|
{
|
||||||
|
fclose(input_file);
|
||||||
|
return READ_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!png_check_sig(sig, 8))
|
||||||
|
{
|
||||||
|
fclose(input_file);
|
||||||
|
return BAD_SIGNATURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PNG structs.
|
||||||
|
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
|
if(!png_ptr)
|
||||||
|
{
|
||||||
|
fclose(input_file);
|
||||||
|
return MEMORY_ALLOC_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if(!info_ptr)
|
||||||
|
{
|
||||||
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||||
|
fclose(input_file);
|
||||||
|
return MEMORY_ALLOC_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
size_t width = png_get_image_width(png_ptr, info_ptr);
|
||||||
|
size_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(size_t), 1, output_file) != 1)
|
||||||
|
{
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
fclose(input_file);
|
||||||
|
return WRITE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fwrite(&height, sizeof(size_t), 1, output_file) != 1)
|
||||||
|
{
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
fclose(input_file);
|
||||||
|
return WRITE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare storage.
|
||||||
|
png_byte src_pixels[height * row_length];
|
||||||
|
png_bytep src_row_ptrs[height];
|
||||||
|
for(png_uint_32 i = 0; i < height; i++)
|
||||||
|
src_row_ptrs[i] = &src_pixels[i * row_length];
|
||||||
|
|
||||||
|
// Read pixels.
|
||||||
|
png_read_image(png_ptr, src_row_ptrs);
|
||||||
|
|
||||||
|
uint16_t dst_pixels[width * height * sizeof(uint16_t)];
|
||||||
|
|
||||||
|
for(size_t i = 0; i < height; i++)
|
||||||
|
{
|
||||||
|
for(size_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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r = 0x1F;
|
||||||
|
g = 0x00;
|
||||||
|
b = 0x1F;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, width * height * sizeof(uint16_t), 1, output_file) != 1)
|
||||||
|
{
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
fclose(input_file);
|
||||||
|
return WRITE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
fclose(input_file);
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
#include "errors.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void print_error(const char *content)
|
||||||
|
{
|
||||||
|
printf("\033[31merror\033[m: %s\n", content);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_error_description(error_t error)
|
||||||
|
{
|
||||||
|
switch(error)
|
||||||
|
{
|
||||||
|
case NO_EXTENSION:
|
||||||
|
print_error("file does not have an extension."); break;
|
||||||
|
|
||||||
|
case EXTENSION_UNSUPPORTED:
|
||||||
|
print_error("extension not yet supported."); break;
|
||||||
|
|
||||||
|
case OPEN_FAILED:
|
||||||
|
print_error("failed to open file."); break;
|
||||||
|
|
||||||
|
case READ_FAILED:
|
||||||
|
print_error("failed to read the input file."); break;
|
||||||
|
|
||||||
|
case WRITE_FAILED:
|
||||||
|
print_error("failed to write to output file."); break;
|
||||||
|
|
||||||
|
case BAD_SIGNATURE:
|
||||||
|
print_error("file not valid."); break;
|
||||||
|
|
||||||
|
case MEMORY_ALLOC_FAILED:
|
||||||
|
print_error("memory allocation failed."); break;
|
||||||
|
|
||||||
|
case PNG_BIT_DEPTH_UNSUPPORTED:
|
||||||
|
print_error("png bit depth not supported."); break;
|
||||||
|
|
||||||
|
case PNG_COLOR_TYPE_UNSUPPORTED:
|
||||||
|
print_error("png color type not supported."); break;
|
||||||
|
|
||||||
|
case NO_ERROR:
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
print_error("unknown error"); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,11 +6,11 @@
|
||||||
|
|
||||||
typedef struct asset_header_def_t {
|
typedef struct asset_header_def_t {
|
||||||
char *name;
|
char *name;
|
||||||
uint32_t start, end;
|
size_t start, end;
|
||||||
} asset_header_def_t;
|
} asset_header_def_t;
|
||||||
|
|
||||||
typedef struct asset_file_header_t {
|
typedef struct asset_file_header_t {
|
||||||
uint32_t assets_number;
|
size_t assets_number;
|
||||||
asset_header_def_t *assets_header_def;
|
asset_header_def_t *assets_header_def;
|
||||||
|
|
||||||
size_t header_size;
|
size_t header_size;
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,23 @@
|
||||||
#ifndef ERRORS_H
|
#ifndef ERROR_H
|
||||||
#define ERRORS_H
|
#define ERROR_H
|
||||||
|
|
||||||
#include <stdio.h>
|
typedef enum error_t {
|
||||||
#include <errno.h>
|
NO_ERROR,
|
||||||
#include <assert.h>
|
NO_EXTENSION,
|
||||||
|
EXTENSION_UNSUPPORTED,
|
||||||
|
OPEN_FAILED,
|
||||||
|
READ_FAILED,
|
||||||
|
WRITE_FAILED,
|
||||||
|
BAD_SIGNATURE,
|
||||||
|
MEMORY_ALLOC_FAILED,
|
||||||
|
|
||||||
#ifndef DEBUG
|
// File-format specific errors
|
||||||
#define DEBUG 0
|
PNG_BIT_DEPTH_UNSUPPORTED,
|
||||||
#endif
|
PNG_COLOR_TYPE_UNSUPPORTED
|
||||||
|
} error_t;
|
||||||
|
|
||||||
#if DEBUG > 0
|
void print_error(const char *content);
|
||||||
#define debug_printf(...) \
|
|
||||||
do { \
|
|
||||||
fprintf(stderr, "\033[32mINFO\033[m: " __VA_ARGS__); \
|
|
||||||
fputc('\n', stderr); \
|
|
||||||
} while (0)
|
|
||||||
#else
|
|
||||||
#define debug_printf(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define warning_printf(...) \
|
void print_error_description(error_t error);
|
||||||
do { \
|
|
||||||
fprintf(stderr, "\033[35mWARNING\033[m: " __VA_ARGS__); \
|
|
||||||
fputc('\n', stderr); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define error_printf(...) \
|
#endif // ERROR_H
|
||||||
do { \
|
|
||||||
fprintf(stderr, "\033[31mERROR\033[m: %s:%d:%s(): ", __FILE__, __LINE__, __func__); \
|
|
||||||
fprintf(stderr, __VA_ARGS__); \
|
|
||||||
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 +0,0 @@
|
||||||
#ifndef IMAGE_H
|
|
||||||
#define IMAGE_H
|
|
||||||
|
|
||||||
#include "asset_file.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);
|
|
||||||
|
|
||||||
#endif // IMAGE_H
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
#ifndef MAP_H
|
|
||||||
#define MAP_H
|
|
||||||
|
|
||||||
#include "asset_file.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);
|
|
||||||
|
|
||||||
#endif // MAP_H
|
|
||||||
|
|
@ -1,215 +0,0 @@
|
||||||
#include "image.h"
|
|
||||||
|
|
||||||
#include <png.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "asset_file.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)
|
|
||||||
{
|
|
||||||
FILE *input_file = fopen(input_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);
|
|
||||||
size_t row_length = png_get_rowbytes(png_ptr, info_ptr);
|
|
||||||
|
|
||||||
// Write image size.
|
|
||||||
if(fwrite(&width, sizeof(width), 1, output_file) != 1)
|
|
||||||
{
|
|
||||||
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(fwrite(&height, sizeof(height), 1, output_file) != 1)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare storage.
|
|
||||||
png_byte src_pixels[height * row_length];
|
|
||||||
png_bytep src_row_ptrs[height];
|
|
||||||
for(png_uint_32 i = 0; i < height; i++)
|
|
||||||
src_row_ptrs[i] = &src_pixels[i * row_length];
|
|
||||||
|
|
||||||
// Read pixels.
|
|
||||||
png_read_image(png_ptr, src_row_ptrs);
|
|
||||||
|
|
||||||
uint16_t dst_pixels[width * height * sizeof(uint16_t)];
|
|
||||||
|
|
||||||
for(uint32_t i = 0; i < height; i++)
|
|
||||||
{
|
|
||||||
for(uint32_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;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
r = 0x1F;
|
|
||||||
g = 0x00;
|
|
||||||
b = 0x1F;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
||||||
fclose(input_file);
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
@ -20,16 +20,17 @@ int main(int argc, char *argv[])
|
||||||
// Header size and content.
|
// Header size and content.
|
||||||
asset_file_header_t asset_file_header;
|
asset_file_header_t asset_file_header;
|
||||||
asset_file_header.assets_number = argc - 2;
|
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.header_size = sizeof(size_t) + sizeof(size_t) * asset_file_header.assets_number;
|
||||||
asset_file_header.assets_header_def = calloc(asset_file_header.assets_number, sizeof(asset_header_def_t));
|
asset_file_header.assets_header_def = malloc(asset_file_header.assets_number * sizeof(asset_header_def_t));
|
||||||
if(!asset_file_header.assets_header_def)
|
if(!asset_file_header.assets_header_def)
|
||||||
{
|
{
|
||||||
error_printf("Failed to allocate memory.");
|
print_error("memory allocation failed.");
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set assets name.
|
// Set assets name.
|
||||||
for(uint32_t i = 0; i < asset_file_header.assets_number; i++)
|
for(size_t i = 0; i < asset_file_header.assets_number; i++)
|
||||||
{
|
{
|
||||||
const char *file_name = argv[i + 2];
|
const char *file_name = argv[i + 2];
|
||||||
|
|
||||||
|
|
@ -53,13 +54,19 @@ int main(int argc, char *argv[])
|
||||||
output_asset_file = fopen(argv[1], "wb");
|
output_asset_file = fopen(argv[1], "wb");
|
||||||
if(!output_asset_file)
|
if(!output_asset_file)
|
||||||
{
|
{
|
||||||
error_printf("could not create output file.");
|
print_error("could not create output file.");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(uint32_t i = 0; i < asset_file_header.assets_number; i++)
|
for(size_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;
|
int ret = parse_file_for_header(argv[i + 2], &asset_file_header.assets_header_def[i]);
|
||||||
|
|
||||||
|
if(ret)
|
||||||
|
{
|
||||||
|
print_error_description(ret);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate absolute position of assets in the file.
|
// 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;
|
if(i) asset_file_header.assets_header_def[i].start = asset_file_header.assets_header_def[i - 1].end;
|
||||||
|
|
@ -69,13 +76,19 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
if(write_header_to_file(&asset_file_header, output_asset_file))
|
if(write_header_to_file(&asset_file_header, output_asset_file))
|
||||||
{
|
{
|
||||||
error_printf("Failed to write to output file : %d", errno);
|
print_error("can't write to output file.");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(uint32_t i = 0; i < asset_file_header.assets_number; i++)
|
for(size_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;
|
int ret = parse_file_for_content_and_write(argv[i + 2], output_asset_file);
|
||||||
|
|
||||||
|
if(ret)
|
||||||
|
{
|
||||||
|
print_error_description(ret);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_status = EXIT_SUCCESS;
|
exit_status = EXIT_SUCCESS;
|
||||||
|
|
@ -83,13 +96,8 @@ int main(int argc, char *argv[])
|
||||||
end:
|
end:
|
||||||
if(asset_file_header.assets_header_def)
|
if(asset_file_header.assets_header_def)
|
||||||
{
|
{
|
||||||
for(uint32_t i = 0; i < asset_file_header.assets_number; i++)
|
for(size_t i = 0; i < asset_file_header.assets_number; i++)
|
||||||
{
|
free(asset_file_header.assets_header_def[i].name);
|
||||||
if(asset_file_header.assets_header_def[i].name)
|
|
||||||
{
|
|
||||||
free(asset_file_header.assets_header_def[i].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(asset_file_header.assets_header_def);
|
free(asset_file_header.assets_header_def);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,536 +0,0 @@
|
||||||
#include "map.h"
|
|
||||||
|
|
||||||
#include <json-c/json.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "asset_file.h"
|
|
||||||
#include "errors.h"
|
|
||||||
|
|
||||||
int parse_map_for_header(const char *input_file_name, asset_header_def_t *asset_header_def)
|
|
||||||
{
|
|
||||||
json_object *root = json_object_from_file(input_file_name);
|
|
||||||
if (!root)
|
|
||||||
{
|
|
||||||
error_printf("Failed to load input file.");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(json_object_object_length(root) != 8)
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Map file doesn't contain 8 elements at its root.");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
json_object *tmp_obj;
|
|
||||||
|
|
||||||
if(!json_object_object_get_ex(root, "MapWidth", &tmp_obj))
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Map file doesn't contain key \"MapWidth\".");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!json_object_is_type(tmp_obj, json_type_int))
|
|
||||||
{
|
|
||||||
error_printf("Map key \"MapWidth\" is not of type int.");
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef enum component_type_t {
|
|
||||||
#define COMPONENT(NAME, ...) NAME,
|
|
||||||
#include "components.def"
|
|
||||||
} component_type_t;
|
|
||||||
|
|
||||||
int parse_map_for_content_and_write(const char *input_file_name, FILE *output_file)
|
|
||||||
{
|
|
||||||
json_object *root = json_object_from_file(input_file_name);
|
|
||||||
if (!root)
|
|
||||||
{
|
|
||||||
error_printf("Failed to load input file.");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
json_object *tmp_obj;
|
|
||||||
|
|
||||||
if(!json_object_object_get_ex(root, "MapWidth", &tmp_obj))
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Map file doesn't contain key \"MapWidth\".");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int map_width = json_object_get_int(tmp_obj);
|
|
||||||
|
|
||||||
if(fwrite(&map_width, sizeof(map_width), 1, output_file) != 1)
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Failed to write to output file : %d", errno);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int map_height = json_object_get_int(tmp_obj);
|
|
||||||
|
|
||||||
if(fwrite(&map_height, sizeof(map_height), 1, output_file) != 1)
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Failed to write to output file : %d", errno);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Background Layer 1
|
|
||||||
if(!json_object_object_get_ex(root, "BackgroundLayer1", &tmp_obj))
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Map file doesn't contain key \"BackgroundLayer1\".");
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t layer_data[map_width * 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);
|
|
||||||
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 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Foreground
|
|
||||||
if(!json_object_object_get_ex(root, "Foreground", &tmp_obj))
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hitboxes
|
|
||||||
if(!json_object_object_get_ex(root, "Hitboxes", &tmp_obj))
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Map file doesn't contain key \"Hitboxes\".");
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t hitboxes_layer[map_width * 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(fwrite(&hitboxes_layer, sizeof(uint8_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t entities_nb = json_object_array_length(entities);
|
|
||||||
|
|
||||||
if(fwrite(&entities_nb, sizeof(entities_nb), 1, output_file) != 1)
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Failed to write to output file : %d", errno);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t entity_id = json_object_get_int(tmp_obj);
|
|
||||||
|
|
||||||
if(fwrite(&entity_id, sizeof(entity_id), 1, output_file) != 1)
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Failed to write to output file : %d", errno);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
json_object *components;
|
|
||||||
|
|
||||||
if(!json_object_object_get_ex(entity, "Components", &components))
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Entity doesn't have key \"Components\".");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t components_nb = json_object_array_length(components);
|
|
||||||
|
|
||||||
if(fwrite(&components_nb, sizeof(components_nb), 1, output_file) != 1)
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Failed to write to output file : %d", errno);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(uint32_t j = 0; j < components_nb; j++)
|
|
||||||
{
|
|
||||||
json_object *component = json_object_array_get_idx(components, j);
|
|
||||||
|
|
||||||
json_object *attributes;
|
|
||||||
|
|
||||||
if(!json_object_object_get_ex(component, "Type", &tmp_obj))
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Component doesn't have key \"Type\".");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Failed to write to output file : %d", errno);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!json_object_object_get_ex(component, "Attributes", &attributes))
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Component doesn't have key \"Attributes\".");
|
|
||||||
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:
|
|
||||||
{
|
|
||||||
int value = json_object_get_int(attribute);
|
|
||||||
if(fwrite(&value, sizeof(value), 1, output_file) != 1)
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Failed to write to output file : %d", errno);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case json_type_double:
|
|
||||||
{
|
|
||||||
float value = json_object_get_double(attribute);
|
|
||||||
if(fwrite(&value, sizeof(value), 1, output_file) != 1)
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Failed to write to output file : %d", errno);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case json_type_boolean:
|
|
||||||
{
|
|
||||||
bool value = json_object_get_boolean(attribute);
|
|
||||||
if(fwrite(&value, sizeof(value), 1, output_file) != 1)
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Failed to write to output file : %d", errno);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
json_object_put(root);
|
|
||||||
error_printf("Failed to write to output file : %d", errno);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
json_object_put(root);
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
@ -134,7 +134,7 @@
|
||||||
{
|
{
|
||||||
"Type": "DOOR_COMPONENT",
|
"Type": "DOOR_COMPONENT",
|
||||||
"Attributes": [
|
"Attributes": [
|
||||||
0,
|
"0",
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@
|
||||||
</item>
|
</item>
|
||||||
<item type="list">
|
<item type="list">
|
||||||
<item value="DOOR_COMPONENT"/>
|
<item value="DOOR_COMPONENT"/>
|
||||||
<item type="int" value="0"/>
|
<item value="0"/>
|
||||||
<item type="bool" value="false"/>
|
<item type="bool" value="false"/>
|
||||||
</item>
|
</item>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ stdenv.mkDerivation {
|
||||||
];
|
];
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
libpng
|
libpng
|
||||||
json_c
|
|
||||||
sdl3
|
sdl3
|
||||||
ncurses
|
ncurses
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ SRC_LDFLAGS = -O3
|
||||||
else
|
else
|
||||||
SRC_CFLAGS = --std=c17 --pedantic -O1 -g -DDEBUG=2 \
|
SRC_CFLAGS = --std=c17 --pedantic -O1 -g -DDEBUG=2 \
|
||||||
-Wall -Wno-missing-braces -Wextra -Wno-missing-field-initializers \
|
-Wall -Wno-missing-braces -Wextra -Wno-missing-field-initializers \
|
||||||
-Wformat=2 -Wswitch-default -Wswitch -Wcast-align \
|
-Wformat=2 -Wswitch-default -Wswitch-enum -Wcast-align \
|
||||||
-Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 \
|
-Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 \
|
||||||
-Wstrict-prototypes -Winline -Wundef -Wnested-externs \
|
-Wstrict-prototypes -Winline -Wundef -Wnested-externs \
|
||||||
-Wcast-qual -Wshadow -Wunreachable-code -Wlogical-op \
|
-Wcast-qual -Wshadow -Wunreachable-code -Wlogical-op \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue