source: oup/releases/0.20a/src/Unit2_functions.pas@ 12

Last change on this file since 12 was 8, checked in by alloc, 18 years ago

Uploaded old revs and structdefs.

File size: 15.0 KB
Line 
1UNIT Unit2_functions;
2INTERFACE
3USES Classes, Dialogs, SysUtils, StrUtils, Math, SQLiteTable3,
4 Unit3_data, Unit4_Exporters;
5
6TYPE
7 TExportSet=SET OF (DO_dat,DO_raw,DO_convert,DO_toone);
8
9FUNCTION GetFilesList(ext:String; pattern:String; NoEmptyFiles:Boolean):TStringList;
10FUNCTION GetExtensionsList:TStringList;
11
12FUNCTION Decode_Int(buffer:Tdata):LongWord;
13FUNCTION Encode_Int(input:LongWord):Tdata;
14FUNCTION Decode_Float(buffer:Tdata):Single;
15FUNCTION Encode_Float(input:Single):Tdata;
16
17FUNCTION LoadDatInfos(filename:String):Boolean;
18PROCEDURE OpenDatabase(FileName:String);
19
20FUNCTION LoadDatFile(fileid:LongWord):Tdata;
21PROCEDURE UpdateDatFile(fileid:LongWord; data:Tdata);
22FUNCTION LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer):Boolean;
23FUNCTION UpdateDatFilePart(fileid,offset,size:LongWord; target:Pointer):Boolean;
24
25FUNCTION LoadRawFile(fileid,datlinkoffset,size:LongWord; target:Pointer):Boolean;
26FUNCTION UpdateRawFile(fileid,datlinkoffset,size:LongWord; target:Pointer):Boolean;
27
28FUNCTION ExportFile(fileid:LongWord; filename:String; settings:TExportSet; path:String):Integer;
29
30FUNCTION FormatNumber(value:LongWord; width:Byte; leadingzeros:Char):String;
31FUNCTION FormatFileSize(size:LongWord):String;
32FUNCTION CreateHexString(data:Tdata; HexOnly:Boolean):String;
33FUNCTION GetWinFileName(name:String):String;
34FUNCTION GetExtractPath:String;
35
36
37IMPLEMENTATION
38
39TYPE
40 TValueSwitcher=Record
41 CASE IsFloat: Boolean OF
42 True: (ValueFloat:Single);
43 False: (ValueInt:LongWord);
44 END;
45
46FUNCTION Decode_Int(buffer:Tdata):LongWord;
47 BEGIN
48 Result:=buffer[0]+buffer[1]*256+buffer[2]*256*256+buffer[3]*256*256*256;
49 END;
50FUNCTION Encode_Int(input:LongWord):Tdata;
51 BEGIN
52 Result[0]:=input MOD 256;
53 input:=input DIV 256;
54 Result[1]:=input MOD 256;
55 input:=input DIV 256;
56 Result[2]:=input MOD 256;
57 input:=input DIV 256;
58 Result[3]:=input MOD 256;
59 END;
60FUNCTION Decode_Float(buffer:Tdata):Single;
61 VAR _valueswitcher:TValueSwitcher;
62 BEGIN
63 _valueswitcher.ValueInt:=Decode_Int(buffer);
64 Result:=_valueswitcher.ValueFloat;
65 END;
66FUNCTION Encode_Float(input:Single):Tdata;
67 VAR _valueswitcher:TValueSwitcher;
68 BEGIN
69 _valueswitcher.ValueFloat:=input;
70 Result:=Encode_Int(_valueswitcher.ValueInt);
71 END;
72
73
74FUNCTION GetFilesList(ext:String; pattern:String; NoEmptyFiles:Boolean):TStringList;
75 VAR
76 i:LongWord;
77 where:String;
78 Tbl:TSQLiteTable;
79 BEGIN
80 SetLength(Result,0);
81 IF opened_state=opened_dat THEN BEGIN
82 FOR i:=0 TO dat_header.Files-1 DO BEGIN
83 IF ( (Length(ext)=0) OR (dat_files[i].Extension=ext) ) AND
84 ( (Length(pattern)=0) OR (Pos(pattern,dat_files[i].Name)>0) ) THEN BEGIN
85 IF NoEmptyFiles THEN BEGIN
86 IF (dat_files[i].FileType AND $02)=0 THEN BEGIN
87 SetLength(Result,Length(Result)+1);
88 Result[High(Result)]:=dat_files[i].FileName;
89 END;
90 END ELSE BEGIN
91 SetLength(Result,Length(Result)+1);
92 Result[High(Result)]:=dat_files[i].FileName;
93 END;
94 END;
95 END;
96 END ELSE BEGIN
97 where:='';
98 IF Length(ext)>0 THEN BEGIN
99 IF Length(where)>0 THEN where:=where+' AND ';
100 where:=where+'(extension="'+ext+'")';
101 END;
102 IF Length(pattern)>0 THEN BEGIN
103 IF Length(where)>0 THEN where:=where+' AND ';
104 where:=where+'(name LIKE "%'+pattern+'%")';
105 END;
106 IF NoEmptyFiles THEN BEGIN
107 IF Length(where)>0 THEN where:=where+' AND ';
108 where:=where+'((contenttype & 2)=0)';
109 END;
110 IF Length(where)>0 THEN where:=' WHERE '+where;
111 Tbl:=DB.GetTable('SELECT id,name,extension FROM datfiles'+where+' ORDER BY id ASC;');
112 IF Tbl.Count>0 THEN BEGIN
113 SetLength(Result,Tbl.Count);
114 i:=0;
115 REPEAT
116 Result[i]:=FormatNumber(Tbl.FieldAsInteger('id'),5,'0')+'-'+Tbl.FieldAsString('name')+'.'+Tbl.FieldAsString('extension');
117 Inc(i);
118 Tbl.Next;
119 UNTIL Tbl.EOF;
120 END;
121 END;
122 END;
123
124FUNCTION GetExtensionsList:TStringList;
125 VAR
126 i:LongWord;
127 Tbl:TSQLiteTable;
128 BEGIN
129 SetLength(Result,0);
130 IF opened_state=opened_dat THEN BEGIN
131 FOR i:=0 TO dat_header.Extensions-1 DO BEGIN
132 SetLength(Result,Length(Result)+1);
133 WITH dat_extensionsmap[i] DO BEGIN
134 Result[High(Result)]:=Extension[3]+Extension[2]+Extension[1]+Extension[0]+' ('+IntToStr(ExtCount)+')';
135 END;
136 END;
137 END ELSE BEGIN
138 Tbl:=DB.GetTable('SELECT extension,count(extension) AS x FROM datfiles GROUP BY extension ORDER BY extension ASC;');
139 IF Tbl.Count>0 THEN BEGIN
140 SetLength(Result,Tbl.Count);
141 i:=0;
142 REPEAT
143 Result[i]:=Tbl.FieldAsString('extension')+' ('+IntToStr(Tbl.FieldAsInteger('x'))+')';
144 Inc(i);
145 Tbl.Next;
146 UNTIL Tbl.EOF;
147 END;
148 END;
149 END;
150
151FUNCTION LoadDatInfos(filename:String):Boolean;
152 VAR i:LongWord;
153 dat_file:TFileStream;
154 BEGIN
155 Result:=True;
156 opened_state:=opened_dat;
157 dat_filename:=filename;
158 raw_filename:=MidStr(filename,1,Length(filename)-3)+'raw';
159 dat_file:=TFileStream.Create(filename, fmOpenRead);
160 dat_file.Read(dat_header,SizeOf(dat_header));
161 FOR i:=0 TO High(dat_header.Ident) DO
162 IF dat_header.Ident[i]<>header_ident1[i] THEN BEGIN
163 Result:=False;
164 Exit;
165 END;
166 SetLength(dat_filesmap,dat_header.Files);
167 SetLength(dat_files,dat_header.Files);
168 FOR i:=0 TO dat_header.Files-1 DO dat_file.Read(dat_filesmap[i],SizeOf(dat_filesmap[i]));
169 FOR i:=0 TO dat_header.Files-1 DO BEGIN
170 dat_files[i].Extension:=dat_filesmap[i].Extension;
171 dat_files[i].Extension:=ReverseString(dat_files[i].Extension);
172 dat_files[i].Size:=dat_filesmap[i].FileSize;
173 dat_files[i].FileType:=dat_filesmap[i].FileType;
174 dat_files[i].DatAddr:=dat_filesmap[i].DataAddr-8+dat_header.DataAddr;
175 IF (dat_filesmap[i].FileType AND $01)=0 THEN BEGIN
176 dat_file.Seek(dat_filesmap[i].NameAddr+dat_header.NamesAddr,soFromBeginning);
177 SetLength(dat_files[i].Name,100);
178 dat_file.Read(dat_files[i].Name[1],100);
179 dat_files[i].Name:=MidStr(dat_files[i].Name,1+4,Pos(#0,dat_files[i].Name)-1-4);
180 END ELSE BEGIN
181 dat_files[i].Name:='';
182 END;
183 dat_files[i].FileName:=FormatNumber(i,5,'0')+'-'+dat_files[i].Name+'.'+dat_files[i].Extension;
184 END;
185 dat_file.Seek($40+dat_header.Files*$14,soFromBeginning);
186 SetLength(dat_namedfilesmap,dat_header.NamedFiles);
187 FOR i:=0 TO dat_header.NamedFiles-1 DO dat_file.Read(dat_namedfilesmap[i],SizeOf(dat_namedfilesmap[i]));
188
189 dat_file.Seek($40+dat_header.Files*$14+dat_header.NamedFiles*$8,soFromBeginning);
190 SetLength(dat_extensionsmap,dat_header.Extensions);
191 FOR i:=0 TO dat_header.Extensions-1 DO dat_file.Read(dat_extensionsmap[i],SizeOf(dat_extensionsmap[i]));
192
193 dat_file.Free;
194 END;
195
196
197FUNCTION LoadDatFile(fileid:LongWord):Tdata;
198 VAR
199 dat_file:TFileStream;
200 Tbl:TSQLiteTable;
201 mem:TMemoryStream;
202 BEGIN
203 IF opened_state=opened_dat THEN BEGIN
204 dat_file:=TFileStream.Create(dat_filename, fmOpenRead);
205 dat_file.Seek(dat_files[fileid].DatAddr,soFromBeginning);
206 SetLength(Result,dat_files[fileid].Size);
207 dat_file.Read(Result[0],dat_files[fileid].Size);
208 dat_file.Free;
209 END ELSE BEGIN
210 Tbl:=DB.GetTable('SELECT data FROM datfiles WHERE id='+IntToStr(fileid)+';');
211 IF Tbl.Count>0 THEN BEGIN
212 mem:=Tbl.FieldAsBlob('data');
213 SetLength(Result,mem.Size);
214 mem.Seek(0,soFromBeginning);
215 mem.Read(Result[0],mem.Size);
216 mem.Free;
217 END;
218 END;
219 END;
220PROCEDURE UpdateDatFile(fileid:LongWord; data:Tdata);
221 VAR
222 dat_file:TFileStream;
223 Tbl:TSQLiteTable;
224 BEGIN
225 IF opened_state=opened_dat THEN BEGIN
226 dat_file:=TFileStream.Create(dat_filename, fmOpenReadWrite);
227 dat_file.Seek(dat_files[fileid].DatAddr,soFromBeginning);
228 dat_file.Write(data[0],Length(data));
229 dat_file.Free;
230 END ELSE BEGIN
231 END;
232 END;
233
234FUNCTION LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer):Boolean;
235 VAR
236 dat_file:TFileStream;
237 Tbl:TSQLiteTable;
238 mem:TMemoryStream;
239 BEGIN
240 IF opened_state=opened_dat THEN BEGIN
241 dat_file:=TFileStream.Create(dat_filename, fmOpenRead);
242 Result:=True;
243 dat_file.Seek(dat_files[fileid].DatAddr+offset,soFromBeginning);
244 dat_file.Read(target^,size);
245 dat_file.Free;
246 END ELSE BEGIN
247 Tbl:=DB.GetTable('SELECT data FROM datfiles WHERE id='+IntToStr(fileid)+';');
248 IF Tbl.Count>0 THEN BEGIN
249 Result:=True;
250 mem:=Tbl.FieldAsBlob('data');
251 mem.Seek(offset,soFromBeginning);
252 mem.Read(target^,size);
253 mem.Free;
254 END;
255 END;
256 END;
257FUNCTION UpdateDatFilePart(fileid,offset,size:LongWord; target:Pointer):Boolean;
258 VAR
259 dat_file:TFileStream;
260 Tbl:TSQLiteTable;
261 BEGIN
262 IF opened_state=opened_dat THEN BEGIN
263 dat_file:=TFileStream.Create(dat_filename, fmOpenReadWrite);
264 Result:=True;
265 dat_file.Seek(dat_files[fileid].DatAddr+offset,soFromBeginning);
266 dat_file.Write(target^,size);
267 dat_file.Free;
268 END ELSE BEGIN
269 END;
270 END;
271
272FUNCTION LoadRawFile(fileid,datlinkoffset,size:LongWord; target:Pointer):Boolean;
273 VAR
274 filestream:TFileStream;
275 raw_addr:LongWord;
276 Tbl:TSQLiteTable;
277 mem:TMemoryStream;
278 BEGIN
279 IF opened_state=opened_dat THEN BEGIN
280 Result:=True;
281 LoadDatFilePart(fileid,datlinkoffset,4,@raw_addr);
282 filestream:=TFileStream.Create(AnsiReplaceStr(dat_filename,'.dat','.raw'),fmOpenRead);
283 filestream.Seek(raw_addr,soFromBeginning);
284 filestream.Read(target^,size);
285 filestream.Free;
286 END ELSE BEGIN
287 Tbl:=DB.GetTable('SELECT data FROM rawmap WHERE (src_id='+IntToStr(fileid)+') AND (src_link_offset='+IntToStr(datlinkoffset)+');');
288 IF Tbl.Count>0 THEN BEGIN
289 Result:=True;
290 mem:=Tbl.FieldAsBlob('data');
291 mem.Seek(0,soFromBeginning);
292 mem.Read(target^,size);
293 mem.Free;
294 END;
295 END;
296 END;
297FUNCTION UpdateRawFile(fileid,datlinkoffset,size:LongWord; target:Pointer):Boolean;
298 VAR
299 filestream:TFileStream;
300 raw_addr:LongWord;
301 BEGIN
302 IF opened_state=opened_dat THEN BEGIN
303 Result:=True;
304 LoadDatFilePart(fileid,datlinkoffset,4,@raw_addr);
305 filestream:=TFileStream.Create(AnsiReplaceStr(dat_filename,'.dat','.raw'),fmOpenReadWrite);
306 filestream.Seek(raw_addr,soFromBeginning);
307 filestream.Write(target^,size);
308 filestream.Free;
309 END ELSE BEGIN
310 END;
311 END;
312
313
314FUNCTION FormatNumber(value:LongWord; width:Byte; leadingzeros:Char):String;
315 BEGIN
316 Result:=AnsiReplaceStr(Format('%'+IntToStr(width)+'u',[value]),' ',leadingzeros);
317 END;
318
319FUNCTION FormatFileSize(size:LongWord):String;
320 BEGIN
321 IF size>=1000*1024*1024 THEN BEGIN
322 Result:=FloatToStrF(size/1024/1024/1024,ffFixed,5,1)+' GB';
323 END ELSE BEGIN
324 IF size>=1000*1024 THEN BEGIN
325 Result:=FloatToStrF(size/1024/1024,ffFixed,5,1)+' MB';
326 END ELSE BEGIN
327 IF size>=1000 THEN BEGIN
328 Result:=FloatToStrF(size/1024,ffFixed,5,1)+' KB';
329 END ELSE BEGIN
330 Result:=IntToStr(size)+' B';
331 END;
332 END;
333 END;
334 END;
335
336FUNCTION CreateHexString(data:Tdata; HexOnly:Boolean):String;
337 VAR
338 string_build,ascii_version:String;
339 i:LongWord;
340 BEGIN
341 string_build:='';
342 ascii_version:='';
343 FOR i:=0 TO High(data) DO BEGIN
344 IF NOT HexOnly THEN
345 IF (i MOD 16)=0 THEN
346 string_build:=string_build+'0x'+IntToHex(i,6)+' ';
347 string_build:=string_build+IntToHex(data[i],2);
348 IF NOT HexOnly THEN BEGIN
349 IF data[i]>=32 THEN ascii_version:=ascii_version+Chr(data[i])
350 ELSE ascii_version:=ascii_version+'.';
351 IF ((i+1) MOD 2)=0 THEN string_build:=string_build+#32;
352 IF ((i+1) MOD 16)=0 THEN BEGIN
353 string_build:=string_build+#32+ascii_version+CrLf;
354 ascii_version:='';
355 END;
356 END;
357 END;
358 Result:=string_build;
359 END;
360
361
362FUNCTION ExportFile(fileid:LongWord; filename:String; settings:TExportSet; path:String):Integer;
363 VAR
364 i:Byte;
365 extension:String;
366 BEGIN
367 Result:=export_noerror;
368 extension:=RightStr(filename,4);
369 IF DO_dat IN settings THEN ExportDatFile(fileid,path+'\'+GetWinFileName(filename));
370 IF DO_raw IN settings THEN BEGIN
371 FOR i:=1 TO Length(ExportHandlers)+1 DO BEGIN
372 IF i<=Length(ExportHandlers) THEN BEGIN
373 IF ExportHandlers[i].Ext=extension THEN BEGIN
374 IF ExportHandlers[i].needed THEN BEGIN
375 CASE ExportHandlers[i].Handler(fileid,path+'\'+GetWinFileName(filename),(DO_convert IN settings)) OF
376 0: Result:=0;
377 ELSE
378 Result:=export_handlererror;
379 END;
380 END;
381 Break;
382 END;
383 END ELSE BEGIN
384 Result:=export_nohandler;
385 END;
386 END;
387 END;
388 END;
389
390
391FUNCTION GetWinFileName(name:String):String;
392 BEGIN
393 Result:=name;
394 Result:=AnsiReplaceStr(Result,'\','__');
395 Result:=AnsiReplaceStr(Result,'/','__');
396 Result:=AnsiReplaceStr(Result,'>','__');
397 Result:=AnsiReplaceStr(Result,'<','__');
398 END;
399
400FUNCTION GetExtractPath:String;
401 BEGIN
402 Result:=ExtractFilePath(dat_filename)+'\extracted_'+ExtractFileName(dat_filename);
403 END;
404
405
406PROCEDURE OpenDatabase(FileName:String);
407 VAR
408 i:Byte;
409 data:Tdata;
410 temps:String;
411 Tbl: TSQLiteTable;
412 BEGIN
413 IF NOT FileExists(FileName) THEN BEGIN
414 ShowMessage('File doesn''t exist!!!');
415 Exit;
416 END;
417 DB:=TSQLiteDatabase.Create(FileName);
418 Tbl:=DB.GetTable('SELECT name,value FROM globals ORDER BY name ASC');
419 REPEAT
420 IF Tbl.FieldAsString('name')='dbversion' THEN BEGIN
421 IF Tbl.FieldAsString('value')<>DBversion THEN BEGIN
422 ShowMessage('Database-file '+CrLf+'"'+FileName+'"'+CrLf+'has wrong version. (Required: '+DBversion+'; found: '+Tbl.FieldAsString('value')+')');
423 Exit;
424 END;
425 END;
426 IF Tbl.FieldAsString('name')='lvl' THEN BEGIN
427 database_level:=StrToInt(Tbl.FieldAsString('value'));
428 END;
429 IF Tbl.FieldAsString('name')='ident' THEN BEGIN
430 temps:=Tbl.FieldAsString('value');
431 FOR i:=0 TO High(database_ident) DO BEGIN
432 CASE temps[(i*2)+1+0] OF
433 '0'..'9': database_ident[i]:=Ord(temps[(i*2)+1+0])-48;
434 'A'..'F': database_ident[i]:=Ord(temps[(i*2)+1+0])-55;
435 END;
436 database_ident[i]:=database_ident[i]*16;
437 CASE temps[(i*2)+1+1] OF
438 '0'..'9': database_ident[i]:=database_ident[i]+Ord(temps[(i*2)+1+0])-48;
439 'A'..'F': database_ident[i]:=database_ident[i]+Ord(temps[(i*2)+1+0])-55;
440 END;
441 END;
442 END;
443 Tbl.Next;
444 UNTIL Tbl.EOF;
445 Tbl.Free;
446 opened_state:=opened_db;
447 END;
448
449
450
451
452END.
Note: See TracBrowser for help on using the repository browser.