金庸群俠傳資源壓縮資料結構研究

來源:互聯網
上載者:User

金庸群俠傳是智冠科技90年代出品的精品DOS遊戲,

 

其資源壓縮包格式緊湊而科學,這裡我們一起學習一下其資料結構。並且編寫一個能夠讀取解析它的程式,

 

 

 

以下是我對 Hdgrp資源檔解包的運行結果展示

下面我們看一下資源類型:

 

其資源套件括 idx和grp檔案,idx記錄了各個資源的索引、grp(group pictures?)儲存了具體資料。

 

另外以Mmap.col作為整體的調色盤,儲存各種顏色資料。

 

idx檔案每4個byte為一個section,每個section記錄一個資源圖片的endoffset,即又是下一個資源圖片的startoffset。

 

----------

int32  |  endoffset

 

grp檔案,以idx檔案為基準,按offset區間劃分儲存圖片,每個圖片資源:

 

---------

int16 | w

int16 | h

int16 | x (不知道有什麼用)

int16 | y(不知道有什麼用)

以下h行,每行支援多個section,每個section資料結構

----------

int8 | 該行位元組數

[section]

int8 | t 透明像素點個數

int8 | nt 非透明像素點個數

nt * int8 | 該點對應調色盤資料,如1,則對應調色盤第一個顏色值

 

 

調色盤檔案Mmap.col

一共256*3 byte,256色,每個顏色按rgb 除以4存放,按順序存放

----------

byte | r

byte | g

byte | b

 

這樣就可以解每個資源檔了。下面是部分核心的C#代碼,我使用WPF的bitmapimage進行渲染。

 

 

 

    class GameResource    {        #region 單例        static public GameResource Instance        {            get            {                if(_instance==null){                    _instance = new GameResource();                    }                return _instance;            }        }        static GameResource _instance = null;        private GameResource()        {            ImageFiles = new Dictionary<string, List<Image>>();        }        #endregion        public Dictionary<string, List<Image>> ImageFiles;    }    .............

        /// <summary>        /// 初始化調色盤        /// </summary>        public void InitColors()         {            FileStream f = new FileStream("data/Mmap.col", FileMode.Open);            BinaryReader reader = new BinaryReader(f);            for (int i = 0; i < 256; ++i)            {                byte[] color = reader.ReadBytes(3);                for (int j = 0; j < color.Length; ++j)                {                    color[j] = (byte)((int)color[j] * 4);                }                colorMap[i] = color;            }            reader.Close();            f.Close();        }        Dictionary<int, byte[]> colorMap = new Dictionary<int, byte[]>();        private BitmapImage ReadImage(BinaryReader reader, int length)        {            int w = reader.ReadInt16();            int h = reader.ReadInt16();            int x = reader.ReadInt16();            int y = reader.ReadInt16();            List<System.Windows.Media.Color> colors = new List<System.Windows.Media.Color>();            colors.Add(System.Windows.Media.Colors.Blue);            colors.Add(System.Windows.Media.Colors.Green);            colors.Add(System.Windows.Media.Colors.Red);                        BitmapPalette palette = new BitmapPalette(colors);            PixelFormat pf = PixelFormats.Bgra32;            int stride = (w * pf.BitsPerPixel + 7) / 8;            byte[] pixels = new byte[h * stride];            for (int i = 0; i < pixels.Length; ++i)            {                pixels[i] = 0x00;            }            int p = 0;            try            {                for (int i = 0; i < h; ++i) //H行                {                    p = i * w * pf.BitsPerPixel / 8;                    int count = reader.ReadByte(); //該行位元組數                    int offset = 0;                    while (offset < count)                    {                        int transparentPixs = reader.ReadByte(); //透明像素個數                        offset++;                        p += transparentPixs * pf.BitsPerPixel / 8;                        int nonTransPix = reader.ReadByte(); //非透明像素個數                        offset++;                        for (int j = 0; j < nonTransPix; ++j)                        {                            int colorKey = reader.ReadByte();                            pixels[p] = colorMap[colorKey][2]; //b                            p++;                            pixels[p] = colorMap[colorKey][1]; //g                            p++;                            pixels[p] = colorMap[colorKey][0]; //r                            p++;                            pixels[p] = 0xFF; //a                            p++;                            offset++;                        }                    }                }            }            catch (Exception e)            {                MessageBox.Show(p.ToString());            }                        BitmapSource image = BitmapSource.Create(                w,                h,                96,                96,                pf,                palette,                pixels,                stride);            PngBitmapEncoder encoder = new PngBitmapEncoder();                        MemoryStream memoryStream = new MemoryStream();            BitmapImage bImg = new BitmapImage();            encoder.Frames.Add(BitmapFrame.Create(image));            encoder.Save(memoryStream);            bImg.BeginInit();            bImg.StreamSource = new MemoryStream(memoryStream.ToArray());            bImg.EndInit();            memoryStream.Close();            return bImg;        }        public List<Image> LoadImages(string filename)        {            List<Image> rst = new List<Image>();            FileStream f = new FileStream(filename + ".idx", FileMode.Open);            BinaryReader reader = new BinaryReader(f);            FileStream gf = new FileStream(filename + ".grp", FileMode.Open);            BinaryReader greader = new BinaryReader(gf);            try            {                int startOffset = 0;                while (f.CanRead)                {                    int endOffset = reader.ReadInt32();                    Image image = new Image();                    image.Source = ReadImage(greader, endOffset-startOffset);                    rst.Add(image);                    startOffset = endOffset;                }            }            catch (Exception e)            {            }            greader.Close();            gf.Close();            reader.Close();            f.Close();            return rst;        }        public void LoadResource(string filename)        {            GameResource.Instance.ImageFiles.Add(filename, LoadImages(filename));        }..................

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.