├── README.md
├── mylib.pas
├── AGS.Font.pas
├── AGSTool.res
├── AGS.Clib32.pas
├── AGS.Sprite.pas
├── AGSTool_Icon.ico
├── BinaryStream.pas
├── AGS.Translation.pas
├── AGSTool.stat
├── AGSTool.identcache
├── AGSTool.dpr
├── Room.pas
├── Room.dfm
├── AGSTool.dproj.local
├── Main.dfm
├── AGS.Room.pas
├── AGS.Characters.pas
├── AGS.Script.pas
├── Main.pas
├── AGSTool.dproj
├── AGS.GameDta.pas
└── AGS.GameDtaMod.pas
/README.md:
--------------------------------------------------------------------------------
1 | "# AGS-Tool"
2 |
--------------------------------------------------------------------------------
/mylib.pas:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SileNTViP/AGS-Tool/HEAD/mylib.pas
--------------------------------------------------------------------------------
/AGS.Font.pas:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SileNTViP/AGS-Tool/HEAD/AGS.Font.pas
--------------------------------------------------------------------------------
/AGSTool.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SileNTViP/AGS-Tool/HEAD/AGSTool.res
--------------------------------------------------------------------------------
/AGS.Clib32.pas:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SileNTViP/AGS-Tool/HEAD/AGS.Clib32.pas
--------------------------------------------------------------------------------
/AGS.Sprite.pas:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SileNTViP/AGS-Tool/HEAD/AGS.Sprite.pas
--------------------------------------------------------------------------------
/AGSTool_Icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SileNTViP/AGS-Tool/HEAD/AGSTool_Icon.ico
--------------------------------------------------------------------------------
/BinaryStream.pas:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SileNTViP/AGS-Tool/HEAD/BinaryStream.pas
--------------------------------------------------------------------------------
/AGS.Translation.pas:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SileNTViP/AGS-Tool/HEAD/AGS.Translation.pas
--------------------------------------------------------------------------------
/AGSTool.stat:
--------------------------------------------------------------------------------
1 | [Stats]
2 | EditorSecs=4531
3 | DesignerSecs=152
4 | InspectorSecs=23
5 | CompileSecs=44153
6 | OtherSecs=187
7 | StartTime=09.07.2016 16:34:21
8 | RealKeys=0
9 | EffectiveKeys=0
10 | DebugSecs=8062
11 |
--------------------------------------------------------------------------------
/AGSTool.identcache:
--------------------------------------------------------------------------------
1 | MC:\Users\SileNTViP\Documents\Embarcadero\Studio\Projects\AGS Tool\AGSTool.dpr JC:\Users\SileNTViP\Documents\Embarcadero\Studio\Projects\AGS Tool\Room.pas JC:\Users\SileNTViP\Documents\Embarcadero\Studio\Projects\AGS Tool\Main.pas
--------------------------------------------------------------------------------
/AGSTool.dpr:
--------------------------------------------------------------------------------
1 | program AGSTool;
2 |
3 | uses
4 | Vcl.Forms,
5 | Main in 'Main.pas' {MainForm},
6 | Room in 'Room.pas' {RoomForm};
7 |
8 | {$R *.res}
9 |
10 | begin
11 | Application.Initialize;
12 | Application.MainFormOnTaskbar := True;
13 | Application.CreateForm(TMainForm, MainForm);
14 | Application.CreateForm(TRoomForm, RoomForm);
15 | Application.Run;
16 | end.
17 |
--------------------------------------------------------------------------------
/Room.pas:
--------------------------------------------------------------------------------
1 | unit Room;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
7 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, AGS.Room;
8 |
9 | type
10 | TRoomForm = class(TForm)
11 | Backcb: TComboBox;
12 | Label1: TLabel;
13 | BackImg: TImage;
14 | ORbtn: TButton;
15 | ScrollBar1: TScrollBar;
16 | odCRM: TOpenDialog;
17 | procedure ORbtnClick(Sender: TObject);
18 | private
19 | { Private declarations }
20 | public
21 | { Public declarations }
22 | end;
23 |
24 | var
25 | RoomForm: TRoomForm;
26 | ERoom: TRoom;
27 |
28 | implementation
29 |
30 | {$R *.dfm}
31 |
32 | procedure TRoomForm.ORbtnClick(Sender: TObject);
33 | begin
34 | if odCRM.Execute then
35 | begin
36 | ERoom := TRoom.Create(odCRM.FileName);
37 | ERoom.Free;
38 | end;
39 | end;
40 |
41 | end.
42 |
--------------------------------------------------------------------------------
/Room.dfm:
--------------------------------------------------------------------------------
1 | object RoomForm: TRoomForm
2 | Left = 0
3 | Top = 0
4 | BorderIcons = [biSystemMenu, biMinimize]
5 | BorderStyle = bsSingle
6 | Caption = #1050#1086#1084#1085#1072#1090#1099
7 | ClientHeight = 322
8 | ClientWidth = 571
9 | Color = clBtnFace
10 | Font.Charset = DEFAULT_CHARSET
11 | Font.Color = clWindowText
12 | Font.Height = -11
13 | Font.Name = 'Tahoma'
14 | Font.Style = []
15 | OldCreateOrder = False
16 | Position = poMainFormCenter
17 | PixelsPerInch = 96
18 | TextHeight = 13
19 | object Label1: TLabel
20 | Left = 8
21 | Top = 8
22 | Width = 72
23 | Height = 13
24 | Caption = #1058#1077#1082#1091#1097#1080#1081' '#1092#1086#1085':'
25 | end
26 | object BackImg: TImage
27 | Left = 8
28 | Top = 51
29 | Width = 555
30 | Height = 240
31 | AutoSize = True
32 | Enabled = False
33 | end
34 | object Backcb: TComboBox
35 | Left = 8
36 | Top = 24
37 | Width = 145
38 | Height = 21
39 | Enabled = False
40 | TabOrder = 0
41 | end
42 | object ORbtn: TButton
43 | Left = 168
44 | Top = 20
45 | Width = 75
46 | Height = 25
47 | Caption = #1054#1090#1082#1088#1099#1090#1100'...'
48 | TabOrder = 1
49 | OnClick = ORbtnClick
50 | end
51 | object ScrollBar1: TScrollBar
52 | Left = 8
53 | Top = 297
54 | Width = 555
55 | Height = 17
56 | Enabled = False
57 | PageSize = 0
58 | TabOrder = 2
59 | end
60 | object odCRM: TOpenDialog
61 | DefaultExt = '*.crm'
62 | Filter = 'AGS Rooms|*.crm'
63 | Left = 472
64 | Top = 72
65 | end
66 | end
67 |
--------------------------------------------------------------------------------
/AGSTool.dproj.local:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1899.12.30 00:00:00.000.326,=C:\Users\SileNTViP\Documents\RAD Studio\Projects\AGS Tool\Untitled1.xml
5 | 1899.12.30 00:00:00.000.000,C:\Users\SileNTViP\Documents\RAD Studio\Projects\Unit1.dfm=C:\Users\SileNTViP\Documents\RAD Studio\Projects\AGS Tool\Main.dfm
6 | 1899.12.30 00:00:00.000.338,C:\Users\SileNTViP\Documents\RAD Studio\Projects\AGS Tool\Room.pas=C:\Users\SileNTViP\Documents\RAD Studio\Projects\AGS Tool\Unit1.pas
7 | 1899.12.30 00:00:00.000.832,=C:\Users\SileNTViP\Documents\RAD Studio\Projects\Unit1.pas
8 | 1899.12.30 00:00:00.000.000,C:\Users\SileNTViP\Documents\RAD Studio\Projects\Unit1.pas=C:\Users\SileNTViP\Documents\RAD Studio\Projects\AGS Tool\Main.pas
9 | 1899.12.30 00:00:00.000.081,=C:\Users\SileNTViP\Documents\RAD Studio\Projects\AGS Tool\Unit1.pas
10 | 1899.12.30 00:00:00.000.812,=C:\Users\SileNTViP\Documents\RAD Studio\Projects\AGS Tool\Unit1.pas
11 | 1899.12.30 00:00:00.000.253,C:\Users\SileNTViP\Documents\RAD Studio\Projects\MyLibs\AGC.Sprite.pas=C:\Users\SileNTViP\Documents\RAD Studio\Projects\AGS Tool\Unit1.pas
12 | 1899.12.30 00:00:00.000.998,C:\Users\SileNTViP\Documents\RAD Studio\Projects\Project2.dproj=C:\Users\SileNTViP\Documents\RAD Studio\Projects\AGS Tool\AGSTool.dproj
13 | 1899.12.30 00:00:00.000.338,C:\Users\SileNTViP\Documents\RAD Studio\Projects\AGS Tool\Room.dfm=C:\Users\SileNTViP\Documents\RAD Studio\Projects\AGS Tool\Unit1.dfm
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Main.dfm:
--------------------------------------------------------------------------------
1 | object MainForm: TMainForm
2 | Left = 0
3 | Top = 0
4 | BorderIcons = [biSystemMenu]
5 | BorderStyle = bsSingle
6 | Caption = 'AGS Tool'
7 | ClientHeight = 394
8 | ClientWidth = 313
9 | Color = clBtnFace
10 | Font.Charset = DEFAULT_CHARSET
11 | Font.Color = clWindowText
12 | Font.Height = -11
13 | Font.Name = 'Tahoma'
14 | Font.Style = []
15 | OldCreateOrder = False
16 | Position = poScreenCenter
17 | OnClose = FormClose
18 | OnCreate = FormCreate
19 | PixelsPerInch = 96
20 | TextHeight = 13
21 | object Label1: TLabel
22 | Left = 167
23 | Top = 133
24 | Width = 115
25 | Height = 13
26 | Caption = 'Version 1.8 by SileNTViP'
27 | end
28 | object GroupBox1: TGroupBox
29 | Left = 159
30 | Top = 8
31 | Width = 145
32 | Height = 87
33 | Caption = 'For Notabenoid'
34 | TabOrder = 2
35 | object ImportTXT: TButton
36 | Left = 8
37 | Top = 51
38 | Width = 128
39 | Height = 25
40 | Caption = 'Create TRS from Inbox'
41 | TabOrder = 0
42 | OnClick = ImportTXTClick
43 | end
44 | object SaveTXT: TButton
45 | Left = 8
46 | Top = 20
47 | Width = 128
48 | Height = 25
49 | Caption = 'Extract TXT from TRS'
50 | TabOrder = 1
51 | OnClick = SaveTXTClick
52 | end
53 | end
54 | object GroupBox2: TGroupBox
55 | Left = 159
56 | Top = 152
57 | Width = 145
58 | Height = 121
59 | Caption = 'Work with game files'
60 | TabOrder = 3
61 | object ExtrLIB: TButton
62 | Left = 8
63 | Top = 16
64 | Width = 128
65 | Height = 25
66 | Caption = 'Extract from game lib'
67 | TabOrder = 0
68 | OnClick = ExtrLIBClick
69 | end
70 | object ExtrEXE: TButton
71 | Left = 8
72 | Top = 47
73 | Width = 128
74 | Height = 25
75 | Caption = 'Extract from EXE'
76 | TabOrder = 1
77 | OnClick = ExtrEXEClick
78 | end
79 | object MakeEXE: TButton
80 | Left = 8
81 | Top = 78
82 | Width = 128
83 | Height = 25
84 | Caption = 'Build EXE'
85 | TabOrder = 2
86 | Visible = False
87 | OnClick = MakeEXEClick
88 | end
89 | end
90 | object Button1: TButton
91 | Left = 167
92 | Top = 399
93 | Width = 19
94 | Height = 22
95 | Caption = 'Button1'
96 | TabOrder = 1
97 | Visible = False
98 | OnClick = Button1Click
99 | end
100 | object GroupBox3: TGroupBox
101 | Left = 8
102 | Top = 8
103 | Width = 145
104 | Height = 119
105 | Caption = 'Create TRS from game'
106 | TabOrder = 0
107 | object ExtractEXE: TButton
108 | Left = 7
109 | Top = 20
110 | Width = 129
111 | Height = 25
112 | Caption = 'Create TXT from game'
113 | TabOrder = 0
114 | OnClick = ExtractEXEClick
115 | end
116 | object CreateTXT2TRS: TButton
117 | Left = 8
118 | Top = 82
119 | Width = 128
120 | Height = 25
121 | Caption = 'Create TRS from TXT'
122 | TabOrder = 1
123 | OnClick = CreateTXT2TRSClick
124 | end
125 | object CreateFromDTA: TButton
126 | Left = 8
127 | Top = 51
128 | Width = 128
129 | Height = 25
130 | Caption = 'TXT from DTA&&CRM'
131 | TabOrder = 2
132 | OnClick = CreateFromDTAClick
133 | end
134 | end
135 | object GroupBox4: TGroupBox
136 | Left = 8
137 | Top = 133
138 | Width = 145
139 | Height = 142
140 | Caption = 'Work with translations'
141 | TabOrder = 4
142 | object DecompileTRA: TButton
143 | Left = 8
144 | Top = 17
145 | Width = 128
146 | Height = 25
147 | Caption = 'Decompile TRA'
148 | TabOrder = 0
149 | OnClick = DecompileTRAClick
150 | end
151 | object CompileTRS: TButton
152 | Left = 8
153 | Top = 48
154 | Width = 128
155 | Height = 25
156 | Caption = 'Compile TRS'
157 | TabOrder = 1
158 | OnClick = CompileTRSClick
159 | end
160 | object TRSAdder: TButton
161 | Left = 8
162 | Top = 79
163 | Width = 128
164 | Height = 25
165 | Caption = 'TRS Adder diff'
166 | TabOrder = 2
167 | OnClick = TRSAdderClick
168 | end
169 | object CreateFrom2TXT: TButton
170 | Left = 8
171 | Top = 110
172 | Width = 128
173 | Height = 25
174 | Caption = 'Create TRS from 2'#1093' TXT'
175 | TabOrder = 3
176 | OnClick = CreateFrom2TXTClick
177 | end
178 | end
179 | object GroupBox5: TGroupBox
180 | Left = 8
181 | Top = 279
182 | Width = 295
183 | Height = 50
184 | Caption = 'WFN fonts'
185 | TabOrder = 5
186 | object wfn2bdf: TButton
187 | Left = 8
188 | Top = 16
189 | Width = 128
190 | Height = 25
191 | Caption = 'WFN to BDF'
192 | TabOrder = 0
193 | OnClick = wfn2bdfClick
194 | end
195 | object bdf2wfn: TButton
196 | Left = 159
197 | Top = 16
198 | Width = 128
199 | Height = 25
200 | Caption = 'BDF to ext. WFN'
201 | TabOrder = 1
202 | OnClick = bdf2wfnClick
203 | end
204 | end
205 | object GroupBox6: TGroupBox
206 | Left = 8
207 | Top = 335
208 | Width = 295
209 | Height = 50
210 | Caption = 'Sprites'
211 | TabOrder = 6
212 | object ExtrSpr: TButton
213 | Left = 8
214 | Top = 14
215 | Width = 128
216 | Height = 25
217 | Caption = 'Decompile sprites'
218 | TabOrder = 0
219 | OnClick = ExtrSprClick
220 | end
221 | object GenSpr: TButton
222 | Left = 159
223 | Top = 16
224 | Width = 128
225 | Height = 25
226 | Caption = 'Compile sprites'
227 | TabOrder = 1
228 | OnClick = GenSprClick
229 | end
230 | end
231 | object RoomBtn: TButton
232 | Left = 177
233 | Top = 427
234 | Width = 128
235 | Height = 25
236 | Caption = #1050#1086#1084#1085#1072#1090#1099
237 | Enabled = False
238 | TabOrder = 7
239 | OnClick = RoomBtnClick
240 | end
241 | object btn1: TButton
242 | Left = 15
243 | Top = 427
244 | Width = 75
245 | Height = 25
246 | Caption = 'btn1'
247 | Enabled = False
248 | TabOrder = 8
249 | OnClick = btn1Click
250 | end
251 | object btn2: TButton
252 | Left = 96
253 | Top = 427
254 | Width = 75
255 | Height = 25
256 | Caption = 'btn2'
257 | Enabled = False
258 | TabOrder = 9
259 | OnClick = btn2Click
260 | end
261 | object chkTRAV2: TCheckBox
262 | Left = 167
263 | Top = 101
264 | Width = 115
265 | Height = 17
266 | Caption = 'Compile TRA for V2'
267 | TabOrder = 10
268 | end
269 | object odGame: TOpenDialog
270 | DefaultExt = '*.exe;ac2game.dat'
271 | Filter = 'AGS Game|*.exe;ac2game.dat'
272 | Left = 264
273 | Top = 200
274 | end
275 | object odTRS: TOpenDialog
276 | DefaultExt = '*.trs'
277 | Filter = 'Translation TRS|*.trs'
278 | Left = 72
279 | Top = 144
280 | end
281 | object odTRA: TOpenDialog
282 | DefaultExt = '*.tra'
283 | Filter = 'Translation TRA|*.tra'
284 | Left = 72
285 | Top = 192
286 | end
287 | object sdTRS: TSaveDialog
288 | DefaultExt = '*.trs'
289 | Filter = 'AGS Translation TRS|*.trs'
290 | Left = 112
291 | Top = 144
292 | end
293 | object odLIB: TOpenDialog
294 | DefaultExt = '*.vox;ac2game.dat'
295 | Filter = 'All Supported Files|*.vox;ac2game.dat'
296 | Left = 264
297 | Top = 160
298 | end
299 | object odTXT: TOpenDialog
300 | DefaultExt = '*.txt'
301 | Filter = 'Translation Text|*.txt'
302 | Left = 120
303 | end
304 | object odWFN: TOpenDialog
305 | DefaultExt = '*.wfn'
306 | Filter = 'AGS WFN Fonts|agsfnt*.wfn'
307 | Left = 136
308 | Top = 288
309 | end
310 | object odBDF: TOpenDialog
311 | DefaultExt = '*.bdf'
312 | Filter = 'Bitmap Font File|*.bdf'
313 | Left = 264
314 | Top = 288
315 | end
316 | object sdEXE: TSaveDialog
317 | DefaultExt = '*.exe'
318 | Filter = 'AGS Game Executable|*.exe'
319 | Left = 264
320 | Top = 240
321 | end
322 | object odSPR: TOpenDialog
323 | DefaultExt = 'acsprset.spr'
324 | Filter = 'AGS Sprites|acsprset.spr'
325 | Left = 136
326 | Top = 336
327 | end
328 | object sdSPR: TSaveDialog
329 | DefaultExt = 'acsprset.spr'
330 | FileName = 'acsprset.spr'
331 | Filter = 'AGS Sprites|acsprset.spr'
332 | Left = 264
333 | Top = 344
334 | end
335 | object odDTACRM: TOpenDialog
336 | DefaultExt = '*.crm;*.dta'
337 | Filter = 'Game Main File & Rooms|*.crm;*.dta'
338 | Title = 'Choose Main Game File DTA or Room file CRM'
339 | Left = 119
340 | Top = 48
341 | end
342 | object sdDTACRM: TSaveDialog
343 | DefaultExt = '*.txt'
344 | Filter = 'Text Files|*.txt'
345 | Title = 'Save Extracted text to file'
346 | Left = 63
347 | Top = 48
348 | end
349 | end
350 |
--------------------------------------------------------------------------------
/AGS.Room.pas:
--------------------------------------------------------------------------------
1 | unit AGS.Room;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, System.Variants, System.Classes, System.SysUtils, System.Types, AGS.Script;
7 |
8 | const
9 | MAX_BSCENE = 5;
10 |
11 | type
12 | PolyPoints = record
13 | x, y: array [0..29] of Integer;
14 | numpoints: Integer;
15 | end;
16 | TRoom = class(TObject)
17 | private
18 | roomstr, objectnames, objectscriptnames, hotspotnames: array of AnsiString;
19 | numstr, fileVer: Integer;
20 | numobj, numhotspots, numwalkareas: Integer;
21 | num_bscenes, bscene_anim_speed: Int8;
22 | numsprs: Short;
23 | room: TFileStream;
24 | ebpalShared: array [0..MAX_BSCENE] of AnsiChar;
25 | function fgeti(FS: TFileStream): Integer;
26 | function fgetw(FS: TFileStream): Word;
27 | function fgetb(FS: TFileStream): Byte;
28 | function freadstring(FS: TFileStream): AnsiString;
29 | procedure ReadFromStream(FS: TFileStream);
30 | procedure ReadFromFile(FileName: AnsiString);
31 | procedure load_main_block(FS: TFileStream);
32 | procedure AddExtrString(Str: AnsiString);
33 | function GetTempDirectory: AnsiString;
34 | procedure CustomProperties(FS: TFileStream);
35 | function fgetstring_limit(FS: TFileStream; BufSize: Integer): AnsiString;
36 | public
37 | constructor Create; overload;
38 | constructor Create(FileName: AnsiString); overload;
39 | constructor Create(FS: TFileStream); overload;
40 | function GetExtractedStringsCount: Integer;
41 | function GetExtractedString(Index: Integer): AnsiString;
42 | procedure ExtractStrings;
43 | end;
44 |
45 | const
46 | // Room versions
47 | kRoomVersion_Undefined = 0;
48 | kRoomVersion_pre114_3 = 3; // exact version unknown
49 | kRoomVersion_pre114_4 = 4; // exact version unknown
50 | kRoomVersion_pre114_5 = 5; // exact version unknown
51 | kRoomVersion_pre114_6 = 6; // exact version unknown
52 | kRoomVersion_114 = 8;
53 | kRoomVersion_200_alpha = 9;
54 | kRoomVersion_200_alpha7 = 10;
55 | kRoomVersion_200_final = 11;
56 | kRoomVersion_208 = 12;
57 | kRoomVersion_214 = 13;
58 | kRoomVersion_240 = 14;
59 | kRoomVersion_241 = 15;
60 | kRoomVersion_250a = 16;
61 | kRoomVersion_250b = 17;
62 | kRoomVersion_251 = 18;
63 | kRoomVersion_253 = 19;
64 | kRoomVersion_255a = 20;
65 | kRoomVersion_255b = 21;
66 | kRoomVersion_261 = 22;
67 | kRoomVersion_262 = 23;
68 | kRoomVersion_270 = 24;
69 | kRoomVersion_272 = 25;
70 | kRoomVersion_300a = 26;
71 | kRoomVersion_300b = 27;
72 | kRoomVersion_303a = 28;
73 | kRoomVersion_303b = 29;
74 | kRoomVersion_334 = 30;
75 | kRoomVersion_Current = kRoomVersion_334;
76 |
77 | MAXOBJNAMELEN = 30;
78 | MAX_SCRIPT_NAME_LEN = 20;
79 | BLOCKTYPE_MAIN = 1;
80 | BLOCKTYPE_SCRIPT = 2;
81 | BLOCKTYPE_COMPSCRIPT = 3;
82 | BLOCKTYPE_COMPSCRIPT2 = 4;
83 | BLOCKTYPE_OBJECTNAMES = 5;
84 | BLOCKTYPE_ANIMBKGRND = 6;
85 | BLOCKTYPE_COMPSCRIPT3 = 7;
86 | BLOCKTYPE_PROPERTIES = 8;
87 | BLOCKTYPE_OBJECTSCRIPTNAMES = 9;
88 | BLOCKTYPE_EOF = $ff;
89 | MAX_CUSTOM_PROPERTY_VALUE_LENGTH = 500;
90 |
91 | implementation
92 |
93 | constructor TRoom.Create;
94 | begin
95 |
96 | end;
97 |
98 | constructor TRoom.Create(FileName: AnsiString);
99 | begin
100 | ReadFromFile(FileName);
101 | end;
102 |
103 | constructor TRoom.Create(FS: TFileStream);
104 | begin
105 | ReadFromStream(FS);
106 | end;
107 |
108 | function TRoom.fgeti(FS: TFileStream): Integer;
109 | begin
110 | FS.Read(Result, 4);
111 | end;
112 |
113 | function TRoom.fgetw(FS: TFileStream): Word;
114 | begin
115 | FS.Read(Result, 2);
116 | end;
117 |
118 | function TRoom.fgetb(FS: TFileStream): Byte;
119 | begin
120 | FS.Read(Result, 1);
121 | end;
122 |
123 | function TRoom.freadstring(FS: TFileStream): AnsiString;
124 | var
125 | buf: AnsiChar;
126 | i: Integer;
127 | begin
128 | Result := '';
129 | while True do
130 | begin
131 | FS.Read(buf, 1);
132 | if buf = #0 then
133 | Break
134 | else
135 | Result := Result + buf;
136 | end;
137 | end;
138 |
139 | function TRoom.GetExtractedString(Index: Integer): AnsiString;
140 | begin
141 | Result := roomstr[Index];
142 | end;
143 |
144 | function TRoom.GetExtractedStringsCount: Integer;
145 | begin
146 | Result := numstr;
147 | end;
148 |
149 | procedure TRoom.ExtractStrings;
150 | var
151 | i: Integer;
152 | begin
153 |
154 | end;
155 |
156 | procedure TRoom.load_main_block(FS: TFileStream);
157 | var
158 | i: Integer;
159 | buf: array of AnsiChar;
160 | begin
161 | if fileVer >= 12 then
162 | fgeti(FS);
163 | numobj := fgetw(FS);
164 | FS.Seek(numobj*2, soFromCurrent);
165 | numhotspots := fgeti(FS);
166 | FS.Seek(numhotspots*4, soFromCurrent);
167 | for i := 0 to numhotspots-1 do
168 | begin
169 | if fileVer >= 28 then
170 | AddExtrString(fgetstring_limit(FS, 2999))
171 | else
172 | begin
173 | SetLength(buf, 30);
174 | FS.Read(PAnsiChar(buf)^, 30);
175 | AddExtrString(AnsiString(buf));
176 | SetLength(buf, 0);
177 | end;
178 | end;
179 | if fileVer >= 24 then
180 | FS.Seek(MAX_SCRIPT_NAME_LEN*numhotspots, soFromCurrent);
181 | numwalkareas := fgetw(FS);
182 | FS.Seek(SizeOf(PolyPoints) * numwalkareas, soFromCurrent);
183 | FS.Seek(8, soFromCurrent);
184 | FS.Read(numsprs, 2);
185 | end;
186 |
187 | procedure TRoom.AddExtrString(Str: AnsiString);
188 | var
189 | Found: Boolean;
190 | i: Integer;
191 | newstr: AnsiString;
192 | begin
193 | Found := False;
194 | newstr := '';
195 | for i := 1 to Length(Str) do
196 | if Str[i] <> #0 then
197 | newstr := newstr + Str[i];
198 | if (newStr = '') or (newStr[1] = #0) then
199 | Exit;
200 | for i := 0 to numstr - 1 do
201 | begin
202 | if roomstr[i] = newStr then
203 | begin
204 | Found := True;
205 | Break;
206 | end;
207 | end;
208 | if not Found then
209 | begin
210 | inc(numstr);
211 | SetLength(roomstr, numstr);
212 | roomstr[numstr-1] := newStr;
213 | end;
214 | end;
215 |
216 | function TRoom.GetTempDirectory: AnsiString;
217 | var
218 | tempFolder: array[0..MAX_PATH] of AnsiChar;
219 | begin
220 | GetTempPathA(MAX_PATH, @tempFolder);
221 | Result := tempFolder;
222 | end;
223 |
224 | procedure TRoom.ReadFromStream(FS: TFileStream);
225 | var
226 | i, thisblock, bloklen, scrsize, fpos, ct: Integer;
227 | roomscr: TScript;
228 | tmpfile: TFileStream;
229 | buf: array of Byte;
230 | begin
231 | fileVer := fgetw(FS);
232 | if (fileVer < kRoomVersion_241) or (fileVer > kRoomVersion_Current) then
233 | Exit;
234 | thisblock := 0;
235 | while thisblock <> BLOCKTYPE_EOF do
236 | begin
237 | thisblock := fgetb(FS);
238 | if thisblock = BLOCKTYPE_EOF then
239 | Break;
240 | bloklen := fgeti(FS);
241 | inc(bloklen, FS.Position);
242 | if thisblock = BLOCKTYPE_MAIN then begin
243 | load_main_block(FS);
244 | end else if thisblock = BLOCKTYPE_SCRIPT then begin
245 | end else if thisblock = BLOCKTYPE_COMPSCRIPT3 then begin
246 | roomscr := TScript.Create(FS);
247 | roomscr.ExtractStrings3;
248 | for i := 0 to roomscr.GetExtractedStringsCount - 1 do
249 | AddExtrString(roomscr.GetExtractedString(i));
250 | roomscr.Free;
251 | end else if (thisblock = BLOCKTYPE_COMPSCRIPT) or (thisblock = BLOCKTYPE_COMPSCRIPT2) then begin
252 | end else if thisblock = BLOCKTYPE_OBJECTNAMES then begin
253 | numsprs := fgetb(FS);
254 | SetLength(objectnames, numsprs);
255 | for i := 0 to numsprs - 1 do
256 | begin
257 | SetLength(objectnames[i], MAXOBJNAMELEN);
258 | FS.Read(PAnsiChar(objectnames[i])^, MAXOBJNAMELEN);
259 | AddExtrString(objectnames[i]);
260 | end;
261 | end else if thisblock = BLOCKTYPE_OBJECTSCRIPTNAMES then begin
262 | numsprs := fgetb(FS);
263 | SetLength(objectscriptnames, numsprs);
264 | for i := 0 to numsprs - 1 do
265 | begin
266 | SetLength(objectscriptnames[i], MAX_SCRIPT_NAME_LEN);
267 | FS.Read(PAnsiChar(objectscriptnames[i])^, MAX_SCRIPT_NAME_LEN);
268 | end;
269 | end else if thisblock = BLOCKTYPE_ANIMBKGRND then begin
270 | num_bscenes := fgetb(FS);
271 | bscene_anim_speed := fgetb(FS);
272 | if fileVer >= kRoomVersion_255a then
273 | FS.Read(PAnsiChar(ebpalShared[0])^, num_bscenes);
274 | fpos := FS.Position;
275 | for ct := 1 to num_bscenes do
276 | begin
277 |
278 | end;
279 | end else if thisblock = BLOCKTYPE_PROPERTIES then begin
280 | i := FS.Position;
281 | if fgeti(FS) = 1 then
282 | begin
283 | CustomProperties(FS);
284 | for i := 0 to numhotspots - 1 do
285 | CustomProperties(FS);
286 | // for i := 0 to numsprs - 1 do
287 | // CustomProperties(FS);
288 | end;
289 | end else if thisblock = -1 then begin
290 | Exit;
291 | end else begin
292 | Exit;
293 | end;
294 | if FS.Position <> bloklen then
295 | FS.Seek(bloklen, soFromBeginning);
296 | end;
297 | end;
298 |
299 | procedure TRoom.CustomProperties(FS: TFileStream);
300 | var
301 | numProps, i: Integer;
302 | buf: AnsiString;
303 | begin
304 | if fgeti(FS) <> 1 then
305 | Exit;
306 | numProps := fgeti(FS);
307 | for i := 0 to numProps - 1 do
308 | begin
309 | buf := fgetstring_limit(FS, 200);
310 | buf := fgetstring_limit(FS, MAX_CUSTOM_PROPERTY_VALUE_LENGTH);
311 | AddExtrString(buf);
312 | end;
313 | end;
314 |
315 | function TRoom.fgetstring_limit(FS: TFileStream; BufSize: Integer): AnsiString;
316 | var
317 | buf: AnsiChar;
318 | curc: Integer;
319 | begin
320 | Result := ''; curc := 1;
321 | while True do
322 | begin
323 | if (FS.Position = FS.Size) or (curc = BufSize) then
324 | Break;
325 | FS.Read(buf, 1);
326 | inc(curc);
327 | if buf = #0 then
328 | Break
329 | else
330 | Result := Result + buf;
331 | end;
332 | end;
333 |
334 | procedure TRoom.ReadFromFile(FileName: AnsiString);
335 | begin
336 | Room := TFileStream.Create(FileName, fmOpenRead);
337 | ReadFromStream(Room);
338 | Room.Free;
339 | end;
340 |
341 | end.
--------------------------------------------------------------------------------
/AGS.Characters.pas:
--------------------------------------------------------------------------------
1 | unit AGS.Characters;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, System.Variants, System.Classes, System.SysUtils, System.Types,
7 | Vcl.Graphics;
8 |
9 | type
10 | TRGBQuadArray = packed array [0..MaxInt div SizeOf (TRGBQuad) - 1] of TRGBQuad;
11 | PRGBQuadArray = ^TRGBQuadArray;
12 | pRGBTripleArray = ^TRGBTripleArray;
13 | TRGBTripleArray = ARRAY[0..32767] OF TRGBTriple;
14 | TFrame = record
15 | ID: Integer;
16 | Image: Integer;
17 | Delay: Word;
18 | Flipped: Boolean;
19 | Sound: Integer;
20 | end;
21 | TView = record
22 | numLoops: Word;
23 | numFrames: array of Word;
24 | Frames: array [0..319] of TFrame;
25 | Bitmaps: array of array of TBitmap;
26 | end;
27 | TCharacter = record
28 | Version: Integer;
29 | Pallete: array [0..255] of DWORD;
30 | SpeechView: DWORD;
31 | StartingRoom: Integer;
32 | StartX: Integer;
33 | StartY: Integer;
34 | IdleView: DWORD;
35 | SpeechColor: Integer;
36 | ThinkingView: DWORD;
37 | BlinkingView: Word;
38 | MovementSpeed: Word;
39 | AnimationDelay: Word;
40 | RealName: array [0..39] of AnsiChar;
41 | ScriptName: array [0..19] of AnsiChar;
42 | end;
43 | TChaFile = class (TObject)
44 | ChaFileName: string;
45 | ChaStream: TFileStream;
46 | Character: TCharacter;
47 | pal: PLogPalette;
48 | ViewsOffset: Integer;
49 | SpeechView, IdleView, ThinkingView, BlinkingView: TView;
50 | private
51 | procedure ReadOldStyleView(var View: TView);
52 | procedure ReadOldStyleViewFrame(var Bit: TBitmap);
53 | public
54 | function GetFullName: string;
55 | constructor Create(FileName: string); overload;
56 | destructor Free;
57 | function GetLoops(ViewType: Integer): Integer;
58 | function ViewExist(ViewType: Integer): Boolean;
59 | function GetBitmap(Loop, Frame: Integer; ViewType: Integer): TBitmap;
60 | end;
61 |
62 | const
63 | CHARACTER_FILE_SIGNATURE = 'AGSCharacter';
64 | SPEECH_VIEW = 0;
65 | IDLE_VIEW = 1;
66 | THINKING_VIEW = 2;
67 | BLINKING_VIEW = 3;
68 |
69 | implementation
70 |
71 | function TChaFile.GetFullName: string;
72 | begin
73 | Result := Character.RealName;
74 | end;
75 |
76 | function TChaFile.GetLoops(ViewType: Integer): Integer;
77 | var
78 | CurView: TView;
79 | begin
80 | Result := 0;
81 | if ViewType = SPEECH_VIEW then
82 | if Character.SpeechView = 0 then
83 | Exit;
84 |
85 | if ViewType = IDLE_VIEW then
86 | if Character.IdleView = 0 then
87 | Exit;
88 |
89 | if ViewType = THINKING_VIEW then
90 | if Character.ThinkingView = 0 then
91 | Exit;
92 |
93 | if ViewType = BLINKING_VIEW then
94 | if Character.BlinkingView = 0 then
95 | Exit;
96 |
97 | case ViewType of
98 | SPEECH_VIEW:
99 | CurView := SpeechView;
100 | IDLE_VIEW:
101 | CurView := IdleView;
102 | THINKING_VIEW:
103 | CurView := ThinkingView;
104 | BLINKING_VIEW:
105 | CurView := BlinkingView;
106 | else
107 | Exit;
108 | end;
109 | Result := CurView.numLoops;
110 | end;
111 |
112 | function TChaFile.ViewExist(ViewType: Integer): Boolean;
113 | begin
114 | Result := False;
115 | case ViewType of
116 | SPEECH_VIEW:
117 | if (Character.SpeechView > 0) and (SpeechView.numLoops > 0) then
118 | Result := True;
119 | IDLE_VIEW:
120 | if (Character.IdleView > 0) and (IdleView.numLoops > 0) then
121 | Result := True;
122 | THINKING_VIEW:
123 | if (Character.ThinkingView > 0) and (ThinkingView.numLoops > 0) then
124 | Result := True;
125 | BLINKING_VIEW:
126 | if (Character.BlinkingView > 0) and (BlinkingView.numLoops > 0) then
127 | Result := True;
128 | else
129 | Result := False;
130 | end;
131 | end;
132 |
133 | function TChaFile.GetBitmap(Loop, Frame: Integer; ViewType: Integer): TBitmap;
134 | var
135 | CurView: TView;
136 | begin
137 | if ViewType = SPEECH_VIEW then
138 | if Character.SpeechView = 0 then
139 | Exit;
140 |
141 | if ViewType = IDLE_VIEW then
142 | if Character.IdleView = 0 then
143 | Exit;
144 |
145 | if ViewType = THINKING_VIEW then
146 | if Character.ThinkingView = 0 then
147 | Exit;
148 |
149 | if ViewType = BLINKING_VIEW then
150 | if Character.BlinkingView = 0 then
151 | Exit;
152 |
153 |
154 | case ViewType of
155 | SPEECH_VIEW:
156 | CurView := SpeechView;
157 | IDLE_VIEW:
158 | CurView := IdleView;
159 | THINKING_VIEW:
160 | CurView := ThinkingView;
161 | BLINKING_VIEW:
162 | CurView := BlinkingView;
163 | else
164 | Exit;
165 | end;
166 | Result := CurView.Bitmaps[Loop][Frame];
167 | end;
168 |
169 | procedure TChaFile.ReadOldStyleView(var View: TView);
170 | var
171 | i, j: Integer;
172 | begin
173 | ChaStream.Read(View.numLoops, 2);
174 | SetLength(View.numFrames, View.numLoops);
175 | for i := 0 to View.numLoops - 1 do
176 | ChaStream.Read(View.numFrames[i], 2);
177 | if View.numLoops < 16 then
178 | ChaStream.Seek((16 - View.numLoops) * 2, soFromCurrent);
179 | ChaStream.Seek(16 * 4 + 2, soFromCurrent);
180 | for i := 0 to 15 do
181 | for j := 0 to 19 do
182 | begin
183 | View.Frames[j].ID := j;
184 | ChaStream.Read(View.Frames[j].Image, 4);
185 | ChaStream.Seek(4, soFromCurrent);
186 | ChaStream.Read(View.Frames[j].Delay, 2);
187 | ChaStream.Seek(2, soFromCurrent);
188 | ChaStream.Read(View.Frames[j].Flipped, 4);
189 | ChaStream.Read(View.Frames[j].Sound, 4);
190 | ChaStream.Seek(8, soFromCurrent);
191 | end;
192 |
193 | SetLength(View.Bitmaps, View.numLoops);
194 | for i := 0 to View.numLoops - 1 do
195 | SetLength(View.Bitmaps[i], View.numFrames[i]);
196 |
197 | for i := 0 to View.numLoops - 1 do
198 | for j := 0 to View.numFrames[i] - 1 do
199 | begin
200 | ReadOldStyleViewFrame(View.Bitmaps[i][j]);
201 | // View.Bitmaps[i][j].SaveToFile(IntToStr(i) + '_' + IntToStr(j) + '.bmp');
202 | end;
203 | end;
204 |
205 | procedure TChaFile.ReadOldStyleViewFrame(var Bit: TBitmap);
206 | var
207 | i, j, colDepth, width, height: Integer;
208 | spriteFlags: Byte;
209 | g: TRGBQuad;
210 | Row8bit: pByteArray;
211 | Row16bit: pWordArray;
212 | Row24bit: PRGBTripleArray;
213 | Row32bit: PRGBQuadArray;
214 | TranspCol: TColor;
215 | begin
216 | ChaStream.Read(colDepth, 4);
217 | if colDepth = 200 then
218 | Exit;
219 | ChaStream.Read(spriteFlags, 1);
220 | ChaStream.Read(width, 4);
221 | ChaStream.Read(height, 4);
222 | Bit := TBitmap.Create;
223 | if colDepth = 8 then
224 | begin
225 | Bit.PixelFormat := pf8bit;
226 | Bit.Palette := CreatePalette(pal^);;
227 | end else if colDepth = 16 then begin
228 | Bit.PixelFormat := pf16bit;
229 | end else if colDepth = 24 then begin
230 | Bit.PixelFormat := pf24bit;
231 | end else if colDepth = 32 then begin
232 | Bit.PixelFormat := pf32bit;
233 | end;
234 | Bit.Width := width;
235 | Bit.Height := height;
236 | TranspCol := $00FF00FF;
237 | Bit.TransparentColor := TranspCol;
238 | Bit.Transparent := True;
239 | for i := 0 to height - 1 do
240 | begin
241 | if colDepth = 8 then
242 | Row8bit := bit.ScanLine[i]
243 | else if colDepth = 16 then
244 | Row16bit := bit.ScanLine[i]
245 | else if colDepth = 24 then
246 | Row24bit := bit.ScanLine[i]
247 | else if colDepth = 32 then
248 | Row32bit := bit.ScanLine[i];
249 |
250 | if colDepth = 8 then begin
251 | ChaStream.Read(Row8bit[0], width * 1);
252 | end else if colDepth = 16 then begin
253 | ChaStream.Read(Row16bit[0], width * 2);
254 | end else if colDepth = 24 then begin
255 | ChaStream.Read(Row24bit[0], width * 3);
256 | end else if colDepth = 32 then begin
257 | ChaStream.Read(Row32bit[0], width * 4);
258 | end;
259 | end;
260 |
261 | end;
262 |
263 | constructor TChaFile.Create(FileName: string);
264 | var
265 | fileSig: array [0..11] of AnsiChar;
266 | fileVersion: Integer;
267 | aa: Integer;
268 | pcol: TRGBQuad;
269 | begin
270 | ChaFileName := FileName;
271 | ChaStream := TFileStream.Create(FileName, fmOpenRead);
272 | ChaStream.Read(fileSig, 12);
273 | if fileSig <> CHARACTER_FILE_SIGNATURE then
274 | begin
275 | Exit;
276 | end;
277 | ChaStream.Read(Character.Version, 4);
278 | if (Character.Version < 5) or (Character.Version > 6) then
279 | begin
280 | Exit;
281 | end;
282 | GetMem(pal, sizeof(TLogPalette) + sizeof(TPaletteEntry) * 255);
283 | pal.palVersion := $300;
284 | pal.palNumEntries := 256;
285 | ChaStream.Read(Character.Pallete, 256 * 4);
286 | for aa := 0 to 255 do
287 | begin
288 | pcol := TRGBQuad(Character.Pallete[aa]);
289 | pal.palPalEntry[aa].peRed := pcol.rgbBlue * 4;
290 | pal.palPalEntry[aa].peGreen := pcol.rgbGreen * 4;
291 | pal.palPalEntry[aa].peBlue := pcol.rgbRed * 4;
292 | end;
293 | ChaStream.Seek(4, soFromCurrent);
294 | ChaStream.Read(Character.SpeechView, 4);
295 | ChaStream.Seek(4, soFromCurrent);
296 | ChaStream.Read(Character.StartingRoom, 4);
297 | ChaStream.Seek(4, soFromCurrent);
298 | ChaStream.Read(Character.StartX, 4);
299 | ChaStream.Read(Character.StartY, 4);
300 | ChaStream.Seek(12, soFromCurrent);
301 | ChaStream.Read(Character.IdleView, 4);
302 | ChaStream.Seek(12, soFromCurrent);
303 | ChaStream.Read(Character.SpeechColor, 4);
304 | ChaStream.Read(Character.ThinkingView, 4);
305 | ChaStream.Read(Character.BlinkingView, 2);
306 | ChaStream.Seek(42, soFromCurrent);
307 | ChaStream.Read(Character.MovementSpeed, 2);
308 | ChaStream.Read(Character.AnimationDelay, 2);
309 | ChaStream.Seek(606, soFromCurrent);
310 | ChaStream.Read(Character.RealName, 40);
311 | ChaStream.Read(Character.ScriptName, 20);
312 | ChaStream.Seek(2, soFromCurrent);
313 |
314 | if Character.SpeechView > 0 then
315 | ReadOldStyleView(SpeechView)
316 | else
317 | Character.SpeechView := 0;
318 |
319 | if Character.IdleView > 0 then
320 | ReadOldStyleView(IdleView)
321 | else
322 | Character.IdleView := 0;
323 |
324 | if (Character.ThinkingView > 0) and (Character.Version >= 6) then
325 | ReadOldStyleView(ThinkingView)
326 | else
327 | Character.ThinkingView := 0;
328 |
329 | if (Character.BlinkingView > 0) and (Character.Version >= 6) then
330 | ReadOldStyleView(BlinkingView)
331 | else
332 | Character.BlinkingView := 0;
333 | end;
334 |
335 | destructor TChaFile.Free;
336 | var
337 | i,j: Integer;
338 | begin
339 | ChaStream.Free;
340 |
341 | for i := 0 to SpeechView.numLoops - 1 do
342 | for j := 0 to SpeechView.numFrames[i] - 1 do
343 | SpeechView.Bitmaps[i][j].Free;
344 |
345 | for i := 0 to IdleView.numLoops - 1 do
346 | for j := 0 to IdleView.numFrames[i] - 1 do
347 | IdleView.Bitmaps[i][j].Free;
348 |
349 | for i := 0 to ThinkingView.numLoops - 1 do
350 | for j := 0 to ThinkingView.numFrames[i] - 1 do
351 | ThinkingView.Bitmaps[i][j].Free;
352 |
353 | for i := 0 to BlinkingView.numLoops - 1 do
354 | for j := 0 to BlinkingView.numFrames[i] - 1 do
355 | BlinkingView.Bitmaps[i][j].Free;
356 |
357 | SetLength(SpeechView.numFrames, 0);
358 | SetLength(SpeechView.Bitmaps, 0);
359 | SetLength(IdleView.numFrames, 0);
360 | SetLength(IdleView.Bitmaps, 0);
361 | SetLength(ThinkingView.numFrames, 0);
362 | SetLength(ThinkingView.Bitmaps, 0);
363 | SetLength(BlinkingView.numFrames, 0);
364 | SetLength(BlinkingView.Bitmaps, 0);
365 | end;
366 |
367 | end.
--------------------------------------------------------------------------------
/AGS.Script.pas:
--------------------------------------------------------------------------------
1 | unit AGS.Script;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, System.Variants, System.Classes, System.SysUtils, System.Types;
7 |
8 | type
9 | ccScript = record
10 | GlobalData: array of AnsiChar;
11 | GlobalDataSize: Integer;
12 | Code: array of Integer;
13 | CodeSize: Integer;
14 | Strings: array of AnsiChar;
15 | StringsSize: Integer;
16 | FixupTypes: array of AnsiChar;
17 | Fixups: array of Integer;
18 | NumFixups: Integer;
19 | Imports: array of AnsiString;
20 | NumImports: Integer;
21 | Exportss: array of AnsiString;
22 | Export_Addr: array of Integer;
23 | NumExports: Integer;
24 | SectionNames: array of AnsiString;
25 | SectionOffsets: array of Integer;
26 | NumSections: Integer;
27 | end;
28 | TScript = class(TObject)
29 | private
30 | Scr: TFileStream;
31 | scri: ccScript;
32 | scrstr, scrstr2: array of AnsiString;
33 | numstr, numstr2: Integer;
34 | function getw(FS: TfileStream): Integer;
35 | function freadstring(FS: TfileStream): AnsiString;
36 | function GetStrByOff(Offset: Integer): AnsiString;
37 | function IsAChar(Chr: AnsiChar): Boolean;
38 | procedure ReadFromStream(fs: TFileStream);
39 | procedure ReadFromFile(FileName: AnsiString);
40 | public
41 | constructor Create(FileName: AnsiString); overload;
42 | constructor Create(FS: TFileStream); overload;
43 | function GetExtractedStringsCount: Integer;
44 | function GetExtractedString(Index: Integer): AnsiString;
45 | function GetExtractedStringsCount2: Integer;
46 | function GetExtractedString2(Index: Integer): AnsiString;
47 | procedure ExtractStrings;
48 | procedure ExtractStrings2;
49 | procedure ExtractStrings3;
50 | procedure ExtractStrings4;
51 | procedure Dump(FileName: AnsiString);
52 | end;
53 |
54 | const
55 | scfilesig = 'SCOM';
56 | SCOM_VERSION = 90;
57 | ENDFILESIG = $beefcafe;
58 | sccmdnames: array [0..72] of AnsiString = ('NULL', '$add', '$sub', '$$mov', 'memwritelit', 'ret', '$mov',
59 | '$memread', '$memwrite', '$$mul', '$$div', '$$add', '$$sub', '$$bit_and', '$$bit_or',
60 | '$$cmp', '$$ncmp', '$$gt', '$$lt', '$$gte', '$$lte', '$$and', '$$or',
61 | '$call', '$memread.b', '$memread.w', '$memwrite.b', '$memwrite.w', 'jz',
62 | '$push', '$pop', 'jmp', '$mul', '$farcall', '$farpush', 'farsubsp', 'sourceline',
63 | '$callscr', 'thisaddr', 'setfuncargs', '$$mod', '$$xor', '$not',
64 | '$$shl', '$shr', '$callobj', '$checkbounds', '$memwrite.ptr',
65 | '$memread.ptr', 'memwrite.ptr.0', '$meminit.ptr', 'load.sp.offs',
66 | 'checknull.ptr', '$f.add', '$f.sub', '$$f.mul', '$$f.div', '$$f.add',
67 | '$$f.sub', '$$f.gt', '$$f.lt', '$$f.gte', '$$f.lte',
68 | 'zeromem', '$newstring', '$$strcmp', '$$strnotcmp', '$checknull',
69 | 'loopcheckoff', 'memwrite.ptr.0.nd', 'jnz', '$dynamicbounds', '$newarray');
70 | regnames: array[0..7] of AnsiString = ('null', 'sp', 'mar', 'ax', 'bx', 'cx', 'op', 'dx');
71 | sccmdargs: array [0..72] of Short = (0, 2, 2, 2, 2, 0, 2,
72 | 1, 1, 2, 2, 2, 2, 2, 2,
73 | 2, 2, 2, 2, 2, 2, 2, 2,
74 | 1, 1, 1, 1, 1, 1,
75 | 1, 1, 1, 2, 1, 1, 1, 1,
76 | 1, 1, 1, 2, 2, 1,
77 | 2, 2, 1, 2, 1,
78 | 1, 0, 1, 1,
79 | 0, 2, 2, 2, 2, 2,
80 | 2, 2, 2, 2, 2,
81 | 1, 1, 2, 2, 1,
82 | 0, 0, 1, 1, 3);
83 |
84 | implementation
85 |
86 | constructor TScript.Create(FileName: AnsiString);
87 | begin
88 | ReadFromFile(FileName);
89 | end;
90 |
91 | constructor TScript.Create(FS: TFileStream);
92 | begin
93 | ReadFromStream(FS);
94 | end;
95 |
96 | function TScript.getw(FS: TfileStream): Integer;
97 | begin
98 | FS.Read(Result, 4);
99 | end;
100 |
101 | function TScript.freadstring(FS: TfileStream): AnsiString;
102 | var
103 | buf: AnsiChar;
104 | i: Integer;
105 | begin
106 | Result := '';
107 | while True do
108 | begin
109 | FS.Read(buf, 1);
110 | if buf = #0 then
111 | Break
112 | else
113 | Result := Result + buf;
114 | end;
115 | end;
116 |
117 | function TScript.GetExtractedString(Index: Integer): AnsiString;
118 | begin
119 | Result := scrstr[Index];
120 | end;
121 |
122 | function TScript.GetExtractedStringsCount: Integer;
123 | begin
124 | Result := numstr;
125 | end;
126 |
127 | function TScript.GetExtractedString2(Index: Integer): AnsiString;
128 | begin
129 | Result := scrstr2[Index];
130 | end;
131 |
132 | function TScript.GetExtractedStringsCount2: Integer;
133 | begin
134 | Result := numstr2;
135 | end;
136 |
137 | procedure TScript.ExtractStrings;
138 | var
139 | i: Integer;
140 | begin
141 | numstr := 0;
142 | if scri.StringsSize > 0 then
143 | begin
144 | inc(numstr);
145 | SetLength(scrstr, numstr);
146 | for i := 0 to scri.StringsSize - 1 do
147 | begin
148 | if scri.Strings[i] <> #0 then
149 | scrstr[numstr-1] := scrstr[numstr-1] + scri.Strings[i]
150 | else begin
151 | inc(numstr);
152 | SetLength(scrstr, numstr);
153 | end;
154 | end;
155 | end;
156 | end;
157 |
158 | procedure TScript.ExtractStrings2;
159 | var
160 | i, l: Integer;
161 | begin
162 | i := 0;
163 | while i < scri.CodeSize - 1 do
164 | begin
165 | if scri.Code[i] = 6 then begin
166 | if scri.Code[i+2] <= scri.NumFixups then
167 | begin
168 | if scri.FixupTypes[scri.Code[i+2]] = #3 then
169 | begin
170 | inc(numstr);
171 | SetLength(scrstr, numstr);
172 | l := scri.Fixups[scri.Code[i+2]];
173 | while scri.Strings[l] <> #0 do
174 | begin
175 | if scri.Strings[l] <> #0 then
176 | scrstr[numstr-1] := scrstr[numstr-1] + scri.Strings[l];
177 | inc(l);
178 | end;
179 | end;
180 | inc(i, 2);
181 | end;
182 | end else
183 | for l := 0 to sccmdargs[scri.Code[i]] - 1 do
184 | begin
185 | inc(i);
186 | end;
187 | inc(i);
188 | end;
189 | end;
190 |
191 | function TScript.IsAChar(Chr: AnsiChar): Boolean;
192 | begin
193 | Result := False;
194 | if (Chr >= ' ') and (Chr <= '~') then
195 | Result := True;
196 | end;
197 |
198 | procedure TScript.ExtractStrings3;
199 | var
200 | i: Integer;
201 | sb: Boolean;
202 | begin
203 | numstr := 0;
204 | sb := False;
205 | if scri.StringsSize > 0 then
206 | begin
207 | inc(numstr);
208 | SetLength(scrstr, numstr);
209 | for i := 0 to scri.StringsSize - 1 do
210 | begin
211 | if scri.Strings[i] <> #0 then
212 | begin
213 | if IsAChar(scri.Strings[i]) then
214 | scrstr[numstr-1] := scrstr[numstr-1] + scri.Strings[i]
215 | end else begin
216 | inc(numstr);
217 | SetLength(scrstr, numstr);
218 | sb := False;
219 | end;
220 | end;
221 | end;
222 | end;
223 |
224 | procedure TScript.ExtractStrings4;
225 | var
226 | i: Integer;
227 | sb, ns: Boolean;
228 | begin
229 | numstr := 0;
230 | sb := False;
231 | ns := True;
232 | if scri.StringsSize > 0 then
233 | begin
234 | inc(numstr);
235 | SetLength(scrstr, numstr);
236 | inc(numstr2);
237 | SetLength(scrstr2, numstr2);
238 | for i := 0 to scri.StringsSize - 1 do
239 | begin
240 | if IsAChar(scri.Strings[i]) and ns then
241 | begin
242 | sb := True;
243 | ns := False;
244 | end;
245 | if sb then begin
246 | if (scri.Strings[i] <> #0) then
247 | begin
248 | scrstr[numstr-1] := scrstr[numstr-1] + scri.Strings[i]
249 | end else begin
250 | inc(numstr);
251 | SetLength(scrstr, numstr);
252 | sb := False;
253 | ns := True;
254 | end
255 | end else begin
256 | if (scri.Strings[i] <> #0) then
257 | begin
258 | scrstr2[numstr2-1] := scrstr2[numstr2-1] + scri.Strings[i]
259 | end else begin
260 | inc(numstr2);
261 | SetLength(scrstr2, numstr2);
262 | sb := False;
263 | ns := True;
264 | end;
265 | end;
266 | end;
267 | end;
268 | end;
269 |
270 | function TScript.GetStrByOff(Offset: Integer): AnsiString;
271 | var
272 | i: Integer;
273 | begin
274 | Result := '';
275 | if (Offset < 0) or (Offset > scri.StringsSize) then
276 | Exit;
277 | for i := Offset to scri.StringsSize - 1 do
278 | begin
279 | if scri.Strings[i] = #0 then
280 | Break;
281 | Result := Result + scri.Strings[i];
282 | end;
283 | end;
284 |
285 | procedure TScript.Dump(FileName: AnsiString);
286 | var
287 | dmp: TextFile;
288 | i, t, l, thisop, isreg, numc: Integer;
289 | buf, toprint: AnsiString;
290 | begin
291 | AssignFile(dmp, FileName);
292 | ReWrite(dmp);
293 | WriteLn(dmp, 'script data size: ' + IntToStr(scri.GlobalDataSize));
294 | WriteLn(dmp, 'string area size: ' + IntToStr(scri.StringsSize));
295 | WriteLn(dmp, 'code size: ' + IntToStr(scri.CodeSize));
296 | WriteLn(dmp, 'SCRIPT VIRTUAL-CODE FOLLOWS:');
297 | i := 0; numc := 0;
298 | while i < scri.CodeSize - 1 do
299 | begin
300 | isreg := 0;
301 | thisop := scri.Code[i];
302 | toprint := sccmdnames[thisop];
303 | inc(numc);
304 | if toprint[1] = '$' then
305 | begin
306 | isreg := 1;
307 | for t := 1 to Length(toprint)-1 do
308 | toprint[t] := toprint[t+1];
309 | toprint[t] := #0;
310 | end;
311 | if toprint[1] = '$' then
312 | begin
313 | isreg := isreg or 2;
314 | for t := 1 to Length(toprint)-1 do
315 | toprint[t] := toprint[t+1];
316 | toprint[t] := #0;
317 | end;
318 | if Length(toprint) > 6 then
319 | toprint := toprint + #9
320 | else
321 | toprint := toprint + #9 + #9;
322 | for l := 0 to sccmdargs[thisop] - 1 do
323 | begin
324 | inc(i);
325 | if (l = 0) and ((isreg and 1) = 1) then
326 | toprint := toprint + ' ' + regnames[scri.Code[i]]
327 | else if (l = 1) and ((isreg and 2) = 2) then
328 | toprint := toprint + ' ' + regnames[scri.Code[i]]
329 | else toprint := toprint + ' ' + IntToStr(scri.Code[i]);
330 | end;
331 | if sccmdnames[thisop] = '$mov' then
332 | toprint := toprint + ' ; "' + GetStrByOff(scri.Code[i]) + '"';
333 | WriteLn(dmp, IntToStr(numc) + ' ' + toprint);
334 | inc(i);
335 | end;
336 | CloseFile(dmp);
337 | end;
338 |
339 | procedure TScript.ReadFromStream(fs: TFileStream);
340 | var
341 | buf: array [0..4] of AnsiChar;
342 | fileVer, i: Integer;
343 | begin
344 | fs.Read(buf, 4);
345 | if buf <> scfilesig then
346 | begin
347 | Exit;
348 | end;
349 | fileVer := getw(fs);
350 | if fileVer > SCOM_VERSION then
351 | begin
352 | Exit;
353 | end;
354 | scri.GlobalDataSize := getw(fs);
355 | scri.CodeSize:= getw(fs);
356 | scri.StringsSize := getw(fs);
357 | if scri.GlobalDataSize > 0 then
358 | begin
359 | SetLength(scri.GlobalData, scri.GlobalDataSize);
360 | fs.Read(PAnsiChar(scri.GlobalData)^, scri.GlobalDataSize);
361 | end;
362 | if scri.CodeSize > 0 then
363 | begin
364 | SetLength(scri.Code, scri.CodeSize);
365 | fs.Read(PAnsiChar(scri.Code)^, scri.CodeSize*4);
366 | end;
367 | if scri.StringsSize > 0 then
368 | begin
369 | SetLength(scri.Strings, scri.StringsSize);
370 | fs.Read(PAnsiChar(scri.Strings)^, scri.StringsSize);
371 | end;
372 | scri.NumFixups := getw(fs);
373 | if scri.NumFixups > 0 then
374 | begin
375 | SetLength(scri.FixupTypes, scri.NumFixups);
376 | SetLength(scri.Fixups, scri.NumFixups);
377 | fs.Read(PAnsiChar(scri.FixupTypes)^, scri.NumFixups);
378 | fs.Read(PAnsiChar(scri.Fixups)^, scri.NumFixups*4);
379 | end;
380 | scri.NumImports := getw(fs);
381 | SetLength(scri.Imports, scri.NumImports);
382 | for i := 0 to scri.NumImports - 1 do
383 | scri.Imports[i] := freadstring(fs);
384 | scri.NumExports := getw(fs);
385 | SetLength(scri.Exportss, scri.NumExports);
386 | SetLength(scri.Export_Addr, scri.NumExports);
387 | for i := 0 to scri.NumExports - 1 do
388 | begin
389 | scri.Exportss[i] := freadstring(fs);
390 | scri.Export_Addr[i] := getw(fs);
391 | end;
392 | if fileVer >= 83 then
393 | begin
394 | scri.NumSections := getw(fs);
395 | SetLength(scri.SectionNames, scri.NumSections);
396 | SetLength(scri.SectionOffsets, scri.NumSections);
397 | for i := 0 to scri.NumSections - 1 do
398 | begin
399 | scri.SectionNames[i] := freadstring(fs);
400 | scri.SectionOffsets[i] := getw(fs);
401 | end;
402 | end;
403 | if uInt(getw(fs)) <> ENDFILESIG then
404 | begin
405 | Exit;
406 | end;
407 | // Dump('temp.dmp');
408 | end;
409 |
410 | procedure TScript.ReadFromFile(FileName: AnsiString);
411 | begin
412 | Scr := TFileStream.Create(FileName, fmOpenRead);
413 | ReadFromStream(Scr);
414 | Scr.Free;
415 | end;
416 |
417 | end.
--------------------------------------------------------------------------------
/Main.pas:
--------------------------------------------------------------------------------
1 | unit Main;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
7 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, AGS.Clib32, AGS.Translation, Xml.xmldom,
8 | Xml.XMLIntf, Xml.Win.msxmldom, Xml.XMLDoc, AGS.GameDta, AGS.Script, AGS.Room, AGS.Font, stdActns,
9 | AGS.Sprite, Room;
10 |
11 | type
12 | TMainForm = class(TForm)
13 | ExtractEXE: TButton;
14 | CompileTRS: TButton;
15 | DecompileTRA: TButton;
16 | odGame: TOpenDialog;
17 | odTRS: TOpenDialog;
18 | odTRA: TOpenDialog;
19 | Label1: TLabel;
20 | TRSAdder: TButton;
21 | SaveTXT: TButton;
22 | ImportTXT: TButton;
23 | sdTRS: TSaveDialog;
24 | GroupBox1: TGroupBox;
25 | GroupBox2: TGroupBox;
26 | ExtrLIB: TButton;
27 | odLIB: TOpenDialog;
28 | Button1: TButton;
29 | GroupBox3: TGroupBox;
30 | GroupBox4: TGroupBox;
31 | CreateTXT2TRS: TButton;
32 | odTXT: TOpenDialog;
33 | ExtrEXE: TButton;
34 | CreateFrom2TXT: TButton;
35 | GroupBox5: TGroupBox;
36 | wfn2bdf: TButton;
37 | odWFN: TOpenDialog;
38 | odBDF: TOpenDialog;
39 | bdf2wfn: TButton;
40 | MakeEXE: TButton;
41 | sdEXE: TSaveDialog;
42 | GroupBox6: TGroupBox;
43 | ExtrSpr: TButton;
44 | GenSpr: TButton;
45 | odSPR: TOpenDialog;
46 | sdSPR: TSaveDialog;
47 | RoomBtn: TButton;
48 | btn1: TButton;
49 | btn2: TButton;
50 | CreateFromDTA: TButton;
51 | odDTACRM: TOpenDialog;
52 | sdDTACRM: TSaveDialog;
53 | chkTRAV2: TCheckBox;
54 | procedure ExtractEXEClick(Sender: TObject);
55 | function ReadGameProj(FileName: string): Boolean;
56 | procedure WriteGameProj(FileName: string);
57 | procedure CompileTRSClick(Sender: TObject);
58 | procedure DecompileTRAClick(Sender: TObject);
59 | procedure TRSAdderClick(Sender: TObject);
60 | procedure SaveTXTClick(Sender: TObject);
61 | procedure ImportTXTClick(Sender: TObject);
62 | procedure ExtrLIBClick(Sender: TObject);
63 | procedure Button1Click(Sender: TObject);
64 | procedure CreateTXT2TRSClick(Sender: TObject);
65 | procedure ExtrEXEClick(Sender: TObject);
66 | procedure CreateFrom2TXTClick(Sender: TObject);
67 | procedure wfn2bdfClick(Sender: TObject);
68 | procedure bdf2wfnClick(Sender: TObject);
69 | procedure MakeEXEClick(Sender: TObject);
70 | procedure ExtrSprClick(Sender: TObject);
71 | procedure GenSprClick(Sender: TObject);
72 | procedure RoomBtnClick(Sender: TObject);
73 | procedure btn1Click(Sender: TObject);
74 | procedure btn2Click(Sender: TObject);
75 | procedure FormCreate(Sender: TObject);
76 | procedure FormClose(Sender: TObject; var Action: TCloseAction);
77 | procedure WriteLog(Text: String);
78 | procedure CreateFromDTAClick(Sender: TObject);
79 | private
80 | function GetTempDirectory: AnsiString;
81 | { Private declarations }
82 | public
83 | { Public declarations }
84 | end;
85 |
86 | var
87 | MainForm: TMainForm;
88 | RoomForm: TRoomForm;
89 | clib: TClib32;
90 | trans: TTranslation;
91 | dta: TGameDta;
92 | scr: TScript;
93 | room: TRoom;
94 | gamepath: AnsiString;
95 | GameName: AnsiString; GameID: uInt;
96 | log: TextFile;
97 |
98 | implementation
99 |
100 | {$R *.dfm}
101 |
102 | procedure TMainForm.GenSprClick(Sender: TObject);
103 | var
104 | sprd: TBrowseForFolder;
105 | spr: TSprite;
106 | newspr: AnsiString;
107 | begin
108 | if sdSPR.Execute then
109 | begin
110 | newspr := sdSPR.FileName;
111 | sprd := TBrowseForFolder.Create(nil);
112 | sprd.Folder := ExtractFilePath(newspr);
113 | if sprd.Execute then
114 | begin
115 | spr := TSprite.Create;
116 | spr.GenerateSpriteFromDir(sprd.Folder, newspr);
117 | spr.Free;
118 | Application.MessageBox('Buildig sprite library done!', 'Info', MB_OK);
119 | end;
120 | sprd.Free;
121 | end;
122 | end;
123 |
124 | function TMainForm.GetTempDirectory: AnsiString;
125 | var
126 | tempFolder: array[0..MAX_PATH] of AnsiChar;
127 | begin
128 | GetTempPathA(MAX_PATH, @tempFolder);
129 | Result := tempFolder;
130 | end;
131 |
132 | procedure TMainForm.ImportTXTClick(Sender: TObject);
133 | var
134 | newf: AnsiString;
135 | begin
136 | if sdTRS.Execute then
137 | begin
138 | gamepath := ExtractFilePath(sdTRS.FileName);
139 | trans := TTranslation.Create;
140 | trans.ImportTextFromDir(gamepath);
141 | trans.WriteToDecompiled(sdTRS.FileName);
142 | trans.Free;
143 | Application.MessageBox('Creating TRS from Inbox done!', 'Info', MB_OK);
144 | end;
145 | end;
146 |
147 | procedure TMainForm.MakeEXEClick(Sender: TObject);
148 | var
149 | exed: TBrowseForFolder;
150 | execli: TClib32;
151 | sRec: TSearchRec;
152 | isFound: Integer;
153 | begin
154 | if sdEXE.Execute then
155 | begin
156 | gamepath := ExtractFilePath(sdEXE.FileName);
157 | exed := TBrowseForFolder.Create(nil);
158 | exed.Folder := gamepath;
159 | if exed.Execute then
160 | begin
161 | execli := TClib32.Create;
162 | execli.WriteToFile(sdEXE.FileName);
163 | execli.WriteGameEngine(exed.Folder + '\acwin.exe');
164 | isFound := FindFirst(exed.Folder + '\*.*', faAnyFile, sRec);
165 | while isFound = 0 do
166 | begin
167 | if (sRec.Name <> '.') and (sRec.Name <> '..') and (LowerCase(sRec.Name) <> 'acwin.exe') then
168 | execli.AddFile(exed.Folder + '\' + sRec.Name);
169 | isFound := FindNext(sRec);
170 | end;
171 | execli.WriteFiles;
172 | execli.Close;
173 | execli.Free;
174 | Application.MessageBox('Bulding EXE done!', 'Info', MB_OK);
175 | end;
176 | exed.Free;
177 | end;
178 | end;
179 |
180 | procedure TMainForm.ExtractEXEClick(Sender: TObject);
181 | var
182 | i, m, strcnt, fullstrcount: Integer;
183 | begin
184 | if odGame.Execute then
185 | begin
186 | fullstrcount := 0;
187 | WriteLog('Begin extracting from game library.');
188 | WriteLog('Try to open "' + ExtractFileName(odGame.FileName) + '" library.');
189 | clib := TClib32.Create(odGame.FileName);
190 | WriteLog('Found ' + IntToStr(clib.GetNumFiles) + ' files in library.');
191 | gamepath := ExtractFilePath(odGame.FileName);
192 |
193 | // DeleteFile(gamepath + 'Extracted.txt');
194 | trans := TTranslation.Create;
195 | WriteLog('Search file: ac2game.dta or game28.dta');
196 | if clib.OpenFile('ac2game.dta') then
197 | begin
198 | WriteLog('Try to open file: ac2game.dta');
199 | dta := TGameDta.Create(clib.GetFileStream);
200 | if dta.GetDtaErr = DTA_ERROR_INC_VER then
201 | begin
202 | Application.MessageBox('Unsupported DTA version!', 'Error', MB_OK);
203 | WriteLog('Unsupported DTA ' + dta.GetDtaVersionString + ' version!');
204 | dta.Free;
205 | clib.Close;
206 | Exit;
207 | end;
208 | WriteLog('Game engine version: ' + dta.GetDtaVersionString);
209 | GameName := dta.GetGameName;
210 | WriteLog('Found game name: ' + GameName);
211 | GameID := dta.GetGameID;
212 | WriteLog('Found game id: ' + IntToStr(GameID));
213 | strcnt := dta.GetExtractedStringsCount;
214 | Inc(fullstrcount, strcnt);
215 | for i := 0 to strcnt - 1 do
216 | trans.Add(dta.GetExtractedString(i), dta.GetExtractedString(i));
217 | dta.Free;
218 | WriteLog('Extracting done. Found strings: ' + IntToStr(strcnt));
219 | clib.Close;
220 | end else if clib.OpenFile('game28.dta') then
221 | begin
222 | WriteLog('Try to open file: game28.dta');
223 | dta := TGameDta.Create(clib.GetFileStream);
224 | if dta.GetDtaErr = DTA_ERROR_INC_VER then
225 | begin
226 | Application.MessageBox('Unsupported DTA version!', 'Error', MB_OK);
227 | dta.Free;
228 | clib.Close;
229 | WriteLog('Unsupported DTA ' + dta.GetDtaVersionString + ' version!');
230 | Exit;
231 | end;
232 | WriteLog('Game engine version: ' + dta.GetDtaVersionString);
233 | GameName := dta.GetGameName;
234 | WriteLog('Found game name: ' + GameName);
235 | GameID := dta.GetGameID;
236 | WriteLog('Found game id: ' + IntToStr(GameID));
237 | strcnt := dta.GetExtractedStringsCount;
238 | Inc(fullstrcount, strcnt);
239 | for i := 0 to strcnt - 1 do
240 | trans.Add(dta.GetExtractedString(i), dta.GetExtractedString(i));
241 | dta.Free;
242 | WriteLog('Extracting done. Found strings: ' + IntToStr(strcnt));
243 | clib.Close;
244 | end;
245 | for i := 1 to 999 do
246 | if clib.OpenFile('room' + IntToStr(i) + '.crm') then
247 | begin
248 | WriteLog('Try to open file: room' + IntToStr(i) + '.crm');
249 | room := TRoom.Create(clib.GetFileStream);
250 | strcnt := room.GetExtractedStringsCount;
251 | Inc(fullstrcount, strcnt);
252 | for m := 0 to strcnt - 1 do
253 | trans.Add(room.GetExtractedString(m), room.GetExtractedString(m));
254 | room.Free;
255 | WriteLog('Extracting done. Found strings: ' + IntToStr(strcnt));
256 | clib.Close;
257 | end;
258 | if FileExists(gamepath + '\game.id') then
259 | DeleteFile(gamepath + '\game.id');
260 | WriteLog('Writing game Name and ID into game.id file.');
261 | WriteGameProj(gamepath + '\game.id');
262 | WriteLog('Extracted ' + IntToStr(fullstrcount) + ' strings.');
263 | clib.Free;
264 | trans.WriteToFullText(gamepath + 'Extracted.txt');
265 | trans.Free;
266 | Application.MessageBox('Extracting done!', 'Info', MB_OK);
267 | end;
268 | end;
269 |
270 | procedure TMainForm.CreateFromDTAClick(Sender: TObject);
271 | var
272 | fext: String;
273 | fullstrcount, strcnt, i: Integer;
274 | begin
275 | if odDTACRM.Execute then
276 | begin
277 | if sdDTACRM.Execute then
278 | begin
279 | fext := ExtractFileExt(odDTACRM.FileName);
280 | trans := TTranslation.Create;
281 | if fext = '.crm' then
282 | begin
283 | WriteLog('Try to open file: ' + ExtractFileName(odDTACRM.FileName));
284 | room := TRoom.Create(odDTACRM.FileName);
285 | strcnt := room.GetExtractedStringsCount;
286 | Inc(fullstrcount, strcnt);
287 | for i := 0 to strcnt - 1 do
288 | trans.Add(room.GetExtractedString(i), room.GetExtractedString(i));
289 | room.Free;
290 | WriteLog('Extracting done. Found strings: ' + IntToStr(strcnt));
291 | end;
292 | if fext = '.dta' then
293 | begin
294 | WriteLog('Try to open file: ' + ExtractFileName(odDTACRM.FileName));
295 | dta := TGameDta.Create(odDTACRM.FileName);
296 | if dta.GetDtaErr = DTA_ERROR_INC_VER then
297 | begin
298 | Application.MessageBox('Unsupported DTA version!', 'Error', MB_OK);
299 | WriteLog('Unsupported DTA ' + dta.GetDtaVersionString + ' version!');
300 | dta.Free;
301 | clib.Close;
302 | Exit;
303 | end;
304 | WriteLog('Game engine version: ' + dta.GetDtaVersionString);
305 | GameName := dta.GetGameName;
306 | WriteLog('Found game name: ' + GameName);
307 | GameID := dta.GetGameID;
308 | WriteLog('Found game id: ' + IntToStr(GameID));
309 | strcnt := dta.GetExtractedStringsCount;
310 | Inc(fullstrcount, strcnt);
311 | for i := 0 to strcnt - 1 do
312 | trans.Add(dta.GetExtractedString(i), dta.GetExtractedString(i));
313 | dta.Free;
314 | WriteLog('Extracting done. Found strings: ' + IntToStr(strcnt));
315 | end;
316 | trans.WriteToFullText(sdDTACRM.FileName);
317 | trans.Free;
318 | Application.MessageBox('Extracting done!', 'Info', MB_OK);
319 | end;
320 | end;
321 | end;
322 |
323 | procedure TMainForm.WriteGameProj(FileName: string);
324 | var
325 | uid: TFileStream;
326 | names: Integer;
327 | begin
328 | uid := TFileStream.Create(FileName, fmCreate);
329 | names := Length(GameName);
330 | uid.Write(names, 1);
331 | uid.Write(PAnsiChar(GameName)^, names);
332 | uid.Write(GameID, 4);
333 | uid.Free;
334 | end;
335 |
336 | procedure TMainForm.ExtrEXEClick(Sender: TObject);
337 | var
338 | fName, buf: AnsiString;
339 | i: Integer;
340 | begin
341 | if odGame.Execute then
342 | begin
343 | gamepath := ExtractFilePath(odGame.FileName);
344 | fName := ExtractFileName(odGame.FileName);
345 | for i := 1 to Length(fName) do
346 | if fName[i] = '.' then Break
347 | else buf := buf + fName[i];
348 | ForceDirectories(gamepath + '\' + buf);
349 | clib := TClib32.Create(odGame.FileName);
350 | clib.ExtractGameEngine(gamepath + buf + '\acwin.exe');
351 | clib.ExtractAllFiles(gamepath + buf + '\');
352 | clib.Free;
353 | Application.MessageBox('Extracting from EXE done!', 'Info', MB_OK);
354 | end;
355 | end;
356 |
357 | procedure TMainForm.ExtrLIBClick(Sender: TObject);
358 | var
359 | fName, buf: AnsiString;
360 | i: Integer;
361 | begin
362 | if odLIB.Execute then
363 | begin
364 | gamepath := ExtractFilePath(odLIB.FileName);
365 | fName := ExtractFileName(odLIB.FileName);
366 | for i := 1 to Length(fName) do
367 | if fName[i] = '.' then Break
368 | else buf := buf + fName[i];
369 | ForceDirectories(gamepath + '\' + buf);
370 | clib := TClib32.Create(odLIB.FileName);
371 | clib.ExtractAllFiles(gamepath + buf + '\');
372 | clib.Free;
373 | Application.MessageBox('Extracting files done!', 'Info', MB_OK);
374 | end;
375 | end;
376 |
377 | procedure TMainForm.ExtrSprClick(Sender: TObject);
378 | var
379 | spr: TSprite;
380 | aa: Integer;
381 | begin
382 | if odSPR.Execute then
383 | begin
384 | gamepath := ExtractFilePath(odSPR.FileName);
385 | spr := TSprite.Create(odSPR.FileName);
386 | spr.ExtractAllSprites(gamepath + 'acsprset\');
387 | // spr.CheckExtract(1);
388 | spr.Free;
389 | Application.MessageBox('Extracting sprites done!', 'Info', MB_OK);
390 | end;
391 | end;
392 |
393 | procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
394 | begin
395 | WriteLog('Exit from tool.');
396 | WriteLog('');
397 | end;
398 |
399 | procedure TMainForm.FormCreate(Sender: TObject);
400 | begin
401 | WriteLog('Tool started.');
402 | end;
403 |
404 | procedure TMainForm.WriteLog(Text: String);
405 | begin
406 | AssignFile(log, 'agstool.log');
407 | if not FileExists('agstool.log') then
408 | ReWrite(log)
409 | else
410 | Append(log);
411 | if Text <> '' then
412 | Writeln(log, DateToStr(Date) + ' ' + FormatDateTime('hh:nn:ss :', Now) + ' ' + Text)
413 | else
414 | Writeln(log, '');
415 | CloseFile(log);
416 | end;
417 |
418 | procedure TMainForm.bdf2wfnClick(Sender: TObject);
419 | var
420 | wfn: TWFNFont;
421 | newf: AnsiString;
422 | begin
423 | if odBDF.Execute then
424 | begin
425 | wfn := TWFNFont.Create(odBDF.FileName);
426 | newf := ChangeFileExt(odBDF.FileName, '.wfn');
427 | wfn.WriteToWFN(newf);
428 | wfn.Free;
429 | Application.MessageBox('Font file created!', 'Info', MB_OK);
430 | end;
431 | end;
432 |
433 | procedure TMainForm.btn1Click(Sender: TObject);
434 | var
435 | strcnt, m: Integer;
436 | begin
437 | trans := TTranslation.Create;
438 | room := TRoom.Create('room1.crm');
439 | strcnt := room.GetExtractedStringsCount;
440 | for m := 0 to strcnt - 1 do
441 | trans.Add(room.GetExtractedString(m), room.GetExtractedString(m));
442 | room.Free;
443 | // clib.Close;
444 | trans.WriteToFullText('Extracted.txt');
445 | trans.Free;
446 | Application.MessageBox('Extracting done!', 'Info', MB_OK);
447 | end;
448 |
449 | procedure TMainForm.btn2Click(Sender: TObject);
450 | var
451 | dta : TGameDta;
452 | i, strcnt: Integer;
453 | begin
454 | trans := TTranslation.Create;
455 | dta := TGameDta.Create('game28.dta');
456 | strcnt := dta.GetExtractedStringsCount;
457 | for i := 0 to strcnt - 1 do
458 | trans.Add(dta.GetExtractedString(i), dta.GetExtractedString(i));
459 | dta.Free;
460 | trans.WriteToFullText('Extracted.txt');
461 | trans.Free;
462 | Application.MessageBox('Extracting done!', 'Info', MB_OK);
463 | end;
464 |
465 | procedure TMainForm.Button1Click(Sender: TObject);
466 | var
467 | tmpscr: TScript;
468 | tmptrs: TTranslation;
469 | i: Integer;
470 | begin
471 | tmpscr := TScript.Create('Kiosk.asc');
472 | // tmpscr.Dump('dump.txt');
473 | tmpscr.ExtractStrings2;
474 | tmptrs := TTranslation.Create;
475 | for i := 0 to tmpscr.GetExtractedStringsCount - 1 do
476 | tmptrs.Add(tmpscr.GetExtractedString(i), '');
477 | tmptrs.WriteToFullText('Kiosk.txt');
478 | tmptrs.Free;
479 | tmpscr.Free;
480 | end;
481 |
482 | procedure TMainForm.wfn2bdfClick(Sender: TObject);
483 | var
484 | wfn: TWFNFont;
485 | newf: AnsiString;
486 | begin
487 | if odWFN.Execute then
488 | begin
489 | wfn := TWFNFont.Create(odWFN.FileName);
490 | newf := ChangeFileExt(odWFN.FileName, '.bdf');
491 | wfn.WriteToBDF(newf);
492 | wfn.Free;
493 | Application.MessageBox('Font file created!', 'Info', MB_OK);
494 | end;
495 | end;
496 |
497 | procedure TMainForm.CompileTRSClick(Sender: TObject);
498 | var
499 | newf: AnsiString;
500 | begin
501 | if odTRS.Execute then
502 | begin
503 | gamepath := ExtractFilePath(odTRS.FileName);
504 | if ReadGameProj(gamepath + '\game.id') then
505 | begin
506 | trans := TTranslation.Create(odTRS.FileName);
507 | newf := ChangeFileExt(odTRS.FileName, '.tra');
508 | trans.bVersion2 := chkTRAV2.Checked;
509 | trans.SetGameName(GameName);
510 | trans.SetGameID(GameID);
511 | trans.WriteToCompiled(newf);
512 | trans.Free;
513 | Application.MessageBox('Compiling done!', 'Info', MB_OK);
514 | end else
515 | Application.MessageBox('File "game.id" not found!', 'Error', MB_OK);
516 | end;
517 | end;
518 |
519 | procedure TMainForm.CreateFrom2TXTClick(Sender: TObject);
520 | var
521 | origtxt, transtxt, newtrs: AnsiString;
522 | begin
523 | if odTXT.Execute then
524 | begin
525 | origtxt := odTXT.FileName;
526 | if odTXT.Execute then
527 | begin
528 | transtxt := odTXT.FileName;
529 | if sdTRS.Execute then
530 | begin
531 | newtrs := sdTRS.FileName;
532 | trans := TTranslation.Create;
533 | trans.ReadFrom2Texts(origtxt, transtxt);
534 | trans.WriteToDecompiled(newtrs);
535 | trans.Free;
536 | Application.MessageBox('Creating TRS is done!', 'Info', MB_OK);
537 | end;
538 | end;
539 | end;
540 | end;
541 |
542 | procedure TMainForm.CreateTXT2TRSClick(Sender: TObject);
543 | var
544 | newf: AnsiString;
545 | begin
546 | if odTXT.Execute then
547 | begin
548 | gamepath := ExtractFilePath(odTXT.FileName);
549 | newf := ChangeFileExt(odTXT.FileName, '.trs');
550 | trans := TTranslation.Create;
551 | trans.ReadFullText(odTXT.FileName);
552 | trans.WriteToDecompiled(newf);
553 | trans.Free;
554 | Application.MessageBox('Creating TRS is done!', 'Info', MB_OK);
555 | end;
556 | end;
557 |
558 | procedure TMainForm.DecompileTRAClick(Sender: TObject);
559 | var
560 | newf: AnsiString;
561 | begin
562 | if odTRA.Execute then
563 | begin
564 | gamepath := ExtractFilePath(odTRA.FileName);
565 | trans := TTranslation.Create(odTRA.FileName);
566 | newf := ChangeFileExt(odTRA.FileName, '.trs');
567 | trans.WriteToDecompiled(newf);
568 | GameName := trans.GetGameName;
569 | GameID := trans.GetGameID;
570 | WriteGameProj(gamepath + '\game.id');
571 | trans.Free;
572 | Application.MessageBox('Decompiled!', 'Info', MB_OK);
573 | end;
574 | end;
575 |
576 | function TMainForm.ReadGameProj(FileName: string): Boolean;
577 | var
578 | uid: TFileStream;
579 | names: Byte;
580 | begin
581 | Result := False;
582 | if FileExists(FileName) then
583 | begin
584 | uid := TFileStream.Create(FileName, fmOpenRead);
585 | uid.Read(names, 1);
586 | SetLength(GameName, names);
587 | uid.Read(PAnsiChar(GameName)^, names);
588 | uid.Read(GameID, 4);
589 | uid.Free;
590 | Result := True;
591 | end;
592 | end;
593 |
594 | procedure TMainForm.RoomBtnClick(Sender: TObject);
595 | begin
596 | RoomForm := TRoomForm.Create(self);
597 | RoomForm.Show;
598 | end;
599 |
600 | procedure TMainForm.SaveTXTClick(Sender: TObject);
601 | var
602 | newf: AnsiString;
603 | begin
604 | if odTRS.Execute then
605 | begin
606 | gamepath := ExtractFilePath(odTRS.FileName);
607 | ForceDirectories(gamepath + '\outbox');
608 | trans := TTranslation.Create(odTRS.FileName);
609 | // newf := ChangeFileExt(odTRS.FileName, '.txt');
610 | trans.WriteToText(gamepath + '\outbox');
611 | trans.Free;
612 | Application.MessageBox('Extracting from TRS is done!', 'Info', MB_OK);
613 | end;
614 | end;
615 |
616 | procedure TMainForm.TRSAdderClick(Sender: TObject);
617 | var
618 | oldtrs, newtrs: AnsiString;
619 | newtr: TTranslation;
620 | begin
621 | oldtrs := ''; newtrs := '';
622 | if odTRS.Execute then
623 | begin
624 | oldtrs := odTRS.FileName;
625 | if odTRS.Execute then
626 | begin
627 | newtrs := odTRS.FileName;
628 | if not FileExists(oldtrs) then Exit;
629 | if not FileExists(newtrs) then Exit;
630 | trans := TTranslation.Create(oldtrs);
631 | newtr := TTranslation.Create(newtrs);
632 | trans.AddDict(newtr.GetDict, newtr.GetDictSize);
633 | trans.WriteToDecompiled(oldtrs);
634 | newtr.Free;
635 | trans.Free;
636 | Application.MessageBox('Adding new strings is done!', 'Info', MB_OK);
637 | end;
638 | end;
639 | end;
640 |
641 | end.
642 |
--------------------------------------------------------------------------------
/AGSTool.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {FDBA7110-3371-47C8-BFE2-3706AD836746}
4 | 18.1
5 | VCL
6 | AGSTool.dpr
7 | True
8 | Debug
9 | Win32
10 | 3
11 | Application
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | true
33 | Cfg_1
34 | true
35 | true
36 |
37 |
38 | true
39 | Base
40 | true
41 |
42 |
43 | true
44 | Cfg_2
45 | true
46 | true
47 |
48 |
49 | AGSTool
50 | bindcompfmx;fmx;rtl;dbrtl;IndySystem;DbxClientDriver;bindcomp;inetdb;DBXInterBaseDriver;DataSnapCommon;DataSnapClient;DataSnapServer;DataSnapProviderClient;xmlrtl;DbxCommonDriver;IndyProtocols;DBXMySQLDriver;dbxcds;bindengine;soaprtl;DBXOracleDriver;dsnap;DBXInformixDriver;IndyCore;fmxase;DBXFirebirdDriver;inet;fmxobj;inetdbxpress;DBXSybaseASADriver;fmxdae;dbexpress;DataSnapIndy10ServerTransport;IPIndyImpl;$(DCC_UsePackage)
51 | $(BDS)\bin\delphi_PROJECTICON.ico
52 | System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
53 | .\$(Platform)\$(Config)
54 | .\$(Platform)\$(Config)
55 | false
56 | false
57 | false
58 | false
59 | false
60 |
61 |
62 | true
63 | vcldbx;frx16;TeeDB;Rave100VCL;vclib;Tee;inetdbbde;DBXOdbcDriver;svnui;ibxpress;DBXSybaseASEDriver;vclimg;frxDB16;intrawebdb_120_160;fmi;fs16;TeeUI;vclactnband;FMXTee;vcldb;vcldsnap;bindcompvcl;vclie;vcltouch;Intraweb_120_160;DBXDb2Driver;websnap;vclribbon;frxe16;VclSmp;fsDB16;vcl;DataSnapConnectors;CloudService;DBXMSSQLDriver;CodeSiteExpressPkg;FmxTeeUI;dsnapcon;vclx;webdsnap;svn;bdertl;adortl;$(DCC_UsePackage)
64 | true
65 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
66 | 1033
67 | $(BDS)\bin\default_app.manifest
68 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
69 |
70 |
71 | true
72 | $(BDS)\bin\default_app.manifest
73 | 1033
74 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
75 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
76 | true
77 | DBXOdbcDriver;DBXSybaseASEDriver;vclimg;vclactnband;vcldb;vcldsnap;bindcompvcl;vclie;vcltouch;DBXDb2Driver;websnap;VclSmp;vcl;DBXMSSQLDriver;dsnapcon;vclx;webdsnap;$(DCC_UsePackage)
78 |
79 |
80 | DEBUG;$(DCC_Define)
81 | false
82 | true
83 | true
84 | true
85 |
86 |
87 | AGSTool_Icon.ico
88 | 1033
89 | true
90 | false
91 |
92 |
93 | false
94 | RELEASE;$(DCC_Define)
95 | 0
96 | 0
97 |
98 |
99 | AGSTool_Icon.ico
100 | true
101 | 1033
102 |
103 |
104 |
105 | MainSource
106 |
107 |
108 |
109 | dfm
110 |
111 |
112 |
113 | dfm
114 |
115 |
116 | Cfg_2
117 | Base
118 |
119 |
120 | Base
121 |
122 |
123 | Cfg_1
124 | Base
125 |
126 |
127 |
128 | Delphi.Personality.12
129 |
130 |
131 |
132 |
133 | False
134 | False
135 | 1
136 | 0
137 | 0
138 | 0
139 | False
140 | False
141 | False
142 | False
143 | False
144 | 1049
145 | 1251
146 |
147 |
148 |
149 |
150 | 1.0.0.0
151 |
152 |
153 |
154 |
155 |
156 | 1.0.0.0
157 |
158 |
159 |
160 | AGSTool.dpr
161 |
162 |
163 | Microsoft Office 2000 Sample Automation Server Wrapper Components
164 | Microsoft Office XP Sample Automation Server Wrapper Components
165 |
166 |
167 |
168 |
169 |
170 | 1
171 |
172 |
173 | 1
174 |
175 |
176 |
177 |
178 | Contents\Resources
179 | 1
180 |
181 |
182 |
183 |
184 | classes
185 | 1
186 |
187 |
188 |
189 |
190 | res\drawable-xxhdpi
191 | 1
192 |
193 |
194 |
195 |
196 | Contents\MacOS
197 | 0
198 |
199 |
200 | 1
201 |
202 |
203 | Contents\MacOS
204 | 1
205 |
206 |
207 |
208 |
209 | library\lib\mips
210 | 1
211 |
212 |
213 |
214 |
215 | 1
216 |
217 |
218 | 1
219 |
220 |
221 | 1
222 |
223 |
224 |
225 |
226 | 0
227 |
228 |
229 | 1
230 |
231 |
232 | Contents\MacOS
233 | 1
234 |
235 |
236 | 1
237 |
238 |
239 | library\lib\armeabi-v7a
240 | 1
241 |
242 |
243 | 1
244 |
245 |
246 |
247 |
248 | 0
249 |
250 |
251 | Contents\MacOS
252 | 1
253 | .framework
254 |
255 |
256 |
257 |
258 | 1
259 |
260 |
261 | 1
262 |
263 |
264 | 1
265 |
266 |
267 |
268 |
269 | library\lib\x86
270 | 1
271 |
272 |
273 |
274 |
275 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
276 | 1
277 |
278 |
279 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
280 | 1
281 |
282 |
283 |
284 |
285 | 1
286 |
287 |
288 | 1
289 |
290 |
291 | 1
292 |
293 |
294 |
295 |
296 | 1
297 |
298 |
299 | 1
300 |
301 |
302 | 1
303 |
304 |
305 |
306 |
307 | 1
308 |
309 |
310 | 1
311 |
312 |
313 | 1
314 |
315 |
316 |
317 |
318 | library\lib\armeabi
319 | 1
320 |
321 |
322 |
323 |
324 | 0
325 |
326 |
327 | 1
328 |
329 |
330 | Contents\MacOS
331 | 1
332 |
333 |
334 |
335 |
336 | 1
337 |
338 |
339 | 1
340 |
341 |
342 | 1
343 |
344 |
345 |
346 |
347 | res\drawable-normal
348 | 1
349 |
350 |
351 |
352 |
353 | res\drawable-xhdpi
354 | 1
355 |
356 |
357 |
358 |
359 | res\drawable-large
360 | 1
361 |
362 |
363 |
364 |
365 | 1
366 |
367 |
368 | 1
369 |
370 |
371 | 1
372 |
373 |
374 |
375 |
376 | ../
377 | 1
378 |
379 |
380 | ../
381 | 1
382 |
383 |
384 |
385 |
386 | library\lib\armeabi-v7a
387 | 1
388 |
389 |
390 |
391 |
392 | res\drawable-hdpi
393 | 1
394 |
395 |
396 |
397 |
398 | Contents
399 | 1
400 |
401 |
402 |
403 |
404 | ../
405 | 1
406 |
407 |
408 |
409 |
410 | 1
411 |
412 |
413 | 1
414 |
415 |
416 | 1
417 |
418 |
419 |
420 |
421 | res\values
422 | 1
423 |
424 |
425 |
426 |
427 | res\drawable-small
428 | 1
429 |
430 |
431 |
432 |
433 | res\drawable
434 | 1
435 |
436 |
437 |
438 |
439 | 1
440 |
441 |
442 | 1
443 |
444 |
445 | 1
446 |
447 |
448 |
449 |
450 | 1
451 |
452 |
453 |
454 |
455 | res\drawable
456 | 1
457 |
458 |
459 |
460 |
461 | 0
462 |
463 |
464 | 0
465 |
466 |
467 | Contents\Resources\StartUp\
468 | 0
469 |
470 |
471 | 0
472 |
473 |
474 | 0
475 |
476 |
477 | 0
478 |
479 |
480 |
481 |
482 | library\lib\armeabi-v7a
483 | 1
484 |
485 |
486 |
487 |
488 | 0
489 | .bpl
490 |
491 |
492 | 1
493 | .dylib
494 |
495 |
496 | Contents\MacOS
497 | 1
498 | .dylib
499 |
500 |
501 | 1
502 | .dylib
503 |
504 |
505 | 1
506 | .dylib
507 |
508 |
509 |
510 |
511 | res\drawable-mdpi
512 | 1
513 |
514 |
515 |
516 |
517 | res\drawable-xlarge
518 | 1
519 |
520 |
521 |
522 |
523 | res\drawable-ldpi
524 | 1
525 |
526 |
527 |
528 |
529 | 0
530 | .dll;.bpl
531 |
532 |
533 | 1
534 | .dylib
535 |
536 |
537 | Contents\MacOS
538 | 1
539 | .dylib
540 |
541 |
542 | 1
543 | .dylib
544 |
545 |
546 | 1
547 | .dylib
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 | True
560 | True
561 |
562 |
563 | 12
564 |
565 |
566 |
567 |
568 |
569 |
--------------------------------------------------------------------------------
/AGS.GameDta.pas:
--------------------------------------------------------------------------------
1 | unit AGS.GameDta;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, System.Variants, System.Classes, System.SysUtils, System.Types, AGS.Script;
7 |
8 | type
9 | GUIListBox = record
10 | numItems, selected, topItem, mousexp, mouseyp: Integer;
11 | rowheight, num_items_fit: Integer;
12 | font, textcol, backcol, exflags: Integer;
13 | end;
14 | GUIObject = record
15 | guin, objn: Integer;
16 | flags: uInt;
17 | x, y: Integer;
18 | wid, hit: Integer;
19 | zorder: Integer;
20 | activated: Integer;
21 | scriptName: array [0..25] of AnsiChar;
22 | eventHandlers: array [0..9] of array [0..30] of AnsiChar;
23 | end;
24 | GUIMain = record
25 | Id: Integer;
26 | Name: AnsiString;
27 | Flags: Integer;
28 | X, Y, Width, Height: Integer;
29 | BgColor: Integer;
30 | BgImage: Integer;
31 | FgColor: Integer;
32 | Padding: Integer;
33 | PopupStyle: Integer;
34 | PopupAtMouseY: Integer;
35 | Transparency: Integer;
36 | ZOrder: Integer;
37 | FocusCtrl: Integer;
38 | HighlightCtrl: Integer;
39 | MouseOverCtrl: Integer;
40 | MouseWasAtX: Integer;
41 | MouseWasAtY: Integer;
42 | MouseDownCtrl: Integer;
43 | clickEventHandler: AnsiString;
44 | ControlCount: Integer;
45 | Visibility: Integer;
46 | end;
47 | DialogTopic = record
48 | optionnames: array [0..29] of array [0..149] of AnsiChar;
49 | optionflags: array [0..29] of Integer;
50 | optionscripts: Integer;
51 | entrypoints: array [0..29] of Short;
52 | startupentrypoint: Short;
53 | codesize: Short;
54 | numoptions: Integer;
55 | topicFlags: Integer;
56 | end;
57 | CharacterInfo = record
58 | defview: Integer;
59 | talkview: Integer;
60 | view: Integer;
61 | room, prevroom: Integer;
62 | x, y, wait: Integer;
63 | flags: Integer;
64 | following: Short;
65 | followinfo: Short;
66 | idleview: Integer;
67 | idletime, idleleft: Short;
68 | transparency: Short;
69 | baseline: Short;
70 | activeinv: Integer;
71 | talkcolor: Integer;
72 | thinkview: Integer;
73 | blinkview, blinkinterval: Short;
74 | blinktimer, blinkframe: Short;
75 | walkspeed_y, pic_yoffs: Short;
76 | z: Integer;
77 | walkwait: Integer;
78 | speech_anim_speed, reserved1: Short;
79 | blocking_width, blocking_height: Short;
80 | index_id: Integer;
81 | pic_xoffs, walkwaitcounter: Short;
82 | loop, frame: Short;
83 | walking, animating: Short;
84 | walkspeed, animspeed: Short;
85 | inv: array [0..300] of Short;
86 | actx, acty: Short;
87 | name: array [0..39] of AnsiChar;
88 | scrname: array [0..19] of AnsiChar;
89 | onn: AnsiChar;
90 | end;
91 | ViewFrame = record
92 | pic: Integer;
93 | xoffs, yoffs: Short;
94 | speed: Short;
95 | flags: Integer;
96 | sound: Integer;
97 | reserved_for_future: array [0..1] of Integer;
98 | end;
99 | ViewLoopNew = record
100 | numFrames: Short;
101 | flags: Integer;
102 | frames: array of ViewFrame;
103 | end;
104 | ViewStruct = record
105 | numLoops: Short;
106 | loops: array of ViewLoopNew;
107 | end;
108 | ViewStruct272 = record
109 | numLoops: Short;
110 | numframes: array [0..15] of Short;
111 | loopFlags: array [0..15] of Integer;
112 | frames: array [0..15] of array [0..19] of ViewFrame;
113 | end;
114 | WordsDictionary = record
115 | num_words: Integer;
116 | wordd: array of AnsiString;
117 | wordnum: array of Short;
118 | end;
119 | InteractionScripts = record
120 | NumEvents: Integer;
121 | ScriptFuncNames: array of AnsiString;
122 | end;
123 | InteractionVariable = record
124 | name: array [0..22] of AnsiChar;
125 | vtype: Byte;
126 | value: Integer;
127 | end;
128 | NewInteractionValue = record
129 | valType: Integer;
130 | val: Integer;
131 | extra: Integer;
132 | end;
133 | NewInteractionCommand = record
134 | Reserved: Integer;
135 | ctype: Integer;
136 | data: array [0..4] of NewInteractionValue;
137 | children: Integer;
138 | parent: Integer;
139 | end;
140 | NewInteractionCommandList = record
141 | numCommands: Integer;
142 | command: array [0..39] of NewInteractionCommand;
143 | timesRun: Integer;
144 | end;
145 | NewInteraction = record
146 | NumEvents: Integer;
147 | EventTypes: array [0..29] of Integer;
148 | TimesRun: array [0..29] of Integer;
149 | Response: array [0..29] of Integer;
150 | end;
151 | MouseCursor = record
152 | Pic: Integer;
153 | HotX: Word;
154 | HotY: Word;
155 | View: Word;
156 | Name: array [0..9] of AnsiChar;
157 | Flags: Byte;
158 | end;
159 | InventoryItemInfo = record
160 | Name: array [0..24] of AnsiChar;
161 | Pic: Integer;
162 | CursorPic: Integer;
163 | HotX: Integer;
164 | HotY: Integer;
165 | Reserved: array [0..4] of Integer;
166 | Flags: ShortInt;
167 | end;
168 | GameSetupStructBase = record
169 | GameName: array [0..49] of AnsiChar;
170 | Options: array [0..99] of Integer;
171 | PalUses: array [0..255] of AnsiChar;
172 | DefPal: array [0..255] of Integer;
173 | NumViews: Integer;
174 | NumCharacters: Integer;
175 | PlayerCharacter: Integer;
176 | TotalScore: Integer;
177 | NumInvItems: Word;
178 | NumDialog: Integer;
179 | NumDlgMessage: Integer;
180 | NumFonts: Integer;
181 | Color_Depth: Integer;
182 | Target_Win: Integer;
183 | Dialog_Bullet: Integer;
184 | HotDot: Word;
185 | HotDotOuter: Word;
186 | UniqueID: Integer;
187 | NumGUI: Integer;
188 | NumCursors: Integer;
189 | Default_Resolution: Integer;
190 | Default_Lipsync_Frame: Integer;
191 | InvHotDotSprite: Integer;
192 | Reserved: array [0..16] of Integer;
193 | Messages: array [0..499] of Integer;
194 | Dict: Integer;
195 | GlobalScript: Integer;
196 | Chars: Integer;
197 | Compiled_Script: Integer;
198 | end;
199 | GameSetupStruct = record
200 | Base: GameSetupStructBase;
201 | GUID: array [0..39] of AnsiChar;
202 | saveGameFileExtension: array [0..19] of AnsiChar;
203 | saveGameFolderName: array [0..49] of AnsiChar;
204 | FontFlags: array [0..14] of AnsiChar;
205 | FontOutline: array [0..14] of AnsiChar;
206 | SpriteFlags: array [0..29999] of AnsiChar;
207 | InvInfo: array [0..300] of InventoryItemInfo;
208 | MCurs: array [0..19] of MouseCursor;
209 | IntrChar: array of NewInteraction;
210 | CharScripts: array of InteractionScripts;
211 | InvScripts: array of InteractionScripts;
212 | Dict: WordsDictionary;
213 | views: array of ViewStruct;
214 | chars: array of CharacterInfo;
215 | lipSyncFrameLetters: array [0..19] of array [0..49] of AnsiChar;
216 | messages: array of AnsiString;
217 | dialog: array of DialogTopic;
218 | end;
219 | TGameDta = class(TObject)
220 | private
221 | DtaF: TFileStream;
222 | DtaVer, DtaErr, numstr, ndmp: Integer;
223 | DtaVerStr: AnsiString;
224 | GSS: GameSetupStruct;
225 | datstr: array of AnsiString;
226 | function ReadInt32(FS: TFileStream): Integer;
227 | function ReadInt16(FS: TFileStream): Word;
228 | function ReadInt8(FS: TFileStream): Byte;
229 | function ReadString(FS: TFileStream): AnsiString;
230 | function fgetstring(FS: TFileStream): AnsiString;
231 | function fgetstring_limit(FS: TFileStream; BufSize: Integer): AnsiString;
232 | function deserialize_interaction_scripts(FS: TFileStream): InteractionScripts;
233 | function deserialize_new_interaction(FS: TFileStream): NewInteraction;
234 | function deserialize_command_list(FS: TFileStream): NewInteractionCommandList;
235 | function read_string_decrypt(FS: TFileStream): AnsiString;
236 | function decrypt_text(Str: AnsiString): AnsiString;
237 | procedure fread_script(FS: TFileStream);
238 | function read_dictionary(FS: TFileStream): WordsDictionary;
239 | procedure strcpy(var arr: array of AnsiChar; str: AnsiString);
240 | procedure AddExtrString(Str: AnsiString);
241 | procedure GUIObjectRead(FS: TFileStream; Version: Integer);
242 | procedure read_gui(FS: TFileStream);
243 | procedure CustomPropertySchema(FS: TFileStream);
244 | procedure CustomProperties(FS: TFileStream);
245 | procedure ReadPluginsFromDisk(FS: TFileStream);
246 | procedure read_dialogs(FS: TFileStream);
247 | procedure ReadFromStream(FS: TFileStream);
248 | procedure ReadGameSetupStructBase(FS: TFileStream);
249 | procedure ReadInventoryItemInfo(FS: TFileStream);
250 | procedure ReadMouseCursor(FS: TFileStream);
251 | procedure ReadFromStream2(FS: TFileStream);
252 | procedure ReadFromFile(FileName: AnsiString);
253 | public
254 | constructor Create(FileName: AnsiString); overload;
255 | constructor Create(FS: TFileStream); overload;
256 | destructor Free; overload;
257 | function GetExtractedString(Index: Integer): AnsiString;
258 | function GetExtractedStringsCount: Integer;
259 | function GetGameName: AnsiString;
260 | function GetGameID: uInt;
261 | function GetDtaErr: UINT;
262 | function GetDtaVersion: UINT;
263 | function GetDtaVersionString: AnsiString;
264 | end;
265 |
266 | const
267 | game_file_sig = 'Adventure Creator Game File v2';
268 | passwencstring = 'Avis Durgan';
269 |
270 | // Game version
271 | kGameVersion_Undefined = 0;
272 | kGameVersion_230 = 12;
273 | kGameVersion_240 = 12;
274 | kGameVersion_250 = 18;
275 | kGameVersion_251 = 19; // same as 2.52
276 | kGameVersion_253 = 20;
277 | kGameVersion_254 = 21;
278 | kGameVersion_255 = 22;
279 | kGameVersion_256 = 24;
280 | kGameVersion_260 = 25;
281 | kGameVersion_261 = 26;
282 | kGameVersion_262 = 27;
283 | kGameVersion_270 = 31;
284 | kGameVersion_272 = 32;
285 | kGameVersion_300 = 35;
286 | kGameVersion_301 = 36;
287 | kGameVersion_310 = 37;
288 | kGameVersion_311 = 39;
289 | kGameVersion_312 = 40;
290 | kGameVersion_320 = 41;
291 | kGameVersion_321 = 42;
292 | kGameVersion_330 = 43;
293 | kGameVersion_331 = 44;
294 | kGameVersion_340_1 = 45;
295 | kGameVersion_340_2 = 46;
296 | kGameVersion_340_4 = 47;
297 | kGameVersion_Current = kGameVersion_340_4;
298 |
299 | // Game resolution
300 | kGameResolution_Undefined = -1;
301 | // definition of 320x200 in very old versions of the engine (somewhere pre-2.56)
302 | kGameResolution_Default = 0;
303 | kGameResolution_320x200 = 1;
304 | kGameResolution_320x240 = 2;
305 | kGameResolution_640x400 = 3;
306 | kGameResolution_640x480 = 4;
307 | kGameResolution_800x600 = 5;
308 | kGameResolution_1024x768 = 6;
309 | kGameResolution_1280x720 = 7;
310 | kGameResolution_Custom = 8;
311 |
312 | kGameResolution_LastLoRes = kGameResolution_320x240;
313 | kGameResolution_FirstHiRes = kGameResolution_640x400;
314 |
315 | // GUI version
316 | kGuiVersion_Initial = 0;
317 | kGuiVersion_214 = 100;
318 | kGuiVersion_222 = 101;
319 | kGuiVersion_230 = 102;
320 | kGuiVersion_unkn_103 = 103;
321 | kGuiVersion_unkn_104 = 104;
322 | kGuiVersion_260 = 105;
323 | kGuiVersion_unkn_106 = 106;
324 | kGuiVersion_unkn_107 = 107;
325 | kGuiVersion_unkn_108 = 108;
326 | kGuiVersion_unkn_109 = 109;
327 | kGuiVersion_270 = 110;
328 | kGuiVersion_272a = 111;
329 | kGuiVersion_272b = 112;
330 | kGuiVersion_272c = 113;
331 | kGuiVersion_272d = 114;
332 | kGuiVersion_272e = 115;
333 | kGuiVersion_330 = 116;
334 | kGuiVersion_331 = 117;
335 | kGuiVersion_340 = 118;
336 | kGuiVersion_Current = kGuiVersion_340;
337 | // Defines the oldest version of gui data that is complying to current
338 | // savedgame format; if the loaded game data is of this version or lower,
339 | // then this value will be written to savedgame instead of current version.
340 | kGuiVersion_ForwardCompatible = kGuiVersion_272e;
341 |
342 | MAX_INTER_FUNCTION_NAME_LENGTH = 200;
343 | MAXGLOBALMES = 500;
344 | MAX_FONTS = 15;
345 | MAX_SPRITES = 30000;
346 | MAX_CURSOR = 20;
347 | MAX_INV = 301;
348 | MAX_GUID_LENGTH = 40;
349 | MAX_SG_EXT_LENGTH = 20;
350 | MAX_SG_FOLDER_LEN = 50;
351 | MAX_NEWINTERACTION_EVENTS = 30;
352 | GUI_MAGIC = $cafebeef;
353 | GUI_VERSION = 116;
354 | MAX_CUSTOM_PROPERTY_VALUE_LENGTH = 500;
355 | MAX_OBJS_ON_GUI = 30;
356 | BASEGOBJ_SIZE = 7;
357 | MAX_GUIOBJ_SCRIPTNAME_LEN = 25;
358 | MAX_GUIOBJ_EVENTHANDLER_LEN = 30;
359 | MAXVIEWNAMELENGTH = 15;
360 | MAX_GUIOBJ_EVENTS = 10;
361 | GLF_SGINDEXVALID = 4;
362 |
363 | LEGACY_MAX_OBJS_ON_GUI = 30;
364 |
365 | GUIMAIN_RESERVED_INTS = 5;
366 | GUIMAIN_NAME_LENGTH = 16;
367 | GUIMAIN_EVENTHANDLER_LENGTH = 20;
368 | GUIMAIN_LEGACY_TW_FLAGS_SIZE = 4;
369 |
370 | //Errors
371 | DTA_ERROR_NULL = 0;
372 | DTA_ERROR_INC_FILE = 1;
373 | DTA_ERROR_INC_VER = 2;
374 |
375 | implementation
376 |
377 | procedure TGameDta.strcpy(var arr: array of AnsiChar; str: AnsiString);
378 | var
379 | i: Integer;
380 | begin
381 | for i := 1 to Length(str) do
382 | arr[i-1] := str[i];
383 | end;
384 |
385 | constructor TGameDta.Create(FileName: AnsiString);
386 | begin
387 | ReadFromFile(FileName);
388 | end;
389 |
390 | constructor TGameDta.Create(FS: TFileStream);
391 | begin
392 | ReadFromStream(FS);
393 | end;
394 |
395 | destructor TGameDta.Free;
396 | begin
397 | FillChar(GSS.Base, SizeOf(GameSetupStructBase), 0);
398 | end;
399 |
400 | function TGameDta.ReadInt32(FS: TFileStream): Integer;
401 | begin
402 | FS.ReadBuffer(Result, SizeOf(Integer));
403 | end;
404 |
405 | function TGameDta.ReadInt16(FS: TFileStream): Word;
406 | begin
407 | FS.ReadBuffer(Result, SizeOf(Word));
408 | end;
409 |
410 | function TGameDta.ReadInt8(FS: TFileStream): Byte;
411 | begin
412 | FS.ReadBuffer(Result, SizeOf(Integer));
413 | end;
414 |
415 | function TGameDta.ReadString(FS: TFileStream): AnsiString;
416 | var
417 | len: Integer;
418 | begin
419 | len := ReadInt32(FS);
420 | if len > 0 then
421 | begin
422 | SetLength(Result, len);
423 | FS.ReadBuffer(PAnsiString(Result)^, len);
424 | end;
425 | end;
426 |
427 | function TGameDta.fgetstring(FS: TFileStream): AnsiString;
428 | begin
429 | Result := fgetstring_limit(FS, 50000000);
430 | end;
431 |
432 | function TGameDta.fgetstring_limit(FS: TFileStream; BufSize: Integer): AnsiString;
433 | var
434 | buf: AnsiChar;
435 | curc: Integer;
436 | begin
437 | Result := ''; curc := 0;
438 | while True do
439 | begin
440 | if (FS.Position = FS.Size) or (curc = BufSize) then
441 | Break;
442 | FS.ReadBuffer(buf, SizeOf(buf));
443 | inc(curc);
444 | if buf = #0 then
445 | Break
446 | else
447 | Result := Result + buf;
448 | end;
449 | end;
450 |
451 | function TGameDta.deserialize_interaction_scripts(FS: TFileStream): InteractionScripts;
452 | var
453 | i: Integer;
454 | begin
455 | Result.NumEvents := ReadInt32(FS);
456 | SetLength(Result.ScriptFuncNames, Result.NumEvents);
457 | for i := 0 to Result.NumEvents - 1 do
458 | Result.ScriptFuncNames[i] := fgetstring_limit(FS, MAX_INTER_FUNCTION_NAME_LENGTH);
459 | end;
460 |
461 | function TGameDta.deserialize_new_interaction(FS: TFileStream): NewInteraction;
462 | var
463 | aa: Integer;
464 | begin
465 | if ReadInt32(FS) <> 1 then
466 | Exit;
467 | Result.NumEvents := ReadInt32(FS);
468 | if Result.NumEvents > MAX_NEWINTERACTION_EVENTS then
469 | Exit;
470 | for aa := 0 to Result.NumEvents - 1 do
471 | Result.EventTypes[aa] := ReadInt32(FS);
472 | for aa := 0 to Result.NumEvents - 1 do
473 | Result.Response[aa] := ReadInt32(FS);
474 | for aa := 0 to Result.NumEvents - 1 do
475 | if Result.Response[aa] <> 0 then
476 | deserialize_command_list(FS);
477 | end;
478 |
479 | function TGameDta.deserialize_command_list(FS: TFileStream): NewInteractionCommandList;
480 | var
481 | aa: Integer;
482 | begin
483 | FillChar(Result, SizeOf(NewInteractionCommandList), 0);
484 | Result.numCommands := ReadInt32(FS);
485 | Result.timesRun := ReadInt32(FS);
486 | for aa := 0 to Result.numCommands - 1 do
487 | FS.Read(Result.command[aa], sizeof(NewInteractionCommand));
488 | for aa := 0 to Result.numCommands - 1 do
489 | if Result.command[aa].children <> 0 then
490 | deserialize_command_list(FS);
491 | end;
492 |
493 | function TGameDta.read_string_decrypt(FS: TFileStream): AnsiString;
494 | var
495 | ss: Integer;
496 | buf: array of Byte;
497 | begin
498 | Result := '';
499 | ss := ReadInt32(FS);
500 | if (ss < 0) or (ss > 5000000) then
501 | begin
502 | FS.Seek(-4, soFromCurrent);
503 | Exit;
504 | end;
505 | SetLength(buf, ss);
506 | FS.Read(PChar(buf)^, ss);
507 | Result := decrypt_text(AnsiString(buf));
508 | SetLength(buf, 0);
509 | end;
510 |
511 | function TGameDta.decrypt_text(Str: AnsiString): AnsiString;
512 | var
513 | i, adx: Integer;
514 | nc: AnsiChar;
515 | begin
516 | Result := '';
517 | adx := 1;
518 | for i := 1 to Length(Str) do
519 | begin
520 | nc := AnsiChar(Byte(Str[i]) - Byte(passwencstring[adx]));
521 | if nc <> #0 then
522 | Result := Result + nc;
523 | inc(adx);
524 | if adx = 12 then
525 | adx := 1;
526 | end;
527 | end;
528 |
529 | function TGameDta.read_dictionary(FS: TFileStream): WordsDictionary;
530 | var
531 | i: Integer;
532 | begin
533 | Result.num_words := ReadInt32(FS);
534 | SetLength(Result.wordd, Result.num_words);
535 | SetLength(Result.wordnum, Result.num_words);
536 | for i := 0 to Result.num_words - 1 do
537 | begin
538 | Result.wordd[i] := read_string_decrypt(FS);
539 | FS.Read(Result.wordnum[i], 2);
540 | end;
541 | end;
542 |
543 | procedure TGameDta.fread_script(FS: TFileStream);
544 | var
545 | tmpscr: TScript;
546 | i, strcnt: Integer;
547 | begin
548 | tmpscr := TScript.Create(FS);
549 | tmpscr.ExtractStrings3;
550 | strcnt := tmpscr.GetExtractedStringsCount;
551 | for i := 0 to strcnt - 1 do
552 | AddExtrString(tmpscr.GetExtractedString(i));
553 | // tmpscr.Dump('new.dmp');
554 | tmpscr.Free;
555 | end;
556 |
557 | function TGameDta.GetExtractedString(Index: Integer): AnsiString;
558 | begin
559 | Result := datstr[Index];
560 | end;
561 |
562 | function TGameDta.GetExtractedStringsCount: Integer;
563 | begin
564 | Result := numstr;
565 | end;
566 |
567 | procedure TGameDta.AddExtrString(Str: AnsiString);
568 | var
569 | Found: Boolean;
570 | i: Integer;
571 | newstr: AnsiString;
572 | begin
573 | Found := False;
574 | newstr := '';
575 | for i := 1 to Length(Str) do
576 | if Str[i] <> #0 then
577 | newstr := newstr + Str[i];
578 | if (newStr = '') or (newStr[1] = #0) then
579 | Exit;
580 | for i := 0 to numstr - 1 do
581 | begin
582 | if datstr[i] = newStr then
583 | begin
584 | Found := True;
585 | Break;
586 | end;
587 | end;
588 | if not Found then
589 | begin
590 | inc(numstr);
591 | SetLength(datstr, numstr);
592 | datstr[numstr-1] := newStr;
593 | end;
594 | end;
595 |
596 | procedure TGameDta.GUIObjectRead(FS: TFileStream; Version: Integer);
597 | var
598 | numev, i: Integer;
599 | tmpobj: GUIObject;
600 | begin
601 | FillChar(tmpobj, SizeOf(GUIObject), 0);
602 | FS.Read(tmpobj, 4*BASEGOBJ_SIZE);
603 | if Version > 106 then
604 | strcpy(tmpobj.scriptName, fgetstring_limit(FS, MAX_GUIOBJ_SCRIPTNAME_LEN));
605 | if Version > 108 then
606 | begin
607 | i := FS.Position;
608 | numev := ReadInt32(FS);
609 | for i := 0 to numev - 1 do
610 | fgetstring_limit(FS, MAX_GUIOBJ_EVENTHANDLER_LEN + 1);
611 | end;
612 | end;
613 |
614 | procedure TGameDta.read_gui(FS: TFileStream);
615 | var
616 | gui_version, exflags, numgui, numguibuts, numguilabels, numguiinv, numguislider, numguitext, numguilist, numItems, i, m, buflen: Integer;
617 | buf: array of AnsiChar;
618 | tmpgui: GUIMain;
619 | tmplb: GUIListBox;
620 | begin
621 | if uInt(ReadInt32(FS)) <> GUI_MAGIC then
622 | Exit;
623 | gui_version := ReadInt32(FS);
624 | if gui_version < kGuiVersion_214 then
625 | numgui := gui_version
626 | else if gui_version > kGuiVersion_Current then
627 | Exit
628 | else numgui := ReadInt32(FS);
629 | if (numgui < 0) or (numgui > 1000) then
630 | Exit;
631 | SetLength(buf, 1000);
632 | // import the main GUI elements
633 | for i := 0 to numgui - 1 do
634 | begin
635 | FS.Seek(GUIMAIN_LEGACY_TW_FLAGS_SIZE, soFromCurrent);
636 | if gui_version < kGuiVersion_340 then
637 | begin
638 | SetLength(tmpgui.name, GUIMAIN_NAME_LENGTH);
639 | FS.ReadBuffer(PAnsiString(tmpgui.name)^, GUIMAIN_NAME_LENGTH);
640 | SetLength(tmpgui.clickEventHandler, GUIMAIN_EVENTHANDLER_LENGTH);
641 | FS.ReadBuffer(PAnsiString(tmpgui.clickEventHandler)^, GUIMAIN_EVENTHANDLER_LENGTH);
642 | end else begin
643 | tmpgui.name := ReadString(FS);
644 | tmpgui.clickEventHandler := ReadString(FS);
645 | end;
646 | tmpgui.X := ReadInt32(FS);
647 | tmpgui.Y := ReadInt32(FS);
648 | tmpgui.Width := ReadInt32(FS);
649 | tmpgui.Height := ReadInt32(FS);
650 | tmpgui.FocusCtrl := ReadInt32(FS);
651 | tmpgui.ControlCount := ReadInt32(FS);
652 | tmpgui.PopupStyle := ReadInt32(FS);
653 | tmpgui.PopupAtMouseY := ReadInt32(FS);
654 | tmpgui.BgColor := ReadInt32(FS);
655 | tmpgui.BgImage := ReadInt32(FS);
656 | tmpgui.FgColor := ReadInt32(FS);
657 | tmpgui.MouseOverCtrl := ReadInt32(FS);
658 | tmpgui.MouseWasAtX := ReadInt32(FS);
659 | tmpgui.MouseWasAtY := ReadInt32(FS);
660 | tmpgui.MouseDownCtrl := ReadInt32(FS);
661 | tmpgui.HighlightCtrl := ReadInt32(FS);
662 | tmpgui.Flags := ReadInt32(FS);
663 | tmpgui.Transparency := ReadInt32(FS);
664 | tmpgui.ZOrder := ReadInt32(FS);
665 | tmpgui.Id := ReadInt32(FS);
666 | tmpgui.Padding := ReadInt32(FS);
667 | FS.Seek(SizeOf(Integer)*GUIMAIN_RESERVED_INTS, soFromCurrent);
668 | tmpgui.Visibility := ReadInt32(FS);
669 | if gui_version < kGuiVersion_340 then
670 | begin
671 | FS.Seek(SizeOf(Integer)*LEGACY_MAX_OBJS_ON_GUI, soFromCurrent);
672 | FS.Seek(SizeOf(Integer)*LEGACY_MAX_OBJS_ON_GUI, soFromCurrent);
673 | end else begin
674 | if tmpgui.ControlCount > 0 then
675 | FS.Seek(SizeOf(Integer)*tmpgui.ControlCount, soFromCurrent);
676 | end;
677 | // FS.Read(tmpgui, SizeOf(GUIMain));
678 | end;
679 | // import the buttons
680 | numguibuts := ReadInt32(FS);
681 | for i := 0 to numguibuts - 1 do
682 | begin
683 | GUIObjectRead(FS, gui_version);
684 | FS.Seek(4 * 12, soFromCurrent);
685 | SetLength(buf, 50);
686 | FS.Read(PAnsiChar(buf)^, 50);
687 | AddExtrString(AnsiString(buf));
688 | if gui_version >= 111 then
689 | FS.Seek(8, soFromCurrent);
690 | SetLength(buf, 0);
691 | end;
692 | // labels
693 | numguilabels := ReadInt32(FS);
694 | for i := 0 to numguilabels - 1 do
695 | begin
696 | GUIObjectRead(FS, gui_version);
697 | if gui_version < 113 then
698 | begin
699 | SetLength(buf, 200);
700 | FS.Read(PAnsiChar(buf)^, 200);
701 | end else begin
702 | buflen := ReadInt32(FS);
703 | SetLength(buf, buflen);
704 | FS.Read(PAnsiChar(buf)^, buflen);
705 | end;
706 | AddExtrString(AnsiString(buf));
707 | FS.Seek(4*3, soFromCurrent);
708 | SetLength(buf, 0);
709 | end;
710 | // inv controls
711 | numguiinv := ReadInt32(FS);
712 | for i := 0 to numguiinv - 1 do
713 | begin
714 | GUIObjectRead(FS, gui_version);
715 | if gui_version >= 109 then
716 | begin
717 | FS.Seek(16, soFromCurrent);
718 | end;
719 | end;
720 | // sliders
721 | if gui_version >= 100 then
722 | begin
723 | numguislider := ReadInt32(FS);
724 | for i := 0 to numguislider - 1 do
725 | begin
726 | GUIObjectRead(FS, gui_version);
727 | if gui_version >= 104 then
728 | FS.Seek(7*4, soFromCurrent)
729 | else
730 | FS.Seek(4*4, soFromCurrent);
731 | end;
732 | end;
733 | // text boxes
734 | if gui_version >= 101 then
735 | begin
736 | numguitext := ReadInt32(FS);
737 | for i := 0 to numguitext - 1 do
738 | begin
739 | GUIObjectRead(FS, gui_version);
740 | SetLength(buf, 200);
741 | FS.Read(PAnsiChar(buf)^, 200);
742 | FS.Seek(12, soFromCurrent);
743 | AddExtrString(AnsiString(buf));
744 | SetLength(buf, 0);
745 | end;
746 | end;
747 | // list boxes
748 | if gui_version >= 101 then
749 | begin
750 | numguilist := ReadInt32(FS);
751 | for i := 0 to numguilist - 1 do
752 | begin
753 | GUIObjectRead(FS, gui_version);
754 | FS.Read(tmplb, SizeOf(tmplb));
755 | // FS.Seek(40, soFromCurrent);
756 | if gui_version >= 112 then
757 | FS.Seek(8, soFromCurrent);
758 | if gui_version >= 107 then
759 | FS.Seek(4, soFromCurrent);
760 | for m := 0 to tmplb.numItems - 1 do
761 | begin
762 | SetLength(buf, 1000);
763 | PAnsiString(buf)^ := fgetstring(FS);
764 | AddExtrString(AnsiString(buf));
765 | SetLength(buf, 0);
766 | end;
767 | if (gui_version >= 114) and ((tmplb.exflags and GLF_SGINDEXVALID) = GLF_SGINDEXVALID) then
768 | FS.Seek(2*tmplb.numItems, soFromCurrent);
769 | end;
770 | end;
771 | SetLength(buf, 0);
772 | end;
773 |
774 | procedure TGameDta.CustomPropertySchema(FS: TFileStream);
775 | var
776 | numProps, i: Integer;
777 | buf: AnsiString;
778 | begin
779 | if ReadInt32(FS) <> 1 then
780 | Exit;
781 | numProps := ReadInt32(FS);
782 | for i := 0 to numProps - 1 do
783 | begin
784 | buf := fgetstring_limit(FS, 20);
785 | buf := fgetstring_limit(FS, 100);
786 | buf := fgetstring_limit(FS, MAX_CUSTOM_PROPERTY_VALUE_LENGTH);
787 | AddExtrString(buf);
788 | ReadInt32(FS);
789 | end;
790 | end;
791 |
792 | procedure TGameDta.CustomProperties(FS: TFileStream);
793 | var
794 | numProps, i: Integer;
795 | buf: AnsiString;
796 | begin
797 | if ReadInt32(FS) <> 1 then
798 | Exit;
799 | numProps := ReadInt32(FS);
800 | for i := 0 to numProps - 1 do
801 | begin
802 | buf := fgetstring_limit(FS, 200);
803 | buf := fgetstring_limit(FS, MAX_CUSTOM_PROPERTY_VALUE_LENGTH);
804 | AddExtrString(buf);
805 | end;
806 | end;
807 |
808 | procedure TGameDta.ReadPluginsFromDisk(FS: TFileStream);
809 | var
810 | numPlug, datasize, i: Integer;
811 | begin
812 | if ReadInt32(FS) <> 1 then
813 | Exit;
814 | numPlug := ReadInt32(FS);
815 | for i := 0 to numPlug - 1 do
816 | begin
817 | fgetstring(FS);
818 | datasize := ReadInt32(FS);
819 | FS.Seek(datasize, soFromCurrent);
820 | end;
821 | end;
822 |
823 | procedure TGameDta.read_dialogs(FS: TFileStream);
824 | begin
825 |
826 | end;
827 |
828 | procedure TGameDta.ReadFromStream(FS: TFileStream);
829 | var
830 | buf: array [0..39] of AnsiChar;
831 | bufstr: array of AnsiChar;
832 | stlen, numScriptModules, numGlobalVars, i, m, n, newlen: Integer;
833 | numToRead, numToRead2: UINT;
834 | news, buf2: AnsiString;
835 | begin
836 | FS.Read(buf, 30);
837 | buf[30] := #0;
838 | if buf <> game_file_sig then
839 | begin
840 | DtaErr := DTA_ERROR_INC_FILE;
841 | Exit;
842 | end;
843 | DtaVer := ReadInt32(FS);
844 | if (DtaVer > kGameVersion_Current) or (DtaVer < 0) then
845 | begin
846 | DtaErr := DTA_ERROR_INC_VER;
847 | Exit;
848 | end;
849 | stlen := ReadInt32(FS);
850 | SetLength(DtaVerStr, stlen);
851 | FS.ReadBuffer(PAnsiString(DtaVerStr)^, stlen);
852 | // FS.Seek(stlen, soFromCurrent);
853 | ReadGameSetupStructBase(FS);
854 | if DtaVer >= kGameVersion_272 then
855 | begin
856 | FS.Read(GSS.GUID, MAX_GUID_LENGTH);
857 | FS.Read(GSS.saveGameFileExtension, MAX_SG_EXT_LENGTH);
858 | FS.Read(GSS.saveGameFolderName, MAX_SG_FOLDER_LEN);
859 | end;
860 | FS.ReadBuffer(GSS.FontFlags, GSS.Base.NumFonts);
861 | FS.ReadBuffer(GSS.FontOutline, GSS.Base.NumFonts);
862 | if DtaVer < kGameVersion_256 then
863 | numToRead := 6000
864 | else
865 | numToRead := ReadInt32(FS);
866 | FS.Seek(numToRead, soFromCurrent); // SpriteFlags
867 | ReadInventoryItemInfo(FS);
868 | for i := 0 to GSS.Base.NumInvItems - 1 do
869 | AddExtrString(GSS.InvInfo[i].Name);
870 | ReadMouseCursor(FS);
871 | SetLength(GSS.CharScripts, GSS.Base.NumCharacters);
872 | SetLength(GSS.InvScripts, GSS.Base.NumInvItems);
873 | if DtaVer > kGameVersion_272 then
874 | begin
875 | for i := 0 to GSS.Base.NumCharacters-1 do
876 | GSS.CharScripts[i] := deserialize_interaction_scripts(FS);
877 | for i := 0 to GSS.Base.NumInvItems-2 do
878 | GSS.InvScripts[i] := deserialize_interaction_scripts(FS);
879 | end else begin
880 | numGlobalVars := FS.Position;
881 | for i := 0 to GSS.Base.NumCharacters-1 do
882 | deserialize_new_interaction(FS);
883 | for i := 0 to GSS.Base.NumInvItems-1 do
884 | deserialize_new_interaction(FS);
885 | numGlobalVars := FS.Position;
886 | numGlobalVars := ReadInt32(FS);
887 | FS.Seek(SizeOf(InteractionVariable)*numGlobalVars, soFromCurrent); // MCurs
888 | end;
889 | if GSS.Base.Dict > 0 then
890 | GSS.Dict := read_dictionary(FS);
891 | // Loading scripts
892 | fread_script(FS); // Global Script
893 | if DtaVer > kGameVersion_310 then
894 | fread_script(FS); // Dialog Script
895 | if DtaVer >= kGameVersion_270 then
896 | begin
897 | numScriptModules := ReadInt32(FS);
898 | for i := 0 to numScriptModules - 1 do
899 | fread_script(FS);
900 | end;
901 | // SetLength(GSS.views, GSS.Base.NumViews);
902 | if DtaVer > kGameVersion_272 then
903 | begin
904 | for i := 0 to GSS.Base.NumViews - 1 do
905 | begin
906 | FS.Read(numToRead, 2);
907 | for m := 0 to numToRead - 1 do
908 | begin
909 | FS.Read(numToRead2, 2);
910 | FS.Seek(4, soFromCurrent);
911 | FS.Seek(SizeOf(ViewFrame)*numToRead2, soFromCurrent);
912 | end;
913 | end;
914 | end else begin
915 | FS.Seek(SizeOf(ViewStruct272)*GSS.Base.NumViews, soFromCurrent);
916 | end;
917 | // <= 2.1 skip unknown data
918 | if DtaVer <= kGameVersion_251 then
919 | FS.Seek(ReadInt32(FS) * $204, soFromCurrent);
920 |
921 | SetLength(GSS.chars, GSS.Base.NumCharacters);
922 | for i := 0 to GSS.Base.NumCharacters - 1 do
923 | begin
924 | FS.Read(GSS.chars[i], SizeOf(CharacterInfo));
925 | AddExtrString(GSS.chars[i].name);
926 | end;
927 | FS.Seek(20 * 50, soFromCurrent); // lipSyncFrameLetters
928 | SetLength(GSS.messages, MAXGLOBALMES);
929 | for i := 0 to MAXGLOBALMES - 1 do
930 | begin
931 | GSS.messages[i] := read_string_decrypt(FS);
932 | end;
933 | // Reading dialogs;
934 | SetLength(GSS.dialog, GSS.Base.NumDialog);
935 | numScriptModules := FS.Position;
936 | for i := 0 to GSS.Base.NumDialog - 1 do
937 | begin
938 | FS.Read(GSS.dialog[i], SizeOf(DialogTopic));
939 | numScriptModules := FS.Position;
940 | for m := 0 to GSS.dialog[i].numoptions - 1 do
941 | AddExtrString(GSS.dialog[i].optionnames[m]);
942 | end;
943 | numScriptModules := FS.Position;
944 | if DtaVer < kGameVersion_272 then
945 | begin
946 | for i := 0 to GSS.Base.NumDialog - 1 do
947 | begin
948 | if GSS.dialog[i].optionscripts <> 0 then
949 | begin
950 | SetLength(bufstr, GSS.dialog[i].codesize + 10);
951 | FS.Read(PChar(bufstr)^, GSS.dialog[i].codesize);
952 | SetLength(bufstr, 0);
953 | end;
954 | NumToRead := ReadInt32(FS);
955 | if NumToRead <= 1 then
956 | FS.Seek(1, soFromCurrent);
957 | SetLength(bufstr, NumToRead + 1);
958 | FS.Read(PChar(bufstr)^, NumToRead);
959 | // AddExtrString(decrypt_text(AnsiString(bufstr)));
960 | SetLength(bufstr, 0);
961 | end;
962 | // for i := 0 to GSS.Base.NumDlgMessage - 1 do
963 | // if (DtaVer >= 26) then
964 | // AddExtrString(read_string_decrypt(FS));
965 | if DtaVer < kGameVersion_260 then
966 | begin
967 | end else begin
968 | while True do
969 | begin
970 | numToRead := FS.Position;
971 | NumToRead := ReadInt32(FS);
972 | if NumToRead = $CAFEBEEF then
973 | begin
974 | FS.Seek(-4, soFromCurrent);
975 | Break;
976 | end;
977 | SetLength(bufstr, NumToRead + 1);
978 | FS.Read(PChar(bufstr)^, NumToRead);
979 | Inc(i);
980 | end;
981 | end;
982 | end;
983 | read_gui(FS);
984 | i := FS.Position;
985 | ReadPluginsFromDisk(FS);
986 | CustomPropertySchema(FS);
987 | for i := 0 to GSS.Base.NumCharacters - 1 do
988 | CustomProperties(FS);
989 | for i := 0 to GSS.Base.NumInvItems - 1 do
990 | CustomProperties(FS);
991 | // for i := 0 to GSS.Base.NumViews - 1 do
992 | // begin
993 | // news := fgetstring_limit(FS, MAXVIEWNAMELENGTH);
994 | // AddExtrString(news);
995 | // end;
996 | end;
997 |
998 | procedure TGameDta.ReadGameSetupStructBase(FS: TFileStream);
999 | var
1000 | i: Integer;
1001 | curpos, curr: UINT;
1002 | begin
1003 | // FS.ReadBuffer(GSS.Base.GameName, Length(GSS.Base.GameName)*SizeOf(GSS.Base.GameName[0]));
1004 | FS.ReadBuffer(GSS.Base.GameName, 52);
1005 | for i := 0 to 99 do
1006 | GSS.Base.Options[i] := ReadInt32(FS);
1007 | FS.ReadBuffer(GSS.Base.PalUses, Length(GSS.Base.PalUses)*SizeOf(GSS.Base.PalUses[i]));
1008 | for i := 0 to 255 do
1009 | GSS.Base.DefPal[i] := ReadInt32(FS);
1010 | GSS.Base.NumViews := ReadInt32(FS);
1011 | GSS.Base.NumCharacters := ReadInt32(FS);
1012 | GSS.Base.PlayerCharacter := ReadInt32(FS);
1013 | GSS.Base.TotalScore := ReadInt32(FS);
1014 | GSS.Base.NumInvItems := ReadInt32(FS);
1015 | // GSS.Base.NumInvItems := ReadInt16(FS);
1016 | GSS.Base.NumDialog := ReadInt32(FS);
1017 | GSS.Base.NumDlgMessage := ReadInt32(FS);
1018 | GSS.Base.NumFonts := ReadInt32(FS);
1019 | GSS.Base.Color_Depth := ReadInt32(FS);
1020 | GSS.Base.Target_Win := ReadInt32(FS);
1021 | GSS.Base.Dialog_Bullet := ReadInt32(FS);
1022 | // GSS.Base.HotDot := ReadInt32(FS);
1023 | // GSS.Base.HotDotOuter := ReadInt32(FS);
1024 | GSS.Base.HotDot := ReadInt16(FS);
1025 | GSS.Base.HotDotOuter := ReadInt16(FS);
1026 | GSS.Base.UniqueID := ReadInt32(FS);
1027 | GSS.Base.NumGUI := ReadInt32(FS);
1028 | GSS.Base.NumCursors := ReadInt32(FS);
1029 | GSS.Base.Default_Resolution := ReadInt32(FS);
1030 | if (GSS.Base.Default_Resolution = kGameResolution_Custom) and (DtaVer >= kGameVersion_340_1) then
1031 | begin
1032 | ReadInt32(FS);
1033 | ReadInt32(FS);
1034 | end;
1035 | GSS.Base.Default_Lipsync_Frame := ReadInt32(FS);
1036 | GSS.Base.InvHotDotSprite := ReadInt32(FS);
1037 | for I := 0 to 16 do
1038 | GSS.Base.Reserved[i] := ReadInt32(FS);
1039 | for I := 0 to MAXGLOBALMES-1 do
1040 | GSS.Base.Messages[i] := ReadInt32(FS);
1041 | GSS.Base.Dict := ReadInt32(FS);
1042 | GSS.Base.GlobalScript := ReadInt32(FS);
1043 | GSS.Base.Chars := ReadInt32(FS);
1044 | GSS.Base.Compiled_Script := ReadInt32(FS);
1045 | end;
1046 |
1047 | procedure TGameDta.ReadInventoryItemInfo(FS: TFileStream);
1048 | var
1049 | i, m: Integer;
1050 | begin
1051 | for I := 0 to GSS.Base.NumInvItems - 1 do
1052 | begin
1053 | FS.ReadBuffer(GSS.InvInfo[i].Name, 28);
1054 | GSS.InvInfo[i].Pic := ReadInt32(FS);
1055 | GSS.InvInfo[i].CursorPic := ReadInt32(FS);
1056 | GSS.InvInfo[i].HotX := ReadInt32(FS);
1057 | GSS.InvInfo[i].HotY := ReadInt32(FS);
1058 | for m := 0 to 4 do
1059 | GSS.InvInfo[i].Reserved[m] := ReadInt32(FS);
1060 | GSS.InvInfo[i].Flags := ReadInt8(FS);
1061 | end;
1062 | end;
1063 |
1064 | procedure TGameDta.ReadMouseCursor(FS: TFileStream);
1065 | var
1066 | i: Integer;
1067 | begin
1068 | for I := 0 to GSS.Base.NumCursors - 1 do
1069 | begin
1070 | GSS.MCurs[i].Pic := ReadInt32(FS);
1071 | GSS.MCurs[i].HotX := ReadInt16(FS);
1072 | GSS.MCurs[i].HotY := ReadInt16(FS);
1073 | GSS.MCurs[i].View := ReadInt16(FS);
1074 | FS.ReadBuffer(GSS.MCurs[i].Name, 10);
1075 | GSS.MCurs[i].Flags := ReadInt8(FS);
1076 | end;
1077 | end;
1078 |
1079 | procedure TGameDta.ReadFromStream2(FS: TFileStream);
1080 | var
1081 | buf: array [0..39] of AnsiChar;
1082 | stlen, numToRead, numScriptModules, i, m, n: Integer;
1083 | begin
1084 | FS.Read(buf, 30);
1085 | buf[30] := #0;
1086 | if buf <> game_file_sig then
1087 | begin
1088 | Exit;
1089 | end;
1090 | DtaVer := ReadInt32(FS);
1091 | if DtaVer <> kGameVersion_321 then
1092 | begin
1093 | Exit;
1094 | end;
1095 | stlen := ReadInt32(FS);
1096 | FS.Seek(stlen, soFromCurrent);
1097 | FS.Read(GSS.Base, SizeOf(GameSetupStructBase));
1098 | FS.Read(GSS.GUID, MAX_GUID_LENGTH);
1099 | FS.Read(GSS.saveGameFileExtension, MAX_SG_EXT_LENGTH);
1100 | FS.Read(GSS.saveGameFolderName, MAX_SG_FOLDER_LEN);
1101 | FS.Read(GSS.FontFlags, GSS.Base.NumFonts);
1102 | FS.Read(GSS.FontOutline, GSS.Base.NumFonts);
1103 | numToRead := ReadInt32(FS);
1104 | FS.Read(GSS.SpriteFlags, numToRead);
1105 | FS.Read(GSS.InvInfo, SizeOf(InventoryItemInfo)*GSS.Base.NumInvItems);
1106 | FS.Read(GSS.MCurs, SizeOf(MouseCursor)*GSS.Base.NumCursors);
1107 | SetLength(GSS.CharScripts, GSS.Base.NumCharacters);
1108 | SetLength(GSS.InvScripts, GSS.Base.NumInvItems);
1109 | for i := 0 to GSS.Base.NumCharacters-1 do
1110 | GSS.CharScripts[i] := deserialize_interaction_scripts(FS);
1111 | for i := 0 to GSS.Base.NumInvItems-2 do
1112 | GSS.InvScripts[i] := deserialize_interaction_scripts(FS);
1113 | if GSS.Base.Dict > 0 then
1114 | GSS.Dict := read_dictionary(FS);
1115 | fread_script(FS); // Global Script
1116 | fread_script(FS); // Dialog Script
1117 | numScriptModules := ReadInt32(FS);
1118 | for i := 0 to numScriptModules - 1 do
1119 | fread_script(FS);
1120 | SetLength(GSS.views, GSS.Base.NumViews);
1121 | for i := 0 to GSS.Base.NumViews - 1 do
1122 | begin
1123 | FS.Read(GSS.views[i].numLoops, 2);
1124 | SetLength(GSS.views[i].loops, GSS.views[i].numLoops);
1125 | for m := 0 to GSS.views[i].numLoops - 1 do
1126 | begin
1127 | FS.Read(GSS.views[i].loops[m].numFrames, 2);
1128 | GSS.views[i].loops[m].flags := ReadInt32(FS);
1129 | SetLength(GSS.views[i].loops[m].frames, GSS.views[i].loops[m].numFrames);
1130 | for n := 0 to GSS.views[i].loops[m].numFrames - 1 do
1131 | FS.Read(GSS.views[i].loops[m].frames[n], SizeOf(ViewFrame))
1132 | end;
1133 | end;
1134 | SetLength(GSS.chars, GSS.Base.NumCharacters);
1135 | for i := 0 to GSS.Base.NumCharacters - 1 do
1136 | begin
1137 | FS.Read(GSS.chars[i], SizeOf(CharacterInfo));
1138 | AddExtrString(GSS.chars[i].name);
1139 | end;
1140 | FS.Read(GSS.lipSyncFrameLetters, 20 * 50);
1141 | SetLength(GSS.messages, MAXGLOBALMES);
1142 | for i := 0 to MAXGLOBALMES - 1 do
1143 | begin
1144 | GSS.messages[i] := read_string_decrypt(FS);
1145 | end;
1146 | SetLength(GSS.dialog, GSS.Base.NumDialog);
1147 | for i := 0 to GSS.Base.NumDialog - 1 do
1148 | begin
1149 | FS.Read(GSS.dialog[i], SizeOf(DialogTopic));
1150 | for m := 0 to GSS.dialog[i].numoptions - 1 do
1151 | AddExtrString(GSS.dialog[i].optionnames[m]);
1152 | end;
1153 | end;
1154 |
1155 |
1156 | procedure TGameDta.ReadFromFile(FileName: AnsiString);
1157 | begin
1158 | DtaF := TFileStream.Create(FileName, fmOpenRead);
1159 | ReadFromStream(DtaF);
1160 | DtaF.Free;
1161 | end;
1162 |
1163 | function TGameDta.GetGameName: AnsiString;
1164 | begin
1165 | Result := GSS.Base.GameName;
1166 | end;
1167 |
1168 | function TGameDta.GetGameID: uInt;
1169 | begin
1170 | Result := GSS.Base.UniqueID;
1171 | end;
1172 |
1173 | function TGameDta.GetDtaErr: UINT;
1174 | begin
1175 | Result := DtaErr;
1176 | end;
1177 |
1178 | function TGameDta.GetDtaVersion: UINT;
1179 | begin
1180 | Result := DtaVer;
1181 | end;
1182 |
1183 | function TGameDta.GetDtaVersionString: AnsiString;
1184 | begin
1185 | Result := DtaVerStr;
1186 | end;
1187 |
1188 | end.
--------------------------------------------------------------------------------
/AGS.GameDtaMod.pas:
--------------------------------------------------------------------------------
1 | unit AGS.GameDtaMod;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, System.Variants, System.Classes, System.SysUtils, System.Types, AGS.Script;
7 |
8 | type
9 | GUIListBox = record
10 | numItems, selected, topItem, mousexp, mouseyp: Integer;
11 | rowheight, num_items_fit: Integer;
12 | font, textcol, backcol, exflags: Integer;
13 | end;
14 | GUIObject = record
15 | guin, objn: Integer;
16 | flags: uInt;
17 | x, y: Integer;
18 | wid, hit: Integer;
19 | zorder: Integer;
20 | activated: Integer;
21 | scriptName: array [0..25] of AnsiChar;
22 | eventHandlers: array [0..9] of array [0..30] of AnsiChar;
23 | end;
24 | GUIMain = record
25 | Id: Integer;
26 | Name: AnsiString;
27 | Flags: Integer;
28 | X, Y, Width, Height: Integer;
29 | BgColor: Integer;
30 | BgImage: Integer;
31 | FgColor: Integer;
32 | Padding: Integer;
33 | PopupStyle: Integer;
34 | PopupAtMouseY: Integer;
35 | Transparency: Integer;
36 | ZOrder: Integer;
37 | FocusCtrl: Integer;
38 | HighlightCtrl: Integer;
39 | MouseOverCtrl: Integer;
40 | MouseWasAtX: Integer;
41 | MouseWasAtY: Integer;
42 | MouseDownCtrl: Integer;
43 | clickEventHandler: AnsiString;
44 | ControlCount: Integer;
45 | Visibility: Integer;
46 | end;
47 | DialogTopic = record
48 | optionnames: array [0..29] of array [0..149] of AnsiChar;
49 | optionflags: array [0..29] of Integer;
50 | optionscripts: Integer;
51 | entrypoints: array [0..29] of Short;
52 | startupentrypoint: Short;
53 | codesize: Short;
54 | numoptions: Integer;
55 | topicFlags: Integer;
56 | end;
57 | CharacterInfo = record
58 | defview: Integer;
59 | talkview: Integer;
60 | view: Integer;
61 | room, prevroom: Integer;
62 | x, y, wait: Integer;
63 | flags: Integer;
64 | following: Short;
65 | followinfo: Short;
66 | idleview: Integer;
67 | idletime, idleleft: Short;
68 | transparency: Short;
69 | baseline: Short;
70 | activeinv: Integer;
71 | talkcolor: Integer;
72 | thinkview: Integer;
73 | blinkview, blinkinterval: Short;
74 | blinktimer, blinkframe: Short;
75 | walkspeed_y, pic_yoffs: Short;
76 | z: Integer;
77 | walkwait: Integer;
78 | speech_anim_speed, reserved1: Short;
79 | blocking_width, blocking_height: Short;
80 | index_id: Integer;
81 | pic_xoffs, walkwaitcounter: Short;
82 | loop, frame: Short;
83 | walking, animating: Short;
84 | walkspeed, animspeed: Short;
85 | inv: array [0..300] of Short;
86 | actx, acty: Short;
87 | name: array [0..39] of AnsiChar;
88 | scrname: array [0..19] of AnsiChar;
89 | onn: AnsiChar;
90 | end;
91 | ViewFrame = record
92 | pic: Integer;
93 | xoffs, yoffs: Short;
94 | speed: Short;
95 | flags: Integer;
96 | sound: Integer;
97 | reserved_for_future: array [0..1] of Integer;
98 | end;
99 | ViewLoopNew = record
100 | numFrames: Short;
101 | flags: Integer;
102 | frames: array of ViewFrame;
103 | end;
104 | ViewStruct = record
105 | numLoops: Short;
106 | loops: array of ViewLoopNew;
107 | end;
108 | ViewStruct272 = record
109 | numLoops: Short;
110 | numframes: array [0..15] of Short;
111 | loopFlags: array [0..15] of Integer;
112 | frames: array [0..15] of array [0..19] of ViewFrame;
113 | end;
114 | WordsDictionary = record
115 | num_words: Integer;
116 | wordd: array of AnsiString;
117 | wordnum: array of Short;
118 | end;
119 | InteractionScripts = record
120 | NumEvents: Integer;
121 | ScriptFuncNames: array of AnsiString;
122 | end;
123 | InteractionVariable = record
124 | name: array [0..22] of AnsiChar;
125 | vtype: Byte;
126 | value: Integer;
127 | end;
128 | NewInteractionValue = record
129 | valType: Integer;
130 | val: Integer;
131 | extra: Integer;
132 | end;
133 | NewInteractionCommand = record
134 | Reserved: Integer;
135 | ctype: Integer;
136 | data: array [0..4] of NewInteractionValue;
137 | children: Integer;
138 | parent: Integer;
139 | end;
140 | NewInteractionCommandList = record
141 | numCommands: Integer;
142 | command: array [0..39] of NewInteractionCommand;
143 | timesRun: Integer;
144 | end;
145 | NewInteraction = record
146 | NumEvents: Integer;
147 | EventTypes: array [0..29] of Integer;
148 | TimesRun: array [0..29] of Integer;
149 | Response: array [0..29] of Integer;
150 | end;
151 | MouseCursor = record
152 | Pic: Integer;
153 | HotX: Word;
154 | HotY: Word;
155 | View: Word;
156 | Name: array [0..9] of AnsiChar;
157 | Flags: Byte;
158 | end;
159 | InventoryItemInfo = record
160 | Name: array [0..24] of AnsiChar;
161 | Pic: Integer;
162 | CursorPic: Integer;
163 | HotX: Integer;
164 | HotY: Integer;
165 | Reserved: array [0..4] of Integer;
166 | Flags: ShortInt;
167 | end;
168 | GameSetupStructBase = record
169 | GameName: array [0..49] of AnsiChar;
170 | Options: array [0..99] of Integer;
171 | PalUses: array [0..255] of AnsiChar;
172 | DefPal: array [0..255] of Integer;
173 | NumViews: Integer;
174 | NumCharacters: Integer;
175 | PlayerCharacter: Integer;
176 | TotalScore: Integer;
177 | NumInvItems: Word;
178 | NumDialog: Integer;
179 | NumDlgMessage: Integer;
180 | NumFonts: Integer;
181 | Color_Depth: Integer;
182 | Target_Win: Integer;
183 | Dialog_Bullet: Integer;
184 | HotDot: Word;
185 | HotDotOuter: Word;
186 | UniqueID: Integer;
187 | NumGUI: Integer;
188 | NumCursors: Integer;
189 | Default_Resolution: Integer;
190 | Default_Lipsync_Frame: Integer;
191 | InvHotDotSprite: Integer;
192 | Reserved: array [0..16] of Integer;
193 | Messages: array [0..499] of Integer;
194 | Dict: Integer;
195 | GlobalScript: Integer;
196 | Chars: Integer;
197 | Compiled_Script: Integer;
198 | end;
199 | GameSetupStruct = record
200 | Base: GameSetupStructBase;
201 | GUID: array [0..39] of AnsiChar;
202 | saveGameFileExtension: array [0..19] of AnsiChar;
203 | saveGameFolderName: array [0..49] of AnsiChar;
204 | FontFlags: array [0..14] of AnsiChar;
205 | FontOutline: array [0..14] of AnsiChar;
206 | SpriteFlags: array [0..29999] of AnsiChar;
207 | InvInfo: array [0..300] of InventoryItemInfo;
208 | MCurs: array [0..19] of MouseCursor;
209 | IntrChar: array of NewInteraction;
210 | CharScripts: array of InteractionScripts;
211 | InvScripts: array of InteractionScripts;
212 | Dict: WordsDictionary;
213 | views: array of ViewStruct;
214 | chars: array of CharacterInfo;
215 | lipSyncFrameLetters: array [0..19] of array [0..49] of AnsiChar;
216 | messages: array of AnsiString;
217 | dialog: array of DialogTopic;
218 | end;
219 | TGameDta = class(TObject)
220 | private
221 | DtaF: TFileStream;
222 | DtaVer, DtaErr, numstr, ndmp: Integer;
223 | DtaVerStr: AnsiString;
224 | GSS: GameSetupStruct;
225 | datstr: array of AnsiString;
226 | function ReadInt32(FS: TFileStream): Integer;
227 | function ReadInt16(FS: TFileStream): Word;
228 | function ReadInt8(FS: TFileStream): Byte;
229 | function ReadString(FS: TFileStream): AnsiString;
230 | function ReadStringNull(FS: TFileStream): AnsiString;
231 | function fgetstring(FS: TFileStream): AnsiString;
232 | function fgetstring_limit(FS: TFileStream; BufSize: Integer): AnsiString;
233 | function deserialize_interaction_scripts(FS: TFileStream): InteractionScripts;
234 | function deserialize_new_interaction(FS: TFileStream): NewInteraction;
235 | function deserialize_command_list(FS: TFileStream): NewInteractionCommandList;
236 | function read_string_decrypt(FS: TFileStream): AnsiString;
237 | function decrypt_text(Str: AnsiString): AnsiString;
238 | procedure fread_script(FS: TFileStream);
239 | function read_dictionary(FS: TFileStream): WordsDictionary;
240 | procedure strcpy(var arr: array of AnsiChar; str: AnsiString);
241 | procedure AddExtrString(Str: AnsiString);
242 | procedure GUIObjectRead(FS: TFileStream; Version: Integer);
243 | procedure read_gui(FS: TFileStream);
244 | procedure CustomPropertySchema(FS: TFileStream);
245 | procedure CustomProperties(FS: TFileStream);
246 | procedure ReadPluginsFromDisk(FS: TFileStream);
247 | procedure read_dialogs(FS: TFileStream);
248 | procedure ReadFromStream(FS: TFileStream);
249 | procedure ReadGameSetupStructBase(FS: TFileStream);
250 | procedure ReadInventoryItemInfo(FS: TFileStream);
251 | procedure ReadMouseCursor(FS: TFileStream);
252 | procedure ReadFromStream2(FS: TFileStream);
253 | procedure ReadFromFile(FileName: AnsiString);
254 | public
255 | constructor Create(FileName: AnsiString); overload;
256 | constructor Create(FS: TFileStream); overload;
257 | destructor Free; overload;
258 | function GetExtractedString(Index: Integer): AnsiString;
259 | function GetExtractedStringsCount: Integer;
260 | function GetGameName: AnsiString;
261 | function GetGameID: uInt;
262 | function GetDtaErr: UINT;
263 | function GetDtaVersion: UINT;
264 | function GetDtaVersionString: AnsiString;
265 | end;
266 |
267 | const
268 | game_file_sig = 'Adventure Creator Game File v2';
269 | passwencstring = 'Avis Durgan';
270 |
271 | // Game version
272 | kGameVersion_Undefined = 0;
273 | kGameVersion_230 = 12;
274 | kGameVersion_240 = 12;
275 | kGameVersion_250 = 18;
276 | kGameVersion_251 = 19; // same as 2.52
277 | kGameVersion_253 = 20;
278 | kGameVersion_254 = 21;
279 | kGameVersion_255 = 22;
280 | kGameVersion_256 = 24;
281 | kGameVersion_260 = 25;
282 | kGameVersion_261 = 26;
283 | kGameVersion_262 = 27;
284 | kGameVersion_270 = 31;
285 | kGameVersion_272 = 32;
286 | kGameVersion_300 = 35;
287 | kGameVersion_301 = 36;
288 | kGameVersion_310 = 37;
289 | kGameVersion_311 = 39;
290 | kGameVersion_312 = 40;
291 | kGameVersion_320 = 41;
292 | kGameVersion_321 = 42;
293 | kGameVersion_330 = 43;
294 | kGameVersion_331 = 44;
295 | kGameVersion_340_1 = 45;
296 | kGameVersion_340_2 = 46;
297 | kGameVersion_340_4 = 47;
298 | kGameVersion_Current = kGameVersion_340_4;
299 |
300 | // Game resolution
301 | kGameResolution_Undefined = -1;
302 | // definition of 320x200 in very old versions of the engine (somewhere pre-2.56)
303 | kGameResolution_Default = 0;
304 | kGameResolution_320x200 = 1;
305 | kGameResolution_320x240 = 2;
306 | kGameResolution_640x400 = 3;
307 | kGameResolution_640x480 = 4;
308 | kGameResolution_800x600 = 5;
309 | kGameResolution_1024x768 = 6;
310 | kGameResolution_1280x720 = 7;
311 | kGameResolution_Custom = 8;
312 |
313 | kGameResolution_LastLoRes = kGameResolution_320x240;
314 | kGameResolution_FirstHiRes = kGameResolution_640x400;
315 |
316 | // GUI version
317 | kGuiVersion_Initial = 0;
318 | kGuiVersion_214 = 100;
319 | kGuiVersion_222 = 101;
320 | kGuiVersion_230 = 102;
321 | kGuiVersion_unkn_103 = 103;
322 | kGuiVersion_unkn_104 = 104;
323 | kGuiVersion_260 = 105;
324 | kGuiVersion_unkn_106 = 106;
325 | kGuiVersion_unkn_107 = 107;
326 | kGuiVersion_unkn_108 = 108;
327 | kGuiVersion_unkn_109 = 109;
328 | kGuiVersion_270 = 110;
329 | kGuiVersion_272a = 111;
330 | kGuiVersion_272b = 112;
331 | kGuiVersion_272c = 113;
332 | kGuiVersion_272d = 114;
333 | kGuiVersion_272e = 115;
334 | kGuiVersion_330 = 116;
335 | kGuiVersion_331 = 117;
336 | kGuiVersion_340 = 118;
337 | kGuiVersion_Current = kGuiVersion_340;
338 | // Defines the oldest version of gui data that is complying to current
339 | // savedgame format; if the loaded game data is of this version or lower,
340 | // then this value will be written to savedgame instead of current version.
341 | kGuiVersion_ForwardCompatible = kGuiVersion_272e;
342 |
343 | MAX_INTER_FUNCTION_NAME_LENGTH = 200;
344 | MAXGLOBALMES = 500;
345 | MAX_FONTS = 15;
346 | MAX_SPRITES = 30000;
347 | MAX_CURSOR = 20;
348 | MAX_INV = 301;
349 | MAX_GUID_LENGTH = 40;
350 | MAX_SG_EXT_LENGTH = 20;
351 | MAX_SG_FOLDER_LEN = 50;
352 | MAX_NEWINTERACTION_EVENTS = 30;
353 | GUI_MAGIC = $cafebeef;
354 | GUI_VERSION = 116;
355 | MAX_CUSTOM_PROPERTY_VALUE_LENGTH = 500;
356 | MAX_OBJS_ON_GUI = 30;
357 | BASEGOBJ_SIZE = 7;
358 | MAX_GUIOBJ_SCRIPTNAME_LEN = 26;
359 | MAX_GUIOBJ_EVENTHANDLER_LEN = 30;
360 | MAXVIEWNAMELENGTH = 15;
361 | MAX_GUIOBJ_EVENTS = 10;
362 | GLF_SGINDEXVALID = 4;
363 |
364 | LEGACY_MAX_OBJS_ON_GUI = 30;
365 |
366 | GUIMAIN_RESERVED_INTS = 5;
367 | GUIMAIN_NAME_LENGTH = 16;
368 | GUIMAIN_EVENTHANDLER_LENGTH = 20;
369 | GUIMAIN_LEGACY_TW_FLAGS_SIZE = 4;
370 |
371 | //Errors
372 | DTA_ERROR_NULL = 0;
373 | DTA_ERROR_INC_FILE = 1;
374 | DTA_ERROR_INC_VER = 2;
375 |
376 | implementation
377 |
378 | procedure TGameDta.strcpy(var arr: array of AnsiChar; str: AnsiString);
379 | var
380 | i: Integer;
381 | begin
382 | for i := 1 to Length(str) do
383 | arr[i-1] := str[i];
384 | end;
385 |
386 | constructor TGameDta.Create(FileName: AnsiString);
387 | begin
388 | ReadFromFile(FileName);
389 | end;
390 |
391 | constructor TGameDta.Create(FS: TFileStream);
392 | begin
393 | ReadFromStream(FS);
394 | end;
395 |
396 | destructor TGameDta.Free;
397 | begin
398 | FillChar(GSS.Base, SizeOf(GameSetupStructBase), 0);
399 | end;
400 |
401 | function TGameDta.ReadInt32(FS: TFileStream): Integer;
402 | begin
403 | FS.ReadBuffer(Result, SizeOf(Integer));
404 | end;
405 |
406 | function TGameDta.ReadInt16(FS: TFileStream): Word;
407 | begin
408 | FS.ReadBuffer(Result, SizeOf(Word));
409 | end;
410 |
411 | function TGameDta.ReadInt8(FS: TFileStream): Byte;
412 | begin
413 | Result := 0;
414 | FS.ReadBuffer(Result, SizeOf(Byte));
415 | end;
416 |
417 | function TGameDta.ReadString(FS: TFileStream): AnsiString;
418 | var
419 | len: Integer;
420 | begin
421 | len := ReadInt32(FS);
422 | if len > 0 then
423 | begin
424 | SetLength(Result, len);
425 | FS.ReadBuffer(PAnsiString(Result)^, len);
426 | end;
427 | end;
428 |
429 | function TGameDta.ReadStringNull(FS: TFileStream): AnsiString;
430 | var
431 | buf: AnsiChar;
432 | begin
433 | Result := '';
434 | while FS.Position < FS.Size do
435 | begin
436 | FS.ReadBuffer(buf, 1);
437 | if buf <> #0 then
438 | Result := Result + buf
439 | else
440 | Break;
441 | end;
442 | end;
443 |
444 | function TGameDta.fgetstring(FS: TFileStream): AnsiString;
445 | begin
446 | Result := fgetstring_limit(FS, 50000000);
447 | end;
448 |
449 | function TGameDta.fgetstring_limit(FS: TFileStream; BufSize: Integer): AnsiString;
450 | var
451 | buf: AnsiChar;
452 | curc: Integer;
453 | begin
454 | Result := ''; curc := 0;
455 | while True do
456 | begin
457 | if (FS.Position = FS.Size) or (curc = BufSize) then
458 | Break;
459 | // buf := AnsiChar(ReadInt8(FS));
460 | FS.ReadBuffer(buf, SizeOf(buf));
461 | // FS.ReadBuffer(buf, 1);
462 | inc(curc);
463 | if buf = #0 then
464 | Break
465 | else
466 | Result := Result + buf;
467 | end;
468 | end;
469 |
470 | function TGameDta.deserialize_interaction_scripts(FS: TFileStream): InteractionScripts;
471 | var
472 | i: Integer;
473 | begin
474 | Result.NumEvents := ReadInt32(FS);
475 | SetLength(Result.ScriptFuncNames, Result.NumEvents);
476 | for i := 0 to Result.NumEvents - 1 do
477 | Result.ScriptFuncNames[i] := fgetstring_limit(FS, MAX_INTER_FUNCTION_NAME_LENGTH);
478 | end;
479 |
480 | function TGameDta.deserialize_new_interaction(FS: TFileStream): NewInteraction;
481 | var
482 | aa: Integer;
483 | begin
484 | if ReadInt32(FS) <> 1 then
485 | Exit;
486 | Result.NumEvents := ReadInt32(FS);
487 | if Result.NumEvents > MAX_NEWINTERACTION_EVENTS then
488 | Exit;
489 | for aa := 0 to Result.NumEvents - 1 do
490 | Result.EventTypes[aa] := ReadInt32(FS);
491 | for aa := 0 to Result.NumEvents - 1 do
492 | Result.Response[aa] := ReadInt32(FS);
493 | for aa := 0 to Result.NumEvents - 1 do
494 | if Result.Response[aa] <> 0 then
495 | deserialize_command_list(FS);
496 | end;
497 |
498 | function TGameDta.deserialize_command_list(FS: TFileStream): NewInteractionCommandList;
499 | var
500 | aa: Integer;
501 | begin
502 | FillChar(Result, SizeOf(NewInteractionCommandList), 0);
503 | Result.numCommands := ReadInt32(FS);
504 | Result.timesRun := ReadInt32(FS);
505 | for aa := 0 to Result.numCommands - 1 do
506 | FS.Read(Result.command[aa], sizeof(NewInteractionCommand));
507 | for aa := 0 to Result.numCommands - 1 do
508 | if Result.command[aa].children <> 0 then
509 | deserialize_command_list(FS);
510 | end;
511 |
512 | function TGameDta.read_string_decrypt(FS: TFileStream): AnsiString;
513 | var
514 | ss: Integer;
515 | buf: array of Byte;
516 | begin
517 | Result := '';
518 | ss := ReadInt32(FS);
519 | if (ss < 0) or (ss > 5000000) then
520 | begin
521 | FS.Seek(-4, soFromCurrent);
522 | Exit;
523 | end;
524 | SetLength(buf, ss);
525 | FS.Read(PChar(buf)^, ss);
526 | Result := decrypt_text(AnsiString(buf));
527 | SetLength(buf, 0);
528 | end;
529 |
530 | function TGameDta.decrypt_text(Str: AnsiString): AnsiString;
531 | var
532 | i, adx: Integer;
533 | nc: AnsiChar;
534 | begin
535 | Result := '';
536 | adx := 1;
537 | for i := 1 to Length(Str) do
538 | begin
539 | nc := AnsiChar(Byte(Str[i]) - Byte(passwencstring[adx]));
540 | if nc <> #0 then
541 | Result := Result + nc;
542 | inc(adx);
543 | if adx = 12 then
544 | adx := 1;
545 | end;
546 | end;
547 |
548 | function TGameDta.read_dictionary(FS: TFileStream): WordsDictionary;
549 | var
550 | i: Integer;
551 | begin
552 | Result.num_words := ReadInt32(FS);
553 | SetLength(Result.wordd, Result.num_words);
554 | SetLength(Result.wordnum, Result.num_words);
555 | for i := 0 to Result.num_words - 1 do
556 | begin
557 | Result.wordd[i] := read_string_decrypt(FS);
558 | FS.Read(Result.wordnum[i], 2);
559 | end;
560 | end;
561 |
562 | procedure TGameDta.fread_script(FS: TFileStream);
563 | var
564 | tmpscr: TScript;
565 | i, strcnt: Integer;
566 | begin
567 | tmpscr := TScript.Create(FS);
568 | tmpscr.ExtractStrings3;
569 | strcnt := tmpscr.GetExtractedStringsCount;
570 | for i := 0 to strcnt - 1 do
571 | AddExtrString(tmpscr.GetExtractedString(i));
572 | // tmpscr.Dump('new.dmp');
573 | tmpscr.Free;
574 | end;
575 |
576 | function TGameDta.GetExtractedString(Index: Integer): AnsiString;
577 | begin
578 | Result := datstr[Index];
579 | end;
580 |
581 | function TGameDta.GetExtractedStringsCount: Integer;
582 | begin
583 | Result := numstr;
584 | end;
585 |
586 | procedure TGameDta.AddExtrString(Str: AnsiString);
587 | var
588 | Found: Boolean;
589 | i: Integer;
590 | newstr: AnsiString;
591 | begin
592 | Found := False;
593 | newstr := '';
594 | for i := 1 to Length(Str) do
595 | if Str[i] <> #0 then
596 | newstr := newstr + Str[i];
597 | if (newStr = '') or (newStr[1] = #0) then
598 | Exit;
599 | for i := 0 to numstr - 1 do
600 | begin
601 | if datstr[i] = newStr then
602 | begin
603 | Found := True;
604 | Break;
605 | end;
606 | end;
607 | if not Found then
608 | begin
609 | inc(numstr);
610 | SetLength(datstr, numstr);
611 | datstr[numstr-1] := newStr;
612 | end;
613 | end;
614 |
615 | procedure TGameDta.GUIObjectRead(FS: TFileStream; Version: Integer);
616 | var
617 | numev, i: Integer;
618 | tmpobj: GUIObject;
619 | begin
620 | FillChar(tmpobj, SizeOf(GUIObject), 0);
621 | FS.Read(tmpobj, 4*BASEGOBJ_SIZE);
622 | if Version >= kGuiVersion_unkn_106 then
623 | strcpy(tmpobj.scriptName, fgetstring_limit(FS, MAX_GUIOBJ_SCRIPTNAME_LEN))
624 | else
625 | tmpobj.scriptName[0] := #0;
626 | if Version >= kGuiVersion_unkn_108 then
627 | begin
628 | i := FS.Position;
629 | numev := ReadInt32(FS);
630 | for i := 0 to numev - 1 do
631 | fgetstring_limit(FS, MAX_GUIOBJ_EVENTHANDLER_LEN + 1);
632 | end;
633 | end;
634 |
635 | procedure TGameDta.read_gui(FS: TFileStream);
636 | var
637 | gui_version, exflags, numgui, numguibuts, numguilabels, numguiinv, numguislider, numguitext, numguilist, numItems, i, m, buflen: Integer;
638 | buf: array of AnsiChar;
639 | tmpgui: GUIMain;
640 | tmplb: GUIListBox;
641 | begin
642 | if uInt(ReadInt32(FS)) <> GUI_MAGIC then
643 | Exit;
644 | gui_version := ReadInt32(FS);
645 | if gui_version < kGuiVersion_214 then
646 | numgui := gui_version
647 | else if gui_version > kGuiVersion_Current then
648 | Exit
649 | else numgui := ReadInt32(FS);
650 | if (numgui < 0) or (numgui > 1000) then
651 | Exit;
652 | SetLength(buf, 1000);
653 | // import the main GUI elements
654 | for i := 0 to numgui - 1 do
655 | begin
656 | FS.Seek(GUIMAIN_LEGACY_TW_FLAGS_SIZE, soFromCurrent);
657 | if gui_version < kGuiVersion_340 then
658 | begin
659 | SetLength(tmpgui.name, GUIMAIN_NAME_LENGTH);
660 | FS.ReadBuffer(PAnsiString(tmpgui.name)^, GUIMAIN_NAME_LENGTH);
661 | SetLength(tmpgui.clickEventHandler, GUIMAIN_EVENTHANDLER_LENGTH);
662 | FS.ReadBuffer(PAnsiString(tmpgui.clickEventHandler)^, GUIMAIN_EVENTHANDLER_LENGTH);
663 | end else begin
664 | tmpgui.name := ReadStringNull(FS);
665 | tmpgui.clickEventHandler := ReadStringNull(FS);
666 | end;
667 | tmpgui.X := ReadInt32(FS);
668 | tmpgui.Y := ReadInt32(FS);
669 | tmpgui.Width := ReadInt32(FS);
670 | tmpgui.Height := ReadInt32(FS);
671 | tmpgui.FocusCtrl := ReadInt32(FS);
672 | tmpgui.ControlCount := ReadInt32(FS);
673 | tmpgui.PopupStyle := ReadInt32(FS);
674 | tmpgui.PopupAtMouseY := ReadInt32(FS);
675 | tmpgui.BgColor := ReadInt32(FS);
676 | tmpgui.BgImage := ReadInt32(FS);
677 | tmpgui.FgColor := ReadInt32(FS);
678 | tmpgui.MouseOverCtrl := ReadInt32(FS);
679 | tmpgui.MouseWasAtX := ReadInt32(FS);
680 | tmpgui.MouseWasAtY := ReadInt32(FS);
681 | tmpgui.MouseDownCtrl := ReadInt32(FS);
682 | tmpgui.HighlightCtrl := ReadInt32(FS);
683 | tmpgui.Flags := ReadInt32(FS);
684 | tmpgui.Transparency := ReadInt32(FS);
685 | tmpgui.ZOrder := ReadInt32(FS);
686 | tmpgui.Id := ReadInt32(FS);
687 | tmpgui.Padding := ReadInt32(FS);
688 | FS.Seek(SizeOf(Integer)*GUIMAIN_RESERVED_INTS, soFromCurrent);
689 | tmpgui.Visibility := ReadInt32(FS);
690 | if gui_version < kGuiVersion_340 then
691 | begin
692 | FS.Seek(SizeOf(Integer)*LEGACY_MAX_OBJS_ON_GUI, soFromCurrent);
693 | FS.Seek(SizeOf(Integer)*LEGACY_MAX_OBJS_ON_GUI, soFromCurrent);
694 | end else begin
695 | if tmpgui.ControlCount > 0 then
696 | FS.Seek(SizeOf(Integer)*tmpgui.ControlCount, soFromCurrent);
697 | end;
698 | // FS.Read(tmpgui, SizeOf(GUIMain));
699 | end;
700 | // import the buttons
701 | numguibuts := ReadInt32(FS);
702 | for i := 0 to numguibuts - 1 do
703 | begin
704 | GUIObjectRead(FS, gui_version);
705 | FS.Seek(4 * 12, soFromCurrent);
706 | SetLength(buf, 50);
707 | FS.Read(PAnsiChar(buf)^, 50);
708 | AddExtrString(AnsiString(buf));
709 | if gui_version >= 111 then
710 | FS.Seek(8, soFromCurrent);
711 | SetLength(buf, 0);
712 | end;
713 | // labels
714 | numguilabels := ReadInt32(FS);
715 | for i := 0 to numguilabels - 1 do
716 | begin
717 | GUIObjectRead(FS, gui_version);
718 | if gui_version < kGuiVersion_272c then
719 | begin
720 | SetLength(buf, 200);
721 | FS.ReadBuffer(PAnsiChar(buf)^, 200);
722 | end else begin
723 | buflen := ReadInt32(FS);
724 | SetLength(buf, buflen);
725 | FS.ReadBuffer(PAnsiChar(buf)^, buflen);
726 | end;
727 | AddExtrString(AnsiString(buf));
728 | FS.Seek(4*3, soFromCurrent);
729 | SetLength(buf, 0);
730 | end;
731 | // Unknown GUI map
732 | numguilabels := ReadInt32(FS);
733 | for i := 0 to numguilabels - 1 do
734 | begin
735 | GUIObjectRead(FS, gui_version);
736 | end;
737 | // Unknown GUI lables
738 | numguilabels := ReadInt32(FS);
739 | for i := 0 to numguilabels - 1 do
740 | begin
741 | GUIObjectRead(FS, gui_version);
742 | FS.Seek(21, soFromCurrent);
743 | end;
744 | // inv controls
745 | FS.Seek(12, soFromCurrent);
746 | numguiinv := ReadInt32(FS);
747 | for i := 0 to numguiinv - 1 do
748 | begin
749 | GUIObjectRead(FS, gui_version);
750 | if gui_version >= kGuiVersion_unkn_109 then
751 | begin
752 | FS.Seek(16, soFromCurrent);
753 | end;
754 | end;
755 | // sliders
756 | if gui_version >= kGuiVersion_214 then
757 | begin
758 | numguislider := ReadInt32(FS);
759 | for i := 0 to numguislider - 1 do
760 | begin
761 | GUIObjectRead(FS, gui_version);
762 | if gui_version >= kGuiVersion_unkn_104 then
763 | FS.Seek(7*4, soFromCurrent)
764 | else
765 | FS.Seek(4*4, soFromCurrent);
766 | end;
767 | end;
768 | // text boxes
769 | if gui_version >= kGuiVersion_222 then
770 | begin
771 | numguitext := ReadInt32(FS);
772 | for i := 0 to numguitext - 1 do
773 | begin
774 | GUIObjectRead(FS, gui_version);
775 | SetLength(buf, 200);
776 | FS.Read(PAnsiChar(buf)^, 200);
777 | FS.Seek(12, soFromCurrent);
778 | AddExtrString(AnsiString(buf));
779 | SetLength(buf, 0);
780 | end;
781 | end;
782 | // list boxes
783 | if gui_version >= kGuiVersion_222 then
784 | begin
785 | numguilist := ReadInt32(FS);
786 | for i := 0 to numguilist - 1 do
787 | begin
788 | GUIObjectRead(FS, gui_version);
789 | FS.Read(tmplb, SizeOf(tmplb));
790 | // FS.Seek(40, soFromCurrent);
791 | if gui_version >= 112 then
792 | FS.Seek(8, soFromCurrent);
793 | if gui_version >= 107 then
794 | FS.Seek(4, soFromCurrent);
795 | for m := 0 to tmplb.numItems - 1 do
796 | begin
797 | SetLength(buf, 1000);
798 | PAnsiString(buf)^ := fgetstring(FS);
799 | AddExtrString(AnsiString(buf));
800 | SetLength(buf, 0);
801 | end;
802 | if (gui_version >= 114) and ((tmplb.exflags and GLF_SGINDEXVALID) = GLF_SGINDEXVALID) then
803 | FS.Seek(2*tmplb.numItems, soFromCurrent);
804 | end;
805 | end;
806 | SetLength(buf, 0);
807 | end;
808 |
809 | procedure TGameDta.CustomPropertySchema(FS: TFileStream);
810 | var
811 | numProps, i: Integer;
812 | buf: AnsiString;
813 | begin
814 | if ReadInt32(FS) <> 1 then
815 | Exit;
816 | numProps := ReadInt32(FS);
817 | for i := 0 to numProps - 1 do
818 | begin
819 | buf := fgetstring_limit(FS, 20);
820 | buf := fgetstring_limit(FS, 100);
821 | buf := fgetstring_limit(FS, MAX_CUSTOM_PROPERTY_VALUE_LENGTH);
822 | AddExtrString(buf);
823 | ReadInt32(FS);
824 | end;
825 | end;
826 |
827 | procedure TGameDta.CustomProperties(FS: TFileStream);
828 | var
829 | numProps, i: Integer;
830 | buf: AnsiString;
831 | begin
832 | if ReadInt32(FS) <> 1 then
833 | Exit;
834 | numProps := ReadInt32(FS);
835 | for i := 0 to numProps - 1 do
836 | begin
837 | buf := fgetstring_limit(FS, 200);
838 | buf := fgetstring_limit(FS, MAX_CUSTOM_PROPERTY_VALUE_LENGTH);
839 | AddExtrString(buf);
840 | end;
841 | end;
842 |
843 | procedure TGameDta.ReadPluginsFromDisk(FS: TFileStream);
844 | var
845 | numPlug, datasize, i: Integer;
846 | begin
847 | if ReadInt32(FS) <> 1 then
848 | Exit;
849 | numPlug := ReadInt32(FS);
850 | for i := 0 to numPlug - 1 do
851 | begin
852 | fgetstring(FS);
853 | datasize := ReadInt32(FS);
854 | FS.Seek(datasize, soFromCurrent);
855 | end;
856 | end;
857 |
858 | procedure TGameDta.read_dialogs(FS: TFileStream);
859 | begin
860 |
861 | end;
862 |
863 | procedure TGameDta.ReadFromStream(FS: TFileStream);
864 | var
865 | buf: array [0..39] of AnsiChar;
866 | bufstr: array of AnsiChar;
867 | stlen, numScriptModules, numGlobalVars, i, m, n, newlen: Integer;
868 | numToRead, numToRead2: UINT;
869 | news, buf2: AnsiString;
870 | begin
871 | FS.Read(buf, 30);
872 | buf[30] := #0;
873 | if buf <> game_file_sig then
874 | begin
875 | DtaErr := DTA_ERROR_INC_FILE;
876 | Exit;
877 | end;
878 | DtaVer := ReadInt32(FS);
879 | if (DtaVer > kGameVersion_Current) or (DtaVer < 0) then
880 | begin
881 | DtaErr := DTA_ERROR_INC_VER;
882 | Exit;
883 | end;
884 | stlen := ReadInt32(FS);
885 | SetLength(DtaVerStr, stlen);
886 | FS.ReadBuffer(PAnsiString(DtaVerStr)^, stlen);
887 | // FS.Seek(stlen, soFromCurrent);
888 | ReadGameSetupStructBase(FS);
889 | if DtaVer >= kGameVersion_272 then
890 | begin
891 | FS.ReadBuffer(GSS.GUID, MAX_GUID_LENGTH);
892 | FS.ReadBuffer(GSS.saveGameFileExtension, MAX_SG_EXT_LENGTH);
893 | FS.ReadBuffer(GSS.saveGameFolderName, MAX_SG_FOLDER_LEN);
894 | end;
895 | FS.ReadBuffer(GSS.FontFlags, GSS.Base.NumFonts);
896 | FS.ReadBuffer(GSS.FontOutline, GSS.Base.NumFonts);
897 | if DtaVer < kGameVersion_256 then
898 | numToRead := 6000
899 | else
900 | numToRead := ReadInt32(FS);
901 | FS.Seek(numToRead, soFromCurrent); // SpriteFlags
902 | for i := 0 to GSS.Base.NumFonts - 1 do // Skip font filenames
903 | begin
904 | FS.ReadBuffer(stlen, SizeOf(Integer));
905 | SetLength(bufstr, stlen);
906 | FS.ReadBuffer(PAnsiChar(bufstr)^, stlen);
907 | // FS.Seek(stlen, soFromCurrent);
908 | end;
909 | ReadInventoryItemInfo(FS);
910 | for i := 0 to GSS.Base.NumInvItems - 1 do
911 | AddExtrString(GSS.InvInfo[i].Name);
912 | ReadMouseCursor(FS);
913 | SetLength(GSS.CharScripts, GSS.Base.NumCharacters);
914 | SetLength(GSS.InvScripts, GSS.Base.NumInvItems);
915 | if DtaVer > kGameVersion_272 then
916 | begin
917 | for i := 0 to GSS.Base.NumCharacters-1 do
918 | GSS.CharScripts[i] := deserialize_interaction_scripts(FS);
919 | for i := 0 to GSS.Base.NumInvItems-2 do
920 | GSS.InvScripts[i] := deserialize_interaction_scripts(FS);
921 | end else begin
922 | numGlobalVars := FS.Position;
923 | for i := 0 to GSS.Base.NumCharacters-1 do
924 | deserialize_new_interaction(FS);
925 | for i := 0 to GSS.Base.NumInvItems-1 do
926 | deserialize_new_interaction(FS);
927 | numGlobalVars := FS.Position;
928 | numGlobalVars := ReadInt32(FS);
929 | FS.Seek(SizeOf(InteractionVariable)*numGlobalVars, soFromCurrent); // MCurs
930 | end;
931 | if GSS.Base.Dict > 0 then
932 | GSS.Dict := read_dictionary(FS);
933 | // Loading scripts
934 | fread_script(FS); // Global Script
935 | if DtaVer > kGameVersion_310 then
936 | fread_script(FS); // Dialog Script
937 | if DtaVer >= kGameVersion_270 then
938 | begin
939 | numScriptModules := ReadInt32(FS);
940 | for i := 0 to numScriptModules - 1 do
941 | fread_script(FS);
942 | end;
943 | // SetLength(GSS.views, GSS.Base.NumViews);
944 | if DtaVer > kGameVersion_272 then
945 | begin
946 | for i := 0 to GSS.Base.NumViews - 1 do
947 | begin
948 | FS.Read(numToRead, 2);
949 | for m := 0 to numToRead - 1 do
950 | begin
951 | FS.Read(numToRead2, 2);
952 | FS.Seek(4, soFromCurrent);
953 | FS.Seek(SizeOf(ViewFrame)*numToRead2, soFromCurrent);
954 | end;
955 | end;
956 | end else begin
957 | FS.Seek(SizeOf(ViewStruct272)*GSS.Base.NumViews, soFromCurrent);
958 | end;
959 | // <= 2.1 skip unknown data
960 | if DtaVer <= kGameVersion_251 then
961 | FS.Seek(ReadInt32(FS) * $204, soFromCurrent);
962 |
963 | SetLength(GSS.chars, GSS.Base.NumCharacters);
964 | for i := 0 to GSS.Base.NumCharacters - 1 do
965 | begin
966 | FS.Read(GSS.chars[i], SizeOf(CharacterInfo));
967 | AddExtrString(GSS.chars[i].name);
968 | end;
969 | FS.Seek(20 * 50, soFromCurrent); // lipSyncFrameLetters
970 | SetLength(GSS.messages, MAXGLOBALMES);
971 | for i := 0 to MAXGLOBALMES - 1 do
972 | begin
973 | GSS.messages[i] := read_string_decrypt(FS);
974 | end;
975 | // Reading dialogs;
976 | SetLength(GSS.dialog, GSS.Base.NumDialog);
977 | numScriptModules := FS.Position;
978 | for i := 0 to GSS.Base.NumDialog - 1 do
979 | begin
980 | FS.Read(GSS.dialog[i], SizeOf(DialogTopic));
981 | numScriptModules := FS.Position;
982 | for m := 0 to GSS.dialog[i].numoptions - 1 do
983 | AddExtrString(GSS.dialog[i].optionnames[m]);
984 | end;
985 | numScriptModules := FS.Position;
986 | if DtaVer < kGameVersion_272 then
987 | begin
988 | for i := 0 to GSS.Base.NumDialog - 1 do
989 | begin
990 | if GSS.dialog[i].optionscripts <> 0 then
991 | begin
992 | SetLength(bufstr, GSS.dialog[i].codesize + 10);
993 | FS.Read(PChar(bufstr)^, GSS.dialog[i].codesize);
994 | SetLength(bufstr, 0);
995 | end;
996 | NumToRead := ReadInt32(FS);
997 | if NumToRead <= 1 then
998 | FS.Seek(1, soFromCurrent);
999 | SetLength(bufstr, NumToRead + 1);
1000 | FS.Read(PChar(bufstr)^, NumToRead);
1001 | // AddExtrString(decrypt_text(AnsiString(bufstr)));
1002 | SetLength(bufstr, 0);
1003 | end;
1004 | // for i := 0 to GSS.Base.NumDlgMessage - 1 do
1005 | // if (DtaVer >= 26) then
1006 | // AddExtrString(read_string_decrypt(FS));
1007 | if DtaVer < kGameVersion_260 then
1008 | begin
1009 | end else begin
1010 | while True do
1011 | begin
1012 | numToRead := FS.Position;
1013 | NumToRead := ReadInt32(FS);
1014 | if NumToRead = $CAFEBEEF then
1015 | begin
1016 | FS.Seek(-4, soFromCurrent);
1017 | Break;
1018 | end;
1019 | SetLength(bufstr, NumToRead + 1);
1020 | FS.Read(PChar(bufstr)^, NumToRead);
1021 | Inc(i);
1022 | end;
1023 | end;
1024 | end;
1025 | read_gui(FS);
1026 | i := FS.Position;
1027 | ReadPluginsFromDisk(FS);
1028 | CustomPropertySchema(FS);
1029 | for i := 0 to GSS.Base.NumCharacters - 1 do
1030 | CustomProperties(FS);
1031 | for i := 0 to GSS.Base.NumInvItems - 1 do
1032 | CustomProperties(FS);
1033 | // for i := 0 to GSS.Base.NumViews - 1 do
1034 | // begin
1035 | // news := fgetstring_limit(FS, MAXVIEWNAMELENGTH);
1036 | // AddExtrString(news);
1037 | // end;
1038 | end;
1039 |
1040 | procedure TGameDta.ReadGameSetupStructBase(FS: TFileStream);
1041 | var
1042 | i: Integer;
1043 | curpos, curr: UINT;
1044 | begin
1045 | // FS.ReadBuffer(GSS.Base.GameName, Length(GSS.Base.GameName)*SizeOf(GSS.Base.GameName[0]));
1046 | FS.ReadBuffer(GSS.Base.GameName, 52);
1047 | for i := 0 to 99 do
1048 | GSS.Base.Options[i] := ReadInt32(FS);
1049 | FS.ReadBuffer(GSS.Base.PalUses, Length(GSS.Base.PalUses)*SizeOf(GSS.Base.PalUses[i]));
1050 | for i := 0 to 255 do
1051 | GSS.Base.DefPal[i] := ReadInt32(FS);
1052 | GSS.Base.NumViews := ReadInt32(FS);
1053 | GSS.Base.NumCharacters := ReadInt32(FS);
1054 | GSS.Base.PlayerCharacter := ReadInt32(FS);
1055 | GSS.Base.TotalScore := ReadInt32(FS);
1056 | GSS.Base.NumInvItems := ReadInt32(FS);
1057 | // GSS.Base.NumInvItems := ReadInt16(FS);
1058 | GSS.Base.NumDialog := ReadInt32(FS);
1059 | GSS.Base.NumDlgMessage := ReadInt32(FS);
1060 | GSS.Base.NumFonts := ReadInt32(FS);
1061 | GSS.Base.Color_Depth := ReadInt32(FS);
1062 | GSS.Base.Target_Win := ReadInt32(FS);
1063 | GSS.Base.Dialog_Bullet := ReadInt32(FS);
1064 | // GSS.Base.HotDot := ReadInt32(FS);
1065 | // GSS.Base.HotDotOuter := ReadInt32(FS);
1066 | GSS.Base.HotDot := ReadInt16(FS);
1067 | GSS.Base.HotDotOuter := ReadInt16(FS);
1068 | GSS.Base.UniqueID := ReadInt32(FS);
1069 | GSS.Base.NumGUI := ReadInt32(FS);
1070 | GSS.Base.NumCursors := ReadInt32(FS);
1071 | GSS.Base.Default_Resolution := ReadInt32(FS);
1072 | if (GSS.Base.Default_Resolution = kGameResolution_Custom) and (DtaVer >= kGameVersion_340_1) then
1073 | begin
1074 | ReadInt32(FS);
1075 | ReadInt32(FS);
1076 | end;
1077 | GSS.Base.Default_Lipsync_Frame := ReadInt32(FS);
1078 | GSS.Base.InvHotDotSprite := ReadInt32(FS);
1079 | for I := 0 to 16 do
1080 | GSS.Base.Reserved[i] := ReadInt32(FS);
1081 | for I := 0 to MAXGLOBALMES-1 do
1082 | GSS.Base.Messages[i] := ReadInt32(FS);
1083 | GSS.Base.Dict := ReadInt32(FS);
1084 | GSS.Base.GlobalScript := ReadInt32(FS);
1085 | GSS.Base.Chars := ReadInt32(FS);
1086 | GSS.Base.Compiled_Script := ReadInt32(FS);
1087 | end;
1088 |
1089 | procedure TGameDta.ReadInventoryItemInfo(FS: TFileStream);
1090 | var
1091 | i, m: Integer;
1092 | begin
1093 | for I := 0 to GSS.Base.NumInvItems - 1 do
1094 | begin
1095 | FS.ReadBuffer(GSS.InvInfo[i].Name, 28);
1096 | GSS.InvInfo[i].Pic := ReadInt32(FS);
1097 | GSS.InvInfo[i].CursorPic := ReadInt32(FS);
1098 | GSS.InvInfo[i].HotX := ReadInt32(FS);
1099 | GSS.InvInfo[i].HotY := ReadInt32(FS);
1100 | for m := 0 to 4 do
1101 | GSS.InvInfo[i].Reserved[m] := ReadInt32(FS);
1102 | GSS.InvInfo[i].Flags := ReadInt32(FS);
1103 | end;
1104 | end;
1105 |
1106 | procedure TGameDta.ReadMouseCursor(FS: TFileStream);
1107 | var
1108 | i: Integer;
1109 | begin
1110 | for I := 0 to GSS.Base.NumCursors - 1 do
1111 | begin
1112 | GSS.MCurs[i].Pic := ReadInt32(FS);
1113 | GSS.MCurs[i].HotX := ReadInt16(FS);
1114 | GSS.MCurs[i].HotY := ReadInt16(FS);
1115 | GSS.MCurs[i].View := ReadInt16(FS);
1116 | FS.ReadBuffer(GSS.MCurs[i].Name, 10);
1117 | GSS.MCurs[i].Flags := ReadInt32(FS);
1118 | end;
1119 | end;
1120 |
1121 | procedure TGameDta.ReadFromStream2(FS: TFileStream);
1122 | var
1123 | buf: array [0..39] of AnsiChar;
1124 | stlen, numToRead, numScriptModules, i, m, n: Integer;
1125 | begin
1126 | FS.Read(buf, 30);
1127 | buf[30] := #0;
1128 | if buf <> game_file_sig then
1129 | begin
1130 | Exit;
1131 | end;
1132 | DtaVer := ReadInt32(FS);
1133 | if DtaVer <> kGameVersion_321 then
1134 | begin
1135 | Exit;
1136 | end;
1137 | stlen := ReadInt32(FS);
1138 | FS.Seek(stlen, soFromCurrent);
1139 | FS.Read(GSS.Base, SizeOf(GameSetupStructBase));
1140 | FS.Read(GSS.GUID, MAX_GUID_LENGTH);
1141 | FS.Read(GSS.saveGameFileExtension, MAX_SG_EXT_LENGTH);
1142 | FS.Read(GSS.saveGameFolderName, MAX_SG_FOLDER_LEN);
1143 | FS.Read(GSS.FontFlags, GSS.Base.NumFonts);
1144 | FS.Read(GSS.FontOutline, GSS.Base.NumFonts);
1145 | numToRead := ReadInt32(FS);
1146 | FS.Read(GSS.SpriteFlags, numToRead);
1147 | FS.Read(GSS.InvInfo, SizeOf(InventoryItemInfo)*GSS.Base.NumInvItems);
1148 | FS.Read(GSS.MCurs, SizeOf(MouseCursor)*GSS.Base.NumCursors);
1149 | SetLength(GSS.CharScripts, GSS.Base.NumCharacters);
1150 | SetLength(GSS.InvScripts, GSS.Base.NumInvItems);
1151 | for i := 0 to GSS.Base.NumCharacters-1 do
1152 | GSS.CharScripts[i] := deserialize_interaction_scripts(FS);
1153 | for i := 0 to GSS.Base.NumInvItems-2 do
1154 | GSS.InvScripts[i] := deserialize_interaction_scripts(FS);
1155 | if GSS.Base.Dict > 0 then
1156 | GSS.Dict := read_dictionary(FS);
1157 | fread_script(FS); // Global Script
1158 | fread_script(FS); // Dialog Script
1159 | numScriptModules := ReadInt32(FS);
1160 | for i := 0 to numScriptModules - 1 do
1161 | fread_script(FS);
1162 | SetLength(GSS.views, GSS.Base.NumViews);
1163 | for i := 0 to GSS.Base.NumViews - 1 do
1164 | begin
1165 | FS.Read(GSS.views[i].numLoops, 2);
1166 | SetLength(GSS.views[i].loops, GSS.views[i].numLoops);
1167 | for m := 0 to GSS.views[i].numLoops - 1 do
1168 | begin
1169 | FS.Read(GSS.views[i].loops[m].numFrames, 2);
1170 | GSS.views[i].loops[m].flags := ReadInt32(FS);
1171 | SetLength(GSS.views[i].loops[m].frames, GSS.views[i].loops[m].numFrames);
1172 | for n := 0 to GSS.views[i].loops[m].numFrames - 1 do
1173 | FS.Read(GSS.views[i].loops[m].frames[n], SizeOf(ViewFrame))
1174 | end;
1175 | end;
1176 | SetLength(GSS.chars, GSS.Base.NumCharacters);
1177 | for i := 0 to GSS.Base.NumCharacters - 1 do
1178 | begin
1179 | FS.Read(GSS.chars[i], SizeOf(CharacterInfo));
1180 | AddExtrString(GSS.chars[i].name);
1181 | end;
1182 | FS.Read(GSS.lipSyncFrameLetters, 20 * 50);
1183 | SetLength(GSS.messages, MAXGLOBALMES);
1184 | for i := 0 to MAXGLOBALMES - 1 do
1185 | begin
1186 | GSS.messages[i] := read_string_decrypt(FS);
1187 | end;
1188 | SetLength(GSS.dialog, GSS.Base.NumDialog);
1189 | for i := 0 to GSS.Base.NumDialog - 1 do
1190 | begin
1191 | FS.Read(GSS.dialog[i], SizeOf(DialogTopic));
1192 | for m := 0 to GSS.dialog[i].numoptions - 1 do
1193 | AddExtrString(GSS.dialog[i].optionnames[m]);
1194 | end;
1195 | end;
1196 |
1197 |
1198 | procedure TGameDta.ReadFromFile(FileName: AnsiString);
1199 | begin
1200 | DtaF := TFileStream.Create(FileName, fmOpenRead);
1201 | ReadFromStream(DtaF);
1202 | DtaF.Free;
1203 | end;
1204 |
1205 | function TGameDta.GetGameName: AnsiString;
1206 | begin
1207 | Result := GSS.Base.GameName;
1208 | end;
1209 |
1210 | function TGameDta.GetGameID: uInt;
1211 | begin
1212 | Result := GSS.Base.UniqueID;
1213 | end;
1214 |
1215 | function TGameDta.GetDtaErr: UINT;
1216 | begin
1217 | Result := DtaErr;
1218 | end;
1219 |
1220 | function TGameDta.GetDtaVersion: UINT;
1221 | begin
1222 | Result := DtaVer;
1223 | end;
1224 |
1225 | function TGameDta.GetDtaVersionString: AnsiString;
1226 | begin
1227 | Result := DtaVerStr;
1228 | end;
1229 |
1230 | end.
--------------------------------------------------------------------------------