public ContainerSG3(string filename) { this.FilenameSG3 = filename; this.Filename555 = Path.ChangeExtension(filename, ".555"); if (Path.GetExtension(filename).ToUpper() == ".SG2") { MAX_FILES = 100; } using (var f = new FileStream(filename, FileMode.Open)) { using (var b = new BinaryReader(f, Encoding.ASCII)) { //OFFSET TYPE DESCRIPTION // 0 uint For some SG's, the filesize, for others, it's a fixed value // 4 uint Version number, always 0xd3 for C3's sg2 files // 8 uint (unknown) //12 int Maximum number of image records in this file //16 int Number of image records in use //20 int Number of bitmap records in use (maximum is 100 for SG2, 200 for SG3 //24 int Unknown: appears to be the number of bitmap records minus one //28 uint Total filesize of all loaded graphics (.555 files) //32 uint Filesize of the .555 file that "belongs" to this .sg2: the one with the same name //36 uint Filesize of any images pulled from external .555 files var header0x00 = b.ReadUInt32(); // 0x0000: 28 9B 0A 00 var header0x04 = b.ReadUInt32(); // 0x0004: D5 00 00 00 var header0x08 = b.ReadUInt32(); // 0x0008: it's some number this.MaxImages = b.ReadUInt32(); // 0x000C: max images count this.TotalImages = b.ReadUInt32(); // 0x0010: total images count this.TotalFiles1 = b.ReadUInt32(); // 0x0014: total files count this.TotalFiles2 = b.ReadUInt32(); // 0x0018: total user files count var fileSize555_All = b.ReadInt32(); // 0x001C: total filesize of all loaded 555 files var fileSize555_This = b.ReadUInt32(); // 0x0020: *.555 file's size - 4 var fileSize555_External = b.ReadInt32(); // 0x0024: total filesize of all external 555 files var header0x28 = b.ReadBytes(40); // 0x0028: 40 bytes empty for (int i = 0; i < MAX_SPRITES; i++) { this.SpriteImageIndex[i] = b.ReadUInt16(); } for (int i = 0; i < MAX_FILES; i++) { //OFFSET TYPE DESCRIPTION // 0 string 65 bytes, the filename of the .bmp file. This translates to the // name of the .555 file, if it's external. // 65 string 51 bytes, comment for this bitmap record //116 int Width of some image in the bitmap (don't pay much attention to this) //120 int Height of some image in the bitmap (idem) //124 uint Number of images in this bitmap //128 uint Index of the first image of this bitmap //132 uint Index of the last image of this bitmap //136 byte* 64 bytes, unkwnown var cname = b.ReadChars(65); // 0 var cdescription = b.ReadChars(51); // 65 var width = b.ReadUInt32(); // 116 var height = b.ReadUInt32(); // 120 var imagesCount = b.ReadUInt32(); // 124 var imagesFirst = b.ReadUInt32(); // 128 var imagesLast = b.ReadUInt32(); // 132 var data = b.ReadBytes(64); // 136 var name = new String(cname, 0, Array.IndexOf(cname, '\0')); var description = new String(cdescription, 0, Array.IndexOf(cdescription, '\0')); if (!string.IsNullOrEmpty(name)) { var sg2File = new Sg3File(); sg2File.Description = description; sg2File.Filename = name; sg2File.LastImage = imagesLast; sg2File.FirstImage = imagesFirst; sg2File.Count = imagesCount; this.Files.Add(sg2File); } } for (ushort i = 0; i < this.MaxImages; i++) { //OFFSET TYPE DESCRIPTION // 0 uint Offset into the .555 file. Of note: if it's an external .555 file, // you have to subtract one from this offset! // 4 uint Length of the image data (total) // 8 uint Length of the image data (tiles) // 12 uint (unknown, zero bytes) // 16 uint Invert offset. For sprites (walkers), the image of the walker // moving to the left is the mirrored version of the image of the // walker going right. If this is set, copy the image at the index // (current - invert offset) and mirror it vertically. // 20 ushort Width of the image // 22 ushort Height of the image // 24 byte* 6 unknown bytes. At least the first 4 bytes are 2 shorts // 30 ushort Number of frames per animation (ex. 12 frames in the 'Walking North' animation) // 32 ushort Number of animations (There is an animation of the walker walking north, south, etc...) // 34 short animation offset // 36 short animation offset // 38 byte* 12 unknown bytes. // 50 ushort Type of image. See below. // 52 byte Flag: 0 = use internal .555, 1 = use external .555 (defined in bitmap) // 53 byte* 2 bytes, 2 unknown flags // 55 byte Tile Size for isometric data // 56 byte Bitmap ID (not always filled in correctly for SG3 files) // 57 byte* 7 bytes, unknown //-- For sg3 files with alpha masks: -- // 64 uint Offset of alpha mask // 68 uint Length of alpha mask data var offset = b.ReadUInt32(); // 0 var imageDataTotalLength = b.ReadUInt32(); // 4 var imageDataTilesLenght = b.ReadUInt32(); // 8 var unknown12 = b.ReadUInt32(); // 12 var offsetInvert = b.ReadUInt32(); // 16 var width = b.ReadUInt16(); // 20 var height = b.ReadUInt16(); // 22 var unknown24 = b.ReadBytes(6); // 24 var totalFramesPerAnimation = b.ReadUInt16(); // 30 var totalAnimations = b.ReadUInt16(); // 32 var unknown32 = b.ReadBytes(12 + 2 + 2); // 34 var type = b.ReadUInt16(); // 50 var externalFlag = b.ReadByte(); // 52 var unknown53 = b.ReadBytes(2); // 53 var tileSize = b.ReadByte(); // 55 var bitmapId = b.ReadByte(); // 56 var unknown57 = b.ReadBytes(7); // 57 f.Seek(-(8 * 4 + 32), SeekOrigin.Current); var data = b.ReadBytes(32 + 8 * 4); if (i <= this.TotalImages) { var sg2Bitmap = new Sg3Image(); sg2Bitmap.Offset = offset; sg2Bitmap.DataLenghtTotal = imageDataTotalLength; sg2Bitmap.DataLengthTiles = imageDataTilesLenght; sg2Bitmap.Width = width; sg2Bitmap.Height = height; sg2Bitmap.Type = (Bitmap555Type)type; sg2Bitmap.ExternalFlag = externalFlag; sg2Bitmap.TileSize = tileSize; sg2Bitmap.Data = data; // bitmap is valid if (width != 0 && height != 0) { if (sg2Bitmap.Type == Bitmap555Type.Isometric) { if (externalFlag != 0) throw new NotImplementedException("Not able to read external tile images"); for (uint tile = 0; tile < tileSize * tileSize; tile++) { var bitmap = Bitmap555.LoadIsometricBitmap(this.Filename555, width, height, offset + tile * Bitmap555.TILE_BYTES); sg2Bitmap.Tiles.Add(bitmap); } if (imageDataTotalLength - imageDataTilesLenght > 0) { var poffset = offset + imageDataTilesLenght; var plength = imageDataTotalLength - imageDataTilesLenght; sg2Bitmap.Plain = Bitmap555.LoadPlainCompressedBitmap(this.Filename555, width, height, poffset, plength); } } else { if (externalFlag == 0) { sg2Bitmap.Plain = Bitmap555.Load((Bitmap555Type)type, this.Filename555, width, height, offset); } else { var file = this.Files.First(ff => ff.FirstImage <= i && ff.LastImage >= i); var externalFilename = Path.ChangeExtension(Path.GetDirectoryName(filename) + "\\" + file.Filename, ".555"); if (!File.Exists(externalFilename)) { externalFilename = Path.ChangeExtension(Path.GetDirectoryName(filename) + "\\555\\" + file.Filename, ".555"); } sg2Bitmap.Plain = Bitmap555.Load((Bitmap555Type)type, externalFilename, width, height, offset - 1); } } //sg2Bitmap.Plain.Save(@"C:\Users\bbdnet6039\Downloads\OpenPharaoh\Test\" + i.ToString() + ".bmp", System.Drawing.Imaging.ImageFormat.Bmp); } this.Images.Add(i, sg2Bitmap); } } for (int i = 0; i < MAX_SPRITES; i++) { var cname = b.ReadChars(48); this.SpriteNames[i] = new String(cname, 0, Array.IndexOf(cname, '\0')); } } } }
public ContainerSG3(string filename) { this.FilenameSG3 = filename; this.Filename555 = Path.ChangeExtension(filename, ".555"); if (Path.GetExtension(filename).ToUpper() == ".SG2") { MAX_FILES = 100; } using (var f = new FileStream(filename, FileMode.Open)) { using (var b = new BinaryReader(f, Encoding.ASCII)) { //OFFSET TYPE DESCRIPTION // 0 uint For some SG's, the filesize, for others, it's a fixed value // 4 uint Version number, always 0xd3 for C3's sg2 files // 8 uint (unknown) //12 int Maximum number of image records in this file //16 int Number of image records in use //20 int Number of bitmap records in use (maximum is 100 for SG2, 200 for SG3 //24 int Unknown: appears to be the number of bitmap records minus one //28 uint Total filesize of all loaded graphics (.555 files) //32 uint Filesize of the .555 file that "belongs" to this .sg2: the one with the same name //36 uint Filesize of any images pulled from external .555 files var header0x00 = b.ReadUInt32(); // 0x0000: 28 9B 0A 00 var header0x04 = b.ReadUInt32(); // 0x0004: D5 00 00 00 var header0x08 = b.ReadUInt32(); // 0x0008: it's some number this.MaxImages = b.ReadUInt32(); // 0x000C: max images count this.TotalImages = b.ReadUInt32(); // 0x0010: total images count this.TotalFiles1 = b.ReadUInt32(); // 0x0014: total files count this.TotalFiles2 = b.ReadUInt32(); // 0x0018: total user files count var fileSize555_All = b.ReadInt32(); // 0x001C: total filesize of all loaded 555 files var fileSize555_This = b.ReadUInt32(); // 0x0020: *.555 file's size - 4 var fileSize555_External = b.ReadInt32(); // 0x0024: total filesize of all external 555 files var header0x28 = b.ReadBytes(40); // 0x0028: 40 bytes empty for (int i = 0; i < MAX_SPRITES; i++) { this.SpriteImageIndex[i] = b.ReadUInt16(); } for (int i = 0; i < MAX_FILES; i++) { //OFFSET TYPE DESCRIPTION // 0 string 65 bytes, the filename of the .bmp file. This translates to the // name of the .555 file, if it's external. // 65 string 51 bytes, comment for this bitmap record //116 int Width of some image in the bitmap (don't pay much attention to this) //120 int Height of some image in the bitmap (idem) //124 uint Number of images in this bitmap //128 uint Index of the first image of this bitmap //132 uint Index of the last image of this bitmap //136 byte* 64 bytes, unkwnown var cname = b.ReadChars(65); // 0 var cdescription = b.ReadChars(51); // 65 var width = b.ReadUInt32(); // 116 var height = b.ReadUInt32(); // 120 var imagesCount = b.ReadUInt32(); // 124 var imagesFirst = b.ReadUInt32(); // 128 var imagesLast = b.ReadUInt32(); // 132 var data = b.ReadBytes(64); // 136 var name = new String(cname, 0, Array.IndexOf(cname, '\0')); var description = new String(cdescription, 0, Array.IndexOf(cdescription, '\0')); if (!string.IsNullOrEmpty(name)) { var sg2File = new Sg3File(); sg2File.Description = description; sg2File.Filename = name; sg2File.LastImage = imagesLast; sg2File.FirstImage = imagesFirst; sg2File.Count = imagesCount; this.Files.Add(sg2File); } } for (ushort i = 0; i < this.MaxImages; i++) { //OFFSET TYPE DESCRIPTION // 0 uint Offset into the .555 file. Of note: if it's an external .555 file, // you have to subtract one from this offset! // 4 uint Length of the image data (total) // 8 uint Length of the image data (tiles) // 12 uint (unknown, zero bytes) // 16 uint Invert offset. For sprites (walkers), the image of the walker // moving to the left is the mirrored version of the image of the // walker going right. If this is set, copy the image at the index // (current - invert offset) and mirror it vertically. // 20 ushort Width of the image // 22 ushort Height of the image // 24 byte* 6 unknown bytes. At least the first 4 bytes are 2 shorts // 30 ushort Number of frames per animation (ex. 12 frames in the 'Walking North' animation) // 32 ushort Number of animations (There is an animation of the walker walking north, south, etc...) // 34 short animation offset // 36 short animation offset // 38 byte* 12 unknown bytes. // 50 ushort Type of image. See below. // 52 byte Flag: 0 = use internal .555, 1 = use external .555 (defined in bitmap) // 53 byte* 2 bytes, 2 unknown flags // 55 byte Tile Size for isometric data // 56 byte Bitmap ID (not always filled in correctly for SG3 files) // 57 byte* 7 bytes, unknown //-- For sg3 files with alpha masks: -- // 64 uint Offset of alpha mask // 68 uint Length of alpha mask data var offset = b.ReadUInt32(); // 0 var imageDataTotalLength = b.ReadUInt32(); // 4 var imageDataTilesLenght = b.ReadUInt32(); // 8 var unknown12 = b.ReadUInt32(); // 12 var offsetInvert = b.ReadUInt32(); // 16 var width = b.ReadUInt16(); // 20 var height = b.ReadUInt16(); // 22 var unknown24 = b.ReadBytes(6); // 24 var totalFramesPerAnimation = b.ReadUInt16(); // 30 var totalAnimations = b.ReadUInt16(); // 32 var unknown32 = b.ReadBytes(12 + 2 + 2); // 34 var type = b.ReadUInt16(); // 50 var externalFlag = b.ReadByte(); // 52 var unknown53 = b.ReadBytes(2); // 53 var tileSize = b.ReadByte(); // 55 var bitmapId = b.ReadByte(); // 56 var unknown57 = b.ReadBytes(7); // 57 f.Seek(-(8 * 4 + 32), SeekOrigin.Current); var data = b.ReadBytes(32 + 8 * 4); if (i <= this.TotalImages) { var sg2Bitmap = new Sg3Image(); sg2Bitmap.Offset = offset; sg2Bitmap.DataLenghtTotal = imageDataTotalLength; sg2Bitmap.DataLengthTiles = imageDataTilesLenght; sg2Bitmap.Width = width; sg2Bitmap.Height = height; sg2Bitmap.Type = (Bitmap555Type)type; sg2Bitmap.ExternalFlag = externalFlag; sg2Bitmap.TileSize = tileSize; sg2Bitmap.Data = data; // bitmap is valid if (width != 0 && height != 0) { if (sg2Bitmap.Type == Bitmap555Type.Isometric) { if (externalFlag != 0) { throw new NotImplementedException("Not able to read external tile images"); } for (uint tile = 0; tile < tileSize * tileSize; tile++) { var bitmap = Bitmap555.LoadIsometricBitmap(this.Filename555, width, height, offset + tile * Bitmap555.TILE_BYTES); sg2Bitmap.Tiles.Add(bitmap); } if (imageDataTotalLength - imageDataTilesLenght > 0) { var poffset = offset + imageDataTilesLenght; var plength = imageDataTotalLength - imageDataTilesLenght; sg2Bitmap.Plain = Bitmap555.LoadPlainCompressedBitmap(this.Filename555, width, height, poffset, plength); } } else { if (externalFlag == 0) { sg2Bitmap.Plain = Bitmap555.Load((Bitmap555Type)type, this.Filename555, width, height, offset); } else { var file = this.Files.First(ff => ff.FirstImage <= i && ff.LastImage >= i); var externalFilename = Path.ChangeExtension(Path.GetDirectoryName(filename) + "\\" + file.Filename, ".555"); if (!File.Exists(externalFilename)) { externalFilename = Path.ChangeExtension(Path.GetDirectoryName(filename) + "\\555\\" + file.Filename, ".555"); } sg2Bitmap.Plain = Bitmap555.Load((Bitmap555Type)type, externalFilename, width, height, offset - 1); } } //sg2Bitmap.Plain.Save(@"C:\Users\bbdnet6039\Downloads\OpenPharaoh\Test\" + i.ToString() + ".bmp", System.Drawing.Imaging.ImageFormat.Bmp); } this.Images.Add(i, sg2Bitmap); } } for (int i = 0; i < MAX_SPRITES; i++) { var cname = b.ReadChars(48); this.SpriteNames[i] = new String(cname, 0, Array.IndexOf(cname, '\0')); } } } }