private void PrepareSegments() { if (segments != null) { // this is because in case of loading the starting memory snapshot // after deserialization (i.e. resetting after deserialization) // memory segments would have been lost return; } // how many segments we need? var segmentsNo = size / SegmentSize + (size % SegmentSize != 0 ? 1 : 0); this.NoisyLog(string.Format("Preparing {0} segments for {1} bytes of memory, each {2} bytes long.", segmentsNo, size, SegmentSize)); segments = new IntPtr[segmentsNo]; originalPointers = new IntPtr[segmentsNo]; // segments are not allocated until they are used by read, write, load etc (or touched) describedSegments = new IMappedSegment[segmentsNo]; for (var i = 0; i < describedSegments.Length - 1; i++) { describedSegments[i] = new MappedSegment(this, i, (uint)SegmentSize); } var last = describedSegments.Length - 1; var sizeOfLast = (uint)(size % (uint)SegmentSize); if (sizeOfLast == 0) { sizeOfLast = (uint)SegmentSize; } describedSegments[last] = new MappedSegment(this, last, sizeOfLast); }
private void PrepareSegments() { if(segments != null) { // this is because in case of loading the starting memory snapshot // after deserialization (i.e. resetting after deserialization) // memory segments would have been lost return; } // how many segments we need? var segmentsNo = size / SegmentSize + (size % SegmentSize != 0 ? 1 : 0); this.NoisyLog(string.Format("Preparing {0} segments for {1} bytes of memory, each {2} bytes long.", segmentsNo, size, SegmentSize)); segments = new IntPtr[segmentsNo]; originalPointers = new IntPtr[segmentsNo]; // segments are not allocated until they are used by read, write, load etc (or touched) describedSegments = new IMappedSegment[segmentsNo]; for(var i = 0; i < describedSegments.Length - 1; i++) { describedSegments[i] = new MappedSegment(this, i, (uint)SegmentSize); } var last = describedSegments.Length - 1; var sizeOfLast = size % (uint)SegmentSize; if(sizeOfLast == 0) { sizeOfLast = (uint)SegmentSize; } describedSegments[last] = new MappedSegment(this, last, sizeOfLast); }
public virtual void MapMemory(IMappedSegment segment) { }
public void MapMemory(IMappedSegment segment) { using(machine.ObtainPausedState()) { currentMappings.Add(new SegmentMapping(segment)); RegisterMemoryChecked(segment.StartingOffset, segment.Size); checked { TranslationCacheSize = (int)(currentMappings.Sum(x => x.Segment.Size) / 4); } } }
public SegmentMapping(IMappedSegment segment) { Segment = segment; }
public MusteinGenericGPU(Machine machine, bool registers64bitAligned = false, uint controlBit = 23, uint frameBufferSize = 0x800000) : base(machine) { this.machine = machine; this.frameBufferSize = (int)frameBufferSize; // default value 0x800000 is enough for 1024x1024 pixels with 64-bit aligment per pixel this.controlBit = controlBit; // All acceses with this bit set are handled by the control registers this.controlOffset = 1L << (int)controlBit; // All acceses smaller than this value are going to the buffer this.is64bitAligned = registers64bitAligned; // Are control register aligned to 32bit or 64bit accessAligment = (registers64bitAligned) ? 8 : 4; // To what bytes the control registers are aligned sync = new object(); // Allows to switch ordering for the 8bit mode lookup table depending what is closer to the native host colorspace #if PLATFORM_WINDOWS this.lookupTableRgbx = false; #else this.lookupTableRgbx = true; #endif // Populating lookup table for the 8bit color mode to 24bit conversion, because the 332 format is unbalanced so // much and the Red/Green have 50% more bits than Blue the value 0xFF has a yellow tint. Balanced white (gray) // color is actually value 0xF6. The white color is fairly gray because the discarted least significant bits // still acumulate to a 1/4 of the total brightness/value (we are cutting away too many bits). colorTable = new uint[256]; for (uint index = 0; index < 256; index++) { uint blue = (index & 0xc0) >> 6; uint green = (index & 0x38) >> 3; uint red = index & 0x7; uint value; if (lookupTableRgbx) { value = red << 21 | green << 13 | blue << 6; // Converting RGB332 to RGB888 which will be used for RGBX8888 } else { value = red << 5 | green << 13 | blue << 22; // Converting RGB332 to BGR888 which will be used for BGRX8888 } colorTable[index] = value; //this.Log(LogLevel.Noisy, string.Format("colorTable[{0}] = 0x{1:X};", index, value)); } // Populating transfer colorModeToPixelFormat colorModeToPixelFormatTable = new Dictionary <ColorMode, PixelFormat>() { { ColorMode.LowColor, (lookupTableRgbx) ? PixelFormat.RGBX8888 : PixelFormat.BGRX8888 }, { ColorMode.HighColor, PixelFormat.RGB565 }, { ColorMode.TrueColor, PixelFormat.RGBX8888 } }; // Allocate and align the framebuffer memory. We are hardcoding the mapped segment between addresses 0 and <size> // the WriteDoubleWord is not going to be invoked for these addresses and the raw data will go directly to the // frame buffer. The MappedSegment increased the complexity of the code, but performs magnitude faster. describedFbSegments = new IMappedSegment[1]; describedFbSegments[0] = new MusteinSegment(this, frameBufferSize); this.NoisyLog("Allocate memory {0} bytes big with aligment margin of {1}. Together it's {2} bytes.", frameBufferSize, alignment, frameBufferSize + alignment); var allocSeg = Marshal.AllocHGlobal(this.frameBufferSize + alignment); var originalPointer = (long)allocSeg; var alignedPointer = (IntPtr)((originalPointer + alignment) & ~(alignment - 1)); musteinFramebufferSegment = alignedPointer; this.NoisyLog(string.Format("FB alloc @ 0x{0:X} (aligned to 0x{1:X}, even after aligment there is at least 0x{2:X} bytes avaiable).", allocSeg.ToInt64(), alignedPointer.ToInt64(), frameBufferSize)); // Populate the buffer with zeros, on bigger buffers and slower perfomance, use the memSet DLLimport. // https://stackoverflow.com/questions/1897555 for (int index = 0; index < this.frameBufferSize; index++) { Marshal.WriteByte(alignedPointer + index, 0); } // Configuire the base class Video width/height/color Reconfigure(defaultWidth, defaultHeight, defaultColor); // Populate a transfer function for each color, alignment and packing modes copyPatterns = new Dictionary <Tuple <ColorMode, bool, PixelPacking>, Action>() { // <colors, is64bitAlignedPeripheral, packingMode> = CommandActionToExecute { Tuple.Create(ColorMode.LowColor, false, PixelPacking.SinglePixelPerWrite), () => ConvertAndSkip(1, 3) }, { Tuple.Create(ColorMode.HighColor, false, PixelPacking.SinglePixelPerWrite), () => CopyAndSkip(2, 2) }, { Tuple.Create(ColorMode.TrueColor, false, PixelPacking.SinglePixelPerWrite), CopyFully }, { Tuple.Create(ColorMode.LowColor, false, PixelPacking.FullyPacked32bit), ConvertFully }, { Tuple.Create(ColorMode.HighColor, false, PixelPacking.FullyPacked32bit), CopyFully }, { Tuple.Create(ColorMode.TrueColor, false, PixelPacking.FullyPacked32bit), CopyFully }, // In a 32bit peripheral aligment mode using fully packed 64bit is ilegal and will act as fully packed 32bit { Tuple.Create(ColorMode.LowColor, false, PixelPacking.FullyPacked64bit), ConvertFully }, { Tuple.Create(ColorMode.HighColor, false, PixelPacking.FullyPacked64bit), CopyFully }, { Tuple.Create(ColorMode.TrueColor, false, PixelPacking.FullyPacked64bit), CopyFully }, { Tuple.Create(ColorMode.LowColor, true, PixelPacking.SinglePixelPerWrite), () => ConvertAndSkip(1, 7) }, { Tuple.Create(ColorMode.HighColor, true, PixelPacking.SinglePixelPerWrite), () => CopyAndSkip(2, 6) }, { Tuple.Create(ColorMode.TrueColor, true, PixelPacking.SinglePixelPerWrite), () => CopyAndSkip(4, 4) }, { Tuple.Create(ColorMode.LowColor, true, PixelPacking.FullyPacked32bit), () => ConvertAndSkip(4, 4) }, { Tuple.Create(ColorMode.HighColor, true, PixelPacking.FullyPacked32bit), () => CopyAndSkip(2, 4) }, { Tuple.Create(ColorMode.TrueColor, true, PixelPacking.FullyPacked32bit), () => CopyAndSkip(4, 4) }, { Tuple.Create(ColorMode.LowColor, true, PixelPacking.FullyPacked64bit), ConvertFully }, { Tuple.Create(ColorMode.HighColor, true, PixelPacking.FullyPacked64bit), CopyFully }, { Tuple.Create(ColorMode.TrueColor, true, PixelPacking.FullyPacked64bit), CopyFully }, }; // Populate the control registers addresses GenerateRegisterCollection(); }