internal void TakeBytes(MemChunk chunk, uint size) { if (chunk.FreeBytes < size) { throw new Exception("took too many bytes"); } chunk.Address += size; chunk.FreeBytes -= size; }
public static List <MemChunk> FindFreeMemoryInFontTexture(MemoryStream fontStream) { DuplicatableStream textureWiiStream = new DuplicatableByteArrayStream(fontStream.CopyToByteArray()); HyoutaTools.Tales.Vesperia.FPS4.FPS4 textureWiiFps4 = new HyoutaTools.Tales.Vesperia.FPS4.FPS4(textureWiiStream); HyoutaTools.Tales.Vesperia.Texture.TXM textureWiiTxm = new HyoutaTools.Tales.Vesperia.Texture.TXM(textureWiiFps4.GetChildByIndex(0).AsFile.DataStream); HyoutaTools.Tales.Vesperia.Texture.TXV textureWiiTxv = new HyoutaTools.Tales.Vesperia.Texture.TXV(textureWiiTxm, textureWiiFps4.GetChildByIndex(1).AsFile.DataStream, false); Bitmap bitmapWii = textureWiiTxv.textures[2].GetBitmaps()[0]; { for (int y = 0; y < bitmapWii.Height; ++y) { for (int x = 0; x < bitmapWii.Width; ++x) { Color color; switch (IdentifyPixel(x, y)) { case TileIdentification.UsedTile: color = Color.FromArgb(0, 255, 0); break; case TileIdentification.UnusedTile: color = Color.FromArgb(0, 0, 255); break; default: throw new Exception("???"); } bitmapWii.SetPixel(x, y, color); } } } var pxit = new HyoutaTools.Textures.PixelOrderIterators.TiledPixelOrderIterator(bitmapWii.Width, bitmapWii.Height, 8, 8); MemoryStream stream = new MemoryStream(); byte storage = 0; bool even = false; foreach (var px in pxit) { if (px.X < bitmapWii.Width && px.Y < bitmapWii.Height) { Color col = bitmapWii.GetPixel(px.X, px.Y); bool pixelUnused = col.B > 0; var colidx = pixelUnused ? 0xF : 0x0; if (!even) { storage = (byte)colidx; } else { storage = (byte)(storage << 4 | (byte)colidx); stream.WriteByte(storage == 0xFF ? (byte)1 : (byte)0); } even = !even; } } List <MemChunk> chunks = new List <MemChunk>(); uint offset = textureWiiFps4.Files[1].Location.Value + textureWiiTxv.textures[2].TXM.TxvLocation; long len = stream.Length; long startOfLastSafeBlock = -1; var fontMapper = new FontMapper(0xE0000000 - textureWiiFps4.Files[1].Location.Value); stream.Position = 0; for (long i = 0; i <= len; ++i) { bool safeToWriteTo = i == len ? false : stream.ReadUInt8() == 1; if (safeToWriteTo && startOfLastSafeBlock == -1) { // start of block startOfLastSafeBlock = i; } else if (!safeToWriteTo && startOfLastSafeBlock != -1) { // end of block long start = startOfLastSafeBlock; long length = i - startOfLastSafeBlock; MemChunk mc = new MemChunk(); mc.Address = (uint)(start + offset); mc.FreeBytes = (uint)length; mc.File = fontStream; mc.Mapper = fontMapper; mc.IsInternal = false; chunks.Add(mc); startOfLastSafeBlock = -1; } } return(chunks); }