📄 ppu.cpp
字号:
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 + -