sync to FCEUX svn

This commit is contained in:
dborth 2009-09-15 08:20:48 +00:00
parent e147c806b4
commit 2c662616c5
18 changed files with 339 additions and 167 deletions

View File

@ -25,7 +25,7 @@
static uint8 reg[16], is153; static uint8 reg[16], is153;
static uint8 IRQa; static uint8 IRQa;
static uint16 IRQCount, IRQLatch; static int16 IRQCount, IRQLatch;
static uint8 *WRAM=NULL; static uint8 *WRAM=NULL;
static uint32 WRAMSIZE; static uint32 WRAMSIZE;
@ -35,7 +35,7 @@ static SFORMAT StateRegs[]=
{reg, 16, "REGS"}, {reg, 16, "REGS"},
{&IRQa, 1, "IRQA"}, {&IRQa, 1, "IRQA"},
{&IRQCount, 2, "IRQC"}, {&IRQCount, 2, "IRQC"},
{&IRQLatch, 2, "IRQL"}, {&IRQLatch, 2, "IRQL"}, // need for Famicom Jump II - Saikyou no 7 Nin (J) [!]
{0} {0}
}; };
@ -75,7 +75,7 @@ static void BandaiSync(void)
setprg16(0x8000,reg[8]); setprg16(0x8000,reg[8]);
setprg16(0xC000,~0); setprg16(0xC000,~0);
} }
switch(reg[9]) switch(reg[9]&3)
{ {
case 0: setmirror(MI_V); break; case 0: setmirror(MI_V); break;
case 1: setmirror(MI_H); break; case 1: setmirror(MI_H); break;

View File

@ -115,7 +115,7 @@ static void mmc5_PPUWrite(uint32 A, uint8 V) {
} }
} }
uint8 mmc5_PPURead(uint32 A) { uint8 FASTCALL mmc5_PPURead(uint32 A) {
if(A<0x2000) if(A<0x2000)
{ {
if(ppuphase == PPUPHASE_BG) if(ppuphase == PPUPHASE_BG)

View File

@ -99,6 +99,8 @@ void ResetCartMapping(void)
{ {
int x; int x;
PPU_ResetHooks();
for(x=0;x<32;x++) for(x=0;x<32;x++)
{ {
Page[x]=nothing-x*2048; Page[x]=nothing-x*2048;

View File

@ -16,9 +16,11 @@ char *FCEUI_GetAboutString() {
const char *aboutTemplate = const char *aboutTemplate =
FCEU_NAME_AND_VERSION "\n\n\ FCEU_NAME_AND_VERSION "\n\n\
Authors:\n\ Authors:\n\
zeromus, adelikat, CaH4e3\n\n\ zeromus, adelikat,\n\n\
Contributers:\n\ Contributers:\n\
Acmlm,DWEdit,QFox\n\ Acmlm,CaH4e3\n\
DWEdit,QFox\n\
qeed,Shinydoofy,ugetab\n\
\n\ \n\
FCEUX 2.0\n\ FCEUX 2.0\n\
mz, nitsujrehtona, Lukas Sabota,\n\ mz, nitsujrehtona, Lukas Sabota,\n\

View File

@ -624,10 +624,22 @@ void DebugCycle() {
else else
vblankScanLines = 0; vblankScanLines = 0;
if (GameInfo->type==GIT_NSF)
{
if ((_PC >= 0x3801) && (_PC <= 0x3824)) return;
}
if (numWPs || dbgstate.step || dbgstate.runline || dbgstate.stepout || watchpoint[64].flags || dbgstate.badopbreak) if (numWPs || dbgstate.step || dbgstate.runline || dbgstate.stepout || watchpoint[64].flags || dbgstate.badopbreak)
breakpoint(); breakpoint();
if(debug_loggingCD) LogCDData(); if(debug_loggingCD) LogCDData();
//mbg 6/30/06 - this was commented out when i got here. i dont understand it anyway //mbg 6/30/06 - this was commented out when i got here. i dont understand it anyway
//if(logging || (hMemView && (EditingMode == 2))) LogInstruction(); //if(logging || (hMemView && (EditingMode == 2))) LogInstruction();
FCEUD_TraceInstruction();
//This needs to be windows only or else the linux build system will fail since logging is declared in a
//windows source file
#ifdef WIN32
extern volatile int logging; //UGETAB: This is required to be an extern, because the info isn't set here
if(logging) FCEUD_TraceInstruction();
#endif
} }

View File

@ -361,7 +361,7 @@ void ResetGameLoaded(void)
int UNIFLoad(const char *name, FCEUFILE *fp); int UNIFLoad(const char *name, FCEUFILE *fp);
int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode); int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode);
int FDSLoad(const char *name, FCEUFILE *fp); int FDSLoad(const char *name, FCEUFILE *fp);
int NSFLoad(FCEUFILE *fp); int NSFLoad(const char *name, FCEUFILE *fp);
//char lastLoadedGameName [2048] = {0,}; // hack for movie WRAM clearing on record from poweron //char lastLoadedGameName [2048] = {0,}; // hack for movie WRAM clearing on record from poweron
@ -424,7 +424,7 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode)
goto endlseq;*/ goto endlseq;*/
if(iNESLoad(name,fp,OverwriteVidMode)) if(iNESLoad(name,fp,OverwriteVidMode))
goto endlseq; goto endlseq;
if(NSFLoad(fp)) if(NSFLoad(name,fp))
goto endlseq; goto endlseq;
if(UNIFLoad(name,fp)) if(UNIFLoad(name,fp))
goto endlseq; goto endlseq;

View File

@ -35,6 +35,7 @@
#include "cart.h" #include "cart.h"
#include "netplay.h" #include "netplay.h"
#include "driver.h" #include "driver.h"
#include "movie.h"
// TODO: Add code to put a delay in between the time a disk is inserted // TODO: Add code to put a delay in between the time a disk is inserted
// and the when it can be successfully read/written to. This should // and the when it can be successfully read/written to. This should
@ -68,7 +69,11 @@ static int32 IRQLatch,IRQCount;
static uint8 IRQa; static uint8 IRQa;
static void FDSClose(void); static void FDSClose(void);
#ifdef GEKKO
uint8 FDSBIOS[8192]; uint8 FDSBIOS[8192];
#else
static uint8 FDSBIOS[8192];
#endif
/* Original disk data backup, to help in creating save states. */ /* Original disk data backup, to help in creating save states. */
static uint8 *diskdatao[8]={0,0,0,0,0,0,0,0}; static uint8 *diskdatao[8]={0,0,0,0,0,0,0,0};
@ -147,6 +152,11 @@ static void FDSInit(void)
void FCEU_FDSInsert(void) void FCEU_FDSInsert(void)
{ {
if(FCEUI_EmulationPaused()) EmulationPaused |= 2;
if(FCEUMOV_Mode(MOVIEMODE_RECORD))
FCEUMOV_AddCommand(FCEUNPCMD_FDSINSERT);
if(TotalSides==0) if(TotalSides==0)
{ {
FCEU_DispMessage("Not FDS; can't eject disk."); FCEU_DispMessage("Not FDS; can't eject disk.");
@ -171,6 +181,11 @@ InDisk=255;
*/ */
void FCEU_FDSSelect(void) void FCEU_FDSSelect(void)
{ {
if(FCEUI_EmulationPaused()) EmulationPaused |= 2;
if(FCEUMOV_Mode(MOVIEMODE_RECORD))
FCEUMOV_AddCommand(FCEUNPCMD_FDSSELECT);
if(TotalSides==0) if(TotalSides==0)
{ {
FCEU_DispMessage("Not FDS; can't select disk."); FCEU_DispMessage("Not FDS; can't select disk.");

View File

@ -36,7 +36,11 @@
#include "utils/endian.h" #include "utils/endian.h"
#include "utils/memory.h" #include "utils/memory.h"
#include "utils/md5.h" #include "utils/md5.h"
#ifdef GEKKO
#include "unzip.h" #include "unzip.h"
#else
#include "utils/unzip.h"
#endif
#include "driver.h" #include "driver.h"
#include "types.h" #include "types.h"
#include "fceu.h" #include "fceu.h"
@ -603,7 +607,7 @@ std::string FCEU_MakeFName(int type, int id1, const char *cd1)
if(odirs[FCEUIOD_MOVIES]) if(odirs[FCEUIOD_MOVIES])
sprintf(ret,"%s"PSS"%s-%d.fm2",odirs[FCEUIOD_MOVIES],FileBase, id1); sprintf(ret,"%s"PSS"%s-%d.fm2",odirs[FCEUIOD_MOVIES],FileBase, id1);
else else
sprintf(ret,"%s"PSS"movie"PSS"%s-%d.fm2",BaseDirectory.c_str(),FileBase, id1); sprintf(ret,"%s"PSS"movies"PSS"%s-%d.fm2",BaseDirectory.c_str(),FileBase, id1);
id1++; id1++;
} while (stat(ret, &fileInfo) == 0); } while (stat(ret, &fileInfo) == 0);
break; break;

View File

@ -14,11 +14,13 @@
#include "palette.h" #include "palette.h"
#include "input.h" #include "input.h"
#include "fceu.h" #include "fceu.h"
#include "netplay.h"
#include "driver.h" #include "driver.h"
#include "state.h" #include "state.h"
#include "file.h" #include "file.h"
#include "video.h" #include "video.h"
#include "movie.h" #include "movie.h"
#include "fds.h"
#ifdef _S9XLUA_H #ifdef _S9XLUA_H
#include "fceulua.h" #include "fceulua.h"
#endif #endif
@ -980,6 +982,12 @@ void FCEUMOV_AddInputState()
if(mr->command_reset()) if(mr->command_reset())
ResetNES(); ResetNES();
if(mr->command_fds_insert())
FCEU_FDSInsert();
if(mr->command_fds_select())
FCEU_FDSSelect();
joyports[0].load(mr); joyports[0].load(mr);
joyports[1].load(mr); joyports[1].load(mr);
} }
@ -1033,6 +1041,11 @@ void FCEUMOV_AddCommand(int cmd)
//NOTE: EMOVIECMD matches FCEUNPCMD_RESET and FCEUNPCMD_POWER //NOTE: EMOVIECMD matches FCEUNPCMD_RESET and FCEUNPCMD_POWER
//we are lucky (well, I planned it that way) //we are lucky (well, I planned it that way)
switch(cmd) {
case FCEUNPCMD_FDSINSERT: cmd = MOVIECMD_FDS_INSERT; break;
case FCEUNPCMD_FDSSELECT: cmd = MOVIECMD_FDS_SELECT; break;
}
_currCommand |= cmd; _currCommand |= cmd;
#endif #endif
} }

View File

@ -65,6 +65,8 @@ enum EMOVIECMD
{ {
MOVIECMD_RESET = 1, MOVIECMD_RESET = 1,
MOVIECMD_POWER = 2, MOVIECMD_POWER = 2,
MOVIECMD_FDS_INSERT = 4,
MOVIECMD_FDS_SELECT = 8
}; };
EMOVIEMODE FCEUMOV_Mode(); EMOVIEMODE FCEUMOV_Mode();
@ -104,6 +106,8 @@ public:
uint8 commands; uint8 commands;
bool command_reset() { return (commands&MOVIECMD_RESET)!=0; } bool command_reset() { return (commands&MOVIECMD_RESET)!=0; }
bool command_power() { return (commands&MOVIECMD_POWER)!=0; } bool command_power() { return (commands&MOVIECMD_POWER)!=0; }
bool command_fds_insert() { return (commands&MOVIECMD_FDS_INSERT)!=0; }
bool command_fds_select() { return (commands&MOVIECMD_FDS_SELECT)!=0; }
void toggleBit(int joy, int bit) void toggleBit(int joy, int bit)
{ {

View File

@ -109,15 +109,19 @@ static DECLFR(NSFROMRead)
static int doreset=0; static int doreset=0;
static int NSFNMIFlags; static int NSFNMIFlags;
static uint8 *NSFDATA=0; uint8 *NSFDATA=0;
static int NSFMaxBank; int NSFMaxBank;
static int NSFSize; static int NSFSize;
static uint8 BSon; static uint8 BSon;
static uint8 BankCounter;
static uint16 PlayAddr; static uint16 PlayAddr;
static uint16 InitAddr; static uint16 InitAddr;
static uint16 LoadAddr; static uint16 LoadAddr;
extern char LoadedRomFName[2048];
NSF_HEADER NSFHeader; //mbg merge 6/29/06 - needs to be global NSF_HEADER NSFHeader; //mbg merge 6/29/06 - needs to be global
void NSFMMC5_Close(void); void NSFMMC5_Close(void);
@ -160,7 +164,7 @@ static INLINE void BANKSET(uint32 A, uint32 bank)
setprg4(A,bank); setprg4(A,bank);
} }
int NSFLoad(FCEUFILE *fp) int NSFLoad(const char *name, FCEUFILE *fp)
{ {
int x; int x;
#ifndef GEKKO #ifndef GEKKO
@ -188,7 +192,7 @@ int NSFLoad(FCEUFILE *fp)
NSFSize=FCEU_fgetsize(fp)-0x80; NSFSize=FCEU_fgetsize(fp)-0x80;
NSFMaxBank=((NSFSize+(LoadAddr&0xfff)+4095)/4096); NSFMaxBank=((NSFSize+(LoadAddr&0xfff)+4095)/4096);
NSFMaxBank=uppow2(NSFMaxBank); NSFMaxBank=PRGsize[0]=uppow2(NSFMaxBank);
if(!(NSFDATA=(uint8 *)FCEU_malloc(NSFMaxBank*4096))) if(!(NSFDATA=(uint8 *)FCEU_malloc(NSFMaxBank*4096)))
return 0; return 0;
@ -200,6 +204,30 @@ int NSFLoad(FCEUFILE *fp)
NSFMaxBank--; NSFMaxBank--;
BSon=0; BSon=0;
for(x=0;x<8;x++)
{
BSon|=NSFHeader.BankSwitch[x];
}
if(BSon==0)
{
BankCounter=0x00;
if ((NSFHeader.LoadAddressHigh & 0x70) >= 0x70)
{
//Ice Climber, and other F000 base address tunes need this
BSon=0xFF;
}
else {
for(x=(NSFHeader.LoadAddressHigh & 0x70) / 0x10;x<8;x++)
{
NSFHeader.BankSwitch[x]=BankCounter;
BankCounter+=0x01;
}
BSon=0;
}
}
for(x=0;x<8;x++) for(x=0;x<8;x++)
BSon|=NSFHeader.BankSwitch[x]; BSon|=NSFHeader.BankSwitch[x];
@ -226,6 +254,8 @@ int NSFLoad(FCEUFILE *fp)
GameInterface=NSFGI; GameInterface=NSFGI;
strcpy(LoadedRomFName,name);
FCEU_printf("NSF Loaded. File information:\n\n"); FCEU_printf("NSF Loaded. File information:\n\n");
FCEU_printf(" Name: %s\n Artist: %s\n Copyright: %s\n\n",NSFHeader.SongName,NSFHeader.Artist,NSFHeader.Copyright); FCEU_printf(" Name: %s\n Artist: %s\n Copyright: %s\n\n",NSFHeader.SongName,NSFHeader.Artist,NSFHeader.Copyright);
if(NSFHeader.SoundChip) if(NSFHeader.SoundChip)

View File

@ -46,6 +46,8 @@ typedef struct {
void NSF_init(void); void NSF_init(void);
void DrawNSF(uint8 *XBuf); void DrawNSF(uint8 *XBuf);
extern NSF_HEADER NSFHeader; //mbg merge 6/29/06 extern NSF_HEADER NSFHeader; //mbg merge 6/29/06
extern uint8 *NSFDATA;
extern int NSFMaxBank;
void NSFDealloc(void); void NSFDealloc(void);
void NSFDodo(void); void NSFDodo(void);
void DoNSFFrame(void); void DoNSFFrame(void);

View File

@ -40,6 +40,7 @@
#include "input.h" #include "input.h"
#include "driver.h" #include "driver.h"
#define VBlankON (PPU[0]&0x80) //Generate VBlank NMI #define VBlankON (PPU[0]&0x80) //Generate VBlank NMI
#define Sprite16 (PPU[0]&0x20) //Sprites 8x16/8x8 #define Sprite16 (PPU[0]&0x20) //Sprites 8x16/8x8
#define BGAdrHI (PPU[0]&0x10) //BG pattern adr $0000/$1000 #define BGAdrHI (PPU[0]&0x10) //BG pattern adr $0000/$1000
@ -68,7 +69,6 @@ static uint32 ppulut1[256];
static uint32 ppulut2[256]; static uint32 ppulut2[256];
static uint32 ppulut3[128]; static uint32 ppulut3[128];
PPUPHASE ppuphase;
int test = 0; int test = 0;
template<typename T, int BITS> template<typename T, int BITS>
@ -102,42 +102,78 @@ BITREVLUT<uint8,8> bitrevlut;
struct PPUSTATUS struct PPUSTATUS
{ {
int sl; int32 sl;
int cycle, end_cycle; int32 cycle, end_cycle;
}; };
struct SPRITE_READ struct SPRITE_READ
{ {
int num; int32 num;
int count; int32 count;
int fetch; int32 fetch;
int found; int32 found;
int found_pos[8]; int32 found_pos[8];
int ret; int32 ret;
int last; int32 last;
int mode; int32 mode;
void reset() {
num = count = fetch = found = ret = last = mode = 0;
found_pos[0] = found_pos[1] = found_pos[2] = found_pos[3] = 0;
found_pos[4] = found_pos[5] = found_pos[6] = found_pos[7] = 0;
}
void start_scanline()
{
num = 1;
found = 0;
fetch = 1;
count = 0;
last = 64;
mode = 0;
found_pos[0] = found_pos[1] = found_pos[2] = found_pos[3] = 0;
found_pos[4] = found_pos[5] = found_pos[6] = found_pos[7] = 0;
}
}; };
struct SPRITE_READ spr_read = { 0 };
//doesn't need to be savestated as it is just a reflection of the current position in the ppu loop
PPUPHASE ppuphase;
//this needs to be savestated since a game may be trying to read from this across vblanks
SPRITE_READ spr_read;
//definitely needs to be savestated
uint8 idleSynch = 1;
//uses the internal counters concept at http://nesdev.icequake.net/PPU%20addressing.txt //uses the internal counters concept at http://nesdev.icequake.net/PPU%20addressing.txt
struct PPUREGS { struct PPUREGS {
//normal clocked regs. as the game can interfere with these at any time, they need to be savestated
uint32 fv;//3 uint32 fv;//3
uint32 v;//1 uint32 v;//1
uint32 h;//1 uint32 h;//1
uint32 vt;//5 uint32 vt;//5
uint32 ht;//5 uint32 ht;//5
uint32 fh;//3
uint32 s;//1
uint32 par;//8
uint32 ar;//2
//temp unlatched regs (need savestating, can be written to at any time)
uint32 _fv, _v, _h, _vt, _ht; uint32 _fv, _v, _h, _vt, _ht;
struct PPUSTATUS status; //other regs that need savestating
uint32 fh;//3 (horz scroll)
uint32 s;//1 ($2000 bit 4: "Background pattern table address (0: $0000; 1: $1000)")
PPUREGS() //other regs that don't need saving
: fv(0), v(0), h(0), vt(0), ht(0), fh(0), s(0), par(0), ar(0) uint32 par;//8 (sort of a hack, just stored in here, but not managed by this system)
, _fv(0), _v(0), _h(0), _vt(0), _ht(0)
{ status.cycle = 0; status.end_cycle = 341; //cached state data. these are always reset at the beginning of a frame and don't need saving
//but just to be safe, we're gonna save it
PPUSTATUS status;
void reset()
{
fv = v = h = vt = ht = 0;
fh = par = s = 0;
_fv = _v = _h = _vt = _ht = 0;
status.cycle = 0;
status.end_cycle = 341;
status.sl = 241; status.sl = 241;
} }
@ -365,6 +401,8 @@ int FCEUPPU_GetAttr(int ntnum, int xt, int yt) {
inline void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) { inline void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) {
uint32 tmp = A; uint32 tmp = A;
if(PPU_hook) PPU_hook(A);
if(tmp<0x2000) if(tmp<0x2000)
{ {
if(PPUCHRRAM&(1<<(tmp>>10))) if(PPUCHRRAM&(1<<(tmp>>10)))
@ -390,9 +428,11 @@ inline void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) {
} }
} }
uint8 FFCEUX_PPURead_Default(uint32 A) { uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A) {
uint32 tmp = A; uint32 tmp = A;
if(PPU_hook) PPU_hook(A);
if(tmp<0x2000) if(tmp<0x2000)
{ {
return VPage[tmp>>10][tmp]; return VPage[tmp>>10][tmp];
@ -421,15 +461,10 @@ uint8 FFCEUX_PPURead_Default(uint32 A) {
} }
uint8 (*FFCEUX_PPURead)(uint32 A) = 0; uint8 (FASTCALL *FFCEUX_PPURead)(uint32 A) = 0;
void (*FFCEUX_PPUWrite)(uint32 A, uint8 V) = 0; void (*FFCEUX_PPUWrite)(uint32 A, uint8 V) = 0;
#define CALL_PPUREAD(A) (FFCEUX_PPURead?FFCEUX_PPURead(A):(\ #define CALL_PPUREAD(A) (FFCEUX_PPURead(A))
((A)<0x2000)? \
VPage[(A)>>10][(A)] \
: vnapage[((A)>>10)&0x3][(A)&0x3FF] \
))
#define CALL_PPUWRITE(A,V) (FFCEUX_PPUWrite?FFCEUX_PPUWrite(A,V):FFCEUX_PPUWrite_Default(A,V)) #define CALL_PPUWRITE(A,V) (FFCEUX_PPUWrite?FFCEUX_PPUWrite(A,V):FFCEUX_PPUWrite_Default(A,V))
@ -1777,6 +1812,11 @@ void FCEUPPU_Init(void)
makeppulut(); makeppulut();
} }
void PPU_ResetHooks()
{
FFCEUX_PPURead = FFCEUX_PPURead_Default;
}
void FCEUPPU_Reset(void) void FCEUPPU_Reset(void)
{ {
VRAMBuffer=PPU[0]=PPU[1]=PPU_status=PPU[3]=0; VRAMBuffer=PPU[0]=PPU[1]=PPU_status=PPU[3]=0;
@ -1786,7 +1826,11 @@ void FCEUPPU_Reset(void)
vtoggle = 0; vtoggle = 0;
ppudead = 2; ppudead = 2;
kook = 0; kook = 0;
idleSynch = 1;
// XOffset=0; // XOffset=0;
ppur.reset();
spr_read.reset();
} }
void FCEUPPU_Power(void) void FCEUPPU_Power(void)
@ -1823,7 +1867,7 @@ void FCEUPPU_Power(void)
int FCEUPPU_Loop(int skip) int FCEUPPU_Loop(int skip)
{ {
if(newppu) { if((newppu) && (GameInfo->type!=GIT_NSF)) {
int FCEUX_PPU_Loop(int skip); int FCEUX_PPU_Loop(int skip);
return FCEUX_PPU_Loop(skip); return FCEUX_PPU_Loop(skip);
} }
@ -1988,6 +2032,41 @@ SFORMAT FCEUPPU_STATEINFO[]={
{ 0 } { 0 }
}; };
SFORMAT FCEU_NEWPPU_STATEINFO[] = {
{ &idleSynch, 1, "IDLS" },
{ &spr_read.num, 4|FCEUSTATE_RLSB, "SR_0" },
{ &spr_read.count, 4|FCEUSTATE_RLSB, "SR_1" },
{ &spr_read.fetch, 4|FCEUSTATE_RLSB, "SR_2" },
{ &spr_read.found, 4|FCEUSTATE_RLSB, "SR_3" },
{ &spr_read.found_pos[0], 4|FCEUSTATE_RLSB, "SRx0" },
{ &spr_read.found_pos[0], 4|FCEUSTATE_RLSB, "SRx1" },
{ &spr_read.found_pos[0], 4|FCEUSTATE_RLSB, "SRx2" },
{ &spr_read.found_pos[0], 4|FCEUSTATE_RLSB, "SRx3" },
{ &spr_read.found_pos[0], 4|FCEUSTATE_RLSB, "SRx4" },
{ &spr_read.found_pos[0], 4|FCEUSTATE_RLSB, "SRx5" },
{ &spr_read.found_pos[0], 4|FCEUSTATE_RLSB, "SRx6" },
{ &spr_read.found_pos[0], 4|FCEUSTATE_RLSB, "SRx7" },
{ &spr_read.ret, 4|FCEUSTATE_RLSB, "SR_4" },
{ &spr_read.last, 4|FCEUSTATE_RLSB, "SR_5" },
{ &spr_read.mode, 4|FCEUSTATE_RLSB, "SR_6" },
{ &ppur.fv, 4|FCEUSTATE_RLSB, "PFVx" },
{ &ppur.v, 4|FCEUSTATE_RLSB, "PVxx" },
{ &ppur.h, 4|FCEUSTATE_RLSB, "PHxx" },
{ &ppur.vt, 4|FCEUSTATE_RLSB, "PVTx" },
{ &ppur.ht, 4|FCEUSTATE_RLSB, "PHTx" },
{ &ppur._fv, 4|FCEUSTATE_RLSB, "P_FV" },
{ &ppur._v, 4|FCEUSTATE_RLSB, "P_Vx" },
{ &ppur._h, 4|FCEUSTATE_RLSB, "P_Hx" },
{ &ppur._vt, 4|FCEUSTATE_RLSB, "P_VT" },
{ &ppur._ht, 4|FCEUSTATE_RLSB, "P_HT" },
{ &ppur.fh, 4|FCEUSTATE_RLSB, "PFHx" },
{ &ppur.s, 4|FCEUSTATE_RLSB, "PSxx" },
{ &ppur.status.sl, 4|FCEUSTATE_RLSB, "PST0" },
{ &ppur.status.cycle, 4|FCEUSTATE_RLSB, "PST1" },
{ &ppur.status.end_cycle, 4|FCEUSTATE_RLSB, "PST2" },
{ 0 }
};
void FCEUPPU_SaveState(void) void FCEUPPU_SaveState(void)
{ {
TempAddrT=TempAddr; TempAddrT=TempAddr;
@ -2000,13 +2079,14 @@ int pputime=0;
int totpputime=0; int totpputime=0;
const int kLineTime=341; const int kLineTime=341;
const int kFetchTime=2; const int kFetchTime=2;
int idleSynch = 1;
void runppu(int x) { void runppu(int x) {
//pputime+=x; //pputime+=x;
//if(cputodo<200) return; //if(cputodo<200) return;
ppur.status.cycle = (ppur.status.cycle + x) % ppur.status.cycle = (ppur.status.cycle + x) %
ppur.status.end_cycle; ppur.status.end_cycle;
X6502_Run(x); X6502_Run(x);
//pputime -= cputodo<<2; //pputime -= cputodo<<2;
} }
@ -2016,7 +2096,7 @@ struct BGData {
struct Record { struct Record {
uint8 nt, at, pt[2]; uint8 nt, at, pt[2];
void Read() { INLINE void Read() {
RefreshAddr = ppur.get_ntread(); RefreshAddr = ppur.get_ntread();
nt = CALL_PPUREAD(RefreshAddr); nt = CALL_PPUREAD(RefreshAddr);
runppu(kFetchTime); runppu(kFetchTime);
@ -2056,6 +2136,7 @@ struct BGData {
int framectr=0; int framectr=0;
int FCEUX_PPU_Loop(int skip) { int FCEUX_PPU_Loop(int skip) {
//262 scanlines //262 scanlines
if (ppudead) if (ppudead)
{ {
@ -2071,7 +2152,7 @@ int FCEUX_PPU_Loop(int skip) {
runppu(20*kLineTime); runppu(20*kLineTime);
ppur.status.sl = 0; ppur.status.sl = 0;
runppu(242*kLineTime); runppu(242*kLineTime);
ppudead = 0; --ppudead;
goto finish; goto finish;
} }
@ -2108,26 +2189,20 @@ int FCEUX_PPU_Loop(int skip) {
//if(PPUON) //if(PPUON)
// ppur.install_latches(); // ppur.install_latches();
uint8 oams[2][64][7]; static uint8 oams[2][64][8]; //[7] turned to [8] for faster indexing
int oamcounts[2]={0,0}; static int oamcounts[2]={0,0};
int oamslot=0; static int oamslot=0;
int oamcount; static int oamcount;
//capture the initial xscroll //capture the initial xscroll
//int xscroll = ppur.fh; //int xscroll = ppur.fh;
//render 241 scanlines (including 1 dummy at beginning) //render 241 scanlines (including 1 dummy at beginning)
for(int sl=0;sl<241;sl++) { for(int sl=0;sl<241;sl++) {
spr_read.num = 1; spr_read.start_scanline();
spr_read.found = 0;
spr_read.fetch = 1;
spr_read.count = 0;
spr_read.last = 64;
spr_read.mode = 0;
memset(spr_read.found_pos, 0, sizeof(spr_read.found_pos));
ppur.status.sl = sl; ppur.status.sl = sl;
int yp = sl-1; const int yp = sl-1;
ppuphase = PPUPHASE_BG; ppuphase = PPUPHASE_BG;
if(sl != 0) { if(sl != 0) {
@ -2139,8 +2214,8 @@ int FCEUX_PPU_Loop(int skip) {
//twiddle the oam buffers //twiddle the oam buffers
int scanslot = oamslot^1; const int scanslot = oamslot^1;
int renderslot = oamslot; const int renderslot = oamslot;
oamslot ^= 1; oamslot ^= 1;
oamcount = oamcounts[renderslot]; oamcount = oamcounts[renderslot];
@ -2151,25 +2226,26 @@ int FCEUX_PPU_Loop(int skip) {
for(int xt=0;xt<32;xt++) { for(int xt=0;xt<32;xt++) {
bgdata.main[xt+2].Read(); bgdata.main[xt+2].Read();
//ok, we're also going to draw here. //ok, we're also going to draw here.
//unless we're on the first dummy scanline //unless we're on the first dummy scanline
if(sl != 0) { if(sl != 0) {
int xstart = xt<<3; int xstart = xt<<3;
oamcount = oamcounts[renderslot]; oamcount = oamcounts[renderslot];
uint8 *target=XBuf+(yp<<8)+xstart; uint8 * const target=XBuf+(yp<<8)+xstart;
uint8 *ptr = target; uint8 *ptr = target;
int rasterpos = xstart; int rasterpos = xstart;
//check all the conditions that can cause things to render in these 8px //check all the conditions that can cause things to render in these 8px
bool renderspritenow = SpriteON && rendersprites && (xt>0 || SpriteLeft8); const bool renderspritenow = SpriteON && rendersprites && (xt>0 || SpriteLeft8);
bool renderbgnow = ScreenON && renderbg && (xt>0 || BGLeft8); const bool renderbgnow = ScreenON && renderbg && (xt>0 || BGLeft8);
for(int xp=0;xp<8;xp++,rasterpos++) { for(int xp=0;xp<8;xp++,rasterpos++) {
//bg pos is different from raster pos due to its offsetability. //bg pos is different from raster pos due to its offsetability.
//so adjust for that here //so adjust for that here
int bgpos = rasterpos + ppur.fh; const int bgpos = rasterpos + ppur.fh;
int bgpx = bgpos&7; const int bgpx = bgpos&7;
int bgtile = bgpos>>3; const int bgtile = bgpos>>3;
uint8 pixel=0, pixelcolor; uint8 pixel=0, pixelcolor;
@ -2236,7 +2312,7 @@ int FCEUX_PPU_Loop(int skip) {
//look for sprites (was supposed to run concurrent with bg rendering) //look for sprites (was supposed to run concurrent with bg rendering)
oamcounts[scanslot] = 0; oamcounts[scanslot] = 0;
oamcount=0; oamcount=0;
int spriteHeight = Sprite16?16:8; const int spriteHeight = Sprite16?16:8;
for(int i=0;i<64;i++) { for(int i=0;i<64;i++) {
uint8* spr = SPRAM+i*4; uint8* spr = SPRAM+i*4;
if(yp >= spr[0] && yp < spr[0]+spriteHeight) { if(yp >= spr[0] && yp < spr[0]+spriteHeight) {
@ -2289,9 +2365,9 @@ int FCEUX_PPU_Loop(int skip) {
//this is how we support the no 8 sprite limit feature. //this is how we support the no 8 sprite limit feature.
//not that at some point we may need a virtual CALL_PPUREAD which just peeks and doesnt increment any counters //not that at some point we may need a virtual CALL_PPUREAD which just peeks and doesnt increment any counters
//this could be handy for the debugging tools also //this could be handy for the debugging tools also
bool realSprite = (s<8); const bool realSprite = (s<8);
uint8* oam = oams[scanslot][s]; uint8* const oam = oams[scanslot][s];
uint32 line = yp - oam[0]; uint32 line = yp - oam[0];
if(oam[2]&0x80) //vflip if(oam[2]&0x80) //vflip
line = spriteHeight-line-1; line = spriteHeight-line-1;

View File

@ -18,8 +18,17 @@ void FCEUPPU_SaveState(void);
void FCEUPPU_LoadState(int version); void FCEUPPU_LoadState(int version);
uint8* FCEUPPU_GetCHR(uint32 vadr, uint32 refreshaddr); uint8* FCEUPPU_GetCHR(uint32 vadr, uint32 refreshaddr);
extern uint8 (*FFCEUX_PPURead)(uint32 A); #ifdef _MSC_VER
#define FASTCALL __fastcall
#else
#define FASTCALL
#endif
void PPU_ResetHooks();
extern uint8 (FASTCALL *FFCEUX_PPURead)(uint32 A);
extern void (*FFCEUX_PPUWrite)(uint32 A, uint8 V); extern void (*FFCEUX_PPUWrite)(uint32 A, uint8 V);
extern uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A);
void FFCEUX_PPUWrite_Default(uint32 A, uint8 V);
extern int scanline; extern int scanline;
extern uint8 PPU[4]; extern uint8 PPU[4];

View File

@ -75,6 +75,7 @@ static int SFEXINDEX;
extern SFORMAT FCEUPPU_STATEINFO[]; extern SFORMAT FCEUPPU_STATEINFO[];
extern SFORMAT FCEU_NEWPPU_STATEINFO[];
extern SFORMAT FCEUSND_STATEINFO[]; extern SFORMAT FCEUSND_STATEINFO[];
extern SFORMAT FCEUCTRL_STATEINFO[]; extern SFORMAT FCEUCTRL_STATEINFO[];
extern SFORMAT FCEUMOV_STATEINFO[]; extern SFORMAT FCEUMOV_STATEINFO[];
@ -248,6 +249,7 @@ static bool ReadStateChunks(std::istream* is, int32 totalsize)
{ {
case 1:if(!ReadStateChunk(is,SFCPU,size)) ret=false;break; case 1:if(!ReadStateChunk(is,SFCPU,size)) ret=false;break;
case 3:if(!ReadStateChunk(is,FCEUPPU_STATEINFO,size)) ret=false;break; case 3:if(!ReadStateChunk(is,FCEUPPU_STATEINFO,size)) ret=false;break;
case 31:if(!ReadStateChunk(is,FCEU_NEWPPU_STATEINFO,size)) ret=false;break;
case 4:if(!ReadStateChunk(is,FCEUCTRL_STATEINFO,size)) ret=false;break; case 4:if(!ReadStateChunk(is,FCEUCTRL_STATEINFO,size)) ret=false;break;
case 7: case 7:
if(!FCEUMOV_ReadState(is,size)) { if(!FCEUMOV_ReadState(is,size)) {
@ -355,6 +357,7 @@ bool FCEUSS_SaveMS(std::ostream* outstream, int compressionLevel)
totalsize=WriteStateChunk(os,1,SFCPU); totalsize=WriteStateChunk(os,1,SFCPU);
totalsize+=WriteStateChunk(os,2,SFCPUC); totalsize+=WriteStateChunk(os,2,SFCPUC);
totalsize+=WriteStateChunk(os,3,FCEUPPU_STATEINFO); totalsize+=WriteStateChunk(os,3,FCEUPPU_STATEINFO);
totalsize+=WriteStateChunk(os,31,FCEU_NEWPPU_STATEINFO);
totalsize+=WriteStateChunk(os,4,FCEUCTRL_STATEINFO); totalsize+=WriteStateChunk(os,4,FCEUCTRL_STATEINFO);
totalsize+=WriteStateChunk(os,5,FCEUSND_STATEINFO); totalsize+=WriteStateChunk(os,5,FCEUSND_STATEINFO);
if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD)) if(FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD))

View File

@ -23,8 +23,8 @@
#define __FCEU_TYPES #define __FCEU_TYPES
#define FCEU_NAME "FCEUX" #define FCEU_NAME "FCEUX"
#define FCEU_VERSION_STRING "2.1.1-interim" #define FCEU_VERSION_STRING "2.1.2-interim"
#define FCEU_VERSION_NUMERIC 20100 #define FCEU_VERSION_NUMERIC 21020
#define FCEU_NAME_AND_VERSION FCEU_NAME " " FCEU_VERSION_STRING #define FCEU_NAME_AND_VERSION FCEU_NAME " " FCEU_VERSION_STRING
///causes the code fragment argument to be compiled in if the build includes debugging ///causes the code fragment argument to be compiled in if the build includes debugging

View File

@ -81,7 +81,7 @@ int GCMemROM(int method, int size)
delete fceumem; delete fceumem;
fceumem = new memorystream((char *) nesrom, size); fceumem = new memorystream((char *) nesrom, size);
fceufp->stream = fceumem; fceufp->stream = fceumem;
romLoaded = NSFLoad(fceufp); romLoaded = NSFLoad(romFilename, fceufp);
} }
if(!romLoaded) if(!romLoaded)

View File

@ -40,7 +40,7 @@ int AddCheatEntry(char *name, uint32 addr, uint8 val, int compare, int status, i
extern int FDSLoad(const char *name, FCEUFILE *fp); extern int FDSLoad(const char *name, FCEUFILE *fp);
extern int iNESLoad(const char *name, FCEUFILE *fp, int o); extern int iNESLoad(const char *name, FCEUFILE *fp, int o);
extern int UNIFLoad(const char *name, FCEUFILE *fp); extern int UNIFLoad(const char *name, FCEUFILE *fp);
extern int NSFLoad(FCEUFILE *fp); extern int NSFLoad(const char *name, FCEUFILE *fp);
extern uint8 FDSBIOS[8192]; extern uint8 FDSBIOS[8192];
extern uint8 *GENIEROM; extern uint8 *GENIEROM;
extern FCEUGI *GameInfo; extern FCEUGI *GameInfo;