mirror of
https://github.com/chev2/botw-toolset.git
synced 2025-10-30 08:12:17 +00:00
Update TSCB methods
FromBytes replaces ReadFile & uses a byte array instead of filename. GetBytes is renamed to ToBytes.
This commit is contained in:
parent
6d6e9f4749
commit
f19f94f459
2 changed files with 132 additions and 139 deletions
|
|
@ -306,7 +306,7 @@ namespace BOTWToolset.Control
|
|||
|
||||
BOTWConsole.Log("Opening file");
|
||||
|
||||
TSCB t = TSCB.ReadFile(openFileDialog.FileName);
|
||||
TSCB t = TSCB.FromBytes(File.ReadAllBytes(openFileDialog.FileName));
|
||||
|
||||
// Set the current file location to the chosen file's location
|
||||
fileLocation = openFileDialog.FileName;
|
||||
|
|
@ -365,7 +365,7 @@ namespace BOTWToolset.Control
|
|||
|
||||
if ((bool)saveFileDialog.ShowDialog())
|
||||
{
|
||||
File.WriteAllBytes(saveFileDialog.FileName, TSCB.GetBytes(currentTSCB));
|
||||
File.WriteAllBytes(saveFileDialog.FileName, TSCB.ToBytes(currentTSCB));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,168 +52,161 @@ namespace BOTWToolset.IO.TSCB
|
|||
/// </summary>
|
||||
/// <param name="file">The .tscb file.</param>
|
||||
/// <returns></returns>
|
||||
public static TSCB ReadFile(string file)
|
||||
public static TSCB FromBytes(byte[] bytes)
|
||||
{
|
||||
if (File.Exists(file))
|
||||
TSCB t = new TSCB();
|
||||
|
||||
// Use big-endian
|
||||
using (var r = new BinaryReaderBig(new MemoryStream(bytes)))
|
||||
{
|
||||
TSCB t = new TSCB();
|
||||
// Set header info from file on the new TSCBInfo
|
||||
t.Signature = new string(r.ReadChars(4));
|
||||
t.Version = r.ReadByte();
|
||||
|
||||
// Use big-endian
|
||||
using (var r = new BinaryReaderBig(File.Open(file, FileMode.Open)))
|
||||
// Skip the 3 extra version bytes
|
||||
r.BaseStream.Seek(3, SeekOrigin.Current);
|
||||
|
||||
// Skip 4 bytes of "00 00 00 01"
|
||||
r.BaseStream.Seek(4, SeekOrigin.Current);
|
||||
|
||||
t.FileBaseOffset = r.ReadUInt32();
|
||||
t.WorldScale = r.ReadSingle();
|
||||
t.TerrainMaxHeight = r.ReadSingle();
|
||||
t.MaterialInfoLength = r.ReadUInt32();
|
||||
t.AreaArrayLength = r.ReadUInt32();
|
||||
|
||||
// Skip 8 bytes of padding
|
||||
r.Advance(8);
|
||||
|
||||
t.TileSize = r.ReadSingle();
|
||||
|
||||
// Skip 4 bytes of "00 00 00 08"
|
||||
r.Advance(4);
|
||||
|
||||
// Read mat info offsets
|
||||
t.MaterialInfoOffsets = r.ReadBytes((int)((t.MaterialInfoLength * 4) + 4));
|
||||
|
||||
BOTWConsole.Log($"Offset before material iteration: {r.BaseStream.Position}");
|
||||
|
||||
// Initialize mat info array with provided length
|
||||
t.MaterialInfo = new MaterialInfo[t.MaterialInfoLength];
|
||||
|
||||
// Initialize every mat info, then add to the array
|
||||
for (int i = 0; i < t.MaterialInfoLength; i++)
|
||||
{
|
||||
// Set header info from file on the new TSCBInfo
|
||||
t.Signature = new string(r.ReadChars(4));
|
||||
t.Version = r.ReadByte();
|
||||
uint index = r.ReadUInt32();
|
||||
float tex_u = r.ReadSingle();
|
||||
float tex_v = r.ReadSingle();
|
||||
float unk_1 = r.ReadSingle();
|
||||
float unk_2 = r.ReadSingle();
|
||||
|
||||
// Skip the 3 extra version bytes
|
||||
r.BaseStream.Seek(3, SeekOrigin.Current);
|
||||
MaterialInfo matInfo = new MaterialInfo(index, tex_u, tex_v, unk_1, unk_2);
|
||||
|
||||
// Skip 4 bytes of "00 00 00 01"
|
||||
r.BaseStream.Seek(4, SeekOrigin.Current);
|
||||
t.MaterialInfo[i] = matInfo;
|
||||
}
|
||||
|
||||
t.FileBaseOffset = r.ReadUInt32();
|
||||
t.WorldScale = r.ReadSingle();
|
||||
t.TerrainMaxHeight = r.ReadSingle();
|
||||
t.MaterialInfoLength = r.ReadUInt32();
|
||||
t.AreaArrayLength = r.ReadUInt32();
|
||||
BOTWConsole.Log($"Offset before area offset iteration: {r.BaseStream.Position}");
|
||||
|
||||
// Skip 8 bytes of padding
|
||||
r.Advance(8);
|
||||
// Read area offsets
|
||||
t.AreaArrayOffsets = r.ReadBytes((int)(t.AreaArrayLength * 4));
|
||||
|
||||
t.TileSize = r.ReadSingle();
|
||||
BOTWConsole.Log($"Offset before area iteration: {r.BaseStream.Position}");
|
||||
|
||||
// Skip 4 bytes of "00 00 00 08"
|
||||
r.Advance(4);
|
||||
t.AreaInfo = new AreaInfo[t.AreaArrayLength];
|
||||
|
||||
// Read mat info offsets
|
||||
t.MaterialInfoOffsets = r.ReadBytes((int)((t.MaterialInfoLength * 4) + 4));
|
||||
// Read every area info entry
|
||||
for (int i = 0; i < t.AreaArrayLength; i++)
|
||||
{
|
||||
uint offset = (uint)r.BaseStream.Position;
|
||||
|
||||
BOTWConsole.Log($"Offset before material iteration: {r.BaseStream.Position}");
|
||||
float xpos = r.ReadSingle();
|
||||
float zpos = r.ReadSingle();
|
||||
float area_size = r.ReadSingle();
|
||||
float min_terrain_height = r.ReadSingle();
|
||||
float max_terrain_height = r.ReadSingle();
|
||||
float min_water_height = r.ReadSingle();
|
||||
float max_water_height = r.ReadSingle();
|
||||
uint unk_1 = r.ReadUInt32();
|
||||
|
||||
// Initialize mat info array with provided length
|
||||
t.MaterialInfo = new MaterialInfo[t.MaterialInfoLength];
|
||||
if (unk_1 == 0)
|
||||
{ // If this unknown is equal to 0, skip the extra byte coming after it
|
||||
uint next_val = r.ReadUInt32();
|
||||
|
||||
// Initialize every mat info, then add to the array
|
||||
for (int i = 0; i < t.MaterialInfoLength; i++)
|
||||
{
|
||||
uint index = r.ReadUInt32();
|
||||
float tex_u = r.ReadSingle();
|
||||
float tex_v = r.ReadSingle();
|
||||
float unk_1 = r.ReadSingle();
|
||||
float unk_2 = r.ReadSingle();
|
||||
|
||||
MaterialInfo matInfo = new MaterialInfo(index, tex_u, tex_v, unk_1, unk_2);
|
||||
|
||||
t.MaterialInfo[i] = matInfo;
|
||||
}
|
||||
|
||||
BOTWConsole.Log($"Offset before area offset iteration: {r.BaseStream.Position}");
|
||||
|
||||
// Read area offsets
|
||||
t.AreaArrayOffsets = r.ReadBytes((int)(t.AreaArrayLength * 4));
|
||||
|
||||
BOTWConsole.Log($"Offset before area iteration: {r.BaseStream.Position}");
|
||||
|
||||
t.AreaInfo = new AreaInfo[t.AreaArrayLength];
|
||||
|
||||
// Read every area info entry
|
||||
for (int i = 0; i < t.AreaArrayLength; i++)
|
||||
{
|
||||
uint offset = (uint)r.BaseStream.Position;
|
||||
|
||||
float xpos = r.ReadSingle();
|
||||
float zpos = r.ReadSingle();
|
||||
float area_size = r.ReadSingle();
|
||||
float min_terrain_height = r.ReadSingle();
|
||||
float max_terrain_height = r.ReadSingle();
|
||||
float min_water_height = r.ReadSingle();
|
||||
float max_water_height = r.ReadSingle();
|
||||
uint unk_1 = r.ReadUInt32();
|
||||
|
||||
if (unk_1 == 0)
|
||||
{ // If this unknown is equal to 0, skip the extra byte coming after it
|
||||
uint next_val = r.ReadUInt32();
|
||||
|
||||
if (next_val != 1) // If the next value isn't extra unneeded info
|
||||
{
|
||||
r.Advance(-4);
|
||||
}
|
||||
}
|
||||
|
||||
uint file_base = r.ReadUInt32();
|
||||
uint unk_2 = r.ReadUInt32();
|
||||
uint unk_3 = r.ReadUInt32();
|
||||
uint ref_extra = r.ReadUInt32();
|
||||
|
||||
AreaInfo areaInfo = new AreaInfo
|
||||
{
|
||||
PositionX = xpos,
|
||||
PositionZ = zpos,
|
||||
AreaSize = area_size,
|
||||
MinTerrainHeight = min_terrain_height,
|
||||
MaxTerrainHeight = max_terrain_height,
|
||||
MinWaterHeight = min_water_height,
|
||||
MaxWaterHeight = max_water_height,
|
||||
Unknown1 = unk_1,
|
||||
FileBase = file_base,
|
||||
Unknown2 = unk_2,
|
||||
Unknown3 = unk_3,
|
||||
ReferenceExtra = ref_extra,
|
||||
Offset = offset
|
||||
};
|
||||
|
||||
areaInfo.ExtraInfoLength = r.ReadUInt32(); //Usually 0, 4, or 8
|
||||
|
||||
if (ref_extra == 4)
|
||||
{
|
||||
if (areaInfo.ExtraInfoLength == 8)
|
||||
{ //Skip the extra "20" after the 8, as well as the extra info
|
||||
areaInfo.HasGrass = true;
|
||||
areaInfo.HasWater = true;
|
||||
r.Advance(36);
|
||||
}
|
||||
else //If the length is 4
|
||||
{
|
||||
var bytes = r.ReadBytes(16).ToArray();
|
||||
if (bytes[7] == 0) //If byte 7 equals 0
|
||||
areaInfo.HasGrass = true;
|
||||
else //Else if the 2nd byte should be anything else (should always be 1)
|
||||
areaInfo.HasWater = true;
|
||||
}
|
||||
}
|
||||
else //If the extra info flags aren't set, go back 4
|
||||
if (next_val != 1) // If the next value isn't extra unneeded info
|
||||
{
|
||||
r.Advance(-4);
|
||||
}
|
||||
|
||||
t.AreaInfo[i] = areaInfo;
|
||||
}
|
||||
|
||||
BOTWConsole.Log($"Offset after area iteration: {r.BaseStream.Position} (should be {t.FileBaseOffset + 16})");
|
||||
uint file_base = r.ReadUInt32();
|
||||
uint unk_2 = r.ReadUInt32();
|
||||
uint unk_3 = r.ReadUInt32();
|
||||
uint ref_extra = r.ReadUInt32();
|
||||
|
||||
//Get the number of filenames by getting how many bytes they take up out of the entire file size
|
||||
var filenames_count = (r.BaseStream.Length - (t.FileBaseOffset + 16)) / 12;
|
||||
|
||||
BOTWConsole.Log($"Filename count: {filenames_count} (should be {t.AreaArrayLength})");
|
||||
|
||||
t.FileNames = new string[filenames_count];
|
||||
|
||||
r.BaseStream.Seek(t.FileBaseOffset + 16, SeekOrigin.Begin); // TODO: change this to 'current' later, or maybe even remove
|
||||
|
||||
for (int i = 0; i < filenames_count; i++)
|
||||
AreaInfo areaInfo = new AreaInfo
|
||||
{
|
||||
string filename = new string(r.ReadChars(12));
|
||||
PositionX = xpos,
|
||||
PositionZ = zpos,
|
||||
AreaSize = area_size,
|
||||
MinTerrainHeight = min_terrain_height,
|
||||
MaxTerrainHeight = max_terrain_height,
|
||||
MinWaterHeight = min_water_height,
|
||||
MaxWaterHeight = max_water_height,
|
||||
Unknown1 = unk_1,
|
||||
FileBase = file_base,
|
||||
Unknown2 = unk_2,
|
||||
Unknown3 = unk_3,
|
||||
ReferenceExtra = ref_extra,
|
||||
Offset = offset
|
||||
};
|
||||
|
||||
t.FileNames[i] = filename;
|
||||
areaInfo.ExtraInfoLength = r.ReadUInt32(); //Usually 0, 4, or 8
|
||||
|
||||
if (ref_extra == 4)
|
||||
{
|
||||
if (areaInfo.ExtraInfoLength == 8)
|
||||
{ //Skip the extra "20" after the 8, as well as the extra info
|
||||
areaInfo.HasGrass = true;
|
||||
areaInfo.HasWater = true;
|
||||
r.Advance(36);
|
||||
}
|
||||
else //If the length is 4
|
||||
{
|
||||
var areabytes = r.ReadBytes(16).ToArray();
|
||||
if (areabytes[7] == 0) //If byte 7 equals 0
|
||||
areaInfo.HasGrass = true;
|
||||
else //Else if the 2nd byte should be anything else (should always be 1)
|
||||
areaInfo.HasWater = true;
|
||||
}
|
||||
}
|
||||
else //If the extra info flags aren't set, go back 4
|
||||
{
|
||||
r.Advance(-4);
|
||||
}
|
||||
|
||||
t.AreaInfo[i] = areaInfo;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FileNotFoundException("Cannot find .tscb file to read.");
|
||||
BOTWConsole.Log($"Offset after area iteration: {r.BaseStream.Position} (should be {t.FileBaseOffset + 16})");
|
||||
|
||||
//Get the number of filenames by getting how many bytes they take up out of the entire file size
|
||||
var filenames_count = (r.BaseStream.Length - (t.FileBaseOffset + 16)) / 12;
|
||||
|
||||
BOTWConsole.Log($"Filename count: {filenames_count} (should be {t.AreaArrayLength})");
|
||||
|
||||
t.FileNames = new string[filenames_count];
|
||||
|
||||
r.BaseStream.Seek(t.FileBaseOffset + 16, SeekOrigin.Begin); // TODO: change this to 'current' later, or maybe even remove
|
||||
|
||||
for (int i = 0; i < filenames_count; i++)
|
||||
{
|
||||
string filename = new string(r.ReadChars(12));
|
||||
|
||||
t.FileNames[i] = filename;
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -221,7 +214,7 @@ namespace BOTWToolset.IO.TSCB
|
|||
/// </summary>
|
||||
/// <param name="tscb"><see cref="TSCB"/> that contains data to write.</param>
|
||||
/// <returns>Byte array containing the TSCB data.</returns>
|
||||
public static byte[] GetBytes(TSCB tscb)
|
||||
public static byte[] ToBytes(TSCB tscb)
|
||||
{
|
||||
List<byte> b = new List<byte>();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue