1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 //		Res.H		Resource Manager header file
20 //		Rex E. Bradford (REX)
21 /*
22  * $Header: n:/project/lib/src/res/rcs/res.h 1.9 1994/06/16 11:56:34 rex Exp $
23  * $Log: res.h $
24  * Revision 1.9  1994/06/16  11:56:34  rex
25  * Got rid of RDF_NODROP
26  *
27  * Revision 1.8  1994/05/26  13:54:27  rex
28  * Added prototype ResInstallPager()
29  *
30  * Revision 1.7  1994/03/09  19:31:48  jak
31  * Res\RefExtractInBlocks transfers a variable/length
32  * block of data in each pass.  The user/defined function
33  * returns the amount that should be passed in NEXT time.
34  *
35  * Revision 1.6  1994/02/17  11:25:02  rex
36  * Massive overhaul, moved some private stuff out to res_.h
37  *
38  * Revision 1.5  1993/09/01  16:02:10  rex
39  * Added prototype for ResExtractRefTable().
40  *
41  * Revision 1.4  1993/05/13  10:38:44  rex
42  * Added prototype for ResUnmake()
43  *
44  * Revision 1.3  1993/05/13  10:30:56  rex
45  * Added Extract routines and macros
46  *
47  * Revision 1.2  1993/03/08  10:06:12  rex
48  * Changed resource directory entry format (reduced from 12 to 10 bytes)
49  *
50  * Revision 1.1  1993/03/04  18:47:58  rex
51  * Initial revision
52  *
53  * Revision 1.6  1993/03/02  18:42:21  rex
54  * Major revision, new system
55  *
56  */
57 
58 #ifndef __RES_H
59 #define __RES_H
60 
61 //��� For now
62 //#define DBG_ON		1
63 
64 #include <stdbool.h>
65 #include <stddef.h>
66 #include <stdint.h>
67 #include <stdio.h> // for FILE*
68 #include <stdlib.h>
69 
70 #include "lg.h"
71 
72 //#ifndef DATAPATH_H
73 //#include <datapath.h>
74 //#endif
75 
76 #ifndef __RESTYPES_H
77 #include "restypes.h"
78 #endif
79 
80 #include "resformat.h"
81 
82 #pragma pack(push,2)
83 
84 //	---------------------------------------------------------
85 //		ID AND REF DEFINITIONS AND MACROS
86 //	---------------------------------------------------------
87 
88 //	Id's refer to resources, Ref's refer to items in compound resources
89 
90 typedef uint16_t Id;       // ID of a resource
91 typedef uint32_t Ref;      // high word is ID, low word is index
92 typedef uint16_t RefIndex; // index part of ref
93 
94 //	Here's how you get parts of a ref, or make a ref
95 
96 #define REFID(ref) (uint16_t)((ref) >> 16u)                            // get id from ref
97 #define REFINDEX(ref) (uint16_t)((ref) & 0xFFFFu)                      // get index from ref
98 #define MKREF(id, index) ((((uint32_t)id) << 16u) | (uint16_t)(index)) // make ref
99 
100 #define ID_NULL 0 // null resource id
101 #define ID_HEAD 1 // holds head ptr for LRU chain
102 #define ID_TAIL 2 // holds tail ptr for LRU chain
103 #define ID_MIN 3  // id's from 3 and up are valid
104 
105 //	---------------------------------------------------------
106 //		ACCESS TO RESOURCES (ID'S)  (resacc.c)
107 //	---------------------------------------------------------
108 
109 void *ResLock(Id id);                  // lock resource & get ptr
110 void ResUnlock(Id id);                 // unlock resource
111 void *ResGet(Id id);                   // get ptr to resource (dangerous!)
112 void *ResExtract(Id id, const ResourceFormat *format, void *buffer); // extract resource into buffer
113 void ResDrop(Id id);                   // drop resource from immediate use
114 void ResDelete(Id id);                 // delete resource forever
115 
116 //	------------------------------------------------------------
117 //		ACCESS TO ITEMS IN COMPOUND RESOURCES (REF'S)  (refacc.c)
118 //	------------------------------------------------------------
119 
120 // Each compound resource starts with a Ref Table. When loaded into memory, a
121 // ref table entry has a size, an offset into the raw resource (if loaded) and a
122 // pointer to the decoded ref (freed when the compound resource is unloaded).
123 typedef struct {
124     uint32_t size;
125     uint32_t offset;
126     void *decoded_data;
127 } RefTableEntry;
128 
129 typedef struct {
130     RefIndex numRefs;  // # items in compound resource
131     void *raw_data;    // resource data if loaded.
132     RefTableEntry entries[]; // numRefs table entries
133 } RefTable;
134 
135 // Decode raw ref table from file and return a RefTable.
136 void *ResDecodeRefTable(void *raw, size_t *size, UserDecodeData);
137 
138 void *RefLock(Ref ref);  // lock compound res, get ptr to item
139 #define RefUnlock(ref) ResUnlock(REFID(ref)) // unlock compound res item
140 void *RefGet(Ref ref);   // get ptr to item in comp. res (dangerous!)
141 
142 RefTable *ResReadRefTable(Id id);        // alloc & read ref table
143 void ResFreeRefTable(void *ptr);         // free ref table
144 int32_t ResExtractRefTable(Id id, RefTable *prt,
145                            int32_t size);             // extract reftable
146 
147 #define RefIndexValid(prt, index) ((index) < (prt)->numRefs)
148 
149 // returns the number of refs in a resource, extracting if necessary.
150 int32_t ResNumRefs(Id id);
151 
152 #define REFTABLESIZE(numrefs) (offsetof(RefTable, entries) + ((numrefs) * sizeof(RefTableEntry)))
153 
154 /*
155 //	-----------------------------------------------------------
156 //		BLOCK-AT-A-TIME ACCESS TO RESOURCES  (resexblk.c)
157 //	-----------------------------------------------------------
158 
159 void ResExtractInBlocks(Id id, void *buff, int32_t blockSize,
160         int32_t (*f_ProcBlock)(void *buff, int32_t numBytes, int32_t iblock));
161 void RefExtractInBlocks(RefTable *prt, Ref ref, void *buff, int32_t blockSize,
162         int32_t (*f_ProcBlock)(void *buff, int32_t numBytes, int32_t iblock));
163 
164 #define REBF_FIRST 0x01         // set for 1st block passed to f_ProcBlock
165 #define REBF_LAST  0x02         // set for last block (may also be first!)
166 */
167 
168 //	-----------------------------------------------------------
169 //		IN-MEMORY RESOURCE DESCRIPTORS, AND INFORMATION ROUTINES
170 //	-----------------------------------------------------------
171 //  For Mac version, keep a handle (rather than ptr).  Most ResDesc info not
172 //  needed because the Mac Resource Mgr takes care of it.
173 
174 //	Each resource id gets one of these resource descriptors
175 
176 /*typedef struct
177 {
178         //Handle        hdl;                    // Mac resource handle.
179 NULL if not in memory (on disk) int32_t filenum;                // Mac
180 resource file number uint8_t    lock;                   // lock count uint8_t
181 flags;                  // misc flags (RDF_XXX, see below) uint8_t      type;
182 // resource type (RTYPE_XXX, see restypes.h) uint32_t   offset; uint32_t
183 size;
184 
185         void*   ptr;
186         Id      next;
187         Id      prev;
188 } ResDesc;*/
189 
190 typedef struct {
191     void *ptr;             // ptr to resource in memory
192     uint32_t lock;         // lock count
193     uint32_t fsize;        // size of resource in bytes (1 Mb max)
194     uint32_t msize;        // size in memory (where used; not for compound)
195     uint32_t filenum;      // file number 0-31
196     uint32_t offset;       // offset in file
197     Id next;               // next resource in LRU order
198     Id prev;               // previous resource in LRU order
199     //uint32_t flags;        // resource management flags
200     /*uint16_t type : 8;*/ // resource type (RTYPE_XXX, see restypes.h)
201     const ResourceFormat *format;// format of resource
202 } ResDesc;
203 
204 typedef struct {
205     uint16_t flags : 8; // misc flags (RDF_XXX, see below)
206     uint16_t type : 8;  // resource type (RTYPE_XXX, see restypes.h)
207 } ResDesc2;
208 
209 #define RESDESC(id) (&gResDesc[id])      // convert id to resource desc ptr
210 #define RESDESC_ID(prd) ((prd)-gResDesc) // convert resdesc ptr to id
211 
212 #define RESDESC2(id) (&gResDesc2[id])      // convert id to rd2 ptr
213 #define RESDESC2_ID(prd) ((prd)-gResDesc2) // convert rd2 ptr to id
214 
215 #define RDF_LZW 0x01        // if 1, LZW compressed
216 #define RDF_COMPOUND 0x02   // if 1, compound resource
217 #define RDF_RESERVED 0x04   // reserved
218 #define RDF_LOADONOPEN 0x08 // if 1, load block when open file
219 
220 #define RES_MAXLOCK 255 // max locks on a resource
221 
222 // ptr to big array of ResDesc's
223 extern ResDesc *gResDesc;
224 // ptr to array of ResDesc2 (shared buff with resdesc)
225 extern ResDesc2 *gResDesc2;
226 
227 extern Id resDescMax; // max id in res desc
228 
229 //      Information about resources
230 #define ResInUse(id) (gResDesc[id].offset)
231 #define ResPtr(id) (gResDesc[id].ptr)
232 #define ResSize(id) (gResDesc[id].msize)
233 #define ResLocked(id) (gResDesc[id].lock)
234 #define ResFilenum(id) (gResDesc[id].filenum)
235 #define ResType(id) (gResDesc2[id].type)
236 #define ResFlags(id) (gResDesc2[id].flags)
237 #define ResCompressed(id) (gResDesc2[id].flags & RDF_LZW)
238 #define ResIsCompound(id) (gResDesc2[id].flags & RDF_COMPOUND)
239 //#define ResZipped(id) (gResDesc2[id].flags & RDF_PKZIP)
240 
241 //#define MaxSizeRsrc(theResource) GetMaxResourceSize(theResource)
242 
243 //	------------------------------------------------------------
244 //		RESOURCE MANAGER GENERAL ROUTINES  (res.c)
245 //	------------------------------------------------------------
246 
247 void ResInit(); // init Res, allocate initial ResDesc[]
248 void ResTerm(); // term Res (done auto via atexit)
249 
250 //	------------------------------------------------------------
251 //		RESOURCE FILE ACCESS (resfile.c)
252 //	------------------------------------------------------------
253 
254 typedef enum {
255     ROM_READ,       // open for reading only
256     ROM_EDIT,       // open for editing (r/w) only
257     ROM_EDITCREATE, // open for editing, create if not found
258     ROM_CREATE      // open for creation (deletes existing)
259 } ResOpenMode;
260 
261 void ResAddPath(char *path); // add search path for resfiles
262 int32_t ResOpenResFile(const char *fname, ResOpenMode mode, bool auxinfo);
263 void ResCloseFile(int32_t filenum); // close res file
264 
265 #define ResOpenFile(fname) ResOpenResFile(fname, ROM_READ, FALSE)
266 #define ResEditFile(fname, creat) ResOpenResFile(fname, (creat) ? ROM_EDITCREATE : ROM_EDIT, TRUE)
267 #define ResCreateFile(fname) ResOpenResFile(fname, ROM_CREATE, TRUE)
268 
269 #define MAX_RESFILENUM 31 // maximum file number
270 
271 // extern Datapath gDatapath;   // res system's datapath (others may use)
272 /*
273 //	---------------------------------------------------------
274 //		RESOURCE MEMORY MANAGMENT ROUTINES  (resmem.c)
275 //	---------------------------------------------------------
276 
277 void *ResMalloc(size_t size);
278 void *ResRealloc(void *p, size_t newsize);
279 void ResFree(void *p);
280 void *ResPage(int32_t size);
281 
282 void ResInstallPager(void *f(int32_t size));
283 
284 //	---------------------------------------------------------
285 //		RESOURCE STATS - ACCESSIBLE AT ANY TIME
286 //	---------------------------------------------------------
287 
288 typedef struct {
289         uint16_t numLoaded;                                     // # resources
290 loaded in ram uint16_t numLocked;                                       // #
291 resources locked int32_t totMemAlloc;                                   // total
292 memory alloted to resources } ResStat;
293 
294 extern ResStat resStat;                         // stats computed if
295 proper DBG bit set
296 */
297 
298 //	----------------------------------------------------------
299 //		PUBLIC INTERFACE FOR CREATORS OF RESOURCES
300 //	----------------------------------------------------------
301 
302 //	----------------------------------------------------------
303 //		RESOURCE MAKING  (resmake.c)
304 //	----------------------------------------------------------
305 
306 // make resource from data block
307 void ResMake(Id id, void *ptr, size_t size, uint8_t type, int32_t filenum, uint8_t flags, const ResourceFormat *format);
308 // make empty compound resource
309 void ResMakeCompound(Id id, uint8_t type, int32_t filenum, uint8_t flags);
310 // add item to compound
311 void ResAddRef(Ref ref, void *pitem, int32_t itemSize);
312 // unmake a resource
313 void ResUnmake(Id id);
314 
315 //	----------------------------------------------------------
316 //		RESOURCE FILE LAYOUT
317 //	----------------------------------------------------------
318 
319 //	Resource-file disk format:  header, data, dir
320 
321 typedef struct {
322     char signature[16];   // "LG ResFile v2.0\n",
323     char comment[96];     // user comment, terminated with '\z'
324     uint8_t reserved[12]; // reserved for future use, must be 0
325     int32_t dirOffset;    // file offset of directory
326 } ResFileHeader;          // total 128 bytes (why not?)
327 
328 typedef struct {
329     uint16_t numEntries; // # items referred to by directory
330     int32_t dataOffset;  // file offset at which data resides
331                          // directory entries follow immediately
332                          // (numEntries of them)
333 } ResDirHeader;
334 
335 typedef struct {
336     Id id;               // resource id (if 0, entry is deleted)
337     uint32_t size : 24;  // uncompressed size (size in ram)
338     uint32_t flags : 8;  // resource flags (RDF_XXX)
339     uint32_t csize : 24; // compressed size (size on disk)
340                          // (this size is valid disk size even if not comp.)
341     uint32_t type : 8;   // resource type
342 } ResDirEntry;
343 
344 // Active resource file table
345 
346 typedef struct {
347     uint16_t flags;         // RFF_XXX
348     ResFileHeader hdr;      // file header
349     ResDirHeader *pdir;     // ptr to resource directory
350     uint16_t numAllocDir;   // # dir entries allocated
351     int32_t currDataOffset; // current data offset in file
352 } ResEditInfo;
353 
354 typedef struct {
355     FILE *fd;           // file descriptor (from open())
356     ResEditInfo *pedit; // editing info, or NULL if read-only file
357 } ResFile;
358 
359 #define RFF_NEEDSPACK 0x0001 // resfile has holes, needs packing
360 #define RFF_AUTOPACK 0x0002  // resfile auto-packs (default TRUE)
361 
362 extern ResFile resFile[MAX_RESFILENUM + 1];
363 
364 // Macros to get ptr to resfile's directory, & iterate across entries
365 
366 #define RESFILE_HASDIR(filenum) (resFile[filenum].pedit)
367 #define RESFILE_DIRPTR(filenum) (resFile[filenum].pedit->pdir)
368 #define RESFILE_DIRENTRY(pdir, n) ((ResDirEntry *)((pdir) + 1) + (n))
369 #define RESFILE_FORALLINDIR(pdir, pde) \
370     for (pde = RESFILE_DIRENTRY(pdir, 0); pde < RESFILE_DIRENTRY(pdir, pdir->numEntries); pde++)
371 
372 extern char resFileSignature[16]; // magic header
373 
374 //	--------------------------------------------------------
375 //		RESOURCE FILE BUILDING  (resbuild.c)
376 //	--------------------------------------------------------
377 
378 void ResSetComment(int32_t filenum, char *comment); // set comment
379 int32_t ResWrite(Id id);                            // write resource to file
380 void ResKill(Id id);                                // delete resource & remove from file
381 int32_t ResPack(int32_t filenum);                   // remove empty entries
382 
383 //#define ResAutoPackOn(filenum) (resFile[filenum].pedit->flags |= RFF_AUTOPACK)
384 //#define ResAutoPackOff(filenum) (resFile[filenum].pedit->flags &=
385 //~RFF_AUTOPACK) #define ResNeedsPacking(filenum) (resFile[filenum].pedit->flags
386 //& RFF_NEEDSPACK)
387 // DG: a case-insensitive fopen()-wrapper (see resfile.c)
388 extern FILE *fopen_caseless(const char *path, const char *mode);
389 
390 #pragma pack(pop)
391 
392 #endif
393