116 lines
3.6 KiB
C
116 lines
3.6 KiB
C
/**
|
|
* Copyright (c) 2026 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "assettilesetloader.h"
|
|
#include "assert/assert.h"
|
|
#include "util/memory.h"
|
|
#include "util/endian.h"
|
|
#include "asset/loader/assetloading.h"
|
|
#include "asset/loader/assetentry.h"
|
|
|
|
errorret_t assetTilesetLoaderAsync(assetloading_t *loading) {
|
|
assertNotNull(loading, "Loading cannot be NULL");
|
|
|
|
if(loading->loading.tileset.state != ASSET_TILESET_LOADING_STATE_READ_FILE) {
|
|
errorOk();
|
|
}
|
|
|
|
assertNull(loading->loading.tileset.data, "Data already defined?");
|
|
|
|
assetfile_t *file = &loading->loading.tileset.file;
|
|
assetLoaderErrorChain(loading, assetFileInit(file, loading->entry->name, NULL, NULL));
|
|
|
|
uint8_t *data = memoryAllocate(file->size);
|
|
assetLoaderErrorChain(loading, assetFileOpen(file));
|
|
assetLoaderErrorChain(loading, assetFileRead(file, data, file->size));
|
|
assetLoaderErrorChain(loading, assetFileClose(file));
|
|
assetLoaderErrorChain(loading, assetFileDispose(file));
|
|
assertTrue(file->lastRead == file->size, "Failed to read entire tileset file.");
|
|
|
|
loading->loading.tileset.data = data;
|
|
loading->loading.tileset.state = ASSET_TILESET_LOADING_STATE_PARSE;
|
|
loading->entry->state = ASSET_ENTRY_STATE_PENDING_SYNC;
|
|
errorOk();
|
|
}
|
|
|
|
errorret_t assetTilesetLoaderSync(assetloading_t *loading) {
|
|
assertNotNull(loading, "Loading cannot be NULL");
|
|
assertTrue(loading->type == ASSET_LOADER_TYPE_TILESET, "Invalid type.");
|
|
|
|
switch(loading->loading.tileset.state) {
|
|
case ASSET_TILESET_LOADING_STATE_INITIAL:
|
|
loading->loading.tileset.state = ASSET_TILESET_LOADING_STATE_READ_FILE;
|
|
loading->entry->state = ASSET_ENTRY_STATE_PENDING_ASYNC;
|
|
errorOk();
|
|
break;
|
|
|
|
case ASSET_TILESET_LOADING_STATE_PARSE:
|
|
break;
|
|
|
|
default:
|
|
errorOk();
|
|
}
|
|
|
|
uint8_t *data = loading->loading.tileset.data;
|
|
assertNotNull(data, "Tileset data should have been loaded by now.");
|
|
|
|
tileset_t *out = &loading->entry->data.tileset;
|
|
|
|
if(data[0] != 'D' || data[1] != 'T' || data[2] != 'F') {
|
|
memoryFree(data);
|
|
assetLoaderErrorThrow(loading, "Invalid tileset header");
|
|
}
|
|
|
|
if(data[3] != 0x00) {
|
|
memoryFree(data);
|
|
assetLoaderErrorThrow(loading, "Unsupported tileset version");
|
|
}
|
|
|
|
out->tileWidth = endianLittleToHost16(*(uint16_t *)(data + 4));
|
|
out->tileHeight = endianLittleToHost16(*(uint16_t *)(data + 6));
|
|
out->columns = endianLittleToHost16(*(uint16_t *)(data + 8));
|
|
out->rows = endianLittleToHost16(*(uint16_t *)(data + 10));
|
|
|
|
if(out->tileWidth == 0) {
|
|
memoryFree(data);
|
|
assetLoaderErrorThrow(loading, "Tile width cannot be 0");
|
|
}
|
|
if(out->tileHeight == 0) {
|
|
memoryFree(data);
|
|
assetLoaderErrorThrow(loading, "Tile height cannot be 0");
|
|
}
|
|
if(out->columns == 0) {
|
|
memoryFree(data);
|
|
assetLoaderErrorThrow(loading, "Column count cannot be 0");
|
|
}
|
|
if(out->rows == 0) {
|
|
memoryFree(data);
|
|
assetLoaderErrorThrow(loading, "Row count cannot be 0");
|
|
}
|
|
|
|
out->uv[0] = endianLittleToHostFloat(*(float *)(data + 16));
|
|
out->uv[1] = endianLittleToHostFloat(*(float *)(data + 20));
|
|
|
|
if(out->uv[1] < 0.0f || out->uv[1] > 1.0f) {
|
|
memoryFree(data);
|
|
assetLoaderErrorThrow(loading, "Invalid v0 value in tileset");
|
|
}
|
|
|
|
out->tileCount = out->columns * out->rows;
|
|
memoryFree(data);
|
|
loading->loading.tileset.data = NULL;
|
|
|
|
loading->entry->state = ASSET_ENTRY_STATE_LOADED;
|
|
errorOk();
|
|
}
|
|
|
|
errorret_t assetTilesetDispose(assetentry_t *entry) {
|
|
assertNotNull(entry, "Entry cannot be NULL");
|
|
assertTrue(entry->type == ASSET_LOADER_TYPE_TILESET, "Invalid type.");
|
|
errorOk();
|
|
}
|