From ead367d3ee5f2fb4c64b220b9663ef428fafabe8 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Fri, 29 Jan 2010 14:42:59 +0100 Subject: [PATCH 1/2] Small code blurbs from Chris' code --- bsa/bsa_file.cpp | 3 +- nifogre/ogre_nif_loader.cpp | 69 ++++++++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/bsa/bsa_file.cpp b/bsa/bsa_file.cpp index fb00c8e83..ac0f09598 100644 --- a/bsa/bsa_file.cpp +++ b/bsa/bsa_file.cpp @@ -112,8 +112,7 @@ void BSAFile::readHeader() fail("Directory information larger than entire archive"); // Read the offset info into a temporary buffer - vector offsets; - offsets.resize(3*filenum); + vector offsets(3*filenum); input->read(&offsets[0], 12*filenum); // Read the string table diff --git a/nifogre/ogre_nif_loader.cpp b/nifogre/ogre_nif_loader.cpp index 5a595b4c1..ad04d8376 100644 --- a/nifogre/ogre_nif_loader.cpp +++ b/nifogre/ogre_nif_loader.cpp @@ -60,6 +60,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, @@ -81,6 +121,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) { @@ -117,7 +184,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; } From 4fc5435001035ae89d27b60d9abba5fd2c2c0315 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Tue, 16 Feb 2010 16:03:18 +0100 Subject: [PATCH 2/2] Started porting ESM reader --- esm/.gitignore | 4 ++ esm/Makefile | 1 + esm/reader.cpp | 144 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 esm/.gitignore create mode 100644 esm/Makefile create mode 100644 esm/reader.cpp diff --git a/esm/.gitignore b/esm/.gitignore new file mode 100644 index 000000000..3f74ae334 --- /dev/null +++ b/esm/.gitignore @@ -0,0 +1,4 @@ +old +*.esm +*.esp +reader diff --git a/esm/Makefile b/esm/Makefile new file mode 100644 index 000000000..4d7d4098d --- /dev/null +++ b/esm/Makefile @@ -0,0 +1 @@ +all: reader diff --git a/esm/reader.cpp b/esm/reader.cpp new file mode 100644 index 000000000..12e3032e9 --- /dev/null +++ b/esm/reader.cpp @@ -0,0 +1,144 @@ +#include +#include +#include +#include +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 +union NAME_T +{ + char name[LEN]; + int32_t val; + + bool operator==(const char *str) + { + for(int i=0; i 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; +}