From bb18303eb4c6024d9b9644ef21001c5cb2f4060c Mon Sep 17 00:00:00 2001 From: morkt Date: Sun, 16 Oct 2016 09:22:53 +0400 Subject: [PATCH] IBinaryStream migration. --- ArcFormats/AZSys/ArcEncrypted.cs | 2 +- ArcFormats/AZSys/ImageCPB.cs | 71 ++--- ArcFormats/AZSys/ImageTYP1.cs | 52 ++- ArcFormats/Abel/ArcARC.cs | 2 +- ArcFormats/Abel/ImageGPS.cs | 28 +- ArcFormats/Actgs/ArcDAT.cs | 4 +- ArcFormats/ActiveSoft/ImageEDT.cs | 67 ++-- ArcFormats/AdvSys/ImageGR2.cs | 55 ++-- ArcFormats/AdvSys/ImageGWD.cs | 4 +- ArcFormats/AliceSoft/ArcAFA.cs | 2 +- ArcFormats/AliceSoft/ImageDCF.cs | 12 +- ArcFormats/AliceSoft/ImageQNT.cs | 28 +- ArcFormats/Amaterasu/ArcAMI.cs | 10 +- ArcFormats/Amaterasu/ImageGRP.cs | 24 +- ArcFormats/AnimeGameSystem/ArcDAT.cs | 2 +- ArcFormats/AnimeGameSystem/AudioPCM.cs | 6 +- ArcFormats/AnimeGameSystem/ImageAinos.cs | 95 +++--- ArcFormats/Ankh/ArcGRP.cs | 6 +- ArcFormats/Ankh/AudioPCM.cs | 2 +- ArcFormats/Aoi/ArcBOX.cs | 2 +- ArcFormats/Aoi/AudioAOG.cs | 10 +- ArcFormats/Aoi/ImageAGF.cs | 10 +- ArcFormats/ArcAST.cs | 4 +- ArcFormats/ArcAVC.cs | 2 +- ArcFormats/ArcAil.cs | 2 +- ArcFormats/ArcKogado.cs | 2 +- ArcFormats/ArcLST.cs | 2 +- ArcFormats/ArcNEKO.cs | 17 +- ArcFormats/ArcPACKDAT.cs | 2 +- ArcFormats/ArcPBX.cs | 2 +- ArcFormats/ArcSPack.cs | 2 +- ArcFormats/Astronauts/ArcGXP.cs | 2 +- ArcFormats/AudioMP3.cs | 8 +- ArcFormats/AudioOGG.cs | 4 +- ArcFormats/AudioVOC.cs | 12 +- ArcFormats/Banana/ImageMAG.cs | 28 +- ArcFormats/Bishop/ImageBSG.cs | 58 ++-- ArcFormats/BlackCyc/AudioVAW.cs | 12 +- ArcFormats/BlackCyc/ImageDWQ.cs | 40 ++- ArcFormats/BlackRainbow/ImageBMD.cs | 24 +- ArcFormats/BlackRainbow/ImageBMZ.cs | 20 +- ArcFormats/BlueGale/ImageZBM.cs | 56 ++-- ArcFormats/BlueGale/VideoAMV.cs | 2 +- ArcFormats/Bruns/ImageEENC.cs | 2 +- ArcFormats/CaramelBox/ArcARC3.cs | 2 +- ArcFormats/CaramelBox/ArcARC4.cs | 2 +- ArcFormats/CatSystem/ArcINT.cs | 2 +- ArcFormats/CatSystem/ImageHG2.cs | 53 ++-- ArcFormats/CatSystem/ImageHG3.cs | 73 ++--- ArcFormats/Cherry/ArcCherry.cs | 4 +- ArcFormats/Cherry/ImageGRP.cs | 42 ++- ArcFormats/Circus/ArcValkyrieComplex.cs | 2 +- ArcFormats/Circus/AudioPCM.cs | 73 ++--- ArcFormats/Circus/ImageCRX.cs | 10 +- ArcFormats/Circus/ImageCRXD.cs | 10 +- ArcFormats/Cmvs/ArcCPZ.cs | 2 +- ArcFormats/Cmvs/ArcPBZ.cs | 2 +- ArcFormats/Cmvs/ImagePB3.cs | 43 ++- ArcFormats/Cri/ArcCPK.cs | 2 +- ArcFormats/Cri/AudioADX.cs | 2 +- ArcFormats/Cri/ImageBIP.cs | 87 +++-- ArcFormats/Cri/ImageSPC.cs | 4 +- ArcFormats/Crowd/AudioEOG.cs | 4 +- ArcFormats/Crowd/ImageCWL.cs | 34 +- ArcFormats/Crowd/ImageCWP.cs | 59 ++-- ArcFormats/Crowd/ImageZBM.cs | 18 +- ArcFormats/CsWare/ArcPCS.cs | 2 +- ArcFormats/Cyberworks/AudioTINK.cs | 5 +- ArcFormats/DDSystem/ArcDDP.cs | 2 +- ArcFormats/Dac/ArcDPK.cs | 2 +- ArcFormats/Dac/ImageDGC.cs | 83 ++--- ArcFormats/Dogenzaka/ImageRSA.cs | 14 +- ArcFormats/DraftImage.cs | 4 +- ArcFormats/DxLib/ArcDX.cs | 2 +- ArcFormats/DxLib/ArcMED.cs | 2 +- ArcFormats/Eagls/ArcEAGLS.cs | 2 +- ArcFormats/Eagls/ImageGR.cs | 9 +- ArcFormats/Emic/ImageMWP.cs | 16 +- ArcFormats/EmonEngine/ArcEME.cs | 2 +- ArcFormats/Emote/ArcPSB.cs | 10 +- ArcFormats/Entis/AudioMIO.cs | 12 +- ArcFormats/Entis/ImageERI.cs | 26 +- ArcFormats/Ethornell/ArcBGI.cs | 2 +- ArcFormats/Ethornell/AudioBGI.cs | 12 +- ArcFormats/Ethornell/ImageBGI.cs | 65 ++-- ArcFormats/Eushully/ImageAGF.cs | 26 +- ArcFormats/Eushully/ImageGP.cs | 60 ++-- ArcFormats/ExHibit/ImageGYU.cs | 33 +- ArcFormats/FC01/ArcMRG.cs | 10 +- ArcFormats/FC01/ImageACD.cs | 26 +- ArcFormats/FC01/ImageCLM.cs | 24 +- ArcFormats/FC01/ImageMCG.cs | 24 +- ArcFormats/Favorite/ArcFVP.cs | 2 +- ArcFormats/Favorite/ImageHZC.cs | 26 +- ArcFormats/Ffa/ArcBlackPackage.cs | 2 +- ArcFormats/Ffa/AudioWA1.cs | 19 +- ArcFormats/Ffa/AudioWA2.cs | 26 +- ArcFormats/Ffa/ImagePT1.cs | 55 ++-- ArcFormats/G2/ArcGCEX.cs | 2 +- ArcFormats/G2/ImageBGRA.cs | 16 +- ArcFormats/Glib2/ArcG2.cs | 2 +- ArcFormats/Glib2/ImagePGX.cs | 22 +- ArcFormats/Gpk2/ImageGFB.cs | 25 +- ArcFormats/GsPack/ImageGS.cs | 43 ++- ArcFormats/Hexenhaus/ArcWAG.cs | 13 +- ArcFormats/Ikura/ArcDRS.cs | 2 +- ArcFormats/Ikura/ImageDRG.cs | 297 +++++++++-------- ArcFormats/Ikura/ImageGGP.cs | 26 +- ArcFormats/Ikura/ImageYGP.cs | 48 ++- ArcFormats/ImageDDS.cs | 30 +- ArcFormats/ImageEGN.cs | 94 +++--- ArcFormats/ImageISG.cs | 51 ++- ArcFormats/ImageLZ.cs | 14 +- ArcFormats/ImageMB.cs | 2 +- ArcFormats/ImagePSD.cs | 36 +-- ArcFormats/ImagePTI.cs | 10 +- ArcFormats/ImageSeraph.cs | 65 ++-- ArcFormats/Interheart/ArcFPK.cs | 2 +- ArcFormats/Interheart/ImageKG.cs | 75 ++--- ArcFormats/Ipac/AudioWST.cs | 2 +- ArcFormats/Ivory/AudioCTRK.cs | 2 +- ArcFormats/Ivory/ImageSG.cs | 14 +- ArcFormats/Kaas/ImageKAAS.cs | 16 +- ArcFormats/Kaguya/ArcKaguya.cs | 2 +- ArcFormats/Kaguya/ArcLINK.cs | 2 +- ArcFormats/Kaguya/ImageAO.cs | 25 +- ArcFormats/Kaguya/ImageAP.cs | 48 ++- ArcFormats/Kaguya/ImageAPS.cs | 109 +++---- ArcFormats/KiriKiri/ImageTLG.cs | 77 ++--- ArcFormats/Liar/ImageLIM.cs | 48 +-- ArcFormats/Liar/ImageWCG.cs | 58 ++-- ArcFormats/Lilim/ArcABM.cs | 58 ++-- ArcFormats/Lilim/ArcAOS.cs | 2 +- ArcFormats/Lilim/ImageABM.cs | 20 +- ArcFormats/LiveMaker/ImageGAL.cs | 30 +- ArcFormats/Lucifen/ArcLPK.cs | 2 +- ArcFormats/Lucifen/ImageELG.cs | 222 ++++++------- ArcFormats/MAI/ImageMAI.cs | 59 ++-- ArcFormats/Macromedia/AudioEDIM.cs | 7 +- ArcFormats/Macromedia/ImageBITD.cs | 8 +- ArcFormats/Majiro/ImageRCT.cs | 153 ++++----- ArcFormats/Malie/ImageDZI.cs | 21 +- ArcFormats/Malie/ImageMGF.cs | 18 +- ArcFormats/MangaGamer/ArcMGPK.cs | 2 +- ArcFormats/Marble/ArcMBL.cs | 2 +- ArcFormats/Marble/AudioWADY.cs | 68 ++-- ArcFormats/Marble/ImagePRS.cs | 32 +- ArcFormats/Masys/ImageAG.cs | 106 +++---- ArcFormats/MnoViolet/ImageDIF.cs | 35 +- ArcFormats/MnoViolet/ImageGRA.cs | 61 ++-- ArcFormats/MokoPro/CompressedFile.cs | 16 +- ArcFormats/Moonhir/ArcFPK.cs | 4 +- ArcFormats/Nags/ImageNGP.cs | 41 ++- ArcFormats/NekoSDK/ImageALP.cs | 2 +- ArcFormats/Nexas/ArcPAC.cs | 2 +- ArcFormats/Nexas/ImageGRP.cs | 32 +- ArcFormats/NitroPlus/ArcNitro.cs | 2 +- ArcFormats/NonColor/ArcDAT.cs | 2 +- ArcFormats/Pajamas/ArcGameDat.cs | 8 +- ArcFormats/Pajamas/ImageEPA.cs | 52 ++- ArcFormats/Palette/ImagePGA.cs | 11 +- ArcFormats/Primel/ImageGBC.cs | 18 +- ArcFormats/Propeller/ArcMGR.cs | 2 +- ArcFormats/Propeller/ArcMPK.cs | 2 +- ArcFormats/Propeller/ImageMGR.cs | 77 +++-- ArcFormats/Qlie/ArcABMP.cs | 4 +- ArcFormats/Qlie/ArcQLIE.cs | 2 +- ArcFormats/Qlie/ImageDPNG.cs | 66 ++-- ArcFormats/RealLive/ArcG00.cs | 3 +- ArcFormats/RealLive/AudioNWA.cs | 53 ++-- ArcFormats/RealLive/AudioOWP.cs | 7 +- ArcFormats/RealLive/ImageG00.cs | 67 ++-- ArcFormats/RealLive/ImagePDT.cs | 40 +-- ArcFormats/Resources/Formats.dat | Bin 513432 -> 513921 bytes ArcFormats/RiddleSoft/ArcPAC.cs | 2 +- ArcFormats/RiddleSoft/ImageGCP.cs | 23 +- ArcFormats/Risa/ImageSYG.cs | 14 +- ArcFormats/SHSystem/ArcHXP.cs | 2 +- ArcFormats/Sas5/ArcSec5.cs | 2 +- ArcFormats/Sas5/ImageIAR.cs | 36 +-- ArcFormats/ScenePlayer/AudioPMW.cs | 4 +- ArcFormats/ScenePlayer/ImagePMP.cs | 14 +- ArcFormats/ScrPlayer/ImageI.cs | 16 +- ArcFormats/ShiinaRio/ArcWARC.cs | 2 +- ArcFormats/ShiinaRio/AudioOGV.cs | 4 +- ArcFormats/ShiinaRio/AudioPAD.cs | 8 +- ArcFormats/ShiinaRio/ImageMI4.cs | 41 +-- ArcFormats/ShiinaRio/ImageS25.cs | 78 ++--- ArcFormats/Silky/ArcIFL.cs | 2 +- ArcFormats/Silky/ImageAKB.cs | 37 +-- ArcFormats/Silky/ImageGRD.cs | 17 +- ArcFormats/Silky/ImageIGF.cs | 22 +- ArcFormats/Silky/ImageMFG.cs | 59 ++-- ArcFormats/Silky/ImageMSK.cs | 18 +- ArcFormats/Silky/ImageZIT.cs | 36 +-- ArcFormats/Slg/AudioVOI.cs | 4 +- ArcFormats/Slg/ImageALB.cs | 47 ++- ArcFormats/Slg/ImageTIG.cs | 16 +- ArcFormats/Softpal/ArcPAC.cs | 2 +- ArcFormats/Softpal/AudioBGM.cs | 12 +- ArcFormats/Softpal/ImageBPIC.cs | 14 +- ArcFormats/Softpal/ImagePGD.cs | 119 +++---- ArcFormats/Softpal/ImagePIC.cs | 30 +- ArcFormats/StudioEgo/ArcPAK0.cs | 2 +- ArcFormats/StudioEgo/ImageANT.cs | 12 +- ArcFormats/SuperNekoX/ArcGPC.cs | 29 +- ArcFormats/Tactics/ArcTactics.cs | 8 +- ArcFormats/Tactics/ImageTGF.cs | 20 +- ArcFormats/TamaSoft/AudioESD.cs | 14 +- ArcFormats/TamaSoft/ImageBTN.cs | 17 +- ArcFormats/TamaSoft/ImageSUR.cs | 14 +- ArcFormats/TechnoBrain/ImageIPH.cs | 71 ++--- ArcFormats/Tmr-Hiro/ArcPAC.cs | 2 +- ArcFormats/Tmr-Hiro/AudioTmr.cs | 17 +- ArcFormats/Tmr-Hiro/ImageGRD.cs | 34 +- ArcFormats/TopCat/ArcTCD3.cs | 6 +- ArcFormats/TopCat/ImageSPD.cs | 12 +- ArcFormats/Triangle/ImageIAF.cs | 10 +- ArcFormats/UMeSoft/ArcPK.cs | 2 +- ArcFormats/UMeSoft/ImageGRX.cs | 82 ++--- ArcFormats/Vitamin/ImageMFC.cs | 17 +- ArcFormats/Vitamin/ImageSBI.cs | 16 +- ArcFormats/VnEngine/ImageZAW.cs | 20 +- ArcFormats/WebP/ImageWEBP.cs | 8 +- ArcFormats/WildBug/AudioWPN.cs | 21 +- ArcFormats/WildBug/AudioWWA.cs | 21 +- ArcFormats/WildBug/ImageWBM.cs | 30 +- ArcFormats/Will/ArcPulltop.cs | 2 +- ArcFormats/Will/ArcWILL.cs | 2 +- ArcFormats/Will/ImageWIP.cs | 68 ++-- ArcFormats/Xuse/ArcWAG.cs | 2 +- ArcFormats/Xuse/ArcXuse.cs | 2 +- ArcFormats/YuRis/ArcYPF.cs | 4 +- ArcFormats/YuRis/ImageYCG.cs | 26 +- ArcFormats/Yuka/ArcYKC.cs | 7 +- ArcFormats/Yuka/ImageYKG.cs | 52 +-- ArcFormats/Zyx/ArcBDF.cs | 2 +- ArcFormats/Zyx/ImageSPL.cs | 74 ++--- ArcFormats/elf/ImageG24.cs | 37 +-- ArcFormats/elf/ImageGCC.cs | 32 +- ArcFormats/elf/ImageGP8.cs | 55 ++-- ArcFormats/elf/ImageGPH.cs | 6 +- ArcFormats/elf/ImageHIZ.cs | 68 ++-- ArcFormats/uGOS/ArcDET.cs | 2 +- ArcFormats/uGOS/ImageBMP.cs | 52 ++- GameRes/ArcView.cs | 22 +- GameRes/BinaryStream.cs | 387 +++++++++++++++-------- GameRes/ByteArray.cs | 196 ++++++++++++ GameRes/GameRes.cs | 2 +- GameRes/GameRes.csproj | 1 + GameRes/Utility.cs | 11 +- 251 files changed, 3277 insertions(+), 3630 deletions(-) create mode 100644 GameRes/ByteArray.cs diff --git a/ArcFormats/AZSys/ArcEncrypted.cs b/ArcFormats/AZSys/ArcEncrypted.cs index bd02620b..1ad23e8e 100644 --- a/ArcFormats/AZSys/ArcEncrypted.cs +++ b/ArcFormats/AZSys/ArcEncrypted.cs @@ -248,7 +248,7 @@ namespace GameRes.Formats.AZSys Buffer.BlockCopy (data, 0, header, 0, 0x10); return new PrefixStream (header, asb); } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } uint ReadSysenvSeed (ArcView file, IEnumerable dir, uint key) diff --git a/ArcFormats/AZSys/ImageCPB.cs b/ArcFormats/AZSys/ImageCPB.cs index 03b3a33c..1c5055e9 100644 --- a/ArcFormats/AZSys/ImageCPB.cs +++ b/ArcFormats/AZSys/ImageCPB.cs @@ -54,51 +54,48 @@ namespace GameRes.Formats.AZSys throw new System.NotImplementedException ("CpbFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - stream.Seek (4, SeekOrigin.Current); - int type = stream.ReadByte(); - int bpp = stream.ReadByte(); + file.Position = 4; + int type = file.ReadByte(); + int bpp = file.ReadByte(); if (24 != bpp && 32 != bpp) throw new NotSupportedException ("Not supported CPB image format"); - using (var input = new ArcView.Reader (stream)) + int version = file.ReadInt16(); + if (1 != version && 0 != version) + throw new NotSupportedException ("Not supported CPB image version"); + var info = new CpbMetaData { + Type = type, + Version = version, + BPP = bpp, + }; + if (1 == version) { - int version = input.ReadInt16 (); - if (1 != version && 0 != version) - throw new NotSupportedException ("Not supported CPB image version"); - var info = new CpbMetaData { - Type = type, - Version = version, - BPP = bpp, - }; - if (1 == version) - { - input.ReadUInt32(); - info.Width = input.ReadUInt16(); - info.Height = input.ReadUInt16(); - info.Channel[0] = input.ReadUInt32(); - info.Channel[1] = input.ReadUInt32(); - info.Channel[2] = input.ReadUInt32(); - info.Channel[3] = input.ReadUInt32(); - } - else - { - info.Width = input.ReadUInt16(); - info.Height = input.ReadUInt16(); - input.ReadUInt32(); - info.Channel[0] = input.ReadUInt32(); - info.Channel[1] = input.ReadUInt32(); - info.Channel[2] = input.ReadUInt32(); - info.Channel[3] = input.ReadUInt32(); - } - info.DataOffset = (uint)stream.Position; - return info; + file.ReadUInt32(); + info.Width = file.ReadUInt16(); + info.Height = file.ReadUInt16(); + info.Channel[0] = file.ReadUInt32(); + info.Channel[1] = file.ReadUInt32(); + info.Channel[2] = file.ReadUInt32(); + info.Channel[3] = file.ReadUInt32(); } + else + { + info.Width = file.ReadUInt16(); + info.Height = file.ReadUInt16(); + file.ReadUInt32(); + info.Channel[0] = file.ReadUInt32(); + info.Channel[1] = file.ReadUInt32(); + info.Channel[2] = file.ReadUInt32(); + info.Channel[3] = file.ReadUInt32(); + } + info.DataOffset = (uint)file.Position; + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var reader = new Reader (stream, (CpbMetaData)info); + var reader = new Reader (stream.AsStream, (CpbMetaData)info); reader.Unpack(); return ImageData.Create (info, reader.Format, reader.Palette, reader.Data); } diff --git a/ArcFormats/AZSys/ImageTYP1.cs b/ArcFormats/AZSys/ImageTYP1.cs index 39e7a7b7..aad4243f 100644 --- a/ArcFormats/AZSys/ImageTYP1.cs +++ b/ArcFormats/AZSys/ImageTYP1.cs @@ -45,46 +45,38 @@ namespace GameRes.Formats.AZSys public override string Description { get { return "AZ system image format"; } } public override uint Signature { get { return 0x31505954; } } // 'TYP1' - public Typ1Format () - { - Extensions = new string[] { "cpb" }; - } - - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { stream.Position = 4; int bpp = stream.ReadByte(); bool has_palette = stream.ReadByte() != 0; - using (var input = new ArcView.Reader (stream)) + var info = new Typ1MetaData { BPP = bpp }; + info.Width = stream.ReadUInt16(); + info.Height = stream.ReadUInt16(); + uint packed_size = stream.ReadUInt32(); + uint palette_size = 8 == bpp ? 0x400u : 0u; + if (packed_size+palette_size+0xE == stream.Length) { - var info = new Typ1MetaData { BPP = bpp }; - info.Width = input.ReadUInt16(); - info.Height = input.ReadUInt16(); - uint packed_size = input.ReadUInt32(); - uint palette_size = 8 == bpp ? 0x400u : 0u; - if (packed_size+palette_size+0xE == stream.Length) - { - info.SeparateChannels = false; - info.HasPalette = palette_size > 0; - info.PackedSize = packed_size; - } - else - { - info.SeparateChannels = true; - info.HasPalette = has_palette; - info.Channel[0] = input.ReadUInt32(); - info.Channel[1] = input.ReadUInt32(); - info.Channel[2] = input.ReadUInt32(); - info.Channel[3] = input.ReadUInt32(); - } - return info; + info.SeparateChannels = false; + info.HasPalette = palette_size > 0; + info.PackedSize = packed_size; } + else + { + info.SeparateChannels = true; + info.HasPalette = has_palette; + info.Channel[0] = stream.ReadUInt32(); + info.Channel[1] = stream.ReadUInt32(); + info.Channel[2] = stream.ReadUInt32(); + info.Channel[3] = stream.ReadUInt32(); + } + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (Typ1MetaData)info; - var reader = new Reader (stream, meta); + var reader = new Reader (stream.AsStream, meta); reader.Unpack(); return ImageData.Create (meta, reader.Format, reader.Palette, reader.Data); } diff --git a/ArcFormats/Abel/ArcARC.cs b/ArcFormats/Abel/ArcARC.cs index b3273a9e..941edd7e 100644 --- a/ArcFormats/Abel/ArcARC.cs +++ b/ArcFormats/Abel/ArcARC.cs @@ -102,7 +102,7 @@ namespace GameRes.Formats.Abel { data[i] = (byte)(0xFF - data[i]); } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } Stream OpenCmpEntry (ArcFile arc, Entry entry) diff --git a/ArcFormats/Abel/ImageGPS.cs b/ArcFormats/Abel/ImageGPS.cs index 39a1649d..229d21ce 100644 --- a/ArcFormats/Abel/ImageGPS.cs +++ b/ArcFormats/Abel/ImageGPS.cs @@ -52,9 +52,9 @@ namespace GameRes.Formats.Abel Extensions = new string[] { "gps", "cmp" }; } - public override ImageMetaData ReadMetaData (IBinaryStream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - var header = stream.ReadHeader (0x29); + var header = file.ReadHeader (0x29); if (header.Length != 0x29) return null; var gps = new GpsMetaData @@ -66,7 +66,8 @@ namespace GameRes.Formats.Abel PackedSize = header.ToInt32 (0x15), }; // read BMP header - using (var input = OpenGpsStream (stream, gps.Compression, 0x54)) + using (var stream = OpenGpsStream (file, gps.Compression, 0x54)) + using (var input = BinaryStream.FromStream (stream, file.Name)) { var bmp_info = base.ReadMetaData (input); if (null == bmp_info) @@ -76,11 +77,12 @@ namespace GameRes.Formats.Abel } } - public override ImageData Read (IBinaryStream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { var gps = (GpsMetaData)info; - stream.Position = 0x29; - using (var input = OpenGpsStream (stream, gps.Compression, gps.UnpackedSize)) + file.Position = 0x29; + using (var stream = OpenGpsStream (file, gps.Compression, gps.UnpackedSize)) + using (var input = BinaryStream.FromStream (stream, file.Name)) return base.Read (input, info); } @@ -89,30 +91,28 @@ namespace GameRes.Formats.Abel throw new System.NotImplementedException ("GpsFormat.Write not implemented"); } - IBinaryStream OpenGpsStream (IBinaryStream input, byte compression, int unpacked_size) + Stream OpenGpsStream (IBinaryStream input, byte compression, int unpacked_size) { - Stream gps = null; if (0 == compression) - gps = new StreamRegion (input.AsStream, 0x29, true); + return new StreamRegion (input.AsStream, 0x29, true); else if (1 == compression) - gps = OpenRLEStream (input.AsStream, unpacked_size); + return OpenRLEStream (input.AsStream, unpacked_size); else if (2 == compression) - gps = new LzssStream (input.AsStream, LzssMode.Decompress, true); + return new LzssStream (input.AsStream, LzssMode.Decompress, true); else if (3 == compression) { using (var lzss = new LzssStream (input.AsStream, LzssMode.Decompress, true)) - gps = OpenRLEStream (lzss, unpacked_size); + return OpenRLEStream (lzss, unpacked_size); } else throw new InvalidFormatException(); - return new BinaryStream (gps); } Stream OpenRLEStream (Stream input, int output_size) { var output = new byte[output_size]; UnpackRLE (input, output); - return new MemoryStream (output); + return new BinMemoryStream (output, ""); } void UnpackRLE (Stream input, byte[] output) diff --git a/ArcFormats/Actgs/ArcDAT.cs b/ArcFormats/Actgs/ArcDAT.cs index 080775ee..07460b1a 100644 --- a/ArcFormats/Actgs/ArcDAT.cs +++ b/ArcFormats/Actgs/ArcDAT.cs @@ -123,7 +123,7 @@ namespace GameRes.Formats.Actgs arc.File.View.Read (entry.Offset, data, 0, entry.Size); Decrypt (data, 1, data.Length-1, actarc.Key); data[0] = (byte)'N'; - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } if (arc.File.View.AsciiEqual (entry.Offset, "PAK ")) { @@ -136,7 +136,7 @@ namespace GameRes.Formats.Actgs arc.File.View.Read (entry.Offset, header, 0, length); Decrypt (header, 0, (int)length, actarc.Key); if (entry.Size <= 0x20) - return new MemoryStream (header); + return new BinMemoryStream (header, entry.Name); var rest = arc.File.CreateStream (entry.Offset+0x20, entry.Size-0x20); return new PrefixStream (header, rest); } diff --git a/ArcFormats/ActiveSoft/ImageEDT.cs b/ArcFormats/ActiveSoft/ImageEDT.cs index b8e6a71d..36aebb57 100644 --- a/ArcFormats/ActiveSoft/ImageEDT.cs +++ b/ArcFormats/ActiveSoft/ImageEDT.cs @@ -107,17 +107,15 @@ namespace GameRes.Formats.AdPack throw new NotImplementedException ("EdtFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x22]; - if (header.Length != stream.Read (header, 0, header.Length)) + var header = stream.ReadHeader (0x22); + if (!header.AsciiEqual (".TRUE\x8d\x5d\x8c\xcb\x00")) return null; - if (!Binary.AsciiEqual (header, ".TRUE\x8d\x5d\x8c\xcb\x00")) - return null; - uint width = LittleEndian.ToUInt16 (header, 0x0e); - uint height = LittleEndian.ToUInt16 (header, 0x10); - uint comp_size = LittleEndian.ToUInt32 (header, 0x1a); - uint extra_size = LittleEndian.ToUInt32 (header, 0x1e); + uint width = header.ToUInt16 (0x0e); + uint height = header.ToUInt16 (0x10); + uint comp_size = header.ToUInt32 (0x1a); + uint extra_size = header.ToUInt32 (0x1e); if (extra_size % 3 != 0 || 0 == extra_size) return null; @@ -131,21 +129,18 @@ namespace GameRes.Formats.AdPack }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as EdtMetaData; - if (null == meta) - throw new ArgumentException ("EdtFormat.Read should be supplied with EdtMetaData", "info"); - + var meta = (EdtMetaData)info; stream.Position = 0x22; - using (var reader = new Reader (stream, meta)) + using (var reader = new Reader (stream.AsStream, meta)) { reader.Unpack(); return ImageData.Create (meta, PixelFormats.Bgr24, null, reader.Data, (int)meta.Width*3); } } - internal class Reader : BitReader, IDisposable + internal sealed class Reader : BitReader, IDisposable { MemoryStream m_packed; MemoryStream m_extra; @@ -244,24 +239,15 @@ namespace GameRes.Formats.AdPack #region IDisposable Members bool disposed = false; - public void Dispose () - { - Dispose (true); - GC.SuppressFinalize (this); - } - - protected virtual void Dispose (bool disposing) { if (!disposed) { - if (disposing) - { - m_packed.Dispose(); - m_extra.Dispose(); - } + m_packed.Dispose(); + m_extra.Dispose(); disposed = true; } + GC.SuppressFinalize (this); } #endregion } @@ -284,17 +270,15 @@ namespace GameRes.Formats.AdPack throw new NotImplementedException ("Ed8Format.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x1a]; - if (header.Length != stream.Read (header, 0, header.Length)) + var header = stream.ReadHeader (0x1A); + if (!header.AsciiEqual (".8Bit\x8d\x5d\x8c\xcb\x00")) return null; - if (!Binary.AsciiEqual (header, ".8Bit\x8d\x5d\x8c\xcb\x00")) - return null; - uint width = LittleEndian.ToUInt16 (header, 0x0e); - uint height = LittleEndian.ToUInt16 (header, 0x10); - uint palette_size = LittleEndian.ToUInt32 (header, 0x12); - uint comp_size = LittleEndian.ToUInt32 (header, 0x16); + uint width = header.ToUInt16 (0x0e); + uint height = header.ToUInt16 (0x10); + uint palette_size = header.ToUInt32 (0x12); + uint comp_size = header.ToUInt32 (0x16); if (palette_size > 0x100) return null; @@ -308,14 +292,11 @@ namespace GameRes.Formats.AdPack }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as Ed8MetaData; - if (null == meta) - throw new ArgumentException ("Ed8Format.Read should be supplied with Ed8MetaData", "info"); - + var meta = (Ed8MetaData)info; stream.Position = 0x1a; - var reader = new Reader (stream, meta); + var reader = new Reader (stream.AsStream, meta); reader.Unpack(); var palette = new BitmapPalette (reader.Palette); return ImageData.Create (info, PixelFormats.Indexed8, palette, reader.Data, (int)info.Width); diff --git a/ArcFormats/AdvSys/ImageGR2.cs b/ArcFormats/AdvSys/ImageGR2.cs index 40ee74b7..af39c86a 100644 --- a/ArcFormats/AdvSys/ImageGR2.cs +++ b/ArcFormats/AdvSys/ImageGR2.cs @@ -38,20 +38,18 @@ namespace GameRes.Formats.AdvSys public override string Description { get { return "AdvSys engine image format"; } } public override uint Signature { get { return 0x5F325247; } } // 'GR2_' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[16]; - if (16 != stream.Read (header, 0, 16)) - return null; + var header = stream.ReadHeader (0x10); return new ImageMetaData { - Width = LittleEndian.ToUInt16 (header, 4), - Height = LittleEndian.ToUInt16 (header, 6), - BPP = LittleEndian.ToInt16 (header, 12) * 8 + Width = header.ToUInt16 (4), + Height = header.ToUInt16 (6), + BPP = header.ToInt16 (12) * 8 }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { stream.Position = 0x10; int stride = ((int)info.Width * info.BPP/8 + 3) & ~3; @@ -92,18 +90,16 @@ namespace GameRes.Formats.AdvSys Extensions = new string[] { "gr2" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[20]; - if (20 != stream.Read (header, 0, 20)) + var header = stream.ReadHeader (20); + if (!header.AsciiEqual ("*Pola* ")) return null; - if (!Binary.AsciiEqual (header, "*Pola* ")) - return null; - int unpacked_size = LittleEndian.ToInt32 (header, 8); + int unpacked_size = header.ToInt32 (8); using (var reader = new PolaReader (stream, 64)) { reader.Unpack(); - using (var temp = new MemoryStream (reader.Data)) + using (var temp = BinaryStream.FromArray (reader.Data, stream.Name)) { var info = base.ReadMetaData (temp); if (null == info) @@ -119,17 +115,14 @@ namespace GameRes.Formats.AdvSys } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as PolaMetaData; - if (null == meta) - throw new ArgumentException ("PolaFormat.Read should be supplied with PolaMetaData", "info"); - + var meta = (PolaMetaData)info; stream.Position = 0x14; using (var reader = new PolaReader (stream, meta.UnpackedSize)) { reader.Unpack(); - using (var temp = new MemoryStream (reader.Data)) + using (var temp = BinaryStream.FromArray (reader.Data, stream.Name)) return base.Read (temp, info); } } @@ -142,14 +135,14 @@ namespace GameRes.Formats.AdvSys internal sealed class PolaReader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; public byte[] Data { get { return m_output; } } - public PolaReader (Stream input, int unpacked_size) + public PolaReader (IBinaryStream input, int unpacked_size) { - m_input = new ArcView.Reader (input); + m_input = input; m_output = new byte[unpacked_size+2]; } @@ -161,14 +154,14 @@ namespace GameRes.Formats.AdvSys { if (0 != NextBit()) { - m_output[dst++] = m_input.ReadByte(); + m_output[dst++] = m_input.ReadUInt8(); continue; } int offset, count = 0; if (0 != NextBit()) { - offset = m_input.ReadByte() - 256; + offset = m_input.ReadUInt8() - 256; if (0 == NextBit()) { @@ -228,7 +221,7 @@ namespace GameRes.Formats.AdvSys } else { - count = m_input.ReadByte() + 17; + count = m_input.ReadUInt8() + 17; } if (dst + count > m_output.Length) count = m_output.Length - dst; @@ -237,7 +230,7 @@ namespace GameRes.Formats.AdvSys } else { - offset = m_input.ReadByte() - 256; + offset = m_input.ReadUInt8() - 256; if (0 == NextBit()) { if (offset != -1) @@ -280,14 +273,8 @@ namespace GameRes.Formats.AdvSys } #region IDisposable Members - bool m_disposed = false; public void Dispose () { - if (!m_disposed) - { - m_input.Dispose(); - m_disposed = true; - } } #endregion } diff --git a/ArcFormats/AdvSys/ImageGWD.cs b/ArcFormats/AdvSys/ImageGWD.cs index 61548b04..29358d02 100644 --- a/ArcFormats/AdvSys/ImageGWD.cs +++ b/ArcFormats/AdvSys/ImageGWD.cs @@ -48,7 +48,7 @@ namespace GameRes.Formats.AdvSys var header = stream.ReadHeader (12); if (header.Length != 12) return null; - if (!Binary.AsciiEqual (header, 4, "GWD")) + if (!header.AsciiEqual (4, "GWD")) return null; return new GwdMetaData { @@ -72,7 +72,7 @@ namespace GameRes.Formats.AdvSys if (24 == info.BPP && 1 == stream.ReadByte()) { using (var part = new StreamRegion (stream.AsStream, stream.Position, true)) - using (var alpha_stream = new BinaryStream (part)) + using (var alpha_stream = new BinaryStream (part, stream.Name)) { var alpha_info = ReadMetaData (alpha_stream) as GwdMetaData; if (null != alpha_info && 8 == alpha_info.BPP diff --git a/ArcFormats/AliceSoft/ArcAFA.cs b/ArcFormats/AliceSoft/ArcAFA.cs index fc9e15af..b8d4f843 100644 --- a/ArcFormats/AliceSoft/ArcAFA.cs +++ b/ArcFormats/AliceSoft/ArcAFA.cs @@ -101,7 +101,7 @@ namespace GameRes.Formats.AliceSoft for (int i = 0; i < prefix.Length; ++i) prefix[i] ^= AffKey[i & 0xF]; if (data_size <= 0x40) - return new MemoryStream (prefix); + return new BinMemoryStream (prefix, entry.Name); var rest = arc.File.CreateStream (entry.Offset+0x10+encrypted_length, data_size-encrypted_length); return new PrefixStream (prefix, rest); } diff --git a/ArcFormats/AliceSoft/ImageDCF.cs b/ArcFormats/AliceSoft/ImageDCF.cs index 6c07b512..f570b8c0 100644 --- a/ArcFormats/AliceSoft/ImageDCF.cs +++ b/ArcFormats/AliceSoft/ImageDCF.cs @@ -137,13 +137,15 @@ namespace GameRes.Formats.AliceSoft long qnt_pos = m_input.Position; if (m_input.ReadUInt32() != Qnt.Signature) throw new InvalidFormatException(); - m_input.Seek (-4, SeekOrigin.Current); - var qnt_info = Qnt.ReadMetaData (m_input) as QntMetaData; + QntMetaData qnt_info; + using (var reg = new StreamRegion (m_input.AsStream, qnt_pos, true)) + using (var qnt = new BinaryStream (reg, m_input.Name)) + qnt_info = Qnt.ReadMetaData (qnt) as QntMetaData; if (null == qnt_info) throw new InvalidFormatException(); m_input.Position = qnt_pos + 0x44; - var overlay = new QntFormat.Reader (m_input, qnt_info); + var overlay = new QntFormat.Reader (m_input.AsStream, qnt_info); overlay.Unpack(); m_overlay_bpp = overlay.BPP; if (m_mask != null) @@ -213,13 +215,13 @@ namespace GameRes.Formats.AliceSoft string dir_name = VFS.GetDirectoryName (m_info.FileName); string base_name = Path.ChangeExtension (m_info.BaseName, "qnt"); base_name = VFS.CombinePath (dir_name, base_name); - using (var base_file = VFS.OpenSeekableStream (base_name)) + using (var base_file = VFS.OpenBinaryStream (base_name)) { var base_info = Qnt.ReadMetaData (base_file) as QntMetaData; if (null != base_info && m_info.Width == base_info.Width && m_info.Height == base_info.Height) { base_info.FileName = base_name; - var reader = new QntFormat.Reader (base_file, base_info); + var reader = new QntFormat.Reader (base_file.AsStream, base_info); reader.Unpack(); m_base_bpp = reader.BPP; m_base = reader.Data; diff --git a/ArcFormats/AliceSoft/ImageQNT.cs b/ArcFormats/AliceSoft/ImageQNT.cs index e696604d..61cb0b83 100644 --- a/ArcFormats/AliceSoft/ImageQNT.cs +++ b/ArcFormats/AliceSoft/ImageQNT.cs @@ -49,36 +49,34 @@ namespace GameRes.Formats.AliceSoft throw new System.NotImplementedException ("QntFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x44]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - int version = LittleEndian.ToInt32 (header, 4); + var header = stream.ReadHeader (0x44); + int version = header.ToInt32 (4); if (version <= 0 || version > 2) return null; - if (0x44 != LittleEndian.ToUInt32 (header, 8)) + if (0x44 != header.ToUInt32 (8)) return null; - uint width = LittleEndian.ToUInt32 (header, 0x14); - uint height = LittleEndian.ToUInt32 (header, 0x18); + uint width = header.ToUInt32 (0x14); + uint height = header.ToUInt32 (0x18); if (0 == width || 0 == height) return null; return new QntMetaData { Width = width, Height = height, - OffsetX = LittleEndian.ToInt32 (header, 0x0c), - OffsetY = LittleEndian.ToInt32 (header, 0x10), - BPP = LittleEndian.ToInt32 (header, 0x1c), - RGBSize = LittleEndian.ToUInt32 (header, 0x24), - AlphaSize = LittleEndian.ToUInt32 (header, 0x28), + OffsetX = header.ToInt32 (0x0c), + OffsetY = header.ToInt32 (0x10), + BPP = header.ToInt32 (0x1c), + RGBSize = header.ToUInt32 (0x24), + AlphaSize = header.ToUInt32 (0x28), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { stream.Position = 0x44; - var reader = new Reader (stream, (QntMetaData)info); + var reader = new Reader (stream.AsStream, (QntMetaData)info); reader.Unpack(); int stride = (int)info.Width * (reader.BPP / 8); PixelFormat format = 24 == reader.BPP ? PixelFormats.Bgr24 : PixelFormats.Bgra32; diff --git a/ArcFormats/Amaterasu/ArcAMI.cs b/ArcFormats/Amaterasu/ArcAMI.cs index 0faaab43..5748a3ee 100644 --- a/ArcFormats/Amaterasu/ArcAMI.cs +++ b/ArcFormats/Amaterasu/ArcAMI.cs @@ -272,7 +272,7 @@ namespace GameRes.Formats.Amaterasu uint WriteAmiEntry (PackedEntry entry, Stream output) { uint packed_size = 0; - using (var input = File.OpenRead (entry.Name)) + using (var input = VFS.OpenBinaryStream (entry)) { long file_size = input.Length; if (file_size > uint.MaxValue) @@ -284,7 +284,7 @@ namespace GameRes.Formats.Amaterasu } else { - input.CopyTo (output); + input.AsStream.CopyTo (output); } } return packed_size; @@ -293,19 +293,19 @@ namespace GameRes.Formats.Amaterasu static Lazy s_grp_format = new Lazy (() => FormatCatalog.Instance.ImageFormats.OfType().FirstOrDefault()); - uint WriteImageEntry (PackedEntry entry, Stream input, Stream output) + uint WriteImageEntry (PackedEntry entry, IBinaryStream input, Stream output) { var grp = s_grp_format.Value; if (null == grp) // probably never happens throw new FileFormatException ("GRP image encoder not available"); - bool is_grp = grp.Signature == FormatCatalog.ReadSignature (input); + bool is_grp = grp.Signature == input.Signature; input.Position = 0; var start = output.Position; using (var zstream = new ZLibStream (output, CompressionMode.Compress, CompressionLevel.Level9, true)) { if (is_grp) { - input.CopyTo (zstream); + input.AsStream.CopyTo (zstream); } else { diff --git a/ArcFormats/Amaterasu/ImageGRP.cs b/ArcFormats/Amaterasu/ImageGRP.cs index 784e10d8..8106b54f 100644 --- a/ArcFormats/Amaterasu/ImageGRP.cs +++ b/ArcFormats/Amaterasu/ImageGRP.cs @@ -40,23 +40,19 @@ namespace GameRes.Formats.Amaterasu public override uint Signature { get { return 0x00505247; } } // 'GRP' public override bool CanWrite { get { return true; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var file = new BinaryReader (stream, Encoding.ASCII, true)) - { - if (file.ReadUInt32() != Signature) - return null; - var meta = new ImageMetaData(); - meta.OffsetX = file.ReadInt16(); - meta.OffsetY = file.ReadInt16(); - meta.Width = file.ReadUInt16(); - meta.Height = file.ReadUInt16(); - meta.BPP = 32; - return meta; - } + file.Position = 4; + var meta = new ImageMetaData(); + meta.OffsetX = file.ReadInt16(); + meta.OffsetY = file.ReadInt16(); + meta.Width = file.ReadUInt16(); + meta.Height = file.ReadUInt16(); + meta.BPP = 32; + return meta; } - public override ImageData Read (Stream file, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { int width = (int)info.Width; int height = (int)info.Height; diff --git a/ArcFormats/AnimeGameSystem/ArcDAT.cs b/ArcFormats/AnimeGameSystem/ArcDAT.cs index 287113f6..75eae8c0 100644 --- a/ArcFormats/AnimeGameSystem/ArcDAT.cs +++ b/ArcFormats/AnimeGameSystem/ArcDAT.cs @@ -92,7 +92,7 @@ namespace GameRes.Formats.Ags data[i] ^= key; key += earc.Key.Increment; } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } public static readonly EncryptionScheme DefaultScheme = new EncryptionScheme { diff --git a/ArcFormats/AnimeGameSystem/AudioPCM.cs b/ArcFormats/AnimeGameSystem/AudioPCM.cs index 6f655b6e..c2e0c020 100644 --- a/ArcFormats/AnimeGameSystem/AudioPCM.cs +++ b/ArcFormats/AnimeGameSystem/AudioPCM.cs @@ -41,12 +41,12 @@ namespace GameRes.Formats.Ags Extensions = new string[] { "pcm" }; } - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - uint signature = FormatCatalog.ReadSignature (file) & 0xF0FFFFFF; + uint signature = file.Signature & 0xF0FFFFFF; if (0x564157 != signature) // 'WAV' return null; - return new PcmInput (file); + return new PcmInput (file.AsStream); } } diff --git a/ArcFormats/AnimeGameSystem/ImageAinos.cs b/ArcFormats/AnimeGameSystem/ImageAinos.cs index 8f8ff3aa..3cc9cd25 100644 --- a/ArcFormats/AnimeGameSystem/ImageAinos.cs +++ b/ArcFormats/AnimeGameSystem/ImageAinos.cs @@ -28,10 +28,7 @@ using System.Collections.Generic; using System.ComponentModel.Composition; using System.IO; using System.Linq; -using System.Text; -using System.Windows; using System.Windows.Media; -using System.Windows.Media.Imaging; using GameRes.Utility; namespace GameRes.Formats.Ags @@ -196,40 +193,37 @@ namespace GameRes.Formats.Ags throw new System.NotImplementedException ("CgFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - int sig = stream.ReadByte(); + int sig = file.ReadByte(); if (sig >= 0x20) return null; - using (var input = new ArcView.Reader (stream)) + int width = file.ReadInt16(); + int height = file.ReadInt16(); + if (width <= 0 || height <= 0 || width > 4096 || height > 4096) + return null; + var meta = new CgMetaData { - int width = input.ReadInt16(); - int height = input.ReadInt16(); - if (width <= 0 || height <= 0 || width > 4096 || height > 4096) + Width = (uint)width, + Height = (uint)height, + BPP = 24, + Type = sig, + }; + if (0 != (sig & 7)) + { + meta.OffsetX = file.ReadInt16(); + meta.OffsetY = file.ReadInt16(); + meta.Right = file.ReadInt16(); + meta.Bottom = file.ReadInt16(); + if (meta.OffsetX > meta.Right || meta.OffsetY > meta.Bottom || + meta.Right > width || meta.Bottom > height || + meta.OffsetX < 0 || meta.OffsetY < 0) return null; - var meta = new CgMetaData - { - Width = (uint)width, - Height = (uint)height, - BPP = 24, - Type = sig, - }; - if (0 != (sig & 7)) - { - meta.OffsetX = input.ReadInt16(); - meta.OffsetY = input.ReadInt16(); - meta.Right = input.ReadInt16(); - meta.Bottom = input.ReadInt16(); - if (meta.OffsetX > meta.Right || meta.OffsetY > meta.Bottom || - meta.Right > width || meta.Bottom > height || - meta.OffsetX < 0 || meta.OffsetY < 0) - return null; - } - return meta; } + return meta; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (CgMetaData)info; using (var reader = new Reader (stream, meta)) @@ -239,9 +233,9 @@ namespace GameRes.Formats.Ags } } - internal class Reader : IDisposable + internal sealed class Reader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; int m_type; int m_width; @@ -253,7 +247,7 @@ namespace GameRes.Formats.Ags public byte[] Data { get { return m_output; } } - public Reader (Stream file, CgMetaData info, byte[] base_image = null) + public Reader (IBinaryStream file, CgMetaData info, byte[] base_image = null) { m_type = info.Type; m_width = (int)info.Width; @@ -263,13 +257,13 @@ namespace GameRes.Formats.Ags m_right = info.Right == 0 ? m_width : info.Right; m_bottom = info.Bottom == 0 ? m_height : info.Bottom; m_output = base_image ?? new byte[3*m_width*m_height]; - m_input = new BinaryReader (file, Encoding.ASCII, true); + m_input = file; ShiftTable = InitShiftTable(); if (0 != (info.Type & 7)) - file.Position = 13; + m_input.Position = 13; else - file.Position = 5; + m_input.Position = 5; } static readonly short[] ShiftX = new short[] { // 409b6c @@ -307,7 +301,7 @@ namespace GameRes.Formats.Ags int dst = left; while (dst != right) { - byte v9 = m_input.ReadByte(); + byte v9 = m_input.ReadUInt8(); if (0 != (v9 & 0x80)) { if (0 != (v9 & 0x40)) @@ -318,10 +312,10 @@ namespace GameRes.Formats.Ags } else { - byte v15 = m_input.ReadByte(); + byte v15 = m_input.ReadUInt8(); m_output[dst] = (byte)(((v9 << 1) + (v15 & 1)) << 1); m_output[dst + 1] = (byte)(v15 & 0xfe); - m_output[dst + 2] = m_input.ReadByte(); + m_output[dst + 2] = m_input.ReadUInt8(); } dst += 3; continue; @@ -330,13 +324,13 @@ namespace GameRes.Formats.Ags int count = v9 & 0xF; if (0 == count) { - count = (int)m_input.ReadByte() + 15; + count = (int)m_input.ReadUInt8() + 15; if (270 == count) { int v12; do { - v12 = m_input.ReadByte(); + v12 = m_input.ReadUInt8(); count += v12; } while (v12 == 0xff); @@ -364,7 +358,7 @@ namespace GameRes.Formats.Ags int dst = left; while (dst != right) { - byte v13 = m_input.ReadByte(); + byte v13 = m_input.ReadUInt8(); if (0 != (v13 & 0x80)) { int color = 3 * (v13 & 0x7F); @@ -378,13 +372,13 @@ namespace GameRes.Formats.Ags int count = v13 & 0xF; if (0 == count) { - count = m_input.ReadByte() + 15; + count = m_input.ReadUInt8() + 15; if (270 == count) { int v16; do { - v16 = m_input.ReadByte(); + v16 = m_input.ReadUInt8(); count += v16; } while (v16 == 0xff); @@ -403,25 +397,10 @@ namespace GameRes.Formats.Ags } #region IDisposable Members - bool disposed = false; - public void Dispose () { - Dispose (true); GC.SuppressFinalize (this); } - - protected virtual void Dispose (bool disposing) - { - if (!disposed) - { - if (disposing) - { - m_input.Dispose(); - } - disposed = true; - } - } #endregion } } diff --git a/ArcFormats/Ankh/ArcGRP.cs b/ArcFormats/Ankh/ArcGRP.cs index 334d2a45..00f66030 100644 --- a/ArcFormats/Ankh/ArcGRP.cs +++ b/ArcFormats/Ankh/ArcGRP.cs @@ -178,7 +178,7 @@ namespace GameRes.Formats.Ankh { var unpacked = new byte[entry.UnpackedSize]; reader.UnpackHDJ (unpacked, 0); - return new MemoryStream (unpacked); + return new BinMemoryStream (unpacked, entry.Name); } } @@ -201,7 +201,7 @@ namespace GameRes.Formats.Ankh reader.UnpackA (unpacked, header_size, channels); else reader.UnpackS (unpacked, header_size, channels); - return new MemoryStream (unpacked); + return new BinMemoryStream (unpacked, entry.Name); } } @@ -276,7 +276,7 @@ namespace GameRes.Formats.Ankh dst += count; } } - return new MemoryStream (output); + return new BinMemoryStream (output, entry.Name); } } } diff --git a/ArcFormats/Ankh/AudioPCM.cs b/ArcFormats/Ankh/AudioPCM.cs index a503e939..b38341ab 100644 --- a/ArcFormats/Ankh/AudioPCM.cs +++ b/ArcFormats/Ankh/AudioPCM.cs @@ -65,7 +65,7 @@ namespace GameRes.Formats.Ice if (0 == format.AverageBytesPerSecond || format.SamplesPerSecond * format.BlockAlign != format.AverageBytesPerSecond) return null; - var pcm = new StreamRegion (file, 0x16, pcm_size); + var pcm = new StreamRegion (file.AsStream, 0x16, pcm_size); return new RawPcmInput (pcm, format); } } diff --git a/ArcFormats/Aoi/ArcBOX.cs b/ArcFormats/Aoi/ArcBOX.cs index 1c6b4e3b..1267a04d 100644 --- a/ArcFormats/Aoi/ArcBOX.cs +++ b/ArcFormats/Aoi/ArcBOX.cs @@ -188,7 +188,7 @@ namespace GameRes.Formats.Aoi { data[i] ^= KeyFromOffset (offset++); } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } static byte KeyFromOffset (uint offset) diff --git a/ArcFormats/Aoi/AudioAOG.cs b/ArcFormats/Aoi/AudioAOG.cs index 77de9396..20a788ee 100644 --- a/ArcFormats/Aoi/AudioAOG.cs +++ b/ArcFormats/Aoi/AudioAOG.cs @@ -36,14 +36,12 @@ namespace GameRes.Formats.Aoi public override string Description { get { return "Aoi engine audio format"; } } public override uint Signature { get { return 0x4F696F41; } } // 'AoiO' - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - var header = new byte[0x30]; - if (header.Length != file.Read (header, 0, header.Length)) + var header = file.ReadHeader (0x30); + if (!header.AsciiEqual (0, "AoiOgg") || !header.AsciiEqual (0x2C, "OggS")) return null; - if (!Binary.AsciiEqual (header, 0, "AoiOgg") || !Binary.AsciiEqual (header, 0x2C, "OggS")) - return null; - var ogg = new StreamRegion (file, 0x2C); + var ogg = new StreamRegion (file.AsStream, 0x2C); return new OggInput (ogg); } } diff --git a/ArcFormats/Aoi/ImageAGF.cs b/ArcFormats/Aoi/ImageAGF.cs index 582a8cd0..4ae15269 100644 --- a/ArcFormats/Aoi/ImageAGF.cs +++ b/ArcFormats/Aoi/ImageAGF.cs @@ -118,7 +118,7 @@ namespace GameRes.Formats.Aoi case 5: count = (count >> 8) & 0xFF; - input.BaseStream.Seek ((count - count / 4) * 4, SeekOrigin.Current); + input.Seek ((count - count / 4) * 4, SeekOrigin.Current); count *= 4; break; @@ -134,9 +134,9 @@ namespace GameRes.Formats.Aoi var base_name = ReadBaseName (input, meta); if (VFS.FileExists (base_name)) { - using (var base_file = VFS.OpenSeekableStream (base_name)) + using (var base_file = VFS.OpenBinaryStream (base_name)) { - var base_image = Read (base_name, base_file); + var base_image = Read (base_file); BlendImage (meta, pixels, base_image.Bitmap); } } @@ -152,13 +152,13 @@ namespace GameRes.Formats.Aoi string ReadBaseName (IBinaryStream input, AgfMetaData info) { - input.BaseStream.Position = info.DataOffset + info.BaseNameOffset; + input.Position = info.DataOffset + info.BaseNameOffset; using (var reader = new BinaryReader (input.AsStream, Encoding.Unicode, true)) { var name = new StringBuilder(); for (;;) { - char c = input.ReadChar(); + char c = reader.ReadChar(); if (0 == c) break; name.Append (c); diff --git a/ArcFormats/ArcAST.cs b/ArcFormats/ArcAST.cs index bcb25c1f..48f03f2c 100644 --- a/ArcFormats/ArcAST.cs +++ b/ArcFormats/ArcAST.cs @@ -125,14 +125,14 @@ namespace GameRes.Formats.AST var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); for (int i = 0; i < data.Length; ++i) data[i] ^= 0xff; - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } return arc.File.CreateStream (entry.Offset, entry.Size); } using (var input = arc.File.CreateStream (entry.Offset, entry.Size)) { var data = UnpackLzss (input, pent.Size, pent.UnpackedSize); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } diff --git a/ArcFormats/ArcAVC.cs b/ArcFormats/ArcAVC.cs index 51fdbc03..4718feff 100644 --- a/ArcFormats/ArcAVC.cs +++ b/ArcFormats/ArcAVC.cs @@ -91,7 +91,7 @@ namespace GameRes.Formats.AVC int base_offset = (int)(entry.Offset-arcf.HeaderOffset); for (int i = 0; i < data.Length; ++i) data[i] ^= arcf.Key[((base_offset+i)&7)]; - return new MemoryStream (data, false); + return new BinMemoryStream (data, entry.Name); } internal class AdvReader diff --git a/ArcFormats/ArcAil.cs b/ArcFormats/ArcAil.cs index dfd08143..eb06175c 100644 --- a/ArcFormats/ArcAil.cs +++ b/ArcFormats/ArcAil.cs @@ -122,7 +122,7 @@ namespace GameRes.Formats.Ail { byte[] data = new byte[pentry.UnpackedSize]; LzssUnpack (input, data); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } diff --git a/ArcFormats/ArcKogado.cs b/ArcFormats/ArcKogado.cs index 6a4c2aa4..214c1988 100644 --- a/ArcFormats/ArcKogado.cs +++ b/ArcFormats/ArcKogado.cs @@ -159,7 +159,7 @@ namespace GameRes.Formats.Kogado var unpacked = new byte[packed_entry.UnpackedSize]; var mariel = new MarielEncoder(); mariel.Unpack (input, unpacked, unpacked.Length); - return new MemoryStream (unpacked); + return new BinMemoryStream (unpacked, entry.Name); } finally { diff --git a/ArcFormats/ArcLST.cs b/ArcFormats/ArcLST.cs index 52dbef53..814fab66 100644 --- a/ArcFormats/ArcLST.cs +++ b/ArcFormats/ArcLST.cs @@ -150,7 +150,7 @@ namespace GameRes.Formats.Nexton var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); for (int i = 0; i != data.Length; ++i) data[i] ^= nxent.Key; - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } private static string ReadName (ArcView view, long offset, uint size, uint key, Encoding enc) diff --git a/ArcFormats/ArcNEKO.cs b/ArcFormats/ArcNEKO.cs index f61c9eaa..34ce53f0 100644 --- a/ArcFormats/ArcNEKO.cs +++ b/ArcFormats/ArcNEKO.cs @@ -50,7 +50,7 @@ namespace GameRes.Formats.Neko /// /// Read a directory record from archive index. /// - DirRecord ReadDir (BinaryReader input); + DirRecord ReadDir (IBinaryStream input); /// /// Returns offset of an entry that immediately follows specified one. /// @@ -65,15 +65,14 @@ namespace GameRes.Formats.Neko internal sealed class IndexReader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; int m_index_size; long m_max_offset; INekoFormat m_format; public IndexReader (ArcView file, INekoFormat enc, byte[] index, int index_size) { - var input = new MemoryStream (index, 0, index_size); - m_input = new BinaryReader (input); + m_input = new BinMemoryStream (index, 0, index_size, file.Name); m_index_size = index_size; m_max_offset = file.MaxOffset; m_format = enc; @@ -85,7 +84,7 @@ namespace GameRes.Formats.Neko var files_map = GetNamesMap (KnownFileNames); var dir = new List(); - while (m_input.BaseStream.Position < m_index_size) + while (m_input.Position < m_index_size) { var dir_info = m_format.ReadDir (m_input); string dir_name; @@ -273,7 +272,7 @@ namespace GameRes.Formats.Neko return arc.File.CreateStream (entry.Offset, entry.Size); int length; var data = ReadBlock (arc.File.View, pak.Decoder, entry.Offset, out length); - return new MemoryStream (data, 0, length); + return new BinMemoryStream (data, 0, length, entry.Name); } static uint HashFromString (uint seed, byte[] str, int offset, int length) @@ -358,7 +357,7 @@ namespace GameRes.Formats.Neko return hash; } - public DirRecord ReadDir (BinaryReader input) + public DirRecord ReadDir (IBinaryStream input) { return new DirRecord { Hash = input.ReadUInt32(), @@ -468,7 +467,7 @@ namespace GameRes.Formats.Neko data = new byte[aligned_size]; arc.File.View.Read (entry.Offset+12, data, 0, (uint)size); narc.Decoder.Decrypt (key, data, 0, aligned_size); - return new MemoryStream (data, 0, size); + return new BinMemoryStream (data, 0, size, entry.Name); } } @@ -506,7 +505,7 @@ namespace GameRes.Formats.Neko return hash; } - public DirRecord ReadDir (BinaryReader input) + public DirRecord ReadDir (IBinaryStream input) { uint hash = input.ReadUInt32(); int count = input.ReadInt32(); diff --git a/ArcFormats/ArcPACKDAT.cs b/ArcFormats/ArcPACKDAT.cs index 92002c28..f9feddfe 100644 --- a/ArcFormats/ArcPACKDAT.cs +++ b/ArcFormats/ArcPACKDAT.cs @@ -102,7 +102,7 @@ namespace GameRes.Formats.SystemEpsylon } } } - return new MemoryStream (input); + return new BinMemoryStream (input, entry.Name); } } } diff --git a/ArcFormats/ArcPBX.cs b/ArcFormats/ArcPBX.cs index 97c75968..a3976b99 100644 --- a/ArcFormats/ArcPBX.cs +++ b/ArcFormats/ArcPBX.cs @@ -76,7 +76,7 @@ namespace GameRes.Formats.Terios using (var reader = new PandoraCompression (input, unpacked_size)) { var data = reader.Unpack(); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } catch diff --git a/ArcFormats/ArcSPack.cs b/ArcFormats/ArcSPack.cs index 95dd812b..185b97f7 100644 --- a/ArcFormats/ArcSPack.cs +++ b/ArcFormats/ArcSPack.cs @@ -108,7 +108,7 @@ namespace GameRes.Formats.SPack using (var reader = new PackedReader (packed_entry, input)) { reader.Unpack(); - return new MemoryStream (reader.Data); + return new BinMemoryStream (reader.Data, entry.Name); } } return input; diff --git a/ArcFormats/Astronauts/ArcGXP.cs b/ArcFormats/Astronauts/ArcGXP.cs index 95524999..0baba6f8 100644 --- a/ArcFormats/Astronauts/ArcGXP.cs +++ b/ArcFormats/Astronauts/ArcGXP.cs @@ -86,7 +86,7 @@ namespace GameRes.Formats.Astronauts { var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); Decrypt (data, entry.Size); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } static void Decrypt (byte[] data, uint length) diff --git a/ArcFormats/AudioMP3.cs b/ArcFormats/AudioMP3.cs index 584c02b6..0c208e95 100644 --- a/ArcFormats/AudioMP3.cs +++ b/ArcFormats/AudioMP3.cs @@ -94,11 +94,9 @@ namespace GameRes.Formats public override uint Signature { get { return 0; } } public override bool CanWrite { get { return false; } } - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - byte[] header = new byte[10]; - if (header.Length != file.Read (header, 0, header.Length)) - return null; + var header = file.ReadHeader (10).ToArray(); long start_offset = SkipId3Tag (header); if (0 != start_offset) { @@ -109,7 +107,7 @@ namespace GameRes.Formats if (0xff != header[0] || 0xe2 != (header[1] & 0xe6) || 0xf0 == (header[2] & 0xf0)) return null; file.Position = 0; - return new Mp3Input (file); + return new Mp3Input (file.AsStream); } long SkipId3Tag (byte[] buffer) diff --git a/ArcFormats/AudioOGG.cs b/ArcFormats/AudioOGG.cs index 9ea80a1b..63bbe1db 100644 --- a/ArcFormats/AudioOGG.cs +++ b/ArcFormats/AudioOGG.cs @@ -131,9 +131,9 @@ namespace GameRes.Formats public override uint Signature { get { return 0x5367674f; } } // 'OggS' public override bool CanWrite { get { return false; } } - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - return new OggInput (file); + return new OggInput (file.AsStream); } public static AudioFormat Instance { get { return s_OggFormat.Value; } } diff --git a/ArcFormats/AudioVOC.cs b/ArcFormats/AudioVOC.cs index a2a97199..9267a3a7 100644 --- a/ArcFormats/AudioVOC.cs +++ b/ArcFormats/AudioVOC.cs @@ -67,8 +67,8 @@ namespace GameRes.Formats.Creative switch (block_type) { case 1: - freq = m_input.ReadByte(); - codec = m_input.ReadByte(); + freq = m_input.ReadUInt8(); + codec = m_input.ReadUInt8(); Copy (block_size-2, pcm); m_format.Channels = 1; m_format.SamplesPerSecond = 1000000u / (256u - freq); @@ -80,16 +80,16 @@ namespace GameRes.Formats.Creative break; case 8: freq = m_input.ReadUInt16(); - codec = m_input.ReadByte(); - m_format.Channels = (ushort)(m_input.ReadByte()+1); + codec = m_input.ReadUInt8(); + m_format.Channels = (ushort)(m_input.ReadUInt8()+1); m_format.SamplesPerSecond = 256000000u / (Format.Channels * (65536u - freq)); m_format.BitsPerSample = 8; format_read = true; break; case 9: m_format.SamplesPerSecond = m_input.ReadUInt32(); - m_format.BitsPerSample = m_input.ReadByte(); - m_format.Channels = (ushort)(m_input.ReadByte()+1); + m_format.BitsPerSample = m_input.ReadUInt8(); + m_format.Channels = (ushort)(m_input.ReadUInt8()+1); codec = m_input.ReadUInt16(); format_read = true; m_input.ReadInt32(); diff --git a/ArcFormats/Banana/ImageMAG.cs b/ArcFormats/Banana/ImageMAG.cs index 01f7433c..92ceb708 100644 --- a/ArcFormats/Banana/ImageMAG.cs +++ b/ArcFormats/Banana/ImageMAG.cs @@ -45,20 +45,18 @@ namespace GameRes.Formats.Banana public override string Description { get { return "BANANA Shu-Shu image format"; } } public override uint Signature { get { return 0; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x24]; - if (header.Length != stream.Read (header, 0, header.Length)) + var header = stream.ReadHeader (0x24); + if (0 != header.ToInt32 (0x10) || 0 != header.ToInt32 (0x14)) return null; - if (0 != LittleEndian.ToInt32 (header, 0x10) || 0 != LittleEndian.ToInt32 (header, 0x14)) - return null; - int left = LittleEndian.ToInt32 (header, 0); - int top = LittleEndian.ToInt32 (header, 4); - int right = LittleEndian.ToInt32 (header, 8); - int bottom = LittleEndian.ToInt32 (header, 0xC); - int back_width = LittleEndian.ToInt32 (header, 0x18); - int back_height = LittleEndian.ToInt32 (header, 0x1C); - uint alpha_channel = LittleEndian.ToUInt32 (header, 0x20); + int left = header.ToInt32 (0); + int top = header.ToInt32 (4); + int right = header.ToInt32 (8); + int bottom = header.ToInt32 (0xC); + int back_width = header.ToInt32 (0x18); + int back_height = header.ToInt32 (0x1C); + uint alpha_channel = header.ToUInt32 (0x20); int width = right - left; int height = bottom - top; if (left >= back_width || top >= back_height @@ -78,12 +76,12 @@ namespace GameRes.Formats.Banana }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { int stride = (int)info.Width * 3; var pixels = new byte[stride * (int)info.Height]; stream.Position = 0x24; - using (var lz = new LzssStream (stream, LzssMode.Decompress, true)) + using (var lz = new LzssStream (stream.AsStream, LzssMode.Decompress, true)) { if (pixels.Length != lz.Read (pixels, 0, pixels.Length)) throw new InvalidFormatException(); @@ -104,7 +102,7 @@ namespace GameRes.Formats.Banana stream.Position = 0x24 + meta.AlphaOffset; var alpha = new byte[meta.BackWidth*meta.BackHeight]; - using (var lz = new LzssStream (stream, LzssMode.Decompress, true)) + using (var lz = new LzssStream (stream.AsStream, LzssMode.Decompress, true)) { if (alpha.Length != lz.Read (alpha, 0, alpha.Length)) throw new InvalidFormatException(); diff --git a/ArcFormats/Bishop/ImageBSG.cs b/ArcFormats/Bishop/ImageBSG.cs index acc40d1d..827bb623 100644 --- a/ArcFormats/Bishop/ImageBSG.cs +++ b/ArcFormats/Bishop/ImageBSG.cs @@ -49,36 +49,34 @@ namespace GameRes.Formats.Bishop public override string Description { get { return "Bishop image format"; } } public override uint Signature { get { return 0x2D535342; } } // 'BSS-' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x60]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x60); int base_offset = 0; - if (Binary.AsciiEqual (header, 0, "BSS-Composition\0")) + if (header.AsciiEqual ("BSS-Composition\0")) base_offset = 0x20; - if (!Binary.AsciiEqual (header, base_offset, "BSS-Graphics\0")) + if (!header.AsciiEqual (base_offset, "BSS-Graphics\0")) return null; int type = header[base_offset+0x30]; if (type > 2) return null; return new BsgMetaData { - Width = LittleEndian.ToUInt16 (header, base_offset+0x16), - Height = LittleEndian.ToUInt16 (header, base_offset+0x18), - OffsetX = LittleEndian.ToInt16 (header, base_offset+0x20), - OffsetY = LittleEndian.ToInt16 (header, base_offset+0x22), - UnpackedSize = LittleEndian.ToInt32 (header, base_offset+0x12), + Width = header.ToUInt16 (base_offset+0x16), + Height = header.ToUInt16 (base_offset+0x18), + OffsetX = header.ToInt16 (base_offset+0x20), + OffsetY = header.ToInt16 (base_offset+0x22), + UnpackedSize = header.ToInt32 (base_offset+0x12), BPP = 2 == type ? 8 : 32, ColorMode = type, CompressionMode = header[base_offset+0x31], - DataOffset = LittleEndian.ToInt32 (header, base_offset+0x32)+base_offset, - DataSize = LittleEndian.ToInt32 (header, base_offset+0x36), - PaletteOffset = LittleEndian.ToInt32 (header, base_offset+0x3A)+base_offset, + DataOffset = header.ToInt32 (base_offset+0x32)+base_offset, + DataSize = header.ToInt32 (base_offset+0x36), + PaletteOffset = header.ToInt32 (base_offset+0x3A)+base_offset, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (BsgMetaData)info; using (var reader = new BsgReader (stream, meta)) @@ -96,7 +94,7 @@ namespace GameRes.Formats.Bishop internal sealed class BsgReader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; BsgMetaData m_info; byte[] m_output; @@ -105,13 +103,13 @@ namespace GameRes.Formats.Bishop public BitmapPalette Palette { get; private set; } public int Stride { get; private set; } - public BsgReader (Stream input, BsgMetaData info) + public BsgReader (IBinaryStream input, BsgMetaData info) { m_info = info; if (m_info.CompressionMode > 2) throw new NotSupportedException ("Not supported BSS Graphics compression"); - m_input = new ArcView.Reader (input); + m_input = input; m_output = new byte[m_info.UnpackedSize]; switch (m_info.ColorMode) { @@ -133,7 +131,7 @@ namespace GameRes.Formats.Bishop public void Unpack () { - m_input.BaseStream.Position = m_info.DataOffset; + m_input.Position = m_info.DataOffset; if (0 == m_info.CompressionMode) { if (1 == m_info.ColorMode) @@ -179,13 +177,13 @@ namespace GameRes.Formats.Bishop int remaining = m_input.ReadInt32(); while (remaining > 0) { - int count = m_input.ReadSByte(); + int count = m_input.ReadInt8(); --remaining; if (count >= 0) { for (int i = 0; i <= count; ++i) { - m_output[dst] = m_input.ReadByte(); + m_output[dst] = m_input.ReadUInt8(); --remaining; dst += pixel_size; } @@ -193,7 +191,7 @@ namespace GameRes.Formats.Bishop else { count = 1 - count; - byte repeat = m_input.ReadByte(); + byte repeat = m_input.ReadUInt8(); --remaining; for (int i = 0; i < count; ++i) { @@ -207,20 +205,20 @@ namespace GameRes.Formats.Bishop void UnpackLz (int plane, int pixel_size) { int dst = plane; - byte control = m_input.ReadByte(); + byte control = m_input.ReadUInt8(); int remaining = m_input.ReadInt32() - 5; while (remaining > 0) { - byte c = m_input.ReadByte(); + byte c = m_input.ReadUInt8(); --remaining; if (c == control) { - int offset = m_input.ReadByte(); + int offset = m_input.ReadUInt8(); --remaining; if (offset != control) { - int count = m_input.ReadByte(); + int count = m_input.ReadUInt8(); --remaining; if (offset > control) @@ -245,7 +243,7 @@ namespace GameRes.Formats.Bishop BitmapPalette ReadPalette () { - m_input.BaseStream.Position = m_info.PaletteOffset; + m_input.Position = m_info.PaletteOffset; var palette_data = new byte[0x400]; if (palette_data.Length != m_input.Read (palette_data, 0, palette_data.Length)) throw new InvalidFormatException(); @@ -259,14 +257,8 @@ namespace GameRes.Formats.Bishop } #region IDisposable Members - bool _disposed = false; public void Dispose () { - if (!_disposed) - { - m_input.Dispose(); - _disposed = true; - } } #endregion } diff --git a/ArcFormats/BlackCyc/AudioVAW.cs b/ArcFormats/BlackCyc/AudioVAW.cs index a0df616c..4840c162 100644 --- a/ArcFormats/BlackCyc/AudioVAW.cs +++ b/ArcFormats/BlackCyc/AudioVAW.cs @@ -44,7 +44,7 @@ namespace GameRes.Formats.BlackCyc Extensions = new string[] { "vaw", "wgq" }; } - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { var header = ResourceHeader.Read (file); if (null == header) @@ -76,8 +76,8 @@ namespace GameRes.Formats.BlackCyc } else return null; - var input = new StreamRegion (file, offset, file.Length-offset); - return format.TryOpen (input); + var input = new StreamRegion (file.AsStream, offset, file.Length-offset); + return format.TryOpen (new BinaryStream (input, file.Name)); } public override void Write (SoundInput source, Stream output) @@ -85,7 +85,7 @@ namespace GameRes.Formats.BlackCyc throw new System.NotImplementedException ("EdimFormat.Write not implemenented"); } - SoundInput Unpack (Stream input) + SoundInput Unpack (IBinaryStream input) { input.Position = 0x40; var header = new byte[0x24]; @@ -106,7 +106,7 @@ namespace GameRes.Formats.BlackCyc { pcm.Write (header, 0, header_size); using (var output = new BinaryWriter (pcm, Encoding.Default, true)) - using (var bits = new LsbBitStream (input, true)) + using (var bits = new LsbBitStream (input.AsStream, true)) { int written = 0; short sample = 0; @@ -128,7 +128,7 @@ namespace GameRes.Formats.BlackCyc } } pcm.Position = 0; - var sound = Wav.TryOpen (pcm); + var sound = Wav.TryOpen (new BinMemoryStream (pcm, input.Name)); if (sound != null) input.Dispose(); else diff --git a/ArcFormats/BlackCyc/ImageDWQ.cs b/ArcFormats/BlackCyc/ImageDWQ.cs index 0de67ae3..5932f0e1 100644 --- a/ArcFormats/BlackCyc/ImageDWQ.cs +++ b/ArcFormats/BlackCyc/ImageDWQ.cs @@ -43,11 +43,9 @@ namespace GameRes.Formats.BlackCyc public int PackType { get; private set; } public bool AType { get; private set; } - public static ResourceHeader Read (Stream file) + public static ResourceHeader Read (IBinaryStream file) { - var header = new byte[0x40]; - if (0x40 != file.Read (header, 0, 0x40)) - return null; + var header = file.ReadHeader (0x40).ToArray(); var header_string = Encoding.ASCII.GetString (header, 0x30, 0x10); var match = PackTypeRe.Match (header_string); @@ -88,9 +86,9 @@ namespace GameRes.Formats.BlackCyc }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - var header = ResourceHeader.Read (stream); + var header = ResourceHeader.Read (file); if (null == header) return null; if (Binary.AsciiEqual (header.Bytes, "IF PACKTYPE==")) @@ -99,7 +97,8 @@ namespace GameRes.Formats.BlackCyc !Binary.AsciiEqual (header.Bytes, 0x2C, "BMP ") || header.PackType != 0 && header.PackType != 1) return null; - using (var bmp = new StreamRegion (stream, 0x40, true)) + using (var reg = new StreamRegion (file.AsStream, 0x40, true)) + using (var bmp = new BinaryStream (reg, file.Name)) { var info = Bmp.ReadMetaData (bmp); if (null == info) @@ -110,7 +109,7 @@ namespace GameRes.Formats.BlackCyc Height = info.Height, BPP = info.BPP, BaseType = "BMP", - PackedSize = (int)(stream.Length-0x40), + PackedSize = (int)(file.Length-0x40), PackType = header.PackType, HasAlpha = header.AType, }; @@ -122,7 +121,7 @@ namespace GameRes.Formats.BlackCyc case 0: // BMP case 5: // JPEG case 8: // PNG - packed_size = (int)(stream.Length-0x40); + packed_size = (int)(file.Length-0x40); break; case 2: // BMP+MASK @@ -146,12 +145,13 @@ namespace GameRes.Formats.BlackCyc }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (DwqMetaData)info; BitmapSource bitmap = null; - using (var input = new StreamRegion (stream, 0x40, meta.PackedSize, true)) + using (var sreg = new StreamRegion (stream.AsStream, 0x40, meta.PackedSize, true)) + using (var input = new BinaryStream (sreg, stream.Name)) { switch (meta.PackType) { @@ -192,7 +192,7 @@ namespace GameRes.Formats.BlackCyc int mask_offset = 0x40+meta.PackedSize; if (mask_offset != stream.Length) { - using (var mask = new StreamRegion (stream, mask_offset, true)) + using (var mask = new StreamRegion (stream.AsStream, mask_offset, true)) { var reader = new DwqBmpReader (mask, meta); if (8 == reader.Format.BitsPerPixel) // mask should be represented as 8bpp bitmap @@ -238,17 +238,15 @@ namespace GameRes.Formats.BlackCyc PixelFormats.Bgra32, null, pixels, stride); } - private BitmapSource ReadFuckedUpBmpImage (Stream file, ImageMetaData info) + private BitmapSource ReadFuckedUpBmpImage (IBinaryStream file, ImageMetaData info) { - var header = new byte[0x36]; - if (header.Length != file.Read (header, 0, header.Length)) - throw new InvalidFormatException(); - int w = LittleEndian.ToInt32 (header, 0x12); - int h = LittleEndian.ToInt32 (header, 0x16); + var header = file.ReadHeader (0x36); + int w = header.ToInt32 (0x12); + int h = header.ToInt32 (0x16); if (w != info.Width || h != info.Height) throw new InvalidFormatException(); - int bpp = LittleEndian.ToUInt16 (header, 0x1c); + int bpp = header.ToUInt16 (0x1c); PixelFormat format; switch (bpp) { @@ -261,8 +259,8 @@ namespace GameRes.Formats.BlackCyc BitmapPalette palette = null; if (8 == bpp) { - int colors = Math.Min (LittleEndian.ToInt32 (header, 0x2E), 0x100); - palette = DwqBmpReader.ReadPalette (file, colors); + int colors = Math.Min (header.ToInt32 (0x2E), 0x100); + palette = DwqBmpReader.ReadPalette (file.AsStream, colors); } int pixel_size = bpp / 8; int stride = ((int)info.Width * pixel_size + 3) & ~3; diff --git a/ArcFormats/BlackRainbow/ImageBMD.cs b/ArcFormats/BlackRainbow/ImageBMD.cs index 8d1830d4..e6b6e447 100644 --- a/ArcFormats/BlackRainbow/ImageBMD.cs +++ b/ArcFormats/BlackRainbow/ImageBMD.cs @@ -51,31 +51,25 @@ namespace GameRes.Formats.BlackRainbow public override uint Signature { get { return 0x444d425fu; } } // '_BMD' public override bool CanWrite { get { return true; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x14]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - + var header = stream.ReadHeader (0x14); return new BmdMetaData { - Width = LittleEndian.ToUInt32 (header, 8), - Height = LittleEndian.ToUInt32 (header, 12), + Width = header.ToUInt32 (8), + Height = header.ToUInt32 (12), BPP = 32, - PackedSize = LittleEndian.ToUInt32 (header, 4), - Flag = LittleEndian.ToInt32 (header, 0x10), + PackedSize = header.ToUInt32 (4), + Flag = header.ToInt32 (0x10), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as BmdMetaData; - if (null == meta) - throw new ArgumentException ("BmdFormat.Read should be supplied with BmdMetaData", "info"); - + var meta = (BmdMetaData)info; stream.Position = 0x14; int image_size = (int)(meta.Width*meta.Height*4); - using (var reader = new LzssReader (stream, (int)meta.PackedSize, image_size)) + using (var reader = new LzssReader (stream.AsStream, (int)meta.PackedSize, image_size)) { PixelFormat format = meta.Flag != 0 ? PixelFormats.Bgra32 : PixelFormats.Bgr32; reader.Unpack(); diff --git a/ArcFormats/BlackRainbow/ImageBMZ.cs b/ArcFormats/BlackRainbow/ImageBMZ.cs index 5cde5ebf..20e231c0 100644 --- a/ArcFormats/BlackRainbow/ImageBMZ.cs +++ b/ArcFormats/BlackRainbow/ImageBMZ.cs @@ -55,21 +55,21 @@ namespace GameRes.Formats.BlackRainbow } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - var header = new byte[8]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - using (var zstream = new ZLibStream (stream, CompressionMode.Decompress, true)) - return base.ReadMetaData (zstream); + var header = file.ReadHeader (8); + using (var zstream = new ZLibStream (file.AsStream, CompressionMode.Decompress, true)) + using (var bmp = new BinaryStream (zstream, file.Name)) + return base.ReadMetaData (bmp); } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { - stream.Seek (8, SeekOrigin.Current); - using (var zstream = new ZLibStream (stream, CompressionMode.Decompress, true)) + file.Seek (8, SeekOrigin.Current); + using (var zstream = new ZLibStream (file.AsStream, CompressionMode.Decompress, true)) using (var input = new SeekableStream (zstream)) - return base.Read (input, info); + using (var bmp = new BinaryStream (input, file.Name)) + return base.Read (bmp, info); } } } diff --git a/ArcFormats/BlueGale/ImageZBM.cs b/ArcFormats/BlueGale/ImageZBM.cs index dd588f48..f9824320 100644 --- a/ArcFormats/BlueGale/ImageZBM.cs +++ b/ArcFormats/BlueGale/ImageZBM.cs @@ -43,48 +43,40 @@ namespace GameRes.Formats.BlueGale public override string Description { get { return "BlueGale compressed image format"; } } public override uint Signature { get { return 0x5F706D61; } } // 'amp_' - public ZbmFormat () - { - Extensions = new string[] { "zbm" }; - } - - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { stream.Position = 4; - using (var reader = new ArcView.Reader (stream)) + int version = stream.ReadInt16(); + if (version != 1) + return null; + int unpacked_size = stream.ReadInt32(); + int data_offset = stream.ReadInt32(); + if (unpacked_size < 0x36 || data_offset < stream.Position) + return null; + var header = new byte[0x20]; + stream.Position = data_offset; + Unpack (stream.AsStream, header); + Decrypt (header); + if ('B' != header[0] || 'M' != header[1]) + return null; + return new ZbmMetaData { - int version = reader.ReadInt16(); - if (version != 1) - return null; - int unpacked_size = reader.ReadInt32(); - int data_offset = reader.ReadInt32(); - if (unpacked_size < 0x36 || data_offset < stream.Position) - return null; - var header = new byte[0x20]; - stream.Position = data_offset; - Unpack (stream, header); - Decrypt (header); - if ('B' != header[0] || 'M' != header[1]) - return null; - return new ZbmMetaData - { - Width = LittleEndian.ToUInt32 (header, 0x12), - Height = LittleEndian.ToUInt32 (header, 0x16), - BPP = LittleEndian.ToInt16 (header, 0x1C), - UnpackedSize = unpacked_size, - DataOffset = data_offset, - }; - } + Width = LittleEndian.ToUInt32 (header, 0x12), + Height = LittleEndian.ToUInt32 (header, 0x16), + BPP = LittleEndian.ToInt16 (header, 0x1C), + UnpackedSize = unpacked_size, + DataOffset = data_offset, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (ZbmMetaData)info; var data = new byte[meta.UnpackedSize]; stream.Position = meta.DataOffset; - Unpack (stream, data); + Unpack (stream.AsStream, data); Decrypt (data); - using (var bmp = new MemoryStream (data)) + using (var bmp = new BinMemoryStream (data, stream.Name)) return Bmp.Read (bmp, info); } diff --git a/ArcFormats/BlueGale/VideoAMV.cs b/ArcFormats/BlueGale/VideoAMV.cs index c87594d9..f30f6fbd 100644 --- a/ArcFormats/BlueGale/VideoAMV.cs +++ b/ArcFormats/BlueGale/VideoAMV.cs @@ -90,7 +90,7 @@ namespace GameRes.Formats.BlueGale LittleEndian.Pack (pent.UnpackedSize, output, 2); int header_size = LittleEndian.ToInt32 (output, 0xE); LittleEndian.Pack (header_size+0xE, output, 0xA); - return new MemoryStream (output); + return new BinMemoryStream (output, entry.Name); } } } diff --git a/ArcFormats/Bruns/ImageEENC.cs b/ArcFormats/Bruns/ImageEENC.cs index bf048a24..5e274aac 100644 --- a/ArcFormats/Bruns/ImageEENC.cs +++ b/ArcFormats/Bruns/ImageEENC.cs @@ -102,7 +102,7 @@ namespace GameRes.Formats.Bruns if (meta.Compressed) input = new ZLibStream (input, CompressionMode.Decompress); using (var bin = new BinaryStream (input, stream.Name, true)) - return meta.Format.Read (input, meta.Info); + return meta.Format.Read (bin, meta.Info); } finally { diff --git a/ArcFormats/CaramelBox/ArcARC3.cs b/ArcFormats/CaramelBox/ArcARC3.cs index 1a17c2a9..f62309d4 100644 --- a/ArcFormats/CaramelBox/ArcARC3.cs +++ b/ArcFormats/CaramelBox/ArcARC3.cs @@ -200,7 +200,7 @@ namespace GameRes.Formats.CaramelBox using (input) { var data = UnpackLze (input, a3ent.UnpackedSize); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } diff --git a/ArcFormats/CaramelBox/ArcARC4.cs b/ArcFormats/CaramelBox/ArcARC4.cs index a51f0c47..d97f257d 100644 --- a/ArcFormats/CaramelBox/ArcARC4.cs +++ b/ArcFormats/CaramelBox/ArcARC4.cs @@ -130,7 +130,7 @@ namespace GameRes.Formats.CaramelBox return input; using (input) using (var tz = new TzCompression (input)) - return new MemoryStream (tz.Unpack()); + return new BinMemoryStream (tz.Unpack(), entry.Name); } static int ReadInt24 (byte[] data, int pos) diff --git a/ArcFormats/CatSystem/ArcINT.cs b/ArcFormats/CatSystem/ArcINT.cs index 558559dd..8718747e 100644 --- a/ArcFormats/CatSystem/ArcINT.cs +++ b/ArcFormats/CatSystem/ArcINT.cs @@ -208,7 +208,7 @@ namespace GameRes.Formats.CatSystem { byte[] data = arc.File.View.ReadBytes (entry.Offset, entry.Size); arc.Encryption.Decipher (data, data.Length/8*8); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } public override Stream OpenEntry (ArcFile arc, Entry entry) diff --git a/ArcFormats/CatSystem/ImageHG2.cs b/ArcFormats/CatSystem/ImageHG2.cs index ddd49041..d0b3ebe2 100644 --- a/ArcFormats/CatSystem/ImageHG2.cs +++ b/ArcFormats/CatSystem/ImageHG2.cs @@ -44,37 +44,34 @@ namespace GameRes.Formats.CatSystem public override string Description { get { return "CatSystem engine image format"; } } public override uint Signature { get { return 0x322D4748; } } // 'HG-2' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { stream.Position = 8; - using (var header = new ArcView.Reader (stream)) - { - var info = new Hg2MetaData(); - int type = header.ReadInt32(); - if (0x25 == type) - info.HeaderSize = 0x58; - else if (0x20 == type) - info.HeaderSize = 0x50; - else - return null; - info.Width = header.ReadUInt32(); - info.Height = header.ReadUInt32(); - info.BPP = header.ReadInt32(); - header.BaseStream.Seek (8, SeekOrigin.Current); - info.DataPacked = header.ReadInt32(); - info.DataUnpacked = header.ReadInt32(); - info.CtlPacked = header.ReadInt32(); - info.CtlUnpacked = header.ReadInt32(); - header.BaseStream.Seek (8, SeekOrigin.Current); - info.CanvasWidth = header.ReadUInt32(); - info.CanvasHeight = header.ReadUInt32(); - info.OffsetX = header.ReadInt32(); - info.OffsetY = header.ReadInt32(); - return info; - } + var info = new Hg2MetaData(); + int type = stream.ReadInt32(); + if (0x25 == type) + info.HeaderSize = 0x58; + else if (0x20 == type) + info.HeaderSize = 0x50; + else + return null; + info.Width = stream.ReadUInt32(); + info.Height = stream.ReadUInt32(); + info.BPP = stream.ReadInt32(); + stream.Seek (8, SeekOrigin.Current); + info.DataPacked = stream.ReadInt32(); + info.DataUnpacked = stream.ReadInt32(); + info.CtlPacked = stream.ReadInt32(); + info.CtlUnpacked = stream.ReadInt32(); + stream.Seek (8, SeekOrigin.Current); + info.CanvasWidth = stream.ReadUInt32(); + info.CanvasHeight = stream.ReadUInt32(); + info.OffsetX = stream.ReadInt32(); + info.OffsetY = stream.ReadInt32(); + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { using (var reader = new Hg2Reader (stream, (Hg2MetaData)info)) { @@ -94,7 +91,7 @@ namespace GameRes.Formats.CatSystem { Hg2MetaData m_hg2; - public Hg2Reader (Stream input, Hg2MetaData info) : base (input, info) + public Hg2Reader (IBinaryStream input, Hg2MetaData info) : base (input, info) { m_hg2 = info; } diff --git a/ArcFormats/CatSystem/ImageHG3.cs b/ArcFormats/CatSystem/ImageHG3.cs index a3131e41..9a6baf2d 100644 --- a/ArcFormats/CatSystem/ImageHG3.cs +++ b/ArcFormats/CatSystem/ImageHG3.cs @@ -25,7 +25,6 @@ using System; using System.IO; -using System.Linq; using System.ComponentModel.Composition; using System.Windows.Media.Imaging; using System.Windows.Media; @@ -48,35 +47,34 @@ namespace GameRes.Formats.CatSystem public override string Description { get { return "CatSystem engine image format"; } } public override uint Signature { get { return 0x332d4748; } } // 'HG-3' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x4c]; - if (0x4c != stream.Read (header, 0, header.Length)) + var header = stream.ReadHeader (0x4c); + if (header.ToUInt32 (4) != 0x0c) return null; - if (LittleEndian.ToUInt32 (header, 4) != 0x0c) - return null; - if (!Binary.AsciiEqual (header, 0x14, "stdinfo\0")) + if (!header.AsciiEqual (0x14, "stdinfo\0")) return null; return new HgMetaData { - HeaderSize = LittleEndian.ToUInt32 (header, 0x1C), - Width = LittleEndian.ToUInt32 (header, 0x24), - Height = LittleEndian.ToUInt32 (header, 0x28), - OffsetX = LittleEndian.ToInt32 (header, 0x30), - OffsetY = LittleEndian.ToInt32 (header, 0x34), - BPP = LittleEndian.ToInt32 (header, 0x2C), - CanvasWidth = LittleEndian.ToUInt32 (header, 0x44), - CanvasHeight = LittleEndian.ToUInt32 (header, 0x48), + HeaderSize = header.ToUInt32 (0x1C), + Width = header.ToUInt32 (0x24), + Height = header.ToUInt32 (0x28), + OffsetX = header.ToInt32 (0x30), + OffsetY = header.ToInt32 (0x34), + BPP = header.ToInt32 (0x2C), + CanvasWidth = header.ToUInt32 (0x44), + CanvasHeight = header.ToUInt32 (0x48), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (HgMetaData)info; if (0x20 != meta.BPP) throw new NotSupportedException ("Not supported HG-3 color depth"); - using (var input = new StreamRegion (stream, 0x14, true)) + using (var reg = new StreamRegion (stream.AsStream, 0x14, true)) + using (var input = new BinaryStream (reg, stream.Name)) using (var reader = new Hg3Reader (input, meta)) { var pixels = reader.Unpack(); @@ -95,17 +93,17 @@ namespace GameRes.Formats.CatSystem internal class HgReader : IDisposable { - private BinaryReader m_input; + private IBinaryStream m_input; protected HgMetaData m_info; protected int m_pixel_size; - protected BinaryReader Input { get { return m_input; } } - protected Stream InputStream { get { return m_input.BaseStream; } } + protected IBinaryStream Input { get { return m_input; } } + protected Stream InputStream { get { return m_input.AsStream; } } public int Stride { get; protected set; } - protected HgReader (Stream input, HgMetaData info) + protected HgReader (IBinaryStream input, HgMetaData info) { - m_input = new ArcView.Reader (input); + m_input = input; m_info = info; m_pixel_size = m_info.BPP / 8; Stride = (int)m_info.Width * m_pixel_size; @@ -228,25 +226,10 @@ namespace GameRes.Formats.CatSystem } #region IDisposable Members - bool _disposed = false; - public void Dispose () { - Dispose (true); GC.SuppressFinalize (this); } - - protected virtual void Dispose (bool disposing) - { - if (!_disposed) - { - if (disposing) - { - m_input.Dispose(); - } - _disposed = true; - } - } #endregion } @@ -254,17 +237,17 @@ namespace GameRes.Formats.CatSystem { public bool Flipped { get; private set; } - public Hg3Reader (Stream input, HgMetaData info) : base (input, info) + public Hg3Reader (IBinaryStream input, HgMetaData info) : base (input, info) { } public byte[] Unpack () { InputStream.Position = m_info.HeaderSize; - var img_type = Input.ReadChars (8); - if (img_type.SequenceEqual ("img0000\0")) + var img_type = Input.ReadBytes (8); + if (Binary.AsciiEqual (img_type, "img0000\0")) return UnpackImg0000(); - else if (img_type.SequenceEqual ("img_jpg\0")) + else if (Binary.AsciiEqual (img_type, "img_jpg\0")) return UnpackJpeg(); else throw new NotSupportedException ("Not supported HG-3 image"); @@ -309,11 +292,11 @@ namespace GameRes.Formats.CatSystem src += src_pixel_size; } - InputStream.Position = next_section; - var section_header = Input.ReadChars (8); - if (!section_header.SequenceEqual ("img_al\0\0")) + Input.Position = next_section; + var section_header = Input.ReadBytes (8); + if (!Binary.AsciiEqual (section_header, "img_al\0\0")) return output; - InputStream.Seek (8, SeekOrigin.Current); + Input.Seek (8, SeekOrigin.Current); int alpha_size = Input.ReadInt32(); using (var alpha_in = new StreamRegion (InputStream, InputStream.Position+4, alpha_size, true)) using (var alpha = new ZLibStream (alpha_in, CompressionMode.Decompress)) diff --git a/ArcFormats/Cherry/ArcCherry.cs b/ArcFormats/Cherry/ArcCherry.cs index 27f31117..2f3c6f8e 100644 --- a/ArcFormats/Cherry/ArcCherry.cs +++ b/ArcFormats/Cherry/ArcCherry.cs @@ -110,7 +110,7 @@ namespace GameRes.Formats.Cherry { data[text_offset+i] ^= (byte)i; } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } @@ -209,7 +209,7 @@ namespace GameRes.Formats.Cherry } Decrypt (data, 0x18, (int)(data.Length - 0x18)); } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } } diff --git a/ArcFormats/Cherry/ImageGRP.cs b/ArcFormats/Cherry/ImageGRP.cs index 897448df..2afc0c11 100644 --- a/ArcFormats/Cherry/ImageGRP.cs +++ b/ArcFormats/Cherry/ImageGRP.cs @@ -54,16 +54,14 @@ namespace GameRes.Formats.Cherry Extensions = new string[] { "grp" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x18]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - uint width = LittleEndian.ToUInt32 (header, 0); - uint height = LittleEndian.ToUInt32 (header, 4); - int bpp = LittleEndian.ToInt32 (header, 8); - int packed_size = LittleEndian.ToInt32 (header, 0x0C); - int unpacked_size = LittleEndian.ToInt32 (header, 0x10); + var header = stream.ReadHeader (0x18); + uint width = header.ToUInt32 (0); + uint height = header.ToUInt32 (4); + int bpp = header.ToInt32 (8); + int packed_size = header.ToInt32 (0x0C); + int unpacked_size = header.ToInt32 (0x10); if (0 == width || 0 == height || width > 0x7fff || height > 0x7fff || (bpp != 24 && bpp != 8) || unpacked_size <= 0 || packed_size < 0) @@ -75,16 +73,16 @@ namespace GameRes.Formats.Cherry BPP = bpp, PackedSize = packed_size, UnpackedSize = unpacked_size, - Offset = LittleEndian.ToInt32 (header, 0x14), + Offset = header.ToInt32 (0x14), HeaderSize = 0x18, AlphaChannel = false, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { var meta = (GrpMetaData)info; - var reader = new GrpReader (stream, meta); + var reader = new GrpReader (file.AsStream, meta); return reader.CreateImage(); } @@ -101,18 +99,16 @@ namespace GameRes.Formats.Cherry public override string Description { get { return "Cherry Soft compressed image format"; } } public override uint Signature { get { return 0; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x28]; - if (header.Length != stream.Read (header, 0, header.Length)) + var header = stream.ReadHeader (0x28); + if (0xFFFF != header.ToInt32 (8)) return null; - if (0xFFFF != LittleEndian.ToInt32 (header, 8)) - return null; - int packed_size = LittleEndian.ToInt32 (header, 0); - int unpacked_size = LittleEndian.ToInt32 (header, 4); - uint width = LittleEndian.ToUInt32 (header, 0x10); - uint height = LittleEndian.ToUInt32 (header, 0x14); - int bpp = LittleEndian.ToInt32 (header, 0x18); + int packed_size = header.ToInt32 (0); + int unpacked_size = header.ToInt32 (4); + uint width = header.ToUInt32 (0x10); + uint height = header.ToUInt32 (0x14); + int bpp = header.ToInt32 (0x18); if (0 == width || 0 == height || width > 0x7fff || height > 0x7fff || (bpp != 32 && bpp != 24 && bpp != 8) || unpacked_size <= 0 || packed_size < 0) @@ -126,7 +122,7 @@ namespace GameRes.Formats.Cherry UnpackedSize = unpacked_size, Offset = 0xFFFF, HeaderSize = 0x28, - AlphaChannel = LittleEndian.ToInt32 (header, 0x24) != 0, + AlphaChannel = header.ToInt32 (0x24) != 0, }; } } diff --git a/ArcFormats/Circus/ArcValkyrieComplex.cs b/ArcFormats/Circus/ArcValkyrieComplex.cs index c6d3ce9d..789552d8 100644 --- a/ArcFormats/Circus/ArcValkyrieComplex.cs +++ b/ArcFormats/Circus/ArcValkyrieComplex.cs @@ -117,7 +117,7 @@ namespace GameRes.Formats.Circus { data = UnpackCps (data); } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } byte[] UnpackCps (byte[] input) diff --git a/ArcFormats/Circus/AudioPCM.cs b/ArcFormats/Circus/AudioPCM.cs index a467bb29..121b3d93 100644 --- a/ArcFormats/Circus/AudioPCM.cs +++ b/ArcFormats/Circus/AudioPCM.cs @@ -38,46 +38,43 @@ namespace GameRes.Formats.Circus public override string Description { get { return "Circus PCM audio"; } } public override uint Signature { get { return 0x4d435058; } } // 'XPCM' - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { file.Position = 4; - using (var input = new ArcView.Reader (file)) + int src_size = file.ReadInt32(); + if (src_size <= 0) + throw new InvalidFormatException(); + int mode = file.ReadInt32(); + int extra = (mode >> 8) & 0xff; + mode &= 0xff; + if (5 == mode) { - int src_size = input.ReadInt32(); - if (src_size <= 0) - throw new InvalidFormatException(); - int mode = input.ReadInt32(); - int extra = (mode >> 8) & 0xff; - mode &= 0xff; - if (5 == mode) - { - uint ogg_size = input.ReadUInt32(); - var ogg = new StreamRegion (file, 0x10, ogg_size); - return new OggInput (ogg); - } - var format = new WaveFormat(); - format.FormatTag = input.ReadUInt16(); - format.Channels = input.ReadUInt16(); - format.SamplesPerSecond = input.ReadUInt32(); - format.AverageBytesPerSecond = input.ReadUInt32(); - format.BlockAlign = input.ReadUInt16(); - format.BitsPerSample = input.ReadUInt16(); - Stream pcm; - if (0 == mode) - { - pcm = new StreamRegion (file, file.Position, src_size); - } - else if (1 == mode || 3 == mode) - { - var decoder = new PcmDecoder (input, src_size, extra, (XpcmCompression)mode); - pcm = new MemoryStream (decoder.Unpack(), 0, src_size); - file.Dispose(); - } - else - throw new NotSupportedException ("Not supported Circus PCM audio compression"); - - return new RawPcmInput (pcm, format); + uint ogg_size = file.ReadUInt32(); + var ogg = new StreamRegion (file.AsStream, 0x10, ogg_size); + return new OggInput (ogg); } + var format = new WaveFormat(); + format.FormatTag = file.ReadUInt16(); + format.Channels = file.ReadUInt16(); + format.SamplesPerSecond = file.ReadUInt32(); + format.AverageBytesPerSecond = file.ReadUInt32(); + format.BlockAlign = file.ReadUInt16(); + format.BitsPerSample = file.ReadUInt16(); + Stream pcm; + if (0 == mode) + { + pcm = new StreamRegion (file.AsStream, file.Position, src_size); + } + else if (1 == mode || 3 == mode) + { + var decoder = new PcmDecoder (file, src_size, extra, (XpcmCompression)mode); + pcm = new MemoryStream (decoder.Unpack(), 0, src_size); + file.Dispose(); + } + else + throw new NotSupportedException ("Not supported Circus PCM audio compression"); + + return new RawPcmInput (pcm, format); } } @@ -97,7 +94,7 @@ namespace GameRes.Formats.Circus public byte[] Data { get { return m_pcm_data; } } - public PcmDecoder (BinaryReader input, int pcm_size, int extra, XpcmCompression mode) + public PcmDecoder (IBinaryStream input, int pcm_size, int extra, XpcmCompression mode) { if (extra < 0 || extra > 3) throw new InvalidFormatException(); @@ -114,7 +111,7 @@ namespace GameRes.Formats.Circus } else if (XpcmCompression.Zlib == mode) { - using (var z = new ZLibStream (input.BaseStream, CompressionMode.Decompress, true)) + using (var z = new ZLibStream (input.AsStream, CompressionMode.Decompress, true)) z.Read (m_encoded, 0, m_encoded.Length); } else diff --git a/ArcFormats/Circus/ImageCRX.cs b/ArcFormats/Circus/ImageCRX.cs index 4961b7e0..74302913 100644 --- a/ArcFormats/Circus/ImageCRX.cs +++ b/ArcFormats/Circus/ImageCRX.cs @@ -266,23 +266,23 @@ namespace GameRes.Formats.Circus { flag >>= 1; if (0 == (flag & 0x100)) - flag = m_input.ReadByte() | 0xff00; + flag = m_input.ReadUInt8() | 0xff00; if (0 != (flag & 1)) { - byte dat = m_input.ReadByte(); + byte dat = m_input.ReadUInt8(); window[win_pos++] = dat; win_pos &= 0xffff; m_output[dst++] = dat; } else { - byte control = m_input.ReadByte(); + byte control = m_input.ReadUInt8(); int count, offset; if (control >= 0xc0) { - offset = ((control & 3) << 8) | m_input.ReadByte(); + offset = ((control & 3) << 8) | m_input.ReadUInt8(); count = 4 + ((control >> 2) & 0xf); } else if (0 != (control & 0x80)) @@ -290,7 +290,7 @@ namespace GameRes.Formats.Circus offset = control & 0x1f; count = 2 + ((control >> 5) & 3); if (0 == offset) - offset = m_input.ReadByte(); + offset = m_input.ReadUInt8(); } else if (0x7f == control) { diff --git a/ArcFormats/Circus/ImageCRXD.cs b/ArcFormats/Circus/ImageCRXD.cs index a0ddb374..3dc09cea 100644 --- a/ArcFormats/Circus/ImageCRXD.cs +++ b/ArcFormats/Circus/ImageCRXD.cs @@ -70,7 +70,7 @@ namespace GameRes.Formats.Circus else if (header.AsciiEqual (0x20, "CRXG")) { using (var crx_input = new StreamRegion (stream.AsStream, 0x20, true)) - using (var crx = new BinaryStream (crx_input)) + using (var crx = new BinaryStream (crx_input, stream.Name)) { var diff_info = base.ReadMetaData (crx) as CrxMetaData; if (null == diff_info) @@ -90,12 +90,12 @@ namespace GameRes.Formats.Circus if (info != null) { info.BaseOffset = header.ToUInt32 (8); - info.BaseFileName = Binary.GetCString (header, 0xC, 0x14); + info.BaseFileName = header.GetCString (0xC, 0x14); } return info; } - Stream OpenByOffset (uint offset) + IBinaryStream OpenByOffset (uint offset) { var vfs = VFS.Top as ArchiveFileSystem; if (null == vfs) @@ -118,9 +118,9 @@ namespace GameRes.Formats.Circus diff = OpenByOffset (info.DiffOffset); if (null == diff) throw new FileNotFoundException ("Referenced diff image not found"); - input = new StreamRegion (diff, 0x20); + input = new StreamRegion (diff.AsStream, 0x20); } - return new BinaryStream (input); + return new BinaryStream (input, diff.Name); } public override ImageData Read (IBinaryStream stream, ImageMetaData info) diff --git a/ArcFormats/Cmvs/ArcCPZ.cs b/ArcFormats/Cmvs/ArcCPZ.cs index aa909b91..c71b9cb4 100644 --- a/ArcFormats/Cmvs/ArcCPZ.cs +++ b/ArcFormats/Cmvs/ArcCPZ.cs @@ -279,7 +279,7 @@ namespace GameRes.Formats.Purple data = UnpackPs2 (data); else if (data.Length > 0x40 && Binary.AsciiEqual (data, 0, "PB3B")) DecryptPb3 (data); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } void DecryptIndexStage1 (byte[] data, uint key, CmvsScheme scheme) diff --git a/ArcFormats/Cmvs/ArcPBZ.cs b/ArcFormats/Cmvs/ArcPBZ.cs index 7223fdd6..69179417 100644 --- a/ArcFormats/Cmvs/ArcPBZ.cs +++ b/ArcFormats/Cmvs/ArcPBZ.cs @@ -122,7 +122,7 @@ namespace GameRes.Formats.Pvns { data = DecryptScript (data, parc.ScriptKey); } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } static void Decrypt (byte[] data, byte[] key) diff --git a/ArcFormats/Cmvs/ImagePB3.cs b/ArcFormats/Cmvs/ImagePB3.cs index 9854f9dc..28f0d0fe 100644 --- a/ArcFormats/Cmvs/ImagePB3.cs +++ b/ArcFormats/Cmvs/ImagePB3.cs @@ -47,33 +47,30 @@ namespace GameRes.Formats.Purple public override string Description { get { return "Purple Software image format"; } } public override uint Signature { get { return 0x42334250; } } // 'PB3B' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { stream.Position = 4; - using (var reader = new ArcView.Reader (stream)) + int input_size = stream.ReadInt32(); + stream.Position = 0x18; + int t2 = stream.ReadInt32(); + int t1 = stream.ReadUInt16(); + uint width = stream.ReadUInt16(); + uint height = stream.ReadUInt16(); + int bpp = stream.ReadUInt16(); + return new Pb3MetaData { - int input_size = reader.ReadInt32(); - stream.Position = 0x18; - int t2 = reader.ReadInt32(); - int t1 = reader.ReadUInt16(); - uint width = reader.ReadUInt16(); - uint height = reader.ReadUInt16(); - int bpp = reader.ReadUInt16(); - return new Pb3MetaData - { - Width = width, - Height = height, - BPP = bpp, - Type = t1, - SubType = t2, - InputSize = input_size, - }; - } + Width = width, + Height = height, + BPP = bpp, + Type = t1, + SubType = t2, + InputSize = input_size, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var reader = new Pb3Reader (stream, (Pb3MetaData)info); + var reader = new Pb3Reader (stream.AsStream, (Pb3MetaData)info); reader.Unpack(); return ImageData.Create (info, reader.Format, null, reader.Data); } @@ -350,9 +347,9 @@ namespace GameRes.Formats.Purple if (name.Equals (m_info.FileName, StringComparison.InvariantCultureIgnoreCase)) throw new InvalidFormatException(); // two files referencing each other still could create infinite recursion - using (var base_file = VFS.OpenSeekableStream (name)) + using (var base_file = VFS.OpenBinaryStream (name)) { - var image_data = ImageFormat.Read (name, base_file); + var image_data = ImageFormat.Read (base_file); int stride = image_data.Bitmap.PixelWidth * 4; var pixels = new byte[stride * image_data.Bitmap.PixelHeight]; image_data.Bitmap.CopyPixels (pixels, stride, 0); diff --git a/ArcFormats/Cri/ArcCPK.cs b/ArcFormats/Cri/ArcCPK.cs index 9c5c9968..a1d1b079 100644 --- a/ArcFormats/Cri/ArcCPK.cs +++ b/ArcFormats/Cri/ArcCPK.cs @@ -104,7 +104,7 @@ namespace GameRes.Formats.Cri } Array.Reverse (output, (int)prefix_size, unpacked_size); arc.File.View.Read (entry.Offset+0x10+packed_size, output, 0, prefix_size); - return new MemoryStream (output); + return new BinMemoryStream (output, entry.Name); } void DetectFileTypes (ArcView file, List dir) diff --git a/ArcFormats/Cri/AudioADX.cs b/ArcFormats/Cri/AudioADX.cs index dddacba8..83f63ed8 100644 --- a/ArcFormats/Cri/AudioADX.cs +++ b/ArcFormats/Cri/AudioADX.cs @@ -43,7 +43,7 @@ namespace GameRes.Formats.Cri uint signature = file.Signature; if (0x80 != (signature & 0xFFFF)) return null; - uint header_size = Binary.BigEndian (signature & 0xFFFF0000); + int header_size = (int)Binary.BigEndian (signature & 0xFFFF0000); if (header_size < 0x10 || header_size >= file.Length) return null; var header = file.ReadBytes (header_size); diff --git a/ArcFormats/Cri/ImageBIP.cs b/ArcFormats/Cri/ImageBIP.cs index 10f63267..58654079 100644 --- a/ArcFormats/Cri/ImageBIP.cs +++ b/ArcFormats/Cri/ImageBIP.cs @@ -61,57 +61,52 @@ namespace GameRes.Formats.Cri throw new NotImplementedException ("BipFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream input) { - using (var input = new BinaryReader (stream, Encoding.ASCII, true)) - { - int sig = input.ReadInt32(); - if (sig != 5 && sig != 10) - return null; - uint header_end = (uint)sig*4; - uint index_offset = input.ReadUInt32(); + int sig = input.ReadInt32(); + if (sig != 5 && sig != 10) + return null; + uint header_end = (uint)sig*4; + uint index_offset = input.ReadUInt32(); - input.BaseStream.Position = header_end-4; - uint data_offset = input.ReadUInt32() + 8; - if (index_offset >= data_offset || index_offset < header_end) - return null; - input.BaseStream.Position = index_offset; - int tile_count = input.ReadInt16(); - int flag = input.ReadInt16(); - if (tile_count <= 0 || 0 != flag) - return null; - input.ReadInt32(); - uint w = input.ReadUInt16(); - uint h = input.ReadUInt16(); - if (0 == w || 0 == h) - return null; - var meta = new BipMetaData { Width = w, Height = h, BPP = 32 }; - meta.Tiles.Capacity = tile_count; - for (int i = 0; i < tile_count; ++i) - { - input.ReadInt64(); - var tile = new BipTile(); - tile.Left = input.ReadUInt16(); - tile.Top = input.ReadUInt16(); - tile.Width = input.ReadUInt16(); - tile.Height = input.ReadUInt16(); - if (tile.Left + tile.Width > meta.Width) - meta.Width = (uint)(tile.Left + tile.Width); - if (tile.Top + tile.Height > meta.Height) - meta.Height = (uint)(tile.Top + tile.Height); - input.ReadInt64(); - tile.Offset = input.ReadUInt32() + data_offset; - meta.Tiles.Add (tile); - } - return meta; + input.Position = header_end-4; + uint data_offset = input.ReadUInt32() + 8; + if (index_offset >= data_offset || index_offset < header_end) + return null; + input.Position = index_offset; + int tile_count = input.ReadInt16(); + int flag = input.ReadInt16(); + if (tile_count <= 0 || 0 != flag) + return null; + input.ReadInt32(); + uint w = input.ReadUInt16(); + uint h = input.ReadUInt16(); + if (0 == w || 0 == h) + return null; + var meta = new BipMetaData { Width = w, Height = h, BPP = 32 }; + meta.Tiles.Capacity = tile_count; + for (int i = 0; i < tile_count; ++i) + { + input.ReadInt64(); + var tile = new BipTile(); + tile.Left = input.ReadUInt16(); + tile.Top = input.ReadUInt16(); + tile.Width = input.ReadUInt16(); + tile.Height = input.ReadUInt16(); + if (tile.Left + tile.Width > meta.Width) + meta.Width = (uint)(tile.Left + tile.Width); + if (tile.Top + tile.Height > meta.Height) + meta.Height = (uint)(tile.Top + tile.Height); + input.ReadInt64(); + tile.Offset = input.ReadUInt32() + data_offset; + meta.Tiles.Add (tile); } + return meta; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as BipMetaData; - if (null == meta) - throw new ArgumentException ("BipFormat.Read should be supplied with BipMetaData", "info"); + var meta = (BipMetaData)info; var header = new byte[0x7c]; var bitmap = new WriteableBitmap ((int)meta.Width, (int)meta.Height, @@ -127,7 +122,7 @@ namespace GameRes.Formats.Cri int alpha = LittleEndian.ToInt32 (header, 0x68); int x = LittleEndian.ToInt32 (header, 0x6c); int y = LittleEndian.ToInt32 (header, 0x70); - using (var png = new StreamRegion (stream, stream.Position, data_size, true)) + using (var png = new StreamRegion (stream.AsStream, stream.Position, data_size, true)) { var decoder = new PngBitmapDecoder (png, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); diff --git a/ArcFormats/Cri/ImageSPC.cs b/ArcFormats/Cri/ImageSPC.cs index 7f65e5dc..36c74963 100644 --- a/ArcFormats/Cri/ImageSPC.cs +++ b/ArcFormats/Cri/ImageSPC.cs @@ -49,7 +49,7 @@ namespace GameRes.Formats.Cri return null; using (var lzss = new LzssStream (stream.AsStream, LzssMode.Decompress, true)) using (var input = new SeekableStream (lzss)) - using (var xtx = new BinaryStream (input)) + using (var xtx = new BinaryStream (input, stream.Name)) return base.ReadMetaData (xtx); } @@ -58,7 +58,7 @@ namespace GameRes.Formats.Cri stream.Position = 4; using (var lzss = new LzssStream (stream.AsStream, LzssMode.Decompress, true)) using (var input = new SeekableStream (lzss)) - using (var xtx = new BinaryStream (input)) + using (var xtx = new BinaryStream (input, stream.Name)) return base.Read (xtx, info); } diff --git a/ArcFormats/Crowd/AudioEOG.cs b/ArcFormats/Crowd/AudioEOG.cs index 14fccce1..f09fc468 100644 --- a/ArcFormats/Crowd/AudioEOG.cs +++ b/ArcFormats/Crowd/AudioEOG.cs @@ -36,9 +36,9 @@ namespace GameRes.Formats.Crowd public override string Description { get { return "Crowd engine audio format (Ogg/Vorbis)"; } } public override uint Signature { get { return 0x004D5243; } } // 'CRM' - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - var ogg = new StreamRegion (file, 8); + var ogg = new StreamRegion (file.AsStream, 8); return new OggInput (ogg); // in case of exception ogg stream is left undisposed } diff --git a/ArcFormats/Crowd/ImageCWL.cs b/ArcFormats/Crowd/ImageCWL.cs index 071d5887..6ac73990 100644 --- a/ArcFormats/Crowd/ImageCWL.cs +++ b/ArcFormats/Crowd/ImageCWL.cs @@ -43,23 +43,21 @@ namespace GameRes.Formats.Crowd static readonly byte[] SignatureText = Encoding.ASCII.GetBytes ("cwd format - version 1.00 -"); - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x38]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x38); if (!header.Take (SignatureText.Length).SequenceEqual (SignatureText)) return null; uint key = header[0x34] + 0x259Au; return new ImageMetaData { - Width = LittleEndian.ToUInt32 (header, 0x2c) + key, - Height = LittleEndian.ToUInt32 (header, 0x30) + key, + Width = header.ToUInt32 (0x2c) + key, + Height = header.ToUInt32 (0x30) + key, BPP = 15, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { stream.Position = 0x38; int size = (int)info.Width * (int)info.Height * 2; @@ -82,36 +80,34 @@ namespace GameRes.Formats.Crowd public override string Description { get { return "LZ-compressed Crowd bitmap"; } } public override uint Signature { get { return 0x44445A53u; } } // 'SZDD' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { stream.Position = 0x0e; - using (var lz = new LzssReader (stream, 100, 0x38)) // extract CWD header + using (var lz = new LzssReader (stream.AsStream, 100, 0x38)) // extract CWD header { lz.FrameSize = 0x1000; lz.FrameFill = 0x20; lz.FrameInitPos = 0x1000 - 0x10; lz.Unpack(); - using (var cwd = new MemoryStream (lz.Data)) + using (var cwd = new BinMemoryStream (lz.Data, stream.Name)) return base.ReadMetaData (cwd); } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { - if (stream.Length > int.MaxValue) + if (file.Length > int.MaxValue) throw new FileSizeException(); - var header = new byte[14]; - if (header.Length != stream.Read (header, 0, header.Length)) - throw new InvalidFormatException(); - int data_length = LittleEndian.ToInt32 (header, 10); - int input_length = (int)(stream.Length-stream.Position); - using (var lz = new LzssReader (stream, input_length, data_length)) + var header = file.ReadHeader (14); + int data_length = header.ToInt32 (10); + int input_length = (int)(file.Length-file.Position); + using (var lz = new LzssReader (file.AsStream, input_length, data_length)) { lz.FrameSize = 0x1000; lz.FrameFill = 0x20; lz.FrameInitPos = 0x1000 - 0x10; lz.Unpack(); - using (var cwd = new MemoryStream (lz.Data)) + using (var cwd = new BinMemoryStream (lz.Data, file.Name)) return base.Read (cwd, info); } } diff --git a/ArcFormats/Crowd/ImageCWP.cs b/ArcFormats/Crowd/ImageCWP.cs index 061aeedf..bcc54d21 100644 --- a/ArcFormats/Crowd/ImageCWP.cs +++ b/ArcFormats/Crowd/ImageCWP.cs @@ -40,50 +40,47 @@ namespace GameRes.Formats.Crowd public override uint Signature { get { return 0x50445743; } } // 'CWDP' public override bool CanWrite { get { return true; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream input) { - using (var input = new ArcView.Reader (stream)) + input.Position = 4; + uint width = Binary.BigEndian (input.ReadUInt32()); + uint height = Binary.BigEndian (input.ReadUInt32()); + if (0 == width || 0 == height) + return null; + int bpp = input.ReadByte(); + int color_type = input.ReadByte(); + switch (color_type) { - input.ReadInt32(); - uint width = Binary.BigEndian (input.ReadUInt32()); - uint height = Binary.BigEndian (input.ReadUInt32()); - if (0 == width || 0 == height) - return null; - int bpp = input.ReadByte(); - int color_type = input.ReadByte(); - switch (color_type) - { - case 2: bpp *= 3; break; - case 4: bpp *= 2; break; - case 6: bpp *= 4; break; - case 3: - case 0: break; - default: return null; - } - return new ImageMetaData - { - Width = width, - Height = height, - BPP = bpp, - }; + case 2: bpp *= 3; break; + case 4: bpp *= 2; break; + case 6: bpp *= 4; break; + case 3: + case 0: break; + default: return null; } + return new ImageMetaData + { + Width = width, + Height = height, + BPP = bpp, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { var header = new byte[0x15]; - using (var mem = new MemoryStream((int)(0x14 + stream.Length + 12))) + using (var mem = new MemoryStream((int)(0x14 + file.Length + 12))) using (var png = new BinaryWriter (mem)) { png.Write (0x474E5089u); // png header png.Write (0x0A1A0A0Du); png.Write (0x0D000000u); png.Write (0x52444849u); // 'IHDR' - stream.Position = 4; - stream.Read (header, 0, header.Length); + file.Position = 4; + file.Read (header, 0, header.Length); png.Write (header, 0, header.Length); png.Write (0x54414449u); // 'IDAT' - stream.CopyTo (mem); + file.AsStream.CopyTo (mem); header[1] = 0; header[2] = 0; header[3] = 0; @@ -149,7 +146,9 @@ namespace GameRes.Formats.Crowd png.Read (header, 0, header.Length); cwp.Write (0x50445743u); // 'CWDP' cwp.Write (header, 0, header.Length); - var idat = PngFormat.FindChunk (png, "IDAT"); + long idat; + using (var bin = new BinMemoryStream (png, "")) + idat = PngFormat.FindChunk (bin, "IDAT"); if (-1 == idat) throw new InvalidFormatException ("CWP conversion failed"); png.Position = idat; diff --git a/ArcFormats/Crowd/ImageZBM.cs b/ArcFormats/Crowd/ImageZBM.cs index a2e33669..d1dbc2f2 100644 --- a/ArcFormats/Crowd/ImageZBM.cs +++ b/ArcFormats/Crowd/ImageZBM.cs @@ -39,10 +39,10 @@ namespace GameRes.Formats.Crowd public override uint Signature { get { return 0x44445A53u; } } // 'SZDD' public override bool CanWrite { get { return false; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { stream.Position = 0x0e; - using (var lz = new LzssReader (stream, 100, 54)) // extract BMP header + using (var lz = new LzssReader (stream.AsStream, 100, 54)) // extract BMP header { lz.FrameSize = 0x1000; lz.FrameFill = 0x20; @@ -51,21 +51,19 @@ namespace GameRes.Formats.Crowd var header = lz.Data; for (int i = 0; i < 54; ++i) header[i] ^= 0xff; - using (var bmp = new MemoryStream (header)) + using (var bmp = new BinMemoryStream (header, stream.Name)) return base.ReadMetaData (bmp); } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { if (stream.Length > int.MaxValue) throw new FileSizeException(); - var header = new byte[14]; - if (header.Length != stream.Read (header, 0, header.Length)) - throw new InvalidFormatException(); - int data_length = LittleEndian.ToInt32 (header, 10); + var header = stream.ReadHeader (14); + int data_length = header.ToInt32 (10); int input_length = (int)(stream.Length-stream.Position); - using (var lz = new LzssReader (stream, input_length, data_length)) + using (var lz = new LzssReader (stream.AsStream, input_length, data_length)) { lz.FrameSize = 0x1000; lz.FrameFill = 0x20; @@ -75,7 +73,7 @@ namespace GameRes.Formats.Crowd int count = Math.Min (100, data.Length); for (int i = 0; i < count; ++i) data[i] ^= 0xff; - using (var bmp = new MemoryStream (data)) + using (var bmp = new BinMemoryStream (data, stream.Name)) return base.Read (bmp, info); } } diff --git a/ArcFormats/CsWare/ArcPCS.cs b/ArcFormats/CsWare/ArcPCS.cs index 82d08317..36c2491a 100644 --- a/ArcFormats/CsWare/ArcPCS.cs +++ b/ArcFormats/CsWare/ArcPCS.cs @@ -149,7 +149,7 @@ namespace GameRes.Formats.CsWare header[i] = (byte)(pent.Key - header[i] - 1); } if (header_size == entry.Size) - return new MemoryStream (header); + return new BinMemoryStream (header, entry.Name); var rest = arc.File.CreateStream (entry.Offset+512, entry.Size-512); return new PrefixStream (header, rest); } diff --git a/ArcFormats/Cyberworks/AudioTINK.cs b/ArcFormats/Cyberworks/AudioTINK.cs index 6ea8ab2f..a30823f7 100644 --- a/ArcFormats/Cyberworks/AudioTINK.cs +++ b/ArcFormats/Cyberworks/AudioTINK.cs @@ -90,9 +90,8 @@ namespace GameRes.Formats.Cyberworks input = new MemoryStream (header); else input = new PrefixStream (header, new StreamRegion (file.AsStream, file.Position)); - var ogg = new BinaryStream (input, file.Name); - var sound = OggAudio.Instance.TryOpen (ogg); - if (sound != null && header.Length >= file.Length) + var sound = new OggInput (input); + if (header.Length >= file.Length) file.Dispose(); return sound; } diff --git a/ArcFormats/DDSystem/ArcDDP.cs b/ArcFormats/DDSystem/ArcDDP.cs index bb36b70d..3922a8a8 100644 --- a/ArcFormats/DDSystem/ArcDDP.cs +++ b/ArcFormats/DDSystem/ArcDDP.cs @@ -130,7 +130,7 @@ namespace GameRes.Formats.DDSystem reader.Unpack (data); if (data.Length > 16 && Binary.AsciiEqual (data, 0, "DDSxHXB")) DecryptHxb (data); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } diff --git a/ArcFormats/Dac/ArcDPK.cs b/ArcFormats/Dac/ArcDPK.cs index 152604c3..9742e776 100644 --- a/ArcFormats/Dac/ArcDPK.cs +++ b/ArcFormats/Dac/ArcDPK.cs @@ -157,7 +157,7 @@ namespace GameRes.Formats.Dac var data = new byte[entry.Size]; arc.File.View.Read (entry.Offset, data, 0, entry.Size); DecryptEntry (data, parc.Key1, parc.Key2, pentry); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } private void DecryptIndex (byte[] buf, int base_offset, int length, byte last) diff --git a/ArcFormats/Dac/ImageDGC.cs b/ArcFormats/Dac/ImageDGC.cs index d9f4e48b..fcbcfc08 100644 --- a/ArcFormats/Dac/ImageDGC.cs +++ b/ArcFormats/Dac/ImageDGC.cs @@ -43,28 +43,22 @@ namespace GameRes.Formats.Dac public override string Description { get { return "DAC engine image format"; } } public override uint Signature { get { return 0x00434744; } } // 'DGC' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var input = new ArcView.Reader (stream)) - { - input.ReadInt32(); - var info = new DgcMetaData(); - info.Flags = input.ReadUInt32(); - info.Width = input.ReadUInt16(); - info.Height = input.ReadUInt16(); - if (info.Width > 0x7fff || info.Height > 0x7fff) - return null; - info.BPP = 0 == (info.Flags & Reader.FlagAlphaChannel) ? 24 : 32; - return info; - } + file.Position = 4; + var info = new DgcMetaData(); + info.Flags = file.ReadUInt32(); + info.Width = file.ReadUInt16(); + info.Height = file.ReadUInt16(); + if (info.Width > 0x7fff || info.Height > 0x7fff) + return null; + info.BPP = 0 == (info.Flags & Reader.FlagAlphaChannel) ? 24 : 32; + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as DgcMetaData; - if (null == meta) - throw new ArgumentException ("DgcFormat.Read should be supplied with DgcMetaData", "info"); - + var meta = (DgcMetaData)info; stream.Position = 12; using (var reader = new Reader (stream, meta)) { @@ -80,7 +74,7 @@ namespace GameRes.Formats.Dac internal class Reader : IDataUnpacker, IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; readonly int m_width; readonly int m_height; @@ -96,11 +90,11 @@ namespace GameRes.Formats.Dac public byte[] Data { get { return m_output; } } public PixelFormat Format { get; private set; } - public Reader (Stream input, DgcMetaData info) + public Reader (IBinaryStream input, DgcMetaData info) { m_width = (int)info.Width; m_height = (int)info.Height; - m_input = new ArcView.Reader (input); + m_input = input; m_use_dict = 0 != (info.Flags & FlagUseDictionary); m_has_alpha = 0 != (info.Flags & FlagAlphaChannel); m_max_dict_size = (int)(info.Flags & 0xffffff); @@ -162,7 +156,7 @@ namespace GameRes.Formats.Dac if (dict_len > 256) i = m_input.ReadUInt16(); else - i = m_input.ReadByte(); + i = m_input.ReadUInt8(); i *= 3; m_output[dst] = dict[i]; m_output[dst+1] = dict[i+1]; @@ -178,7 +172,7 @@ namespace GameRes.Formats.Dac { var dict = new byte[m_max_dict_size * 3]; - int dict_len = m_input.ReadByte() + 1; + int dict_len = m_input.ReadUInt8() + 1; m_input.Read (dict, 0, dict_len * 3); for (int y = 0; y < m_height; y++) @@ -198,7 +192,7 @@ namespace GameRes.Formats.Dac { for (int x = 0; x < m_width; x++) { - int i = 3 * m_input.ReadByte(); + int i = 3 * m_input.ReadUInt8(); m_output[dst] = dict[i]; m_output[dst+1] = dict[i+1]; m_output[dst+2] = dict[i+2]; @@ -260,7 +254,7 @@ namespace GameRes.Formats.Dac { for (int x = 0; x < m_width; x++) { - m_output[dst] = m_input.ReadByte(); + m_output[dst] = m_input.ReadUInt8(); dst += m_pixel_size; } } @@ -290,7 +284,7 @@ namespace GameRes.Formats.Dac int index = 0; if (0 != (ctl & 0x2000)) { - index = m_input.ReadByte(); + index = m_input.ReadUInt8(); --length; } else @@ -314,7 +308,7 @@ namespace GameRes.Formats.Dac int index = 0; if (0 != (ctl & 0x2000)) { - index = m_input.ReadByte(); + index = m_input.ReadUInt8(); --length; } else @@ -337,11 +331,11 @@ namespace GameRes.Formats.Dac { while (length > 0) { - byte ctl = m_input.ReadByte(); + byte ctl = m_input.ReadUInt8(); --length; if (0 != ctl) { - int index = 3 * m_input.ReadByte(); + int index = 3 * m_input.ReadUInt8(); --length; while (0 != ctl--) { @@ -353,13 +347,13 @@ namespace GameRes.Formats.Dac } else { - ctl = m_input.ReadByte(); + ctl = m_input.ReadUInt8(); --length; if (0 == (ctl & 0x80)) { for (int count = ctl + 2; 0 != count; --count) { - int src = 3 * m_input.ReadByte(); + int src = 3 * m_input.ReadUInt8(); --length; m_output[dst] = dict[src]; m_output[dst+1] = dict[src+1]; @@ -369,7 +363,7 @@ namespace GameRes.Formats.Dac } else { - int offset = (short)((ctl << 8) | m_input.ReadByte()); + int offset = (short)((ctl << 8) | m_input.ReadUInt8()); --length; int count = (offset & 0x3F) + 4; offset >>= 6; @@ -386,11 +380,11 @@ namespace GameRes.Formats.Dac { while (length > 0) { - byte ctl = m_input.ReadByte(); + byte ctl = m_input.ReadUInt8(); --length; if (0 != ctl) { - byte alpha = m_input.ReadByte(); + byte alpha = m_input.ReadUInt8(); --length; while (0 != ctl--) { @@ -400,7 +394,7 @@ namespace GameRes.Formats.Dac } else { - ctl = m_input.ReadByte(); + ctl = m_input.ReadUInt8(); --length; if (0 == (ctl & 0x80)) { @@ -408,13 +402,13 @@ namespace GameRes.Formats.Dac length -= count; while (0 != count--) { - m_output[dst] = m_input.ReadByte(); + m_output[dst] = m_input.ReadUInt8(); dst += m_pixel_size; } } else { - int offset = (short)((ctl << 8) | m_input.ReadByte()); + int offset = (short)((ctl << 8) | m_input.ReadUInt8()); --length; int count = (offset & 0x3F) + 4; offset >>= 6; @@ -479,25 +473,10 @@ namespace GameRes.Formats.Dac } #region IDisposable Members - bool disposed = false; - public void Dispose () { - Dispose (true); GC.SuppressFinalize (this); } - - protected virtual void Dispose (bool disposing) - { - if (!disposed) - { - if (disposing) - { - m_input.Dispose(); - } - disposed = true; - } - } #endregion } } diff --git a/ArcFormats/Dogenzaka/ImageRSA.cs b/ArcFormats/Dogenzaka/ImageRSA.cs index 20caf11b..69e114b1 100644 --- a/ArcFormats/Dogenzaka/ImageRSA.cs +++ b/ArcFormats/Dogenzaka/ImageRSA.cs @@ -53,13 +53,14 @@ namespace GameRes.Formats.Dogenzaka public static readonly byte[] KnownKey = Encoding.ASCII.GetBytes ("Hlk9D28p"); - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { using (var sha = SHA1.Create()) { var key = sha.ComputeHash (KnownKey).Take (16).ToArray(); - using (var proxy = new InputProxyStream (stream, true)) - using (var input = new CryptoStream (proxy, new Rc4Transform (key), CryptoStreamMode.Read)) + using (var proxy = new InputProxyStream (stream.AsStream, true)) + using (var crypto = new CryptoStream (proxy, new Rc4Transform (key), CryptoStreamMode.Read)) + using (var input = new BinaryStream (crypto, stream.Name)) { var info = base.ReadMetaData (input); if (null == info) @@ -77,12 +78,13 @@ namespace GameRes.Formats.Dogenzaka } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var rc4 = (Rc4PngMetaData)info; using (var sha = SHA1.Create()) - using (var proxy = new InputProxyStream (stream, true)) - using (var input = new CryptoStream (proxy, new Rc4Transform (rc4.Key), CryptoStreamMode.Read)) + using (var proxy = new InputProxyStream (stream.AsStream, true)) + using (var crypto = new CryptoStream (proxy, new Rc4Transform (rc4.Key), CryptoStreamMode.Read)) + using (var input = new BinaryStream (crypto, stream.Name)) return base.Read (input, info); } diff --git a/ArcFormats/DraftImage.cs b/ArcFormats/DraftImage.cs index de6b481d..ca9b236f 100644 --- a/ArcFormats/DraftImage.cs +++ b/ArcFormats/DraftImage.cs @@ -31,11 +31,11 @@ namespace GameRes.Formats.?????? public override string Description { get { return "?????? image format"; } } public override uint Signature { get { return 0; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { var meta = (xxxMetaData)info; diff --git a/ArcFormats/DxLib/ArcDX.cs b/ArcFormats/DxLib/ArcDX.cs index 39e3be96..fdb3fcd1 100644 --- a/ArcFormats/DxLib/ArcDX.cs +++ b/ArcFormats/DxLib/ArcDX.cs @@ -145,7 +145,7 @@ namespace GameRes.Formats.DxLib using (input) { var data = Unpack (input); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } diff --git a/ArcFormats/DxLib/ArcMED.cs b/ArcFormats/DxLib/ArcMED.cs index eaeb94fa..d375a432 100644 --- a/ArcFormats/DxLib/ArcMED.cs +++ b/ArcFormats/DxLib/ArcMED.cs @@ -162,7 +162,7 @@ namespace GameRes.Formats.DxLib var offset = scr_arc.Encryption.StartOffset; scr_arc.Encryption.Decrypt (data, offset, data.Length-offset); } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } public override ResourceOptions GetDefaultOptions () diff --git a/ArcFormats/Eagls/ArcEAGLS.cs b/ArcFormats/Eagls/ArcEAGLS.cs index 010c8518..406b3288 100644 --- a/ArcFormats/Eagls/ArcEAGLS.cs +++ b/ArcFormats/Eagls/ArcEAGLS.cs @@ -333,7 +333,7 @@ namespace GameRes.Formats.Eagls { byte[] input = File.View.ReadBytes (entry.Offset, entry.Size); Encryption.Decrypt (input); - return new MemoryStream (input); + return new BinMemoryStream (input, entry.Name); } } } diff --git a/ArcFormats/Eagls/ImageGR.cs b/ArcFormats/Eagls/ImageGR.cs index cf95d0de..e8a80541 100644 --- a/ArcFormats/Eagls/ImageGR.cs +++ b/ArcFormats/Eagls/ImageGR.cs @@ -45,9 +45,9 @@ namespace GameRes.Formats.Eagls public override uint Signature { get { return 0; } } public override bool CanWrite { get { return false; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var lzs = new LzssStream (stream, LzssMode.Decompress, true)) + using (var lzs = new LzssStream (file.AsStream, LzssMode.Decompress, true)) { if (lzs.ReadByte() != 'B' || lzs.ReadByte() != 'M') return null; @@ -71,10 +71,11 @@ namespace GameRes.Formats.Eagls } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { var meta = (GrMetaData)info; - using (var bmp = new LzssStream (stream, LzssMode.Decompress, true)) + using (var lzs = new LzssStream (file.AsStream, LzssMode.Decompress, true)) + using (var bmp = new BinaryStream (lzs, file.Name)) { if (32 != info.BPP) return base.Read (bmp, info); diff --git a/ArcFormats/Emic/ImageMWP.cs b/ArcFormats/Emic/ImageMWP.cs index 7681d25e..53a542c1 100644 --- a/ArcFormats/Emic/ImageMWP.cs +++ b/ArcFormats/Emic/ImageMWP.cs @@ -43,24 +43,22 @@ namespace GameRes.Formats.Emic Signatures = new uint[] { 0x1050574D, 0x4C594554 }; // 'TEYL' } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - var header = new byte[12]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + file.Position = 4; return new ImageMetaData { - Width = LittleEndian.ToUInt32 (header, 4), - Height = LittleEndian.ToUInt32 (header, 8), + Width = file.ReadUInt32(), + Height = file.ReadUInt32(), BPP = 32, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { var pixels = new byte[info.Width*info.Height*4]; - stream.Position = 12; - if (pixels.Length != stream.Read (pixels, 0, pixels.Length)) + file.Position = 12; + if (pixels.Length != file.Read (pixels, 0, pixels.Length)) throw new EndOfStreamException(); return ImageData.Create (info, PixelFormats.Bgra32, null, pixels); } diff --git a/ArcFormats/EmonEngine/ArcEME.cs b/ArcFormats/EmonEngine/ArcEME.cs index c23272f8..e41ed383 100644 --- a/ArcFormats/EmonEngine/ArcEME.cs +++ b/ArcFormats/EmonEngine/ArcEME.cs @@ -128,7 +128,7 @@ namespace GameRes.Formats.EmonEngine lzss.Config.FrameInitPos = entry.LzssInitPos; lzss.Read (data, part1_size, unpacked_size); } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } else { diff --git a/ArcFormats/Emote/ArcPSB.cs b/ArcFormats/Emote/ArcPSB.cs index d5ee40e5..1243e09d 100644 --- a/ArcFormats/Emote/ArcPSB.cs +++ b/ArcFormats/Emote/ArcPSB.cs @@ -583,10 +583,10 @@ namespace GameRes.Formats.Emote Extensions = new string[0]; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { stream.Position = 4; - using (var reader = new BinaryReader (stream, Encoding.UTF8, true)) + using (var reader = new BinaryReader (stream.AsStream, Encoding.UTF8, true)) { var info = new PsbTexMetaData { BPP = 32 }; info.DataOffset = reader.ReadInt32(); @@ -599,14 +599,14 @@ namespace GameRes.Formats.Emote } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (PsbTexMetaData)info; var pixels = new byte[meta.Width * meta.Height * 4]; if ("RGBA8" == meta.TexType) - ReadRgba8 (stream, meta, pixels); + ReadRgba8 (stream.AsStream, meta, pixels); else if ("RGBA4444" == meta.TexType) - ReadRgba4444 (stream, meta, pixels); + ReadRgba4444 (stream.AsStream, meta, pixels); else throw new NotImplementedException (string.Format ("PSB texture format '{0}' not implemented", meta.TexType)); return ImageData.Create (info, PixelFormats.Bgra32, null, pixels); diff --git a/ArcFormats/Entis/AudioMIO.cs b/ArcFormats/Entis/AudioMIO.cs index 9c787f7d..890de297 100644 --- a/ArcFormats/Entis/AudioMIO.cs +++ b/ArcFormats/Entis/AudioMIO.cs @@ -42,17 +42,15 @@ namespace GameRes.Formats.Entis public override string Description { get { return "Entis engine compressed audio format"; } } public override uint Signature { get { return 0x69746e45u; } } // 'Enti' - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - byte[] header = new byte[0x40]; - if (header.Length != file.Read (header, 0, header.Length)) + var header = file.ReadHeader (0x40); + if (0x03000100 != header.ToUInt32 (8)) return null; - if (0x03000100 != LittleEndian.ToUInt32 (header, 8)) - return null; - if (!Binary.AsciiEqual (header, 0x10, "Music Interleaved")) + if (!header.AsciiEqual (0x10, "Music Interleaved")) return null; - return new MioInput (file); + return new MioInput (file.AsStream); } } diff --git a/ArcFormats/Entis/ImageERI.cs b/ArcFormats/Entis/ImageERI.cs index 7dbde246..38e39a9f 100644 --- a/ArcFormats/Entis/ImageERI.cs +++ b/ArcFormats/Entis/ImageERI.cs @@ -149,17 +149,15 @@ namespace GameRes.Formats.Entis public override string Description { get { return "Entis rasterized image format"; } } public override uint Signature { get { return 0x69746e45u; } } // 'Enti' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - byte[] header = new byte[0x40]; - if (header.Length != stream.Read (header, 0, header.Length)) + var header = stream.ReadHeader (0x40); + if (0x03000100 != header.ToUInt32 (8)) return null; - if (0x03000100 != LittleEndian.ToUInt32 (header, 8)) + if (!header.AsciiEqual (0x10, "Entis Rasterized Image") + && !header.AsciiEqual (0x10, "Moving Entis Image")) return null; - if (!Binary.AsciiEqual (header, 0x10, "Entis Rasterized Image") - && !Binary.AsciiEqual (header, 0x10, "Moving Entis Image")) - return null; - using (var reader = new EriFile (stream)) + using (var reader = new EriFile (stream.AsStream)) { var section = reader.ReadSection(); if (section.Id != "Header " || section.Length <= 0) @@ -240,7 +238,7 @@ namespace GameRes.Formats.Entis } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var reader = ReadImageData (stream, (EriMetaData)info); return ImageData.Create (info, reader.Format, reader.Palette, reader.Data, reader.Stride); @@ -261,11 +259,11 @@ namespace GameRes.Formats.Entis return colors; } - internal EriReader ReadImageData (Stream stream, EriMetaData meta) + internal EriReader ReadImageData (IBinaryStream stream, EriMetaData meta) { stream.Position = meta.StreamPos; Color[] palette = null; - using (var input = new EriFile (stream)) + using (var input = new EriFile (stream.AsStream)) { for (;;) // ReadSection throws an exception in case of EOF { @@ -276,13 +274,13 @@ namespace GameRes.Formats.Entis break; if ("Palette " == section.Id && meta.BPP <= 8 && section.Length <= 0x400) { - palette = ReadPalette (stream, (int)section.Length); + palette = ReadPalette (stream.AsStream, (int)section.Length); continue; } input.BaseStream.Seek (section.Length, SeekOrigin.Current); } } - var reader = new EriReader (stream, meta, palette); + var reader = new EriReader (stream.AsStream, meta, palette); reader.DecodeImage(); if (!string.IsNullOrEmpty (meta.Description)) @@ -298,7 +296,7 @@ namespace GameRes.Formats.Entis throw new InvalidFormatException(); ref_file = VFS.CombinePath (VFS.GetDirectoryName (meta.FileName), ref_file); - using (var ref_src = VFS.OpenSeekableStream (ref_file)) + using (var ref_src = VFS.OpenBinaryStream (ref_file)) { var ref_info = ReadMetaData (ref_src) as EriMetaData; if (null == ref_info) diff --git a/ArcFormats/Ethornell/ArcBGI.cs b/ArcFormats/Ethornell/ArcBGI.cs index 9a99cc28..951e6ec2 100644 --- a/ArcFormats/Ethornell/ArcBGI.cs +++ b/ArcFormats/Ethornell/ArcBGI.cs @@ -83,7 +83,7 @@ namespace GameRes.Formats.BGI using (var decoder = new DscDecoder (input)) { decoder.Unpack(); - return new MemoryStream (decoder.Output); + return new BinMemoryStream (decoder.Output, entry.Name); } } return new ArcView.ArcStream (input, entry_offset, entry.Size); diff --git a/ArcFormats/Ethornell/AudioBGI.cs b/ArcFormats/Ethornell/AudioBGI.cs index c03c3153..8e72f6c1 100644 --- a/ArcFormats/Ethornell/AudioBGI.cs +++ b/ArcFormats/Ethornell/AudioBGI.cs @@ -41,18 +41,16 @@ namespace GameRes.Formats.BGI Extensions = new string[] { "" }; } - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - var header = new byte[8]; - if (8 != file.Read (header, 0, 8)) + var header = file.ReadHeader (8); + if (!header.AsciiEqual (4, "bw ")) return null; - if (!Binary.AsciiEqual (header, 4, "bw ")) - return null; - uint offset = LittleEndian.ToUInt32 (header, 0); + uint offset = header.ToUInt32 (0); if (offset >= file.Length) return null; - var input = new StreamRegion (file, offset); + var input = new StreamRegion (file.AsStream, offset); return new OggInput (input); // input is left undisposed in case of exception. } diff --git a/ArcFormats/Ethornell/ImageBGI.cs b/ArcFormats/Ethornell/ImageBGI.cs index 995216d6..35e89dab 100644 --- a/ArcFormats/Ethornell/ImageBGI.cs +++ b/ArcFormats/Ethornell/ImageBGI.cs @@ -51,29 +51,26 @@ namespace GameRes.Formats.BGI throw new System.NotImplementedException ("BgiFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - using (var input = new ArcView.Reader (stream)) + int width = stream.ReadInt16(); + int height = stream.ReadInt16(); + if (width <= 0 || height <= 0) + return null; + int bpp = stream.ReadInt32(); + if (24 != bpp && 32 != bpp && 8 != bpp) + return null; + if (0 != stream.ReadInt64()) + return null; + return new ImageMetaData { - int width = input.ReadInt16(); - int height = input.ReadInt16(); - if (width <= 0 || height <= 0) - return null; - int bpp = input.ReadInt32(); - if (24 != bpp && 32 != bpp && 8 != bpp) - return null; - if (0 != input.ReadInt64()) - return null; - return new ImageMetaData - { - Width = (uint)width, - Height = (uint)height, - BPP = bpp, - }; - } + Width = (uint)width, + Height = (uint)height, + BPP = bpp, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { PixelFormat format; if (24 == info.BPP) @@ -119,33 +116,29 @@ namespace GameRes.Formats.BGI throw new System.NotImplementedException ("BgiFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x30]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - if (!Binary.AsciiEqual (header, "CompressedBG___")) + var header = stream.ReadHeader (0x30); + if (!header.AsciiEqual ("CompressedBG___")) return null; return new CbgMetaData { - Width = LittleEndian.ToUInt16 (header, 0x10), - Height = LittleEndian.ToUInt16 (header, 0x12), - BPP = LittleEndian.ToInt32 (header, 0x14), - IntermediateLength = LittleEndian.ToInt32 (header, 0x20), - Key = LittleEndian.ToUInt32 (header, 0x24), - EncLength = LittleEndian.ToInt32 (header, 0x28), + Width = header.ToUInt16 (0x10), + Height = header.ToUInt16 (0x12), + BPP = header.ToInt32 (0x14), + IntermediateLength = header.ToInt32 (0x20), + Key = header.ToUInt32 (0x24), + EncLength = header.ToInt32 (0x28), CheckSum = header[0x2C], CheckXor = header[0x2D], - Version = LittleEndian.ToUInt16 (header, 0x2E), + Version = header.ToUInt16 (0x2E), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as CbgMetaData; - if (null == meta) - throw new ArgumentException ("CompressedBGFormat.Read should be supplied with CbgMetaData", "info"); - using (var reader = new CbgReader (stream, meta)) + var meta = (CbgMetaData)info as CbgMetaData; + using (var reader = new CbgReader (stream.AsStream, meta)) { reader.Unpack(); return ImageData.Create (meta, reader.Format, null, reader.Data, reader.Stride); diff --git a/ArcFormats/Eushully/ImageAGF.cs b/ArcFormats/Eushully/ImageAGF.cs index 68b41ce3..cbc6c4e6 100644 --- a/ArcFormats/Eushully/ImageAGF.cs +++ b/ArcFormats/Eushully/ImageAGF.cs @@ -51,7 +51,7 @@ namespace GameRes.Formats.Eushully Signatures = new uint[] { 0x46474341, 0 }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { var header = new byte[0x20]; if (0x18 != stream.Read (header, 0, 0x18)) @@ -64,7 +64,7 @@ namespace GameRes.Formats.Eushully return null; int unpacked_size = LittleEndian.ToInt32 (header, 0x10); int packed_size = LittleEndian.ToInt32 (header, 0x14); - using (var unpacked = AgfReader.OpenSection (stream, unpacked_size, packed_size)) + using (var unpacked = AgfReader.OpenSection (stream.AsStream, unpacked_size, packed_size)) using (var reader = new BinaryReader (unpacked)) { if (0x20 != reader.Read (header, 0, 0x20)) @@ -101,7 +101,7 @@ namespace GameRes.Formats.Eushully return palette; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { using (var reader = new AgfReader (stream, (AgfMetaData)info)) { @@ -118,7 +118,7 @@ namespace GameRes.Formats.Eushully internal sealed class AgfReader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; int m_width; int m_height; @@ -129,9 +129,9 @@ namespace GameRes.Formats.Eushully public PixelFormat Format { get; private set; } public byte[] Data { get { return m_output; } } - public AgfReader (Stream input, AgfMetaData info) + public AgfReader (IBinaryStream input, AgfMetaData info) { - m_input = new ArcView.Reader (input); + m_input = input; m_bpp = info.BPP; m_source_bpp = info.SourceBPP; input.Position = info.DataOffset; @@ -155,15 +155,15 @@ namespace GameRes.Formats.Eushully m_input.ReadInt32(); int data_size = m_input.ReadInt32(); int packed_size = m_input.ReadInt32(); - var data_pos = m_input.BaseStream.Position; + var data_pos = m_input.Position; var bmp_data = new byte[data_size]; - using (var unpacked = OpenSection (m_input.BaseStream, data_size, packed_size)) + using (var unpacked = OpenSection (m_input.AsStream, data_size, packed_size)) if (data_size != unpacked.Read (bmp_data, 0, data_size)) throw new EndOfStreamException(); byte[] alpha = null; if (32 == m_bpp) { - m_input.BaseStream.Position = data_pos + packed_size; + m_input.Position = data_pos + packed_size; alpha = ReadAlphaChannel(); if (null == alpha) m_bpp = 24; @@ -231,21 +231,15 @@ namespace GameRes.Formats.Eushully if (m_width*m_height != unpacked_size) return null; var alpha = new byte[unpacked_size]; - using (var unpacked = OpenSection (m_input.BaseStream, unpacked_size, packed_size)) + using (var unpacked = OpenSection (m_input.AsStream, unpacked_size, packed_size)) if (unpacked_size != unpacked.Read (alpha, 0, unpacked_size)) return null; return alpha; } #region IDisposable methods - bool _disposed = false; public void Dispose () { - if (!_disposed) - { - m_input.Dispose(); - _disposed = true; - } } #endregion } diff --git a/ArcFormats/Eushully/ImageGP.cs b/ArcFormats/Eushully/ImageGP.cs index 7dc45e16..ab7e1ece 100644 --- a/ArcFormats/Eushully/ImageGP.cs +++ b/ArcFormats/Eushully/ImageGP.cs @@ -53,7 +53,7 @@ namespace GameRes.Formats.Eushully Extensions = new string[] { "gpcf" }; // made-up, real files have no extension } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { int alpha_channel = stream.ReadByte(); int method = stream.ReadByte(); @@ -64,30 +64,28 @@ namespace GameRes.Formats.Eushully || align1 < 0 || align1 > 4 || align2 < 0 || align2 > 4 || bpp <= 0 || !(bpp <= 16 || 24 == bpp || 32 == bpp)) return null; - using (var reader = new ArcView.Reader (stream)) + + int palette_size = stream.ReadInt32(); + uint width = stream.ReadUInt16(); + uint height = stream.ReadUInt16(); + if (palette_size <= 0 || 0 == width || 0 == height || palette_size >= stream.Length) + return null; + if (bpp <= 8 && palette_size > 0x100) + return null; + return new GpMetaData { - int palette_size = reader.ReadInt32(); - uint width = reader.ReadUInt16(); - uint height = reader.ReadUInt16(); - if (palette_size <= 0 || 0 == width || 0 == height || palette_size >= stream.Length) - return null; - if (bpp <= 8 && palette_size > 0x100) - return null; - return new GpMetaData - { - Width = width, - Height = height, - BPP = bpp, - HasAlpha = alpha_channel != 0, - Method = method, - ElementSize = align1, - PixelsPerElement = align2, - PaletteSize = palette_size, - }; - } + Width = width, + Height = height, + BPP = bpp, + HasAlpha = alpha_channel != 0, + Method = method, + ElementSize = align1, + PixelsPerElement = align2, + PaletteSize = palette_size, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (GpMetaData)info; using (var reader = new GpReader (stream, meta)) @@ -105,7 +103,7 @@ namespace GameRes.Formats.Eushully internal sealed class GpReader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; GpMetaData m_info; int m_width; int m_height; @@ -115,17 +113,17 @@ namespace GameRes.Formats.Eushully public byte[] Data { get; private set; } public int Stride { get; private set; } - public GpReader (Stream input, GpMetaData info) + public GpReader (IBinaryStream input, GpMetaData info) { m_info = info; m_width = (int)m_info.Width; m_height = (int)m_info.Height; - m_input = new ArcView.Reader (input); + m_input = input; } public void Unpack () { - m_input.BaseStream.Position = 0xD; + m_input.Position = 0xD; switch (m_info.Method) { case 0: UnpackV0(); break; @@ -293,8 +291,8 @@ namespace GameRes.Formats.Eushully int i = 3; while (i < Data.Length) { - byte alpha = m_input.ReadByte(); - int count = m_input.ReadByte(); + byte alpha = m_input.ReadUInt8(); + int count = m_input.ReadUInt8(); for (int j = 0; j < count && i < Data.Length; ++j) { Data[i] = alpha; @@ -305,14 +303,8 @@ namespace GameRes.Formats.Eushully } #region IDisposable Members - bool _disposed = false; public void Dispose () { - if (!_disposed) - { - m_input.Dispose(); - _disposed = true; - } } #endregion } diff --git a/ArcFormats/ExHibit/ImageGYU.cs b/ArcFormats/ExHibit/ImageGYU.cs index b96f131d..e0ad42d0 100644 --- a/ArcFormats/ExHibit/ImageGYU.cs +++ b/ArcFormats/ExHibit/ImageGYU.cs @@ -69,29 +69,26 @@ namespace GameRes.Formats.ExHibit set { KnownKeys = ((GyuMap)value).KnownKeys; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - using (var reader = new ArcView.Reader (stream)) + stream.Position = 4; + return new GyuMetaData { - reader.ReadInt32(); - return new GyuMetaData - { - Flags = reader.ReadUInt16(), - CompressionMode = reader.ReadUInt16(), - Key = reader.ReadUInt32(), - BPP = reader.ReadInt32(), - Width = reader.ReadUInt32(), - Height = reader.ReadUInt32(), - DataSize = reader.ReadInt32(), - AlphaSize = reader.ReadInt32(), - PaletteSize = reader.ReadInt32(), - }; - } + Flags = stream.ReadUInt16(), + CompressionMode = stream.ReadUInt16(), + Key = stream.ReadUInt32(), + BPP = stream.ReadInt32(), + Width = stream.ReadUInt32(), + Height = stream.ReadUInt32(), + DataSize = stream.ReadInt32(), + AlphaSize = stream.ReadInt32(), + PaletteSize = stream.ReadInt32(), + }; } IDictionary CurrentMap = null; - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (GyuMetaData)info; if (0 == meta.Key) @@ -111,7 +108,7 @@ namespace GameRes.Formats.ExHibit throw new UnknownEncryptionScheme ("Unknown image encryption key"); } } - var reader = new GyuReader (stream, meta); + var reader = new GyuReader (stream.AsStream, meta); reader.Unpack(); return ImageData.CreateFlipped (meta, reader.Format, reader.Palette, reader.Data, reader.Stride); } diff --git a/ArcFormats/FC01/ArcMRG.cs b/ArcFormats/FC01/ArcMRG.cs index 631b1c92..f2752e7c 100644 --- a/ArcFormats/FC01/ArcMRG.cs +++ b/ArcFormats/FC01/ArcMRG.cs @@ -114,7 +114,7 @@ namespace GameRes.Formats.FC01 var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); var reader = new MrgDecoder (data); reader.Unpack(); - input = new MemoryStream (reader.Data); + input = new BinMemoryStream (reader.Data, entry.Name); } else input = arc.File.CreateStream (entry.Offset, entry.Size); @@ -124,7 +124,7 @@ namespace GameRes.Formats.FC01 using (var reader = new MrgLzssReader (input, (int)input.Length, (int)packed_entry.UnpackedSize)) { reader.Unpack(); - return new MemoryStream (reader.Data); + return new BinMemoryStream (reader.Data, entry.Name); } } return input; @@ -240,14 +240,14 @@ namespace GameRes.Formats.FC01 { var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); Decrypt (data, 0, data.Length, mrg_entry.Key, mrg_entry.ArcKey); - input = new MemoryStream (data); + input = new BinMemoryStream (data, entry.Name); } else if (mrg_entry.Method >= 2) { var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); var reader = new MrgDecoder (data); reader.Unpack(); - input = new MemoryStream (reader.Data); + input = new BinMemoryStream (reader.Data, entry.Name); } else input = arc.File.CreateStream (entry.Offset, entry.Size); @@ -257,7 +257,7 @@ namespace GameRes.Formats.FC01 using (var reader = new MrgLzssReader (input, (int)input.Length, (int)mrg_entry.UnpackedSize)) { reader.Unpack(); - return new MemoryStream (reader.Data); + return new BinMemoryStream (reader.Data, entry.Name); } } return input; diff --git a/ArcFormats/FC01/ImageACD.cs b/ArcFormats/FC01/ImageACD.cs index ade96d95..95b1ea9f 100644 --- a/ArcFormats/FC01/ImageACD.cs +++ b/ArcFormats/FC01/ImageACD.cs @@ -45,20 +45,18 @@ namespace GameRes.Formats.FC01 public override string Description { get { return "F&C Co. image format"; } } public override uint Signature { get { return 0x20444341; } } // 'ACD' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x1c]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - int header_size = LittleEndian.ToInt32 (header, 8); - if (!Binary.AsciiEqual (header, 4, "1.00") || header_size < 0x1c) + var header = stream.ReadHeader (0x1c); + int header_size = header.ToInt32 (8); + if (!header.AsciiEqual (4, "1.00") || header_size < 0x1c) throw new NotSupportedException ("Not supported ACD image version"); - int packed_size = LittleEndian.ToInt32 (header, 0x0C); - int unpacked_size = LittleEndian.ToInt32 (header, 0x10); + int packed_size = header.ToInt32 (0x0C); + int unpacked_size = header.ToInt32 (0x10); return new AcdMetaData { - Width = LittleEndian.ToUInt32 (header, 0x14), - Height = LittleEndian.ToUInt32 (header, 0x18), + Width = header.ToUInt32 (0x14), + Height = header.ToUInt32 (0x18), BPP = 24, DataOffset = header_size, PackedSize = packed_size, @@ -66,14 +64,12 @@ namespace GameRes.Formats.FC01 }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as AcdMetaData; - if (null == meta) - throw new ArgumentException ("AcdFormat.Read should be supplied with AcdMetaData", "info"); + var meta = (AcdMetaData)info; stream.Position = meta.DataOffset; - using (var reader = new MrgLzssReader (stream, meta.PackedSize, meta.UnpackedSize)) + using (var reader = new MrgLzssReader (stream.AsStream, meta.PackedSize, meta.UnpackedSize)) { reader.Unpack(); var decoder = new AcdDecoder (reader.Data, meta); diff --git a/ArcFormats/FC01/ImageCLM.cs b/ArcFormats/FC01/ImageCLM.cs index 7196ed78..10cd3e6b 100644 --- a/ArcFormats/FC01/ImageCLM.cs +++ b/ArcFormats/FC01/ImageCLM.cs @@ -45,20 +45,18 @@ namespace GameRes.Formats.FC01 public override string Description { get { return "F&C Co. image format"; } } public override uint Signature { get { return 0x204D4C43; } } // 'CLM' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x40]; - if (header.Length != stream.Read (header, 0, header.Length)) + var header = stream.ReadHeader (0x40); + if (!header.AsciiEqual (4, "1.00")) return null; - if (!Binary.AsciiEqual (header, 4, "1.00")) - return null; - uint data_offset = LittleEndian.ToUInt32 (header, 0x10); + uint data_offset = header.ToUInt32 (0x10); if (data_offset < 0x40) return null; - uint width = LittleEndian.ToUInt32 (header, 0x1C); - uint height = LittleEndian.ToUInt32 (header, 0x20); - int bpp = LittleEndian.ToInt32 (header, 0x24); - int unpacked_size = LittleEndian.ToInt32 (header, 0x28); + uint width = header.ToUInt32 (0x1C); + uint height = header.ToUInt32 (0x20); + int bpp = header.ToInt32 (0x24); + int unpacked_size = header.ToInt32 (0x28); return new ClmMetaData { Width = width, @@ -69,7 +67,7 @@ namespace GameRes.Formats.FC01 }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (ClmMetaData)info; stream.Position = meta.DataOffset; @@ -78,7 +76,7 @@ namespace GameRes.Formats.FC01 if (8 == meta.BPP) { format = PixelFormats.Indexed8; - palette = ReadPalette (stream); + palette = ReadPalette (stream.AsStream); } else if (24 == meta.BPP) format = PixelFormats.Bgr24; @@ -87,7 +85,7 @@ namespace GameRes.Formats.FC01 else throw new NotSupportedException ("Not supported CLM color depth"); int packed_size = (int)(stream.Length - stream.Position); - using (var reader = new MrgLzssReader (stream, packed_size, meta.UnpackedSize)) + using (var reader = new MrgLzssReader (stream.AsStream, packed_size, meta.UnpackedSize)) { reader.Unpack(); return ImageData.Create (info, format, palette, reader.Data); diff --git a/ArcFormats/FC01/ImageMCG.cs b/ArcFormats/FC01/ImageMCG.cs index 8edb2bb0..e1e38b2f 100644 --- a/ArcFormats/FC01/ImageMCG.cs +++ b/ArcFormats/FC01/ImageMCG.cs @@ -67,31 +67,29 @@ namespace GameRes.Formats.FC01 set { KnownKeys = ((McgScheme)value).KnownKeys; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - byte[] header = new byte[0x40]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x40); if (header[5] != '.') return null; int version = header[4] * 100 + header[6] * 10 + header[7] - 0x14D0; if (version != 200 && version != 101) throw new NotSupportedException ("Not supported MCG format version"); - int header_size = LittleEndian.ToInt32 (header, 0x10); + int header_size = header.ToInt32 (0x10); if (header_size < 0x40) return null; - int bpp = LittleEndian.ToInt32 (header, 0x24); + int bpp = header.ToInt32 (0x24); if (24 != bpp) throw new NotSupportedException ("Not supported MCG image bitdepth"); return new McgMetaData { - Width = LittleEndian.ToUInt32 (header, 0x1c), - Height = LittleEndian.ToUInt32 (header, 0x20), - OffsetX = LittleEndian.ToInt32 (header, 0x14), - OffsetY = LittleEndian.ToInt32 (header, 0x18), + Width = header.ToUInt32 (0x1c), + Height = header.ToUInt32 (0x20), + OffsetX = header.ToInt32 (0x14), + OffsetY = header.ToInt32 (0x18), BPP = bpp, DataOffset = header_size, - PackedSize = LittleEndian.ToInt32 (header, 0x38) - header_size, + PackedSize = header.ToInt32 (0x38) - header_size, Version = version, }; } @@ -99,7 +97,7 @@ namespace GameRes.Formats.FC01 // cache key value so that dialog does not pop up on every file accessed. byte? LastKey = null; - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (McgMetaData)info; byte key = Settings.Default.MCGLastKey; @@ -113,7 +111,7 @@ namespace GameRes.Formats.FC01 else key = LastKey.Value; } - var reader = new McgDecoder (stream, meta, key); + var reader = new McgDecoder (stream.AsStream, meta, key); reader.Unpack(); if (reader.Key != 0) LastKey = reader.Key; diff --git a/ArcFormats/Favorite/ArcFVP.cs b/ArcFormats/Favorite/ArcFVP.cs index d62efd9b..e8d4b48d 100644 --- a/ArcFormats/Favorite/ArcFVP.cs +++ b/ArcFormats/Favorite/ArcFVP.cs @@ -80,7 +80,7 @@ namespace GameRes.Formats.FVP using (var decoder = new LzwDecoder (input, unpacked_size)) { decoder.Unpack(); - return new MemoryStream (decoder.Output); + return new BinMemoryStream (decoder.Output, entry.Name); } } } diff --git a/ArcFormats/Favorite/ImageHZC.cs b/ArcFormats/Favorite/ImageHZC.cs index 2d911654..a0a71166 100644 --- a/ArcFormats/Favorite/ImageHZC.cs +++ b/ArcFormats/Favorite/ImageHZC.cs @@ -47,28 +47,26 @@ namespace GameRes.Formats.FVP public override string Description { get { return "Favorite View Point image format"; } } public override uint Signature { get { return 0x31637A68; } } // 'HZC1' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x2C]; - if (header.Length != stream.Read (header, 0, header.Length)) + var header = stream.ReadHeader (0x2C); + if (!header.AsciiEqual (0xC, "NVSG")) return null; - if (!Binary.AsciiEqual (header, 0xC, "NVSG")) - return null; - int type = LittleEndian.ToUInt16 (header, 0x12); + int type = header.ToUInt16 (0x12); return new HzcMetaData { - Width = LittleEndian.ToUInt16 (header, 0x14), - Height = LittleEndian.ToUInt16 (header, 0x16), - OffsetX = LittleEndian.ToInt16 (header, 0x18), - OffsetY = LittleEndian.ToInt16 (header, 0x1A), + Width = header.ToUInt16 (0x14), + Height = header.ToUInt16 (0x16), + OffsetX = header.ToInt16 (0x18), + OffsetY = header.ToInt16 (0x1A), BPP = 0 == type ? 24 : type > 2 ? 8 : 32, Type = type, - UnpackedSize = LittleEndian.ToInt32 (header, 4), - HeaderSize = LittleEndian.ToInt32 (header, 8), + UnpackedSize = header.ToInt32 (4), + HeaderSize = header.ToInt32 (8), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (HzcMetaData)info; BitmapPalette palette = null; @@ -90,7 +88,7 @@ namespace GameRes.Formats.FVP } } stream.Position = 12 + meta.HeaderSize; - using (var z = new ZLibStream (stream, CompressionMode.Decompress, true)) + using (var z = new ZLibStream (stream.AsStream, CompressionMode.Decompress, true)) { var pixels = new byte[stride * (int)meta.Height]; if (pixels.Length != z.Read (pixels, 0, pixels.Length)) diff --git a/ArcFormats/Ffa/ArcBlackPackage.cs b/ArcFormats/Ffa/ArcBlackPackage.cs index ab2f7d6d..d65e98c9 100644 --- a/ArcFormats/Ffa/ArcBlackPackage.cs +++ b/ArcFormats/Ffa/ArcBlackPackage.cs @@ -92,7 +92,7 @@ namespace GameRes.Formats.Ffa using (var reader = new LzssReader (input, packed, unpacked)) { reader.Unpack(); - return new MemoryStream (reader.Data); + return new BinMemoryStream (reader.Data, entry.Name); } } } diff --git a/ArcFormats/Ffa/AudioWA1.cs b/ArcFormats/Ffa/AudioWA1.cs index 3e10175f..cacb797a 100644 --- a/ArcFormats/Ffa/AudioWA1.cs +++ b/ArcFormats/Ffa/AudioWA1.cs @@ -39,18 +39,9 @@ namespace GameRes.Formats.Ffa public override string Description { get { return "FFA System wave audio format"; } } public override uint Signature { get { return 0; } } - private static int ReadInt32 (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - int dword = file.ReadByte(); - dword |= file.ReadByte() << 8; - dword |= file.ReadByte() << 16; - dword |= file.ReadByte() << 24; - return dword; - } - - public override SoundInput TryOpen (Stream file) - { - int packed = ReadInt32 (file); + int packed = file.ReadInt32(); if (packed < 0) return null; byte[] input; @@ -58,10 +49,10 @@ namespace GameRes.Formats.Ffa { if ((packed + 8) != file.Length) return null; - int unpacked = ReadInt32 (file); + int unpacked = file.ReadInt32(); if (unpacked <= 0) return null; - using (var reader = new LzssReader (file, packed, unpacked)) + using (var reader = new LzssReader (file.AsStream, packed, unpacked)) { reader.Unpack(); if (Binary.AsciiEqual (reader.Data, 0, "RIFF")) @@ -75,7 +66,7 @@ namespace GameRes.Formats.Ffa } else { - if (0x46464952 != ReadInt32 (file)) // 'RIFF' + if (0x46464952 != file.ReadInt32()) // 'RIFF' return null; file.Position = 0; input = new byte[file.Length]; diff --git a/ArcFormats/Ffa/AudioWA2.cs b/ArcFormats/Ffa/AudioWA2.cs index 9a5e2eb2..1ffb3763 100644 --- a/ArcFormats/Ffa/AudioWA2.cs +++ b/ArcFormats/Ffa/AudioWA2.cs @@ -36,7 +36,7 @@ namespace GameRes.Formats.Ffa public override string Description { get { return "FFA System PCM audio format"; } } public override uint Signature { get { return 0x4D435041; } } // 'APCM' - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { return new Wa2Input (file); } @@ -51,27 +51,25 @@ namespace GameRes.Formats.Ffa get { return (int)Format.AverageBytesPerSecond * 8; } } - public Wa2Input (Stream file) : base (null) + public Wa2Input (IBinaryStream file) : base (null) { - var header = new byte[0x2C]; - if (header.Length != file.Read (header, 0, header.Length)) - throw new EndOfStreamException(); - if (!Binary.AsciiEqual (header, 8, "WAVEfmt ")) + var header = file.ReadHeader (0x2C); + if (!header.AsciiEqual (8, "WAVEfmt ")) throw new InvalidFormatException(); var format = new WaveFormat(); - format.FormatTag = LittleEndian.ToUInt16 (header, 0x14); - format.Channels = LittleEndian.ToUInt16 (header, 0x16); - format.SamplesPerSecond = LittleEndian.ToUInt32 (header, 0x18); - format.AverageBytesPerSecond = LittleEndian.ToUInt32 (header, 0x1C); - format.BlockAlign = LittleEndian.ToUInt16 (header, 0x20); - format.BitsPerSample = LittleEndian.ToUInt16 (header, 0x22); + format.FormatTag = header.ToUInt16 (0x14); + format.Channels = header.ToUInt16 (0x16); + format.SamplesPerSecond = header.ToUInt32 (0x18); + format.AverageBytesPerSecond = header.ToUInt32 (0x1C); + format.BlockAlign = header.ToUInt16 (0x20); + format.BitsPerSample = header.ToUInt16 (0x22); format.ExtraSize = 0; this.Format = format; - uint pcm_size = LittleEndian.ToUInt32 (header, 0x28); + uint pcm_size = header.ToUInt32 (0x28); var pcm = new byte[pcm_size]; - Decode (file, pcm); + Decode (file.AsStream, pcm); Source = new MemoryStream (pcm); this.PcmSize = pcm_size; file.Dispose(); diff --git a/ArcFormats/Ffa/ImagePT1.cs b/ArcFormats/Ffa/ImagePT1.cs index 6fa53187..9095fdf7 100644 --- a/ArcFormats/Ffa/ImagePT1.cs +++ b/ArcFormats/Ffa/ImagePT1.cs @@ -59,40 +59,37 @@ namespace GameRes.Formats.Ffa throw new NotImplementedException ("Pt1Format.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var input = new ArcView.Reader (stream)) - { - int type = input.ReadInt32(); - if (type < 0 || type > 3) - return null; - if (-1 != input.ReadInt32()) - return null; - int x = input.ReadInt32(); - int y = input.ReadInt32(); - uint width = input.ReadUInt32(); - uint height = input.ReadUInt32(); - uint comp_size = input.ReadUInt32(); - uint uncomp_size = input.ReadUInt32(); - if (uncomp_size != width*height*3u) - return null; - return new Pt1MetaData { - Width = width, - Height = height, - OffsetX = x, - OffsetY = y, - BPP = 3 == type ? 32 : 24, - Type = type, - PackedSize = comp_size, - UnpackedSize = uncomp_size - }; - } + int type = file.ReadInt32(); + if (type < 0 || type > 3) + return null; + if (-1 != file.ReadInt32()) + return null; + int x = file.ReadInt32(); + int y = file.ReadInt32(); + uint width = file.ReadUInt32(); + uint height = file.ReadUInt32(); + uint comp_size = file.ReadUInt32(); + uint uncomp_size = file.ReadUInt32(); + if (uncomp_size != width*height*3u) + return null; + return new Pt1MetaData { + Width = width, + Height = height, + OffsetX = x, + OffsetY = y, + BPP = 3 == type ? 32 : 24, + Type = type, + PackedSize = comp_size, + UnpackedSize = uncomp_size + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (Pt1MetaData)info; - var reader = new Reader (stream, meta); + var reader = new Reader (stream.AsStream, meta); reader.Unpack(); return ImageData.Create (meta, reader.Format, null, reader.Data); } diff --git a/ArcFormats/G2/ArcGCEX.cs b/ArcFormats/G2/ArcGCEX.cs index 13a2c705..dba94f48 100644 --- a/ArcFormats/G2/ArcGCEX.cs +++ b/ArcFormats/G2/ArcGCEX.cs @@ -125,7 +125,7 @@ namespace GameRes.Formats.G2 using (input) using (var reader = new GceReader (input, (int)pentry.UnpackedSize)) { - return new MemoryStream (reader.Data); + return new BinMemoryStream (reader.Data, entry.Name); } } } diff --git a/ArcFormats/G2/ImageBGRA.cs b/ArcFormats/G2/ImageBGRA.cs index a00094d8..50d179a2 100644 --- a/ArcFormats/G2/ImageBGRA.cs +++ b/ArcFormats/G2/ImageBGRA.cs @@ -42,25 +42,23 @@ namespace GameRes.Formats.G2 Extensions = new string[] { "argb", "arg" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x10]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - uint bitmap = LittleEndian.ToUInt32 (header, 4); + stream.Position = 4; + uint bitmap = stream.ReadUInt32(); if (0x08080808 != bitmap) return null; return new ImageMetaData { - Width = LittleEndian.ToUInt32 (header, 8), - Height = LittleEndian.ToUInt32 (header, 12), + Width = stream.ReadUInt32(), + Height = stream.ReadUInt32(), BPP = 32, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - stream.Seek (0x10, SeekOrigin.Current); + stream.Position = 0x10; var pixels = new byte[info.Width*info.Height*4]; if (pixels.Length != stream.Read (pixels, 0, pixels.Length)) throw new EndOfStreamException(); diff --git a/ArcFormats/Glib2/ArcG2.cs b/ArcFormats/Glib2/ArcG2.cs index e04b338f..19b87f13 100644 --- a/ArcFormats/Glib2/ArcG2.cs +++ b/ArcFormats/Glib2/ArcG2.cs @@ -193,7 +193,7 @@ namespace GameRes.Formats.Glib2 current_decoder = (current_decoder + 1) & 3; offset += current_chunk_size; } - return new MemoryStream (output); + return new BinMemoryStream (output, entry.Name); } } diff --git a/ArcFormats/Glib2/ImagePGX.cs b/ArcFormats/Glib2/ImagePGX.cs index 2e8d53bf..e7c1d03f 100644 --- a/ArcFormats/Glib2/ImagePGX.cs +++ b/ArcFormats/Glib2/ImagePGX.cs @@ -58,34 +58,32 @@ namespace GameRes.Formats.Glib2 static readonly InfoReader InfoCache = new InfoReader(); - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x18]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x18); return new PgxMetaData { - Width = LittleEndian.ToUInt32 (header, 8), - Height = LittleEndian.ToUInt32 (header, 12), - BPP = (LittleEndian.ToInt16 (header, 0x10) & 1) == 0 ? 24 : 32, - PackedSize = LittleEndian.ToInt32 (header, 0x14), - Flags = LittleEndian.ToUInt16 (header, 0x12), + Width = header.ToUInt32 (8), + Height = header.ToUInt32 (12), + BPP = (header.ToInt16 (0x10) & 1) == 0 ? 24 : 32, + PackedSize = header.ToInt32 (0x14), + Flags = header.ToUInt16 (0x12), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (PgxMetaData)info; stream.Position = 0x20; if (0 != (meta.Flags & 0x1000)) { - ReadGms (stream); + ReadGms (stream.AsStream); } PixelFormat format = 32 == meta.BPP ? PixelFormats.Bgra32 : PixelFormats.Bgr32; int stride = (int)meta.Width * 4; var pixels = new byte[stride * (int)meta.Height]; // stream.Seek (-meta.PackedSize, SeekOrigin.End); - LzssUnpack (stream, pixels); + LzssUnpack (stream.AsStream, pixels); var layer = InfoCache.GetInfo (info.FileName); if (null != layer && null != layer.Rect) { diff --git a/ArcFormats/Gpk2/ImageGFB.cs b/ArcFormats/Gpk2/ImageGFB.cs index ed18ca7f..4d0d1c9e 100644 --- a/ArcFormats/Gpk2/ImageGFB.cs +++ b/ArcFormats/Gpk2/ImageGFB.cs @@ -29,7 +29,6 @@ using System.IO; using System.Windows.Media; using System.Windows.Media.Imaging; using GameRes.Compression; -using GameRes.Utility; namespace GameRes.Formats.Gpk2 { @@ -47,37 +46,35 @@ namespace GameRes.Formats.Gpk2 public override string Description { get { return "GPK2 image format"; } } public override uint Signature { get { return 0x20424647; } } // 'GFB ' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x40]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x40); return new GfbMetaData { - Width = LittleEndian.ToUInt32 (header, 0x1C), - Height = LittleEndian.ToUInt32 (header, 0x20), - BPP = LittleEndian.ToUInt16 (header, 0x26), - PackedSize = LittleEndian.ToInt32 (header,0x0C), - UnpackedSize = LittleEndian.ToInt32 (header,0x10), - DataOffset = LittleEndian.ToInt32 (header,0x14), + Width = header.ToUInt32 (0x1C), + Height = header.ToUInt32 (0x20), + BPP = header.ToUInt16 (0x26), + PackedSize = header.ToInt32 (0x0C), + UnpackedSize = header.ToInt32 (0x10), + DataOffset = header.ToInt32 (0x14), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (GfbMetaData)info; BitmapPalette palette = null; if (8 == meta.BPP && meta.DataOffset != 0x40) { stream.Position = 0x40; - palette = ReadPalette (stream, meta.DataOffset - 0x40); + palette = ReadPalette (stream.AsStream, meta.DataOffset - 0x40); } stream.Position = meta.DataOffset; byte[] pixels = new byte[meta.UnpackedSize]; if (0 != meta.PackedSize) { - using (var lzss = new LzssStream (stream, LzssMode.Decompress, true)) + using (var lzss = new LzssStream (stream.AsStream, LzssMode.Decompress, true)) lzss.Read (pixels, 0, pixels.Length); } else diff --git a/ArcFormats/GsPack/ImageGS.cs b/ArcFormats/GsPack/ImageGS.cs index 328290bd..c515c99c 100644 --- a/ArcFormats/GsPack/ImageGS.cs +++ b/ArcFormats/GsPack/ImageGS.cs @@ -54,36 +54,33 @@ namespace GameRes.Formats.Gs Extensions = new string[] { "pic" }; // made-up } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var input = new ArcView.Reader (stream)) + file.Position = 4; + var info = new PicMetaData(); + info.PackedSize = file.ReadUInt32(); + info.UnpackedSize = file.ReadUInt32(); + info.HeaderSize = file.ReadUInt32(); + if (info.HeaderSize >= file.Length || info.PackedSize + info.HeaderSize > file.Length) + return null; + file.ReadUInt32(); + info.Width = file.ReadUInt32(); + info.Height = file.ReadUInt32(); + info.BPP = file.ReadInt32(); + if (info.HeaderSize >= 0x2C) { - var info = new PicMetaData(); - input.ReadUInt32(); - info.PackedSize = input.ReadUInt32(); - info.UnpackedSize = input.ReadUInt32(); - info.HeaderSize = input.ReadUInt32(); - if (info.HeaderSize >= stream.Length || info.PackedSize + info.HeaderSize > stream.Length) - return null; - input.ReadUInt32(); - info.Width = input.ReadUInt32(); - info.Height = input.ReadUInt32(); - info.BPP = input.ReadInt32(); - if (info.HeaderSize >= 0x2C) - { - input.ReadInt32(); - info.OffsetX = input.ReadInt32(); - info.OffsetY = input.ReadInt32(); - } - return info; + file.ReadInt32(); + info.OffsetX = file.ReadInt32(); + info.OffsetY = file.ReadInt32(); } + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { var meta = (PicMetaData)info; - stream.Position = meta.HeaderSize; - using (var input = new LzssStream (stream, LzssMode.Decompress, true)) + file.Position = meta.HeaderSize; + using (var input = new LzssStream (file.AsStream, LzssMode.Decompress, true)) { BitmapPalette palette = null; PixelFormat format; diff --git a/ArcFormats/Hexenhaus/ArcWAG.cs b/ArcFormats/Hexenhaus/ArcWAG.cs index f477306b..cb04dd08 100644 --- a/ArcFormats/Hexenhaus/ArcWAG.cs +++ b/ArcFormats/Hexenhaus/ArcWAG.cs @@ -157,16 +157,16 @@ namespace GameRes.Formats.Hexenhaus Extensions = new string[] { "png" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { ImageMetaData info; - using (var png = new StreamRegion (stream, 0x10, true)) + using (var input = new StreamRegion (stream.AsStream, 0x10, true)) + using (var png = new BinaryStream (input, stream.Name)) info = base.ReadMetaData (png); if (null == info) return null; stream.Seek (-14, SeekOrigin.End); - var cntr = new byte[12]; - stream.Read (cntr, 0, 12); + var cntr = stream.ReadBytes (12); if (Binary.AsciiEqual (cntr, "CNTR")) { info.OffsetX = LittleEndian.ToInt32 (cntr, 4); @@ -175,9 +175,10 @@ namespace GameRes.Formats.Hexenhaus return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - using (var png = new StreamRegion (stream, 0x10, true)) + using (var input = new StreamRegion (stream.AsStream, 0x10, true)) + using (var png = new BinaryStream (input, stream.Name)) return base.Read (png, info); } diff --git a/ArcFormats/Ikura/ArcDRS.cs b/ArcFormats/Ikura/ArcDRS.cs index bd33b2fc..25cedd97 100644 --- a/ArcFormats/Ikura/ArcDRS.cs +++ b/ArcFormats/Ikura/ArcDRS.cs @@ -213,7 +213,7 @@ namespace GameRes.Formats.Ikura byte key = data[6]; ApplyTransformation (data, 8, x => x ^ key); } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } public override ResourceOptions GetDefaultOptions () diff --git a/ArcFormats/Ikura/ImageDRG.cs b/ArcFormats/Ikura/ImageDRG.cs index 0ae21c29..b33a8868 100644 --- a/ArcFormats/Ikura/ImageDRG.cs +++ b/ArcFormats/Ikura/ImageDRG.cs @@ -58,9 +58,9 @@ namespace GameRes.Formats.Ikura } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - uint signature = ~FormatCatalog.ReadSignature (stream); + uint signature = ~stream.Signature; int bpp; switch (signature) { @@ -69,19 +69,16 @@ namespace GameRes.Formats.Ikura case 0x48474948: bpp = 16; break; default: return null; } - using (var input = new BinaryReader (stream, Encoding.ASCII, true)) - { - uint width = input.ReadUInt16(); - uint height = input.ReadUInt16(); - return new ImageMetaData { - Width = width, - Height = height, - BPP = bpp, - }; - } + uint width = stream.ReadUInt16(); + uint height = stream.ReadUInt16(); + return new ImageMetaData { + Width = width, + Height = height, + BPP = bpp, + }; } - public override ImageData Read (Stream file, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { file.Position = 8; PixelFormat format; @@ -91,7 +88,7 @@ namespace GameRes.Formats.Ikura format = PixelFormats.Bgr565; int stride = ((int)info.Width * info.BPP / 8 + 3) & ~3; - var pixel_data = DecodeStream (file, stride*(int)info.Height); + var pixel_data = DecodeStream (file.AsStream, stride*(int)info.Height); if (null == pixel_data) throw new InvalidFormatException(); return ImageData.Create (info, format, null, pixel_data, stride); @@ -414,28 +411,25 @@ namespace GameRes.Formats.Ikura public override string Description { get { return "Digital Romance System indexed image format"; } } public override uint Signature { get { return ~0x47363532u; } } // '256G' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var input = new ArcView.Reader (stream)) + file.Position = 4; + var info = new GgdMetaData { BPP = 8 }; + info.HeaderSize = file.ReadUInt32(); + info.Width = file.ReadUInt32(); + int height = file.ReadInt32(); + if (height < 0) { - input.ReadUInt32(); - var info = new GgdMetaData { BPP = 8 }; - info.HeaderSize = input.ReadUInt32(); - info.Width = input.ReadUInt32(); - int height = input.ReadInt32(); - if (height < 0) - { - height = -height; - info.Flipped = true; - } - info.Height = (uint)height; - input.ReadInt64(); - info.BitmapSize = input.ReadUInt32(); - return info; + height = -height; + info.Flipped = true; } + info.Height = (uint)height; + file.ReadInt64(); + info.BitmapSize = file.ReadUInt32(); + return info; } - public override ImageData Read (Stream file, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { var meta = (GgdMetaData)info; file.Position = meta.HeaderSize + 4; @@ -449,7 +443,7 @@ namespace GameRes.Formats.Ikura } file.Seek (4, SeekOrigin.Current); int input_size = (int)(file.Length - file.Position); - using (var reader = new LzssReader (file, input_size, (int)meta.BitmapSize)) + using (var reader = new LzssReader (file.AsStream, input_size, (int)meta.BitmapSize)) { reader.Unpack(); var palette = new BitmapPalette (colors); @@ -488,153 +482,146 @@ namespace GameRes.Formats.Ikura throw new NotImplementedException ("GgaFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[24]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - if (!Binary.AsciiEqual (header, "GGA00000")) + var header = stream.ReadHeader (24); + if (!header.AsciiEqual ("GGA00000")) return null; return new GgaMetaData { - Width = LittleEndian.ToUInt16 (header, 8), - Height = LittleEndian.ToUInt16 (header, 10), + Width = header.ToUInt16 (8), + Height = header.ToUInt16 (10), BPP = header[14], Flags = header[15], - HeaderSize = LittleEndian.ToUInt32 (header, 16), - CompSize = LittleEndian.ToUInt32 (header, 20) + HeaderSize = header.ToUInt32 (16), + CompSize = header.ToUInt32 (20) }; } - public override ImageData Read (Stream file, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { - var meta = info as GgaMetaData; - if (null == meta) - throw new ArgumentException ("GgaFormat.Read should be supplied with GgaMetaData", "info"); + var meta = (GgaMetaData)info; file.Position = meta.HeaderSize; var pixel_data = DecodeStream (file, meta); PixelFormat format = 0 == (meta.Flags & 1) ? PixelFormats.Bgr32 : PixelFormats.Bgra32; return ImageData.Create (info, format, null, pixel_data); } - byte[] DecodeStream (Stream file, GgaMetaData meta) + byte[] DecodeStream (IBinaryStream input, GgaMetaData meta) { int dst = 0; var output = new byte[meta.Width*meta.Height*4]; - using (var input = new BinaryReader (file, Encoding.ASCII, true)) + var end_pos = input.Position + meta.CompSize; + while (input.Position < end_pos) { - var end_pos = input.BaseStream.Position + meta.CompSize; - while (input.BaseStream.Position < end_pos) + int code = input.ReadByte(); + switch (code) { - int code = input.ReadByte(); - switch (code) + case 0: { - case 0: - { - int src = dst - 4; - int count = input.ReadByte() * 4; - Binary.CopyOverlapped (output, src, dst, count); - dst += count; - break; - } - case 1: - { - int src = dst - 4; - int count = input.ReadUInt16() * 4; - Binary.CopyOverlapped (output, src, dst, count); - dst += count; - break; - } - case 2: - { - int l = input.ReadByte(); - int src = dst - (l << 2); - System.Buffer.BlockCopy (output, src, output, dst, 4); - dst += 4; - break; - } - case 3: - { - int l = input.ReadUInt16(); - int src = dst - (l << 2); - System.Buffer.BlockCopy (output, src, output, dst, 4); - dst += 4; - break; - } - case 4: - { - int l = input.ReadByte(); - int src = dst - (l << 2); - int count = input.ReadByte() * 4; - Binary.CopyOverlapped (output, src, dst, count); - dst += count; - break; - } - case 5: - { - int l = input.ReadByte(); - int src = dst - (l << 2); - int count = input.ReadUInt16() * 4; - Binary.CopyOverlapped (output, src, dst, count); - dst += count; - break; - } - case 6: - { - int l = input.ReadUInt16(); - int src = dst - (l << 2); - int count = input.ReadByte() * 4; - Binary.CopyOverlapped (output, src, dst, count); - dst += count; - break; - } - case 7: - { - int l = input.ReadUInt16(); - int src = dst - (l << 2); - int count = input.ReadUInt16() * 4; - Binary.CopyOverlapped (output, src, dst, count); - dst += count; - break; - } - case 8: - { - System.Buffer.BlockCopy (output, dst-4, output, dst, 4); - dst += 4; - break; - } - case 9: - { - int src = dst - (int)meta.Width * 4; - System.Buffer.BlockCopy (output, src, output, dst, 4); - dst += 4; - break; - } - case 0x0a: - { - int src = dst - ((int)meta.Width * 4 + 4); - System.Buffer.BlockCopy (output, src, output, dst, 4); - dst += 4; - break; - } - case 0x0b: - { - int src = dst - ((int)meta.Width * 4 - 4); - System.Buffer.BlockCopy (output, src, output, dst, 4); - dst += 4; - break; - } - default: - { - int count = (code-11)*4; - if (count != input.Read (output, dst, count)) - throw new InvalidFormatException ("Unexpected end of input"); - dst += count; - break; - } + int src = dst - 4; + int count = input.ReadByte() * 4; + Binary.CopyOverlapped (output, src, dst, count); + dst += count; + break; + } + case 1: + { + int src = dst - 4; + int count = input.ReadUInt16() * 4; + Binary.CopyOverlapped (output, src, dst, count); + dst += count; + break; + } + case 2: + { + int l = input.ReadByte(); + int src = dst - (l << 2); + System.Buffer.BlockCopy (output, src, output, dst, 4); + dst += 4; + break; + } + case 3: + { + int l = input.ReadUInt16(); + int src = dst - (l << 2); + System.Buffer.BlockCopy (output, src, output, dst, 4); + dst += 4; + break; + } + case 4: + { + int l = input.ReadByte(); + int src = dst - (l << 2); + int count = input.ReadByte() * 4; + Binary.CopyOverlapped (output, src, dst, count); + dst += count; + break; + } + case 5: + { + int l = input.ReadByte(); + int src = dst - (l << 2); + int count = input.ReadUInt16() * 4; + Binary.CopyOverlapped (output, src, dst, count); + dst += count; + break; + } + case 6: + { + int l = input.ReadUInt16(); + int src = dst - (l << 2); + int count = input.ReadByte() * 4; + Binary.CopyOverlapped (output, src, dst, count); + dst += count; + break; + } + case 7: + { + int l = input.ReadUInt16(); + int src = dst - (l << 2); + int count = input.ReadUInt16() * 4; + Binary.CopyOverlapped (output, src, dst, count); + dst += count; + break; + } + case 8: + { + System.Buffer.BlockCopy (output, dst-4, output, dst, 4); + dst += 4; + break; + } + case 9: + { + int src = dst - (int)meta.Width * 4; + System.Buffer.BlockCopy (output, src, output, dst, 4); + dst += 4; + break; + } + case 0x0a: + { + int src = dst - ((int)meta.Width * 4 + 4); + System.Buffer.BlockCopy (output, src, output, dst, 4); + dst += 4; + break; + } + case 0x0b: + { + int src = dst - ((int)meta.Width * 4 - 4); + System.Buffer.BlockCopy (output, src, output, dst, 4); + dst += 4; + break; + } + default: + { + int count = (code-11)*4; + if (count != input.Read (output, dst, count)) + throw new InvalidFormatException ("Unexpected end of input"); + dst += count; + break; } } - return output; } + return output; } } } diff --git a/ArcFormats/Ikura/ImageGGP.cs b/ArcFormats/Ikura/ImageGGP.cs index f437dcac..9ba72803 100644 --- a/ArcFormats/Ikura/ImageGGP.cs +++ b/ArcFormats/Ikura/ImageGGP.cs @@ -45,22 +45,21 @@ namespace GameRes.Formats.Ikura public override uint Signature { get { return 0x46504747u; } } // 'GGPF' public override bool CanWrite { get { return false; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x24]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - if (!Binary.AsciiEqual (header, 0, "GGPFAIKE")) + var header = stream.ReadHeader (0x24); + if (!header.AsciiEqual ("GGPFAIKE")) return null; var info = new GgpMetaData { - Offset = LittleEndian.ToUInt32 (header, 0x14), - Length = LittleEndian.ToUInt32 (header, 0x18), + Offset = header.ToUInt32 (0x14), + Length = header.ToUInt32 (0x18), }; for (int i = 0; i < 8; ++i) info.Key[i] = (byte)(header[i] ^ header[i+0xC]); stream.Position = info.Offset; - using (var png = new EncryptedStream (stream, info.Key, true)) + using (var enc = new EncryptedStream (stream.AsStream, info.Key, true)) + using (var png = new BinaryStream (enc, stream.Name)) { var png_info = base.ReadMetaData (png); info.Width = png_info.Width; @@ -72,13 +71,12 @@ namespace GameRes.Formats.Ikura } } - public override ImageData Read (Stream file, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { - var meta = info as GgpMetaData; - if (null == meta) - throw new ArgumentException ("GgpFormat.Read should be supplied with GgpMetaData", "info"); - using (var input = new StreamRegion (file, meta.Offset, meta.Length, true)) - using (var png = new EncryptedStream (input, meta.Key, true)) + var meta = (GgpMetaData)info; + using (var input = new StreamRegion (file.AsStream, meta.Offset, meta.Length, true)) + using (var enc = new EncryptedStream (input, meta.Key)) + using (var png = new BinaryStream (enc, file.Name)) return base.Read (png, info); } diff --git a/ArcFormats/Ikura/ImageYGP.cs b/ArcFormats/Ikura/ImageYGP.cs index 2ba18d6b..f721c444 100644 --- a/ArcFormats/Ikura/ImageYGP.cs +++ b/ArcFormats/Ikura/ImageYGP.cs @@ -45,50 +45,44 @@ namespace GameRes.Formats.Ikura public override string Description { get { return "Ikura GDL image format"; } } public override uint Signature { get { return 0x504759; } } // 'YGP' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { stream.Position = 4; - using (var reader = new ArcView.Reader (stream)) + int mask_pos = stream.ReadUInt16(); // 04 + byte type = stream.ReadUInt8(); // 06 + if (type != 1 && type != 2) + return null; + var info = new YgpMetaData { Type = type, BPP = 32 }; + info.Flags = stream.ReadUInt8(); // 07 + int header_size = stream.ReadInt32(); // 08 + stream.Position = header_size; + info.DataSize = stream.ReadInt32(); // XX+00 + info.Width = stream.ReadUInt16(); // XX+04 + info.Height = stream.ReadUInt16(); // XX+06 + info.DataOffset = header_size+8; + if (0 != (info.Flags & 4)) { - int mask_pos = reader.ReadUInt16(); // 04 - byte type = reader.ReadByte(); // 06 - if (type != 1 && type != 2) - return null; - var info = new YgpMetaData { Type = type, BPP = 32 }; - info.Flags = reader.ReadByte(); // 07 - int header_size = reader.ReadInt32(); // 08 - stream.Position = header_size; - info.DataSize = reader.ReadInt32(); // XX+00 - info.Width = reader.ReadUInt16(); // XX+04 - info.Height = reader.ReadUInt16(); // XX+06 - info.DataOffset = header_size+8; - if (0 != (info.Flags & 4)) - { - stream.Position = 0x14; - info.OffsetX = reader.ReadInt16(); - info.OffsetY = reader.ReadInt16(); - } - return info; + stream.Position = 0x14; + info.OffsetX = stream.ReadInt16(); + info.OffsetY = stream.ReadInt16(); } + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (YgpMetaData)info; stream.Position = meta.DataOffset; int stride = (int)meta.Width * 4; var pixels = new byte[stride * (int)meta.Height]; if (0 != (meta.Flags & 1)) - { - using (var reader = new ArcView.Reader (stream)) - Unpack (reader, meta.DataSize, pixels); - } + Unpack (stream, meta.DataSize, pixels); else stream.Read (pixels, 0, pixels.Length); return ImageData.Create (info, PixelFormats.Bgra32, null, pixels); } - void Unpack (BinaryReader input, int input_size, byte[] output) + void Unpack (IBinaryStream input, int input_size, byte[] output) { int dst = 0; while (input_size > 0) diff --git a/ArcFormats/ImageDDS.cs b/ArcFormats/ImageDDS.cs index 174b134c..85299076 100644 --- a/ArcFormats/ImageDDS.cs +++ b/ArcFormats/ImageDDS.cs @@ -61,34 +61,32 @@ namespace GameRes.Formats.Microsoft public override string Description { get { return "Direct Draw Surface format"; } } public override uint Signature { get { return 0x20534444; } } // 'DDS' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x6C]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - int dwSize = LittleEndian.ToInt32 (header, 4); + var header = stream.ReadHeader (0x6C); + int dwSize = header.ToInt32 (4); if (dwSize < 0x7C) return null; - var bitflags = (DdsPF)LittleEndian.ToUInt32 (header, 0x50); + var bitflags = (DdsPF)header.ToUInt32 (0x50); string four_cc = null; if (bitflags.HasFlag (DdsPF.FourCC)) - four_cc = Binary.GetCString (header, 0x54, 4, Encoding.ASCII); + four_cc = Binary.GetCString (header.ToArray(), 0x54, 4, Encoding.ASCII); return new DdsMetaData { - Width = LittleEndian.ToUInt32 (header, 0x10), - Height = LittleEndian.ToUInt32 (header, 0xC), - BPP = LittleEndian.ToInt32 (header, 0x58), + Width = header.ToUInt32 (0x10), + Height = header.ToUInt32 (0xC), + BPP = header.ToInt32 (0x58), PixelFlags = bitflags, FourCC = four_cc, - RBitMask = LittleEndian.ToUInt32 (header, 0x5C), - GBitMask = LittleEndian.ToUInt32 (header, 0x60), - BBitMask = LittleEndian.ToUInt32 (header, 0x64), - ABitMask = LittleEndian.ToUInt32 (header, 0x68), + RBitMask = header.ToUInt32 (0x5C), + GBitMask = header.ToUInt32 (0x60), + BBitMask = header.ToUInt32 (0x64), + ABitMask = header.ToUInt32 (0x68), DataOffset = 4 + dwSize, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (DdsMetaData)info; if (meta.PixelFlags.HasFlag (DdsPF.Yuv | DdsPF.Luminance)) @@ -98,7 +96,7 @@ namespace GameRes.Formats.Microsoft if (meta.PixelFlags.HasFlag (DdsPF.Rgb) && (0 == meta.RBitMask || 0 == meta.GBitMask || 0 == meta.BBitMask)) throw new InvalidFormatException(); - var pixels = ReadPixelData (stream, meta); + var pixels = ReadPixelData (stream.AsStream, meta); PixelFormat format; if (meta.PixelFlags.HasFlag (DdsPF.AlphaPixels) && meta.ABitMask != 0) format = PixelFormats.Bgra32; diff --git a/ArcFormats/ImageEGN.cs b/ArcFormats/ImageEGN.cs index 94aaeec6..9079493d 100644 --- a/ArcFormats/ImageEGN.cs +++ b/ArcFormats/ImageEGN.cs @@ -49,74 +49,66 @@ namespace GameRes.Formats.Unknown public override uint Signature { get { return 0; } } public override bool CanWrite { get { return false; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - using (var input = new ArcView.Reader (stream)) + int signature = (int)~stream.Signature; + int mode = (signature & 0x70) >> 4; // v6 + if (0 != (mode & 4)) + return null; + int flag = signature & 0xF; // v7 + int data_size, data_offset; + if (0 != (signature & 0x80)) { - int signature = ~input.ReadInt32(); - int mode = (signature & 0x70) >> 4; // v6 - if (0 != (mode & 4)) + data_offset = 4; + data_size = Binary.BigEndian (signature) & 0xFFFFFF; + } + else + { + data_offset = 8; + data_size = Binary.BigEndian (stream.ReadInt32()); + } + if (data_size <= 0 || data_size > 0xFFFFFF) // arbitrary max BMP size + return null; + var reader = new Reader (stream, 0x36, mode, flag); // size of BMP header + reader.Unpack(); + using (var bmp = new BinMemoryStream (reader.Data, stream.Name)) + { + var info = base.ReadMetaData (bmp); + if (null == info) return null; - int flag = signature & 0xF; // v7 - int data_size, data_offset; - if (0 != (signature & 0x80)) + return new EgnMetaData { - data_offset = 4; - data_size = Binary.BigEndian (signature) & 0xFFFFFF; - } - else - { - data_offset = 8; - data_size = Binary.BigEndian (input.ReadInt32()); - } - if (data_size <= 0 || data_size > 0xFFFFFF) // arbitrary max BMP size - return null; - var reader = new Reader (input, 0x36, mode, flag); // size of BMP header - reader.Unpack(); - using (var bmp = new MemoryStream (reader.Data)) - { - var info = base.ReadMetaData (bmp); - if (null == info) - return null; - return new EgnMetaData - { - Width = info.Width, - Height = info.Height, - BPP = info.BPP, - Mode = mode, - Flag = flag, - DataOffset = data_offset, - UnpackedSize = data_size, - }; - } + Width = info.Width, + Height = info.Height, + BPP = info.BPP, + Mode = mode, + Flag = flag, + DataOffset = data_offset, + UnpackedSize = data_size, + }; } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as EgnMetaData; - if (null == meta) - throw new ArgumentException ("EgnFormat.Read should be supplied with EgnMetaData", "info"); + var meta = (EgnMetaData)info; stream.Position = meta.DataOffset; - using (var input = new ArcView.Reader (stream)) - { - var reader = new Reader (input, meta.UnpackedSize, meta.Mode, meta.Flag); - reader.Unpack(); - using (var bmp = new MemoryStream (reader.Data)) - return base.Read (bmp, info); - } + var reader = new Reader (stream, meta.UnpackedSize, meta.Mode, meta.Flag); + reader.Unpack(); + using (var bmp = new BinMemoryStream (reader.Data, stream.Name)) + return base.Read (bmp, info); } internal class Reader { - BinaryReader m_input; + IBinaryStream m_input; int m_mode; int m_flag; byte[] m_output; public byte[] Data { get { return m_output; } } - public Reader (BinaryReader input, int output_size, int mode, int flag) + public Reader (IBinaryStream input, int output_size, int mode, int flag) { m_input = input; m_mode = mode; @@ -153,12 +145,12 @@ namespace GameRes.Formats.Unknown v8 >>= 1; if (0 == v8) { - v12 = m_input.ReadByte(); + v12 = m_input.ReadUInt8(); v8 = 0x80; } if (0 != (v8 & v12)) { - m_output[dst++] = m_input.ReadByte(); + m_output[dst++] = m_input.ReadUInt8(); } else { diff --git a/ArcFormats/ImageISG.cs b/ArcFormats/ImageISG.cs index c7371923..1fef6d27 100644 --- a/ArcFormats/ImageISG.cs +++ b/ArcFormats/ImageISG.cs @@ -55,33 +55,29 @@ namespace GameRes.Formats.ISM throw new NotImplementedException ("IsgFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x24]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - if (!Binary.AsciiEqual (header, "ISM IMAGEFILE\x00")) + var header = stream.ReadHeader (0x24); + if (!header.AsciiEqual ("ISM IMAGEFILE\x00")) return null; int colors = header[0x23]; if (0 == colors) colors = 256; return new IsgMetaData { - Width = LittleEndian.ToUInt16 (header, 0x1d), - Height = LittleEndian.ToUInt16 (header, 0x1f), + Width = header.ToUInt16 (0x1d), + Height = header.ToUInt16 (0x1f), BPP = 8, Type = header[0x10], Colors = colors, - Packed = LittleEndian.ToUInt32 (header, 0x11), - Unpacked = LittleEndian.ToUInt32 (header, 0x15), + Packed = header.ToUInt32 (0x11), + Unpacked = header.ToUInt32 (0x15), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as IsgMetaData; - if (null == meta) - throw new ArgumentException ("IsgFormat.Read should be supplied with IsgMetaData", "info"); + var meta = (IsgMetaData)info; if (0x21 != meta.Type && 0x10 != meta.Type) throw new InvalidFormatException ("Unsupported ISM image type"); @@ -99,7 +95,7 @@ namespace GameRes.Formats.ISM internal class Reader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_data; Color[] m_palette; int m_input_size; @@ -107,7 +103,7 @@ namespace GameRes.Formats.ISM public Color[] Palette { get { return m_palette; } } public byte[] Data { get { return m_data; } } - public Reader (Stream file, IsgMetaData info) + public Reader (IBinaryStream file, IsgMetaData info) { int palette_size = (int)info.Colors*4; var palette_data = new byte[Math.Max (0x400, palette_size)]; @@ -118,7 +114,7 @@ namespace GameRes.Formats.ISM { m_palette[i] = Color.FromRgb (palette_data[i*4+2], palette_data[i*4+1], palette_data[i*4]); } - m_input = new BinaryReader (file, Encoding.ASCII, true); + m_input = file; m_input_size = (int)info.Packed; m_data = new byte[info.Width * info.Height]; } @@ -129,15 +125,15 @@ namespace GameRes.Formats.ISM var frame = new byte[2048]; int frame_pos = 2039; int remaining = m_input_size; - byte ctl = m_input.ReadByte(); + byte ctl = m_input.ReadUInt8(); --remaining; int bit = 0x80; while (remaining > 0) { if (0 != (ctl & bit)) { - byte hi = m_input.ReadByte(); - byte lo = m_input.ReadByte(); + byte hi = m_input.ReadUInt8(); + byte lo = m_input.ReadUInt8(); remaining -= 2; int offset = (hi & 7) << 8 | lo; for (int count = (hi >> 3) + 3; count > 0; --count) @@ -151,7 +147,7 @@ namespace GameRes.Formats.ISM } else { - byte p = m_input.ReadByte(); + byte p = m_input.ReadUInt8(); --remaining; m_data[dst++] = p; frame[frame_pos] = p; @@ -159,7 +155,7 @@ namespace GameRes.Formats.ISM } if (0 == (bit >>= 1)) { - ctl = m_input.ReadByte(); + ctl = m_input.ReadUInt8(); --remaining; bit = 0x80; } @@ -170,16 +166,16 @@ namespace GameRes.Formats.ISM { int dst = 0; int remaining = m_input_size; - byte ctl = m_input.ReadByte(); + byte ctl = m_input.ReadUInt8(); --remaining; int bit = 1; while (remaining > 0) { - byte p = m_input.ReadByte(); + byte p = m_input.ReadUInt8(); --remaining; if (0 != (ctl & bit)) { - for (int count = 2 + m_input.ReadByte(); count > 0; --count) + for (int count = 2 + m_input.ReadUInt8(); count > 0; --count) m_data[dst++] = p; --remaining; } @@ -189,7 +185,7 @@ namespace GameRes.Formats.ISM } if (0x100 == (bit <<= 1)) { - ctl = m_input.ReadByte(); + ctl = m_input.ReadUInt8(); --remaining; bit = 1; } @@ -199,11 +195,6 @@ namespace GameRes.Formats.ISM #region IDisposable Members public void Dispose () { - if (null != m_input) - { - m_input.Dispose(); - m_input = null; - } GC.SuppressFinalize (this); } #endregion diff --git a/ArcFormats/ImageLZ.cs b/ArcFormats/ImageLZ.cs index a76b12ff..d42d8396 100644 --- a/ArcFormats/ImageLZ.cs +++ b/ArcFormats/ImageLZ.cs @@ -38,27 +38,29 @@ namespace GameRes.Formats public override uint Signature { get { return 0x44445A53u; } } // 'SZDD' public override bool CanWrite { get { return false; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { stream.Position = 0x0e; - using (var lz = new LzssStream (stream, LzssMode.Decompress, true)) + using (var lz = new LzssStream (stream.AsStream, LzssMode.Decompress, true)) { lz.Config.FrameSize = 0x1000; lz.Config.FrameFill = 0x20; lz.Config.FrameInitPos = 0x1000 - 0x10; - return base.ReadMetaData (lz); + using (var bmp = new BinaryStream (lz, stream.Name)) + return base.ReadMetaData (bmp); } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { stream.Position = 0x0e; - using (var lz = new LzssStream (stream, LzssMode.Decompress, true)) + using (var lz = new LzssStream (stream.AsStream, LzssMode.Decompress, true)) { lz.Config.FrameSize = 0x1000; lz.Config.FrameFill = 0x20; lz.Config.FrameInitPos = 0x1000 - 0x10; - return base.Read (lz, info); + using (var bmp = new BinaryStream (lz, stream.Name)) + return base.Read (bmp, info); } } diff --git a/ArcFormats/ImageMB.cs b/ArcFormats/ImageMB.cs index d1afc649..6f5871ae 100644 --- a/ArcFormats/ImageMB.cs +++ b/ArcFormats/ImageMB.cs @@ -56,7 +56,7 @@ namespace GameRes.Formats { var header = new byte[2] { (byte)'B', (byte)'M' }; Stream stream = new StreamRegion (input.AsStream, 2, true); - stream = new PrefixStream (header, input); + stream = new PrefixStream (header, stream); return new BinaryStream (stream, input.Name); } diff --git a/ArcFormats/ImagePSD.cs b/ArcFormats/ImagePSD.cs index c1399cb2..9d58d0d8 100644 --- a/ArcFormats/ImagePSD.cs +++ b/ArcFormats/ImagePSD.cs @@ -46,11 +46,9 @@ namespace GameRes.Formats.Adobe public override string Description { get { return "Adobe Photoshop image format"; } } public override uint Signature { get { return 0x53504238; } } // '8BPS' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[26]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (26).ToArray(); int version = BigEndian.ToInt16 (header, 4); if (1 != version) return null; @@ -72,7 +70,7 @@ namespace GameRes.Formats.Adobe }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (PsdMetaData)info; using (var reader = new PsdReader (stream, meta)) @@ -90,7 +88,7 @@ namespace GameRes.Formats.Adobe internal class PsdReader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; PsdMetaData m_info; byte[] m_output; int m_channel_size; @@ -99,10 +97,10 @@ namespace GameRes.Formats.Adobe public BitmapPalette Palette { get; private set; } public byte[] Data { get { return m_output; } } - public PsdReader (Stream input, PsdMetaData info) + public PsdReader (IBinaryStream input, PsdMetaData info) { m_info = info; - m_input = new BinaryReader (input, Encoding.Unicode, true); + m_input = input; int bpc = m_info.BPP / m_info.Channels; switch (m_info.Mode) { @@ -134,22 +132,22 @@ namespace GameRes.Formats.Adobe public void Unpack () { - m_input.BaseStream.Position = 0x1A; + m_input.Position = 0x1A; int color_data_length = Binary.BigEndian (m_input.ReadInt32()); - long next_pos = m_input.BaseStream.Position + color_data_length; + long next_pos = m_input.Position + color_data_length; if (0 != color_data_length) { if (8 == m_info.BPP) ReadPalette (color_data_length); - m_input.BaseStream.Position = next_pos; + m_input.Position = next_pos; } next_pos += 4 + Binary.BigEndian (m_input.ReadInt32()); - m_input.BaseStream.Position = next_pos; // skip Image Resources + m_input.Position = next_pos; // skip Image Resources next_pos += 4 + Binary.BigEndian (m_input.ReadInt32()); - m_input.BaseStream.Position = next_pos; // skip Layer and Mask Information + m_input.Position = next_pos; // skip Layer and Mask Information int compression = Binary.BigEndian (m_input.ReadInt16()); - int remaining = checked((int)(m_input.BaseStream.Length - m_input.BaseStream.Position)); + int remaining = checked((int)(m_input.Length - m_input.Position)); byte[] pixels; if (0 == compression) pixels = m_input.ReadBytes (remaining); @@ -212,7 +210,7 @@ namespace GameRes.Formats.Adobe int n = 0; while (n < line_count) { - int count = m_input.ReadSByte(); + int count = m_input.ReadInt8(); ++n; if (count >= 0) { @@ -224,7 +222,7 @@ namespace GameRes.Formats.Adobe else if (count > -128) { count = 1 - count; - byte color = m_input.ReadByte(); + byte color = m_input.ReadUInt8(); ++n; for (int i = 0; i < count; ++i) pixels[dst++] = color; @@ -236,14 +234,8 @@ namespace GameRes.Formats.Adobe } #region IDisposable Members - bool _disposed = false; public void Dispose () { - if (!_disposed) - { - m_input.Dispose(); - _disposed = true; - } } #endregion } diff --git a/ArcFormats/ImagePTI.cs b/ArcFormats/ImagePTI.cs index 632c7d03..10bf23d8 100644 --- a/ArcFormats/ImagePTI.cs +++ b/ArcFormats/ImagePTI.cs @@ -37,16 +37,16 @@ namespace GameRes.Formats.Misc public override uint Signature { get { return 0; } } public override bool CanWrite { get { return false; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { var header = ReadHeader (stream); if (null == header) return null; - using (var bmp = new MemoryStream (header)) + using (var bmp = new BinMemoryStream (header, stream.Name)) return base.ReadMetaData (bmp); } - byte[] ReadHeader (Stream stream) + byte[] ReadHeader (IBinaryStream stream) { var header = new byte[0x36]; if (0x10 != stream.Read (header, 0, 0x10) @@ -58,7 +58,7 @@ namespace GameRes.Formats.Misc return header; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { uint length = (uint)(stream.Length - 0x38); var image = new byte[length+0x38]; @@ -71,7 +71,7 @@ namespace GameRes.Formats.Misc length += 2; } LittleEndian.Pack (length+0x36, image, 2); - using (var bmp = new MemoryStream (image)) + using (var bmp = new BinMemoryStream (image, stream.Name)) return base.Read (bmp, info); } diff --git a/ArcFormats/ImageSeraph.cs b/ArcFormats/ImageSeraph.cs index 78ca5d18..59454e35 100644 --- a/ArcFormats/ImageSeraph.cs +++ b/ArcFormats/ImageSeraph.cs @@ -45,22 +45,20 @@ namespace GameRes.Formats.Seraphim public override string Description { get { return "Seraphim engine image format"; } } public override uint Signature { get { return 0x4643; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x10]; - if (0x10 != stream.Read (header, 0, 0x10)) - return null; - int packed_size = LittleEndian.ToInt32 (header, 12); + var header = stream.ReadHeader (0x10); + int packed_size = header.ToInt32 (12); if (packed_size <= 0 || packed_size > stream.Length-0x10) return null; - uint width = LittleEndian.ToUInt16 (header, 8); - uint height = LittleEndian.ToUInt16 (header, 10); + uint width = header.ToUInt16 (8); + uint height = header.ToUInt16 (10); if (0 == width || 0 == height) return null; return new SeraphMetaData { - OffsetX = LittleEndian.ToInt16 (header, 4), - OffsetY = LittleEndian.ToInt16 (header, 6), + OffsetX = header.ToInt16 (4), + OffsetY = header.ToInt16 (6), Width = width, Height = height, BPP = 24, @@ -68,13 +66,10 @@ namespace GameRes.Formats.Seraphim }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as SeraphMetaData; - if (null == meta) - throw new ArgumentException ("SeraphCfImage.Read should be supplied with SeraphMetaData", "info"); - - var reader = new SeraphReader (stream, meta); + var meta = (SeraphMetaData)info; + var reader = new SeraphReader (stream.AsStream, meta); reader.UnpackCf(); return ImageData.Create (info, PixelFormats.Bgr24, null, reader.Data); } @@ -91,20 +86,17 @@ namespace GameRes.Formats.Seraphim public override string Tag { get { return "CT"; } } public override uint Signature { get { return 0x5443; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { var info = base.ReadMetaData (stream); info.BPP = 32; return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as SeraphMetaData; - if (null == meta) - throw new ArgumentException ("SeraphCtImage.Read should be supplied with SeraphMetaData", "info"); - - var reader = new SeraphReader (stream, meta); + var meta = (SeraphMetaData)info; + var reader = new SeraphReader (stream.AsStream, meta); reader.UnpackCt(); return ImageData.Create (info, reader.Format, null, reader.Data); } @@ -122,25 +114,23 @@ namespace GameRes.Formats.Seraphim public override string Description { get { return "Seraphim engine image format"; } } public override uint Signature { get { return 0; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - if ('C' != stream.ReadByte() || 'B' != stream.ReadByte()) + var header = stream.ReadHeader (0x10); + if ('C' != header[0] || 'B' != header[1]) return null; - var header = new byte[0x10]; - if (0xE != stream.Read (header, 2, 0xE)) - return null; - int colors = LittleEndian.ToUInt16 (header, 2); - int packed_size = LittleEndian.ToInt32 (header, 12); + int colors = header.ToUInt16 (2); + int packed_size = header.ToInt32 (12); if (packed_size <= 0 || packed_size > stream.Length-0x10) return null; - uint width = LittleEndian.ToUInt16 (header, 8); - uint height = LittleEndian.ToUInt16 (header, 10); + uint width = header.ToUInt16 (8); + uint height = header.ToUInt16 (10); if (0 == width || 0 == height) return null; return new SeraphMetaData { - OffsetX = LittleEndian.ToInt16 (header, 4), - OffsetY = LittleEndian.ToInt16 (header, 6), + OffsetX = header.ToInt16 (4), + OffsetY = header.ToInt16 (6), Width = width, Height = height, BPP = 8, @@ -149,13 +139,10 @@ namespace GameRes.Formats.Seraphim }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as SeraphMetaData; - if (null == meta) - throw new ArgumentException ("SeraphCbImage.Read should be supplied with SeraphMetaData", "info"); - - var reader = new SeraphReader (stream, meta, 1); + var meta = (SeraphMetaData)info; + var reader = new SeraphReader (stream.AsStream, meta, 1); reader.UnpackCb(); return ImageData.Create (info, reader.Format, reader.Palette, reader.Data); } diff --git a/ArcFormats/Interheart/ArcFPK.cs b/ArcFormats/Interheart/ArcFPK.cs index 650e1df4..c8e8c905 100644 --- a/ArcFormats/Interheart/ArcFPK.cs +++ b/ArcFormats/Interheart/ArcFPK.cs @@ -141,7 +141,7 @@ namespace GameRes.Formats.CandySoft using (var reader = new Zlc2Reader (input, (int)entry.Size)) { reader.Unpack(); - return new MemoryStream (reader.Data); + return new BinMemoryStream (reader.Data, entry.Name); } } } diff --git a/ArcFormats/Interheart/ImageKG.cs b/ArcFormats/Interheart/ImageKG.cs index 49000084..43677246 100644 --- a/ArcFormats/Interheart/ImageKG.cs +++ b/ArcFormats/Interheart/ImageKG.cs @@ -38,14 +38,12 @@ namespace GameRes.Formats.Interheart public override string Description { get { return "Interheart image format"; } } public override uint Signature { get { return 0x4B474347; } } // 'GCGK' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - byte[] header = new byte[12]; - if (12 != stream.Read (header, 0, 12)) - return null; - uint width = LittleEndian.ToUInt16 (header, 4); - uint height = LittleEndian.ToUInt16 (header, 6); - int packed_size = LittleEndian.ToInt32 (header, 8); + stream.Position = 4; + uint width = stream.ReadUInt16(); + uint height = stream.ReadUInt16(); + int packed_size = stream.ReadInt32(); if (packed_size <= 0) return null; return new ImageMetaData @@ -56,47 +54,44 @@ namespace GameRes.Formats.Interheart }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream input, ImageMetaData info) { byte[] pixels = new byte[info.Width*info.Height*4]; - using (var input = new ArcView.Reader (stream)) - { - input.BaseStream.Position = 12; - uint[] offset_table = new uint[info.Height]; - for (uint i = 0; i < info.Height; ++i) - offset_table[i] = input.ReadUInt32(); + input.Position = 12; + uint[] offset_table = new uint[info.Height]; + for (uint i = 0; i < info.Height; ++i) + offset_table[i] = input.ReadUInt32(); - long base_offset = input.BaseStream.Position; - int dst = 0; - foreach (var offset in offset_table) + long base_offset = input.Position; + int dst = 0; + foreach (var offset in offset_table) + { + input.Position = base_offset + offset; + for (int x = 0; x < info.Width; ) { - input.BaseStream.Position = base_offset + offset; - for (int x = 0; x < info.Width; ) + byte alpha = input.ReadUInt8(); + int count = input.ReadUInt8(); + if (0 == count) + count = 0x100; + if (0 == alpha) { - byte alpha = input.ReadByte(); - int count = input.ReadByte(); - if (0 == count) - count = 0x100; - if (0 == alpha) - { - dst += count * 4; - } - else - { - for (int n = 0; n < count; ++n) - { - pixels[dst+3] = alpha; - pixels[dst+2] = input.ReadByte(); - pixels[dst+1] = input.ReadByte(); - pixels[dst] = input.ReadByte(); - dst += 4; - } - } - x += count; + dst += count * 4; } + else + { + for (int n = 0; n < count; ++n) + { + pixels[dst+3] = alpha; + pixels[dst+2] = input.ReadUInt8(); + pixels[dst+1] = input.ReadUInt8(); + pixels[dst] = input.ReadUInt8(); + dst += 4; + } + } + x += count; } - return ImageData.Create (info, PixelFormats.Bgra32, null, pixels); } + return ImageData.Create (info, PixelFormats.Bgra32, null, pixels); } public override void Write (Stream file, ImageData image) diff --git a/ArcFormats/Ipac/AudioWST.cs b/ArcFormats/Ipac/AudioWST.cs index 6c52a55d..4dfeb5df 100644 --- a/ArcFormats/Ipac/AudioWST.cs +++ b/ArcFormats/Ipac/AudioWST.cs @@ -68,7 +68,7 @@ namespace GameRes.Formats.BaseUnit wav.Write (adpcm_data, 0, adpcm_data.Length); wav.Write (0x61746164); // 'data' wav.Write (data_length); - file.CopyTo (wav_file); + file.AsStream.CopyTo (wav_file); } wav_file.Position = 0; var sound = new WaveInput (wav_file); diff --git a/ArcFormats/Ivory/AudioCTRK.cs b/ArcFormats/Ivory/AudioCTRK.cs index fb8a2acd..b9c2d71e 100644 --- a/ArcFormats/Ivory/AudioCTRK.cs +++ b/ArcFormats/Ivory/AudioCTRK.cs @@ -90,7 +90,7 @@ namespace GameRes.Formats.Ivory } else if (3 == type) { - var input = new StreamRegion (file, start_offset, data_length); + var input = new StreamRegion (file.AsStream, start_offset, data_length); return new OggInput (input); } else diff --git a/ArcFormats/Ivory/ImageSG.cs b/ArcFormats/Ivory/ImageSG.cs index a24a1d5b..59003ef6 100644 --- a/ArcFormats/Ivory/ImageSG.cs +++ b/ArcFormats/Ivory/ImageSG.cs @@ -144,7 +144,7 @@ namespace GameRes.Formats.Ivory public byte[] Data { get { return m_output; } } public int Stride { get { return m_stride; } } - public SgRgbReader (Stream input, SgMetaData info) + public SgRgbReader (IBinaryStream input, SgMetaData info) { if (info.Type != SgType.cRGB || !(0x18 == info.BPP || 0x20 == info.BPP)) throw new InvalidFormatException(); @@ -189,16 +189,16 @@ namespace GameRes.Formats.Ivory { for (int x = 0; x < m_width; ) { - byte ctl = m_input.ReadByte(); + byte ctl = m_input.ReadUInt8(); int count = ctl & 0x3F; if (0 != (ctl & 0x40)) { count <<= 8; - count |= m_input.ReadByte(); + count |= m_input.ReadUInt8(); } if (0 != (ctl & 0x80)) { - byte v = m_input.ReadByte(); + byte v = m_input.ReadUInt8(); for (int i = 0; i < count; ++i) line[line_pos++] = v; } @@ -250,17 +250,17 @@ namespace GameRes.Formats.Ivory m_input.Position = data_pos + index[y]; for (int x = 0; x < m_width; ) { - int ctl = m_input.ReadByte(); + int ctl = m_input.ReadUInt8(); int count = ctl >> 2; if (0 != (ctl & 2)) { - count |= m_input.ReadByte() << 6; + count |= m_input.ReadUInt8() << 6; } count = Math.Min (count, m_width - x); x += count; if (0 != (ctl & 1)) { - byte c = m_input.ReadByte(); + byte c = m_input.ReadUInt8(); for (int i = 0; i < count; ++i) m_output[dst++] = c; } diff --git a/ArcFormats/Kaas/ImageKAAS.cs b/ArcFormats/Kaas/ImageKAAS.cs index d1a50553..b86a0a0f 100644 --- a/ArcFormats/Kaas/ImageKAAS.cs +++ b/ArcFormats/Kaas/ImageKAAS.cs @@ -55,7 +55,7 @@ namespace GameRes.Formats.KAAS throw new NotImplementedException ("PicFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { int mode = stream.ReadByte(); switch (mode) @@ -66,8 +66,8 @@ namespace GameRes.Formats.KAAS return null; } int key = stream.ReadByte(); - var header = new byte[0x10]; - if (header.Length != stream.Read (header, 0, header.Length)) + var header = stream.ReadBytes (0x10); + if (header.Length != 0x10) return null; uint width = LittleEndian.ToUInt16 (header, 0); uint height = LittleEndian.ToUInt16 (header, 2); @@ -92,17 +92,13 @@ namespace GameRes.Formats.KAAS }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as PicMetaData; - if (null == meta) - throw new ArgumentException ("PicFormat.Read should be supplied with PicMetaData", "info"); - stream.Position = 0x12; - using (var reader = new Reader (stream, meta)) + using (var reader = new Reader (stream.AsStream, (PicMetaData)info)) { reader.Unpack(); - return ImageData.Create (meta, PixelFormats.Bgr24, null, reader.Data, (int)meta.Width*3); + return ImageData.Create (info, PixelFormats.Bgr24, null, reader.Data, (int)info.Width*3); } } diff --git a/ArcFormats/Kaguya/ArcKaguya.cs b/ArcFormats/Kaguya/ArcKaguya.cs index ac7c2b5c..1d3c6b00 100644 --- a/ArcFormats/Kaguya/ArcKaguya.cs +++ b/ArcFormats/Kaguya/ArcKaguya.cs @@ -70,7 +70,7 @@ namespace GameRes.Formats.Kaguya using (var reader = new LzReader (input, entry.Size, packed_entry.UnpackedSize)) { reader.Unpack(); - return new MemoryStream (reader.Data); + return new BinMemoryStream (reader.Data, entry.Name); } } } diff --git a/ArcFormats/Kaguya/ArcLINK.cs b/ArcFormats/Kaguya/ArcLINK.cs index ce90af54..37652bbb 100644 --- a/ArcFormats/Kaguya/ArcLINK.cs +++ b/ArcFormats/Kaguya/ArcLINK.cs @@ -82,7 +82,7 @@ namespace GameRes.Formats.Kaguya using (var bmr = new BmrDecoder (input)) { bmr.Unpack(); - return new MemoryStream (bmr.Data); + return new BinMemoryStream (bmr.Data, entry.Name); } } } diff --git a/ArcFormats/Kaguya/ImageAO.cs b/ArcFormats/Kaguya/ImageAO.cs index 82ab342b..f1c30c03 100644 --- a/ArcFormats/Kaguya/ImageAO.cs +++ b/ArcFormats/Kaguya/ImageAO.cs @@ -45,27 +45,24 @@ namespace GameRes.Formats.Kaguya Extensions = new string[] { "sp_" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { int A = stream.ReadByte(); int O = stream.ReadByte(); if ('A' != A || 'O' != O) return null; - using (var file = new ArcView.Reader (stream)) - { - var info = new ImageMetaData(); - info.Width = file.ReadUInt32(); - info.Height = file.ReadUInt32(); - info.BPP = file.ReadInt16(); - info.OffsetX = file.ReadInt32(); - info.OffsetY = file.ReadInt32(); - if (info.Width > 0x8000 || info.Height > 0x8000 || !(32 == info.BPP || 24 == info.BPP)) - return null; - return info; - } + var info = new ImageMetaData(); + info.Width = stream.ReadUInt32(); + info.Height = stream.ReadUInt32(); + info.BPP = stream.ReadInt16(); + info.OffsetX = stream.ReadInt32(); + info.OffsetY = stream.ReadInt32(); + if (info.Width > 0x8000 || info.Height > 0x8000 || !(32 == info.BPP || 24 == info.BPP)) + return null; + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { stream.Position = 0x14; return ReadBitmapData (stream, info); diff --git a/ArcFormats/Kaguya/ImageAP.cs b/ArcFormats/Kaguya/ImageAP.cs index 975d27c6..4a2866c4 100644 --- a/ArcFormats/Kaguya/ImageAP.cs +++ b/ArcFormats/Kaguya/ImageAP.cs @@ -45,31 +45,28 @@ namespace GameRes.Formats.Kaguya Extensions = new string[] { "bg_", "cg_", "cgw", "sp_", "aps", "alp", "prs" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { int A = stream.ReadByte(); int P = stream.ReadByte(); if ('A' != A || 'P' != P) return null; - using (var file = new ArcView.Reader (stream)) - { - var info = new ImageMetaData(); - info.Width = file.ReadUInt32(); - info.Height = file.ReadUInt32(); - info.BPP = file.ReadInt16(); - if (info.Width > 0x8000 || info.Height > 0x8000 || !(32 == info.BPP || 24 == info.BPP)) - return null; - return info; - } + var info = new ImageMetaData(); + info.Width = stream.ReadUInt32(); + info.Height = stream.ReadUInt32(); + info.BPP = stream.ReadInt16(); + if (info.Width > 0x8000 || info.Height > 0x8000 || !(32 == info.BPP || 24 == info.BPP)) + return null; + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { stream.Position = 12; return ReadBitmapData (stream, info); } - protected ImageData ReadBitmapData (Stream stream, ImageMetaData info) + protected ImageData ReadBitmapData (IBinaryStream stream, ImageMetaData info) { int stride = (int)info.Width*4; var pixels = new byte[stride*info.Height]; @@ -126,24 +123,21 @@ namespace GameRes.Formats.Kaguya Extensions = new string[] { "alp" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { stream.Position = 4; - using (var file = new ArcView.Reader (stream)) - { - var info = new ImageMetaData(); - info.OffsetX = file.ReadInt32(); - info.OffsetY = file.ReadInt32(); - info.Width = file.ReadUInt32(); - info.Height = file.ReadUInt32(); - info.BPP = 32; - if (info.Width > 0x8000 || info.Height > 0x8000) - return null; - return info; - } + var info = new ImageMetaData(); + info.OffsetX = stream.ReadInt32(); + info.OffsetY = stream.ReadInt32(); + info.Width = stream.ReadUInt32(); + info.Height = stream.ReadUInt32(); + info.BPP = 32; + if (info.Width > 0x8000 || info.Height > 0x8000) + return null; + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { stream.Position = 0x18; var pixels = new byte[4*info.Width*info.Height]; diff --git a/ArcFormats/Kaguya/ImageAPS.cs b/ArcFormats/Kaguya/ImageAPS.cs index 0835767a..23b0434c 100644 --- a/ArcFormats/Kaguya/ImageAPS.cs +++ b/ArcFormats/Kaguya/ImageAPS.cs @@ -49,39 +49,36 @@ namespace GameRes.Formats.Kaguya Extensions = new string[] { "aps", "parts" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { stream.Position = 4; if (stream.ReadByte() != '3') return null; var rect = new Rectangle (0, 0, 0, 0); - using (var reader = new ArcView.Reader (stream)) + int count = stream.ReadInt32(); + for (int i = 0; i < count; ++i) { - int count = reader.ReadInt32(); - for (int i = 0; i < count; ++i) + stream.ReadInt32(); + int name_length = stream.ReadByte(); + stream.Seek (name_length, SeekOrigin.Current); + int x = stream.ReadInt32(); + int y = stream.ReadInt32(); + int w = stream.ReadInt32() - x; + int h = stream.ReadInt32() - y; + if (name_length > 0) { - reader.ReadInt32(); - int name_length = reader.ReadByte(); - reader.BaseStream.Seek (name_length, SeekOrigin.Current); - int x = reader.ReadInt32(); - int y = reader.ReadInt32(); - int w = reader.ReadInt32() - x; - int h = reader.ReadInt32() - y; - if (name_length > 0) - { - var part_rect = new Rectangle (x, y, w, h); - rect = Rectangle.Union (rect, part_rect); - } - reader.BaseStream.Seek (12, SeekOrigin.Current); + var part_rect = new Rectangle (x, y, w, h); + rect = Rectangle.Union (rect, part_rect); } - uint data_size = reader.ReadUInt32(); - if (data_size > stream.Length-stream.Position) - return null; - return ReadCompressionMetaData (reader, rect); + stream.Seek (12, SeekOrigin.Current); } + uint data_size = stream.ReadUInt32(); + if (data_size > stream.Length-stream.Position) + return null; + return ReadCompressionMetaData (stream, rect); } - internal ApsMetaData ReadCompressionMetaData (BinaryReader reader, Rectangle rect) + internal ApsMetaData ReadCompressionMetaData (IBinaryStream reader, Rectangle rect) { int compression = reader.ReadInt16(); var info = new ApsMetaData @@ -102,18 +99,18 @@ namespace GameRes.Formats.Kaguya } else return null; - info.DataOffset = (uint)reader.BaseStream.Position; + info.DataOffset = (uint)reader.Position; return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (ApsMetaData)info; stream.Position = meta.DataOffset; byte[] image_data; if (meta.IsPacked) { - using (var reader = new LzReader (stream, meta.PackedSize, meta.UnpackedSize)) + using (var reader = new LzReader (stream.AsStream, meta.PackedSize, meta.UnpackedSize)) { reader.Unpack(); image_data = reader.Data; @@ -121,10 +118,9 @@ namespace GameRes.Formats.Kaguya } else { - using (var reader = new ArcView.Reader (stream)) - image_data = reader.ReadBytes ((int)meta.UnpackedSize); + image_data = stream.ReadBytes ((int)meta.UnpackedSize); } - using (var unpacked = new MemoryStream (image_data)) + using (var unpacked = BinaryStream.FromArray (image_data, stream.Name)) { var ap_info = base.ReadMetaData (unpacked); if (null == ap_info) @@ -151,40 +147,37 @@ namespace GameRes.Formats.Kaguya Extensions = new string[] { "aps", "parts" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - using (var reader = new ArcView.Reader (stream)) + int name_count = stream.ReadInt16(); + if (name_count <= 0 || name_count > 1000) + return null; + for (int i = 0; i < name_count; ++i) { - int name_count = reader.ReadInt16(); - if (name_count <= 0 || name_count > 1000) + int name_length = stream.ReadInt32(); + if (name_length <= 0 || name_length > 260) return null; - for (int i = 0; i < name_count; ++i) - { - int name_length = reader.ReadInt32(); - if (name_length <= 0 || name_length > 260) - return null; - stream.Seek (name_length, SeekOrigin.Current); - } - int tile_count = reader.ReadInt16(); - if (tile_count <= 0 || tile_count > 1000) - return null; - var rect = new Rectangle (0, 0, 0, 0); - for (int i = 0; i < tile_count; ++i) - { - int name_length = reader.ReadInt32(); - if (name_length <= 0 || name_length > 260) - return null; - stream.Seek (name_length+0xC, SeekOrigin.Current); - int x = reader.ReadInt32(); - int y = reader.ReadInt32(); - int w = reader.ReadInt32() - x; - int h = reader.ReadInt32() - y; - var part_rect = new Rectangle (x, y, w, h); - rect = Rectangle.Union (rect, part_rect); - stream.Seek (0x28, SeekOrigin.Current); - } - return ReadCompressionMetaData (reader, rect); + stream.Seek (name_length, SeekOrigin.Current); } + int tile_count = stream.ReadInt16(); + if (tile_count <= 0 || tile_count > 1000) + return null; + var rect = new Rectangle (0, 0, 0, 0); + for (int i = 0; i < tile_count; ++i) + { + int name_length = stream.ReadInt32(); + if (name_length <= 0 || name_length > 260) + return null; + stream.Seek (name_length+0xC, SeekOrigin.Current); + int x = stream.ReadInt32(); + int y = stream.ReadInt32(); + int w = stream.ReadInt32() - x; + int h = stream.ReadInt32() - y; + var part_rect = new Rectangle (x, y, w, h); + rect = Rectangle.Union (rect, part_rect); + stream.Seek (0x28, SeekOrigin.Current); + } + return ReadCompressionMetaData (stream, rect); } public override void Write (Stream file, ImageData image) diff --git a/ArcFormats/KiriKiri/ImageTLG.cs b/ArcFormats/KiriKiri/ImageTLG.cs index af6a06a0..4bcc343f 100644 --- a/ArcFormats/KiriKiri/ImageTLG.cs +++ b/ArcFormats/KiriKiri/ImageTLG.cs @@ -38,30 +38,28 @@ namespace GameRes.Formats.KiriKiri Signatures = new uint[] { 0x30474c54, 0x35474c54, 0x36474c54, 0x35474cAB }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x26]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x26); int offset = 0xf; - if (!Binary.AsciiEqual (header, "TLG0.0\x00sds\x1a")) + if (!header.AsciiEqual ("TLG0.0\x00sds\x1a")) offset = 0; int version; - if (!Binary.AsciiEqual (header, offset+6, "\x00raw\x1a")) + if (!header.AsciiEqual (offset+6, "\x00raw\x1a")) return null; if (0xAB == header[offset]) header[offset] = (byte)'T'; - if (Binary.AsciiEqual (header, offset, "TLG6.0")) + if (header.AsciiEqual (offset, "TLG6.0")) version = 6; - else if (Binary.AsciiEqual (header, offset, "TLG5.0")) + else if (header.AsciiEqual (offset, "TLG5.0")) version = 5; - else if (Binary.AsciiEqual (header, offset, "XXXYYY")) + else if (header.AsciiEqual (offset, "XXXYYY")) { version = 5; header[offset+0x0C] ^= 0xAB; header[offset+0x10] ^= 0xAC; } - else if (Binary.AsciiEqual (header, offset, "XXXZZZ")) + else if (header.AsciiEqual (offset, "XXXZZZ")) { version = 6; header[offset+0x0F] ^= 0xAB; @@ -84,44 +82,40 @@ namespace GameRes.Formats.KiriKiri return null; offset += 12; } - uint width = LittleEndian.ToUInt32 (header, offset); - uint height = LittleEndian.ToUInt32 (header, offset+4); - return new TlgMetaData { - Width = width, - Height = height, + return new TlgMetaData + { + Width = header.ToUInt32 (offset), + Height = header.ToUInt32 (offset+4), BPP = colors*8, Version = version, DataOffset = offset+8, }; } - public override ImageData Read (Stream file, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { var meta = (TlgMetaData)info; file.Position = meta.DataOffset; - using (var src = new ArcView.Reader (file)) - { - var image = ReadTlg (src, meta); + var image = ReadTlg (file, meta); - int tail_size = (int)Math.Min (file.Length - file.Position, 512); - if (tail_size > 8) + int tail_size = (int)Math.Min (file.Length - file.Position, 512); + if (tail_size > 8) + { + var tail = file.ReadBytes (tail_size); + try { - var tail = src.ReadBytes (tail_size); - try - { - var blended_image = ApplyTags (image, meta, tail); - if (null != blended_image) - return blended_image; - } - catch (Exception X) - { - Trace.WriteLine (X.Message, "[TlgFormat.Read]"); - } + var blended_image = ApplyTags (image, meta, tail); + if (null != blended_image) + return blended_image; + } + catch (Exception X) + { + Trace.WriteLine (X.Message, "[TlgFormat.Read]"); } - PixelFormat format = 32 == meta.BPP ? PixelFormats.Bgra32 : PixelFormats.Bgr32; - return ImageData.Create (meta, format, null, image, (int)meta.Width * 4); } + PixelFormat format = 32 == meta.BPP ? PixelFormats.Bgra32 : PixelFormats.Bgr32; + return ImageData.Create (meta, format, null, image, (int)meta.Width * 4); } public override void Write (Stream file, ImageData image) @@ -129,7 +123,7 @@ namespace GameRes.Formats.KiriKiri throw new NotImplementedException ("TlgFormat.Write not implemented"); } - byte[] ReadTlg (BinaryReader src, TlgMetaData info) + byte[] ReadTlg (IBinaryStream src, TlgMetaData info) { if (6 == info.Version) return ReadV6 (src, info); @@ -163,15 +157,14 @@ namespace GameRes.Formats.KiriKiri TlgMetaData base_info; byte[] base_image; - using (var base_file = VFS.OpenSeekableStream (base_name)) - using (var base_src = new BinaryReader (base_file)) + using (var base_file = VFS.OpenBinaryStream (base_name)) { base_info = ReadMetaData (base_file) as TlgMetaData; if (null == base_info) return null; base_info.FileName = base_name; base_file.Position = base_info.DataOffset; - base_image = ReadTlg (base_src, base_info); + base_image = ReadTlg (base_file, base_info); } var pixels = BlendImage (base_image, base_info, image, meta); PixelFormat format = 32 == base_info.BPP ? PixelFormats.Bgra32 : PixelFormats.Bgr32; @@ -226,7 +219,7 @@ namespace GameRes.Formats.KiriKiri const int TVP_TLG6_LeadingZeroTable_BITS = 12; const int TVP_TLG6_LeadingZeroTable_SIZE = (1< 0xFF) return null; - frame_offset = LittleEndian.ToUInt32 (header, 0x42); + frame_offset = header.ToUInt32 (0x42); } else if (32 == type || 24 == type) { - uint unpacked_size = LittleEndian.ToUInt32 (header, 2); + uint unpacked_size = header.ToUInt32 (2); if (0 == unpacked_size || unpacked_size == stream.Length) // probably an ordinary bmp file return null; - frame_offset = LittleEndian.ToUInt32 (header, 0xA); + frame_offset = header.ToUInt32 (0xA); } else return null; @@ -67,15 +65,15 @@ namespace GameRes.Formats.Lilim return null; return new AbmImageData { - Width = LittleEndian.ToUInt32 (header, 0x12), - Height = LittleEndian.ToUInt32 (header, 0x16), + Width = header.ToUInt32 (0x12), + Height = header.ToUInt32 (0x16), BPP = 24, Mode = type, BaseOffset = frame_offset, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { using (var reader = new AbmReader (stream, (AbmImageData)info)) { diff --git a/ArcFormats/LiveMaker/ImageGAL.cs b/ArcFormats/LiveMaker/ImageGAL.cs index 2d8c2b5b..9bc66e16 100644 --- a/ArcFormats/LiveMaker/ImageGAL.cs +++ b/ArcFormats/LiveMaker/ImageGAL.cs @@ -75,7 +75,7 @@ namespace GameRes.Formats.LiveMaker set { KnownKeys = ((GalScheme)value).KnownKeys; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { var header = new byte[0x30]; if (11 != stream.Read (header, 0, 11)) @@ -110,7 +110,7 @@ namespace GameRes.Formats.LiveMaker uint? LastKey = null; - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (GalMetaData)info; uint key = 0; @@ -171,7 +171,7 @@ namespace GameRes.Formats.LiveMaker internal sealed class GalReader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; GalMetaData m_info; byte[] m_output; List m_frames; @@ -182,14 +182,14 @@ namespace GameRes.Formats.LiveMaker public BitmapPalette Palette { get; private set; } public int Stride { get; private set; } - public GalReader (Stream input, GalMetaData info, uint key) + public GalReader (IBinaryStream input, GalMetaData info, uint key) { m_info = info; if (m_info.Compression < 0 || m_info.Compression > 2) throw new InvalidFormatException(); m_frames = new List (m_info.FrameCount); m_key = key; - m_input = new ArcView.Reader (input); + m_input = input; } internal class Frame @@ -216,11 +216,11 @@ namespace GameRes.Formats.LiveMaker public void Unpack () { - m_input.BaseStream.Position = m_info.DataOffset; + m_input.Position = m_info.DataOffset; uint name_length = m_input.ReadUInt32(); - m_input.BaseStream.Seek (name_length, SeekOrigin.Current); + m_input.Seek (name_length, SeekOrigin.Current); uint mask = m_input.ReadUInt32(); - m_input.BaseStream.Seek (9, SeekOrigin.Current); + m_input.Seek (9, SeekOrigin.Current); int layer_count = m_input.ReadInt32(); if (layer_count < 1) throw new InvalidFormatException(); @@ -251,14 +251,14 @@ namespace GameRes.Formats.LiveMaker m_input.ReadInt32(); // 0xFF m_input.ReadByte(); name_length = m_input.ReadUInt32(); - m_input.BaseStream.Seek (name_length, SeekOrigin.Current); + m_input.Seek (name_length, SeekOrigin.Current); if (m_info.Version >= 107) m_input.ReadByte(); var layer = new Layer(); int layer_size = m_input.ReadInt32(); - long layer_end = m_input.BaseStream.Position + layer_size; + long layer_end = m_input.Position + layer_size; layer.Pixels = UnpackLayer (frame, layer_size); - m_input.BaseStream.Position = layer_end; + m_input.Position = layer_end; int alpha_size = m_input.ReadInt32(); if (alpha_size != 0) { @@ -271,7 +271,7 @@ namespace GameRes.Formats.LiveMaker byte[] UnpackLayer (Frame frame, int length, bool is_alpha = false) { - using (var packed = new StreamRegion (m_input.BaseStream, m_input.BaseStream.Position, length, true)) + using (var packed = new StreamRegion (m_input.AsStream, m_input.Position, length, true)) { if (0 == m_info.Compression || 2 == m_info.Compression && is_alpha) return ReadZlib (frame, packed, is_alpha); @@ -563,14 +563,8 @@ namespace GameRes.Formats.LiveMaker } #region IDisposable Members - bool _disposed = false; public void Dispose () { - if (!_disposed) - { - m_input.Dispose(); - _disposed = true; - } } #endregion } diff --git a/ArcFormats/Lucifen/ArcLPK.cs b/ArcFormats/Lucifen/ArcLPK.cs index 8c1d3932..2293156f 100644 --- a/ArcFormats/Lucifen/ArcLPK.cs +++ b/ArcFormats/Lucifen/ArcLPK.cs @@ -182,7 +182,7 @@ namespace GameRes.Formats.Lucifen if (count != 0) DecryptEntry (data, count, larc.Info.Key, larc.Scheme.RotatePattern); } - input = new MemoryStream (data); + input = new BinMemoryStream (data, entry.Name); if (null != larc.Info.Prefix) return new PrefixStream (larc.Info.Prefix, input); else diff --git a/ArcFormats/Lucifen/ImageELG.cs b/ArcFormats/Lucifen/ImageELG.cs index d2bcdbff..9cae8650 100644 --- a/ArcFormats/Lucifen/ImageELG.cs +++ b/ArcFormats/Lucifen/ImageELG.cs @@ -56,53 +56,50 @@ namespace GameRes.Formats.Lucifen throw new NotImplementedException ("ElgFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - stream.Seek (3, SeekOrigin.Current); - using (var input = new ArcView.Reader (stream)) + file.Position = 3; + int bpp = file.ReadByte(); + int x = 0; + int y = 0; + int type = bpp; + int header_size = 8; + if (2 == type) { - int bpp = input.ReadByte(); - int x = 0; - int y = 0; - int type = bpp; - int header_size = 8; - if (2 == type) - { - bpp = input.ReadByte(); - header_size = 13; - } - else if (1 == type) - { - bpp = input.ReadByte(); - x = input.ReadInt16(); - y = input.ReadInt16(); - header_size = 13; - } - else - type = 0; - if (8 != bpp && 24 != bpp && 32 != bpp) - return null; - uint w = input.ReadUInt16(); - uint h = input.ReadUInt16(); - if (2 == type) - { - x = input.ReadInt16(); - y = input.ReadInt16(); - } - return new ElgMetaData - { - Width = w, - Height = h, - OffsetX = x, - OffsetY = y, - BPP = bpp, - Type = type, - HeaderSize = header_size, - }; + bpp = file.ReadByte(); + header_size = 13; } + else if (1 == type) + { + bpp = file.ReadByte(); + x = file.ReadInt16(); + y = file.ReadInt16(); + header_size = 13; + } + else + type = 0; + if (8 != bpp && 24 != bpp && 32 != bpp) + return null; + uint w = file.ReadUInt16(); + uint h = file.ReadUInt16(); + if (2 == type) + { + x = file.ReadInt16(); + y = file.ReadInt16(); + } + return new ElgMetaData + { + Width = w, + Height = h, + OffsetX = x, + OffsetY = y, + BPP = bpp, + Type = type, + HeaderSize = header_size, + }; } - public override ImageData Read (Stream file, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { var meta = (ElgMetaData)info; file.Position = meta.HeaderSize; @@ -119,33 +116,33 @@ namespace GameRes.Formats.Lucifen int m_height; int m_bpp; int m_type; - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; public PixelFormat Format { get; private set; } public BitmapPalette Palette { get; private set; } public byte[] Data { get { return m_output; } } - public Reader (Stream stream, ElgMetaData info) + public Reader (IBinaryStream stream, ElgMetaData info) { m_width = (int)info.Width; m_height = (int)info.Height; m_bpp = info.BPP; m_type = info.Type; m_output = new byte[m_width*m_height*m_bpp/8]; - m_input = new ArcView.Reader (stream); + m_input = stream; } public void Unpack () { if (2 == m_type) { - while (0 != m_input.ReadByte()) + while (0 != m_input.ReadUInt8()) { int size = m_input.ReadInt32(); if (size < 4) throw new InvalidFormatException(); - m_input.BaseStream.Seek (size-4, SeekOrigin.Current); + m_input.Seek (size-4, SeekOrigin.Current); } } if (8 == m_bpp) @@ -182,7 +179,7 @@ namespace GameRes.Formats.Lucifen int dst = 0; for (;;) { - byte flags = m_input.ReadByte(); + byte flags = m_input.ReadUInt8(); if (0xff == flags || dst >= output.Length) break; int count, pos; @@ -190,7 +187,7 @@ namespace GameRes.Formats.Lucifen if (0 == (flags & 0xc0)) { if (0 != (flags & 0x20)) - count = ((flags & 0x1f) << 8) + m_input.ReadByte() + 33; + count = ((flags & 0x1f) << 8) + m_input.ReadUInt8() + 33; else count = (flags & 0x1f) + 1; @@ -200,11 +197,11 @@ namespace GameRes.Formats.Lucifen else if ((flags & 0xc0) == 0x40) { if (0 != (flags & 0x20)) - count = ((flags & 0x1f) << 8) + m_input.ReadByte() + 35; + count = ((flags & 0x1f) << 8) + m_input.ReadUInt8() + 35; else count = (flags & 0x1f) + 3; - byte v = m_input.ReadByte(); + byte v = m_input.ReadUInt8(); for (int i = 0; i < count; ++i) output[dst++] = v; } @@ -215,21 +212,21 @@ namespace GameRes.Formats.Lucifen if (0 == (flags & 0x30)) { count = (flags & 0xf) + 2; - pos = m_input.ReadByte() + 2; + pos = m_input.ReadUInt8() + 2; } else if ((flags & 0x30) == 0x10) { - pos = ((flags & 0xf) << 8) + m_input.ReadByte() + 3; - count = m_input.ReadByte() + 4; + pos = ((flags & 0xf) << 8) + m_input.ReadUInt8() + 3; + count = m_input.ReadUInt8() + 4; } else if ((flags & 0x30) == 0x20) { - pos = ((flags & 0xf) << 8) + m_input.ReadByte() + 3; + pos = ((flags & 0xf) << 8) + m_input.ReadUInt8() + 3; count = 3; } else { - pos = ((flags & 0xf) << 8) + m_input.ReadByte() + 3; + pos = ((flags & 0xf) << 8) + m_input.ReadUInt8() + 3; count = 4; } } @@ -255,7 +252,7 @@ namespace GameRes.Formats.Lucifen int dst = 0; for (;;) { - byte flags = m_input.ReadByte(); + byte flags = m_input.ReadUInt8(); if (0xff == flags || dst >= m_output.Length) break; int count, pos, src; @@ -263,28 +260,28 @@ namespace GameRes.Formats.Lucifen if (0 == (flags & 0xc0)) { if (0 != (flags & 0x20)) - count = ((flags & 0x1f) << 8) + m_input.ReadByte() + 33; + count = ((flags & 0x1f) << 8) + m_input.ReadUInt8() + 33; else count = (flags & 0x1f) + 1; for (int i = 0; i < count; ++i) { - m_output[dst++] = m_input.ReadByte(); - m_output[dst++] = m_input.ReadByte(); - m_output[dst++] = m_input.ReadByte(); + m_output[dst++] = m_input.ReadUInt8(); + m_output[dst++] = m_input.ReadUInt8(); + m_output[dst++] = m_input.ReadUInt8(); m_output[dst++] = 0xff; } } else if ((flags & 0xc0) == 0x40) { if (0 != (flags & 0x20)) - count = ((flags & 0x1f) << 8) + m_input.ReadByte() + 34; + count = ((flags & 0x1f) << 8) + m_input.ReadUInt8() + 34; else count = (flags & 0x1f) + 2; - byte b = m_input.ReadByte(); - byte g = m_input.ReadByte(); - byte r = m_input.ReadByte(); + byte b = m_input.ReadUInt8(); + byte g = m_input.ReadUInt8(); + byte r = m_input.ReadUInt8(); for (int i = 0; i < count; ++i) { m_output[dst++] = b; @@ -298,23 +295,23 @@ namespace GameRes.Formats.Lucifen if (0 == (flags & 0x30)) { count = (flags & 0xf) + 1; - pos = m_input.ReadByte() + 2; + pos = m_input.ReadUInt8() + 2; } else if ((flags & 0x30) == 0x10) { - pos = ((flags & 0xf) << 8) + m_input.ReadByte() + 2; - count = m_input.ReadByte() + 1; + pos = ((flags & 0xf) << 8) + m_input.ReadUInt8() + 2; + count = m_input.ReadUInt8() + 1; } else if ((flags & 0x30) == 0x20) { - byte tmp = m_input.ReadByte(); - pos = ((((flags & 0xf) << 8) + tmp) << 8) + m_input.ReadByte() + 4098; - count = m_input.ReadByte() + 1; + byte tmp = m_input.ReadUInt8(); + pos = ((((flags & 0xf) << 8) + tmp) << 8) + m_input.ReadUInt8() + 4098; + count = m_input.ReadUInt8() + 1; } else { if (0 != (flags & 8)) - pos = ((flags & 0x7) << 8) + m_input.ReadByte() + 10; + pos = ((flags & 0x7) << 8) + m_input.ReadUInt8() + 10; else pos = (flags & 0x7) + 2; count = 1; @@ -332,22 +329,22 @@ namespace GameRes.Formats.Lucifen { if (0 == (flags & 0xc)) { - y = ((flags & 0x3) << 8) + m_input.ReadByte() + 16; + y = ((flags & 0x3) << 8) + m_input.ReadUInt8() + 16; x = 0; } else if ((flags & 0xc) == 0x4) { - y = ((flags & 0x3) << 8) + m_input.ReadByte() + 16; + y = ((flags & 0x3) << 8) + m_input.ReadUInt8() + 16; x = -1; } else if ((flags & 0xc) == 0x8) { - y = ((flags & 0x3) << 8) + m_input.ReadByte() + 16; + y = ((flags & 0x3) << 8) + m_input.ReadUInt8() + 16; x = 1; } else { - pos = ((flags & 0x3) << 8) + m_input.ReadByte() + 2058; + pos = ((flags & 0x3) << 8) + m_input.ReadUInt8() + 2058; src = dst - 4 * pos; Buffer.BlockCopy (m_output, src, m_output, dst, 4); dst += 4; @@ -381,7 +378,7 @@ namespace GameRes.Formats.Lucifen int dst = 3; for (;;) { - byte flags = m_input.ReadByte(); + byte flags = m_input.ReadUInt8(); if (0xff == flags || dst >= m_output.Length) break; @@ -390,24 +387,24 @@ namespace GameRes.Formats.Lucifen if (0 == (flags & 0xc0)) { if (0 != (flags & 0x20)) - count = ((flags & 0x1f) << 8) + m_input.ReadByte() + 33; + count = ((flags & 0x1f) << 8) + m_input.ReadUInt8() + 33; else count = (flags & 0x1f) + 1; for (int i = 0; i < count; ++i) { - m_output[dst] = m_input.ReadByte(); + m_output[dst] = m_input.ReadUInt8(); dst += 4; } } else if (0x40 == (flags & 0xc0)) { if (0 != (flags & 0x20)) - count = ((flags & 0x1f) << 8) + m_input.ReadByte() + 35; + count = ((flags & 0x1f) << 8) + m_input.ReadUInt8() + 35; else count = (flags & 0x1f) + 3; - byte a = m_input.ReadByte(); + byte a = m_input.ReadUInt8(); for (int i = 0; i < count; ++i) { m_output[dst] = a; @@ -421,21 +418,21 @@ namespace GameRes.Formats.Lucifen if (0 == (flags & 0x30)) { count = (flags & 0xf) + 2; - pos = m_input.ReadByte() + 2; + pos = m_input.ReadUInt8() + 2; } else if (0x10 == (flags & 0x30)) { - pos = ((flags & 0xf) << 8) + m_input.ReadByte() + 3; - count = m_input.ReadByte() + 4; + pos = ((flags & 0xf) << 8) + m_input.ReadUInt8() + 3; + count = m_input.ReadUInt8() + 4; } else if ((flags & 0x30) == 0x20) { - pos = ((flags & 0xf) << 8) + m_input.ReadByte() + 3; + pos = ((flags & 0xf) << 8) + m_input.ReadUInt8() + 3; count = 3; } else { - pos = ((flags & 0xf) << 8) + m_input.ReadByte() + 3; + pos = ((flags & 0xf) << 8) + m_input.ReadUInt8() + 3; count = 4; } } @@ -466,34 +463,34 @@ namespace GameRes.Formats.Lucifen int dst = 0; for (;;) { - byte flags = m_input.ReadByte(); + byte flags = m_input.ReadUInt8(); if (0xff == flags || dst >= m_output.Length) break; int count, pos, src; if (0 == (flags & 0xc0)) { if (0 != (flags & 0x20)) - count = ((flags & 0x1f) << 8) + m_input.ReadByte() + 33; + count = ((flags & 0x1f) << 8) + m_input.ReadUInt8() + 33; else count = (flags & 0x1f) + 1; for (int i = 0; i < count; ++i) { - m_output[dst++] = m_input.ReadByte(); - m_output[dst++] = m_input.ReadByte(); - m_output[dst++] = m_input.ReadByte(); + m_output[dst++] = m_input.ReadUInt8(); + m_output[dst++] = m_input.ReadUInt8(); + m_output[dst++] = m_input.ReadUInt8(); } } else if ((flags & 0xc0) == 0x40) { if (0 != (flags & 0x20)) - count = ((flags & 0x1f) << 8) + m_input.ReadByte() + 34; + count = ((flags & 0x1f) << 8) + m_input.ReadUInt8() + 34; else count = (flags & 0x1f) + 2; - byte b = m_input.ReadByte(); - byte g = m_input.ReadByte(); - byte r = m_input.ReadByte(); + byte b = m_input.ReadUInt8(); + byte g = m_input.ReadUInt8(); + byte r = m_input.ReadUInt8(); for (int i = 0; i < count; ++i) { m_output[dst++] = b; @@ -506,23 +503,23 @@ namespace GameRes.Formats.Lucifen if (0 == (flags & 0x30)) { count = (flags & 0xf) + 1; - pos = m_input.ReadByte() + 2; + pos = m_input.ReadUInt8() + 2; } else if ((flags & 0x30) == 0x10) { - pos = ((flags & 0xf) << 8) + m_input.ReadByte() + 2; - count = m_input.ReadByte() + 1; + pos = ((flags & 0xf) << 8) + m_input.ReadUInt8() + 2; + count = m_input.ReadUInt8() + 1; } else if ((flags & 0x30) == 0x20) { - byte tmp = m_input.ReadByte(); - pos = ((((flags & 0xf) << 8) + tmp) << 8) + m_input.ReadByte() + 4098; - count = m_input.ReadByte() + 1; + byte tmp = m_input.ReadUInt8(); + pos = ((((flags & 0xf) << 8) + tmp) << 8) + m_input.ReadUInt8() + 4098; + count = m_input.ReadUInt8() + 1; } else { if (0 != (flags & 8)) - pos = ((flags & 0x7) << 8) + m_input.ReadByte() + 10; + pos = ((flags & 0x7) << 8) + m_input.ReadUInt8() + 10; else pos = (flags & 0x7) + 2; count = 1; @@ -540,22 +537,22 @@ namespace GameRes.Formats.Lucifen { if (0 == (flags & 0xc)) { - y = ((flags & 0x3) << 8) + m_input.ReadByte() + 16; + y = ((flags & 0x3) << 8) + m_input.ReadUInt8() + 16; x = 0; } else if ((flags & 0xc) == 0x4) { - y = ((flags & 0x3) << 8) + m_input.ReadByte() + 16; + y = ((flags & 0x3) << 8) + m_input.ReadUInt8() + 16; x = -1; } else if ((flags & 0xc) == 0x8) { - y = ((flags & 0x3) << 8) + m_input.ReadByte() + 16; + y = ((flags & 0x3) << 8) + m_input.ReadUInt8() + 16; x = 1; } else { - pos = ((flags & 0x3) << 8) + m_input.ReadByte() + 2058; + pos = ((flags & 0x3) << 8) + m_input.ReadUInt8() + 2058; src = dst - 3 * pos; m_output[dst++] = m_output[src++]; m_output[dst++] = m_output[src++]; @@ -587,23 +584,10 @@ namespace GameRes.Formats.Lucifen } #region IDisposable Members - bool disposed = false; - public void Dispose () { - Dispose (true); GC.SuppressFinalize (this); } - - protected virtual void Dispose (bool disposing) - { - if (!disposed) - { - if (disposing) - m_input.Dispose(); - disposed = true; - } - } #endregion } } diff --git a/ArcFormats/MAI/ImageMAI.cs b/ArcFormats/MAI/ImageMAI.cs index 1e4a30a8..8a38ba05 100644 --- a/ArcFormats/MAI/ImageMAI.cs +++ b/ArcFormats/MAI/ImageMAI.cs @@ -58,12 +58,12 @@ namespace GameRes.Formats.MAI throw new NotImplementedException ("CmFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { if ('C' != stream.ReadByte() || 'M' != stream.ReadByte()) return null; - var header = new byte[0x1e]; - if (header.Length != stream.Read (header, 0, header.Length)) + var header = stream.ReadBytes (0x1e); + if (header.Length != 0x1e) return null; if (1 != header[0x0c]) return null; @@ -83,9 +83,9 @@ namespace GameRes.Formats.MAI return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var reader = new Reader (stream, (CmMetaData)info); + var reader = new Reader (stream.AsStream, (CmMetaData)info); reader.Unpack(); return ImageData.CreateFlipped (info, reader.Format, reader.Palette, reader.Data, reader.Stride); } @@ -166,7 +166,7 @@ namespace GameRes.Formats.MAI throw new NotImplementedException ("AmFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { if ('A' != stream.ReadByte() || 'M' != stream.ReadByte()) return null; @@ -197,9 +197,9 @@ namespace GameRes.Formats.MAI return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var reader = new Reader (stream, (AmMetaData)info); + var reader = new Reader (stream.AsStream, (AmMetaData)info); reader.Unpack(); return ImageData.Create (info, reader.Format, reader.Palette, reader.Data); } @@ -300,40 +300,37 @@ namespace GameRes.Formats.MAI throw new NotImplementedException ("MaskFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var input = new ArcView.Reader (stream)) - { - uint size = input.ReadUInt32(); - if (size != stream.Length) - return null; - uint width = input.ReadUInt32(); - uint height = input.ReadUInt32(); - int compressed = input.ReadInt32(); - if (compressed > 1 || 0 == compressed && (width*height + 0x410) != size) - return null; - return new CmMetaData { - Width = width, - Height = height, - BPP = 8, - IsCompressed = 1 == compressed, - DataOffset = 0x10, - DataLength = size, - }; - } + uint size = file.ReadUInt32(); + if (size != file.Length) + return null; + uint width = file.ReadUInt32(); + uint height = file.ReadUInt32(); + int compressed = file.ReadInt32(); + if (compressed > 1 || 0 == compressed && (width*height + 0x410) != size) + return null; + return new CmMetaData { + Width = width, + Height = height, + BPP = 8, + IsCompressed = 1 == compressed, + DataOffset = 0x10, + DataLength = size, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (CmMetaData)info; stream.Position = meta.DataOffset; - var palette = RleDecoder.ReadPalette (stream, 0x100, 4); + var palette = RleDecoder.ReadPalette (stream.AsStream, 0x100, 4); var pixels = new byte[info.Width*info.Height]; if (meta.IsCompressed) { int packed_size = (int)(stream.Length - meta.DataOffset); - RleDecoder.Unpack (stream, packed_size, pixels, 1); + RleDecoder.Unpack (stream.AsStream, packed_size, pixels, 1); } else if (pixels.Length != stream.Read (pixels, 0, pixels.Length)) throw new InvalidFormatException(); diff --git a/ArcFormats/Macromedia/AudioEDIM.cs b/ArcFormats/Macromedia/AudioEDIM.cs index f4b20926..18925d59 100644 --- a/ArcFormats/Macromedia/AudioEDIM.cs +++ b/ArcFormats/Macromedia/AudioEDIM.cs @@ -42,10 +42,11 @@ namespace GameRes.Formats.Selen Signatures = new uint[] { 0x40010000, 0x64010000 }; } - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - uint offset = 4 + Binary.BigEndian (FormatCatalog.ReadSignature (file)); - return base.TryOpen (new StreamRegion (file, offset)); + uint offset = 4 + Binary.BigEndian (file.Signature); + var mp3 = new StreamRegion (file.AsStream, offset); + return base.TryOpen (new BinaryStream (mp3, file.Name)); } public override void Write (SoundInput source, Stream output) diff --git a/ArcFormats/Macromedia/ImageBITD.cs b/ArcFormats/Macromedia/ImageBITD.cs index 7abfdf59..a9c8856d 100644 --- a/ArcFormats/Macromedia/ImageBITD.cs +++ b/ArcFormats/Macromedia/ImageBITD.cs @@ -40,17 +40,17 @@ namespace GameRes.Formats.Selen public override string Description { get { return "Selen RLE-compressed bitmap"; } } public override uint Signature { get { return 0; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { if (stream.Length > 0xffffff) return null; - var scanner = new BitdScanner (stream); + var scanner = new BitdScanner (stream.AsStream); return scanner.GetInfo(); } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var reader = new BitdReader (stream, info); + var reader = new BitdReader (stream.AsStream, info); reader.Unpack(); return ImageData.Create (info, reader.Format, null, reader.Data); } diff --git a/ArcFormats/Majiro/ImageRCT.cs b/ArcFormats/Majiro/ImageRCT.cs index eca85e9f..c85583b2 100644 --- a/ArcFormats/Majiro/ImageRCT.cs +++ b/ArcFormats/Majiro/ImageRCT.cs @@ -42,8 +42,8 @@ namespace GameRes.Formats.Majiro public int Version; public bool IsEncrypted; public uint DataOffset; - public uint DataSize; - public uint AddSize; + public int DataSize; + public int AddSize; } internal class RctOptions : ResourceOptions @@ -76,7 +76,7 @@ namespace GameRes.Formats.Majiro set { KnownKeys = ((RctScheme)value).KnownKeys; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { stream.Position = 4; int id = stream.ReadByte(); @@ -93,38 +93,35 @@ namespace GameRes.Formats.Majiro if (version != 0 && version != 1) return null; - using (var reader = new BinaryReader (stream, Encoding.ASCII, true)) + uint width = stream.ReadUInt32(); + uint height = stream.ReadUInt32(); + int data_size = stream.ReadInt32(); + int additional_size = 0; + if (1 == version) { - uint width = reader.ReadUInt32(); - uint height = reader.ReadUInt32(); - uint data_size = reader.ReadUInt32(); - uint additional_size = 0; - if (1 == version) - { - additional_size = reader.ReadUInt16(); - } - if (width > 0x8000 || height > 0x8000) - return null; - - return new RctMetaData - { - Width = width, - Height = height, - OffsetX = 0, - OffsetY = 0, - BPP = 24, - Version = version, - IsEncrypted = is_encrypted, - DataOffset = (uint)stream.Position, - DataSize = data_size, - AddSize = additional_size, - }; + additional_size = stream.ReadUInt16(); } + if (width > 0x8000 || height > 0x8000) + return null; + + return new RctMetaData + { + Width = width, + Height = height, + OffsetX = 0, + OffsetY = 0, + BPP = 24, + Version = version, + IsEncrypted = is_encrypted, + DataOffset = (uint)stream.Position, + DataSize = data_size, + AddSize = additional_size, + }; } byte[] Key = null; - public override ImageData Read (Stream file, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { var meta = (RctMetaData)info; @@ -155,9 +152,9 @@ namespace GameRes.Formats.Majiro ImageData ApplyMaskToImage (RctMetaData info, byte[] image, string mask_name) { - using (var mask_file = VFS.OpenSeekableStream (mask_name)) + using (var mask_file = VFS.OpenBinaryStream (mask_name)) { - var format = FindFormat (mask_file, mask_name); + var format = FindFormat (mask_file); if (null == format || !(format.Item1 is Rc8Format) || info.Width != format.Item2.Width || info.Height != format.Item2.Height) throw new InvalidFormatException(); @@ -198,7 +195,7 @@ namespace GameRes.Formats.Majiro return overlay; } - byte[] ReadPixelsData (Stream file, RctMetaData meta) + byte[] ReadPixelsData (IBinaryStream file, RctMetaData meta) { file.Position = meta.DataOffset + meta.AddSize; if (meta.IsEncrypted) @@ -219,11 +216,11 @@ namespace GameRes.Formats.Majiro } } - byte[] ReadBaseImage (Stream file, RctMetaData meta) + byte[] ReadBaseImage (IBinaryStream file, RctMetaData meta) { file.Position = meta.DataOffset; - byte[] name_bin = new byte[meta.AddSize]; - if (name_bin.Length != file.Read (name_bin, 0, name_bin.Length)) + byte[] name_bin = file.ReadBytes (meta.AddSize); + if (name_bin.Length != meta.AddSize) throw new EndOfStreamException(); try { @@ -232,7 +229,7 @@ namespace GameRes.Formats.Majiro name = VFS.CombinePath (dir_name, name); if (VFS.FileExists (name)) { - using (var base_file = VFS.OpenSeekableStream (name)) + using (var base_file = VFS.OpenBinaryStream (name)) { var base_info = ReadMetaData (base_file) as RctMetaData; if (null != base_info && 0 == base_info.AddSize @@ -248,7 +245,7 @@ namespace GameRes.Formats.Majiro return null; } - Stream OpenEncryptedStream (Stream file, uint data_size) + IBinaryStream OpenEncryptedStream (IBinaryStream file, int data_size) { if (null == Key) { @@ -257,15 +254,15 @@ namespace GameRes.Formats.Majiro throw new UnknownEncryptionScheme(); Key = InitDecryptionKey (password); } - byte[] data = new byte[data_size]; - if (data.Length != file.Read (data, 0, data.Length)) + byte[] data = file.ReadBytes (data_size); + if (data.Length != data_size) throw new EndOfStreamException(); for (int i = 0; i < data.Length; ++i) { data[i] ^= Key[i & 0x3FF]; } - return new MemoryStream (data); + return new BinMemoryStream (data, file.Name); } private byte[] InitDecryptionKey (string password) @@ -517,19 +514,19 @@ namespace GameRes.Formats.Majiro #endregion } - internal class Reader : IDisposable + internal sealed class Reader : IDisposable { - private BinaryReader m_input; + private IBinaryStream m_input; private uint m_width; private byte[] m_data; public byte[] Data { get { return m_data; } } - public Reader (Stream file, RctMetaData info) + public Reader (IBinaryStream file, RctMetaData info) { m_width = info.Width; m_data = new byte[m_width * info.Height * 3]; - m_input = new BinaryReader (file, Encoding.ASCII, true); + m_input = file; } internal static readonly sbyte[] ShiftTable = new sbyte[] { @@ -588,25 +585,10 @@ namespace GameRes.Formats.Majiro } #region IDisposable Members - bool disposed = false; - public void Dispose () { - Dispose (true); GC.SuppressFinalize (this); } - - protected virtual void Dispose (bool disposing) - { - if (!disposed) - { - if (disposing) - m_input.Dispose(); - m_input = null; - m_data = null; - disposed = true; - } - } #endregion } } @@ -618,7 +600,7 @@ namespace GameRes.Formats.Majiro public override string Description { get { return "Majiro game engine indexed image format"; } } public override uint Signature { get { return 0x9a925a98; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { stream.Position = 4; int id = stream.ReadByte(); @@ -634,24 +616,21 @@ namespace GameRes.Formats.Majiro if (version != 0) return null; - using (var reader = new BinaryReader (stream, Encoding.ASCII, true)) + uint width = stream.ReadUInt32(); + uint height = stream.ReadUInt32(); + if (width > 0x8000 || height > 0x8000) + return null; + return new ImageMetaData { - uint width = reader.ReadUInt32(); - uint height = reader.ReadUInt32(); - if (width > 0x8000 || height > 0x8000) - return null; - return new ImageMetaData - { - Width = width, - Height = height, - OffsetX = 0, - OffsetY = 0, - BPP = 8, - }; - } + Width = width, + Height = height, + OffsetX = 0, + OffsetY = 0, + BPP = 8, + }; } - public override ImageData Read (Stream file, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { using (var reader = new Reader (file, info)) { @@ -666,9 +645,9 @@ namespace GameRes.Formats.Majiro throw new NotImplementedException ("Rc8Format.Write is not implemented."); } - internal class Reader : IDisposable + internal sealed class Reader : IDisposable { - private BinaryReader m_input; + private IBinaryStream m_input; private uint m_width; private Color[] m_palette; private byte[] m_data; @@ -676,7 +655,7 @@ namespace GameRes.Formats.Majiro public Color[] Palette { get { return m_palette; } } public byte[] Data { get { return m_data; } } - public Reader (Stream file, ImageMetaData info) + public Reader (IBinaryStream file, ImageMetaData info) { m_width = info.Width; file.Position = 0x14; @@ -689,7 +668,7 @@ namespace GameRes.Formats.Majiro m_palette[i] = Color.FromRgb (palette_data[i*3], palette_data[i*3+1], palette_data[i*3+2]); } m_data = new byte[m_width * info.Height]; - m_input = new BinaryReader (file, Encoding.ASCII, true); + m_input = file; } private static readonly sbyte[] ShiftTable = new sbyte[] { @@ -746,24 +725,8 @@ namespace GameRes.Formats.Majiro } #region IDisposable Members - bool disposed = false; - public void Dispose () { - Dispose (true); - GC.SuppressFinalize (this); - } - - protected virtual void Dispose (bool disposing) - { - if (!disposed) - { - if (disposing) - m_input.Dispose(); - m_input = null; - m_data = null; - disposed = true; - } } #endregion } diff --git a/ArcFormats/Malie/ImageDZI.cs b/ArcFormats/Malie/ImageDZI.cs index 2794ec9a..8690ca79 100644 --- a/ArcFormats/Malie/ImageDZI.cs +++ b/ArcFormats/Malie/ImageDZI.cs @@ -56,12 +56,13 @@ namespace GameRes.Formats.Malie static readonly Regex pair_re = new Regex (@"^(\d+),(\d+)"); - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - var tex = VFS.FindFile (VFS.CombinePath (VFS.Top.CurrentDirectory, "tex")); + var dir = VFS.GetDirectoryName (file.Name); + var tex = VFS.FindFile (VFS.CombinePath (dir, "tex")); if (!(tex is SubDirEntry)) return null; - using (var reader = new StreamReader (stream, Encoding.UTF8, false, 2048, true)) + using (var reader = new StreamReader (file.AsStream, Encoding.UTF8, false, 2048, true)) { reader.ReadLine(); // skip signature string line = reader.ReadLine(); @@ -98,12 +99,12 @@ namespace GameRes.Formats.Malie if (null == line) return null; line = line.TrimEnd(); - foreach (var file in line.Split (',')) + foreach (var filename in line.Split (',')) { - if (!string.IsNullOrEmpty (file)) + if (!string.IsNullOrEmpty (filename)) { - var filename = VFS.CombinePath (tex.Name, file); - tiles.Add (new DziTile { X = x, Y = y, FileName = filename }); + var fullname = VFS.CombinePath (tex.Name, filename); + tiles.Add (new DziTile { X = x, Y = y, FileName = fullname }); } x += 256; } @@ -121,7 +122,7 @@ namespace GameRes.Formats.Malie } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (DziMetaData)info; PixelFormat format = PixelFormats.Bgra32; @@ -135,9 +136,9 @@ namespace GameRes.Formats.Malie var image_entry = VFS.GetFiles (tile.FileName + ".*").FirstOrDefault(); if (null == image_entry) throw new FileNotFoundException ("Tile not found", tile.FileName); - using (var input = VFS.OpenStream (image_entry)) + using (var input = VFS.OpenBinaryStream (image_entry)) { - var image = Read (image_entry.Name, input); + var image = Read (input); if (null == image) throw new FileFormatException ("Unknown DZI tile format"); var converted = image.Bitmap; diff --git a/ArcFormats/Malie/ImageMGF.cs b/ArcFormats/Malie/ImageMGF.cs index 0b382151..fc324859 100644 --- a/ArcFormats/Malie/ImageMGF.cs +++ b/ArcFormats/Malie/ImageMGF.cs @@ -41,25 +41,25 @@ namespace GameRes.Formats.Malie static readonly byte[] PngHeader = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[8]; - if (8 != stream.Read (header, 0, 8)) - return null; + var header = stream.ReadHeader (8).ToArray(); if (!Binary.AsciiEqual (header, "MalieGF")) return null; Buffer.BlockCopy (PngHeader, 0, header, 0, 8); - using (var data = new StreamRegion (stream, 8, stream.Length - 8, true)) - using (var png = new PrefixStream (header, data)) + using (var data = new StreamRegion (stream.AsStream, 8, true)) + using (var pre = new PrefixStream (header, data)) + using (var png = new BinaryStream (pre, stream.Name)) return base.ReadMetaData (png); } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var header = PngHeader.Clone() as byte[]; - using (var data = new StreamRegion (stream, 8, stream.Length - 8, true)) - using (var png = new PrefixStream (header, data)) + using (var data = new StreamRegion (stream.AsStream, 8, true)) + using (var pre = new PrefixStream (header, data)) + using (var png = new BinaryStream (pre, stream.Name)) return base.Read (png, info); } diff --git a/ArcFormats/MangaGamer/ArcMGPK.cs b/ArcFormats/MangaGamer/ArcMGPK.cs index 1e405f42..01296f67 100644 --- a/ArcFormats/MangaGamer/ArcMGPK.cs +++ b/ArcFormats/MangaGamer/ArcMGPK.cs @@ -115,7 +115,7 @@ namespace GameRes.Formats.Mg data = DecryptBlock (data, mgarc.Key); if (entry.Name.EndsWith (".txt", StringComparison.InvariantCultureIgnoreCase)) return DecompressStream (data); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } diff --git a/ArcFormats/Marble/ArcMBL.cs b/ArcFormats/Marble/ArcMBL.cs index f0d0b8ea..479a2554 100644 --- a/ArcFormats/Marble/ArcMBL.cs +++ b/ArcFormats/Marble/ArcMBL.cs @@ -184,7 +184,7 @@ namespace GameRes.Formats.Marble data[i] ^= marc.Key[i % marc.Key.Length]; } } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } public override ResourceOptions GetDefaultOptions () diff --git a/ArcFormats/Marble/AudioWADY.cs b/ArcFormats/Marble/AudioWADY.cs index 11fa54a4..214cde84 100644 --- a/ArcFormats/Marble/AudioWADY.cs +++ b/ArcFormats/Marble/AudioWADY.cs @@ -64,38 +64,36 @@ namespace GameRes.Formats.Marble return Source.ReadByte(); } - public WadyInput (Stream file) : base (new MemoryStream()) + public WadyInput (IBinaryStream input) : base (new MemoryStream()) { - using (var input = new BinaryReader (file)) + input.Seek (5, SeekOrigin.Begin); + MulValue = input.ReadUInt8(); + input.Seek (6, SeekOrigin.Current); + int src_size = input.ReadInt32(); + input.Seek (16, SeekOrigin.Current); + var format = new WaveFormat(); + format.FormatTag = input.ReadUInt16(); + format.Channels = input.ReadUInt16(); + format.SamplesPerSecond = input.ReadUInt32(); + format.AverageBytesPerSecond = input.ReadUInt32(); + format.BlockAlign = input.ReadUInt16(); + format.BitsPerSample = input.ReadUInt16(); + format.ExtraSize = 0; + this.Format = format; + int remaining = (int)(input.Length-input.Position); + if (remaining == src_size) { - input.BaseStream.Seek (5, SeekOrigin.Begin); - MulValue = input.ReadByte(); - input.BaseStream.Seek (6, SeekOrigin.Current); - int src_size = input.ReadInt32(); - input.BaseStream.Seek (16, SeekOrigin.Current); - var format = new WaveFormat(); - format.FormatTag = input.ReadUInt16(); - format.Channels = input.ReadUInt16(); - format.SamplesPerSecond = input.ReadUInt32(); - format.AverageBytesPerSecond = input.ReadUInt32(); - format.BlockAlign = input.ReadUInt16(); - format.BitsPerSample = input.ReadUInt16(); - format.ExtraSize = 0; - this.Format = format; - int remaining = (int)(input.BaseStream.Length-input.BaseStream.Position); - if (remaining == src_size) - { - (Source as MemoryStream).Capacity = src_size * 2; - Decode (input, src_size, Source); - } - else - Decode2 (input, Source); - Source.Position = 0; - this.PcmSize = Source.Length; + (Source as MemoryStream).Capacity = src_size * 2; + Decode (input, src_size, Source); } + else + Decode2 (input, Source); + Source.Position = 0; + this.PcmSize = Source.Length; + input.Dispose(); } - private void Decode (BinaryReader input, int count, Stream output) + private void Decode (IBinaryStream input, int count, Stream output) { using (var buffer = new BinaryWriter (output, Encoding.ASCII, true)) { @@ -103,7 +101,7 @@ namespace GameRes.Formats.Marble ushort sampleR = 0; for (int i = 0; i < count; ++i) { - byte v = input.ReadByte(); + byte v = input.ReadUInt8(); if (0 != (v & 0x80)) sampleL = (ushort)(v << 9); else @@ -112,7 +110,7 @@ namespace GameRes.Formats.Marble if (1 != Format.Channels) { ++i; - v = input.ReadByte(); + v = input.ReadUInt8(); if (0 != (v & 0x80)) sampleR = (ushort)(v << 9); else @@ -123,13 +121,13 @@ namespace GameRes.Formats.Marble } } - private void Decode2 (BinaryReader input, Stream output) + private void Decode2 (IBinaryStream input, Stream output) { if (1 != Format.Channels) { int channel_size = input.ReadInt32(); Decode3 (input, output, 2); - input.BaseStream.Position = 0x38 + channel_size; + input.Position = 0x38 + channel_size; output.Position = 2; Decode3 (input, output, 2); } @@ -137,7 +135,7 @@ namespace GameRes.Formats.Marble Decode3 (input, output, 0); } - private void Decode3 (BinaryReader input, Stream output, int step) + private void Decode3 (IBinaryStream input, Stream output, int step) { input.ReadInt32(); // unpacked_size int count = input.ReadInt32(); @@ -149,7 +147,7 @@ namespace GameRes.Formats.Marble { if (count - 300 == i) sample = 0; - ushort v = input.ReadByte(); + ushort v = input.ReadUInt8(); if (0 != (v & 1)) { ushort v14 = (ushort)((v >> 1) & 0x7F); @@ -163,7 +161,7 @@ namespace GameRes.Formats.Marble } else { - v |= (ushort)(input.ReadByte() << 8); + v |= (ushort)(input.ReadUInt8() << 8); int repeat = SizeTable[(v >> 1) & 7]; short end = (short)(v & 0xFFF0); double inc = (end - sample) / (double)repeat; @@ -221,7 +219,7 @@ namespace GameRes.Formats.Marble public override string Description { get { return "Marble engine wave audio format"; } } public override uint Signature { get { return 0x59444157u; } } // 'WADY' - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { return new WadyInput (file); } diff --git a/ArcFormats/Marble/ImagePRS.cs b/ArcFormats/Marble/ImagePRS.cs index 2e3bdb28..7386b88f 100644 --- a/ArcFormats/Marble/ImagePRS.cs +++ b/ArcFormats/Marble/ImagePRS.cs @@ -53,11 +53,9 @@ namespace GameRes.Formats.Marble throw new NotImplementedException ("PrsFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x10]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x10); if (header[0] != 'Y' || header[1] != 'B') return null; int bpp = header[3]; @@ -66,15 +64,15 @@ namespace GameRes.Formats.Marble return new PrsMetaData { - Width = LittleEndian.ToUInt16 (header, 12), - Height = LittleEndian.ToUInt16 (header, 14), + Width = header.ToUInt16 (12), + Height = header.ToUInt16 (14), BPP = 8 * bpp, Flag = header[2], - PackedSize = LittleEndian.ToUInt32 (header, 4), + PackedSize = header.ToUInt32 (4), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { using (var reader = new Reader (stream, (PrsMetaData)info)) { @@ -85,7 +83,7 @@ namespace GameRes.Formats.Marble internal class Reader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; uint m_size; byte m_flag; @@ -95,9 +93,9 @@ namespace GameRes.Formats.Marble public PixelFormat Format { get; private set; } public int Stride { get; private set; } - public Reader (Stream file, PrsMetaData info) + public Reader (IBinaryStream file, PrsMetaData info) { - m_input = new BinaryReader (file, Encoding.ASCII, true); + m_input = file; m_size = info.PackedSize; m_flag = info.Flag; m_depth = info.BPP / 8; @@ -123,7 +121,7 @@ namespace GameRes.Formats.Marble public void Unpack () { - m_input.BaseStream.Position = 0x10; + m_input.Position = 0x10; int dst = 0; int remaining = (int)m_size; int bit = 0; @@ -133,7 +131,7 @@ namespace GameRes.Formats.Marble bit >>= 1; if (0 == bit) { - ctl = m_input.ReadByte(); + ctl = m_input.ReadUInt8(); --remaining; bit = 0x80; } @@ -141,11 +139,11 @@ namespace GameRes.Formats.Marble break; if (0 == (ctl & bit)) { - m_output[dst++] = m_input.ReadByte(); + m_output[dst++] = m_input.ReadUInt8(); --remaining; continue; } - int b = m_input.ReadByte(); + int b = m_input.ReadUInt8(); --remaining; int length = 0; int shift = 0; @@ -154,14 +152,14 @@ namespace GameRes.Formats.Marble { if (remaining <= 0) break; - shift = m_input.ReadByte(); + shift = m_input.ReadUInt8(); --remaining; shift |= (b & 0x3f) << 8; if (0 != (b & 0x40)) { if (remaining <= 0) break; - int offset = m_input.ReadByte(); + int offset = m_input.ReadUInt8(); --remaining; length = LengthTable[offset]; } diff --git a/ArcFormats/Masys/ImageAG.cs b/ArcFormats/Masys/ImageAG.cs index 315d5178..c559df84 100644 --- a/ArcFormats/Masys/ImageAG.cs +++ b/ArcFormats/Masys/ImageAG.cs @@ -38,22 +38,19 @@ namespace GameRes.Formats.Megu public override string Description { get { return "Masys image format"; } } public override uint Signature { get { return 0x00644741u; } } // 'AGd' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var file = new ArcView.Reader (stream)) - { - file.ReadUInt32(); - var info = new ImageMetaData(); - info.Width = file.ReadUInt32(); - info.Height = file.ReadUInt32(); - file.BaseStream.Position = 0x38; - int alpha_size = file.ReadInt32(); - info.BPP = 0 == alpha_size ? 24 : 32; - return info; - } + file.Position = 4; + var info = new ImageMetaData(); + info.Width = file.ReadUInt32(); + info.Height = file.ReadUInt32(); + file.Position = 0x38; + int alpha_size = file.ReadInt32(); + info.BPP = 0 == alpha_size ? 24 : 32; + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var reader = new AgReader (stream, info); reader.Unpack(); @@ -83,54 +80,51 @@ namespace GameRes.Formats.Megu public byte[] Data { get { return m_output; } } public PixelFormat Format { get; private set; } - public AgReader (Stream stream, ImageMetaData info) + public AgReader (IBinaryStream input, ImageMetaData info) { m_width = (int)info.Width; m_height = (int)info.Height; - stream.Position = 0x0c; - using (var input = new ArcView.Reader (stream)) + input.Position = 0x0c; + uint offset1 = input.ReadUInt32(); + int size1 = input.ReadInt32(); + uint offset2 = input.ReadUInt32(); + int size2 = input.ReadInt32(); + uint offset3 = input.ReadUInt32(); + int size3 = input.ReadInt32(); + uint offset4 = input.ReadUInt32(); + int size4 = input.ReadInt32(); + uint offset5 = input.ReadUInt32(); + int size5 = input.ReadInt32(); + uint offset6 = input.ReadUInt32(); + int size6 = input.ReadInt32(); + input.Read (m_first, 0, 3); + if (size1 != 0) + in1 = ReadSection (input, offset1, size1); + if (size2 != 0) + in2 = ReadSection (input, offset2, size2); + if (size3 != 0) + in3 = ReadSection (input, offset3, size3); + if (size4 != 0) + in4 = ReadSection (input, offset4, size4); + if (size5 != 0) + in5 = ReadSection (input, offset5, size5); + if (size6 != 0) { - uint offset1 = input.ReadUInt32(); - int size1 = input.ReadInt32(); - uint offset2 = input.ReadUInt32(); - int size2 = input.ReadInt32(); - uint offset3 = input.ReadUInt32(); - int size3 = input.ReadInt32(); - uint offset4 = input.ReadUInt32(); - int size4 = input.ReadInt32(); - uint offset5 = input.ReadUInt32(); - int size5 = input.ReadInt32(); - uint offset6 = input.ReadUInt32(); - int size6 = input.ReadInt32(); - input.Read (m_first, 0, 3); - if (size1 != 0) - in1 = ReadSection (stream, offset1, size1); - if (size2 != 0) - in2 = ReadSection (stream, offset2, size2); - if (size3 != 0) - in3 = ReadSection (stream, offset3, size3); - if (size4 != 0) - in4 = ReadSection (stream, offset4, size4); - if (size5 != 0) - in5 = ReadSection (stream, offset5, size5); - if (size6 != 0) - { - input.BaseStream.Position = offset6; - m_alpha = new byte[m_height*m_width]; - RleDecode (input, m_alpha); - Format = PixelFormats.Bgra32; - m_pixel_size = 4; - } - else - { - Format = PixelFormats.Bgr24; - m_pixel_size = 3; - } - m_output = new byte[m_width*m_height*m_pixel_size]; + input.Position = offset6; + m_alpha = new byte[m_height*m_width]; + RleDecode (input, m_alpha); + Format = PixelFormats.Bgra32; + m_pixel_size = 4; } + else + { + Format = PixelFormats.Bgr24; + m_pixel_size = 3; + } + m_output = new byte[m_width*m_height*m_pixel_size]; } - static private byte[] ReadSection (Stream input, long offset, int size) + static private byte[] ReadSection (IBinaryStream input, long offset, int size) { input.Position = offset; var buf = new byte[size + 4]; @@ -362,13 +356,13 @@ namespace GameRes.Formats.Megu } } - private static void RleDecode (BinaryReader src, byte[] dst_buf) + private static void RleDecode (IBinaryStream src, byte[] dst_buf) { int remaining = dst_buf.Length; int dst = 0; while (remaining > 0) { - byte v = src.ReadByte(); + byte v = src.ReadUInt8(); int count; if (0 != (v & 0x80)) { diff --git a/ArcFormats/MnoViolet/ImageDIF.cs b/ArcFormats/MnoViolet/ImageDIF.cs index 71ecf562..f0802ba8 100644 --- a/ArcFormats/MnoViolet/ImageDIF.cs +++ b/ArcFormats/MnoViolet/ImageDIF.cs @@ -67,23 +67,22 @@ namespace GameRes.Formats.MnoViolet Extensions = new string[] { "dif" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x7C]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - var base_name = Binary.GetCString (header, 4, 100); + var header = stream.ReadHeader (0x7C); + var base_name = header.GetCString (4, 100); if (string.IsNullOrEmpty (base_name)) return null; var files = VFS.GetFiles (base_name+".*"); if (!files.Any()) throw new FileNotFoundException (string.Format ("Base image '{0}' not found", base_name)); var base_entry = files.First(); - using (var input = VFS.OpenSeekableStream (base_entry)) + if (base_entry.Name.Equals (stream.Name, StringComparison.InvariantCultureIgnoreCase)) + throw new InvalidFormatException ("DIF image references itself"); + using (var input = VFS.OpenBinaryStream (base_entry)) { - // ReadMetaData isn't supplied with a filename being processed, so infinite recursion can't be - // prevented here unless we save state in a static member. - var format = ImageFormat.FindFormat (input, base_entry.Name); + // infinite recursion still possible in case of two files referencing each other. + var format = ImageFormat.FindFormat (input); if (null == format) throw new InvalidFormatException (string.Format ("Unable to interpret base image '{0}'", base_name)); format.Item2.FileName = base_entry.Name; @@ -95,27 +94,27 @@ namespace GameRes.Formats.MnoViolet BaseEntry = base_entry, BaseFormat = format.Item1, BaseInfo = format.Item2, - PackedIndexSize = LittleEndian.ToInt32 (header, 0x68), - IndexSize = LittleEndian.ToInt32 (header, 0x6C), - PackedDiffSize = LittleEndian.ToInt32 (header, 0x70), - DiffDataSize = LittleEndian.ToInt32 (header, 0x74), - DiffCount = LittleEndian.ToInt32 (header, 0x78), + PackedIndexSize = header.ToInt32 (0x68), + IndexSize = header.ToInt32 (0x6C), + PackedDiffSize = header.ToInt32 (0x70), + DiffDataSize = header.ToInt32 (0x74), + DiffCount = header.ToInt32 (0x78), }; } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (DifMetaData)info; BitmapSource base_bitmap; - using (var input = VFS.OpenSeekableStream (meta.BaseEntry)) + using (var input = VFS.OpenBinaryStream (meta.BaseEntry)) { var image = meta.BaseFormat.Read (input, meta.BaseInfo); base_bitmap = image.Bitmap; } stream.Position = 0x7C; var index = new byte[meta.IndexSize]; - using (var input = new LzssStream (stream, LzssMode.Decompress, true)) + using (var input = new LzssStream (stream.AsStream, LzssMode.Decompress, true)) if (index.Length != input.Read (index, 0, index.Length)) throw new EndOfStreamException(); @@ -134,7 +133,7 @@ namespace GameRes.Formats.MnoViolet } stream.Position = 0x7C + meta.PackedIndexSize; - using (var diff = new LzssStream (stream, LzssMode.Decompress, true)) + using (var diff = new LzssStream (stream.AsStream, LzssMode.Decompress, true)) { int index_src = 0; for (int i = 0; i < meta.DiffCount; ++i) diff --git a/ArcFormats/MnoViolet/ImageGRA.cs b/ArcFormats/MnoViolet/ImageGRA.cs index 97bf9f8b..d439e9b5 100644 --- a/ArcFormats/MnoViolet/ImageGRA.cs +++ b/ArcFormats/MnoViolet/ImageGRA.cs @@ -55,45 +55,42 @@ namespace GameRes.Formats.MnoViolet throw new NotImplementedException ("GraFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var input = new ArcView.Reader (stream)) + uint sign = file.ReadUInt32(); + uint width = file.ReadUInt32(); + uint height = file.ReadUInt32(); + if (0 == width || width > 0x8000 || 0 == height || height > 0x8000) + return null; + int bpp; + if (0x617267 == sign) // 'gra' + bpp = 24; + else if (0x73616D == sign) // 'mas' + bpp = 8; + else if (1 == sign) + bpp = file.ReadInt32(); + else + return null; + if (bpp != 32 && bpp != 24 && bpp != 8) + return null; + int packed_size = file.ReadInt32(); + int data_size = file.ReadInt32(); + return new GraMetaData { - uint sign = input.ReadUInt32(); - uint width = input.ReadUInt32(); - uint height = input.ReadUInt32(); - if (0 == width || width > 0x8000 || 0 == height || height > 0x8000) - return null; - int bpp; - if (0x617267 == sign) // 'gra' - bpp = 24; - else if (0x73616D == sign) // 'mas' - bpp = 8; - else if (1 == sign) - bpp = input.ReadInt32(); - else - return null; - if (bpp != 32 && bpp != 24 && bpp != 8) - return null; - int packed_size = input.ReadInt32(); - int data_size = input.ReadInt32(); - return new GraMetaData - { - Width = width, - Height = height, - PackedSize = packed_size, - UnpackedSize = data_size, - BPP = bpp, - DataOffset = stream.Position, - }; - } + Width = width, + Height = height, + PackedSize = packed_size, + UnpackedSize = data_size, + BPP = bpp, + DataOffset = file.Position, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (GraMetaData)info; stream.Position = meta.DataOffset; - using (var reader = new LzssReader (stream, meta.PackedSize, meta.UnpackedSize)) + using (var reader = new LzssReader (stream.AsStream, meta.PackedSize, meta.UnpackedSize)) { reader.Unpack(); int stride = ((int)info.Width*info.BPP/8 + 3) & ~3; diff --git a/ArcFormats/MokoPro/CompressedFile.cs b/ArcFormats/MokoPro/CompressedFile.cs index 84311ca4..95c1359d 100644 --- a/ArcFormats/MokoPro/CompressedFile.cs +++ b/ArcFormats/MokoPro/CompressedFile.cs @@ -98,12 +98,13 @@ namespace GameRes.Formats.Mokopro Extensions = new string[0]; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var moko = new MokoCrypt (stream); + var moko = new MokoCrypt (stream.AsStream); using (var lzss = moko.UnpackStream()) + using (var bmp = new BinaryStream (lzss, stream.Name)) { - var info = base.ReadMetaData (lzss); + var info = base.ReadMetaData (bmp); if (null == info) return null; return new NNNNMetaData @@ -117,11 +118,12 @@ namespace GameRes.Formats.Mokopro } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (NNNNMetaData)info; using (var lzss = meta.Input.UnpackStream()) - return base.Read (lzss, meta.BmpInfo); + using (var bmp = new BinaryStream (lzss, stream.Name)) + return base.Read (bmp, meta.BmpInfo); } public override void Write (Stream file, ImageData image) @@ -142,9 +144,9 @@ namespace GameRes.Formats.Mokopro Extensions = new string[0]; } - public override SoundInput TryOpen (Stream stream) + public override SoundInput TryOpen (IBinaryStream stream) { - var moko = new MokoCrypt (stream); + var moko = new MokoCrypt (stream.AsStream); var ogg = moko.UnpackBytes(); var output = new MemoryStream (ogg); try diff --git a/ArcFormats/Moonhir/ArcFPK.cs b/ArcFormats/Moonhir/ArcFPK.cs index 7a7fcf09..3a6f1167 100644 --- a/ArcFormats/Moonhir/ArcFPK.cs +++ b/ArcFormats/Moonhir/ArcFPK.cs @@ -132,7 +132,7 @@ namespace GameRes.Formats.MoonhirGames var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); Decrypt (data, 0, data.Length, farc.Key); int length = LittleEndian.ToInt32 (data, data.Length-8); - input = new MemoryStream (data, 0, length); + input = new BinMemoryStream (data, 0, length, entry.Name); header = data; } if (!Binary.AsciiEqual (header, "FBX\x01")) @@ -143,7 +143,7 @@ namespace GameRes.Formats.MoonhirGames int unpacked_size = LittleEndian.ToInt32 (header, 0xC); input.Position = header[7]; var unpacked = UnpackFbx (input, packed_size, unpacked_size); - return new MemoryStream (unpacked); + return new BinMemoryStream (unpacked, entry.Name); } } diff --git a/ArcFormats/Nags/ImageNGP.cs b/ArcFormats/Nags/ImageNGP.cs index 2206a4da..b5257e6a 100644 --- a/ArcFormats/Nags/ImageNGP.cs +++ b/ArcFormats/Nags/ImageNGP.cs @@ -43,34 +43,31 @@ namespace GameRes.Formats.Nags public override string Description { get { return "NAGS engine image format"; } } public override uint Signature { get { return 0x2050474E; } } // 'NGP ' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - stream.Position = 0x12; - using (var reader = new ArcView.Reader (stream)) + file.Position = 0x12; + int packed_size = file.ReadInt32(); + uint width = file.ReadUInt32(); + uint height = file.ReadUInt32(); + int bpp = file.ReadUInt16() * 8; + file.Position = 0x100; + int unpacked_size = file.ReadInt32(); + if (packed_size <= 0 || unpacked_size <= 0) + return null; + return new NgpMetaData { - int packed_size = reader.ReadInt32(); - uint width = reader.ReadUInt32(); - uint height = reader.ReadUInt32(); - int bpp = reader.ReadUInt16() * 8; - reader.BaseStream.Position = 0x100; - int unpacked_size = reader.ReadInt32(); - if (packed_size <= 0 || unpacked_size <= 0) - return null; - return new NgpMetaData - { - Width = width, - Height = height, - BPP = bpp, - PackedSize = packed_size, - UnpackedSize = unpacked_size, - }; - } + Width = width, + Height = height, + BPP = bpp, + PackedSize = packed_size, + UnpackedSize = unpacked_size, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (NgpMetaData)info; - using (var input = new StreamRegion (stream, 0x104, meta.PackedSize, true)) + using (var input = new StreamRegion (stream.AsStream, 0x104, meta.PackedSize, true)) using (var z = new ZLibStream (input, CompressionMode.Decompress)) { var pixels = new byte[meta.UnpackedSize]; diff --git a/ArcFormats/NekoSDK/ImageALP.cs b/ArcFormats/NekoSDK/ImageALP.cs index 3c2af24a..8970997b 100644 --- a/ArcFormats/NekoSDK/ImageALP.cs +++ b/ArcFormats/NekoSDK/ImageALP.cs @@ -33,7 +33,7 @@ namespace GameRes.Formats.NekoSDK [Export(typeof(IBmpExtension))] public class AlpBitmap : IBmpExtension { - public ImageData Read (Stream file, BmpMetaData info) + public ImageData Read (IBinaryStream file, BmpMetaData info) { if (info.BPP != 24 && info.BPP != 32 || !file.CanSeek) return null; diff --git a/ArcFormats/Nexas/ArcPAC.cs b/ArcFormats/Nexas/ArcPAC.cs index 19c017de..f3d9daea 100644 --- a/ArcFormats/Nexas/ArcPAC.cs +++ b/ArcFormats/Nexas/ArcPAC.cs @@ -194,7 +194,7 @@ namespace GameRes.Formats.NeXAS var packed = new byte[entry.Size]; input.Read (packed, 0, packed.Length); var unpacked = HuffmanDecode (packed, (int)pent.UnpackedSize); - return new MemoryStream (unpacked, 0, (int)pent.UnpackedSize); + return new BinMemoryStream (unpacked, 0, (int)pent.UnpackedSize, entry.Name); } case Compression.Deflate: default: diff --git a/ArcFormats/Nexas/ImageGRP.cs b/ArcFormats/Nexas/ImageGRP.cs index 95d6e4d0..f39b391a 100644 --- a/ArcFormats/Nexas/ImageGRP.cs +++ b/ArcFormats/Nexas/ImageGRP.cs @@ -48,21 +48,19 @@ namespace GameRes.Formats.NeXAS Extensions = new string[] { "grp" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x11]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x11); return new GrpMetaData { - Width = LittleEndian.ToUInt32 (header, 5), - Height = LittleEndian.ToUInt32 (header, 9), - BPP = LittleEndian.ToUInt16 (header, 3), - UnpackedSize = LittleEndian.ToInt32 (header, 0xD), + Width = header.ToUInt32 (5), + Height = header.ToUInt32 (9), + BPP = header.ToUInt16 (3), + UnpackedSize = header.ToInt32 (0xD), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { using (var reader = new GrpReader (stream, (GrpMetaData)info)) { @@ -79,15 +77,15 @@ namespace GameRes.Formats.NeXAS internal sealed class GrpReader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; public byte[] Data { get { return m_output; } } public PixelFormat Format { get; private set; } - public GrpReader (Stream input, GrpMetaData info) + public GrpReader (IBinaryStream input, GrpMetaData info) { - m_input = new ArcView.Reader (input); + m_input = input; m_output = new byte[info.UnpackedSize]; if (24 == info.BPP) Format = PixelFormats.Bgr24; @@ -99,7 +97,7 @@ namespace GameRes.Formats.NeXAS public void Unpack () { - m_input.BaseStream.Position = 0x11; + m_input.Position = 0x11; int ctl_length = (m_input.ReadInt32() + 7) / 8; var ctl_bytes = m_input.ReadBytes (ctl_length); m_input.ReadInt32(); @@ -114,7 +112,7 @@ namespace GameRes.Formats.NeXAS break; if (0 == bit) { - m_output[dst++] = m_input.ReadByte(); + m_output[dst++] = m_input.ReadUInt8(); } else { @@ -129,14 +127,8 @@ namespace GameRes.Formats.NeXAS } #region IDisposable Members - bool _disposed = false; public void Dispose () { - if (!_disposed) - { - m_input.Dispose(); - _disposed = true; - } } #endregion } diff --git a/ArcFormats/NitroPlus/ArcNitro.cs b/ArcFormats/NitroPlus/ArcNitro.cs index d4612b4d..595f3fd4 100644 --- a/ArcFormats/NitroPlus/ArcNitro.cs +++ b/ArcFormats/NitroPlus/ArcNitro.cs @@ -215,7 +215,7 @@ namespace GameRes.Formats.NitroPlus key = Binary.RotR (key, 8); } if (enc_size == entry.Size) - return new MemoryStream (buf); + return new BinMemoryStream (buf, entry.Name); return new PrefixStream (buf, arc.File.CreateStream (entry.Offset+enc_size, entry.Size-enc_size)); } } diff --git a/ArcFormats/NonColor/ArcDAT.cs b/ArcFormats/NonColor/ArcDAT.cs index 16006ff5..8198d178 100644 --- a/ArcFormats/NonColor/ArcDAT.cs +++ b/ArcFormats/NonColor/ArcDAT.cs @@ -193,7 +193,7 @@ namespace GameRes.Formats.NonColor for (int i = 0; i < dent.RawName.Length-1; ++i) for (int j = 0; j < block_length; ++j) data[n++] ^= dent.RawName[i]; - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } static IDictionary> FileMapIndex = null; diff --git a/ArcFormats/Pajamas/ArcGameDat.cs b/ArcFormats/Pajamas/ArcGameDat.cs index 55eef147..1477ee95 100644 --- a/ArcFormats/Pajamas/ArcGameDat.cs +++ b/ArcFormats/Pajamas/ArcGameDat.cs @@ -27,7 +27,6 @@ using System; using System.Collections.Generic; using System.ComponentModel.Composition; using System.IO; -using GameRes.Utility; namespace GameRes.Formats.Pajamas { @@ -84,10 +83,9 @@ namespace GameRes.Formats.Pajamas public override Stream OpenEntry (ArcFile arc, Entry entry) { - if (!entry.Name.Equals ("textdata.bin", StringComparison.InvariantCultureIgnoreCase)) + if (!entry.Name.EndsWith ("textdata.bin", StringComparison.InvariantCultureIgnoreCase)) return arc.File.CreateStream (entry.Offset, entry.Size); - var data = new byte[entry.Size]; - arc.File.View.Read (entry.Offset, data, 0, entry.Size); + var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); // encrypted PJADV if (0x95 == data[0] && 0x6B == data[1] && 0x3C == data[2] && 0x9D == data[3] && 0x63 == data[4]) @@ -99,7 +97,7 @@ namespace GameRes.Formats.Pajamas key += 0x5C; } } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } } diff --git a/ArcFormats/Pajamas/ImageEPA.cs b/ArcFormats/Pajamas/ImageEPA.cs index c44fed68..d970f067 100644 --- a/ArcFormats/Pajamas/ImageEPA.cs +++ b/ArcFormats/Pajamas/ImageEPA.cs @@ -56,41 +56,35 @@ namespace GameRes.Formats.Pajamas throw new NotImplementedException ("EpaFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var header = new ArcView.Reader (stream)) + var info = new EpaMetaData(); + info.Mode = file.ReadInt32() >> 24; + info.ColorType = file.ReadInt32() & 0xff; + switch (info.ColorType) { - var info = new EpaMetaData(); - info.Mode = header.ReadInt32() >> 24; - info.ColorType = header.ReadInt32() & 0xff; - switch (info.ColorType) - { - case 0: info.BPP = 8; break; - case 1: info.BPP = 24; break; - case 2: info.BPP = 32; break; - case 3: info.BPP = 15; break; - case 4: info.BPP = 8; break; - default: return null; - } - info.Width = header.ReadUInt32(); - info.Height = header.ReadUInt32(); - if (2 == info.Mode) - { - info.OffsetX = header.ReadInt32(); - info.OffsetY = header.ReadInt32(); - } - return info; + case 0: info.BPP = 8; break; + case 1: info.BPP = 24; break; + case 2: info.BPP = 32; break; + case 3: info.BPP = 15; break; + case 4: info.BPP = 8; break; + default: return null; } + info.Width = file.ReadUInt32(); + info.Height = file.ReadUInt32(); + if (2 == info.Mode) + { + info.OffsetX = file.ReadInt32(); + info.OffsetY = file.ReadInt32(); + } + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { - var meta = info as EpaMetaData; - if (null == meta) - throw new ArgumentException ("EpaFormat.Read should be supplied with EpaMetaData", "info"); - - stream.Position = 2 == meta.Mode ? 0x18 : 0x10; - var reader = new Reader (stream, meta); + var meta = (EpaMetaData)info as EpaMetaData; + file.Position = 2 == meta.Mode ? 0x18 : 0x10; + var reader = new Reader (file.AsStream, meta); reader.Unpack(); return ImageData.Create (meta, reader.Format, reader.Palette, reader.Data); } diff --git a/ArcFormats/Palette/ImagePGA.cs b/ArcFormats/Palette/ImagePGA.cs index c732871a..e42f748e 100644 --- a/ArcFormats/Palette/ImagePGA.cs +++ b/ArcFormats/Palette/ImagePGA.cs @@ -36,13 +36,13 @@ namespace GameRes.Formats.Palette public override uint Signature { get { return 0x50414750; } } // 'PGAP' public override bool CanWrite { get { return true; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { using (var png = DeobfuscateStream (stream)) return base.ReadMetaData (png); } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { using (var png = DeobfuscateStream (stream)) return base.Read (png, info); @@ -66,15 +66,16 @@ namespace GameRes.Formats.Palette public static readonly byte[] PngHeader = { 0x89, 0x50, 0x4E, 0x47, 0xD, 0xA, 0x1A, 0xA }; public static readonly byte[] PngFooter = { 0, 0, 0, 0, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82 }; - Stream DeobfuscateStream (Stream stream) + IBinaryStream DeobfuscateStream (IBinaryStream stream) { var png_header = new byte[0x10]; stream.Read (png_header, 5, 11); System.Buffer.BlockCopy (PngHeader, 0, png_header, 0, 8); for (int i = 0; i < 8; ++i) png_header[i+8] ^= (byte)"PGAECODE"[i]; - var png_body = new StreamRegion (stream, 11, true); - return new PrefixStream (png_header, png_body); + var png_body = new StreamRegion (stream.AsStream, 11, true); + var pre = new PrefixStream (png_header, png_body); + return new BinaryStream (pre, stream.Name); } } } diff --git a/ArcFormats/Primel/ImageGBC.cs b/ArcFormats/Primel/ImageGBC.cs index 8b883859..628204e8 100644 --- a/ArcFormats/Primel/ImageGBC.cs +++ b/ArcFormats/Primel/ImageGBC.cs @@ -43,23 +43,21 @@ namespace GameRes.Formats.Primel public override string Description { get { return "Primel Adventure System image format"; } } public override uint Signature { get { return 0x46434247; } } // 'GBCF' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x14]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x14); return new GbcMetaData { - Width = LittleEndian.ToUInt32 (header, 8), - Height = LittleEndian.ToUInt32 (header, 0xC), - BPP = LittleEndian.ToUInt16 (header, 0x10), - Flags = LittleEndian.ToUInt16 (header, 0x12), + Width = header.ToUInt32 (8), + Height = header.ToUInt32 (0xC), + BPP = header.ToUInt16 (0x10), + Flags = header.ToUInt16 (0x12), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - using (var reader = new GbcReader (stream, (GbcMetaData)info)) + using (var reader = new GbcReader (stream.AsStream, (GbcMetaData)info)) { reader.Unpack(); return ImageData.Create (info, reader.Format, null, reader.Pixels); diff --git a/ArcFormats/Propeller/ArcMGR.cs b/ArcFormats/Propeller/ArcMGR.cs index 680acac8..1525d7ae 100644 --- a/ArcFormats/Propeller/ArcMGR.cs +++ b/ArcFormats/Propeller/ArcMGR.cs @@ -96,7 +96,7 @@ namespace GameRes.Formats.Propeller { var bmp = new byte[(entry as PackedEntry).UnpackedSize]; Decompress (input, bmp); - return new MemoryStream (bmp); + return new BinMemoryStream (bmp, entry.Name); } } diff --git a/ArcFormats/Propeller/ArcMPK.cs b/ArcFormats/Propeller/ArcMPK.cs index b20c86c2..39c23ffe 100644 --- a/ArcFormats/Propeller/ArcMPK.cs +++ b/ArcFormats/Propeller/ArcMPK.cs @@ -81,7 +81,7 @@ namespace GameRes.Formats.Propeller var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); for (int i = 0; i < data.Length; ++i) data[i] ^= 0x88; - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } } diff --git a/ArcFormats/Propeller/ImageMGR.cs b/ArcFormats/Propeller/ImageMGR.cs index d3a82dc4..de6af451 100644 --- a/ArcFormats/Propeller/ImageMGR.cs +++ b/ArcFormats/Propeller/ImageMGR.cs @@ -45,60 +45,57 @@ namespace GameRes.Formats.Propeller public override string Description { get { return "Propeller image format"; } } public override uint Signature { get { return 0; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - using (var reader = new ArcView.Reader (stream)) + int count = stream.ReadInt16(); + if (count <= 0 || count >= 0x100) + return null; + int offset; + if (count > 1) { - int count = reader.ReadInt16(); - if (count <= 0 || count >= 0x100) + offset = stream.ReadInt32(); + if (offset != 2 + count * 4) return null; - int offset; - if (count > 1) + } + else + offset = 2; + stream.Position = offset; + int unpacked_size = stream.ReadInt32(); + int packed_size = stream.ReadInt32(); + offset += 8; + if (offset + packed_size > stream.Length) + return null; + byte[] header = new byte[0x36]; + if (0x36 != MgrOpener.Decompress (stream.AsStream, header) + || header[0] != 'B' || header[1] != 'M') + return null; + using (var bmp = new BinMemoryStream (header, stream.Name)) + { + var info = Bmp.ReadMetaData (bmp); + if (null == info) + return null; + return new MgrMetaData { - offset = reader.ReadInt32(); - if (offset != 2 + count * 4) - return null; - } - else - offset = 2; - stream.Position = offset; - int unpacked_size = reader.ReadInt32(); - int packed_size = reader.ReadInt32(); - offset += 8; - if (offset + packed_size > stream.Length) - return null; - byte[] header = new byte[0x36]; - if (0x36 != MgrOpener.Decompress (stream, header) - || header[0] != 'B' || header[1] != 'M') - return null; - using (var bmp = new MemoryStream (header)) - { - var info = Bmp.ReadMetaData (bmp); - if (null == info) - return null; - return new MgrMetaData - { - Width = info.Width, - Height = info.Height, - BPP = info.BPP, - Offset = offset, - PackedSize = packed_size, - UnpackedSize = unpacked_size, - }; - } + Width = info.Width, + Height = info.Height, + BPP = info.BPP, + Offset = offset, + PackedSize = packed_size, + UnpackedSize = unpacked_size, + }; } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (MgrMetaData)info; stream.Position = meta.Offset; var data = new byte[meta.UnpackedSize]; - if (data.Length != MgrOpener.Decompress (stream, data)) + if (data.Length != MgrOpener.Decompress (stream.AsStream, data)) throw new InvalidFormatException(); if (meta.BPP != 32) { - using (var bmp = new MemoryStream (data)) + using (var bmp = new BinMemoryStream (data, stream.Name)) return Bmp.Read (bmp, info); } // special case for 32bpp bitmaps with alpha-channel diff --git a/ArcFormats/Qlie/ArcABMP.cs b/ArcFormats/Qlie/ArcABMP.cs index 16d58d18..0e9af691 100644 --- a/ArcFormats/Qlie/ArcABMP.cs +++ b/ArcFormats/Qlie/ArcABMP.cs @@ -140,8 +140,8 @@ namespace GameRes.Formats.Qlie arc.File.View.Read (entry.Offset, packed, 0, entry.Size); var unpacked = PackOpener.Decompress (packed); if (null == unpacked) - return new MemoryStream (packed); - return new MemoryStream (unpacked); + unpacked = packed; + return new BinMemoryStream (unpacked, entry.Name); } static protected void DetectFileType (ArcView file, Entry entry) diff --git a/ArcFormats/Qlie/ArcQLIE.cs b/ArcFormats/Qlie/ArcQLIE.cs index 5f3469a9..b8d241ad 100644 --- a/ArcFormats/Qlie/ArcQLIE.cs +++ b/ArcFormats/Qlie/ArcQLIE.cs @@ -192,7 +192,7 @@ namespace GameRes.Formats.Qlie if (null == qent || null == qarc || (!qent.IsEncrypted && !qent.IsPacked)) return arc.File.CreateStream (entry.Offset, entry.Size); var data = ReadEntryBytes (arc.File, qent, qarc.Hash, qarc.GameKeyData); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } private byte[] ReadEntryBytes (ArcView file, QlieEntry entry, uint hash, byte[] game_key) diff --git a/ArcFormats/Qlie/ImageDPNG.cs b/ArcFormats/Qlie/ImageDPNG.cs index e563f91c..432c0cdc 100644 --- a/ArcFormats/Qlie/ImageDPNG.cs +++ b/ArcFormats/Qlie/ImageDPNG.cs @@ -48,52 +48,46 @@ namespace GameRes.Formats.Qlie Extensions = new string[] { "png" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - stream.Position = 8; - using (var header = new ArcView.Reader (stream)) - { - var info = new DpngMetaData { BPP = 32 }; - info.TileCount = header.ReadInt32(); - if (info.TileCount <= 0) - return null; - info.Width = header.ReadUInt32(); - info.Height = header.ReadUInt32(); - return info; - } + file.Position = 8; + var info = new DpngMetaData { BPP = 32 }; + info.TileCount = file.ReadInt32(); + if (info.TileCount <= 0) + return null; + info.Width = file.ReadUInt32(); + info.Height = file.ReadUInt32(); + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (DpngMetaData)info; var bitmap = new WriteableBitmap ((int)info.Width, (int)info.Height, ImageData.DefaultDpiX, ImageData.DefaultDpiY, PixelFormats.Pbgra32, null); long next_tile = 0x14; - using (var dpng = new ArcView.Reader (stream)) + for (int i = 0; i < meta.TileCount; ++i) { - for (int i = 0; i < meta.TileCount; ++i) + stream.Position = next_tile; + int x = stream.ReadInt32(); + int y = stream.ReadInt32(); + int width = stream.ReadInt32(); + int height = stream.ReadInt32(); + uint size = stream.ReadUInt32(); + stream.Seek (8, SeekOrigin.Current); + next_tile = stream.Position + size; + if (0 == size) + continue; + using (var png = new StreamRegion (stream.AsStream, stream.Position, size, true)) { - stream.Position = next_tile; - int x = dpng.ReadInt32(); - int y = dpng.ReadInt32(); - int width = dpng.ReadInt32(); - int height = dpng.ReadInt32(); - uint size = dpng.ReadUInt32(); - stream.Seek (8, SeekOrigin.Current); - next_tile = stream.Position + size; - if (0 == size) - continue; - using (var png = new StreamRegion (stream, stream.Position, size, true)) - { - var decoder = new PngBitmapDecoder (png, - BitmapCreateOptions.None, BitmapCacheOption.OnLoad); - var frame = new FormatConvertedBitmap (decoder.Frames[0], PixelFormats.Pbgra32, null, 0); - int stride = frame.PixelWidth * 4; - var pixels = new byte[stride * frame.PixelHeight]; - frame.CopyPixels (pixels, stride, 0); - var rect = new Int32Rect (0, 0, frame.PixelWidth, frame.PixelHeight); - bitmap.WritePixels (rect, pixels, stride, x, y); - } + var decoder = new PngBitmapDecoder (png, + BitmapCreateOptions.None, BitmapCacheOption.OnLoad); + var frame = new FormatConvertedBitmap (decoder.Frames[0], PixelFormats.Pbgra32, null, 0); + int stride = frame.PixelWidth * 4; + var pixels = new byte[stride * frame.PixelHeight]; + frame.CopyPixels (pixels, stride, 0); + var rect = new Int32Rect (0, 0, frame.PixelWidth, frame.PixelHeight); + bitmap.WritePixels (rect, pixels, stride, x, y); } } bitmap.Freeze(); diff --git a/ArcFormats/RealLive/ArcG00.cs b/ArcFormats/RealLive/ArcG00.cs index 89d9d66c..8a734136 100644 --- a/ArcFormats/RealLive/ArcG00.cs +++ b/ArcFormats/RealLive/ArcG00.cs @@ -97,8 +97,7 @@ namespace GameRes.Formats.RealLive } byte[] bitmap; using (var input = file.CreateStream (index_offset)) - using (var bin = new BinaryReader (input)) - bitmap = G00Reader.LzDecompress (bin, 2, 1); + bitmap = G00Reader.LzDecompress (input, 2, 1); using (var input = new MemoryStream (bitmap)) using (var reader = new BinaryReader (input)) diff --git a/ArcFormats/RealLive/AudioNWA.cs b/ArcFormats/RealLive/AudioNWA.cs index 05d2eed6..60e1fb19 100644 --- a/ArcFormats/RealLive/AudioNWA.cs +++ b/ArcFormats/RealLive/AudioNWA.cs @@ -50,41 +50,39 @@ namespace GameRes.Formats.RealLive public override string Description { get { return "RealLive engine audio format"; } } public override uint Signature { get { return 0; } } - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - var header = new byte[0x28]; - if (header.Length != file.Read (header, 0, header.Length)) - return null; - ushort channels = LittleEndian.ToUInt16 (header, 0); + var header = file.ReadHeader (0x28); + ushort channels = header.ToUInt16 (0); if (0 == channels || channels > 2) return null; - ushort bps = LittleEndian.ToUInt16 (header, 2); + ushort bps = header.ToUInt16 (2); if (bps != 8 && bps != 16) return null; var info = new NwaMetaData { - Compression = LittleEndian.ToInt32 (header, 8), - RunLengthEncoded = 0 != LittleEndian.ToInt32 (header, 0xC), - BlockCount = LittleEndian.ToInt32 (header, 0x10), - PcmSize = LittleEndian.ToInt32 (header, 0x14), - PackedSize = LittleEndian.ToInt32 (header, 0x18), - SampleCount = LittleEndian.ToInt32 (header, 0x1C), - BlockSize = LittleEndian.ToInt32 (header, 0x20), - FinalBlockSize = LittleEndian.ToInt32 (header, 0x24), + Compression = header.ToInt32 (8), + RunLengthEncoded = 0 != header.ToInt32 (0xC), + BlockCount = header.ToInt32 (0x10), + PcmSize = header.ToInt32 (0x14), + PackedSize = header.ToInt32 (0x18), + SampleCount = header.ToInt32 (0x1C), + BlockSize = header.ToInt32 (0x20), + FinalBlockSize = header.ToInt32 (0x24), }; if (info.PcmSize <= 0) return null; info.Format.FormatTag = 1; info.Format.Channels = channels; info.Format.BitsPerSample = bps; - info.Format.SamplesPerSecond = LittleEndian.ToUInt32 (header, 4); + info.Format.SamplesPerSecond = header.ToUInt32 (4); info.Format.BlockAlign = (ushort)(channels * bps/8); info.Format.AverageBytesPerSecond = info.Format.BlockAlign * info.Format.SamplesPerSecond; if (-1 == info.Compression) { if (info.PcmSize > file.Length - 0x2C) return null; - return new RawPcmInput (new StreamRegion (file, 0x2C, info.PcmSize), info.Format); + return new RawPcmInput (new StreamRegion (file.AsStream, 0x2C, info.PcmSize), info.Format); } if (info.Compression > 5) return null; @@ -103,7 +101,7 @@ namespace GameRes.Formats.RealLive internal sealed class NwaDecoder : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; NwaMetaData m_info; short[] m_sample; @@ -112,20 +110,20 @@ namespace GameRes.Formats.RealLive public byte[] Output { get { return m_output; } } - public NwaDecoder (Stream input, NwaMetaData info) + public NwaDecoder (IBinaryStream input, NwaMetaData info) { - m_input = new ArcView.Reader (input); + m_input = input; m_info = info; m_output = new byte[m_info.PcmSize]; m_sample = new short[2]; - m_bits = new LsbBitStream (input, true); + m_bits = new LsbBitStream (input.AsStream, true); } int m_dst; public void Decode () { - m_input.BaseStream.Position = 0x2C; + m_input.Position = 0x2C; var offsets = new uint[m_info.BlockCount]; for (int i = 0; i < offsets.Length; ++i) offsets[i] = m_input.ReadUInt32(); @@ -133,10 +131,10 @@ namespace GameRes.Formats.RealLive m_dst = 0; for (int i = 0; i < offsets.Length-1; ++i) { - m_input.BaseStream.Position = offsets[i]; + m_input.Position = offsets[i]; DecodeBlock (m_info.BlockSize); } - m_input.BaseStream.Position = offsets[offsets.Length-1]; + m_input.Position = offsets[offsets.Length-1]; if (m_info.FinalBlockSize > 0) DecodeBlock (m_info.FinalBlockSize); else @@ -149,7 +147,7 @@ namespace GameRes.Formats.RealLive for (int c = 0; c < channel_count; ++c) { if (8 == m_info.Format.BitsPerSample) - m_sample[c] = m_input.ReadByte(); + m_sample[c] = m_input.ReadUInt8(); else m_sample[c] = m_input.ReadInt16(); } @@ -237,15 +235,8 @@ namespace GameRes.Formats.RealLive } #region IDisposable Members - bool _disposed = false; public void Dispose () { - if (!_disposed) - { - m_bits.Dispose(); - m_input.Dispose(); - _disposed = true; - } } #endregion } diff --git a/ArcFormats/RealLive/AudioOWP.cs b/ArcFormats/RealLive/AudioOWP.cs index cc65e38d..0796b235 100644 --- a/ArcFormats/RealLive/AudioOWP.cs +++ b/ArcFormats/RealLive/AudioOWP.cs @@ -36,11 +36,10 @@ namespace GameRes.Formats.RealLive public override string Description { get { return "RealLive engine obfuscated OGG audio"; } } public override uint Signature { get { return 0x6A5E5E76; } } // 'OggS' ^ 0x39 - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - Stream input = new CryptoStream (file, new XorTransform (0x39), CryptoStreamMode.Read); - input = new SeekableStream (input); - return OggAudio.Instance.TryOpen (input); + var input = new XoredStream (file.AsStream, 0x39); + return new OggInput (input); } } } diff --git a/ArcFormats/RealLive/ImageG00.cs b/ArcFormats/RealLive/ImageG00.cs index f520ef11..53871a05 100644 --- a/ArcFormats/RealLive/ImageG00.cs +++ b/ArcFormats/RealLive/ImageG00.cs @@ -46,39 +46,36 @@ namespace GameRes.Formats.RealLive public override string Description { get { return "RealLive engine image format"; } } public override uint Signature { get { return 0; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - int type = stream.ReadByte(); + int type = file.ReadByte(); if (type > 2) return null; - using (var reader = new ArcView.Reader (stream)) + uint width = file.ReadUInt16(); + uint height = file.ReadUInt16(); + if (0 == width || width > 0x8000 || 0 == height || height > 0x8000) + return null; + if (2 == type) { - uint width = reader.ReadUInt16(); - uint height = reader.ReadUInt16(); - if (0 == width || width > 0x8000 || 0 == height || height > 0x8000) + int count = file.ReadInt32(); + if (count <= 0 || count > 0x100) return null; - if (2 == type) - { - int count = reader.ReadInt32(); - if (count <= 0 || count > 0x100) - return null; - } - else - { - uint length = reader.ReadUInt32(); - if (length + 5 != stream.Length) - return null; - } - return new G00MetaData { - Width = width, - Height = height, - BPP = 1 == type ? 8 : 24, - Type = type, - }; } + else + { + uint length = file.ReadUInt32(); + if (length + 5 != file.Length) + return null; + } + return new G00MetaData { + Width = width, + Height = height, + BPP = 1 == type ? 8 : 24, + Type = type, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { using (var reader = new G00Reader (stream, (G00MetaData)info)) { @@ -103,7 +100,7 @@ namespace GameRes.Formats.RealLive internal sealed class G00Reader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; int m_width; int m_height; @@ -113,17 +110,17 @@ namespace GameRes.Formats.RealLive public PixelFormat Format { get; private set; } public BitmapPalette Palette { get; private set; } - public G00Reader (Stream input, G00MetaData info) + public G00Reader (IBinaryStream input, G00MetaData info) { m_width = (int)info.Width; m_height = (int)info.Height; m_type = info.Type; - m_input = new ArcView.Reader (input); + m_input = input; } public void Unpack () { - m_input.BaseStream.Position = 5; + m_input.Position = 5; if (0 == m_type) UnpackV0(); else if (1 == m_type) @@ -165,7 +162,7 @@ namespace GameRes.Formats.RealLive tile.X = m_input.ReadInt32(); tile.Y = m_input.ReadInt32(); tiles.Add (tile); - m_input.BaseStream.Seek (0x10, SeekOrigin.Current); + m_input.Seek (0x10, SeekOrigin.Current); } using (var input = new MemoryStream (LzDecompress (m_input, 2, 1))) using (var reader = new BinaryReader (input)) @@ -211,7 +208,7 @@ namespace GameRes.Formats.RealLive } } - public static byte[] LzDecompress (BinaryReader input, int min_count, int bytes_pp) + public static byte[] LzDecompress (IBinaryStream input, int min_count, int bytes_pp) { int packed_size = input.ReadInt32() - 8; int output_size = input.ReadInt32(); @@ -223,7 +220,7 @@ namespace GameRes.Formats.RealLive bits >>= 1; if (1 == bits) { - bits = input.ReadByte() | 0x100; + bits = input.ReadUInt8() | 0x100; --packed_size; } if (0 != (bits & 1)) @@ -250,14 +247,8 @@ namespace GameRes.Formats.RealLive } #region IDisposable Members - bool _disposed = false; public void Dispose () { - if (!_disposed) - { - m_input.Dispose(); - _disposed = true; - } } #endregion } diff --git a/ArcFormats/RealLive/ImagePDT.cs b/ArcFormats/RealLive/ImagePDT.cs index 1639ae58..ec3ff60b 100644 --- a/ArcFormats/RealLive/ImagePDT.cs +++ b/ArcFormats/RealLive/ImagePDT.cs @@ -44,23 +44,21 @@ namespace GameRes.Formats.RealLive public override string Description { get { return "AVG32 engine image format"; } } public override uint Signature { get { return 0x31544450; } } // 'PDT1' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[32]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - if (!Binary.AsciiEqual (header, "PDT10\0")) + var header = stream.ReadHeader (32); + if (!header.AsciiEqual ("PDT10\0")) return null; return new PdtMetaData { - Width = LittleEndian.ToUInt32 (header, 0x0C), - Height = LittleEndian.ToUInt32 (header, 0x10), + Width = header.ToUInt32 (0x0C), + Height = header.ToUInt32 (0x10), BPP = 32, - AlphaOffset = LittleEndian.ToUInt32 (header, 0x1C), + AlphaOffset = header.ToUInt32 (0x1C), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { using (var reader = new PdtReader (stream, (PdtMetaData)info)) { @@ -77,7 +75,7 @@ namespace GameRes.Formats.RealLive internal sealed class PdtReader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; PdtMetaData m_info; @@ -85,9 +83,9 @@ namespace GameRes.Formats.RealLive public PixelFormat Format { get; private set; } public BitmapPalette Palette { get; private set; } - public PdtReader (Stream input, PdtMetaData info) + public PdtReader (IBinaryStream input, PdtMetaData info) { - m_input = new ArcView.Reader (input); + m_input = input; m_info = info; m_output = new byte[m_info.Width * m_info.Height * 4]; if (0 == m_info.AlphaOffset) @@ -98,11 +96,11 @@ namespace GameRes.Formats.RealLive public void Unpack () { - m_input.BaseStream.Position = 0x20; + m_input.Position = 0x20; Unpack24(); if (0 != m_info.AlphaOffset) { - m_input.BaseStream.Position = m_info.AlphaOffset; + m_input.Position = m_info.AlphaOffset; var alpha = Unpack8(); int src = 0; for (int i = 3; i < m_output.Length; i += 4) @@ -152,17 +150,17 @@ namespace GameRes.Formats.RealLive mask >>= 1; if (0 == mask) { - bits = m_input.ReadByte(); + bits = m_input.ReadUInt8(); mask = 0x80; } if (0 != (bits & mask)) { - output[dst++] = m_input.ReadByte(); + output[dst++] = m_input.ReadUInt8(); } else { - int count = 2 + m_input.ReadByte(); - int offset = 1 + m_input.ReadByte(); + int count = 2 + m_input.ReadUInt8(); + int offset = 1 + m_input.ReadUInt8(); Binary.CopyOverlapped (output, dst-offset, dst, count); dst += count; } @@ -171,14 +169,8 @@ namespace GameRes.Formats.RealLive } #region IDisposable Members - bool _disposed = false; public void Dispose () { - if (!_disposed) - { - m_input.Dispose(); - _disposed = true; - } } #endregion } diff --git a/ArcFormats/Resources/Formats.dat b/ArcFormats/Resources/Formats.dat index 08f64516a379457d7bd5cad2191d957f942a6bd0..b6ef94e5e69f1ce56275b24a49ec423390717303 100644 GIT binary patch delta 236663 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�WV(lvMei!PiN`%-S5*C0< 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 delta 236155 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%0A;Yc$dae+J0^Mkn*Xkoh*sb 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 G%q6Kv#}2;$ diff --git a/ArcFormats/RiddleSoft/ArcPAC.cs b/ArcFormats/RiddleSoft/ArcPAC.cs index 3cc1c673..026eaa1f 100644 --- a/ArcFormats/RiddleSoft/ArcPAC.cs +++ b/ArcFormats/RiddleSoft/ArcPAC.cs @@ -93,7 +93,7 @@ namespace GameRes.Formats.Riddle { var reader = new CmpReader (input, (int)entry.Size, unpacked_size); reader.Unpack(); - return new MemoryStream (reader.Data); + return new BinMemoryStream (reader.Data, entry.Name); } } } diff --git a/ArcFormats/RiddleSoft/ImageGCP.cs b/ArcFormats/RiddleSoft/ImageGCP.cs index 2298b5e3..29d830e1 100644 --- a/ArcFormats/RiddleSoft/ImageGCP.cs +++ b/ArcFormats/RiddleSoft/ImageGCP.cs @@ -53,16 +53,14 @@ namespace GameRes.Formats.Riddle throw new NotImplementedException ("GcpFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[12]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - int data_size = LittleEndian.ToInt32 (header, 4); - int pack_size = LittleEndian.ToInt32 (header, 8); + var header = stream.ReadHeader (12); + int data_size = header.ToInt32 (4); + int pack_size = header.ToInt32 (8); if (data_size < 54) return null; - var reader = new CmpReader (stream, pack_size, 0x22); // BMP header + var reader = new CmpReader (stream.AsStream, pack_size, 0x22); // BMP header reader.Unpack(); var bmp = reader.Data; if (bmp[0] != 'B' || bmp[1] != 'M') @@ -80,16 +78,13 @@ namespace GameRes.Formats.Riddle }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as GcpMetaData; - if (null == meta) - throw new ArgumentException ("GcpFormat.Read should be supplied with GcpMetaData", "info"); - + var meta = (GcpMetaData)info; stream.Position = 12; - var reader = new CmpReader (stream, meta.PackedSize, meta.DataSize); + var reader = new CmpReader (stream.AsStream, meta.PackedSize, meta.DataSize); reader.Unpack(); - using (var bmp = new MemoryStream (reader.Data, false)) + using (var bmp = new MemoryStream (reader.Data)) { var decoder = new BmpBitmapDecoder (bmp, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); diff --git a/ArcFormats/Risa/ImageSYG.cs b/ArcFormats/Risa/ImageSYG.cs index d57d7b2c..ac65de79 100644 --- a/ArcFormats/Risa/ImageSYG.cs +++ b/ArcFormats/Risa/ImageSYG.cs @@ -42,22 +42,20 @@ namespace GameRes.Formats.WestVision public override string Description { get { return "Risa game platform system image"; } } public override uint Signature { get { return 0x47595324; } } // '$SYG' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x20]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - uint alpha_offset = LittleEndian.ToUInt32 (header, 0x1C); + var header = stream.ReadHeader (0x20); + uint alpha_offset = header.ToUInt32 (0x1C); return new SygMetaData { - Width = LittleEndian.ToUInt32 (header, 0x10), - Height = LittleEndian.ToUInt32 (header, 0x14), + Width = header.ToUInt32 (0x10), + Height = header.ToUInt32 (0x14), BPP = 0 == alpha_offset ? 24 : 32, AlphaOffset = alpha_offset, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (SygMetaData)info; int pixel_count = (int)meta.Width * (int)meta.Height; diff --git a/ArcFormats/SHSystem/ArcHXP.cs b/ArcFormats/SHSystem/ArcHXP.cs index 910cdd13..175dccbf 100644 --- a/ArcFormats/SHSystem/ArcHXP.cs +++ b/ArcFormats/SHSystem/ArcHXP.cs @@ -129,7 +129,7 @@ namespace GameRes.Formats.SHSystem using (var reader = new ShsCompression (input)) { reader.Unpack (data); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } } diff --git a/ArcFormats/Sas5/ArcSec5.cs b/ArcFormats/Sas5/ArcSec5.cs index 38a6dcde..c2c9b3ef 100644 --- a/ArcFormats/Sas5/ArcSec5.cs +++ b/ArcFormats/Sas5/ArcSec5.cs @@ -73,7 +73,7 @@ namespace GameRes.Formats.Sas5 var code = new byte[entry.Size]; arc.File.View.Read (entry.Offset, code, 0, entry.Size); DecryptCodeSection (code); - return new MemoryStream (code); + return new BinMemoryStream (code, entry.Name); } static void DecryptCodeSection (byte[] code) diff --git a/ArcFormats/Sas5/ImageIAR.cs b/ArcFormats/Sas5/ImageIAR.cs index fcecf77b..1496bf51 100644 --- a/ArcFormats/Sas5/ImageIAR.cs +++ b/ArcFormats/Sas5/ImageIAR.cs @@ -65,32 +65,27 @@ namespace GameRes.Formats.Sas5 Extensions = new string[] { "" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x28]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - if (!Binary.AsciiEqual (header, 4, "SAS5")) + var header = stream.ReadHeader (0x28); + if (!header.AsciiEqual (4, "SAS5")) return null; return new IarMetaData { - Width = LittleEndian.ToUInt32 (header, 0x08), - Height = LittleEndian.ToUInt32 (header, 0x0C), - OffsetX = -LittleEndian.ToInt32 (header, 0x10), - OffsetY = -LittleEndian.ToInt32 (header, 0x14), - BPP = LittleEndian.ToInt32 (header, 0x18), - Stride = LittleEndian.ToInt32 (header, 0x1C), - PaletteSize = LittleEndian.ToInt32 (header, 0x20), - ImageSize = LittleEndian.ToInt32 (header, 0x24), + Width = header.ToUInt32 (0x08), + Height = header.ToUInt32 (0x0C), + OffsetX = -header.ToInt32 (0x10), + OffsetY = -header.ToInt32 (0x14), + BPP = header.ToInt32 (0x18), + Stride = header.ToInt32 (0x1C), + PaletteSize = header.ToInt32 (0x20), + ImageSize = header.ToInt32 (0x24), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as IarMetaData; - if (null == meta) - throw new ArgumentException ("IarFormat.Read should be supplied with IarMetaData", "info"); - + var meta = (IarMetaData)info; PixelFormat format; if (32 == meta.BPP) format = PixelFormats.Bgra32; @@ -104,9 +99,8 @@ namespace GameRes.Formats.Sas5 stream.Position = 0x28; BitmapPalette palette = null; if (meta.PaletteSize > 0) - palette = ReadPalette (stream, meta.PaletteSize); - var pixels = new byte[meta.ImageSize]; - stream.Read (pixels, 0, pixels.Length); + palette = ReadPalette (stream.AsStream, meta.PaletteSize); + var pixels = stream.ReadBytes (meta.ImageSize); return ImageData.Create (info, format, palette, pixels, meta.Stride); } diff --git a/ArcFormats/ScenePlayer/AudioPMW.cs b/ArcFormats/ScenePlayer/AudioPMW.cs index 7f391204..3b75ed13 100644 --- a/ArcFormats/ScenePlayer/AudioPMW.cs +++ b/ArcFormats/ScenePlayer/AudioPMW.cs @@ -37,13 +37,13 @@ namespace GameRes.Formats.ScenePlayer public override uint Signature { get { return 0; } } public override bool CanWrite { get { return true; } } - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { int first = file.ReadByte(); if ((first ^ 0x21) != 0x78) // doesn't look like zlib stream return null; file.Position = 0; - using (var input = new XoredStream (file, 0x21, true)) + using (var input = new XoredStream (file.AsStream, 0x21, true)) using (var zstream = new ZLibStream (input, CompressionMode.Decompress)) { SoundInput sound = null; diff --git a/ArcFormats/ScenePlayer/ImagePMP.cs b/ArcFormats/ScenePlayer/ImagePMP.cs index 6b15cc71..760a1eca 100644 --- a/ArcFormats/ScenePlayer/ImagePMP.cs +++ b/ArcFormats/ScenePlayer/ImagePMP.cs @@ -46,23 +46,25 @@ namespace GameRes.Formats.ScenePlayer base.Write (zstream, image); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { int first = stream.ReadByte() ^ 0x21; if (first != 0x78) // doesn't look like zlib stream return null; stream.Position = 0; - using (var input = new XoredStream (stream, 0x21, true)) + using (var input = new XoredStream (stream.AsStream, 0x21, true)) using (var zstream = new ZLibStream (input, CompressionMode.Decompress)) - return base.ReadMetaData (zstream); + using (var bmp = new BinaryStream (zstream, stream.Name)) + return base.ReadMetaData (bmp); } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - using (var input = new XoredStream (stream, 0x21, true)) + using (var input = new XoredStream (stream.AsStream, 0x21, true)) using (var zstream = new ZLibStream (input, CompressionMode.Decompress)) - return base.Read (zstream, info); + using (var bmp = new BinaryStream (zstream, stream.Name)) + return base.Read (bmp, info); } } } diff --git a/ArcFormats/ScrPlayer/ImageI.cs b/ArcFormats/ScrPlayer/ImageI.cs index b09541f4..94c2adeb 100644 --- a/ArcFormats/ScrPlayer/ImageI.cs +++ b/ArcFormats/ScrPlayer/ImageI.cs @@ -43,22 +43,20 @@ namespace GameRes.Formats.ScrPlayer Extensions = new string[] { "i" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x20]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x20); return new ImageMetaData { - Width = LittleEndian.ToUInt16 (header, 0xC), - Height = LittleEndian.ToUInt16 (header, 0xE), - BPP = LittleEndian.ToUInt16 (header, 0x10), + Width = header.ToUInt16 (0xC), + Height = header.ToUInt16 (0xE), + BPP = header.ToUInt16 (0x10), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - using (var reader = new Img2Reader (stream, info)) + using (var reader = new Img2Reader (stream.AsStream, info)) { reader.Unpack(); return ImageData.Create (info, reader.Format, null, reader.Data); diff --git a/ArcFormats/ShiinaRio/ArcWARC.cs b/ArcFormats/ShiinaRio/ArcWARC.cs index e65882b1..e2b3479d 100644 --- a/ArcFormats/ShiinaRio/ArcWARC.cs +++ b/ArcFormats/ShiinaRio/ArcWARC.cs @@ -188,7 +188,7 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒 if (warc.Decoder.ExtraCrypt != null) warc.Decoder.ExtraCrypt.Decrypt (unpacked, 0, (uint)unpacked.Length, 0x204); } - return new MemoryStream (unpacked); + return new BinMemoryStream (unpacked, entry.Name); } delegate void UnpackMethod (byte[] input, byte[] output); diff --git a/ArcFormats/ShiinaRio/AudioOGV.cs b/ArcFormats/ShiinaRio/AudioOGV.cs index 79899712..6c95cab2 100644 --- a/ArcFormats/ShiinaRio/AudioOGV.cs +++ b/ArcFormats/ShiinaRio/AudioOGV.cs @@ -36,7 +36,7 @@ namespace GameRes.Formats.ShiinaRio public override string Description { get { return "ShiinaRio audio format (Ogg/Vorbis)"; } } public override uint Signature { get { return 0x0056474f; } } // 'OGV' - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { file.Position = 0xc; var header = new byte[8]; @@ -51,7 +51,7 @@ namespace GameRes.Formats.ShiinaRio if (!Binary.AsciiEqual (header, 0, "data")) return null; - var input = new StreamRegion (file, file.Position); + var input = new StreamRegion (file.AsStream, file.Position); return new OggInput (input); // input is left undisposed in case of exception. } diff --git a/ArcFormats/ShiinaRio/AudioPAD.cs b/ArcFormats/ShiinaRio/AudioPAD.cs index b18c8e93..86eefc6c 100644 --- a/ArcFormats/ShiinaRio/AudioPAD.cs +++ b/ArcFormats/ShiinaRio/AudioPAD.cs @@ -37,11 +37,9 @@ namespace GameRes.Formats.ShiinaRio public override string Description { get { return "ShiinaRio compressed audio format"; } } public override uint Signature { get { return 0x444150; } } // 'PAD' - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - var wav_header = new byte[0x2c]; - if (0x2c != file.Read (wav_header, 0, 0x2c)) - return null; + var wav_header = file.ReadHeader (0x2c).ToArray(); int pcm_size = LittleEndian.ToInt32 (wav_header, 0x28); int channels = LittleEndian.ToUInt16 (wav_header, 0x16); wav_header[0] = (byte)'R'; @@ -50,7 +48,7 @@ namespace GameRes.Formats.ShiinaRio wav_header[3] = (byte)'F'; LittleEndian.Pack (pcm_size+0x24, wav_header, 4); - var decoder = new PadDecoder (file, pcm_size, channels); + var decoder = new PadDecoder (file.AsStream, pcm_size, channels); decoder.Unpack(); var data = new MemoryStream (decoder.Data, 0, pcm_size); var wav = new PrefixStream (wav_header, data); diff --git a/ArcFormats/ShiinaRio/ImageMI4.cs b/ArcFormats/ShiinaRio/ImageMI4.cs index 039eb77a..a8cb0fdf 100644 --- a/ArcFormats/ShiinaRio/ImageMI4.cs +++ b/ArcFormats/ShiinaRio/ImageMI4.cs @@ -37,23 +37,20 @@ namespace GameRes.Formats.ShiinaRio public override string Description { get { return "ShiinaRio image format"; } } public override uint Signature { get { return 0x3449414D; } } // 'MAI4' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - stream.Seek (8, SeekOrigin.Current); - using (var input = new ArcView.Reader (stream)) + file.Position = 8; + uint width = file.ReadUInt32(); + uint height = file.ReadUInt32(); + return new ImageMetaData { - uint width = input.ReadUInt32(); - uint height = input.ReadUInt32(); - return new ImageMetaData - { - Width = width, - Height = height, - BPP = 24, - }; - } + Width = width, + Height = height, + BPP = 24, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { stream.Position = 0x10; using (var reader = new Reader (stream, (int)info.Width, (int)info.Height)) @@ -70,15 +67,15 @@ namespace GameRes.Formats.ShiinaRio internal sealed class Reader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; int m_stride; public byte[] Data { get { return m_output; } } - public Reader (Stream file, int width, int height) + public Reader (IBinaryStream file, int width, int height) { - m_input = new ArcView.Reader (file); + m_input = file; m_stride = width * 3; m_output = new byte[m_stride*height]; } @@ -125,9 +122,9 @@ namespace GameRes.Formats.ShiinaRio { if (GetBit() != 0) { - b = m_input.ReadByte(); - g = m_input.ReadByte(); - r = m_input.ReadByte(); + b = m_input.ReadUInt8(); + g = m_input.ReadUInt8(); + r = m_input.ReadUInt8(); } else if (GetBit() != 0) { @@ -203,14 +200,8 @@ namespace GameRes.Formats.ShiinaRio } #region IDisposable Members - bool disposed = false; public void Dispose () { - if (!disposed) - { - m_input.Dispose (); - disposed = true; - } GC.SuppressFinalize (this); } #endregion diff --git a/ArcFormats/ShiinaRio/ImageS25.cs b/ArcFormats/ShiinaRio/ImageS25.cs index 1bf00f69..04e3b190 100644 --- a/ArcFormats/ShiinaRio/ImageS25.cs +++ b/ArcFormats/ShiinaRio/ImageS25.cs @@ -50,33 +50,30 @@ namespace GameRes.Formats.ShiinaRio // in current implementation, only the first frame is returned. // per-frame access is provided by S25Opener class. - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var input = new ArcView.Reader (stream)) - { - input.ReadUInt32(); - int count = input.ReadInt32(); - if (count < 0 || count > 0xfffff) - return null; - uint first_offset = 0; - for (int i = 0; i < count && 0 == first_offset; ++i) - first_offset = input.ReadUInt32(); - if (0 == first_offset) - return null; - input.BaseStream.Position = first_offset; - var info = new S25MetaData(); - info.Width = input.ReadUInt32(); - info.Height = input.ReadUInt32(); - info.OffsetX = input.ReadInt32(); - info.OffsetY = input.ReadInt32(); - info.FirstOffset = first_offset+0x14; - info.Incremental = 0 != (input.ReadUInt32() & 0x80000000u); - info.BPP = 32; - return info; - } + file.Position = 4; + int count = file.ReadInt32(); + if (count < 0 || count > 0xfffff) + return null; + uint first_offset = 0; + for (int i = 0; i < count && 0 == first_offset; ++i) + first_offset = file.ReadUInt32(); + if (0 == first_offset) + return null; + file.Position = first_offset; + var info = new S25MetaData(); + info.Width = file.ReadUInt32(); + info.Height = file.ReadUInt32(); + info.OffsetX = file.ReadInt32(); + info.OffsetY = file.ReadInt32(); + info.FirstOffset = first_offset+0x14; + info.Incremental = 0 != (file.ReadUInt32() & 0x80000000u); + info.BPP = 32; + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { using (var reader = new Reader (stream, (S25MetaData)info)) { @@ -90,9 +87,9 @@ namespace GameRes.Formats.ShiinaRio throw new NotImplementedException ("S25Format.Write not implemented"); } - internal class Reader : IDisposable + internal sealed class Reader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; int m_width; int m_height; uint m_origin; @@ -101,19 +98,19 @@ namespace GameRes.Formats.ShiinaRio public byte[] Data { get { return m_output; } } - public Reader (Stream file, S25MetaData info) + public Reader (IBinaryStream file, S25MetaData info) { m_width = (int)info.Width; m_height = (int)info.Height; m_output = new byte[m_width * m_height * 4]; - m_input = new ArcView.Reader (file); + m_input = file; m_origin = info.FirstOffset; m_incremental = info.Incremental; } public byte[] Unpack () { - m_input.BaseStream.Position = m_origin; + m_input.Position = m_origin; if (m_incremental) return UnpackIncremental(); var rows = new uint[m_height]; @@ -124,7 +121,7 @@ namespace GameRes.Formats.ShiinaRio for (int y = 0; y < m_height && dst < m_output.Length; ++y) { uint row_pos = rows[y]; - m_input.BaseStream.Position = row_pos; + m_input.Position = row_pos; int row_length = m_input.ReadUInt16(); row_pos += 2; if (0 != (row_pos & 1)) @@ -142,7 +139,7 @@ namespace GameRes.Formats.ShiinaRio void UpdateRepeatCount (Dictionary rows_count) { - m_input.BaseStream.Position = 4; + m_input.Position = 4; int count = m_input.ReadInt32(); var frames = new List (count); for (int i = 0; i < count; ++i) @@ -155,9 +152,9 @@ namespace GameRes.Formats.ShiinaRio { if (offset+0x14 == m_origin) continue; - m_input.BaseStream.Position = offset+4; + m_input.Position = offset+4; int height = m_input.ReadInt32(); - m_input.BaseStream.Position = offset+0x14; + m_input.Position = offset+0x14; for (int i = 0; i < height; ++i) { var row_offset = m_input.ReadUInt32(); @@ -286,7 +283,7 @@ namespace GameRes.Formats.ShiinaRio byte[] ReadLine (uint offset, int repeat) { - m_input.BaseStream.Position = offset; + m_input.Position = offset; int row_length = m_input.ReadUInt16(); if (0 != (offset & 1)) { @@ -355,23 +352,10 @@ namespace GameRes.Formats.ShiinaRio } #region IDisposable Members - bool disposed = false; - public void Dispose () { - Dispose (true); GC.SuppressFinalize (this); } - - protected virtual void Dispose (bool disposing) - { - if (!disposed) - { - if (disposing) - m_input.Dispose(); - disposed = true; - } - } #endregion } } diff --git a/ArcFormats/Silky/ArcIFL.cs b/ArcFormats/Silky/ArcIFL.cs index 45801db0..a7d4f5b5 100644 --- a/ArcFormats/Silky/ArcIFL.cs +++ b/ArcFormats/Silky/ArcIFL.cs @@ -78,7 +78,7 @@ namespace GameRes.Formats.Silky { lzss.FrameFill = 0x20; lzss.Unpack(); - return new MemoryStream (lzss.Data); + return new BinMemoryStream (lzss.Data, entry.Name); } } } diff --git a/ArcFormats/Silky/ImageAKB.cs b/ArcFormats/Silky/ImageAKB.cs index d1fab0a1..87650817 100644 --- a/ArcFormats/Silky/ImageAKB.cs +++ b/ArcFormats/Silky/ImageAKB.cs @@ -46,30 +46,27 @@ namespace GameRes.Formats.Silky public override string Description { get { return "AI6WIN engine image format"; } } public override uint Signature { get { return 0x20424B41; } } // 'AKB ' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var reader = new ArcView.Reader (stream)) - { - reader.ReadInt32(); - var info = new AkbMetaData(); - info.Width = reader.ReadUInt16(); - info.Height = reader.ReadUInt16(); - int flags = reader.ReadInt32() & 0xFFFF; - info.BPP = 0 == flags ? 32 : 24; - info.Background = reader.ReadBytes (4); - info.OffsetX = reader.ReadInt32(); - info.OffsetY = reader.ReadInt32(); - info.InnerWidth = reader.ReadInt32() - info.OffsetX; - info.InnerHeight = reader.ReadInt32() - info.OffsetY; - if (info.InnerWidth > info.Width || info.InnerHeight > info.Height) - return null; - return info; - } + file.ReadInt32(); + var info = new AkbMetaData(); + info.Width = file.ReadUInt16(); + info.Height = file.ReadUInt16(); + int flags = file.ReadInt32() & 0xFFFF; + info.BPP = 0 == flags ? 32 : 24; + info.Background = file.ReadBytes (4); + info.OffsetX = file.ReadInt32(); + info.OffsetY = file.ReadInt32(); + info.InnerWidth = file.ReadInt32() - info.OffsetX; + info.InnerHeight = file.ReadInt32() - info.OffsetY; + if (info.InnerWidth > info.Width || info.InnerHeight > info.Height) + return null; + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { - var reader = new AkbReader (stream, (AkbMetaData)info); + var reader = new AkbReader (file.AsStream, (AkbMetaData)info); var image = reader.Unpack(); return ImageData.Create (info, reader.Format, null, image, reader.Stride); } diff --git a/ArcFormats/Silky/ImageGRD.cs b/ArcFormats/Silky/ImageGRD.cs index 05066aca..a902cd2c 100644 --- a/ArcFormats/Silky/ImageGRD.cs +++ b/ArcFormats/Silky/ImageGRD.cs @@ -52,12 +52,12 @@ namespace GameRes.Formats.Silky throw new NotImplementedException ("GrdFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { stream.Seek (4, SeekOrigin.Current); - int data_size = stream.ReadByte() | stream.ReadByte() << 8 | stream.ReadByte() << 16 | stream.ReadByte() << 24; + int data_size = stream.ReadInt32(); stream.Seek (4, SeekOrigin.Current); - using (var reader = new Reader (stream, 0x22)) // BMP header + using (var reader = new Reader (stream.AsStream, 0x22)) // BMP header { reader.Unpack(); var bmp = reader.Data; @@ -76,18 +76,15 @@ namespace GameRes.Formats.Silky } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as GrdMetaData; - if (null == meta) - throw new ArgumentException ("GrdFormat.Read should be supplied with GrdMetaData", "info"); - + var meta = (GrdMetaData)info; stream.Position = 12; - using (var reader = new Reader (stream, meta.DataSize)) + using (var reader = new Reader (stream.AsStream, meta.DataSize)) { reader.Unpack(); byte[] pixels = reader.Data; - using (var bmp = new MemoryStream (reader.Data, false)) + using (var bmp = new MemoryStream (reader.Data)) { var decoder = new BmpBitmapDecoder (bmp, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); diff --git a/ArcFormats/Silky/ImageIGF.cs b/ArcFormats/Silky/ImageIGF.cs index 1d806b50..09f07d54 100644 --- a/ArcFormats/Silky/ImageIGF.cs +++ b/ArcFormats/Silky/ImageIGF.cs @@ -46,15 +46,13 @@ namespace GameRes.Formats.Silky public override string Description { get { return "Silky's image format"; } } public override uint Signature { get { return 0x5355455Au; } } // 'ZEUS' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x14]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - uint width = LittleEndian.ToUInt32 (header, 4); - uint height = LittleEndian.ToUInt32 (header, 8); - int unpacked_size = LittleEndian.ToInt32 (header, 0xC); - int flags = LittleEndian.ToInt32 (header, 0x10); + var header = stream.ReadHeader (0x14); + uint width = header.ToUInt32 (4); + uint height = header.ToUInt32 (8); + int unpacked_size = header.ToInt32 (0xC); + int flags = header.ToInt32 (0x10); int bpp = flags & 0xff; if (0 == bpp) bpp = 32; @@ -68,11 +66,9 @@ namespace GameRes.Formats.Silky }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as IgfMetaData; - if (null == meta) - throw new ArgumentException ("IgfFormat.Read should be supplied with IgfMetaData", "info"); + var meta = (IgfMetaData)info as IgfMetaData; int stride = (int)info.Width*info.BPP/8; stream.Position = 0x14; @@ -80,7 +76,7 @@ namespace GameRes.Formats.Silky if (meta.IsPacked) { int in_size = (int)(stream.Length - 0x14); - using (var lzss = new LzssReader (stream, in_size, meta.UnpackedSize)) + using (var lzss = new LzssReader (stream.AsStream, in_size, meta.UnpackedSize)) { lzss.FrameFill = 0x20; lzss.Unpack(); diff --git a/ArcFormats/Silky/ImageMFG.cs b/ArcFormats/Silky/ImageMFG.cs index 12e7cf43..d0cbf3d6 100644 --- a/ArcFormats/Silky/ImageMFG.cs +++ b/ArcFormats/Silky/ImageMFG.cs @@ -58,49 +58,40 @@ namespace GameRes.Formats.Silky throw new NotImplementedException ("MfgFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var file = new ArcView.Reader (stream)) + file.Position = 3; + byte id = file.ReadUInt8(); + uint data_size = file.ReadUInt32(); + uint width = file.ReadUInt32(); + uint height = file.ReadUInt32(); + uint stride = file.ReadUInt32(); + if (stride < width) + throw new NotSupportedException(); + if (stride*height != data_size) + return null; + return new MfgMetaData { - stream.Seek (3, SeekOrigin.Current); - byte id = file.ReadByte(); - uint data_size = file.ReadUInt32(); - uint width = file.ReadUInt32(); - uint height = file.ReadUInt32(); - uint stride = file.ReadUInt32(); - if (stride < width) - throw new NotSupportedException(); - if (stride*height != data_size) - return null; - return new MfgMetaData - { - Width = width, - Height = height, - BPP = (int)(stride*8/width), - Type = id, - Stride = (int)stride, - }; - } + Width = width, + Height = height, + BPP = (int)(stride*8/width), + Type = id, + Stride = (int)stride, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { - var meta = info as MfgMetaData; - if (null == meta) - throw new ArgumentException ("MfgFormat.Read should be supplied with MfgMetaData", "info"); - - stream.Position = 0x14; + var meta = (MfgMetaData)info; + file.Position = 0x14; if ('_' != meta.Type) - using (var file = new ArcView.Reader (stream)) + for (uint i = 0; i < meta.Height; ++i) { - for (uint i = 0; i < meta.Height; ++i) - { - uint n = file.ReadUInt32(); - file.BaseStream.Seek (n*8, SeekOrigin.Current); - } + uint n = file.ReadUInt32(); + file.Seek (n*8, SeekOrigin.Current); } byte[] pixels = new byte[meta.Stride*info.Height]; - if (pixels.Length != stream.Read (pixels, 0, pixels.Length)) + if (pixels.Length != file.Read (pixels, 0, pixels.Length)) throw new InvalidFormatException ("Unexpected end of file"); PixelFormat format; if (24 == meta.BPP) diff --git a/ArcFormats/Silky/ImageMSK.cs b/ArcFormats/Silky/ImageMSK.cs index 39328a23..bc74b0e5 100644 --- a/ArcFormats/Silky/ImageMSK.cs +++ b/ArcFormats/Silky/ImageMSK.cs @@ -43,24 +43,22 @@ namespace GameRes.Formats.Silky Extensions = new string[] { "msk" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[12]; - if (12 != stream.Read (header, 0, 12)) - return null; + var header = stream.ReadHeader (12); return new ImageMetaData { - Width = LittleEndian.ToUInt16 (header, 8), - Height = LittleEndian.ToUInt16 (header, 10), - OffsetX = LittleEndian.ToInt16 (header, 4), - OffsetY = LittleEndian.ToInt16 (header, 6), + Width = header.ToUInt16 (8), + Height = header.ToUInt16 (10), + OffsetX = header.ToInt16 (4), + OffsetY = header.ToInt16 (6), BPP = 8, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - using (var reader = new RmskReader (stream, info)) + using (var reader = new RmskReader (stream.AsStream, info)) { reader.Unpack(); return ImageData.CreateFlipped (info, PixelFormats.Gray8, null, reader.Data, (int)info.Width); diff --git a/ArcFormats/Silky/ImageZIT.cs b/ArcFormats/Silky/ImageZIT.cs index 613b5f69..1e324aa2 100644 --- a/ArcFormats/Silky/ImageZIT.cs +++ b/ArcFormats/Silky/ImageZIT.cs @@ -49,22 +49,20 @@ namespace GameRes.Formats.Silky Signatures = new uint[] { 0x1803545A, 0x2084545A, 0x8803545A }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x10]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x10); return new ZitMetaData { - Type = LittleEndian.ToUInt16 (header, 2), - Width = LittleEndian.ToUInt16 (header, 8), - Height = LittleEndian.ToUInt16 (header, 10), + Type = header.ToUInt16 (2), + Width = header.ToUInt16 (8), + Height = header.ToUInt16 (10), BPP = 32, - Colors = LittleEndian.ToUInt16 (header, 4), + Colors = header.ToUInt16 (4), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { using (var reader = new ZitReader (stream, (ZitMetaData)info)) { @@ -81,7 +79,7 @@ namespace GameRes.Formats.Silky internal class ZitReader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; int m_width; int m_height; @@ -90,9 +88,9 @@ namespace GameRes.Formats.Silky public byte[] Data { get { return m_output; } } - public ZitReader (Stream input, ZitMetaData info) + public ZitReader (IBinaryStream input, ZitMetaData info) { - m_input = new ArcView.Reader (input); + m_input = input; m_width = (int)info.Width; m_height = (int)info.Height; m_type = info.Type; @@ -102,7 +100,7 @@ namespace GameRes.Formats.Silky public void Unpack () { - m_input.BaseStream.Position = 0x10; + m_input.Position = 0x10; switch (m_type) { case 0x1803: Unpack1(); break; @@ -118,9 +116,9 @@ namespace GameRes.Formats.Silky int dst = 0; while (dst < m_output.Length) { - byte b = m_input.ReadByte(); - byte g = m_input.ReadByte(); - byte r = m_input.ReadByte(); + byte b = m_input.ReadUInt8(); + byte g = m_input.ReadUInt8(); + byte r = m_input.ReadUInt8(); if (b != 0 || g != 0xFF || r != 0) { m_output[dst++] = b; @@ -167,14 +165,8 @@ namespace GameRes.Formats.Silky } #region IDisposable Members - bool _disposed = false; public void Dispose () { - if (!_disposed) - { - m_input.Dispose(); - _disposed = true; - } } #endregion } diff --git a/ArcFormats/Slg/AudioVOI.cs b/ArcFormats/Slg/AudioVOI.cs index 41b60a18..fc1426b5 100644 --- a/ArcFormats/Slg/AudioVOI.cs +++ b/ArcFormats/Slg/AudioVOI.cs @@ -35,7 +35,7 @@ namespace GameRes.Formats.Slg public override string Description { get { return "SLG system obfuscated Ogg audio"; } } public override uint Signature { get { return 0; } } // 'OggS' - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { file.Position = 0x1E; int offset = file.ReadByte(); @@ -45,7 +45,7 @@ namespace GameRes.Formats.Slg if (!(file.ReadByte() == 'O' && file.ReadByte() == 'g' && file.ReadByte() == 'g' && file.ReadByte() == 'S')) return null; - return new OggInput (new StreamRegion (file, 0x20+offset)); + return new OggInput (new StreamRegion (file.AsStream, 0x20+offset)); } } } diff --git a/ArcFormats/Slg/ImageALB.cs b/ArcFormats/Slg/ImageALB.cs index f6b00766..d50a80c9 100644 --- a/ArcFormats/Slg/ImageALB.cs +++ b/ArcFormats/Slg/ImageALB.cs @@ -47,24 +47,23 @@ namespace GameRes.Formats.Slg static readonly Lazy Dds = new Lazy (() => ImageFormat.FindByTag ("DDS")); - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x10]; - if (0x10 != stream.Read (header, 0, 0x10)) - return null; - int unpacked_size = LittleEndian.ToInt32 (header, 8); + var header = stream.ReadHeader (0x10); + int unpacked_size = header.ToInt32 (8); using (var alb = new AlbStream (stream, unpacked_size)) - using (var file = new SeekableStream (alb)) + using (var s = new SeekableStream (alb)) + using (var file = new BinaryStream (s, stream.Name)) { - uint signature = FormatCatalog.ReadSignature (file); - file.Position = 0; + uint signature = file.Signature; ImageFormat format; - if (ImageFormat.Png.Signature == signature) + if (Png.Signature == signature) format = ImageFormat.Png; else if (Dds.Value.Signature == signature) format = Dds.Value; else format = ImageFormat.Jpeg; + file.Position = 0; var info = format.ReadMetaData (file); if (null == info) return null; @@ -82,12 +81,13 @@ namespace GameRes.Formats.Slg } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (AlbMetaData)info; stream.Position = 0x10; using (var alb = new AlbStream (stream, meta.UnpackedSize)) - using (var file = new SeekableStream (alb)) + using (var s = new SeekableStream (alb)) + using (var file = new BinaryStream (s, stream.Name)) return meta.Format.Read (file, meta.Info); } @@ -99,7 +99,7 @@ namespace GameRes.Formats.Slg internal class AlbStream : Stream { - BinaryReader m_input; + IBinaryStream m_input; int m_unpacked_size; IEnumerator m_iterator; byte[] m_output; @@ -110,9 +110,9 @@ namespace GameRes.Formats.Slg public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return false; } } - public AlbStream (Stream source, int unpacked_size) + public AlbStream (IBinaryStream source, int unpacked_size) { - m_input = new ArcView.Reader (source); + m_input = source; m_unpacked_size = unpacked_size; m_iterator = ReadSeq(); } @@ -132,7 +132,7 @@ namespace GameRes.Formats.Slg IEnumerator ReadSeq () { var stack = new byte[256]; - while (m_input.PeekChar() != -1) + while (m_input.PeekByte() != -1) { int packed_size = UnpackDict(); int src = 0; @@ -146,7 +146,7 @@ namespace GameRes.Formats.Slg } else if (src < packed_size) { - s = m_input.ReadByte(); + s = m_input.ReadUInt8(); src++; } else @@ -175,16 +175,16 @@ namespace GameRes.Formats.Slg throw new InvalidFormatException(); int table_size = m_input.ReadUInt16(); int packed_size = m_input.ReadUInt16(); - bool is_packed = m_input.ReadByte() != 0; - byte marker = m_input.ReadByte(); + bool is_packed = m_input.ReadUInt8() != 0; + byte marker = m_input.ReadUInt8(); if (is_packed) { for (int i = 0; i < 256; ) { - byte b = m_input.ReadByte(); + byte b = m_input.ReadUInt8(); if (marker == b) { - int count = m_input.ReadByte(); + int count = m_input.ReadUInt8(); for (int j = 0; j < count; ++j) { m_dict[i,0] = (byte)i; @@ -195,7 +195,7 @@ namespace GameRes.Formats.Slg else { m_dict[i,0] = b; - m_dict[i,1] = m_input.ReadByte(); + m_dict[i,1] = m_input.ReadUInt8(); ++i; } } @@ -204,8 +204,8 @@ namespace GameRes.Formats.Slg { for (int i = 0; i < 256; ++i) { - m_dict[i,0] = m_input.ReadByte(); - m_dict[i,1] = m_input.ReadByte(); + m_dict[i,0] = m_input.ReadUInt8(); + m_dict[i,1] = m_input.ReadUInt8(); } } return packed_size; @@ -252,7 +252,6 @@ namespace GameRes.Formats.Slg { if (disposing) { - m_input.Dispose(); m_iterator.Dispose(); } _alb_disposed = true; diff --git a/ArcFormats/Slg/ImageTIG.cs b/ArcFormats/Slg/ImageTIG.cs index c5c7d3d8..f952830c 100644 --- a/ArcFormats/Slg/ImageTIG.cs +++ b/ArcFormats/Slg/ImageTIG.cs @@ -37,17 +37,19 @@ namespace GameRes.Formats.Slg public override uint Signature { get { return 0x7CF3C28B; } } public override bool CanWrite { get { return false; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - using (var proxy = new ProxyStream (stream, true)) - using (var input = new CryptoStream (proxy, new TigTransform(), CryptoStreamMode.Read)) + using (var proxy = new ProxyStream (stream.AsStream, true)) + using (var crypt = new CryptoStream (proxy, new TigTransform(), CryptoStreamMode.Read)) + using (var input = new BinaryStream (crypt, stream.Name)) return base.ReadMetaData (input); } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - using (var proxy = new ProxyStream (stream, true)) - using (var input = new CryptoStream (proxy, new TigTransform(), CryptoStreamMode.Read)) + using (var proxy = new ProxyStream (stream.AsStream, true)) + using (var crypt = new CryptoStream (proxy, new TigTransform(), CryptoStreamMode.Read)) + using (var input = new BinaryStream (crypt, stream.Name)) return base.Read (input, info); } @@ -59,7 +61,7 @@ namespace GameRes.Formats.Slg internal sealed class TigTransform : ICryptoTransform { - const int BlockSize = 256; + const int BlockSize = 1; uint m_key; public bool CanReuseTransform { get { return true; } } diff --git a/ArcFormats/Softpal/ArcPAC.cs b/ArcFormats/Softpal/ArcPAC.cs index 7de7c6c3..e40d450b 100644 --- a/ArcFormats/Softpal/ArcPAC.cs +++ b/ArcFormats/Softpal/ArcPAC.cs @@ -107,7 +107,7 @@ namespace GameRes.Formats.Softpal } } } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } diff --git a/ArcFormats/Softpal/AudioBGM.cs b/ArcFormats/Softpal/AudioBGM.cs index 0b73772e..0431cc35 100644 --- a/ArcFormats/Softpal/AudioBGM.cs +++ b/ArcFormats/Softpal/AudioBGM.cs @@ -31,7 +31,7 @@ using GameRes.Utility; namespace GameRes.Formats.Softpal { [Export(typeof(AudioFormat))] - public class BgmAudio : OggAudio + public class BgmAudio : AudioFormat { public override string Tag { get { return "BGM/SOFTPAL"; } } public override string Description { get { return "Softpal BGM format (Ogg/Vorbis)"; } } @@ -42,14 +42,12 @@ namespace GameRes.Formats.Softpal Extensions = new string[] { "ogg" }; } - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - var header = new byte[0x10]; // header contains music loop timing - if (0x10 != file.Read (header, 0, 0x10)) + var header = file.ReadHeader (0x10); // header contains music loop timing + if (!header.AsciiEqual (0xC, "OggS")) return null; - if (!Binary.AsciiEqual (header, 0xC, "OggS")) - return null; - var input = new StreamRegion (file, 12); + var input = new StreamRegion (file.AsStream, 12); return new OggInput (input); // input is [intentionally] left undisposed in case of exception. } diff --git a/ArcFormats/Softpal/ImageBPIC.cs b/ArcFormats/Softpal/ImageBPIC.cs index 54be2259..2e9c221e 100644 --- a/ArcFormats/Softpal/ImageBPIC.cs +++ b/ArcFormats/Softpal/ImageBPIC.cs @@ -37,23 +37,21 @@ namespace GameRes.Formats.Softpal public override string Description { get { return "Softpal engine image format"; } } public override uint Signature { get { return 0x43495042; } } // 'BPIC' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x10]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - int pixel_size = LittleEndian.ToInt32 (header, 12); + var header = stream.ReadHeader (0x10); + int pixel_size = header.ToInt32 (12); if (pixel_size != 4 && pixel_size != 3 && pixel_size != 1) return null; return new ImageMetaData { - Width = LittleEndian.ToUInt32(header, 4), - Height = LittleEndian.ToUInt32(header, 8), + Width = header.ToUInt32 (4), + Height = header.ToUInt32 (8), BPP = pixel_size * 8, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { stream.Position = 0x10; int pixel_size = info.BPP/8; diff --git a/ArcFormats/Softpal/ImagePGD.cs b/ArcFormats/Softpal/ImagePGD.cs index 86f04c52..61d8b2ba 100644 --- a/ArcFormats/Softpal/ImagePGD.cs +++ b/ArcFormats/Softpal/ImagePGD.cs @@ -43,24 +43,22 @@ namespace GameRes.Formats.Softpal Extensions = new string[] { "pgd" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x20]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - if (!Binary.AsciiEqual (header, 0x1C, "11_C")) + var header = stream.ReadHeader (0x20); + if (!header.AsciiEqual (0x1C, "11_C")) return null; return new ImageMetaData { - Width = LittleEndian.ToUInt32 (header, 0x0C), - Height = LittleEndian.ToUInt32 (header, 0x10), - OffsetX = LittleEndian.ToInt32 (header, 4), - OffsetY = LittleEndian.ToInt32 (header, 8), + Width = header.ToUInt32 (0x0C), + Height = header.ToUInt32 (0x10), + OffsetX = header.ToInt32 (4), + OffsetY = header.ToInt32 (8), BPP = 32, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { using (var reader = new PgdReader (stream, 0x20)) { @@ -101,29 +99,27 @@ namespace GameRes.Formats.Softpal Extensions = new string[] { "pgd" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x24]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - if (!Binary.AsciiEqual (header, 0x18, "00_C")) + var header = stream.ReadHeader (0x24); + if (!header.AsciiEqual (0x18, "00_C")) return null; return new ImageMetaData { - Width = LittleEndian.ToUInt32 (header, 8), - Height = LittleEndian.ToUInt32 (header, 12), - OffsetX = LittleEndian.ToInt32 (header, 0), - OffsetY = LittleEndian.ToInt32 (header, 4), + Width = header.ToUInt32 (8), + Height = header.ToUInt32 (12), + OffsetX = header.ToInt32 (0), + OffsetY = header.ToInt32 (4), BPP = 32, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { using (var reader = new PgdReader (stream, 0x1C)) { var data = reader.Unpack00(); - using (var tga = new MemoryStream (data)) + using (var tga = new BinMemoryStream (data, stream.Name)) { var tga_info = Tga.ReadMetaData (tga); if (null == tga_info) @@ -153,20 +149,18 @@ namespace GameRes.Formats.Softpal Extensions = new string[] { "pgd" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x2A]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - int x = LittleEndian.ToInt32 (header, 0); - int y = LittleEndian.ToInt32 (header, 4); + var header = stream.ReadHeader (0x2A); + int x = header.ToInt32 (0); + int y = header.ToInt32 (4); if (Math.Abs (x) > 0x2000 || Math.Abs (y) > 0x2000) return null; - uint width = LittleEndian.ToUInt32 (header, 8); - uint height = LittleEndian.ToUInt32 (header, 12); + uint width = header.ToUInt32 (8); + uint height = header.ToUInt32 (12); if (0 == width || 0 == height - || width != LittleEndian.ToUInt16 (header, 0x24) - || height != LittleEndian.ToUInt16 (header, 0x26)) + || width != header.ToUInt16 (0x24) + || height != header.ToUInt16 (0x26)) return null; stream.Position = 0x18; var tga_info = base.ReadMetaData (stream); @@ -177,9 +171,10 @@ namespace GameRes.Formats.Softpal return tga_info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - using (var tga = new StreamRegion (stream, 0x18, true)) + using (var mem = new StreamRegion (stream.AsStream, 0x18, true)) + using (var tga = new BinaryStream (mem, stream.Name)) return base.Read (tga, info); } @@ -206,23 +201,21 @@ namespace GameRes.Formats.Softpal Extensions = new string[] { "pgd" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x20]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x20); return new PgdGeMetaData { - Width = LittleEndian.ToUInt32 (header, 0x0C), - Height = LittleEndian.ToUInt32 (header, 0x10), - OffsetX = LittleEndian.ToInt32 (header, 4), - OffsetY = LittleEndian.ToInt32 (header, 8), + Width = header.ToUInt32 (0x0C), + Height = header.ToUInt32 (0x10), + OffsetX = header.ToInt32 (4), + OffsetY = header.ToInt32 (8), BPP = 32, - Method = LittleEndian.ToUInt16 (header, 0x1C), + Method = header.ToUInt16 (0x1C), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { using (var reader = new PgdReader (stream, (PgdGeMetaData)info)) { @@ -255,28 +248,26 @@ namespace GameRes.Formats.Softpal Signatures = new uint[] { 0x33444750, 0x32444750 }; // 'PGD3', 'PGD2' } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x30]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - string base_name = Binary.GetCString (header, 0xE, 0x22); + var header = stream.ReadHeader (0x30); + string base_name = header.GetCString (0xE, 0x22); if (string.IsNullOrEmpty (base_name)) return null; return new PgdIncMetaData { - OffsetX = LittleEndian.ToUInt16 (header, 4), - OffsetY = LittleEndian.ToUInt16 (header, 6), - Width = LittleEndian.ToUInt16 (header, 8), - Height = LittleEndian.ToUInt16 (header, 0xA), - BPP = LittleEndian.ToUInt16 (header, 0xC), + OffsetX = header.ToUInt16 (4), + OffsetY = header.ToUInt16 (6), + Width = header.ToUInt16 (8), + Height = header.ToUInt16 (0xA), + BPP = header.ToUInt16 (0xC), BaseName = base_name, }; } static readonly Lazy PalFormat = new Lazy (() => FindByTag ("PGD/GE")); - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (PgdIncMetaData)info; string dir_name = VFS.GetDirectoryName (meta.FileName); @@ -284,7 +275,7 @@ namespace GameRes.Formats.Softpal PgdGeMetaData base_info; byte[] image, overlay; PixelFormat format; - using (var base_file = VFS.OpenSeekableStream (name)) + using (var base_file = VFS.OpenBinaryStream (name)) { base_info = PalFormat.Value.ReadMetaData (base_file) as PgdGeMetaData; if (null == base_info) @@ -334,7 +325,7 @@ namespace GameRes.Formats.Softpal internal sealed class PgdReader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; int m_width; int m_height; @@ -343,23 +334,23 @@ namespace GameRes.Formats.Softpal public PixelFormat Format { get; private set; } - public PgdReader (Stream input, int position) + public PgdReader (IBinaryStream input, int position) { - input.Position = position; - m_input = new ArcView.Reader (input); + m_input = input; + m_input.Position = position; int unpacked_size = m_input.ReadInt32(); m_input.ReadInt32(); // packed_size m_output = new byte[unpacked_size]; } - public PgdReader (Stream input, PgdGeMetaData info) : this (input, 0x20) + public PgdReader (IBinaryStream input, PgdGeMetaData info) : this (input, 0x20) { m_width = (int)info.Width; m_height = (int)info.Height; m_method = info.Method; } - public PgdReader (Stream input, PgdIncMetaData info) : this (input, 0x30) + public PgdReader (IBinaryStream input, PgdIncMetaData info) : this (input, 0x30) { m_width = (int)info.Width; m_height = (int)info.Height; @@ -589,14 +580,8 @@ namespace GameRes.Formats.Softpal } #region IDisposable Members - bool _disposed = false; public void Dispose () { - if (!_disposed) - { - m_input.Dispose(); - _disposed = true; - } } #endregion } diff --git a/ArcFormats/Softpal/ImagePIC.cs b/ArcFormats/Softpal/ImagePIC.cs index 205007f6..9817c182 100644 --- a/ArcFormats/Softpal/ImagePIC.cs +++ b/ArcFormats/Softpal/ImagePIC.cs @@ -49,16 +49,14 @@ namespace GameRes.Formats.Softpal Extensions = new string[] { "" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[8]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - int bpp = LittleEndian.ToInt16 (header, 0); + var header = stream.ReadHeader (8); + int bpp = header.ToInt16 (0); if (1 != bpp && 3 != bpp && 4 != bpp) return null; - uint width = LittleEndian.ToUInt16 (header, 2); - uint height = LittleEndian.ToUInt16 (header, 4); + uint width = header.ToUInt16 (2); + uint height = header.ToUInt16 (4); if (0 == width || 0 == height || header[6]*8 < width || header[7]*8 < height) return null; return new PicMetaData @@ -71,7 +69,7 @@ namespace GameRes.Formats.Softpal }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (PicMetaData)info; using (var reader = new PicReader (stream, meta)) @@ -89,7 +87,7 @@ namespace GameRes.Formats.Softpal internal sealed class PicReader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; PicMetaData m_info; byte[] m_control; @@ -102,9 +100,9 @@ namespace GameRes.Formats.Softpal readonly byte[] Values4bit = InitBlockValues (8); readonly byte[] Values6bit = InitBlockValues (0x20); - public PicReader (Stream input, PicMetaData info) + public PicReader (IBinaryStream input, PicMetaData info) { - m_input = new ArcView.Reader (input); + m_input = input; m_info = info; m_src_stride = m_info.BlocksWidth * m_info.BPP; } @@ -122,7 +120,7 @@ namespace GameRes.Formats.Softpal public void Unpack () { - m_input.BaseStream.Position = 8; + m_input.Position = 8; m_control = m_input.ReadBytes (m_info.BlocksHeight * m_info.BlocksWidth); m_output = new byte[m_src_stride * m_info.BlocksHeight * 8]; if (8 == m_info.BPP) @@ -259,7 +257,7 @@ namespace GameRes.Formats.Softpal } else { - byte pixel = m_input.ReadByte(); + byte pixel = m_input.ReadUInt8(); DecodeBlock (ctl, pixel, block); } int dst = 8 * (x + 8 * y * m_info.BlocksWidth); @@ -394,14 +392,8 @@ namespace GameRes.Formats.Softpal } #region IDisposable Members - bool _disposed = false; public void Dispose () { - if (!_disposed) - { - m_input.Dispose(); - _disposed = true; - } } #endregion } diff --git a/ArcFormats/StudioEgo/ArcPAK0.cs b/ArcFormats/StudioEgo/ArcPAK0.cs index 8b9ca7ac..febcbdb4 100644 --- a/ArcFormats/StudioEgo/ArcPAK0.cs +++ b/ArcFormats/StudioEgo/ArcPAK0.cs @@ -75,7 +75,7 @@ namespace GameRes.Formats.Ego return base.OpenEntry (arc, entry); var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); DecryptScript (method, data); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } unsafe void DecryptScript (uint method, byte[] script) diff --git a/ArcFormats/StudioEgo/ImageANT.cs b/ArcFormats/StudioEgo/ImageANT.cs index b6e4f911..c48cdff9 100644 --- a/ArcFormats/StudioEgo/ImageANT.cs +++ b/ArcFormats/StudioEgo/ImageANT.cs @@ -37,20 +37,18 @@ namespace GameRes.Formats.Ego public override string Description { get { return "Studio e.go! bitmap format"; } } public override uint Signature { get { return 0x49544E41; } } // 'ANTI' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x18]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x18); return new ImageMetaData { - Width = LittleEndian.ToUInt32 (header, 0xC), - Height = LittleEndian.ToUInt32 (header, 0x10), + Width = header.ToUInt32 (0xC), + Height = header.ToUInt32 (0x10), BPP = 32, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var pixels = new byte[info.Width*info.Height*4]; stream.Position = 0x18; diff --git a/ArcFormats/SuperNekoX/ArcGPC.cs b/ArcFormats/SuperNekoX/ArcGPC.cs index ece9ab91..9491c2eb 100644 --- a/ArcFormats/SuperNekoX/ArcGPC.cs +++ b/ArcFormats/SuperNekoX/ArcGPC.cs @@ -75,37 +75,34 @@ namespace GameRes.Formats.SuperNekoX public override Stream OpenEntry (ArcFile arc, Entry entry) { var pent = entry as PackedEntry; - Stream input = arc.File.CreateStream (entry.Offset, entry.Size); + IBinaryStream input = arc.File.CreateStream (entry.Offset, entry.Size, entry.Name); if (null != pent && pent.IsPacked) { - Stream unpacked; + IBinaryStream unpacked; using (input) { var data = new byte[pent.UnpackedSize]; - UnpackEntry (input, data); - unpacked = new MemoryStream (data); + UnpackEntry (input.AsStream, data); + unpacked = new BinMemoryStream (data, entry.Name); } input = unpacked; } if (input.Length > 4 && input.Length < 0x10000) { - using (var reader = new ArcView.Reader (input)) + int unpacked_size = input.ReadUInt16(); + int packed_size = input.ReadUInt16(); + if (packed_size == input.Length-4) { - int unpacked_size = reader.ReadUInt16(); - int packed_size = reader.ReadUInt16(); - if (packed_size == input.Length-4) + using (input) { - using (input) - { - var data = new byte[unpacked_size]; - UnpackLz77 (input, data); - return new MemoryStream (data); - } + var data = new byte[unpacked_size]; + UnpackLz77 (input.AsStream, data); + return new BinMemoryStream (data, entry.Name); } - input.Position = 0; } + input.Position = 0; } - return input; + return input.AsStream; } void DetectFileTypes (ArcView file, List dir) diff --git a/ArcFormats/Tactics/ArcTactics.cs b/ArcFormats/Tactics/ArcTactics.cs index e3286237..3a72a20c 100644 --- a/ArcFormats/Tactics/ArcTactics.cs +++ b/ArcFormats/Tactics/ArcTactics.cs @@ -87,9 +87,9 @@ namespace GameRes.Formats.Tactics var tarc = arc as TacticsArcFile; var tent = (PackedEntry)entry; if (null == tarc || null == tarc.Password && !tent.IsPacked) - return arc.File.CreateStream (entry.Offset, entry.Size); + return base.OpenEntry (arc, entry); if (null == tarc.Password) - return new LzssStream (arc.File.CreateStream (entry.Offset, entry.Size)); + return new LzssStream (base.OpenEntry (arc, entry)); var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); int p = 0; @@ -102,9 +102,9 @@ namespace GameRes.Formats.Tactics if (tarc.CustomLzss && tent.IsPacked) { data = UnpackCustomLzss (data); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } - Stream input = new MemoryStream (data); + Stream input = new BinMemoryStream (data, entry.Name); if (tent.IsPacked) input = new LzssStream (input); return input; diff --git a/ArcFormats/Tactics/ImageTGF.cs b/ArcFormats/Tactics/ImageTGF.cs index 524eb002..369bc731 100644 --- a/ArcFormats/Tactics/ImageTGF.cs +++ b/ArcFormats/Tactics/ImageTGF.cs @@ -53,16 +53,13 @@ namespace GameRes.Formats.Tactics throw new NotImplementedException ("TgfFormat.Write not implemented"); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[8]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - uint length = LittleEndian.ToUInt32 (header, 0); - int chunk_size = LittleEndian.ToInt32 (header, 4); + uint length = stream.ReadUInt32(); + int chunk_size = stream.ReadInt32(); if (length > 0xffffff || chunk_size <= 0 || length < chunk_size) return null; - using (var reader = new Reader (stream, (uint)Math.Max (0x20, chunk_size+2), chunk_size)) + using (var reader = new Reader (stream.AsStream, (uint)Math.Max (0x20, chunk_size+2), chunk_size)) { reader.Unpack(); var bmp = reader.Data; @@ -79,14 +76,11 @@ namespace GameRes.Formats.Tactics } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as TgfMetaData; - if (null == meta) - throw new ArgumentException ("TgfFormat.Read should be supplied with TgfMetaData", "info"); - + var meta = (TgfMetaData)info; stream.Position = 8; - using (var reader = new Reader (stream, meta.BitmapSize, meta.ChunkSize)) + using (var reader = new Reader (stream.AsStream, meta.BitmapSize, meta.ChunkSize)) { reader.Unpack(); using (var bmp = new MemoryStream (reader.Data)) diff --git a/ArcFormats/TamaSoft/AudioESD.cs b/ArcFormats/TamaSoft/AudioESD.cs index 2a6ff490..55150228 100644 --- a/ArcFormats/TamaSoft/AudioESD.cs +++ b/ArcFormats/TamaSoft/AudioESD.cs @@ -37,21 +37,19 @@ namespace GameRes.Formats.Tama public override string Description { get { return "TamaSoft ADV system audio"; } } public override uint Signature { get { return 0x20445345; } } // 'ESD ' - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - var header = new byte[0x20]; - if (header.Length != file.Read (header, 0, header.Length)) - return null; + var header = file.ReadHeader (0x20); var format = new WaveFormat { FormatTag = 1, - Channels = LittleEndian.ToUInt16 (header, 0x10), - SamplesPerSecond = LittleEndian.ToUInt32 (header, 8), - BitsPerSample = LittleEndian.ToUInt16 (header, 0xC), + Channels = header.ToUInt16 (0x10), + SamplesPerSecond = header.ToUInt32 (8), + BitsPerSample = header.ToUInt16 (0xC), }; format.BlockAlign = (ushort)(format.Channels * format.BitsPerSample / 8); format.AverageBytesPerSecond = format.SamplesPerSecond * format.BlockAlign; - var pcm = new StreamRegion (file, 0x20); + var pcm = new StreamRegion (file.AsStream, 0x20); return new RawPcmInput (pcm, format); } } diff --git a/ArcFormats/TamaSoft/ImageBTN.cs b/ArcFormats/TamaSoft/ImageBTN.cs index c1c7a614..18cf9731 100644 --- a/ArcFormats/TamaSoft/ImageBTN.cs +++ b/ArcFormats/TamaSoft/ImageBTN.cs @@ -25,7 +25,6 @@ using System.ComponentModel.Composition; using System.IO; -using GameRes.Utility; namespace GameRes.Formats.Tama { @@ -41,14 +40,13 @@ namespace GameRes.Formats.Tama public override string Description { get { return "TamaSoft ADV system button image"; } } public override uint Signature { get { return 0x4E544245; } } // 'EBTN' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[8]; - if (header.Length != stream.Read (header, 0, 8)) - return null; - int count = LittleEndian.ToInt32 (header, 4); + stream.Position = 4; + int count = stream.ReadInt32(); int offset = 0x30 + count * 4; - using (var input = new StreamRegion (stream, offset, true)) + using (var data = new StreamRegion (stream.AsStream, offset, true)) + using (var input = new BinaryStream (data, stream.Name)) { var info = base.ReadMetaData (input); if (null == info) @@ -63,10 +61,11 @@ namespace GameRes.Formats.Tama } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (BtnMetaData)info; - using (var input = new StreamRegion (stream, meta.SurOffset, true)) + using (var data = new StreamRegion (stream.AsStream, meta.SurOffset, true)) + using (var input = new BinaryStream (data, stream.Name)) return base.Read (input, info); } diff --git a/ArcFormats/TamaSoft/ImageSUR.cs b/ArcFormats/TamaSoft/ImageSUR.cs index 5f6afcb0..8a21acf1 100644 --- a/ArcFormats/TamaSoft/ImageSUR.cs +++ b/ArcFormats/TamaSoft/ImageSUR.cs @@ -38,24 +38,22 @@ namespace GameRes.Formats.Tama public override string Description { get { return "TamaSoft ADV system image"; } } public override uint Signature { get { return 0x52555345; } } // 'ESUR' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x10]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x10); return new ImageMetaData { - Width = LittleEndian.ToUInt32 (header, 8), - Height = LittleEndian.ToUInt32 (header, 12), + Width = header.ToUInt32 (8), + Height = header.ToUInt32 (12), BPP = 32, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var pixels = new byte[info.Width * info.Height * 4]; stream.Position = 0x20; - UnpackLzss (stream, pixels); + UnpackLzss (stream.AsStream, pixels); return ImageData.Create (info, PixelFormats.Bgra32, null, pixels); } diff --git a/ArcFormats/TechnoBrain/ImageIPH.cs b/ArcFormats/TechnoBrain/ImageIPH.cs index 3720557a..6997d16d 100644 --- a/ArcFormats/TechnoBrain/ImageIPH.cs +++ b/ArcFormats/TechnoBrain/ImageIPH.cs @@ -44,36 +44,33 @@ namespace GameRes.Formats.TechnoBrain public override string Description { get { return "TechnoBrain's 'Inteligent Picture Format'"; } } public override uint Signature { get { return 0; } } // 'RIFF' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { // 'RIFF' isn't included into signature to avoid auto-detection of the WAV files as IPH images. - if (0x46464952 != FormatCatalog.ReadSignature (stream)) // 'RIFF' + if (0x46464952 != file.Signature) // 'RIFF' return null; - using (var reader = new ArcView.Reader (stream)) - { - if (0x38 != reader.ReadInt32()) - return null; - var signature = reader.ReadInt32(); - if (signature != 0x20485049 && signature != 0x00485049) // 'IPH' - return null; - if (0x20746D66 != reader.ReadInt32()) // 'fmt ' - return null; - reader.BaseStream.Position = 0x38; - if (0x20706D62 != reader.ReadInt32()) // 'bmp ' - return null; - var info = new IphMetaData(); - info.PackedSize = reader.ReadInt32(); - info.Width = reader.ReadUInt16(); - info.Height = reader.ReadUInt16(); - reader.BaseStream.Position = 0x50; - info.BPP = reader.ReadUInt16(); - info.IsCompressed = 0 != reader.ReadInt16(); - // XXX int16@[0x54] is a transparency color or 0xFFFF if image is not transparent - return info; - } + if (0x38 != file.ReadInt32()) + return null; + var signature = file.ReadInt32(); + if (signature != 0x20485049 && signature != 0x00485049) // 'IPH' + return null; + if (0x20746D66 != file.ReadInt32()) // 'fmt ' + return null; + file.Position = 0x38; + if (0x20706D62 != file.ReadInt32()) // 'bmp ' + return null; + var info = new IphMetaData(); + info.PackedSize = file.ReadInt32(); + info.Width = file.ReadUInt16(); + info.Height = file.ReadUInt16(); + file.Position = 0x50; + info.BPP = file.ReadUInt16(); + info.IsCompressed = 0 != file.ReadInt16(); + // XXX int16@[0x54] is a transparency color or 0xFFFF if image is not transparent + return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { if (info.BPP != 16) throw new NotSupportedException ("Not supported IPH color depth"); @@ -92,7 +89,7 @@ namespace GameRes.Formats.TechnoBrain internal sealed class IphReader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; int m_width; int m_height; @@ -101,10 +98,10 @@ namespace GameRes.Formats.TechnoBrain public PixelFormat Format { get { return PixelFormats.Bgr555; } } public byte[] Data { get { return m_output; } } - public IphReader (Stream input, IphMetaData info) + public IphReader (IBinaryStream input, IphMetaData info) { m_info = info; - m_input = new ArcView.Reader (input); + m_input = input; m_width = (int)info.Width; m_height = (int)info.Height; m_output = new byte[m_width*m_height*2]; @@ -112,7 +109,7 @@ namespace GameRes.Formats.TechnoBrain public void Unpack () { - m_input.BaseStream.Position = 0x58; + m_input.Position = 0x58; if (!m_info.IsCompressed) { m_input.Read (m_output, 0, m_output.Length); @@ -123,14 +120,14 @@ namespace GameRes.Formats.TechnoBrain for (int y = 0; y < m_height; ++y) { int row = stride * y; - byte ctl = m_input.ReadByte(); + byte ctl = m_input.ReadUInt8(); if (ctl != 0) { int dst = row; int pixel = 0; while (dst < m_output.Length) { - ctl = m_input.ReadByte(); + ctl = m_input.ReadUInt8(); if (0xFF == ctl) break; if (0xFE == ctl) @@ -145,7 +142,7 @@ namespace GameRes.Formats.TechnoBrain } else if (ctl < 0x80) { - byte lo = m_input.ReadByte(); + byte lo = m_input.ReadUInt8(); m_output[dst++] = lo; m_output[dst++] = ctl; pixel = ctl << 8 | lo; @@ -169,13 +166,13 @@ namespace GameRes.Formats.TechnoBrain m_input.Read (m_output, row, stride); m_input.ReadByte(); } - ctl = m_input.ReadByte(); + ctl = m_input.ReadUInt8(); if (0 != ctl) { int dst = 0; for (;;) { - ctl = m_input.ReadByte(); + ctl = m_input.ReadUInt8(); if (0xFF == ctl) break; if (ctl >= 0x80) @@ -209,14 +206,8 @@ namespace GameRes.Formats.TechnoBrain } #region IDisposable Members - bool _disposed = false; public void Dispose () { - if (!_disposed) - { - m_input.Dispose(); - _disposed = true; - } } #endregion } diff --git a/ArcFormats/Tmr-Hiro/ArcPAC.cs b/ArcFormats/Tmr-Hiro/ArcPAC.cs index deac5f4f..a27b5661 100644 --- a/ArcFormats/Tmr-Hiro/ArcPAC.cs +++ b/ArcFormats/Tmr-Hiro/ArcPAC.cs @@ -136,7 +136,7 @@ namespace GameRes.Formats.TmrHiro ++pos; } } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } } diff --git a/ArcFormats/Tmr-Hiro/AudioTmr.cs b/ArcFormats/Tmr-Hiro/AudioTmr.cs index a7bcf13e..8f9b08a5 100644 --- a/ArcFormats/Tmr-Hiro/AudioTmr.cs +++ b/ArcFormats/Tmr-Hiro/AudioTmr.cs @@ -44,15 +44,15 @@ namespace GameRes.Formats.TmrHiro Extensions = new string[] { "" }; } - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { if (file.ReadByte() != 0x44) return null; file.Position = 4; if (file.ReadByte() != 0) return null; - int length = ReadInt32 (file); - if (-1 == length || length != file.Length - 9) + int length = file.ReadInt32(); + if (length != file.Length - 9) return null; var format = new WaveFormat { @@ -63,17 +63,8 @@ namespace GameRes.Formats.TmrHiro BlockAlign = 4, AverageBytesPerSecond = 44100*4, }; - var pcm = new StreamRegion (file, 9, length); + var pcm = new StreamRegion (file.AsStream, 9, length); return new RawPcmInput (pcm, format); } - - private static int ReadInt32 (Stream file) - { - int dword = file.ReadByte(); - dword |= file.ReadByte() << 8; - dword |= file.ReadByte() << 16; - dword |= file.ReadByte() << 24; - return dword; - } } } diff --git a/ArcFormats/Tmr-Hiro/ImageGRD.cs b/ArcFormats/Tmr-Hiro/ImageGRD.cs index 8729fa62..61ec3a87 100644 --- a/ArcFormats/Tmr-Hiro/ImageGRD.cs +++ b/ArcFormats/Tmr-Hiro/ImageGRD.cs @@ -52,45 +52,43 @@ namespace GameRes.Formats.TmrHiro Extensions = new string[] { "grd", "" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x20]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x20); if (header[0] != 1 && header[0] != 2) return null; if (header[1] != 1 && header[1] != 0xA1 && header[1] != 0xA2) return null; - int bpp = LittleEndian.ToUInt16 (header, 6); + int bpp = header.ToUInt16 (6); if (bpp != 24 && bpp != 32) return null; - int screen_width = LittleEndian.ToUInt16 (header, 2); - int screen_height = LittleEndian.ToUInt16 (header, 4); - int left = LittleEndian.ToUInt16 (header, 8); - int right = LittleEndian.ToUInt16 (header, 0xA); - int top = LittleEndian.ToUInt16 (header, 0xC); - int bottom = LittleEndian.ToUInt16 (header, 0xE); + int screen_width = header.ToUInt16 (2); + int screen_height = header.ToUInt16 (4); + int left = header.ToUInt16 (8); + int right = header.ToUInt16 (0xA); + int top = header.ToUInt16 (0xC); + int bottom = header.ToUInt16 (0xE); var info = new GrdMetaData { - Format = LittleEndian.ToUInt16 (header, 0), + Format = header.ToUInt16 (0), Width = (uint)(right-left), Height = (uint)(bottom-top), BPP = bpp, OffsetX = left, OffsetY = screen_height - bottom, - AlphaSize = LittleEndian.ToInt32 (header, 0x10), - RSize = LittleEndian.ToInt32 (header, 0x14), - GSize = LittleEndian.ToInt32 (header, 0x18), - BSize = LittleEndian.ToInt32 (header, 0x1C), + AlphaSize = header.ToInt32 (0x10), + RSize = header.ToInt32 (0x14), + GSize = header.ToInt32 (0x18), + BSize = header.ToInt32 (0x1C), }; if (0x20 + info.AlphaSize + info.RSize + info.BSize + info.GSize != stream.Length) return null; return info; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (GrdMetaData)info; - var reader = new GrdReader (stream, meta); + var reader = new GrdReader (stream.AsStream, meta); reader.Unpack(); return ImageData.Create (info, reader.Format, null, reader.Data); } diff --git a/ArcFormats/TopCat/ArcTCD3.cs b/ArcFormats/TopCat/ArcTCD3.cs index 08a8a8cf..897859f3 100644 --- a/ArcFormats/TopCat/ArcTCD3.cs +++ b/ArcFormats/TopCat/ArcTCD3.cs @@ -122,7 +122,7 @@ namespace GameRes.Formats.TopCat return OpenScript (arc, entry); if (entry.Name.EndsWith (".SPD", StringComparison.InvariantCultureIgnoreCase)) return OpenSpdc (arc, entry); - return arc.File.CreateStream (entry.Offset, entry.Size); + return base.OpenEntry (arc, entry); } Stream OpenSpdc (ArcFile arc, Entry entry) @@ -187,7 +187,7 @@ namespace GameRes.Formats.TopCat using (var input = arc.File.CreateStream (entry.Offset+4, entry.Size-4)) UnpackLz (input, data); DecryptScript (data); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } void UnpackLz (Stream input, byte[] output) @@ -253,7 +253,7 @@ namespace GameRes.Formats.TopCat LittleEndian.Pack (crc, data, src+0x16); src += page_size; } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } diff --git a/ArcFormats/TopCat/ImageSPD.cs b/ArcFormats/TopCat/ImageSPD.cs index 384b50bb..fb6214ab 100644 --- a/ArcFormats/TopCat/ImageSPD.cs +++ b/ArcFormats/TopCat/ImageSPD.cs @@ -62,11 +62,9 @@ namespace GameRes.Formats.TopCat Signatures = new uint[] { 0x43445053, 0x38445053 }; // 'SPD8' } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x14]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x14).ToArray(); unsafe { fixed (byte* raw = header) @@ -88,13 +86,13 @@ namespace GameRes.Formats.TopCat } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (SpdMetaData)info; if (Compression.Jpeg == meta.Method) - return ReadJpeg (stream, meta); + return ReadJpeg (stream.AsStream, meta); - using (var reader = new SpdReader (stream, meta)) + using (var reader = new SpdReader (stream.AsStream, meta)) { reader.Unpack(); return ImageData.Create (info, reader.Format, null, reader.Data); diff --git a/ArcFormats/Triangle/ImageIAF.cs b/ArcFormats/Triangle/ImageIAF.cs index d8b7007f..50de3430 100644 --- a/ArcFormats/Triangle/ImageIAF.cs +++ b/ArcFormats/Triangle/ImageIAF.cs @@ -48,7 +48,7 @@ namespace GameRes.Formats.Triangle public override uint Signature { get { return 0; } } public override bool CanWrite { get { return false; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { var header = new byte[0x14]; if (12 != stream.Read (header, 0, 12)) @@ -100,7 +100,7 @@ namespace GameRes.Formats.Triangle return null; unpacked_size &= (int)~0xC0000000; stream.Position = data_offset; - byte[] bmp = UnpackBitmap (stream, pack_type, packed_size, 0x26); + byte[] bmp = UnpackBitmap (stream.AsStream, pack_type, packed_size, 0x26); if (bmp[0] != 'B' && bmp[0] != 'C' || bmp[1] != 'M') return null; return new IafMetaData @@ -117,11 +117,11 @@ namespace GameRes.Formats.Triangle }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (IafMetaData)info; stream.Position = meta.DataOffset; - var bitmap = UnpackBitmap (stream, meta.PackType, meta.PackedSize, meta.UnpackedSize); + var bitmap = UnpackBitmap (stream.AsStream, meta.PackType, meta.PackedSize, meta.UnpackedSize); if ('C' == bitmap[0]) { bitmap[0] = (byte)'B'; @@ -151,7 +151,7 @@ namespace GameRes.Formats.Triangle // fallback to a plain bitmap } } - using (var bmp = new MemoryStream (bitmap)) + using (var bmp = new BinMemoryStream (bitmap, stream.Name)) return base.Read (bmp, info); } diff --git a/ArcFormats/UMeSoft/ArcPK.cs b/ArcFormats/UMeSoft/ArcPK.cs index 1f89e150..3d0294f2 100644 --- a/ArcFormats/UMeSoft/ArcPK.cs +++ b/ArcFormats/UMeSoft/ArcPK.cs @@ -94,7 +94,7 @@ namespace GameRes.Formats.UMeSoft var data = LzUnpack (input, output_size); for (int i = 0; i < data.Length; ++i) data[i] ^= 0x42; - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } diff --git a/ArcFormats/UMeSoft/ImageGRX.cs b/ArcFormats/UMeSoft/ImageGRX.cs index e69d74e4..10b54823 100644 --- a/ArcFormats/UMeSoft/ImageGRX.cs +++ b/ArcFormats/UMeSoft/ImageGRX.cs @@ -45,25 +45,27 @@ namespace GameRes.Formats.UMeSoft public override string Description { get { return "U-Me Soft image format"; } } public override uint Signature { get { return 0x1A585247; } } // 'GRX' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - byte[] header = new byte[0x10]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - return new GrxMetaData - { - Width = LittleEndian.ToUInt16 (header, 8), - Height = LittleEndian.ToUInt16 (header, 10), - BPP = LittleEndian.ToUInt16 (header, 6), - IsPacked = 0 != header[4], - HasAlpha = 0 != header[5], - AlphaOffset = LittleEndian.ToInt32 (header, 12), - }; + file.Position = 4; + return ReadInfo (file); } - public override ImageData Read (Stream stream, ImageMetaData info) + internal GrxMetaData ReadInfo (IBinaryStream file) { - var reader = new Reader (stream, (GrxMetaData)info); + var info = new GrxMetaData(); + info.IsPacked = file.ReadByte() != 0; + info.HasAlpha = file.ReadByte() != 0; + info.BPP = file.ReadUInt16(); + info.Width = file.ReadUInt16(); + info.Height = file.ReadUInt16(); + info.AlphaOffset = file.ReadInt32(); + return info; + } + + public override ImageData Read (IBinaryStream file, ImageMetaData info) + { + var reader = new Reader (file.AsStream, (GrxMetaData)info); reader.Unpack(); return ImageData.Create (info, reader.Format, null, reader.Data, reader.Stride); } @@ -292,38 +294,36 @@ namespace GameRes.Formats.UMeSoft Extensions = new string[] { "grx" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var reader = new ArcView.Reader (stream)) + file.Position = 4; + int offset = file.ReadInt32(); + if (offset <= 8) + return null; + file.Position = offset; + uint signature = file.ReadUInt32(); + if (signature != base.Signature) + return null; + var info = ReadInfo (file); + return new SgxMetaData { - stream.Seek (4, SeekOrigin.Current); - int offset = reader.ReadInt32(); - if (offset <= 8) - return null; - stream.Position = offset; - uint signature = reader.ReadUInt32(); - if (signature != base.Signature) - return null; - stream.Seek (-4, SeekOrigin.Current); - var info = base.ReadMetaData (stream) as GrxMetaData; - if (null == info) - return null; - return new SgxMetaData - { - Width = info.Width, - Height = info.Height, - BPP = info.BPP, - GrxOffset = offset, - GrxInfo = info - }; - } + Width = info.Width, + Height = info.Height, + BPP = info.BPP, + GrxOffset = offset, + GrxInfo = info + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (SgxMetaData)info; - using (var grx = new StreamRegion (stream, meta.GrxOffset, true)) - return base.Read (grx, meta.GrxInfo); + using (var grx = new StreamRegion (stream.AsStream, meta.GrxOffset, true)) + { + var reader = new Reader (grx, (GrxMetaData)meta.GrxInfo); + reader.Unpack(); + return ImageData.Create (info, reader.Format, null, reader.Data, reader.Stride); + } } } } diff --git a/ArcFormats/Vitamin/ImageMFC.cs b/ArcFormats/Vitamin/ImageMFC.cs index b82ea858..d3bea9af 100644 --- a/ArcFormats/Vitamin/ImageMFC.cs +++ b/ArcFormats/Vitamin/ImageMFC.cs @@ -49,17 +49,16 @@ namespace GameRes.Formats.Vitamin Extensions = new string[] { "mfc" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x18]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x18); if (header[4] != 1 || header[5] != 0 || header[6] != 1 || header[7] != 4) return null; - int alpha_size = LittleEndian.ToInt32 (header, 12); - using (var sbi = new StreamRegion (stream, alpha_size, true)) + int alpha_size = header.ToInt32 (12); + using (var reg = new StreamRegion (stream.AsStream, alpha_size, true)) + using (var sbi = new BinaryStream (reg, stream.Name)) { var info = base.ReadMetaData (sbi) as SbiMetaData; if (null == info) @@ -75,15 +74,15 @@ namespace GameRes.Formats.Vitamin } } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { var meta = (MfcMetaData)info; // XXX implemented like in reference code, width is expected to be even. var alpha = new byte[info.Width * info.Height / 2]; stream.Position = 0x18; - RleUnpack (stream, meta.AlphaSize - 0x18, alpha); + RleUnpack (stream.AsStream, meta.AlphaSize - 0x18, alpha); byte[] pixels; - using (var sbi = new StreamRegion (stream, meta.AlphaSize, true)) + using (var sbi = new StreamRegion (stream.AsStream, meta.AlphaSize, true)) using (var reader = new SbiReader (sbi, meta.BaseInfo)) { reader.Unpack(); diff --git a/ArcFormats/Vitamin/ImageSBI.cs b/ArcFormats/Vitamin/ImageSBI.cs index e439ea75..4055522c 100644 --- a/ArcFormats/Vitamin/ImageSBI.cs +++ b/ArcFormats/Vitamin/ImageSBI.cs @@ -51,11 +51,9 @@ namespace GameRes.Formats.Vitamin Extensions = new string[] { "cmp" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x20]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x20); if (header[4] != 1 || header[5] != 0) return null; int bpp = header[6]; @@ -63,18 +61,18 @@ namespace GameRes.Formats.Vitamin return null; return new SbiMetaData { - Width = LittleEndian.ToUInt16 (header, 7), - Height = LittleEndian.ToUInt16 (header, 9), + Width = header.ToUInt16 (7), + Height = header.ToUInt16 (9), BPP = bpp, - InputSize = LittleEndian.ToInt32 (header, 0xB), + InputSize = header.ToInt32 (0xB), IsPacked = 0 != header[0x10], HasPalette = 8 == bpp && 0 == header[0xF], }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - using (var reader = new SbiReader (stream, (SbiMetaData)info)) + using (var reader = new SbiReader (stream.AsStream, (SbiMetaData)info)) { reader.Unpack(); return ImageData.Create (info, reader.Format, reader.Palette, reader.Data, reader.Stride); diff --git a/ArcFormats/VnEngine/ImageZAW.cs b/ArcFormats/VnEngine/ImageZAW.cs index 79bfe215..9320a780 100644 --- a/ArcFormats/VnEngine/ImageZAW.cs +++ b/ArcFormats/VnEngine/ImageZAW.cs @@ -38,12 +38,10 @@ namespace GameRes.Formats.VnEngine public override string Description { get { return "GEM/vnengine image format"; } } public override uint Signature { get { return 0x57415A; } } // 'ZAW' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x40]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - uint crc = LittleEndian.ToUInt32 (header, 4); + var header = stream.ReadHeader (0x40).ToArray(); + uint crc = header.ToUInt32 (4); LittleEndian.Pack (0u, header, 4); if (crc != Crc32.Compute (header, 0, header.Length)) return null; @@ -52,21 +50,21 @@ namespace GameRes.Formats.VnEngine : 1 == header[12] ? 24 : 8; return new ImageMetaData { - Width = LittleEndian.ToUInt32 (header, 0x10), - Height = LittleEndian.ToUInt32 (header, 0x14), - OffsetX = LittleEndian.ToInt32 (header, 0x18), - OffsetY = LittleEndian.ToInt32 (header, 0x1C), + Width = header.ToUInt32 (0x10), + Height = header.ToUInt32 (0x14), + OffsetX = header.ToInt32 (0x18), + OffsetY = header.ToInt32 (0x1C), BPP = bpp, }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { int pixel_size = info.BPP / 8; int stride = (int)info.Width * pixel_size; var pixels = new byte[stride * (int)info.Height]; stream.Position = 0x40; - using (var input = new ZLibStream (stream, CompressionMode.Decompress, true)) + using (var input = new ZLibStream (stream.AsStream, CompressionMode.Decompress, true)) input.Read (pixels, 0, pixels.Length); if (24 == info.BPP) return ImageData.Create (info, PixelFormats.Rgb24, null, pixels, stride); diff --git a/ArcFormats/WebP/ImageWEBP.cs b/ArcFormats/WebP/ImageWEBP.cs index a18f16fe..e86909fa 100644 --- a/ArcFormats/WebP/ImageWEBP.cs +++ b/ArcFormats/WebP/ImageWEBP.cs @@ -60,9 +60,9 @@ namespace GameRes.Formats.Google public override string Description { get { return "Google WebP image format"; } } public override uint Signature { get { return 0; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - if (0x46464952 != FormatCatalog.ReadSignature (stream)) // 'RIFF' + if (0x46464952 != stream.Signature) // 'RIFF' return null; var header = new byte[0x10]; if (8 != stream.Read (header, 0, 8)) @@ -141,9 +141,9 @@ namespace GameRes.Formats.Google return (uint)(src[offset] | src[offset+1] << 8 | src[offset+2] << 16); } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - using (var reader = new WebPDecoder (stream, (WebPMetaData)info)) + using (var reader = new WebPDecoder (stream.AsStream, (WebPMetaData)info)) { reader.Decode(); return ImageData.Create (info, reader.Format, null, reader.Output); diff --git a/ArcFormats/WildBug/AudioWPN.cs b/ArcFormats/WildBug/AudioWPN.cs index 0b41d73e..b994d010 100644 --- a/ArcFormats/WildBug/AudioWPN.cs +++ b/ArcFormats/WildBug/AudioWPN.cs @@ -37,19 +37,18 @@ namespace GameRes.Formats.WildBug public override string Description { get { return "Wild Bug's audio format"; } } public override uint Signature { get { return 0x1A444257; } } // 'WBD' - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - var header = new byte[0x24]; - if (header.Length != file.Read (header, 0, header.Length)) + var header = file.ReadHeader (0x24); + if (!header.AsciiEqual (4, "WAV")) return null; - if (!Binary.AsciiEqual (header, 4, "WAV")) + if (header.ToInt32 (8) < 2) return null; - if (LittleEndian.ToInt32 (header, 8) < 2) - return null; - int fmt_offset = LittleEndian.ToInt32 (header, 0x10); - int fmt_size = LittleEndian.ToInt32 (header, 0x14); - int data_offset = LittleEndian.ToInt32 (header, 0x1C); - int data_size = LittleEndian.ToInt32 (header, 0x20); + int fmt_offset = header.ToInt32 (0x10); + int fmt_size = header.ToInt32 (0x14); + int data_offset = header.ToInt32 (0x1C); + int data_size = header.ToInt32 (0x20); + var wav_header = new byte[8+12+fmt_size+8]; Buffer.BlockCopy (WavHeader, 0, wav_header, 0, WavHeader.Length); LittleEndian.Pack (wav_header.Length-8+data_size, wav_header, 4); @@ -62,7 +61,7 @@ namespace GameRes.Formats.WildBug wav_header[d++]= (byte)'t'; wav_header[d++]= (byte)'a'; LittleEndian.Pack (data_size, wav_header, d); - var wav_data = new StreamRegion (file, data_offset, data_size); + var wav_data = new StreamRegion (file.AsStream, data_offset, data_size); return new WaveInput (new PrefixStream (wav_header, wav_data)); } diff --git a/ArcFormats/WildBug/AudioWWA.cs b/ArcFormats/WildBug/AudioWWA.cs index c51ee912..1d506b15 100644 --- a/ArcFormats/WildBug/AudioWWA.cs +++ b/ArcFormats/WildBug/AudioWWA.cs @@ -37,12 +37,10 @@ namespace GameRes.Formats.WildBug public override string Description { get { return "Wild Bug's compressed audio format"; } } public override uint Signature { get { return 0x1A585057; } } // 'WPX' - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - var header = new byte[0x10]; - if (header.Length != file.Read (header, 0, header.Length)) - return null; - if (!Binary.AsciiEqual (header, 4, "WAV")) + var header = file.ReadHeader (0x10); + if (!header.AsciiEqual (4, "WAV")) return null; int count = header[0xE]; int dir_size = header[0xF]; @@ -50,22 +48,19 @@ namespace GameRes.Formats.WildBug return null; file.Position = 0x10; - header = new byte[count * dir_size]; - if (header.Length != file.Read (header, 0, header.Length)) - throw new InvalidFormatException(); + var index = file.ReadBytes (count * dir_size); - var section = WpxSection.Find (header, 0x20, count, dir_size); + var section = WpxSection.Find (index, 0x20, count, dir_size); if (null == section || section.UnpackedSize < 0x10 || section.DataFormat != 0x80) throw new InvalidFormatException(); - var fmt = new byte[section.UnpackedSize]; file.Position = section.Offset; - file.Read (fmt, 0, section.UnpackedSize); + var fmt = file.ReadBytes (section.UnpackedSize); - section = WpxSection.Find (header, 0x21, count, dir_size); + section = WpxSection.Find (index, 0x21, count, dir_size); if (null == section) throw new InvalidFormatException(); - var reader = new WwaReader (file, section); + var reader = new WwaReader (file.AsStream, section); var data = reader.Unpack (section.DataFormat); if (null == data) throw new InvalidFormatException(); diff --git a/ArcFormats/WildBug/ImageWBM.cs b/ArcFormats/WildBug/ImageWBM.cs index 28e3febb..69b9a775 100644 --- a/ArcFormats/WildBug/ImageWBM.cs +++ b/ArcFormats/WildBug/ImageWBM.cs @@ -74,29 +74,25 @@ namespace GameRes.Formats.WildBug public override string Description { get { return "Wild Bug's image format"; } } public override uint Signature { get { return 0x1A585057; } } // 'WPX' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - byte[] header = new byte[0x10]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - if (!Binary.AsciiEqual (header, 4, "BMP")) + var header = stream.ReadHeader (0x10); + if (!header.AsciiEqual (4, "BMP")) return null; int count = header[0xE]; int dir_size = header[0xF]; if (1 != header[0xC] || 0 == count || 0 == dir_size) return null; - header = new byte[count * dir_size]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - var section = WpxSection.Find (header, 0x10, count, dir_size); + var dir = stream.ReadBytes (count * dir_size); + var section = WpxSection.Find (dir, 0x10, count, dir_size); if (null == section) return null; if (section.UnpackedSize < 0x10) return null; - stream.Seek (section.Offset, SeekOrigin.Begin); - byte[] data = new byte[section.UnpackedSize]; - if (data.Length != stream.Read (data, 0, data.Length)) + stream.Position = section.Offset; + var data = stream.ReadBytes (section.UnpackedSize); + if (data.Length != section.UnpackedSize) return null; return new WbmMetaData @@ -106,15 +102,13 @@ namespace GameRes.Formats.WildBug BPP = data[0xC], EntryCount = count, EntrySize = dir_size, - Header = header, + Header = header.ToArray(), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as WbmMetaData; - if (null == meta) - throw new ArgumentException ("WbmFormat.Read should be supplied with WbmMetaData", "info"); + var meta = (WbmMetaData)info; var section = WpxSection.Find (meta.Header, 0x11, meta.EntryCount, meta.EntrySize); if (null == section) @@ -215,7 +209,7 @@ namespace GameRes.Formats.WildBug internal class WbmReader : WpxDecoder { - public WbmReader (Stream input, WpxSection section) : base (input, section) + public WbmReader (IBinaryStream input, WpxSection section) : base (input.AsStream, section) { } diff --git a/ArcFormats/Will/ArcPulltop.cs b/ArcFormats/Will/ArcPulltop.cs index b7e7c35a..d1dafedb 100644 --- a/ArcFormats/Will/ArcPulltop.cs +++ b/ArcFormats/Will/ArcPulltop.cs @@ -102,7 +102,7 @@ namespace GameRes.Formats.Will { data[i] = Binary.RotByteR (data[i], 2); } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } } diff --git a/ArcFormats/Will/ArcWILL.cs b/ArcFormats/Will/ArcWILL.cs index f1541cc5..871178c8 100644 --- a/ArcFormats/Will/ArcWILL.cs +++ b/ArcFormats/Will/ArcWILL.cs @@ -123,7 +123,7 @@ namespace GameRes.Formats.Will return arc.File.CreateStream (entry.Offset, entry.Size); var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); DecodeScript (data); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } private static void DecodeScript (byte[] data) diff --git a/ArcFormats/Will/ImageWIP.cs b/ArcFormats/Will/ImageWIP.cs index d748f15c..f5d5a877 100644 --- a/ArcFormats/Will/ImageWIP.cs +++ b/ArcFormats/Will/ImageWIP.cs @@ -51,36 +51,32 @@ namespace GameRes.Formats.Will Extensions = new string[] { "wip", "msk", "mos" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var file = new BinaryReader (stream, Encoding.ASCII, true)) + file.Position = 4; + int frames = file.ReadUInt16(); + int bpp = file.ReadUInt16(); + uint width = file.ReadUInt32(); + uint height = file.ReadUInt32(); + int x = file.ReadInt32(); + int y = file.ReadInt32(); + file.ReadInt32(); // 0 + uint frame_size = file.ReadUInt32(); + if (24 != bpp && 8 != bpp) { - if (Signature != file.ReadUInt32()) - return null; - int frames = file.ReadUInt16(); - int bpp = file.ReadUInt16(); - uint width = file.ReadUInt32(); - uint height = file.ReadUInt32(); - int x = file.ReadInt32(); - int y = file.ReadInt32(); - file.ReadUInt32(); // 0 - uint frame_size = file.ReadUInt32(); - if (24 != bpp && 8 != bpp) - { - Trace.WriteLine ("unsupported bpp", "WipFormat"); - return null; - } - return new WipMetaData - { - Width = width, - Height = height, - OffsetX = x, - OffsetY = y, - BPP = bpp, - FrameCount = frames, - FrameSize = frame_size, - }; + Trace.WriteLine ("unsupported bpp", "WipFormat"); + return null; } + return new WipMetaData + { + Width = width, + Height = height, + OffsetX = x, + OffsetY = y, + BPP = bpp, + FrameCount = frames, + FrameSize = frame_size, + }; } public override void Write (Stream file, ImageData image) @@ -88,7 +84,7 @@ namespace GameRes.Formats.Will throw new NotImplementedException ("WipFormat.Write not implemented"); } - public override ImageData Read (Stream file, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { var meta = (WipMetaData)info; if (meta.FrameCount > 1) @@ -106,7 +102,7 @@ namespace GameRes.Formats.Will palette[i] = Color.FromRgb (palette_data[i*4], palette_data[i*4+1], palette_data[i*4+2]); } } - using (var reader = new Reader (file, meta)) + using (var reader = new Reader (file.AsStream, meta)) { reader.Unpack(); if (24 == meta.BPP) @@ -134,7 +130,7 @@ namespace GameRes.Formats.Will } } - internal class Reader : IDisposable + internal sealed class Reader : IDisposable { private BinaryReader m_input; private uint m_length; @@ -199,21 +195,13 @@ namespace GameRes.Formats.Will bool disposed = false; public void Dispose () - { - Dispose (true); - GC.SuppressFinalize (this); - } - - protected virtual void Dispose (bool disposing) { if (!disposed) { - if (disposing) - m_input.Dispose(); - m_input = null; - m_data = null; + m_input.Dispose(); disposed = true; } + GC.SuppressFinalize (this); } #endregion } diff --git a/ArcFormats/Xuse/ArcWAG.cs b/ArcFormats/Xuse/ArcWAG.cs index 493205b4..03b19be5 100644 --- a/ArcFormats/Xuse/ArcWAG.cs +++ b/ArcFormats/Xuse/ArcWAG.cs @@ -82,7 +82,7 @@ namespace GameRes.Formats.Xuse return arc.File.CreateStream (entry.Offset, entry.Size); var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); Decrypt ((uint)entry.Offset, warc.Key, data); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } static private byte[] GenerateKey (byte[] keyword) diff --git a/ArcFormats/Xuse/ArcXuse.cs b/ArcFormats/Xuse/ArcXuse.cs index 6e4d3c37..df8a4e90 100644 --- a/ArcFormats/Xuse/ArcXuse.cs +++ b/ArcFormats/Xuse/ArcXuse.cs @@ -185,7 +185,7 @@ namespace GameRes.Formats.Xuse { data[i] ^= key[i&0xF]; } - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } } diff --git a/ArcFormats/YuRis/ArcYPF.cs b/ArcFormats/YuRis/ArcYPF.cs index 2ead8653..6b6ccb97 100644 --- a/ArcFormats/YuRis/ArcYPF.cs +++ b/ArcFormats/YuRis/ArcYPF.cs @@ -138,7 +138,7 @@ namespace GameRes.Formats.YuRis { var packed_entry = entry as PackedEntry; var ypf = arc as YpfArchive; - Stream input = arc.File.CreateStream (entry.Offset, entry.Size); + Stream input = base.OpenEntry (arc, entry); if (null != packed_entry && packed_entry.IsPacked) input = new ZLibStream (input, CompressionMode.Decompress); uint unpacked_size = null == packed_entry ? entry.Size : packed_entry.UnpackedSize; @@ -151,7 +151,7 @@ namespace GameRes.Formats.YuRis input.Read (data, 0, data.Length); if (Binary.AsciiEqual (data, 0, "YSTB")) DecryptYstb (data, ypf.ScriptKey); - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } } diff --git a/ArcFormats/YuRis/ImageYCG.cs b/ArcFormats/YuRis/ImageYCG.cs index 0a310519..89135c1b 100644 --- a/ArcFormats/YuRis/ImageYCG.cs +++ b/ArcFormats/YuRis/ImageYCG.cs @@ -48,27 +48,25 @@ namespace GameRes.Formats.YuRis public override string Description { get { return "YU-RIS compressed image format"; } } public override uint Signature { get { return 0x474359; } } // 'YCG' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x38]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x38); return new YcgMetaData { - Width = LittleEndian.ToUInt32 (header, 4), - Height = LittleEndian.ToUInt32 (header, 8), - BPP = LittleEndian.ToInt32 (header, 12), - CompressionMethod = LittleEndian.ToInt32 (header, 0x10), - UnpackedSize1 = LittleEndian.ToInt32 (header, 0x20), - CompressedSize1 = LittleEndian.ToInt32 (header, 0x24), - UnpackedSize2 = LittleEndian.ToInt32 (header, 0x30), - CompressedSize2 = LittleEndian.ToInt32 (header, 0x34), + Width = header.ToUInt32 (4), + Height = header.ToUInt32 (8), + BPP = header.ToInt32 (12), + CompressionMethod = header.ToInt32 (0x10), + UnpackedSize1 = header.ToInt32 (0x20), + CompressedSize1 = header.ToInt32 (0x24), + UnpackedSize2 = header.ToInt32 (0x30), + CompressedSize2 = header.ToInt32 (0x34), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var reader = new YcgReader (stream, (YcgMetaData)info); + var reader = new YcgReader (stream.AsStream, (YcgMetaData)info); reader.Unpack(); return ImageData.Create (info, reader.Format, null, reader.Data); } diff --git a/ArcFormats/Yuka/ArcYKC.cs b/ArcFormats/Yuka/ArcYKC.cs index cd7175f1..99bdd42f 100644 --- a/ArcFormats/Yuka/ArcYKC.cs +++ b/ArcFormats/Yuka/ArcYKC.cs @@ -93,15 +93,14 @@ namespace GameRes.Formats.Yuka || !entry.Name.EndsWith (".yks", StringComparison.InvariantCultureIgnoreCase) || !arc.File.View.AsciiEqual (entry.Offset, "YKS001") || 1 != arc.File.View.ReadUInt16 (entry.Offset+6)) - return arc.File.CreateStream (entry.Offset, entry.Size); + return base.OpenEntry (arc, entry); // decrypt script contents - var data = new byte[entry.Size]; - arc.File.View.Read (entry.Offset, data, 0, entry.Size); + var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); uint text_offset = LittleEndian.ToUInt32 (data, 0x20); for (uint i = text_offset; i < data.Length; ++i) data[i] ^= 0xAA; data[6] = 0; - return new MemoryStream (data); + return new BinMemoryStream (data, entry.Name); } public override void Create (Stream output, IEnumerable list, ResourceOptions options, diff --git a/ArcFormats/Yuka/ImageYKG.cs b/ArcFormats/Yuka/ImageYKG.cs index ea93b4aa..421eb289 100644 --- a/ArcFormats/Yuka/ImageYKG.cs +++ b/ArcFormats/Yuka/ImageYKG.cs @@ -52,44 +52,43 @@ namespace GameRes.Formats.Yuka static readonly byte[] PngPrefix = new byte[4] { 0x89, 'P'^0, 'N'^0, 'G'^0 }; - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - var header = new byte[0x40]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - if (!Binary.AsciiEqual (header, 4, "00\0\0")) + var header = file.ReadHeader (0x40); + if (!header.AsciiEqual (4, "00\0\0")) return null; var ykg = new YkgMetaData { - DataOffset = LittleEndian.ToUInt32 (header, 0x28), - DataSize = LittleEndian.ToUInt32 (header, 0x2C) + DataOffset = header.ToUInt32 (0x28), + DataSize = header.ToUInt32 (0x2C) }; if (0 == ykg.DataOffset) - ykg.DataOffset = LittleEndian.ToUInt32 (header, 8); + ykg.DataOffset = header.ToUInt32 (8); if (ykg.DataOffset < 0x30) return null; if (0 == ykg.DataSize) - ykg.DataSize = (uint)(stream.Length - ykg.DataOffset); + ykg.DataSize = (uint)(file.Length - ykg.DataOffset); ImageMetaData info = null; - using (var img = new StreamRegion (stream, ykg.DataOffset, ykg.DataSize, true)) + using (var reg = new StreamRegion (file.AsStream, ykg.DataOffset, ykg.DataSize, true)) + using (var img = new BinaryStream (reg, file.Name)) { - if (4 != img.Read (header, 0, 4)) - return null; - if (Binary.AsciiEqual (header, "BM")) + var img_header = img.ReadHeader (4); + if (header.AsciiEqual ("BM")) { img.Position = 0; - info = ImageFormat.Bmp.ReadMetaData (img); + info = Bmp.ReadMetaData (img); ykg.Format = YkgImage.Bmp; } - else if (Binary.AsciiEqual (header, "\x89PNG")) + else if (header.AsciiEqual ("\x89PNG")) { img.Position = 0; info = Png.ReadMetaData (img); ykg.Format = YkgImage.Png; } - else if (Binary.AsciiEqual (header, "\x89GNP")) + else if (header.AsciiEqual ("\x89GNP")) { - using (var body = new StreamRegion (stream, ykg.DataOffset+4, ykg.DataSize-4, true)) - using (var png = new PrefixStream (PngPrefix, body)) + using (var body = new StreamRegion (file.AsStream, ykg.DataOffset+4, ykg.DataSize-4, true)) + using (var pre = new PrefixStream (PngPrefix, body)) + using (var png = new BinaryStream (pre, file.Name)) info = Png.ReadMetaData (png); ykg.Format = YkgImage.Gnp; } @@ -104,23 +103,24 @@ namespace GameRes.Formats.Yuka return ykg; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as YkgMetaData; - if (null == meta) - throw new ArgumentException ("YkgFormat.Read should be supplied with YkgMetaData", "info"); + var meta = (YkgMetaData)info; switch (meta.Format) { case YkgImage.Bmp: - using (var bmp = new StreamRegion (stream, meta.DataOffset, meta.DataSize, true)) + using (var reg = new StreamRegion (stream.AsStream, meta.DataOffset, meta.DataSize, true)) + using (var bmp = new BinaryStream (reg, stream.Name)) return Bmp.Read (bmp, info); case YkgImage.Png: - using (var png = new StreamRegion (stream, meta.DataOffset, meta.DataSize, true)) + using (var reg = new StreamRegion (stream.AsStream, meta.DataOffset, meta.DataSize, true)) + using (var png = new BinaryStream (reg, stream.Name)) return Png.Read (png, info); case YkgImage.Gnp: - using (var body = new StreamRegion (stream, meta.DataOffset+4, meta.DataSize-4, true)) - using (var png = new PrefixStream (PngPrefix, body)) + using (var body = new StreamRegion (stream.AsStream, meta.DataOffset+4, meta.DataSize-4, true)) + using (var pre = new PrefixStream (PngPrefix, body)) + using (var png = new BinaryStream (pre, stream.Name)) return Png.Read (png, info); default: throw new InvalidFormatException(); diff --git a/ArcFormats/Zyx/ArcBDF.cs b/ArcFormats/Zyx/ArcBDF.cs index 7c622378..d0a43142 100644 --- a/ArcFormats/Zyx/ArcBDF.cs +++ b/ArcFormats/Zyx/ArcBDF.cs @@ -222,7 +222,7 @@ namespace GameRes.Formats.Zyx var bdf = arc as BdfArchive; var frame = entry as BdfFrame; if (null == bdf || null == frame) - return arc.File.CreateStream (entry.Offset, entry.Size); + return base.OpenEntry (arc, entry); var pixels = bdf.ReadFrame (frame); var header = new byte[0x12]; diff --git a/ArcFormats/Zyx/ImageSPL.cs b/ArcFormats/Zyx/ImageSPL.cs index 30d11e7c..bd26100b 100644 --- a/ArcFormats/Zyx/ImageSPL.cs +++ b/ArcFormats/Zyx/ImageSPL.cs @@ -49,54 +49,48 @@ namespace GameRes.Formats.Zyx public override string Description { get { return "Zyx tiled image format"; } } public override uint Signature { get { return 0; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var reader = new ArcView.Reader (stream)) + int count = file.ReadInt16(); + if (count <= 0) + return null; + var tiles = new Tile[count]; + for (int i = 0; i < count; ++i) { - int count = reader.ReadInt16(); - if (count <= 0) + var tile = new Tile(); + tile.Left = file.ReadInt16(); + tile.Top = file.ReadInt16(); + if (tile.Left < 0 || tile.Top < 0) return null; - var tiles = new Tile[count]; - for (int i = 0; i < count; ++i) - { - var tile = new Tile(); - tile.Left = reader.ReadInt16(); - tile.Top = reader.ReadInt16(); - if (tile.Left < 0 || tile.Top < 0) - return null; - tile.Right = reader.ReadInt16(); - tile.Bottom = reader.ReadInt16(); - if (tile.Right <= tile.Left || tile.Bottom <= tile.Top) - return null; - tiles[i] = tile; - } - int width = reader.ReadInt16(); - int height = reader.ReadInt16(); - if (width <= 0 || height <= 0) + tile.Right = file.ReadInt16(); + tile.Bottom = file.ReadInt16(); + if (tile.Right <= tile.Left || tile.Bottom <= tile.Top) return null; - foreach (var tile in tiles) - { - if (tile.Right > width || tile.Bottom > height) - return null; - } - return new SplMetaData - { - Width = (uint)width, - Height = (uint)height, - BPP = 24, - Tiles = tiles, - DataOffset = stream.Position, - }; + tiles[i] = tile; } + int width = file.ReadInt16(); + int height = file.ReadInt16(); + if (width <= 0 || height <= 0) + return null; + foreach (var tile in tiles) + { + if (tile.Right > width || tile.Bottom > height) + return null; + } + return new SplMetaData + { + Width = (uint)width, + Height = (uint)height, + BPP = 24, + Tiles = tiles, + DataOffset = file.Position, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as SplMetaData; - if (null == meta) - throw new System.ArgumentException ("SplFormat.Read should be supplied with SplMetaData", "info"); - - var reader = new SplReader (stream, meta); + var meta = (SplMetaData)info; + var reader = new SplReader (stream.AsStream, meta); reader.Unpack (); return ImageData.Create (info, PixelFormats.Bgr24, null, reader.Data); } diff --git a/ArcFormats/elf/ImageG24.cs b/ArcFormats/elf/ImageG24.cs index 80d31362..5ef39e5e 100644 --- a/ArcFormats/elf/ImageG24.cs +++ b/ArcFormats/elf/ImageG24.cs @@ -38,33 +38,30 @@ namespace GameRes.Formats.Elf public override string Description { get { return "Ai5 engine RGB image format"; } } public override uint Signature { get { return 0; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream input) { - using (var input = new ArcView.Reader (stream)) - { - int x = input.ReadInt16(); - int y = input.ReadInt16(); - int w = input.ReadInt16(); - int h = input.ReadInt16(); - if (w <= 0 || w > 0x1000 || h <= 0 || h > 0x1000 - || x < 0 || x > 0x800 || y < 0 || y > 0x800) - return null; - return new ImageMetaData { - Width = (uint)w, - Height = (uint)h, - OffsetX = x, - OffsetY = y, - BPP = 24, - }; - } + int x = input.ReadInt16(); + int y = input.ReadInt16(); + int w = input.ReadInt16(); + int h = input.ReadInt16(); + if (w <= 0 || w > 0x1000 || h <= 0 || h > 0x1000 + || x < 0 || x > 0x800 || y < 0 || y > 0x800) + return null; + return new ImageMetaData { + Width = (uint)w, + Height = (uint)h, + OffsetX = x, + OffsetY = y, + BPP = 24, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { stream.Position = 8; int stride = (((int)info.Width * 3 + 3) & -4); var pixels = new byte[stride * (int)info.Height]; - using (var reader = new LzssStream (stream, LzssMode.Decompress, true)) + using (var reader = new LzssStream (stream.AsStream, LzssMode.Decompress, true)) { if (pixels.Length != reader.Read (pixels, 0, pixels.Length)) throw new InvalidFormatException(); diff --git a/ArcFormats/elf/ImageGCC.cs b/ArcFormats/elf/ImageGCC.cs index ff1b4033..58437006 100644 --- a/ArcFormats/elf/ImageGCC.cs +++ b/ArcFormats/elf/ImageGCC.cs @@ -52,34 +52,26 @@ namespace GameRes.Formats.Elf Signatures = new uint[] { 0x6d343252, 0x6E343252, 0x6D343247, 0x6E343247 }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[12]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; - + var header = stream.ReadHeader (12); return new GccMetaData { - Width = LittleEndian.ToUInt16 (header, 8), - Height = LittleEndian.ToUInt16 (header, 10), + Width = header.ToUInt16 (8), + Height = header.ToUInt16 (10), BPP = 'm' == header[3] ? 32 : 24, - OffsetX = LittleEndian.ToInt16 (header, 4), - OffsetY = LittleEndian.ToInt16 (header, 6), - Signature = LittleEndian.ToUInt32 (header, 0), + OffsetX = header.ToInt16 (4), + OffsetY = header.ToInt16 (6), + Signature = header.ToUInt32 (0), }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as GccMetaData; - if (null == meta) - throw new ArgumentException ("GccFormat.Read should be supplied with GccMetaData", "info"); - - var reader = new Reader (stream, meta); - { - reader.Unpack(); - return ImageData.Create (info, reader.Format, null, reader.Data); - } + var meta = (GccMetaData)info; + var reader = new Reader (stream.AsStream, meta); + reader.Unpack(); + return ImageData.Create (info, reader.Format, null, reader.Data); } public override void Write (Stream file, ImageData image) diff --git a/ArcFormats/elf/ImageGP8.cs b/ArcFormats/elf/ImageGP8.cs index c532ba8f..18192ccc 100644 --- a/ArcFormats/elf/ImageGP8.cs +++ b/ArcFormats/elf/ImageGP8.cs @@ -39,16 +39,14 @@ namespace GameRes.Formats.Elf public override string Description { get { return "Ai5 engine indexed image format"; } } public override uint Signature { get { return 0; } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - if (stream.Length <= 0x408) + if (file.Length <= 0x408) return null; - var header = new byte[8]; - stream.Read (header, 0, 8); - if (0 != LittleEndian.ToInt32 (header, 0)) + if (0 != file.ReadInt32()) return null; - int w = LittleEndian.ToInt16 (header, 4); - int h = LittleEndian.ToInt16 (header, 6); + int w = file.ReadInt16(); + int h = file.ReadInt16(); if (w <= 0 || w > 0x1000 || h <= 0 || h > 0x1000) return null; return new ImageMetaData { @@ -58,12 +56,12 @@ namespace GameRes.Formats.Elf }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { stream.Position = 8; - var palette = ReadPalette (stream); + var palette = ReadPalette (stream.AsStream); var pixels = new byte[info.Width * info.Height]; - using (var reader = new LzssStream (stream, LzssMode.Decompress, true)) + using (var reader = new LzssStream (stream.AsStream, LzssMode.Decompress, true)) { if (pixels.Length != reader.Read (pixels, 0, pixels.Length)) throw new InvalidFormatException(); @@ -103,32 +101,29 @@ namespace GameRes.Formats.Elf Extensions = new string[] { "msk" }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream input) { - using (var input = new ArcView.Reader (stream)) - { - int x = input.ReadInt16(); - int y = input.ReadInt16(); - int w = input.ReadInt16(); - int h = input.ReadInt16(); - if (w <= 0 || w > 0x1000 || h <= 0 || h > 0x1000 - || x < 0 || x > 0x800 || y < 0 || y > 0x800) - return null; - return new ImageMetaData { - Width = (uint)w, - Height = (uint)h, - OffsetX = x, - OffsetY = y, - BPP = 8, - }; - } + int x = input.ReadInt16(); + int y = input.ReadInt16(); + int w = input.ReadInt16(); + int h = input.ReadInt16(); + if (w <= 0 || w > 0x1000 || h <= 0 || h > 0x1000 + || x < 0 || x > 0x800 || y < 0 || y > 0x800) + return null; + return new ImageMetaData { + Width = (uint)w, + Height = (uint)h, + OffsetX = x, + OffsetY = y, + BPP = 8, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { stream.Position = 8; var pixels = new byte[info.Width * info.Height]; - using (var reader = new LzssStream (stream, LzssMode.Decompress, true)) + using (var reader = new LzssStream (stream.AsStream, LzssMode.Decompress, true)) { if (pixels.Length != reader.Read (pixels, 0, pixels.Length)) throw new InvalidFormatException(); diff --git a/ArcFormats/elf/ImageGPH.cs b/ArcFormats/elf/ImageGPH.cs index 71246bee..f132e2d8 100644 --- a/ArcFormats/elf/ImageGPH.cs +++ b/ArcFormats/elf/ImageGPH.cs @@ -119,12 +119,12 @@ namespace GameRes.Formats.Elf public void Unpack () { - m_input.BaseStream.Position = m_info.DataOffset+2; + m_input.Position = m_info.DataOffset+2; if (0 == (m_info.Flags & 4)) ReadPalette(); else SetDefaultPalette(); - m_input.BaseStream.Seek (8, SeekOrigin.Current); + m_input.Seek (8, SeekOrigin.Current); int stride = Stride; if (stride <= 0x10) @@ -379,7 +379,7 @@ namespace GameRes.Formats.Elf void ReadNext () { bits &= 0xFF00; - int b = m_input.BaseStream.ReadByte(); + int b = m_input.ReadByte(); if (-1 != b) bits |= b; } diff --git a/ArcFormats/elf/ImageHIZ.cs b/ArcFormats/elf/ImageHIZ.cs index 031ce9b1..1ebfb668 100644 --- a/ArcFormats/elf/ImageHIZ.cs +++ b/ArcFormats/elf/ImageHIZ.cs @@ -46,43 +46,38 @@ namespace GameRes.Formats.Elf public override string Description { get { return "elf bitmap format"; } } public override uint Signature { get { return 0x007A6968; } } // 'hiz' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var input = new ArcView.Reader (stream)) // sub_4BF900 + file.Position = 4; + int n = file.ReadInt32(); + if (100 != n) + return null; + uint right = file.ReadUInt32() ^ 0xAA5A5A5A; + uint bottom = file.ReadUInt32() ^ 0xAC9326AF; + int unknown1 = file.ReadInt32(); // @0x10 + if (unknown1 == 0x375A8436) + return null; + uint unpacked_size = file.ReadUInt32() ^ 0x19739D6A; // @0x14 + if (unpacked_size != right*bottom*4) + return null; + return new HizMetaData { - input.ReadInt32(); - int n = input.ReadInt32(); - if (100 != n) - return null; - uint right = input.ReadUInt32() ^ 0xAA5A5A5A; - uint bottom = input.ReadUInt32() ^ 0xAC9326AF; - int unknown1 = input.ReadInt32(); // @0x10 - if (unknown1 == 0x375A8436) - return null; - uint unpacked_size = input.ReadUInt32() ^ 0x19739D6A; // @0x14 - if (unpacked_size != right*bottom*4) - return null; - return new HizMetaData - { - Width = right, - Height = bottom, - BPP = 32, - IsPacked = true, - DataOffset = 0x4c, - UnpackedSize = unpacked_size, - }; - } + Width = right, + Height = bottom, + BPP = 32, + IsPacked = true, + DataOffset = 0x4c, + UnpackedSize = unpacked_size, + }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream stream, ImageMetaData info) { - var meta = info as HizMetaData; - if (null == meta) - throw new ArgumentException ("HizFormat.Read should be supplied with HizMetaData", "info"); + var meta = (HizMetaData)info; var pixels = new byte[meta.UnpackedSize]; stream.Position = meta.DataOffset; - using (var lzss = new LzssStream (stream, LzssMode.Decompress, true)) + using (var lzss = new LzssStream (stream.AsStream, LzssMode.Decompress, true)) { var channel = new byte[info.Width*info.Height]; for (int p = 0; p < 4; ++p) @@ -110,24 +105,22 @@ namespace GameRes.Formats.Elf public override string Description { get { return "elf composite image format"; } } public override uint Signature { get { return 0x00706968; } } // 'hip' - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - byte[] header = new byte[0x18]; - if (0x18 != stream.Read (header, 0, 0x18)) - return null; + var header = stream.ReadHeader (0x18); int index_offset = 0xC; - uint first_offset = LittleEndian.ToUInt32 (header, index_offset); + uint first_offset = header.ToUInt32 (index_offset); if (0 == first_offset) { index_offset += 4; - first_offset = LittleEndian.ToUInt32 (header, index_offset); + first_offset = header.ToUInt32 (index_offset); if (0 == first_offset) return null; } index_offset += 4; long first_length; - uint second_offset = LittleEndian.ToUInt32 (header, index_offset); + uint second_offset = header.ToUInt32 (index_offset); if (0 == second_offset) first_length = stream.Length - first_offset; else if (second_offset < first_offset) @@ -135,7 +128,8 @@ namespace GameRes.Formats.Elf else first_length = second_offset - first_offset; - using (var hiz = new StreamRegion (stream, first_offset, first_length, true)) + using (var reg = new StreamRegion (stream.AsStream, first_offset, first_length, true)) + using (var hiz = new BinaryStream (reg, stream.Name)) { var info = base.ReadMetaData (hiz); (info as HizMetaData).DataOffset += 0x18; diff --git a/ArcFormats/uGOS/ArcDET.cs b/ArcFormats/uGOS/ArcDET.cs index 85104a08..b4445e94 100644 --- a/ArcFormats/uGOS/ArcDET.cs +++ b/ArcFormats/uGOS/ArcDET.cs @@ -87,7 +87,7 @@ namespace GameRes.Formats.uGOS using (var input = arc.File.CreateStream (entry.Offset, entry.Size)) { if (Unpack (input, output)) - return new MemoryStream (output); + return new BinMemoryStream (output, entry.Name); else return base.OpenEntry (arc, entry); } diff --git a/ArcFormats/uGOS/ImageBMP.cs b/ArcFormats/uGOS/ImageBMP.cs index 03916e80..ebbaa455 100644 --- a/ArcFormats/uGOS/ImageBMP.cs +++ b/ArcFormats/uGOS/ImageBMP.cs @@ -44,22 +44,20 @@ namespace GameRes.Formats.uGOS Signatures = new uint[] { 0x206546, 0x186546 }; } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { - var header = new byte[0x10]; - if (header.Length != stream.Read (header, 0, header.Length)) - return null; + var header = stream.ReadHeader (0x10); return new ImageMetaData { - Width = LittleEndian.ToUInt16 (header, 4), - Height = LittleEndian.ToUInt16 (header, 6), + Width = header.ToUInt16 (4), + Height = header.ToUInt16 (6), BPP = header[2], }; } - public override ImageData Read (Stream stream, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { - using (var reader = new Reader (stream, info)) + using (var reader = new Reader (file, info)) { reader.Unpack(); return ImageData.CreateFlipped (info, reader.Format, null, reader.Data, reader.Stride); @@ -73,7 +71,7 @@ namespace GameRes.Formats.uGOS internal sealed class Reader : IDisposable { - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; int m_width; int m_height; @@ -83,9 +81,9 @@ namespace GameRes.Formats.uGOS public byte[] Data { get { return m_output; } } public int Stride { get; private set; } - public Reader (Stream input, ImageMetaData info) + public Reader (IBinaryStream input, ImageMetaData info) { - m_input = new ArcView.Reader (input); + m_input = input; m_width = (int)info.Width; m_height = (int)info.Height; m_bpp = info.BPP; @@ -122,7 +120,7 @@ namespace GameRes.Formats.uGOS public void Unpack () { - m_input.BaseStream.Position = 0x10; + m_input.Position = 0x10; InitTable1(); InitTable2(); InitTable3(); @@ -183,10 +181,10 @@ namespace GameRes.Formats.uGOS if (0 == v35) { // v60 = (((src1[2] + ((src1[1] + (*src1 << 8)) << 8)) << 8) ^ 0x80000080u) >> byte_4CBA80[v38]; - uint v60 = (uint)m_input.ReadByte() << 16; + uint v60 = (uint)m_input.ReadUInt8() << 16; uint v38 = m_bits & 0xFF; - v60 |= (uint)m_input.ReadByte () << 8; - v60 |= m_input.ReadByte (); + v60 |= (uint)m_input.ReadUInt8 () << 8; + v60 |= m_input.ReadUInt8 (); v60 <<= 8; v60 = (v60 ^ 0x80000080u) >> byte_4CBA80[v38]; m_bits = v60; @@ -208,7 +206,7 @@ namespace GameRes.Formats.uGOS int d; if (0x80 == (m_bits & 0xFF)) { - byte n = m_input.ReadByte(); + byte n = m_input.ReadUInt8(); d = n >> 7; m_bits = (uint)(n << 1 | 1); } @@ -260,7 +258,7 @@ namespace GameRes.Formats.uGOS int v23 = byte_4CAD28[2 * m_bits + 1]; while (0 == v23) { - int b = m_input.ReadByte(); + int b = m_input.ReadUInt8(); v26 += byte_4CAF28[2 * b]; v23 = byte_4CAF28[2 * b + 1]; } @@ -269,12 +267,12 @@ namespace GameRes.Formats.uGOS if (v26 - v27 > 0) { uint v29 = (uint)(v26 - v27 - 1); - int v30 = m_input.ReadByte() + (int)((v28 << v27) & 0xFFFFFF00); + int v30 = m_input.ReadUInt8() + (int)((v28 << v27) & 0xFFFFFF00); if ((int)v29 >= 8) { for (uint v31 = v29 >> 3; v31 != 0; --v31) { - v30 = (v30 << 8) | m_input.ReadByte(); + v30 = (v30 << 8) | m_input.ReadUInt8(); } v29 -= 8 * (v29 >> 3); } @@ -305,13 +303,13 @@ namespace GameRes.Formats.uGOS uint v7 = ((uint)(v5 - 9) >> 3) + 1; do { - v6 = m_input.ReadByte() + (v6 << 8); + v6 = m_input.ReadUInt8() + (v6 << 8); v5 -= 8; --v7; } while (0 != v7); } - m_bits = m_input.ReadByte(); + m_bits = m_input.ReadUInt8(); alpha = (uint)((v6 << v5) + (m_bits >> (8 - v5))); m_bits = ((m_bits << v5) + (1u << (v5 - 1))) & 0xFFu; } @@ -326,7 +324,7 @@ namespace GameRes.Formats.uGOS uint v4 = byte_4CAD28[2 * v2 + 1]; while (0 == v4) { - v2 = m_input.ReadByte(); + v2 = m_input.ReadUInt8(); i += byte_4CAF28[2 * v2]; v4 = byte_4CAF28[2 * v2 + 1]; } @@ -345,11 +343,11 @@ namespace GameRes.Formats.uGOS { for (uint v8 = ((uint)(v6 - 9) >> 3) + 1; v8 != 0; --v8) { - v7 = (v7 << 8) | m_input.ReadByte(); + v7 = (v7 << 8) | m_input.ReadUInt8(); } v6 += -8 * (int)(((uint)(v6 - 9) >> 3) + 1); } - m_bits = m_input.ReadByte(); + m_bits = m_input.ReadUInt8(); uint n = (v7 << v6) + (m_bits >> (8 - v6)); m_bits = (m_bits << v6) + (1u << (v6 - 1)); return (int)n - 2; @@ -433,14 +431,8 @@ namespace GameRes.Formats.uGOS } #region IDisposable Members - bool _disposed = false; public void Dispose () { - if (!_disposed) - { - m_input.Dispose(); - _disposed = true; - } } #endregion } diff --git a/GameRes/ArcView.cs b/GameRes/ArcView.cs index fd2efa82..522d5d46 100644 --- a/GameRes/ArcView.cs +++ b/GameRes/ArcView.cs @@ -232,9 +232,9 @@ namespace GameRes return new ArcStream (this, offset, (uint)size); } - public ArcStream CreateStream (long offset, uint size) + public ArcStream CreateStream (long offset, uint size, string name = null) { - return new ArcStream (this, offset, size); + return new ArcStream (this, offset, size, name); } public MemoryMappedViewAccessor CreateViewAccessor (long offset, uint size) @@ -510,27 +510,30 @@ namespace GameRes m_start = 0; m_size = file.MaxOffset; m_position = 0; + Name = file.Name; } - public ArcStream (Frame view) + public ArcStream (Frame view, string name = null) { m_view = view; m_start = m_view.Offset; m_size = m_view.Reserved; m_position = 0; + Name = name ?? ""; } - public ArcStream (ArcView file, long offset, uint size) - : this (new Frame (file, offset, size)) + public ArcStream (ArcView file, long offset, uint size, string name = null) + : this (new Frame (file, offset, size), name) { } - public ArcStream (Frame view, long offset, uint size) + public ArcStream (Frame view, long offset, uint size, string name = null) { m_view = view; m_start = offset; m_size = Math.Min (size, m_view.Reserve (offset, size)); m_position = 0; + Name = name ?? ""; } ///

@@ -573,7 +576,7 @@ namespace GameRes return b; } - public sbyte ReadSByte () + public sbyte ReadInt8 () { int b = ReadByte(); if (-1 == b) @@ -581,6 +584,11 @@ namespace GameRes return (sbyte)b; } + public byte ReadUInt8 () + { + return (byte)ReadInt8(); + } + public short ReadInt16 () { if (m_position + 2 > m_size) diff --git a/GameRes/BinaryStream.cs b/GameRes/BinaryStream.cs index 67238406..0706dbec 100644 --- a/GameRes/BinaryStream.cs +++ b/GameRes/BinaryStream.cs @@ -43,6 +43,7 @@ namespace GameRes /// uint Signature { get; } Stream AsStream { get; } + bool CanSeek { get; } long Length { get; } long Position { get; set; } @@ -57,7 +58,8 @@ namespace GameRes /// Next byte, or -1 if end of stream is reached. int PeekByte (); - sbyte ReadSByte (); + sbyte ReadInt8 (); + byte ReadUInt8 (); short ReadInt16 (); ushort ReadUInt16 (); int ReadInt24 (); @@ -102,127 +104,6 @@ namespace GameRes byte[] ReadBytes (int count); } - /// - /// Array segment with copy-on-write semantics. - /// - public struct CowArray : IReadOnlyList - { - T[] m_source; - int m_offset; - int m_count; - bool m_own_copy; - - public CowArray (T[] src) : this (src, 0, src.Length) - { - } - - public CowArray (T[] src, int start, int length) - { - m_source = src; - m_offset = start; - m_count = length; - m_own_copy = false; - } - - public int Count { get { return m_count; } } - public int Length { get { return Count; } } - public T this[int pos] - { - get { return m_source[m_offset+pos]; } - set - { - if (!m_own_copy) - { - Reclaim(); - } - m_source[pos] = value; - } - } - - public IEnumerator GetEnumerator () - { - for (int i = 0; i < m_count; ++i) - yield return m_source[m_offset + i]; - } - - IEnumerator IEnumerable.GetEnumerator () - { - return GetEnumerator(); - } - - public T[] ToArray () - { - if (m_own_copy) - return m_source; - var copy = new T[m_count]; - Array.Copy (m_source, m_offset, copy, 0, m_count); - return copy; - } - - internal void Reclaim () - { - m_source = ToArray(); - m_offset = 0; - m_own_copy = true; - } - } - - public static class CowByteArray - { - public static ushort ToUInt16 (this CowArray arr, int index) - { - return (ushort)(arr[index] | arr[index+1] << 8); - } - - public static short ToInt16 (this CowArray arr, int index) - { - return (short)(arr[index] | arr[index+1] << 8); - } - - public static int ToInt24 (this CowArray arr, int index) - { - return arr[index] | arr[index+1] << 8 | arr[index+2] << 16; - } - - public static uint ToUInt32 (this CowArray arr, int index) - { - return (uint)(arr[index] | arr[index+1] << 8 | arr[index+2] << 16 | arr[index+3] << 24); - } - - public static int ToInt32 (this CowArray arr, int index) - { - return (int)ToUInt32 (arr, index); - } - - public static ulong ToUInt64 (this CowArray arr, int index) - { - return (ulong)ToUInt32 (arr, index) | ((ulong)ToUInt32 (arr, index+4) << 32); - } - - public static long ToInt64 (this CowArray arr, int index) - { - return (long)ToUInt64 (arr, index); - } - - public static bool AsciiEqual (this CowArray arr, int index, string str) - { - arr.Reclaim(); - return Binary.AsciiEqual (arr.ToArray(), index, str); - } - - public static bool AsciiEqual (this CowArray arr, string str) - { - arr.Reclaim(); - return Binary.AsciiEqual (arr.ToArray(), str); - } - - public static string GetCString (this CowArray arr, int index, int length_limit) - { - arr.Reclaim(); - return Binary.GetCString (arr.ToArray(), index, length_limit); - } - } - public class BinaryStream : Stream, IBinaryStream { Stream m_source; @@ -238,9 +119,9 @@ namespace GameRes public uint Signature { get { return m_signature.Value; } } public Stream AsStream { get { return this; } } - public BinaryStream (Stream input, bool leave_open = false) : this (input, "", leave_open) - { - } +// public BinaryStream (Stream input, bool leave_open = false) : this (input, "", leave_open) +// { +// } public BinaryStream (Stream input, string name, bool leave_open = false) { @@ -266,12 +147,24 @@ namespace GameRes } } - public static BinaryStream FromFile (string filename) + public static IBinaryStream FromFile (string filename) { var stream = File.OpenRead (filename); return new BinaryStream (stream, filename); } + public static IBinaryStream FromArray (byte[] data, string filename) + { + return new BinMemoryStream (data, filename); + } + + public static IBinaryStream FromStream (Stream input, string filename) + { + if (input is IBinaryStream) + return input as IBinaryStream; + return new BinaryStream (input, filename); + } + uint ReadSignature () { if (m_header_size >= 4) @@ -338,13 +231,18 @@ namespace GameRes return m_buffer[m_buffer_pos]; } - public sbyte ReadSByte () + public sbyte ReadInt8 () { if (1 != FillBuffer (1)) throw new EndOfStreamException(); return (sbyte)m_buffer[m_buffer_pos++]; } + public byte ReadUInt8 () + { + return (byte)ReadInt8(); + } + public short ReadInt16 () { if (2 != FillBuffer (2)) @@ -549,4 +447,239 @@ namespace GameRes } #endregion } + + public class BinMemoryStream : Stream, IBinaryStream + { + byte[] m_source; + int m_start; + int m_length; + int m_position; + uint m_signature; + + public string Name { get; private set; } + public uint Signature { get { return m_signature; } } + public Stream AsStream { get { return this; } } + + public BinMemoryStream (byte[] input, string name) : this (input, 0, input.Length, name) + { } + + public BinMemoryStream (byte[] input, int pos, int length, string name) + { + m_source = input; + m_start = pos; + m_length = length; + Init (name); + } + + public BinMemoryStream (MemoryStream input, string name) + { + try + { + m_source = input.GetBuffer(); + if (null == m_source) + m_source = new byte[0]; + } + catch (UnauthorizedAccessException) + { + m_source = input.ToArray(); + } + m_start = 0; + m_length = (int)input.Length; + Init (name); + } + + void Init (string name) + { + m_position = 0; + Name = name ?? ""; + if (m_length >= 4) + m_signature = LittleEndian.ToUInt32 (m_source, 0); + } + + public CowArray ReadHeader (int size) + { + if (size > m_length) + { + m_position = m_length; + throw new EndOfStreamException(); + } + m_position = size; + return new CowArray (m_source, m_start, size); + } + + public int PeekByte () + { + if (m_position >= m_length) + return -1; + return m_source[m_start+m_position]; + } + + public sbyte ReadInt8 () + { + if (m_position >= m_length) + throw new EndOfStreamException(); + return (sbyte)m_source[m_start+m_position++]; + } + + public byte ReadUInt8 () + { + return (byte)ReadInt8(); + } + + public short ReadInt16 () + { + if (m_length - m_position < 2) + throw new EndOfStreamException(); + short v = LittleEndian.ToInt16 (m_source, m_start+m_position); + m_position += 2; + return v; + } + + public ushort ReadUInt16 () + { + return (ushort)ReadInt16(); + } + + public int ReadInt24 () + { + if (m_length - m_position < 3) + throw new EndOfStreamException(); + int v = LittleEndian.ToUInt16 (m_source, m_start+m_position); + v |= m_source[m_start+m_position+2] << 16; + m_position += 3; + return v; + } + + public int ReadInt32 () + { + if (m_length - m_position < 4) + throw new EndOfStreamException(); + int v = LittleEndian.ToInt32 (m_source, m_start+m_position); + m_position += 4; + return v; + } + + public uint ReadUInt32 () + { + return (uint)ReadInt32(); + } + + public long ReadInt64 () + { + if (m_length - m_position < 8) + throw new EndOfStreamException(); + long v = LittleEndian.ToInt64 (m_source, m_start+m_position); + m_position += 8; + return v; + } + + public ulong ReadUInt64 () + { + return (ulong)ReadInt64(); + } + + public string ReadCString (int length) + { + return ReadCString (length, Encodings.cp932); + } + + public string ReadCString (int length, Encoding enc) + { + length = Math.Min (length, m_length - m_position); + int i = Array.IndexOf (m_source, 0, m_start+m_position, length); + if (-1 == i) + i = length; + string s = enc.GetString (m_source, m_start+m_position, i); + m_position += length; + return s; + } + + public string ReadCString () + { + return ReadCString (Encodings.cp932); + } + + public string ReadCString (Encoding enc) + { + int start = m_start+m_position; + int count = Array.IndexOf (m_source, 0, start, m_length-m_position); + if (-1 == count) + { + count = m_length - m_position; + m_position = m_length; + } + else + { + m_position += count + 1; + } + return enc.GetString (m_source, start, count); + } + + public byte[] ReadBytes (int count) + { + count = Math.Min (count, m_length - m_position); + var buffer = new byte[count]; + Buffer.BlockCopy (m_source, m_start+m_position, buffer, 0, count); + return buffer; + } + + #region IO.Stream Members + public override bool CanRead { get { return true; } } + public override bool CanSeek { get { return true; } } + public override bool CanWrite { get { return false; } } + public override long Length { get { return m_length; } } + public override long Position + { + get { return m_position; } + set { m_position = (int)Math.Max (Math.Min (m_length, value), 0); } + } + + public override int Read (byte[] buffer, int offset, int count) + { + count = Math.Min (count, m_length - m_position); + Buffer.BlockCopy (m_source, m_start+m_position, buffer, offset, count); + m_position += count; + return count; + } + + public override int ReadByte () + { + if (m_position < m_length) + return m_source[m_start+m_position++]; + else + return -1; + } + + public override void Flush() + { + } + + public override long Seek (long offset, SeekOrigin origin) + { + if (SeekOrigin.Begin == origin) + Position = offset; + else if (SeekOrigin.Current == origin) + Position = m_position + offset; + else + Position = Length + offset; + + return m_position; + } + + public override void SetLength (long length) + { + throw new NotSupportedException ("BinaryStream.SetLength method is not supported"); + } + + public override void Write (byte[] buffer, int offset, int count) + { + throw new NotSupportedException ("BinaryStream.Write method is not supported"); + } + + public override void WriteByte (byte value) + { + throw new NotSupportedException ("BinaryStream.WriteByte method is not supported"); + } + #endregion + } } diff --git a/GameRes/ByteArray.cs b/GameRes/ByteArray.cs new file mode 100644 index 00000000..b9352405 --- /dev/null +++ b/GameRes/ByteArray.cs @@ -0,0 +1,196 @@ +//! \file ByteArray.cs +//! \date Sun Oct 16 06:25:52 2016 +//! \brief specialized collection for copy-on-write byte arrays. +// +// Copyright (C) 2016 by morkt +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +using System; +using System.Collections; +using System.Collections.Generic; +using GameRes.Utility; + +namespace GameRes +{ + /// + /// Array segment with copy-on-write semantics. + /// + public struct CowArray : IList + { + T[] m_source; + int m_offset; + int m_count; + bool m_own_copy; + + public CowArray (T[] src) : this (src, 0, src.Length) + { + } + + public CowArray (T[] src, int start, int length) + { + m_source = src; + m_offset = start; + m_count = length; + m_own_copy = false; + } + + public int Count { get { return m_count; } } + public int Length { get { return Count; } } + public bool IsReadOnly { get { return true; } } + public T this[int pos] + { + get { return m_source[m_offset+pos]; } + set + { + if (!m_own_copy) + { + Reclaim(); + } + m_source[pos] = value; + } + } + + public int IndexOf (T item) + { + return Array.IndexOf (m_source, item, m_offset, m_count); + } + + public bool Contains (T item) + { + return IndexOf (item) != -1; + } + + public void CopyTo (T[] arr, int dst) + { + Array.Copy (m_source, m_offset, arr, dst, m_count); + } + + public IEnumerator GetEnumerator () + { + for (int i = 0; i < m_count; ++i) + yield return m_source[m_offset + i]; + } + + IEnumerator IEnumerable.GetEnumerator () + { + return GetEnumerator(); + } + + public T[] ToArray () + { + if (m_own_copy) + return m_source; + var copy = new T[m_count]; + Array.Copy (m_source, m_offset, copy, 0, m_count); + return copy; + } + + internal void Reclaim () + { + m_source = ToArray(); + m_offset = 0; + m_own_copy = true; + } + + #region Not supported methods + public void Insert (int index, T item) + { + throw new NotSupportedException(); + } + + public bool Remove (T item) + { + throw new NotSupportedException(); + } + + public void RemoveAt (int index) + { + throw new NotSupportedException(); + } + + public void Add (T item) + { + throw new NotSupportedException(); + } + + public void Clear () + { + throw new NotSupportedException(); + } + #endregion + } + + public static class ByteArrayExt + { + public static ushort ToUInt16 (this CowArray arr, int index) + { + return (ushort)(arr[index] | arr[index+1] << 8); + } + + public static short ToInt16 (this CowArray arr, int index) + { + return (short)(arr[index] | arr[index+1] << 8); + } + + public static int ToInt24 (this CowArray arr, int index) + { + return arr[index] | arr[index+1] << 8 | arr[index+2] << 16; + } + + public static uint ToUInt32 (this TArray arr, int index) where TArray : IList + { + return (uint)(arr[index] | arr[index+1] << 8 | arr[index+2] << 16 | arr[index+3] << 24); + } + + public static int ToInt32 (this TArray arr, int index) where TArray : IList + { + return (int)ToUInt32 (arr, index); + } + + public static ulong ToUInt64 (this CowArray arr, int index) + { + return (ulong)ToUInt32 (arr, index) | ((ulong)ToUInt32 (arr, index+4) << 32); + } + + public static long ToInt64 (this CowArray arr, int index) + { + return (long)ToUInt64 (arr, index); + } + + public static bool AsciiEqual (this CowArray arr, int index, string str) + { + arr.Reclaim(); + return Binary.AsciiEqual (arr.ToArray(), index, str); + } + + public static bool AsciiEqual (this CowArray arr, string str) + { + arr.Reclaim(); + return Binary.AsciiEqual (arr.ToArray(), str); + } + + public static string GetCString (this CowArray arr, int index, int length_limit) + { + arr.Reclaim(); + return Binary.GetCString (arr.ToArray(), index, length_limit); + } + } +} diff --git a/GameRes/GameRes.cs b/GameRes/GameRes.cs index f4a969ad..c8da1a68 100644 --- a/GameRes/GameRes.cs +++ b/GameRes/GameRes.cs @@ -194,7 +194,7 @@ namespace GameRes /// public virtual Stream OpenEntry (ArcFile arc, Entry entry) { - return arc.File.CreateStream (entry.Offset, entry.Size); + return arc.File.CreateStream (entry.Offset, entry.Size, entry.Name); } /// diff --git a/GameRes/GameRes.csproj b/GameRes/GameRes.csproj index d44ee8ab..0e6fa073 100644 --- a/GameRes/GameRes.csproj +++ b/GameRes/GameRes.csproj @@ -67,6 +67,7 @@ + diff --git a/GameRes/Utility.cs b/GameRes/Utility.cs index 594fc7a3..69cce941 100644 --- a/GameRes/Utility.cs +++ b/GameRes/Utility.cs @@ -23,6 +23,7 @@ // IN THE SOFTWARE. // +using System.Collections.Generic; using System.Text; namespace GameRes.Utility @@ -145,22 +146,22 @@ namespace GameRes.Utility public static class BigEndian { - public static ushort ToUInt16 (byte[] value, int index) + public static ushort ToUInt16 (TArray value, int index) where TArray : IList { return (ushort)(value[index] << 8 | value[index+1]); } - public static short ToInt16 (byte[] value, int index) + public static short ToInt16 (TArray value, int index) where TArray : IList { return (short)(value[index] << 8 | value[index+1]); } - public static uint ToUInt32 (byte[] value, int index) + public static uint ToUInt32 (TArray value, int index) where TArray : IList { return (uint)(value[index] << 24 | value[index+1] << 16 | value[index+2] << 8 | value[index+3]); } - public static int ToInt32 (byte[] value, int index) + public static int ToInt32 (TArray value, int index) where TArray : IList { return (int)ToUInt32 (value, index); } @@ -178,7 +179,7 @@ namespace GameRes.Utility return (short)(value[index] | value[index+1] << 8); } - public static uint ToUInt32 (byte[] value, int index) + public static uint ToUInt32 (TArray value, int index) where TArray : IList { return (uint)(value[index] | value[index+1] << 8 | value[index+2] << 16 | value[index+3] << 24); }