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

📄 ppu.cpp

📁 著名的任天堂FC游戏机模拟器VirtuaNes 085版的源码!
💻 CPP
📖 第 1 页 / 共 2 页
字号:
						ntbl_x = 0;
						ntbladr ^= 0x41F;
						attradr = 0x03C0+((ntbladr&0x0380)>>4);
						pNTBL = PPU_MEM_BANK[ntbladr>>10];
					} else {
						ntbladr++;
					}
				}
			} else {
				// With Extension Latch(For MMC5)
				LPBYTE	pScn = lpScanline+(8-loopy_shift);
				LPBYTE	pBGw = BGwrite;

				INT	ntbladr = 0x2000+(loopy_v&0x0FFF);
				INT	ntbl_x  = ntbladr & 0x1F;

				INT	cache_tile = 0xFFFF0000;
				BYTE	cache_attr = 0xFF;

				BYTE	chr_h, chr_l, attr, exattr;

				for( INT i = 0; i < 33; i++ ) {
					nes->mapper->PPU_ExtLatchX( i );
					nes->mapper->PPU_ExtLatch( ntbladr, chr_l, chr_h, exattr );
					attr = exattr&0x0C;

					if( cache_tile != (((INT)chr_h<<8)+(INT)chr_l) || cache_attr != attr ) {
						cache_tile = (((INT)chr_h<<8)+(INT)chr_l);
						cache_attr = attr;
						*pBGw = chr_h|chr_l;

						LPBYTE	pBGPAL = &BGPAL[attr];
						{
						register INT	c1 = ((chr_l>>1)&0x55)|(chr_h&0xAA);
						register INT	c2 = (chr_l&0x55)|((chr_h<<1)&0xAA);
						pScn[0] = pBGPAL[(c1>>6)];
						pScn[4] = pBGPAL[(c1>>2)&3];
						pScn[1] = pBGPAL[(c2>>6)];
						pScn[5] = pBGPAL[(c2>>2)&3];
						pScn[2] = pBGPAL[(c1>>4)&3];
						pScn[6] = pBGPAL[c1&3];
						pScn[3] = pBGPAL[(c2>>4)&3];
						pScn[7] = pBGPAL[c2&3];
						}
					} else {
						*(DWORD*)(pScn+0) = *(DWORD*)(pScn-8);
						*(DWORD*)(pScn+4) = *(DWORD*)(pScn-4);
						*(pBGw+0) = *(pBGw-1);
					}
					pScn+=8;
					pBGw++;

					if( ++ntbl_x == 32 ) {
						ntbl_x = 0;
						ntbladr ^= 0x41F;
					} else {
						ntbladr++;
					}
				}
			}
		} else {
			if( !bExtLatch ) {
				// Without Extension Latch
				if( !bExtNameTable ) {
					LPBYTE	pScn = lpScanline+(8-loopy_shift);
					LPBYTE	pBGw = BGwrite;

					INT	ntbladr = 0x2000+(loopy_v&0x0FFF);
					INT	attradr = 0x03C0+((loopy_v&0x0380)>>4);
					INT	ntbl_x  = ntbladr&0x001F;
					INT	attrsft = (ntbladr&0x0040)>>4;
					LPBYTE	pNTBL = PPU_MEM_BANK[ntbladr>>10];

					INT	tileadr;
					INT	cache_tile = 0xFFFF0000;
					BYTE	cache_attr = 0xFF;
					BYTE	cache_mono = 0x00;

					BYTE	chr_h, chr_l, attr;

					for( INT i = 0; i < 33; i++ ) {
						tileadr = ((PPUREG[0]&PPU_BGTBL_BIT)<<8)+pNTBL[ntbladr&0x03FF]*0x10+loopy_y;

						if( i != 0 ) {
							nes->EmulationCPU( FETCH_CYCLES*4 );
						}

						attr = ((pNTBL[attradr+(ntbl_x>>2)]>>((ntbl_x&2)+attrsft))&3)<<2;

						if( cache_tile != tileadr || cache_attr != attr ) {
							cache_tile = tileadr;
							cache_attr = attr;

							chr_l = PPU_MEM_BANK[tileadr>>10][ tileadr&0x03FF   ];
							chr_h = PPU_MEM_BANK[tileadr>>10][(tileadr&0x03FF)+8];
							*pBGw = chr_l|chr_h;

							LPBYTE	pBGPAL = &BGPAL[attr];
							{
							register INT	c1 = ((chr_l>>1)&0x55)|(chr_h&0xAA);
							register INT	c2 = (chr_l&0x55)|((chr_h<<1)&0xAA);
							pScn[0] = pBGPAL[(c1>>6)];
							pScn[4] = pBGPAL[(c1>>2)&3];
							pScn[1] = pBGPAL[(c2>>6)];
							pScn[5] = pBGPAL[(c2>>2)&3];
							pScn[2] = pBGPAL[(c1>>4)&3];
							pScn[6] = pBGPAL[c1&3];
							pScn[3] = pBGPAL[(c2>>4)&3];
							pScn[7] = pBGPAL[c2&3];
							}
						} else {
							*(DWORD*)(pScn+0) = *(DWORD*)(pScn-8);
							*(DWORD*)(pScn+4) = *(DWORD*)(pScn-4);
							*(pBGw+0) = *(pBGw-1);
						}
						pScn+=8;
						pBGw++;

						// Character latch(For MMC2/MMC4)
						if( bChrLatch ) {
							nes->mapper->PPU_ChrLatch( tileadr );
						}

						if( ++ntbl_x == 32 ) {
							ntbl_x = 0;
							ntbladr ^= 0x41F;
							attradr = 0x03C0+((ntbladr&0x0380)>>4);
							pNTBL = PPU_MEM_BANK[ntbladr>>10];
						} else {
							ntbladr++;
						}
					}
				} else {
					LPBYTE	pScn = lpScanline+(8-loopy_shift);
					LPBYTE	pBGw = BGwrite;

					INT	ntbladr;
					INT	tileadr;
					INT	cache_tile = 0xFFFF0000;
					BYTE	cache_attr = 0xFF;
					BYTE	cache_mono = 0x00;

					BYTE	chr_h, chr_l, attr;

					WORD	loopy_v_tmp = loopy_v;

					for( INT i = 0; i < 33; i++ ) {
						if( i != 0 ) {
							nes->EmulationCPU( FETCH_CYCLES*4 );
						}

						ntbladr = 0x2000+(loopy_v&0x0FFF);
						tileadr = ((PPUREG[0]&PPU_BGTBL_BIT)<<8)+PPU_MEM_BANK[ntbladr>>10][ntbladr&0x03FF]*0x10+((loopy_v&0x7000)>>12);
						attr = ((PPU_MEM_BANK[ntbladr>>10][0x03C0+((ntbladr&0x0380)>>4)+((ntbladr&0x001C)>>2)]>>(((ntbladr&0x40)>>4)+(ntbladr&0x02)))&3)<<2;

						if( cache_tile != tileadr || cache_attr != attr ) {
							cache_tile = tileadr;
							cache_attr = attr;

							chr_l = PPU_MEM_BANK[tileadr>>10][ tileadr&0x03FF   ];
							chr_h = PPU_MEM_BANK[tileadr>>10][(tileadr&0x03FF)+8];
							*pBGw = chr_l|chr_h;

							LPBYTE	pBGPAL = &BGPAL[attr];
							{
							register INT	c1 = ((chr_l>>1)&0x55)|(chr_h&0xAA);
							register INT	c2 = (chr_l&0x55)|((chr_h<<1)&0xAA);
							pScn[0] = pBGPAL[(c1>>6)];
							pScn[4] = pBGPAL[(c1>>2)&3];
							pScn[1] = pBGPAL[(c2>>6)];
							pScn[5] = pBGPAL[(c2>>2)&3];
							pScn[2] = pBGPAL[(c1>>4)&3];
							pScn[6] = pBGPAL[c1&3];
							pScn[3] = pBGPAL[(c2>>4)&3];
							pScn[7] = pBGPAL[c2&3];
							}
						} else {
							*(DWORD*)(pScn+0) = *(DWORD*)(pScn-8);
							*(DWORD*)(pScn+4) = *(DWORD*)(pScn-4);
							*(pBGw+0) = *(pBGw-1);
						}
						pScn+=8;
						pBGw++;

						// Character latch(For MMC2/MMC4)
						if( bChrLatch ) {
							nes->mapper->PPU_ChrLatch( tileadr );
						}

						if( (loopy_v & 0x1F) == 0x1F ) {
							loopy_v ^= 0x041F;
						} else {
							loopy_v++;
						}
					}
					loopy_v = loopy_v_tmp;
				}
			} else {
				// With Extension Latch(For MMC5)
				LPBYTE	pScn = lpScanline+(8-loopy_shift);
				LPBYTE	pBGw = BGwrite;

				INT	ntbladr = 0x2000+(loopy_v&0x0FFF);
				INT	ntbl_x  = ntbladr & 0x1F;

				INT	cache_tile = 0xFFFF0000;
				BYTE	cache_attr = 0xFF;

				BYTE	chr_h, chr_l, attr, exattr;

				for( INT i = 0; i < 33; i++ ) {
					if( i != 0 ) {
						nes->EmulationCPU( FETCH_CYCLES*4 );
					}
					nes->mapper->PPU_ExtLatchX( i );
					nes->mapper->PPU_ExtLatch( ntbladr, chr_l, chr_h, exattr );
					attr = exattr&0x0C;

					if( cache_tile != (((INT)chr_h<<8)+(INT)chr_l) || cache_attr != attr ) {
						cache_tile = (((INT)chr_h<<8)+(INT)chr_l);
						cache_attr = attr;
						*pBGw = chr_l|chr_h;

						LPBYTE	pBGPAL   = &BGPAL[attr];
						{
						register INT	c1 = ((chr_l>>1)&0x55)|(chr_h&0xAA);
						register INT	c2 = (chr_l&0x55)|((chr_h<<1)&0xAA);
						pScn[0] = pBGPAL[(c1>>6)];
						pScn[4] = pBGPAL[(c1>>2)&3];
						pScn[1] = pBGPAL[(c2>>6)];
						pScn[5] = pBGPAL[(c2>>2)&3];
						pScn[2] = pBGPAL[(c1>>4)&3];
						pScn[6] = pBGPAL[c1&3];
						pScn[3] = pBGPAL[(c2>>4)&3];
						pScn[7] = pBGPAL[c2&3];
						}
					} else {
						*(DWORD*)(pScn+0) = *(DWORD*)(pScn-8);
						*(DWORD*)(pScn+4) = *(DWORD*)(pScn-4);
						*(pBGw+0) = *(pBGw-1);
					}
					pScn+=8;
					pBGw++;

					if( ++ntbl_x == 32 ) {
						ntbl_x = 0;
						ntbladr ^= 0x41F;
					} else {
						ntbladr++;
					}
				}
			}
		}
		if( !(PPUREG[1]&PPU_BGCLIP_BIT) && bLeftClip ) {
			LPBYTE	pScn = lpScanline+8;
			for( INT i = 0; i < 8; i++ ) {
				pScn[i] = BGPAL[0];
			}
		}
	}

	// Render sprites
	PPUREG[2] &= ~PPU_SPMAX_FLAG;

	// 昞帵婜娫奜偱偁傟偽僉儍儞僙儖
	if( scanline > 239 )
		return;

	if( !(PPUREG[1]&PPU_SPDISP_BIT) ) {
		return;
	}

	BYTE	SPwrite[33+1];
	INT	spmax;
	INT	spraddr, sp_y, sp_h;
	BYTE	chr_h, chr_l;
	LPSPRITE sp;

	LPBYTE	pBGw = BGwrite;
	LPBYTE	pSPw = SPwrite;
	LPBYTE	pBit2Rev = Bit2Rev;

	ZEROMEMORY( SPwrite, sizeof(SPwrite) );

	spmax = 0;
	sp = (LPSPRITE)SPRAM;
	sp_h = (PPUREG[0]&PPU_SP16_BIT)?15:7;

	// Left clip
	if( !(PPUREG[1]&PPU_SPCLIP_BIT) && bLeftClip ) {
		SPwrite[0] = 0xFF;
	}

	for( INT i = 0; i < 64; i++, sp++ ) {
		sp_y = scanline - (sp->y+1);
		// 僗僉儍儞儔僀儞撪偵SPRITE偑懚嵼偡傞偐傪僠僃僢僋
		if( sp_y != (sp_y & sp_h) )
			continue;

		if( !(PPUREG[0]&PPU_SP16_BIT) ) {
		// 8x8 Sprite
			spraddr = (((INT)PPUREG[0]&PPU_SPTBL_BIT)<<9)+((INT)sp->tile<<4);
			if( !(sp->attr&SP_VMIRROR_BIT) )
				spraddr += sp_y;
			else
				spraddr += 7-sp_y;
		} else {
		// 8x16 Sprite
			spraddr = (((INT)sp->tile&1)<<12)+(((INT)sp->tile&0xFE)<<4);
			if( !(sp->attr&SP_VMIRROR_BIT) )
				spraddr += ((sp_y&8)<<1)+(sp_y&7);
			else
				spraddr += ((~sp_y&8)<<1)+(7-(sp_y&7));
		}
		// Character pattern
		chr_l = PPU_MEM_BANK[spraddr>>10][ spraddr&0x3FF   ];
		chr_h = PPU_MEM_BANK[spraddr>>10][(spraddr&0x3FF)+8];

		// Character latch(For MMC2/MMC4)
		if( bChrLatch ) {
			nes->mapper->PPU_ChrLatch( spraddr );
		}

		// pattern mask
		if( sp->attr&SP_HMIRROR_BIT ) {
			chr_l = pBit2Rev[chr_l];
			chr_h = pBit2Rev[chr_h];
		}
		BYTE	SPpat = chr_l|chr_h;

		// Sprite hitcheck
		if( i == 0 && !(PPUREG[2]&PPU_SPHIT_FLAG) ) {
			INT	BGpos = ((sp->x&0xF8)+((loopy_shift+(sp->x&7))&8))>>3;
			INT	BGsft = 8-((loopy_shift+sp->x)&7);
			BYTE	BGmsk = (((WORD)pBGw[BGpos+0]<<8)|(WORD)pBGw[BGpos+1])>>BGsft;

			if( SPpat & BGmsk ) {
				PPUREG[2] |= PPU_SPHIT_FLAG;
			}
		}

		// Sprite mask
		INT	SPpos = sp->x/8;
		INT	SPsft = 8-(sp->x&7);
		BYTE	SPmsk = (((WORD)pSPw[SPpos+0]<<8)|(WORD)pSPw[SPpos+1])>>SPsft;
		WORD	SPwrt = (WORD)SPpat<<SPsft;
		pSPw[SPpos+0] |= SPwrt >> 8;
		pSPw[SPpos+1] |= SPwrt & 0xFF;
		SPpat &= ~SPmsk;

		if( sp->attr&SP_PRIORITY_BIT ) {
		// BG > SP priority
			INT	BGpos = ((sp->x&0xF8)+((loopy_shift+(sp->x&7))&8))>>3;
			INT	BGsft = 8-((loopy_shift+sp->x)&7);
			BYTE	BGmsk = (((WORD)pBGw[BGpos+0]<<8)|(WORD)pBGw[BGpos+1])>>BGsft;

			SPpat &= ~BGmsk;
		}

		// Attribute
		LPBYTE	pSPPAL = &SPPAL[(sp->attr&SP_COLOR_BIT)<<2];
		// Ptr
		LPBYTE	pScn   = lpScanline+sp->x+8;

		if( !bExtMono ) {
			register INT	c1 = ((chr_l>>1)&0x55)|(chr_h&0xAA);
			register INT	c2 = (chr_l&0x55)|((chr_h<<1)&0xAA);
			if( SPpat&0x80 ) pScn[0] = pSPPAL[(c1>>6)];
			if( SPpat&0x08 ) pScn[4] = pSPPAL[(c1>>2)&3];
			if( SPpat&0x40 ) pScn[1] = pSPPAL[(c2>>6)];
			if( SPpat&0x04 ) pScn[5] = pSPPAL[(c2>>2)&3];
			if( SPpat&0x20 ) pScn[2] = pSPPAL[(c1>>4)&3];
			if( SPpat&0x02 ) pScn[6] = pSPPAL[c1&3];
			if( SPpat&0x10 ) pScn[3] = pSPPAL[(c2>>4)&3];
			if( SPpat&0x01 ) pScn[7] = pSPPAL[c2&3];
		} else {
		// Monocrome effect (for Final Fantasy)
			BYTE	mono = BGmono[((sp->x&0xF8)+((loopy_shift+(sp->x&7))&8))>>3];

			register INT	c1 = ((chr_l>>1)&0x55)|(chr_h&0xAA);
			register INT	c2 = (chr_l&0x55)|((chr_h<<1)&0xAA);
			if( SPpat&0x80 ) pScn[0] = pSPPAL[c1>>6]	|mono;
			if( SPpat&0x08 ) pScn[4] = pSPPAL[(c1>>2)&3]	|mono;
			if( SPpat&0x40 ) pScn[1] = pSPPAL[c2>>6]	|mono;
			if( SPpat&0x04 ) pScn[5] = pSPPAL[(c2>>2)&3]	|mono;
			if( SPpat&0x20 ) pScn[2] = pSPPAL[(c1>>4)&3]	|mono;
			if( SPpat&0x02 ) pScn[6] = pSPPAL[c1&3]		|mono;
			if( SPpat&0x10 ) pScn[3] = pSPPAL[(c2>>4)&3]	|mono;
			if( SPpat&0x01 ) pScn[7] = pSPPAL[c2&3]		|mono;
		}

		if( ++spmax > 8-1 ) {
			if( !bMax )
				break;
		}
	}
	if( spmax > 8-1 ) {
		PPUREG[2] |= PPU_SPMAX_FLAG;
	}
}

// 僗僾儔僀僩侽偑僸僢僩偡傞偐傕抦傟側偄儔僀儞丠
BOOL	PPU::IsSprite0( INT scanline )
{
	// 僗僾儔僀僩orBG旕昞帵偼僉儍儞僙儖(僸僢僩偟側偄)
	if( (PPUREG[1]&(PPU_SPDISP_BIT|PPU_BGDISP_BIT)) != (PPU_SPDISP_BIT|PPU_BGDISP_BIT) )
		return	FALSE;

	// 婛偵僸僢僩偟偰偄偨傜僉儍儞僙儖
	if( PPUREG[2]&PPU_SPHIT_FLAG )
		return	FALSE;

	if( !(PPUREG[0]&PPU_SP16_BIT) ) {
	// 8x8
		if( (scanline < (INT)SPRAM[0]+1) || (scanline > ((INT)SPRAM[0]+7+1)) )
			return	FALSE;
	} else {
	// 8x16
		if( (scanline < (INT)SPRAM[0]+1) || (scanline > ((INT)SPRAM[0]+15+1)) )
			return	FALSE;
	}

	return	TRUE;
}

void	PPU::DummyScanline( INT scanline )
{
INT	i;
INT	spmax;
INT	sp_h;
LPSPRITE sp;

	PPUREG[2] &= ~PPU_SPMAX_FLAG;

	// 僗僾儔僀僩旕昞帵偼僉儍儞僙儖
	if( !(PPUREG[1]&PPU_SPDISP_BIT) )
		return;

	// 昞帵婜娫奜偱偁傟偽僉儍儞僙儖
	if( scanline < 0 || scanline > 239 )
		return;

	sp = (LPSPRITE)SPRAM;
	sp_h = (PPUREG[0]&PPU_SP16_BIT)?15:7;

	spmax = 0;
	// Sprite Max check
	for( i = 0; i < 64; i++, sp++ ) {
		// 僗僉儍儞儔僀儞撪偵SPRITE偑懚嵼偡傞偐傪僠僃僢僋
		if( (scanline < (INT)sp->y+1) || (scanline > ((INT)sp->y+sp_h+1)) ) {
			continue;
		}

		if( ++spmax > 8-1 ) {
			PPUREG[2] |= PPU_SPMAX_FLAG;
			break;
		}
	}
}

⌨️ 快捷键说明

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