source: oup/releases/0.23a/Unit2_functions.pas@ 794

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