From 0a4e83314bbe4148b821bbd5d57e2c77b10c170f Mon Sep 17 00:00:00 2001 From: zeromus Date: Sun, 23 Jul 2006 05:38:15 +0000 Subject: [PATCH] testing svn rename --- fceu.cpp | 792 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 792 insertions(+) create mode 100644 fceu.cpp diff --git a/fceu.cpp b/fceu.cpp new file mode 100644 index 00000000..836186ed --- /dev/null +++ b/fceu.cpp @@ -0,0 +1,792 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2003 Xodnizel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#ifdef _USE_SHARED_MEMORY_ +#include +#endif + +#include "types.h" +#include "x6502.h" +#include "fceu.h" +#include "ppu.h" +#include "sound.h" +#include "netplay.h" +#include "general.h" +#include "endian.h" +#include "memory.h" + +#include "cart.h" +#include "nsf.h" +#include "fds.h" +#include "ines.h" +#include "unif.h" +#include "cheat.h" +#include "palette.h" +#include "state.h" +#include "movie.h" +#include "video.h" +#include "input.h" +#include "file.h" +#include "crc32.h" +#include "vsuni.h" +#ifdef _USE_SHARED_MEMORY_ +#include "drivers/win/basicbot.h" +#endif + +uint64 timestampbase; + + +FCEUGI *FCEUGameInfo = NULL; +void (*GameInterface)(int h); + +void (*GameStateRestore)(int version); + +readfunc ARead[0x10000]; +writefunc BWrite[0x10000]; +static readfunc *AReadG; +static writefunc *BWriteG; +static int RWWrap=0; + +//mbg merge 7/18/06 docs +//bit0 indicates whether emulation is paused +//bit1 indicates whether emulation is in frame step mode +static int EmulationPaused=0; + +static int RewindStatus[4] = {0, 0, 0, 0}; //is it safe to load rewind state +static int RewindIndex = 0; //which rewind state we're on +int EnableRewind = 0; //is rewind enabled + +static DECLFW(BNull) +{ + +} + +static DECLFR(ANull) +{ + return(X.DB); +} + +int AllocGenieRW(void) +{ + if(!(AReadG=(readfunc *)FCEU_malloc(0x8000*sizeof(readfunc)))) + return 0; + if(!(BWriteG=(writefunc *)FCEU_malloc(0x8000*sizeof(writefunc)))) + return 0; + RWWrap=1; + return 1; +} + +void FlushGenieRW(void) +{ + int32 x; + + if(RWWrap) + { + for(x=0;x<0x8000;x++) + { + ARead[x+0x8000]=AReadG[x]; + BWrite[x+0x8000]=BWriteG[x]; + } + free(AReadG); + free(BWriteG); + AReadG=0; + BWriteG=0; + RWWrap=0; + } +} + +readfunc FASTAPASS(1) GetReadHandler(int32 a) +{ + if(a>=0x8000 && RWWrap) + return AReadG[a-0x8000]; + else + return ARead[a]; +} + +void FASTAPASS(3) SetReadHandler(int32 start, int32 end, readfunc func) +{ + int32 x; + + if(!func) + func=ANull; + + if(RWWrap) + for(x=end;x>=start;x--) + { + if(x>=0x8000) + AReadG[x-0x8000]=func; + else + ARead[x]=func; + } + else + + for(x=end;x>=start;x--) + ARead[x]=func; +} + +writefunc FASTAPASS(1) GetWriteHandler(int32 a) +{ + if(RWWrap && a>=0x8000) + return BWriteG[a-0x8000]; + else + return BWrite[a]; +} + +void FASTAPASS(3) SetWriteHandler(int32 start, int32 end, writefunc func) +{ + int32 x; + + if(!func) + func=BNull; + + if(RWWrap) + for(x=end;x>=start;x--) + { + if(x>=0x8000) + BWriteG[x-0x8000]=func; + else + BWrite[x]=func; + } + else + for(x=end;x>=start;x--) + BWrite[x]=func; +} + +#ifdef _USE_SHARED_MEMORY_ +HANDLE mapGameMemBlock; +uint8 *GameMemBlock; +HANDLE mapRAM; +uint8 *RAM; +HANDLE mapBotInput; +uint32 *BotInput; +#else +uint8 GameMemBlock[131072]; +uint8 RAM[0x800]; +#endif //_USE_SHARED_MEMORY_ + +uint8 PAL=0; + + +static DECLFW(BRAML) +{ + RAM[A]=V; +} + +static DECLFW(BRAMH) +{ + RAM[A&0x7FF]=V; +} + +static DECLFR(ARAML) +{ + return RAM[A]; +} + +static DECLFR(ARAMH) +{ + return RAM[A&0x7FF]; +} + +static void CloseGame(void) +{ + if(FCEUGameInfo) + { + if(FCEUnetplay) + FCEUD_NetworkClose(); + FCEUI_StopMovie(); + if(FCEUGameInfo->name) + { + free(FCEUGameInfo->name); + FCEUGameInfo->name=0; + } + if(FCEUGameInfo->type!=GIT_NSF) + FCEU_FlushGameCheats(0,0); + GameInterface(GI_CLOSE); + ResetExState(0,0); + CloseGenie(); + free(FCEUGameInfo); + FCEUGameInfo = 0; + } +} + +void ResetGameLoaded(void) +{ + if(FCEUGameInfo) CloseGame(); + GameStateRestore=0; + PPU_hook=0; + GameHBIRQHook=0; + if(GameExpSound.Kill) + GameExpSound.Kill(); + memset(&GameExpSound,0,sizeof(GameExpSound)); + MapIRQHook=0; + MMC5Hack=0; + PAL&=1; + pale=0; +} + +int UNIFLoad(const char *name, FCEUFILE *fp); +int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode); +int FDSLoad(const char *name, FCEUFILE *fp); +int NSFLoad(FCEUFILE *fp); + +char lastLoadedGameName [2048] = {0,}; // hack for movie WRAM clearing on record from poweron + +FCEUGI *FCEUI_LoadGame(const char *name, int OverwriteVidMode) +{ + //mbg merge 7/17/07 - why is this here +//#ifdef WIN32 +// StopSound(); +//#endif + + FCEUFILE *fp; + char *ipsfn; + + ResetGameLoaded(); + + RewindStatus[0] = RewindStatus[1] = 0; + RewindStatus[2] = RewindStatus[3] = 0; + + FCEUGameInfo = (FCEUGI*)malloc(sizeof(FCEUGI)); + memset(FCEUGameInfo, 0, sizeof(FCEUGI)); + + FCEUGameInfo->soundchan = 0; + FCEUGameInfo->soundrate = 0; + FCEUGameInfo->name=0; + FCEUGameInfo->type=GIT_CART; + FCEUGameInfo->vidsys=GIV_USER; + FCEUGameInfo->input[0]=FCEUGameInfo->input[1]=-1; + FCEUGameInfo->inputfc=-1; + FCEUGameInfo->cspecial=0; + + FCEU_printf("Loading %s...\n\n",name); + + GetFileBase(name); + + ipsfn=FCEU_MakeFName(FCEUMKF_IPS,0,0); + fp=FCEU_fopen(name,ipsfn,"rb",0); + free(ipsfn); + + if(!fp) + { + FCEU_PrintError("Error opening \"%s\"!",name); + return 0; + } + + if(iNESLoad(name,fp,OverwriteVidMode)) + goto endlseq; + if(NSFLoad(fp)) + goto endlseq; + if(UNIFLoad(name,fp)) + goto endlseq; + if(FDSLoad(name,fp)) + goto endlseq; + + FCEU_PrintError("An error occurred while loading the file."); + FCEUD_PrintError("An error occurred while loading the file."); + FCEU_fclose(fp); + return 0; + + endlseq: + + FCEU_fclose(fp); + + FCEU_ResetVidSys(); + + if(FCEUGameInfo->type!=GIT_NSF) + if(FSettings.GameGenie) + OpenGenie(); + PowerNES(); + + FCEUSS_CheckStates(); + FCEUMOV_CheckMovies(); + + if(FCEUGameInfo->type!=GIT_NSF) + { + FCEU_LoadGamePalette(); + FCEU_LoadGameCheats(0); + } + + FCEU_ResetPalette(); + FCEU_ResetMessages(); // Save state, status messages, etc. + + strcpy(lastLoadedGameName, name); + + return(FCEUGameInfo); +} + + +int FCEUI_Initialize(void) +{ +#ifdef _USE_SHARED_MEMORY_ + // set up shared memory mappings + mapGameMemBlock = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, 131072,"fceu.GameMemBlock"); + if(mapGameMemBlock == NULL || GetLastError() == ERROR_ALREADY_EXISTS) + { + CloseHandle(mapGameMemBlock); + mapGameMemBlock = NULL; + GameMemBlock = (uint8 *) malloc(131072); + RAM = (uint8 *) malloc(2048); + } + else + { + GameMemBlock = (uint8 *)MapViewOfFile(mapGameMemBlock, FILE_MAP_WRITE, 0, 0, 0); + + // set up shared memory mappings + mapRAM = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, 0x800,"fceu.RAM"); + RAM = (uint8 *)MapViewOfFile(mapRAM, FILE_MAP_WRITE, 0, 0, 0); + } + + // Give RAM pointer to state structure + extern SFORMAT SFCPU[]; + SFCPU[6].v = RAM; + + //Bot input + mapBotInput = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0, 4096, "fceu.BotInput"); + BotInput = (uint32 *) MapViewOfFile(mapBotInput, FILE_MAP_WRITE, 0, 0, 0); + BotInput[0] = 0; + +#endif //_USE_SHARED_MEMORY_ + + if(!FCEU_InitVirtualVideo()) + return 0; + memset(&FSettings,0,sizeof(FSettings)); + FSettings.UsrFirstSLine[0]=8; + FSettings.UsrFirstSLine[1]=0; + FSettings.UsrLastSLine[0]=231; + FSettings.UsrLastSLine[1]=239; + FSettings.SoundVolume=100; + FCEUPPU_Init(); + X6502_Init(); + return 1; +} + +void FCEUI_Kill(void) +{ + FCEU_KillVirtualVideo(); + FCEU_KillGenie(); + +#ifdef _USE_SHARED_MEMORY_ + //clean up shared memory + if(mapRAM) + { + UnmapViewOfFile(mapRAM); + CloseHandle(mapRAM); + RAM = NULL; + } + else + { + free(RAM); + RAM = NULL; + } + if(mapGameMemBlock) + { + UnmapViewOfFile(mapGameMemBlock); + CloseHandle(mapGameMemBlock); + GameMemBlock = NULL; + } + else + { + free(GameMemBlock); + GameMemBlock = NULL; + } + + UnmapViewOfFile(mapBotInput); + CloseHandle(mapBotInput); + BotInput = NULL; +#endif +} + +int rapidAlternator = 0; +int AutoFirePattern[8] = {1,0,0,0,0,0,0,0}; +int AutoFirePatternLength = 2; +int AutoFireOffset = 0; + +void SetAutoFirePattern(int onframes, int offframes) +{ + int i; + for(i = 0; i < onframes && i < 8; i++) + { + AutoFirePattern[i] = 1; + } + for(;i < 8; i++) + { + AutoFirePattern[i] = 0; + } + if(onframes + offframes < 2) + { + AutoFirePatternLength = 2; + } + else if(onframes + offframes > 8) + { + AutoFirePatternLength = 8; + } + else + { + AutoFirePatternLength = onframes + offframes; + } +} + +void SetAutoFireOffset(int offset) +{ + if(offset < 0 || offset > 8) return; + AutoFireOffset = offset; +} + +void AutoFire(void) +{ + static int counter = 0; + counter = (++counter) % (8*7*5*3); + //If recording a movie, use the frame # for the autofire so the offset + //doesn't get screwed up when loading. + if(FCEUMOV_IsPlaying() || FCEUMOV_IsRecording()) + { + rapidAlternator= AutoFirePattern[(AutoFireOffset + FCEUMOV_GetFrame())%AutoFirePatternLength]; + } + else + { + rapidAlternator= AutoFirePattern[(AutoFireOffset + counter)%AutoFirePatternLength]; + } +} + +void UpdateRewind(void); + +void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int skip) +{ + int r,ssize; + +#ifdef _USE_SHARED_MEMORY_ + UpdateBasicBot(); +#endif + + FCEU_UpdateBot(); + + if(EmulationPaused&2) + EmulationPaused &= ~1; // clear paused flag temporarily (frame advance) + else if(EmulationPaused&1 || FCEU_BotMode()) + { + memcpy(XBuf, XBackBuf, 256*256); + FCEU_PutImage(); + *pXBuf=XBuf; + *SoundBuf=WaveFinal; + *SoundBufSize=0; + + return; + } + + if(!FCEU_BotMode()) + { + AutoFire(); + UpdateRewind(); + } + + FCEU_UpdateInput(); + if(geniestage!=1) FCEU_ApplyPeriodicCheats(); + r=FCEUPPU_Loop(skip); + + ssize=FlushEmulateSound(); + +//#ifdef WIN32 +// FCEUI_AviVideoUpdate(XBuf); +//#endif + + timestampbase += timestamp; + timestamp = 0; + + + *pXBuf=skip?0:XBuf; + *SoundBuf=WaveFinal; + *SoundBufSize=ssize; + + if(EmulationPaused&2) + { + EmulationPaused = 1; // restore paused flag +#ifdef WIN32 + #define SO_MUTEFA 16 + extern int soundoptions; + if(soundoptions&SO_MUTEFA) +#endif + *SoundBufSize=0; // keep sound muted + } +} + +void FCEUI_CloseGame(void) +{ + CloseGame(); +} + +void RestartMovieOrReset(int pow) +{ + extern int movie_readonly; + if(FCEUMOV_IsPlaying() || FCEUMOV_IsRecording() && movie_readonly) + { + extern char curMovieFilename[512]; + FCEUI_LoadMovie(curMovieFilename, movie_readonly, 0); + if(FCEUI_IsMovieActive()) + return; + } + + if(pow) + FCEUI_PowerNES(); + else + FCEUI_ResetNES(); +} + +void ResetNES(void) +{ + FCEUMOV_AddCommand(FCEUNPCMD_RESET); + if(!FCEUGameInfo) return; + GameInterface(GI_RESETM2); + FCEUSND_Reset(); + FCEUPPU_Reset(); + X6502_Reset(); + + // clear back baffer + extern uint8 *XBackBuf; + memset(XBackBuf,0,256*256); +} + +void FCEU_MemoryRand(uint8 *ptr, uint32 size) +{ + int x=0; + while(size) + { + *ptr=(x&4)?0xFF:0x00; + x++; + size--; + ptr++; + } +} + +void hand(X6502 *X, int type, unsigned int A) +{ + +} + +int suppressAddPowerCommand=0; // hack... yeah, I know... +void PowerNES(void) +{ + if(!suppressAddPowerCommand) + FCEUMOV_AddCommand(FCEUNPCMD_POWER); + if(!FCEUGameInfo) return; + + FCEU_CheatResetRAM(); + FCEU_CheatAddRAM(2,0,RAM); + + GeniePower(); + + FCEU_MemoryRand(RAM,0x800); + //memset(RAM,0xFF,0x800); + + SetReadHandler(0x0000,0xFFFF,ANull); + SetWriteHandler(0x0000,0xFFFF,BNull); + + SetReadHandler(0,0x7FF,ARAML); + SetWriteHandler(0,0x7FF,BRAML); + + SetReadHandler(0x800,0x1FFF,ARAMH); /* Part of a little */ + SetWriteHandler(0x800,0x1FFF,BRAMH); /* hack for a small speed boost. */ + + InitializeInput(); + FCEUSND_Power(); + FCEUPPU_Power(); + + /* Have the external game hardware "powered" after the internal NES stuff. + Needed for the NSF code and VS System code. + */ + GameInterface(GI_POWER); + if(FCEUGameInfo->type==GIT_VSUNI) + FCEU_VSUniPower(); + + timestampbase=0; + X6502_Power(); + FCEU_PowerCheats(); + // clear back baffer + extern uint8 *XBackBuf; + memset(XBackBuf,0,256*256); +} + +void FCEU_ResetVidSys(void) +{ + int w; + + if(FCEUGameInfo->vidsys==GIV_NTSC) + w=0; + else if(FCEUGameInfo->vidsys==GIV_PAL) + w=1; + else + w=FSettings.PAL; + + PAL=w?1:0; + FCEUPPU_SetVideoSystem(w); + SetSoundVariables(); +} + +FCEUS FSettings; + +void FCEU_printf(char *format, ...) +{ + char temp[2048]; + + va_list ap; + + va_start(ap,format); + vsprintf(temp,format,ap); + FCEUD_Message(temp); + + va_end(ap); +} + +void FCEU_PrintError(char *format, ...) +{ + char temp[2048]; + + va_list ap; + + va_start(ap,format); + vsprintf(temp,format,ap); + FCEUD_PrintError(temp); + + va_end(ap); +} + +void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall) +{ + FSettings.UsrFirstSLine[0]=ntscf; + FSettings.UsrLastSLine[0]=ntscl; + FSettings.UsrFirstSLine[1]=palf; + FSettings.UsrLastSLine[1]=pall; + if(PAL) + { + FSettings.FirstSLine=FSettings.UsrFirstSLine[1]; + FSettings.LastSLine=FSettings.UsrLastSLine[1]; + } + else + { + FSettings.FirstSLine=FSettings.UsrFirstSLine[0]; + FSettings.LastSLine=FSettings.UsrLastSLine[0]; + } + +} + +void FCEUI_SetVidSystem(int a) +{ + FSettings.PAL=a?1:0; + if(FCEUGameInfo) + { + FCEU_ResetVidSys(); + FCEU_ResetPalette(); + } +} + +int FCEUI_GetCurrentVidSystem(int *slstart, int *slend) +{ + if(slstart) + *slstart=FSettings.FirstSLine; + if(slend) + *slend=FSettings.LastSLine; + return(PAL); +} + +void FCEUI_SetGameGenie(int a) +{ + FSettings.GameGenie=a?1:0; +} + +void FCEUI_SetSnapName(int a) +{ + FSettings.SnapName=a; +} + +int32 FCEUI_GetDesiredFPS(void) +{ + if(PAL) + return(838977920); // ~50.007 + else + return(1008307711); // ~60.1 +} + +int FCEUI_EmulationPaused(void) +{ + return (EmulationPaused&1); +} + +//mbg merge 7/18/06 added +//ideally maybe we shouldnt be using this, but i need it for quick merging +void FCEUI_SetEmulationPaused(int val) { + EmulationPaused = val; +} + +void FCEUI_ToggleEmulationPause(void) +{ + EmulationPaused = (EmulationPaused&1)^1; +} + +void FCEUI_FrameAdvance(void) +{ + EmulationPaused |= 1|2; +} + +static int RewindCounter = 0; + +void UpdateRewind(void) +{ + if(!EnableRewind) + return; + + char * f; + RewindCounter = (RewindCounter + 1) % 256; + if(RewindCounter == 0) + { + RewindIndex = (RewindIndex + 1) % 4; + f = FCEU_MakeFName(FCEUMKF_REWINDSTATE,RewindIndex,0); + FCEUSS_Save(f); + free(f); + RewindStatus[RewindIndex] = 1; + } +} + +void FCEUI_Rewind(void) +{ + if(!EnableRewind) + return; + + if(RewindStatus[RewindIndex] == 1) + { + char * f; + f = FCEU_MakeFName(FCEUMKF_REWINDSTATE,RewindIndex,0); + FCEUSS_Load(f); + free(f); + + //Set pointer to previous available slot + if(RewindStatus[(RewindIndex + 3)%4] == 1) + { + RewindIndex = (RewindIndex + 3)%4; + } + + //Reset time to next rewind save + RewindCounter = 0; + } +} +