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