diff --git a/source/fceultra/boards/mmc5.cpp b/source/fceultra/boards/mmc5.cpp index 771be44..125e562 100644 --- a/source/fceultra/boards/mmc5.cpp +++ b/source/fceultra/boards/mmc5.cpp @@ -50,7 +50,7 @@ static INLINE void MMC5BGVROM_BANK8(uint32 V) {if(CHRptr[0]){V&=CHRmask8[0];MMC5 static uint8 PRGBanks[4]; static uint8 WRAMPage; -static uint8 CHRBanksA[8], CHRBanksB[4]; +static uint16 CHRBanksA[8], CHRBanksB[4]; static uint8 WRAMMaskEnable[2]; uint8 mmc5ABMode; /* A=0, B=1 */ @@ -352,7 +352,8 @@ static DECLFW(Mapper5_write) if(A>=0x5120&&A<=0x5127) { mmc5ABMode = 0; - CHRBanksA[A&7]=V; + CHRBanksA[A&7]=V | ((MMC50x5130&0x3)<<8); //if we had a test case for this then we could test this, but it hasnt been verified + //CHRBanksA[A&7]=V; MMC5CHRA(); } else switch(A) @@ -416,6 +417,8 @@ static DECLFW(Mapper5_write) } ATFill=V; break; + case 0x5130: MMC50x5130=V;break; + case 0x5200: MMC5HackSPMode=V;break; case 0x5201: MMC5HackSPScroll=(V>>3)&0x1F;break; case 0x5202: MMC5HackSPPage=V&0x3F;break; @@ -804,8 +807,8 @@ static void GenMMC5Reset(void) static SFORMAT MMC5_StateRegs[]={ { PRGBanks, 4, "PRGB"}, - { CHRBanksA, 8, "CHRA"}, - { CHRBanksB, 4, "CHRB"}, + { CHRBanksA, 16, "CHRA"}, + { CHRBanksB, 8, "CHRB"}, { &WRAMPage, 1, "WRMP"}, { WRAMMaskEnable, 2, "WRME"}, { &mmc5ABMode, 1, "ABMD"}, @@ -844,6 +847,7 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) AddExState(&MMC5HackSPMode, 1, 0, "SPLM"); AddExState(&MMC5HackSPScroll, 1, 0, "SPLS"); AddExState(&MMC5HackSPPage, 1, 0, "SPLP"); + AddExState(&MMC50x5130, 1, 0, "5130"); MMC5WRAMsize=wsize/8; BuildWRAMSizeTable(); diff --git a/source/fceultra/cart.cpp b/source/fceultra/cart.cpp index 316d4ec..1a0f254 100644 --- a/source/fceultra/cart.cpp +++ b/source/fceultra/cart.cpp @@ -24,7 +24,7 @@ #include #include #include - +#include #include "types.h" #include "fceu.h" #include "ppu.h" @@ -293,7 +293,7 @@ void setchr8r(int r, unsigned int V) if(CHRram[r]) PPUCHRRAM|=(255); else - PPUCHRRAM&=~(255); + PPUCHRRAM=0; } void setchr1(unsigned int A, unsigned int V) @@ -640,7 +640,7 @@ void FCEU_SaveGameSave(CartInfo *LocalHWInfo) std::string soot = FCEU_MakeFName(FCEUMKF_SAV,0,"sav"); if((sp=FCEUD_UTF8fopen(soot,"wb"))==NULL) { - FCEU_PrintError("WRAM file \"%s\" cannot be written to.\n",soot); + FCEU_PrintError("WRAM file \"%s\" cannot be written to.\n",soot.c_str()); } else { diff --git a/source/fceultra/fceu.h b/source/fceultra/fceu.h index 0611bc4..83e2fdf 100644 --- a/source/fceultra/fceu.h +++ b/source/fceultra/fceu.h @@ -38,6 +38,7 @@ extern int MMC5Hack; extern uint8 *MMC5HackVROMPTR; extern uint8 MMC5HackCHRMode; extern uint8 MMC5HackSPMode; +extern uint8 MMC50x5130; extern uint8 MMC5HackSPScroll; extern uint8 MMC5HackSPPage; diff --git a/source/fceultra/file.cpp b/source/fceultra/file.cpp index 6cc006e..2d9daaf 100644 --- a/source/fceultra/file.cpp +++ b/source/fceultra/file.cpp @@ -242,7 +242,7 @@ zpfail: unzCloseCurrentFile(tz); unzClose(tz); - FCEUFILE *fceufp=fceufp = new FCEUFILE(); + FCEUFILE *fceufp = new FCEUFILE(); fceufp->stream = ms; fceufp->size = size; return fceufp; @@ -259,7 +259,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext bool read = (std::string)mode == "rb"; bool write = (std::string)mode == "wb"; - if(read&&write || (!read&&!write)) + if((read&&write) || (!read&&!write)) { FCEU_PrintError("invalid file open mode specified (only wb and rb are supported)"); return 0; @@ -764,4 +764,4 @@ void FCEUARCHIVEFILEINFO::FilterByExtension(const char** ext) this->erase(begin()+i); ok: ; } -} \ No newline at end of file +} diff --git a/source/fceultra/ines.cpp b/source/fceultra/ines.cpp index 0cd45a8..84d81c6 100644 --- a/source/fceultra/ines.cpp +++ b/source/fceultra/ines.cpp @@ -753,6 +753,33 @@ int iNesSave(){ return 1; } +int iNesSaveAs(char* name) +{ + //adelikat: TODO: iNesSave() and this have pretty much the same code, outsource the common code to a single function + FILE *fp; + + if(GameInfo->type != GIT_CART)return 0; + if(GameInterface!=iNESGI)return 0; + + fp = fopen(name,"wb"); + int x = 0; + if (!fp) + int x = 1; + if(fwrite(&head,1,16,fp)!=16)return 0; + + if(head.ROM_type&4) /* Trainer */ + { + fwrite(trainerpoo,512,1,fp); + } + + fwrite(ROM,0x4000,ROM_size,fp); + + if(head.VROM_size)fwrite(VROM,0x2000,head.VROM_size,fp); + fclose(fp); + + return 1; +} + //para edit: added function below char *iNesShortFName() { char *ret; diff --git a/source/fceultra/ines.h b/source/fceultra/ines.h index 91e6ac2..516428a 100644 --- a/source/fceultra/ines.h +++ b/source/fceultra/ines.h @@ -74,6 +74,7 @@ extern uint8 *VROM; extern uint32 VROM_size; extern uint32 ROM_size; extern int iNesSave(); //bbit Edited: line added +extern int iNesSaveAs(char* name); extern char LoadedRomFName[2048]; //bbit Edited: line added //mbg merge 7/19/06 changed to c++ decl format diff --git a/source/fceultra/input.cpp b/source/fceultra/input.cpp index 15a4946..3fed7b9 100644 --- a/source/fceultra/input.cpp +++ b/source/fceultra/input.cpp @@ -202,6 +202,9 @@ static void UpdateGP(int w, void *data, int arg) joy[2]= FCEU_LuaUsingJoypad(2) ? (FCEU_LuaReadJoypad(2) | (*(uint32 *)joyports[0].ptr >> 16)) : *(uint32 *)joyports[0].ptr >> 16; if (FCEU_LuaReadJoypadFalse(2)) joy[2] &= FCEU_LuaReadJoypadFalse(2); + #else // without this, there seems to be no input at all without Lua + joy[0] = *(uint32 *)joyports[0].ptr;; + joy[2] = *(uint32 *)joyports[0].ptr >> 16; #endif } else @@ -215,6 +218,9 @@ static void UpdateGP(int w, void *data, int arg) joy[3]= FCEU_LuaUsingJoypad(3) ? (FCEU_LuaReadJoypad(3) | (*(uint32 *)joyports[1].ptr >> 24)) : *(uint32 *)joyports[1].ptr >> 24; if (FCEU_LuaReadJoypadFalse(3)) joy[3] &= FCEU_LuaReadJoypadFalse(3); + #else // same goes for the other two pads + joy[1] = *(uint32 *)joyports[1].ptr >> 8; + joy[3] = *(uint32 *)joyports[1].ptr >> 24; #endif } @@ -609,6 +615,7 @@ static void CloseRom(void); static void MovieSubtitleToggle(void); static void UndoRedoSavestate(void); static void FCEUI_DoExit(void); +static void ToggleFullscreen(void); struct EMUCMDTABLE FCEUI_CommandTable[]= { @@ -619,8 +626,6 @@ struct EMUCMDTABLE FCEUI_CommandTable[]= { EMUCMD_SCREENSHOT, EMUCMDTYPE_MISC, FCEUI_SaveSnapshot, 0, 0, "Screenshot", EMUCMDFLAG_TASEDIT }, { EMUCMD_HIDE_MENU_TOGGLE, EMUCMDTYPE_MISC, FCEUD_HideMenuToggle, 0, 0, "Hide Menu Toggle", EMUCMDFLAG_TASEDIT }, { EMUCMD_EXIT, EMUCMDTYPE_MISC, FCEUI_DoExit, 0, 0, "Exit", 0}, - //adelikat: CaH4e3, perhaps finding the true cause should be on the person who made the change? - //Also, removing the windows only function from this table. This is a core file and should stay compatible with the SDL build { EMUCMD_SPEED_SLOWEST, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Slowest Speed", 0 }, { EMUCMD_SPEED_SLOWER, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Speed Down", 0 }, { EMUCMD_SPEED_NORMAL, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Normal Speed", 0 }, @@ -671,7 +676,7 @@ struct EMUCMDTABLE FCEUI_CommandTable[]= { EMUCMD_MOVIE_PLAY_FROM_BEGINNING, EMUCMDTYPE_MOVIE, FCEUI_MoviePlayFromBeginning, 0, 0, "Play Movie From Beginning", 0 }, { EMUCMD_MOVIE_STOP, EMUCMDTYPE_MOVIE, FCEUI_StopMovie, 0, 0, "Stop Movie", 0 }, { EMUCMD_MOVIE_READONLY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleReadOnly, 0, 0, "Toggle Read-Only", EMUCMDFLAG_TASEDIT }, - { EMUCMD_MOVIE_FRAME_DISPLAY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleFrameDisplay, 0, 0, "Movie Frame Display Toggle", 0 }, + { EMUCMD_MOVIE_FRAME_DISPLAY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleFrameDisplay, 0, 0, "Frame Display Toggle", 0 }, { EMUCMD_MOVIE_INPUT_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_ToggleInputDisplay, 0, 0, "Toggle Input Display", 0 }, { EMUCMD_MOVIE_ICON_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUD_ToggleStatusIcon, 0, 0, "Toggle Status Icon", 0 }, @@ -722,15 +727,12 @@ struct EMUCMDTABLE FCEUI_CommandTable[]= { EMUCMD_OPENROM, EMUCMDTYPE_TOOL, OpenRom, 0, 0, "Open ROM", 0}, { EMUCMD_CLOSEROM, EMUCMDTYPE_TOOL, CloseRom, 0, 0, "Close ROM", 0}, { EMUCMD_MISC_DISPLAY_MOVIESUBTITLES, EMUCMDTYPE_MISC, MovieSubtitleToggle,0,0,"Toggle Movie Subtitles", 0}, - { EMUCMD_MISC_UNDOREDOSAVESTATE, EMUCMDTYPE_MISC, UndoRedoSavestate, 0,0,"Undo/Redo Savestate", 0} + { EMUCMD_MISC_UNDOREDOSAVESTATE, EMUCMDTYPE_MISC, UndoRedoSavestate, 0,0,"Undo/Redo Savestate", 0}, + { EMUCMD_MISC_TOGGLEFULLSCREEN, EMUCMDTYPE_MISC, ToggleFullscreen, 0, 0, "Toggle Fullscreen", 0} }; #define NUM_EMU_CMDS (sizeof(FCEUI_CommandTable)/sizeof(FCEUI_CommandTable[0])) -// jabberwoocky my son, don't be aware lol -// this is much mindfucking thing i ever seen here -// even when i fixed it, there is a lot of possibilities to break all key input stuff with one -// unarranged command enumerator. static int execcmd, i; void FCEUI_HandleEmuCommands(TestCommandState* testfn) @@ -949,4 +951,18 @@ static void FCEUI_DoExit(void) #ifdef WIN32 DoFCEUExit(); #endif +} + +static void ToggleFullscreen(void) +{ +#ifdef WIN32 + extern int SetVideoMode(int fs); //adelikat: Yeah, I know, hacky + extern void UpdateCheckedMenuItems(); + + UpdateCheckedMenuItems(); + changerecursive=1; + if(!SetVideoMode(fullscreen^1)) + SetVideoMode(fullscreen); + changerecursive=0; +#endif } \ No newline at end of file diff --git a/source/fceultra/input.h b/source/fceultra/input.h index dd410e6..0b0779f 100644 --- a/source/fceultra/input.h +++ b/source/fceultra/input.h @@ -218,6 +218,7 @@ enum EMUCMD //----------------------------- EMUCMD_MISC_DISPLAY_MOVIESUBTITLES, EMUCMD_MISC_UNDOREDOSAVESTATE, + EMUCMD_MISC_TOGGLEFULLSCREEN, EMUCMD_MAX }; diff --git a/source/fceultra/movie.cpp b/source/fceultra/movie.cpp index 9541fcb..735ed05 100644 --- a/source/fceultra/movie.cpp +++ b/source/fceultra/movie.cpp @@ -34,11 +34,12 @@ #ifdef WIN32 #include +extern void AddRecentMovieFile(const char *filename); #endif using namespace std; -#define MOVIE_VERSION 3 +#define MOVIE_VERSION 3 extern char FileBase[]; extern bool AutoSS; //Declared in fceu.cpp, keeps track if a auto-savestate has been made @@ -105,7 +106,7 @@ void MovieData::clearRecordRange(int start, int len) void MovieData::insertEmpty(int at, int frames) { #ifndef GEKKO - if(at == -1) + if(at == -1) { int currcount = records.size(); records.resize(records.size()+frames); @@ -465,7 +466,7 @@ bool FCEUI_GetLagged(void) bool FCEUMOV_ShouldPause(void) { - if(pauseframe && currFrameCounter == pauseframe) + if(pauseframe && currFrameCounter == (pauseframe-1)) //adelikat: changed to pauseframe -1 to prevent an off by 1 error. THis is probably the hackiest solution but I think it would cause some major restructuring to fix it properly. { pauseframe = 0; //only pause once! return true; @@ -529,7 +530,7 @@ static void LoadFM2_binarychunk(MovieData& movieData, std::istream* fp, int size } //yuck... another custom text parser. -static bool LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopAfterHeader) +bool LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopAfterHeader) { #ifndef GEKKO //first, look for an fcm signature @@ -780,11 +781,11 @@ void MovieData::dumpSavestateTo(std::vector* buf, int compressionLevel) } //begin playing an existing movie -void FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _pauseframe) +bool FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _pauseframe) { #ifndef GEKKO if(!tasedit && !FCEU_IsValidUI(FCEUI_PLAYMOVIE)) - return; + return true; //adelikat: file did not fail to load, so let's return true here, just do nothing assert(fname); @@ -796,17 +797,22 @@ void FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _paus //-------------- currMovieData = MovieData(); - + strcpy(curMovieFilename, fname); FCEUFILE *fp = FCEU_fopen(fname,0,"rb",0); - if (!fp) return; + if (!fp) return false; if(fp->isArchive() && !_read_only) { FCEU_PrintError("Cannot open a movie in read+write from an archive."); - return; + return true; //adelikat: file did not fail to load, so return true (false is only for file not exist/unable to open errors } +#ifdef WIN32 + //Add to the recent movie menu + AddRecentMovieFile(fname); +#endif + LoadFM2(currMovieData, fp->stream, INT_MAX, false); - LoadSubtitles(); + LoadSubtitles(currMovieData); delete fp; freshMovie = true; //Movie has been loaded, so it must be unaltered @@ -818,7 +824,7 @@ void FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _paus if(currMovieData.savestate.size() != 0) { bool success = MovieData::loadSavestateFrom(&currMovieData.savestate); - if(!success) return; + if(!success) return true; //adelikat: I guess return true here? False is only for a bad movie filename, if it got this far the file was god? } //if there is no savestate, we won't have this crucial piece of information at the start of the movie. @@ -852,7 +858,7 @@ void FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _paus else FCEU_DispMessage("Replay started Read+Write."); } - + #ifdef CREATE_AVI if(LoggingEnabled) { @@ -860,6 +866,9 @@ void FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _paus LoggingEnabled = 2; } #endif + return true; +#else + return false; #endif } @@ -1326,16 +1335,16 @@ bool FCEUI_MovieGetInfo(FCEUFILE* fp, MOVIE_INFO& info, bool skipFrameCount) } //This function creates an array of frame numbers and corresponding strings for displaying subtitles -void LoadSubtitles(void) +void LoadSubtitles(MovieData moviedata) { #ifndef GEKKO extern std::vector subtitles; - for(uint32 i=0;i comments; #endif @@ -93,7 +92,7 @@ class MovieRecord public: ValueArray joysticks; - + struct { uint8 x,y,b,bogo; uint64 zaphit; @@ -133,7 +132,7 @@ public: } void clear(); - + //a waste of memory in lots of cases.. maybe make it a pointer later? std::vector savestate; @@ -143,7 +142,7 @@ public: void dumpBinary(MovieData* md, std::ostream* os, int index); void parseJoy(std::istream* is, uint8& joystate); void dumpJoy(std::ostream* os, uint8 joystate); - + static const char mnemonics[8]; private: @@ -154,7 +153,7 @@ class MovieData { public: MovieData(); - + int version; int emuVersion; @@ -179,7 +178,7 @@ public: int ports[3]; //whether fourscore is enabled bool fourscore; - + //----TasEdit stuff--- int greenZoneCount; //---- @@ -219,7 +218,7 @@ public: int dump(std::ostream* os, bool binary); void clearRecordRange(int start, int len); void insertEmpty(int at, int frames); - + static bool loadSavestateFrom(std::vector* buf); static void dumpSavestateTo(std::vector* buf, int compressionLevel); void TryDumpIncremental(); @@ -246,10 +245,11 @@ extern bool autoMovieBackup; //-------------------------------------------------- bool CheckFileExists(const char* filename); //Receives a filename (fullpath) and checks to see if that file exists void FCEUI_MakeBackupMovie(bool dispMessage); +void FCEUI_CreateMovieFile(std::string fn); #ifndef GEKKO void FCEUI_SaveMovie(const char *fname, EMOVIE_FLAG flags, std::wstring author); #endif -void FCEUI_LoadMovie(const char *fname, bool read_only, bool tasedit, int _stopframe); +bool FCEUI_LoadMovie(const char *fname, bool read_only, bool tasedit, int _stopframe); void FCEUI_MoviePlayFromBeginning(void); void FCEUI_StopMovie(void); bool FCEUI_MovieGetInfo(FCEUFILE* fp, MOVIE_INFO& info, bool skipFrameCount = false); @@ -263,8 +263,8 @@ std::string FCEUI_GetMovieName(void); void FCEUI_MovieToggleFrameDisplay(); void FCEUI_ToggleInputDisplay(void); -void LoadSubtitles(void); +void LoadSubtitles(MovieData); void ProcessSubtitles(void); void FCEU_DisplaySubtitles(char *format, ...); -#endif //__MOVIE_H_ +#endif //__MOVIE_H_ \ No newline at end of file diff --git a/source/fceultra/ops.inc b/source/fceultra/ops.inc index 0d66b63..1524d61 100644 --- a/source/fceultra/ops.inc +++ b/source/fceultra/ops.inc @@ -343,8 +343,9 @@ case 0x6B: { /* ASR */ case 0x4B: LD_IM(AND;LSRA); -/* ATX(OAL) Is this(OR with $EE) correct? */ -case 0xAB: LD_IM(_A|=0xEE;AND;_X=_A); +/* ATX(OAL) Is this(OR with $EE) correct? Blargg did some test + and found the constant to be OR with is $FF for NES */ +case 0xAB: LD_IM(_A|=0xFF;AND;_X=_A); /* AXS */ case 0xCB: LD_IM(AXS); diff --git a/source/fceultra/ppu.cpp b/source/fceultra/ppu.cpp index 6d9965e..d440083 100644 --- a/source/fceultra/ppu.cpp +++ b/source/fceultra/ppu.cpp @@ -49,6 +49,7 @@ #define SpriteON (PPU[1]&0x10) //Show Sprite #define ScreenON (PPU[1]&0x08) //Show screen #define PPUON (PPU[1]&0x18) //PPU should operate +#define GRAYSCALE (PPU[1]&0x01) //Grayscale (AND palette entries with 0x30) #define SpriteLeft8 (PPU[1]&0x04) #define BGLeft8 (PPU[1]&0x02) @@ -99,6 +100,24 @@ struct BITREVLUT { }; BITREVLUT bitrevlut; +struct PPUSTATUS +{ + int sl; + int cycle, end_cycle; +}; +struct SPRITE_READ +{ + int num; + int count; + int fetch; + int found; + int found_pos[8]; + int ret; + int last; + int mode; +}; +struct SPRITE_READ spr_read = { 0 }; + //uses the internal counters concept at http://nesdev.icequake.net/PPU%20addressing.txt struct PPUREGS { uint32 fv;//3 @@ -110,13 +129,17 @@ struct PPUREGS { uint32 s;//1 uint32 par;//8 uint32 ar;//2 - - uint32 _fv, _v, _h, _vt, _ht; - + + uint32 _fv, _v, _h, _vt, _ht; + + struct PPUSTATUS status; + PPUREGS() : fv(0), v(0), h(0), vt(0), ht(0), fh(0), s(0), par(0), ar(0) , _fv(0), _v(0), _h(0), _vt(0), _ht(0) - {} + { status.cycle = 0; status.end_cycle = 341; + status.sl = 241; + } void install_latches() { fv = _fv; @@ -127,9 +150,6 @@ struct PPUREGS { } void install_h_latches() { - if(ht!=_ht || h != _h) { - int zzz=9; - } ht = _ht; h = _h; } @@ -261,6 +281,7 @@ uint8 *MMC5HackExNTARAMPtr=0; uint8 *MMC5HackVROMPTR=0; uint8 MMC5HackCHRMode=0; uint8 MMC5HackSPMode=0; +uint8 MMC50x5130=0; uint8 MMC5HackSPScroll=0; uint8 MMC5HackSPPage=0; @@ -291,8 +312,8 @@ static uint32 scanlines_per_frame; uint8 PPU[4]; uint8 PPUSPL; uint8 NTARAM[0x800],PALRAM[0x20],SPRAM[0x100],SPRBUF[0x100]; - - +uint8 UPALRAM[0x03]; //for 0x4/0x8/0xC addresses in palette, the ones in + //0x20 are 0 to not break fceu rendering. #define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V)>>10][(V)] @@ -320,6 +341,7 @@ uint8* FCEUPPU_GetCHR(uint32 vadr, uint32 refreshaddr) { if(MMC5HackCHRMode==1) { uint8 *C = MMC5HackVROMPTR; C += (((MMC5HackExNTARAMPtr[refreshaddr & 0x3ff]) & 0x3f & MMC5HackVROMMask) << 12) + (vadr & 0xfff); + C += (MMC50x5130&0x3)<<18; //11-jun-2009 for kuja_killer return C; } else { return MMC5BGVRAMADR(vadr); @@ -343,23 +365,29 @@ int FCEUPPU_GetAttr(int ntnum, int xt, int yt) { inline void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) { uint32 tmp = A; - if(tmp>=0x3F00) - { - // 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) - { - if(PPUCHRRAM&(1<<(tmp>>10))) - VPage[tmp>>10][tmp]=V; - } - else - { - if(PPUNTARAM&(1<<((tmp&0xF00)>>10))) - vnapage[((tmp&0xF00)>>10)][tmp&0x3FF]=V; - } + if(tmp<0x2000) + { + if(PPUCHRRAM&(1<<(tmp>>10))) + VPage[tmp>>10][tmp]=V; + } + else if (tmp<0x3F00) + { + if(PPUNTARAM&(1<<((tmp&0xF00)>>10))) + vnapage[((tmp&0xF00)>>10)][tmp&0x3FF]=V; + } + else + { + if (!(tmp & 3)) + { + if (!(tmp & 0xC)) + PALRAM[0x00] = PALRAM[0x04] = + PALRAM[0x08] = PALRAM[0x0C] = V & 0x3F; + else + UPALRAM[((tmp & 0xC) >> 2) - 1] = V & 0x3F; + } + else + PALRAM[tmp & 0x1F] = V & 0x3F; + } } uint8 FFCEUX_PPURead_Default(uint32 A) { @@ -369,10 +397,27 @@ uint8 FFCEUX_PPURead_Default(uint32 A) { { return VPage[tmp>>10][tmp]; } - else + else if (tmp < 0x3F00) { return vnapage[(tmp>>10)&0x3][tmp&0x3FF]; } + else + { + uint8 ret; + if (!(tmp & 3)) + { + if (!(tmp & 0xC)) + ret = PALRAM[0x00]; + else + ret = UPALRAM[((tmp & 0xC) >> 2) - 1]; + } + else + ret = PALRAM[tmp & 0x1F]; + + if (GRAYSCALE) + ret &= 0x30; + return ret; + } } @@ -419,6 +464,191 @@ static DECLFR(A2002) return ret; } +static DECLFR(A2004) +{ + if (newppu) + { + if ((ppur.status.sl < 241) && PPUON) + { + /* from cycles 0 to 63, the + * 32 byte OAM buffer gets init + * to 0xFF */ + if (ppur.status.cycle < 64) + return spr_read.ret = 0xFF; + else + { + for (int i = spr_read.last; + i != ppur.status.cycle; ++i) + { + if (i < 256) + { + switch (spr_read.mode) + { + case 0: + if (spr_read.count < 2) + spr_read.ret = (PPU[3] & 0xF8) + + (spr_read.count << 2); + else + spr_read.ret = spr_read.count << 2; + spr_read.found_pos[spr_read.found] = + spr_read.ret; + + spr_read.ret = SPRAM[spr_read.ret]; + + if (i & 1) //odd cycle + { + //see if in range + if ( !((ppur.status.sl - 1 - + spr_read.ret) + & ~(Sprite16 ? 0xF : 0x7)) ) + + { + ++spr_read.found; + spr_read.fetch = 1; + spr_read.mode = 1; + } + else + { + if (++spr_read.count == 64) + { + spr_read.mode = 4; + spr_read.count = 0; + } + else if (spr_read.found == 8) + { + spr_read.fetch = 0; + spr_read.mode = 2; + } + } + } + break; + case 1: //sprite is in range fetch next 3 bytes + if (i & 1) + { + ++spr_read.fetch; + if (spr_read.fetch == 4) + { + spr_read.fetch = 1; + if (++spr_read.count == 64) + { + spr_read.count = 0; + spr_read.mode = 4; + } + else if (spr_read.found == 8) + { + spr_read.fetch = 0; + spr_read.mode = 2; + } + else + spr_read.mode = 0; + } + } + + if (spr_read.count < 2) + spr_read.ret = (PPU[3] & 0xF8) + + (spr_read.count << 2); + else + spr_read.ret = spr_read.count << 2; + + spr_read.ret = SPRAM[spr_read.ret | + spr_read.fetch]; + break; + case 2: //8th sprite fetched + spr_read.ret = SPRAM[(spr_read.count << 2) + | spr_read.fetch]; + if (i & 1) + { + if ( !((ppur.status.sl - 1 - + SPRAM[((spr_read.count << 2) + | spr_read.fetch)]) + & ~((Sprite16) ? 0xF : 0x7)) ) + { + spr_read.fetch = 1; + spr_read.mode = 3; + } + else + { + if (++spr_read.count == 64) + { + spr_read.count = 0; + spr_read.mode = 4; + } + spr_read.fetch = + (spr_read.fetch + 1) & 3; + } + } + spr_read.ret = spr_read.count; + break; + case 3: //9th sprite overflow detected + spr_read.ret = SPRAM[spr_read.count + | spr_read.fetch]; + if (i & 1) + { + if (++spr_read.fetch == 4) + { + spr_read.count = (spr_read.count + + 1) & 63; + spr_read.mode = 4; + } + } + break; + case 4: //read OAM[n][0] until hblank + if (i & 1) + spr_read.count = + (spr_read.count + 1) & 63; + spr_read.fetch = 0; + spr_read.ret = SPRAM[spr_read.count << 2]; + break; + } + } + else if (i < 320) + { + spr_read.ret = (i & 0x38) >> 3; + if (spr_read.found < (spr_read.ret + 1)) + { + if (spr_read.num) + { + spr_read.ret = SPRAM[252]; + spr_read.num = 0; + } + else + spr_read.ret = 0xFF; + } + else if ((i & 7) < 4) + { + spr_read.ret = + SPRAM[spr_read.found_pos[spr_read.ret] + | spr_read.fetch++]; + if (spr_read.fetch == 4) + spr_read.fetch = 0; + } + else + spr_read.ret = SPRAM[spr_read.found_pos + [spr_read.ret | 3]]; + } + else + { + if (!spr_read.found) + spr_read.ret = SPRAM[252]; + else + spr_read.ret = SPRAM[spr_read.found_pos[0]]; + break; + } + } + spr_read.last = ppur.status.cycle; + return spr_read.ret; + } + } + else + return SPRAM[PPU[3]]; + } + else + { + FCEUPPU_LineUpdate(); + return PPUGenLatch; + } +} + static DECLFR(A200x) /* Not correct for $2004 reads. */ { FCEUPPU_LineUpdate(); @@ -456,14 +686,34 @@ static DECLFR(A2007) uint32 tmp=RefreshAddr&0x3FFF; if(newppu) { - //mbg - ret = VRAMBuffer; - RefreshAddr = ppur.get_2007access(); - VRAMBuffer = CALL_PPUREAD(RefreshAddr); + ret = VRAMBuffer; + RefreshAddr = ppur.get_2007access() & 0x3FFF; + if ((RefreshAddr & 0x3F00) == 0x3F00) + { + //if it is in the palette range bypass the + //delayed read, and what gets filled in the temp + //buffer is the address - 0x1000, also + //if grayscale is set then the return is AND with 0x30 + //to get a gray color reading + if (!(tmp & 3)) + { + if (!(tmp & 0xC)) + ret = PALRAM[0x00]; + else + ret = UPALRAM[((tmp & 0xC) >> 2) - 1]; + } + else + ret = PALRAM[tmp & 0x1F]; + if (GRAYSCALE) + ret &= 0x30; + VRAMBuffer = CALL_PPUREAD(RefreshAddr - 0x1000); + } + else + VRAMBuffer = CALL_PPUREAD(RefreshAddr); ppur.increment2007(INC32!=0); RefreshAddr = ppur.get_2007access(); - return ret; - } else { + return ret; + } else { FCEUPPU_LineUpdate(); ret=VRAMBuffer; @@ -478,7 +728,7 @@ static DECLFR(A2007) { VRAMBuffer=VPage[tmp>>10][tmp]; } - else + else if (tmp < 0x3F00) { VRAMBuffer=vnapage[(tmp>>10)&0x3][tmp&0x3FF]; } @@ -525,7 +775,7 @@ static DECLFW(B2001) if(V&0xE0) deemp=V>>5; } - +// static DECLFW(B2002) { PPUGenLatch=V; @@ -542,21 +792,32 @@ static DECLFW(B2003) static DECLFW(B2004) { //printf("Wr: %04x:$%02x\n",A,V); - - PPUGenLatch=V; - if(PPUSPL>=8) - { - if(PPU[3]>=8) - SPRAM[PPU[3]]=V; - } - else - { - //printf("$%02x:$%02x\n",PPUSPL,V); - SPRAM[PPUSPL]=V; - } - PPU[3]++; - PPUSPL++; - + PPUGenLatch=V; + if (newppu) + { + //the attribute upper bits are not connected + //so AND them out on write, since reading them + //should return 0 in those bits. + if ((PPU[3] & 3) == 2) + V &= 0xE3; + SPRAM[PPU[3]] = V; + PPU[3] = (PPU[3] + 1) & 0xFF; + } + else + { + if(PPUSPL>=8) + { + if(PPU[3]>=8) + SPRAM[PPU[3]]=V; + } + else + { + //printf("$%02x:$%02x\n",PPUSPL,V); + SPRAM[PPUSPL]=V; + } + PPU[3]++; + PPUSPL++; + } } static DECLFW(B2005) @@ -618,15 +879,8 @@ static DECLFW(B2006) ppur._ht = V&31; ppur.install_latches(); - - if(RefreshAddr==0x18DE) { - int zzz=9; - } } - if(ppur._fv == 1) { - int zzz=9; - } vtoggle^=1; } @@ -635,7 +889,7 @@ static DECLFW(B2007) uint32 tmp=RefreshAddr&0x3FFF; if(newppu) { - RefreshAddr = ppur.get_2007access(); + RefreshAddr = ppur.get_2007access() & 0x3FFF; CALL_PPUWRITE(RefreshAddr,V); //printf("%04x ",RefreshAddr); ppur.increment2007(INC32!=0); @@ -644,13 +898,6 @@ static DECLFW(B2007) else { //printf("%04x ",tmp); - if(tmp==0x2679) - { - int zzz=9; - } - if(tmp == 0x3f13 ) { - int zzz=9; - } PPUGenLatch=V; if(tmp>=0x3F00) { @@ -1539,7 +1786,6 @@ void FCEUPPU_Reset(void) vtoggle = 0; ppudead = 2; kook = 0; - // XOffset=0; } @@ -1548,7 +1794,8 @@ void FCEUPPU_Power(void) int x; memset(NTARAM,0x00,0x800); - memset(PALRAM,0x00,0x20); + memset(PALRAM,0x00,0x20); + memset(UPALRAM,0x00,0x03); memset(SPRAM,0x00,0x100); FCEUPPU_Reset(); @@ -1562,7 +1809,7 @@ void FCEUPPU_Power(void) BWrite[x+2]=B2002; ARead[x+3]=A200x; BWrite[x+3]=B2003; - ARead[x+4]=A200x; //A2004; + ARead[x+4]=A2004; //A2004; BWrite[x+4]=B2004; ARead[x+5]=A200x; BWrite[x+5]=B2005; @@ -1753,11 +2000,13 @@ int pputime=0; int totpputime=0; const int kLineTime=341; const int kFetchTime=2; -int idleSynch = 0; +int idleSynch = 1; void runppu(int x) { //pputime+=x; //if(cputodo<200) return; + ppur.status.cycle = (ppur.status.cycle + x) % + ppur.status.end_cycle; X6502_Run(x); //pputime -= cputodo<<2; } @@ -1774,24 +2023,30 @@ struct BGData { RefreshAddr = ppur.get_atread(); at = CALL_PPUREAD(RefreshAddr); - runppu(kFetchTime); - + //modify at to get appropriate palette shift if(ppur.vt&2) at >>= 4; if(ppur.ht&2) at >>= 2; at &= 0x03; at <<= 2; - - ppur.par = nt; + //horizontal scroll clocked at cycle 3 and then + //vertical scroll at 251 + runppu(1); + if (PPUON) + { + ppur.increment_hsc(); + if (ppur.status.cycle == 251) + ppur.increment_vs(); + } + runppu(1); + + ppur.par = nt; RefreshAddr = ppur.get_ptread(); pt[0] = CALL_PPUREAD(RefreshAddr); runppu(kFetchTime); RefreshAddr |= 8; pt[1] = CALL_PPUREAD(RefreshAddr); runppu(kFetchTime); - - if(PPUON) - ppur.increment_hsc(); } }; @@ -1802,15 +2057,24 @@ struct BGData { int framectr=0; int FCEUX_PPU_Loop(int skip) { //262 scanlines - - if(ppudead) - { - memset(XBuf, 0x80, 256*240); - runppu(262*kLineTime); - ppudead--; - goto finish; - } - + if (ppudead) + { + /* not quite emulating all the NES power up behavior + * since it is known that the NES ignores writes to some + * register before around a full frame, but no games + * should write to those regs during that time, it needs + * to wait for vblank */ + ppur.status.sl = 241; + if (PAL) + runppu(70*kLineTime); + else + runppu(20*kLineTime); + ppur.status.sl = 0; + runppu(242*kLineTime); + ppudead = 0; + goto finish; + } + { PPU_status |= 0x80; ppuphase = PPUPHASE_VBL; @@ -1818,16 +2082,20 @@ int FCEUX_PPU_Loop(int skip) { //Not sure if this is correct. According to Matt Conte and my own tests, it is. //Timing is probably off, though. //NOTE: Not having this here breaks a Super Donkey Kong game. - //PPU[3]=PPUSPL=0; - + PPU[3]=PPUSPL=0; const int delay = 20; //fceu used 12 here but I couldnt get it to work in marble madness and pirates. - runppu(delay); //X6502_Run(12); + + ppur.status.sl = 241; //for sprite reads + + runppu(delay); //X6502_Run(12); if(VBlankON) TriggerNMI(); - runppu(20*(kLineTime)-delay); - + if (PAL) + runppu(70*(kLineTime)-delay); + else + runppu(20*(kLineTime)-delay); + //this seems to run just before the dummy scanline begins - PPU_status&=0x1f; - + PPU_status = 0; //this early out caused metroid to fail to boot. I am leaving it here as a reminder of what not to do //if(!PPUON) { runppu(kLineTime*242); goto finish; } @@ -1837,8 +2105,8 @@ int FCEUX_PPU_Loop(int skip) { //rendering data for the first time in a frame (this update won't happen if //all rendering is disabled via 2001.3 and 2001.4). - if(PPUON) - ppur.install_latches(); + //if(PPUON) + // ppur.install_latches(); uint8 oams[2][64][7]; int oamcounts[2]={0,0}; @@ -1847,11 +2115,19 @@ int FCEUX_PPU_Loop(int skip) { //capture the initial xscroll //int xscroll = ppur.fh; - //render 241 scanlines (including 1 dummy at beginning) for(int sl=0;sl<241;sl++) { - int yp = sl-1; + spr_read.num = 1; + 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; + + int yp = sl-1; ppuphase = PPUPHASE_BG; if(sl != 0) { @@ -1875,7 +2151,7 @@ int FCEUX_PPU_Loop(int skip) { for(int xt=0;xt<32;xt++) { 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 if(sl != 0) { int xstart = xt<<3; @@ -1887,7 +2163,6 @@ int FCEUX_PPU_Loop(int skip) { //check all the conditions that can cause things to render in these 8px bool renderspritenow = SpriteON && rendersprites && (xt>0 || SpriteLeft8); bool renderbgnow = ScreenON && renderbg && (xt>0 || BGLeft8); - for(int xp=0;xp<8;xp++,rasterpos++) { //bg pos is different from raster pos due to its offsetability. @@ -1987,14 +2262,19 @@ 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 (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(); + + //this is done at cycle 251 + //rendering scanline, it doesn't need to be scanline 0, + //because on the first scanline when the increment is 0, the vs_scroll is reloaded. + //if(PPUON && sl != 0) + // ppur.increment_vs(); //todo - think about clearing oams to a predefined value to force deterministic behavior //so.. this is the end of hblank. latch horizontal scroll values - if(PPUON && sl != 0) - ppur.install_h_latches(); + //do it cycle at 251 + if(PPUON && sl != 0) + ppur.install_h_latches(); ppuphase = PPUPHASE_OBJ; @@ -2035,7 +2315,23 @@ int FCEUX_PPU_Loop(int skip) { patternAddress += line&7; //garbage nametable fetches - if(realSprite) runppu(kFetchTime); + //reset the scroll counter, happens at cycle 304 + if (realSprite) + { + if ((sl == 0) && PPUON) + { + if (ppur.status.cycle == 304) + { + runppu(1); + ppur.install_latches(); + runppu(1); + } + else + runppu(kFetchTime); + } + else + 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)) @@ -2050,15 +2346,16 @@ int FCEUX_PPU_Loop(int skip) { if(realSprite) runppu(kFetchTime); + //pattern table fetches RefreshAddr = patternAddress; oam[4] = CALL_PPUREAD(RefreshAddr); if(realSprite) runppu(kFetchTime); + RefreshAddr += 8; oam[5] = CALL_PPUREAD(RefreshAddr); if(realSprite) runppu(kFetchTime); - //hflip if(!(oam[2]&0x40)) { oam[4] = bitrevlut[oam[4]]; @@ -2077,29 +2374,32 @@ int FCEUX_PPU_Loop(int skip) { //same nametable address that points to the 3rd tile to be rendered on the //screen (or basically, the first nametable address that will be accessed when //the PPU is fetching background data on the next scanline). - //(not implemented yet) + //(not implemented yet) runppu(kFetchTime); + if (sl == 0) + { + if (idleSynch && PPUON && !PAL) + ppur.status.end_cycle = 340; + else + ppur.status.end_cycle = 341; + idleSynch ^= 1; + } + else + ppur.status.end_cycle = 341; runppu(kFetchTime); - - //After memory access 170, the PPU simply rests for 4 cycles (or the + //After memory access 170, the PPU simply rests for 4 cycles (or the //equivelant of half a memory access cycle) before repeating the whole //pixel/scanline rendering process. If the scanline being rendered is the very //first one on every second frame, then this delay simply doesn't exist. - if(sl==0 && idleSynch==0) - {} - else - runppu(1); - } - - idleSynch ++; - if(idleSynch==2) idleSynch = 0; + if (ppur.status.end_cycle == 341) + runppu(1); + } if(MMC5Hack && PPUON) MMC5_hb(240); //idle for one line runppu(kLineTime); - framectr++; } diff --git a/source/fceultra/pputile.inc b/source/fceultra/pputile.inc index 7eacb59..733b1d6 100644 --- a/source/fceultra/pputile.inc +++ b/source/fceultra/pputile.inc @@ -76,6 +76,7 @@ pshift[1]<<=8; C = MMC5HackVROMPTR; C += (((MMC5HackExNTARAMPtr[RefreshAddr & 0x3ff]) & 0x3f & MMC5HackVROMMask) << 12) + (vadr & 0xfff); + C += (MMC50x5130&0x3)<<18; //11-jun-2009 for kuja_killer #elif defined(PPUT_MMC5) C=MMC5BGVRAMADR(vadr); #else diff --git a/source/fceultra/sound.cpp b/source/fceultra/sound.cpp index 2f5f37e..1da02c9 100644 --- a/source/fceultra/sound.cpp +++ b/source/fceultra/sound.cpp @@ -89,25 +89,41 @@ static int32 sqacc[2]; static int32 lengthcount[4]; static const uint8 lengthtable[0x20]= { - 0x5*2,0x7f*2,0xA*2,0x1*2,0x14*2,0x2*2,0x28*2,0x3*2,0x50*2,0x4*2,0x1E*2,0x5*2,0x7*2,0x6*2,0x0E*2,0x7*2, - 0x6*2,0x08*2,0xC*2,0x9*2,0x18*2,0xa*2,0x30*2,0xb*2,0x60*2,0xc*2,0x24*2,0xd*2,0x8*2,0xe*2,0x10*2,0xf*2 + 10,254, 20, 2, 40, 4, 80, 6, 160, 8, 60, 10, 14, 12, 26, 14, + 12, 16, 24, 18, 48, 20, 96, 22, 192, 24, 72, 26, 16, 28, 32, 30 }; -static const uint32 NoiseFreqTable[0x10]= + +static const uint32 NoiseFreqTableNTSC[0x10] = { - 2,4,8,0x10,0x20,0x30,0x40,0x50,0x65,0x7f,0xbe,0xfe,0x17d,0x1fc,0x3f9,0x7f2 + 4, 8, 16, 32, 64, 96, 128, 160, 202, + 254, 380, 508, 762, 1016, 2034, 4068 }; +static const uint32 NoiseFreqTablePAL[0x10] = +{ + 4, 7, 14, 30, 60, 88, 118, 148, 188, + 236, 354, 472, 708, 944, 1890, 3778 +}; + +static const uint32 *NoiseFreqTable = NoiseFreqTableNTSC; + static const uint32 NTSCDMCTable[0x10]= { 428,380,340,320,286,254,226,214, 190,160,142,128,106, 84 ,72,54 }; +/* Previous values for PAL DMC was value - 1, + * I am not certain if this is if FCEU handled + * PAL differently or not, the NTSC values are right, + * so I am assuming that the current value is handled + * the same way NTSC is handled. */ + static const uint32 PALDMCTable[0x10]= { - 397, 353, 315, 297, 265, 235, 209, 198, - 176, 148, 131, 118, 98, 78, 66, 50, + 398, 354, 316, 298, 276, 236, 210, 198, + 176, 148, 132, 118, 98, 78, 66, 50 }; // $4010 - Frequency @@ -575,7 +591,7 @@ static INLINE void RDoSQ(int x) //Int x decides if this is Square Wave 1 or 2 //Modify Square wave volume based on channel volume modifiers //adelikat: Note: the formulat x = x * y /100 does not yield exact results, but is "close enough" and avoids the need for using double vales or implicit cohersion which are slower (we need speed here) - ampx = x ? FSettings.Square1Volume : FSettings.Square2Volume; // TODO OPTIMIZE ME! + ampx = x ? FSettings.Square2Volume : FSettings.Square1Volume; // TODO OPTIMIZE ME! if (ampx != 256) amp = (amp * ampx) / 256; // CaH4e3: fixed - setting up maximum volume for square2 caused complete mute square2 channel amp<<=24; @@ -837,7 +853,9 @@ static void RDoTriangleNoisePCMLQ(void) if(noiseacc<=0) { rea2: - noiseacc+=NoiseFreqTable[PSG[0xE]&0xF]<<(16+2); + //used to added <<(16+2) when the noise table + //values were half. + noiseacc+=NoiseFreqTable[PSG[0xE]&0xF]<<(16+1); nreg=(nreg<<1)+(((nreg>>nshift)^(nreg>>14))&1); nreg&=0x7fff; noiseout=amptab[(nreg>>0xe)]; @@ -876,7 +894,9 @@ static void RDoTriangleNoisePCMLQ(void) if(noiseacc<=0) { area2: - noiseacc+=NoiseFreqTable[PSG[0xE]&0xF]<<(16+2); + //used to be added <<(16+2) when the noise table + //values were half. + noiseacc+=NoiseFreqTable[PSG[0xE]&0xF]<<(16+1); nreg=(nreg<<1)+(((nreg>>nshift)^(nreg>>14))&1); nreg&=0x7fff; noiseout=amptab[(nreg>>0xe)]; @@ -927,7 +947,7 @@ static void RDoNoise(void) if(!wlcount[3]) { uint8 feedback; - wlcount[3]=NoiseFreqTable[PSG[0xE]&0xF]<<1; + wlcount[3]=NoiseFreqTable[PSG[0xE]&0xF]; feedback=((nreg>>8)&1)^((nreg>>14)&1); nreg=(nreg<<1)+feedback; nreg&=0x7fff; @@ -942,7 +962,7 @@ static void RDoNoise(void) if(!wlcount[3]) { uint8 feedback; - wlcount[3]=NoiseFreqTable[PSG[0xE]&0xF]<<1; + wlcount[3]=NoiseFreqTable[PSG[0xE]&0xF]; feedback=((nreg>>13)&1)^((nreg>>14)&1); nreg=(nreg<<1)+feedback; nreg&=0x7fff; @@ -1063,25 +1083,32 @@ due to that whole MegaMan 2 Game Genie thing. void FCEUSND_Reset(void) { - int x; - + int x; + IRQFrameMode=0x0; - fhcnt=fhinc; - fcnt=0; + fhcnt=fhinc; + fcnt=0; + nreg=1; - nreg=1; - for(x=0;x<2;x++) + if (PAL) + NoiseFreqTable = NoiseFreqTablePAL; + else + NoiseFreqTable = NoiseFreqTableNTSC; + + for(x=0;x<2;x++) { - wlcount[x]=2048; - if(nesincsize) // lq mode - sqacc[x]=((uint32)2048<<17)/nesincsize; - else - sqacc[x]=1; - sweepon[x]=0; - curfreq[x]=0; + wlcount[x]=2048; + if(nesincsize) // lq mode + sqacc[x]=((uint32)2048<<17)/nesincsize; + else + sqacc[x]=1; + sweepon[x]=0; + curfreq[x]=0; } - wlcount[2]=1; //2048; - wlcount[3]=2048; + + wlcount[2]=1; //2048; + wlcount[3]=2048; + DMCHaveDMA=DMCHaveSample=0; SIRQStat=0x00; diff --git a/source/fceultra/state.cpp b/source/fceultra/state.cpp index 7afb7b9..65cbee1 100644 --- a/source/fceultra/state.cpp +++ b/source/fceultra/state.cpp @@ -332,7 +332,7 @@ static bool ReadStateChunks(std::istream* is, int32 totalsize) return ret; } -int CurrentState=1; +int CurrentState=0; extern int geniestage; diff --git a/source/fceultra/types.h b/source/fceultra/types.h index ebc8a0b..56b23c9 100644 --- a/source/fceultra/types.h +++ b/source/fceultra/types.h @@ -23,7 +23,7 @@ #define __FCEU_TYPES #define FCEU_NAME "FCEUX" -#define FCEU_VERSION_STRING "2.1.0a" +#define FCEU_VERSION_STRING "2.1.1-interim" #define FCEU_VERSION_NUMERIC 20100 #define FCEU_NAME_AND_VERSION FCEU_NAME " " FCEU_VERSION_STRING diff --git a/source/fceultra/utils/md5.cpp b/source/fceultra/utils/md5.cpp index 6471c3c..f4ea950 100644 --- a/source/fceultra/utils/md5.cpp +++ b/source/fceultra/utils/md5.cpp @@ -237,8 +237,8 @@ char *md5_asciistr(MD5DATA& md5) for(x=0;x<16;x++) { - str[x*2]=trans[digest[x]&0x0F]; - str[x*2+1]=trans[digest[x]>>4]; + str[x*2]=trans[digest[x]>>4]; + str[x*2+1]=trans[digest[x]&0x0F]; } return(str); } diff --git a/source/fceultra/utils/memorystream.h b/source/fceultra/utils/memorystream.h index 8c13dcd..7c6a343 100644 --- a/source/fceultra/utils/memorystream.h +++ b/source/fceultra/utils/memorystream.h @@ -185,7 +185,7 @@ private: throw new std::runtime_error("memory_streambuf is not expandable"); size_t newcapacity; - if(upto == 0) + if(upto == -1) newcapacity = capacity + capacity/2 + 2; else newcapacity = std::max(upto,capacity); diff --git a/source/fceultra/x6502.cpp b/source/fceultra/x6502.cpp index 1920f26..1e03bd0 100644 --- a/source/fceultra/x6502.cpp +++ b/source/fceultra/x6502.cpp @@ -29,7 +29,6 @@ #endif #include "x6502abbrev.h" - X6502 X; uint32 timestamp; void (*MapIRQHook)(int a); @@ -574,4 +573,4 @@ const uint8 optype[256] = { /*0xD0*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0, /*0xE0*/ 0,1,0,0,2,2,2,0,0,0,0,0,3,3,3,0, /*0xF0*/ 0,4,0,0,0,5,5,0,0,6,0,0,0,7,7,0 -}; \ No newline at end of file +};