⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gfx.cpp

📁 nes游戏模拟器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		// Move to the next line.
		if (byAttributes & 0x80)
			pSurfaceMemory -= lSurfacePitch;
		else
			pSurfaceMemory += lSurfacePitch;

		// Move to the next byte in the sprite.
		pbyTileByte++;
	}

	// Restore the surface memory pointer to the beginning
	// of the scanline.
	pSurfaceMemory = pSaveVideoMemStart;

	//-------------------------------------------------------------------------
	// Draw the second part of the sprite if its a 8x16 sprite.
	// Thats located in in bit 5 of reg $2000.
	//-------------------------------------------------------------------------
	if (CPU.Memory[0x2000] & 0x20)
	{
		BYTE  byColor;             // Index into the NES palette for the sprite.
		BYTE* pbyTileByte;         // Pointer to the pattern table byte.
		BYTE* pSaveVideoMemStart = pSurfaceMemory;

		// Save all the information about the sprite.
		BYTE byYPos = abySPRRAM[(bySpriteNum*4)] + 8;
		BYTE byTileNum = abySPRRAM[(bySpriteNum*4)+1] + 1;
		BYTE byAttributes = abySPRRAM[(bySpriteNum*4)+2];
		BYTE byXPos = abySPRRAM[(bySpriteNum*4)+3];
		BYTE byUpperColor = (byAttributes & 0x3) << 2;

		// Get the pointer to the tile byte in the pattern table for the sprite.
		pbyTileByte = (byTileNum * 16) + PPU.apbyPatternTables[(CPU.Memory[0x2000]&0x08)>>3];
		
		// Move the video memory pointer to where the sprite is supposed to be horizontally.
		if (byAttributes & 0x40)
			pSurfaceMemory += (byXPos * lBytesPerPixel) + (8 * lBytesPerPixel);
		else
			pSurfaceMemory += byXPos * lBytesPerPixel;

		// Move the video memory pointer to where the sprite is supposed to be vertically.
		if (byAttributes & 0x80)
			pSurfaceMemory += ((byYPos + 8) * lSurfacePitch);
		else
			pSurfaceMemory += byYPos * lSurfacePitch;

		// Draw the sprite by drawing each tile line then moving to the next byte.
		for (int i = 0; i < 8; i++)
		{
			BYTE  byTestBit = 0x80;    // Color testing bit for the sprite tile.
			BYTE  byColorShiftVal = 7; // Number of bits to shift the color by.

			while (byTestBit != 0)
			{
				// The color is the to lower bits from the pattern table
				// obtained in the same way as a background tile plus the
				// two uppercolor bits in the lower 2 bits of the attribute
				// byte.
				byColor = ((*pbyTileByte & byTestBit) >> byColorShiftVal) |
					(((*(pbyTileByte+8) & byTestBit) >> byColorShiftVal) << 1);

				// Draw the pixel on the screen if the color is not 0.
				if (byColor != 0)
					PutSpritePixel(byColor | byUpperColor);

				// Move to the next pixel.
				if (byAttributes & 0x40)
					pSurfaceMemory -= lBytesPerPixel;
				else
					pSurfaceMemory += lBytesPerPixel;
				
				byColorShiftVal--;
				byTestBit >>= 1;
			}

			// Reset the horizontal video position for the next line.
			if (byAttributes & 0x40)
				pSurfaceMemory += (8 * lBytesPerPixel);
			else
				pSurfaceMemory -= (8 * lBytesPerPixel);

			// Move to the next line.
			if (byAttributes & 0x80)
				pSurfaceMemory -= lSurfacePitch;
			else
				pSurfaceMemory += lSurfacePitch;

			// Move to the next byte in the sprite.
			pbyTileByte++;
		}

		// Restore the surface memory pointer to the beginning
		// of the scanline.
		pSurfaceMemory = pSaveVideoMemStart;
	}
} // end DrawSprite()


//------------------------------------------------------------------------------
// Name: DrawSpriteLine()
// Desc: Draws a 8 pixel scanline for the sprite.
//------------------------------------------------------------------------------
VOID DrawSpriteLine(BYTE bySpriteNum)
{
	BYTE  byTestBit = 0x80;    // Color testing bit for the sprite tile.
	BYTE  byColorShiftVal = 7; // Number of bits to shift the color by.
	BYTE  byColor;             // Index into the NES palette for the sprite.
	BYTE* pbyScanlineByte;     // Pointer to the pattern table byte.
	BYTE* pSaveVideoMemStart = pSurfaceMemory;

	// Save all the information about the sprite.
	BYTE byYPos = abySPRRAM[(bySpriteNum*4)];
	BYTE byTileNum = abySPRRAM[(bySpriteNum*4)+1];
	BYTE byAttributes = abySPRRAM[(bySpriteNum*4)+2];
	BYTE byXPos = abySPRRAM[(bySpriteNum*4)+3];
	BYTE byUpperColor = (byAttributes & 0x3) << 2;

	// If one of the sprites scanlines is on this screen scaline,
	// then we have to draw that sprite scanline.
	if ((unsigned)(wScanline - byYPos) < 8)
	{
		// Get the pointer to the scanline byte in the pattern table for the sprite.
		pbyScanlineByte = (byTileNum * 16) + PPU.apbyPatternTables[(CPU.Memory[0x2000]&0x08)>>3];
		pbyScanlineByte += (wScanline - byYPos);
		
		// Move the video memory pointer to where the sprite is supposed to be.
		if (byAttributes & 0x40)
			pSurfaceMemory += (byXPos * lBytesPerPixel) + (7 * lBytesPerPixel);
		else
            pSurfaceMemory += byXPos * lBytesPerPixel;

		// Draw the sprite scanline.
		while (byTestBit != 0)
		{
			// The color is the to lower bits from the pattern table
			// obtained in the same way as a background tile plus the
			// two uppercolor bits in the lower 2 bits of the attribute
			// byte.
			byColor = ((*pbyScanlineByte & byTestBit) >> byColorShiftVal) |
				(((*(pbyScanlineByte+8) & byTestBit) >> byColorShiftVal) << 1) |
				byUpperColor;

			// Draw the pixel on the screen if the color is not 0.
			if (byColor != 0)
				PutSpritePixel(byColor);

			// Move to the next pixel.
			if (byAttributes & 0x40)
				pSurfaceMemory -= lBytesPerPixel;
			else
				pSurfaceMemory += lBytesPerPixel;
			
			byColorShiftVal--;
			byTestBit >>= 1;
		}

		// Restore the surface memory pointer to the beginning
		// of the scanline.
		pSurfaceMemory = pSaveVideoMemStart;
	}
} // end DrawSpriteLine()


//------------------------------------------------------------------------------
// Name: GetMaskInfo()
// Desc: Uses the color's bitmasks to calculate values which we 
//       will use to compile the pixel value.
//------------------------------------------------------------------------------
INT GetMaskInfo(DWORD dwBitmask, int* pnShift)
{
	int nPrecision = 0;
	int nShift     = 0;

	// Count the zeros on right hand side.
	while (!(dwBitmask & 0x01))
	{
		dwBitmask >>= 1;
		nShift++;
	}

	// Count the ones on right hand side.
	while (dwBitmask & 0x01)
	{
		dwBitmask >>= 1;
		nPrecision++;
	}

	// Save the shift value.
	*pnShift = nShift;

	// Return the number of ones.
	return nPrecision;
} // end GetMaskInfo()


//------------------------------------------------------------------------------
// Name: CompilePixel()
// Desc: Stores the four bytes corresponding to the compiled pixel 
//       value in a class variable.
//------------------------------------------------------------------------------
VOID CompilePixel(LPDIRECTDRAWSURFACE7 lpSurf, int nColorIndex, int r, int g, int b)
{
	DDPIXELFORMAT DDpf;    // DirectDraw pixel format structure.
	int rsz, gsz, bsz; 	   // Bitsize of field.
	int rsh, gsh, bsh;	   // 0抯 on left (the shift value).
	DWORD dwCompiledPixel; // Our pixel with r,g,b values compiled.

	// Get the pixel format.
	ZeroMemory (&DDpf, sizeof(DDpf));
	DDpf.dwSize = sizeof(DDpf);
	lpSurf->GetPixelFormat(&DDpf);

	// Get the shift and precision values and store them.
	rsz = GetMaskInfo(DDpf.dwRBitMask, &rsh);
	gsz = GetMaskInfo(DDpf.dwGBitMask, &gsh);
	bsz = GetMaskInfo(DDpf.dwBBitMask, &bsh);

	// Keep only the MSB bits of component.
	r >>= (8-rsz);
	g >>= (8-gsz);
	b >>= (8-bsz);

	// Shift them into place.
	r <<= rsh;
	g <<= gsh;
	b <<= bsh;

	// Store the compiled pixel.
	dwCompiledPixel = (DWORD)(r | g | b);
	abyColors[nColorIndex][3] = (BYTE)(dwCompiledPixel);
	abyColors[nColorIndex][2] = (BYTE)(dwCompiledPixel >>= 8);
	abyColors[nColorIndex][1] = (BYTE)(dwCompiledPixel >>= 8);
	abyColors[nColorIndex][0] = (BYTE)(dwCompiledPixel >>= 8);

	return;
} // end CompilePixel()


//------------------------------------------------------------------------------
// Name: PutBackgroundPixel()
// Desc: Puts a background pixel independant of the bit depth 
//       on the locked surface.
//------------------------------------------------------------------------------
VOID __stdcall PutBackgroundPixel(BYTE nColor)
{
	// Copy the pointer to video memory so the main one doesn't get modified.
	BYTE *pVideoMem = pSurfaceMemory;
	// Speed up the array access in the loop by storing this here.
	BYTE byColor = PPU.abyPalettes[nColor];

	// Put the number of bytes for each pixel on the surface.
	for (int i = 3; i >= FourMinusBPP; i--)
	{
		*pVideoMem = abyColors[byColor][i];
		pVideoMem++;
	}
} // end PutBackgroundPixel()


//------------------------------------------------------------------------------
// Name: PutSpritePixel()
// Desc: Puts a background pixel independant of the bit depth 
//       on the locked surface.
//------------------------------------------------------------------------------
VOID __stdcall PutSpritePixel(BYTE nColor)
{
	// Copy the pointer to video memory so the main one doesn't get modified.
	BYTE *pVideoMem = pSurfaceMemory;
	// Speed up the array access in the loop by storing this here.
	BYTE byColor = PPU.abyPalettes[0x10+nColor];

	// Put the number of bytes for each pixel on the surface.
	for (int i = 3; i >= FourMinusBPP; i--)
	{
		*pVideoMem = abyColors[byColor][i];
		pVideoMem++;
	}
} // end PutSpritePixel()


//------------------------------------------------------------------------------
// Name: ClearScreen()
// Desc: Clears the NES screen to the background color.
//------------------------------------------------------------------------------
VOID ClearScreen(COLORREF crColor)
{
	DDBLTFX ddbltfx;

	// Fill the NES screen surface with the background color.
	ddbltfx.dwSize = sizeof(DDBLTFX);
	ddbltfx.dwFillColor = crColor;
	lpddsScreen->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
} // end ClearScreen()


//------------------------------------------------------------------------------
// Name: UpdateBounds()
// Desc: Updates the rect for ......
//------------------------------------------------------------------------------
HRESULT UpdateBounds(HWND hwnd)
{
	POINT ptWindow; // Point used for converting client to window coordinates.

	// Get the client rectangle.
	GetClientRect(hwnd, &rcScreen);

	// Convert the top left coordinates.
	ptWindow.x = rcScreen.left;
	ptWindow.y = rcScreen.top;
	ClientToScreen(hwnd, &ptWindow);
	rcScreen.left = ptWindow.x;
	rcScreen.top = ptWindow.y;

	// Convert the bottom right coordinates.
	ptWindow.x = rcScreen.right;
	ptWindow.y = rcScreen.bottom;
	ClientToScreen(hwnd, &ptWindow);
	rcScreen.right = ptWindow.x;
	rcScreen.bottom = ptWindow.y;

	return S_OK;
} // end UpdateBounds()


//------------------------------------------------------------------------------
// Name: OutputText()
// Desc: Outputs text to the screen surface.
//------------------------------------------------------------------------------
VOID OutputText(LPSTR strText, INT nX, INT nY, COLORREF cfFront, COLORREF cfBack)
{
	HDC hdc;

	if (lpddsScreen->GetDC(&hdc) == DD_OK)
	{
		SetBkColor(hdc, cfBack);
		SetTextColor(hdc, cfFront);
		TextOut(hdc, nX, nY, strText, lstrlen(strText));
		lpddsScreen->ReleaseDC(hdc);
	}
} // end OutputText()

⌨️ 快捷键说明

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