using System; namespace Cosmos.Core { /// /// ManagedMemoryBlock class. Used to read and write a managed memory block. /// public unsafe class ManagedMemoryBlock { private byte[] memory; /// /// Offset. /// public UInt32 Offset; /// /// Size. /// public UInt32 Size; /// /// Create a new buffer with the given size, not aligned /// /// Size of buffer public ManagedMemoryBlock(UInt32 size) : this(size, 1, false) { } /// /// Create a new buffer with the given size, aligned on the byte boundary specified /// /// Size of buffer /// Byte Boundary alignment public ManagedMemoryBlock(UInt32 size, int alignment) : this(size, alignment, true) { } /// /// Create a new buffer with the given size, and aligned on the byte boundary if align is true /// /// Size of buffer /// Byte Boundary alignment /// true if buffer should be aligned, false otherwise public ManagedMemoryBlock(UInt32 size, int alignment, bool align) { memory = new byte[size + alignment - 1]; fixed (byte* bodystart = memory) { Offset = (UInt32)bodystart; Size = size; } if (align == true) { while (this.Offset % alignment != 0) { this.Offset++; } } } /// /// Get or set the byte at the given offset /// /// Address Offset /// Byte value at given offset /// Thrown on invalid offset. public byte this[uint offset] { get { if (offset > Size) throw new ArgumentOutOfRangeException("offset"); return *(byte*)(this.Offset + offset); } set { if (offset < 0 || offset > Size) throw new ArgumentOutOfRangeException("offset"); (*(byte*)(this.Offset + offset)) = value; } } /// /// Fill memory block. /// /// A start. /// A count. /// A data. public unsafe void Fill(uint aStart, uint aCount, uint aData) { // TODO thow exception if aStart and aCount are not in bound. I've tried to do this but Bochs dies :-( uint* xDest = (uint*)(this.Offset + aStart); MemoryOperations.Fill(xDest, aData, (int)aCount); } /// /// Fill data to memory block. /// /// A starting position in the memory block. /// Data size. /// A data to fill memory block with. public unsafe void Fill(int aStart, int aCount, int aData) { // TODO thow exception if aStart and aCount are not in bound. I've tried to do this but Bochs dies :-( fixed (byte* aArrayPtr = this.memory) { MemoryOperations.Fill(aArrayPtr + aStart, aData, (int)aCount); } } /// /// Fill memory block. /// /// A data to fill. public void Fill(uint aData) { fixed (byte* destPtr = this.memory) { MemoryOperations.Fill(destPtr, (int)aData, (int)this.Size); } } public unsafe void Copy(int aStart, int[] aData, int aIndex, int aCount) { // TODO thow exception if aStart and aCount are not in bound. I've tried to do this but Bochs dies :-( int* xDest; fixed (byte* aArrayPtr = this.memory) { xDest = (int*)(aArrayPtr + aStart); } fixed (int* aDataPtr = aData) { MemoryOperations.Copy(xDest, aDataPtr + aIndex, aCount); } } /// /// Copy MemoryBlock into ManagedMemoryBlock /// /// MemoryBlock to copy. public unsafe void Copy(MemoryBlock block) { byte* xDest = (byte*)(this.Offset); byte* aDataPtr = (byte*)block.Base; MemoryOperations.Copy(xDest, aDataPtr, (int)block.Size); } /// /// Read 16-bit from the memory block. /// /// Data offset. /// UInt16 value. /// Thrown if offset if bigger than memory block size. public UInt16 Read16(uint offset) { if (offset > Size) throw new ArgumentOutOfRangeException("offset"); return *(UInt16*)(this.Offset + offset); } /// /// Write 16-bit to the memory block. /// /// Data offset. /// Value to write. /// Thrown if offset if bigger than memory block size or smaller than 0. public void Write16(uint offset, UInt16 value) { if (offset < 0 || offset > Size) throw new ArgumentOutOfRangeException("offset"); (*(UInt16*)(this.Offset + offset)) = value; } /// /// Read 32-bit from the memory block. /// /// Data offset. /// UInt32 value. /// Thrown if offset if bigger than memory block size. public UInt32 Read32(uint offset) { if (offset > Size) throw new ArgumentOutOfRangeException("offset"); return *(UInt32*)(this.Offset + offset); } /// /// Write 32-bit to the memory block. /// /// Data offset. /// Value to write. /// Thrown if offset if bigger than memory block size or smaller than 0. public void Write32(uint offset, UInt32 value) { if (offset < 0 || offset > Size) throw new ArgumentOutOfRangeException("offset"); (*(UInt32*)(this.Offset + offset)) = value; } } }