//#define COSMOSDEBUG using System; using IL2CPU.API.Attribs; namespace Cosmos.Core { /// /// MemoryBlock class. Used to read and write to memory blocks. /// public class MemoryBlock { /// /// Memory block base address. /// public readonly uint Base; /// /// Memory block size. /// public readonly uint Size; /// /// Bytes memory block. /// public readonly MemoryBlock08 Bytes; /// /// Words memory block. /// public readonly MemoryBlock16 Words; /// /// DWords memory block. /// public readonly MemoryBlock32 DWords; /// /// Create new instance of the class. /// /// A base. /// A size. public MemoryBlock(uint aBase, uint aSize) { Base = aBase; Size = aSize; Bytes = new MemoryBlock08(aBase, aSize); Words = new MemoryBlock16(aBase, aSize); DWords = new MemoryBlock32(aBase, aSize); } //TODO: Fill all these methods with fast ASM //TODO: Make an attribute that can be applied to methods to tell the copmiler to inline them to save // the overhead of a call on operations like this. // Need to check bounds for 16 and 32 better so offset cannot be size - 1 and then the 4 bytes write past the end /// /// Get and set memory block. /// /// A byte offset. /// uint value. /// Thrown on memory access violation. public unsafe uint this[uint aByteOffset] { get { if (aByteOffset >= Size) { throw new Exception("Memory access violation"); } return *(uint*)(Base + aByteOffset); } set { if (aByteOffset >= Size) { throw new Exception("Memory access violation"); } (*(uint*)(Base + aByteOffset)) = value; } } /// /// Fill memory block. /// /// A data to fill. public void Fill(uint aData) { //Fill(0, Size / 4, aData); Fill(0, Size, aData); } /// /// Fill memory block. /// /// A start. /// A count. /// A data. [DebugStub(Off = true)] 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*)(Base + 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. [DebugStub(Off = true)] 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 :-( int* xDest = (int*)(Base + aStart); MemoryOperations.Fill(xDest, aData, (int)aCount); } /// /// Fill data to memory block. /// /// Data to fill the memory block with. public void Fill(byte aData) { Fill(0, Size, aData); } /// /// Fill data to memory block. /// /// Data to fill the memory block with. public void Fill(ushort aData) { Fill(0, Size, aData); } /// /// Fill data to memory block. /// /// A starting position in the memory block. /// Data size. /// A data to fill memory block with. [DebugStub(Off = true)] public unsafe void Fill(uint aStart, uint aCount, ushort aData) { // TODO thow exception if aStart and aCount are not in bound. I've tried to do this but Bochs dies :-( ushort* xDest = (ushort*)(Base + 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. [DebugStub(Off = true)] public unsafe void Fill(uint aStart, uint aCount, byte aData) { // TODO thow exception if aStart and aCount are not in bound. I've tried to do this but Bochs dies :-( byte* xDest = (byte*)(Base + aStart); MemoryOperations.Fill(xDest, aData, (int)aCount); } /// /// Copy data from the buffer to the start of the memory block. /// /// A data buffer array. /// Thrown if aData length in greater then Int32.MaxValue. [DebugStub(Off = true)] public unsafe void Copy(uint[] aData) { Copy(0, aData, 0, aData.Length); } /// /// Copy data from the buffer array to the memory block. /// /// A data starting position inside the memory block. /// A data buffer array. /// A staring index in the source data buffer array. /// Number of bytes to copy. unsafe public void Copy(uint aStart, uint[] 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 :-( uint* xDest = (uint*)(Base + aStart); Global.mDebugger.SendInternal($"Base is {Base} xDest is {(uint)xDest}"); fixed (uint* aDataPtr = aData) { MemoryOperations.Copy(xDest, aDataPtr + aIndex, aCount); } } /// /// Copy data from the buffer to the start of the memory block. /// /// A data buffer array. /// Thrown if aData length in greater then Int32.MaxValue. public void Copy(byte[] aData) { Copy(0, aData, 0, aData.Length); } /// /// Copy data from the buffer array to the memory block. /// /// A data starting position inside the memory block. /// A data buffer array. /// A staring index in the source data buffer array. /// Number of bytes to copy. public unsafe void Copy(int aStart, byte[] 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 = (int*)(Base + aStart); fixed (byte* aDataPtr = aData) { MemoryOperations.Copy((byte*)xDest, aDataPtr + aIndex, aCount); } } /// /// Copy data from the buffer to the start of the memory block. /// /// A data buffer array. /// Thrown if aData length in greater then Int32.MaxValue. public void Copy(int[] aData) { Copy(0, aData, 0, aData.Length); } /// /// Copy data from the buffer array to the start of the memory block. /// /// A data buffer array. /// A staring index in the source data buffer array. /// Number of bytes to copy. /// Thrown if aData length in greater then Int32.MaxValue. public void Copy(int []aData, int aIndex, int aCount) { Copy(0, aData, aIndex, aData.Length); } /// /// Copy data from the buffer array to the memory block. /// /// A data starting position inside the memory block. /// A data buffer array. /// A staring index in the source data buffer array. /// Number of bytes to copy. 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 = (int*)(Base + aStart); fixed (int* aDataPtr = aData) { MemoryOperations.Copy(xDest, aDataPtr + aIndex, aCount); } } /// /// Copy ManagedMemoryBlock into MemoryBlock /// /// ManagedMemoryBlock to copy. public unsafe void Copy(ManagedMemoryBlock block) { byte* xDest = (byte*)(Base); byte* aDataPtr = (byte*)block.Offset; MemoryOperations.Copy(xDest, aDataPtr, (int)block.Size); } /// /// Move bytes array down the memory block. /// /// Destination location. /// Sourcs location. /// Number of bytes to move. [DebugStub(Off = true)] public unsafe void MoveDown(uint aDest, uint aSrc, uint aCount) { byte* xDest = (byte*)(Base + aDest); byte* xSrc = (byte*)(Base + aSrc); MemoryOperations.Copy(xDest, xSrc, (int)aCount); } /// /// Move data inside the block. Undone. /// /// Always throw. Yet to be done. /// A destination address. /// A source address. /// Number of bytes to move. /// Thrown always. public void MoveUp(uint aDest, uint aSrc, uint aCount) { throw new Exception("TODO"); } #region ReadWrite /// /// Read 8-bit from the memory block. /// /// A buffer to write the data to. /// Thrown if aBuffer length in greater then Int32.MaxValue. /// Thrown on memory access violation. public unsafe void Read8(Byte[] aBuffer) { if(aBuffer.Length >= Size) { throw new Exception("Memory access violation"); } for (int i = 0; i < aBuffer.Length; i++) aBuffer[i] = (*(Byte*)(Base + i)); } /// /// Write 8-bit to the memory block. /// /// A buffer to be written to the memory block. /// Thrown if aBuffer length in greater then Int32.MaxValue. /// Thrown on memory access violation. public unsafe void Write8(Byte[] aBuffer) { if(aBuffer.Length >= Size) { throw new Exception("Memory access violation"); } for (int i = 0; i < aBuffer.Length; i++) (*(Byte*)(Base + i)) = aBuffer[i]; } /// /// Read 16-bit from the memory block. /// /// A buffer to write the data to. /// Thrown if aBuffer length in greater then Int32.MaxValue. /// Thrown on memory access violation. public unsafe void Read16(ushort[] aBuffer) { if(aBuffer.Length >= Size) { throw new Exception("Memory access violation"); } for (int i = 0; i < aBuffer.Length / 2; i++) { aBuffer[i] = (*(ushort*)(Base + i)); } } /// /// Write 16-bit to the memory block. /// /// A buffer to be written to the memory block. /// Thrown if aBuffer length in greater then Int32.MaxValue. /// Thrown on memory access violation. public unsafe void Write16(ushort[] aBuffer) { if(aBuffer.Length >= Size) { throw new Exception("Memory access violation"); } for (int i = 0; i < aBuffer.Length / sizeof(ushort); i++) { (*(ushort*)(Base + i)) = aBuffer[i]; } } /// /// Read 32-bit from the memory block. /// /// A buffer to write the data to. /// Thrown if aBuffer length in greater then Int32.MaxValue. /// Thrown on memory access violation. public unsafe void Read32(uint[] aBuffer) { if(aBuffer.Length >= Size) { throw new Exception("Memory access violation"); } for (int i = 0; i < aBuffer.Length / sizeof(uint); i++) aBuffer[i] = (*(uint*)(Base + i)); } /// /// Write 32-bit to the memory block. /// /// A buffer to be written to the memory block. /// Thrown if aBuffer length in greater then Int32.MaxValue. /// Thrown on memory access violation. public unsafe void Write32(uint[] aBuffer) { if(aBuffer.Length >= Size) { throw new Exception("Memory access violation"); } for (int i = 0; i < aBuffer.Length / sizeof(uint); i++) (*(uint*)(Base + i)) = aBuffer[i]; } #endregion ReadWrite /// /// Convert part for the memory block to array. /// /// A starting position of the data at the source memory block. /// A index to be the staring index at the destination array. /// Number of bytes to get. /// uint array. public unsafe uint[] ToArray(int aStart, int aIndex, int aCount) { uint* xDest = (uint*)(Base + aStart); uint[] array = new uint[aCount]; fixed (uint* aArrayPtr = array) { MemoryOperations.Copy(aArrayPtr + aIndex, xDest, aCount); } return array; } /// /// Convert the memory block to array. /// /// uint array. public uint[] ToArray() { return ToArray(0, 0, (int)Size); } } /// /// MemoryBlock08 class. /// public class MemoryBlock08 { /// /// Base. /// public readonly uint Base; /// /// Size. /// public readonly uint Size; /// /// Create new instance of the class. /// /// A base. /// A size. internal MemoryBlock08(uint aBase, uint aSize) { Base = aBase; Size = aSize; } /// /// Get and set memory block. /// /// A byte offset. /// byte value. /// Thrown on memory access violation. public unsafe byte this[uint aByteOffset] { get { if (aByteOffset >= Size) { throw new Exception("Memory access violation"); } return *(byte*)(Base + aByteOffset); } set { if (aByteOffset >= Size) { // Also this exception gets eaten? throw new Exception("Memory access violation"); } (*(byte*)(Base + aByteOffset)) = value; } } } /// /// MemoryBlock16 class. /// public class MemoryBlock16 { /// /// Base. /// public readonly uint Base; /// /// Size. /// public readonly uint Size; /// /// Create new instance of the class. /// /// A base. /// A size. internal MemoryBlock16(uint aBase, uint aSize) { Base = aBase; Size = aSize; } /// /// Get and set memory block. /// /// A byte offset. /// ushort value. /// Thrown on memory access violation. public unsafe ushort this[uint aByteOffset] { get { if (aByteOffset >= Size) { throw new Exception("Memory access violation"); } return *(ushort*)(Base + aByteOffset); } set { if (aByteOffset >= Size) { throw new Exception("Memory access violation"); } (*(ushort*)(Base + aByteOffset)) = value; } } } /// /// MemoryBlock32 class. /// public class MemoryBlock32 { /// /// Base. /// public readonly uint Base; /// /// Size. /// public readonly uint Size; /// /// Create new instance of the class. /// /// A base. /// A size. internal MemoryBlock32(uint aBase, uint aSize) { Base = aBase; Size = aSize; } /// /// Get and set memory block. /// /// A byte offset. /// uint value. /// Thrown on memory access violation. public unsafe uint this[uint aByteOffset] { get { if (aByteOffset >= Size) { throw new Exception("Memory access violation"); } return *(uint*)(Base + aByteOffset); } set { if (aByteOffset >= Size) { throw new Exception("Memory access violation"); } (*(uint*)(Base + aByteOffset)) = value; } } } }