private static void GenerateUndubMap01(string datadir, string voicedir, string outdir, string mapcpkname, SubcpkInjectData[] injects) { Console.WriteLine(string.Format("processing {0}", mapcpkname)); var datastream = new DuplicatableFileStream(Path.Combine(datadir, mapcpkname)); var voicestream = new DuplicatableFileStream(Path.Combine(voicedir, mapcpkname)); var datacpk = new HyoutaTools.Tales.CPK.CpkContainer(datastream.Duplicate()); var voicecpk = new HyoutaTools.Tales.CPK.CpkContainer(voicestream); string outfile = Path.Combine(outdir, mapcpkname); var builder = new HyoutaTools.Tales.CPK.CpkBuilder(datastream.Duplicate()); foreach (var subdata in injects) { var subbuilder = new HyoutaTools.Tales.CPK.CpkBuilder(datacpk.GetChildByName(subdata.Name).AsFile.DataStream); var subvoicecpk = new HyoutaTools.Tales.CPK.CpkContainer(voicecpk.GetChildByName(subdata.Name).AsFile.DataStream); foreach (string subpath in subdata.Subpaths) { Console.WriteLine(string.Format("injecting {0}/{1}", subdata.Name, subpath)); var subvoicestream = subvoicecpk.GetChildByName(subpath).AsFile.DataStream.Duplicate(); var subfile = subbuilder.Files.Where(x => (x.Directory + "/" + x.Name) == subpath).First(); ReplaceFile(subfile, subvoicestream.CopyToByteArrayStreamAndDispose()); } MemoryStream subbuild = new MemoryStream(); subbuilder.Build(subbuild); var file = builder.Files.Where(x => x.Name == subdata.Name).First(); ReplaceFile(file, subbuild.CopyToByteArrayStreamAndDispose()); } CreateDirectory(outdir); WriteCpk(outfile, builder); }
private static void WriteCpk(string outfile, HyoutaTools.Tales.CPK.CpkBuilder cpk) { Console.WriteLine(string.Format("writing {0}", outfile)); using (var fs = new FileStream(outfile, FileMode.Create)) { cpk.Build(fs); // ToGf is buggy and fails to boot if bit 31 of the file length is set // (probably something somewhere is interpreted incorrectly as a signed 32 bit integer) // so work around that long length = fs.Length; if ((length % 0x100000000L) >= 0x80000000L) { fs.WriteAlign(0x80000000L); } } }