Started cleaning out d code. Updated Mangle.

actorid
Nicolay Korslund 15 years ago
parent 769eae99b3
commit 129da4f214

@ -1 +1 @@
Subproject commit fb1eec974c63fa435286456f5c82b9d9387ff900
Subproject commit 2a6ed21351464751245c485f933ed788d6cb0698

@ -1,370 +0,0 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: http://openmw.snaptoad.com/
This file (bored.d) is part of the OpenMW package.
OpenMW is distributed as free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 3, as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see
http://www.gnu.org/licenses/ .
*/
module bored;
import std.stdio;
import std.cstream;
import std.stream;
import std.random;
import std.file;
double rnd()
{
return cast(double)std.random.rand()/uint.max;
}
int rand(int a, int b)
{
return cast(int)((1+b-a)*rnd()+a);
}
void main()
{
int gold = 0;
int loot = 0;
int level = 1;
int life = 20;
bool play = true;
writefln("\nWelcome to Norrowind!");
while(play)
{
writefln();
if(life < 4) writefln("You are badly hurt.");
else if(life < 10) writefln("You are injured.");
else if(life < 15) writefln("You are slightly wounded.");
if(gold) writefln("You have %d gold.", gold);
if(loot) writefln("You have loot.");
if(level>1) writefln("You are level ", level);
writefln("
1) Kill a monster
2) Read a book
3) Read an NPC
4) Sell some loot
5) Walk around and get drunk on skooma
6) Watch TEH k33wL P1XAL SHADID W4T3R!!!!1
7) Exit
");
uint input;
dout.writef("Your choice: ");
do
{
input = cast(uint)(din.getc() - '0');
}
while(input >= 8);
if(rnd() < 0.01)
{
writefln("Program has performed an illegal instruction, the programmer will be shot.");
break;
}
writefln();
if(((input == 5) || (input == 3) || (input == 1)) && (loot > 100))
{
writefln("You are encumbered and cannot move. Try selling some of your junk.");
continue;
}
char[] str;
int lootinc, goldinc;
int oldlife = life;
switch(input)
{
case 1: // Hunting
if(rnd() < 0.02)
{
writefln("You killed a Bodak and a Greater Mumm.. oops, wrong game, never mind.");
break;
}
if(rnd() < 0.02)
{
writefln(
"You were killed by an white striped aquatic flying dire gigant dragon
bear in a Balmora mansion. This is largely your own fault for using all
those plugins.");
play=false;
break;
}
if(rnd() < 0.02)
{
writefln("You were eaten by a grue.");
play=false;
break;
}
switch(rand(0,15))
{
case 0: str = "Fjol the Outlaw"; goldinc = rand(0,70); lootinc = rand(10,120); break;
case 1: str = "a Betty Netch"; lootinc = rand(0,7); break;
case 2: str = "a Vampire"; goldinc = rand(0,10); lootinc = rand(20,40); break;
case 3: str = "a Dremora"; lootinc = rand(50,200); break;
case 4: str = "some NPC"; goldinc = rand(0,80); lootinc = rand(3,35); break;
case 5: str = "an Ordinator"; lootinc = rand(30,45); break;
case 6: str = "a Skeleton"; lootinc = 1; break;
case 7: str = "Fargoth"; goldinc = 10; lootinc = 4; break;
case 8: str = "a Cliff Racer"; lootinc = 2; break;
case 9: str = "Vivec"; lootinc = rand(0,20); goldinc = rand(0,60); life-=rand(1,2); break;
case 10: str = "a soultrapped Vivec"; goldinc = rand(0,60); lootinc = rand(100,300);
life-=rand(1,3); break;
case 11: str = "an Ascended Sleeper"; lootinc = rand(5,12); goldinc = rand(0,10); break;
case 12: str = "the entire town of Gnaar Mok"; goldinc = rand(40,50); lootinc = rand(70,140);
life-=rand(0,2); break;
case 13: str = "a Bethesda programmer for being so late with Oblivion"; break;
case 14: str = "a Werewolf. Which is kinda strange since you don't have Bloodmoon"; lootinc = rand(4,50); break;
case 15: str = "an important quest character. Way to go"; goldinc = rand(0,40); lootinc = rand(0,70); break;
}
if(rnd() < 0.65)
life -= rand(1,8);
if(life > 0)
{
writefln("You killed ", str, ".");
if(life < oldlife) writefln("You were hurt in the fight.");
else writefln("You survived the fight unscathed.");
if(goldinc) writefln("You got ", goldinc, " bucks.");
if(lootinc) writefln("You found some loot.");
gold += goldinc;
loot += lootinc;
if(rnd() < 0.2)
{
writefln("You have gained a level!");
life += rand(3,10);
level++;
}
}
else
{
writefln("You met ", str, " and were killed.");
play = false;
}
break;
case 2:// Book
switch(rand(0,5))
{
case 0:
writefln("You read The History of The Emipire and fell asleep.");
break;
case 1:
writefln("You read The Pilgrim's Path and became a fanatical religious nut.");
break;
case 2:
writefln("You read the scroll 'Divine Intervention' and suddenly found yourself
outside, wearing only your night gown and slippers.");
break;
case 3:
writefln("You read Divine Metaphysics. Again");
if(rnd()<0.09)
{
writefln("You discovered where the dwarwes went! And, more importantly, where
they stashed all their loot.");
loot += 1000;
}
break;
case 4:
writefln("You learned a new skill.");
if(rnd() < 0.4) level++;
break;
case 5:
writefln("You dropped a book on you toe.");
life--;
if(life == 0)
{
writefln("You are dead.");
play = false;
}
break;
}
break;
case 3://NPC
if(rnd()<0.05)
{
writefln("Nobody wants to speak with you.");
break;
}
writefln("You met an NPC");
switch(rand(0,9))
{
case 0: writefln("He had nothing interesting to say."); break;
case 1: writefln("She was really boring."); break;
case 2: writefln("You got a quest!"); break;
case 3: writefln("You completed a quest and got some dough."); gold += rand(1,10); break;
case 4: writefln("The nice NPC gave you a healing potion."); life+=rand(2,4); break;
case 5: writefln("You robbed 'em blind and got some loot."); loot+=(10,20); break;
case 6: writefln("The guard took some of your money, saying you were
late on your child support payments."); gold = gold/3; break;
case 7: writefln("You spent some money on bribes"); gold -= gold/4; break;
case 8: writefln("You had to travel all the way accross the island to talk to this person."); gold -= gold/4; break;
case 9: writefln("The Breton mistook you for his mother, and gave you tons of gold."); gold += 100; break;
}
break;
case 4://Sell
if(loot == 0)
writefln("You have nothing to sell (except that moon sugar and the home made poetry that nobody wants)");
else if(rnd()<0.93)
{
goldinc = cast(int)(loot*rnd()*2);
if(goldinc > loot) writefln("The merchant likes you, you got ", goldinc, " gold for stuff worth only ", loot, ".");
if(goldinc <= loot) writefln("The merchant didn't like you, your ", loot, " worth of stuff
only got you ", goldinc, " gold.");
}
else
{
writefln("You met a talking mudcrab and an unfunny scamp! You got lots of\ncash for your loot.");
goldinc = 5*loot;
}
gold += goldinc;
loot = 0;
break;
case 5://Skooma
switch(rand(0,7))
{
case 0:
str = "gigant, flesh eating mushrooms"; break;
case 1:
str = "a firm, slender and agile female argonian"; break;
case 2:
str = "dead people and some stupid guy in a golden mask"; break;
case 3:
str = "the whole world only being part of a computer game"; break;
case 4:
str = "nothing in particular"; break;
case 5:
str = "an old, half naked guy giving you orders, insisting you\ncall him 'spymaster'";
break;
case 6:
str = "being a geek who sits in front of a screen all day long"; break;
case 7:
str = "the clouds, man, the crazy clouds!"; break;
}
writefln("You fall asleep in a ditch and dream about ", str, ".");
break;
case 6: //Water effects
switch(rand(0,5))
{
case 0: writefln("Them waves sure are pretty!"); break;
case 1:
writefln("A slaughter fish jumps up and bites you in the nose.");
life--;
if(life == 0)
{
writefln("You are dead.");
play = false;
}
break;
case 2: writefln("Those graphics might have looked impressive six years ago...");
break;
case 3: writefln("You were eaten by a Mudcrab. You are dead."); play=false; break;
case 4: writefln("You suddenly realize that the person who made this program has way too much time on his hands.");break;
case 5: writefln("You found a note with cheat codes on them."); level+=2; life+=rand(5,15); break;
}
break;
// Exit
case 7: play=false; break;
}
}
writefln("\nScore:");
writefln("Gold: %d : %d points", gold, gold);
writefln("Level: %d : %d points", level, (level-1)*40);
if(loot) writefln("Loot: you have to sell the loot to get any points for it.");
Entry n;
n.score = gold + (level-1) * 40;
writefln("Total score: ", n.score);
Entry[] high = getScores();
int index = 10;
foreach(int i, Entry e; high)
if(n.score > e.score)
{
index = i;
break;
}
writefln();
if(index != 10)
{
writef("Congratulations! You've made it to the Hall of Fame.\nEnter your name: ");
din.readLine();
n.name = din.readLine();
for(int i = 9; i>index; i--)
high[i] = high[i-1];
high[index] = n;
setScores(high);
}
writefln("Hall of Fame:");
foreach(int i, Entry e; high)
if(e.score) writefln("%-2d: %-10d %s", i+1, e.score, e.name);
writefln("\n(Apologies to Bethesda Softworks)");
}
struct Entry
{
char[] name;
int score;
}
void setScores(Entry[] l)
{
auto File f = new File("bored.highscores", FileMode.OutNew);
foreach(Entry e; l)
{
f.write(e.name);
f.write(e.score);
}
}
Entry[] getScores()
{
Entry[] l;
l.length = 10;
if(exists("bored.highscores"))
{
auto File f = new File("bored.highscores");
foreach(ref Entry e; l)
{
f.read(e.name);
f.read(e.score);
}
}
return l;
}

@ -1,366 +0,0 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: http://openmw.snaptoad.com/
This file (bsafile.d) is part of the OpenMW package.
OpenMW is distributed as free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 3, as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see
http://www.gnu.org/licenses/ .
*/
module bsa.bsafile;
//debug=checkHash;
// This file does not have any unit tests, since you really need the
// data to test it. Use the program named 'bsatool', it uses the NIF
// reader library and scans through a bsa archive, providing a good
// test of both libraries.
//import std.stream;
import std.stdio;
import std.string;
import std.mmfile;
import core.memory;
import monster.util.aa;
class BSAFileException : Exception
{
this(char[] msg) {super("BSAFileException: " ~ msg);}
}
/**
* This class is used to read "Bethesda Archive Files", or BSAs.
*
* The BSA archives are typically held open for the entire lifetime of
* the application, and are accessed more or less randomly. For that
* reason the BSAFile class uses memory mapped files. However, to be
* reasonably memory efficient, only the last requested file is
* guaranteed to be mapped at any given time, therefore make sure you
* don't use any persistant slices.
*
*/
class BSAFile
{
private:
// Size of the blocks to map with the memory mapped file. If set to
// 0, we map the entire file, but then we use a LOT of system
// memory. There is really no penalty in setting it too small, since
// multiple blocks may be mapped simultaneously. However, it MUST be
// a multiple of the system page size. TODO: On my system it is 4K,
// later on I will have to call getpagesize and the windows
// equivalent to find this (include the word "granularity" when you
// google for it.) For now I just assume 4K is ok on UNIX, but on
// Windows we need 64K. (Hands up if you agree that MMFile should
// handle this internally!). UPDATE: This is now duplicated in
// util.c_mmfile, if we make it more fancy we should collect it in
// one place.
version(Windows)
static int pageSize = 64*1024;
else
static int pageSize = 4*1024;
// Represents one file entry in the archive
struct FileStruct
{
// File size and offset in file. We store the offset from the
// beginning of the file, not the offset into the data buffer
// (which is what is stored in the archive.)
uint fileSize, offset;
char[] name;
void getName(char[] buf, uint start)
{
if(start >= buf.length)
throw new BSAFileException("Name offset outside buffer");
uint end = start;
// We have to search for the end of the name string, marked by a zero.
for(; end<buf.length; end++)
if(buf[end] == 0) break;
if(end == buf.length)
throw new BSAFileException("String buffer overflow");
name = buf[start..end];
}
// This currently isn't needed, but it would be if we wanted to
// write our own bsa archives.
debug(checkHash)
{
void hashName(out uint hash1, out uint hash2)
{
uint sum, off, temp, n;
foreach(char c; name[0..$/2])
{
sum ^= (cast(uint)c) << (off & 31);
off += 8;
}
hash1 = sum;
sum = off = 0;
foreach(char c; name[$/2..$])
{
temp = (cast(uint)c) << (off & 31);
sum ^= temp;
n = temp & 0x1F;
sum = (sum << (32-n)) | (sum >> n); // "rotate right" operation
off += 8;
}
hash2 = sum;
}
}
}
MmFile mmf; // Handle to memory mapped file
char[] filename; // File name
FileStruct files[]; // The file table is stored here
bool isLoaded; // Set to true if a file has been loaded
// An AA for fast file name lookup. The CITextHash is a
// case-insensitive text hasher, meaning that all lookups are case
// insensitive.
HashTable!(char[], int, ESMRegionAlloc, CITextHash) lookup;
void fail(char[] msg)
{
throw new BSAFileException(msg ~ "\nFile: " ~ filename);
}
void read()
{
/*
* The layout of a BSA archive is as follows:
*
* - 12 bytes header, contains 3 ints:
* id number - equal to 0x100
* dirsize - size of the directory block (see below)
* numfiles - number of files
*
* ---------- start of directory block -----------
*
* - 8 bytes*numfiles, each record contains
* fileSize
* offset into data buffer (see below)
*
* - 4 bytes*numfiles, each record is an offset into the following name buffer
*
* - name buffer, indexed by the previous table, each string is
* null-terminated. Size is (dirsize - 12*numfiles).
*
* ---------- end of directory block -------------
*
* - 8*filenum - hast table block, we currently ignore this
*
* Data buffer:
*
* - The rest of the archive is file data, indexed by the
* offsets in the directory block. The offsets start at 0 at
* the beginning of this buffer.
*
*/
assert(!isLoaded);
ulong fsize = mmf.length;
if( fsize < 12 )
fail("File too small to be a valid BSA archive");
// Recast the file header as a list of uints
uint[] array = cast(uint[]) mmf[0..12];
if(array[0] != 0x100)
fail("Unrecognized BSA header");
// Total number of bytes used in size/offset-table + filename
// sections.
uint dirsize = array[1];
debug writefln("Directory size: ", dirsize);
// Number of files
uint filenum = array[2];
debug writefln("Number of files: ", filenum);
// Each file must take up at least 21 bytes of data in the
// bsa. So if files*21 overflows the file size then we are
// guaranteed that the archive is corrupt.
if( (filenum*21 > fsize -12) ||
(dirsize+8*filenum > fsize -12) )
fail("Directory information larger than entire archive");
// Map the entire directory (skip the hashes if we don't need them)
debug(checkHash)
void[] mm = mmf[12..(12+dirsize+8*filenum)];
else
void[] mm = mmf[12..(12+dirsize)];
// Allocate the file list from esmRegion
files = esmRegion.allocateT!(FileStruct)(filenum);
// Calculate the offset of the data buffer. All file offsets are
// relative to this.
uint fileDataOffset = 12 + dirsize + 8*filenum;
// Get a slice of the size/offset table
array = cast(uint[])mm[0..(8*filenum)];
int index = 0; // Used for indexing array[]
// Read the size/offset table
foreach(ref FileStruct fs; files)
{
fs.fileSize = array[index++];
fs.offset = array[index++] + fileDataOffset;
if(fs.offset+fs.fileSize > fsize) fail("Archive contains files outside itself");
}
// Get a slice of the name offset table
array = cast(uint[])mm[(8*filenum)..(12*filenum)];
// Get a slice of the name field
char[] nameBuf = cast(char[])mm[(12*filenum)..dirsize];
// And copy it!
nameBuf = esmRegion.copy(nameBuf);
// Tell the lookup table how big it should be
lookup.rehash(filenum);
// Loop through the name offsets and pick out the names
foreach(int idx, ref FileStruct fs; files)
{
fs.getName(nameBuf, array[idx]);
lookup[fs.name] = idx;
debug(2) writefln("%d: %s, %d bytes at %x", idx,
fs.name, fs.fileSize, fs.offset);
}
// Code to check if file hashes are correct - this was mostly
// used to check our hash algorithm.
debug(checkHash)
{
// Slice the Hash table
array = cast(uint[])mm[dirsize..(dirsize+8*filenum)];
index = 0;
foreach(ref FileStruct fs; files)
{
uint h1, h2;
fs.hashName(h1,h2);
uint h11 = array[index++];
uint h22 = array[index++];
if(h1 != h11) writefln("1 : %d vs. %d", h1, h11);
if(h2 != h22) writefln("2 : %d vs. %d", h2, h22);
}
}
isLoaded = true;
}
public:
/* -----------------------------------
* BSA management methods
* -----------------------------------
*/
this() {}
this(char[] file) {open(file);}
// We should clean up after us
~this() {clear();}
// Open a new file. Clears any existing data
void open(char[] file)
{
clear();
filename = file;
// Open a memory mapped file
mmf = new MmFile(
file, // File name
MmFile.Mode.Read, // Read only
0, // We need the entire file
null, // Don't care where it is mapped
pageSize); // DON'T map the entire file, uses
// too much memory.
// Load header and file directory
read();
}
// Clear all data and close file
void clear()
{
delete mmf;
lookup.reset;
files.length = 0;
isLoaded = false;
}
/* -----------------------------------
* Archive file routines
* -----------------------------------
*/
void[] findSlice(int index)
{
if(!isLoaded)
fail("No archive is open");
if(index < 0 || index >= files.length)
fail("Index out of bounds");
//writefln("\noffset %d, filesize %d", files[index].offset, files[index].fileSize);
// Get a slice of the buffer that comprises this file
with(files[index])
return mmf[offset..offset+fileSize];
}
int getIndex(char[] name)
{
int i;
// Look it up in the AA
if( lookup.inList( name, i ) )
return i;
else
return -1;
}
// Return a slice. This routine converts the name to lower case,
// since all BSA file names are stored that way, but references to
// them in ESM/ESPs and NIFs are not.
void[] findSlice(char[] name)
{
int i = getIndex(name);
if(i == -1) return null;
return findSlice(i);
}
// Used by the 'bsatest' program to loop through the entire
// archive.
FileStruct[] getFiles() { return files; }
// Number of files in the archive
uint numFiles() { return files.length; }
// Gets the name of the archive file.
char[] getName() { return filename; }
}

@ -1,152 +0,0 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: http://openmw.snaptoad.com/
This file (bsatool.d) is part of the OpenMW package.
OpenMW is distributed as free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 3, as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see
http://www.gnu.org/licenses/ .
*/
module bsatool;
import std.stdio;
import bsa.bsafile;
import nif.nif;
import nif.niffile;
import core.memory;
void scanAllNifs(BSAFile f)
{
uint totSize;
BSAFile.FileStruct[] files = f.getFiles();
foreach(int ind, BSAFile.FileStruct file; files)
{
if(file.name[$-4..$] == ".nif" ||
file.name[$-3..$] == ".kf" )
{
void[] str = f.findSlice(ind);
totSize += str.length;
try nifMesh.open(str, file.name);
catch(NIFFileException e)
writefln("Got exception: %s", e);
}
}
writefln("Total NIF/KF size in this archive: ", totSize);
}
void dumpAllFiles(BSAFile f)
{
File o = new File();
auto files = f.getFiles();
foreach(int ind, file; files)
{
void[] s = cast(ubyte[]) f.findSlice(ind);
char[] name = file.name;
assert(s !is null);
name = getWinBaseName(name);
o.open(name, FileMode.OutNew);
o.writeExact(s.ptr, s.length);
o.close();
writefln("Wrote '%s'", name);
}
}
void listFiles(BSAFile f)
{
BSAFile.FileStruct[] files = f.getFiles();
foreach(BSAFile.FileStruct file; files)
writefln(file.name, " (%d bytes)", file.fileSize);
}
int main(char[][] args)
{
//*
int help(char[] msg)
{
writefln("%s", msg);
writefln("Format: bsatool archive.bsa [-x filename] [-l] [-n] [-xa]");
writefln(" -x filename extract file");
writefln(" -xa extract everything");
writefln(" -l list all files");
writefln(" -n scan through all nifs");
return 1;
}
if(args.length < 3) return help("Insufficient arguments");
initializeMemoryRegions();
char[] filename, ext;
bool list, nifs, extract, dumpAll;
foreach(char[] a; args[1..$])
if(a == "-l") list = true;
else if(a == "-n") nifs = true;
else if(a == "-x") extract = true;
else if(a == "-xa") dumpAll = true;
else if(extract && ext == "") ext = a;
else if(filename == "") filename = a;
else return help("Unknown option " ~ a);
if(filename == "") return help("No file specified");
auto BSAFile f = new BSAFile(filename);
if(list) listFiles(f);
if(nifs) scanAllNifs(f);
if(dumpAll) dumpAllFiles(f);
if(extract)
{
if(ext == "") return help("No file to extract");
void[] s = cast(ubyte[]) f.findSlice(ext);
if(s.ptr == null)
{
writefln("File '%s' not found in '%s'", ext, filename);
return 1;
}
ext = getWinBaseName(ext);
File o = new File(ext, FileMode.OutNew);
o.writeExact(s.ptr, s.length);
o.close();
writefln("File extracted to '%s'", ext);
}
//din.readLine();
return 0;
}
// Picks out part of a string after the last '\'.
char[] getWinBaseName(char[] input)
{
uint i;
for(i = input.length; i > 0; i--)
if(input[i-1] == '\\') break;
return input[i..$];
}
//import std.cstream;

@ -1,51 +0,0 @@
###########################
# Main program #
###########################
[openmw.d]
# Add libraries and the two C++ object files
buildflags = -llmygui -llOgreMain -llopenal -llOIS -lluuid -llavcodec -llavformat cpp_ogre.o cpp_avcodec.o cpp_bullet.o bullet/libbulletdynamics.a bullet/libbulletcollision.a bullet/libbulletmath.a
# Make sure the C++ object files are built first
version(Windows) {
prebuild = warn Not designed for Windows yet.
}
version(Posix) {
prebuild = make cpp;
}
# Make sure we recompile the nif files without the debug output
prebuild += dsss clean niftool
###########################
# Bsa inspection tool #
###########################
[bsatool.d]
###########################
# Esm inspection tool #
###########################
[esmtool.d]
# Because of interdepencies between the ESM code and the resource
# manager, we have to include all the C++ stuff.
buildflags = -llmygui -llOgreMain -llopenal -llOIS -lluuid -llavcodec -llavformat cpp_ogre.o cpp_avcodec.o cpp_bullet.o bullet/libbulletdynamics.a bullet/libbulletcollision.a bullet/libbulletmath.a
###########################
# Nif inspection tool #
###########################
[niftool.d]
buildflags = -debug=warnstd -debug=check -debug=statecheck -debug=strict -debug=verbose
# Clean the nif object files to make sure they are recompiled in debug mode
prebuild = dsss clean niftool
[bored.d]

@ -1,63 +0,0 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: http://openmw.snaptoad.com/
This file (niftool.d) is part of the OpenMW package.
OpenMW is distributed as free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 3, as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see
http://www.gnu.org/licenses/ .
*/
module niftool;
import nif.nif;
import nif.niffile;
import std.stdio;
import std.utf;
int main(char[][] args)
{
if(args.length < 2)
{
writefln("You must specify a file");
return 1;
}
initializeMemoryRegions();
bool errors;
foreach(char[] fn; args[1..$])
{
writefln("Opening %s", fn);
try nifMesh.open(fn);
catch(NIFFileException e)
{
writefln("Got exception: %s", e);
errors = true;
}
catch(UtfException e)
{
writefln("Got an UTF-error: %s", e);
writefln("We have to ignore the rest of the file at this point. If you want to");
writefln("test the entire file, compile the NIF lib without verbose output.");
}
nifMesh.clear();
writefln();
}
if(errors) return 1;
return 0;
}

@ -1,158 +0,0 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: http://openmw.snaptoad.com/
This file (cpp_bsaarchive.cpp) is part of the OpenMW package.
OpenMW is distributed as free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 3, as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
version 3 along with this program. If not, see
http://www.gnu.org/licenses/ .
*/
// This file inserts an archive manager for .bsa files into the ogre
// resource loading system. It uses callbacks to D to interact with
// the D-based bsa handling code. The D bindings are in
// core/resource.d.
// Callbacks to D code
// Does the file exist in the archives?
extern "C" int32_t d_bsaExists(const char *filename);
// Open a file. Return the pointer and size.
extern "C" void d_bsaOpenFile(const char *filename,
void **retPtr, uint32_t *retSize);
// This archive does not cover one .bsa file, instead it interacts
// with the all the loaded bsas and treates them as one archive.
class BSAArchive : public Archive
{
public:
BSAArchive(const String& name)
: Archive(name, "BSA") {}
~BSAArchive() {}
bool isCaseSensitive(void) const { return false; }
// The archives are already loaded in D code, and they are never
// unloaded. Just ignore these.
void load() {}
void unload() {}
// Open a file in the archive. We delegate the function to D-code.
DataStreamPtr open(const String& filename) const
{
//std::cout << "open(" << filename << ")\n";
void *ptr;
uint32_t size;
// Open the file. The BSA archives are memory mapped, D code
// returns a pointer and a file size.
d_bsaOpenFile(filename.c_str(), &ptr, &size);
return DataStreamPtr(new MemoryDataStream(ptr, size));
}
// This is never called as far as I can see.
StringVectorPtr list(bool recursive = true, bool dirs = false)
{
std::cout << "list(" << recursive << ", " << dirs << ")\n";
StringVectorPtr ptr = StringVectorPtr(new StringVector());
return ptr;
}
// Also never called.
FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false)
{
std::cout << "listFileInfo(" << recursive << ", " << dirs << ")\n";
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList());
return ptr;
}
time_t getModifiedTime(const String&) { return 0; }
// After load() is called, find("*") is called once. It doesn't seem
// to matter that we return an empty list, exists() gets called on
// the correct files anyway.
StringVectorPtr find(const String& pattern, bool recursive = true,
bool dirs = false)
{
//std::cout << "find(" << pattern << ", " << recursive
// << ", " << dirs << ")\n";
StringVectorPtr ptr = StringVectorPtr(new StringVector());
return ptr;
}
// Gets called once for each of the ogre formats, *.program,
// *.material etc. It's also called by MyGUI to find textures, so we
// have to channel it through exists().
FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true,
bool dirs = false)
{
/*
std::cout << "findFileInfo(" << pattern << ", " << recursive
<< ", " << dirs << ")\n";
*/
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList());
// Check if the file exists (only works for single files - wild
// cards and recursive search isn't implemented.)
if(exists(pattern))
{
FileInfo fi;
fi.archive = this;
fi.filename = pattern;
fi.path = "";
// It apparently doesn't matter that we return bogus
// information
fi.compressedSize = fi.uncompressedSize = 0;
ptr->push_back(fi);
}
return ptr;
}
// Check if the file exists.
bool exists(const String& filename)
{
//std::cout << "exists(" << filename << ")\n";
return d_bsaExists(filename.c_str()) != 0;
}
};
// An archive factory for BSA archives
class BSAArchiveFactory : public ArchiveFactory
{
public:
virtual ~BSAArchiveFactory() {}
const String& getType() const
{
static String name = "BSA";
return name;
}
Archive *createInstance( const String& name )
{
return new BSAArchive(name);
}
void destroyInstance( Archive* arch) { delete arch; }
};
BSAArchiveFactory mBSAFactory;
Loading…
Cancel
Save