123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
- namespace MinorShift.Emuera.Sub
- {
- #region reader/writer共通データ
- public enum EraSaveFileType : byte
- {
- Normal = 0x00,
- Global = 0x01,
- Var = 0x02,
- CharVar = 0x03
- }
- public enum EraSaveDataType : byte
- {
- Int = 0x00,
- IntArray = 0x01,
- IntArray2D = 0x02,
- IntArray3D = 0x03,
- Str = 0x10,
- StrArray = 0x11,
- StrArray2D = 0x12,
- StrArray3D = 0x13,
- //SOC = 0xFD,//キャラデータ始まり
- Separator = 0xFD,//データ区切り
- EOC = 0xFE,//キャラデータ終わり
- EOF = 0xFF//ファイル終端
- }
- static class Ebdb//EraBinaryData中のマジックナンバーなバイト
- {
- public const byte Byte = 0xCF;
- public const byte Int16 = 0xD0;//直後の2バイトがInt16
- public const byte Int32 = 0xD1;//直後の4バイトがInt32
- public const byte Int64 = 0xD2;//直後の8バイトがInt64
- public const byte String = 0xD8;//直後がString
- public const byte EoA1 = 0xE0;//データ区切り(一次元
- public const byte EoA2 = 0xE1;//データ区切り(二次元
- public const byte Zero = 0xF0;//直後にゼロが連続する数
- public const byte ZeroA1 = 0xF1;//直後に空配列が連続する数(一次元
- public const byte ZeroA2 = 0xF2;//直後に空配列が連続する数(二次元
- public const byte EoD = 0xFF;//変数データ終わり
- }
- static class EraBDConst
- {
- //Headerはpngのパクリ
- public const UInt64 Header = 0x0A1A0A0D41524589UL;
- public const UInt32 Version1808 = 1808;
- public const UInt32 DataCount = 0;
- }
- #endregion
- /// <summary>
- /// 1808追加 新しいデータ保存形式
- /// 将来形式を変更したときのためにabstractにしておく
- /// </summary>
- internal abstract class EraBinaryDataReader : IDisposable
- {
- private EraBinaryDataReader() {}
-
- protected EraBinaryDataReader(BinaryReader stream, int ver, UInt32[] buf)
- {
- reader = stream;
- version = ver;
- data = buf;
- }
- protected BinaryReader reader;
- protected readonly int version;
- protected readonly UInt32[] data;
- public abstract int ReaderVersion { get; }
- /// <summary>
- /// FileStreamからReaderを作成
- /// 不正なファイルの場合はnullを返す・例外は投げない
- /// </summary>
- /// <param name="fs"></param>
- /// <returns></returns>
- public static EraBinaryDataReader CreateReader(FileStream fs)
- {
- try
- {
- if ((fs == null) || (fs.Length < 16))
- return null;
- BinaryReader reader = new BinaryReader(fs, Encoding.Unicode);
- if (reader.ReadUInt64() != EraBDConst.Header)
- return null;
- int version = (int)reader.ReadUInt32();
- int datacount = (int)reader.ReadUInt32();
- UInt32[] data = new UInt32[datacount];
- for (int i = 0; i < datacount; i++)
- data[i] = reader.ReadUInt32();
- if (version == EraBDConst.Version1808)
- return new EraBinaryDataReader1808(reader, version, data);
- return null;
- }
- catch
- {
- return null;
- }
- }
- public abstract EraSaveFileType ReadFileType();
- /// <summary>
- /// システム用の特殊処理・圧縮なし
- /// </summary>
- /// <returns></returns>
- public abstract Int64 ReadInt64();
- public abstract string ReadString();
- public abstract Int64 ReadInt();
- public abstract void ReadIntArray(Int64[] refArray, bool needInit);
- public abstract void ReadIntArray2D(Int64[,] refArray, bool needInit);
- public abstract void ReadIntArray3D(Int64[, ,] refArray, bool needInit);
- public abstract void ReadStrArray(string[] refArray, bool needInit);
- public abstract void ReadStrArray2D(string[,] refArray, bool needInit);
- public abstract void ReadStrArray3D(string[, ,] refArray, bool needInit);
- public abstract KeyValuePair<string, EraSaveDataType> ReadVariableCode();
- #region IDisposable メンバ
- public void Dispose()
- {
- if (reader != null)
- reader.Close();
- reader = null;
- }
- #endregion
- public void Close()
- {
- Dispose();
- }
- private sealed class EraBinaryDataReader1808 : EraBinaryDataReader
- {
- public EraBinaryDataReader1808(BinaryReader stream, int ver, UInt32[] buf)
- : base(stream, ver, buf)
- {
- }
- //public bool EOF
- //{
- // get
- // {
- // return (reader.BaseStream.Length == reader.BaseStream.Position);
- // }
- //}
- public override int ReaderVersion => 1808;
- public override EraSaveFileType ReadFileType()
- {
- byte type = reader.ReadByte();
- if (type >= 0 && type <= 3)
- return (EraSaveFileType)type;
- throw new FileEE("ファイルデータ型異常");
- }
- private Int64 m_ReadInt()
- {
- byte b = reader.ReadByte();
- if (b <= Ebdb.Byte)
- return b;
- if (b == Ebdb.Int16)
- return reader.ReadInt16();
- if (b == Ebdb.Int32)
- return reader.ReadInt32();
- if (b == Ebdb.Int64)
- return reader.ReadInt64();
- throw new FileEE("バイナリデータの異常");
- }
- public override Int64 ReadInt64()
- {
- return reader.ReadInt64();
- }
- public override KeyValuePair<string, EraSaveDataType> ReadVariableCode()
- {
- EraSaveDataType type = (EraSaveDataType)reader.ReadByte();
- if (type == EraSaveDataType.EOC || type == EraSaveDataType.EOF || type == EraSaveDataType.Separator)
- return new KeyValuePair<string, EraSaveDataType>(null, type);
- string key = reader.ReadString();
- return new KeyValuePair<string, EraSaveDataType>(key, type);
- }
- //配列じゃないやつは特殊処理
- public override Int64 ReadInt()
- {
- return m_ReadInt();
- }
- public override string ReadString()
- {
- return reader.ReadString();
- }
- public override void ReadIntArray(Int64[] refArray, bool needInit)
- {
- Int64[] oriArray = null;
- byte b;
- int x = 0;
- int saveLength0 = reader.ReadInt32();
- if (refArray == null)//読み捨て。レアケースのはず
- refArray = new Int64[saveLength0];
- int length0 = refArray.Length;
- //保存されたデータの方が大きいとき。レアケースのはず
- if (length0 < saveLength0)
- {
- oriArray = refArray;
- //1818修正 サイズ違いの時にあふれないように/配列は最大まで確保、作業するのは重複部分だけ
- refArray = new Int64[Math.Max(length0, saveLength0)];
- length0 = Math.Min(length0, saveLength0);
- }
- while (true)
- {
- b = reader.ReadByte();
- if (b == Ebdb.EoD)
- break;
- if (b == Ebdb.Zero)
- {
- int cnt = (int)m_ReadInt();
- if (needInit)
- for (int i = 0; i < cnt; i++)
- refArray[x + i] = 0;
- x += cnt;
- continue;
- }
- if (b <= Ebdb.Byte)
- refArray[x] = b;
- else if (b == Ebdb.Int16)
- refArray[x] = reader.ReadInt16();
- else if (b == Ebdb.Int32)
- refArray[x] = reader.ReadInt32();
- else if (b == Ebdb.Int64)
- refArray[x] = reader.ReadInt64();
- else
- throw new FileEE("バイナリデータの異常");
- x++;
- }
- if (needInit)
- for (; x < length0; x++)
- refArray[x] = 0;
- if (oriArray != null)
- {
- for (x = 0; x < length0; x++)
- oriArray[x] = refArray[x];
- }
- }
- public override void ReadIntArray2D(Int64[,] refArray, bool needInit)
- {
- Int64[,] oriArray = null;
- byte b;
- int x = 0;
- int y = 0;
- int saveLength0 = reader.ReadInt32();
- int saveLength1 = reader.ReadInt32();
- if (refArray == null)
- refArray = new Int64[saveLength0, saveLength1];
- int length0 = refArray.GetLength(0);
- int length1 = refArray.GetLength(1);
- if (length0 < saveLength0 || length1 < saveLength1)
- {
- oriArray = refArray;
- //1818修正 サイズ違いの時にあふれないように/配列は最大まで確保、作業するのは重複部分だけ
- refArray = new Int64[Math.Max(length0, saveLength0), Math.Max(length1, saveLength1)];
- length0 = Math.Min(length0, saveLength0);
- length1 = Math.Min(length1, saveLength1);
- }
- while (true)
- {
- b = reader.ReadByte();
- if (b == Ebdb.EoD)
- break;
- if (b == Ebdb.ZeroA1)
- {
- int cnt = (int)m_ReadInt();
- if (needInit)
- for (int i = 0; i < cnt; i++)
- for (y = 0; y < length1; y++)
- refArray[x + i, y] = 0;
- x += cnt;
- y = 0;
- continue;
- }
- if (b == Ebdb.EoA1)
- {
- if (needInit)
- for (; y < length1; y++)
- refArray[x, y] = 0;
- x++;
- y = 0;
- continue;
- }
- if (b == Ebdb.Zero)
- {
- int cnt = (int)m_ReadInt();
- if (needInit)
- for (int i = 0; i < cnt; i++)
- refArray[x, y + i] = 0;
- y += cnt;
- continue;
- }
- if (b <= Ebdb.Byte)
- refArray[x, y] = b;
- else if (b == Ebdb.Int16)
- refArray[x, y] = reader.ReadInt16();
- else if (b == Ebdb.Int32)
- refArray[x, y] = reader.ReadInt32();
- else if (b == Ebdb.Int64)
- refArray[x, y] = reader.ReadInt64();
- else
- throw new FileEE("バイナリデータの異常");
- y++;
- }
- if (needInit)
- {
- for (; x < length0; x++)
- {
- for (; y < length1; y++)
- refArray[x, y] = 0;
- y = 0;
- }
- }
- if (oriArray != null)
- {
- for (x = 0; x < length0; x++)
- for (y = 0; y < length1; y++)
- oriArray[x, y] = refArray[x, y];
- }
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="refArray">データを書き出す先。読み捨てるならnull</param>
- /// <param name="needInit">データがない部分を0で埋める必要があるか</param>
- public override void ReadIntArray3D(Int64[, ,] refArray, bool needInit)
- {
- Int64[, ,] oriArray = null;
- byte b;
- int x = 0;
- int y = 0;
- int z = 0;
- int saveLength0 = reader.ReadInt32();
- int saveLength1 = reader.ReadInt32();
- int saveLength2 = reader.ReadInt32();
- if (refArray == null)
- refArray = new Int64[saveLength0, saveLength1, saveLength2];
- int length0 = refArray.GetLength(0);
- int length1 = refArray.GetLength(1);
- int length2 = refArray.GetLength(2);
- if (length0 < saveLength0 || length1 < saveLength1 || length2 < saveLength2)
- {
- oriArray = refArray;
- //1818修正 サイズ違いの時にあふれないように/配列は最大まで確保、作業するのは重複部分だけ
- refArray = new Int64[Math.Max(length0, saveLength0), Math.Max(length1, saveLength1), Math.Max(length2, saveLength2)];
- length0 = Math.Min(length0, saveLength0);
- length1 = Math.Min(length1, saveLength1);
- length2 = Math.Min(length2, saveLength2);
- }
- while (true)
- {
- b = reader.ReadByte();
- if (b == Ebdb.EoD)
- break;
- if (b == Ebdb.ZeroA2)//cnt分だけ空の行列が連続
- {
- int cnt = (int)m_ReadInt();
- if (needInit)
- for (int i = 0; i < cnt; i++)
- for (y = 0; y < length1; y++)
- for (z = 0; z < length2; z++)
- refArray[x + i, y, z] = 0;
- x += cnt;
- y = 0;
- z = 0;
- continue;
- }
- if (b == Ebdb.EoA2)//行列終わりor残りが全て0
- {
- if (needInit)
- {
- for (; y < length1; y++)
- {
- for (; z < length2; z++)
- refArray[x, y, z] = 0;
- z = 0;
- }
- }
- x++;
- y = 0;
- z = 0;
- continue;
- }
- if (b == Ebdb.ZeroA1)//cnt分だけ空の列が連続
- {
- int cnt = (int)m_ReadInt();
- if (needInit)
- for (int i = 0; i < cnt; i++)
- for (z = 0; z < length2; z++)
- refArray[x, y + i, z] = 0;
- y += cnt;
- z = 0;
- continue;
- }
- if (b == Ebdb.EoA1)//列終わりor残り全て0
- {
- if (needInit)
- for (; z < length2; z++)
- refArray[x, y, z] = 0;
- y++;
- z = 0;
- continue;
- }
- if (b == Ebdb.Zero)//cnt分だけ0が連続
- {
- int cnt = (int)m_ReadInt();
- if (needInit)
- for (int i = 0; i < cnt; i++)
- refArray[x, y, z + i] = 0;
- z += cnt;
- continue;
- }
- if (b <= Ebdb.Byte)
- refArray[x, y, z] = b;
- else if (b == Ebdb.Int16)
- refArray[x, y, z] = reader.ReadInt16();
- else if (b == Ebdb.Int32)
- refArray[x, y, z] = reader.ReadInt32();
- else if (b == Ebdb.Int64)
- refArray[x, y, z] = reader.ReadInt64();
- else
- throw new FileEE("バイナリデータの異常");
- z++;
- }
- if (needInit)
- {
- for (; x < length0; x++)
- {
- for (; y < length1; y++)
- {
- for (; z < length2; z++)
- refArray[x, y, z] = 0;
- z = 0;
- }
- y = 0;
- }
- }
- if (oriArray != null)
- {
- for (x = 0; x < length0; x++)
- for (y = 0; y < length1; y++)
- for (z = 0; z < length2; z++)
- oriArray[x, y, z] = refArray[x, y, z];
- }
- }
- public override void ReadStrArray(string[] refArray, bool needInit)
- {
- string[] oriArray = null;
- byte b;
- int x = 0;
- int saveLength0 = reader.ReadInt32();
- if (refArray == null)//読み捨て。レアケースのはず
- refArray = new string[saveLength0];
- int length0 = refArray.Length;
- //保存されたデータの方が大きいとき。レアケースのはず
- if (length0 < saveLength0)
- {
- oriArray = refArray;
- //1818修正 サイズ違いの時にあふれないように/配列は最大まで確保、作業するのは重複部分だけ
- refArray = new string[Math.Max(length0, saveLength0)];
- length0 = Math.Min(length0, saveLength0);
- }
- while (true)
- {
- b = reader.ReadByte();
- if (b == Ebdb.EoD)
- break;
- if (b == Ebdb.Zero)
- {
- int cnt = (int)m_ReadInt();
- if (needInit)
- for (int i = 0; i < cnt; i++)
- refArray[x + i] = null;
- x += cnt;
- continue;
- }
- if (b == Ebdb.String)
- refArray[x] = ReadString();
- else
- throw new FileEE("バイナリデータの異常");
- x++;
- }
- if (needInit)
- for (; x < length0; x++)
- refArray[x] = null;
- if (oriArray != null)
- {
- for (x = 0; x < length0; x++)
- oriArray[x] = refArray[x];
- }
- }
- public override void ReadStrArray2D(string[,] refArray, bool needInit)
- {
- string[,] oriArray = null;
- byte b;
- int x = 0;
- int y = 0;
- int saveLength0 = reader.ReadInt32();
- int saveLength1 = reader.ReadInt32();
- if (refArray == null)
- refArray = new string[saveLength0, saveLength1];
- int length0 = refArray.GetLength(0);
- int length1 = refArray.GetLength(1);
- if (length0 < saveLength0 || length1 < saveLength1)
- {
- oriArray = refArray;
- //1818修正 サイズ違いの時にあふれないように/配列は最大まで確保、作業するのは重複部分だけ
- refArray = new string[Math.Max(length0, saveLength0), Math.Max(length1, saveLength1)];
- length0 = Math.Min(length0, saveLength0);
- length1 = Math.Min(length1, saveLength1);
- }
- while (true)
- {
- b = reader.ReadByte();
- if (b == Ebdb.EoD)
- break;
- if (b == Ebdb.ZeroA1)
- {
- int cnt = (int)m_ReadInt();
- if (needInit)
- for (int i = 0; i < cnt; i++)
- for (y = 0; y < length1; y++)
- refArray[x + i, y] = null;
- x += cnt;
- y = 0;
- continue;
- }
- if (b == Ebdb.EoA1)
- {
- if (needInit)
- for (; y < length1; y++)
- refArray[x, y] = null;
- x++;
- y = 0;
- continue;
- }
- if (b == Ebdb.Zero)
- {
- int cnt = (int)m_ReadInt();
- if (needInit)
- for (int i = 0; i < cnt; i++)
- refArray[x, y + i] = null;
- y += cnt;
- continue;
- }
- if (b == Ebdb.String)
- refArray[x, y] = ReadString();
- else
- throw new FileEE("バイナリデータの異常");
- y++;
- }
- if (needInit)
- {
- for (; x < length0; x++)
- {
- for (; y < length1; y++)
- refArray[x, y] = null;
- y = 0;
- }
- }
- if (oriArray != null)
- {
- for (x = 0; x < length0; x++)
- for (y = 0; y < length1; y++)
- oriArray[x, y] = refArray[x, y];
- }
- }
- public override void ReadStrArray3D(string[, ,] refArray, bool needInit)
- {
- string[, ,] oriArray = null;
- byte b;
- int x = 0;
- int y = 0;
- int z = 0;
- int saveLength0 = reader.ReadInt32();
- int saveLength1 = reader.ReadInt32();
- int saveLength2 = reader.ReadInt32();
- if (refArray == null)
- refArray = new string[saveLength0, saveLength1, saveLength2];
- int length0 = refArray.GetLength(0);
- int length1 = refArray.GetLength(1);
- int length2 = refArray.GetLength(2);
- if (length0 < saveLength0 || length1 < saveLength1 || length2 < saveLength2)
- {
- oriArray = refArray;
- //1818修正 サイズ違いの時にあふれないように/配列は最大まで確保、作業するのは重複部分だけ
- refArray = new string[Math.Max(length0, saveLength0), Math.Max(length1, saveLength1), Math.Max(length2, saveLength2)];
- length0 = Math.Min(length0, saveLength0);
- length1 = Math.Min(length1, saveLength1);
- length2 = Math.Min(length2, saveLength2);
- }
- while (true)
- {
- b = reader.ReadByte();
- if (b == Ebdb.EoD)
- break;
- if (b == Ebdb.ZeroA2)//cnt分だけ空の行列が連続
- {
- int cnt = (int)m_ReadInt();
- if (needInit)
- for (int i = 0; i < cnt; i++)
- for (y = 0; y < length1; y++)
- for (z = 0; z < length2; z++)
- refArray[x + i, y, z] = null;
- x += cnt;
- y = 0;
- z = 0;
- continue;
- }
- if (b == Ebdb.EoA2)//行列終わりor残りが全て0
- {
- if (needInit)
- {
- for (; y < length1; y++)
- {
- for (; z < length2; z++)
- refArray[x, y, z] = null;
- z = 0;
- }
- }
- x++;
- y = 0;
- z = 0;
- continue;
- }
- if (b == Ebdb.ZeroA1)//cnt分だけ空の列が連続
- {
- int cnt = (int)m_ReadInt();
- if (needInit)
- for (int i = 0; i < cnt; i++)
- for (z = 0; z < length2; z++)
- refArray[x, y + i, z] = null;
- y += cnt;
- z = 0;
- continue;
- }
- if (b == Ebdb.EoA1)//列終わりor残り全て0
- {
- if (needInit)
- for (; z < length2; z++)
- refArray[x, y, z] = null;
- y++;
- z = 0;
- continue;
- }
- if (b == Ebdb.Zero)//cnt分だけ0が連続
- {
- int cnt = (int)m_ReadInt();
- if (needInit)
- for (int i = 0; i < cnt; i++)
- refArray[x, y, z + i] = null;
- z += cnt;
- continue;
- }
- if (b == Ebdb.String)
- refArray[x, y, z] = ReadString();
- else
- throw new FileEE("バイナリデータの異常");
- z++;
- }
- if (needInit)
- {
- for (; x < length0; x++)
- {
- for (; y < length1; y++)
- {
- for (; z < length2; z++)
- refArray[x, y, z] = null;
- z = 0;
- }
- y = 0;
- }
- }
- if (oriArray != null)
- {
- for (x = 0; x < length0; x++)
- for (y = 0; y < length1; y++)
- for (z = 0; z < length2; z++)
- oriArray[x, y, z] = refArray[x, y, z];
- }
- }
- }
- }
- }
|