#include "crc32.h"
#include "ppu.h"
+#include "palette.h"
#include "movie.h"
-#define Pal (PALRAM)
-
+#include "dprintf.h"
-#ifdef DEBUG_ASM_6502
-extern int cpu_repeat;
-extern int cpu_lastval;
+#ifdef GP2X
+#include "drivers/gp2x/asmutils.h"
#endif
+#define Pal (PALRAM)
+
+
static void (*RefreshLine)(uint8 *P, uint32 vofs) = NULL;
static void PRefreshLine(void);
uint64 timestampbase=0;
+static int ppudead=1;
+static int kook=0;
+
int MMC5Hack;
uint32 MMC5HackVROMMask;
uint8 *MMC5HackExNTARAMPtr;
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];
#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)
X6502_Rebase_a();
nes_registers[4] = X.S << 24;
nes_registers[4]|= X.IRQlow << 8;
- nes_registers[7] = (uint32)X.count;
+ nes_registers[7] = (uint32)X.count << 16;
// NVUB DIZC
nes_registers[4]|= X.P & 0x5d;
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;
ARead[x+0x8000]=AReadG[x];
BWrite[x+0x8000]=BWriteG[x];
}
+#ifdef ASM_6502
+ GenieSetPages(1);
+#endif
free(AReadG);
free(BWriteG);
AReadG=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;
static DECLFR(A2002)
{
+ /* merged */
uint8 ret;
-#ifdef DEBUG_ASM_6502
- if (cpu_repeat) return cpu_lastval;
-#endif
+
+ TryFixit1();
ret = PPU_status;
+ ret|=PPUGenLatch&0x1F;
vtoggle=0;
PPU_status&=0x7F;
-#ifdef DEBUG_ASM_6502
-// cpu_lastval=ret|(PPUGenLatch&0x1F);
-#endif
- 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;
-#ifdef DEBUG_ASM_6502
- if (cpu_repeat) return cpu_lastval;
-#endif
- PPUGenLatch=ret=VRAMBuffer;
+ TryFixit1();
+
+ ret=VRAMBuffer;
+
if(PPU_hook) PPU_hook(tmp);
+ PPUGenLatch=VRAMBuffer;
if(tmp<0x2000)
{
VRAMBuffer=VPage[tmp>>10][tmp];
if (INC32) RefreshAddr+=32;
else RefreshAddr++;
if(PPU_hook) PPU_hook(RefreshAddr&0x3fff);
-#ifdef DEBUG_ASM_6502
-// cpu_lastval=ret;
-#endif
+ dprintf("r [2007] %02x",ret);
return ret;
}
static DECLFW(B2000)
{
+ /* NMI2? */
+ TryFixit1();
PPUGenLatch=V;
PPU[0]=V;
TempAddr&=0xF3FF;
static DECLFW(B2001)
{
+ /* merged */
+ TryFixit1();
PPUGenLatch=V;
PPU[1]=V;
if(V&0xE0)
static DECLFW(B2002)
{
+ /* merged */
PPUGenLatch=V;
}
static DECLFW(B2003)
{
+ /* merged */
PPUGenLatch=V;
PPU[3]=V;
PPUSPL=V&0x7;
static DECLFW(B2004)
{
+ /* merged */
PPUGenLatch=V;
- //SPRAM[PPU[3]++]=V;
- if(PPUSPL&8)
+ if(PPUSPL>=8)
{
if(PPU[3]>=8)
SPRAM[PPU[3]]=V;
{
//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)
{
static DECLFW(B2006)
{
+ /* merged */
+ TryFixit1();
+
PPUGenLatch=V;
if(!vtoggle)
{
{
TempAddr&=0xFF00;
TempAddr|=V;
- RefreshAddr=TempAddr;
+ RefreshAddr=TempAddr;
if(PPU_hook)
PPU_hook(RefreshAddr);
}
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)
{
{
uint32 t=V<<8;
int x;
+
for(x=0;x<256;x++)
B2004(0x2004,X.DB=ARead[t+x](t+x));
X6502_AddCycles(512);
}
#ifdef FRAMESKIP
-int FSkip_setting=-1; // auto
int FSkip=0;
void FCEUI_FrameSkip(int x)
{
for(x=63;x>=0;x--)
((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]=(((uint32*)target)[x]&0x3f3f3f3f)|0x40404040;
+ ((uint32 *)target)[x]=(((uint32*)target)[x])|0xc0c0c0c0;
else if(PPU[1]&0xE0)
for(x=63;x>=0;x--)
- ((uint32 *)target)[x]=((uint32*)target)[x]|0xC0C0C0C0;
+ ((uint32 *)target)[x]=(((uint32*)target)[x]&0x3f3f3f3f)|0x40404040;
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);
+ ((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
}
}
-//static INLINE
+static INLINE
void Fixit2(void)
{
if(ScreenON || SpriteON)
}
}
-//static INLINE
+static INLINE
void Fixit1(void)
{
if(ScreenON || SpriteON)
}
}
-//#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))
+ 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);
}
-#endif
// ============================//
if(GameLoaded)
{
if(FCEUGameInfo.type!=GIT_NSF)
- FlushGameCheats();
+ FCEU_FlushGameCheats(0,0);
#ifdef NETWORK
if(FSettings.NetworkPlay) KillNetplay();
#endif
if(GameLoaded) CloseGame();
GameStateRestore=0;
PPU_hook=0;
- GameHBIRQHook=0;
+ GameHBIRQHook=GameHBIRQHook2=0;
GameExpSound.Fill=0;
GameExpSound.RChange=0;
if(GameExpSound.Kill)
}
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)
{
int have_movie = 0;
int fp;
- Exit=1;
+ //Exit=1;
+ LoadGameLastError = 0;
ResetGameLoaded();
strncpy(name2, name, sizeof(name2));
if(!fp)
{
FCEU_PrintError("Error opening \"%s\"!",name);
+ LoadGameLastError = 1;
return 0;
}
FCEU_fclose(fp);
*p = 0;
fp=FCEU_fopen(name2,"rb");
+ if (!fp && p - name2 > 2) p[-2] = 0;
+ fp=FCEU_fopen(name2,"rb");
if (!fp) {
printf("no ROM for movie\n");
+ LoadGameLastError = 2;
return 0;
}
have_movie = 1;
}
}
- strcpy(lastLoadedGameName, name2);
-
GetFileBase(name2);
if(iNESLoad(name2,fp))
goto endlseq;
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:
SaveStateRefresh();
if(FCEUGameInfo.type!=GIT_NSF)
{
- LoadGamePalette();
- LoadGameCheats();
+ FCEU_LoadGamePalette();
+ FCEU_LoadGameCheats(0);
}
FCEU_ResetPalette();
if (have_movie)
FCEUI_LoadMovie(name, 1);
+
+ strcpy(lastLoadedGameName, name2);
+
return(&FCEUGameInfo);
}
FSettings.FirstSLine=FSettings.UsrFirstSLine[0];
FSettings.LastSLine=FSettings.UsrLastSLine[0];
}
- printf("PAL = %i\n", PAL);
+ printf("ResetVidSys: PAL = %i\n", PAL);
SetSoundVariables();
}
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();
-#ifndef NEW_TRY
+ 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();
-#else
- X6502_Run_scanline();
-#endif
}
-#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;
of this delay.
*/
if(FCEUGameInfo.type==GIT_NSF)
- TriggerNMINSF();
+ DoNSFFrame();
else if(VBlankON)
TriggerNMI();
- X6502_Run(256+85-12);
- for(scanline=242+1;scanline<scanlines_per_frame;scanline++)
- X6502_Run(256+85);
-
+ // 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-kook);
- kook=(kook+1)&1;
- }
+ X6502_Run(85-16);
- if(ScreenON || SpriteON)
- {
- RefreshAddr=TempAddr;
- if(PPU_hook) PPU_hook(RefreshAddr&0x3fff);
+ if(ScreenON || SpriteON)
+ {
+ RefreshAddr=TempAddr;
+ if(PPU_hook) PPU_hook(RefreshAddr&0x3fff);
+ }
+ ResetRL();
+
+ X6502_Run(16-kook);
+ kook ^= 1;
}
+
if(FCEUGameInfo.type==GIT_NSF)
{
- X6502_Run((256+85)*240);
+ // run scanlines for asm core to fuction
+ for(scanline=0;scanline<240;scanline++)
+ X6502_Run(256+85);
}
else
{
deemp=PPU[1]>>5;
SetRefreshLine();
- for(scanline=0;scanline<240;scanline++)
+ 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)
}
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)
{
FCEU_PutImage();
FCEUD_Update(XBuf+8,WaveFinalMono,ssize);
}
- UpdateInput();
}
if(Exit)
{
- CloseGame();
+ //CloseGame();
break;
}
- }
+ } // for
}
#ifdef FPS
PPUGenLatch=0;
RefreshAddr=TempAddr=0;
vtoggle = 0;
+ ppudead = 2;
+ kook = 0;
}
static void PowerPPU(void)
void ResetNES(void)
{
- if(!GameLoaded || (FCEUGameInfo.type==GIT_NSF)) return;
+ if(!GameLoaded) return;
GameInterface(GI_RESETM2);
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;
GeniePower();
+#ifndef DEBUG_ASM_6502
+ FCEU_MemoryRand(RAM,0x800);
+#else
memset(RAM,0x00,0x800);
+#endif
ResetMapping();
GameInterface(GI_POWER);
PowerSound();
PowerPPU();
timestampbase=0;
+#ifdef ASM_6502
+ if (geniestage)
+ GenieSetPages(0);
+#endif
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 }
+ };
+
+