ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/oup/current/Code_OniDataClass.pas
Revision: 45
Committed: Sat Dec 23 00:03:50 2006 UTC (18 years, 9 months ago) by alloc
Content type: text/x-pascal
File size: 36694 byte(s)
Log Message:

File Contents

# Content
1 unit Code_OniDataClass;
2
3 interface
4
5 uses Data, Code_DataStructures, Classes, SysUtils, StrUtils,
6 Dialogs, ABSDecUtil, ABSMain, DB;
7
8 type
9 TOniData = class
10 private
11 FFileName: String;
12 FLevelInfo: TLevelInfo;
13 FBackend: Integer;
14 Fos_mac: Boolean;
15 protected
16 public
17 property FileName: String Read FFileName Write FFileName;
18 property Backend: Integer Read FBackend Write FBackend;
19 property OSisMac: Boolean Read Fos_mac Write Fos_mac;
20 property LevelInfo: TLevelinfo Read FLevelInfo Write FLevelInfo;
21
22 constructor Create(filename: String; var Result: Boolean); virtual; abstract;
23 procedure Close; virtual; abstract;
24
25 function GetFileInfo(fileid: LongWord): TFileInfo; virtual; abstract;
26 function GetFilesList(ext: String; pattern: String;
27 NoEmptyFiles: Boolean): TStringArray; virtual; abstract;
28 function GetFilesCount: LongWord; virtual; abstract;
29 function GetExtensionsList: TStringArray; virtual; abstract;
30 function GetExtendedExtensionsList: TExtensionsMap; virtual; abstract;
31 function ExtractFileID(Name: String): Integer;
32 function GetFileIDByName(Name: String): Integer;
33
34 function LoadDatFile(fileid: LongWord): Tdata; virtual; abstract;
35 procedure UpdateDatFile(fileid: LongWord; Data: Tdata); virtual; abstract;
36 procedure LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer);
37 virtual; abstract;
38 procedure UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer);
39 virtual; abstract;
40
41 function GetRawList(fileid: LongWord): TRawList; virtual; abstract;
42 function GetRawInfo(fileid, dat_offset: LongWord): TRawInfo;
43 procedure LoadRawFile(fileid, dat_offset: LongWord; target: Pointer);
44 virtual; abstract;
45 procedure UpdateRawFile(fileid, dat_offset: LongWord; size: LongWord; target: Pointer);
46 virtual; abstract;
47 procedure LoadRawFilePart(fileid, dat_offset: LongWord;
48 offset, size: LongWord; target: Pointer); virtual; abstract;
49 procedure UpdateRawFilePart(fileid, dat_offset: LongWord;
50 offset, size: LongWord; target: Pointer); virtual; abstract;
51 function AppendRawFile(loc_sep: Boolean; size: LongWord; target: Pointer): LongWord;
52 virtual; abstract;//Returns new Address
53 published
54 end;
55
56 TOniDataDat = class(TOniData)
57 private
58 Fdat_file: TFileStream;
59 Fraw_file: TFileStream;
60 Fsep_file: TFileStream;
61 Fdat_header: THeader;
62 Fdat_filesmap: TFilesMap;
63 Fdat_files: TFiles;
64 Fdat_namedfilesmap: TNamedFilesMap;
65 Fdat_extensionsmap: TExtensionsMap;
66 FUnloadWhenUnused: Boolean;
67 FDatOpened: Boolean;
68 FRawOpened: Boolean;
69 FSepOpened: Boolean;
70 protected
71 public
72 property UnloadWhenUnused: Boolean Read FUnloadWhenUnused Write FUnloadWhenUnused;
73
74 constructor Create(DatFilename: String; var Result: Boolean); override;
75 procedure Close; override;
76
77 function GetFileInfo(fileid: LongWord): TFileInfo; override;
78 function GetFilesList(ext: String; pattern: String;
79 NoEmptyFiles: Boolean): TStringArray; override;
80 function GetFilesCount: LongWord; override;
81 function GetExtensionsList: TStringArray; override;
82 function GetExtendedExtensionsList: TExtensionsMap; override;
83
84 function LoadDatFile(fileid: LongWord): Tdata; override;
85 procedure UpdateDatFile(fileid: LongWord; Data: Tdata); override;
86 procedure LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
87 procedure UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
88
89 procedure LoadRawOffset(loc_sep: Boolean; raw_addr, size: LongWord; target: Pointer);
90 function GetRawList(fileid: LongWord): TRawList; override;
91 procedure LoadRawFile(fileid, dat_offset: LongWord; target: Pointer); override;
92 procedure UpdateRawFile(fileid, dat_offset: LongWord; size: LongWord;
93 target: Pointer); override;
94 procedure LoadRawFilePart(fileid, dat_offset: LongWord;
95 offset, size: LongWord; target: Pointer); override;
96 procedure UpdateRawFilePart(fileid, dat_offset: LongWord;
97 offset, size: LongWord; target: Pointer); override;
98 function AppendRawFile(loc_sep: Boolean; size: LongWord; target: Pointer): LongWord;
99 override;//Returns new Address
100 published
101 end;
102
103 TOniDataADB = class(TOniData)
104 private
105 FDatabase: TABSDatabase;
106 FQuery: TABSQuery;
107 protected
108 public
109 constructor Create(OLDBFilename: String; var Result: Boolean); override;
110 procedure Close; override;
111
112 // function GetDatLinks(srcid:LongWord):TDatLinks;
113 function GetFileInfo(fileid: LongWord): TFileInfo; override;
114 function GetFilesList(ext: String; pattern: String;
115 NoEmptyFiles: Boolean): TStringArray; override;
116 function GetFilesCount: LongWord; override;
117 function GetExtensionsList: TStringArray; override;
118 function GetExtendedExtensionsList: TExtensionsMap; override;
119 function GetNamedFilesMap: TNamedFilesMap;
120
121 function LoadDatFile(fileid: LongWord): Tdata; override;
122 procedure UpdateDatFile(fileid: LongWord; Data: Tdata); override;
123 procedure LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
124 procedure UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
125
126 function GetRawList(fileid: LongWord): TRawList; override;
127 procedure LoadRawFile(fileid, dat_offset: LongWord; target: Pointer); override;
128 procedure UpdateRawFile(fileid, dat_offset: LongWord; size: LongWord;
129 target: Pointer); override;
130 procedure LoadRawFilePart(fileid, dat_offset: LongWord;
131 offset, size: LongWord; target: Pointer); override;
132 procedure UpdateRawFilePart(fileid, dat_offset: LongWord;
133 offset, size: LongWord; target: Pointer); override;
134 published
135 end;
136
137
138 const
139 ODB_None = -1;
140 ODB_Dat = 0;
141 ODB_ADB = 1;
142
143 var
144 OniDataConnection: TOniData;
145
146 function CreateDataConnection(filename: String; backend: Integer): Boolean;
147 procedure CloseDataConnection;
148
149
150
151
152 implementation
153
154 uses Code_Functions;
155
156
157
158 (*
159 Implementation of TOniData
160 *)
161
162 function TOniData.GetFileIDByName(Name: String): Integer;
163 var
164 files: TStringArray;
165 i: Integer;
166 begin
167 Result := -1;
168 files := Self.GetFilesList('', Name, False);
169 if Length(files) > 0 then
170 for i := 0 to High(files) do
171 if Pos(Name, files[i]) = Pos('-', files[i]) + 1 then
172 begin
173 // if MidStr(files[i],Pos('-',files[i])+1,Length(files[i])-Pos('-',files[i])-5)=name then begin
174 Result := Self.ExtractFileID(files[i]);
175 Break;
176 end;
177 end;
178
179
180
181
182 function TOniData.ExtractFileID(Name: String): Integer;
183 begin
184 if Name[5] = '-' then
185 Result := HexToLong(MidStr(Name, 1, 4))
186 else
187 Result := StrToInt(MidStr(Name, 1, 5));
188 end;
189
190
191
192
193 function TOniData.GetRawInfo(fileid, dat_offset: LongWord): TRawInfo;
194 var
195 i: LongWord;
196 raw_list: TRawList;
197 begin
198 raw_list := Self.GetRawList(fileid);
199 Result.src_id := 0;
200 Result.src_offset := 0;
201 Result.raw_addr := 0;
202 Result.raw_size := 0;
203 for i := 0 to High(raw_list) do
204 begin
205 if raw_list[i].src_offset = dat_offset then
206 begin
207 Result.src_id := fileid;
208 Result.src_offset := raw_list[i].src_offset;
209 Result.raw_addr := raw_list[i].raw_addr;
210 Result.raw_size := raw_list[i].raw_size;
211 Result.loc_sep := raw_list[i].loc_sep;
212 Break;
213 end;
214 end;
215 end;
216
217
218
219
220
221
222
223 (*
224 ================================================================================
225 Implementation of TOniDataDat
226 *)
227
228 constructor TOniDataDat.Create(DatFilename: String; var Result: Boolean);
229 const
230 header_ident1_pc: array[0..$13] of Byte =
231 ($1F, $27, $DC, $33, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
232 $14, $00, $10, $00, $08, $00);
233 header_ident1_mac: array[0..$13] of Byte =
234 ($61, $30, $C1, $23, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
235 $14, $00, $10, $00, $08, $00);
236 header_ident1_macbeta: array[0..$13] of Byte =
237 ($81, $11, $8D, $23, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
238 $14, $00, $10, $00, $08, $00);
239 header_ident2: array[0..$F] of Byte =
240 ($99, $CF, $40, $00, $90, $4F, $63, $00, $F4, $55, $5F, $00, $90, $4F, $63, $00);
241 var
242 i: LongWord;
243 header_pc, header_mac: Boolean;
244 begin
245 FUnloadWhenUnused := True;
246 FDatOpened := False;
247 FRawOpened := False;
248 if not FileExists(DatFilename) then
249 begin
250 ShowMessage('File doesn''t exist!!!');
251 Result := False;
252 Exit;
253 end;
254 FFileName := DatFilename;
255 Fdat_file := TFileStream.Create(FFileName, fmOpenRead);
256 Fdat_file.Read(Fdat_header, SizeOf(Fdat_header));
257 header_pc := True;
258 header_mac := True;
259 for i := 0 to High(Fdat_header.Ident) do
260 begin
261 FLevelInfo.Ident[i] := Fdat_header.Ident[i];
262 if Fdat_header.Ident[i] <> header_ident1_pc[i] then
263 header_pc := False;
264 if Fdat_header.Ident[i] <> header_ident1_mac[i] then
265 header_mac := False;
266 end;
267 if not (header_pc xor header_mac) then
268 begin
269 Result := False;
270 Exit;
271 end
272 else
273 begin
274 if (header_pc and not header_mac) then
275 Fos_mac := False
276 else
277 Fos_mac := True;
278 end;
279 SetLength(Fdat_filesmap, Fdat_header.Files);
280 SetLength(Fdat_files, Fdat_header.Files);
281 for i := 0 to Fdat_header.Files - 1 do
282 Fdat_file.Read(Fdat_filesmap[i], SizeOf(Fdat_filesmap[i]));
283 for i := 0 to Fdat_header.Files - 1 do
284 begin
285 Fdat_files[i].ID := i;
286 Fdat_files[i].Extension := Fdat_filesmap[i].Extension;
287 Fdat_files[i].Extension := ReverseString(Fdat_files[i].Extension);
288 Fdat_files[i].Size := Fdat_filesmap[i].FileSize;
289 Fdat_files[i].FileType := Fdat_filesmap[i].FileType;
290 Fdat_files[i].DatAddr := Fdat_filesmap[i].DataAddr - 8 + Fdat_header.DataAddr;
291 if (Fdat_filesmap[i].FileType and $01) = 0 then
292 begin
293 Fdat_file.Seek(Fdat_filesmap[i].NameAddr + Fdat_header.NamesAddr, soFromBeginning);
294 SetLength(Fdat_files[i].Name, 100);
295 Fdat_file.Read(Fdat_files[i].Name[1], 100);
296 Fdat_files[i].Name := MidStr(Fdat_files[i].Name, 1 + 4, Pos(
297 #0, Fdat_files[i].Name) - 1 - 4);
298 end
299 else
300 begin
301 Fdat_files[i].Name := '';
302 end;
303 Fdat_files[i].FileName :=
304 FormatNumber(i, 5, '0') + '-' + Fdat_files[i].Name + '.' + Fdat_files[i].Extension;
305 Fdat_files[i].FileNameHex :=
306 IntToHex(i, 4) + '-' + Fdat_files[i].Name + '.' + Fdat_files[i].Extension;
307 end;
308 Fdat_file.Seek($40 + Fdat_header.Files * $14, soFromBeginning);
309 SetLength(Fdat_namedfilesmap, Fdat_header.NamedFiles);
310 for i := 0 to Fdat_header.NamedFiles - 1 do
311 Fdat_file.Read(Fdat_namedfilesmap[i], SizeOf(Fdat_namedfilesmap[i]));
312
313 Fdat_file.Seek($40 + Fdat_header.Files * $14 + Fdat_header.NamedFiles * $8, soFromBeginning);
314 SetLength(Fdat_extensionsmap, Fdat_header.Extensions);
315 for i := 0 to Fdat_header.Extensions - 1 do
316 Fdat_file.Read(Fdat_extensionsmap[i], SizeOf(Fdat_extensionsmap[i]));
317
318 Fdat_file.Seek(Fdat_files[0].DatAddr + 7, soFromBeginning);
319 Fdat_file.Read(FLevelInfo.LevelNumber, 1);
320 FLevelInfo.LevelNumber := FLevelInfo.LevelNumber div 2;
321
322 Fdat_file.Free;
323
324 Result := True;
325 FBackend := ODB_Dat;
326 end;
327
328
329
330
331 procedure TOniDataDat.Close;
332 begin
333 if not FUnloadWhenUnused and FDatOpened then
334 Fdat_file.Free;
335 if not FUnloadWhenUnused and FRawOpened then
336 Fraw_file.Free;
337 if not FUnloadWhenUnused and FSepOpened then
338 Fsep_file.Free;
339 Self.Free;
340 end;
341
342
343
344
345 function TOniDataDat.GetFileInfo(fileid: LongWord): TFileInfo;
346 begin
347 if fileid < Self.GetFilesCount then
348 Result := Fdat_files[fileid]
349 else
350 Result.ID := -1;
351 end;
352
353
354
355
356 function TOniDataDat.GetFilesList(ext: String; pattern: String;
357 NoEmptyFiles: Boolean): TStringArray;
358 var
359 i: LongWord;
360 begin
361 SetLength(Result, 0);
362 for i := 0 to Fdat_header.Files - 1 do
363 begin
364 if ((Length(ext) = 0) or (Pos(Fdat_files[i].Extension, ext) > 0)) and
365 ((Length(pattern) = 0) or
366 (Pos(UpperCase(pattern), UpperCase(Fdat_files[i].Name)) > 0)) then
367 begin
368 if (NoEmptyFiles = False) or ((Fdat_files[i].FileType and $02) = 0) then
369 begin
370 SetLength(Result, Length(Result) + 1);
371 if AppSettings.FilenumbersAsHex then
372 Result[High(Result)] := Fdat_files[i].FileNameHex
373 else
374 Result[High(Result)] := Fdat_files[i].FileName;
375 end;
376 end;
377 end;
378 end;
379
380
381
382
383 function TOniDataDat.GetFilesCount: LongWord;
384 begin
385 Result := Fdat_header.Files;
386 end;
387
388
389
390
391 function TOniDataDat.GetExtensionsList: TStringArray;
392 var
393 i: LongWord;
394 begin
395 SetLength(Result, Fdat_header.Extensions);
396 for i := 0 to Fdat_header.Extensions - 1 do
397 begin
398 with Fdat_extensionsmap[i] do
399 begin
400 Result[i] := Extension[3] + Extension[2] + Extension[1] + Extension[0] +
401 ' (' + IntToStr(ExtCount) + ')';
402 end;
403 end;
404 end;
405
406
407
408
409 function TOniDataDat.GetExtendedExtensionsList: TExtensionsMap;
410 var
411 i: LongWord;
412 begin
413 SetLength(Result, Fdat_header.Extensions);
414 for i := 0 to Fdat_header.Extensions - 1 do
415 begin
416 Result[i] := Fdat_extensionsmap[i];
417 end;
418 end;
419
420
421
422
423 function TOniDataDat.LoadDatFile(fileid: LongWord): Tdata;
424 begin
425 if fileid < Self.GetFilesCount then
426 begin
427 if FUnloadWhenUnused or not FDatOpened then
428 Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
429 Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
430 SetLength(Result, Fdat_files[fileid].Size);
431 Fdat_file.Read(Result[0], Fdat_files[fileid].Size);
432 if UnloadWhenUnused then
433 Fdat_file.Free
434 else
435 FDatOpened := True;
436 end;
437 end;
438
439
440
441
442 procedure TOniDataDat.UpdateDatFile(fileid: LongWord; Data: Tdata);
443 begin
444 if fileid < Self.GetFilesCount then
445 begin
446 if FUnloadWhenUnused or not FDatOpened then
447 Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
448 Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
449 Fdat_file.Write(Data[0], Length(Data));
450 if UnloadWhenUnused then
451 Fdat_file.Free
452 else
453 FDatOpened := True;
454 end;
455 end;
456
457
458
459
460 procedure TOniDataDat.LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer);
461 begin
462 if fileid < Self.GetFilesCount then
463 begin
464 if FUnloadWhenUnused or not FDatOpened then
465 Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
466 Fdat_file.Seek(Fdat_files[fileid].DatAddr + offset, soFromBeginning);
467 Fdat_file.Read(target^, size);
468 if UnloadWhenUnused then
469 Fdat_file.Free
470 else
471 FDatOpened := True;
472 end;
473 end;
474
475
476
477
478 procedure TOniDataDat.UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer);
479 begin
480 if fileid < Self.GetFilesCount then
481 begin
482 if FUnloadWhenUnused or not FDatOpened then
483 Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
484 Fdat_file.Seek(Fdat_files[fileid].DatAddr + offset, soFromBeginning);
485 Fdat_file.Write(target^, size);
486 if UnloadWhenUnused then
487 Fdat_file.Free
488 else
489 FDatOpened := True;
490 end;
491 end;
492
493
494
495
496 function TOniDataDat.GetRawList(fileid: LongWord): TRawList;
497 var
498 i: LongWord;
499 begin
500 SetLength(Result, 0);
501 for i := 0 to High(RawListHandlers) do
502 if UpperCase(RawListHandlers[i].Ext) = UpperCase(Fdat_files[fileid].extension) then
503 if RawListHandlers[i].needed then
504 begin
505 Result := RawListHandlers[i].Handler(fileid);
506 Break;
507 end
508 else
509 Break;
510 end;
511
512
513
514
515 procedure TOniDataDat.LoadRawOffset(loc_sep: Boolean; raw_addr, size: LongWord;
516 target: Pointer);
517 begin
518 if not loc_sep then
519 begin
520 if FUnloadWhenUnused or not FRawOpened then
521 Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
522 fmOpenReadWrite);
523 if raw_addr <= Fraw_file.Size then
524 begin
525 Fraw_file.Seek(raw_addr, soFromBeginning);
526 Fraw_file.Read(target^, size);
527 end;
528 if UnloadWhenUnused then
529 Fraw_file.Free
530 else
531 FRawOpened := True;
532 end
533 else
534 begin
535 if FUnloadWhenUnused or not FSepOpened then
536 Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
537 fmOpenReadWrite);
538 if raw_addr <= Fsep_file.Size then
539 begin
540 Fsep_file.Seek(raw_addr, soFromBeginning);
541 Fsep_file.Read(target^, size);
542 end;
543 if UnloadWhenUnused then
544 Fsep_file.Free
545 else
546 FSepOpened := True;
547 end;
548 end;
549
550
551
552
553 procedure TOniDataDat.LoadRawFile(fileid, dat_offset: LongWord; target: Pointer);
554 var
555 raw_info: TRawInfo;
556 begin
557 if fileid < Self.GetFilesCount then
558 begin
559 raw_info := Self.GetRawInfo(fileid, dat_offset);
560 if not raw_info.loc_sep then
561 begin
562 if FUnloadWhenUnused or not FRawOpened then
563 Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
564 fmOpenReadWrite);
565 Fraw_file.Seek(raw_info.raw_addr, soFromBeginning);
566 Fraw_file.Read(target^, raw_info.raw_size);
567 if UnloadWhenUnused then
568 Fraw_file.Free
569 else
570 FRawOpened := True;
571 end
572 else
573 begin
574 if FUnloadWhenUnused or not FSepOpened then
575 Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
576 fmOpenReadWrite);
577 Fsep_file.Seek(raw_info.raw_addr, soFromBeginning);
578 Fsep_file.Read(target^, raw_info.raw_size);
579 if UnloadWhenUnused then
580 Fsep_file.Free
581 else
582 FSepOpened := True;
583 end;
584 end;
585 end;
586
587
588
589
590 procedure TOniDataDat.UpdateRawFile(fileid, dat_offset: LongWord;
591 size: LongWord; target: Pointer);
592 var
593 raw_info: TRawInfo;
594 begin
595 if fileid < Self.GetFilesCount then
596 begin
597 raw_info := Self.GetRawInfo(fileid, dat_offset);
598 if not raw_info.loc_sep then
599 begin
600 if FUnloadWhenUnused or not FRawOpened then
601 Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
602 fmOpenReadWrite);
603 Fraw_file.Seek(raw_info.raw_addr, soFromBeginning);
604 Fraw_file.Write(target^, raw_info.raw_size);
605 if UnloadWhenUnused then
606 Fraw_file.Free
607 else
608 FRawOpened := True;
609 end
610 else
611 begin
612 if FUnloadWhenUnused or not FSepOpened then
613 Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
614 fmOpenReadWrite);
615 Fsep_file.Seek(raw_info.raw_addr, soFromBeginning);
616 Fsep_file.Write(target^, raw_info.raw_size);
617 if UnloadWhenUnused then
618 Fsep_file.Free
619 else
620 FSepOpened := True;
621 end;
622 end;
623 end;
624
625
626
627
628 procedure TOniDataDat.LoadRawFilePart(fileid, dat_offset: LongWord;
629 offset, size: LongWord; target: Pointer);
630 var
631 raw_info: TRawInfo;
632 Data: Tdata;
633 mem: TMemoryStream;
634 begin
635 if fileid < Self.GetFilesCount then
636 begin
637 raw_info := Self.GetRawInfo(fileid, dat_offset);
638 SetLength(Data, raw_info.raw_size);
639 Self.LoadRawFile(fileid, dat_offset, @Data[0]);
640 mem := TMemoryStream.Create;
641 mem.Write(Data[offset], size);
642 mem.Read(target^, size);
643 mem.Free;
644 end;
645 end;
646
647
648
649
650 procedure TOniDataDat.UpdateRawFilePart(fileid, dat_offset: LongWord;
651 offset, size: LongWord; target: Pointer);
652 var
653 raw_info: TRawInfo;
654 begin
655 if fileid < Self.GetFilesCount then
656 begin
657 raw_info := Self.GetRawInfo(fileid, dat_offset);
658 if not raw_info.loc_sep then
659 begin
660 if FUnloadWhenUnused or not FRawOpened then
661 Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
662 fmOpenReadWrite);
663 Fraw_file.Seek(raw_info.raw_addr + offset, soFromBeginning);
664 Fraw_file.Write(target^, raw_info.raw_size);
665 if UnloadWhenUnused then
666 Fraw_file.Free
667 else
668 FRawOpened := True;
669 end
670 else
671 begin
672 if FUnloadWhenUnused or not FSepOpened then
673 Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
674 fmOpenReadWrite);
675 Fsep_file.Seek(raw_info.raw_addr + offset, soFromBeginning);
676 Fsep_file.Write(target^, raw_info.raw_size);
677 if UnloadWhenUnused then
678 Fsep_file.Free
679 else
680 FSepOpened := True;
681 end;
682 end;
683 end;
684
685
686
687
688 function TOniDataDat.AppendRawFile(loc_sep: Boolean; size: LongWord;
689 target: Pointer): LongWord; //Returns new Address
690 begin
691 if not loc_sep then
692 begin
693 if FUnloadWhenUnused or not FRawOpened then
694 Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
695 fmOpenReadWrite);
696 Result := Fraw_file.Size;
697 Fraw_file.Seek(0, soFromEnd);
698 Fraw_file.Write(target^, size);
699 if UnloadWhenUnused then
700 Fraw_file.Free
701 else
702 FRawOpened := True;
703 end
704 else
705 begin
706 if FUnloadWhenUnused or not FSepOpened then
707 Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
708 fmOpenReadWrite);
709 Result := Fsep_file.Size;
710 Fsep_file.Seek(0, soFromEnd);
711 Fsep_file.Write(target^, size);
712 if UnloadWhenUnused then
713 Fsep_file.Free
714 else
715 FSepOpened := True;
716 end;
717 end;
718
719
720
721
722
723
724
725
726
727
728
729 (*
730 ================================================================================
731 Implementation of TOniDataADB
732 *)
733
734 constructor TOniDataADB.Create(OLDBFilename: String; var Result: Boolean);
735 var
736 i, j: Byte;
737 temps: String;
738 begin
739 if not FileExists(OLDBFilename) then
740 begin
741 ShowMessage('File doesn''t exist!!!');
742 Result := False;
743 Exit;
744 end;
745 FFileName := OLDBFilename;
746 FDatabase := TABSDatabase.Create(nil);
747 FDatabase.DatabaseName := 'OLDBcon';
748 FDatabase.DatabaseFileName := OLDBFilename;
749 FDatabase.Open;
750 FQuery := TABSQuery.Create(FDatabase);
751 FQuery.DatabaseName := 'OLDBcon';
752 FQuery.SQL.Text := 'SELECT [name],[value] FROM globals ORDER BY [name] ASC';
753 FQuery.Open;
754 FQuery.First;
755 repeat
756 if FQuery.FieldByName('name').AsString = 'dbversion' then
757 begin
758 if FQuery.FieldByName('value').AsString <> DBversion then
759 begin
760 ShowMessage('Database-file ' + #13 + #10 +
761 '"' + OLDBFilename + '"' + #13 + #10 +
762 'has wrong version. (Required: ' + DBversion + '; found: ' +
763 FQuery.FieldByName('value').AsString + ')');
764 FQuery.Close;
765 Result := False;
766 Exit;
767 end;
768 end;
769 if FQuery.FieldByName('name').AsString = 'lvl' then
770 begin
771 FLevelInfo.LevelNumber := StrToInt(FQuery.FieldByName('value').AsString);
772 end;
773 if FQuery.FieldByName('name').AsString = 'ident' then
774 begin
775 temps := FQuery.FieldByName('value').AsString;
776 for i := 0 to High(FLevelInfo.Ident) do
777 begin
778 j := i * 2 + 1;
779 case temps[j] of
780 '0'..'9':
781 FLevelInfo.Ident[i] := Ord(temps[j]) - 48;
782 'A'..'F':
783 FLevelInfo.Ident[i] := Ord(temps[j]) - 55;
784 end;
785 FLevelInfo.Ident[i] := FLevelInfo.Ident[i] * 16;
786 case temps[j + 1] of
787 '0'..'9':
788 FLevelInfo.Ident[i] := FLevelInfo.Ident[i] + Ord(temps[j + 1]) - 48;
789 'A'..'F':
790 FLevelInfo.Ident[i] := FLevelInfo.Ident[i] + Ord(temps[j + 1]) - 55;
791 end;
792 end;
793 end;
794 if FQuery.FieldByName('name').AsString = 'ident' then
795 begin
796 temps := FQuery.FieldByName('value').AsString;
797 Fos_mac := temps = 'MAC';
798 end;
799 FQuery.Next;
800 until FQuery.EOF;
801 FQuery.Close;
802
803 Result := True;
804 FBackend := ODB_ADB;
805 end;
806
807
808
809
810 procedure TOniDataADB.Close;
811 begin
812 FDatabase.Close;
813 FDatabase.Free;
814 Self.Free;
815 end;
816
817
818
819
820 function TOniDataADB.GetFileInfo(fileid: LongWord): TFileInfo;
821 begin
822 if fileid < Self.GetFilesCount then
823 begin
824 FQuery.SQL.Text := 'SELECT * FROM datfiles WHERE id=' + IntToStr(
825 fileid) + ' ORDER BY id ASC;';
826 FQuery.Open;
827 if FQuery.RecordCount = 1 then
828 begin
829 FQuery.First;
830 Result.ID := FQuery.FieldByName('id').AsInteger;
831 Result.Name := FQuery.FieldByName('name').AsString;
832 Result.Extension := FQuery.FieldByName('extension').AsString;
833 Result.FileName := FormatNumber(Result.ID, 5, '0') + '-' + Result.Name + '.' +
834 Result.Extension;
835 Result.Size := FQuery.FieldByName('size').AsInteger;
836 Result.FileType := HexToLong(FQuery.FieldByName('contenttype').AsString);
837 Result.DatAddr := 0;
838 Result.opened := False;
839 end;
840 FQuery.Close;
841 end
842 else
843 begin
844 Result.ID := -1;
845 end;
846 end;
847
848
849
850
851 function TOniDataADB.GetFilesList(ext: String; pattern: String;
852 NoEmptyFiles: Boolean): TStringArray;
853 var
854 i: LongWord;
855 where: String;
856 where_ext: String;
857 begin
858 where := '';
859 if Length(ext) > 0 then
860 begin
861 if Length(where) > 0 then
862 where := where + ' AND ';
863 if Pos(',', ext) > 0 then
864 begin
865 i := 1;
866 where_ext := '';
867 while i < Length(ext) do
868 begin
869 if Length(where_ext) > 0 then
870 where_ext := where_ext + ' OR ';
871 where_ext := where_ext + '(extension="' + MidStr(ext, i, 4) + '")';
872 i := i + 5;
873 end;
874 where := where + '(' + where_ext + ')';
875 end
876 else
877 begin
878 where := where + '(extension="' + ext + '")';
879 end;
880 end;
881 if Length(pattern) > 0 then
882 begin
883 if Length(where) > 0 then
884 where := where + ' AND ';
885 where := where + '(name LIKE "%' + pattern + '%")';
886 end;
887 if NoEmptyFiles then
888 begin
889 if Length(where) > 0 then
890 where := where + ' AND ';
891 where := where + '(contenttype<>2)';
892 end;
893 if Length(where) > 0 then
894 where := ' WHERE ' + where;
895 FQuery.SQL.Text := 'SELECT id,name,extension FROM datfiles' + where + ' ORDER BY id ASC;';
896 FQuery.Open;
897 if FQuery.RecordCount > 0 then
898 begin
899 FQuery.First;
900 SetLength(Result, FQuery.RecordCount);
901 i := 0;
902 repeat
903 Result[i] := FormatNumber(FQuery.FieldByName('id').AsInteger, 5, '0') + '-' +
904 FQuery.FieldByName('name').AsString + '.' + FQuery.FieldByName('extension').AsString;
905 Inc(i);
906 FQuery.Next;
907 until FQuery.EOF;
908 end;
909 FQuery.Close;
910 end;
911
912
913
914
915 function TOniDataADB.GetFilesCount: LongWord;
916 begin
917 FQuery.SQL.Text := 'SELECT Count(*) AS cnumber FROM datfiles;';
918 FQuery.Open;
919 if FQuery.RecordCount > 0 then
920 begin
921 FQuery.First;
922 Result := FQuery.FieldByName('cnumber').AsInteger;
923 end
924 else
925 Result := 0;
926 FQuery.Close;
927 end;
928
929
930
931
932 function TOniDataADB.GetExtensionsList: TStringArray;
933 var
934 i: LongWord;
935 begin
936 SetLength(Result, 0);
937 FQuery.SQL.Text :=
938 'SELECT extension,count(extension) AS x FROM datfiles GROUP BY extension ORDER BY extension ASC;';
939 FQuery.Open;
940 if FQuery.RecordCount > 0 then
941 begin
942 SetLength(Result, FQuery.RecordCount);
943 i := 0;
944 repeat
945 Result[i] := FQuery.FieldByName('extension').AsString + ' (' +
946 IntToStr(FQuery.FieldByName('x').AsInteger) + ')';
947 Inc(i);
948 FQuery.Next;
949 until FQuery.EOF;
950 end;
951 FQuery.Close;
952 end;
953
954
955
956
957 function TOniDataADB.GetExtendedExtensionsList: TExtensionsMap;
958 var
959 i, j: LongWord;
960 temps: String;
961 Data: Tdata;
962 begin
963 SetLength(Result, 0);
964 FQuery.SQL.Text := 'SELECT ext,ident FROM extlist ORDER BY ext ASC;';
965 FQuery.Open;
966 if FQuery.RecordCount > 0 then
967 begin
968 SetLength(Result, FQuery.RecordCount);
969 i := 0;
970 repeat
971 temps := FQuery.FieldByName('ext').AsString;
972 for j := 0 to 3 do
973 Result[i].Extension[j] := temps[4 - j];
974 Data := DecodeHexString(FQuery.FieldByName('ident').AsString);
975 for j := 0 to 7 do
976 Result[i].Ident[j] := Data[j];
977 Inc(i);
978 FQuery.Next;
979 until FQuery.EOF;
980 end;
981 FQuery.Close;
982 end;
983
984
985
986
987 function TOniDataADB.GetNamedFilesMap: TNamedFilesMap;
988 var
989 i: LongWord;
990 temp: Integer;
991 temps: String;
992 temparray: array of record
993 id: Integer;
994 fullname: String[50];
995 end;
996 begin
997 SetLength(temparray, 0);
998 FQuery.SQL.Text :=
999 'SELECT id,(extension+name) AS xname FROM datfiles WHERE Length(name)>0 ORDER BY extension,name ASC;';
1000 FQuery.Open;
1001 if FQuery.RecordCount > 0 then
1002 begin
1003 repeat
1004 temp := FQuery.FieldByName('id').AsInteger;
1005 temps := FQuery.FieldByName('xname').AsString;
1006
1007 SetLength(temparray, Length(temparray) + 1);
1008 if Length(temparray) > 1 then
1009 begin
1010 for i := High(temparray) - 1 downto 0 do
1011 begin
1012 if StringSmaller(temps, temparray[i].fullname) then
1013 begin
1014 temparray[i + 1] := temparray[i];
1015 if i = 0 then
1016 begin
1017 temparray[i].id := temp;
1018 temparray[i].fullname := temps;
1019 end;
1020 end
1021 else
1022 begin
1023 temparray[i + 1].id := temp;
1024 temparray[i + 1].fullname := temps;
1025 Break;
1026 end;
1027 end;
1028 end
1029 else
1030 begin
1031 temparray[0].id := temp;
1032 temparray[0].fullname := temps;
1033 end;
1034 FQuery.Next;
1035 until FQuery.EOF;
1036 end;
1037 FQuery.Close;
1038 SetLength(Result, Length(temparray));
1039 for i := 0 to High(temparray) do
1040 begin
1041 Result[i].FileNumber := temparray[i].id;
1042 Result[i].blubb := 0;
1043 end;
1044 end;
1045
1046
1047
1048
1049 function TOniDataADB.LoadDatFile(fileid: LongWord): Tdata;
1050 var
1051 mem: TStream;
1052 begin
1053 if fileid < Self.GetFilesCount then
1054 begin
1055 FQuery.SQL.Text := 'SELECT data FROM datfiles WHERE id=' + IntToStr(fileid) + ';';
1056 FQuery.Open;
1057 if FQuery.RecordCount > 0 then
1058 begin
1059 mem := FQuery.CreateBlobStream(FQuery.FieldByName('data'), bmRead);
1060 SetLength(Result, mem.Size);
1061 mem.Seek(0, soFromBeginning);
1062 mem.Read(Result[0], mem.Size);
1063 mem.Free;
1064 end;
1065 FQuery.Close;
1066 end;
1067 end;
1068
1069
1070
1071
1072 procedure TOniDataADB.UpdateDatFile(fileid: LongWord; Data: Tdata);
1073 var
1074 MimeCoder: TStringFormat_MIME64;
1075 mem: TMemoryStream;
1076 begin
1077 if fileid < Self.GetFilesCount then
1078 begin
1079 mimecoder := TStringFormat_MIME64.Create;
1080 mem := TMemoryStream.Create;
1081 mem.Write(Data[0], Length(Data));
1082 mem.Seek(0, soFromBeginning);
1083 FQuery.SQL.Text := 'UPDATE datfiles SET data=MimeToBin("' +
1084 MimeCoder.StrTo(mem.Memory, mem.Size) + '") WHERE id=' + IntToStr(fileid) + ';';
1085 FQuery.ExecSQL;
1086 mem.Free;
1087 mimecoder.Free;
1088 end;
1089 end;
1090
1091
1092
1093
1094 procedure TOniDataADB.LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer);
1095 var
1096 mem: TStream;
1097 begin
1098 if fileid < Self.GetFilesCount then
1099 begin
1100 FQuery.SQL.Text := 'SELECT data FROM datfiles WHERE id=' + IntToStr(fileid) + ';';
1101 FQuery.Open;
1102 if FQuery.RecordCount > 0 then
1103 begin
1104 mem := FQuery.CreateBlobStream(FQuery.FieldByName('data'), bmRead);
1105 mem.Seek(offset, soFromBeginning);
1106 mem.Read(target^, size);
1107 mem.Free;
1108 end;
1109 FQuery.Close;
1110 end;
1111 end;
1112
1113
1114
1115
1116 procedure TOniDataADB.UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer);
1117 var
1118 MimeCoder: TStringFormat_MIME64;
1119 mem: TMemoryStream;
1120 Data: Tdata;
1121 begin
1122 if fileid < Self.GetFilesCount then
1123 begin
1124 Data := Self.LoadDatFile(fileid);
1125 mimecoder := TStringFormat_MIME64.Create;
1126 mem := TMemoryStream.Create;
1127 mem.Write(Data[0], Length(Data));
1128 mem.Seek(offset, soFromBeginning);
1129 mem.Write(target^, size);
1130 mem.Seek(0, soFromBeginning);
1131 FQuery.SQL.Text := 'UPDATE datfiles SET data=MimeToBin("' +
1132 MimeCoder.StrTo(mem.Memory, mem.Size) + '") WHERE id=' + IntToStr(fileid) + ';';
1133 FQuery.ExecSQL;
1134 mem.Free;
1135 mimecoder.Free;
1136 end;
1137 end;
1138
1139
1140
1141
1142 function TOniDataADB.GetRawList(fileid: LongWord): TRawList;
1143 var
1144 i: LongWord;
1145 begin
1146 SetLength(Result, 0);
1147 FQuery.SQL.Text := 'SELECT [src_link_offset],[size],[sep] FROM rawmap WHERE [src_id]=' +
1148 IntToStr(fileid) + ' ORDER BY src_link_offset ASC;';
1149 FQuery.Open;
1150 if FQuery.RecordCount > 0 then
1151 begin
1152 FQuery.First;
1153 SetLength(Result, FQuery.RecordCount);
1154 i := 0;
1155 repeat
1156 Result[i].src_id := fileid;
1157 Result[i].src_offset := FQuery.FieldByName('src_link_offset').AsInteger;
1158 Result[i].raw_addr := 0;
1159 Result[i].raw_size := FQuery.FieldByName('size').AsInteger;
1160 Result[i].loc_sep := FQuery.FieldByName('sep').AsBoolean;
1161 Inc(i);
1162 FQuery.Next;
1163 until FQuery.EOF;
1164 end;
1165 FQuery.Close;
1166 end;
1167
1168
1169
1170
1171 procedure TOniDataADB.LoadRawFile(fileid, dat_offset: LongWord; target: Pointer);
1172 var
1173 mem: TStream;
1174 begin
1175 if fileid < Self.GetFilesCount then
1176 begin
1177 FQuery.SQL.Text := 'SELECT data FROM rawmap WHERE (src_id=' +
1178 IntToStr(fileid) + ') AND (src_link_offset=' + IntToStr(dat_offset) + ');';
1179 FQuery.Open;
1180 if FQuery.RecordCount > 0 then
1181 begin
1182 mem := FQuery.CreateBlobStream(FQuery.FieldByName('data'), bmRead);
1183 mem.Seek(0, soFromBeginning);
1184 mem.Read(target^, mem.size);
1185 mem.Free;
1186 end;
1187 FQuery.Close;
1188 end;
1189 end;
1190
1191
1192
1193
1194 procedure TOniDataADB.UpdateRawFile(fileid, dat_offset: LongWord;
1195 size: LongWord; target: Pointer);
1196 var
1197 MimeCoder: TStringFormat_MIME64;
1198 mem: TMemoryStream;
1199 begin
1200 if fileid < Self.GetFilesCount then
1201 begin
1202 mimecoder := TStringFormat_MIME64.Create;
1203 mem := TMemoryStream.Create;
1204 mem.Write(target^, size);
1205 mem.Seek(0, soFromBeginning);
1206 FQuery.SQL.Text := 'UPDATE rawmap SET data=MimeToBin("' + MimeCoder.StrTo(
1207 mem.Memory, mem.Size) + '") WHERE (src_id=' + IntToStr(fileid) +
1208 ') AND (src_link_offset=' + IntToStr(dat_offset) + ');';
1209 FQuery.ExecSQL;
1210 mem.Free;
1211 mimecoder.Free;
1212 end;
1213 end;
1214
1215
1216
1217
1218 procedure TOniDataADB.LoadRawFilePart(fileid, dat_offset: LongWord;
1219 offset, size: LongWord; target: Pointer);
1220 var
1221 Data: Tdata;
1222 mem: TMemoryStream;
1223 begin
1224 if fileid < Self.GetFilesCount then
1225 begin
1226 SetLength(Data, Self.GetRawInfo(fileid, dat_offset).raw_size);
1227 Self.LoadRawFile(fileid, dat_offset, @Data[0]);
1228 mem := TMemoryStream.Create;
1229 mem.Write(Data[offset], size);
1230 mem.Read(target^, size);
1231 mem.Free;
1232 end;
1233 end;
1234
1235
1236
1237
1238 procedure TOniDataADB.UpdateRawFilePart(fileid, dat_offset: LongWord;
1239 offset, size: LongWord; target: Pointer);
1240 var
1241 MimeCoder: TStringFormat_MIME64;
1242 mem: TMemoryStream;
1243 Data: Tdata;
1244 begin
1245 if fileid < Self.GetFilesCount then
1246 begin
1247 SetLength(Data, Self.GetRawInfo(fileid, offset).raw_size);
1248 Self.LoadRawFile(fileid, offset, @Data[0]);
1249 mimecoder := TStringFormat_MIME64.Create;
1250 mem := TMemoryStream.Create;
1251 mem.Write(Data[0], Length(Data));
1252 mem.Seek(offset, soFromBeginning);
1253 mem.Write(target^, size);
1254 mem.Seek(0, soFromBeginning);
1255 FQuery.SQL.Text := 'UPDATE rawmap SET data=MimeToBin("' + MimeCoder.StrTo(
1256 mem.Memory, mem.Size) + '") WHERE (src_id=' + IntToStr(fileid) +
1257 ') AND (src_link_offset=' + IntToStr(dat_offset) + ');';
1258 FQuery.ExecSQL;
1259 mem.Free;
1260 mimecoder.Free;
1261 end;
1262 end;
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274 function CreateDataConnection(filename: String; backend: Integer): Boolean;
1275 var
1276 answer: Boolean;
1277 begin
1278 if Assigned(OniDataConnection) then
1279 begin
1280 OniDataConnection.Close;
1281 OniDataConnection.Free;
1282 OniDataConnection := nil;
1283 end;
1284 case backend of
1285 ODB_Dat:
1286 OniDataConnection := TOniDataDat.Create(filename, answer);
1287 ODB_ADB:
1288 OniDataConnection := TOniDataADB.Create(filename, answer);
1289 else
1290 ShowMessage('Unknown Backend');
1291 Result := False;
1292 Exit;
1293 end;
1294
1295 if answer then
1296 begin
1297 // ShowMessage('file loaded');
1298 // ShowMessage('Files: '+IntToStr(OniDataConnection.GetFilesCount));
1299 Result := True;
1300 end
1301 else
1302 begin
1303 ShowMessage('File not loaded');
1304 OniDataConnection.Close;
1305 OniDataConnection.Free;
1306 Result := False;
1307 end;
1308 end;
1309
1310
1311
1312
1313 procedure CloseDataConnection;
1314 begin
1315 if Assigned(OniDataConnection) then
1316 begin
1317 OniDataConnection.Close;
1318 OniDataConnection := nil;
1319 end;
1320 end;
1321
1322 end.