예제 #1
0
        private IVisualization2d GenerateHiResSprite(ReadOnlyDictionary <string, object> parms)
        {
            int  offset       = Util.GetFromObjDict(parms, P_OFFSET, 0);
            byte color        = (byte)Util.GetFromObjDict(parms, P_COLOR, 0);
            bool isDoubleWide = Util.GetFromObjDict(parms, P_DOUBLE_WIDE, false);
            bool isDoubleHigh = Util.GetFromObjDict(parms, P_DOUBLE_HIGH, false);

            if (offset < 0 || offset >= mFileData.Length || color < 0 || color > MAX_COLOR)
            {
                // the UI should flag these based on range (and ideally wouldn't have called us)
                mAppRef.ReportError("Invalid parameter");
                return(null);
            }

            int lastOffset = offset + SPRITE_SIZE - 1;

            if (lastOffset >= mFileData.Length)
            {
                mAppRef.ReportError("Sprite runs off end of file (last offset +" +
                                    lastOffset.ToString("x6") + ")");
                return(null);
            }

            int xwide = isDoubleWide ? 2 : 1;
            int xhigh = isDoubleHigh ? 2 : 1;

            VisBitmap8 vb = new VisBitmap8(BYTE_WIDTH * 8 * xwide, HEIGHT * xhigh);

            SetPalette(vb);

            // Clear all pixels to transparent, then just draw the non-transparent ones.
            vb.SetAllPixelIndices(TRANSPARENT);

            for (int row = 0; row < HEIGHT; row++)
            {
                for (int col = 0; col < BYTE_WIDTH; col++)
                {
                    byte val = mFileData[offset + row * BYTE_WIDTH + col];
                    for (int bit = 0; bit < 8; bit++)
                    {
                        if ((val & 0x80) != 0)
                        {
                            int xc = (col * 8 + bit) * xwide;
                            int yc = row * xhigh;
                            vb.SetPixelIndex(xc, yc, color);
                            if (isDoubleWide || isDoubleHigh)
                            {
                                // Draw doubled pixels.  If we're only doubled in one dimension
                                // this will draw pixels twice.
                                vb.SetPixelIndex(xc + xwide - 1, yc, color);
                                vb.SetPixelIndex(xc, yc + xhigh - 1, color);
                                vb.SetPixelIndex(xc + xwide - 1, yc + xhigh - 1, color);
                            }
                        }
                        val <<= 1;
                    }
                }
            }
            return(vb);
        }
예제 #2
0
        private IVisualization2d GenerateBitmap(ReadOnlyDictionary <string, object> parms)
        {
            int offset    = Util.GetFromObjDict(parms, P_OFFSET, 0);
            int byteWidth = Util.GetFromObjDict(parms, P_BYTE_WIDTH, 1);
            int height    = Util.GetFromObjDict(parms, P_HEIGHT, 1);
            int rowStride = Util.GetFromObjDict(parms, P_ROW_STRIDE, 0);

            if (rowStride == 0)
            {
                rowStride = byteWidth;  // provide nice default when stride==0
            }
            if (offset < 0 || offset >= mFileData.Length ||
                byteWidth <= 0 || byteWidth > MAX_DIM ||
                height <= 0 || height > MAX_DIM)
            {
                mAppRef.ReportError("Invalid parameter");
                return(null);
            }
            if (rowStride < byteWidth || rowStride > MAX_DIM)
            {
                mAppRef.ReportError("Invalid row stride");
                return(null);
            }

            int lastOffset = offset + rowStride * height - 1;

            if (lastOffset >= mFileData.Length)
            {
                mAppRef.ReportError("Bitmap runs off end of file (last offset +" +
                                    lastOffset.ToString("x6") + ")");
                return(null);
            }

            VisBitmap8 vb = new VisBitmap8(byteWidth * 8, height);

            SetPalette(vb);

            // Convert bits to pixels.
            for (int row = 0; row < height; row++)
            {
                for (int byteCol = 0; byteCol < byteWidth; byteCol++)
                {
                    byte val = mFileData[offset + row * rowStride + byteCol];
                    for (int bit = 0; bit < 8; bit++)
                    {
                        if ((val & 0x80) != 0)
                        {
                            vb.SetPixelIndex(byteCol * 8 + bit, row, (byte)Color.Solid);
                        }
                        else
                        {
                            vb.SetPixelIndex(byteCol * 8 + bit, row, (byte)Color.Transparent);
                        }
                        val <<= 1;
                    }
                }
            }
            return(vb);
        }
예제 #3
0
        // IPlugin_Visualizer
        public IVisualization2d Generate2d(VisDescr descr,
                                           ReadOnlyDictionary <string, object> parms)
        {
            VisBitmap8 vb = new VisBitmap8(1, 1);

            vb.AddColor(0, 0, 0, 0);
            vb.SetPixelIndex(0, 0, 0);
            return(vb);
        }
예제 #4
0
        /// <summary>
        /// Plots a point if appropriate, and updates xc/yc according to the vector.  The
        /// min/max values are updated if a point is plotted -- no need to expand the bitmap
        /// outside the range of actual plotted points.
        /// </summary>
        private void DrawVector(int bits, bool isC, ref int xc, ref int yc,
                                ref int xmin, ref int xmax, ref int ymin, ref int ymax, VisBitmap8 vb)
        {
            if ((bits & 0x04) != 0)
            {
                if (vb != null)
                {
                    // plot a point
                    vb.SetPixelIndex(xc - xmin, yc - ymin, 1);
                }
                if (xmin > xc)
                {
                    xmin = xc;
                }
                if (xmax < xc)
                {
                    xmax = xc;
                }
                if (ymin > yc)
                {
                    ymin = yc;
                }
                if (ymax < yc)
                {
                    ymax = yc;
                }
            }
            switch (bits & 0x03)
            {
            case 0x00:
                if (isC)
                {
                    // do nothing
                }
                else
                {
                    // move up
                    yc--;
                }
                break;

            case 0x01:
                // move right
                xc++;
                break;

            case 0x02:
                // move down
                yc++;
                break;

            case 0x03:
                // move left
                xc--;
                break;
            }
        }
예제 #5
0
        private IVisualization2d GenerateSprite(ReadOnlyDictionary <string, object> parms)
        {
            int offset = Util.GetFromObjDict(parms, P_OFFSET, 0);
            int height = Util.GetFromObjDict(parms, P_HEIGHT, 1);

            if (offset < 0 || offset >= mFileData.Length ||
                height <= 0 || height > MAX_HEIGHT)
            {
                // the UI should flag these based on range (and ideally wouldn't have called us)
                mAppRef.ReportError("Invalid parameter");
                return(null);
            }

            int lastOffset = offset + height - 1;

            if (lastOffset >= mFileData.Length)
            {
                mAppRef.ReportError("Sprite runs off end of file (last offset +" +
                                    lastOffset.ToString("x6") + ")");
                return(null);
            }

            VisBitmap8 vb = new VisBitmap8(8, height);

            SetPalette(vb);

            for (int row = 0; row < height; row++)
            {
                byte val = mFileData[offset + row];
                for (int col = 0; col < 8; col++)
                {
                    if ((val & 0x80) != 0)
                    {
                        vb.SetPixelIndex(col, row, (byte)Color.Solid);
                    }
                    else
                    {
                        vb.SetPixelIndex(col, row, (byte)Color.Transparent);
                    }
                    val <<= 1;
                }
            }
            return(vb);
        }
예제 #6
0
        private void RenderHiResBitmap(int offset, int byteWidth, int height,
                                       bool isDoubleWide, bool isDoubleHigh,
                                       byte color, VisBitmap8 vb, int startx, int starty)
        {
            int xwide = isDoubleWide ? 2 : 1;
            int xhigh = isDoubleHigh ? 2 : 1;

            for (int row = 0; row < height; row++)
            {
                for (int col = 0; col < byteWidth; col++)
                {
                    byte val = mFileData[offset + row * byteWidth + col];
                    for (int bit = 0; bit < 8; bit++)
                    {
                        byte pixColor;
                        if ((val & 0x80) == 0)
                        {
                            pixColor = TRANSPARENT;
                        }
                        else
                        {
                            pixColor = color;
                        }
                        int xc = startx + (col * 8 + bit) * xwide;
                        int yc = starty + row * xhigh;
                        vb.SetPixelIndex(xc, yc, pixColor);
                        if (isDoubleWide || isDoubleHigh)
                        {
                            // Draw doubled pixels.  If we're only doubled in one dimension
                            // this will draw some pixels twice.
                            vb.SetPixelIndex(xc + xwide - 1, yc, pixColor);
                            vb.SetPixelIndex(xc, yc + xhigh - 1, pixColor);
                            vb.SetPixelIndex(xc + xwide - 1, yc + xhigh - 1, pixColor);
                        }
                        val <<= 1;
                    }
                }
            }
        }
예제 #7
0
        private void RenderMultiColorBitmap(int offset, int byteWidth, int height,
                                            bool isDoubleWide, bool isDoubleHigh,
                                            byte color, byte color01, byte color11, VisBitmap8 vb, int startx, int starty)
        {
            int xwide = isDoubleWide ? 2 : 1;
            int xhigh = isDoubleHigh ? 2 : 1;

            for (int row = 0; row < height; row++)
            {
                for (int col = 0; col < byteWidth; col++)
                {
                    byte val = mFileData[offset + row * byteWidth + col];
                    for (int bit = 0; bit < 8; bit += 2)
                    {
                        byte pixColor = 0;
                        switch (val & 0xc0)
                        {
                        case 0x00:  pixColor = TRANSPARENT; break;

                        case 0x80:  pixColor = color;       break;

                        case 0x40:  pixColor = color01;     break;

                        case 0xc0:  pixColor = color11;     break;
                        }
                        int xc = startx + (col * 8 + bit) * xwide;
                        int yc = starty + row * xhigh;
                        // Set two adjacent pixels.
                        vb.SetPixelIndex(xc, yc, pixColor);
                        vb.SetPixelIndex(xc + 1, yc, pixColor);
                        if (isDoubleWide || isDoubleHigh)
                        {
                            // Draw doubled pixels.  If we're only doubled in one dimension
                            // this will draw some pixels twice.
                            vb.SetPixelIndex(xc + xwide * 2 - 2, yc, pixColor);
                            vb.SetPixelIndex(xc + xwide * 2 - 1, yc, pixColor);
                            vb.SetPixelIndex(xc, yc + xhigh - 1, pixColor);
                            vb.SetPixelIndex(xc + 1, yc + xhigh - 1, pixColor);
                            vb.SetPixelIndex(xc + xwide * 2 - 2, yc + xhigh - 1, pixColor);
                            vb.SetPixelIndex(xc + xwide * 2 - 1, yc + xhigh - 1, pixColor);
                        }
                        val <<= 2;
                    }
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Renders a tile from the PPU pattern table.
        /// </summary>
        /// <param name="tileNum">Tile number (0-511).</param>
        /// <param name="vb">Bitmap to render to.</param>
        /// <param name="xc">X coordinate for upper-left coordinate.</param>
        /// <param name="yc">Y coordinate for upper-left coordinate.</param>
        /// <param name="flipHoriz">Flip pixels horizontally</param>
        private void RenderTile(int tileNum, VisBitmap8 vb, int xc, int yc, bool flipHoriz)
        {
            int tileOff = mChrRomOffset + tileNum * BytesPerTile;

            for (int row = 0; row < 8; row++)
            {
                byte part0 = mFileData[tileOff];
                byte part1 = mFileData[tileOff + 8];
                for (int bit = 7; bit >= 0; bit--)
                {
                    int val = ((part0 >> bit) & 0x01) | (((part1 >> bit) & 0x01) << 1);
                    vb.SetPixelIndex(xc + (flipHoriz ? bit : 7 - bit), yc,
                                     (byte)((byte)Color.Color0 + val));
                }

                tileOff++;
                yc++;
            }
        }
예제 #9
0
        private void RenderHalfField(VisBitmap8 vb, int row, int rowDup, int startCol, int val,
                                     Color setColor)
        {
            for (int col = startCol; col < startCol + HALF_WIDTH; col++)
            {
                val <<= 1;
                byte colorIdx;
                if ((val & (1 << HALF_WIDTH)) != 0)
                {
                    colorIdx = (byte)setColor;
                }
                else
                {
                    colorIdx = (byte)Color.Black;
                }

                for (int r = row; r < row + rowDup; r++)
                {
                    vb.SetPixelIndex(col, r, colorIdx);
                }
            }
        }
예제 #10
0
        /// <summary>
        /// Renders bitmap data.
        /// </summary>
        /// <param name="data">Data source, typically the file data.</param>
        /// <param name="offset">Offset into data of the first byte.</param>
        /// <param name="byteWidth">Width, in bytes, of the data to render.  Each byte
        ///   represents 7 pixels in the output (more or less).</param>
        /// <param name="height">Height, in lines, of the data to render.</param>
        /// <param name="colStride">Column stride.  The number of bytes used to hold each
        ///   byte of data.  Must be >= 1.</param>
        /// <param name="rowStride">Row stride.  The number of bytes used to hold each row
        ///   of data.  Must be >= (colStride * byteWidth - (colStride - 1)).</param>
        /// <param name="colorMode">Color conversion mode.</param>
        /// <param name="isFirstOdd">If true, render as if we're starting on an odd column.
        ///   This affects the colors.</param>
        /// <param name="isHighBitFlipped">If true, render as if the high bit has the
        ///   opposite value.  This affects the colors.</param>
        /// <param name="vb">Output bitmap object.</param>
        /// <param name="xstart">Initial X position in the output.</param>
        /// <param name="ystart">Initial Y position in the output.</param>
        private void RenderBitmap(byte[] data, int offset, int byteWidth, int height,
                                  int colStride, int rowStride, ColorMode colorMode, bool isFirstOdd,
                                  bool isHighBitFlipped, VisBitmap8 vb, int xstart, int ystart)
        {
            int bx = xstart;
            int by = ystart;

            switch (colorMode)
            {
            case ColorMode.Mono: {
                // Since we're not displaying this we don't need to worry about
                // half-pixel shifts, and can just convert 7 bits to pixels.
                for (int row = 0; row < height; row++)
                {
                    int colIdx = 0;
                    for (int col = 0; col < byteWidth; col++)
                    {
                        byte val = data[offset + colIdx];
                        for (int bit = 0; bit < 7; bit++)
                        {
                            if ((val & 0x01) == 0)
                            {
                                vb.SetPixelIndex(bx, by, (int)HiResColors.Black0);
                            }
                            else
                            {
                                vb.SetPixelIndex(bx, by, (int)HiResColors.White0);
                            }
                            val >>= 1;
                            bx++;
                        }
                        colIdx += colStride;
                    }
                    bx = xstart;
                    by++;
                    offset += rowStride;
                }
            }
            break;

            case ColorMode.SimpleColor: {
                // Straightforward conversion, with no funky border effects.  This
                // represents an idealized version of the hardware.

                // Bits for every byte, plus a couple of "fake" bits on the ends so
                // we don't have to throw range-checks everywhere.
                const int OVER     = 2;
                bool[]    lineBits = new bool[OVER + byteWidth * 7 + OVER];
                bool[]    hiFlags  = new bool[OVER + byteWidth * 7 + OVER];
                for (int row = 0; row < height; row++)
                {
                    // Unravel the bits.  Note we do each byte "backwards", i.e. the
                    // low bit (which is generally considered to be on the right) is
                    // the leftmost pixel.
                    int idx    = OVER;          // start past "fake" bits
                    int colIdx = 0;
                    for (int col = 0; col < byteWidth; col++)
                    {
                        byte val      = data[offset + colIdx];
                        bool hiBitSet = (val & 0x80) != 0;

                        for (int bit = 0; bit < 7; bit++)
                        {
                            hiFlags[idx]  = hiBitSet ^ isHighBitFlipped;
                            lineBits[idx] = (val & 0x01) != 0;
                            idx++;
                            val >>= 1;
                        }
                        colIdx += colStride;
                    }

                    // Convert to color.
                    int lastBit = byteWidth * 7;
                    for (idx = OVER; idx < lastBit + OVER; idx++)
                    {
                        int colorShift = hiFlags[idx] ? 2 : 0;
                        if (lineBits[idx] && (lineBits[idx - 1] || lineBits[idx + 1]))
                        {
                            // [X]11 or [1]1X; two 1s in a row is always white
                            vb.SetPixelIndex(bx++, by, (byte)HiResColors.White0);
                        }
                        else if (lineBits[idx])
                        {
                            // [0]10, color pixel
                            bool isOdd = ((idx & 0x01) != 0) ^ isFirstOdd;
                            if (isOdd)
                            {
                                vb.SetPixelIndex(bx++, by,
                                                 (byte)((int)HiResColors.Green + colorShift));
                            }
                            else
                            {
                                vb.SetPixelIndex(bx++, by,
                                                 (byte)((int)HiResColors.Purple + colorShift));
                            }
                        }
                        else if (lineBits[idx - 1] && lineBits[idx + 1])
                        {
                            // [1]01, keep color going
                            bool isOdd = ((idx & 0x01) != 0) ^ isFirstOdd;
                            if (isOdd)
                            {
                                vb.SetPixelIndex(bx++, by,
                                                 (byte)((int)HiResColors.Purple + colorShift));
                            }
                            else
                            {
                                vb.SetPixelIndex(bx++, by,
                                                 (byte)((int)HiResColors.Green + colorShift));
                            }
                        }
                        else
                        {
                            // [0]0X or [X]01
                            vb.SetPixelIndex(bx++, by, (byte)HiResColors.Black0);
                        }
                    }

                    // move to next row
                    bx = xstart;
                    by++;
                    offset += rowStride;
                }
            }
            break;

            case ColorMode.IIgsRGB: {
                // Color conversion similar to what CiderPress does, but without the
                // half-pixel shift (we're trying to create a 1:1 bitmap, not 1:2).
                //
                // This replicates some of the oddness in Apple IIgs RGB monitor output,
                // but it's not quite right though.  For example:
                //
                //                   observed                 generated
                //  d5 2a:    blue   [dk blue] purple       ... black ...
                //  aa 55:    orange [yellow]  green        ... white ...
                //  55 aa:    purple [lt blue] blue         ... black ...
                //  2a d5:    green  [brown]   orange       ... black ...
                //
                // KEGS doesn't seem to try to model this; it shows solid colors with no
                // wackiness.  AppleWin in "Color TV" mode shows similar effects, but is
                // much blurrier (by design).
                bool[] lineBits = new bool[byteWidth * 7];
                bool[] hiFlags  = new bool[byteWidth * 7];          // overkill, but simpler
                int[]  colorBuf = new int[byteWidth * 7];
                for (int row = 0; row < height; row++)
                {
                    // Unravel the bits.
                    int idx    = 0;
                    int colIdx = 0;
                    for (int col = 0; col < byteWidth; col++)
                    {
                        byte val      = data[offset + colIdx];
                        bool hiBitSet = (val & 0x80) != 0;

                        for (int bit = 0; bit < 7; bit++)
                        {
                            hiFlags[idx]  = hiBitSet ^ isHighBitFlipped;
                            lineBits[idx] = (val & 0x01) != 0;
                            idx++;
                            val >>= 1;
                        }
                        colIdx += colStride;
                    }

                    // Convert to color.
                    int lastBit = byteWidth * 7;
                    for (idx = 0; idx < lastBit; idx++)
                    {
                        int colorShift = hiFlags[idx] ? 2 : 0;
                        if (!lineBits[idx])
                        {
                            // Bit not set, set pixel to black.
                            colorBuf[idx] = (int)HiResColors.Black0;
                        }
                        else
                        {
                            // Bit set, set pixel to white or color.
                            if (idx > 0 && colorBuf[idx - 1] != (int)HiResColors.Black0)
                            {
                                // previous bit was also set, this is white
                                colorBuf[idx] = (int)HiResColors.White0;

                                // the previous pixel is part of a run of white
                                colorBuf[idx - 1] = (int)HiResColors.White0;
                            }
                            else
                            {
                                // previous bit not set *or* was first pixel in line;
                                // set color based on whether this is even or odd pixel col
                                bool isOdd = ((idx & 0x01) != 0) ^ isFirstOdd;
                                if (isOdd)
                                {
                                    colorBuf[idx] = (int)HiResColors.Green + colorShift;
                                }
                                else
                                {
                                    colorBuf[idx] = (int)HiResColors.Purple + colorShift;
                                }
                            }

                            // Do we have a run of the same color?  If so, smooth the
                            // color out. Note that white blends smoothly with everything.
                            if (idx > 1 && (colorBuf[idx - 2] == colorBuf[idx] ||
                                            colorBuf[idx - 2] == (int)HiResColors.White0))
                            {
                                colorBuf[idx - 1] = colorBuf[idx];
                            }
                        }
                    }

                    // Write to bitmap.
                    for (idx = 0; idx < lastBit; idx++)
                    {
                        vb.SetPixelIndex(bx++, by, (byte)colorBuf[idx]);
                    }

                    // move to next row
                    bx = xstart;
                    by++;
                    offset += rowStride;
                }
            }
            break;

            default:
                // just leave the bitmap empty
                mAppRef.ReportError("Unknown ColorMode " + colorMode);
                break;
            }
        }