windows-nt/Source/XPSP1/NT/shell/osshell/ep/snake/blk.c
2020-09-26 16:20:57 +08:00

560 lines
11 KiB
C

/***************/
/* file: blk.c */
/***************/
#define _WINDOWS
#include <windows.h>
#include <port1632.h>
#include "snake.h"
#include "res.h"
#include "rtns.h"
#include "grafix.h"
#include "blk.h"
#include "pref.h"
#define cbDibHeader (16*4 + sizeof(BITMAPINFOHEADER))
BOOL fWipe = fFalse;
extern PREF Preferences;
extern LPSTR lpDibWall;
extern LPSTR lpDibLvl;
extern HDC hdcBlk;
extern HDC hdcCor;
extern HDC hdcMain;
extern HBITMAP hbmpCor;
extern LONG coDarkGreen;
extern LONG coLiteGreen;
extern STATUS status;
#define icoDark 0
#define icoLite 1
/* CO: RESERVED RED GREEN BLUE */
DWORD rgcoDark[coMax+1] =
{0x007F0000, 0x0000007F, 0x007F7F00, 0x007F007F, 0x00007F7F, 0x00000000};
DWORD rgcoLite[coMax+1] =
{0x00FF0000, 0x000000FF, 0x00FFFF00, 0x00FF00FF, 0x0000FFFF, 0x00FFFFFF};
DWORD rgcoFill[coMax+1] =
{0x0000007F, 0x007F0000, 0x00007F7F, 0x007F007F, 0x007F7F00, 0x00BFBFBF};
#define SurFromBlk(blk) ((SUR) ((blk) & 0x0007))
COR rgmpsurcor[4][8] =
{
/* 000 001 010 011 100 101 110 111 */
{corNW*4, corN*4, corNW*4, corN*4, corW*4, corFNW*4, corW*4, corF*4}, /*NW*/
{corNE*4, corE*4, corNE*4, corE*4, corN*4, corFNE*4, corN*4, corF*4}, /*NE*/
{corSE*4, corS*4, corSE*4, corS*4, corE*4, corFSE*4, corE*4, corF*4}, /*SE*/
{corSW*4, corW*4, corSW*4, corW*4, corS*4, corFSW*4, corS*4, corF*4} /*SW*/
};
BYTE rgblknum[10][7] =
{
{0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E}, /* 0 */
{0x04, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x0E}, /* 1 */
{0x1F, 0x01, 0x01, 0x1F, 0x10, 0x10, 0x1F}, /* 2 */
{0x1F, 0x01, 0x01, 0x0F, 0x01, 0x01, 0x1F}, /* 3 */
{0x11, 0x11, 0x11, 0x1F, 0x01, 0x01, 0x01}, /* 4 */
{0x1F, 0x10, 0x10, 0x1F, 0x01, 0x01, 0x1F}, /* 5 */
{0x1F, 0x10, 0x10, 0x1F, 0x11, 0x11, 0x1F}, /* 6 */
{0x1F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, /* 7 */
{0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x0E}, /* 8 */
{0x1F, 0x11, 0x11, 0x1F, 0x01, 0x01, 0x01} /* 9 */
};
/*** External Data ***/
extern HWND hwndMain;
extern HANDLE hInst;
extern BLK mpposblk[posMax];
extern INT cLevel;
/****** S E T B L K C O ******/
/* Set Block Color */
VOID SetBlkCo(LONG coDark, LONG coLite)
{
#define SetClr(clr,co) \
{ \
((LPBITMAPINFO)lpDibWall)->bmiColors[clr].rgbBlue = (BYTE)(co); \
((LPBITMAPINFO)lpDibWall)->bmiColors[clr].rgbGreen = (BYTE)(co>>8); \
((LPBITMAPINFO)lpDibWall)->bmiColors[clr].rgbRed = (BYTE)(co>>16); \
((LPBITMAPINFO)lpDibWall)->bmiColors[clr].rgbReserved = (BYTE)(0x00); \
}
SetClr(icoDark,coDark);
SetClr(icoLite,coLite);
SetDIBits(hdcCor, hbmpCor, 0, dypCorMax,
lpDibWall + 8 + sizeof(BITMAPINFOHEADER),
(LPBITMAPINFO) lpDibWall, DIB_RGB_COLORS);
}
/****** D R A W B L K ******/
VOID DrawBlk(INT x, INT y, BLK blk)
{
BitBlt(hdcMain, x, y, dxpBlk, dypBlk, hdcBlk, 0, blk<<3, SRCCOPY);
}
/****** D I S P L A Y B L K ******/
VOID DisplayBlk(INT x, INT y, BLK blk)
{
StartDraw();
DrawBlk(x, y, blk);
EndDraw();
}
/****** D R A W C O R ******/
/* cor must be a multiple of 4 */
VOID DrawCor(INT x, INT y, COR cor)
{
#ifdef DEBUG
if (cor & 0x0003)
OutputDebugString("Invalid Cor\r\n");
#endif
BitBlt(hdcMain, x, y, dxpCor, dypCor, hdcCor, 0, cor, SRCCOPY);
}
/****** D R A W W A L L ******/
VOID DrawWall(INT x, INT y, BLK blk)
{
INT x2, y2;
DrawCor(x,y, rgmpsurcor[0][SurFromBlk(blk)]);
DrawCor(x2 = x+4, y, rgmpsurcor[1][SurFromBlk(blk >>= 2)]);
DrawCor(x2,y2 = y + 4, rgmpsurcor[2][SurFromBlk(blk >>= 2)]);
DrawCor(x,y2, rgmpsurcor[3][SurFromBlk(blk >>= 2)]);
}
/****** D I S P L A Y P O S ******/
VOID DisplayPos(POS pos)
{
INT x = dxpGridOff + ((pos % xMax) << 3);
INT y = dypGridOff + ((pos / xMax) << 3);
BLK blk;
StartDraw();
if ((blk = mpposblk[pos]) > blkMax)
DrawWall(x, y, blk);
else
DrawBlk(x, y, blk);
EndDraw();
}
/****** C L E A R B O R D E R ******/
VOID ClearBorder(VOID)
{
POS pos;
for (pos = posMax; pos--;) /* BLT !! */
mpposblk[pos] = blkNull;
for (pos = xMax; pos < (posMax-xMax); pos += xMax)
mpposblk[pos] = mpposblk[pos+xMax-1] = blkWallNS;
for (pos = xMax-1; --pos > 0;)
mpposblk[pos] = mpposblk[(posMax-1)-pos] = blkWallEW;
mpposblk[posNW] = blkWallNW;
mpposblk[posNE] = blkWallNE;
mpposblk[posSW] = blkWallSW;
mpposblk[posSE] = blkWallSE;
}
/****** S E T L E V E L C O L O R ******/
VOID SetLevelColor(VOID)
{
INT ico = (Preferences.fColor) ? cLevel % coMax : coMax;
SetBlkCo(rgcoDark[ico], rgcoLite[ico]);
}
/****** S E T U P B O R D E R ******/
/* Just draw the border pieces */
VOID SetupBorder(VOID)
{
INT x1,x2;
SetLevelColor();
DrawWall(dxpGridOff, dypGridOff, blkWallNW);
DrawWall(dxpGridOff+dxpGrid-dxpBlk, dypGridOff, blkWallNE);
DrawWall(dxpGridOff, dypGridOff+dypGrid-dypBlk, blkWallSW);
DrawWall(dxpGridOff+dxpGrid-dxpBlk, dypGridOff+dypGrid-dypBlk, blkWallSE);
for (x1 = dxpBlk, x2 = dypGrid - 2*dypBlk;
x1 < (dxpGrid/2); x1 +=dxpBlk, x2 -= dypBlk)
{
DrawWall(dxpGridOff + x1, dypGridOff, blkWallEW);
DrawWall(dxpGridOff -dxpBlk + x2, dypGridOff, blkWallEW);
DrawWall(dxpGridOff, dypGridOff + x1, blkWallNS);
DrawWall(dxpGridOff, dypGridOff + x2, blkWallNS);
DrawWall(dxpGridOff + x1, dypGridOff+dypGrid-dypBlk, blkWallEW);
DrawWall(dxpGridOff -dxpBlk + x2, dypGridOff+dypGrid-dypBlk, blkWallEW);
DrawWall(dxpGridOff+dxpGrid-dxpBlk, dypGridOff + x1, blkWallNS);
DrawWall(dxpGridOff+dxpGrid-dxpBlk, dypGridOff + x2, blkWallNS);
}
}
/****** D R A W G R I D ******/
VOID DrawGrid(VOID)
{
INT x,y;
POS pos;
BLK blk;
x = dxpGridOff;
y = dypGridOff;
for (pos = 0; pos < posMax; pos++)
{
blk = mpposblk[pos];
if (blk > blkMax)
DrawWall(x,y, blk);
else
DrawBlk(x,y, blk);
if ( (x += dxpBlk) >= (dxpGridOff+dxpGrid) )
{
x = dxpGridOff;
y += dypBlk;
}
}
}
/****** G E T L E V E L D A T A ******/
/* Get the level data from the bitmap */
VOID GetLevelData(INT lvl)
{
LONG FAR * lpData;
INT x, b;
LONG lData;
CHAR bData;
POS pos;
lpData = (LONG FAR * ) (lpDibLvl + (lvl * (32 * 4)) );
pos = posMax - (xMax + xMax - 1);
while (pos > xMax)
{
lData = *lpData;
for (b = 4; b--;)
{
bData = (BYTE) lData;
lData >>= 8;
for (x = 8; x--;)
{
if (!(bData & 0x80))
mpposblk[pos] = 0x1000;
bData <<= 1;
pos++;
}
}
lpData++;
pos -= (xMax+xMax-1);
}
}
/****** M A K E W A L L S ******/
VOID MakeWalls(VOID)
{
POS pos;
BLK blk;
pos = posSW;
while (pos > posNE)
{
if (mpposblk[--pos] != blkNull)
{
blk = 0x1000;
if (mpposblk[--pos]) blk |= 0x0101;
if (mpposblk[pos -= xMax]) blk |= 0x0002;
if (mpposblk[++pos]) blk |= 0x0004;
if (mpposblk[++pos]) blk |= 0x0008;
if (mpposblk[pos += xMax]) blk |= 0x0010;
if (mpposblk[pos += xMax]) blk |= 0x0020;
if (mpposblk[--pos]) blk |= 0x0040;
if (mpposblk[--pos]) blk |= 0x0080;
mpposblk[pos -= (xMax-1)]= blk;
}
}
/* Fix Border */
for (pos = xMax; pos < (posSW-1); pos += xMax)
{
mpposblk[pos] &= 0x10FE; /* Left */
mpposblk[pos+posNE] &= 0x11EF; /* Right */
}
for (pos = posNE-1; pos > posNW;)
{
blk = 0x1111;
if (mpposblk[pos += xMax+1]) blk |= 0x0020;
if (mpposblk[--pos]) blk |= 0x0040;
if (mpposblk[--pos]) blk |= 0x0080;
mpposblk[pos -= (xMax-1)] = blk; /* Top */
blk = 0x1111;
pos += posSW;
if (mpposblk[pos -= (xMax-1)]) blk |= 0x0002;
if (mpposblk[--pos]) blk |= 0x0004;
if (mpposblk[--pos]) blk |= 0x0008;
mpposblk[pos += (xMax+1)] = blk; /* Bottom */
pos -= posSW;
pos--;
}
if (mpposblk[posNW +xMax+1])
mpposblk[posNW] = blkWallNW | 0x0020;
else
mpposblk[posNW] = blkWallNW;
if (mpposblk[posNE +xMax-1])
mpposblk[posNE] = blkWallNE | 0x0080;
else
mpposblk[posNE] = blkWallNE;
if (mpposblk[posSW-(xMax-1)])
mpposblk[posSW] = blkWallSW | 0x0008;
else
mpposblk[posSW] = blkWallSW;
if (mpposblk[posSE-(xMax+1)])
mpposblk[posSE] = blkWallSE | 0x0002;
else
mpposblk[posSE] = blkWallSE;
}
/****** A D D N U M ******/
VOID AddNum(POS pos, INT num)
{
INT x,y;
INT b;
for (y = 0; y < 7; y++)
{
b = rgblknum[num][y];
for (x = 0; x++ < 5;)
{
if ((b <<= 1) & 0x20)
mpposblk[pos] = 0x1000;
pos++;
}
pos += (xMax - 5);
}
}
/****** A D D L E V E L N U M ******/
VOID AddLevelNum(INT lvl)
{
AddNum(xMax*20+10, lvl/10);
AddNum(xMax*20+18, lvl%10);
}
/****** D R A W D A T A ******/
VOID DrawData(VOID)
{
POS pos;
BLK blk;
INT x,y;
x = dxpGridOff+dxpBlk;
y = dypGridOff+dypBlk;
for (pos = xMax+1; pos < posMax-xMax; pos++)
{
blk = mpposblk[pos];
if (blk != blkNull)
{
DrawWall(x,y, blk);
}
if ( (x += dxpBlk) >= (dxpGridOff+dxpGrid-dxpBlk) )
{
x = dxpGridOff+dxpBlk;
y += dypBlk;
pos += 2;
}
}
}
/****** W I P E C L E A R ******/
VOID WipeClear(VOID)
{
LONG co = rgcoFill[ Preferences.fColor ? (cLevel % coMax) : coMax];
LONG lco = co & 0x00030303;
INT dxp = dxpGridOff+dxpBlk;
INT dyp = dypGridOff+dypBlk;
INT dxp2;
HBRUSH hbrush, hbrush2;
fWipe = fTrue;
SelectObject(hdcMain, GetStockObject(NULL_PEN));
hbrush = SelectObject(hdcMain, CreateSolidBrush(co));
for (dxp2 = dxp;
dxp < (dxpGridOff + dxpGrid - dxpBlk);
dxp = dxp2, dyp += dypBlk)
{
dxp2 += dxpBlk;
hbrush2 = SelectObject(hdcMain, CreateSolidBrush(co));
if (hbrush2)
DeleteObject(hbrush2);
Rectangle(hdcMain, dxpGridOff+dxpBlk, dyp, dxp2+1, dyp + dypBlk+1);
Rectangle(hdcMain, dxp, dypGridOff+dypBlk, dxp2+1, dyp+1);
co -= lco;
}
hbrush2 = SelectObject(hdcMain, CreateSolidBrush(co));
if (hbrush2)
DeleteObject(hbrush2);
Rectangle(hdcMain, dxpGridOff+dxpBlk, dyp, dxp2+1, dyp+dxpBlk+1);
hbrush2 = SelectObject(hdcMain, hbrush);
if (hbrush2)
DeleteObject(hbrush2);
}
/****** S E T U P L E V E L D A T A ******/
VOID SetupLevelData(VOID)
{
StartDraw();
ClearBorder();
SetupBorder();
EndDraw();
GetLevelData(cLevel % lvlMax);
MakeWalls();
}
/****** D I S P L A Y L E V E L N U M ******/
VOID DrawLevelNum(VOID)
{
if (cLevel > 98)
cLevel = 0;
ClearBorder();
SetupBorder();
WipeClear();
GetLevelData(lvlLevel);
AddLevelNum(cLevel+1);
MakeWalls();
SetBlkCo(coDarkGreen, coLiteGreen);
DrawData();
DrawTime();
DrawLives();
}
VOID DisplayLevelNum(VOID)
{
StartDraw();
DrawLevelNum();
EndDraw();
}
/****** D I S P L A Y G A M E O V E R ******/
VOID DrawGameOver(VOID)
{
ClearBorder();
SetupBorder();
WipeClear();
GetLevelData(lvlGameOver);
MakeWalls();
SetBlkCo(coDarkGreen, coLiteGreen);
DrawData();
}
VOID DisplayGameOver(VOID)
{
StartDraw();
DrawGameOver();
EndDraw();
}
VOID ReWipe(VOID)
{
if (FPlay())
{
POS pos;
BLK mpposblk2[posMax]; /* A copy of the playing grid */
for (pos=posMax; --pos >= 0;)
mpposblk2[pos] = mpposblk[pos];
DrawLevelNum();
for (pos=posMax; --pos >= 0;)
mpposblk[pos] = mpposblk2[pos];
}
else
DrawGameOver();
}