CacheManifestHeader.cs 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using System;
  2. using System.Runtime.InteropServices;
  3. namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
  4. {
  5. /// <summary>
  6. /// Header of the shader cache manifest.
  7. /// </summary>
  8. [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x10)]
  9. struct CacheManifestHeader
  10. {
  11. /// <summary>
  12. /// The version of the cache.
  13. /// </summary>
  14. public ulong Version;
  15. /// <summary>
  16. /// The graphics api used for this cache.
  17. /// </summary>
  18. public CacheGraphicsApi GraphicsApi;
  19. /// <summary>
  20. /// The hash type used for this cache.
  21. /// </summary>
  22. public CacheHashType HashType;
  23. /// <summary>
  24. /// CRC-16 checksum over the data in the file.
  25. /// </summary>
  26. public ushort TableChecksum;
  27. /// <summary>
  28. /// Construct a new cache manifest header.
  29. /// </summary>
  30. /// <param name="version">The version of the cache</param>
  31. /// <param name="graphicsApi">The graphics api used for this cache</param>
  32. /// <param name="hashType">The hash type used for this cache</param>
  33. public CacheManifestHeader(ulong version, CacheGraphicsApi graphicsApi, CacheHashType hashType)
  34. {
  35. Version = version;
  36. GraphicsApi = graphicsApi;
  37. HashType = hashType;
  38. TableChecksum = 0;
  39. }
  40. /// <summary>
  41. /// Update the checksum in the header.
  42. /// </summary>
  43. /// <param name="data">The data to perform the checksum on</param>
  44. public void UpdateChecksum(ReadOnlySpan<byte> data)
  45. {
  46. TableChecksum = CalculateCrc16(data);
  47. }
  48. /// <summary>
  49. /// Calculate a CRC-16 over data.
  50. /// </summary>
  51. /// <param name="data">The data to perform the CRC-16 on</param>
  52. /// <returns>A CRC-16 over data</returns>
  53. private static ushort CalculateCrc16(ReadOnlySpan<byte> data)
  54. {
  55. int crc = 0;
  56. const ushort poly = 0x1021;
  57. for (int i = 0; i < data.Length; i++)
  58. {
  59. crc ^= data[i] << 8;
  60. for (int j = 0; j < 8; j++)
  61. {
  62. crc <<= 1;
  63. if ((crc & 0x10000) != 0)
  64. {
  65. crc = (crc ^ poly) & 0xFFFF;
  66. }
  67. }
  68. }
  69. return (ushort)crc;
  70. }
  71. /// <summary>
  72. /// Check the validity of the header.
  73. /// </summary>
  74. /// <param name="graphicsApi">The target graphics api in use</param>
  75. /// <param name="hashType">The target hash type in use</param>
  76. /// <param name="data">The data after this header</param>
  77. /// <returns>True if the header is valid</returns>
  78. /// <remarks>This doesn't check that versions match</remarks>
  79. public bool IsValid(CacheGraphicsApi graphicsApi, CacheHashType hashType, ReadOnlySpan<byte> data)
  80. {
  81. return GraphicsApi == graphicsApi && HashType == hashType && TableChecksum == CalculateCrc16(data);
  82. }
  83. }
  84. }