123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629 |
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <dos.h>
- #include <io.h>
- #include <fcntl.h>
- #include "db.h"
- #include "getopt.h"
- #include "engine.h"
- #include "error.h"
- #include "misc.h"
- #include <memcheck.h>
- #define kBloodMapSig "BLM\x1A"
- #define kBloodMapVersion 0x0300
- struct FNODE
- {
- FNODE *next;
- char name[1];
- };
- FNODE head = { &head, "" };
- FNODE *tail = &head;
- SECTOR sector[kMaxSectors];
- XSECTOR xsector[kMaxXSectors];
- WALL wall[kMaxWalls];
- XWALL xwall[kMaxXWalls];
- SPRITE sprite[kMaxSprites];
- XSPRITE xsprite[kMaxXSprites];
- uchar spriteSurf[kMaxSprites];
- uchar wallSurf[kMaxWalls];
- uchar floorSurf[kMaxSectors];
- uchar ceilingSurf[kMaxSectors];
- short pskyoff[kMaxSkyTiles];
- short pskybits;
- char gMapAuthor[64] = "";
- char gMapName[64] = "";
- ulong gMapCRC;
- int gSkyCount;
- short numsectors, numwalls;
- struct IOBuffer
- {
- int remain;
- char *p;
- IOBuffer( char *buffer, int l ) : p(buffer), remain(l) {};
- void Read(void *, int, int);
- void Write(void *, int, int);
- };
- void IOBuffer::Read(void *s, int size, int nError)
- {
- if (size <= remain)
- {
- memcpy(s, p, size);
- remain -= size;
- p += size;
- }
- else
- ThrowError("IOB", nError, "Read buffer overflow", ES_ERROR);
- }
- void IOBuffer::Write(void *s, int size, int nError)
- {
- if (size <= remain)
- {
- memcpy(p, s, size);
- remain -= size;
- p += size;
- }
- else
- ThrowError("IOB", nError, "Write buffer overflow", ES_ERROR);
- }
- struct OLDHEADER
- {
- long version;
- long x, y, z;
- short angle;
- short sectnum;
- };
- struct MPXHEADER
- {
- char signature[4];
- short version;
- short dummy;
- };
- struct HEADER
- {
- char signature[4];
- short version;
- };
- // version 2.x header
- struct INFO2
- {
- short xspriteSize;
- short xwallSize;
- short xsectorSize;
- char visibility;
- short xspriteCount;
- short xwallCount;
- short xsectorCount;
- short pskybits;
- char lenAuthor;
- char lenName;
- };
- // version 3.x header
- struct INFO3
- {
- long x, y, z;
- ushort angle;
- ushort sector;
- ushort pskybits;
- uchar visibility;
- int songId;
- uchar parallax;
- int mapRevisions;
- uchar lenName;
- uchar lenAuthor;
- ushort numsectors;
- ushort numwalls;
- ushort numsprites;
- };
- struct XSPRITE2
- {
- signed reference : 16;
- unsigned rxID : 10;
- unsigned difficulty : 2;
- unsigned detail : 2;
- unsigned map : 2;
- unsigned txID : 10;
- unsigned key : 3;
- unsigned command : 3;
- unsigned type : 10;
- unsigned state: 1;
- unsigned triggerOn : 1;
- unsigned triggerOff : 1;
- unsigned triggerOnce : 1;
- unsigned view : 2; // changed to : 3
- unsigned soundKit : 8;
- unsigned data : 16;
- };
- struct XWALL2
- {
- signed reference : 16;
- unsigned rxID : 10;
- unsigned surfType : 6;
- unsigned txID : 10;
- unsigned key : 3;
- unsigned command : 3;
- unsigned type : 10;
- unsigned map : 2;
- unsigned state: 1;
- unsigned triggerOn : 1;
- unsigned triggerOff : 1;
- unsigned data : 16;
- };
- struct XSECTOR2
- {
- signed reference : 16;
- unsigned rxID : 10;
- unsigned command : 3;
- unsigned triggerOn : 1;
- unsigned triggerOff : 1;
- unsigned triggerOnce : 1;
- signed ceilingShade0 : 8; // deleted
- signed floorShade0 : 8; // deleted
- signed amplitude : 8;
- unsigned freq : 8;
- unsigned wave : 8;
- unsigned phase : 8;
- unsigned state: 1;
- unsigned shadeFloor : 1;
- unsigned shadeCeiling : 1;
- unsigned shadeWalls : 1;
- unsigned panFloor : 1;
- unsigned panCeiling : 1;
- unsigned panDrag : 1;
- unsigned panWalls : 1;
- unsigned panAngle : 12;
- signed panSpeed : 8;
- signed shade : 8;
- unsigned surfType : 6; // deleted
- unsigned ceilSurf : 6;
- unsigned floorSurf : 6;
- unsigned txID : 10;
- unsigned key : 3;
- unsigned type : 10;
- unsigned underwater : 1;
- unsigned data : 16;
- };
- void ShowUsage(void)
- {
- printf("Usage:\n");
- printf(" CONVDB3 map1 map2 (wild cards ok)\n");
- printf("\nTECHNICAL INFO:\n sizeof(XSPRITE)=%d\n sizeof(XSECTOR)=%d\n sizeof(XWALL)=%d",
- sizeof(XSPRITE), sizeof(XSECTOR), sizeof(XWALL));
- exit(0);
- }
- void QuitMessage(char * fmt, ...)
- {
- char msg[80];
- va_list argptr;
- va_start( argptr, fmt );
- vsprintf( msg, fmt, argptr );
- va_end(argptr);
- printf(msg);
- exit(1);
- }
- void ProcessFile(char *filespec)
- {
- int hFile;
- int i;
- OLDHEADER oldHeader;
- MPXHEADER mpxheader;
- HEADER header;
- INFO2 info2;
- INFO3 info3;
- char filename[_MAX_PATH], bakfilename[_MAX_PATH];
- int x, y, z;
- short angle, nSector, numsprites;
- int length;
- char *buffer;
- strcpy(filename, filespec);
- printf("%s ", filename);
- hFile = open(filename, O_RDONLY | O_BINARY);
- if ( hFile == -1 )
- ThrowError( "MPX", 0, "unable to open MAP file", ES_ERROR);
- length = filelength(hFile);
- buffer = (char *)malloc(length);
- if (read(hFile, buffer, length) == length)
- {
- close(hFile);
- IOBuffer iob(buffer, length);
- iob.Read(&oldHeader, sizeof(OLDHEADER), 1);
- if (oldHeader.version != 6)
- {
- printf("not old format, skipping\n");
- return;
- }
- x = oldHeader.x;
- y = oldHeader.y;
- z = oldHeader.z;
- angle = oldHeader.angle;
- nSector = oldHeader.sectnum;
- iob.Read(&numsectors, sizeof(numsectors), 2);
- iob.Read(§or[0], sizeof(SECTOR) * numsectors, 3);
- iob.Read(&numwalls, sizeof(numwalls), 4);
- iob.Read(&wall[0], sizeof(WALL) * numwalls, 5);
- iob.Read(&numsprites, sizeof(numsprites), 6);
- iob.Read(&sprite[0], sizeof(SPRITE) * numsprites, 7);
- }
- else
- ThrowError( "DB", 8, "Error reading map file", ES_ERROR);
- free(buffer);
- ChangeExtension(filename, "MPX");
- printf("%s ", filename);
- hFile = open(filename, O_RDONLY | O_BINARY);
- if ( hFile == -1 )
- ThrowError( "MPX", 9, "unable to open MPX file", ES_ERROR);
- length = filelength(hFile);
- buffer = (char *)malloc(length);
- if (read(hFile, buffer, length) == length)
- {
- close(hFile);
- IOBuffer iob(buffer, length);
- iob.Read(&mpxheader, sizeof(MPXHEADER), 10);
- if (memcmp(mpxheader.signature, "MPX\x1A", 4) != 0)
- {
- close(hFile);
- ThrowError( "MPX", 11, "MPX file corrupted", ES_ERROR);
- }
- if ( (mpxheader.version >> 8) != 2)
- ThrowError("MPX", 12, "Incorrect MPX version encounted.", ES_ERROR);
- iob.Read(&info2, sizeof(INFO2), 13);
- for (i = 0; i < info2.xspriteCount; i++)
- {
- XSPRITE2 xsprite2;
- iob.Read(&xsprite2, sizeof(XSPRITE2), 14);
- memset(&xsprite[i], 0, sizeof(XSPRITE));
- xsprite[i].reference = xsprite2.reference;
- xsprite[i].rxID = xsprite2.rxID;
- xsprite[i].difficulty = xsprite2.difficulty;
- xsprite[i].detail = xsprite2.detail;
- xsprite[i].map = xsprite2.map;
- xsprite[i].txID = xsprite2.txID;
- xsprite[i].key = xsprite2.key;
- xsprite[i].command = xsprite2.command;
- xsprite[i].type = xsprite2.type;
- xsprite[i].state = xsprite2.state;
- xsprite[i].triggerOn = xsprite2.triggerOn;
- xsprite[i].triggerOff = xsprite2.triggerOff;
- xsprite[i].triggerOnce = xsprite2.triggerOnce;
- xsprite[i].view = xsprite2.view;
- xsprite[i].soundKit = xsprite2.soundKit;
- xsprite[i].data = xsprite2.data;
- }
- for (i = 0; i < info2.xwallCount; i++)
- {
- XWALL2 xwall2;
- iob.Read(&xwall2, sizeof(XWALL2), 15);
- memset(&xwall[i], 0, sizeof(XWALL));
- xwall[i].reference = xwall2.reference;
- xwall[i].rxID = xwall2.rxID;
- xwall[i].txID = xwall2.txID;
- xwall[i].key = xwall2.key;
- xwall[i].command = xwall2.command;
- xwall[i].type = xwall2.type;
- xwall[i].map = xwall2.map;
- xwall[i].state = xwall2.state;
- xwall[i].triggerOn = xwall2.triggerOn;
- xwall[i].triggerOff = xwall2.triggerOff;
- xwall[i].data = xwall2.data;
- }
- for (i = 0; i < info2.xsectorCount; i++)
- {
- XSECTOR2 xsector2;
- iob.Read(&xsector2, sizeof(XSECTOR2), 16);
- memset(&xsector[i], 0, sizeof(XSECTOR));
- xsector[i].reference = xsector2.reference;
- xsector[i].rxID = xsector2.rxID;
- xsector[i].command = xsector2.command;
- xsector[i].triggerOn = xsector2.triggerOn;
- xsector[i].triggerOff = xsector2.triggerOff;
- xsector[i].triggerOnce = xsector2.triggerOnce;
- xsector[i].amplitude = xsector2.amplitude ;
- xsector[i].freq = xsector2.freq;
- xsector[i].wave = xsector2.wave;
- xsector[i].phase = xsector2.phase;
- xsector[i].state = xsector2.state;
- xsector[i].shadeFloor = xsector2.shadeFloor;
- xsector[i].shadeCeiling = xsector2.shadeCeiling;
- xsector[i].shadeWalls = xsector2.shadeWalls;
- xsector[i].panFloor = xsector2.panFloor;
- xsector[i].panCeiling = xsector2.panCeiling;
- xsector[i].panDrag = xsector2.panDrag;
- xsector[i].panAngle = xsector2.panAngle;
- xsector[i].panVel = xsector2.panSpeed;
- xsector[i].shade = xsector2.shade ;
- xsector[i].txID = xsector2.txID;
- xsector[i].key = xsector2.key;
- xsector[i].type = xsector2.type;
- xsector[i].underwater = xsector2.underwater;
- xsector[i].data = xsector2.data;
- }
- pskybits = info2.pskybits;
- gSkyCount = 1 << pskybits;
- iob.Read(pskyoff, gSkyCount * sizeof(pskyoff[0]), 17);
- iob.Read(gMapAuthor, info2.lenAuthor + 1, 18);
- iob.Read(gMapName, info2.lenName + 1, 19);
- }
- else
- ThrowError( "DB", 20, "Error reading MPX file", ES_ERROR);
- free(buffer);
- // remove sectors with a state of OFF
- for (i = 0; i < numsectors; i++)
- {
- if (sector[i].extra != -1)
- {
- if (!xsector[sector[i].extra].state)
- sector[i].extra = -1;
- }
- }
- // modify new hitscan bit for face,wall,floor sprites
- for (i = 0; i < numsprites; i++)
- {
- // skip invalid sprites
- if (sprite[i].statnum >= kMaxStatus)
- continue;
- // process valid sprites
- if (sprite[i].cstat & kSpriteBlocking) {
- if ((sprite[i].cstat & kSpriteRMask) == 0) {
- // set hitscan for all blocking face sprites
- sprite[i].cstat |= kSpriteHitscan;
- } else {
- // clear hitscan for all blocking wall and floor sprites
- // game should re-set these if they are switches
- sprite[i].cstat &= ~kSpriteHitscan;
- }
- }
- }
- // add up all the elements in the file to determine the size of the buffer
- length = 0;
- length += sizeof(HEADER);
- length += sizeof(INFO3);
- length += strlen(gMapName) + 1;
- length += strlen(gMapAuthor) + 1;
- length += gSkyCount * sizeof(pskyoff[0]);
- length += numsectors * sizeof(SECTOR);
- length += numsectors * sizeof(ceilingSurf[0]);
- length += numsectors * sizeof(floorSurf[0]);
- for (i = 0; i < numsectors; i++)
- {
- if (sector[i].extra > 0)
- length += sizeof(XSECTOR);
- }
- length += numwalls * sizeof(WALL);
- length += numwalls * sizeof(wallSurf[0]);
- for (i = 0; i < numwalls; i++)
- {
- if (wall[i].extra > 0)
- length += sizeof(XWALL);
- }
- for (i = 0; i < numsprites; i++)
- {
- if (sprite[i].extra > 0)
- length += sizeof(XSPRITE);
- }
- length += numsprites * sizeof(SPRITE);
- length += numsprites * sizeof(spriteSurf[0]);
- length += 4; // CRC
- buffer = (char *)malloc(length);
- IOBuffer iob(buffer, length);
- memcpy(header.signature, kBloodMapSig, 4);
- header.version = kBloodMapVersion;
- iob.Write(&header, sizeof(header), 1);
- info3.x = oldHeader.x;
- info3.y = oldHeader.y;
- info3.z = oldHeader.z;
- info3.angle = oldHeader.angle;
- info3.sector = oldHeader.sectnum;
- info3.pskybits = pskybits;
- info3.visibility = info2.visibility;
- info3.songId = 0;
- info3.parallax = 0;
- info3.mapRevisions = 0;
- info3.lenName = (char)strlen(gMapName);
- info3.lenAuthor = (char)strlen(gMapAuthor);
- info3.numsectors = numsectors;
- info3.numwalls = numwalls;
- info3.numsprites = (short)numsprites;
- iob.Write(&info3, sizeof(INFO3), 2);
- iob.Write(gMapName, info3.lenName + 1, 3);
- iob.Write(gMapAuthor, info3.lenAuthor + 1, 4);
- iob.Write(pskyoff, gSkyCount * sizeof(pskyoff[0]), 5);
- for (i = 0; i < numsectors; i++)
- {
- iob.Write(§or[i], sizeof(SECTOR), 6);
- iob.Write(&ceilingSurf[i], sizeof(ceilingSurf[i]), 7);
- iob.Write(&floorSurf[i], sizeof(floorSurf[i]), 8);
- if (sector[i].extra > 0)
- iob.Write(&xsector[sector[i].extra], sizeof(XSECTOR), 9);
- }
- for (i = 0; i < numwalls; i++)
- {
- iob.Write(&wall[i], sizeof(WALL), 10);
- iob.Write(&wallSurf[i], sizeof(wallSurf[i]), 11);
- if (wall[i].extra > 0)
- iob.Write(&xwall[wall[i].extra], sizeof(XWALL), 12);
- }
- for (i = 0; i < numsprites; i++)
- {
- iob.Write(&sprite[i], sizeof(SPRITE), 13);
- iob.Write(&spriteSurf[i], sizeof(spriteSurf[i]), 14);
- if (sprite[i].extra > 0)
- iob.Write(&xsprite[sprite[i].extra], sizeof(XSPRITE), 15);
- }
- gMapCRC = CRC32(buffer, length - sizeof(gMapCRC));
- iob.Write(&gMapCRC, sizeof(gMapCRC), 16);
- // backup the map file
- strcpy(bakfilename, filename);
- ChangeExtension(filename, "MAP");
- ChangeExtension(bakfilename, "~AK");
- rename(filename, bakfilename);
- ChangeExtension(filename, "MPX");
- ChangeExtension(bakfilename, "~PX");
- rename(filename, bakfilename);
- ChangeExtension(filename, "MAP");
- printf("=> %s ", filename);
- hFile = open(filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, S_IWUSR);
- if ( hFile == -1 )
- ThrowError( "DB", 0, "Error opening MAP file", ES_ERROR);
- if (write(hFile, buffer, length) != length)
- ThrowError( "DB", 1, "Error write MAP file", ES_ERROR);
- close(hFile);
- free(buffer);
- printf("OK.\n");
- }
- void InsertFilename( char *fname )
- {
- FNODE *n = (FNODE *)malloc(sizeof(FNODE) + strlen(fname));
- strcpy(n->name, fname);
- // insert the node at the tail, so it stays in order
- n->next = tail->next;
- tail->next = n;
- tail = n;
- }
- void ProcessArgument(char *s)
- {
- char filespec[_MAX_PATH];
- char buffer[_MAX_PATH2];
- char path[_MAX_PATH];
- strcpy(filespec, s);
- ChangeExtension(filespec, ".MAP");
- char *drive, *dir;
- // separate the path from the filespec
- _splitpath2(s, buffer, &drive, &dir, NULL, NULL);
- _makepath(path, drive, dir, NULL, NULL);
- struct find_t fileinfo;
- unsigned r = _dos_findfirst(s, _A_NORMAL, &fileinfo);
- if (r != 0)
- printf("%s not found\n", s);
- while ( r == 0 )
- {
- strcpy(filespec, path);
- strcat(filespec, fileinfo.name);
- InsertFilename(filespec);
- r = _dos_findnext( &fileinfo );
- }
- _dos_findclose(&fileinfo);
- }
- /***********************************************************************
- * Process command line arguments
- **********************************************************************/
- void ParseOptions( int argc, char *argv[])
- {
- int c;
- while ( (c = GetOptions(argc, argv, "")) != GO_EOF ) {
- switch (c) {
- case GO_INVALID:
- QuitMessage("Invalid argument: %s", OptArgument);
- case GO_FULL:
- ProcessArgument(OptArgument);
- break;
- }
- }
- }
- void main(int argc, char *argv[])
- {
- printf("Blood Map 3 Converter Copyright (c) 1995 Q Studios Corporation\n");
- if (argc < 2) ShowUsage();
- ParseOptions(argc, argv);
- // process the file list
- for (FNODE *n = head.next; n != &head; n = n->next)
- ProcessFile(n->name);
- }
|