/* SPDX-License-Identifier: GPL-3.0-or-later */ /* Copyright (C) 2021 KikooDX */ #include #include #include #include "level.h" static const int kble_fmt_version = 0; static int read_byte(FILE *file); static int read_byte_group(FILE *file, int number); void level_read(struct Level *level, char *path) { FILE *file = NULL; int byte = 0; int width = 0; int height = 0; int tile_size = 0; int level_size = 0; int tile = 0; int i = 0; /* open file in read mode */ file = fopen(path, "rb"); if (file == NULL) { fprintf(stderr, "ERROR: Cannot open input file %s\n", path); exit(EXIT_FAILURE); } /* check KBLE format version */ byte = read_byte(file); if (byte != kble_fmt_version) { fprintf(stderr, "ERROR: KBLE format version doesn't match ; " "expected %d, got %d\n", kble_fmt_version, byte); exit(EXIT_FAILURE); } /* get tile size (in bytes) */ tile_size = read_byte(file); /* get width */ width = read_byte_group(file, 2); /* get height */ height = read_byte_group(file, 2); /* allocate memory for data */ level_size = width * height; if (level->data == NULL) { level->data = malloc(level_size * sizeof(int)); } else { level->data = realloc(level->data, level_size * sizeof(int)); } /* check for allocation failure */ if (level->data == NULL) { fprintf(stderr, "ERROR: memory allocation failure\n"); exit(EXIT_FAILURE); } /* read file content */ for (i = 0; i < level_size; i += 1) { tile = read_byte_group(file, tile_size); level->data[i] = tile; } /* close file */ fclose(file); } void level_free(struct Level *level) { free(level->data); } /* Read a single byte safely (handles EOF). */ static int read_byte(FILE *file) { const int byte = getc(file); if (byte == EOF) { fprintf(stderr, "ERROR: unexpected EOF\n"); exit(EXIT_FAILURE); } return byte; } /* Read multiple bytes and "merge" them into one integer. */ static int read_byte_group(FILE *file, int number) { int byte = 0; int merged = 0; int i = 0; int shift = number * 8; for (i = 0; i < number; i += 1) { shift -= 8; byte = read_byte(file); merged |= byte << shift; } return merged; }