private static Bitmap ConvertTileToBitmap(TileDescriptor tileDesc, byte[] tmem, ushort[][] palettes) { if (Math.Floor(tileDesc.sHi - tileDesc.sLo) != tileDesc.sHi - tileDesc.sLo) { throw new Exception(); } if (Math.Floor(tileDesc.tHi - tileDesc.tLo) != tileDesc.tHi - tileDesc.tLo) { throw new Exception(); } // Break into lines int startPtrBytes = tileDesc.tmemAddressInWords * 8; int width = (int)(tileDesc.sHi - tileDesc.sLo + 1); int height = (int)(tileDesc.tHi - tileDesc.tLo + 1); int bytesPerLine = tileDesc.wordsPerLine * 8; byte[] data = tmem.Subsection(startPtrBytes, bytesPerLine * height); ushort[]? palette = tileDesc.palette == 0 ? null : palettes[tileDesc.palette - 1]; return(Texels.ConvertToBitmap(data, tileDesc.format, tileDesc.bitSize, width, height, bytesPerLine, true, true, palette)); }
public static void DumpFonts(byte[] romBytes, string outputDir) { Directory.CreateDirectory(outputDir + "Converted"); string fullOutputPath = outputDir + "Converted/font/"; Directory.CreateDirectory(fullOutputPath); // ok this is dumb i need to fix this Filesystem.Filesystem filesystem = new Filesystem.Filesystem(romBytes); foreach (Filesystem.Filesystem.File file in filesystem.AllFiles.Where(file => file.fileTypeFromFileHeader == "UVFT")) { // TODO string outputSubfolder = $"{fullOutputPath}[0x{file.formLocationInROM:x6}]/"; Directory.CreateDirectory(outputSubfolder); List <byte[]> imageDatas = file.SectionsOfType("IMAG"); byte[] charIndexToASCII = file.Section("STRG"); byte[] frmtSec = file.Section("FRMT"); if (frmtSec.Length != 8) { throw new Exception(); } Texels.ColorFormat colorFormat = (Texels.ColorFormat)frmtSec.ReadUInt32(0); Texels.BitSize bitSize = (Texels.BitSize)frmtSec.ReadUInt32(4); CharacterDescriptor[] characterDescriptors = file.Section("BITM") .InGroupsOf(16) .Select((charDescData, index) => new CharacterDescriptor(charDescData, index)) .ToArray(); // First, save off the main images //for (int i = 0; i < imageDatas.Count; i++) //{ // byte[] imageData = imageDatas[i]; // IEnumerable<CharacterDescriptor> relevantChars = characterDescriptors.Where(c => c.sourceIMAGIndex == i); // int texelsPerLine = relevantChars.First().sourceIMAGTexelsPerLine; // if(relevantChars.Any(c => c.sourceIMAGTexelsPerLine != texelsPerLine)) // { // throw new Exception("Inconsistent texels per line in BITM section!"); // } // int imagHeightTexels = relevantChars.Max(c => c.heightTexels); // int bytesPerLine = Texels.GetNumBytes(texelsPerLine, bitSize); // Bitmap bitmap = Texels.ConvertToBitmap(imageData, colorFormat, bitSize, texelsPerLine, imagHeightTexels, bytesPerLine, false, false, null); // bitmap.Save($"{outputSubfolder}{i+1}.png"); //} // Now save each of the characters //string individualCharsDirectory = $"{outputSubfolder}Individual Characters/"; //Directory.CreateDirectory(individualCharsDirectory); foreach (CharacterDescriptor charDesc in characterDescriptors) { byte[] sourceIMAG = imageDatas[charDesc.sourceIMAGIndex]; byte[] texelData; if (bitSize == Texels.BitSize._4) { texelData = GetByteArrayStartingFromFourBitIndex(sourceIMAG, charDesc.startTexel).ToArray(); } else { texelData = sourceIMAG.Skip(Texels.GetNumBytes(charDesc.startTexel, bitSize)).ToArray(); } int bytesPerLine = Texels.GetNumBytes(charDesc.sourceIMAGTexelsPerLine, bitSize); Bitmap bitmap = Texels.ConvertToBitmap(texelData, colorFormat, bitSize, charDesc.widthTexels, charDesc.heightTexels, bytesPerLine, false, false, null); string filename = $"{charDesc.indexInBITM:D2}"; char ascii = Convert.ToChar(charIndexToASCII[charDesc.indexInBITM]); if (!Path.GetInvalidFileNameChars().Contains(ascii)) { filename += $" ({ascii})"; } bitmap.Save($"{outputSubfolder}{filename}.png"); } Console.WriteLine($"Converted font at {file.formLocationInROM:x6}"); } }
public static void DumpBlits(byte[] romBytes, string outputDir) { Directory.CreateDirectory(outputDir + "Converted"); string fullOutputPath = outputDir + "Converted/blit/"; Directory.CreateDirectory(fullOutputPath); // ok this is dumb i need to fix this Filesystem.Filesystem filesystem = new Filesystem.Filesystem(romBytes); foreach (Filesystem.Filesystem.File file in filesystem.AllFiles.Where(file => file.fileTypeFromFileHeader == "UVBT")) { string outputFileName = $"[0x{file.formLocationInROM:x6}]"; byte[] bytes = file.Sections.Single().Item2; ColorFormat colorFormat = (ColorFormat)bytes.ReadUInt16(0); BitSize bitSize = Texels.NumBitsToBitSize(bytes.ReadUInt16(2)); ushort width = bytes.ReadUInt16(4); ushort texelsPerLine = bytes.ReadUInt16(6); ushort height = bytes.ReadUInt16(8); ushort tileWidth = bytes.ReadUInt16(10); ushort tileHeight = bytes.ReadUInt16(12); byte[] colorData = bytes.Subsection(14, bytes.Length - 14); Console.WriteLine(bytes.Subsection(0, 14).PrettyPrint()); Console.WriteLine($"{outputFileName} {bitSize}-bit {colorFormat}\t <{width} ({texelsPerLine}), {height}> [{tileWidth} {tileHeight}]"); int bytesPerTile = (int)(tileWidth * tileHeight * Texels.BitSizeToNumBytesFloat(bitSize)); Bitmap outBitmap = new Bitmap(width, height); int p = 0; int curTopLeftX = 0; int curTopLeftY = 0; while (p < colorData.Length) { if (curTopLeftY + tileHeight > height) { tileHeight = (ushort)(height - curTopLeftY); bytesPerTile = (int)(tileWidth * tileHeight * Texels.BitSizeToNumBytesFloat(bitSize)); } byte[] tileColorData; if (p + bytesPerTile >= colorData.Length) { tileColorData = new byte[bytesPerTile]; Array.Copy(colorData, p, tileColorData, 0, colorData.Length - p); } else { tileColorData = colorData.Subsection(p, bytesPerTile); } // TODO: why arent 32-bit textures deinterleaved? Bitmap tile = Texels.ConvertToBitmap(tileColorData, colorFormat, bitSize, tileWidth, tileHeight, (int)(tileWidth * Texels.BitSizeToNumBytesFloat(bitSize)), false, bitSize != BitSize._32, null); CopyToMainBitmap(tile, curTopLeftX, curTopLeftY, outBitmap); p += bytesPerTile; curTopLeftX += tileWidth; if (curTopLeftX >= width) { curTopLeftX = 0; curTopLeftY += tileHeight; if (curTopLeftY >= height) { break; } } } outBitmap.Save(fullOutputPath + outputFileName + ".png"); } }