CONVDB4.CPP 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  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 <memcheck.h>
  14. #define kBloodMapSig "BLM\x1A"
  15. #define kBloodMapVersion 0x0400
  16. #define kBloodMapOldVersion 0x0301
  17. struct FNODE
  18. {
  19. FNODE *next;
  20. char name[1];
  21. };
  22. FNODE head = { &head, "" };
  23. FNODE *tail = &head;
  24. // Build globals
  25. SECTOR sector[kMaxSectors];
  26. WALL wall[kMaxWalls];
  27. SPRITE sprite[kMaxSprites];
  28. // Q globals
  29. XSECTOR xsector[kMaxXSectors];
  30. XWALL xwall[kMaxXWalls];
  31. XSPRITE xsprite[kMaxXSprites];
  32. uchar spriteSurf[kMaxSprites];
  33. uchar wallSurf[kMaxWalls];
  34. uchar floorSurf[kMaxSectors];
  35. uchar ceilingSurf[kMaxSectors];
  36. short pskyoff[kMaxSkyTiles];
  37. short pskybits;
  38. char gMapAuthor[64] = "";
  39. char gMapName[64] = "";
  40. ulong gMapCRC;
  41. int gSkyCount;
  42. short numsectors, numwalls;
  43. struct IOBuffer
  44. {
  45. int remain;
  46. char *p;
  47. IOBuffer( char *buffer, int l ) : p(buffer), remain(l) {};
  48. void Read(void *, int, int);
  49. void Write(void *, int, int);
  50. };
  51. void IOBuffer::Read(void *s, int size, int nError)
  52. {
  53. if (size <= remain)
  54. {
  55. memcpy(s, p, size);
  56. remain -= size;
  57. p += size;
  58. }
  59. else
  60. ThrowError("IOB", nError, "Read buffer overflow", ES_ERROR);
  61. }
  62. void IOBuffer::Write(void *s, int size, int nError)
  63. {
  64. if (size <= remain)
  65. {
  66. memcpy(p, s, size);
  67. remain -= size;
  68. p += size;
  69. }
  70. else
  71. ThrowError("IOB", nError, "Write buffer overflow", ES_ERROR);
  72. }
  73. struct HEADER3
  74. {
  75. char signature[4];
  76. short version;
  77. };
  78. struct HEADER4
  79. {
  80. char signature[4];
  81. short version;
  82. };
  83. // version 3.x header
  84. struct INFO3
  85. {
  86. long x, y, z;
  87. ushort angle;
  88. ushort sector;
  89. ushort pskybits;
  90. uchar visibility;
  91. int songId;
  92. uchar parallax;
  93. int mapRevisions;
  94. uchar lenName;
  95. uchar lenAuthor;
  96. ushort numsectors;
  97. ushort numwalls;
  98. ushort numsprites;
  99. };
  100. // version 4.x header
  101. struct INFO4
  102. {
  103. long x, y, z;
  104. ushort angle;
  105. ushort sector;
  106. ushort pskybits;
  107. long visibility;
  108. int songId;
  109. uchar parallax;
  110. int mapRevisions;
  111. uchar lenName;
  112. uchar lenAuthor;
  113. ushort numsectors;
  114. ushort numwalls;
  115. ushort numsprites;
  116. };
  117. /***********************************************************************
  118. * Old version structures and typedefs
  119. **********************************************************************/
  120. struct XSPRITE3
  121. {
  122. signed reference : 16;
  123. unsigned state : 1;
  124. // trigger data
  125. unsigned busy : 16;
  126. unsigned type : 10;
  127. signed data : 16;
  128. unsigned txID : 10;
  129. unsigned rxID : 10;
  130. unsigned command : 3;
  131. unsigned triggerOn : 1;
  132. unsigned triggerOff : 1;
  133. unsigned triggerOnce : 1;
  134. unsigned restState : 1; // state to return to on callback
  135. unsigned key : 3;
  136. unsigned difficulty : 2;
  137. unsigned detail : 2;
  138. unsigned map : 2;
  139. unsigned view : 4;
  140. unsigned soundKit : 8;
  141. unsigned isTriggered : 1; // used for triggerOnce objects
  142. unsigned triggerPush : 1; // gates?
  143. unsigned triggerImpact : 1; // exploding things, etc.
  144. unsigned triggerPickup : 1; // secrets
  145. unsigned triggerTouch : 1; // sawblades, spikes, zaps?
  146. unsigned triggerSight : 1; // dunno, yet.
  147. unsigned triggerProximity : 1; // proximity bombs
  148. unsigned decoupled : 1;
  149. unsigned waitTime : 8;
  150. };
  151. struct XWALL3
  152. {
  153. signed reference : 16;
  154. unsigned state : 1;
  155. unsigned map : 2;
  156. // trigger data
  157. unsigned busy : 16;
  158. unsigned type : 10;
  159. signed data : 16;
  160. unsigned txID : 10;
  161. unsigned rxID : 10;
  162. unsigned command : 3;
  163. unsigned triggerOn : 1;
  164. unsigned triggerOff : 1;
  165. unsigned triggerOnce : 1;
  166. unsigned key : 3;
  167. // panning data
  168. signed panXVel : 8;
  169. signed panYVel : 8;
  170. unsigned isTriggered : 1; // used for triggerOnce objects
  171. unsigned triggerPush : 1;
  172. unsigned triggerImpact : 1;
  173. unsigned triggerRsvd1 : 1;
  174. unsigned triggerRsvd2 : 1;
  175. unsigned decoupled : 1;
  176. unsigned panAlways : 1;
  177. unsigned restState : 1; // state to return to on callback
  178. unsigned waitTime : 8;
  179. };
  180. struct XSECTOR3
  181. {
  182. signed reference : 16;
  183. unsigned state : 1;
  184. // trigger data
  185. unsigned busy : 16;
  186. unsigned type : 10;
  187. signed data : 16;
  188. unsigned txID : 10;
  189. unsigned rxID : 10;
  190. unsigned command : 3;
  191. unsigned triggerOn : 1;
  192. unsigned triggerOff : 1;
  193. unsigned triggerOnce : 1;
  194. unsigned restState : 1; // state to return to on callback
  195. unsigned key : 3;
  196. // lighting data
  197. signed amplitude : 8;
  198. unsigned freq : 8;
  199. unsigned wave : 4;
  200. unsigned shadeAlways : 1;
  201. unsigned unused2 : 3; // !!! USE ME !!!
  202. unsigned phase : 8;
  203. unsigned shadeFloor : 1;
  204. unsigned shadeCeiling : 1;
  205. unsigned shadeWalls : 1;
  206. signed shade : 8;
  207. // panning data
  208. unsigned panFloor : 1;
  209. unsigned panCeiling : 1;
  210. unsigned panDrag : 1;
  211. unsigned waitTime : 8;
  212. unsigned panAlways : 1;
  213. unsigned unused3 : 3; // !!! USE ME !!!
  214. // speed for moving sectors
  215. unsigned busyTime : 8;
  216. // water stuff
  217. unsigned underwater : 1;
  218. unsigned depth : 2;
  219. unsigned panVel : 8;
  220. unsigned panAngle : 12; // change to 11 bits in CONVDB4!!!
  221. unsigned wind : 3;
  222. unsigned isTriggered : 1; // used for triggerOnce objects
  223. unsigned triggerPush : 1;
  224. unsigned triggerImpact : 1;
  225. unsigned triggerEnter : 1;
  226. unsigned triggerExit : 1;
  227. unsigned decoupled : 1;
  228. unsigned triggerWPush : 1; // push from outside wall (convenience bit)
  229. };
  230. void ShowUsage(void)
  231. {
  232. printf("Usage:\n");
  233. printf(" CONVDB4 map1 map2 (wild cards ok)\n");
  234. printf("\nTECHNICAL INFO:\n sizeof(XSPRITE)=%d\n sizeof(XSECTOR)=%d\n sizeof(XWALL)=%d",
  235. sizeof(XSPRITE), sizeof(XSECTOR), sizeof(XWALL));
  236. exit(0);
  237. }
  238. void QuitMessage(char * fmt, ...)
  239. {
  240. char msg[80];
  241. va_list argptr;
  242. va_start( argptr, fmt );
  243. vsprintf( msg, fmt, argptr );
  244. va_end(argptr);
  245. printf(msg);
  246. exit(1);
  247. }
  248. void ProcessFile(char *filespec)
  249. {
  250. int hFile;
  251. int i;
  252. HEADER3 header3;
  253. HEADER4 header4;
  254. INFO3 info3;
  255. INFO4 info4;
  256. char filename[_MAX_PATH], bakfilename[_MAX_PATH];
  257. short numsprites;
  258. int length;
  259. char *buffer;
  260. strcpy(filename, filespec);
  261. printf("%s ", filename);
  262. hFile = open(filename, O_RDONLY | O_BINARY);
  263. if ( hFile == -1 )
  264. ThrowError( "MAP", 0, "unable to open MAP file", ES_ERROR);
  265. length = filelength(hFile);
  266. buffer = (char *)malloc(length);
  267. if (read(hFile, buffer, length) == length)
  268. {
  269. close(hFile);
  270. IOBuffer iob(buffer, length);
  271. iob.Read(&header3, sizeof(HEADER3), 1);
  272. // check signature and major version number
  273. if ( (memcmp(header3.signature, kBloodMapSig, 4) != 0)
  274. || ((header3.version >> 8) != (kBloodMapOldVersion >> 8)) )
  275. {
  276. printf("not expected format, skipping\n");
  277. return;
  278. }
  279. iob.Read(&info3, sizeof(INFO3), 2);
  280. numsectors = info3.numsectors;
  281. numwalls = info3.numwalls;
  282. numsprites = info3.numsprites;
  283. iob.Read(gMapName, info3.lenName + 1, 3);
  284. iob.Read(gMapAuthor, info3.lenAuthor + 1, 4);
  285. pskybits = info3.pskybits;
  286. gSkyCount = 1 << pskybits;
  287. iob.Read(pskyoff, gSkyCount * sizeof(pskyoff[0]), 5);
  288. // printf("Converting %i sectors...\n",numsectors);
  289. for (i = 0; i < numsectors; i++)
  290. {
  291. iob.Read(&sector[i], sizeof(SECTOR), 6);
  292. iob.Read(&ceilingSurf[i], sizeof(ceilingSurf[i]), 7);
  293. iob.Read(&floorSurf[i], sizeof(floorSurf[i]), 8);
  294. // expand sector shade range
  295. sector[i].ceilingshade = (schar)ClipRange(sector[i].ceilingshade << 1, -128, 127);
  296. sector[i].floorshade = (schar)ClipRange(sector[i].floorshade << 1, -128, 127);
  297. if (sector[i].extra > 0)
  298. {
  299. int j = sector[i].extra;
  300. XSECTOR3 xsector3;
  301. iob.Read(&xsector3, sizeof(XSECTOR3), 9);
  302. memset(&xsector[j], 0, sizeof(XSECTOR));
  303. xsector[j].reference = xsector3.reference;
  304. xsector[j].state = xsector3.state;
  305. xsector[j].busy = 0;
  306. xsector[j].type = xsector3.type;
  307. xsector[j].data = xsector3.data;
  308. xsector[j].txID = xsector3.txID;
  309. xsector[j].rxID = xsector3.rxID;
  310. xsector[j].command = xsector3.command;
  311. xsector[j].triggerOn = xsector3.triggerOn;
  312. xsector[j].triggerOff = xsector3.triggerOff;
  313. xsector[j].triggerOnce = xsector3.triggerOnce;
  314. xsector[j].restState = xsector3.restState;
  315. xsector[j].key = xsector3.key;
  316. xsector[j].amplitude = ClipRange(xsector3.amplitude << 1, -128, 127);
  317. xsector[j].freq = xsector3.freq;
  318. xsector[j].wave = xsector3.wave;
  319. xsector[j].shadeAlways = xsector3.shadeAlways;
  320. xsector[j].phase = xsector3.phase;
  321. xsector[j].shadeFloor = xsector3.shadeFloor;
  322. xsector[j].shadeCeiling = xsector3.shadeCeiling;
  323. xsector[j].shadeWalls = xsector3.shadeWalls;
  324. xsector[j].shade = xsector3.shade;
  325. xsector[j].panFloor = xsector3.panFloor;
  326. xsector[j].panCeiling = xsector3.panCeiling;
  327. xsector[j].panDrag = xsector3.panDrag;
  328. xsector[j].waitTime = xsector3.waitTime;
  329. xsector[j].panAlways = xsector3.panAlways;
  330. xsector[j].busyTime = xsector3.busyTime;
  331. xsector[j].underwater = xsector3.underwater;
  332. xsector[j].depth = xsector3.depth;
  333. xsector[j].panVel = xsector3.panVel;
  334. xsector[j].panAngle = xsector3.panAngle;
  335. xsector[j].wind = xsector3.wind ? 1 : 0;
  336. xsector[j].isTriggered = 0;
  337. xsector[j].triggerPush = xsector3.triggerPush;
  338. xsector[j].triggerImpact = xsector3.triggerImpact;
  339. xsector[j].triggerEnter = xsector3.triggerEnter;
  340. xsector[j].triggerExit = xsector3.triggerExit;
  341. xsector[j].triggerWPush = xsector3.triggerWPush;
  342. xsector[j].decoupled = xsector3.decoupled;
  343. // default all onZ/offZ values
  344. xsector[j].offCeilZ = sector[i].ceilingz;
  345. xsector[j].onCeilZ = sector[i].ceilingz;
  346. xsector[j].offFloorZ = sector[i].floorz;
  347. xsector[j].onFloorZ = sector[i].floorz;
  348. switch( xsector[j].type )
  349. {
  350. case kSectorTopDoor:
  351. xsector[j].offCeilZ = sector[i].floorz;
  352. xsector[j].type = kSectorZMotion;
  353. break;
  354. case kSectorBottomDoor:
  355. xsector[j].offFloorZ = sector[i].ceilingz;
  356. xsector[j].type = kSectorZMotion;
  357. break;
  358. case kSectorHSplitDoor:
  359. xsector[j].offCeilZ = (sector[i].ceilingz + sector[i].floorz) / 2;
  360. xsector[j].offFloorZ = (sector[i].ceilingz + sector[i].floorz) / 2;
  361. xsector[j].type = kSectorZMotion;
  362. break;
  363. default:
  364. break;
  365. }
  366. }
  367. }
  368. // printf("Converting %i walls...\n",numwalls);
  369. for (i = 0; i < numwalls; i++)
  370. {
  371. iob.Read(&wall[i], sizeof(WALL), 10);
  372. iob.Read(&wallSurf[i], sizeof(wallSurf[i]), 11);
  373. // expand wall shade range
  374. wall[i].shade = (schar)ClipRange(wall[i].shade << 1, -128, 127);
  375. if (wall[i].extra > 0)
  376. {
  377. int j = wall[i].extra;
  378. XWALL3 xwall3;
  379. iob.Read(&xwall3, sizeof(XWALL3), 12);
  380. memset(&xwall[j], 0, sizeof(XWALL));
  381. xwall[j].reference = xwall3.reference;
  382. xwall[j].type = xwall3.type;
  383. xwall[j].state = xwall3.state;
  384. xwall[j].busy = xwall3.busy;
  385. xwall[j].txID = xwall3.txID;
  386. xwall[j].rxID = xwall3.rxID;
  387. xwall[j].command = xwall3.command;
  388. xwall[j].triggerOn = xwall3.triggerOn;
  389. xwall[j].triggerOff = xwall3.triggerOff;
  390. xwall[j].key = xwall3.key;
  391. xwall[j].data = xwall3.data;
  392. xwall[j].waitTime = xwall3.waitTime;
  393. xwall[j].restState = xwall3.restState;
  394. xwall[j].triggerPush = xwall3.triggerPush;
  395. xwall[j].triggerImpact = xwall3.triggerImpact;
  396. xwall[j].triggerRsvd1 = xwall3.triggerRsvd1;
  397. xwall[j].triggerRsvd2 = xwall3.triggerRsvd2;
  398. xwall[j].decoupled = xwall3.decoupled;
  399. xwall[j].triggerOnce = xwall3.triggerOnce;
  400. xwall[j].isTriggered = xwall3.isTriggered;
  401. xwall[j].panXVel = xwall3.panXVel;
  402. xwall[j].panYVel = xwall3.panYVel;
  403. xwall[j].panAlways = xwall3.panAlways;
  404. xwall[j].map = xwall3.map;
  405. }
  406. }
  407. // printf("Converting %i sprites...\n",numsprites);
  408. for (i = 0; i < numsprites; i++)
  409. {
  410. iob.Read(&sprite[i], sizeof(SPRITE), 13);
  411. iob.Read(&spriteSurf[i], sizeof(spriteSurf[i]), 14);
  412. // expand sprite shade range
  413. if ( sprite[i].statnum < kMaxStatus )
  414. sprite[i].shade = (schar)ClipRange(sprite[i].shade << 1, -128, 127);
  415. if (sprite[i].extra > 0)
  416. {
  417. int j = sprite[i].extra;
  418. XSPRITE3 xsprite3;
  419. iob.Read(&xsprite3, sizeof(XSPRITE3), 15);
  420. memset(&xsprite[j], 0, sizeof(XSPRITE));
  421. xsprite[j].reference = xsprite3.reference;
  422. xsprite[j].state = xsprite3.state;
  423. xsprite[j].type = xsprite3.type;
  424. xsprite[j].txID = xsprite3.txID;
  425. xsprite[j].rxID = xsprite3.rxID;
  426. xsprite[j].command = xsprite3.command;
  427. xsprite[j].triggerOn = xsprite3.triggerOn;
  428. xsprite[j].triggerOff = xsprite3.triggerOff;
  429. xsprite[j].triggerOnce = xsprite3.triggerOnce;
  430. xsprite[j].restState = xsprite3.restState;
  431. xsprite[j].key = xsprite3.key;
  432. xsprite[j].difficulty = xsprite3.difficulty;
  433. xsprite[j].detail = xsprite3.detail;
  434. xsprite[j].map = xsprite3.map;
  435. xsprite[j].view = xsprite3.view;
  436. xsprite[j].soundKit = xsprite3.soundKit;
  437. xsprite[j].data = xsprite3.data;
  438. xsprite[j].isTriggered = 0;
  439. xsprite[j].triggerPush = xsprite3.triggerPush;
  440. xsprite[j].triggerImpact = xsprite3.triggerImpact;
  441. xsprite[j].triggerPickup = xsprite3.triggerPickup;
  442. xsprite[j].triggerTouch = xsprite3.triggerTouch;
  443. xsprite[j].triggerSight = xsprite3.triggerSight;
  444. xsprite[j].triggerProximity = xsprite3.triggerProximity;
  445. xsprite[j].decoupled = xsprite3.decoupled;
  446. xsprite[j].waitTime = xsprite3.waitTime;
  447. xsprite[j].permanent = 0;
  448. xsprite[j].respawn = 0;
  449. xsprite[j].respawnTime = 0;
  450. xsprite[j].launchMode = 0;
  451. }
  452. }
  453. }
  454. else
  455. ThrowError( "DB", 16, "Error reading map file", ES_ERROR);
  456. free(buffer);
  457. // add up all the elements in the file to determine the size of the buffer
  458. length = 0;
  459. length += sizeof(HEADER4);
  460. length += sizeof(INFO4);
  461. length += strlen(gMapName) + 1;
  462. length += strlen(gMapAuthor) + 1;
  463. length += gSkyCount * sizeof(pskyoff[0]);
  464. length += numsectors * sizeof(SECTOR);
  465. length += numsectors * sizeof(ceilingSurf[0]);
  466. length += numsectors * sizeof(floorSurf[0]);
  467. for (i = 0; i < numsectors; i++)
  468. {
  469. if (sector[i].extra > 0)
  470. length += sizeof(XSECTOR);
  471. }
  472. length += numwalls * sizeof(WALL);
  473. length += numwalls * sizeof(wallSurf[0]);
  474. for (i = 0; i < numwalls; i++)
  475. {
  476. if (wall[i].extra > 0)
  477. length += sizeof(XWALL);
  478. }
  479. length += numsprites * sizeof(SPRITE);
  480. length += numsprites * sizeof(spriteSurf[0]);
  481. for (i = 0; i < numsprites; i++)
  482. {
  483. if (sprite[i].extra > 0)
  484. length += sizeof(XSPRITE);
  485. }
  486. length += 4; // CRC
  487. buffer = (char *)malloc(length);
  488. IOBuffer iob(buffer, length);
  489. memcpy(header4.signature, kBloodMapSig, 4);
  490. header4.version = kBloodMapVersion;
  491. iob.Write(&header4, sizeof(header4), 1);
  492. info4.x = info3.x;
  493. info4.y = info3.y;
  494. info4.z = info3.z;
  495. info4.angle = info3.angle;
  496. info4.sector = info3.sector;
  497. info4.pskybits = info3.pskybits;
  498. info4.visibility = 1 << (22 - info3.visibility);
  499. info4.songId = info3.songId;
  500. info4.parallax = info3.parallax;
  501. info4.mapRevisions = info3.mapRevisions;
  502. info4.lenName = (char)strlen(gMapName);
  503. info4.lenAuthor = (char)strlen(gMapAuthor);
  504. info4.numsectors = numsectors;
  505. info4.numwalls = numwalls;
  506. info4.numsprites = numsprites;
  507. iob.Write(&info4, sizeof(INFO4), 2);
  508. iob.Write(gMapName, info4.lenName + 1, 3);
  509. iob.Write(gMapAuthor, info4.lenAuthor + 1, 4);
  510. iob.Write(pskyoff, gSkyCount * sizeof(pskyoff[0]), 5);
  511. for (i = 0; i < numsectors; i++)
  512. {
  513. iob.Write(&sector[i], sizeof(SECTOR), 6);
  514. iob.Write(&ceilingSurf[i], sizeof(ceilingSurf[i]), 7);
  515. iob.Write(&floorSurf[i], sizeof(floorSurf[i]), 8);
  516. if (sector[i].extra > 0)
  517. iob.Write(&xsector[sector[i].extra], sizeof(XSECTOR), 9);
  518. }
  519. for (i = 0; i < numwalls; i++)
  520. {
  521. iob.Write(&wall[i], sizeof(WALL), 10);
  522. iob.Write(&wallSurf[i], sizeof(wallSurf[i]), 11);
  523. if (wall[i].extra > 0)
  524. iob.Write(&xwall[wall[i].extra], sizeof(XWALL), 12);
  525. }
  526. for (i = 0; i < numsprites; i++)
  527. {
  528. iob.Write(&sprite[i], sizeof(SPRITE), 13);
  529. iob.Write(&spriteSurf[i], sizeof(spriteSurf[i]), 14);
  530. if (sprite[i].extra > 0)
  531. iob.Write(&xsprite[sprite[i].extra], sizeof(XSPRITE), 15);
  532. }
  533. gMapCRC = CRC32(buffer, length - sizeof(gMapCRC));
  534. iob.Write(&gMapCRC, sizeof(gMapCRC), 16);
  535. // backup the map file
  536. strcpy(bakfilename, filename);
  537. ChangeExtension(filename, "MAP");
  538. ChangeExtension(bakfilename, "MA3");
  539. // printf("Creating backup file %s",bakfilename);
  540. rename(filename, bakfilename);
  541. // printf("Saving converted file %s",filename);
  542. ChangeExtension(filename, "MAP");
  543. printf("=> %s ", filename);
  544. hFile = open(filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, S_IWUSR);
  545. if ( hFile == -1 )
  546. ThrowError( "DB", 0, "Error opening MAP file", ES_ERROR);
  547. if (write(hFile, buffer, length) != length)
  548. ThrowError( "DB", 1, "Error write MAP file", ES_ERROR);
  549. close(hFile);
  550. free(buffer);
  551. printf("OK.\n");
  552. }
  553. void InsertFilename( char *fname )
  554. {
  555. FNODE *n = (FNODE *)malloc(sizeof(FNODE) + strlen(fname));
  556. strcpy(n->name, fname);
  557. // insert the node at the tail, so it stays in order
  558. n->next = tail->next;
  559. tail->next = n;
  560. tail = n;
  561. }
  562. void ProcessArgument(char *s)
  563. {
  564. char filespec[_MAX_PATH];
  565. char buffer[_MAX_PATH2];
  566. char path[_MAX_PATH];
  567. strcpy(filespec, s);
  568. ChangeExtension(filespec, ".MAP");
  569. char *drive, *dir;
  570. // separate the path from the filespec
  571. _splitpath2(s, buffer, &drive, &dir, NULL, NULL);
  572. _makepath(path, drive, dir, NULL, NULL);
  573. struct find_t fileinfo;
  574. unsigned r = _dos_findfirst(s, _A_NORMAL, &fileinfo);
  575. if (r != 0)
  576. printf("%s not found\n", s);
  577. while ( r == 0 )
  578. {
  579. strcpy(filespec, path);
  580. strcat(filespec, fileinfo.name);
  581. InsertFilename(filespec);
  582. r = _dos_findnext( &fileinfo );
  583. }
  584. _dos_findclose(&fileinfo);
  585. }
  586. /***********************************************************************
  587. * Process command line arguments
  588. **********************************************************************/
  589. void ParseOptions( int argc, char *argv[])
  590. {
  591. int c;
  592. while ( (c = GetOptions(argc, argv, "")) != GO_EOF ) {
  593. switch (c) {
  594. case GO_INVALID:
  595. QuitMessage("Invalid argument: %s", OptArgument);
  596. case GO_FULL:
  597. ProcessArgument(OptArgument);
  598. break;
  599. }
  600. }
  601. }
  602. void main(int argc, char *argv[])
  603. {
  604. printf("Blood Map 4 Converter Copyright (c) 1995 Q Studios Corporation\n");
  605. if (argc < 2) ShowUsage();
  606. ParseOptions(argc, argv);
  607. // process the file list
  608. for (FNODE *n = head.next; n != &head; n = n->next)
  609. ProcessFile(n->name);
  610. }