X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=fceu.git;a=blobdiff_plain;f=fce.c;h=89a54a360b7989bf0b7e6222b2be5dfcaf1c573a;hp=79aa4beddafb43e37ef609513c2f5b7776ef10ca;hb=892b1f6c68346fa00dc3029ab8bd31178e730509;hpb=81bd66a11186efb420eb8d6fd5766f0ef26d5919 diff --git a/fce.c b/fce.c index 79aa4be..89a54a3 100644 --- a/fce.c +++ b/fce.c @@ -39,6 +39,7 @@ #include "fds.h" #include "ines.h" #include "unif.h" +#include "vsuni.h" #include "cheat.h" #include "state.h" @@ -48,8 +49,15 @@ #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) @@ -61,6 +69,9 @@ static void PowerPPU(void); uint64 timestampbase=0; +static int ppudead=1; +static int kook=0; + int MMC5Hack; uint32 MMC5HackVROMMask; uint8 *MMC5HackExNTARAMPtr; @@ -84,15 +95,13 @@ uint8 PPUCHRRAM; static uint8 deemp=0; static int deempcnt[8]; -int tosprite=256; - FCEUGI FCEUGameInfo; -void (*GameInterface)(int h); +void (*GameInterface)(int h, void *param); 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]; @@ -103,9 +112,6 @@ static int RWWrap=0; #ifdef ASM_6502 static void asmcpu_update(int32 cycles) { - // timestamp.. - timestamp += ((cycles >> 4) * 43) >> 7; // aproximating /= 48 - // some code from x6502.c fhcnt-=cycles; if(fhcnt<=0) @@ -140,7 +146,9 @@ void asmcpu_unpack(void) X6502_Rebase_a(); nes_registers[4] = X.S << 24; nes_registers[4]|= X.IRQlow << 8; - nes_registers[7] = (uint32)X.count; + if (MapIRQHook) + nes_registers[4] |= 1<<16; // MapIRQHook set bit + nes_registers[7] = (uint32)X.count << 16; // NVUB DIZC nes_registers[4]|= X.P & 0x5d; @@ -156,7 +164,7 @@ void asmcpu_pack(void) 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]; + X.count = (int32) nes_registers[7] >> 16; // NVUB DIZC X.P = nes_registers[4] & 0x5d; @@ -196,6 +204,9 @@ void FlushGenieRW(void) ARead[x+0x8000]=AReadG[x]; BWrite[x+0x8000]=BWriteG[x]; } +#ifdef ASM_6502 + GenieSetPages(1); +#endif free(AReadG); free(BWriteG); AReadG=0; @@ -287,6 +298,71 @@ 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 uint8 *Plinef; + +extern uint8 sprlinebuf[256+8]; +extern int32 sphitx; +extern uint8 sphitdata; + +extern int spork; /* spork the world. Any sprites on this line? + Then this will be set to 1. Needed for zapper + emulation and *gasp* sprite emulation. + */ + +static void ResetRL(uint8 *target) +{ + if(InputScanlineHook) + InputScanlineHook(0,0,0,0); + Plinef=target; + linestartts=timestamp*48+X6502_GetCycleCount(); + tofix=1; +} + +static INLINE void Fixit1(void); + +/* faking FCEUPPU_LineUpdate() from later versions of the emu */ +static void FakedLineUpdate(void) +{ + #define TOFIXNUM (272-0x4) + int lastpixel; + + if (scanline >= 240) return; + + if (tofix || sphitx != 0x100) + { + lastpixel = (timestamp*48-linestartts)>>4; + if (PAL) lastpixel += lastpixel>>4; + //printf("lastpixel: %i\n", lastpixel); + } + + if (tofix && lastpixel>=TOFIXNUM) + { + Fixit1(); + tofix=0; + } + + // CheckSpriteHit() + if(sphitx!=0x100) + { + int l=lastpixel-16; + int x; + + for(x=sphitx;x<(sphitx+8) && x>(x-sphitx))) && !(Plinef[x]&64)) + { + PPU_status|=0x40; + sphitx=0x100; + break; + } + } + } +} + + static DECLFW(BRAML) { RAM[A]=V; @@ -310,25 +386,38 @@ static DECLFR(ARAMH) static DECLFR(A2002) { + /* merged */ uint8 ret; + + FakedLineUpdate(); 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 */ + FakedLineUpdate(); return PPUGenLatch; } static DECLFR(A2007) { + /* merged */ uint8 ret; uint32 tmp=RefreshAddr&0x3FFF; - PPUGenLatch=ret=VRAMBuffer; + FakedLineUpdate(); + + ret=VRAMBuffer; + if(PPU_hook) PPU_hook(tmp); + PPUGenLatch=VRAMBuffer; if(tmp<0x2000) { VRAMBuffer=VPage[tmp>>10][tmp]; @@ -341,11 +430,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? */ + FakedLineUpdate(); PPUGenLatch=V; PPU[0]=V; TempAddr&=0xF3FF; @@ -354,6 +446,8 @@ static DECLFW(B2000) static DECLFW(B2001) { + /* merged */ + FakedLineUpdate(); PPUGenLatch=V; PPU[1]=V; if(V&0xE0) @@ -363,11 +457,13 @@ static DECLFW(B2001) static DECLFW(B2002) { + /* merged */ PPUGenLatch=V; } static DECLFW(B2003) { + /* merged */ PPUGenLatch=V; PPU[3]=V; PPUSPL=V&0x7; @@ -375,9 +471,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; @@ -386,16 +482,17 @@ static DECLFW(B2004) { //printf("$%02x:$%02x\n",PPUSPL,V); SPRAM[PPUSPL]=V; - PPUSPL++; } PPU[3]++; + PPUSPL++; } static DECLFW(B2005) { + /* merged */ uint32 tmp=TempAddr; - + FakedLineUpdate(); PPUGenLatch=V; if (!vtoggle) { @@ -416,6 +513,9 @@ static DECLFW(B2005) static DECLFW(B2006) { + /* merged */ + FakedLineUpdate(); + PPUGenLatch=V; if(!vtoggle) { @@ -426,8 +526,8 @@ static DECLFW(B2006) { TempAddr&=0xFF00; TempAddr|=V; - RefreshAddr=TempAddr; + RefreshAddr=TempAddr; if(PPU_hook) PPU_hook(RefreshAddr); } @@ -436,16 +536,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) { @@ -466,6 +565,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); @@ -496,7 +596,6 @@ void BGRender(uint8 *target) } #ifdef FRAMESKIP -int FSkip_setting=-1; // auto int FSkip=0; void FCEUI_FrameSkip(int x) { @@ -505,74 +604,90 @@ void FCEUI_FrameSkip(int x) #endif /* This is called at the beginning of each visible scanline */ -static void Loop6502(void) +static void LineUpdate(uint8 *target) { uint32 tem; - int x; - uint8 *target=XBuf+scanline*320+32; + int y; - if(ScreenON || SpriteON) - { - /* PRefreshLine() will not get called on skipped frames. This - could cause a problem, but the solution would be rather complex, - due to the current sprite 0 hit code. + /* PRefreshLine() will not get called on skipped frames. This + * could cause a problem, but the solution would be rather complex, + * due to the current sprite 0 hit code. */ - #ifdef FRAMESKIP - if(!FSkip) + if(FSkip) + { + y=(int)SPRAM[0] + 1; + if(scanline==y && SpriteON) PPU_status|=0x40; // hack + return; + } + + if(scanline < FSettings.FirstSLine || scanline > FSettings.LastSLine) + { + if(PPU_hook) + PRefreshLine(); + y=(int)SPRAM[0] + 1; + if(scanline==y && SpriteON) PPU_status|=0x40; + } + else + { + if(ScreenON) { - #endif - if(ScreenON) - { - if(scanline>=FSettings.FirstSLine && scanline<=FSettings.LastSLine) - BGRender(target); - else - { - if(PPU_hook) - PRefreshLine(); - } - } - else - { - tem=Pal[0]|(Pal[0]<<8)|(Pal[0]<<16)|(Pal[0]<<24); - tem|=0x40404040; - FCEU_dwmemset(target,tem,264); - } - #ifdef FRAMESKIP + BGRender(target); } - #endif - if (SpriteON && scanline) - RefreshSprite(target); - #ifdef FRAMESKIP - if(!FSkip) + else { - #endif - if(PPU[1]&0x01) - { - for(x=63;x>=0;x--) - ((uint32 *)target)[x]=((uint32*)target)[x]&0xF0F0F0F0; - } - if((PPU[1]>>5)==0x7) - for(x=63;x>=0;x--) - ((uint32 *)target)[x]=(((uint32*)target)[x]&0x3f3f3f3f)|0x40404040; - else if(PPU[1]&0xE0) - for(x=63;x>=0;x--) - ((uint32 *)target)[x]=((uint32*)target)[x]|0xC0C0C0C0; - else - for(x=63;x>=0;x--) - ((uint32 *)target)[x]=((uint32*)target)[x]&0x3f3f3f3f; - FCEU_dwmemset(target- 8,0x3f3f3f3f,8); - FCEU_dwmemset(target+256,0x3f3f3f3f,8); - #ifdef FRAMESKIP + tem=Pal[0]|0x40; + tem|=tem << 8; + tem|=tem << 16; + FCEU_dwmemset(target,tem,256); } - #endif - } - else - { - tem=Pal[0]|(Pal[0]<<8)|(Pal[0]<<16)|(Pal[0]<<24); - FCEU_dwmemset(target,tem,256); } + if(InputScanlineHook) - InputScanlineHook(target, scanline); + InputScanlineHook(target,spork?sprlinebuf:0,linestartts,256); +} + + +static void LineUpdateEnd(uint8 *target) +{ +#ifdef GP2X + if(ScreenON || SpriteON) // Yes, very el-cheapo. + { + if(PPU[1]&0x01) + block_and(target, 256, 0x30); + } + if((PPU[1]>>5)==0x7) + block_or(target, 256, 0xc0); + else if(PPU[1]&0xE0) + block_or(target, 256, 0x40); + else + block_andor(target, 256, 0x3f, 0x80); +#else + int x; + + if(ScreenON || SpriteON) // Yes, very el-cheapo. + { + if(PPU[1]&0x01) + { + for(x=63;x>=0;x--) + *(uint32 *)&target[x<<2]=(*(uint32*)&target[x<<2])&0x30303030; + } + } + if((PPU[1]>>5)==0x7) + { + for(x=63;x>=0;x--) + *(uint32 *)&target[x<<2]=((*(uint32*)&target[x<<2])&0x3f3f3f3f)|0xc0c0c0c0; + } + else if(PPU[1]&0xE0) + for(x=63;x>=0;x--) + *(uint32 *)&target[x<<2]=(*(uint32*)&target[x<<2])|0x40404040; + else + for(x=63;x>=0;x--) + *(uint32 *)&target[x<<2]=((*(uint32*)&target[x<<2])&0x3f3f3f3f)|0x80808080; +#endif + + // black borders + ((uint32 *)target)[-2]=((uint32 *)target)[-1]=0; + ((uint32 *)target)[64]=((uint32 *)target)[65]=0; } #define PAL(c) ((c)+cc) @@ -580,27 +695,29 @@ static void Loop6502(void) static void PRefreshLine(void) { - uint32 vofs; - uint8 X1; + uint32 vofs; + int X1; + vofs=((PPU[0]&0x10)<<8) | ((RefreshAddr>>12)&7); + void (*PPU_hook_)(uint32 A) = PPU_hook; + - vofs = 0; - if (BGAdrHI) vofs = 0x1000; + for(X1=33;X1;X1--) + { + uint32 zz2; + uint32 vadr; - vofs+=(RefreshAddr>>12)&7; + zz2=(RefreshAddr>>10)&3; + PPU_hook_(0x2000|(RefreshAddr&0xFFF)); + + vadr=(vnapage[zz2][RefreshAddr&0x3ff]<<4)+vofs; + + PPU_hook_(vadr); - for(X1=33;X1;X1--) - { - register uint8 no; - register uint8 zz2; - zz2=(uint8)((RefreshAddr>>10)&3); - PPU_hook(0x2000|(RefreshAddr&0xFFF)); - no = vnapage[zz2][(RefreshAddr&0x3ff)]; - PPU_hook((no<<4)+vofs); if((RefreshAddr&0x1f)==0x1f) RefreshAddr^=0x41F; else RefreshAddr++; - } + } } /* This high-level graphics MMC5 emulation code was written @@ -758,30 +875,34 @@ static void RefreshLine_MMC5Hack4(uint8 *P, uint32 vofs) static void RefreshLine_PPU_hook(uint8 *P, uint32 vofs) { int8 X1; + void (*PPU_hook_)(uint32 A) = PPU_hook; + uint32 rfraddr = RefreshAddr; + uint8 *page = vnapage[(rfraddr>>10)&3]; for(X1=33;X1;X1--,P+=8) { uint8 *C; - uint8 cc,zz,zz2; + uint8 cc,zz; uint32 vadr; - zz=RefreshAddr&0x1F; - zz2=(RefreshAddr>>10)&3; - PPU_hook(0x2000|(RefreshAddr&0xFFF)); - cc=vnapage[zz2][0x3c0+(zz>>2)+((RefreshAddr&0x380)>>4)]; - cc=((cc >> ((zz&2) + ((RefreshAddr&0x40)>>4))) &3) <<2; - vadr=(vnapage[zz2][RefreshAddr&0x3ff]<<4)+vofs; + zz=rfraddr&0x1F; + PPU_hook_(0x2000|(rfraddr&0xFFF)); + cc=page[0x3c0+(zz>>2)+((rfraddr&0x380)>>4)]; + cc=((cc >> ((zz&2) + ((rfraddr&0x40)>>4))) &3) <<2; + vadr=(page[rfraddr&0x3ff]<<4)+vofs; C = VRAMADR(vadr); #include "fceline.h" - PPU_hook(vadr); + PPU_hook_(vadr); - if((RefreshAddr&0x1f)==0x1f) - RefreshAddr^=0x41F; - else - RefreshAddr++; + if((rfraddr&0x1f)==0x1f) { + rfraddr^=0x41F; + page = vnapage[(rfraddr>>10)&3]; + } else + rfraddr++; } + RefreshAddr = rfraddr; } static void RefreshLine_normal(uint8 *P, uint32 vofs) // vofs is 0x107 max @@ -853,7 +974,7 @@ static void SetRefreshLine(void) } } -//static INLINE +static INLINE void Fixit2(void) { if(ScreenON || SpriteON) @@ -866,7 +987,7 @@ void Fixit2(void) } } -//static INLINE +static INLINE void Fixit1(void) { if(ScreenON || SpriteON) @@ -895,33 +1016,6 @@ void Fixit1(void) } } -//#define NEW_TRY - -/* This is called at the beginning of all h-blanks on visible lines. */ -#ifndef NEW_TRY -static void DoHBlank(void) -{ - if(ScreenON || SpriteON) - FetchSpriteData(); - if(GameHBIRQHook && (ScreenON || SpriteON)) - { - X6502_Run(12); - GameHBIRQHook(); - X6502_Run(25-12); - Fixit2(); - X6502_Run(85-25); - } - else - { - X6502_Run(25); // Tried 65, caused problems with Slalom(maybe others) - Fixit2(); - X6502_Run(85-25); - } - //PPU_hook(0,-1); - //fprintf(stderr,"%3d: $%04x\n",scanline,RefreshAddr); -} -#endif - // ============================// // end of new code @@ -968,14 +1062,15 @@ void ResetMapping(void) int GameLoaded=0; void CloseGame(void) { + FCEUI_StopMovie(); if(GameLoaded) { if(FCEUGameInfo.type!=GIT_NSF) - FlushGameCheats(); + FCEU_FlushGameCheats(0,0); #ifdef NETWORK if(FSettings.NetworkPlay) KillNetplay(); #endif - GameInterface(GI_CLOSE); + GameInterface(GI_CLOSE, 0); CloseGenie(); GameLoaded=0; } @@ -986,7 +1081,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) @@ -1005,14 +1100,20 @@ void ResetGameLoaded(void) } char lastLoadedGameName [2048]; +int LoadGameLastError = 0; +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 have_movie = 0, have_ips = 0; int fp; - Exit=1; + //Exit=1; + LoadGameLastError = 0; ResetGameLoaded(); strncpy(name2, name, sizeof(name2)); @@ -1022,27 +1123,44 @@ FCEUGI *FCEUI_LoadGame(char *name) if(!fp) { FCEU_PrintError("Error opening \"%s\"!",name); + LoadGameLastError = 1; return 0; } { char *p = name2 + strlen(name2) - 4; - if (strcmp(p, ".fcm") == 0) + if (strcasecmp(p, ".fcm") == 0) printf("movie detected\n"), have_movie = 1; + if (strcasecmp(p, ".ips") == 0) printf("ips detected\n"), have_ips = 1; + if (have_movie || have_ips) { // movie detected - printf("movie detected\n"); FCEU_fclose(fp); *p = 0; fp=FCEU_fopen(name2,"rb"); + if (!fp && p - name2 > 2) + { + for (p--; p > name2 && *p != '.'; p--); + *p = 0; + fp=FCEU_fopen(name2,"rb"); + } if (!fp) { - printf("no ROM for movie\n"); + printf("no ROM for ips/movie\n"); + LoadGameLastError = 2; return 0; } - have_movie = 1; } } - strcpy(lastLoadedGameName, name2); + // do IPS patch + if (have_ips) + { + FCEU_fclose(fp); + FILE *ips = fopen(name, "rb"); + if (!ips) return 0; + fp=FCEU_fopen_forcemem(name2); + if (!fp) { fclose(ips); return 0; } + ApplyIPS(ips, fp); // closes ips + } GetFileBase(name2); if(iNESLoad(name2,fp)) @@ -1056,6 +1174,8 @@ FCEUGI *FCEUI_LoadGame(char *name) FCEU_PrintError("An error occurred while loading the file."); FCEU_fclose(fp); + // format handlers may set LoadGameLastError themselves. + if (LoadGameLastError == 0) LoadGameLastError = 3; return 0; endlseq: @@ -1074,8 +1194,8 @@ FCEUGI *FCEUI_LoadGame(char *name) SaveStateRefresh(); if(FCEUGameInfo.type!=GIT_NSF) { - LoadGamePalette(); - LoadGameCheats(); + FCEU_LoadGamePalette(); + FCEU_LoadGameCheats(0); } FCEU_ResetPalette(); @@ -1083,6 +1203,9 @@ FCEUGI *FCEUI_LoadGame(char *name) if (have_movie) FCEUI_LoadMovie(name, 1); + + strcpy(lastLoadedGameName, name2); + return(&FCEUGameInfo); } @@ -1110,7 +1233,7 @@ void FCEU_ResetVidSys(void) FSettings.FirstSLine=FSettings.UsrFirstSLine[0]; FSettings.LastSLine=FSettings.UsrLastSLine[0]; } - printf("PAL = %i\n", PAL); + printf("ResetVidSys: PAL = %i\n", PAL); SetSoundVariables(); } @@ -1122,58 +1245,85 @@ 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 -static INLINE void Thingo(void) +void MMC5_hb(int); /* Ugh ugh ugh. */ +static void DoLine(void) { - Loop6502(); -#ifndef NEW_TRY + uint8 *target=XBuf+scanline*320+32; + + LineUpdate(target); - if(tosprite>=256) + if(MMC5Hack && (ScreenON || SpriteON)) MMC5_hb(scanline); + + X6502_Run(256); + + // check: Battletoads & Double Dragon, Addams Family + // sky glitches in SMB1 if done wrong + FakedLineUpdate(); + +#ifdef FRAMESKIP + if(!FSkip) +#endif + if(scanline>=FSettings.FirstSLine && scanline<=FSettings.LastSLine) { - X6502_Run(256-harko); - Fixit1(); - X6502_Run(harko); + if(SpriteON && spork) + CopySprites(target); + + LineUpdateEnd(target); + } + sphitx=0x100; + + if(ScreenON || SpriteON) + FetchSpriteData(); + + // DoHBlank(); + if(GameHBIRQHook && (ScreenON || SpriteON) && ((PPU[0]&0x38)!=0x18)) + { + X6502_Run(6); + Fixit2(); + X6502_Run(4); + GameHBIRQHook(); + X6502_Run(85-10-16); } else { - if(tosprite<=240) - { - 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; + X6502_Run(6); // Tried 65, caused problems with Slalom(maybe others) + Fixit2(); + X6502_Run(85-6-16); } - DoHBlank(); -#else - X6502_Run_scanline(); -#endif + + if(SpriteON) + RefreshSprites(); + if(GameHBIRQHook2 && (ScreenON || SpriteON)) + GameHBIRQHook2(); + scanline++; + if (scanline<240) + ResetRL(XBuf+scanline*320+32); + X6502_Run(16); } -#undef harko + void EmLoop(void) { for(;;) { + int x; uint32 scanlines_per_frame = PAL ? 312 : 262; - //extern int asdc; - //printf("asdc: %i\n", asdc); - //asdc=0; - ApplyPeriodicCheats(); + 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; @@ -1186,35 +1336,52 @@ void EmLoop(void) of this delay. */ if(FCEUGameInfo.type==GIT_NSF) - TriggerNMINSF(); + DoNSFFrame(); else if(VBlankON) TriggerNMI(); - X6502_Run(256+85-12); - for(scanline=242+1;scanline>5; SetRefreshLine(); - for(scanline=0;scanline<240;scanline++) + for(scanline=0;scanline<240;) // scanline is incremented in DoLine. Evil. :/ { deempcnt[deemp]++; - Thingo(); + DoLine(); } + if(MMC5Hack && (ScreenON || SpriteON)) MMC5_hb(scanline); for(x=1,max=0,maxref=0;x<7;x++) { if(deempcnt[x]>max) @@ -1236,16 +1404,24 @@ 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: + if(Exit) + { + //CloseGame(); + break; + } + { int ssize; ssize=FlushEmulateSound(); + timestampbase += timestamp; + timestamp = 0; + #ifdef FRAMESKIP if(FSkip) { @@ -1259,16 +1435,9 @@ void EmLoop(void) FCEU_PutImage(); FCEUD_Update(XBuf+8,WaveFinalMono,ssize); } - UpdateInput(); - } - - if(Exit) - { - CloseGame(); - break; } - } + } // for } #ifdef FPS @@ -1315,6 +1484,8 @@ static void ResetPPU(void) PPUGenLatch=0; RefreshAddr=TempAddr=0; vtoggle = 0; + ppudead = 2; + kook = 0; } static void PowerPPU(void) @@ -1327,13 +1498,25 @@ static void PowerPPU(void) void ResetNES(void) { - if(!GameLoaded || (FCEUGameInfo.type==GIT_NSF)) return; - GameInterface(GI_RESETM2); + if(!GameLoaded) return; + GameInterface(GI_RESETM2, 0); ResetSound(); ResetPPU(); X6502_Reset(); } +static void FCEU_MemoryRand(uint8 *ptr, uint32 size) +{ + int x=0; + while(size) + { + *ptr=(x&4)?0xFF:0x00; + x++; + size--; + ptr++; + } +} + void PowerNES(void) { if(!GameLoaded) return; @@ -1343,12 +1526,46 @@ void PowerNES(void) GeniePower(); +#ifndef DEBUG_ASM_6502 + FCEU_MemoryRand(RAM,0x800); +#else memset(RAM,0x00,0x800); +#endif ResetMapping(); - GameInterface(GI_POWER); PowerSound(); PowerPPU(); + GameInterface(GI_POWER, 0); + if(FCEUGameInfo.type==GIT_VSUNI) + FCEU_VSUniPower(); +#ifdef ASM_6502 + if (geniestage) + GenieSetPages(0); +#endif timestampbase=0; X6502_Power(); + FCEU_PowerCheats(); } + +/* 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 } + }; + +