source: oup/current/Code/OniDataClass.pas@ 47

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