private static List<LoffBlock.RoomOffset> ReadRoomOffsets(ScummBinaryReader reader, byte numRooms) { var result = new List<LoffBlock.RoomOffset>(); for (int i = 0; i < numRooms; i++) { var offset = new LoffBlock.RoomOffset { RoomId = reader.ReadByte(), Offset = reader.ReadUInt32() }; result.Add(offset); } return result; }
private static List <LoffBlock.RoomOffset> ReadRoomOffsets(ScummBinaryReader reader, byte numRooms) { var result = new List <LoffBlock.RoomOffset>(); for (int i = 0; i < numRooms; i++) { var offset = new LoffBlock.RoomOffset { RoomId = reader.ReadByte(), Offset = reader.ReadUInt32() }; result.Add(offset); } return(result); }
private ResourceIndexEntry[] ReadResourceReferenceList(ScummBinaryReader reader, ref ushort itemsCount) { itemsCount = reader.ReadUInt16(); var resourceReferenceList = new ResourceIndexEntry[itemsCount]; var roomIdList = new byte[itemsCount]; for (int i = 0; i < itemsCount; i++) { roomIdList[i] = reader.ReadByte(); } for (int i = 0; i < itemsCount; i++) { var resourceOffset = reader.ReadUInt32(); resourceReferenceList[i] = new ResourceIndexEntry(roomIdList[i], resourceOffset); } return(resourceReferenceList); }
public override Resource LoadResourceData(ScummBinaryReader reader, string resourceId, IDictionary <string, object> parameters) { var charset = new Charset(resourceId); uint blockSize = reader.FindDataBlock("CHAR"); if (blockSize == 0) { throw new InvalidOperationException("Could not find the script header block."); } // Load the room palette associated with the charset // (huge hack - I have no idea what to do when room is 0) if ((byte)parameters["RoomId"] == 0) { parameters["RoomId"] = (byte)10; } long keepPos = reader.BaseStream.Position; var roomPalette = this.resourceManager.Load <Room>("ROOM", (byte)parameters["RoomId"]).Palette; reader.BaseStream.Position = keepPos; // Read charset header information var unknown = reader.ReadBytes(6); byte[] colormap = new byte[16]; colormap[0] = 0; for (int i = 0; i < 15; ++i) { colormap[i + 1] = reader.ReadByte(); } long initPosition = reader.BaseStream.Position; byte numBitsPerPixel = reader.ReadByte(); byte bitMask = (byte)(0xFF << (8 - numBitsPerPixel)); byte fontHeight = reader.ReadByte(); short numChars = reader.ReadInt16(); uint[] offsets = new uint[numChars]; for (int i = 0; i < numChars; ++i) { offsets[i] = reader.ReadUInt32(); } // Read each char for (int i = 0; i < numChars; ++i) { if (offsets[i] == 0) { continue; } reader.BaseStream.Position = initPosition + offsets[i]; charset.Chars[i].width = reader.ReadByte(); charset.Chars[i].height = reader.ReadByte(); // a flag is needed to disable offX charset.Chars[i].offX = 0; reader.ReadByte(); charset.Chars[i].offY = reader.ReadByte(); charset.Chars[i].pic = new Texture2D(graphicsDevice, charset.Chars[i].width, charset.Chars[i].height); byte[] bytes = new byte[charset.Chars[i].width * charset.Chars[i].height * 4]; Byte bits = reader.ReadByte(); Byte remainingBits = 8; for (int y = 0; y < charset.Chars[i].height; ++y) { for (int x = 0; x < charset.Chars[i].width; ++x) { long colorId = (bits & bitMask) >> (8 - numBitsPerPixel); long color = colormap[colorId]; byte alpha = 255; if (colorId == 0) { alpha = 0; } bytes[(y * charset.Chars[i].width + x) * 4] = roomPalette[color].R; bytes[(y * charset.Chars[i].width + x) * 4 + 1] = roomPalette[color].G; bytes[(y * charset.Chars[i].width + x) * 4 + 2] = roomPalette[color].B; bytes[(y * charset.Chars[i].width + x) * 4 + 3] = alpha; bits = (byte)(bits << numBitsPerPixel); remainingBits -= numBitsPerPixel; if (remainingBits <= 0) { bits = reader.ReadByte(); remainingBits = 8; } } } charset.Chars[i].pic.SetData(bytes); } return(charset); }
public override Resource LoadResourceData(ScummBinaryReader reader, string resourceId, IDictionary <string, object> parameters) { // TODO: If the anim is mirrored, point to the same textures and do a matrix transform while rendering the costume var costume = new Costume(resourceId); // Read Room Header information if (reader.FindDataBlock("COST") == 0) { throw new InvalidOperationException("Could not find the costume header block."); } reader.BaseStream.Position -= 6; var startOffset = reader.BaseStream.Position; var size = reader.ReadUInt32(); var test = ((char)reader.ReadByte()).ToString() + ((char)reader.ReadByte()).ToString(); var animationsCount = reader.ReadByte(); var format = reader.ReadByte(); var paletteSize = ((format & 0x7F) == 0x58 || (format & 0x7F) == 0x60) ? 16 : 32; var containsRedirection = ((format & 0x7E) == 0x60); var mirrorWestPositions = (format & 0x80) == 0; // TODO: Decode bit 7 // TODO : Read the full palette var palette = new byte[paletteSize]; for (int i = 0; i < paletteSize; i++) { palette[i] = reader.ReadByte(); } var animationCommandOffset = reader.ReadUInt16(); // Read limb offsets var limbOffsets = new ushort[16]; for (int i = 0; i < 16; i++) { limbOffsets[i] = reader.ReadUInt16(); } // Read animation offsets var animationOffsets = new ushort[animationsCount]; for (int i = 0; i < animationOffsets.Length; i++) { animationOffsets[i] = reader.ReadUInt16(); } // Load the room palette associated with the costume // (huge hack - I have no idea what to do when room is 0) if ((byte)parameters["RoomId"] == 0) { parameters["RoomId"] = (byte)10; } var roomPalette = this.resourceManager.Load <Room>("ROOM", (byte)parameters["RoomId"]).Palette; for (int i = 4; i < animationsCount; i++) { try { var animation = LoadAnimation(reader, resourceId, i, startOffset, animationOffsets, limbOffsets, animationCommandOffset, palette, roomPalette, containsRedirection, (i % 4) == 0 && mirrorWestPositions); costume.Animations.Add(animation); } // TODO: Remove the empty catch later catch { } } return(costume); }
private void ReadSMAP(ScummBinaryReader reader, Image image, Color[] roomPalette) { var smapStartOffset = reader.BaseStream.Position; var stripesCount = image.Width / 8; // Create the texture data array var textureData = new byte[image.Width * image.Height * 4]; var stripeOffsets = new uint[stripesCount]; // Read the offset table for (int i = 0; i < stripesCount; i++) { var offset = reader.ReadUInt32() - 8; stripeOffsets[i] = offset; } // Read and decode each stripes for (int i = 0; i < stripesCount; i++) { reader.BaseStream.Position = smapStartOffset + stripeOffsets[i]; var stripeHeader = reader.ReadByte(); var codingShift = (byte)(stripeHeader % 10); var encoderType = stripeHeader / 10; byte[] decodedData = null; if (encoderType == (int)EncoderType.UnkAOpaque) { decodedData = DecodeUnkAStripe(reader, codingShift, image.Height, roomPalette); } else if (encoderType == (int)EncoderType.UnkBOpaque) { decodedData = DecodeUnkBStripe(reader, codingShift, image.Height, roomPalette); } else if (encoderType == (int)EncoderType.UnkCOpaque) { decodedData = DecodeUnkCStripe(reader, codingShift, image.Height, roomPalette); } if (decodedData != null) { int decodedDataIndex = 0; for (int j = 0; j < image.Height; j++) { for (int k = 0; k < 8; k++) { var pixelIndex = i * 32 + j * image.Width * 4 + k * 4; textureData[pixelIndex] = decodedData[decodedDataIndex]; textureData[pixelIndex + 1] = decodedData[decodedDataIndex + 1]; textureData[pixelIndex + 2] = decodedData[decodedDataIndex + 2]; textureData[pixelIndex + 3] = decodedData[decodedDataIndex + 3]; decodedDataIndex += 4; } } } } image.Texture = new Microsoft.Xna.Framework.Graphics.Texture2D(graphicsDevice, image.Width, image.Height, false, Microsoft.Xna.Framework.Graphics.SurfaceFormat.Color); image.Texture.SetData(textureData); }
private void ReadIndexBlock(ScummBinaryReader reader, string blockType) { if (blockType == "RNAM") { byte roomId = reader.ReadByte(); while (roomId != 0) { var roomNameData = reader.ReadBytes(9); var roomName = string.Empty; for (int i = 0; i < roomNameData.Length; i++) { roomName += (char)(roomNameData[i] ^ 0xFF); } roomId = reader.ReadByte(); } } else if (blockType == "MAXS") { var variablesCount = reader.ReadUInt16(); // Skip 2 bytes reader.ReadUInt16(); uint bitVariablesCount = reader.ReadUInt16(); uint localObjectsCount = reader.ReadUInt16(); uint newNamesCount = reader.ReadUInt16(); uint charsetsCount = reader.ReadUInt16(); uint verbsCount = reader.ReadUInt16(); uint arraysCount = reader.ReadUInt16(); uint inventoryObjectsCount = reader.ReadUInt16(); } else if (blockType == "DROO") { // just read, not keeping anything besides roomsCount ReadResourceReferenceList(reader, ref roomsCount); } else if (blockType == "DSCR") { this.scriptsIndexList = ReadResourceReferenceList(reader, ref scriptsCount); } else if (blockType == "DSOU") { this.soundsIndexList = ReadResourceReferenceList(reader, ref soundsCount); } else if (blockType == "DCOS") { this.costumesIndexList = ReadResourceReferenceList(reader, ref costumesCount); } else if (blockType == "DCHR") { this.charsetsIndexList = ReadResourceReferenceList(reader, ref charsetsCount); } else if (blockType == "DOBJ") { uint itemsCount = reader.ReadUInt16(); objects = new Object[itemsCount]; for (int i = 0; i < itemsCount; i++) { objects[i] = new Object(); objects[i].Id = (UInt16)i; objects[i].OwnerState = reader.ReadByte(); } for (int i = 0; i < itemsCount; i++) { objects[i].ClassData = reader.ReadUInt32(); } } else if (blockType == "AARY") { } else { //throw new InvalidOperationException(string.Format("Cannot read block of type '{0}' in the index file.", blockType)); } }