All pastes #382326 Raw Edit

NBHDump

public text v1 · immutable
·published 2007-03-05 15:04 UTC
rendered paste body
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.IO;

namespace NBHDump
{
    class NBHDumper
    {
        protected byte[] romtype = null;
        public int headerblock, signerblock;
        public int[] roms, romsaddr, romssize;
        public byte headerflag;
        public bool ArrayEquals(byte[] a, byte[] b) //Dear Microsoft: add a fucking Array compare function
        {
            if (a.Length != b.Length)
                return false;
            for (int i = 0; i < a.Length; i++)
            {
                if (a[i] != b[i])
                    return false;
            }
            return true;
        }
        protected int StreamtoInt(byte[] arr)
        {
            return (arr[0] + (arr[1] * 0x100) + (arr[2] * 0x10000) + (arr[3] * 0x1000000));
        }
        protected FileStream f_nbh;
        public NBHDumper(string thenbh)
        {
            f_nbh = new FileStream(thenbh,FileMode.Open,FileAccess.Read);
        }
        byte[] headersig = new byte[7] {82, 48, 48, 48, 70, 70, 10};
        
        protected int readheader()
        {
            byte[] retval = new byte[4];
            f_nbh.Read(retval, 0, 4);
            return StreamtoInt(retval);
        }

        protected int[] readnbtypes()
        {
            romtype = new byte[4];
            ArrayList arr = new ArrayList();
            for(int i = 0; i < 32; i++)
            {
                f_nbh.Read(romtype,0,4);
                if (StreamtoInt(romtype) != 0)
                    arr.Add(StreamtoInt(romtype));
            }
            roms = new int[arr.Count];
            arr.CopyTo(roms);
            return roms;
        }
        protected int[] readnbaddr()
        {
            byte[] romaddr = new byte[4];
            ArrayList arr = new ArrayList();
            for (int i = 0; i < 32; i++)
            {
                f_nbh.Read(romaddr, 0, 4);
                if (StreamtoInt(romaddr) != 0 && i < this.roms.Length)
                    arr.Add(StreamtoInt(romaddr)+32);
            }
            romsaddr = new int[arr.Count];
            arr.CopyTo(romsaddr);
            return romsaddr;
        }
        protected int[] readnbsize()
        {
            byte[] romsize = new byte[4];
            ArrayList arr = new ArrayList();
            for (int i = 0; i < 32; i++)
            {
                f_nbh.Read(romsize, 0, 4);
                if (StreamtoInt(romsize) != 0 && i < roms.Length)
                {
                    arr.Add(StreamtoInt(romsize));
                }
            }
            romssize = new int[arr.Count];
            arr.CopyTo(romssize);
            return romssize;
        }
        public int[] romstemp, romssyze;
        public long[] sigspots = null;
        int[] getsigssize()
        {
            long remember = f_nbh.Position;
            romstemp = new int[romsaddr.Length];
            romstemp = romsaddr;
            romssyze = new int[romssize.Length];
            romssyze = romssize;
            ArrayList sigspts = new ArrayList();
            f_nbh.Seek(23, SeekOrigin.Begin);
            int flag = 0;
            //long total = 0;
            byte[] block = new byte[4], sign = new byte[4];
            int g = 0;
            while (flag != 2)
            {
                long place2 = f_nbh.Position;
                
                f_nbh.Read(block, 0, 4);
                f_nbh.Read(sign, 0, 4);
                flag = f_nbh.ReadByte();
                f_nbh.Seek(StreamtoInt(block) + StreamtoInt(sign), SeekOrigin.Current);
                long place = f_nbh.Position;
                if (StreamtoInt(sign) == 128)
                {
                    sigspts.Add(place);
                    for (int i = 1; i < romstemp.Length; i++)
                    {
                        if (place2 < (romstemp[i] + romssyze[i]) && place2 > romstemp[i])
                            romssyze[i] += 137;
                        if (place < romstemp[i])
                            romstemp[i] += 137;
                        
                    }  
                }
                g++;
            }
            for(int i = 0;i < romssyze.Length;i++)
                romssyze[i] += romstemp[i]-1;
            if((romssyze[0]+1) != romstemp[1])
                romssyze[0] = romstemp[1] - 1;
            f_nbh.Seek(remember, SeekOrigin.Begin);
            sigspots = new long[sigspts.Count];
            sigspts.CopyTo(sigspots);
            return romstemp;
        }
        public string romtypetoname(int Romval)
        {
            if (Romval == 256)
                return "00_IPL.nb";
            if (Romval == 512)
                return "01_SPL.nb";
            if (Romval == 768)
                return "03_GSM.nb";
            if (Romval == 1024)
                return "04_OS.nb";
            if (Romval == 1536)
                return "05_MainSplash.nb";
            if (Romval == 1537)
                return "06_SubSplash.nb";
            if (Romval == 1792)
                return "07_ExtROM.nb";
            return "Unknown.nb";
        }
        public void donbjob()
        {
            long dss;
            byte[] writer;
            byte[] signat = new byte[4];
            byte[] blocks = new byte[4];
            FileStream f_nb;
            for (int i = 0; i < romstemp.Length; i++)
            {
                f_nb = new FileStream(romtypetoname(roms[i]),FileMode.OpenOrCreate,FileAccess.ReadWrite);
                Console.Out.WriteLine("Extracting: " +romtypetoname(roms[i]));
                f_nbh.Seek(romstemp[i], SeekOrigin.Begin);
                while(f_nbh.Position < romssyze[i])
                {
                    if ((f_nbh.Position + 65536) > romssyze[i])
                    {
                        if((dss = SigbetweenFiles(((long)romssyze[i]))) != 0)
                        {
                            writer = new byte[((int)(dss - (f_nbh.Position + 128)))];
                            f_nbh.Read(writer, 0, ((int)(dss - (f_nbh.Position + 128))));
                            f_nb.Write(writer, 0, writer.Length/*((int)(dss - (f_nbh.Position + 128)))*/);
                            f_nb.Flush();
                        }
                        else 
                        {
                            writer = new byte[((int)(romssyze[i]+1 - f_nbh.Position))];
                            f_nbh.Read(writer, 0, ((int)(romssyze[i]+1 - f_nbh.Position)));
                            f_nb.Write(writer, 0, writer.Length/*((int)(romssyze[i]+1 - f_nbh.Position))*/);
                            f_nb.Flush();
                        }
                    }
                    else if ((dss = SigbetweenFiles((f_nbh.Position + 65536))) != 0)
                    {
                        writer = new byte[((int)(dss - (f_nbh.Position+128)))];
                        f_nbh.Read(writer, 0, ((int)(dss - (f_nbh.Position+128))));
                        f_nb.Write(writer, 0, writer.Length/*((int)(dss - (f_nbh.Position + 128)))*/);
                        f_nb.Flush();
                        
                    }
                    else
                    {
                        writer = new byte[65536];
                        f_nbh.Read(writer, 0, 65536);
                        f_nb.Write(writer, 0, writer.Length);
                        f_nb.Flush();
                    }
                    f_nbh.Seek(137, SeekOrigin.Current);
                }
                f_nb.Flush();
                f_nb.Close();
                f_nb = null;
            }
            Console.Out.WriteLine("Done!");
        }
        public long SigbetweenFiles(long val)
        {
            for (int i = 0; i < sigspots.Length; i++)
            {
                if (sigspots[i] > f_nbh.Position && sigspots[i] < val)
                    return sigspots[i];
            }
            return 0;
        }
        public void CloseFile()
        {
            f_nbh.Close();
        }
        public void readheaders() //This is essentially the main part of the class
        {
            byte[] headercheck = new byte[7];
            byte[] htcimage = new byte[32];
            int headerflag;
            f_nbh.Read(headercheck, 0, 7);
            if(!ArrayEquals(headercheck,headersig))
                errorcodes(2);
            f_nbh.Seek(23,SeekOrigin.Begin);
            headerblock = readheader();
            signerblock = readheader();
            headerflag = f_nbh.ReadByte();
            f_nbh.Read(htcimage, 0, 32);
            Console.Out.WriteLine("ImageType: " + Encoding.UTF32.GetString(htcimage));
            f_nbh.Read(htcimage, 0, 32);
            Console.Out.WriteLine("Device: " + Encoding.ASCII.GetString(htcimage));
            readnbtypes(); //these bastards could be in this function but I moved them out for my benefit.
            readnbaddr();
            readnbsize();
            getsigssize();
            donbjob();
        }
        void errorcodes(int errors)
        {
            if (errors == 2)
                throw new Exception("Error: File is not an NBH");
        }   
    }
}