source: oup/releases/0.25a/Unit2_functions.pas @ 25

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