vga.c

来自「这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统」· C语言 代码 · 共 1,275 行 · 第 1/3 页

C
1,275
字号
                 "Buffer: %p. Delta: %lx\n",
                 Width,
                 Height,
                 Left,
                 Top,
                 BitsPerPixel,
                 Buffer,
                 Delta);
        return;
    }

    /* Get the masks and other values */
    LeftAnd = Left & 0x7;
    lMask = lMaskTable[LeftAnd];
    Distance = Width + Left;
    rMask = rMaskTable[(Distance - 1) & 0x7];
    Left >>= 3;

    /* Set some values */
    SomeYesNoFlag = FALSE;
    SomeYesNoFlag2 = FALSE;
    Distance = (Distance - 1) >> 3;
    DistanceMinusLeftBpp = Distance - Left;

    /* Check if the distance is equal to the left position and add the masks */
    if (Left == Distance) lMask += rMask;

    /* Check if there's no distance offset */
    if (DistanceMinusLeftBpp)
    {
        /* Set the first flag on */
        SomeYesNoFlag = TRUE;

        /* Decrease offset and check if we still have one */
        if (--DistanceMinusLeftBpp)
        {
            /* Still have a distance offset */
            SomeYesNoFlag2 = TRUE;
        }
    }

    /* Calculate initial pixel position */
    PixelPosition = (PUCHAR)VgaBase + (Top * 80) + Left;

    /* Set loop buffer variable */
    i = Buffer;

    /* Switch to mode 0 */
    ReadWriteMode(0);

    /* Leave now if the height is 0 */
    if (Height <= 0) return;

    /* Set more weird values */
    CurrentLeft = &LeftArray[Left];
    NotlMask = ~(UCHAR)lMask;
    LeftPlusOne = Left + 1;
    LeftShifted = (lMask << 8) | 8;
    j = Height;

    /* Start the height loop */
    do
    {
        /* Start the plane loop */
        Plane = 0;
        do
        {
            /* Clear the current value */
            *CurrentLeft = 0;
            LoopCount = 0;

            /* Set the buffer loop variable for this loop */
            k = i;

            /* Calculate plane shift and pixel mask */
            PlaneShift = 1 << Plane;
            pMask = PixelMask[LeftAnd];

            /* Check if we have a width */
            if (Width > 0)
            {
                /* Loop it */
                l = CurrentLeft;
                x = Width;
                do
                {
                    /* Check if we're odd and increase the loop count */
                    Odd = LoopCount & 1 ? TRUE : FALSE;
                    LoopCount++;
                    if (Odd)
                    {
                        /* Check for the plane shift */
                        if (*k & PlaneShift)
                        {
                            /* Write the pixel mask */
                            *l |= pMask;
                        }

                        /* Increase buffer position */
                        k++;
                    }
                    else
                    {
                        /* Check for plane shift */
                        if ((*k >> 4) & PlaneShift)
                        {
                            /* Write the pixel mask */
                            *l |= pMask;
                        }
                    }

                    /* Shift the pixel mask */
                    pMask >>= 1;
                    if (!pMask)
                    {
                        /* Move to the next current left position and clear it */
                        l++;
                        *l = 0;

                        /* Set the pixel mask to 0x80 */
                        pMask = 0x80;
                    }
                } while (--x);
            }

            /* Set the plane value */
            __outpw(0x3C4, (1 << (Plane + 8) | 2));

            /* Select the bitmask register and write the mask */
            __outpw(0x3CE, (USHORT)LeftShifted);

            /* Read the current Pixel value */
            Value = READ_REGISTER_UCHAR(PixelPosition);

            /* Add our mask */
            Value = (Value & NotlMask) | *CurrentLeft;

            /* Set current left for the loop, and write new pixel value */
            LeftPos = LeftPlusOne;
            WRITE_REGISTER_UCHAR(PixelPosition, Value);

            /* Set loop pixel position and check if we should loop */
            m = PixelPosition + 1;
            if (SomeYesNoFlag2)
            {
                /* Set the bitmask to 0xFF for all 4 planes */
                __outpw(0x3CE, 0xFF08);

                /* Check if we have any distance left */
                if (DistanceMinusLeftBpp > 0)
                {
                    /* Start looping it */
                    x = DistanceMinusLeftBpp;
                    do
                    {
                        /* Write the value */
                        WRITE_REGISTER_UCHAR(m, LeftArray[LeftPos]);

                        /* Go to the next position */
                        m++;
                        LeftPos++;
                    } while (--x);
                }
            }

            /* Check if the first flag is on */
            if (SomeYesNoFlag)
            {
                /* Set the mask value */
                __outpw(0x3CE, (rMask << 8) | 8);

                /* Read the current Pixel value */
                Value = READ_REGISTER_UCHAR(m);

                /* Add our mask */
                Value = (Value & ~(UCHAR)rMask) | LeftArray[LeftPos];

                /* Set current left for the loop, and write new pixel value */
                WRITE_REGISTER_UCHAR(m, Value);
            }
        } while (++Plane < 4);

        /* Update pixel position, buffer and height */
        PixelPosition += 80;
        i += Delta;
    } while (--j);
}

VOID
NTAPI
RleBitBlt(IN ULONG Left,
          IN ULONG Top,
          IN ULONG Width,
          IN ULONG Height,
          IN PUCHAR Buffer)
{
    ULONG YDelta;
    ULONG x;
    ULONG RleValue, NewRleValue;
    ULONG Color, Color2;
    ULONG i, j;
    ULONG Code;

    /* Set Y height and current X value and start loop */
    YDelta = Top + Height - 1;
    x = Left;
    for (;;)
    {
        /* Get the current value and advance in the buffer */
        RleValue = *Buffer;
        Buffer++;
        if (RleValue)
        {
            /* Check if we've gone past the edge */
            if ((x + RleValue) > (Width + Left))
            {
                /* Fixeup the pixel value */
                RleValue = Left - x + Width;
            }

            /* Get the new value */
            NewRleValue = *Buffer;

            /* Get the two colors */
            Color = NewRleValue >> 4;
            Color2 = NewRleValue & 0xF;

            /* Increase buffer positition */
            Buffer++;

            /* Check if we need to do a fill */
            if (Color == Color2)
            {
                /* Do a fill and continue the loop */
                RleValue += x;
                VidSolidColorFill(x, YDelta, RleValue - 1, YDelta, (UCHAR)Color);
                x = RleValue;
                continue;
            }

            /* Check if the pixel value is 1 or below */
            if (RleValue > 1)
            {
                /* Set loop variables */
                i = (RleValue - 2) / 2 + 1;
                do
                {
                    /* Set the pixels */
                    SetPixel(x, YDelta, (UCHAR)Color);
                    x++;
                    SetPixel(x, YDelta, (UCHAR)Color2);
                    x++;

                    /* Decrease pixel value */
                    RleValue -= 2;
                } while (--i);
            }

            /* Check if there is any value at all */
            if (RleValue)
            {
                /* Set the pixel and increase posititon */
                SetPixel(x, YDelta, (UCHAR)Color);
                x++;
            }

            /* Start over */
            continue;
        }

        /* Get the current pixel value */
        RleValue = *Buffer;
        Code = RleValue;
        switch (Code)
        {
            /* Case 0 */
            case 0:

                /* Set new x value, decrease distance and restart */
                x = Left;
                YDelta--;
                Buffer++;
                continue;

            /* Case 1 */
            case 1:

                /* Done */
                return;

            /* Case 2 */
            case 2:

                /* Set new x value, decrease distance and restart */
                Buffer++;
                x += *Buffer;
                Buffer++;
                YDelta -= *Buffer;
                Buffer++;
                continue;

            /* Other values */
            default:

                Buffer++;
                break;
        }

        /* Check if we've gone past the edge */
        if ((x + RleValue) > (Width + Left))
        {
            /* Set fixed up loop count */
            i = RleValue - Left - Width + x;

            /* Fixup pixel value */
            RleValue -= i;
        }
        else
        {
            /* Clear loop count */
            i = 0;
        }

        /* Check the value now */
        if (RleValue > 1)
        {
            /* Set loop variables */
            j = (RleValue - 2) / 2 + 1;
            do
            {
                /* Get the new value */
                NewRleValue = *Buffer;

                /* Get the two colors */
                Color = NewRleValue >> 4;
                Color2 = NewRleValue & 0xF;

                /* Increase buffer position */
                Buffer++;

                /* Set the pixels */
                SetPixel(x, YDelta, (UCHAR)Color);
                x++;
                SetPixel(x, YDelta, (UCHAR)Color2);
                x++;

                /* Decrease pixel value */
                RleValue -= 2;
            } while (--j);
        }

        /* Check if there is any value at all */
        if (RleValue)
        {
            /* Set the pixel and increase position */
            Color = *Buffer >> 4;
            Buffer++;
            SetPixel(x, YDelta, (UCHAR)Color);
            x++;
            i--;
        }

        /* Check loop count now */
        if ((LONG)i > 0)
        {
            /* Decrease it */
            i--;

            /* Set new position */
            Buffer = Buffer + (i / 2) + 1;
        }

        /* Check if we need to increase the buffer */
        if ((ULONG_PTR)Buffer & 1) Buffer++;
    }
}

/* PUBLIC FUNCTIONS **********************************************************/

/*
 * @implemented
 */
ULONG
NTAPI
VidSetTextColor(ULONG Color)
{
    ULONG OldColor;

    /* Save the old color and set the new one */
    OldColor = TextColor;
    TextColor = Color;
    return OldColor;
}

/*
 * @implemented
 */
VOID
NTAPI
VidDisplayStringXY(PUCHAR String,
                   ULONG Left,
                   ULONG Top,
                   BOOLEAN Transparent)
{
    ULONG BackColor;

    /* If the caller wanted transparent, then send the special value (16), else */
    /* use our default and call the helper routine. */
    BackColor = (Transparent) ? 16 : 14;
    DisplayStringXY(String, Left, Top, 12, BackColor);
}

/*
 * @implemented
 */
VOID
NTAPI
VidSetScrollRegion(ULONG x1,
                   ULONG y1,
                   ULONG x2,
                   ULONG y2)
{
    /* Assert alignment */
    ASSERT((x1 & 0x7) == 0);
    ASSERT((x2 & 0x7) == 7);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?