X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=fceu.git;a=blobdiff_plain;f=fce.c;h=d3a0f6104d57a58c3b07c5478da7dfb0685d290b;hp=214a41f7ac337eb6905505debaf8b26ab42ed4b9;hb=6587f34612d28a36fede21bd6293c4e0e383b343;hpb=15300263784975ac57355208762caa5ef7906624 diff --git a/fce.c b/fce.c index 214a41f..d3a0f61 100644 --- a/fce.c +++ b/fce.c @@ -48,10 +48,19 @@ #include "crc32.h" #include "ppu.h" +#include "palette.h" +#include "movie.h" + +#include "dprintf.h" + +#ifdef GP2X +#include "drivers/gp2x/asmutils.h" +#endif + #define Pal (PALRAM) -static void FASTAPASS(1) RefreshLine(uint8 *target); +static void (*RefreshLine)(uint8 *P, uint32 vofs) = NULL; static void PRefreshLine(void); static void ResetPPU(void); @@ -59,6 +68,9 @@ static void PowerPPU(void); uint64 timestampbase=0; +static int ppudead=1; +static int kook=0; + int MMC5Hack; uint32 MMC5HackVROMMask; uint8 *MMC5HackExNTARAMPtr; @@ -90,7 +102,7 @@ void (*GameInterface)(int h); void FP_FASTAPASS(1) (*PPU_hook)(uint32 A); void (*GameStateRestore)(int version); -void (*GameHBIRQHook)(void); +void (*GameHBIRQHook)(void), (*GameHBIRQHook2)(void); readfunc ARead[0x10000]; writefunc BWrite[0x10000]; @@ -98,6 +110,68 @@ static readfunc *AReadG; static writefunc *BWriteG; static int RWWrap=0; +#ifdef ASM_6502 +static void asmcpu_update(int32 cycles) +{ + // some code from x6502.c + fhcnt-=cycles; + if(fhcnt<=0) + { + FrameSoundUpdate(); + fhcnt+=fhinc; + } + + if(PCMIRQCount>0) + { + PCMIRQCount-=cycles; + if(PCMIRQCount<=0) + { + vdis=1; + if((PSG[0x10]&0x80) && !(PSG[0x10]&0x40)) + { + extern uint8 SIRQStat; + SIRQStat|=0x80; + X6502_IRQBegin(FCEU_IQDPCM); + } + } + } +} + +void asmcpu_unpack(void) +{ + nes_registers[0] = X.A << 24; + nes_registers[1] = X.X; + nes_registers[2] = X.Y; + pc_base = 0; + nes_registers[3] = X.PC; + X6502_Rebase_a(); + nes_registers[4] = X.S << 24; + nes_registers[4]|= X.IRQlow << 8; + nes_registers[7] = (uint32)X.count << 16; + + // NVUB DIZC + nes_registers[4]|= X.P & 0x5d; + nes_registers[5] = X.P << 24; // N + if (!(X.P&0x02)) nes_registers[5] |= 1; // Z +} + +void asmcpu_pack(void) +{ + X.A = nes_registers[0] >> 24; + X.X = nes_registers[1]; + X.Y = nes_registers[2]; + X.PC= nes_registers[3] - pc_base; + X.S = nes_registers[4] >> 24; + X.IRQlow = nes_registers[4] >> 8; + X.count = (int32) nes_registers[7] >> 16; + + // NVUB DIZC + X.P = nes_registers[4] & 0x5d; + if ( nes_registers[5]&0x80000000) X.P |= 0x80; // N + if (!(nes_registers[5]&0x000000ff)) X.P |= 0x02; // Z +} +#endif + DECLFW(BNull) { @@ -203,21 +277,55 @@ uint32 TempAddr,RefreshAddr; /* scanline is equal to the current visible scanline we're on. */ int scanline; -static uint32 scanlines_per_frame; + +uint8 GameMemBlock[131072] __attribute__ ((aligned (4))); +uint8 NTARAM[0x800] __attribute__ ((aligned (4))); +uint8 PALRAM[0x20] __attribute__ ((aligned (4))); +#if !defined(ASM_6502) || defined(DEBUG_ASM_6502) +uint8 RAM[0x800] __attribute__ ((aligned (4))); +#endif uint8 PPU[4]; uint8 PPUSPL; -uint8 GameMemBlock[131072]; -uint8 NTARAM[0x800],PALRAM[0x20]; -uint8 RAM[0x800]; - uint8 PAL=0; #define MMC5BGVRAMADR(V) &MMC5BGVPage[(V)>>10][(V)] #define VRAMADR(V) &VPage[(V)>>10][(V)] +static int linestartts; +static int tofix=0; + +static void ResetRL(void) +{ + linestartts=timestamp*48+X6502_GetCycleCount(); + tofix=1; +} + +static INLINE void Fixit1(void); + +static void TryFixit1(void) +{ + #define TOFIXNUM (272-0x4) + int lastpixel; + + if (scanline < 240 && tofix) + { + lastpixel = (timestamp*48-linestartts)>>4; + if (PAL) lastpixel += lastpixel>>4; + + //printf("lastpixel: %i\n", lastpixel); + + if(lastpixel>=TOFIXNUM) + { + Fixit1(); + tofix=0; + } + } +} + + static DECLFW(BRAML) { RAM[A]=V; @@ -241,25 +349,38 @@ static DECLFR(ARAMH) static DECLFR(A2002) { + /* merged */ uint8 ret; + + TryFixit1(); ret = PPU_status; + ret|=PPUGenLatch&0x1F; vtoggle=0; PPU_status&=0x7F; - return ret|(PPUGenLatch&0x1F); + PPUGenLatch=ret; + //dprintf("r [2002] %02x",ret); + return ret; } static DECLFR(A200x) { + /* merged */ + TryFixit1(); return PPUGenLatch; } static DECLFR(A2007) { + /* merged */ uint8 ret; uint32 tmp=RefreshAddr&0x3FFF; - PPUGenLatch=ret=VRAMBuffer; + TryFixit1(); + + ret=VRAMBuffer; + if(PPU_hook) PPU_hook(tmp); + PPUGenLatch=VRAMBuffer; if(tmp<0x2000) { VRAMBuffer=VPage[tmp>>10][tmp]; @@ -272,11 +393,14 @@ static DECLFR(A2007) if (INC32) RefreshAddr+=32; else RefreshAddr++; if(PPU_hook) PPU_hook(RefreshAddr&0x3fff); + dprintf("r [2007] %02x",ret); return ret; } static DECLFW(B2000) { + /* NMI2? */ + TryFixit1(); PPUGenLatch=V; PPU[0]=V; TempAddr&=0xF3FF; @@ -285,6 +409,8 @@ static DECLFW(B2000) static DECLFW(B2001) { + /* merged */ + TryFixit1(); PPUGenLatch=V; PPU[1]=V; if(V&0xE0) @@ -294,11 +420,13 @@ static DECLFW(B2001) static DECLFW(B2002) { + /* merged */ PPUGenLatch=V; } static DECLFW(B2003) { + /* merged */ PPUGenLatch=V; PPU[3]=V; PPUSPL=V&0x7; @@ -306,9 +434,9 @@ static DECLFW(B2003) static DECLFW(B2004) { + /* merged */ PPUGenLatch=V; - //SPRAM[PPU[3]++]=V; - if(PPUSPL&8) + if(PPUSPL>=8) { if(PPU[3]>=8) SPRAM[PPU[3]]=V; @@ -317,16 +445,17 @@ static DECLFW(B2004) { //printf("$%02x:$%02x\n",PPUSPL,V); SPRAM[PPUSPL]=V; - PPUSPL++; } PPU[3]++; + PPUSPL++; } static DECLFW(B2005) { + /* merged */ uint32 tmp=TempAddr; - + TryFixit1(); PPUGenLatch=V; if (!vtoggle) { @@ -347,6 +476,9 @@ static DECLFW(B2005) static DECLFW(B2006) { + /* merged */ + TryFixit1(); + PPUGenLatch=V; if(!vtoggle) { @@ -357,8 +489,8 @@ static DECLFW(B2006) { TempAddr&=0xFF00; TempAddr|=V; - RefreshAddr=TempAddr; + RefreshAddr=TempAddr; if(PPU_hook) PPU_hook(RefreshAddr); } @@ -367,16 +499,15 @@ static DECLFW(B2006) static DECLFW(B2007) { + /* merged */ uint32 tmp=RefreshAddr&0x3FFF; - PPUGenLatch=V; if(tmp>=0x3F00) { - // hmmm.... - if(!(tmp&0xf)) - PALRAM[0x00]=PALRAM[0x04]=PALRAM[0x08]=PALRAM[0x0C]= - PALRAM[0x10]=PALRAM[0x14]=PALRAM[0x18]=PALRAM[0x1c]=V&0x3f; - else if(tmp&3) PALRAM[(tmp&0x1f)]=V&0x3f; + // hmmm.... + if(!(tmp&0xf)) + PALRAM[0x00]=PALRAM[0x04]=PALRAM[0x08]=PALRAM[0x0C]=V&0x3f; + else if(tmp&3) PALRAM[(tmp&0x1f)]=V&0x3f; } else if(tmp<0x2000) { @@ -397,6 +528,7 @@ static DECLFW(B4014) { uint32 t=V<<8; int x; + for(x=0;x<256;x++) B2004(0x2004,X.DB=ARead[t+x](t+x)); X6502_AddCycles(512); @@ -404,12 +536,24 @@ static DECLFW(B4014) void BGRender(uint8 *target) { - uint32 tem; - RefreshLine(target); + uint32 tem, vofs; + vofs=((PPU[0]&0x10)<<8) | ((RefreshAddr>>12)&7); + + Pal[0]|=64; + Pal[4]|=64; + Pal[8]|=64; + Pal[0xC]|=64; + RefreshLine(target-XOffset, vofs); + Pal[0]&=63; + Pal[4]&=63; + Pal[8]&=63; + Pal[0xC]&=63; + if(!(PPU[1]&2)) { - tem=Pal[0]|(Pal[0]<<8)|(Pal[0]<<16)|(Pal[0]<<24); - tem|=0x40404040; + tem=Pal[0]|0x40; + tem|=tem<<8; + tem|=tem<<16; *(uint32 *)target=*(uint32 *)(target+4)=tem; } } @@ -428,7 +572,7 @@ static void Loop6502(void) { uint32 tem; int x; - uint8 *target=XBuf+(scanline<<8)+(scanline<<4)+8; + uint8 *target=XBuf+scanline*320+32; if(ScreenON || SpriteON) { @@ -442,7 +586,7 @@ static void Loop6502(void) #endif if(ScreenON) { - if(scanline>=FSettings.FirstSLine && scanline<=FSettings.LastSLine) + if(scanline>=FSettings.FirstSLine && scanline<=Settings.LastSLine) BGRender(target); else { @@ -468,18 +612,26 @@ static void Loop6502(void) if(PPU[1]&0x01) { for(x=63;x>=0;x--) - *(uint32 *)&target[x<<2]=(*(uint32*)&target[x<<2])&0xF0F0F0F0; + ((uint32 *)target)[x]=((uint32*)target)[x]&0xF0F0F0F0; } +#ifdef GP2X + if((PPU[1]>>5)==0x7) block_or(target, 256, 0xc0); + else if(PPU[1]&0xE0) block_andor(target, 256, 0x3f, 0x40); + else block_andor(target, 256, 0x3f, 0x80); +#else if((PPU[1]>>5)==0x7) for(x=63;x>=0;x--) - *(uint32 *)&target[x<<2]=((*(uint32*)&target[x<<2])&0x3f3f3f3f)|0x40404040; + ((uint32 *)target)[x]=(((uint32*)target)[x])|0xc0c0c0c0; else if(PPU[1]&0xE0) for(x=63;x>=0;x--) - *(uint32 *)&target[x<<2]=(*(uint32*)&target[x<<2])|0xC0C0C0C0; + ((uint32 *)target)[x]=(((uint32*)target)[x]&0x3f3f3f3f)|0x40404040; else for(x=63;x>=0;x--) - *(uint32 *)&target[x<<2]=(*(uint32*)&target[x<<2])&0x3f3f3f3f; - + ((uint32 *)target)[x]=(((uint32*)target)[x]&0x3f3f3f3f)|0x80808080; +#endif + // black borders + ((uint32 *)target)[-2]=((uint32 *)target)[-1]=0; + ((uint32 *)target)[64]=((uint32 *)target)[65]=0; #ifdef FRAMESKIP } #endif @@ -521,32 +673,13 @@ static void PRefreshLine(void) } } -/* Total of 33 tiles(32 + 1 extra) */ -static void FASTAPASS(1) RefreshLine(uint8 *target) +/* This high-level graphics MMC5 emulation code was written + for MMC5 carts in "CL" mode. It's probably not totally + correct for carts in "SL" mode. + */ +static void RefreshLine_MMC5Hack1(uint8 *P, uint32 vofs) { - uint32 vofs; - int X1; - uint8 *P=target; - - vofs=0; - - Pal[0]|=64; - Pal[4]|=64; - Pal[8]|=64; - Pal[0xC]|=64; - - vofs=((PPU[0]&0x10)<<8) | ((RefreshAddr>>12)&7); - P-=XOffset; - - /* This high-level graphics MMC5 emulation code was written - for MMC5 carts in "CL" mode. It's probably not totally - correct for carts in "SL" mode. - */ - if(MMC5Hack && geniestage!=1) - { - if(MMC5HackCHRMode==0 && (MMC5HackSPMode&0x80)) - { - int8 tochange; + int8 tochange, X1; tochange=MMC5HackSPMode&0x1F; @@ -589,10 +722,11 @@ static void FASTAPASS(1) RefreshLine(uint8 *target) RefreshAddr++; tochange--; } - } - else if(MMC5HackCHRMode==1 && (MMC5HackSPMode&0x80)) - { - int8 tochange; +} + +static void RefreshLine_MMC5Hack2(uint8 *P, uint32 vofs) +{ + int8 tochange, X1; tochange=MMC5HackSPMode&0x1F; @@ -636,10 +770,12 @@ static void FASTAPASS(1) RefreshLine(uint8 *target) RefreshAddr++; tochange--; } - } +} + +static void RefreshLine_MMC5Hack3(uint8 *P, uint32 vofs) +{ + int8 X1; - else if(MMC5HackCHRMode==1) - { for(X1=33;X1;X1--,P+=8) { uint8 *C; @@ -661,9 +797,12 @@ static void FASTAPASS(1) RefreshLine(uint8 *target) else RefreshAddr++; } - } - else - { +} + +static void RefreshLine_MMC5Hack4(uint8 *P, uint32 vofs) +{ + int8 X1; + for(X1=33;X1;X1--,P+=8) { uint8 *C; @@ -684,11 +823,12 @@ static void FASTAPASS(1) RefreshLine(uint8 *target) else RefreshAddr++; } - } - } // End if(MMC5Hack) +} + +static void RefreshLine_PPU_hook(uint8 *P, uint32 vofs) +{ + int8 X1; - else if(PPU_hook) - { for(X1=33;X1;X1--,P+=8) { uint8 *C; @@ -712,39 +852,79 @@ static void FASTAPASS(1) RefreshLine(uint8 *target) else RefreshAddr++; } - } - else - { - for(X1=33;X1;X1--,P+=8) +} + +static void RefreshLine_normal(uint8 *P, uint32 vofs) // vofs is 0x107 max +{ + int8 X1; + uint32 rfraddr = RefreshAddr; + uint8 *page = vnapage[(rfraddr>>10)&3]; + uint32 cc2=0; + + if ((rfraddr&0xc)!=0) + cc2=*(uint32 *) (page + ((rfraddr&0x380)>>4) + ((rfraddr&0x10)>>2) + 0x3c0); + + for (X1=33;X1;X1--,P+=8) { - uint8 *C; - uint8 cc,zz,zz2; + uint8 cc,*C; uint32 vadr; - zz=RefreshAddr&0x1F; - zz2=(RefreshAddr>>10)&3; - vadr=(vnapage[zz2][RefreshAddr&0x3ff]<<4)+vofs; + vadr=(page[rfraddr&0x3ff]<<4)+vofs; C = VRAMADR(vadr); - cc=vnapage[zz2][0x3c0+(zz>>2)+((RefreshAddr&0x380)>>4)]; - cc=((cc >> ((zz&2) + ((RefreshAddr&0x40)>>4))) &3) <<2; - #include "fceline.h" + if ((rfraddr&0xc)==0) + cc2=*(uint32 *) (page + ((rfraddr&0x380)>>4) + ((rfraddr&0x10)>>2) + 0x3c0); + cc=((cc2 >> ((rfraddr&2) + ((rfraddr&0x40)>>4) + ((rfraddr&0xc)<<1))) & 3) << 2; - if((RefreshAddr&0x1f)==0x1f) - RefreshAddr^=0x41F; - else - RefreshAddr++; - } - } + #include "fceline.h" - #undef vofs + if((rfraddr&0x1f)==0x1f) { + rfraddr^=0x41F; + page = vnapage[(rfraddr>>10)&3]; + } else + rfraddr++; + } + RefreshAddr = rfraddr; +} - Pal[0]&=63; - Pal[4]&=63; - Pal[8]&=63; - Pal[0xC]&=63; +static void SetRefreshLine(void) +{ + if(MMC5Hack && geniestage!=1) + { + if(MMC5HackCHRMode==0 && (MMC5HackSPMode&0x80)) + { + if (RefreshLine != RefreshLine_MMC5Hack1) printf("set refr RefreshLine_MMC5Hack1\n"); + RefreshLine = RefreshLine_MMC5Hack1; + } + else if(MMC5HackCHRMode==1 && (MMC5HackSPMode&0x80)) + { + if (RefreshLine != RefreshLine_MMC5Hack2) printf("set refr RefreshLine_MMC5Hack2\n"); + RefreshLine = RefreshLine_MMC5Hack2; + } + else if(MMC5HackCHRMode==1) + { + if (RefreshLine != RefreshLine_MMC5Hack3) printf("set refr RefreshLine_MMC5Hack3\n"); + RefreshLine = RefreshLine_MMC5Hack3; + } + else + { + if (RefreshLine != RefreshLine_MMC5Hack4) printf("set refr RefreshLine_MMC5Hack4\n"); + RefreshLine = RefreshLine_MMC5Hack4; + } + } // End if(MMC5Hack) + else if(PPU_hook) + { + if (RefreshLine != RefreshLine_PPU_hook) printf("set refr RefreshLine_PPU_hook\n"); + RefreshLine = RefreshLine_PPU_hook; + } + else + { + if (RefreshLine != RefreshLine_normal) printf("set refr RefreshLine_normal\n"); + RefreshLine = RefreshLine_normal; + } } -static INLINE void Fixit2(void) +static INLINE +void Fixit2(void) { if(ScreenON || SpriteON) { @@ -756,7 +936,8 @@ static INLINE void Fixit2(void) } } -static INLINE void Fixit1(void) +static INLINE +void Fixit1(void) { if(ScreenON || SpriteON) { @@ -784,45 +965,37 @@ static INLINE void Fixit1(void) } } + /* This is called at the beginning of all h-blanks on visible lines. */ static void DoHBlank(void) { if(ScreenON || SpriteON) FetchSpriteData(); - if(GameHBIRQHook && (ScreenON || SpriteON)) + if(GameHBIRQHook && (ScreenON || SpriteON) && ((PPU[0]&0x38)!=0x18)) { - X6502_Run(12); - GameHBIRQHook(); - X6502_Run(25-12); + X6502_Run(6); Fixit2(); - X6502_Run(85-25); + X6502_Run(4); + GameHBIRQHook(); + X6502_Run(85-16-10); } else { - X6502_Run(25); // Tried 65, caused problems with Slalom(maybe others) + X6502_Run(6); // Tried 65, caused problems with Slalom(maybe others) Fixit2(); - X6502_Run(85-25); + X6502_Run(85-6-16); } + if(GameHBIRQHook2 && (ScreenON || SpriteON)) + GameHBIRQHook2(); //PPU_hook(0,-1); //fprintf(stderr,"%3d: $%04x\n",scanline,RefreshAddr); + scanline++; + if (scanline<240) + ResetRL(); + X6502_Run(16); } - - - - - - - - - - - - - - - // ============================// // end of new code // ===========================// @@ -871,7 +1044,7 @@ void CloseGame(void) if(GameLoaded) { if(FCEUGameInfo.type!=GIT_NSF) - FlushGameCheats(); + FCEU_FlushGameCheats(0,0); #ifdef NETWORK if(FSettings.NetworkPlay) KillNetplay(); #endif @@ -886,7 +1059,7 @@ void ResetGameLoaded(void) if(GameLoaded) CloseGame(); GameStateRestore=0; PPU_hook=0; - GameHBIRQHook=0; + GameHBIRQHook=GameHBIRQHook2=0; GameExpSound.Fill=0; GameExpSound.RChange=0; if(GameExpSound.Kill) @@ -904,28 +1077,58 @@ void ResetGameLoaded(void) FCEUGameInfo.inputfc=-1; } +char lastLoadedGameName [2048]; +int UNIFLoad(const char *name, int fp); +int iNESLoad(const char *name, int fp); +int FDSLoad(const char *name, int fp); +int NSFLoad(int fp); + FCEUGI *FCEUI_LoadGame(char *name) { + char name2[512]; + int have_movie = 0; int fp; Exit=1; ResetGameLoaded(); - fp=FCEU_fopen(name,"rb"); + strncpy(name2, name, sizeof(name2)); + name2[sizeof(name2)-1] = 0; + + fp=FCEU_fopen(name2,"rb"); if(!fp) { FCEU_PrintError("Error opening \"%s\"!",name); return 0; } - GetFileBase(name); - if(iNESLoad(name,fp)) + { + char *p = name2 + strlen(name2) - 4; + if (strcmp(p, ".fcm") == 0) + { + // movie detected + printf("movie detected\n"); + FCEU_fclose(fp); + *p = 0; + fp=FCEU_fopen(name2,"rb"); + if (!fp) { + printf("no ROM for movie\n"); + return 0; + } + have_movie = 1; + } + } + + strcpy(lastLoadedGameName, name2); + + GetFileBase(name2); + if(iNESLoad(name2,fp)) goto endlseq; if(NSFLoad(fp)) goto endlseq; - if(FDSLoad(name,fp)) + if(FDSLoad(name2,fp)) goto endlseq; - if(UNIFLoad(name,fp)) + if(UNIFLoad(name2,fp)) goto endlseq; FCEU_PrintError("An error occurred while loading the file."); @@ -948,12 +1151,15 @@ FCEUGI *FCEUI_LoadGame(char *name) SaveStateRefresh(); if(FCEUGameInfo.type!=GIT_NSF) { - LoadGamePalette(); - LoadGameCheats(); + FCEU_LoadGamePalette(); + FCEU_LoadGameCheats(0); } FCEU_ResetPalette(); Exit=0; + + if (have_movie) + FCEUI_LoadMovie(name, 1); return(&FCEUGameInfo); } @@ -972,14 +1178,12 @@ void FCEU_ResetVidSys(void) if(w) { PAL=1; - scanlines_per_frame=312; FSettings.FirstSLine=FSettings.UsrFirstSLine[1]; FSettings.LastSLine=FSettings.UsrLastSLine[1]; } else { PAL=0; - scanlines_per_frame=262; FSettings.FirstSLine=FSettings.UsrFirstSLine[0]; FSettings.LastSLine=FSettings.UsrLastSLine[0]; } @@ -995,50 +1199,52 @@ int FCEUI_Initialize(void) FSettings.UsrFirstSLine[0]=8; FSettings.UsrFirstSLine[1]=0; FSettings.UsrLastSLine[0]=FSettings.UsrLastSLine[1]=239; - FSettings.SoundVolume=65535; // 100% + FSettings.SoundVolume=100; return 1; } -#define harko 0xe //0x9 +void MMC5_hb(int); /* Ugh ugh ugh. */ static INLINE void Thingo(void) { Loop6502(); + if(MMC5Hack && (ScreenON || SpriteON)) MMC5_hb(scanline); + + // check: Battletoads & Double Dragon if(tosprite>=256) { - X6502_Run(256-harko); - Fixit1(); - X6502_Run(harko); + X6502_Run(256); } else { - if(tosprite<=240) - { + // sky glitches in SMB1 if done wrong X6502_Run(tosprite); PPU[2]|=0x40; - X6502_Run(256-tosprite-harko); - Fixit1(); - X6502_Run(harko); - } - else - { - X6502_Run(256-harko); - Fixit1(); - X6502_Run(tosprite-(256-harko)); - PPU[2]|=0x40; X6502_Run(256-tosprite); - } - tosprite=256; + tosprite = 256; } + TryFixit1(); DoHBlank(); } -#undef harko void EmLoop(void) { for(;;) { - ApplyPeriodicCheats(); + int x; + uint32 scanlines_per_frame = PAL ? 312 : 262; + UpdateInput(); + FCEU_ApplyPeriodicCheats(); + + // FCEUPPU_Loop: + if(ppudead) /* Needed for Knight Rider, possibly others. */ + { + //memset(XBuf, 0, 320*240); + X6502_Run(scanlines_per_frame*(256+85)); + ppudead--; + goto update; + } + X6502_Run(256+85); PPU[2]|=0x80; @@ -1051,42 +1257,64 @@ void EmLoop(void) of this delay. */ if(FCEUGameInfo.type==GIT_NSF) - TriggerNMINSF(); + DoNSFFrame(); else if(VBlankON) TriggerNMI(); - X6502_Run((scanlines_per_frame-242)*(256+85)-12); - + // Note: this is needed for asm core + // Warning: using 'scanline' var here breaks Castlevania III + { + int lines; + X6502_Run(256+85-12); + for (lines=scanlines_per_frame-242-1;lines;lines--) + X6502_Run(256+85); + } + // X6502_Run((scanlines_per_frame-242)*(256+85)-12); PPU_status&=0x1f; - X6502_Run(256); + { - static int kook=0; if(ScreenON || SpriteON) + { if(GameHBIRQHook) GameHBIRQHook(); + if(PPU_hook) + for(x=0;x<42;x++) {PPU_hook(0x2000); PPU_hook(0);} // ugh + if(GameHBIRQHook2) + GameHBIRQHook2(); + } + + X6502_Run(85-16); - X6502_Run(85-kook); - kook=(kook+1)&1; + if(ScreenON || SpriteON) + { + RefreshAddr=TempAddr; + if(PPU_hook) PPU_hook(RefreshAddr&0x3fff); + } + ResetRL(); + + X6502_Run(16-kook); + kook ^= 1; } - if(ScreenON || SpriteON) + if(FCEUGameInfo.type==GIT_NSF) { - RefreshAddr=TempAddr; - if(PPU_hook) PPU_hook(RefreshAddr&0x3fff); + // run scanlines for asm core to fuction + for(scanline=0;scanline<240;scanline++) + X6502_Run(256+85); } - if(FCEUGameInfo.type==GIT_NSF) - X6502_Run((256+85)*240); else { int x,max,maxref; deemp=PPU[1]>>5; - for(scanline=0;scanline<240;scanline++) + SetRefreshLine(); + for(scanline=0;scanline<240;) // scanline is incremented in DoLine. Evil. :/ { deempcnt[deemp]++; Thingo(); } + if(MMC5Hack && (ScreenON || SpriteON)) MMC5_hb(scanline); for(x=1,max=0,maxref=0;x<7;x++) { if(deempcnt[x]>max) @@ -1096,16 +1324,18 @@ void EmLoop(void) } deempcnt[x]=0; } - //FCEU_DispMessage("%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x %d",deempcnt[0],deempcnt[1],deempcnt[2],deempcnt[3],deempcnt[4],deempcnt[5],deempcnt[6],deempcnt[7],maxref); - //memset(deempcnt,0,sizeof(deempcnt)); SetNESDeemph(maxref,0); } +update: { int ssize; ssize=FlushEmulateSound(); + timestampbase += timestamp; + timestamp = 0; + #ifdef FRAMESKIP if(FSkip) { @@ -1119,7 +1349,6 @@ void EmLoop(void) FCEU_PutImage(); FCEUD_Update(XBuf+8,WaveFinalMono,ssize); } - UpdateInput(); } if(Exit) @@ -1128,7 +1357,7 @@ void EmLoop(void) break; } - } + } // for } #ifdef FPS @@ -1175,6 +1404,8 @@ static void ResetPPU(void) PPUGenLatch=0; RefreshAddr=TempAddr=0; vtoggle = 0; + ppudead = 2; + kook = 0; } static void PowerPPU(void) @@ -1187,7 +1418,7 @@ static void PowerPPU(void) void ResetNES(void) { - if(!GameLoaded || (FCEUGameInfo.type==GIT_NSF)) return; + if(!GameLoaded) return; GameInterface(GI_RESETM2); ResetSound(); ResetPPU(); @@ -1212,3 +1443,26 @@ void PowerNES(void) X6502_Power(); } + +/* savestate stuff */ +uint16 TempAddrT,RefreshAddrT; + +SFORMAT FCEUPPU_STATEINFO[]={ + { NTARAM, 0x800, "NTAR"}, + { PALRAM, 0x20, "PRAM"}, + { SPRAM, 0x100, "SPRA"}, + { PPU, 0x4, "PPUR"}, + { &XOffset, 1, "XOFF"}, + { &vtoggle, 1, "VTOG"}, + { &RefreshAddrT, 2|RLSB, "RADD"}, + { &TempAddrT, 2|RLSB, "TADD"}, + { &VRAMBuffer, 1, "VBUF"}, + { &PPUGenLatch, 1, "PGEN"}, + // from 0.98.15 + { &kook, 1, "KOOK"}, + { &ppudead, 1, "DEAD"}, + { &PPUSPL, 1, "PSPL"}, + { 0 } + }; + +