Msd.Reader.cs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.IO;
  5. using System.Linq;
  6. namespace OpenVIII.Fields
  7. {
  8. public static partial class Msd
  9. {
  10. public static class Reader
  11. {
  12. public static IReadOnlyList<FF8String> FromBytes(byte[] buff)
  13. {
  14. var monologues = new List<FF8String>();
  15. var bufferSize = buff.Length;
  16. if (bufferSize < 4)
  17. return monologues;
  18. ReadMessages(buff, monologues);
  19. return monologues;
  20. }
  21. private static void ReadMessages(byte[] buff, List<FF8String> monologues)
  22. {
  23. using (var br = new BinaryReader(new MemoryStream(buff)))
  24. {
  25. var dataOffset = br.ReadUInt32();
  26. var count = checked((int)GetMessageNumber(dataOffset, br.BaseStream.Length));
  27. if (count == 0)
  28. return;
  29. monologues.Capacity = count;
  30. var Offsets = new List<uint>(count)
  31. {
  32. dataOffset
  33. };
  34. foreach (var i in Enumerable.Range(1,count-1))
  35. {
  36. Offsets.Add(br.ReadUInt32());
  37. }
  38. for (var i = 0; i < Offsets.Count; i++)
  39. {
  40. var offset = Offsets[i];
  41. var nextoffset = i+1<Offsets.Capacity ? Offsets[i+1] : (uint)br.BaseStream.Length;
  42. if (offset == nextoffset)
  43. {
  44. monologues.Add(string.Empty);
  45. continue;
  46. }
  47. var length = checked((int)(nextoffset - offset - 1));
  48. var message = new FF8String(br.ReadBytes(length));
  49. monologues.Add(message);
  50. }
  51. }
  52. }
  53. private static uint GetMessageNumber(uint dataOffset, long bufferSize)
  54. {
  55. var count = dataOffset / 4;
  56. if (dataOffset % 4 != 0)
  57. throw new InvalidDataException($"The offset to the beginning of the text data also determines the number of lines in the file and must be a multiple of 4. Occured: {dataOffset} mod 4 = {dataOffset % 4}");
  58. if (count < 0)
  59. throw new InvalidDataException($"Unexpected negative value occured: {dataOffset}. Expected positive offset to the text data.");
  60. if (dataOffset > bufferSize)
  61. throw new InvalidDataException($"Invalid data offset ({dataOffset}) is out of bounds ({bufferSize}).");
  62. return count;
  63. }
  64. }
  65. }
  66. }