rendered paste bodyusing 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");
}
}
}