mirror of
https://github.com/chev2/botw-toolset.git
synced 2025-12-18 14:03:18 +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");
|
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
|
// Set the current file location to the chosen file's location
|
||||||
fileLocation = openFileDialog.FileName;
|
fileLocation = openFileDialog.FileName;
|
||||||
|
|
@ -365,7 +365,7 @@ namespace BOTWToolset.Control
|
||||||
|
|
||||||
if ((bool)saveFileDialog.ShowDialog())
|
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>
|
/// </summary>
|
||||||
/// <param name="file">The .tscb file.</param>
|
/// <param name="file">The .tscb file.</param>
|
||||||
/// <returns></returns>
|
/// <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
|
// Skip the 3 extra version bytes
|
||||||
using (var r = new BinaryReaderBig(File.Open(file, FileMode.Open)))
|
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
|
uint index = r.ReadUInt32();
|
||||||
t.Signature = new string(r.ReadChars(4));
|
float tex_u = r.ReadSingle();
|
||||||
t.Version = r.ReadByte();
|
float tex_v = r.ReadSingle();
|
||||||
|
float unk_1 = r.ReadSingle();
|
||||||
|
float unk_2 = r.ReadSingle();
|
||||||
|
|
||||||
// Skip the 3 extra version bytes
|
MaterialInfo matInfo = new MaterialInfo(index, tex_u, tex_v, unk_1, unk_2);
|
||||||
r.BaseStream.Seek(3, SeekOrigin.Current);
|
|
||||||
|
|
||||||
// Skip 4 bytes of "00 00 00 01"
|
t.MaterialInfo[i] = matInfo;
|
||||||
r.BaseStream.Seek(4, SeekOrigin.Current);
|
}
|
||||||
|
|
||||||
t.FileBaseOffset = r.ReadUInt32();
|
BOTWConsole.Log($"Offset before area offset iteration: {r.BaseStream.Position}");
|
||||||
t.WorldScale = r.ReadSingle();
|
|
||||||
t.TerrainMaxHeight = r.ReadSingle();
|
|
||||||
t.MaterialInfoLength = r.ReadUInt32();
|
|
||||||
t.AreaArrayLength = r.ReadUInt32();
|
|
||||||
|
|
||||||
// Skip 8 bytes of padding
|
// Read area offsets
|
||||||
r.Advance(8);
|
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"
|
t.AreaInfo = new AreaInfo[t.AreaArrayLength];
|
||||||
r.Advance(4);
|
|
||||||
|
|
||||||
// Read mat info offsets
|
// Read every area info entry
|
||||||
t.MaterialInfoOffsets = r.ReadBytes((int)((t.MaterialInfoLength * 4) + 4));
|
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
|
if (unk_1 == 0)
|
||||||
t.MaterialInfo = new MaterialInfo[t.MaterialInfoLength];
|
{ // 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
|
if (next_val != 1) // If the next value isn't extra unneeded info
|
||||||
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
|
|
||||||
{
|
{
|
||||||
r.Advance(-4);
|
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
|
AreaInfo areaInfo = new AreaInfo
|
||||||
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));
|
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;
|
BOTWConsole.Log($"Offset after area iteration: {r.BaseStream.Position} (should be {t.FileBaseOffset + 16})");
|
||||||
}
|
|
||||||
else
|
//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;
|
||||||
throw new FileNotFoundException("Cannot find .tscb file to read.");
|
|
||||||
|
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>
|
/// <summary>
|
||||||
|
|
@ -221,7 +214,7 @@ namespace BOTWToolset.IO.TSCB
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tscb"><see cref="TSCB"/> that contains data to write.</param>
|
/// <param name="tscb"><see cref="TSCB"/> that contains data to write.</param>
|
||||||
/// <returns>Byte array containing the TSCB data.</returns>
|
/// <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>();
|
List<byte> b = new List<byte>();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue