public void FillTextureBlock(Texture2D tex, int blockX, int blockY, int relX, int relY, byte[] imageBuffer, int imageBufferOffset, IList<ARGB1555Color> pal, int paletteInd, bool flipX, bool flipY) { var offset1 = imageBufferOffset; var offset2 = imageBufferOffset + 16; for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { int actualX = blockX + relX * 8 + (flipX ? (8 - x - 1) : x); int actualY = blockY + relY * 8 + (flipY ? (8 - y - 1) : y); int off = y * 8 + (8 - x - 1); var bit0 = BitHelpers.ExtractBits(imageBuffer[offset1 + ((off / 8) * 2)], 1, off % 8); var bit1 = BitHelpers.ExtractBits(imageBuffer[offset1 + ((off / 8) * 2 + 1)], 1, off % 8); var bit2 = BitHelpers.ExtractBits(imageBuffer[offset2 + ((off / 8) * 2)], 1, off % 8); var bit3 = BitHelpers.ExtractBits(imageBuffer[offset2 + ((off / 8) * 2 + 1)], 1, off % 8); int b = 0; b = BitHelpers.SetBits(b, bit0, 1, 0); b = BitHelpers.SetBits(b, bit1, 1, 1); b = BitHelpers.SetBits(b, bit2, 1, 2); b = BitHelpers.SetBits(b, bit3, 1, 3); Color c = pal[paletteInd * 0x10 + b].GetColor(); if (b != 0) c = new Color(c.r, c.g, c.b, 1f); tex.SetPixel(actualX, actualY, c); } } }
public XM_PatternRow( byte?note = null, byte?instrument = null, byte?volumeColumnByte = null, byte?effectType = null, byte?effectParameter = null) { if (!(instrument.HasValue || volumeColumnByte.HasValue || effectType.HasValue || effectParameter.HasValue)) { if (note.HasValue) { Flags = note.Value; Note = note.Value; } Size = 1; } else { Size = 1; if (note.HasValue) { Flags = (byte)BitHelpers.SetBits(Flags, 1, 1, 0); Note = note.Value; Size++; } if (instrument.HasValue) { Flags = (byte)BitHelpers.SetBits(Flags, 1, 1, 1); Instrument = instrument.Value; Size++; } if (volumeColumnByte.HasValue) { Flags = (byte)BitHelpers.SetBits(Flags, 1, 1, 2); VolumeColumnByte = volumeColumnByte.Value; Size++; } if (effectType.HasValue) { Flags = (byte)BitHelpers.SetBits(Flags, 1, 1, 3); EffectType = effectType.Value; Size++; } if (effectParameter.HasValue) { Flags = (byte)BitHelpers.SetBits(Flags, 1, 1, 4); EffectParameter = effectParameter.Value; Size++; } } }
public override async UniTask ExportMenuSpritesAsync(GameSettings settings, string outputPath, bool exportAnimFrames) { using (var menuContext = new Context(settings)) { using (var bigRayContext = new Context(settings)) { await LoadFilesAsync(menuContext); await LoadFilesAsync(bigRayContext); // Read the allfix & font files for the menu await LoadExtraFile(menuContext, GetAllfixFilePath(menuContext.Settings), false); var fix = FileFactory.Read <R1_PS1_AllfixFile>(GetAllfixFilePath(menuContext.Settings), menuContext); await LoadExtraFile(menuContext, GetFontFilePath(menuContext.Settings), false); // Correct font palette if (settings.EngineVersion == EngineVersion.R1_PS1_JP) { foreach (R1_PS1_FontData font in fix.AllfixData.FontData) { foreach (R1_ImageDescriptor imgDescr in font.ImageDescriptors) { var paletteInfo = imgDescr.PaletteInfo; paletteInfo = (ushort)BitHelpers.SetBits(paletteInfo, 509, 10, 6); imgDescr.PaletteInfo = paletteInfo; } } } else { foreach (R1_PS1_FontData font in fix.AllfixData.FontData) { foreach (R1_ImageDescriptor imgDescr in font.ImageDescriptors) { var paletteInfo = imgDescr.PaletteInfo; paletteInfo = (ushort)BitHelpers.SetBits(paletteInfo, 492, 10, 6); imgDescr.PaletteInfo = paletteInfo; } } } // Read the BigRay file await LoadExtraFile(bigRayContext, GetBigRayFilePath(bigRayContext.Settings), false); var br = bigRayContext.FileExists(GetBigRayFilePath(bigRayContext.Settings)) ? FileFactory.Read <R1_PS1_BigRayFile>(GetBigRayFilePath(bigRayContext.Settings), bigRayContext) : null; // Export await ExportMenuSpritesAsync(menuContext, bigRayContext, outputPath, exportAnimFrames, fix.AllfixData.FontData, fix.AllfixData.WldObj, br?.BigRayData); } } }
public override void SerializeBitValues <T>(Action <SerializeBits> serializeFunc) { int valueInt = 0; int pos = 0; string logPrefix = LogPrefix; // Set bits serializeFunc((v, length, name) => { valueInt = BitHelpers.SetBits(valueInt, v, length, pos); if (Settings.Log) { Context.Log.Log(logPrefix + $" ({typeof(T)}) {name ?? "<no name>"}: {v}"); } pos += length; return(v); }); // Serialize value Serialize <T>((T)Convert.ChangeType(valueInt, typeof(T)), name: "Value"); }
private Stream XORStream(Stream s) { byte compr_incremental_xor = 0x57; var decompressedStream = new MemoryStream(); Reader reader = new Reader(s, isLittleEndian: true); // No using, because we don't want to close the stream byte bytes_in_window = reader.ReadByte(); bytes_in_window ^= 0x53; decompressedStream.WriteByte(bytes_in_window); uint decompressedSize = reader.ReadUInt32(); decompressedSize ^= 0x54555657; decompressedStream.Write(BitConverter.GetBytes(decompressedSize), 0, 4); while (s.Position < s.Length) { byte b = reader.ReadByte(); byte xor = 0; // Bit reverse for (int i = 0; i < 8; i++) { xor = (byte)BitHelpers.SetBits(xor, BitHelpers.ExtractBits(compr_incremental_xor, 1, i), 1, 7 - i); } b = (byte)(b ^ (xor ^ 0xB9)); if (compr_incremental_xor == 0xFF) { compr_incremental_xor = 0x0; } else { compr_incremental_xor++; } decompressedStream.WriteByte(b); } decompressedStream.Position = 0; return(decompressedStream); }
/// <summary> /// Handles the data serialization /// </summary> /// <param name="s">The serializer object</param> public override void SerializeImpl(SerializerObject s) { if (s.GameSettings.GameModeSelection == GameModeSelection.MapperPC || s.GameSettings.EngineVersion == EngineVersion.R1_GBA || s.GameSettings.EngineVersion == EngineVersion.R1_DSi) { TileMapY = s.Serialize <ushort>(TileMapY, name: nameof(TileMapY)); TileMapX = 0; CollisionType = (byte)s.Serialize <ushort>((ushort)CollisionType, name: nameof(CollisionType)); } else if (s.GameSettings.EngineVersion == EngineVersion.R1_PC || s.GameSettings.EngineVersion == EngineVersion.R1_PC_Kit || s.GameSettings.EngineVersion == EngineVersion.R1_PC_Edu || s.GameSettings.EngineVersion == EngineVersion.R1_PS1_Edu || s.GameSettings.EngineVersion == EngineVersion.R1_PocketPC) { TileMapY = s.Serialize <ushort>(TileMapY, name: nameof(TileMapY)); TileMapX = 0; CollisionType = s.Serialize <byte>(CollisionType, name: nameof(CollisionType)); PC_Unk1 = s.Serialize <byte>(PC_Unk1, name: nameof(PC_Unk1)); PC_TransparencyMode = s.Serialize <R1_PC_MapTileTransparencyMode>(PC_TransparencyMode, name: nameof(PC_TransparencyMode)); PC_Unk2 = s.Serialize <byte>(PC_Unk2, name: nameof(PC_Unk2)); } else if (s.GameSettings.EngineVersion == EngineVersion.R1_PS1_JPDemoVol3 || s.GameSettings.EngineVersion == EngineVersion.R1_PS1_JPDemoVol6) { s.SerializeBitValues <int>(bitFunc => { TileMapX = (ushort)bitFunc(TileMapX, 10, name: nameof(TileMapX)); TileMapY = (ushort)bitFunc(TileMapY, 6, name: nameof(TileMapY)); CollisionType = (byte)bitFunc(CollisionType, 8, name: nameof(CollisionType)); }); } else if (s.GameSettings.EngineVersion == EngineVersion.R1_Saturn) { s.SerializeBitValues <ushort>(bitFunc => { TileMapX = (ushort)bitFunc(TileMapX, 4, name: nameof(TileMapX)); TileMapY = (ushort)bitFunc(TileMapY, 12, name: nameof(TileMapY)); }); CollisionType = s.Serialize <byte>(CollisionType, name: nameof(CollisionType)); s.Serialize <byte>(0, name: "Padding"); } else if (s.GameSettings.MajorEngineVersion == MajorEngineVersion.Rayman1_Jaguar) { s.SerializeBitValues <ushort>(bitFunc => { TileMapY = (ushort)bitFunc(TileMapY, 12, name: nameof(TileMapY)); CollisionType = (byte)bitFunc(CollisionType, 4, name: nameof(CollisionType)); }); TileMapX = 0; } else if (s.GameSettings.MajorEngineVersion == MajorEngineVersion.SNES) { s.SerializeBitValues <ushort>(bitFunc => { TileMapY = (ushort)bitFunc(TileMapY, 10, name: nameof(TileMapY)); HorizontalFlip = bitFunc(HorizontalFlip ? 1 : 0, 1, name: nameof(HorizontalFlip)) == 1; VerticalFlip = bitFunc(VerticalFlip ? 1 : 0, 1, name: nameof(VerticalFlip)) == 1; CollisionType = (byte)bitFunc(CollisionType, 4, name: nameof(CollisionType)); }); TileMapX = 0; } else if (s.GameSettings.MajorEngineVersion == MajorEngineVersion.GBA) { // TODO: Use SerializeBitValues if ((GBATileType == GBA_TileType.BGTile || GBATileType == GBA_TileType.FGTile) && s.GameSettings.EngineVersion != EngineVersion.GBA_SplinterCell_NGage && s.GameSettings.EngineVersion != EngineVersion.GBA_BatmanVengeance) { int numBits = Is8Bpp ? 9 : 10; if (s.GameSettings.EngineVersion <= EngineVersion.GBA_BatmanVengeance) { numBits = 8; }/*else if(s.GameSettings.EngineVersion >= EngineVersion.GBA_StarWarsTrilogy) { * numBits = Is8Bpp ? 9 : 10; * } else if (s.GameSettings.EngineVersion >= EngineVersion.GBA_SplinterCell) { * numBits = 9; * if (GBATileType == GBA_TileType.FGTile) numBits = 10; * }*/ ushort value = 0; value = (ushort)BitHelpers.SetBits(value, TileMapY, numBits, 0); //value = (ushort)BitHelpers.SetBits(value, VerticalFlip ? 1 : 0, 1, numBits); value = (ushort)BitHelpers.SetBits(value, HorizontalFlip ? 1 : 0, 1, numBits); value = (ushort)BitHelpers.SetBits(value, PaletteIndex, 4, 12); value = s.Serialize <ushort>(value, name: nameof(value)); TileMapY = (ushort)BitHelpers.ExtractBits(value, numBits, 0); TileMapX = 0; if (Is8Bpp) { IsFirstBlock = BitHelpers.ExtractBits(value, 1, 9) == 1; } HorizontalFlip = BitHelpers.ExtractBits(value, 1, 10) == 1; VerticalFlip = BitHelpers.ExtractBits(value, 1, 11) == 1; PaletteIndex = (byte)BitHelpers.ExtractBits(value, 4, 12); s.Log($"{nameof(TileMapY)}: {TileMapY}"); s.Log($"{nameof(HorizontalFlip)}: {HorizontalFlip}"); s.Log($"{nameof(IsFirstBlock)}: {IsFirstBlock}"); s.Log($"{nameof(PaletteIndex)}: {PaletteIndex}"); } else if (GBATileType == GBA_TileType.Mode7Tile) { ushort value = 0; value = (ushort)BitHelpers.SetBits(value, TileMapY, 9, 0); //value = (ushort)BitHelpers.SetBits(value, VerticalFlip ? 1 : 0, 1, numBits); value = (ushort)BitHelpers.SetBits(value, HorizontalFlip ? 1 : 0, 1, 9); value = s.Serialize <ushort>(value, name: nameof(value)); TileMapY = (ushort)BitHelpers.ExtractBits(value, 9, 0); TileMapX = 0; IsFirstBlock = BitHelpers.ExtractBits(value, 1, 9) == 1; HorizontalFlip = BitHelpers.ExtractBits(value, 1, 10) == 1; VerticalFlip = BitHelpers.ExtractBits(value, 1, 11) == 1; s.Log($"{nameof(TileMapY)}: {TileMapY}"); s.Log($"{nameof(HorizontalFlip)}: {HorizontalFlip}"); s.Log($"{nameof(IsFirstBlock)}: {IsFirstBlock}"); } else { int numBits = Is8Bpp ? 14 : 11; if (s.GameSettings.EngineVersion <= EngineVersion.GBA_BatmanVengeance) { numBits = 10; } else if (s.GameSettings.EngineVersion == EngineVersion.GBA_SplinterCell_NGage) { numBits = Is8Bpp ? 14 : 12; } else if (s.GameSettings.EngineVersion >= EngineVersion.GBA_SplinterCell) { numBits = Is8Bpp ? 14 : 12; } ushort value = 0; value = (ushort)BitHelpers.SetBits(value, TileMapY, numBits, 0); value = (ushort)BitHelpers.SetBits(value, HorizontalFlip ? 1 : 0, 1, numBits); value = (ushort)BitHelpers.SetBits(value, PaletteIndex, 4, 12); value = s.Serialize <ushort>(value, name: nameof(value)); TileMapY = (ushort)BitHelpers.ExtractBits(value, numBits, 0); if (s.GameSettings.EngineVersion == EngineVersion.GBA_SplinterCell_NGage && Is8Bpp) { TileMapY = (ushort)BitHelpers.ExtractBits(value, numBits - 1, 0); } TileMapX = 0; HorizontalFlip = BitHelpers.ExtractBits(value, 1, numBits) == 1; if (s.GameSettings.EngineVersion == EngineVersion.GBA_BatmanVengeance) { VerticalFlip = BitHelpers.ExtractBits(value, 1, numBits + 1) == 1; } if (!Is8Bpp) { if (s.GameSettings.EngineVersion >= EngineVersion.GBA_SplinterCell) { PaletteIndex = (byte)BitHelpers.ExtractBits(value, 3, 13); } else { PaletteIndex = (byte)BitHelpers.ExtractBits(value, 4, 12); } if (s.GameSettings.EngineVersion == EngineVersion.GBA_SplinterCell) { PaletteIndex += 8; } } else if (s.GameSettings.EngineVersion != EngineVersion.GBA_BatmanVengeance) { VerticalFlip = BitHelpers.ExtractBits(value, 1, numBits + 1) == 1; } s.Log($"{nameof(TileMapY)}: {TileMapY}"); s.Log($"{nameof(HorizontalFlip)}: {HorizontalFlip}"); s.Log($"{nameof(PaletteIndex)}: {PaletteIndex}"); } } else if (s.GameSettings.EngineVersion == EngineVersion.R1_PS1 || s.GameSettings.EngineVersion == EngineVersion.R2_PS1) { s.SerializeBitValues <ushort>(bitFunc => { TileMapX = (ushort)bitFunc(TileMapX, 4, name: nameof(TileMapX)); TileMapY = (ushort)bitFunc(TileMapY, 6, name: nameof(TileMapY)); CollisionType = (byte)bitFunc(CollisionType, 6, name: nameof(CollisionType)); }); } else if (s.GameSettings.EngineVersion == EngineVersion.R1_PS1_JP) { s.SerializeBitValues <ushort>(bitFunc => { TileMapX = (ushort)bitFunc(TileMapX, 9, name: nameof(TileMapX)); CollisionType = (byte)bitFunc(CollisionType, 7, name: nameof(CollisionType)); }); } else if (s.GameSettings.MajorEngineVersion == MajorEngineVersion.GBARRR) { if (GBARRRType == GBARRR_MapBlock.MapType.Collision) { CollisionType = s.Serialize <byte>(CollisionType, name: nameof(CollisionType)); } else if (GBARRRType == GBARRR_MapBlock.MapType.Tiles) { TileMapY = s.Serialize <ushort>(TileMapY, name: nameof(TileMapY)); } else if (GBARRRType == GBARRR_MapBlock.MapType.Foreground) { s.SerializeBitValues <ushort>(bitFunc => { TileMapY = (ushort)bitFunc(TileMapY, 10, name: nameof(TileMapY)); HorizontalFlip = bitFunc(HorizontalFlip ? 1 : 0, 1, name: nameof(HorizontalFlip)) == 1; VerticalFlip = bitFunc(VerticalFlip ? 1 : 0, 1, name: nameof(VerticalFlip)) == 1; PaletteIndex = (byte)bitFunc(PaletteIndex, 4, name: nameof(PaletteIndex)); //Unk = (byte)bitFunc(Unk, 4, name: nameof(Unk)); }); } else if (GBARRRType == GBARRR_MapBlock.MapType.Menu) { s.SerializeBitValues <ushort>(bitFunc => { TileMapY = (ushort)bitFunc(TileMapY, 8, name: nameof(TileMapY)); GBARRR_MenuUnk = (byte)bitFunc(GBARRR_MenuUnk, 2, name: nameof(GBARRR_MenuUnk)); HorizontalFlip = bitFunc(HorizontalFlip ? 1 : 0, 1, name: nameof(HorizontalFlip)) == 1; VerticalFlip = bitFunc(VerticalFlip ? 1 : 0, 1, name: nameof(VerticalFlip)) == 1; PaletteIndex = (byte)bitFunc(PaletteIndex, 4, name: nameof(PaletteIndex)); //Unk = (byte)bitFunc(Unk, 4, name: nameof(Unk)); }); } else if (GBARRRType == GBARRR_MapBlock.MapType.Mode7Tiles) { TileMapY = s.Serialize <byte>((byte)TileMapY, name: nameof(TileMapY)); } } }
public Stream EncodeStream(Stream s) { var memStream = new MemoryStream(); Reader reader = new Reader(s); using (Stream temp = new MemoryStream()) { using (Writer writer = new Writer(temp)) { byte[] compr_big_window = new byte[256 * 8]; for (int i = 0; i < 256; i++) { for (int j = 0; j < 8; j++) { compr_big_window[i * 8 + j] = (byte)i; } } byte[] compr_window = new byte[8]; for (int j = 0; j < 8; j++) { compr_window[j] = 0; } writer.Write((byte)0); // checksum writer.Write((uint)0); // size uint startPos = (uint)reader.BaseStream.Position; writer.BeginCalculateChecksum(new Checksum8Calculator()); bool isFinished = false; while (!isFinished) { uint num_bytesToCompress = 0; for (int i = 0; i < 8; i++) { if (reader.BaseStream.Position >= reader.BaseStream.Length) { break; } num_bytesToCompress++; byte b = reader.ReadByte(); compr_window[i] = b; } if (num_bytesToCompress > 0) { int maxOccurrencesInBigWindow = -1; int bestBigWindowI = 0; for (int i = 0; i < 256; i++) { int occurrencesInBigWindow = 0; for (int j = 0; j < num_bytesToCompress; j++) { if (compr_big_window[i * 8 + j] == compr_window[j]) { occurrencesInBigWindow++; } } if (occurrencesInBigWindow > maxOccurrencesInBigWindow) { maxOccurrencesInBigWindow = occurrencesInBigWindow; bestBigWindowI = i; if (occurrencesInBigWindow == num_bytesToCompress) { break; } } } writer.Write((byte)bestBigWindowI); byte windowUpdateBitArray = 0; for (int i = 0; i < Math.Min(8, num_bytesToCompress); i++) { if (compr_big_window[bestBigWindowI * 8 + i] != compr_window[i]) { windowUpdateBitArray = (byte)BitHelpers.SetBits(windowUpdateBitArray, 1, 1, i); } } writer.Write(windowUpdateBitArray); for (int i = 0; i < 8; i++) { if (windowUpdateBitArray % 2 == 1) { writer.Write((byte)compr_window[i]); } windowUpdateBitArray /= 2; } if (num_bytesToCompress >= 8) { for (int i = 0; i < 8; i++) { compr_big_window[bestBigWindowI * 8 + i] = compr_window[i]; } } else { writer.Write((byte)num_bytesToCompress); isFinished = true; } } else { isFinished = true; } } byte checksum = writer.EndCalculateChecksum <byte>(); uint decompressedSize = (uint)reader.BaseStream.Position - startPos; writer.BaseStream.Position = 0; writer.Write((byte)checksum); writer.Write((uint)decompressedSize); writer.BaseStream.Position = 0; using (Stream xor = XORStream(writer.BaseStream)) { xor.CopyTo(memStream); } } } memStream.Position = 0; return(memStream); }