126 lines
3.2 KiB
C
126 lines
3.2 KiB
C
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
|
/* Copyright (C) 2021 KikooDX */
|
|
|
|
#include <gint/display.h>
|
|
#include <gint/keyboard.h>
|
|
#include <gint/bfile.h>
|
|
#include <gint/gint.h>
|
|
#include <stdint.h>
|
|
|
|
#define LEVEL_WIDTH 16
|
|
#define LEVEL_HEIGHT 16
|
|
#define LEVEL_SIZE (LEVEL_WIDTH * LEVEL_HEIGHT)
|
|
#define assert(condition, error_msg) if (!(condition)) \
|
|
{ fatal_error = -1; fatal_error_msg = error_msg; return; }
|
|
|
|
typedef unsigned int tile_t;
|
|
|
|
static uint16_t *filepath = u"\\\\fls0\\sample.kble";
|
|
static const int kble_format_version = 0;
|
|
|
|
tile_t level[LEVEL_SIZE];
|
|
int level_id = 0;
|
|
int fatal_error = 0;
|
|
char *fatal_error_msg = "no error, happy kikoo :D";
|
|
int debug_value = 0;
|
|
|
|
static void load_level(void);
|
|
static int read_byte(int file);
|
|
static tile_t read_merge_bytes(int file, int size);
|
|
|
|
int main(void) {
|
|
dclear(C_WHITE);
|
|
dtext(1, 1, C_BLACK, "loading level (well trying to)...");
|
|
dupdate();
|
|
|
|
gint_switch(load_level);
|
|
|
|
dclear(C_BLACK);
|
|
dtext(1, 1, C_WHITE, fatal_error_msg);
|
|
dprint(1, 20, C_WHITE, "%d", debug_value);
|
|
dupdate();
|
|
getkey();
|
|
return 1;
|
|
}
|
|
|
|
static void load_level(void) {
|
|
int file;
|
|
int tile_size;
|
|
int width;
|
|
int height;
|
|
int file_size;
|
|
int i;
|
|
char byte;
|
|
tile_t tile;
|
|
|
|
/* open file read only */
|
|
file = BFile_Open(filepath, BFile_ReadOnly);
|
|
assert(file >= 0, "can't open file\n"
|
|
"don't forget to put it on the calculator dummy");
|
|
|
|
/* assert KBLE format version */
|
|
byte = read_byte(file);
|
|
assert(byte == kble_format_version,
|
|
"kble format version doesn't match");
|
|
|
|
/* get tile size (in bytes) */
|
|
tile_size = read_byte(file);
|
|
assert(tile_size >= 0, "can't read tile size");
|
|
assert((unsigned int)tile_size <= sizeof(tile_t),
|
|
"tiles are too heavy");
|
|
|
|
/* assert than width and height are correct */
|
|
width = read_merge_bytes(file, 2);
|
|
height = read_merge_bytes(file, 2);
|
|
assert(width >= 0, "can't read level width");
|
|
assert(width == LEVEL_WIDTH, "invalid level width");
|
|
assert(height >= 0, "can't read level height");
|
|
assert(height == LEVEL_HEIGHT, "invalid level height");
|
|
|
|
/* using those informations, see if the file size make sense */
|
|
file_size = BFile_Size(file);
|
|
assert(file_size >= 0, "can't read file size");
|
|
/* KBLE header len is 6 bytes */
|
|
assert(file_size == 6 + LEVEL_SIZE * tile_size,
|
|
"file size doesn't make sense");
|
|
|
|
/* read file content */
|
|
for (i = 0; i < LEVEL_SIZE; i += 1) {
|
|
tile = read_merge_bytes(file, tile_size);
|
|
assert(tile != (tile_t)-1, "can't read tile");
|
|
level[i] = tile;
|
|
}
|
|
|
|
/* close file */
|
|
file = BFile_Close(file);
|
|
assert(file >= 0, "closure failed miserably");
|
|
}
|
|
|
|
/* Read a single byte. Negative value is BFile error code. */
|
|
static int read_byte(int file) {
|
|
char byte;
|
|
const int error = BFile_Read(file, &byte, sizeof(char), -1);
|
|
if (error < 0)
|
|
return error;
|
|
else
|
|
return byte;
|
|
}
|
|
|
|
/* Read multiple bytes and merge them as one integer.
|
|
* Return -1 on failure. */
|
|
static tile_t read_merge_bytes(int file, int size) {
|
|
tile_t merged = 0;
|
|
int byte = 0;
|
|
char *byte_ptr = (char*)&merged;
|
|
int i = 0;
|
|
byte_ptr += sizeof(tile_t) - size;
|
|
for (i = 0; i < size; i += 1) {
|
|
byte = read_byte(file);
|
|
if (byte < 0)
|
|
return -1;
|
|
*byte_ptr = byte;
|
|
byte_ptr += 1;
|
|
}
|
|
return merged;
|
|
}
|