UnmanagedGigabyteBlockSeparatedRamDisk.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. using System;
  2. using System.Runtime.InteropServices;
  3. namespace DiskAccessLibrary.Mod
  4. {
  5. public class UnmanagedGigabyteBlockSeparatedRamDisk : Disk, ILoadableRamDisk
  6. {
  7. private const int SectorSize = 512;
  8. private const int BlockSize = Consts.Gigabyte;
  9. private IntPtr[] _blocks;
  10. public UnmanagedGigabyteBlockSeparatedRamDisk(int sizeInGigabyte)
  11. {
  12. _blocks = new IntPtr[sizeInGigabyte];
  13. Size = (long)sizeInGigabyte * Consts.Gigabyte;
  14. }
  15. public void Allocate()
  16. {
  17. for (var i = 0; i < _blocks.Length; i++)
  18. {
  19. _blocks[i] = Marshal.AllocHGlobal(BlockSize);
  20. }
  21. }
  22. public void Free()
  23. {
  24. foreach (var block in _blocks)
  25. {
  26. if (block != IntPtr.Zero) Marshal.FreeHGlobal(block);
  27. }
  28. _blocks = null;
  29. GC.Collect();
  30. GC.WaitForPendingFinalizers();
  31. }
  32. private void ReadBlock(byte[] buffer, int offset, int count, int blockIndex, int blockOffset)
  33. {
  34. Marshal.Copy(_blocks[blockIndex] + blockOffset, buffer, offset, count);
  35. }
  36. private void WriteBlock(byte[] buffer, int offset, int count, int blockIndex, int blockOffset)
  37. {
  38. Marshal.Copy(buffer, offset, _blocks[blockIndex] + blockOffset, count);
  39. }
  40. public void WriteData(long rawOffset, byte[] data)
  41. {
  42. for (var i = 0; i < data.Length;)
  43. {
  44. var blockIndex = (int)(rawOffset / BlockSize);
  45. var blockOffset = (int)(rawOffset % BlockSize);
  46. var bytesToWrite = BlockSize - blockOffset;
  47. if (i + bytesToWrite > data.Length)
  48. {
  49. bytesToWrite = data.Length - i;
  50. }
  51. WriteBlock(data, i, bytesToWrite, blockIndex, blockOffset);
  52. i += bytesToWrite;
  53. rawOffset += bytesToWrite;
  54. }
  55. }
  56. public override byte[] ReadSectors(long sectorIndex, int sectorCount)
  57. {
  58. var rawOffset = sectorIndex * SectorSize;
  59. var rawSize = sectorCount * SectorSize;
  60. var buffer = new byte[rawSize];
  61. for (var i = 0; i < rawSize;)
  62. {
  63. var blockIndex = (int)(rawOffset / BlockSize);
  64. var blockOffset = (int)(rawOffset % BlockSize);
  65. var bytesToRead = BlockSize - blockOffset;
  66. if (i + bytesToRead > rawSize)
  67. {
  68. bytesToRead = rawSize - i;
  69. }
  70. ReadBlock(buffer, i, bytesToRead, blockIndex, blockOffset);
  71. i += bytesToRead;
  72. rawOffset += bytesToRead;
  73. }
  74. return buffer;
  75. }
  76. public override void WriteSectors(long sectorIndex, byte[] data)
  77. {
  78. var rawOffset = sectorIndex * SectorSize;
  79. WriteData(rawOffset, data);
  80. }
  81. public override int BytesPerSector => SectorSize;
  82. public override long Size { get; }
  83. }
  84. }