1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
/* SPDX-License-Identifier: MIT */
/*
* konassets.h
*
* Copyright (c) 2026 KonAki
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef KONASSETS_H
#define KONASSETS_H
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include "konpack.h"
#include "konsofren.h"
/*** definition ***/
typedef struct kon_assets kon_assets_t;
/* what a loaded file turns into, picked from the file extension. anything unknown is a blob */
typedef enum kon_assetType {
KON_ASSET_BLOB = 0,
KON_ASSET_IMAGE,
KON_ASSET_SOUND,
KON_ASSET_CUSTOM = 16
} kon_assetType_t;
typedef struct kon_blob {
uint8_t *data; /* has one extra 0 byte after the end, so text files can be used as strings */
size_t size;
} kon_blob_t;
/* 16 bit interleaved samples, played back at sampleRate */
typedef struct kon_sound {
int16_t *frames;
uint64_t frameCount;
uint32_t channels;
uint32_t sampleRate;
} kon_sound_t;
/* load gets the raw file and returns your object, or NULL. set *bytes to what it uses for the debug view.
name and extensions (".lvl .map", lowercase, space separated) have to stay valid for as long as assets does */
typedef struct kon_assetLoader {
const char *name;
const char *extensions;
void *(*load)(const uint8_t *data, size_t size, size_t *bytes);
void (*unload)(void *object);
/* both can be NULL. bind is called right after load and is the place to get other assets the object needs, like the textures of a model.
unbind is called by kon_assetsCollect before the object is freed, and gives those assets back. assets that depend on each other in a circle never get freed */
void (*bind)(void *object, kon_assets_t *assets);
void (*unbind)(void *object, kon_assets_t *assets);
} kon_assetLoader_t;
typedef struct kon_assetInfo {
const char *name;
const char *typeName;
int type;
int refs;
size_t bytes;
int loose; /* 1 if it came from the loose folder instead of the pack, developer builds only */
} kon_assetInfo_t;
/* pack and looseDir can each be NULL. the pack stays yours, close it after kon_assetsDestroy.
with KON_DEVELOPER defined files in looseDir win over the pack so you can edit without repacking,
without it looseDir is ignored and not even compiled in */
kon_assets_t *kon_assetsCreate(kon_pack_t *pack, const char *looseDir);
void kon_assetsDestroy(kon_assets_t *assets);
/* returns the type id to use with kon_assetGetAs, or -1 */
int kon_assetsRegister(kon_assets_t *assets, const kon_assetLoader_t *loader);
/* loads the file the first time and counts a use every time. the object belongs to the manager, do not free it.
NULL if it is not found or fails to load, see kon_assetsError */
void *kon_assetGet(kon_assets_t *assets, const char *name);
/* same, but NULL if the file is not of that type. counts a use the same way, and a file of the wrong type isn't loaded */
void *kon_assetGetAs(kon_assets_t *assets, const char *name, int type);
#define kon_assetBlob(assets, name) ((kon_blob_t *)kon_assetGetAs((assets), (name), KON_ASSET_BLOB))
#define kon_assetImage(assets, name) ((kon_image *)kon_assetGetAs((assets), (name), KON_ASSET_IMAGE))
#define kon_assetSound(assets, name) ((kon_sound_t *)kon_assetGetAs((assets), (name), KON_ASSET_SOUND))
/* the loaded object, or NULL if it isn't loaded. does not load anything and does not count a use, so the pointer is only good
until the asset is collected. meant for getting at something another part of the program loaded */
void *kon_assetFind(const kon_assets_t *assets, const char *name);
/* gives back one use. nothing is freed until kon_assetsCollect */
void kon_assetRelease(kon_assets_t *assets, const char *name);
/* gives back one use and frees the asset right away if nothing uses it any more, other unused assets stay.
what it was using, like the textures of a model, is only given back, they are freed by the next kon_assetsCollect.
returns 1 if it was freed */
int kon_assetUnload(kon_assets_t *assets, const char *name);
/* frees everything nobody is using, and then what only that was using, returns how many it freed */
int kon_assetsCollect(kon_assets_t *assets);
/*** groups ***/
/* a group is a list of assets that live and die together, like everything one level needs.
loading the next level's group before freeing the old one keeps what both use */
typedef struct kon_assetGroup kon_assetGroup_t;
kon_assetGroup_t *kon_assetGroupCreate(kon_assets_t *assets);
/* adds a name to the waiting list, nothing is loaded yet. returns 0 if there was no memory */
int kon_assetGroupQueue(kon_assetGroup_t *group, const char *name);
/* queues count names from an array, or all of them up to a NULL at the end if count is -1. returns how many it queued, or -1 on no memory.
static const char *const level1[] = { "wall.png", "floor.png", "door.wav", NULL };
kon_assetGroupQueueArray(group, level1, -1);
once they are loaded kon_assetImage and friends find them again, or use kon_assetFind to look at one without counting a use */
int kon_assetGroupQueueArray(kon_assetGroup_t *group, const char *const *names, int count);
/* queues every name in a text asset, one per line. empty lines and lines starting with # are skipped.
returns how many it queued, or -1 if the list can't be read */
int kon_assetGroupQueueList(kon_assetGroup_t *group, const char *listName);
/* loads one waiting asset and returns how many are still waiting, so a loading bar can call it once per frame */
int kon_assetGroupStep(kon_assetGroup_t *group);
/* loads everything that is waiting and returns how many could not be loaded */
int kon_assetGroupLoadAll(kon_assetGroup_t *group);
/* loaded counts the assets that are in, total also counts the ones waiting and the ones that failed */
void kon_assetGroupProgress(const kon_assetGroup_t *group, int *loaded, int *total);
/* takes one name out of the group and frees it if nothing else uses it, the rest stay loaded. returns 1 if it was freed,
0 if it is still used somewhere else or was not in the group */
int kon_assetGroupUnload(kon_assetGroup_t *group, const char *name);
/* gives back every use the group holds and frees what nothing else uses. the group is gone after this */
void kon_assetGroupFree(kon_assetGroup_t *group);
/* for the debug view */
int kon_assetsCount(const kon_assets_t *assets);
int kon_assetsInfo(const kon_assets_t *assets, int index, kon_assetInfo_t *info);
size_t kon_assetsBytes(const kon_assets_t *assets);
void kon_assetsDump(const kon_assets_t *assets, FILE *out);
const char *kon_assetsError(const kon_assets_t *assets);
#endif
|