1 /*
2 PLIB - A Suite of Portable Game Libraries
3 Copyright (C) 1998,2002 Steve Baker
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library 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 GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 For further information visit http://plib.sourceforge.net
20
21 $Id: ssgLoadSSG.cxx 1568 2002-09-02 06:05:49Z sjbaker $
22 */
23
24 // code for loading and writing .ssg files
25
26 #include "ssgLocal.h"
27
28 // used for reading only:
29 int _ssgFileVersionNumber = 0 ;
30
31 // simple list of ssgBase derived objects:
32 class _ssgBaseList : public ssgSimpleList
33 {
34 public:
35
_ssgBaseList()36 _ssgBaseList() : ssgSimpleList( sizeof(ssgBase *), 16 ) {}
37
~_ssgBaseList()38 ~_ssgBaseList() {}
39
get(unsigned n)40 ssgBase *get ( unsigned n )
41 {
42 return n < total ? ((ssgBase **) list) [ n ] : NULL;
43 }
44
add(ssgBase * obj)45 void add ( ssgBase *obj )
46 {
47 sizeChk ( 1 ) ;
48 ((ssgBase **) list) [ total++ ] = obj ;
49 }
50
find(ssgBase * obj)51 int find ( ssgBase *obj )
52 {
53 for ( unsigned i = 0 ; i < total ; i++ )
54 if ( ((ssgBase **) list) [ i ] == obj )
55 return i ;
56 return -1 ;
57 }
58
59 };
60
61 // list of ssgBase objects for instance referencing:
62 static _ssgBaseList *_ssgInstanceList ;
63
64
_ssgLoadObject(FILE * f,ssgBase ** objp,int type_mask)65 int _ssgLoadObject ( FILE *f, ssgBase **objp, int type_mask )
66 {
67 int type = 0, key = 0;
68 ssgBase *obj;
69
70 _ssgReadInt ( f, &type ) ;
71
72 if ( type == _SSG_BACKWARDS_REFERENCE )
73 {
74 _ssgReadInt ( f, &key ) ;
75
76 obj = _ssgInstanceList -> get ( key ) ;
77 if ( obj == NULL )
78 {
79 if ( key != 0 )
80 {
81 ulSetError ( UL_WARNING,
82 "ssgLoadObject: Unexpected null object for key %d.", key ) ;
83 return FALSE ;
84 }
85 }
86 else if ( ! obj -> isAKindOf ( type_mask ) )
87 {
88 ulSetError ( UL_WARNING, "ssgLoadObject: Bad type %#x (%s), expected %#x.",
89 obj -> getType (), obj -> getTypeName (), type_mask ) ;
90 return FALSE ;
91 }
92 }
93 else
94 {
95 if ( ( type & type_mask ) != type_mask )
96 {
97 ulSetError ( UL_WARNING, "ssgLoadObject: Bad type %#x, expected %#x.",
98 type, type_mask ) ;
99 return FALSE ;
100 }
101
102 obj = ssgCreateOfType ( type ) ;
103 if ( obj == NULL )
104 return FALSE ;
105
106 _ssgInstanceList -> add ( obj ) ;
107
108 if ( ! obj -> load ( f ) )
109 {
110 ulSetError ( UL_DEBUG, "ssgLoadObject: Failed to load object of type %s.",
111 obj -> getTypeName () ) ;
112 return FALSE ;
113 }
114
115 if ( obj -> isAKindOf ( ssgTypeEntity () ) )
116 {
117 ((ssgEntity *) obj) -> recalcBSphere () ;
118 }
119 }
120
121 if ( _ssgReadError () )
122 {
123 ulSetError ( UL_WARNING, "ssgLoadObject: Read error." ) ;
124 return FALSE ;
125 }
126
127 *objp = obj ;
128
129 return TRUE ;
130 }
131
132
_ssgSaveObject(FILE * f,ssgBase * obj)133 int _ssgSaveObject ( FILE *f, ssgBase *obj )
134 {
135 int key = _ssgInstanceList -> find ( obj ) ;
136
137 if ( key >= 0 )
138 {
139 _ssgWriteInt ( f, _SSG_BACKWARDS_REFERENCE ) ;
140 _ssgWriteInt ( f, key ) ;
141 }
142 else
143 {
144 _ssgWriteInt ( f, obj -> getType () ) ;
145
146 _ssgInstanceList -> add ( obj ) ;
147
148 if ( ! obj -> save ( f ) )
149 {
150 ulSetError ( UL_DEBUG, "ssgSaveObject: Failed to save object of type %s.",
151 obj -> getTypeName () ) ;
152 return FALSE ;
153 }
154 }
155
156 if ( _ssgWriteError () )
157 {
158 ulSetError ( UL_WARNING, "ssgSaveObject: Write error." ) ;
159 return FALSE ;
160 }
161
162 return TRUE ;
163 }
164
165
ssgLoadSSG(const char * fname,const ssgLoaderOptions * options)166 ssgEntity *ssgLoadSSG ( const char *fname, const ssgLoaderOptions* options )
167 {
168 ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ;
169 const ssgLoaderOptions* current_options = ssgGetCurrentOptions () ;
170
171 char filename [ 1024 ] ;
172 current_options -> makeModelPath ( filename, fname ) ;
173
174 FILE *fd = fopen ( filename, "rb" ) ;
175
176 if ( fd == NULL )
177 {
178 perror ( filename ) ;
179 ulSetError ( UL_WARNING,
180 "ssgLoadSSG: Failed to open '%s' for reading.", filename ) ;
181 return NULL ;
182 }
183
184 int magic ;
185 ssgEntity *kid ;
186
187 _ssgReadInt ( fd, & magic ) ;
188
189 if ( ( magic & 0xFFFFFF00 ) != ( SSG_FILE_MAGIC_NUMBER & 0xFFFFFF00 ) )
190 {
191 if (((magic & 0x0000FF)>> 0)==((SSG_FILE_MAGIC_NUMBER & 0xFF000000)>>24) &&
192 ((magic & 0x00FF00)>> 8)==((SSG_FILE_MAGIC_NUMBER & 0x00FF0000)>>16) &&
193 ((magic & 0xFF0000)>>16)==((SSG_FILE_MAGIC_NUMBER & 0x0000FF00)>> 8) )
194 ulSetError ( UL_WARNING, "ssgLoadSSG: File appears to be byte swapped!" ) ;
195 else
196 ulSetError ( UL_WARNING, "ssgLoadSSG: File has incorrect magic number!" ) ;
197
198 return NULL ;
199 }
200
201 /*
202 Save the old version number so we can do recursive loads
203 */
204
205 int oldFileVersion = _ssgFileVersionNumber ;
206 _ssgFileVersionNumber = ( magic & 0xFF ) ;
207
208 if ( _ssgFileVersionNumber == 0 )
209 {
210 ulSetError ( UL_WARNING,
211 "ssgLoadSSG: SSG file format version zero is no longer supported, sorry! For more, see the docs." ) ;
212 _ssgFileVersionNumber = oldFileVersion ;
213 return NULL ;
214 }
215
216 if ( _ssgFileVersionNumber > SSG_FILE_VERSION )
217 {
218 ulSetError ( UL_WARNING,
219 "ssgLoadSSG: This version of SSG is too old to load this file!" ) ;
220 _ssgFileVersionNumber = oldFileVersion ;
221 return NULL ;
222 }
223
224 _ssgBaseList *oldInstanceList = _ssgInstanceList ; // in case of recursive loads
225 _ssgInstanceList = new _ssgBaseList ;
226 _ssgInstanceList -> add ( NULL ) ; // index 0 --> NULL
227
228 int success = _ssgLoadObject ( fd, (ssgBase **) &kid, ssgTypeEntity () ) ;
229
230 if ( ! success )
231 {
232 ulSetError ( UL_WARNING, "ssgLoadSSG: Failed to load object." ) ;
233 kid = NULL ;
234 }
235
236 delete _ssgInstanceList ;
237 _ssgInstanceList = oldInstanceList ;
238 _ssgFileVersionNumber = oldFileVersion ;
239
240 fclose ( fd ) ;
241
242 return kid ;
243 }
244
245
ssgSaveSSG(const char * filename,ssgEntity * ent)246 int ssgSaveSSG ( const char *filename, ssgEntity *ent )
247 {
248 FILE *fd = fopen ( filename, "wb" ) ;
249
250 if ( fd == NULL )
251 {
252 perror ( filename ) ;
253 ulSetError ( UL_WARNING,
254 "ssgSaveSSG: Failed to open '%s' for writing.", filename ) ;
255 return FALSE ;
256 }
257
258 _ssgBaseList *oldInstanceList = _ssgInstanceList ; // for recursive saves
259 _ssgInstanceList = new _ssgBaseList ;
260 _ssgInstanceList -> add ( NULL ) ; // index 0 --> NULL
261
262 _ssgWriteInt ( fd, SSG_FILE_MAGIC_NUMBER ) ;
263
264 int success = _ssgSaveObject ( fd, ent ) ;
265
266 if ( ! success )
267 ulSetError ( UL_WARNING, "ssgSaveSSG: Failed to write object." ) ;
268
269 delete _ssgInstanceList ;
270 _ssgInstanceList = oldInstanceList ;
271
272 fclose ( fd ) ;
273
274 return success ;
275 }
276
277
278