forked from mirror/openmw-tes3mp
Merge branch 'master' of git@github.com:korslund/openmw
This commit is contained in:
commit
7c9b1adc8d
5 changed files with 218 additions and 3 deletions
|
@ -112,8 +112,7 @@ void BSAFile::readHeader()
|
|||
fail("Directory information larger than entire archive");
|
||||
|
||||
// Read the offset info into a temporary buffer
|
||||
vector<uint32_t> offsets;
|
||||
offsets.resize(3*filenum);
|
||||
vector<uint32_t> offsets(3*filenum);
|
||||
input->read(&offsets[0], 12*filenum);
|
||||
|
||||
// Read the string table
|
||||
|
|
4
esm/.gitignore
vendored
Normal file
4
esm/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
old
|
||||
*.esm
|
||||
*.esp
|
||||
reader
|
1
esm/Makefile
Normal file
1
esm/Makefile
Normal file
|
@ -0,0 +1 @@
|
|||
all: reader
|
144
esm/reader.cpp
Normal file
144
esm/reader.cpp
Normal file
|
@ -0,0 +1,144 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
using namespace std;
|
||||
|
||||
#include "../mangle/stream/stream.h"
|
||||
#include "../mangle/stream/servers/file_stream.h"
|
||||
#include "../mangle/tools/str_exception.h"
|
||||
|
||||
/* A structure used for holding fixed-length strings. In the case of
|
||||
LEN=4, it can be more efficient to match the string as a 32 bit
|
||||
number, therefore the struct is implemented as a union with an int.
|
||||
*/
|
||||
template <int LEN>
|
||||
union NAME_T
|
||||
{
|
||||
char name[LEN];
|
||||
int32_t val;
|
||||
|
||||
bool operator==(const char *str)
|
||||
{
|
||||
for(int i=0; i<LEN; i++)
|
||||
if(name[i] != str[i]) return false;
|
||||
else if(name[i] == 0) return true;
|
||||
return str[LEN] == 0;
|
||||
}
|
||||
bool operator!=(const char *str) { return !((*this)==str); }
|
||||
|
||||
bool operator==(const string &str)
|
||||
{
|
||||
return (*this) == str.c_str();
|
||||
}
|
||||
bool operator!=(const string &str) { return !((*this)==str); }
|
||||
|
||||
bool operator==(int v) { return v == val; }
|
||||
bool operator!=(int v) { return v != val; }
|
||||
};
|
||||
|
||||
typedef NAME_T<4> NAME;
|
||||
typedef NAME_T<32> NAME32;
|
||||
typedef NAME_T<256> NAME256;
|
||||
|
||||
class ESMReader
|
||||
{
|
||||
Mangle::Stream::StreamPtr esm;
|
||||
size_t leftFile;
|
||||
uint32_t leftRec;
|
||||
string filename;
|
||||
|
||||
NAME recName, subName;
|
||||
|
||||
public:
|
||||
void open(Mangle::Stream::StreamPtr _esm, const string &name)
|
||||
{
|
||||
esm = _esm;
|
||||
filename = name;
|
||||
leftFile = esm->size();
|
||||
leftRec = 0;
|
||||
recName.val = 0;
|
||||
subName.val = 0;
|
||||
|
||||
cout << "left: " << leftFile << endl;
|
||||
if(getRecName() != "TES3")
|
||||
fail("Not a valid Morrowind file");
|
||||
cout << "left: " << leftFile << endl;
|
||||
|
||||
// The flags are always zero
|
||||
uint32_t flags;
|
||||
getRecHeader(flags);
|
||||
}
|
||||
|
||||
void open(const string &file)
|
||||
{
|
||||
using namespace Mangle::Stream;
|
||||
open(StreamPtr(new FileStream(file)), file);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Low level reading methods
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
NAME getRecName()
|
||||
{
|
||||
if(!hasMoreRecs())
|
||||
fail("No more records, getRecName() failed");
|
||||
getName(recName);
|
||||
leftFile -= 4;
|
||||
return recName;
|
||||
}
|
||||
|
||||
/* Read record header. This updatesleftFile BEYOND the data that
|
||||
follows the header, ie beyond the entire record. You should use
|
||||
leftRec to orient yourself inside the record itself.
|
||||
*/
|
||||
void getRecHeader(uint32_t &flags)
|
||||
{
|
||||
// General error checking
|
||||
if(leftFile < 12)
|
||||
fail("End of file while reading record header");
|
||||
if(leftRec)
|
||||
fail("Previous record contains unread bytes");
|
||||
|
||||
getUint(leftRec);
|
||||
getUint(flags);// This header entry is always zero
|
||||
getUint(flags);
|
||||
leftFile -= 12;
|
||||
|
||||
// Check that sizes add up
|
||||
if(leftFile < leftRec)
|
||||
fail("Record size is larger than rest of file");
|
||||
|
||||
// Adjust number of bytes left in file
|
||||
leftFile -= leftRec;
|
||||
}
|
||||
|
||||
bool hasMoreRecs() { return leftFile > 0; }
|
||||
|
||||
void getName(NAME &name) { esm->read(&name,4); }
|
||||
void getUint(uint32_t &u) { esm->read(&u,4); }
|
||||
|
||||
/// Used for error handling
|
||||
void fail(const std::string &msg)
|
||||
{
|
||||
std::string err = "ESM Error: " + msg;
|
||||
err += "\n File: " + filename;
|
||||
err += "\n Record: " + string(recName.name,4);
|
||||
err += "\n Subrecord: " + string(subName.name,4);
|
||||
throw str_exception(err);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char**argv)
|
||||
{
|
||||
if(argc != 2)
|
||||
return 1;
|
||||
|
||||
ESMReader esm;
|
||||
esm.open(argv[1]);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -58,6 +58,46 @@ static void warn(const string &msg)
|
|||
cout << "WARNING (NIF:" << errName << "): " << msg << endl;
|
||||
}
|
||||
|
||||
// Conversion of blend / test mode from NIF -> OGRE. Not in use yet.
|
||||
static SceneBlendFactor getBlendFactor(int mode)
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case 0: return SBF_ONE;
|
||||
case 1: return SBF_ZERO;
|
||||
case 2: return SBF_SOURCE_COLOUR;
|
||||
case 3: return SBF_ONE_MINUS_SOURCE_COLOUR;
|
||||
case 4: return SBF_DEST_COLOUR;
|
||||
case 5: return SBF_ONE_MINUS_DEST_COLOUR;
|
||||
case 6: return SBF_SOURCE_ALPHA;
|
||||
case 7: return SBF_ONE_MINUS_SOURCE_ALPHA;
|
||||
case 8: return SBF_DEST_ALPHA;
|
||||
case 9: return SBF_ONE_MINUS_DEST_ALPHA;
|
||||
/* [Comment from Chris Robinson:] Can't handle this mode? :/
|
||||
case 10: return SBF_SOURCE_ALPHA_SATURATE;
|
||||
*/
|
||||
default:
|
||||
return SBF_SOURCE_ALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
static CompareFunction getTestMode(int mode)
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case 0: return CMPF_ALWAYS_PASS;
|
||||
case 1: return CMPF_LESS;
|
||||
case 2: return CMPF_EQUAL;
|
||||
case 3: return CMPF_LESS_EQUAL;
|
||||
case 4: return CMPF_GREATER;
|
||||
case 5: return CMPF_NOT_EQUAL;
|
||||
case 6: return CMPF_GREATER_EQUAL;
|
||||
case 7: return CMPF_ALWAYS_FAIL;
|
||||
default:
|
||||
return CMPF_ALWAYS_PASS;
|
||||
}
|
||||
}
|
||||
|
||||
static void createMaterial(const String &name,
|
||||
const Vector &ambient,
|
||||
const Vector &diffuse,
|
||||
|
@ -79,6 +119,33 @@ static void createMaterial(const String &name,
|
|||
Pass *pass = material->getTechnique(0)->getPass(0);
|
||||
TextureUnitState *txt = pass->createTextureUnitState(texName);
|
||||
|
||||
/* As of yet UNTESTED code from Chris:
|
||||
pass->setTextureFiltering(Ogre::TFO_ANISOTROPIC);
|
||||
pass->setDepthFunction(Ogre::CMPF_LESS_EQUAL);
|
||||
pass->setDepthCheckEnabled(true);
|
||||
|
||||
// Add transparency if NiAlphaProperty was present
|
||||
if(alphaFlags != -1)
|
||||
{
|
||||
if((alphaFlags&1))
|
||||
{
|
||||
pass->setDepthWriteEnabled(false);
|
||||
pass->setSceneBlending(getBlendFactor((alphaFlags>>1)&0xf),
|
||||
getBlendFactor((alphaFlags>>5)&0xf));
|
||||
}
|
||||
else
|
||||
pass->setDepthWriteEnabled(true);
|
||||
|
||||
if((alphaFlags>>9)&1)
|
||||
pass->setAlphaRejectSettings(getTestMode((alphaFlags>>10)&0x7),
|
||||
alphaTest);
|
||||
|
||||
pass->setTransparentSortingEnabled(!((alphaFlags>>13)&1));
|
||||
}
|
||||
else
|
||||
pass->setDepthWriteEnabled(true);
|
||||
*/
|
||||
|
||||
// Add transparency if NiAlphaProperty was present
|
||||
if(alphaFlags != -1)
|
||||
{
|
||||
|
@ -115,7 +182,7 @@ static String getUniqueName(const String &input)
|
|||
snprintf(buf,8,"_%d", addon++);
|
||||
|
||||
// Don't overflow the buffer
|
||||
if(addon > 1999999) addon = 0;
|
||||
if(addon > 999999) addon = 0;
|
||||
|
||||
return input + buf;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue