source: oup/releases/0.22a/Unit2_functions.pas@ 786

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