Created
April 9, 2020 22:37
-
-
Save WamWooWam/ff233622fd46beb31fbd2f2718fa0d7d to your computer and use it in GitHub Desktop.
Sonic 4 PC AMB Repacker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Text; | |
namespace AMBRepack | |
{ | |
class Program | |
{ | |
private const uint MAGIC = 0x424d4123u; // #AMB | |
private const uint MAGIC_2 = 0x00000020u; | |
private const uint MAGIC_WITH_A_VENGEANCE = 0x00040000u; | |
private const uint LIVE_FREE_OR_MAGIC_HARD = 0xFFFFFFFFu; | |
static void Main(string[] args) | |
{ | |
if (args.Length < 1) | |
return; | |
var directory = args[0]; | |
var output = args[1]; | |
output = Path.ChangeExtension(output, "AMB").ToUpperInvariant(); | |
var files = new DirectoryInfo(directory).GetFiles(); | |
using (var fileStream = File.Create(output)) | |
using (var writer = new BinaryWriter(fileStream, Encoding.ASCII, true)) | |
{ | |
writer.Write(MAGIC); | |
writer.Write(MAGIC_2); // unused in game :omegalul: | |
writer.Write(MAGIC_WITH_A_VENGEANCE); | |
writer.Write(0); | |
// file count now | |
writer.Write(files.Length); | |
// entry table offset next | |
writer.Write(0x20); // safe to assume | |
// then data offset | |
writer.Write(0x20 + (0x10 * files.Length)); // easy to calculate | |
// then string table offset (we'll write this later) | |
fileStream.Position = 0x20; | |
var offset = (long)(0x20 + (0x10 * files.Length)); | |
// let's write the entries then | |
for (var i = 0; i < files.Length; i++) | |
{ | |
var file = files[i]; | |
writer.Write((uint)offset); | |
writer.Write((uint)file.Length); | |
writer.Write(LIVE_FREE_OR_MAGIC_HARD); | |
writer.Write(0); | |
offset += file.Length; | |
} | |
// now the content | |
for (int i = 0; i < files.Length; i++) | |
{ | |
var file = files[i]; | |
using (var newFileStream = file.OpenRead()) | |
{ | |
newFileStream.CopyTo(fileStream); | |
} | |
} | |
// now we're at the string offset table | |
var stringTablePosition = (uint)fileStream.Position; | |
// let's write that | |
fileStream.Seek(0x1C, SeekOrigin.Begin); | |
writer.Write(stringTablePosition); | |
fileStream.Seek(stringTablePosition, SeekOrigin.Begin); | |
var array = new char[0x20]; | |
// and let's write the table itself | |
for (int i = 0; i < files.Length; i++) | |
{ | |
for (int j = 0; j < array.Length; j++) | |
array[j] = (char)0; // clear the array | |
var file = files[i]; | |
var fileName = file.Name.ToUpperInvariant(); | |
if (fileName.Length > 0x20) | |
{ | |
Console.WriteLine($"Truncating {fileName}! This is bad!!"); | |
fileName = fileName.Substring(0, 0x20); | |
} | |
fileName.CopyTo(0, array, 0, fileName.Length); | |
for (int j = 0; j < array.Length; j++) | |
writer.Write((byte)array[j]); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment