source: oup/releases/0.24a/Unit2_functions.pas@ 1109

Last change on this file since 1109 was 24, checked in by alloc, 18 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.