Author Topic: Hak Reading and Writing?  (Read 2216 times)

Baaleos

  • Administrator
  • Hero Member
  • *****
  • Posts: 1916
  • Karma: +0/-0
Hak Reading and Writing?
« on: July 28, 2010, 08:08:10 pm »


               Does anyone know any open source projects where the application can read and write content into hak files?

I currently have a content downloader, used by my players to download sounds and bmu's, but It would be beneficial for me, to learn how to pack these into a hak file on the clients PC via c#.

I'd like to look at some source examples of how to pack content into a hak, or even just reading from a hak via code.
               
               

               
            

Baaleos

  • Administrator
  • Hero Member
  • *****
  • Posts: 1916
  • Karma: +0/-0
Hak Reading and Writing?
« Reply #1 on: July 28, 2010, 08:52:25 pm »


               Nevermind, Discovered that the OEIShared.dll that apparently comes with NWN2, has hak reading and writing functions inside it.



Not exactly revealing the source code etc, but it will do.

Wonder if I can embed the OEIShared.dll in my application, and have it still run?
               
               

               
            

Legacy_Tarot Redhand

  • Hero Member
  • *****
  • Posts: 4165
  • Karma: +0/-0
Hak Reading and Writing?
« Reply #2 on: July 29, 2010, 12:20:49 am »


               Beware, the format of nwn2 hak files appears to be different to nwn1. I tried to open a nwn2 hak with nw.hak in nwn1's utils folder and it wouldn't read it at all.



TR
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Hak Reading and Writing?
« Reply #3 on: July 29, 2010, 12:48:21 am »


               A hak is just all the files packed into the same file with a header.  It is the boiware.  ERF file format. you can look at the file format to see how they are packed  



FOR DEVELOPERS main page



you will need to know the GFF format.



Documentation: GFF File Format





Documentation: ERF File Format
               
               

               
            

Baaleos

  • Administrator
  • Hero Member
  • *****
  • Posts: 1916
  • Karma: +0/-0
Hak Reading and Writing?
« Reply #4 on: July 29, 2010, 03:44:55 am »


               Odd.

There is an application called

hakpacker or something

Found the source on the vault.



While it is able to read and write nwn1 and nwn2 haks, when I copy the implimentation, it wrote a corrupted file inside the hak.




using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using OEIShared.IO.ERF;
using TaniTerrain;
using TaniWaterMill;

namespace ERFReader {
    public partial class ERFinder : Form {
        ERFFile myFile;
        bool loaded = false;
        bool messed = false;
        bool stripped = false;
        string[] cmdline;

        public ERFinder(string[] args) {
            InitializeComponent();
            cmdline = args;
        }
        private bool watermaps() {
            foreach (ListViewItem lvi in FileTable.Items)
                if (((ERFResource)lvi.Tag).ResourceType == 2062)
                    return true;
            return false;
        }
        private void updatebtns() {
            BTN_Open.Enabled = !loaded;
            BTN_New.Enabled = !loaded;
            BTN_Import.Enabled = loaded;
            BTN_Impor****er.Enabled = loaded && watermaps();
            BTN_StripMod.Enabled = loaded && (myFile.Filename.ToLower().EndsWith(".mod")) && !stripped;
            BTN_Export.Enabled = (FileTable.SelectedItems.Count > 0);
            BTN_Remove.Enabled = (FileTable.SelectedItems.Count > 0);
            if (loaded)
                BTN_Save.Enabled = (myFile.Filename != "") && messed && !stripped;
            else
                BTN_Save.Enabled = false;
            BTN_SaveAs.Enabled = loaded;
            BTN_Close.Enabled = loaded;
            cb_v10.Enabled = loaded;
            BTN_Exit.Enabled = true;

            if (loaded) {
                DateTime dt = new DateTime((int)(1900 + myFile.FileHeader.BuildYear), 1, 1);
                dt = dt.AddDays((double)myFile.FileHeader.BuildDay - 1.0);
                LBL_Status.Text = myFile.Filename + " [" + myFile.FileHeader.FileType + " " + myFile.FileHeader.FileVersion + "] " + myFile.Resources.Count + " files";
            } else
                LBL_Status.Text = "no file loaded";

        }
        private ListViewItem FileTableItem(ERFResource r) {
            ListViewItem l = new ListViewItem(new string[] { r.FullName.ToLower(), r.Extension.ToLower(), r.ResourceSize.ToString() });
            l.Text = r.FullName.ToLower();
            l.Name = r.FullName.ToLower();
            l.Tag = r;
            l.ToolTipText = r.FullName.ToLower() + " (" + r.ResourceSize.ToString() + " bytes)";
            return l;
        }
        private void updatelist() {
            FileTable.Items.Clear();
            if (loaded) {
                foreach (ERFResource r in myFile.Resources)
                    FileTable.Items.Add(FileTableItem(r));
            } else LBL_Status.Text = "";
            updatebtns();
        }
        private void LoadERF(string fn) {
            if (loaded) myFile.Dispose();
            try {
                myFile = new ERFFile(fn, true);
                messed = false;
                loaded = true;
                stripped = false;
                cb_v10.Checked = (myFile.FileHeader.Has16CharResrefs);
            } catch (Exception ex) {
                MessageBox.Show("file loading failed: " + ex.Message);
                myFile.Dispose();
                loaded = false;
                messed = false;
                stripped = false;
            }
            updatelist();
        }
        private void BTN_Open_Click(object sender, EventArgs e) {
            this.Enabled = false; // true;
            if (FileOpen.ShowDialog() == DialogResult.OK)
                LoadERF(FileOpen.FileName);
            this.Enabled = true;
        }
        string exportfolder = "";
        private void BTN_Export_Click(object sender, EventArgs e) {
            this.Enabled = false; // true;
            try {
                if (exportfolder != "")
                    Folder.SelectedPath = exportfolder;
                if (loaded)
                    if (Folder.ShowDialog() == DialogResult.OK) {
                        foreach (ListViewItem lvi in FileTable.SelectedItems) {
                            ERFResource r = (ERFResource)lvi.Tag;
                            r.SaveData(Folder.SelectedPath + "\\\\" + r.FullName);
                        }
                        exportfolder = Folder.SelectedPath;
                    }
            } catch (Exception ex) {
                MessageBox.Show("ooops! something went wrong: " + ex.Message, "nasty bug detected!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            this.Enabled = true;
        }
        private ERFResource FileTableContains(string filename) {
            foreach (ListViewItem lvi in FileTable.Items)
                if (((ERFResource)lvi.Tag).FullName.ToLower() == filename.ToLower())
                    return (ERFResource)lvi.Tag;
            return null;
        }
        private void ResourceRemover(string fullname) {
            List<ERFResource> l = new List<ERFResource>();
            foreach (ERFResource r in myFile.Resources)
                if (fullname.ToLower().EndsWith(r.FullName.ToLower()))
                    l.Add(r);
            foreach (ERFResource r in l)
                myFile.Resources.Remove(r);
        }
        void importFiles(string[] names) {
            foreach (string f in names) {
                ERFResource newres = new ERFResource();
                newres.DiskFilename = f;
                if (FileTable.Items.Find(newres.FullName.ToLower(), false).Length > 0)
                    switch (MessageBox.Show("File already exists: " + newres.FullName + "n\\r\\n\\rStill import?", "file exists", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning)) {
                        case DialogResult.Yes:
                            ResourceRemover(f);
                            myFile.Resources.Add(newres);
                            messed = true;
                            break;
                        case DialogResult.Cancel:
                            return;
                    } else {
                    myFile.Resources.Add(newres);
                    messed = true;
                }
            }
            updatelist();

        }
        private void BTN_Import_Click(object sender, EventArgs e) {
            this.Enabled = false; // true;
            if (loaded) {
                if (FileImport.ShowDialog() == DialogResult.OK) {
                    importFiles(FileImport.FileNames);
                }
            }
            this.Enabled = true;
        }
        private void BTN_Save_Click(object sender, EventArgs e) {
            this.Enabled = false; // true;
            try {
                if (loaded && myFile.Filename != "") {
                    string fn = myFile.Filename;
                    FileStream fs = new FileStream(fn + ".tmp", FileMode.Create);
                    myFile.Save(fs);
                    fs.Seek(7, SeekOrigin.Begin);
                    if (cb_v10.Checked) {
                        fs.WriteByte(48);
                        fs.Seek(myFile.FileHeader.OffsetToKeyList, SeekOrigin.Begin);
                        byte[] buf = new byte[(32 + 4 + 4) * myFile.FileHeader.FileCount];
                        fs.Read(buf, 0, (int)((32 + 4 + 4) * myFile.FileHeader.FileCount));
                        fs.Seek(myFile.FileHeader.OffsetToKeyList, SeekOrigin.Begin);
                        for (int n = 0; n < myFile.FileHeader.FileCount; n++) {
                            fs.Write(buf, n * (32 + 4 + 4), 16);
                            fs.Write(buf, n * (32 + 4 + 4) + 32, 8);
                        }
                    } else {
                        fs.WriteByte(49);
                    }
                    fs.Close();
                    myFile.Dispose();
                    System.IO.File.Delete(fn);
                    System.IO.File.Move(fn + ".tmp", fn);
                    myFile = new ERFFile(fn, true);
                    messed = false;
                    stripped = false;
                    updatebtns();
                }
            } catch (Exception) {
                MessageBox.Show("An error occurred while saving.  Please check to see that the file is not already in use.");
            }
            this.Enabled = true;
        }
        private void BTN_Close_Click(object sender, EventArgs e) {
            this.Enabled = false; // true;
            if (loaded) {
                bool really = true;
                if (messed)
                    if (MessageBox.Show("you haven't saved your changes. really close?", "caution! unsaved changes!", MessageBoxButtons.OKCancel) != DialogResult.OK)
                        really = false;
                if (really) {
                    myFile.Dispose();
                    loaded = false;
                    messed = false;
                    stripped = false;
                    updatelist();
                }
            }
            this.Enabled = true;
        }
        private void BTN_SaveAs_Click(object sender, EventArgs e) {
            this.Enabled = false; // true;
            try {
                if (loaded)
                    if (FileSave.ShowDialog() == DialogResult.OK) {
                        string fn = FileSave.FileName.ToLower();
                        string dbk = "";
                        if (fn.EndsWith(".hak"))
                            dbk = "HAK ";
                        else if (fn.EndsWith(".erf"))
                            dbk = "ERF ";
                        else if (fn.EndsWith(".mod"))
                            dbk = "MOD ";
                        else if (fn.EndsWith(".pwc"))
                            dbk = "ERF ";
                        if (dbk == "")
                            MessageBox.Show("sorry, you must select either .hak, .erf, .mod or .pwc as an extension!", "unknown extension selected");
                        else {
                            myFile.FileHeader.FileType = dbk;
                            myFile.FileHeader.BuildYear = (uint)(DateTime.Now.Year - 1900);
                            myFile.FileHeader.BuildDay = (uint)DateTime.Now.DayOfYear;
                            FileStream fs = new FileStream(fn, FileMode.Create);
                            myFile.Save(fs);
                            if (cb_v10.Checked) {
                                fs.Seek(7, SeekOrigin.Begin);
                                fs.WriteByte(48);
                                fs.Seek(myFile.FileHeader.OffsetToKeyList, SeekOrigin.Begin);
                                byte[] buf = new byte[(32 + 4 + 4) * myFile.FileHeader.FileCount];
                                fs.Read(buf, 0, (int)((32 + 4 + 4) * myFile.FileHeader.FileCount));
                                fs.Seek(myFile.FileHeader.OffsetToKeyList, SeekOrigin.Begin);
                                for (int n = 0; n < myFile.FileHeader.FileCount; n++) {
                                    fs.Write(buf, n * (32 + 4 + 4), 16);
                                    fs.Write(buf, n * (32 + 4 + 4) + 32, 8);
                                }
                            } else {
                                fs.Seek(7, SeekOrigin.Begin);
                                fs.WriteByte(49);
                            }
                            fs.Close();
                            myFile.Filename = fn;
                            updatelist();
                        }
                    }
                messed = false;
                stripped = false;
            } catch (Exception ex) {
                MessageBox.Show("oooops! something went wrong: " + ex.Message, "nasty bug detected!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            updatebtns();
            this.Enabled = true;
        }
        private void BTN_exit_Click(object sender, EventArgs e) {
            bool really = true;
            if (loaded && messed)
                if (MessageBox.Show("you haven't saved your changes. really exit?", "caution! unsaved changes!", MessageBoxButtons.OKCancel) != DialogResult.OK)
                    really = false;
            if (really)
                this.Close();
        }
        private void BTN_NewHAK_Click(object sender, EventArgs e) {
            this.Enabled = false; // true;
            if (loaded) myFile.Dispose();
            myFile = new ERFFile();
            myFile.FileHeader.FileType = "??? ";
            myFile.FileHeader.BuildYear = (uint)(DateTime.Now.Year - 1900);
            myFile.FileHeader.BuildDay = (uint)DateTime.Now.DayOfYear;
            cb_v10.Checked = false;
            loaded = true;
            messed = false;
            stripped = false;
            updatelist();
            this.Enabled = true;
        }
        private void BTN_Remove_Click(object sender, EventArgs e) {
            this.Enabled = false; // true;
            if (loaded) {
                if (FileTable.SelectedItems.Count > 0)
                    messed = true;
                foreach (ListViewItem lvi in FileTable.SelectedItems)
                    myFile.Resources.Remove((ERFResource)lvi.Tag);
                updatelist();
            }
            this.Enabled = true;
        }
        private void ERFinder_Load(object sender, EventArgs e) {
            if (cmdline.Length > 0)
                LoadERF(cmdline[0]);
            else
                updatelist();
        }

        private void BTN_Impor****er_Click(object sender, EventArgs e) {
            this.Enabled = false; // true;
            if (loaded) {
                this.Enabled = false;
                List<ERFResource> watermaps = new List<ERFResource>();
                foreach (ERFResource watermap in myFile.Resources)
                    if (watermap.FullName.ToLower().EndsWith(".nwm"))
                        watermaps.Add(watermap);
                foreach (ERFResource watermap in watermaps) {
                    WaterMillArea wma = new WaterMillArea(new MemoryStream(watermap.Data));
                    string t = watermap.FullName.ToLower().Replace(".nwm", "");
                    List<ERFResource> found_resources = new List<ERFResource>();
                    foreach (ERFResource r in myFile.Resources)
                        if (r.FullName.ToLower() == t + ".trn" || r.FullName.ToLower() == t + ".trx")
                            found_resources.Add(r);
                    foreach (ERFResource found in found_resources) {
                        TaniTRN wm_trn = new TaniTRN();
                        wm_trn.Load(new MemoryStream(found.Data));
                        myFile.Resources.Remove(found);
                        wm_trn.WaterRemoveAll();
                        foreach (TaniWM wm in wma.layers)
                            if (wm.wm_selected)
                                foreach (TaniWATR tw in wm.lwaters)
                                    if (wm.wm_global_water) {
                                        tw.Move(wm.wm_move_x, wm.wm_move_y, wm.wm_raisewater);
                                        wm.ValuesToWATR(tw);
                                        if (tw.AdjustFlagsToTreshold(wm.wm_treshold))
                                            wm_trn.WaterAdd(tw);
                                    } else wm_trn.WaterAdd(tw);
                        MemoryStream ms = new MemoryStream();
                        BinaryWriter bw = new BinaryWriter(ms);
                        wm_trn.Save(bw);
                        found.Data = ms.ToArray();
                        myFile.Resources.Add(found);
                        messed = true;
                    }
                }
                updatebtns();
                this.Enabled = true;
            }
        }
        private int col = 0;
        private int updown = +1;
        private void listView1_ColumnClick(object sender, ColumnClickEventArgs e) {
            if (e.Column == col)
                updown *= -1;
            col = e.Column;
            FileTable.ListViewItemSorter = new ListViewItemComparer(e.Column, updown);
        }
        private void FileTable_SelectedIndexChanged(object sender, EventArgs e) {
            updatebtns();
        }

        private void BTN_StripMod_Click(object sender, EventArgs e) {
            int module_size = 0;
            int walkmesh_size = 0;
            int walkmesh_oversize = 0;
            this.Enabled = false; // true;
            if (loaded && (MessageBox.Show("attention!\\r\\n\\r\\nthis will remove all data which is not needed for running on a standalone server. after stripping you can no more edit this file in toolset or run it inside the game. do not save this module to the original file, unless you know exactly what you are doing - you might loose your work!\\r\\n\\r\\ndo you really want to continue?", "warning!", MessageBoxButtons.OKCancel) == DialogResult.OK)) {
                this.Enabled = false;
                List<ERFResource> remres = new List<ERFResource>();
                List<ERFResource> trxs = new List<ERFResource>();
                foreach (ERFResource r in myFile.Resources) {
                    if (r.FullName.ToLower().EndsWith(".trn") || r.FullName.ToLower().EndsWith(".nwm"))
                        remres.Add(r);
                    if (r.FullName.ToLower().EndsWith(".trx"))
                        trxs.Add(r);
                }
                foreach (ERFResource r in remres)
                    myFile.Resources.Remove(r);
                foreach (ERFResource r in trxs) {
                    TaniTRN trx = new TaniTRN();
                    trx.Load(new MemoryStream(r.Data));
                    myFile.Resources.Remove(r);
                    walkmesh_size += trx.m_cASWM.len_uncomp;
                    walkmesh_oversize += trx.m_cASWM.len_uncomp - trx.m_cASWM.len_comp;
                    MemoryStream ms = new MemoryStream();
                    BinaryWriter bw = new BinaryWriter(ms);
                    trx.SaveStripped(bw);
                    r.Data = ms.ToArray();
                    myFile.Resources.Add(r);
                    messed = true;
                    stripped = true;
                }
                foreach (ERFResource r in myFile.Resources)
                    module_size += (int)r.ResourceSize;
                int size_in_mem_min = 50 * 1024 * 1024 + 3 * walkmesh_size;
                int size_in_mem_max = 70 * 1024 * 1024 + 5 * walkmesh_size;
                MessageBox.Show("your module was stripped of all unneeded data, new size is " + ((int)(module_size / (1024 * 1024))).ToString() + " mb (" + module_size.ToString() + " bytes); but don't let the new, smaller size fool you: uncompressed walkmesh sums up to " + ((int)(walkmesh_size / (1024 * 1024))).ToString() + " mb (" + walkmesh_size.ToString() + " bytes), which must be loaded to memory! my best guess is that your module will use between " + ((int)((size_in_mem_min) / (1024 * 1024))).ToString() + " and " + ((int)((size_in_mem_max) / (1024 * 1024))).ToString() + " mb in memory.", "stripping done");
                updatelist();
            }
            this.Enabled = true;
        }

        private void OnDragEnter(object sender, DragEventArgs e) {
            e.Effect = DragDropEffects.Copy;
        }

        private void OnDragDrop(object sender, DragEventArgs e) {
            importFiles((string[])e.Data.GetData(DataFormats.FileDrop));
            updatelist();
        }

        private void OnItemDrag(object sender, ItemDragEventArgs e) {
            //string color = strTables;
            if (FileTable.SelectedItems.Count == 0)
                return;

            List<String> files = new List<String>();
            String temp = System.IO.Path.GetTempPath();
            foreach (ListViewItem lvi in FileTable.SelectedItems) {
                ERFResource r = (ERFResource)lvi.Tag;
                r.SaveData(temp + r.FullName);
                files.Add(temp + r.FullName);
            }
            // WriteFile(fileName, sbCSV);
            string[] list = files.ToArray();
            DataObject data = new DataObject(DataFormats.FileDrop, files.ToArray());
            FileTable.DoDragDrop(data, DragDropEffects.Move);
        }

        private void OnQueryContinueDrag(object sender, QueryContinueDragEventArgs e) { }
        private void OnMouseClick(object sender, MouseEventArgs e) {}
        private void BTN_selall_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem lvi in FileTable.Items)
                lvi.Selected = true;
        }

        private void BTN_selnone_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem lvi in FileTable.Items)
                lvi.Selected = false;
        }

        private void BTN_selinvert_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem lvi in FileTable.Items)
                lvi.Selected = !lvi.Selected;
        }

    }
    class ListViewItemComparer : System.Collections.IComparer {
        private int col;
        private int updown;
        public ListViewItemComparer(int column, int up) {
            col = column;
            updown = up;
        }
        public int Compare(object x, object y) {
            switch (col) {
                case 2:
                    return updown * ((int)(((ERFResource)((ListViewItem)x).Tag).ResourceSize - ((ERFResource)((ListViewItem)y).Tag).ResourceSize));
                default:
                    return updown * (String.Compare(((ListViewItem)x).SubItems[col].Text, ((ListViewItem)y).SubItems[col].Text));
            }
        }
    }


}

               
               

               
            

Legacy_pkpeachykeen

  • Jr. Member
  • **
  • Posts: 89
  • Karma: +0/-0
Hak Reading and Writing?
« Reply #5 on: July 30, 2010, 02:05:08 am »


               I have source of a (mostly) working HAK/ERF/etc reader/writer I worked up a while ago. It has a few rough corners that need polished, but gives a pretty simple interface to loading and working with such files from C#. I can post source links if the above isn't what you need.
               
               

               
            

Baaleos

  • Administrator
  • Hero Member
  • *****
  • Posts: 1916
  • Karma: +0/-0
Hak Reading and Writing?
« Reply #6 on: July 30, 2010, 04:13:18 am »


               If what you have is alot more simple to use, then by all means I would love it.



Basically, the plan on what I hope to create is

1. My program will open a hak

2. Save the contents to a tmp folder

3. Overwrite the contents with the new updated content

4. Pack the contents back into the hak

5. Save the hak.



I tried that with the source above, but I think the bits I left out, was the streamwriter bits where it writes a header to each file. I couldnt be bothered writing a wrapper for it, to do it for each file....
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Hak Reading and Writing?
« Reply #7 on: July 30, 2010, 05:19:53 am »


               BTW Anyone ever messed with bif files? I would appreciate any kind of source for that '<img'>.
               
               

               


                     Modifié par ShaDoOoW, 30 juillet 2010 - 04:20 .
                     
                  


            

Legacy_The Fred

  • Newbie
  • *
  • Posts: 46
  • Karma: +0/-0
Hak Reading and Writing?
« Reply #8 on: July 30, 2010, 10:37:43 am »


               I think BIFs are the same as ERFs and HAKs, though I forget. I'm going to look into them soon myself for my own current project, as it happens.
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Hak Reading and Writing?
« Reply #9 on: July 30, 2010, 11:16:51 am »


               BIF's are different.  they have there headder in the .KEY  file.
               
               

               
            

Baaleos

  • Administrator
  • Hero Member
  • *****
  • Posts: 1916
  • Karma: +0/-0
Hak Reading and Writing?
« Reply #10 on: July 30, 2010, 02:19:18 pm »


               The DLL that comes with nwn2, I believe it contains some BIF functions.



It had alot of functions regarding nwn1 and nwn2 content.

I remember seeing BIF mentioned in the function names I think.
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Hak Reading and Writing?
« Reply #11 on: July 30, 2010, 11:08:53 pm »


               When you start messing with the BIF's, Keep in mind that you are dealing with the OC content.  Just because something is in a BIF does not mean it is still being used by the game.  They have a hierarchy to them like the haks.  



It may be good to mention here that a .key file is the index into a BIF.  I do not think the Bif even contains the name of the file. (unless it is in the file somewhere).  



Here is the way I visualize the loading of resources used by the game.  



I see a new freshly created folder.  



into this folder I copy all the content from   chitin.key (the OC)

then I copy into that  folder all the content from xp1.key (first patch)



Any of the files that have the same name get automatically overwritten.



then we copy in the next three key files.



xp2.key

xp2patch.key

xp3.key



After the .key files are copied to the folder the Contents of the module file is the copied in.  Still overwriting any file with the same name.  



Then the Override folder followed by the HAKs starting with the lowest one on the list first.



And that is how I visualize what my final list of resources is.



Sorry, if this is a little to far off topic.  



               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Hak Reading and Writing?
« Reply #12 on: July 31, 2010, 07:15:52 am »


               

Lightfoot8 wrote...

I do not think the Bif even contains the name of the file. (unless it is in the file somewhere).

Yes they contain name, but not extension.

BIF has lowest priority so I don't know The Fred what purpose you want to use it. Its however exactly what I need for my project.
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Hak Reading and Writing?
« Reply #13 on: August 01, 2010, 08:50:58 pm »


               

ShaDoOoW wrote...

Lightfoot8 wrote...

I do not think the Bif even contains the name of the file. (unless it is in the file somewhere).

Yes they contain name, but not extension.

BIF has lowest priority so I don't know The Fred what purpose you want to use it. Its however exactly what I need for my project.



I think you missunderstood,


The name of the file in not contained in the BIF.  Only the data of the file is in the Bif.  The Inxex of the file names for the data in the Bif file is in the .key  file.   inorer to find the data for a file name you first have to look up its name in the key file. the Key file then tell you where in the bif file the data is located.

edit:
you can check the Key and BIF File Formats  at  http://nwn.bioware.com/developers/
               
               

               


                     Modifié par Lightfoot8, 01 août 2010 - 07:54 .
                     
                  


            

Legacy_Calvinthesneak

  • Hero Member
  • *****
  • Posts: 1159
  • Karma: +0/-0
Hak Reading and Writing?
« Reply #14 on: August 03, 2010, 04:45:27 am »


               

Baaleos wrote...

If what you have is alot more simple to use, then by all means I would love it.

Basically, the plan on what I hope to create is
1. My program will open a hak
2. Save the contents to a tmp folder
3. Overwrite the contents with the new updated content
4. Pack the contents back into the hak
5. Save the hak.

I tried that with the source above, but I think the bits I left out, was the streamwriter bits where it writes a header to each file. I couldnt be bothered writing a wrapper for it, to do it for each file....



Maybe talk to the folk from CEP and/or someone who's made an Rsync updater to work with haks.  What it should do is maintain a manifest of hak contents and compare them, if there is new files it downloads those and extracts them into the hak container.  Maybe it works by creating a tmp folder but that seems a bit of a waste of overhead.  The manifest could probably simply be a small text file, I'm not really sure what's possible there, I don't know enough of the technical details of GFF and ERF.