示例#1
0
        /// <summary>
        /// Returns a single row (byte) in the character data.
        /// </summary>
        /// <param name="CharacterCode">Character code</param>
        /// <param name="Row">Row in glpyh</param>
        /// <returns></returns>
        public byte Read(int CharacterCode, int Row)
        {
            if (CharacterData == null)
            {
                return(0);
            }
            int addr = StartAddress + CharacterCode * charHeight + Row;

            return(CharacterData.ReadByte(addr));
        }
示例#2
0
文件: Gpu.cs 项目: dwsJason/FoenixIDE
        public static int[] LoadLUT(MemoryRAM VKY)
        {
            // Read the color lookup tables
            int lutAddress   = MemoryMap.GRP_LUT_BASE_ADDR - MemoryMap.VICKY_BASE_ADDR;
            int lookupTables = 4;

            int[] result = new int[lookupTables * 256];


            for (int c = 0; c < lookupTables * 256; c++)
            {
                byte blue  = VKY.ReadByte(lutAddress++);
                byte green = VKY.ReadByte(lutAddress++);
                byte red   = VKY.ReadByte(lutAddress++);
                lutAddress++; // skip the alpha channel
                result[c] = (0xFF << 24) + (red << 16) + (green << 8) + blue;
            }
            return(result);
        }
示例#3
0
文件: Gpu.cs 项目: dwsJason/FoenixIDE
        private void DrawBitmap(ref BitmapData bd, bool bkgrnd)
        {
            // Bitmap Controller is located at $AF:0140
            int reg = VICKY.ReadByte(MemoryMap.BITMAP_CONTROL_REGISTER_ADDR - MemoryMap.VICKY_BASE_ADDR);

            if ((reg & 0x01) == 00)
            {
                return;
            }
            int lutIndex = (reg & 14) >> 1;  // 8 possible LUTs

            int bitmapAddress = VICKY.ReadLong(0xAF_0141 - MemoryMap.VICKY_BASE_ADDR);
            int width         = VICKY.ReadWord(0xAF_0144 - MemoryMap.VICKY_BASE_ADDR);
            int height        = VICKY.ReadWord(0xAF_0146 - MemoryMap.VICKY_BASE_ADDR);
            int borderXSize   = VICKY.ReadByte(0xAF_0008 - MemoryMap.VICKY_BASE_ADDR);
            int borderYSize   = VICKY.ReadByte(0xAF_0009 - MemoryMap.VICKY_BASE_ADDR);

            //BitmapData bitmapData = frameBuffer.LockBits(new Rectangle(0,0,640, 480), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
            IntPtr p     = bd.Scan0;
            int    value = 0;

            for (int line = borderYSize; line < (height - borderYSize); line++)
            {
                for (int col = borderXSize; col < (width - borderXSize); col++)
                {
                    value = graphicsLUT[lutIndex * 256 + VRAM.ReadByte(bitmapAddress + col + line * 640)];
                    if (gammaCorrection != null)
                    {
                        value = (int)((gammaCorrection[(value & 0x00FF0000) >> 0x10] << 0x10) +
                                      (gammaCorrection[0x100 + ((value & 0x0000FF00) >> 0x08)] << 0x08) +
                                      (gammaCorrection[0x200 + (value & 0x000000FF)]) + 0xFF000000);
                    }

                    System.Runtime.InteropServices.Marshal.WriteInt32(p, (line * width + col) * 4, value);
                }
            }
        }
示例#4
0
        private unsafe void DrawTiles(int *p, bool gammaCorrection, byte TextColumns, int layer, bool bkgrnd, int borderXSize, int line, int width)
        {
            // There are four possible tilemaps to choose from
            int addrTileCtrlReg = MemoryMap.TILE_CONTROL_REGISTER_ADDR + layer * 12 - MemoryMap.VICKY_BASE_ADDR;
            int reg             = VICKY.ReadByte(addrTileCtrlReg);

            // if the set is not enabled, we're done.
            if ((reg & 0x01) == 00)
            {
                return;
            }

            int tilemapWidth   = VICKY.ReadWord(addrTileCtrlReg + 4) & 0x3FF; // 10 bits
            int tilemapHeight  = VICKY.ReadWord(addrTileCtrlReg + 6) & 0x3FF; // 10 bits
            int tilemapAddress = VICKY.ReadLong(addrTileCtrlReg + 1);

            int  tilemapWindowX = VICKY.ReadWord(addrTileCtrlReg + 8);
            bool dirUp          = (tilemapWindowX & 0x4000) != 0;
            byte scrollX        = (byte)(tilemapWindowX & 0x3C00 >> 10);

            tilemapWindowX &= 0x3FF;
            byte tileXOffset = (byte)(tilemapWindowX % TILE_SIZE);

            int  tilemapWindowY = VICKY.ReadWord(addrTileCtrlReg + 10);
            bool dirRight       = (tilemapWindowY & 0x4000) != 0;
            byte scrollY        = (byte)(tilemapWindowY & 0x3C00 >> 10);

            tilemapWindowY &= 0x3FF;

            int tileRow     = (line + tilemapWindowY) / TILE_SIZE;
            int tileYOffset = (line + tilemapWindowY) % TILE_SIZE;

            // we always read tiles 0 to width/TILE_SIZE + 1 - this is to ensure we can display partial tiles, with X,Y offsets
            int tilemapItemCount = width / TILE_SIZE + 1;

            byte[] tiles          = new byte[tilemapItemCount * 2];
            int[]  tilesetOffsets = new int[tilemapItemCount];
            VRAM.CopyIntoBuffer(tilemapAddress + (1 + tilemapWindowX / TILE_SIZE) * 2 + (tileRow + 0) * tilemapWidth * 2, tiles, 0, tilemapItemCount * 2);

            // cache of tilesetPointers
            int[] tilesetPointers = new int[8];
            int[] strides         = new int[8];
            for (int i = 0; i < 8; i++)
            {
                tilesetPointers[i] = VICKY.ReadLong(MemoryMap.TILESET_BASE_ADDR - MemoryMap.VICKY_BASE_ADDR + i * 4);
                byte tilesetConfig = VICKY.ReadByte(MemoryMap.TILESET_BASE_ADDR - MemoryMap.VICKY_BASE_ADDR + i * 4 + 3);
                strides[i] = (tilesetConfig & 8) != 0 ? 256 : 1;
            }
            for (int i = 0; i < tilemapItemCount; i++)
            {
                byte tile       = tiles[i * 2];
                byte tilesetReg = tiles[i * 2 + 1];
                byte tileset    = (byte)(tilesetReg & 7);
                //byte tileLUT = (byte)((tilesetReg & 0x38) >> 3);

                // tileset
                int tilesetPointer = tilesetPointers[tileset];
                int strideX        = strides[tileset];

                tilesetOffsets[i] = tilesetPointer + ((tile / TILE_SIZE) * strideX * TILE_SIZE + (tile % TILE_SIZE) * TILE_SIZE) + tileYOffset * strideX;
            }

            int *ptr = p + line * STRIDE;

            // Ensure that only one line gets drawn, this avoid incorrect wrapping
            for (int x = borderXSize; x < width - borderXSize; x++)
            {
                int tileIndex = (x + tileXOffset) / TILE_SIZE;
                //byte tile = tiles[tileIndex];
                byte tilesetReg = tiles[tileIndex * 2 + 1];
                //byte tileset = (byte)(tilesetReg & 7);
                byte tileLUT = (byte)((tilesetReg & 0x38) >> 3);

                // tileset
                //int tilesetPointer = tilesetPointers[tileset];
                //int strideX = strides[tileset];

                int tilesetOffsetAddress = tilesetOffsets[tileIndex] + (x + tilemapWindowX) % TILE_SIZE;   //((tile / TILE_SIZE) * strideX * TILE_SIZE + (tile % TILE_SIZE) * TILE_SIZE) + tileYOffset * strideX + (x + tilemapWindowX) % TILE_SIZE;
                //byte pixelIndex = VRAM.ReadByte(tilesetPointer + tilesetOffsetAddress );
                byte pixelIndex = VRAM.ReadByte(tilesetOffsetAddress);
                if (pixelIndex > 0)
                {
                    int value = GetLUTValue(tileLUT, pixelIndex, gammaCorrection);
                    ptr[x] = value;
                }
            }
        }
示例#5
0
        private unsafe void DrawBitmapText(int *p, int MCR, bool gammaCorrection, byte TextColumns, byte TextRows, int colOffset, int rowOffset, int line, int width, int height)
        {
            bool overlayBitSet = (MCR & 0x02) == 0x02;

            int lineStartAddress  = MemoryLocations.MemoryMap.SCREEN_PAGE0 - VICKY.StartAddress;
            int colorStartAddress = MemoryLocations.MemoryMap.SCREEN_PAGE1 - VICKY.StartAddress;
            int fontBaseAddress   = MemoryLocations.MemoryMap.FONT0_MEMORY_BANK_START - VICKY.StartAddress;

            // Find which line of characters to display
            int txtline = (line - rowOffset) / CHAR_HEIGHT;

            //if (txtline + 1 > RAM.ReadByte(MemoryMap.LINES_MAX)) return;
            //byte COLS_PER_LINE = RAM.ReadByte(MemoryMap.COLS_PER_LINE);

            // Initialize the LUTs
            FGTextLUT = new int[16];
            BGTextLUT = new int[16];

            // Cursor Values
            byte CursorY       = RAM.ReadByte(MemoryMap.CURSORY);
            byte CursorX       = RAM.ReadByte(MemoryMap.CURSORX);
            bool CursorEnabled = (VICKY.ReadByte(MemoryMap.VKY_TXT_CURSOR_CTRL_REG - MemoryMap.VICKY_START) & 1) != 0;

            // Each character is defined by 8 bytes
            int  fontLine = (line - rowOffset) % CHAR_HEIGHT;
            int *ptr      = p + line * STRIDE + colOffset;

            for (int col = 0; col < width / CHAR_WIDTH; col++)
            {
                int x = col * CHAR_WIDTH;
                if (x + colOffset > width - 1 - colOffset)
                {
                    continue;
                }
                int offset = 0;
                if (col < TextColumns)
                {
                    offset = TextColumns * txtline + col;
                }
                int textAddr  = lineStartAddress + offset;
                int colorAddr = colorStartAddress + offset;
                // Each character will have foreground and background colors
                byte character = VICKY.ReadByte(textAddr);
                byte color     = VICKY.ReadByte(colorAddr);

                // Display the cursor
                if (CursorX == col && CursorY == txtline && CursorState && CursorEnabled)
                {
                    character = VICKY.ReadByte(MemoryLocations.MemoryMap.VKY_TXT_CURSOR_CHAR_REG - VICKY.StartAddress);
                }

                byte fgColor = (byte)((color & 0xF0) >> 4);
                byte bgColor = (byte)(color & 0x0F);

                int[] textColors = GetTextLUT(fgColor, bgColor, gammaCorrection);

                byte value = VICKY.ReadByte(fontBaseAddress + character * 8 + fontLine);
                //int offset = (x + line * 640) * 4;

                // For each bit in the font, set the foreground color - if the bit is 0 and overlay is set, skip it (keep the background)
                for (int b = 0x80; b > 0; b = b >> 1)
                {
                    if ((value & b) != 0)
                    {
                        //System.Runtime.InteropServices.Marshal.WriteInt32(p, offset, fgValue);
                        ptr[0] = textColors[0];
                    }
                    else if (!overlayBitSet)
                    {
                        //System.Runtime.InteropServices.Marshal.WriteInt32(p, offset, bgValue);
                        ptr[0] = textColors[1];
                    }
                    ptr++;
                    //offset += 4;
                }
            }
        }
示例#6
0
        public Point GetScreenSize()
        {
            byte MCRHigh = (byte)(VICKY.ReadByte(1) & 3); // Reading address $AF:0001

            Point p = new Point(640, 480);

            switch (MCRHigh)
            {
            case 1:
                p.X = 800;
                p.Y = 600;
                break;

            case 2:
                p.X = 320;
                p.Y = 240;
                break;

            case 3:
                p.X = 400;
                p.Y = 300;
                break;
            }
            return(p);
        }
示例#7
0
文件: Gpu.cs 项目: dwsJason/FoenixIDE
        void Gpu_Paint(object sender, PaintEventArgs e)
        {
            paintCycle++;
            if (DesignMode)
            {
                e.Graphics.DrawString("Design Mode", this.Font, TextBrush, 0, 0);
                return;
            }
            if (VICKY == null)
            {
                e.Graphics.DrawString("IO Memory Not Initialized", this.Font, TextBrush, 0, 0);
                return;
            }
            if (VRAM == null)
            {
                e.Graphics.DrawString("VRAM Not Initialized", this.Font, TextBrush, 0, 0);
                return;
            }
            if (RAM == null)
            {
                e.Graphics.DrawString("RAM Not Initialized", this.Font, TextBrush, 0, 0);
                return;
            }
            // Read the Master Control Register
            byte     MCRegister = VICKY.ReadByte(0); // Reading address $AF:0000
            int      top        = 0;                 // top gets modified if error messages are displayed
            Graphics g          = Graphics.FromImage(frameBuffer);

            if (MCRegister == 0 || (MCRegister & 0x80) == 0x80)
            {
                e.Graphics.DrawString("Graphics Mode disabled", this.Font, TextBrush, 0, 0);
                return;
            }
            else if ((MCRegister & 0x1) == 0x1)
            {
                if (ColumnsVisible < 1 || ColumnsVisible > MAX_TEXT_COLS)
                {
                    DrawTextWithBackground("ColumnsVisible invalid:" + ColumnsVisible.ToString(), g, Color.Black, 0, top);
                    top += 12;
                }
                if (LinesVisible < 1 || LinesVisible > MAX_TEXT_LINES)
                {
                    DrawTextWithBackground("LinesVisible invalid:" + LinesVisible.ToString(), g, Color.Black, 0, top);
                    top += 12;
                }
            }

            if (drawing)
            {
                // drop the frame
                return;
            }
            drawing = true;
            Stopwatch stopWatch = new Stopwatch();

            stopWatch.Start();
            e.Graphics.CompositingMode    = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
            e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
            e.Graphics.InterpolationMode  = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
            e.Graphics.SmoothingMode      = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;

            // Determine if we display a border
            int  border_register = VICKY.ReadByte(4);
            bool displayBorder   = (border_register & 1) == 1;

            int colOffset = VICKY.ReadByte(8);
            int rowOffset = VICKY.ReadByte(9);

            // Load Graphical LUTs
            graphicsLUT = LoadLUT(VICKY);

            // Apply gamma correct
            if ((MCRegister & 0x40) == 0x40)
            {
                gammaCorrection = LoadGammaCorrection(VICKY);
            }
            else
            {
                gammaCorrection = null;
            }

            // Default background color to border color
            // In Text mode, the border color is stored at $AF:0005.
            byte borderRed   = VICKY.ReadByte(5);
            byte borderGreen = VICKY.ReadByte(6);
            byte borderBlue  = VICKY.ReadByte(7);

            if (gammaCorrection != null)
            {
                borderRed   = gammaCorrection[0x200 + borderRed];
                borderGreen = gammaCorrection[0x100 + borderGreen];
                borderBlue  = gammaCorrection[borderBlue];
            }
            int borderColor = (int)(0xFF000000 + (borderBlue << 16) + (borderGreen << 8) + borderRed);

            if (tileEditorMode)
            {
                g.Clear(Color.LightGray);
                DrawTextWithBackground("Tile Editing Mode", g, Color.Black, 240, 10);
                DrawTextWithBackground("Tile Editing Mode", g, Color.Black, 240, 455);
            }
            else
            {
                g.Clear(Color.FromArgb(borderColor));
            }

            // Graphics Mode
            if ((MCRegister & 0x4) == 0x4)
            {
                byte backRed   = VICKY.ReadByte(0xD);
                byte backGreen = VICKY.ReadByte(0XE);
                byte backBlue  = VICKY.ReadByte(0xF);
                if (gammaCorrection != null)
                {
                    backRed   = gammaCorrection[0x200 + backRed];
                    backGreen = gammaCorrection[0x100 + backGreen];
                    backBlue  = gammaCorrection[backBlue];
                }
                int   backgroundColor      = (int)(0xFF000000 + (backBlue << 16) + (backGreen << 8) + backRed);
                Brush graphBackgroundBrush = new SolidBrush(Color.FromArgb(backgroundColor));
                g.FillRectangle(graphBackgroundBrush, colOffset, rowOffset, 640 - 2 * colOffset, 480 - 2 * rowOffset);
            }

            Rectangle  rect       = new Rectangle(0, 0, 640, 480);
            BitmapData bitmapData = frameBuffer.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

            // Bitmap Mode
            if ((MCRegister & 0x4) == 0x4 || tileEditorMode)
            {
                if ((MCRegister & 0x8) == 0x8)
                {
                    DrawBitmap(ref bitmapData, displayBorder);
                }

                for (int layer = 4; layer > 0; --layer)
                {
                    if ((MCRegister & 0x10) == 0x10)
                    {
                        DrawTiles(ref bitmapData, layer - 1, 640, displayBorder);
                    }
                    if ((MCRegister & 0x20) == 0x20)
                    {
                        DrawSprites(ref bitmapData, layer - 1, 640, displayBorder);
                    }
                }
            }
            if ((MCRegister & 7) == 0x1 || (MCRegister & 7) == 3 || (MCRegister & 7) == 7)
            {
                if (top == 0)
                {
                    DrawBitmapText(ref bitmapData, colOffset, rowOffset);
                }
            }
            byte mouseReg = VICKY.ReadByte(0x700);

            MousePointerMode = (mouseReg & 1) == 1;
            if (MousePointerMode && !TileEditorMode)
            {
                DrawMouse(ref bitmapData, 640);
            }
            frameBuffer.UnlockBits(bitmapData);
            e.Graphics.DrawImage(frameBuffer, ClientRectangle);
            drawing = false;
            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;

            if (ts.Milliseconds > 10)
            {
                Console.WriteLine("Drawing Time: " + ts.Milliseconds + "ms");
            }
            // This seems to make the rendering much better.  Do we care if this is 1 frame off?
            if (MCRegister != 0 && MCRegister != 0x80)
            {
                StartOfFrame?.Invoke();
            }
        }
示例#8
0
        private void DrawVectorText(Graphics g)
        {
            float x;
            float y;

            if (TextFont == null)
            {
                TextFont = GetBestFont();
            }
            SizeF charSize   = MeasureFont(TextFont, g);
            float charWidth  = charSize.Width / MEASURE_STRING.Length;
            float charHeight = charSize.Height;
            float RightCol   = charWidth * ColumnsVisible;
            float BottomRow  = charWidth * LinesVisible;

            float ScaleX = this.ClientRectangle.Width / RightCol;
            float ScaleY = this.ClientRectangle.Height / BottomRow;

            g.ResetTransform();
            g.ScaleTransform(ScaleX, ScaleY);

            if (VRAM == null)
            {
                return;
            }

            int col = 0, row = 0;

            for (int i = 0; i < BufferSize; i++)
            {
                if (col < ColumnsVisible)
                {
                    x = col * charWidth;
                    y = row * charHeight;

                    char c = (char)VRAM.ReadByte(i);
                    g.DrawString(c.ToString(),
                                 this.Font,
                                 TextBrush,
                                 x, y,
                                 StringFormat.GenericTypographic);
                }

                col++;
                if (col >= COLS_PER_LINE)
                {
                    col = 0;
                    row++;
                }
            }

            //if (CursorState && CursorEnabled)
            //{
            //    x = X * charWidth;
            //    y = Y * charHeight;
            //    g.FillRectangle(CursorBrush, x, y, charWidth, charHeight);
            //    g.DrawString(CharacterData[GetCharPos(Y, X)].ToString(),
            //        TextFont,
            //        InvertedBrush,
            //        x, y,
            //        StringFormat.GenericTypographic);
            //}
        }