📄 13506blt.c
字号:
}
//---------------------------------------------------------------------------
// ReadBlt()
//---------------------------------------------------------------------------
//
// Purpose: Performs Read Blit.
//
// Source :
// lpBlt->SrcLeft
// lpBlt->SrcTop
// lpBlt->SrcWidth
// lpBlt->SrcHeight
//
// Destination:
// memaddress: pointer to memory to store the ReadBlt bitmap.
//
//---------------------------------------------------------------------------
static void ReadBlt(LPBLT_INFO lpBlt,DWORD memaddress)
{
int j,BytesPerPixel;
DWORD srcAddr;
int nTotalWords,nWords,phase,nFIFO,byte100;
volatile WORD *dst16;
WORD *w16;
BytesPerPixel = Control.BytesPerPixel;
srcAddr = lpBlt->SrcLeft*BytesPerPixel + lpBlt->SrcTop * Control.Stride;
phase = memaddress & 1;
// Wait for any pending blits to finish...
WaitForBltEnd();
// ask for read blt
seWriteRegByte(0x103, 0x01);
seWriteRegByte(0x104, srcAddr);
seWriteRegByte(0x105, srcAddr>>8);
seWriteRegByte(0x106, srcAddr>>16);
seWriteRegByte(0x108, phase);
seWriteRegWord(0x10c, Control.Stride/2);
// program the BLT rect dimensions
seWriteRegWord(0x110, lpBlt->SrcWidth-1);
seWriteRegWord(0x112, lpBlt->SrcHeight-1);
// Engage the blt engine.
seWriteRegByte(0x100,0x80);
// wait for the blit to start
while ((seReadRegByte(0x100) & 0x80) == 0)
;
// calculate the address of the BLT aperture
dst16 = (WORD*)gLinBltAddr;
// calculate number of 16bit words per one line
if (BytesPerPixel == 2)
nWords = lpBlt->SrcWidth;
else
nWords = (lpBlt->SrcWidth + 1 + phase)/2;
w16 = (WORD*)(memaddress & 0xFFFFFFFE); // Word aligned
nTotalWords = nWords*lpBlt->SrcHeight;
while (nTotalWords > 0)
{
// wait for the FIFO not empty
byte100 = seReadRegByte(0x100);
if (byte100 & 0x10) //FIFO full, 16 WORDs available
nFIFO = 16;
else if (byte100 & 0x20) //FIFO half full, 8 WORDS available
nFIFO = 8;
else if (byte100 & 0x40) //FIFO not empty, (at least one word available)
nFIFO = 1;
else
continue;
for (j = 0; j < nFIFO && nTotalWords > 0; j++,nTotalWords--)
*w16++ = *dst16;
}
}
//---------------------------------------------------------------------------
// WriteBlt()
//---------------------------------------------------------------------------
//
// Purpose: Performs Rectangular Write Blit.
//
// Destination:
// lpBlt->SrcLeft
// lpBlt->SrcTop
// lpBlt->SrcWidth
// lpBlt->SrcHeight
//
// Source :
// memaddress: pointer to memory bitmap
//
//---------------------------------------------------------------------------
static void WriteBlt(LPBLT_INFO lpBlt, DWORD memaddress)
{
int j,BytesPerPixel;
DWORD dstAddr;
int byte100,nTotalWords,nFIFO,nWords,phase,stride;
volatile WORD *dst;
WORD *w16;
BytesPerPixel = Control.BytesPerPixel;
stride = Control.Stride;
dstAddr = lpBlt->DstLeft*BytesPerPixel + lpBlt->DstTop * stride;
phase = memaddress & 1;
// Wait for any pending blits to finish ...
WaitForBltEnd();
if (lpBlt->Attribute & Transparent)
{
seWriteRegWord(0x114, lpBlt->ColorBg);
seWriteRegByte(0x103, 0x4);
}
else
{
seWriteRegByte(0x103, 0x0);
seWriteRegByte(0x102, lpBlt->ROP);
}
seWriteRegByte(0x104, phase);
seWriteRegWord(0x10c, Control.Stride/2);
seWriteRegByte(0x108, dstAddr);
seWriteRegByte(0x109, dstAddr>>8);
seWriteRegByte(0x10a, dstAddr>>16);
seWriteRegWord(0x110, lpBlt->DstWidth-1);
seWriteRegWord(0x112, lpBlt->DstHeight-1);
// Engage the blt engine.
seWriteRegByte(0x100,0x80);
// wait for the blit to start
while (seReadRegByte(0x100) & 0x80 == 0)
;
dst = (WORD*)gLinBltAddr;
// calculate the number of 16 bit words per one blt line
nWords = phase + ((lpBlt->DstWidth-phase)*BytesPerPixel + 1)/2;
nTotalWords = nWords*lpBlt->DstHeight;
w16 = (WORD*)(memaddress & 0xFFFFFFFE); // Word aligned
while (nTotalWords > 0)
{
// read the FIFO status
byte100 = seReadRegByte(0x100);
if ((byte100 & 0x30) == 0x20) //FIFO at least half full, not full
nFIFO = 1;
else if ((byte100 & 0x40) == 0) //FIFO empty
nFIFO = 16;
else
continue;
for (j = 0; j < nFIFO && nTotalWords > 0; j++,nTotalWords--)
*dst = (WORD)*w16++;
}
}
//---------------------------------------------------------------------------
// InitModeInfo
//---------------------------------------------------------------------------
//
// Purpose: Fills in the mode dependent values in the control info structure.
//
//---------------------------------------------------------------------------
void InitModeInfo(LPCONTROL_INFO lpInfo)
{
unsigned byte,colordepth;
lpInfo->TotalVmem = seGetAvailableMemorySize();
// Crack the active display
byte = seReadRegByte(0x1fc) & 0x7;
if (byte == 0x00 || byte == 0x01) // No display or LCD only...
{
lpInfo->Width = ((seReadRegByte(0x32)+1)*8);
lpInfo->Height= ( seReadRegByte(0x38) | (seReadRegByte(0x39)<<8)) +1;
colordepth = seReadRegByte(0x40);
}
else // CRT or CRT+LCD, TV etc...
{
lpInfo->Width = ((seReadRegByte(0x50)+1)*8);
lpInfo->Height= ( seReadRegByte(0x56) | (seReadRegByte(0x57)<<8)) +1;
colordepth = seReadRegByte(0x60);
}
switch (colordepth & 0x7)
{
case 3: lpInfo->ColorDepth = 8; break;
case 4: lpInfo->ColorDepth = 15; break;
case 5: lpInfo->ColorDepth = 16; break;
default:
printf("\nERROR: invalid chip configuration");
exit(1);
}
switch (lpInfo->ColorDepth)
{
case 8:
seWriteRegByte(0x101, 0x00); //8BPP blit
lpInfo->BytesPerPixel = 1;
break;
case 15:
case 16:
seWriteRegByte(0x101, 0x01); //15/16BPP blit
lpInfo->BytesPerPixel = 2;
break;
}
lpInfo->Stride = lpInfo->BytesPerPixel * lpInfo->Width;
seWriteRegWord(0x46,lpInfo->Stride/2);
seWriteRegWord(0x66,lpInfo->Stride/2);
}
//---------------------------------------------------------------------------
// WaitForBltEnd()
//---------------------------------------------------------------------------
//
// Purpose:
//
// Returns:
//
//
//---------------------------------------------------------------------------
static void WaitForBltEnd(void)
{
// wait until the Blt Engine is idle and Command Queue is empty
while (seReadRegByte(0x100) & 0x80);
}
//---------------------------------------------------------------------------
// ChkForBreak()
//---------------------------------------------------------------------------
//
// Purpose: Checks for an ESC key press.
//
// Returns: TRUE if a break key sequence has been pressed.
// FALSE for any other keyboard condition.
//
//---------------------------------------------------------------------------
static BOOL EscPressed(void)
{
if (kbhit())
{
if (getch() == ESC)
return TRUE;
}
return FALSE;
}
//---------------------------------------------------------------------------
//
// RandomBltValues: generate coodinates of a rectangle that does not
// wrap or clip on screen edges. While at it generate ome random colors.
// Also randomizes ROP. Different fileds of the BLT_INFO are used by different
// blt routines.
//
//---------------------------------------------------------------------------
static WORD rand16(void)
{
// Bit 15 of MS rand() is always 0. We want full 16 bit range.
return ((rand() << 1) | (rand() & 1));
}
static void RandomBltValues(LPBLT_INFO lpBlt)
{
WORD nMaxX = Control.Width;
WORD nMaxY = Control.Height;
lpBlt->ColorFg = rand16();
lpBlt->ColorBg = rand16();
lpBlt->ROP = rand() & 0xF;
lpBlt->PatternX = rand() & 0x7;
lpBlt->PatternY = rand() & 0x7;
// Make sure the foreground and background colors are different.
if ((lpBlt->ColorBg & 0xFF) == (lpBlt->ColorFg & 0xFF))
lpBlt->ColorBg ^= 0xFF;
lpBlt->Attribute = rand() & Transparent;
//
// Dst location and size.
//
do
{
lpBlt->DstTop = (WORD)(rand() % nMaxY-10);
} while (lpBlt->DstTop >= nMaxY - 1);
do
{
lpBlt->DstLeft = (WORD)(rand() & 0x07FF);
} while (lpBlt->DstLeft +8 >= nMaxX - 1);
do
{
lpBlt->DstWidth = (WORD)(rand() % nMaxX);
if (!lpBlt->DstWidth)
lpBlt->DstWidth++; //width cannot be 0
} while (lpBlt->DstLeft + lpBlt->DstWidth >= nMaxX);
do
{
lpBlt->DstHeight = (WORD)(rand() & 0x1FF);
if (!lpBlt->DstHeight)
lpBlt->DstHeight++; //height cannot be 0
} while (lpBlt->DstTop + lpBlt->DstHeight >= nMaxY-2);
}
//---------------------------------------------------------------------------
//
// Given a character string, generate a monochrome bitmap based on bitmaps
// of inividual characters.
//
//---------------------------------------------------------------------------
BOOL CreateMonoBitmap(char *str,WORD **wpt,int *strideout)
{
char *bpt,*bpt1;
int stride,line,i;
int len = strlen(str);
stride = (len+1) & ~1; //round up to be even
bpt = malloc (stride * 16); //16 bytes per character
if (bpt == NULL)
return FALSE;
*wpt = (WORD*)bpt;
*strideout = stride;
for (line = 0; line < 16; line++)
{
bpt1 = bpt;
for (i = 0; i < len; i++)
{
*bpt1++ = GetCharacterByte(str[i],line);
}
bpt += stride;
}
return TRUE;
}
//---------------------------------------------------------------------------
//
//
//---------------------------------------------------------------------------
static int GetCharacterByte(int c,int line)
{
char *chpt = &CharSet16[16*c+line];
return *chpt;
}
//---------------------------------------------------------------------------
//
//
//---------------------------------------------------------------------------
static void ClearVideoMemory(void)
{
memset((char*)gLinBufAddr,0,Control.TotalVmem);
}
//---------------------------------------------------------------------------
//
// Verify if Source and Destination rectangles overlap.
//
//---------------------------------------------------------------------------
static BOOL RectOverlap(LPBLT_INFO lpBlt)
{
int Sx0,Sx1,Dx0,Dx1,Sy0,Sy1,Dy0,Dy1;
Sx0 = lpBlt->SrcLeft;
Sx1 = Sx0 + lpBlt->SrcWidth;
Dx0 = lpBlt->DstLeft;
Dx1 = Dx0 + lpBlt->DstWidth;
Sy0 = lpBlt->SrcTop;
Sy1 = Sy0 + lpBlt->SrcHeight;
Dy0 = lpBlt->DstTop;
Dy1 = Dy0 + lpBlt->DstHeight;
if (Dx0 > Sx1 || Dy0 > Sy1 || Dx1 < Sx0 || Dy1 < Sy0)
return FALSE;
return TRUE;
}
//---------------------------------------------------------------------------
//
//
//---------------------------------------------------------------------------
void DrawRect(int x,int y,int width,int height,DWORD color)
{
BLT_INFO Blt;
Blt.DstWidth = width;
Blt.DstHeight = height;
Blt.DstTop = y;
Blt.DstLeft = x;
Blt.Attribute = 0;
Blt.ColorFg = color;
SolidFillBlt(&Blt);
}
//---------------------------------------------------------------------------
//
//
//---------------------------------------------------------------------------
DWORD CreateRandomPattern(LPBLT_INFO lpBlt)
{
int i;
DWORD PatternAddress;
WORD pattern[8*8];
DWORD data = rand16();
// generate the 8x8 pattern
for (i = 0; i < (8*8*Control.BytesPerPixel)/2 ;i++)
{
pattern[i] = (WORD)data;
data = _rotl(data,1);
}
// for transparent fills, paste in transparent pixels
if (lpBlt->Attribute & Transparent)
{
data = rand16();
if (Control.BytesPerPixel == 2)
{
WORD *ptrw = (WORD*)pattern;
// paste in randomly transparent pixels
for (i = 0; i < 36; i++, data >>= 1, ptrw++)
{
if (i == 32)
data = lpBlt->ColorFg;
if (data & 1)
*ptrw = (WORD)lpBlt->ColorBg;
}
}
else
{
BYTE *ptrb = (BYTE*)pattern;
// paste in randomly transparent pixels
for (i = 0; i < 36; i++, data >>= 1, ptrb++)
{
if (i == 32)
data = lpBlt->ColorFg;
if (data & 1)
*ptrb = (BYTE)lpBlt->ColorBg;
}
}
}
// Copy the pattern in the video memory. Here we place it in the
// first 128 byte aligned address in the offscreen memory.
PatternAddress = (gOffscreenOffset+127) & 0xffffff80L;
memcpy((DWORD*)(gLinBufAddr+PatternAddress),pattern,(8*8*Control.BytesPerPixel));
return PatternAddress;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -