Digimon World 3 decomp
The European version, SLES_039.36
Loading...
Searching...
No Matches
file_cache.c
Go to the documentation of this file.
1#include "engine/game.h"
2#include <libgs.h>
3#include <libetc.h>
4#include <libsnd.h>
5
6/* The file cache */
23
24/* The cache slot of a file, or NULL */
26 FileSlot *slot;
27 s32 i;
28
29 for (slot = FILE_CACHE.slots, i = 0; i < FILE_CACHE_SLOTS; i++, slot++) {
30 if (slot->file == file) {
31 return slot;
32 }
33 }
34 return NULL;
35}
36
37/* A free cache slot, or NULL */
39 FileSlot *slot;
40 s32 i;
41
42 for (slot = FILE_CACHE.slots, i = 0; i < FILE_CACHE_SLOTS; i++, slot++) {
43 if (slot->file == 0) {
44 return slot;
45 }
46 }
47 return NULL;
48}
49
50/* 0 once the file is in the cache; requests it if needed */
52 FileSlot *slot = findFileSlot(file);
53
54 if (slot != NULL) {
55 slot->lastUsed = GFX.funcs.getTime();
56 if (slot->state == FILE_LOADED) {
57 return 0;
58 }
59 } else {
60 requestFile(file);
61 }
62 return 1;
63}
64
65/* The loaded file used least recently (the biggest one on a tie) */
67 FileSlot *best = NULL;
68 s32 bestSize = 0;
69 s32 i = 0;
70 s32 time = GFX.funcs.getTime();
71 FileSlot *slot;
72
73 for (slot = FILE_CACHE.slots; i < FILE_CACHE_SLOTS; i++, slot++) {
74 if (slot->file != 0 && slot->state == FILE_LOADED && time >= slot->lastUsed) {
75 if (time != slot->lastUsed || FILE_TABLE.getSectorCount(slot->file) >= bestSize) {
76 bestSize = FILE_TABLE.getSectorCount(slot->file);
77 time = slot->lastUsed;
78 best = slot;
79 }
80 }
81 }
82 return best;
83}
84
85/* Frees the loaded file used least recently, to make room in the heap */
86void evictOldestFile(void) {
87 FileSlot *slot = findOldestFile();
88
89 HEAP.free(slot->data);
90 slot->file = 0;
91 slot->data = NULL;
92 slot->lastUsed = 0;
93 slot->marked = 0;
94 slot->state = FILE_FREE;
95}
96
97/* Queues a file for the cache (just marks it used when it is there) */
98void requestFile(s32 file) {
99 FileSlot *slot = findFileSlot(file);
100
101 if (slot != NULL) {
102 slot->lastUsed = GFX.funcs.getTime();
103 return;
104 }
105 slot = findFreeFileSlot();
106 slot->file = file;
108 slot->state = FILE_QUEUED;
109 slot->lastUsed = 0;
110 slot->marked = 0;
112}
113
114/* Starts reading the next queued file and marks the one read as loaded */
115void updateFileCache(void) {
116 FileSlot *slot;
117 s32 i;
118 s32 busy;
119 s32 reading;
120
121 if (FILE_CACHE.pending != 0 && CD_READER.isBusy() != 1) {
122 slot = FILE_CACHE.slots;
123 reading = 0;
124 busy = 0;
125 for (i = 0; i < FILE_CACHE_SLOTS; i++, slot++) {
126 if (slot->file != 0) {
127 switch (slot->state) {
128 case FILE_READING:
129 slot->state = FILE_LOADED;
130 busy = 1;
131 slot->lastUsed = GFX.funcs.getTime();
132 break;
133 case FILE_QUEUED:
134 busy = 1;
135 if (!reading) {
136 CD_READER.read(slot->file, 0, 0, slot->data, NULL);
137 slot->state = FILE_READING;
138 reading = busy;
139 slot->lastUsed = GFX.funcs.getTime();
140 }
141 break;
142 }
143 }
144 }
145 if (!busy) {
147 }
148 }
149}
150
151/* Reads a file into the cache before returning */
152void waitForFile(s32 file) {
153 requestFile(file);
154 do {
156 } while (isFileLoading(file) != 0);
157}
158
159/* Returns the file's data, reading it now if it is not in the cache */
160void *loadFile(u32 file) {
161 FileSlot *slot = findFileSlot(file);
162
163 if (slot != NULL && slot->state == FILE_LOADED) {
164 slot->lastUsed = GFX.funcs.getTime();
165 return slot->data;
166 }
167 while (CD_READER.isBusy() != 0) {
168 }
169 waitForFile(file);
170 return findFileSlot(file)->data;
171}
172
173/* Drops a loaded file from the cache */
174void freeFile(s32 file) {
175 FileSlot *slot = findFileSlot(file);
176
177 if (slot != NULL && slot->state == FILE_LOADED) {
178 HEAP.free(slot->data);
179 slot->file = 0;
180 slot->data = NULL;
181 slot->lastUsed = 0;
182 slot->marked = 0;
183 slot->state = FILE_FREE;
184 }
185}
186
187/* Drops every file from the cache */
188void freeAllFiles(void) {
189 FileSlot *slot;
190 s32 i;
191
192 for (slot = FILE_CACHE.slots, i = 0; i < FILE_CACHE_SLOTS; i++, slot++) {
193 if (slot->file != 0) {
194 HEAP.free(slot->data);
195 slot->file = 0;
196 slot->data = NULL;
197 slot->lastUsed = 0;
198 slot->marked = 0;
199 slot->state = FILE_FREE;
200 }
201 }
202}
203
204/* Frees the files that reach past addr (to load something there) */
205void freeFilesFrom(u32 addr) {
206 FileSlot *slot = FILE_CACHE.slots;
207 s32 i;
208 u32 end;
209
210 for (i = 0; i < FILE_CACHE_SLOTS; i++, slot++) {
211 if (slot->file != 0) {
212 end = (u32)slot->data + 0x20;
214 if (end >= addr) {
215 HEAP.free(slot->data);
216 slot->file = 0;
217 slot->data = NULL;
218 slot->lastUsed = 0;
219 slot->marked = 0;
220 slot->state = FILE_FREE;
221 }
222 }
223 }
224}
225
226/*
227 * Files are often archives: a table of offsets from the start of the file.
228 * getFileEntry((file << 16) | index) loads the file and returns that entry.
229 */
230void *getFileEntry(u32 fileAndIndex) {
231 s32 index = fileAndIndex & 0xFFFF;
232 s32 *table = loadFile(fileAndIndex >> 16);
233
234 /* summed as integers: as pointer arithmetic GCC swaps the operands */
235 return (void *)(table[index] + (s32)table);
236}
237
238/* Entry `index` (the low 16 bits) of an archive already in memory */
239void *getArchiveEntry(s32 index, void *archive) {
240 s32 *table = archive;
241
242 return (void *)(table[index & 0xFFFF] + (s32)table); /* as in getFileEntry */
243}
244
245/* markCachedFiles + touchMarkedFiles: refresh the files cached before a load */
246void markCachedFiles(void) {
247 FileSlot *slot;
248 s32 i;
249
250 for (i = 0, slot = FILE_CACHE.slots; i < FILE_CACHE_SLOTS; i++, slot++) {
251 if (slot->file == 0) {
252 slot->marked = 0;
253 } else {
254 slot->marked = 1;
255 }
256 }
257}
258
259/*
260 * Marks the files markCachedFiles saw as just used (the European and Japanese versions, 10 frames
261 * before), so they stay cached
262 */
264 FileSlot *slot = FILE_CACHE.slots;
265#if VERSION_US
266 s32 now = GFX.funcs.getTime();
267#elif VERSION_EU || VERSION_JP
268 s32 now = GFX.funcs.getTime() - 10;
269#endif
270 s32 i;
271
272 for (i = 0; i < FILE_CACHE_SLOTS; i++, slot++) {
273 if (slot->file != 0 && slot->marked != 0) {
274 slot->lastUsed = now;
275 slot->marked = 0;
276 }
277 }
278}
CdReader CD_READER
The CD reader.
Definition cd_reader.c:10
#define NULL
Definition common.h:17
signed int s32
Definition common.h:11
unsigned int u32
Definition common.h:12
GfxState GFX
GFX: the graphics state and its methods.
Definition display.c:209
#define CD_SECTOR_SIZE
The bytes of data in a sector (Mode 2 Form 1), as the reader reads them.
Definition file.h:48
@ FILE_READING
Definition file.h:24
@ FILE_FREE
Definition file.h:24
@ FILE_LOADED
Definition file.h:24
@ FILE_QUEUED
Definition file.h:24
#define FILE_CACHE_SLOTS
The files the cache holds at most.
Definition file.h:27
void * getFileEntry(u32 fileAndIndex)
Files are often archives: a table of offsets from the start of the file.
Definition file_cache.c:230
FileSlot * findOldestFile(void)
The loaded file used least recently (the biggest one on a tie)
Definition file_cache.c:66
void freeFilesFrom(u32 addr)
Frees the files that reach past addr (to load something there)
Definition file_cache.c:205
void freeFile(s32 file)
Drops a loaded file from the cache.
Definition file_cache.c:174
void updateFileCache(void)
Starts reading the next queued file and marks the one read as loaded.
Definition file_cache.c:115
FileSlot * findFreeFileSlot(void)
A free cache slot, or NULL.
Definition file_cache.c:38
void requestFile(s32 file)
Queues a file for the cache (just marks it used when it is there)
Definition file_cache.c:98
s32 isFileLoading(s32 file)
0 once the file is in the cache; requests it if needed
Definition file_cache.c:51
void * getArchiveEntry(s32 index, void *archive)
Entry index (the low 16 bits) of an archive already in memory.
Definition file_cache.c:239
void markCachedFiles(void)
markCachedFiles + touchMarkedFiles: refresh the files cached before a load
Definition file_cache.c:246
void freeAllFiles(void)
Drops every file from the cache.
Definition file_cache.c:188
void waitForFile(s32 file)
Reads a file into the cache before returning.
Definition file_cache.c:152
void evictOldestFile(void)
Frees the loaded file used least recently, to make room in the heap.
Definition file_cache.c:86
void * loadFile(u32 file)
Returns the file's data, reading it now if it is not in the cache.
Definition file_cache.c:160
void touchMarkedFiles(void)
Marks the files markCachedFiles saw as just used (the European and Japanese versions,...
Definition file_cache.c:263
FileSlot * findFileSlot(s32 file)
The cache slot of a file, or NULL.
Definition file_cache.c:25
FileCache FILE_CACHE
The file cache.
Definition file_cache.c:7
FileTableFuncs FILE_TABLE
The disc's file table.
Heap HEAP
The functions that return what a call left in v0 (allocMemHigh, findTask) and the ones that take othe...
Definition heap.c:184
#define MEM_FILE_CACHE
Definition heap.h:18
void(* read)(s32 file, s32 offset, s32 size, void *buf, s32 *done)
Definition file.h:64
s32(* isBusy)(void)
Definition file.h:63
The file cache (FILE_CACHE): up to 64 files loaded in the heap (tag 3), read in the background one at...
Definition file.h:85
FileSlot slots[64]
Definition file.h:87
s32 pending
Definition file.h:86
s16 marked
Definition file.h:31
s16 state
FILE_*.
Definition file.h:30
s32 file
Definition file.h:32
s32 lastUsed
GFX time.
Definition file.h:33
void * data
Definition file.h:34
s32(* getSectorCount)(s32 file)
Definition file.h:17
s32(* getTime)(void)
Definition gfx.h:31
GfxFuncs funcs
Definition gfx.h:77
void *(* alloc)(s32 size, s32 tag)
Definition heap.h:29
void(* free)(void *ptr)
Definition heap.h:27