1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the AUTHORS
5 * file distributed with this source distribution.
6 *
7 * Additional copyright for this file:
8 * Copyright (C) 1999-2000 Revolution Software Ltd.
9 * This code is based on source code created by Revolution Software,
10 * used with permission.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 *
26 */
27
28 #ifndef ICB_PX_LINKED_DATA_FILE_H
29 #define ICB_PX_LINKED_DATA_FILE_H
30
31 #include "engines/icb/common/px_rcutypes.h"
32 #include "engines/icb/common/px_common.h"
33 #include "engines/icb/common/px_clu_api.h"
34 #include "engines/icb/debug.h"
35
36 namespace ICB {
37
38 // This value is returned as an error condition.
39 #define PX_LINKED_DATA_FILE_ERROR (0xffffffff)
40
41 #define ORDER_PRESERVED_FLAG 1
42 #define NO_NAMES_FLAG 2
43 #define SUPPRESS_OUTPUT 4 // Suppress printing of output
44
45 typedef struct {
46 int32 name_offset; // offset to Null terminated name of the item
47 int32 data_offset; // Offset to the item
48 int32 data_size; // Size of the items data
49 uint32 name_hash_value; // hash value of name item...
50 } _linkedDataFileEntry;
51
52 class _linked_data_file { // Should be CObjectFile
53
54 public:
Fetch_number_of_items()55 inline uint32 Fetch_number_of_items() { // how many
56 return (number_of_items);
57 }
58
GetHeaderVersion()59 inline uint32 GetHeaderVersion() { return (header.GetVersion()); }
60
OrderPreserved()61 inline int32 OrderPreserved() { return ((flags) & (ORDER_PRESERVED_FLAG)); }
62
NameSearchable()63 inline int32 NameSearchable() { return (!OrderPreserved()); }
64
65 uint32 Fetch_item_number_by_hash(const uint32 hash);
66 uint32 Fetch_item_number_by_name(const char *name); // reference a number by its ascii name
67
68 void *Fetch_item_by_number(uint32 number); // reference a resource by number
69
70 void *Fetch_item_by_name(const char *name); // reference a resource by its ascii name
71
72 void *Fetch_items_name_by_number(uint32 number); // return pointer to name of item number n
73
74 void *Try_fetch_item_by_name(const char *); // reference a resource by name
75 void *Try_fetch_item_by_hash(uint32); // reference a resource by hash
76
77 void *Try_fetch_item_by_script_name(const char *name);
78
79 px_standard_header header;
80
81 uint32 number_of_items;
82 uint32 flags;
83
84 _linkedDataFileEntry list[1]; // 1 used to prevent 0 sized array warnings
85 // This structure is a variable size and so should never
86 // be a parameter to sizeof anyway
87 };
88
89 // get DATA given NUMBER
Fetch_item_by_number(uint32 number)90 inline void *_linked_data_file::Fetch_item_by_number(uint32 number) {
91 // illegal reference number
92 assert(number < number_of_items);
93 // return address of resource
94 return (((uint8 *)&header) + list[number].data_offset);
95 }
96
97 // get NAME given NUMBER
Fetch_items_name_by_number(uint32 number)98 inline void *_linked_data_file::Fetch_items_name_by_number(uint32 number) {
99 // illegal reference number
100 assert(number < number_of_items);
101 // return name
102 return (((uint8 *)&header) + list[number].name_offset);
103 }
104
105 // this is the one that does the search...
106 // get NUMBER given NAME (does search)
Fetch_item_number_by_name(const char * name)107 inline uint32 _linked_data_file::Fetch_item_number_by_name(const char *name) {
108 uint32 hash;
109
110 if (!NameSearchable()) {
111 Fatal_error("This file is not searchable by name and was created as such (name %s)", name);
112 }
113
114 hash = EngineHashString(name);
115
116 return Fetch_item_number_by_hash(hash);
117 }
118
119 // get ITEM given NAME (uses Try_fetch_item_by_name, fatal error if can't find)
Fetch_item_by_name(const char * name)120 inline void *_linked_data_file::Fetch_item_by_name(const char *name) {
121 void *search;
122
123 search = Try_fetch_item_by_name(name);
124
125 if (search == 0) {
126 Fatal_error("pxLinked_data_file::Fetch_item_by_name Object %s not found", name);
127 // Note, for not the engine then the error is not caught which is a bad thing
128 // but we need a generic Fatal_error type thing that converters & the engine can call
129 // i.e. the converters need a Fatal_error function
130 return (NULL);
131 } else
132 return search;
133 }
134
135 // get DATA given NAME (uses get NUMBER given NAME and returns 0 if not found or uses get DATA given NUMBER to return DATA)
Try_fetch_item_by_name(const char * name)136 inline void *_linked_data_file::Try_fetch_item_by_name(const char *name) {
137 // as Fetch_item_with_name but will return 0 if entry could not be found as opposed to an assert
138 uint32 search = 0;
139
140 search = Fetch_item_number_by_name(name);
141
142 if (search == PX_LINKED_DATA_FILE_ERROR)
143 return 0; // not found (legal)
144 else
145 return Fetch_item_by_number(search);
146 }
147
148 // get DATA given HASH (uses get NUMBER given HASH and returns 0 if not found or uses get DATA given NUMBER to return DATA)
Try_fetch_item_by_hash(uint32 hash)149 inline void *_linked_data_file::Try_fetch_item_by_hash(uint32 hash) {
150 // as Fetch_item_with_name but will return 0 if entry could not be found as opposed to an assert
151 uint32 search = 0;
152
153 search = Fetch_item_number_by_hash(hash);
154
155 if (search == PX_LINKED_DATA_FILE_ERROR)
156 return 0; // not found (legal)
157 else
158 return Fetch_item_by_number(search);
159 }
160
Try_fetch_item_by_script_name(const char * name)161 inline void *_linked_data_file::Try_fetch_item_by_script_name(const char *name) {
162 uint32 search = 0;
163
164 do {
165 if (strstr((const char *)((uint8 *)&header) + list[search].name_offset, (const char *)name))
166 return (((uint8 *)&header) + list[search].data_offset);
167
168 search++;
169 } while (search < number_of_items);
170
171 // not found at all
172 return (0);
173 }
174
175 } // End of namespace ICB
176
177 #endif
178