CONVDB6.CPP 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <stdarg.h>
  5. #include <dos.h>
  6. #include <io.h>
  7. #include <fcntl.h>
  8. #include "db.h"
  9. #include "getopt.h"
  10. #include "engine.h"
  11. #include "error.h"
  12. #include "misc.h"
  13. #include "iob.h"
  14. #include "tile.h"
  15. #include "trig.h"
  16. #include <memcheck.h>
  17. #define kBloodMapSig "BLM\x1A"
  18. #define kBloodMapVersion 0x0600
  19. #define kBloodMapOldVersion 0x0503
  20. struct FNODE
  21. {
  22. FNODE *next;
  23. char name[1];
  24. };
  25. FNODE head = { &head, "" };
  26. FNODE *tail = &head;
  27. // Build globals
  28. SECTOR sector[kMaxSectors];
  29. WALL wall[kMaxWalls];
  30. SPRITE sprite[kMaxSprites];
  31. // Q globals
  32. XSECTOR xsector[kMaxXSectors];
  33. XWALL xwall[kMaxXWalls];
  34. XSPRITE xsprite[kMaxXSprites];
  35. short pskyoff[kMaxSkyTiles];
  36. ulong gMapCRC;
  37. int gSkyCount;
  38. short numsectors, numwalls;
  39. struct HEADER5
  40. {
  41. char signature[4];
  42. short version;
  43. };
  44. struct HEADER6
  45. {
  46. char signature[4];
  47. short version;
  48. };
  49. // version 5.x header
  50. struct INFO5
  51. {
  52. long x, y, z;
  53. ushort angle;
  54. ushort sector;
  55. ushort pskybits;
  56. long visibility;
  57. int songId;
  58. uchar parallax;
  59. int mapRevisions;
  60. ushort numsectors;
  61. ushort numwalls;
  62. ushort numsprites;
  63. };
  64. struct INFO6
  65. {
  66. long x, y, z;
  67. ushort angle;
  68. ushort sector;
  69. ushort pskybits;
  70. long visibility;
  71. int songId;
  72. uchar parallax;
  73. int mapRevisions;
  74. ushort numsectors;
  75. ushort numwalls;
  76. ushort numsprites;
  77. };
  78. /***********************************************************************
  79. * Old version structures and typedefs
  80. **********************************************************************/
  81. struct SPRITE5
  82. {
  83. long x;
  84. long y;
  85. long z;
  86. ushort cstat;
  87. schar shade;
  88. uchar pal;
  89. uchar clipdist;
  90. uchar xrepeat;
  91. uchar yrepeat;
  92. schar xoffset;
  93. schar yoffset;
  94. sshort picnum;
  95. sshort ang;
  96. sshort xvel;
  97. sshort yvel;
  98. sshort zvel;
  99. sshort owner;
  100. sshort sectnum;
  101. sshort statnum;
  102. ushort type;
  103. ushort mass;
  104. sshort extra;
  105. };
  106. struct WALL5
  107. {
  108. long x;
  109. long y;
  110. ushort point2;
  111. short nextsector;
  112. short nextwall;
  113. short picnum;
  114. short overpicnum;
  115. signed char shade;
  116. char pal;
  117. short cstat;
  118. uchar xrepeat;
  119. uchar yrepeat;
  120. uchar xpanning;
  121. uchar ypanning;
  122. ushort type;
  123. short hitag;
  124. short extra;
  125. };
  126. struct SECTOR5
  127. {
  128. unsigned short wallptr;
  129. unsigned short wallnum;
  130. short ceilingpicnum;
  131. short floorpicnum;
  132. short ceilingslope;
  133. short floorslope;
  134. long ceilingz;
  135. long floorz;
  136. schar ceilingshade;
  137. schar floorshade;
  138. uchar ceilingxpanning;
  139. uchar floorxpanning;
  140. uchar ceilingypanning;
  141. uchar floorypanning;
  142. uchar ceilingstat;
  143. uchar floorstat;
  144. uchar ceilingpal;
  145. uchar floorpal;
  146. uchar visibility;
  147. ushort type;
  148. short hitag;
  149. short extra;
  150. };
  151. struct XSPRITE5
  152. {
  153. signed reference : 14;
  154. unsigned state : 1;
  155. // trigger data
  156. unsigned busy : 17;
  157. unsigned txID : 10;
  158. unsigned rxID : 10;
  159. unsigned command : 8;
  160. unsigned triggerOn : 1;
  161. unsigned triggerOff : 1;
  162. unsigned busyTime : 12; // time to reach next state
  163. unsigned waitTime : 12; // delay before callback
  164. unsigned restState : 1; // state to return to on callback
  165. unsigned difficulty : 2;
  166. unsigned map : 2;
  167. unsigned soundKit : 8;
  168. // physical triggers
  169. unsigned decoupled : 1;
  170. unsigned triggerOnce : 1;
  171. unsigned isTriggered : 1; // used for triggerOnce objects
  172. unsigned key : 3;
  173. unsigned triggerPush : 1; // action key
  174. unsigned triggerImpact : 1; // vector hits
  175. unsigned triggerExplode : 1; // exploding things, etc.
  176. unsigned triggerPickup : 1; // secrets
  177. unsigned triggerTouch : 1; // sawblades, spikes, zaps?
  178. unsigned triggerSight : 1; // dunno, yet.
  179. unsigned triggerProximity : 1; // proximity bombs
  180. unsigned triggerReserved1 : 1;
  181. unsigned triggerReserved2 : 1;
  182. signed data1 : 16; // combo value?
  183. signed data2 : 16; // combo key?
  184. signed data3 : 16; // combo max?
  185. unsigned respawn : 2; // 0=optional never, 1=optional always, 2=always, 3=never
  186. unsigned respawnTime : 12; // 0=permanent, >0=time in tenths of a second,
  187. unsigned launchMode : 2; // 0=all, 1=bloodbath, 2=ally, 3=ally&bloodbath,
  188. // this stuff needed for dudes
  189. unsigned moveState : 8; // same as player move states
  190. unsigned aiState : 8;
  191. signed health : 12;
  192. unsigned dudeDeaf : 1;
  193. unsigned dudeAmbush : 1;
  194. unsigned dudeFlag3 : 1;
  195. unsigned dudeFlag4 : 1;
  196. signed target : 16;
  197. signed targetX : 32;
  198. signed targetY : 32;
  199. signed targetZ : 32;
  200. signed avel : 16;
  201. unsigned weaponTimer : 16;
  202. unsigned stateTimer : 16;
  203. signed support : 16; // will be used by physics system
  204. unsigned interruptable : 1;
  205. unsigned pad : 31;
  206. };
  207. struct XWALL5
  208. {
  209. signed reference : 14;
  210. unsigned state : 1;
  211. // trigger data
  212. unsigned busy : 17;
  213. signed data : 16;
  214. unsigned txID : 10;
  215. unsigned rxID : 10;
  216. unsigned command : 8;
  217. unsigned triggerOn : 1;
  218. unsigned triggerOff : 1;
  219. unsigned busyTime : 12; // time to reach next state
  220. unsigned waitTime : 12; // delay before callback
  221. unsigned restState : 1; // state to return to on callback
  222. unsigned map : 2;
  223. // panning data
  224. unsigned panAlways : 1;
  225. signed panXVel : 8;
  226. signed panYVel : 8;
  227. // physical triggers
  228. unsigned decoupled : 1;
  229. unsigned triggerOnce : 1;
  230. unsigned isTriggered : 1; // used for triggerOnce objects
  231. unsigned key : 3;
  232. unsigned triggerPush : 1;
  233. unsigned triggerImpact : 1;
  234. unsigned triggerExplode : 1; // exploding things, etc.
  235. unsigned triggerReserved1 : 1;
  236. unsigned triggerReserved2 : 1;
  237. unsigned xpanFrac : 8;
  238. unsigned ypanFrac : 8;
  239. unsigned interruptable : 1;
  240. unsigned pad1 : 15;
  241. unsigned pad2 : 32;
  242. };
  243. struct XSECTOR5
  244. {
  245. signed reference : 14;
  246. unsigned state : 1;
  247. // trigger data
  248. unsigned busy : 17;
  249. signed data : 16;
  250. unsigned txID : 10;
  251. unsigned rxID : 10;
  252. unsigned command : 8;
  253. unsigned triggerOn : 1;
  254. unsigned triggerOff : 1;
  255. unsigned busyTime : 12; // time to reach next state
  256. unsigned waitTime : 12; // delay before callback
  257. unsigned restState : 1; // state to return to on callback
  258. // lighting data
  259. unsigned shadeAlways : 1;
  260. signed amplitude : 8;
  261. unsigned freq : 8;
  262. unsigned wave : 4;
  263. unsigned phase : 8;
  264. unsigned shadeFloor : 1;
  265. unsigned shadeCeiling : 1;
  266. unsigned shadeWalls : 1;
  267. signed shade : 8;
  268. // panning data
  269. unsigned panAlways : 1;
  270. unsigned panFloor : 1;
  271. unsigned panCeiling : 1;
  272. unsigned drag : 1;
  273. // wind/water stuff
  274. unsigned underwater : 1;
  275. unsigned depth : 2;
  276. unsigned panVel : 8;
  277. unsigned panAngle : 11;
  278. unsigned wind : 1;
  279. // physical triggers
  280. unsigned decoupled : 1;
  281. unsigned triggerOnce : 1;
  282. unsigned isTriggered : 1;
  283. unsigned key : 3;
  284. unsigned triggerPush : 1;
  285. unsigned triggerImpact : 1;
  286. unsigned triggerExplode : 1; // exploding things, etc.
  287. unsigned triggerEnter : 1;
  288. unsigned triggerExit : 1;
  289. unsigned triggerWPush : 1;
  290. unsigned triggerReserved1 : 1;
  291. unsigned triggerReserved2 : 1;
  292. // movement data
  293. signed offCeilZ : 32;
  294. signed onCeilZ : 32;
  295. signed offFloorZ : 32;
  296. signed onFloorZ : 32;
  297. signed marker0 : 16;
  298. signed marker1 : 16;
  299. // unsigned crush : 1;
  300. unsigned ceilxpanFrac : 8;
  301. unsigned ceilypanFrac : 8;
  302. unsigned floorxpanFrac : 8;
  303. unsigned floorypanFrac : 8;
  304. unsigned interruptable : 1;
  305. unsigned pad1 : 31;
  306. };
  307. void ShowUsage(void)
  308. {
  309. printf("Usage:\n");
  310. printf(" CONVDB6 map1 map2 (wild cards ok)\n");
  311. printf("\nTECHNICAL INFO:\n sizeof(XSPRITE)=%d\n sizeof(XSECTOR)=%d\n sizeof(XWALL)=%d",
  312. sizeof(XSPRITE), sizeof(XSECTOR), sizeof(XWALL));
  313. exit(0);
  314. }
  315. void QuitMessage(char * fmt, ...)
  316. {
  317. char msg[80];
  318. va_list argptr;
  319. va_start( argptr, fmt );
  320. vsprintf( msg, fmt, argptr );
  321. va_end(argptr);
  322. printf(msg);
  323. exit(1);
  324. }
  325. void ProcessFile(char *filespec)
  326. {
  327. int hFile;
  328. int i;
  329. HEADER5 header5;
  330. HEADER6 header6;
  331. INFO5 info5;
  332. INFO6 info6;
  333. char filename[_MAX_PATH], bakfilename[_MAX_PATH];
  334. short numsprites;
  335. int length;
  336. BYTE *buffer;
  337. strcpy(filename, filespec);
  338. printf("%s ", filename);
  339. hFile = open(filename, O_RDONLY | O_BINARY);
  340. if ( hFile == -1 )
  341. ThrowError("unable to open MAP file", ES_ERROR);
  342. length = filelength(hFile);
  343. buffer = (BYTE *)malloc(length);
  344. if (read(hFile, buffer, length) == length)
  345. {
  346. close(hFile);
  347. IOBuffer iob(buffer, length);
  348. iob.Read(&header5, sizeof(HEADER5));
  349. // check signature and major version number
  350. if ( (memcmp(header5.signature, kBloodMapSig, sizeof(header5.signature)) != 0)
  351. || ((header5.version >> 8) != (kBloodMapOldVersion >> 8)) )
  352. {
  353. printf("not expected format, skipping\n");
  354. return;
  355. }
  356. iob.Read(&info5, sizeof(INFO5));
  357. numsectors = info5.numsectors;
  358. numwalls = info5.numwalls;
  359. numsprites = info5.numsprites;
  360. gSkyCount = 1 << info5.pskybits;
  361. iob.Read(pskyoff, gSkyCount * sizeof(pskyoff[0]));
  362. for (i = 0; i < numsectors; i++)
  363. {
  364. SECTOR5 sector5;
  365. iob.Read(&sector5, sizeof(sector5));
  366. sector[i].wallptr = sector5.wallptr;
  367. sector[i].wallnum = sector5.wallnum;
  368. sector[i].ceilingz = sector5.ceilingz;
  369. sector[i].floorz = sector5.floorz;
  370. sector[i].ceilingstat = sector5.ceilingstat;
  371. sector[i].floorstat = sector5.floorstat;
  372. sector[i].ceilingpicnum = sector5.ceilingpicnum;
  373. sector[i].ceilingslope = (sshort)(sector5.ceilingslope << 5);
  374. sector[i].ceilingshade = sector5.ceilingshade;
  375. sector[i].ceilingpal = sector5.ceilingpal;
  376. sector[i].ceilingxpanning = sector5.ceilingxpanning;
  377. sector[i].ceilingypanning = sector5.ceilingypanning;
  378. sector[i].floorpicnum = sector5.floorpicnum;
  379. sector[i].floorslope = (sshort)(sector5.floorslope << 5);
  380. sector[i].floorshade = sector5.floorshade;
  381. sector[i].floorpal = sector5.floorpal;
  382. sector[i].floorxpanning = sector5.floorxpanning;
  383. sector[i].floorypanning = sector5.floorypanning;
  384. sector[i].visibility = sector5.visibility;
  385. sector[i].filler = 0;
  386. sector[i].type = sector5.type;
  387. sector[i].hitag = sector5.hitag;
  388. sector[i].extra = sector5.extra;
  389. if ( sector[i].ceilingslope == 0 )
  390. sector[i].ceilingstat &= ~kSectorSloped;
  391. if ( sector[i].floorslope == 0 )
  392. sector[i].floorstat &= ~kSectorSloped;
  393. if (sector[i].extra > 0)
  394. {
  395. int j = sector[i].extra;
  396. XSECTOR5 xsector5;
  397. iob.Read(&xsector5, sizeof(XSECTOR5));
  398. memset(&xsector[j], 0, sizeof(XSECTOR));
  399. xsector[j].reference = xsector5.reference;
  400. xsector[j].state = xsector5.state;
  401. // trigger data
  402. xsector[j].busy = 0;
  403. xsector[j].data = xsector5.data;
  404. xsector[j].txID = xsector5.txID;
  405. xsector[j].rxID = xsector5.rxID;
  406. xsector[j].command = xsector5.command;
  407. xsector[j].triggerOn = xsector5.triggerOn;
  408. xsector[j].triggerOff = xsector5.triggerOff;
  409. xsector[j].busyTime = xsector5.busyTime;
  410. xsector[j].waitTime = xsector5.waitTime;
  411. xsector[j].restState = xsector5.restState;
  412. xsector[j].interruptable = xsector5.interruptable;
  413. // lighting data
  414. xsector[j].amplitude = xsector5.amplitude;
  415. xsector[j].freq = xsector5.freq;
  416. xsector[j].phase = xsector5.phase;
  417. xsector[j].wave = xsector5.wave;
  418. xsector[j].shadeAlways = xsector5.shadeAlways;
  419. xsector[j].shadeFloor = xsector5.shadeFloor;
  420. xsector[j].shadeCeiling = xsector5.shadeCeiling;
  421. xsector[j].shadeWalls = xsector5.shadeWalls;
  422. xsector[j].shade = xsector5.shade;
  423. // panning data
  424. xsector[j].panAlways = xsector5.panAlways;
  425. xsector[j].panFloor = xsector5.panFloor;
  426. xsector[j].panCeiling = xsector5.panCeiling;
  427. xsector[j].drag = xsector5.drag;
  428. // wind/water stuff
  429. xsector[j].underwater = xsector5.underwater;
  430. xsector[j].depth = xsector5.depth;
  431. xsector[j].panVel = xsector5.panVel;
  432. xsector[j].panAngle = xsector5.panAngle;
  433. xsector[j].wind = xsector5.wind;
  434. // physical triggers
  435. xsector[j].decoupled = xsector5.decoupled;
  436. xsector[j].triggerOnce = xsector5.triggerOnce;
  437. xsector[j].isTriggered = xsector5.isTriggered;
  438. xsector[j].key = xsector5.key;
  439. xsector[j].triggerPush = xsector5.triggerPush;
  440. xsector[j].triggerImpact = xsector5.triggerImpact;
  441. xsector[j].triggerExplode = xsector5.triggerExplode;
  442. xsector[j].triggerEnter = xsector5.triggerEnter;
  443. xsector[j].triggerExit = xsector5.triggerExit;
  444. xsector[j].triggerWPush = xsector5.triggerWPush;
  445. xsector[j].triggerReserved1 = xsector5.triggerReserved1;
  446. xsector[j].triggerReserved2 = xsector5.triggerReserved2;
  447. // movement data
  448. xsector[j].offCeilZ = xsector5.offCeilZ;
  449. xsector[j].onCeilZ = xsector5.onCeilZ;
  450. xsector[j].offFloorZ = xsector5.offFloorZ;
  451. xsector[j].onFloorZ = xsector5.onFloorZ;
  452. xsector[j].marker0 = xsector5.marker0;
  453. xsector[j].marker1 = xsector5.marker1;
  454. xsector[j].crush = 0;
  455. }
  456. }
  457. for (i = 0; i < numwalls; i++)
  458. {
  459. WALL5 wall5;
  460. iob.Read(&wall5, sizeof(wall5));
  461. wall[i].x = wall5.x;
  462. wall[i].y = wall5.y;
  463. wall[i].point2 = wall5.point2;
  464. wall[i].nextwall = wall5.nextwall;
  465. wall[i].nextsector = wall5.nextsector;
  466. wall[i].cstat = wall5.cstat;
  467. wall[i].picnum = wall5.picnum;
  468. wall[i].overpicnum = wall5.overpicnum;
  469. wall[i].shade = wall5.shade;
  470. wall[i].pal = wall5.pal;
  471. wall[i].xrepeat = wall5.xrepeat;
  472. wall[i].yrepeat = wall5.yrepeat;
  473. wall[i].xpanning = wall5.xpanning;
  474. wall[i].ypanning = wall5.ypanning;
  475. wall[i].type = wall5.type;
  476. wall[i].hitag = wall5.hitag;
  477. wall[i].extra = wall5.extra;
  478. if (wall[i].extra > 0)
  479. {
  480. int j = wall[i].extra;
  481. XWALL5 xwall5;
  482. iob.Read(&xwall5, sizeof(XWALL5));
  483. memset(&xwall[j], 0, sizeof(XWALL));
  484. xwall[j].reference = xwall5.reference;
  485. xwall[j].state = xwall5.state;
  486. // trigger data
  487. xwall[j].busy = xwall5.busy;
  488. xwall[j].data = xwall5.data;
  489. xwall[j].txID = xwall5.txID;
  490. xwall[j].rxID = xwall5.rxID;
  491. xwall[j].command = xwall5.command;
  492. xwall[j].triggerOn = xwall5.triggerOn;
  493. xwall[j].triggerOff = xwall5.triggerOff;
  494. xwall[j].busyTime = xwall5.busyTime;
  495. xwall[j].waitTime = xwall5.waitTime;
  496. xwall[j].restState = xwall5.restState;
  497. xwall[j].interruptable = xwall5.interruptable;
  498. // panning data
  499. xwall[j].panAlways = xwall5.panAlways;
  500. xwall[j].panXVel = xwall5.panXVel;
  501. xwall[j].panYVel = xwall5.panYVel;
  502. // physical triggers
  503. xwall[j].decoupled = xwall5.decoupled;
  504. xwall[j].triggerOnce = xwall5.triggerOnce;
  505. xwall[j].isTriggered = xwall5.isTriggered;
  506. xwall[j].key = xwall5.key;
  507. xwall[j].triggerPush = xwall5.triggerPush;
  508. xwall[j].triggerImpact = xwall5.triggerImpact;
  509. xwall[j].triggerExplode = xwall5.triggerExplode;
  510. }
  511. }
  512. for (i = 0; i < numsprites; i++)
  513. {
  514. SPRITE5 sprite5;
  515. iob.Read(&sprite5, sizeof(sprite5));
  516. sprite[i].x = sprite5.x;
  517. sprite[i].y = sprite5.y;
  518. sprite[i].z = sprite5.z;
  519. sprite[i].cstat = sprite5.cstat;
  520. sprite[i].picnum = sprite5.picnum;
  521. sprite[i].shade = sprite5.shade;
  522. sprite[i].pal = sprite5.pal;
  523. sprite[i].clipdist = sprite5.clipdist;
  524. sprite[i].filler = 0;
  525. sprite[i].xrepeat = sprite5.xrepeat;
  526. sprite[i].yrepeat = sprite5.yrepeat;
  527. sprite[i].xoffset = sprite5.xoffset;
  528. sprite[i].yoffset = sprite5.yoffset;
  529. sprite[i].sectnum = sprite5.sectnum;
  530. sprite[i].statnum = sprite5.statnum;
  531. sprite[i].ang = sprite5.ang;
  532. sprite[i].owner = sprite5.owner;
  533. sprite[i].xvel = sprite5.xvel;
  534. sprite[i].yvel = sprite5.yvel;
  535. sprite[i].zvel = sprite5.zvel;
  536. sprite[i].type = sprite5.type;
  537. sprite[i].flags = 0; // sprite5.mass;
  538. sprite[i].extra = sprite5.extra;
  539. if (sprite[i].extra > 0)
  540. {
  541. int j = sprite[i].extra;
  542. XSPRITE5 xsprite5;
  543. iob.Read(&xsprite5, sizeof(XSPRITE5));
  544. memset(&xsprite[j], 0, sizeof(XSPRITE));
  545. xsprite[j].reference = xsprite5.reference;
  546. xsprite[j].state = xsprite5.state;
  547. // trigger data
  548. xsprite[j].busy = 0;
  549. xsprite[j].txID = xsprite5.txID;
  550. xsprite[j].rxID = xsprite5.rxID;
  551. xsprite[j].command = xsprite5.command;
  552. xsprite[j].triggerOn = xsprite5.triggerOn;
  553. xsprite[j].triggerOff = xsprite5.triggerOff;
  554. xsprite[j].busyTime = xsprite5.busyTime;
  555. xsprite[j].waitTime = xsprite5.waitTime;
  556. xsprite[j].restState = xsprite5.restState;
  557. xsprite[j].interruptable = xsprite5.interruptable;
  558. xsprite[j].difficulty = xsprite5.difficulty;
  559. xsprite[j].soundKit = xsprite5.soundKit;
  560. // physical triggers
  561. xsprite[j].decoupled = xsprite5.decoupled;
  562. xsprite[j].triggerOnce = xsprite5.triggerOnce;
  563. xsprite[j].isTriggered = 0;
  564. xsprite[j].key = xsprite5.key;
  565. xsprite[j].triggerPush = xsprite5.triggerPush;
  566. xsprite[j].triggerImpact = xsprite5.triggerImpact;
  567. xsprite[j].triggerExplode = xsprite5.triggerExplode;
  568. xsprite[j].triggerPickup = xsprite5.triggerPickup;
  569. xsprite[j].triggerTouch = xsprite5.triggerTouch;
  570. xsprite[j].triggerSight = xsprite5.triggerSight;
  571. xsprite[j].triggerProximity = xsprite5.triggerProximity;
  572. xsprite[j].data1 = xsprite5.data1;
  573. xsprite[j].data2 = xsprite5.data2;
  574. xsprite[j].data3 = xsprite5.data3;
  575. xsprite[j].support = xsprite5.support;
  576. // respawn flags
  577. xsprite[j].respawn = xsprite5.respawn;
  578. xsprite[j].respawnTime = xsprite5.respawnTime;
  579. xsprite[j].launchMode = xsprite5.launchMode;
  580. // this stuff needed for dudes (probably initialized dynamically)
  581. xsprite[j].moveState = 0;
  582. xsprite[j].aiState = 0;
  583. xsprite[j].health = 0;
  584. xsprite[j].dudeDeaf = 0;
  585. xsprite[j].dudeAmbush = 0;
  586. xsprite[j].dudeGuard = 0;
  587. xsprite[j].dudeFlag4 = 0;
  588. xsprite[j].target = 0;
  589. xsprite[j].targetX = 0;
  590. xsprite[j].targetY = 0;
  591. xsprite[j].targetZ = 0;
  592. xsprite[j].avel = 0;
  593. xsprite[j].stateTimer = 0;
  594. }
  595. }
  596. }
  597. else
  598. ThrowError("Error reading map file", ES_ERROR);
  599. free(buffer);
  600. // convert slide types and angle markers for maps before 5.03
  601. if ( (header5.version & 0xFF) < 3 )
  602. {
  603. for ( i = 0; i < kMaxSectors; i++)
  604. {
  605. if ( sector[i].type == kSectorSlide )
  606. {
  607. sector[i].type = kSectorSlideMarked;
  608. }
  609. }
  610. for ( i = 0; i < kMaxSprites; i++)
  611. if ( sprite[i].statnum == kStatMarker )
  612. {
  613. if ( sprite[i].ang >= kAngle180 )
  614. sprite[i].ang -= kAngle360;
  615. }
  616. }
  617. // add up all the elements in the file to determine the size of the buffer
  618. length = 0;
  619. length += sizeof(HEADER6);
  620. length += sizeof(INFO6);
  621. length += gSkyCount * sizeof(pskyoff[0]);
  622. length += numsectors * sizeof(SECTOR);
  623. for (i = 0; i < numsectors; i++)
  624. {
  625. if (sector[i].extra > 0)
  626. length += sizeof(XSECTOR);
  627. }
  628. length += numwalls * sizeof(WALL);
  629. for (i = 0; i < numwalls; i++)
  630. {
  631. if (wall[i].extra > 0)
  632. length += sizeof(XWALL);
  633. }
  634. length += numsprites * sizeof(SPRITE);
  635. for (i = 0; i < numsprites; i++)
  636. {
  637. if (sprite[i].extra > 0)
  638. length += sizeof(XSPRITE);
  639. }
  640. length += 4; // CRC
  641. buffer = (BYTE *)malloc(length);
  642. IOBuffer iob(buffer, length);
  643. memcpy(header6.signature, kBloodMapSig, sizeof(header6.signature));
  644. header6.version = kBloodMapVersion;
  645. iob.Write(&header6, sizeof(header6));
  646. info6.x = info5.x;
  647. info6.y = info5.y;
  648. info6.z = info5.z;
  649. info6.angle = info5.angle;
  650. info6.sector = info5.sector;
  651. info6.pskybits = info5.pskybits;
  652. info6.visibility = info5.visibility;
  653. info6.songId = info5.songId;
  654. info6.parallax = info5.parallax;
  655. info6.mapRevisions = info5.mapRevisions;
  656. info6.numsectors = numsectors;
  657. info6.numwalls = numwalls;
  658. info6.numsprites = numsprites;
  659. iob.Write(&info6, sizeof(info6));
  660. iob.Write(pskyoff, gSkyCount * sizeof(pskyoff[0]));
  661. for (i = 0; i < numsectors; i++)
  662. {
  663. iob.Write(&sector[i], sizeof(SECTOR));
  664. if (sector[i].extra > 0)
  665. iob.Write(&xsector[sector[i].extra], sizeof(XSECTOR));
  666. }
  667. for (i = 0; i < numwalls; i++)
  668. {
  669. iob.Write(&wall[i], sizeof(WALL));
  670. if (wall[i].extra > 0)
  671. iob.Write(&xwall[wall[i].extra], sizeof(XWALL));
  672. }
  673. for (i = 0; i < numsprites; i++)
  674. {
  675. iob.Write(&sprite[i], sizeof(SPRITE));
  676. if (sprite[i].extra > 0)
  677. iob.Write(&xsprite[sprite[i].extra], sizeof(XSPRITE));
  678. }
  679. gMapCRC = CRC32(buffer, length - sizeof(gMapCRC));
  680. iob.Write(&gMapCRC, sizeof(gMapCRC));
  681. // backup the map file
  682. strcpy(bakfilename, filename);
  683. ChangeExtension(bakfilename, "MA5");
  684. rename(filename, bakfilename);
  685. printf("=> %s ", filename);
  686. hFile = open(filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, S_IWUSR);
  687. if ( hFile == -1 )
  688. ThrowError("Error opening MAP file", ES_ERROR);
  689. if (write(hFile, buffer, length) != length)
  690. ThrowError("Error writing MAP file", ES_ERROR);
  691. close(hFile);
  692. free(buffer);
  693. printf("OK.\n");
  694. }
  695. void InsertFilename( char *fname )
  696. {
  697. FNODE *n = (FNODE *)malloc(sizeof(FNODE) + strlen(fname));
  698. strcpy(n->name, fname);
  699. // insert the node at the tail, so it stays in order
  700. n->next = tail->next;
  701. tail->next = n;
  702. tail = n;
  703. }
  704. void ProcessArgument(char *s)
  705. {
  706. char filespec[_MAX_PATH];
  707. char buffer[_MAX_PATH2];
  708. char path[_MAX_PATH];
  709. strcpy(filespec, s);
  710. AddExtension(filespec, ".MAP");
  711. char *drive, *dir;
  712. // separate the path from the filespec
  713. _splitpath2(filespec, buffer, &drive, &dir, NULL, NULL);
  714. _makepath(path, drive, dir, NULL, NULL);
  715. struct find_t fileinfo;
  716. unsigned r = _dos_findfirst(filespec, _A_NORMAL, &fileinfo);
  717. if (r != 0)
  718. printf("%s not found\n", filespec);
  719. while ( r == 0 )
  720. {
  721. strcpy(filespec, path);
  722. strcat(filespec, fileinfo.name);
  723. InsertFilename(filespec);
  724. r = _dos_findnext( &fileinfo );
  725. }
  726. _dos_findclose(&fileinfo);
  727. }
  728. /***********************************************************************
  729. * Process command line arguments
  730. **********************************************************************/
  731. void ParseOptions( void )
  732. {
  733. static SWITCH switches[] = { { NULL, 0, FALSE } };
  734. int r;
  735. while ( (r = GetOptions(switches)) != GO_EOF ) {
  736. switch (r)
  737. {
  738. case GO_INVALID:
  739. QuitMessage("Invalid argument: %s", OptArgument);
  740. case GO_FULL:
  741. ProcessArgument(OptArgument);
  742. break;
  743. }
  744. }
  745. }
  746. void main(int argc)
  747. {
  748. printf("Blood Map 6 Converter Copyright (c) 1995 Q Studios Corporation\n");
  749. if (argc < 2) ShowUsage();
  750. ParseOptions();
  751. // process the file list
  752. for (FNODE *n = head.next; n != &head; n = n->next)
  753. ProcessFile(n->name);
  754. }