DEADSOFTWARE

Fix access violation on x86_64
[d2df-sdl.git] / src / shared / MAPREADER.pas
1 (* Copyright (C) DooM 2D:Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$MODE DELPHI}
17 unit MAPREADER;
19 {
20 -----------------------------------
21 MAPREADER.PAS ÂÅÐÑÈß ÎÒ 13.11.07
23 Ïîääåðæêà êàðò âåðñèè 1
24 -----------------------------------
25 }
27 interface
29 uses
30 MAPSTRUCT;
32 type
33 TDataBlock = packed record
34 Block: TBlock;
35 Data: Pointer;
36 end;
38 TDataBlocksArray = packed array of TDataBlock;
40 TMapReader = class(TObject)
41 private
42 FError: Byte;
43 FVersion: Byte;
44 FDataBlocks: TDataBlocksArray;
45 function GetBlocks(BlocksType: Byte): TDataBlocksArray;
46 public
47 constructor Create();
48 destructor Destroy(); override;
49 function LoadMap(Data: Pointer): Boolean;
50 procedure FreeMap();
51 function HandledVersion(): Byte; virtual;
53 property GetError: Byte read FError;
54 property GetVersion: Byte read FVersion;
55 end;
57 TMapReader_1 = class(TMapReader)
58 private
59 public
60 function GetMapHeader(): TMapHeaderRec_1;
61 function GetTextures(): TTexturesRec1Array;
62 function GetPanels(): TPanelsRec1Array;
63 function GetItems(): TItemsRec1Array;
64 function GetAreas(): TAreasRec1Array;
65 function GetMonsters(): TMonsterRec1Array;
66 function GetTriggers(): TTriggersRec1Array;
67 function HandledVersion(): Byte; override;
68 end;
70 const
71 MAP_ERROR_NONE = $00;
72 MAP_ERROR_SIGNATURE = $01;
73 MAP_ERROR_VERSION = $02;
75 NNF_NO_NAME = 0;
76 NNF_NAME_BEFORE = 1;
77 NNF_NAME_EQUALS = 2;
78 NNF_NAME_AFTER = 3;
80 function g_Texture_NumNameFindStart(name: String): Boolean;
81 function g_Texture_NumNameFindNext(var newName: String): Byte;
83 implementation
85 uses
86 SysUtils, BinEditor, MAPDEF;
88 var
89 NNF_PureName: String; // Èìÿ òåêñòóðû áåç öèôð â êîíöå
90 NNF_FirstNum: Integer; // ×èñëî ó íà÷àëüíîé òåêñòóðû
91 NNF_CurrentNum: Integer; // Ñëåäóþùåå ÷èñëî ó òåêñòóðû
93 function g_Texture_NumNameFindStart(name: String): Boolean;
94 var
95 i: Integer;
97 begin
98 Result := False;
99 NNF_PureName := '';
100 NNF_FirstNum := -1;
101 NNF_CurrentNum := -1;
103 for i := Length(name) downto 1 do
104 if (name[i] = '_') then // "_" - ñèìâîë íà÷àëà íîìåðíîãî ïîñòôèêñà
105 begin
106 if i = Length(name) then
107 begin // Íåò öèôð â êîíöå ñòðîêè
108 Exit;
109 end
110 else
111 begin
112 NNF_PureName := Copy(name, 1, i);
113 Delete(name, 1, i);
114 Break;
115 end;
116 end;
118 // Íå ïåðåâåñòè â ÷èñëî:
119 if not TryStrToInt(name, NNF_FirstNum) then
120 Exit;
122 NNF_CurrentNum := 0;
124 Result := True;
125 end;
127 function g_Texture_NumNameFindNext(var newName: String): Byte;
128 begin
129 if (NNF_PureName = '') or (NNF_CurrentNum < 0) then
130 begin
131 newName := '';
132 Result := NNF_NO_NAME;
133 Exit;
134 end;
136 newName := NNF_PureName + IntToStr(NNF_CurrentNum);
138 if NNF_CurrentNum < NNF_FirstNum then
139 Result := NNF_NAME_BEFORE
140 else
141 if NNF_CurrentNum > NNF_FirstNum then
142 Result := NNF_NAME_AFTER
143 else
144 Result := NNF_NAME_EQUALS;
146 Inc(NNF_CurrentNum);
147 end;
149 { T M a p R e a d e r _ 1 : }
151 function TMapReader_1.GetAreas(): TAreasRec1Array;
152 var
153 TempDataBlocks: TDataBlocksArray;
154 a: Integer;
155 b, Size: NativeInt;
156 begin
157 Result := nil;
159 TempDataBlocks := GetBlocks(BLOCK_AREAS);
161 if TempDataBlocks = nil then Exit;
163 size := SizeOf_TAreaRec_1;
165 for a := 0 to High(TempDataBlocks) do
166 for b := 0 to (TempDataBlocks[a].Block.BlockSize div size)-1 do
167 begin
168 SetLength(Result, Length(Result)+1);
169 //CopyMemory(@Result[High(Result)], Pointer(LongWord(TempDataBlocks[a].Data)+b*size), size);
170 mb_Read_TAreaRec_1(Result[High(Result)], Pointer(NativeInt(TempDataBlocks[a].Data)+b*size)^, size);
171 end;
173 TempDataBlocks := nil;
174 end;
176 function TMapReader_1.GetItems(): TItemsRec1Array;
177 var
178 TempDataBlocks: TDataBlocksArray;
179 a: Integer;
180 b, Size: NativeInt;
181 begin
182 Result := nil;
184 TempDataBlocks := GetBlocks(BLOCK_ITEMS);
186 if TempDataBlocks = nil then Exit;
188 size := SizeOf_TItemRec_1;
190 for a := 0 to High(TempDataBlocks) do
191 for b := 0 to (TempDataBlocks[a].Block.BlockSize div size)-1 do
192 begin
193 SetLength(Result, Length(Result)+1);
194 //CopyMemory(@Result[High(Result)], Pointer(LongWord(TempDataBlocks[a].Data)+b*size), size);
195 mb_Read_TItemRec_1(Result[High(Result)], Pointer(NativeInt(TempDataBlocks[a].Data)+b*size)^, size);
196 end;
198 TempDataBlocks := nil;
199 end;
201 function TMapReader_1.GetMapHeader(): TMapHeaderRec_1;
202 var
203 TempDataBlocks: TDataBlocksArray;
204 begin
205 ZeroMemory(@Result, SizeOf(TMapHeaderRec_1));
207 TempDataBlocks := GetBlocks(BLOCK_HEADER);
209 if TempDataBlocks = nil then Exit;
211 //CopyMemory(@Result, TempDataBlocks[0].Data, SizeOf(TMapHeaderRec_1));
212 mb_Read_TMapHeaderRec_1(Result, TempDataBlocks[0].Data^, SizeOf_TMapHeaderRec_1);
214 TempDataBlocks := nil;
215 end;
217 function TMapReader_1.GetMonsters(): TMonsterRec1Array;
218 var
219 TempDataBlocks: TDataBlocksArray;
220 a: Integer;
221 b, Size: NativeInt;
222 begin
223 Result := nil;
225 TempDataBlocks := GetBlocks(BLOCK_MONSTERS);
227 if TempDataBlocks = nil then Exit;
229 size := SizeOf_TMonsterRec_1;
231 for a := 0 to High(TempDataBlocks) do
232 for b := 0 to (TempDataBlocks[a].Block.BlockSize div size)-1 do
233 begin
234 SetLength(Result, Length(Result)+1);
235 //CopyMemory(@Result[High(Result)], Pointer(LongWord(TempDataBlocks[a].Data)+b*size), size);
236 mb_Read_TMonsterRec_1(Result[High(Result)], Pointer(NativeInt(TempDataBlocks[a].Data)+b*size)^, size);
237 end;
239 TempDataBlocks := nil;
240 end;
242 function TMapReader_1.GetPanels(): TPanelsRec1Array;
243 var
244 TempDataBlocks: TDataBlocksArray;
245 a: Integer;
246 b, Size: NativeInt;
247 begin
248 Result := nil;
250 TempDataBlocks := GetBlocks(BLOCK_PANELS);
252 if TempDataBlocks = nil then Exit;
254 size := SizeOf_TPanelRec_1;
256 for a := 0 to High(TempDataBlocks) do
257 for b := 0 to (TempDataBlocks[a].Block.BlockSize div size)-1 do
258 begin
259 SetLength(Result, Length(Result)+1);
260 //CopyMemory(@Result[High(Result)], Pointer(LongWord(TempDataBlocks[a].Data)+b*size), size);
261 mb_Read_TPanelRec_1(Result[High(Result)], Pointer(NativeInt(TempDataBlocks[a].Data)+b*size)^, size);
262 end;
264 TempDataBlocks := nil;
265 end;
267 function TMapReader_1.GetTextures(): TTexturesRec1Array;
268 var
269 TempDataBlocks: TDataBlocksArray;
270 a: Integer;
271 b, Size: NativeInt;
272 begin
273 Result := nil;
275 TempDataBlocks := GetBlocks(BLOCK_TEXTURES);
277 if TempDataBlocks = nil then Exit;
279 size := SizeOf_TTextureRec_1;
281 for a := 0 to High(TempDataBlocks) do
282 for b := 0 to (TempDataBlocks[a].Block.BlockSize div size)-1 do
283 begin
284 SetLength(Result, Length(Result)+1);
285 //CopyMemory(@Result[High(Result)], Pointer(LongWord(TempDataBlocks[a].Data)+b*size), size);
286 mb_Read_TTextureRec_1(Result[High(Result)], Pointer(NativeInt(TempDataBlocks[a].Data)+b*size)^, size);
287 end;
289 TempDataBlocks := nil;
290 end;
292 function TMapReader_1.GetTriggers(): TTriggersRec1Array;
293 var
294 TempDataBlocks: TDataBlocksArray;
295 a: Integer;
296 b: NativeInt;
297 Size: LongWord;
298 trdata: TTriggerData;
299 begin
300 Result := nil;
302 TempDataBlocks := GetBlocks(BLOCK_TRIGGERS);
304 if TempDataBlocks = nil then Exit;
306 size := SizeOf_TTriggerRec_1;
308 for a := 0 to High(TempDataBlocks) do
309 for b := 0 to (TempDataBlocks[a].Block.BlockSize div size)-1 do
310 begin
311 SetLength(Result, Length(Result)+1);
312 //CopyMemory(@Result[High(Result)], Pointer(LongWord(TempDataBlocks[a].Data)+b*size), size);
313 mb_Read_TTriggerRec_1(Result[High(Result)], Pointer(NativeInt(TempDataBlocks[a].Data)+b*size)^, size);
314 if (Result[High(Result)].TriggerType <> 0) then
315 begin
316 // preprocess trigger data
317 ZeroMemory(@trdata, SizeOf(trdata));
318 mb_Read_TriggerData(trdata, Result[High(Result)].TriggerType, Result[High(Result)].DATA, sizeof(trdata));
319 Result[High(Result)].DATA := trdata.Default;
320 end;
321 end;
323 TempDataBlocks := nil;
324 end;
326 function TMapReader_1.HandledVersion: Byte;
327 begin
328 Result := $01;
329 end;
331 { T M a p R e a d e r : }
333 constructor TMapReader.Create();
334 begin
335 FDataBlocks := nil;
336 FError := MAP_ERROR_NONE;
337 FVersion := $00;
338 end;
340 destructor TMapReader.Destroy();
341 begin
342 FreeMap();
344 inherited;
345 end;
347 procedure TMapReader.FreeMap();
348 var
349 a: Integer;
350 begin
351 if FDataBlocks <> nil then
352 for a := 0 to High(FDataBlocks) do
353 if FDataBlocks[a].Data <> nil then FreeMem(FDataBlocks[a].Data);
355 FDataBlocks := nil;
356 FVersion := $00;
357 FError := MAP_ERROR_NONE;
358 end;
360 function TMapReader.GetBlocks(BlocksType: Byte): TDataBlocksArray;
361 var
362 a: Integer;
363 begin
364 Result := nil;
366 if FDataBlocks = nil then Exit;
368 for a := 0 to High(FDataBlocks) do
369 if FDataBlocks[a].Block.BlockType = BlocksType then
370 begin
371 SetLength(Result, Length(Result)+1);
372 Result[High(Result)] := FDataBlocks[a];
373 end;
374 end;
376 function TMapReader.HandledVersion(): Byte;
377 begin
378 Result := $00;
379 end;
381 function TMapReader.LoadMap(Data: Pointer): Boolean;
382 var
383 adr: NativeInt;
384 _id: Integer;
385 Sign: array[0..2] of Char;
386 Ver: Byte;
387 begin
388 Result := False;
390 CopyMemory(@Sign[0], Data, 3);
391 if Sign <> MAP_SIGNATURE then
392 begin
393 FError := MAP_ERROR_SIGNATURE;
394 Exit;
395 end;
396 adr := 3;
398 CopyMemory(@Ver, Pointer(NativeInt(Data)+adr), 1);
399 FVersion := Ver;
400 if Ver > HandledVersion() then
401 begin
402 FError := MAP_ERROR_VERSION;
403 Exit;
404 end;
405 adr := adr+1;
407 repeat
408 SetLength(FDataBlocks, Length(FDataBlocks)+1);
409 _id := High(FDataBlocks);
411 CopyMemory(@FDataBlocks[_id].Block, Pointer(NativeInt(Data)+adr), SizeOf(TBlock));
412 adr := adr+SizeOf(TBlock);
414 FDataBlocks[_id].Data := GetMemory(FDataBlocks[_id].Block.BlockSize);
416 CopyMemory(FDataBlocks[_id].Data, Pointer(NativeInt(Data)+adr), FDataBlocks[_id].Block.BlockSize);
418 adr := adr+FDataBlocks[_id].Block.BlockSize;
419 until FDataBlocks[_id].Block.BlockType = BLOCK_NONE;
421 Result := True;
422 end;
424 end.