newppu: refine mmc3 hblank timing even more, fixes crystalis and kirby

This commit is contained in:
zeromus 2008-08-18 08:46:29 +00:00
parent 2930675eac
commit 29350a7bdd
1 changed files with 22 additions and 18 deletions

View File

@ -340,6 +340,7 @@ int FCEUPPU_GetAttr(int ntnum, int xt, int yt) {
//new ppu----- //new ppu-----
void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) { void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) {
uint32 tmp = A; uint32 tmp = A;
if(tmp>=0x3F00) if(tmp>=0x3F00)
{ {
// hmmm.... // hmmm....
@ -361,6 +362,7 @@ void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) {
uint8 FFCEUX_PPURead_Default(uint32 A) { uint8 FFCEUX_PPURead_Default(uint32 A) {
uint32 tmp = A; uint32 tmp = A;
if(tmp<0x2000) if(tmp<0x2000)
{ {
return VPage[tmp>>10][tmp]; return VPage[tmp>>10][tmp];
@ -1977,23 +1979,17 @@ int FCEUX_PPU_Loop(int skip) {
} }
oamcounts[scanslot] = oamcount; oamcounts[scanslot] = oamcount;
//FV is clocked by the PPU's horizontal blanking impulse, and therefore will increment every scanline.
//well, according to (which?) tests, maybe at the end of hblank.
//but, according to what it took to get crystalis working, it is at the beginning of hblank.
if(PPUON && sl != 0)
ppur.increment_vs();
//todo - think about clearing oams to a predefined value to force deterministic behavior //todo - think about clearing oams to a predefined value to force deterministic behavior
//fetch sprite patterns //fetch sprite patterns
for(int s=0;s<8;s++) { for(int s=0;s<8;s++) {
if(s==1 && sl != 0) {
//begin hblank!
//the screen is always behind the ppu operation so we need to wait a little longer before triggering it
//NOTE: SMB3 is very sensitive about this timing, for the statusbar
if(PPUON) {
if(GameHBIRQHook)
GameHBIRQHook();
} else {
int zzz=9;
}
}
uint8* oam = oams[scanslot][s]; uint8* oam = oams[scanslot][s];
uint32 line = yp - oam[0]; uint32 line = yp - oam[0];
if(oam[2]&0x80) //vflip if(oam[2]&0x80) //vflip
@ -2019,6 +2015,18 @@ int FCEUX_PPU_Loop(int skip) {
//garbage nametable fetches //garbage nametable fetches
runppu(kFetchTime); runppu(kFetchTime);
if(((PPU[0]&0x38)!=0x18) && s == 2 && SpriteON ) {
//(The MMC3 scanline counter is based entirely on PPU A12, triggered on rising edges (after the line remains low for a sufficiently long period of time))
//http://nesdevwiki.org/wiki/index.php/Nintendo_MMC3
//test cases for timing: SMB3, Crystalis
//crystalis requires deferring this til somewhere in sprite [1,3]
//kirby requires deferring this til somewhere in sprite [2,5..
if(PPUON && GameHBIRQHook) {
GameHBIRQHook();
}
}
runppu(kFetchTime); runppu(kFetchTime);
//pattern table fetches //pattern table fetches
@ -2029,6 +2037,7 @@ int FCEUX_PPU_Loop(int skip) {
oam[5] = FFCEUX_PPURead(RefreshAddr); oam[5] = FFCEUX_PPURead(RefreshAddr);
runppu(kFetchTime); runppu(kFetchTime);
//hflip //hflip
if(!(oam[2]&0x40)) { if(!(oam[2]&0x40)) {
oam[4] = bitrevlut[oam[4]]; oam[4] = bitrevlut[oam[4]];
@ -2036,12 +2045,7 @@ int FCEUX_PPU_Loop(int skip) {
} }
} }
// FV is clocked by the PPU's horizontal blanking impulse, and therefore will increment every scanline.
//well, according to my tests, maybe at the end of hblank.
//but where is the end of hblank?
//well, i imagine it needs to be before the BG fetches for the next line.
if(PPUON && sl != 0)
ppur.increment_vs();
//so.. this is the end of hblank. latch horizontal scroll values //so.. this is the end of hblank. latch horizontal scroll values
if(PPUON && sl != 0) if(PPUON && sl != 0)