1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2010-2019 EDuke32 developers and contributors
4 Copyright (C) 2019 Nuke.YKT
5 
6 This file is part of NBlood.
7 
8 NBlood is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License version 2
10 as published by the Free Software Foundation.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 
16 See the GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 */
22 //-------------------------------------------------------------------------
23 #include "build.h"
24 #include "editor.h"
25 #ifdef POLYMER
26 #include "polymer.h"
27 #endif
28 #include "compat.h"
29 #include "common_game.h"
30 #include "crc32.h"
31 #include "md4.h"
32 
33 //#include "actor.h"
34 #include "globals.h"
35 #include "db.h"
36 #include "iob.h"
37 #include "eventq.h"
38 #ifdef NOONE_EXTENSIONS
39 #include "nnexts.h"
40 #endif
41 
42 #ifdef NOONE_EXTENSIONS
43 bool gModernMap = false;
44 #endif // !NOONE_EXTENSIONS
45 
46 
47 unsigned short gStatCount[kMaxStatus + 1];
48 
49 XSPRITE xsprite[kMaxXSprites];
50 XSECTOR xsector[kMaxXSectors];
51 XWALL xwall[kMaxXWalls];
52 
53 SPRITEHIT gSpriteHit[kMaxXSprites];
54 
55 int xvel[kMaxSprites], yvel[kMaxSprites], zvel[kMaxSprites];
56 
57 #ifdef POLYMER
58 PolymerLight_t gPolymerLight[kMaxSprites];
59 #endif
60 
61 char qsprite_filler[kMaxSprites], qsector_filler[kMaxSectors];
62 
63 int gVisibility;
64 const char *gItemText[] = {
65     "Skull Key",
66     "Eye Key",
67     "Fire Key",
68     "Dagger Key",
69     "Spider Key",
70     "Moon Key",
71     "Key 7",
72     "Doctor's Bag",
73     "Medicine Pouch",
74     "Life Essence",
75     "Life Seed",
76     "Red Potion",
77     "Feather Fall",
78     "Limited Invisibility",
79     "INVULNERABILITY",
80     "Boots of Jumping",
81     "Raven Flight",
82     "Guns Akimbo",
83     "Diving Suit",
84     "Gas mask",
85     "Clone",
86     "Crystal Ball",
87     "Decoy",
88     "Doppleganger",
89     "Reflective shots",
90     "Beast Vision",
91     "ShadowCloak",
92     "Rage shroom",
93     "Delirium Shroom",
94     "Grow shroom",
95     "Shrink shroom",
96     "Death mask",
97     "Wine Goblet",
98     "Wine Bottle",
99     "Skull Grail",
100     "Silver Grail",
101     "Tome",
102     "Black Chest",
103     "Wooden Chest",
104     "Asbestos Armor",
105     "Basic Armor",
106     "Body Armor",
107     "Fire Armor",
108     "Spirit Armor",
109     "Super Armor",
110     "Blue Team Base",
111     "Red Team Base",
112     "Blue Flag",
113     "Red Flag",
114     "DUMMY",
115     "Level map",
116 };
117 
118 const char *gAmmoText[] = {
119     "Spray can",
120     "Bundle of TNT*",
121     "Bundle of TNT",
122     "Case of TNT",
123     "Proximity Detonator",
124     "Remote Detonator",
125     "Trapped Soul",
126     "4 shotgun shells",
127     "Box of shotgun shells",
128     "A few bullets",
129     "Voodoo Doll",
130     "OBSOLETE",
131     "Full drum of bullets",
132     "Tesla Charge",
133     "OBSOLETE",
134     "OBSOLETE",
135     "Flares",
136     "OBSOLETE",
137     "OBSOLETE",
138     "Gasoline Can",
139     NULL,
140 };
141 
142 const char *gWeaponText[] = {
143     "RANDOM",
144     "Sawed-off",
145     "Tommy Gun",
146     "Flare Pistol",
147     "Voodoo Doll",
148     "Tesla Cannon",
149     "Napalm Launcher",
150     "Pitchfork",
151     "Spray Can",
152     "Dynamite",
153     "Life Leech",
154 };
155 
156 
157 
dbCrypt(char * pPtr,int nLength,int nKey)158 void dbCrypt(char *pPtr, int nLength, int nKey)
159 {
160     for (int i = 0; i < nLength; i++)
161     {
162         pPtr[i] = pPtr[i] ^ nKey;
163         nKey++;
164     }
165 }
166 
167 #ifdef POLYMER
168 
DeleteLight(int32_t s)169 void DeleteLight(int32_t s)
170 {
171     if (gPolymerLight[s].lightId >= 0)
172         polymer_deletelight(gPolymerLight[s].lightId);
173     gPolymerLight[s].lightId = -1;
174     gPolymerLight[s].lightptr = NULL;
175 }
176 
177 #endif
178 
179 
InsertSpriteSect(int nSprite,int nSector)180 void InsertSpriteSect(int nSprite, int nSector)
181 {
182     dassert(nSprite >= 0 && nSprite < kMaxSprites);
183     dassert(nSector >= 0 && nSector < kMaxSectors);
184     int nOther = headspritesect[nSector];
185     if (nOther >= 0)
186     {
187         prevspritesect[nSprite] = prevspritesect[nOther];
188         nextspritesect[nSprite] = -1;
189         nextspritesect[prevspritesect[nOther]] = nSprite;
190         prevspritesect[nOther] = nSprite;
191     }
192     else
193     {
194         prevspritesect[nSprite] = nSprite;
195         nextspritesect[nSprite] = -1;
196         headspritesect[nSector] = nSprite;
197     }
198     sprite[nSprite].sectnum = nSector;
199 }
200 
RemoveSpriteSect(int nSprite)201 void RemoveSpriteSect(int nSprite)
202 {
203     dassert(nSprite >= 0 && nSprite < kMaxSprites);
204     int nSector = sprite[nSprite].sectnum;
205     dassert(nSector >= 0 && nSector < kMaxSectors);
206     int nOther = nextspritesect[nSprite];
207     if (nOther < 0)
208     {
209         nOther = headspritesect[nSector];
210     }
211     prevspritesect[nOther] = prevspritesect[nSprite];
212     if (headspritesect[nSector] != nSprite)
213     {
214         nextspritesect[prevspritesect[nSprite]] = nextspritesect[nSprite];
215     }
216     else
217     {
218         headspritesect[nSector] = nextspritesect[nSprite];
219     }
220     sprite[nSprite].sectnum = -1;
221 }
222 
InsertSpriteStat(int nSprite,int nStat)223 void InsertSpriteStat(int nSprite, int nStat)
224 {
225     dassert(nSprite >= 0 && nSprite < kMaxSprites);
226     dassert(nStat >= 0 && nStat <= kMaxStatus);
227     int nOther = headspritestat[nStat];
228     if (nOther >= 0)
229     {
230         prevspritestat[nSprite] = prevspritestat[nOther];
231         nextspritestat[nSprite] = -1;
232         nextspritestat[prevspritestat[nOther]] = nSprite;
233         prevspritestat[nOther] = nSprite;
234     }
235     else
236     {
237         prevspritestat[nSprite] = nSprite;
238         nextspritestat[nSprite] = -1;
239         headspritestat[nStat] = nSprite;
240     }
241     sprite[nSprite].statnum = nStat;
242     gStatCount[nStat]++;
243 }
244 
RemoveSpriteStat(int nSprite)245 void RemoveSpriteStat(int nSprite)
246 {
247     dassert(nSprite >= 0 && nSprite < kMaxSprites);
248     int nStat = sprite[nSprite].statnum;
249     dassert(nStat >= 0 && nStat <= kMaxStatus);
250     int nOther = nextspritestat[nSprite];
251     if (nOther < 0)
252     {
253         nOther = headspritestat[nStat];
254     }
255     prevspritestat[nOther] = prevspritestat[nSprite];
256     if (headspritestat[nStat] != nSprite)
257     {
258         nextspritestat[prevspritestat[nSprite]] = nextspritestat[nSprite];
259     }
260     else
261     {
262         headspritestat[nStat] = nextspritestat[nSprite];
263     }
264     sprite[nSprite].statnum = kStatNothing;
265     gStatCount[nStat]--;
266 }
267 
qinitspritelists(void)268 void qinitspritelists(void) // Replace
269 {
270     for (short i = 0; i <= kMaxSectors; i++)
271     {
272         headspritesect[i] = -1;
273     }
274     for (short i = 0; i <= kMaxStatus; i++)
275     {
276         headspritestat[i] = -1;
277     }
278     int const nMaxSprites = bVanilla ? 4096 : kMaxSprites;
279     for (short i = 0; i < nMaxSprites; i++)
280     {
281         sprite[i].sectnum = -1;
282         sprite[i].index = -1;
283         InsertSpriteStat(i, kMaxStatus);
284     }
285     memset(gStatCount, 0, sizeof(gStatCount));
286     Numsprites = 0;
287 }
288 
InsertSprite(int nSector,int nStat)289 int InsertSprite(int nSector, int nStat)
290 {
291     int nSprite = headspritestat[kMaxStatus];
292     dassert(nSprite < kMaxSprites);
293     if (nSprite < 0)
294     {
295         return nSprite;
296     }
297     RemoveSpriteStat(nSprite);
298     spritetype *pSprite = &sprite[nSprite];
299     memset(&sprite[nSprite], 0, sizeof(spritetype));
300     InsertSpriteStat(nSprite, nStat);
301     InsertSpriteSect(nSprite, nSector);
302     pSprite->cstat = 128;
303     pSprite->clipdist = 32;
304     pSprite->xrepeat = pSprite->yrepeat = 64;
305     pSprite->owner = -1;
306     pSprite->extra = -1;
307     pSprite->index = nSprite;
308     xvel[nSprite] = yvel[nSprite] = zvel[nSprite] = 0;
309 
310 #ifdef POLYMER
311     gPolymerLight[nSprite].lightId = -1;
312 #endif
313 
314     Numsprites++;
315 
316     return nSprite;
317 }
318 
qinsertsprite(short nSector,short nStat)319 int qinsertsprite(short nSector, short nStat) // Replace
320 {
321     return InsertSprite(nSector, nStat);
322 }
323 
DeleteSprite(int nSprite)324 int DeleteSprite(int nSprite)
325 {
326 #ifdef POLYMER
327     if (gPolymerLight[nSprite].lightptr != NULL && videoGetRenderMode() == REND_POLYMER)
328         DeleteLight(nSprite);
329 #endif
330     if (sprite[nSprite].extra > 0)
331     {
332         dbDeleteXSprite(sprite[nSprite].extra);
333     }
334     dassert(sprite[nSprite].statnum >= 0 && sprite[nSprite].statnum < kMaxStatus);
335     RemoveSpriteStat(nSprite);
336     dassert(sprite[nSprite].sectnum >= 0 && sprite[nSprite].sectnum < kMaxSectors);
337     RemoveSpriteSect(nSprite);
338     InsertSpriteStat(nSprite, kMaxStatus);
339 
340     Numsprites--;
341 
342     return nSprite;
343 }
344 
qdeletesprite(short nSprite)345 int qdeletesprite(short nSprite) // Replace
346 {
347     return DeleteSprite(nSprite);
348 }
349 
ChangeSpriteSect(int nSprite,int nSector)350 int ChangeSpriteSect(int nSprite, int nSector)
351 {
352     dassert(nSprite >= 0 && nSprite < kMaxSprites);
353     dassert(nSector >= 0 && nSector < kMaxSectors);
354     dassert(sprite[nSprite].sectnum >= 0 && sprite[nSprite].sectnum < kMaxSectors);
355     RemoveSpriteSect(nSprite);
356     InsertSpriteSect(nSprite, nSector);
357     return 0;
358 }
359 
qchangespritesect(short nSprite,short nSector)360 int qchangespritesect(short nSprite, short nSector)
361 {
362     return ChangeSpriteSect(nSprite, nSector);
363 }
364 
ChangeSpriteStat(int nSprite,int nStatus)365 int ChangeSpriteStat(int nSprite, int nStatus)
366 {
367     dassert(nSprite >= 0 && nSprite < kMaxSprites);
368     dassert(nStatus >= 0 && nStatus < kMaxStatus);
369     dassert(sprite[nSprite].statnum >= 0 && sprite[nSprite].statnum < kMaxStatus);
370     dassert(sprite[nSprite].sectnum >= 0 && sprite[nSprite].sectnum < kMaxSectors);
371     RemoveSpriteStat(nSprite);
372     InsertSpriteStat(nSprite, nStatus);
373     return 0;
374 }
375 
qchangespritestat(short nSprite,short nStatus)376 int qchangespritestat(short nSprite, short nStatus)
377 {
378     return ChangeSpriteStat(nSprite, nStatus);
379 }
380 
381 unsigned short nextXSprite[kMaxXSprites];
382 unsigned short nextXWall[kMaxXWalls];
383 unsigned short nextXSector[kMaxXSectors];
384 
InitFreeList(unsigned short * pList,int nCount)385 void InitFreeList(unsigned short *pList, int nCount)
386 {
387     for (int i = 1; i < nCount; i++)
388     {
389         pList[i] = i-1;
390     }
391     pList[0] = nCount - 1;
392 }
393 
InsertFree(unsigned short * pList,int nIndex)394 void InsertFree(unsigned short *pList, int nIndex)
395 {
396     pList[nIndex] = pList[0];
397     pList[0] = nIndex;
398 }
399 
dbInsertXSprite(int nSprite)400 unsigned short dbInsertXSprite(int nSprite)
401 {
402     int nXSprite = nextXSprite[0];
403     nextXSprite[0] = nextXSprite[nXSprite];
404     if (nXSprite == 0)
405     {
406         ThrowError("Out of free XSprites");
407     }
408     memset(&xsprite[nXSprite], 0, sizeof(XSPRITE));
409     if (!bVanilla)
410         memset(&gSpriteHit[nXSprite], 0, sizeof(SPRITEHIT));
411     xsprite[nXSprite].reference = nSprite;
412     sprite[nSprite].extra = nXSprite;
413     return nXSprite;
414 }
415 
dbDeleteXSprite(int nXSprite)416 void dbDeleteXSprite(int nXSprite)
417 {
418     dassert(xsprite[nXSprite].reference >= 0);
419     dassert(sprite[xsprite[nXSprite].reference].extra == nXSprite);
420     InsertFree(nextXSprite, nXSprite);
421     sprite[xsprite[nXSprite].reference].extra = -1;
422     xsprite[nXSprite].reference = -1;
423 }
424 
dbInsertXWall(int nWall)425 unsigned short dbInsertXWall(int nWall)
426 {
427     int nXWall = nextXWall[0];
428     nextXWall[0] = nextXWall[nXWall];
429     if (nXWall == 0)
430     {
431         ThrowError("Out of free XWalls");
432     }
433     memset(&xwall[nXWall], 0, sizeof(XWALL));
434     xwall[nXWall].reference = nWall;
435     wall[nWall].extra = nXWall;
436     return nXWall;
437 }
438 
dbDeleteXWall(int nXWall)439 void dbDeleteXWall(int nXWall)
440 {
441     dassert(xwall[nXWall].reference >= 0);
442     InsertFree(nextXWall, nXWall);
443     wall[xwall[nXWall].reference].extra = -1;
444     xwall[nXWall].reference = -1;
445 }
446 
dbInsertXSector(int nSector)447 unsigned short dbInsertXSector(int nSector)
448 {
449     int nXSector = nextXSector[0];
450     nextXSector[0] = nextXSector[nXSector];
451     if (nXSector == 0)
452     {
453         ThrowError("Out of free XSectors");
454     }
455     memset(&xsector[nXSector], 0, sizeof(XSECTOR));
456     xsector[nXSector].reference = nSector;
457     sector[nSector].extra = nXSector;
458     return nXSector;
459 }
460 
dbDeleteXSector(int nXSector)461 void dbDeleteXSector(int nXSector)
462 {
463     dassert(xsector[nXSector].reference >= 0);
464     InsertFree(nextXSector, nXSector);
465     sector[xsector[nXSector].reference].extra = -1;
466     xsector[nXSector].reference = -1;
467 }
468 
dbXSpriteClean(void)469 void dbXSpriteClean(void)
470 {
471     for (int i = 0; i < kMaxSprites; i++)
472     {
473         int nXSprite = sprite[i].extra;
474         if (nXSprite == 0)
475         {
476             sprite[i].extra = -1;
477         }
478         if (sprite[i].statnum < kMaxStatus && nXSprite > 0)
479         {
480             dassert(nXSprite < kMaxXSprites);
481             if (xsprite[nXSprite].reference != i)
482             {
483                 int nXSprite2 = dbInsertXSprite(i);
484                 memcpy(&xsprite[nXSprite2], &xsprite[nXSprite], sizeof(XSPRITE));
485                 xsprite[nXSprite2].reference = i;
486             }
487         }
488     }
489     for (int i = 1; i < kMaxXSprites; i++)
490     {
491         int nSprite = xsprite[i].reference;
492         if (nSprite >= 0)
493         {
494             dassert(nSprite < kMaxSprites);
495             if (sprite[nSprite].statnum >= kMaxStatus || sprite[nSprite].extra != i)
496             {
497                 InsertFree(nextXSprite, i);
498                 xsprite[i].reference = -1;
499             }
500         }
501     }
502 }
503 
dbXWallClean(void)504 void dbXWallClean(void)
505 {
506     for (int i = 0; i < numwalls; i++)
507     {
508         int nXWall = wall[i].extra;
509         if (nXWall == 0)
510         {
511             wall[i].extra = -1;
512         }
513         if (nXWall > 0)
514         {
515             dassert(nXWall < kMaxXWalls);
516             if (xwall[nXWall].reference == -1)
517             {
518                 wall[i].extra = -1;
519             }
520             else
521             {
522                 xwall[nXWall].reference = i;
523             }
524         }
525     }
526     for (int i = 0; i < numwalls; i++)
527     {
528         int nXWall = wall[i].extra;
529         if (nXWall > 0)
530         {
531             dassert(nXWall < kMaxXWalls);
532             if (xwall[nXWall].reference != i)
533             {
534                 int nXWall2 = dbInsertXWall(i);
535                 memcpy(&xwall[nXWall2], &xwall[nXWall], sizeof(XWALL));
536                 xwall[nXWall2].reference = i;
537             }
538         }
539     }
540     for (int i = 1; i < kMaxXWalls; i++)
541     {
542         int nWall = xwall[i].reference;
543         if (nWall >= 0)
544         {
545             dassert(nWall < kMaxWalls);
546             if (nWall >= numwalls || wall[nWall].extra != i)
547             {
548                 InsertFree(nextXWall, i);
549                 xwall[i].reference = -1;
550             }
551         }
552     }
553 }
554 
dbXSectorClean(void)555 void dbXSectorClean(void)
556 {
557 
558 
559     for (int i = 0; i < numsectors; i++)
560     {
561         int nXSector = sector[i].extra;
562         if (nXSector == 0)
563         {
564             sector[i].extra = -1;
565         }
566         if (nXSector > 0)
567         {
568             dassert(nXSector < kMaxXSectors);
569             if (xsector[nXSector].reference == -1)
570             {
571                 sector[i].extra = -1;
572             }
573             else
574             {
575                 xsector[nXSector].reference = i;
576             }
577         }
578     }
579     for (int i = 0; i < numsectors; i++)
580     {
581         int nXSector = sector[i].extra;
582         if (nXSector > 0)
583         {
584             dassert(nXSector < kMaxXSectors);
585             if (xsector[nXSector].reference != i)
586             {
587                 int nXSector2 = dbInsertXSector(i);
588                 memcpy(&xsector[nXSector2], &xsector[nXSector], sizeof(XSECTOR));
589                 xsector[nXSector2].reference = i;
590             }
591         }
592     }
593     for (int i = 1; i < kMaxXSectors; i++)
594     {
595         int nSector = xsector[i].reference;
596         if (nSector >= 0)
597         {
598             dassert(nSector < kMaxSectors);
599             if (nSector >= numsectors || sector[nSector].extra != i)
600             {
601                 InsertFree(nextXSector, i);
602                 xsector[i].reference = -1;
603             }
604         }
605     }
606 }
607 
dbInit(void)608 void dbInit(void)
609 {
610     InitFreeList(nextXSprite, kMaxXSprites);
611     for (int i = 1; i < kMaxXSprites; i++)
612     {
613         xsprite[i].reference = -1;
614     }
615     InitFreeList(nextXWall, kMaxXWalls);
616     for (int i = 1; i < kMaxXWalls; i++)
617     {
618         xwall[i].reference = -1;
619     }
620     InitFreeList(nextXSector, kMaxXSectors);
621     for (int i = 1; i < kMaxXSectors; i++)
622     {
623         xsector[i].reference = -1;
624     }
625     initspritelists();
626     for (int i = 0; i < kMaxSprites; i++)
627     {
628         sprite[i].cstat = 128;
629     }
630 }
631 
PropagateMarkerReferences(void)632 void PropagateMarkerReferences(void)
633 {
634     int nSprite, nNextSprite;
635     for (nSprite = headspritestat[kStatMarker]; nSprite != -1; nSprite = nNextSprite) {
636 
637         nNextSprite = nextspritestat[nSprite];
638 
639         switch (sprite[nSprite].type)  {
640             case kMarkerOff:
641             case kMarkerAxis:
642             case kMarkerWarpDest: {
643                 int nOwner = sprite[nSprite].owner;
644                 if (nOwner >= 0 && nOwner < numsectors) {
645                     int nXSector = sector[nOwner].extra;
646                     if (nXSector > 0 && nXSector < kMaxXSectors) {
647                         xsector[nXSector].marker0 = nSprite;
648                         continue;
649                     }
650                 }
651             }
652             break;
653             case kMarkerOn: {
654                 int nOwner = sprite[nSprite].owner;
655                 if (nOwner >= 0 && nOwner < numsectors) {
656                     int nXSector = sector[nOwner].extra;
657                     if (nXSector > 0 && nXSector < kMaxXSectors) {
658                         xsector[nXSector].marker1 = nSprite;
659                         continue;
660                     }
661                 }
662             }
663             break;
664         }
665 
666         DeleteSprite(nSprite);
667     }
668 }
669 
670 bool byte_1A76C6, byte_1A76C7, byte_1A76C8;
671 
672 MAPHEADER2 byte_19AE44;
673 
dbReadMapCRC(const char * pPath)674 unsigned int dbReadMapCRC(const char *pPath)
675 {
676     char name2[BMAX_PATH];
677     byte_1A76C7 = 0;
678     byte_1A76C8 = 0;
679 
680     int const bakpathsearchmode = pathsearchmode;
681     pathsearchmode = 1;
682 
683     Bstrncpy(name2, pPath, BMAX_PATH);
684     Bstrupr(name2);
685     DICTNODE* pNode = *gSysRes.Probe(name2, "MAP");
686     if (pNode && pNode->flags & DICT_EXTERNAL)
687     {
688         gSysRes.RemoveNode(pNode);
689     }
690     pNode = gSysRes.Lookup(pPath, "MAP");
691     if (!pNode)
692     {
693         char name2[BMAX_PATH];
694         Bstrncpy(name2, pPath, BMAX_PATH);
695         ChangeExtension(name2, "");
696         pNode = gSysRes.Lookup(name2, "MAP");
697     }
698 
699     if (!pNode)
700     {
701         initprintf("Error opening map file %s", pPath);
702         pathsearchmode = bakpathsearchmode;
703         return -1;
704     }
705     char *pData = (char*)gSysRes.Lock(pNode);
706     pathsearchmode = bakpathsearchmode;
707 
708     int nSize = pNode->size;
709     MAPSIGNATURE header;
710     IOBuffer(nSize, pData).Read(&header, 6);
711 #if B_BIG_ENDIAN == 1
712     header.version = B_LITTLE16(header.version);
713 #endif
714     if (memcmp(header.signature, "BLM\x1a", 4))
715     {
716         ThrowError("Map file corrupted");
717     }
718     if ((header.version & 0xff00) == 0x600)
719     {
720     }
721     else if ((header.version & 0xff00) == 0x700)
722     {
723         byte_1A76C8 = 1;
724     }
725     else
726     {
727         ThrowError("Map file is wrong version");
728     }
729     unsigned int nCRC = *(unsigned int*)(pData+nSize-4);
730     gSysRes.Unlock(pNode);
731     return nCRC;
732 }
733 
734 int gMapRev, gSongId, gSkyCount;
735 //char byte_19AE44[128];
736 const int nXSectorSize = 60;
737 const int nXSpriteSize = 56;
738 const int nXWallSize = 24;
739 
dbLoadMap(const char * pPath,int * pX,int * pY,int * pZ,short * pAngle,short * pSector,unsigned int * pCRC)740 int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short *pSector, unsigned int *pCRC) {
741     char name2[BMAX_PATH]; int16_t tpskyoff[256];
742     memset(show2dsector, 0, sizeof(show2dsector));
743     memset(show2dwall, 0, sizeof(show2dwall));
744     memset(show2dsprite, 0, sizeof(show2dsprite));
745     #ifdef NOONE_EXTENSIONS
746     gModernMap = false;
747     #endif
748 
749 #ifdef USE_OPENGL
750     Polymost_prepare_loadboard();
751 #endif
752 
753     int const bakpathsearchmode = pathsearchmode;
754     pathsearchmode = 1;
755 
756     Bstrncpy(name2, pPath, BMAX_PATH);
757     Bstrupr(name2);
758     DICTNODE* pNode = *gSysRes.Probe(name2, "MAP");
759     if (pNode && pNode->flags & DICT_EXTERNAL)
760     {
761         gSysRes.RemoveNode(pNode);
762     }
763 
764     pNode = gSysRes.Lookup(pPath, "MAP");
765     if (!pNode)
766     {
767         char name2[BMAX_PATH];
768         Bstrncpy(name2, pPath, BMAX_PATH);
769         ChangeExtension(name2, "");
770         pNode = gSysRes.Lookup(name2, "MAP");
771     }
772 
773     if (!pNode)
774     {
775         initprintf("Error opening map file %s", pPath);
776         pathsearchmode = bakpathsearchmode;
777         return -1;
778     }
779     char *pData = (char*)gSysRes.Lock(pNode);
780     pathsearchmode = bakpathsearchmode;
781     int nSize = pNode->size;
782     MAPSIGNATURE header;
783     IOBuffer IOBuffer1 = IOBuffer(nSize, pData);
784     IOBuffer1.Read(&header, 6);
785 #if B_BIG_ENDIAN == 1
786     header.version = B_LITTLE16(header.version);
787 #endif
788     if (memcmp(header.signature, "BLM\x1a", 4))
789     {
790         initprintf("Map file corrupted");
791         gSysRes.Unlock(pNode);
792         return -1;
793     }
794     byte_1A76C8 = 0;
795     if ((header.version & 0xff00) == 0x700) {
796         byte_1A76C8 = 1;
797 
798         #ifdef NOONE_EXTENSIONS
799         // indicate if the map requires modern features to work properly
800         // for maps wich created in PMAPEDIT BETA13 or higher versions. Since only minor version changed,
801         // the map is still can be loaded with vanilla BLOOD / MAPEDIT and should work in other ports too.
802         if ((header.version & 0x00ff) == 0x001) gModernMap = true;
803         #endif
804 
805     } else {
806         initprintf("Map file is wrong version");
807         gSysRes.Unlock(pNode);
808         return -1;
809     }
810 
811     MAPHEADER mapHeader;
812     IOBuffer1.Read(&mapHeader,37/* sizeof(mapHeader)*/);
813     if (mapHeader.at16 != 0 && mapHeader.at16 != 0x7474614d && mapHeader.at16 != 0x4d617474) {
814         dbCrypt((char*)&mapHeader, sizeof(mapHeader), 0x7474614d);
815         byte_1A76C7 = 1;
816     }
817 
818 #if B_BIG_ENDIAN == 1
819     mapHeader.at0 = B_LITTLE32(mapHeader.at0);
820     mapHeader.at4 = B_LITTLE32(mapHeader.at4);
821     mapHeader.at8 = B_LITTLE32(mapHeader.at8);
822     mapHeader.atc = B_LITTLE16(mapHeader.atc);
823     mapHeader.ate = B_LITTLE16(mapHeader.ate);
824     mapHeader.at10 = B_LITTLE16(mapHeader.at10);
825     mapHeader.at12 = B_LITTLE32(mapHeader.at12);
826     mapHeader.at16 = B_LITTLE32(mapHeader.at16);
827     mapHeader.at1b = B_LITTLE32(mapHeader.at1b);
828     mapHeader.at1f = B_LITTLE16(mapHeader.at1f);
829     mapHeader.at21 = B_LITTLE16(mapHeader.at21);
830     mapHeader.at23 = B_LITTLE16(mapHeader.at23);
831 #endif
832 
833     psky_t *pSky = tileSetupSky(0);
834     pSky->horizfrac = 65536;
835 
836     *pX = mapHeader.at0;
837     *pY = mapHeader.at4;
838     *pZ = mapHeader.at8;
839     *pAngle = mapHeader.atc;
840     *pSector = mapHeader.ate;
841     pSky->lognumtiles = mapHeader.at10;
842     gVisibility = g_visibility = mapHeader.at12;
843     gSongId = mapHeader.at16;
844     if (byte_1A76C8)
845     {
846         if (mapHeader.at16 == 0x7474614d || mapHeader.at16 == 0x4d617474)
847         {
848             byte_1A76C6 = 1;
849         }
850         else if (!mapHeader.at16)
851         {
852             byte_1A76C6 = 0;
853         }
854         else
855         {
856             initprintf("Corrupted Map file");
857             gSysRes.Unlock(pNode);
858             return -1;
859         }
860     }
861     else if (mapHeader.at16)
862     {
863         initprintf("Corrupted Map file");
864         gSysRes.Unlock(pNode);
865         return -1;
866     }
867     parallaxtype = mapHeader.at1a;
868     gMapRev = mapHeader.at1b;
869     numsectors = mapHeader.at1f;
870     numwalls = mapHeader.at21;
871     dbInit();
872     if (byte_1A76C8)
873     {
874         IOBuffer1.Read(&byte_19AE44, 128);
875         dbCrypt((char*)&byte_19AE44, 128, numwalls);
876 #if B_BIG_ENDIAN == 1
877         byte_19AE44.at40 = B_LITTLE32(byte_19AE44.at40);
878         byte_19AE44.at44 = B_LITTLE32(byte_19AE44.at44);
879         byte_19AE44.at48 = B_LITTLE32(byte_19AE44.at48);
880 #endif
881     }
882     else
883     {
884         memset(&byte_19AE44, 0, 128);
885     }
886     gSkyCount = 1<<pSky->lognumtiles;
887     IOBuffer1.Read(tpskyoff, gSkyCount*sizeof(tpskyoff[0]));
888     if (byte_1A76C8)
889     {
890         dbCrypt((char*)tpskyoff, gSkyCount*sizeof(tpskyoff[0]), gSkyCount*2);
891     }
892     for (int i = 0; i < ClipHigh(gSkyCount, MAXPSKYTILES); i++)
893     {
894         pSky->tileofs[i] = B_LITTLE16(tpskyoff[i]);
895     }
896     for (int i = 0; i < numsectors; i++)
897     {
898         sectortype *pSector = &sector[i];
899         IOBuffer1.Read(pSector, sizeof(sectortype));
900         if (byte_1A76C8)
901         {
902             dbCrypt((char*)pSector, sizeof(sectortype), gMapRev*sizeof(sectortype));
903         }
904 #if B_BIG_ENDIAN == 1
905         pSector->wallptr = B_LITTLE16(pSector->wallptr);
906         pSector->wallnum = B_LITTLE16(pSector->wallnum);
907         pSector->ceilingz = B_LITTLE32(pSector->ceilingz);
908         pSector->floorz = B_LITTLE32(pSector->floorz);
909         pSector->ceilingstat = B_LITTLE16(pSector->ceilingstat);
910         pSector->floorstat = B_LITTLE16(pSector->floorstat);
911         pSector->ceilingpicnum = B_LITTLE16(pSector->ceilingpicnum);
912         pSector->ceilingheinum = B_LITTLE16(pSector->ceilingheinum);
913         pSector->floorpicnum = B_LITTLE16(pSector->floorpicnum);
914         pSector->floorheinum = B_LITTLE16(pSector->floorheinum);
915         pSector->type = B_LITTLE16(pSector->type);
916         pSector->hitag = B_LITTLE16(pSector->hitag);
917         pSector->extra = B_LITTLE16(pSector->extra);
918 #endif
919         qsector_filler[i] = pSector->fogpal;
920         pSector->fogpal = 0;
921         if (sector[i].extra > 0)
922         {
923             char pBuffer[nXSectorSize];
924             int nXSector = dbInsertXSector(i);
925             XSECTOR *pXSector = &xsector[nXSector];
926             memset(pXSector, 0, sizeof(XSECTOR));
927             int nCount;
928             if (!byte_1A76C8)
929             {
930                 nCount = nXSectorSize;
931             }
932             else
933             {
934                 nCount = byte_19AE44.at48;
935             }
936             dassert(nCount <= nXSectorSize);
937             IOBuffer1.Read(pBuffer, nCount);
938             BitReader bitReader(pBuffer, nCount);
939             pXSector->reference = bitReader.readSigned(14);
940             pXSector->state = bitReader.readUnsigned(1);
941             pXSector->busy = bitReader.readUnsigned(17);
942             pXSector->data = bitReader.readUnsigned(16);
943             pXSector->txID = bitReader.readUnsigned(10);
944             pXSector->busyWaveA = bitReader.readUnsigned(3);
945             pXSector->busyWaveB = bitReader.readUnsigned(3);
946             pXSector->rxID = bitReader.readUnsigned(10);
947             pXSector->command = bitReader.readUnsigned(8);
948             pXSector->triggerOn = bitReader.readUnsigned(1);
949             pXSector->triggerOff = bitReader.readUnsigned(1);
950             pXSector->busyTimeA = bitReader.readUnsigned(12);
951             pXSector->waitTimeA = bitReader.readUnsigned(12);
952             pXSector->restState = bitReader.readUnsigned(1);
953             pXSector->interruptable = bitReader.readUnsigned(1);
954             pXSector->amplitude = bitReader.readSigned(8);
955             pXSector->freq = bitReader.readUnsigned(8);
956             pXSector->reTriggerA = bitReader.readUnsigned(1);
957             pXSector->reTriggerB = bitReader.readUnsigned(1);
958             pXSector->phase = bitReader.readUnsigned(8);
959             pXSector->wave = bitReader.readUnsigned(4);
960             pXSector->shadeAlways = bitReader.readUnsigned(1);
961             pXSector->shadeFloor = bitReader.readUnsigned(1);
962             pXSector->shadeCeiling = bitReader.readUnsigned(1);
963             pXSector->shadeWalls = bitReader.readUnsigned(1);
964             pXSector->shade = bitReader.readSigned(8);
965             pXSector->panAlways = bitReader.readUnsigned(1);
966             pXSector->panFloor = bitReader.readUnsigned(1);
967             pXSector->panCeiling = bitReader.readUnsigned(1);
968             pXSector->Drag = bitReader.readUnsigned(1);
969             pXSector->Underwater = bitReader.readUnsigned(1);
970             pXSector->Depth = bitReader.readUnsigned(3);
971             pXSector->panVel = bitReader.readUnsigned(8);
972             pXSector->panAngle = bitReader.readUnsigned(11);
973             pXSector->unused1 = bitReader.readUnsigned(1);
974             pXSector->decoupled = bitReader.readUnsigned(1);
975             pXSector->triggerOnce = bitReader.readUnsigned(1);
976             pXSector->isTriggered = bitReader.readUnsigned(1);
977             pXSector->Key = bitReader.readUnsigned(3);
978             pXSector->Push = bitReader.readUnsigned(1);
979             pXSector->Vector = bitReader.readUnsigned(1);
980             pXSector->Reserved = bitReader.readUnsigned(1);
981             pXSector->Enter = bitReader.readUnsigned(1);
982             pXSector->Exit = bitReader.readUnsigned(1);
983             pXSector->Wallpush = bitReader.readUnsigned(1);
984             pXSector->color = bitReader.readUnsigned(1);
985             pXSector->unused2 = bitReader.readUnsigned(1);
986             pXSector->busyTimeB = bitReader.readUnsigned(12);
987             pXSector->waitTimeB = bitReader.readUnsigned(12);
988             pXSector->stopOn = bitReader.readUnsigned(1);
989             pXSector->stopOff = bitReader.readUnsigned(1);
990             pXSector->ceilpal = bitReader.readUnsigned(4);
991             pXSector->offCeilZ = bitReader.readSigned(32);
992             pXSector->onCeilZ = bitReader.readSigned(32);
993             pXSector->offFloorZ = bitReader.readSigned(32);
994             pXSector->onFloorZ = bitReader.readSigned(32);
995             pXSector->marker0 = bitReader.readUnsigned(16);
996             pXSector->marker1 = bitReader.readUnsigned(16);
997             pXSector->Crush = bitReader.readUnsigned(1);
998             pXSector->ceilXPanFrac = bitReader.readUnsigned(8);
999             pXSector->ceilYPanFrac = bitReader.readUnsigned(8);
1000             pXSector->floorXPanFrac = bitReader.readUnsigned(8);
1001             pXSector->damageType = bitReader.readUnsigned(3);
1002             pXSector->floorpal = bitReader.readUnsigned(4);
1003             pXSector->floorYPanFrac = bitReader.readUnsigned(8);
1004             pXSector->locked = bitReader.readUnsigned(1);
1005             pXSector->windVel = bitReader.readUnsigned(10);
1006             pXSector->windAng = bitReader.readUnsigned(11);
1007             pXSector->windAlways = bitReader.readUnsigned(1);
1008             pXSector->dudeLockout = bitReader.readUnsigned(1);
1009             pXSector->bobTheta = bitReader.readUnsigned(11);
1010             pXSector->bobZRange = bitReader.readUnsigned(5);
1011             pXSector->bobSpeed = bitReader.readSigned(12);
1012             pXSector->bobAlways = bitReader.readUnsigned(1);
1013             pXSector->bobFloor = bitReader.readUnsigned(1);
1014             pXSector->bobCeiling = bitReader.readUnsigned(1);
1015             pXSector->bobRotate = bitReader.readUnsigned(1);
1016             xsector[sector[i].extra].reference = i;
1017             xsector[sector[i].extra].busy = xsector[sector[i].extra].state<<16;
1018 
1019         }
1020     }
1021     for (int i = 0; i < numwalls; i++)
1022     {
1023         walltype *pWall = &wall[i];
1024         IOBuffer1.Read(pWall, sizeof(walltype));
1025         if (byte_1A76C8)
1026         {
1027             dbCrypt((char*)pWall, sizeof(walltype), (gMapRev*sizeof(sectortype)) | 0x7474614d);
1028         }
1029 #if B_BIG_ENDIAN == 1
1030         pWall->x = B_LITTLE32(pWall->x);
1031         pWall->y = B_LITTLE32(pWall->y);
1032         pWall->point2 = B_LITTLE16(pWall->point2);
1033         pWall->nextwall = B_LITTLE16(pWall->nextwall);
1034         pWall->nextsector = B_LITTLE16(pWall->nextsector);
1035         pWall->cstat = B_LITTLE16(pWall->cstat);
1036         pWall->picnum = B_LITTLE16(pWall->picnum);
1037         pWall->overpicnum = B_LITTLE16(pWall->overpicnum);
1038         pWall->type = B_LITTLE16(pWall->type);
1039         pWall->hitag = B_LITTLE16(pWall->hitag);
1040         pWall->extra = B_LITTLE16(pWall->extra);
1041 #endif
1042         if (wall[i].extra > 0)
1043         {
1044             char pBuffer[nXWallSize];
1045             int nXWall = dbInsertXWall(i);
1046             XWALL *pXWall = &xwall[nXWall];
1047             memset(pXWall, 0, sizeof(XWALL));
1048             int nCount;
1049             if (!byte_1A76C8)
1050             {
1051                 nCount = nXWallSize;
1052             }
1053             else
1054             {
1055                 nCount = byte_19AE44.at44;
1056             }
1057             dassert(nCount <= nXWallSize);
1058             IOBuffer1.Read(pBuffer, nCount);
1059             BitReader bitReader(pBuffer, nCount);
1060             pXWall->reference = bitReader.readSigned(14);
1061             pXWall->state = bitReader.readUnsigned(1);
1062             pXWall->busy = bitReader.readUnsigned(17);
1063             pXWall->data = bitReader.readSigned(16);
1064             pXWall->txID = bitReader.readUnsigned(10);
1065             pXWall->unused1 = bitReader.readUnsigned(6);
1066             pXWall->rxID = bitReader.readUnsigned(10);
1067             pXWall->command = bitReader.readUnsigned(8);
1068             pXWall->triggerOn = bitReader.readUnsigned(1);
1069             pXWall->triggerOff = bitReader.readUnsigned(1);
1070             pXWall->busyTime = bitReader.readUnsigned(12);
1071             pXWall->waitTime = bitReader.readUnsigned(12);
1072             pXWall->restState = bitReader.readUnsigned(1);
1073             pXWall->interruptable = bitReader.readUnsigned(1);
1074             pXWall->panAlways = bitReader.readUnsigned(1);
1075             pXWall->panXVel = bitReader.readSigned(8);
1076             pXWall->panYVel = bitReader.readSigned(8);
1077             pXWall->decoupled = bitReader.readUnsigned(1);
1078             pXWall->triggerOnce = bitReader.readUnsigned(1);
1079             pXWall->isTriggered = bitReader.readUnsigned(1);
1080             pXWall->key = bitReader.readUnsigned(3);
1081             pXWall->triggerPush = bitReader.readUnsigned(1);
1082             pXWall->triggerVector = bitReader.readUnsigned(1);
1083             pXWall->triggerTouch = bitReader.readUnsigned(1);
1084             pXWall->unused2 = bitReader.readUnsigned(2);
1085             pXWall->xpanFrac = bitReader.readUnsigned(8);
1086             pXWall->ypanFrac = bitReader.readUnsigned(8);
1087             pXWall->locked = bitReader.readUnsigned(1);
1088             pXWall->dudeLockout = bitReader.readUnsigned(1);
1089             pXWall->unused3 = bitReader.readUnsigned(4);
1090             pXWall->unused4 = bitReader.readUnsigned(32);
1091             xwall[wall[i].extra].reference = i;
1092             xwall[wall[i].extra].busy = xwall[wall[i].extra].state << 16;
1093 
1094         }
1095     }
1096     initspritelists();
1097     for (int i = 0; i < mapHeader.at23; i++)
1098     {
1099         RemoveSpriteStat(i);
1100         spritetype *pSprite = &sprite[i];
1101         IOBuffer1.Read(pSprite, sizeof(spritetype));
1102         if (byte_1A76C8)
1103         {
1104             dbCrypt((char*)pSprite, sizeof(spritetype), (gMapRev*sizeof(spritetype)) | 0x7474614d);
1105         }
1106 #if B_BIG_ENDIAN == 1
1107         pSprite->x = B_LITTLE32(pSprite->x);
1108         pSprite->y = B_LITTLE32(pSprite->y);
1109         pSprite->z = B_LITTLE32(pSprite->z);
1110         pSprite->cstat = B_LITTLE16(pSprite->cstat);
1111         pSprite->picnum = B_LITTLE16(pSprite->picnum);
1112         pSprite->sectnum = B_LITTLE16(pSprite->sectnum);
1113         pSprite->statnum = B_LITTLE16(pSprite->statnum);
1114         pSprite->ang = B_LITTLE16(pSprite->ang);
1115         pSprite->owner = B_LITTLE16(pSprite->owner);
1116         pSprite->index = B_LITTLE16(pSprite->index);
1117         pSprite->yvel = B_LITTLE16(pSprite->yvel);
1118         pSprite->inittype = B_LITTLE16(pSprite->inittype);
1119         pSprite->type = B_LITTLE16(pSprite->type);
1120         pSprite->flags = B_LITTLE16(pSprite->hitag);
1121         pSprite->extra = B_LITTLE16(pSprite->extra);
1122 #endif
1123         InsertSpriteSect(i, sprite[i].sectnum);
1124         InsertSpriteStat(i, sprite[i].statnum);
1125         Numsprites++;
1126         sprite[i].index = i;
1127         qsprite_filler[i] = pSprite->blend;
1128         pSprite->blend = 0;
1129         if (sprite[i].extra > 0)
1130         {
1131             char pBuffer[nXSpriteSize];
1132             int nXSprite = dbInsertXSprite(i);
1133             XSPRITE *pXSprite = &xsprite[nXSprite];
1134             memset(pXSprite, 0, sizeof(XSPRITE));
1135             int nCount;
1136             if (!byte_1A76C8)
1137             {
1138                 nCount = nXSpriteSize;
1139             }
1140             else
1141             {
1142                 nCount = byte_19AE44.at40;
1143             }
1144             dassert(nCount <= nXSpriteSize);
1145             IOBuffer1.Read(pBuffer, nCount);
1146             BitReader bitReader(pBuffer, nCount);
1147             pXSprite->reference = bitReader.readSigned(14);
1148             pXSprite->state = bitReader.readUnsigned(1);
1149             pXSprite->busy = bitReader.readUnsigned(17);
1150             pXSprite->txID = bitReader.readUnsigned(10);
1151             pXSprite->rxID = bitReader.readUnsigned(10);
1152             pXSprite->command = bitReader.readUnsigned(8);
1153             pXSprite->triggerOn = bitReader.readUnsigned(1);
1154             pXSprite->triggerOff = bitReader.readUnsigned(1);
1155             pXSprite->wave = bitReader.readUnsigned(2);
1156             pXSprite->busyTime = bitReader.readUnsigned(12);
1157             pXSprite->waitTime = bitReader.readUnsigned(12);
1158             pXSprite->restState = bitReader.readUnsigned(1);
1159             pXSprite->Interrutable = bitReader.readUnsigned(1);
1160             pXSprite->unused1 = bitReader.readUnsigned(2);
1161             pXSprite->respawnPending = bitReader.readUnsigned(2);
1162             pXSprite->unused2 = bitReader.readUnsigned(1);
1163             pXSprite->lT = bitReader.readUnsigned(1);
1164             pXSprite->dropMsg = bitReader.readUnsigned(8);
1165             pXSprite->Decoupled = bitReader.readUnsigned(1);
1166             pXSprite->triggerOnce = bitReader.readUnsigned(1);
1167             pXSprite->isTriggered = bitReader.readUnsigned(1);
1168             pXSprite->key = bitReader.readUnsigned(3);
1169             pXSprite->Push = bitReader.readUnsigned(1);
1170             pXSprite->Vector = bitReader.readUnsigned(1);
1171             pXSprite->Impact = bitReader.readUnsigned(1);
1172             pXSprite->Pickup = bitReader.readUnsigned(1);
1173             pXSprite->Touch = bitReader.readUnsigned(1);
1174             pXSprite->Sight = bitReader.readUnsigned(1);
1175             pXSprite->Proximity = bitReader.readUnsigned(1);
1176             pXSprite->unused3 = bitReader.readUnsigned(2);
1177             pXSprite->lSkill = bitReader.readUnsigned(5);
1178             pXSprite->lS = bitReader.readUnsigned(1);
1179             pXSprite->lB = bitReader.readUnsigned(1);
1180             pXSprite->lC = bitReader.readUnsigned(1);
1181             pXSprite->DudeLockout = bitReader.readUnsigned(1);
1182             pXSprite->data1 = bitReader.readSigned(16);
1183             pXSprite->data2 = bitReader.readSigned(16);
1184             pXSprite->data3 = bitReader.readSigned(16);
1185             pXSprite->goalAng = bitReader.readUnsigned(11);
1186             pXSprite->dodgeDir = bitReader.readSigned(2);
1187             pXSprite->locked = bitReader.readUnsigned(1);
1188             pXSprite->medium = bitReader.readUnsigned(2);
1189             pXSprite->respawn = bitReader.readUnsigned(2);
1190             pXSprite->data4 = bitReader.readUnsigned(16);
1191             pXSprite->unused4 = bitReader.readUnsigned(6);
1192             pXSprite->lockMsg = bitReader.readUnsigned(8);
1193             pXSprite->health = bitReader.readUnsigned(12);
1194             pXSprite->dudeDeaf = bitReader.readUnsigned(1);
1195             pXSprite->dudeAmbush = bitReader.readUnsigned(1);
1196             pXSprite->dudeGuard = bitReader.readUnsigned(1);
1197             pXSprite->dudeFlag4 = bitReader.readUnsigned(1);
1198             pXSprite->target = bitReader.readSigned(16);
1199             pXSprite->targetX = bitReader.readSigned(32);
1200             pXSprite->targetY = bitReader.readSigned(32);
1201             pXSprite->targetZ = bitReader.readSigned(32);
1202             pXSprite->burnTime = bitReader.readUnsigned(16);
1203             pXSprite->burnSource = bitReader.readSigned(16);
1204             pXSprite->height = bitReader.readUnsigned(16);
1205             pXSprite->stateTimer = bitReader.readUnsigned(16);
1206             pXSprite->aiState = NULL;
1207             bitReader.skipBits(32);
1208             xsprite[sprite[i].extra].reference = i;
1209             xsprite[sprite[i].extra].busy = xsprite[sprite[i].extra].state << 16;
1210             if (!byte_1A76C8) {
1211                 xsprite[sprite[i].extra].lT |= xsprite[sprite[i].extra].lB;
1212             }
1213 
1214             #ifdef NOONE_EXTENSIONS
1215             // indicate if the map requires modern features to work properly
1216             // for maps wich created in different editors (include vanilla MAPEDIT) or in PMAPEDIT version below than BETA13
1217             if (!gModernMap && pXSprite->rxID == kChannelMapModernize && pXSprite->rxID == pXSprite->txID && pXSprite->command == kCmdModernFeaturesEnable)
1218                 gModernMap = true;
1219             #endif
1220         }
1221 #if 0
1222         if ((sprite[i].cstat & 0x30) == 0x30)
1223         {
1224             sprite[i].cstat &= ~0x30;
1225         }
1226 #endif
1227     }
1228     unsigned int nCRC;
1229     IOBuffer1.Read(&nCRC, 4);
1230 #if B_BIG_ENDIAN == 1
1231     nCRC = B_LITTLE32(nCRC);
1232 #endif
1233     md4once((unsigned char*)pData, nSize, g_loadedMapHack.md4);
1234     if (Bcrc32(pData, nSize-4, 0) != nCRC)
1235     {
1236         initprintf("Map File does not match CRC");
1237         gSysRes.Unlock(pNode);
1238         return -1;
1239     }
1240     if (pCRC)
1241         *pCRC = nCRC;
1242     gSysRes.Unlock(pNode);
1243     PropagateMarkerReferences();
1244     if (byte_1A76C8)
1245     {
1246         if (gSongId == 0x7474614d || gSongId == 0x4d617474)
1247         {
1248             byte_1A76C6 = 1;
1249         }
1250         else if (!gSongId)
1251         {
1252             byte_1A76C6 = 0;
1253         }
1254         else
1255         {
1256             initprintf("Corrupted Map file");
1257             gSysRes.Unlock(pNode);
1258             return -1;
1259         }
1260     }
1261     else if (gSongId != 0)
1262     {
1263         initprintf("Corrupted Map file");
1264         gSysRes.Unlock(pNode);
1265         return -1;
1266     }
1267 
1268 #ifdef POLYMER
1269     if (videoGetRenderMode() == REND_POLYMER)
1270         polymer_loadboard();
1271 #endif
1272 
1273     if ((header.version & 0xff00) == 0x600)
1274     {
1275         switch (header.version&0xff)
1276         {
1277         case 0:
1278             for (int i = 0; i < numsectors; i++)
1279             {
1280                 sectortype *pSector = &sector[i];
1281                 if (pSector->extra > 0)
1282                 {
1283                     XSECTOR *pXSector = &xsector[pSector->extra];
1284                     pXSector->busyTimeB = pXSector->busyTimeA;
1285                     if (pXSector->busyTimeA > 0)
1286                     {
1287                         if (!pXSector->restState)
1288                         {
1289                             pXSector->reTriggerA = 1;
1290                         }
1291                         else
1292                         {
1293                             pXSector->waitTimeB = pXSector->busyTimeA;
1294                             pXSector->waitTimeA = 0;
1295                             pXSector->reTriggerB = 1;
1296                         }
1297                     }
1298                 }
1299             }
1300             fallthrough__;
1301         case 1:
1302             for (int i = 0; i < numsectors; i++)
1303             {
1304                 sectortype *pSector = &sector[i];
1305                 if (pSector->extra > 0)
1306                 {
1307                     XSECTOR *pXSector = &xsector[pSector->extra];
1308                     pXSector->freq >>= 1;
1309                 }
1310             }
1311             fallthrough__;
1312         case 2:
1313             for (int i = 0; i < kMaxSprites; i++)
1314             {
1315             }
1316             break;
1317 
1318         }
1319     }
1320 
1321 #ifdef YAX_ENABLE
1322     yax_update((header.version & 0xff00) > 0x700 ? 0 : 1);
1323     if (editstatus)
1324         yax_updategrays(*pZ);
1325 #endif
1326 
1327     g_loadedMapVersion = 7;
1328 
1329     return 0;
1330 }
1331 
dbSaveMap(const char * pPath,int nX,int nY,int nZ,short nAngle,short nSector)1332 int dbSaveMap(const char *pPath, int nX, int nY, int nZ, short nAngle, short nSector)
1333 {
1334     char sMapExt[BMAX_PATH];
1335     char sBakExt[BMAX_PATH];
1336     int16_t tpskyoff[256];
1337     int nSpriteNum;
1338     psky_t *pSky = tileSetupSky(0);
1339     gSkyCount = 1<<pSky->lognumtiles;
1340     gMapRev++;
1341     nSpriteNum = 0;
1342     strcpy(sMapExt, pPath);
1343     ChangeExtension(sMapExt, ".MAP");
1344     int nSize = sizeof(MAPSIGNATURE)+sizeof(MAPHEADER);
1345     if (byte_1A76C8)
1346     {
1347         nSize += sizeof(MAPHEADER2);
1348     }
1349     for (int i = 0; i < gSkyCount; i++)
1350         tpskyoff[i] = pSky->tileofs[i];
1351     nSize += gSkyCount*sizeof(tpskyoff[0]);
1352     nSize += sizeof(sectortype)*numsectors;
1353     for (int i = 0; i < numsectors; i++)
1354     {
1355         if (sector[i].extra > 0)
1356         {
1357             nSize += nXSectorSize;
1358         }
1359     }
1360     nSize += sizeof(walltype)*numwalls;
1361     for (int i = 0; i < numwalls; i++)
1362     {
1363         if (wall[i].extra > 0)
1364         {
1365             nSize += nXWallSize;
1366         }
1367     }
1368     for (int i = 0; i < kMaxSprites; i++)
1369     {
1370         if (sprite[i].statnum < kMaxStatus)
1371         {
1372             nSpriteNum++;
1373             if (sprite[i].extra > 0)
1374             {
1375                 nSize += nXSpriteSize;
1376             }
1377         }
1378     }
1379     nSize += sizeof(spritetype)*nSpriteNum;
1380     nSize += 4;
1381     char *pData = (char*)Xmalloc(nSize);
1382     IOBuffer IOBuffer1 = IOBuffer(nSize, pData);
1383     MAPSIGNATURE header;
1384     memcpy(&header, "BLM\x1a", 4);
1385     if (byte_1A76C8)
1386     {
1387         header.version = 0x700;
1388         byte_1A76C7 = 1;
1389     }
1390     else
1391     {
1392         header.version = 0x603;
1393         byte_1A76C7 = 0;
1394     }
1395     IOBuffer1.Write(&header, sizeof(header));
1396     MAPHEADER mapheader;
1397     mapheader.at0 = B_LITTLE32(nX);
1398     mapheader.at4 = B_LITTLE32(nY);
1399     mapheader.at8 = B_LITTLE32(nZ);
1400     mapheader.atc = B_LITTLE16(nAngle);
1401     mapheader.ate = B_LITTLE16(nSector);
1402     mapheader.at10 = B_LITTLE16(pSky->lognumtiles);
1403     mapheader.at12 = B_LITTLE32(gVisibility);
1404     if (byte_1A76C6)
1405     {
1406         gSongId = 0x7474614d;
1407     }
1408     else
1409     {
1410         gSongId = 0;
1411     }
1412     mapheader.at16 = B_LITTLE32(gSongId);
1413     mapheader.at1a = parallaxtype;
1414     mapheader.at1b = gMapRev;
1415     mapheader.at1f = B_LITTLE16(numsectors);
1416     mapheader.at21 = B_LITTLE16(numwalls);
1417     mapheader.at23 = B_LITTLE16(nSpriteNum);
1418     if (byte_1A76C7)
1419     {
1420         dbCrypt((char*)&mapheader, sizeof(MAPHEADER), 'ttaM');
1421     }
1422     IOBuffer1.Write(&mapheader, sizeof(MAPHEADER));
1423     if (byte_1A76C8)
1424     {
1425         Bstrcpy(byte_19AE44.at0, AppProperName);
1426         byte_19AE44.at48 = nXSectorSize;
1427         byte_19AE44.at44 = nXWallSize;
1428         byte_19AE44.at40 = nXSpriteSize;
1429         dbCrypt((char*)&byte_19AE44, sizeof(MAPHEADER2), numwalls);
1430         IOBuffer1.Write(&byte_19AE44, sizeof(MAPHEADER2));
1431         dbCrypt((char*)&byte_19AE44, sizeof(MAPHEADER2), numwalls);
1432     }
1433     if (byte_1A76C8)
1434     {
1435         dbCrypt((char*)tpskyoff, gSkyCount*sizeof(tpskyoff[0]), gSkyCount*sizeof(tpskyoff[0]));
1436     }
1437     IOBuffer1.Write(tpskyoff, gSkyCount*sizeof(tpskyoff[0]));
1438     if (byte_1A76C8)
1439     {
1440         dbCrypt((char*)tpskyoff, gSkyCount*sizeof(tpskyoff[0]), gSkyCount*sizeof(tpskyoff[0]));
1441     }
1442     for (int i = 0; i < numsectors; i++)
1443     {
1444         if (byte_1A76C8)
1445         {
1446             dbCrypt((char*)&sector[i], sizeof(sectortype), gMapRev*sizeof(sectortype));
1447         }
1448         IOBuffer1.Write(&sector[i], sizeof(sectortype));
1449         if (byte_1A76C8)
1450         {
1451             dbCrypt((char*)&sector[i], sizeof(sectortype), gMapRev*sizeof(sectortype));
1452         }
1453         if (sector[i].extra > 0)
1454         {
1455             char pBuffer[nXSectorSize];
1456             BitWriter bitWriter(pBuffer, nXSectorSize);
1457             XSECTOR* pXSector = &xsector[sector[i].extra];
1458             bitWriter.write(pXSector->reference, 14);
1459             bitWriter.write(pXSector->state, 1);
1460             bitWriter.write(pXSector->busy, 17);
1461             bitWriter.write(pXSector->data, 16);
1462             bitWriter.write(pXSector->txID, 10);
1463             bitWriter.write(pXSector->busyWaveA, 3);
1464             bitWriter.write(pXSector->busyWaveB, 3);
1465             bitWriter.write(pXSector->rxID, 10);
1466             bitWriter.write(pXSector->command, 8);
1467             bitWriter.write(pXSector->triggerOn, 1);
1468             bitWriter.write(pXSector->triggerOff, 1);
1469             bitWriter.write(pXSector->busyTimeA, 12);
1470             bitWriter.write(pXSector->waitTimeA, 12);
1471             bitWriter.write(pXSector->restState, 1);
1472             bitWriter.write(pXSector->interruptable, 1);
1473             bitWriter.write(pXSector->amplitude, 8);
1474             bitWriter.write(pXSector->freq, 8);
1475             bitWriter.write(pXSector->reTriggerA, 1);
1476             bitWriter.write(pXSector->reTriggerB, 1);
1477             bitWriter.write(pXSector->phase, 8);
1478             bitWriter.write(pXSector->wave, 4);
1479             bitWriter.write(pXSector->shadeAlways, 1);
1480             bitWriter.write(pXSector->shadeFloor, 1);
1481             bitWriter.write(pXSector->shadeCeiling, 1);
1482             bitWriter.write(pXSector->shadeWalls, 1);
1483             bitWriter.write(pXSector->shade, 8);
1484             bitWriter.write(pXSector->panAlways, 1);
1485             bitWriter.write(pXSector->panFloor, 1);
1486             bitWriter.write(pXSector->panCeiling, 1);
1487             bitWriter.write(pXSector->Drag, 1);
1488             bitWriter.write(pXSector->Underwater, 1);
1489             bitWriter.write(pXSector->Depth, 3);
1490             bitWriter.write(pXSector->panVel, 8);
1491             bitWriter.write(pXSector->panAngle, 11);
1492             bitWriter.write(pXSector->unused1, 1);
1493             bitWriter.write(pXSector->decoupled, 1);
1494             bitWriter.write(pXSector->triggerOnce, 1);
1495             bitWriter.write(pXSector->isTriggered, 1);
1496             bitWriter.write(pXSector->Key, 3);
1497             bitWriter.write(pXSector->Push, 1);
1498             bitWriter.write(pXSector->Vector, 1);
1499             bitWriter.write(pXSector->Reserved, 1);
1500             bitWriter.write(pXSector->Enter, 1);
1501             bitWriter.write(pXSector->Exit, 1);
1502             bitWriter.write(pXSector->Wallpush, 1);
1503             bitWriter.write(pXSector->color, 1);
1504             bitWriter.write(pXSector->unused2, 1);
1505             bitWriter.write(pXSector->busyTimeB, 12);
1506             bitWriter.write(pXSector->waitTimeB, 12);
1507             bitWriter.write(pXSector->stopOn, 1);
1508             bitWriter.write(pXSector->stopOff, 1);
1509             bitWriter.write(pXSector->ceilpal, 4);
1510             bitWriter.write(pXSector->offCeilZ, 32);
1511             bitWriter.write(pXSector->onCeilZ, 32);
1512             bitWriter.write(pXSector->offFloorZ, 32);
1513             bitWriter.write(pXSector->onFloorZ, 32);
1514             bitWriter.write(pXSector->marker0, 16);
1515             bitWriter.write(pXSector->marker1, 16);
1516             bitWriter.write(pXSector->Crush, 1);
1517             bitWriter.write(pXSector->ceilXPanFrac, 8);
1518             bitWriter.write(pXSector->ceilYPanFrac, 8);
1519             bitWriter.write(pXSector->floorXPanFrac, 8);
1520             bitWriter.write(pXSector->damageType, 3);
1521             bitWriter.write(pXSector->floorpal, 4);
1522             bitWriter.write(pXSector->floorYPanFrac, 8);
1523             bitWriter.write(pXSector->locked, 1);
1524             bitWriter.write(pXSector->windVel, 10);
1525             bitWriter.write(pXSector->windAng, 11);
1526             bitWriter.write(pXSector->windAlways, 1);
1527             bitWriter.write(pXSector->dudeLockout, 1);
1528             bitWriter.write(pXSector->bobTheta, 11);
1529             bitWriter.write(pXSector->bobZRange, 5);
1530             bitWriter.write(pXSector->bobSpeed, 12);
1531             bitWriter.write(pXSector->bobAlways, 1);
1532             bitWriter.write(pXSector->bobFloor, 1);
1533             bitWriter.write(pXSector->bobCeiling, 1);
1534             bitWriter.write(pXSector->bobRotate, 1);
1535             IOBuffer1.Write(pBuffer, nXSectorSize);
1536         }
1537     }
1538     for (int i = 0; i < numwalls; i++)
1539     {
1540         if (byte_1A76C8)
1541         {
1542             dbCrypt((char*)&wall[i], sizeof(walltype), gMapRev*sizeof(sectortype) | 0x7474614d);
1543         }
1544         IOBuffer1.Write(&wall[i], sizeof(walltype));
1545         if (byte_1A76C8)
1546         {
1547             dbCrypt((char*)&wall[i], sizeof(walltype), gMapRev*sizeof(sectortype) | 0x7474614d);
1548         }
1549         if (wall[i].extra > 0)
1550         {
1551             char pBuffer[nXWallSize];
1552             BitWriter bitWriter(pBuffer, nXWallSize);
1553             XWALL* pXWall = &xwall[wall[i].extra];
1554             bitWriter.write(pXWall->reference, 14);
1555             bitWriter.write(pXWall->state, 1);
1556             bitWriter.write(pXWall->busy, 17);
1557             bitWriter.write(pXWall->data, 16);
1558             bitWriter.write(pXWall->txID, 10);
1559             bitWriter.write(pXWall->unused1, 6);
1560             bitWriter.write(pXWall->rxID, 10);
1561             bitWriter.write(pXWall->command, 8);
1562             bitWriter.write(pXWall->triggerOn, 1);
1563             bitWriter.write(pXWall->triggerOff, 1);
1564             bitWriter.write(pXWall->busyTime, 12);
1565             bitWriter.write(pXWall->waitTime, 12);
1566             bitWriter.write(pXWall->restState, 1);
1567             bitWriter.write(pXWall->interruptable, 1);
1568             bitWriter.write(pXWall->panAlways, 1);
1569             bitWriter.write(pXWall->panXVel, 8);
1570             bitWriter.write(pXWall->panYVel, 8);
1571             bitWriter.write(pXWall->decoupled, 1);
1572             bitWriter.write(pXWall->triggerOnce, 1);
1573             bitWriter.write(pXWall->isTriggered, 1);
1574             bitWriter.write(pXWall->key, 3);
1575             bitWriter.write(pXWall->triggerPush, 1);
1576             bitWriter.write(pXWall->triggerVector, 1);
1577             bitWriter.write(pXWall->triggerTouch, 1);
1578             bitWriter.write(pXWall->unused2, 2);
1579             bitWriter.write(pXWall->xpanFrac, 8);
1580             bitWriter.write(pXWall->ypanFrac, 8);
1581             bitWriter.write(pXWall->locked, 1);
1582             bitWriter.write(pXWall->dudeLockout, 1);
1583             bitWriter.write(pXWall->unused3, 4);
1584             bitWriter.write(pXWall->unused4, 32);
1585             IOBuffer1.Write(pBuffer, nXWallSize);
1586         }
1587     }
1588     for (int i = 0; i < kMaxSprites; i++)
1589     {
1590         if (sprite[i].statnum < kMaxStatus)
1591         {
1592             if (byte_1A76C8)
1593             {
1594                 dbCrypt((char*)&sprite[i], sizeof(spritetype), gMapRev*sizeof(spritetype) | 'ttaM');
1595             }
1596             IOBuffer1.Write(&sprite[i], sizeof(spritetype));
1597             if (byte_1A76C8)
1598             {
1599                 dbCrypt((char*)&sprite[i], sizeof(spritetype), gMapRev*sizeof(spritetype) | 'ttaM');
1600             }
1601             if (sprite[i].extra > 0)
1602             {
1603                 char pBuffer[nXSpriteSize];
1604                 BitWriter bitWriter(pBuffer, nXSpriteSize);
1605                 XSPRITE* pXSprite = &xsprite[sprite[i].extra];
1606                 bitWriter.write(pXSprite->reference, 14);
1607                 bitWriter.write(pXSprite->state, 1);
1608                 bitWriter.write(pXSprite->busy, 17);
1609                 bitWriter.write(pXSprite->txID, 10);
1610                 bitWriter.write(pXSprite->rxID, 10);
1611                 bitWriter.write(pXSprite->command, 8);
1612                 bitWriter.write(pXSprite->triggerOn, 1);
1613                 bitWriter.write(pXSprite->triggerOff, 1);
1614                 bitWriter.write(pXSprite->wave, 2);
1615                 bitWriter.write(pXSprite->busyTime, 12);
1616                 bitWriter.write(pXSprite->waitTime, 12);
1617                 bitWriter.write(pXSprite->restState, 1);
1618                 bitWriter.write(pXSprite->Interrutable, 1);
1619                 bitWriter.write(pXSprite->unused1, 2);
1620                 bitWriter.write(pXSprite->respawnPending, 2);
1621                 bitWriter.write(pXSprite->unused2, 1);
1622                 bitWriter.write(pXSprite->lT, 1);
1623                 bitWriter.write(pXSprite->dropMsg, 8);
1624                 bitWriter.write(pXSprite->Decoupled, 1);
1625                 bitWriter.write(pXSprite->triggerOnce, 1);
1626                 bitWriter.write(pXSprite->isTriggered, 1);
1627                 bitWriter.write(pXSprite->key, 3);
1628                 bitWriter.write(pXSprite->Push, 1);
1629                 bitWriter.write(pXSprite->Vector, 1);
1630                 bitWriter.write(pXSprite->Impact, 1);
1631                 bitWriter.write(pXSprite->Pickup, 1);
1632                 bitWriter.write(pXSprite->Touch, 1);
1633                 bitWriter.write(pXSprite->Sight, 1);
1634                 bitWriter.write(pXSprite->Proximity, 1);
1635                 bitWriter.write(pXSprite->unused3, 2);
1636                 bitWriter.write(pXSprite->lSkill, 5);
1637                 bitWriter.write(pXSprite->lS, 1);
1638                 bitWriter.write(pXSprite->lB, 1);
1639                 bitWriter.write(pXSprite->lC, 1);
1640                 bitWriter.write(pXSprite->DudeLockout, 1);
1641                 bitWriter.write(pXSprite->data1, 16);
1642                 bitWriter.write(pXSprite->data2, 16);
1643                 bitWriter.write(pXSprite->data3, 16);
1644                 bitWriter.write(pXSprite->goalAng, 11);
1645                 bitWriter.write(pXSprite->dodgeDir, 2);
1646                 bitWriter.write(pXSprite->locked, 1);
1647                 bitWriter.write(pXSprite->medium, 2);
1648                 bitWriter.write(pXSprite->respawn, 2);
1649                 bitWriter.write(pXSprite->data4, 16);
1650                 bitWriter.write(pXSprite->unused4, 6);
1651                 bitWriter.write(pXSprite->lockMsg, 8);
1652                 bitWriter.write(pXSprite->health, 12);
1653                 bitWriter.write(pXSprite->dudeDeaf, 1);
1654                 bitWriter.write(pXSprite->dudeAmbush, 1);
1655                 bitWriter.write(pXSprite->dudeGuard, 1);
1656                 bitWriter.write(pXSprite->dudeFlag4, 1);
1657                 bitWriter.write(pXSprite->target, 16);
1658                 bitWriter.write(pXSprite->targetX, 32);
1659                 bitWriter.write(pXSprite->targetY, 32);
1660                 bitWriter.write(pXSprite->targetZ, 32);
1661                 bitWriter.write(pXSprite->burnTime, 16);
1662                 bitWriter.write(pXSprite->burnSource, 16);
1663                 bitWriter.write(pXSprite->height, 16);
1664                 bitWriter.write(pXSprite->stateTimer, 16);
1665                 IOBuffer1.Write(pBuffer, nXSpriteSize);
1666             }
1667         }
1668     }
1669     unsigned int nCRC = Bcrc32(pData, nSize-4, 0);
1670     IOBuffer1.Write(&nCRC, 4);
1671     int nHandle = Bopen(sMapExt, BO_BINARY|BO_TRUNC|BO_CREAT|BO_WRONLY, BS_IREAD|BS_IWRITE);
1672     if (nHandle == -1)
1673     {
1674         initprintf("Couldn't open \"%s\" for writing: %s\n", sMapExt, strerror(errno));
1675         Bfree(pData);
1676         return -1;
1677     }
1678     if (Bwrite(nHandle, pData, nSize) != nSize)
1679     {
1680         initprintf("Couldn't write to \"%s\": %s\n", sMapExt, strerror(errno));
1681         Bclose(nHandle);
1682         Bfree(pData);
1683         return -1;
1684     }
1685     Bclose(nHandle);
1686     Bfree(pData);
1687     return 0;
1688 #if 0
1689     char *pExt = strchr(sMapExt, '.');
1690     if (pExt)
1691     {
1692         *pExt = 0;
1693     }
1694     gSysRes.AddExternalResource(sMapExt, "MAP", nSize);
1695     DICTNODE *hMap = gSysRes.Lookup(sMapExt, "MAP");
1696     dassert(hMap != NULL);
1697 #endif
1698 }
1699 
qloadboard(const char * filename,char flags,vec3_t * dapos,int16_t * daang,int16_t * dacursectnum)1700 int32_t qloadboard(const char* filename, char flags, vec3_t* dapos, int16_t* daang, int16_t* dacursectnum)
1701 {
1702     // NUKE-TODO: implement flags, see mapedit.cpp
1703     return dbLoadMap(filename, &dapos->x, &dapos->y, &dapos->z, (short*)daang, (short*)dacursectnum, NULL);
1704 }
1705 
qsaveboard(const char * filename,const vec3_t * dapos,int16_t daang,int16_t dacursectnum)1706 int32_t qsaveboard(const char* filename, const vec3_t* dapos, int16_t daang, int16_t dacursectnum)
1707 {
1708     // NUKE-TODO: see mapedit.cpp
1709     byte_1A76C6 = byte_1A76C8 = byte_1A76C7 = 1;
1710     return dbSaveMap(filename, dapos->x, dapos->y, dapos->z, daang, dacursectnum);
1711 }
1712