123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891 |
- #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 "iob.h"
- #include "tile.h"
- #include "trig.h"
- #include <memcheck.h>
- #define kBloodMapSig "BLM\x1A"
- #define kBloodMapVersion 0x0600
- #define kBloodMapOldVersion 0x0503
- struct FNODE
- {
- FNODE *next;
- char name[1];
- };
- FNODE head = { &head, "" };
- FNODE *tail = &head;
- // Build globals
- SECTOR sector[kMaxSectors];
- WALL wall[kMaxWalls];
- SPRITE sprite[kMaxSprites];
- // Q globals
- XSECTOR xsector[kMaxXSectors];
- XWALL xwall[kMaxXWalls];
- XSPRITE xsprite[kMaxXSprites];
- short pskyoff[kMaxSkyTiles];
- ulong gMapCRC;
- int gSkyCount;
- short numsectors, numwalls;
- struct HEADER5
- {
- char signature[4];
- short version;
- };
- struct HEADER6
- {
- char signature[4];
- short version;
- };
- // version 5.x header
- struct INFO5
- {
- long x, y, z;
- ushort angle;
- ushort sector;
- ushort pskybits;
- long visibility;
- int songId;
- uchar parallax;
- int mapRevisions;
- ushort numsectors;
- ushort numwalls;
- ushort numsprites;
- };
- struct INFO6
- {
- long x, y, z;
- ushort angle;
- ushort sector;
- ushort pskybits;
- long visibility;
- int songId;
- uchar parallax;
- int mapRevisions;
- ushort numsectors;
- ushort numwalls;
- ushort numsprites;
- };
- /***********************************************************************
- * Old version structures and typedefs
- **********************************************************************/
- struct SPRITE5
- {
- long x;
- long y;
- long z;
- ushort cstat;
- schar shade;
- uchar pal;
- uchar clipdist;
- uchar xrepeat;
- uchar yrepeat;
- schar xoffset;
- schar yoffset;
- sshort picnum;
- sshort ang;
- sshort xvel;
- sshort yvel;
- sshort zvel;
- sshort owner;
- sshort sectnum;
- sshort statnum;
- ushort type;
- ushort mass;
- sshort extra;
- };
- struct WALL5
- {
- long x;
- long y;
- ushort point2;
- short nextsector;
- short nextwall;
- short picnum;
- short overpicnum;
- signed char shade;
- char pal;
- short cstat;
- uchar xrepeat;
- uchar yrepeat;
- uchar xpanning;
- uchar ypanning;
- ushort type;
- short hitag;
- short extra;
- };
- struct SECTOR5
- {
- unsigned short wallptr;
- unsigned short wallnum;
- short ceilingpicnum;
- short floorpicnum;
- short ceilingslope;
- short floorslope;
- long ceilingz;
- long floorz;
- schar ceilingshade;
- schar floorshade;
- uchar ceilingxpanning;
- uchar floorxpanning;
- uchar ceilingypanning;
- uchar floorypanning;
- uchar ceilingstat;
- uchar floorstat;
- uchar ceilingpal;
- uchar floorpal;
- uchar visibility;
- ushort type;
- short hitag;
- short extra;
- };
- struct XSPRITE5
- {
- signed reference : 14;
- unsigned state : 1;
- // trigger data
- unsigned busy : 17;
- unsigned txID : 10;
- unsigned rxID : 10;
- unsigned command : 8;
- unsigned triggerOn : 1;
- unsigned triggerOff : 1;
- unsigned busyTime : 12; // time to reach next state
- unsigned waitTime : 12; // delay before callback
- unsigned restState : 1; // state to return to on callback
- unsigned difficulty : 2;
- unsigned map : 2;
- unsigned soundKit : 8;
- // physical triggers
- unsigned decoupled : 1;
- unsigned triggerOnce : 1;
- unsigned isTriggered : 1; // used for triggerOnce objects
- unsigned key : 3;
- unsigned triggerPush : 1; // action key
- unsigned triggerImpact : 1; // vector hits
- unsigned triggerExplode : 1; // exploding things, etc.
- unsigned triggerPickup : 1; // secrets
- unsigned triggerTouch : 1; // sawblades, spikes, zaps?
- unsigned triggerSight : 1; // dunno, yet.
- unsigned triggerProximity : 1; // proximity bombs
- unsigned triggerReserved1 : 1;
- unsigned triggerReserved2 : 1;
- signed data1 : 16; // combo value?
- signed data2 : 16; // combo key?
- signed data3 : 16; // combo max?
- unsigned respawn : 2; // 0=optional never, 1=optional always, 2=always, 3=never
- unsigned respawnTime : 12; // 0=permanent, >0=time in tenths of a second,
- unsigned launchMode : 2; // 0=all, 1=bloodbath, 2=ally, 3=ally&bloodbath,
- // this stuff needed for dudes
- unsigned moveState : 8; // same as player move states
- unsigned aiState : 8;
- signed health : 12;
- unsigned dudeDeaf : 1;
- unsigned dudeAmbush : 1;
- unsigned dudeFlag3 : 1;
- unsigned dudeFlag4 : 1;
- signed target : 16;
- signed targetX : 32;
- signed targetY : 32;
- signed targetZ : 32;
- signed avel : 16;
- unsigned weaponTimer : 16;
- unsigned stateTimer : 16;
- signed support : 16; // will be used by physics system
- unsigned interruptable : 1;
- unsigned pad : 31;
- };
- struct XWALL5
- {
- signed reference : 14;
- unsigned state : 1;
- // trigger data
- unsigned busy : 17;
- signed data : 16;
- unsigned txID : 10;
- unsigned rxID : 10;
- unsigned command : 8;
- unsigned triggerOn : 1;
- unsigned triggerOff : 1;
- unsigned busyTime : 12; // time to reach next state
- unsigned waitTime : 12; // delay before callback
- unsigned restState : 1; // state to return to on callback
- unsigned map : 2;
- // panning data
- unsigned panAlways : 1;
- signed panXVel : 8;
- signed panYVel : 8;
- // physical triggers
- unsigned decoupled : 1;
- unsigned triggerOnce : 1;
- unsigned isTriggered : 1; // used for triggerOnce objects
- unsigned key : 3;
- unsigned triggerPush : 1;
- unsigned triggerImpact : 1;
- unsigned triggerExplode : 1; // exploding things, etc.
- unsigned triggerReserved1 : 1;
- unsigned triggerReserved2 : 1;
- unsigned xpanFrac : 8;
- unsigned ypanFrac : 8;
- unsigned interruptable : 1;
- unsigned pad1 : 15;
- unsigned pad2 : 32;
- };
- struct XSECTOR5
- {
- signed reference : 14;
- unsigned state : 1;
- // trigger data
- unsigned busy : 17;
- signed data : 16;
- unsigned txID : 10;
- unsigned rxID : 10;
- unsigned command : 8;
- unsigned triggerOn : 1;
- unsigned triggerOff : 1;
- unsigned busyTime : 12; // time to reach next state
- unsigned waitTime : 12; // delay before callback
- unsigned restState : 1; // state to return to on callback
- // lighting data
- unsigned shadeAlways : 1;
- signed amplitude : 8;
- unsigned freq : 8;
- unsigned wave : 4;
- unsigned phase : 8;
- unsigned shadeFloor : 1;
- unsigned shadeCeiling : 1;
- unsigned shadeWalls : 1;
- signed shade : 8;
- // panning data
- unsigned panAlways : 1;
- unsigned panFloor : 1;
- unsigned panCeiling : 1;
- unsigned drag : 1;
- // wind/water stuff
- unsigned underwater : 1;
- unsigned depth : 2;
- unsigned panVel : 8;
- unsigned panAngle : 11;
- unsigned wind : 1;
- // physical triggers
- unsigned decoupled : 1;
- unsigned triggerOnce : 1;
- unsigned isTriggered : 1;
- unsigned key : 3;
- unsigned triggerPush : 1;
- unsigned triggerImpact : 1;
- unsigned triggerExplode : 1; // exploding things, etc.
- unsigned triggerEnter : 1;
- unsigned triggerExit : 1;
- unsigned triggerWPush : 1;
- unsigned triggerReserved1 : 1;
- unsigned triggerReserved2 : 1;
- // movement data
- signed offCeilZ : 32;
- signed onCeilZ : 32;
- signed offFloorZ : 32;
- signed onFloorZ : 32;
- signed marker0 : 16;
- signed marker1 : 16;
- // unsigned crush : 1;
- unsigned ceilxpanFrac : 8;
- unsigned ceilypanFrac : 8;
- unsigned floorxpanFrac : 8;
- unsigned floorypanFrac : 8;
- unsigned interruptable : 1;
- unsigned pad1 : 31;
- };
- void ShowUsage(void)
- {
- printf("Usage:\n");
- printf(" CONVDB6 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;
- HEADER5 header5;
- HEADER6 header6;
- INFO5 info5;
- INFO6 info6;
- char filename[_MAX_PATH], bakfilename[_MAX_PATH];
- short numsprites;
- int length;
- BYTE *buffer;
- strcpy(filename, filespec);
- printf("%s ", filename);
- hFile = open(filename, O_RDONLY | O_BINARY);
- if ( hFile == -1 )
- ThrowError("unable to open MAP file", ES_ERROR);
- length = filelength(hFile);
- buffer = (BYTE *)malloc(length);
- if (read(hFile, buffer, length) == length)
- {
- close(hFile);
- IOBuffer iob(buffer, length);
- iob.Read(&header5, sizeof(HEADER5));
- // check signature and major version number
- if ( (memcmp(header5.signature, kBloodMapSig, sizeof(header5.signature)) != 0)
- || ((header5.version >> 8) != (kBloodMapOldVersion >> 8)) )
- {
- printf("not expected format, skipping\n");
- return;
- }
- iob.Read(&info5, sizeof(INFO5));
- numsectors = info5.numsectors;
- numwalls = info5.numwalls;
- numsprites = info5.numsprites;
- gSkyCount = 1 << info5.pskybits;
- iob.Read(pskyoff, gSkyCount * sizeof(pskyoff[0]));
- for (i = 0; i < numsectors; i++)
- {
- SECTOR5 sector5;
- iob.Read(§or5, sizeof(sector5));
- sector[i].wallptr = sector5.wallptr;
- sector[i].wallnum = sector5.wallnum;
- sector[i].ceilingz = sector5.ceilingz;
- sector[i].floorz = sector5.floorz;
- sector[i].ceilingstat = sector5.ceilingstat;
- sector[i].floorstat = sector5.floorstat;
- sector[i].ceilingpicnum = sector5.ceilingpicnum;
- sector[i].ceilingslope = (sshort)(sector5.ceilingslope << 5);
- sector[i].ceilingshade = sector5.ceilingshade;
- sector[i].ceilingpal = sector5.ceilingpal;
- sector[i].ceilingxpanning = sector5.ceilingxpanning;
- sector[i].ceilingypanning = sector5.ceilingypanning;
- sector[i].floorpicnum = sector5.floorpicnum;
- sector[i].floorslope = (sshort)(sector5.floorslope << 5);
- sector[i].floorshade = sector5.floorshade;
- sector[i].floorpal = sector5.floorpal;
- sector[i].floorxpanning = sector5.floorxpanning;
- sector[i].floorypanning = sector5.floorypanning;
- sector[i].visibility = sector5.visibility;
- sector[i].filler = 0;
- sector[i].type = sector5.type;
- sector[i].hitag = sector5.hitag;
- sector[i].extra = sector5.extra;
- if ( sector[i].ceilingslope == 0 )
- sector[i].ceilingstat &= ~kSectorSloped;
- if ( sector[i].floorslope == 0 )
- sector[i].floorstat &= ~kSectorSloped;
- if (sector[i].extra > 0)
- {
- int j = sector[i].extra;
- XSECTOR5 xsector5;
- iob.Read(&xsector5, sizeof(XSECTOR5));
- memset(&xsector[j], 0, sizeof(XSECTOR));
- xsector[j].reference = xsector5.reference;
- xsector[j].state = xsector5.state;
- // trigger data
- xsector[j].busy = 0;
- xsector[j].data = xsector5.data;
- xsector[j].txID = xsector5.txID;
- xsector[j].rxID = xsector5.rxID;
- xsector[j].command = xsector5.command;
- xsector[j].triggerOn = xsector5.triggerOn;
- xsector[j].triggerOff = xsector5.triggerOff;
- xsector[j].busyTime = xsector5.busyTime;
- xsector[j].waitTime = xsector5.waitTime;
- xsector[j].restState = xsector5.restState;
- xsector[j].interruptable = xsector5.interruptable;
- // lighting data
- xsector[j].amplitude = xsector5.amplitude;
- xsector[j].freq = xsector5.freq;
- xsector[j].phase = xsector5.phase;
- xsector[j].wave = xsector5.wave;
- xsector[j].shadeAlways = xsector5.shadeAlways;
- xsector[j].shadeFloor = xsector5.shadeFloor;
- xsector[j].shadeCeiling = xsector5.shadeCeiling;
- xsector[j].shadeWalls = xsector5.shadeWalls;
- xsector[j].shade = xsector5.shade;
- // panning data
- xsector[j].panAlways = xsector5.panAlways;
- xsector[j].panFloor = xsector5.panFloor;
- xsector[j].panCeiling = xsector5.panCeiling;
- xsector[j].drag = xsector5.drag;
- // wind/water stuff
- xsector[j].underwater = xsector5.underwater;
- xsector[j].depth = xsector5.depth;
- xsector[j].panVel = xsector5.panVel;
- xsector[j].panAngle = xsector5.panAngle;
- xsector[j].wind = xsector5.wind;
- // physical triggers
- xsector[j].decoupled = xsector5.decoupled;
- xsector[j].triggerOnce = xsector5.triggerOnce;
- xsector[j].isTriggered = xsector5.isTriggered;
- xsector[j].key = xsector5.key;
- xsector[j].triggerPush = xsector5.triggerPush;
- xsector[j].triggerImpact = xsector5.triggerImpact;
- xsector[j].triggerExplode = xsector5.triggerExplode;
- xsector[j].triggerEnter = xsector5.triggerEnter;
- xsector[j].triggerExit = xsector5.triggerExit;
- xsector[j].triggerWPush = xsector5.triggerWPush;
- xsector[j].triggerReserved1 = xsector5.triggerReserved1;
- xsector[j].triggerReserved2 = xsector5.triggerReserved2;
- // movement data
- xsector[j].offCeilZ = xsector5.offCeilZ;
- xsector[j].onCeilZ = xsector5.onCeilZ;
- xsector[j].offFloorZ = xsector5.offFloorZ;
- xsector[j].onFloorZ = xsector5.onFloorZ;
- xsector[j].marker0 = xsector5.marker0;
- xsector[j].marker1 = xsector5.marker1;
- xsector[j].crush = 0;
- }
- }
- for (i = 0; i < numwalls; i++)
- {
- WALL5 wall5;
- iob.Read(&wall5, sizeof(wall5));
- wall[i].x = wall5.x;
- wall[i].y = wall5.y;
- wall[i].point2 = wall5.point2;
- wall[i].nextwall = wall5.nextwall;
- wall[i].nextsector = wall5.nextsector;
- wall[i].cstat = wall5.cstat;
- wall[i].picnum = wall5.picnum;
- wall[i].overpicnum = wall5.overpicnum;
- wall[i].shade = wall5.shade;
- wall[i].pal = wall5.pal;
- wall[i].xrepeat = wall5.xrepeat;
- wall[i].yrepeat = wall5.yrepeat;
- wall[i].xpanning = wall5.xpanning;
- wall[i].ypanning = wall5.ypanning;
- wall[i].type = wall5.type;
- wall[i].hitag = wall5.hitag;
- wall[i].extra = wall5.extra;
- if (wall[i].extra > 0)
- {
- int j = wall[i].extra;
- XWALL5 xwall5;
- iob.Read(&xwall5, sizeof(XWALL5));
- memset(&xwall[j], 0, sizeof(XWALL));
- xwall[j].reference = xwall5.reference;
- xwall[j].state = xwall5.state;
- // trigger data
- xwall[j].busy = xwall5.busy;
- xwall[j].data = xwall5.data;
- xwall[j].txID = xwall5.txID;
- xwall[j].rxID = xwall5.rxID;
- xwall[j].command = xwall5.command;
- xwall[j].triggerOn = xwall5.triggerOn;
- xwall[j].triggerOff = xwall5.triggerOff;
- xwall[j].busyTime = xwall5.busyTime;
- xwall[j].waitTime = xwall5.waitTime;
- xwall[j].restState = xwall5.restState;
- xwall[j].interruptable = xwall5.interruptable;
- // panning data
- xwall[j].panAlways = xwall5.panAlways;
- xwall[j].panXVel = xwall5.panXVel;
- xwall[j].panYVel = xwall5.panYVel;
- // physical triggers
- xwall[j].decoupled = xwall5.decoupled;
- xwall[j].triggerOnce = xwall5.triggerOnce;
- xwall[j].isTriggered = xwall5.isTriggered;
- xwall[j].key = xwall5.key;
- xwall[j].triggerPush = xwall5.triggerPush;
- xwall[j].triggerImpact = xwall5.triggerImpact;
- xwall[j].triggerExplode = xwall5.triggerExplode;
- }
- }
- for (i = 0; i < numsprites; i++)
- {
- SPRITE5 sprite5;
- iob.Read(&sprite5, sizeof(sprite5));
- sprite[i].x = sprite5.x;
- sprite[i].y = sprite5.y;
- sprite[i].z = sprite5.z;
- sprite[i].cstat = sprite5.cstat;
- sprite[i].picnum = sprite5.picnum;
- sprite[i].shade = sprite5.shade;
- sprite[i].pal = sprite5.pal;
- sprite[i].clipdist = sprite5.clipdist;
- sprite[i].filler = 0;
- sprite[i].xrepeat = sprite5.xrepeat;
- sprite[i].yrepeat = sprite5.yrepeat;
- sprite[i].xoffset = sprite5.xoffset;
- sprite[i].yoffset = sprite5.yoffset;
- sprite[i].sectnum = sprite5.sectnum;
- sprite[i].statnum = sprite5.statnum;
- sprite[i].ang = sprite5.ang;
- sprite[i].owner = sprite5.owner;
- sprite[i].xvel = sprite5.xvel;
- sprite[i].yvel = sprite5.yvel;
- sprite[i].zvel = sprite5.zvel;
- sprite[i].type = sprite5.type;
- sprite[i].flags = 0; // sprite5.mass;
- sprite[i].extra = sprite5.extra;
- if (sprite[i].extra > 0)
- {
- int j = sprite[i].extra;
- XSPRITE5 xsprite5;
- iob.Read(&xsprite5, sizeof(XSPRITE5));
- memset(&xsprite[j], 0, sizeof(XSPRITE));
- xsprite[j].reference = xsprite5.reference;
- xsprite[j].state = xsprite5.state;
- // trigger data
- xsprite[j].busy = 0;
- xsprite[j].txID = xsprite5.txID;
- xsprite[j].rxID = xsprite5.rxID;
- xsprite[j].command = xsprite5.command;
- xsprite[j].triggerOn = xsprite5.triggerOn;
- xsprite[j].triggerOff = xsprite5.triggerOff;
- xsprite[j].busyTime = xsprite5.busyTime;
- xsprite[j].waitTime = xsprite5.waitTime;
- xsprite[j].restState = xsprite5.restState;
- xsprite[j].interruptable = xsprite5.interruptable;
- xsprite[j].difficulty = xsprite5.difficulty;
- xsprite[j].soundKit = xsprite5.soundKit;
- // physical triggers
- xsprite[j].decoupled = xsprite5.decoupled;
- xsprite[j].triggerOnce = xsprite5.triggerOnce;
- xsprite[j].isTriggered = 0;
- xsprite[j].key = xsprite5.key;
- xsprite[j].triggerPush = xsprite5.triggerPush;
- xsprite[j].triggerImpact = xsprite5.triggerImpact;
- xsprite[j].triggerExplode = xsprite5.triggerExplode;
- xsprite[j].triggerPickup = xsprite5.triggerPickup;
- xsprite[j].triggerTouch = xsprite5.triggerTouch;
- xsprite[j].triggerSight = xsprite5.triggerSight;
- xsprite[j].triggerProximity = xsprite5.triggerProximity;
- xsprite[j].data1 = xsprite5.data1;
- xsprite[j].data2 = xsprite5.data2;
- xsprite[j].data3 = xsprite5.data3;
- xsprite[j].support = xsprite5.support;
- // respawn flags
- xsprite[j].respawn = xsprite5.respawn;
- xsprite[j].respawnTime = xsprite5.respawnTime;
- xsprite[j].launchMode = xsprite5.launchMode;
- // this stuff needed for dudes (probably initialized dynamically)
- xsprite[j].moveState = 0;
- xsprite[j].aiState = 0;
- xsprite[j].health = 0;
- xsprite[j].dudeDeaf = 0;
- xsprite[j].dudeAmbush = 0;
- xsprite[j].dudeGuard = 0;
- xsprite[j].dudeFlag4 = 0;
- xsprite[j].target = 0;
- xsprite[j].targetX = 0;
- xsprite[j].targetY = 0;
- xsprite[j].targetZ = 0;
- xsprite[j].avel = 0;
- xsprite[j].stateTimer = 0;
- }
- }
- }
- else
- ThrowError("Error reading map file", ES_ERROR);
- free(buffer);
- // convert slide types and angle markers for maps before 5.03
- if ( (header5.version & 0xFF) < 3 )
- {
- for ( i = 0; i < kMaxSectors; i++)
- {
- if ( sector[i].type == kSectorSlide )
- {
- sector[i].type = kSectorSlideMarked;
- }
- }
- for ( i = 0; i < kMaxSprites; i++)
- if ( sprite[i].statnum == kStatMarker )
- {
- if ( sprite[i].ang >= kAngle180 )
- sprite[i].ang -= kAngle360;
- }
- }
- // add up all the elements in the file to determine the size of the buffer
- length = 0;
- length += sizeof(HEADER6);
- length += sizeof(INFO6);
- length += gSkyCount * sizeof(pskyoff[0]);
- length += numsectors * sizeof(SECTOR);
- for (i = 0; i < numsectors; i++)
- {
- if (sector[i].extra > 0)
- length += sizeof(XSECTOR);
- }
- length += numwalls * sizeof(WALL);
- for (i = 0; i < numwalls; i++)
- {
- if (wall[i].extra > 0)
- length += sizeof(XWALL);
- }
- length += numsprites * sizeof(SPRITE);
- for (i = 0; i < numsprites; i++)
- {
- if (sprite[i].extra > 0)
- length += sizeof(XSPRITE);
- }
- length += 4; // CRC
- buffer = (BYTE *)malloc(length);
- IOBuffer iob(buffer, length);
- memcpy(header6.signature, kBloodMapSig, sizeof(header6.signature));
- header6.version = kBloodMapVersion;
- iob.Write(&header6, sizeof(header6));
- info6.x = info5.x;
- info6.y = info5.y;
- info6.z = info5.z;
- info6.angle = info5.angle;
- info6.sector = info5.sector;
- info6.pskybits = info5.pskybits;
- info6.visibility = info5.visibility;
- info6.songId = info5.songId;
- info6.parallax = info5.parallax;
- info6.mapRevisions = info5.mapRevisions;
- info6.numsectors = numsectors;
- info6.numwalls = numwalls;
- info6.numsprites = numsprites;
- iob.Write(&info6, sizeof(info6));
- iob.Write(pskyoff, gSkyCount * sizeof(pskyoff[0]));
- for (i = 0; i < numsectors; i++)
- {
- iob.Write(§or[i], sizeof(SECTOR));
- if (sector[i].extra > 0)
- iob.Write(&xsector[sector[i].extra], sizeof(XSECTOR));
- }
- for (i = 0; i < numwalls; i++)
- {
- iob.Write(&wall[i], sizeof(WALL));
- if (wall[i].extra > 0)
- iob.Write(&xwall[wall[i].extra], sizeof(XWALL));
- }
- for (i = 0; i < numsprites; i++)
- {
- iob.Write(&sprite[i], sizeof(SPRITE));
- if (sprite[i].extra > 0)
- iob.Write(&xsprite[sprite[i].extra], sizeof(XSPRITE));
- }
- gMapCRC = CRC32(buffer, length - sizeof(gMapCRC));
- iob.Write(&gMapCRC, sizeof(gMapCRC));
- // backup the map file
- strcpy(bakfilename, filename);
- ChangeExtension(bakfilename, "MA5");
- rename(filename, bakfilename);
- printf("=> %s ", filename);
- hFile = open(filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, S_IWUSR);
- if ( hFile == -1 )
- ThrowError("Error opening MAP file", ES_ERROR);
- if (write(hFile, buffer, length) != length)
- ThrowError("Error writing 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);
- AddExtension(filespec, ".MAP");
- char *drive, *dir;
- // separate the path from the filespec
- _splitpath2(filespec, buffer, &drive, &dir, NULL, NULL);
- _makepath(path, drive, dir, NULL, NULL);
- struct find_t fileinfo;
- unsigned r = _dos_findfirst(filespec, _A_NORMAL, &fileinfo);
- if (r != 0)
- printf("%s not found\n", filespec);
- 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( void )
- {
- static SWITCH switches[] = { { NULL, 0, FALSE } };
- int r;
- while ( (r = GetOptions(switches)) != GO_EOF ) {
- switch (r)
- {
- case GO_INVALID:
- QuitMessage("Invalid argument: %s", OptArgument);
- case GO_FULL:
- ProcessArgument(OptArgument);
- break;
- }
- }
- }
- void main(int argc)
- {
- printf("Blood Map 6 Converter Copyright (c) 1995 Q Studios Corporation\n");
- if (argc < 2) ShowUsage();
- ParseOptions();
- // process the file list
- for (FNODE *n = head.next; n != &head; n = n->next)
- ProcessFile(n->name);
- }
|