public Fletcher(BitSize bitSize) { this.bitSize = bitSize; bytesPerCycle = (int)bitSize / 16; modValue = (ulong)(Math.Pow(2, 8 * bytesPerCycle) - 1); Initialize(); }
void pack_roundtrip_check <T>(BitSize bitcount) where T : unmanaged { var src = Random.BitString(bitcount); Claim.eq(bitcount, src.Length); var x = src.ToBits(); Claim.eq(bitcount, x.Length); var y = Bits.pack(x); var sizeT = size <T>(); var q = Math.DivRem(bitcount, 8, out int r); var bytes = q + (r == 0 ? 0 : 1); Claim.eq(bytes, y.Length); var bulk = ByteSpan.ReadValues <T>(y, out Span <byte> rem); var merged = rem.Length != 0 ? bulk.Extend(bulk.Length + 1) : bulk; if (merged.Length != bulk.Length) { merged[merged.Length - 1] = rem.TakeScalar <T>(); } var bsOutput = merged.ToBitString().Truncate(bitcount); Claim.eq(src, bsOutput); Claim.eq((src & ~bsOutput).PopCount(), 0); }
public static BitVector <T> Alloc(BitSize len, T?fill = null) { Span <T> cells = new T[CellCount(len)]; if (fill.HasValue) { cells.Fill(fill.Value); } return(Load(cells)); }
public static int GetNumBytes(this int numTexels, BitSize bitSize) { float numBytesFloat = numTexels * BitSizeToNumBytesFloat(bitSize); int numBytes = (int)numBytesFloat; if ((float)numBytes != numBytesFloat) { throw new Exception("Non-integer number of bytes for the given number of texels"); } return(numBytes); }
public void bitsizes() { Claim.eq(8, BitSize.Size <byte>()); Claim.eq(8, BitSize.Size <sbyte>()); Claim.eq(16, BitSize.Size <short>()); Claim.eq(16, BitSize.Size <ushort>()); Claim.eq(32, BitSize.Size <int>()); Claim.eq(32, BitSize.Size <uint>()); Claim.eq(64, BitSize.Size <long>()); Claim.eq(64, BitSize.Size <ulong>()); Claim.eq(32, BitSize.Size <float>()); Claim.eq(64, BitSize.Size <double>()); }
/// <summary> /// BitItems 태그에 값을 가진 BitItem Element를 추가한다. /// </summary> /// <param name="xDoc"></param> /// <param name="bitItemsNode"></param> /// <returns></returns> public XmlNode GetXml(XmlDocument xDoc, XmlNode bitItemsNode) { XmlNode root = XmlAdder.Element(xDoc, "BitItem", bitItemsNode); XmlAdder.Attribute(xDoc, "Name", BitName, root); XmlAdder.Attribute(xDoc, "StartOffset", StartOffset.ToString(), root); XmlAdder.Attribute(xDoc, "BitSize", BitSize.ToString(), root); XmlAdder.Attribute(xDoc, "PassCondition", PassCondition.Replace("<", "<").Replace(">", ">"), root); XmlAdder.Attribute(xDoc, "Description", Description, root); //XmlAdder.Attribute(xDoc, "Visible", Visible?"True":"False", root); XmlAdder.Attribute(xDoc, "ShowOnReport", ShowOnReport ? "True" : "False", root); return(root); }
public static float BitSizeToNumBytesFloat(BitSize bitSize) { switch (bitSize) { case BitSize._4: return(0.5f); case BitSize._8: return(1); case BitSize._16: return(2); case BitSize._32: return(4); default: throw new Exception(); } }
void dotg_check <T>(BitSize bitcount, T rep = default, int cycles = DefaltCycleCount) where T : unmanaged { TypeCaseStart <T>(); for (var i = 0; i < cycles; i++) { var x = Random.BitVector <T>(bitcount); var y = Random.BitVector <T>(bitcount); var a = x % y; var b = ModProd(x, y); Claim.yea(a == b); } TypeCaseEnd <T>(); }
void bv_disable_check <T>(BitSize n) where T : unmanaged { for (var k = 0; k < SampleSize; k++) { var bv = Random.BitVector <T>(n); var bs = bv.ToBitString(); Claim.eq(bv.Length, n); Claim.eq(bv.Length, bs.Length); for (var i = 0; i < bv.Length; i += 2) { bv.Disable(i); bs[i] = Bit.Off; } Claim.eq(bv.ToBitString(), bs); } }
public void pop_generic() { BitSize bitlen = 128 + 8; ByteSize bytelen = (ByteSize)bitlen; Claim.eq((int)bytelen, (int)bitlen / 8); for (var i = 0; i < CycleCount; i++) { var bv = Random.BitVector <ulong>(bitlen); var actual = bv.Pop(); var expect = 0ul; var bytes = bv.Bytes; for (var j = 0; j < bytes.Length; j++) { expect += Bits.pop(bytes[j]); } Claim.eq(expect, actual); } }
public override int GetHashCode() { return((int)Domain * 17 ^ BitAddress.GetHashCode() ^ BitSize.GetHashCode()); }
public static Bitmap ConvertToBitmap(byte[] data, ColorFormat format, BitSize bitSize, int width, int height, int bytesPerLine, bool flipVertically, bool deinterleave, ushort[]?palette) { if (bytesPerLine % 8 != 0) { throw new Exception(); } byte[][] lines = new byte[height][]; for (int l = 0; l < height; l++) { lines[l] = data.Subsection(l * bytesPerLine, bytesPerLine); } // Deinterleave odd lines if (deinterleave) { for (int l = 1; l < height; l += 2) { byte[] line = lines[l]; for (int word = 0; word < bytesPerLine / 8; word++) { int wordPos = word * 8; byte b1 = line[wordPos]; byte b2 = line[wordPos + 1]; byte b3 = line[wordPos + 2]; byte b4 = line[wordPos + 3]; byte b5 = line[wordPos + 4]; byte b6 = line[wordPos + 5]; byte b7 = line[wordPos + 6]; byte b8 = line[wordPos + 7]; line[wordPos] = b5; line[wordPos + 1] = b6; line[wordPos + 2] = b7; line[wordPos + 3] = b8; line[wordPos + 4] = b1; line[wordPos + 5] = b2; line[wordPos + 6] = b3; line[wordPos + 7] = b4; } // might not be necessary but w/e lines[l] = line; } } Bitmap bmp = new Bitmap(width, height); for (int l = 0; l < height; l++) { byte[] line = lines[l]; for (int x = 0; x < width; x++) { Color texelColor; if (format == ColorFormat.CI) { if (bitSize != BitSize._4) { throw new Exception(); } if (palette == null) { throw new Exception(); } int index = Get4BitTexel(line, x); // We know it's always in RGBA16 texelColor = RGBA16ToColor(palette[index]); } else { texelColor = GetTexel(line, x, format, bitSize); } bmp.SetPixel(x, flipVertically ? (height - 1) - l : l, texelColor); } } return(bmp); }
public static Color GetTexel(byte[] line, int texelX, ColorFormat format, BitSize bitSize) { ulong texel; switch (bitSize) { case BitSize._4: texel = Get4BitTexel(line, texelX); break; case BitSize._8: texel = line[texelX]; break; case BitSize._16: texel = line.ReadUInt16(texelX * 2); break; case BitSize._32: texel = line.ReadUInt32(texelX * 4); break; default: throw new Exception(); } if (format == ColorFormat.I) { byte i; if (bitSize == BitSize._4) { i = (byte)(texel | (texel << 4)); } else if (bitSize == BitSize._8) { i = (byte)texel; } else { throw new Exception(); } return(Color.FromArgb(i, i, i, i)); } else if (format == ColorFormat.IA) { byte i; byte alpha; if (bitSize == BitSize._4) { ulong i3 = texel >> 1; i = (byte)(((i3 << 5) | (i3 << 2) | (i3 >> 1)) & 0xFF); alpha = (byte)(0xFF * (texel & 1)); } else if (bitSize == BitSize._8) { ulong i4 = texel >> 4; ulong a4 = texel & 0x0F; i = (byte)(i4 | (i4 << 4)); alpha = (byte)(a4 | (a4 << 4)); } else if (bitSize == BitSize._16) { i = (byte)(texel >> 8); alpha = (byte)(texel & 0xFF); } else { throw new Exception(); } return(Color.FromArgb(alpha, i, i, i)); } else if (format == ColorFormat.RGBA) { if (bitSize == BitSize._16) { return(RGBA16ToColor((ushort)texel)); } else if (bitSize == BitSize._32) { int argb = (int)((texel >> 8) | ((texel & 0xFF) << 24)); return(Color.FromArgb(argb)); } else { throw new Exception(); } } else { throw new Exception(); } }
public static int FetchBits(this int word, BitNumber high, BitSize length) { var mask = ~(-1 << length.Value); return(word >> (high.Value - length.Value + 1) & mask); }
public static int CellCount(BitSize len) { var q = Math.DivRem(len, SegmentCapacity, out int r); return(r == 0 ? q : q + 1); }
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"); } }
public static ITextureConverter GetConverter( ColorFormat colorFormat, BitSize bitSize) { switch (colorFormat) { case ColorFormat.RGBA: switch (bitSize) { case BitSize.S_32B: // TODO: Implement OGLTexImg = N64TexImg throw new NotImplementedException(); case BitSize.S_16B: return(new Rgba16()); default: throw new NotSupportedException(); } case ColorFormat.CI: switch (bitSize) { case BitSize.S_8B: return(new Ci8()); case BitSize.S_4B: return(new Ci4()); default: throw new NotSupportedException(); } case ColorFormat.IA: switch (bitSize) { case BitSize.S_16B: return(new Ia16()); case BitSize.S_8B: return(new Ia8()); case BitSize.S_4B: return(new Ia4()); default: throw new NotSupportedException(); } case ColorFormat.I: switch (bitSize) { case BitSize.S_8B: return(new I8()); case BitSize.S_4B: return(new I4()); default: throw new NotSupportedException(); } default: throw new NotSupportedException(); } }
public static RDPState ExecuteCommands(UVTXFile uvtx, out StringBuilder cmdsString) { RDPState rdpState = new RDPState(); cmdsString = new StringBuilder(); foreach (byte[] commandBytes in uvtx.displayListCommands) { byte[] bytes = commandBytes; string operationDesc; switch ((Fast3DEX2Opcode)bytes[0]) { case Fast3DEX2Opcode.G_TEXTURE: { ulong word = bytes.ReadUInt64(0); byte mipMap = (byte)(word.Bits(43, 3) + 1); byte tileDescIndex = (byte)word.Bits(40, 3); bool on = word.Bit(33); float scaleFactorS = bytes.ReadUInt16(4) / (float)0x10000; float scaleFactorT = bytes.ReadUInt16(6) / (float)0x10000; rdpState.tileToUseWhenTexturing = tileDescIndex; rdpState.maxMipMapLevels = mipMap; rdpState.texturingEnabled = on; rdpState.textureScaleS = scaleFactorS; rdpState.textureScaleT = scaleFactorT; operationDesc = "G_TEXTURE (Set RSP texture state)"; operationDesc += $": tile {tileDescIndex} scale=<{scaleFactorS}, {scaleFactorT}>; mm={mipMap} on={on}"; break; } case Fast3DEX2Opcode.G_SetOtherMode_H: { // TODO: actually implement this? operationDesc = "G_SetOtherMode_H (Set Other Modes Hi)"; int length = bytes[3] + 1; int shift = 32 - length - bytes[2]; string str = otherModeHShiftToStr[shift]; byte val = (byte)bytes.ReadUInt64(0).Bits(shift, length); // TODO?: https://wiki.cloudmodding.com/oot/F3DZEX#RDP_Other_Modes.2C_Higher_Half string valStr = Convert.ToString(val, 2).PadLeft(length, '0'); operationDesc += $": {str} = {valStr}"; break; } case Fast3DEX2Opcode.G_SETTILESIZE: { ulong word = bytes.ReadUInt64(0); ushort sLoRaw = (ushort)word.Bits(44, 12); ushort tLoRaw = (ushort)word.Bits(32, 12); byte tileDescIndex = (byte)word.Bits(24, 3); ushort sHiRaw = (ushort)word.Bits(12, 12); ushort tHiRaw = (ushort)word.Bits(0, 12); TileDescriptor t = rdpState.tileDescriptors[tileDescIndex]; t.sLo = sLoRaw / 4.0f; t.tLo = tLoRaw / 4.0f; t.sHi = sHiRaw / 4.0f; t.tHi = tHiRaw / 4.0f; float visWidth = (t.sHi - t.sLo) + 1; float visHeight = (t.tHi - t.tLo) + 1; operationDesc = "G_SETTILESIZE (Set texture coords and size)"; operationDesc += $": tile {tileDescIndex} lo=({t.sLo}, {t.tLo}) hi=({t.sHi}, {t.tHi}) [[{visWidth}, {visHeight}]]"; break; } case Fast3DEX2Opcode.G_LOADBLOCK: { ulong word = bytes.ReadUInt64(0); ushort sLo = (ushort)word.Bits(44, 12); ushort tLo = (ushort)word.Bits(32, 12); byte tileDescIndex = (byte)word.Bits(24, 3); ushort sHi = (ushort)word.Bits(12, 12); ushort dxt = (ushort)word.Bits(0, 12); if (dxt != 0) { throw new Exception(); } if (sLo != 0 || tLo != 0) { throw new Exception(); } if (rdpState.nextDRAMAddrForLoad == null || rdpState.bitSizeOfNextDataForLoad == null) { throw new Exception(); } rdpState.tileDescriptors[tileDescIndex].sLo = sLo; rdpState.tileDescriptors[tileDescIndex].tLo = tLo; rdpState.tileDescriptors[tileDescIndex].sHi = sHi; rdpState.tileDescriptors[tileDescIndex].tHi = dxt; // Not 100% sure this is the correct behavior int dataStart = (int)rdpState.nextDRAMAddrForLoad; int dataLengthBytes = (sHi + 1) * Texels.BitSizeToNumBytes((BitSize)rdpState.bitSizeOfNextDataForLoad); int destPtr = rdpState.tileDescriptors[tileDescIndex].tmemAddressInWords * 8; // I'm assuming this is the correct behavior because if I don't do this a lot of textures have a notch at the top right // (Also it would make sense given that interleaving and addresses are all done on 64-bit words dataLengthBytes = (int)Math.Ceiling(dataLengthBytes / 8f) * 8; // Note: technically this inaccurate, we shouldn't clamp. But the instructions read beyond the file and IDK why, // it doesn't seem to serve any purpose so I assume it's a bug (or I don't understand something about how the RSP works) Array.Copy(uvtx.texelData, dataStart, rdpState.tmem, destPtr, Math.Min(uvtx.texelData.Length - dataStart, dataLengthBytes)); operationDesc = "G_LOADBLOCK (Load data into TMEM (uses params set in SETTIMG))"; operationDesc += $": tile {tileDescIndex} sLo={sLo} tLo={tLo} sHi={sHi} dxt={dxt}"; break; } case Fast3DEX2Opcode.G_SETTILE: { ulong word = bytes.ReadUInt64(0); TileDescriptor t = new TileDescriptor { format = (ColorFormat)word.Bits(53, 3), bitSize = (BitSize)word.Bits(51, 2), wordsPerLine = (ushort)word.Bits(41, 9), tmemAddressInWords = (ushort)word.Bits(32, 9), palette = (byte)word.Bits(20, 4), clampEnableT = word.Bit(19), mirrorEnableT = word.Bit(18), maskT = (byte)word.Bits(14, 4), shiftT = (byte)word.Bits(10, 4), clampEnableS = word.Bit(9), mirrorEnableS = word.Bit(8), maskS = (byte)word.Bits(4, 4), shiftS = (byte)word.Bits(0, 4), }; byte tileDescIndex = (byte)word.Bits(24, 3); rdpState.tileDescriptors[tileDescIndex] = t; operationDesc = "G_SETTILE (Set texture properties)"; operationDesc += $": tile {tileDescIndex} fmt={t.bitSize}-bit {t.format} wordsPerLine={t.wordsPerLine} addrWords={t.tmemAddressInWords} palette={t.palette}" + $" s(clmp={t.clampEnableS} mirr={t.mirrorEnableS} mask={t.maskS} shift={t.shiftS}) t(clmp={t.clampEnableT} mirr={t.mirrorEnableT} mask={t.maskT} shift={t.shiftT})"; break; } case Fast3DEX2Opcode.G_SETPRIMCOLOR: { float minLODLevel = bytes[2] / 0x100f; float LODfrac = bytes[3] / 0x100f; byte r = bytes[4]; byte g = bytes[5]; byte b = bytes[6]; byte a = bytes[7]; rdpState.colorCombinerSettings.primR = r; rdpState.colorCombinerSettings.primG = g; rdpState.colorCombinerSettings.primB = b; rdpState.colorCombinerSettings.primA = a; rdpState.colorCombinerSettings.minLODLevel = minLODLevel; rdpState.colorCombinerSettings.LODfrac = LODfrac; operationDesc = "G_SETPRIMCOLOR (Set color combiner primitive color + LOD)"; operationDesc += $": rgba({r}, {g}, {b}, {a}) minLOD={minLODLevel} LODfrac={LODfrac}"; break; } case Fast3DEX2Opcode.G_SETENVCOLOR: { byte r = bytes[4]; byte g = bytes[5]; byte b = bytes[6]; byte a = bytes[7]; rdpState.colorCombinerSettings.envR = r; rdpState.colorCombinerSettings.envG = g; rdpState.colorCombinerSettings.envB = b; rdpState.colorCombinerSettings.envA = a; operationDesc = "G_SETENVCOLOR (Set color combiner environment color)"; operationDesc += $": rgba({r}, {g}, {b}, {a})"; break; } case Fast3DEX2Opcode.G_SETCOMBINE: operationDesc = "G_SETCOMBINE (Set color combiner algorithm)"; break; case Fast3DEX2Opcode.G_SETTIMG: { ulong word = bytes.ReadUInt64(0); ColorFormat format = (ColorFormat)word.Bits(53, 3); BitSize bitSize = (BitSize)word.Bits(51, 2); uint dramAddress = (uint)word.Bits(0, 25); rdpState.nextDRAMAddrForLoad = dramAddress; rdpState.bitSizeOfNextDataForLoad = bitSize; operationDesc = "G_SETTIMG (Set pointer to data to load + size of data)"; operationDesc += $": DRAM 0x{dramAddress:X8}; fmt={bitSize}-bit {format}"; break; } case Fast3DEX2Opcode.G_RDPLOADSYNC: operationDesc = "G_RDPLOADSYNC (Wait for texture load)"; break; case Fast3DEX2Opcode.G_RDPTILESYNC: operationDesc = "G_RDPTILESYNC (Wait for rendering + update tile descriptor attributes)"; break; case Fast3DEX2Opcode.G_ENDDL: operationDesc = "G_ENDDL (End display list)"; break; default: throw new InvalidOperationException(); } string bytesStr = String.Join(" ", bytes.Select(b => b.ToString("X2"))); cmdsString.AppendLine(bytesStr + " | " + operationDesc); } return(rdpState); }