Exemple #1
0
        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);
        }
Exemple #2
0
 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)
 {
 }
Exemple #4
0
 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);
         }
     }
 }
Exemple #5
0
 public SegmentMapping(IMappedSegment segment)
 {
     Segment = segment;
 }
Exemple #6
0
 public virtual void MapMemory(IMappedSegment segment)
 {
 }
Exemple #7
0
        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();
        }