3 Commits

Author SHA1 Message Date
clobber 07de1ad746 Merge pull request #13 from ShutOstrich/master 2023-09-06 18:50:19 -06:00
ShutOstrich 23bc100386 Update to FCEUX 2.6.6 2023-08-27 23:45:32 +02:00
ShutOstrich f2c6ba0c43 Disable all messages 2023-08-27 23:45:26 +02:00
81 changed files with 2917 additions and 472 deletions
+14
View File
@@ -72,6 +72,7 @@
8F28FD5229FD3E7D008FC4A9 /* inx007t.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F28FD4F29FD3E7D008FC4A9 /* inx007t.cpp */; };
8F28FD5529FD3EA4008FC4A9 /* debugsymboltable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F28FD5329FD3EA4008FC4A9 /* debugsymboltable.cpp */; };
8F28FD5829FD3EB8008FC4A9 /* mutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F28FD5629FD3EB8008FC4A9 /* mutex.cpp */; };
8F5A69CF2A9BF26400B405DB /* ld65dbg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F5A69CB2A9BF26400B405DB /* ld65dbg.cpp */; };
945942D014E4F2DC0015D2AA /* FCEUX.icns in Resources */ = {isa = PBXBuildFile; fileRef = 945942CF14E4F2DC0015D2AA /* FCEUX.icns */; };
949BBA741A9EF079007B49CC /* 01-222.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949BB7521A9EED55007B49CC /* 01-222.cpp */; };
949BBA751A9EF079007B49CC /* 09-034a.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949BB7531A9EED55007B49CC /* 09-034a.cpp */; };
@@ -346,6 +347,12 @@
8F28FD5429FD3EA4008FC4A9 /* debugsymboltable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debugsymboltable.h; sourceTree = "<group>"; };
8F28FD5629FD3EB8008FC4A9 /* mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mutex.cpp; sourceTree = "<group>"; };
8F28FD5729FD3EB8008FC4A9 /* mutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mutex.h; sourceTree = "<group>"; };
8F5A69C72A9BF26400B405DB /* timeStamp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timeStamp.cpp; sourceTree = "<group>"; };
8F5A69C82A9BF26400B405DB /* profiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = profiler.h; sourceTree = "<group>"; };
8F5A69C92A9BF26400B405DB /* profiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profiler.cpp; sourceTree = "<group>"; };
8F5A69CA2A9BF26400B405DB /* timeStamp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timeStamp.h; sourceTree = "<group>"; };
8F5A69CB2A9BF26400B405DB /* ld65dbg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ld65dbg.cpp; sourceTree = "<group>"; };
8F5A69CC2A9BF26400B405DB /* ld65dbg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ld65dbg.h; sourceTree = "<group>"; };
945942CE14E4EF180015D2AA /* OENESSystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OENESSystemResponderClient.h; path = ../OpenEmu/SystemPlugins/NES/OENESSystemResponderClient.h; sourceTree = "<group>"; };
945942CF14E4F2DC0015D2AA /* FCEUX.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = FCEUX.icns; sourceTree = "<group>"; };
949BB74E1A9EED55007B49CC /* asm.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = asm.cpp; sourceTree = "<group>"; };
@@ -816,6 +823,8 @@
949BB9A11A9EED59007B49CC /* input */,
949BB9B61A9EED59007B49CC /* input.cpp */,
949BB9B71A9EED59007B49CC /* input.h */,
8F5A69CB2A9BF26400B405DB /* ld65dbg.cpp */,
8F5A69CC2A9BF26400B405DB /* ld65dbg.h */,
949BB9F71A9EED5A007B49CC /* lua-engine.cpp */,
949BB9F81A9EED5A007B49CC /* movie.cpp */,
949BB9F91A9EED5A007B49CC /* movie.h */,
@@ -832,6 +841,8 @@
949BBA0B1A9EED5A007B49CC /* ppu.cpp */,
949BBA0C1A9EED5A007B49CC /* ppu.h */,
949BBA0D1A9EED5A007B49CC /* pputile.inc */,
8F5A69C92A9BF26400B405DB /* profiler.cpp */,
8F5A69C82A9BF26400B405DB /* profiler.h */,
949BBA0F1A9EED5A007B49CC /* sound.cpp */,
949BBA101A9EED5A007B49CC /* sound.h */,
949BBA111A9EED5A007B49CC /* state.cpp */,
@@ -1185,6 +1196,8 @@
949BBA291A9EED5B007B49CC /* memory.h */,
8F28FD5629FD3EB8008FC4A9 /* mutex.cpp */,
8F28FD5729FD3EB8008FC4A9 /* mutex.h */,
8F5A69C72A9BF26400B405DB /* timeStamp.cpp */,
8F5A69CA2A9BF26400B405DB /* timeStamp.h */,
949BBA2B1A9EED5B007B49CC /* unzip.cpp */,
949BBA2C1A9EED5B007B49CC /* unzip.h */,
949BBA2D1A9EED5B007B49CC /* valuearray.h */,
@@ -1463,6 +1476,7 @@
949BBAF61A9EF07A007B49CC /* sa-9602b.cpp in Sources */,
870D6EA61D4C1F82001E8FC6 /* BMW8544.cpp in Sources */,
870D6EB41D4C20B3001E8FC6 /* inlnsf.cpp in Sources */,
8F5A69CF2A9BF26400B405DB /* ld65dbg.cpp in Sources */,
949BBAF71A9EF07A007B49CC /* sachen.cpp in Sources */,
949BBAF81A9EF07A007B49CC /* sc-127.cpp in Sources */,
870D6EB31D4C20B3001E8FC6 /* hp898f.cpp in Sources */,
+1 -1
View File
@@ -17,7 +17,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>2.6.5</string>
<string>2.6.6</string>
<key>NSPrincipalClass</key>
<string>OEGameCoreController</string>
<key>OEGameCoreClass</key>
+31 -2
View File
@@ -22,6 +22,12 @@ if ( ${QHELP} )
add_definitions( -D_USE_QHELP )
endif()
if ( ${FCEU_PROFILER_ENABLE} )
message( STATUS "FCEU Profiler Enabled")
add_definitions( -D__FCEU_PROFILER_ENABLE__ )
endif()
if ( ${QT6} )
find_package( Qt6 REQUIRED COMPONENTS Widgets OpenGL OpenGLWidgets ${QtHelpModule})
add_definitions( ${Qt6Widgets_DEFINITIONS} ${Qt6Help_DEFINITIONS} ${Qt6OpenGLWidgets_DEFINITIONS} )
@@ -41,12 +47,15 @@ if(WIN32)
add_definitions( -DMSVC -D_CRT_SECURE_NO_WARNINGS )
add_definitions( -D__SDL__ -D__QT_DRIVER__ -DQT_DEPRECATED_WARNINGS )
add_definitions( -DFCEUDEF_DEBUGGER )
add_definitions( -D_USE_LIBARCHIVE )
add_definitions( /wd4267 /wd4244 )
#add_definitions( /wd4018 ) # Integer comparison sign mismatch warnings
include_directories( ${SDL_INSTALL_PREFIX}/SDL2/include )
include_directories( ${LIBARCHIVE_INSTALL_PREFIX}/libarchive/include )
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib )
set( OPENGL_LDFLAGS OpenGL::GL )
set( SDL2_LDFLAGS ${SDL_INSTALL_PREFIX}/SDL2/lib/x64/SDL2.lib )
set( LIBARCHIVE_LDFLAGS ${LIBARCHIVE_INSTALL_PREFIX}/libarchive/lib/archive.lib )
set( SYS_LIBS wsock32 ws2_32 vfw32 Htmlhelp )
set(APP_ICON_RESOURCES_WINDOWS ${CMAKE_SOURCE_DIR}/icons/fceux.rc )
@@ -93,6 +102,12 @@ else(WIN32)
#endif()
add_definitions( -D__QT_DRIVER__ -DQT_DEPRECATED_WARNINGS )
if ( ${GPROF_ENABLE} )
add_definitions( -pg )
set( GPROF_LDFLAGS -pg )
message( STATUS "GNU Profiling Enabled" )
endif()
if ( ${ASAN_ENABLE} )
add_definitions( -fsanitize=address -fsanitize=bounds-strict )
add_definitions( -fsanitize=undefined -fno-sanitize=vptr )
@@ -110,6 +125,13 @@ else(WIN32)
add_definitions( -D_SYSTEM_MINIZIP ${MINIZIP_CFLAGS} )
endif()
pkg_check_modules( LIBARCHIVE libarchive)
if ( ${LIBARCHIVE_FOUND} )
message( STATUS "Using System Libarchive Library ${LIBARCHIVE_VERSION}" )
add_definitions( -D_USE_LIBARCHIVE ${LIBARCHIVE_CFLAGS} )
endif()
pkg_check_modules( X264 x264)
if ( ${X264_FOUND} )
@@ -287,11 +309,13 @@ set(SRC_CORE
${CMAKE_CURRENT_SOURCE_DIR}/filter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ines.cpp
${CMAKE_CURRENT_SOURCE_DIR}/input.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ld65dbg.cpp
${CMAKE_CURRENT_SOURCE_DIR}/movie.cpp
${CMAKE_CURRENT_SOURCE_DIR}/netplay.cpp
${CMAKE_CURRENT_SOURCE_DIR}/nsf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/oldmovie.cpp
${CMAKE_CURRENT_SOURCE_DIR}/palette.cpp
${CMAKE_CURRENT_SOURCE_DIR}/profiler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ppu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/sound.cpp
${CMAKE_CURRENT_SOURCE_DIR}/state.cpp
@@ -503,6 +527,7 @@ set(SRC_CORE
${CMAKE_CURRENT_SOURCE_DIR}/utils/md5.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utils/memory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utils/mutex.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utils/timeStamp.cpp
)
@@ -525,6 +550,8 @@ set(SRC_DRIVERS_SDL
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleWindow.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleViewerGL.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleViewerSDL.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleViewerQWidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleViewerInterface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/InputConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GamePadConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/FamilyKeyboard.cpp
@@ -550,6 +577,7 @@ set(SRC_DRIVERS_SDL
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleUtilities.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleVideoConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleSoundConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/StateRecorderConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/iNesHeaderEditor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/SplashScreen.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TraceLogger.cpp
@@ -634,14 +662,15 @@ add_executable( ${APP_NAME} ${SOURCES} ../resources.qrc
${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp)
endif()
target_link_libraries( ${APP_NAME} ${ASAN_LDFLAGS}
target_link_libraries( ${APP_NAME}
${ASAN_LDFLAGS} ${GPROF_LDFLAGS}
${${Qt}Widgets_LIBRARIES}
${${Qt}Help_LIBRARIES}
${${Qt}OpenGL_LIBRARIES}
${${Qt}OpenGLWidgets_LIBRARIES}
${OPENGL_LDFLAGS}
${SDL2_LDFLAGS}
${MINIZIP_LDFLAGS} ${ZLIB_LIBRARIES}
${MINIZIP_LDFLAGS} ${ZLIB_LIBRARIES} ${LIBARCHIVE_LDFLAGS}
${LUA_LDFLAGS} ${X264_LDFLAGS} ${X265_LDFLAGS} ${LIBAV_LDFLAGS}
${SYS_LIBS}
)
+2 -3
View File
@@ -24,7 +24,7 @@
static uint16 latchea;
static uint8 latched;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
static SFORMAT StateRegs[] =
{
{ &latchea, 2, "AREG" },
@@ -108,8 +108,7 @@ void Mapper15_Init(CartInfo *info) {
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
AddExState(&StateRegs, ~0, 0, 0);
+4 -7
View File
@@ -27,7 +27,7 @@
static uint8 laststrobe, trigger;
static uint8 reg[8];
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
static writefunc pcmwrite;
@@ -123,8 +123,7 @@ void Mapper164_Init(CartInfo *info) {
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
GameStateRestore = StateRestore;
@@ -172,8 +171,7 @@ void Mapper163_Init(CartInfo *info) {
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
@@ -223,8 +221,7 @@ void UNLFS304_Init(CartInfo *info) {
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
GameStateRestore = StateRestore;
+2 -3
View File
@@ -23,7 +23,7 @@
static uint8 reg;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
static SFORMAT StateRegs[] =
{
@@ -73,8 +73,7 @@ void Mapper177_Init(CartInfo *info) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(&StateRegs, ~0, 0, 0);
+2 -3
View File
@@ -27,7 +27,7 @@
static uint8 reg[4];
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
// Tennis with VR sensor, very simple behaviour
extern void GetMouseData(uint32 (&md)[3]);
@@ -192,8 +192,7 @@ void Mapper178_Init(CartInfo *info) {
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
+2 -3
View File
@@ -24,7 +24,7 @@ static uint8 preg[4], creg[8];
static uint8 IRQa, mirr;
static int32 IRQCount, IRQLatch;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
static SFORMAT StateRegs[] =
{
@@ -125,8 +125,7 @@ void Mapper18_Init(CartInfo *info) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(&StateRegs, ~0, 0, 0);
+2 -3
View File
@@ -22,7 +22,7 @@
static uint8 regs[8];
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE = 0;
static SFORMAT StateRegs[] =
{
@@ -79,8 +79,7 @@ void Mapper246_Init(CartInfo *info) {
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(&StateRegs, ~0, 0, 0);
+3 -4
View File
@@ -23,9 +23,9 @@
static uint8 creg[8], preg[2];
static int32 IRQa, IRQCount, IRQClock, IRQLatch;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
static uint8 *CHRRAM = NULL;
static uint32 CHRRAMSIZE;
static uint32 CHRRAMSIZE=0;
static SFORMAT StateRegs[] =
{
@@ -127,8 +127,7 @@ void Mapper252_Init(CartInfo *info) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
+3 -4
View File
@@ -23,9 +23,9 @@
static uint8 chrlo[8], chrhi[8], prg[2], mirr, vlock;
static int32 IRQa, IRQCount, IRQLatch, IRQClock;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
static uint8 *CHRRAM = NULL;
static uint32 CHRRAMSIZE;
static uint32 CHRRAMSIZE=0;
static SFORMAT StateRegs[] =
{
@@ -144,8 +144,7 @@ void Mapper253_Init(CartInfo *info) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(&StateRegs, ~0, 0, 0);
+1
View File
@@ -58,6 +58,7 @@ static void Mapper354_Sync(void)
setprg32(0x8000, prg >> 1 | 3);
break;
}
SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], (latchAddr & 8) ? 0 : 1);
setchr8(0);
setmirror(latchData & 0x40 ? MI_H : MI_V);
}
+2 -3
View File
@@ -24,7 +24,7 @@ static uint8 chr_reg[4];
static uint8 kogame, prg_reg, nt1, nt2, mirr;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE, count;
static uint32 WRAMSIZE=0, count=0;
static SFORMAT StateRegs[] =
{
@@ -156,8 +156,7 @@ void Mapper68_Init(CartInfo *info) {
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
AddExState(&StateRegs, ~0, 0, 0);
+2 -3
View File
@@ -25,7 +25,7 @@ static uint8 cmdreg, preg[4], creg[8], mirr;
static uint8 IRQa;
static int32 IRQCount;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
static SFORMAT StateRegs[] =
{
@@ -266,8 +266,7 @@ void Mapper69_Init(CartInfo *info) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
GameStateRestore = StateRestore;
Mapper69_ESI();
+1 -2
View File
@@ -169,8 +169,7 @@ void Mapper80_Init(CartInfo *info) {
GameStateRestore = StateRestore;
if (info->battery) {
info->SaveGame[0] = wram;
info->SaveGameLen[0] = 256;
info->addSaveGameBuf( wram, sizeof(wram) );
}
AddExState(&StateRegs80, ~0, 0, 0);
+2 -3
View File
@@ -25,7 +25,7 @@
static uint8 regs[9], ctrl;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
static SFORMAT StateRegs[] =
{
@@ -90,8 +90,7 @@ void Mapper82_Init(CartInfo *info) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
+1 -2
View File
@@ -92,8 +92,7 @@ void MapperNNN_Init(CartInfo *info) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
*/
AddExState(&StateRegs, ~0, 0, 0);
+27 -12
View File
@@ -26,7 +26,8 @@ static uint8 dipswitch;
static void (*WSync)(void);
static readfunc defread;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
static uint8 hasBattery = 0;
static DECLFW(LatchWrite) {
latche = A;
@@ -77,8 +78,7 @@ static void Latch_Init(CartInfo *info, void (*proc)(void), readfunc func, uint16
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
}
@@ -221,6 +221,23 @@ void Mapper92_Init(CartInfo *info) {
Latch_Init(info, M92Sync, NULL, 0x80B0, 0x8000, 0xFFFF, 0);
}
//------------------ Map 174 ---------------------------
static void M174Sync(void) {
if (latche & 0x80) {
setprg32(0x8000, (latche >> 5) & 3);
} else {
setprg16(0x8000, (latche >> 4) & 7);
setprg16(0xC000, (latche >> 4) & 7);
}
setchr8((latche >> 1) & 7);
setmirror((latche & 1) ^ 1);
}
void Mapper174_Init(CartInfo *info) {
Latch_Init(info, M174Sync, NULL, 0, 0x8000, 0xFFFF, 0);
}
//------------------ Map 200 ---------------------------
static void M200Sync(void) {
@@ -342,20 +359,17 @@ void Mapper217_Init(CartInfo *info) {
}
//------------------ Map 227 ---------------------------
static void M227Sync(void) {
uint32 S = latche & 1;
uint32 p = ((latche >> 2) & 0x1F) + ((latche & 0x100) >> 3);
uint32 L = (latche >> 9) & 1;
// ok, according to nesdev wiki (refrenced to the nesdev dumping thread) there is a CHR write protection bit7.
// however, this bit clearly determined a specific PRG layout for some game but does not meant to have additional
// functionality. as I see from the menu code, it disables the chr writing before run an actual game.
// this fix here makes happy both waixing rpgs and multigame menus at once. can't veryfy it on a hardware
// but if I find some i'll definitly do this.
if ((latche & 0xF000) == 0xF000)
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0);
// Only Waixing appear to have battery flag enabled, while multicarts don't.
// Multicarts needs CHR-RAM protect in NROM modes, so only apply CHR-RAM protect
// on non battery-enabled carts.
if (!hasBattery && (latche & 0x80) == 0x80)
/* CHR-RAM write protect hack, needed for some multicarts */
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0);
else
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1);
@@ -393,6 +407,7 @@ static void M227Sync(void) {
void Mapper227_Init(CartInfo *info) {
Latch_Init(info, M227Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1);
hasBattery = info->battery;
}
//------------------ Map 229 ---------------------------
+5 -9
View File
@@ -29,7 +29,7 @@ static uint8 IRQa;
static int16 IRQCount, IRQLatch;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
static SFORMAT StateRegs[] =
{
@@ -317,8 +317,7 @@ void Mapper16_Init(CartInfo *info) {
MapIRQHook = BandaiIRQHook;
info->battery = 1;
info->SaveGame[0] = x24c0x_data + 256;
info->SaveGameLen[0] = 256;
info->addSaveGameBuf( x24c0x_data + 256, 256 );
AddExState(x24c0x_data, 256, 0, "DATA");
AddExState(&x24c02StateRegs, ~0, 0, 0);
@@ -333,8 +332,7 @@ void Mapper159_Init(CartInfo *info) {
MapIRQHook = BandaiIRQHook;
info->battery = 1;
info->SaveGame[0] = x24c0x_data;
info->SaveGameLen[0] = 128;
info->addSaveGameBuf( x24c0x_data, 128 );
AddExState(x24c0x_data, 128, 0, "DATA");
AddExState(&x24c01StateRegs, ~0, 0, 0);
@@ -378,8 +376,7 @@ void Mapper153_Init(CartInfo *info) {
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
GameStateRestore = StateRestore;
@@ -599,8 +596,7 @@ void Mapper157_Init(CartInfo *info) {
GameInfo->cspecial = SIS_DATACH;
info->battery = 1;
info->SaveGame[0] = x24c0x_data;
info->SaveGameLen[0] = 512;
info->addSaveGameBuf( x24c0x_data, 512 );
AddExState(x24c0x_data, 512, 0, "DATA");
AddExState(&x24c01StateRegs, ~0, 0, 0);
AddExState(&x24c02StateRegs, ~0, 0, 0);
+1 -2
View File
@@ -252,8 +252,7 @@ void Mapper111_Init(CartInfo *info) {
if (flash)
{
FLASHROM = (uint8*)FCEU_gmalloc(FLASHROMSIZE);
info->SaveGame[0] = FLASHROM;
info->SaveGameLen[0] = FLASHROMSIZE;
info->addSaveGameBuf( FLASHROM, FLASHROMSIZE );
AddExState(FLASHROM, FLASHROMSIZE, 0, "FROM");
AddExState(&FlashRegs, ~0, 0, 0);
+1 -2
View File
@@ -454,8 +454,7 @@ void CommonInit(CartInfo* info, int submapper)
Flash[i] = PRGptr[ROM_CHIP][i % PRGsize[ROM_CHIP]];
}
SetupCartPRGMapping(FLASH_CHIP, Flash, PRGsize[ROM_CHIP], 1);
info->SaveGame[1] = Flash;
info->SaveGameLen[1] = PRGsize[ROM_CHIP];
info->addSaveGameBuf( Flash, PRGsize[ROM_CHIP] );
}
AddExState(EXPREGS, 4, 0, "EXPR");
+66 -95
View File
@@ -16,11 +16,11 @@
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Very complicated homebrew multicart mapper with.
* The code is so obscured and weird because it's ported from Verilog CPLD source code:
*
* Very complicated homebrew multicart mapper with.
* The code is so obscured and weird because it's ported from Verilog CPLD source code:
* https://github.com/ClusterM/coolgirl-famicom-multicart/blob/master/CoolGirl_mappers.vh
*
*
* Range: $5000-$5FFF
*
* Mask: $5007
@@ -103,14 +103,12 @@ const uint32 FLASH_SECTOR_SIZE = 128 * 1024;
const int ROM_CHIP = 0x00;
const int WRAM_CHIP = 0x10;
const int FLASH_CHIP = 0x11;
const int CHR_RAM_CHIP = 0x12;
const int CFI_CHIP = 0x13;
static int CHR_SIZE = 0;
static uint32 WRAM_SIZE = 0;
static uint8 *WRAM = NULL;
static uint32 CHR_RAM_SIZE = 0;
static uint8 *CHR_RAM;
static uint8 *SAVE_FLASH = NULL;
static uint8* WRAM = NULL;
static uint8* SAVE_FLASH = NULL;
static uint8* CFI;
static uint8 sram_enabled = 0;
@@ -388,75 +386,75 @@ static void COOLGIRL_Sync_CHR(void) {
int chr_shift_left = 0;
// enable or disable writes to CHR RAM, setup CHR mask
SetupCartCHRMapping(CHR_RAM_CHIP, CHR_RAM, ((((~(chr_mask >> 13) & 0x3F) + 1) * 0x2000 - 1) & (CHR_RAM_SIZE - 1)) + 1, can_write_chr);
SetupCartCHRMapping(0, UNIFchrrama, ((((~(chr_mask >> 13) & 0x3F) + 1) * 0x2000 - 1) & (CHR_SIZE - 1)) + 1, can_write_chr);
switch (chr_mode & 7)
{
default:
case 0:
setchr8r(0x12, chr_bank_a >> 3 >> chr_shift_right << chr_shift_left);
setchr8(chr_bank_a >> 3 >> chr_shift_right << chr_shift_left);
break;
case 1:
setchr4r(0x12, 0x0000, mapper_163_latch >> chr_shift_right << chr_shift_left);
setchr4r(0x12, 0x1000, mapper_163_latch >> chr_shift_right << chr_shift_left);
setchr4(0x0000, mapper_163_latch >> chr_shift_right << chr_shift_left);
setchr4(0x1000, mapper_163_latch >> chr_shift_right << chr_shift_left);
break;
case 2:
setchr2r(0x12, 0x0000, chr_bank_a >> 1 >> chr_shift_right << chr_shift_left);
setchr2(0x0000, chr_bank_a >> 1 >> chr_shift_right << chr_shift_left);
TKSMIR[0] = TKSMIR[1] = chr_bank_a;
setchr2r(0x12, 0x0800, chr_bank_c >> 1 >> chr_shift_right << chr_shift_left);
setchr2(0x0800, chr_bank_c >> 1 >> chr_shift_right << chr_shift_left);
TKSMIR[2] = TKSMIR[3] = chr_bank_c;
setchr1r(0x12, 0x1000, chr_bank_e >> chr_shift_right << chr_shift_left);
setchr1(0x1000, chr_bank_e >> chr_shift_right << chr_shift_left);
TKSMIR[4] = chr_bank_e;
setchr1r(0x12, 0x1400, chr_bank_f >> chr_shift_right << chr_shift_left);
setchr1(0x1400, chr_bank_f >> chr_shift_right << chr_shift_left);
TKSMIR[5] = chr_bank_f;
setchr1r(0x12, 0x1800, chr_bank_g >> chr_shift_right << chr_shift_left);
setchr1(0x1800, chr_bank_g >> chr_shift_right << chr_shift_left);
TKSMIR[6] = chr_bank_g;
setchr1r(0x12, 0x1C00, chr_bank_h >> chr_shift_right << chr_shift_left);
setchr1(0x1C00, chr_bank_h >> chr_shift_right << chr_shift_left);
TKSMIR[7] = chr_bank_h;
break;
case 3:
setchr1r(0x12, 0x0000, chr_bank_e >> chr_shift_right << chr_shift_left);
setchr1(0x0000, chr_bank_e >> chr_shift_right << chr_shift_left);
TKSMIR[0] = chr_bank_e;
setchr1r(0x12, 0x0400, chr_bank_f >> chr_shift_right << chr_shift_left);
setchr1(0x0400, chr_bank_f >> chr_shift_right << chr_shift_left);
TKSMIR[1] = chr_bank_f;
setchr1r(0x12, 0x0800, chr_bank_g >> chr_shift_right << chr_shift_left);
setchr1(0x0800, chr_bank_g >> chr_shift_right << chr_shift_left);
TKSMIR[2] = chr_bank_g;
setchr1r(0x12, 0x0C00, chr_bank_h >> chr_shift_right << chr_shift_left);
setchr1(0x0C00, chr_bank_h >> chr_shift_right << chr_shift_left);
TKSMIR[3] = chr_bank_h;
setchr2r(0x12, 0x1000, chr_bank_a >> 1 >> chr_shift_right << chr_shift_left);
setchr2(0x1000, chr_bank_a >> 1 >> chr_shift_right << chr_shift_left);
TKSMIR[4] = TKSMIR[5] = chr_bank_a;
setchr2r(0x12, 0x1800, chr_bank_c >> 1 >> chr_shift_right << chr_shift_left);
setchr2(0x1800, chr_bank_c >> 1 >> chr_shift_right << chr_shift_left);
TKSMIR[6] = TKSMIR[7] = chr_bank_c;
break;
case 4:
setchr4r(0x12, 0x0000, chr_bank_a >> 2 >> chr_shift_right << chr_shift_left);
setchr4r(0x12, 0x1000, chr_bank_e >> 2 >> chr_shift_right << chr_shift_left);
setchr4(0x0000, chr_bank_a >> 2 >> chr_shift_right << chr_shift_left);
setchr4(0x1000, chr_bank_e >> 2 >> chr_shift_right << chr_shift_left);
break;
case 5:
if (!ppu_latch0)
setchr4r(0x12, 0x0000, chr_bank_a >> 2 >> chr_shift_right << chr_shift_left);
setchr4(0x0000, chr_bank_a >> 2 >> chr_shift_right << chr_shift_left);
else
setchr4r(0x12, 0x0000, chr_bank_b >> 2 >> chr_shift_right << chr_shift_left);
setchr4(0x0000, chr_bank_b >> 2 >> chr_shift_right << chr_shift_left);
if (!ppu_latch1)
setchr4r(0x12, 0x1000, chr_bank_e >> 2 >> chr_shift_right << chr_shift_left);
setchr4(0x1000, chr_bank_e >> 2 >> chr_shift_right << chr_shift_left);
else
setchr4r(0x12, 0x1000, chr_bank_f >> 2 >> chr_shift_right << chr_shift_left);
setchr4(0x1000, chr_bank_f >> 2 >> chr_shift_right << chr_shift_left);
break;
case 6:
setchr2r(0x12, 0x0000, chr_bank_a >> 1 >> chr_shift_right << chr_shift_left);
setchr2r(0x12, 0x0800, chr_bank_c >> 1 >> chr_shift_right << chr_shift_left);
setchr2r(0x12, 0x1000, chr_bank_e >> 1 >> chr_shift_right << chr_shift_left);
setchr2r(0x12, 0x1800, chr_bank_g >> 1 >> chr_shift_right << chr_shift_left);
setchr2(0x0000, chr_bank_a >> 1 >> chr_shift_right << chr_shift_left);
setchr2(0x0800, chr_bank_c >> 1 >> chr_shift_right << chr_shift_left);
setchr2(0x1000, chr_bank_e >> 1 >> chr_shift_right << chr_shift_left);
setchr2(0x1800, chr_bank_g >> 1 >> chr_shift_right << chr_shift_left);
break;
case 7:
setchr1r(0x12, 0x0000, chr_bank_a >> chr_shift_right << chr_shift_left);
setchr1r(0x12, 0x0400, chr_bank_b >> chr_shift_right << chr_shift_left);
setchr1r(0x12, 0x0800, chr_bank_c >> chr_shift_right << chr_shift_left);
setchr1r(0x12, 0x0C00, chr_bank_d >> chr_shift_right << chr_shift_left);
setchr1r(0x12, 0x1000, chr_bank_e >> chr_shift_right << chr_shift_left);
setchr1r(0x12, 0x1400, chr_bank_f >> chr_shift_right << chr_shift_left);
setchr1r(0x12, 0x1800, chr_bank_g >> chr_shift_right << chr_shift_left);
setchr1r(0x12, 0x1C00, chr_bank_h >> chr_shift_right << chr_shift_left);
setchr1(0x0000, chr_bank_a >> chr_shift_right << chr_shift_left);
setchr1(0x0400, chr_bank_b >> chr_shift_right << chr_shift_left);
setchr1(0x0800, chr_bank_c >> chr_shift_right << chr_shift_left);
setchr1(0x0C00, chr_bank_d >> chr_shift_right << chr_shift_left);
setchr1(0x1000, chr_bank_e >> chr_shift_right << chr_shift_left);
setchr1(0x1400, chr_bank_f >> chr_shift_right << chr_shift_left);
setchr1(0x1800, chr_bank_g >> chr_shift_right << chr_shift_left);
setchr1(0x1C00, chr_bank_h >> chr_shift_right << chr_shift_left);
break;
}
}
@@ -468,10 +466,10 @@ static void COOLGIRL_Sync_Mirroring(void) {
setmirror((mirroring < 2) ? (mirroring ^ 1) : mirroring);
}
else { // four screen mode
vnapage[0] = CHR_RAM + 0x3F000;
vnapage[1] = CHR_RAM + 0x3F400;
vnapage[2] = CHR_RAM + 0x3F800;
vnapage[3] = CHR_RAM + 0x3FC00;
vnapage[0] = UNIFchrrama + 0x3F000;
vnapage[1] = UNIFchrrama + 0x3F400;
vnapage[2] = UNIFchrrama + 0x3F800;
vnapage[3] = UNIFchrrama + 0x3FC00;
}
}
@@ -509,9 +507,8 @@ static DECLFW(COOLGIRL_Flash_Write) {
uint32 sector_address = sector * FLASH_SECTOR_SIZE;
for (uint32 i = sector_address; i < sector_address + FLASH_SECTOR_SIZE; i++)
SAVE_FLASH[i % SAVE_FLASH_SIZE] = 0xFF;
FCEU_printf("Flash sector #%d is erased: 0x%08x - 0x%08x.\n", sector, sector_address, sector_address + FLASH_SECTOR_SIZE - 1);
flash_state = 0;
}
}
// write byte
if ((flash_state == 4) &&
@@ -557,7 +554,6 @@ static DECLFW(COOLGIRL_WRITE) {
if (A >= 0x5000 && A < 0x6000 && !lockout)
{
//FCEU_printf("Write: %02x => %04x\n", V, A);
switch (A & 7)
{
case 0:
@@ -573,7 +569,6 @@ static DECLFW(COOLGIRL_WRITE) {
// {chr_mask[18], prg_mask[20:14]} = cpu_data_in[7:0];
SET_BITS(chr_mask, "18", V, "7");
SET_BITS(prg_mask, "20:14", V, "6:0");
//FCEU_printf("REG_prg_mask: %02x\n", REG_prg_mask);
break;
case 3:
// {prg_mode[2:0], chr_bank_a[7:3]} = cpu_data_in[7:0];
@@ -886,7 +881,7 @@ static DECLFW(COOLGIRL_WRITE) {
if (mapper == 0b000100)
{
// prg_bank_a[5:1] = cpu_data_in[4:0];
SET_BITS(chr_bank_a, "5:1", V, "4:0");
SET_BITS(prg_bank_a, "5:1", V, "4:0");
// mirroring = { 1'b0, ~cpu_data_in[7]};
mirroring = get_bits(V, "7") ^ 1;
}
@@ -1176,7 +1171,6 @@ static DECLFW(COOLGIRL_WRITE) {
// Mapper #1 - MMC1
/*
r0 - load register
flag0 - 16KB of SRAM (SOROM)
*/
if (mapper == 0b010000)
@@ -1230,7 +1224,7 @@ static DECLFW(COOLGIRL_WRITE) {
SET_BITS(chr_bank_e, "6:2", mmc1_load_register, "5:1");
break;
case 0b11: // 2'b11
// prg_bank_a[4:1] = r0[4:1];
// prg_bank_a[4:1] = mmc1_load_register[4:1];
SET_BITS(prg_bank_a, "4:1", mmc1_load_register, "4:1");
// sram_enabled = ~mmc1_load_register[5];
sram_enabled = get_bits(mmc1_load_register, "5") ^ 1;
@@ -1397,9 +1391,6 @@ static DECLFW(COOLGIRL_WRITE) {
}
// Mapper #112
/*
r0[2:0] - internal register
*/
if (mapper == 0b010101)
{
switch (get_bits(A, "14:13"))
@@ -1464,6 +1455,7 @@ static DECLFW(COOLGIRL_WRITE) {
case 0b1100: // 4'b1100: if (flags[0]) mirroring = {1'b0, cpu_data_in[6]}; // $E000, mirroring, for mapper #48
if (flags & 1) // 48
mirroring = get_bits(V, "6"); // mirroring = cpu_data_in[6];
break;
case 0b1000: // 4'b1000: irq_scanline_latch = ~cpu_data_in; // $C000, IRQ latch
mmc3_irq_latch = set_bits(mmc3_irq_latch, "7:0", get_bits(V, "7:0") ^ 0b11111111);
break;
@@ -1813,7 +1805,7 @@ static DECLFW(COOLGIRL_WRITE) {
SET_BITS(chr_bank_c, "8:1", V, "7:0"); break; // 3'b001: chr_bank_c[8:1] <= cpu_data_in[7:0];
case 0b110:
SET_BITS(chr_bank_e, "8:1", V, "7:0"); break; // 3'b110: chr_bank_e[8:1] <= cpu_data_in[7:0];
case 0b111:
case 0b111:
SET_BITS(chr_bank_g, "8:1", V, "7:0"); break; // 3'b111: chr_bank_g[8:1] <= cpu_data_in[7:0];
}
}
@@ -1963,32 +1955,19 @@ static void COOLGIRL_CpuCounter(int a) {
// Mapper #23 - VRC4
if (vrc4_irq_control & 2) // if (ENABLE_MAPPER_021_022_023_025 & ENABLE_VRC4_INTERRUPTS & (vrc4_irq_control[1]))
{
// Cycle mode without prescaler is not used by any games? It's missed in fceux source code.
if (vrc4_irq_control & 4) // if (vrc4_irq_control[2]) // cycle mode
vrc4_irq_prescaler++; // vrc4_irq_prescaler = vrc4_irq_prescaler + 1'b1; // count prescaler
// if ((vrc4_irq_prescaler_counter[1] == 0 && vrc4_irq_prescaler == 114)
// || (vrc4_irq_prescaler_counter[1] == 1 && vrc4_irq_prescaler == 113)) // 114, 114, 113
if ((!(vrc4_irq_prescaler_counter & 2) && vrc4_irq_prescaler == 114) || ((vrc4_irq_prescaler_counter & 2) && vrc4_irq_prescaler == 113))
{
FCEU_PrintError("Cycle IRQ mode is not supported, please report to Cluster");
vrc4_irq_value++; // {carry, vrc4_irq_value[7:0]} = vrc4_irq_value[7:0] + 1'b1; // just count IRQ value
if (vrc4_irq_value == 0) // if (carry)
vrc4_irq_prescaler = 0; // vrc4_irq_prescaler = 0;
vrc4_irq_prescaler_counter++; // vrc4_irq_prescaler_counter = vrc4_irq_prescaler_counter + 1'b1;
if (vrc4_irq_prescaler_counter == 0b11) vrc4_irq_prescaler_counter = 0; // if (vrc4_irq_prescaler_counter == 2'b11) vrc4_irq_prescaler_counter = 2'b00;
vrc4_irq_value++; // {carry, vrc4_irq_value[7:0]} = vrc4_irq_value[7:0] + 1'b1;
if (vrc4_irq_value == 0) // f (carry)
{
X6502_IRQBegin(FCEU_IQEXT); // vrc4_irq_out = 1;
vrc4_irq_value = vrc4_irq_latch; // vrc4_irq_value[7:0] = vrc4_irq_latch[7:0];
}
}
else {
vrc4_irq_prescaler++; // vrc4_irq_prescaler = vrc4_irq_prescaler + 1'b1; // count prescaler
// if ((vrc4_irq_prescaler_counter[1] == 0 && vrc4_irq_prescaler == 114)
// || (vrc4_irq_prescaler_counter[1] == 1 && vrc4_irq_prescaler == 113)) // 114, 114, 113
if ((!(vrc4_irq_prescaler_counter & 2) && vrc4_irq_prescaler == 114) || ((vrc4_irq_prescaler_counter & 2) && vrc4_irq_prescaler == 113))
{
vrc4_irq_prescaler = 0; // vrc4_irq_prescaler = 0;
vrc4_irq_prescaler_counter++; // vrc4_irq_prescaler_counter = vrc4_irq_prescaler_counter + 1'b1;
if (vrc4_irq_prescaler_counter == 0b11) vrc4_irq_prescaler_counter = 0; // if (vrc4_irq_prescaler_counter == 2'b11) vrc4_irq_prescaler_counter = 2'b00;
vrc4_irq_value++; // {carry, vrc4_irq_value[7:0]} = vrc4_irq_value[7:0] + 1'b1;
if (vrc4_irq_value == 0) // f (carry)
{
X6502_IRQBegin(FCEU_IQEXT);
vrc4_irq_value = vrc4_irq_latch; // irq_cpu_value[7:0] = vrc4_irq_latch[7:0];
}
X6502_IRQBegin(FCEU_IQEXT);
vrc4_irq_value = vrc4_irq_latch; // irq_cpu_value[7:0] = vrc4_irq_latch[7:0];
}
}
}
@@ -2238,15 +2217,13 @@ static void COOLGIRL_Power(void) {
}
static void COOLGIRL_Close(void) {
if (CHR_RAM)
FCEU_gfree(CHR_RAM);
if (WRAM)
FCEU_gfree(WRAM);
if (SAVE_FLASH)
FCEU_gfree(SAVE_FLASH);
if (CFI)
FCEU_gfree(CFI);
CHR_RAM = WRAM = SAVE_FLASH = CFI = NULL;
WRAM = SAVE_FLASH = CFI = NULL;
}
static void COOLGIRL_Restore(int version) {
@@ -2256,12 +2233,8 @@ static void COOLGIRL_Restore(int version) {
#define ExState(var, varname) AddExState(&var, sizeof(var), 0, varname)
void COOLGIRL_Init(CartInfo *info) {
CHR_RAM_SIZE = info->ines2 ? (info->vram_size + info->battery_vram_size) : (512 * 1024);
CHR_RAM = (uint8*)FCEU_gmalloc(CHR_RAM_SIZE);
memset(CHR_RAM, 0, CHR_RAM_SIZE);
SetupCartCHRMapping(CHR_RAM_CHIP, CHR_RAM, CHR_RAM_SIZE, 0);
AddExState(CHR_RAM, sizeof(CHR_RAM_SIZE), 0, "CHR_");
void COOLGIRL_Init(CartInfo* info) {
CHR_SIZE = info->vram_size ? info->vram_size /* NES 2.0 */ : 256 * 1024 /* UNIF, fixed */;
WRAM_SIZE = info->ines2 ? (info->wram_size + info->battery_wram_size) : (32 * 1024);
if (WRAM_SIZE > 0) {
@@ -2271,8 +2244,7 @@ void COOLGIRL_Init(CartInfo *info) {
AddExState(WRAM, 32 * 1024, 0, "SRAM");
if (info->battery)
{
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = 32 * 1024;
info->addSaveGameBuf(WRAM, 32 * 1024);
}
}
@@ -2281,8 +2253,7 @@ void COOLGIRL_Init(CartInfo *info) {
SAVE_FLASH = (uint8*)FCEU_gmalloc(SAVE_FLASH_SIZE);
SetupCartPRGMapping(FLASH_CHIP, SAVE_FLASH, SAVE_FLASH_SIZE, 1);
AddExState(SAVE_FLASH, SAVE_FLASH_SIZE, 0, "SAVF");
info->SaveGame[1] = SAVE_FLASH;
info->SaveGameLen[1] = SAVE_FLASH_SIZE;
info->addSaveGameBuf(SAVE_FLASH, SAVE_FLASH_SIZE);
}
CFI = (uint8*)FCEU_gmalloc(sizeof(cfi_data) * 2);
+16 -15
View File
@@ -21,11 +21,12 @@
#include "mapinc.h"
#include "../ines.h"
static uint8 latche, latcheinit, bus_conflict;
static uint16 addrreg0, addrreg1;
static uint8 latche=0, latcheinit=0, bus_conflict=0;
static uint16 addrreg0=0, addrreg1=0;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static void (*WSync)(void);
static uint32 WRAMSIZE=0;
static void (*WSync)(void) = nullptr;
static uint8 submapper;
static DECLFW(LatchWrite) {
// FCEU_printf("bs %04x %02x\n",A,V);
@@ -68,6 +69,7 @@ static void Latch_Init(CartInfo *info, void (*proc)(void), uint8 init, uint16 ad
info->Power = LatchPower;
info->Close = LatchClose;
GameStateRestore = StateRestore;
submapper = info->submapper;
if(info->ines2)
if(info->battery_wram_size + info->wram_size > 0)
wram = 1;
@@ -85,14 +87,12 @@ static void Latch_Init(CartInfo *info, void (*proc)(void), uint8 init, uint16 ad
//else if(!info->wram_size && info->battery_wram_size)
//{
// SetupCartPRGMapping(0x10, WRAM, info->battery_wram_size, 1);
// info->SaveGame[0] = WRAM;
// info->SaveGameLen[0] = info->battery_wram_size;
// info->addSaveGameBuf( WRAM, info->battery_wram_size );
//} else {
// //well, this is annoying
// SetupCartPRGMapping(0x10, WRAM, info->wram_size, 1);
// SetupCartPRGMapping(0x11, WRAM, info->battery_wram_size, 1); //? ? ? there probably isnt even a way to select this
// info->SaveGame[0] = WRAM + info->wram_size;
// info->SaveGameLen[0] = info->battery_wram_size;
// info->addSaveGameBuf( WRAM + info->wram_size, info->battery_wram_size );
//}
//this is more likely the only practical scenario
@@ -104,8 +104,7 @@ static void Latch_Init(CartInfo *info, void (*proc)(void), uint8 init, uint16 ad
setprg8r(0x10, 0x6000, 0);
if(info->battery_wram_size)
{
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = 8192;
info->addSaveGameBuf( WRAM, 8192 );
}
}
else
@@ -114,8 +113,7 @@ static void Latch_Init(CartInfo *info, void (*proc)(void), uint8 init, uint16 ad
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
}
@@ -158,8 +156,7 @@ void NROM_Init(CartInfo *info) {
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
}
@@ -300,7 +297,11 @@ static void M78Sync() {
setprg16(0x8000, (latche & 7));
setprg16(0xc000, ~0);
setchr8(latche >> 4);
setmirror(MI_0 + ((latche >> 3) & 1));
if (submapper == 3) {
setmirror((latche >> 3) & 1);
} else {
setmirror(MI_0 + ((latche >> 3) & 1));
}
}
void Mapper78_Init(CartInfo *info) {
+1 -2
View File
@@ -70,8 +70,7 @@ void UNLEDU2000_Init(CartInfo *info) {
WRAM = (uint8*)FCEU_gmalloc(32768);
SetupCartPRGMapping(0x10, WRAM, 32768, 1);
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = 32768;
info->addSaveGameBuf( WRAM, 32768 );
}
AddExState(WRAM, 32768, 0, "WRAM");
AddExState(StateRegs, ~0, 0, 0);
+1 -2
View File
@@ -141,8 +141,7 @@ void Mapper6_Init(CartInfo *info) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(&StateRegs, ~0, 0, 0);
+2 -3
View File
@@ -28,7 +28,7 @@
static uint8 DRegs[4];
static uint8 Buffer, BufferShift;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
static uint8 *WRAM = NULL;
static int kanji_pos, kanji_page, r40C0;
@@ -256,8 +256,7 @@ void FNS_Init(CartInfo *info) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
AddExState(DRegs, 4, 0, "DREG");
AddExState(&lreset, 8, 1, "LRST");
+1 -2
View File
@@ -306,8 +306,7 @@ static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int bram) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (bram) {
info->SaveGame[0] = WRAM + NONBRAMSIZE;
info->SaveGameLen[0] = bram * 1024;
info->addSaveGameBuf( WRAM + NONBRAMSIZE, bram * 1024 );
}
}
if (!chr) {
+2 -3
View File
@@ -25,7 +25,7 @@
static uint8 is10;
static uint8 creg[4], latch0, latch1, preg, mirr;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
static SFORMAT StateRegs[] =
{
@@ -130,8 +130,7 @@ void Mapper10_Init(CartInfo *info) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
+70 -18
View File
@@ -324,8 +324,7 @@ void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery) {
if (battery) {
mmc3opts |= 2;
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
// KT-008 boards hack 2-in-1, TODO assign to new ines mapper, most dump of KT-boards on the net are mapper 4, so need database or goodnes fix support
@@ -1137,20 +1136,73 @@ void Mapper198_Init(CartInfo *info) {
info->Power = M195Power;
}
// ---------------------------- Mapper 205 ------------------------------
// GN-45 BOARD
/* ---------------------------- Mapper 205 ------------------------------ */
/* UNIF boardname BMC-JC-016-2
https://wiki.nesdev.com/w/index.php/INES_Mapper_205 */
/* 2023-02 : Update reg write logic and add solder pad */
static void M205PW(uint32 A, uint8 V) {
// GN-30A - íà÷àëüíàÿ ìàñêà äîëæíà áûòü 1F + àïïàðàòíûé ïåðåêëþ÷àòåëü íà øèíå àäðåñà
setprg8(A, (V & 0x0f) | EXPREGS[0]);
uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x0F : 0x1F);
if (PRGsize[1]) { // split-rom variant
setprg8r((EXPREGS[0] & 3) ? (EXPREGS[0] - 1) : 0, A, bank);
} else {
setprg8(A, EXPREGS[0] << 4 | bank);
}
}
static void M205CW(uint32 A, uint8 V) {
// GN-30A - íà÷àëüíàÿ ìàñêà äîëæíà áûòü FF
uint8 bank = V & ((EXPREGS[0] & 0x02) ? 0x7F : 0xFF);
if (CHRsize[1]) { // split-rom variant
setchr1r((EXPREGS[0] & 3) ? (EXPREGS[0] - 1) : 0, A, bank);
} else {
setchr1(A, (EXPREGS[0] << 7) | bank);
}
}
static DECLFW(M205Write) {
EXPREGS[0] = V & 3;
if (V & 1) {
EXPREGS[0] |= EXPREGS[1];
}
CartBW(A, V);
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
static void M205Reset(void) {
EXPREGS[0] = 0;
EXPREGS[1] ^= 2; /* solder pad */
MMC3RegReset();
}
static void M205Power(void) {
EXPREGS[0] = EXPREGS[1] = 0;
GenMMC3Power();
SetWriteHandler(0x6000, 0x7FFF, M205Write);
}
void Mapper205_Init(CartInfo *info) {
GenMMC3_Init(info, 256, 128, 0, 0);
pwrap = M205PW;
cwrap = M205CW;
info->Power = M205Power;
info->Reset = M205Reset;
AddExState(EXPREGS, 2, 0, "EXPR");
}
/* --------------------------- GN-45 BOARD ------------------------------ */
/* Mapper 361 and 366, previously assigned as Mapper 205 */
static void GN45PW(uint32 A, uint8 V) {
setprg8(A, (V & 0x0f) | EXPREGS[0]);
}
static void GN45CW(uint32 A, uint8 V) {
setchr1(A, (V & 0x7F) | (EXPREGS[0] << 3));
}
static DECLFW(M205Write0) {
static DECLFW(GN45Write0) {
if (EXPREGS[2] == 0) {
EXPREGS[0] = A & 0x30;
EXPREGS[2] = A & 0x80;
@@ -1160,7 +1212,7 @@ static DECLFW(M205Write0) {
CartBW(A, V);
}
static DECLFW(M205Write1) {
static DECLFW(GN45Write1) {
if (EXPREGS[2] == 0) {
EXPREGS[0] = V & 0x30;
FixMMC3PRG(MMC3_cmd);
@@ -1169,23 +1221,23 @@ static DECLFW(M205Write1) {
CartBW(A, V);
}
static void M205Reset(void) {
static void GN45Reset(void) {
EXPREGS[0] = EXPREGS[2] = 0;
MMC3RegReset();
}
static void M205Power(void) {
static void GN45Power(void) {
GenMMC3Power();
SetWriteHandler(0x6000, 0x6fff, M205Write0);
SetWriteHandler(0x7000, 0x7fff, M205Write1); // OK-411 boards, the same logic, but data latched, 2-in-1 frankenstein
SetWriteHandler(0x6000, 0x6fff, GN45Write0);
SetWriteHandler(0x7000, 0x7fff, GN45Write1); /* OK-411 boards, the same logic, but data latched, 2-in-1 frankenstein */
}
void Mapper205_Init(CartInfo *info) {
void GN45_Init(CartInfo *info) {
GenMMC3_Init(info, 128, 128, 8, 0);
pwrap = M205PW;
cwrap = M205CW;
info->Power = M205Power;
info->Reset = M205Reset;
pwrap = GN45PW;
cwrap = GN45CW;
info->Power = GN45Power;
info->Reset = GN45Reset;
AddExState(EXPREGS, 1, 0, "EXPR");
}
+7 -6
View File
@@ -424,7 +424,7 @@ static void MMC5PRG(void) {
switch (mmc5psize & 3) {
case 0:
MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = MMC5ROMWrProtect[2] = MMC5ROMWrProtect[3] = 1;
setprg32(0x8000, ((PRGBanks[1] & 0x7F) >> 2));
setprg32(0x8000, ((PRGBanks[3] & 0x7F) >> 2));
for (x = 0; x < 4; x++)
MMC5MemIn[1 + x] = 1;
break;
@@ -1021,22 +1021,23 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
MMC5battery = battery;
if (battery) {
info->SaveGame[0] = WRAM;
uint32 saveGameSize = 0;
if (info->ines2)
{
info->SaveGameLen[0] = info->battery_wram_size;
saveGameSize = info->battery_wram_size;
}
else
{
//this is more complex than it looks because it MUST BE, I guess. is there an assumption that only 8KB of 16KB is battery backed? That's NES mappers for you
//I added 64KB for the new 64KB homebrews
if (wsize <= 16)
info->SaveGameLen[0] = 8192;
saveGameSize = 8192;
else if(wsize == 64)
info->SaveGameLen[0] = 64*1024;
saveGameSize = 64*1024;
else
info->SaveGameLen[0] = 32768;
saveGameSize = 32768;
}
info->addSaveGameBuf( WRAM, saveGameSize );
}
MMC5HackVROMMask = CHRmask4[0];
+2 -4
View File
@@ -429,10 +429,8 @@ void Mapper19_Init(CartInfo *info) {
AddExState(N106_StateRegs, ~0, 0, 0);
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = 8192;
info->SaveGame[1] = IRAM;
info->SaveGameLen[1] = 128;
info->addSaveGameBuf( WRAM, 8192 );
info->addSaveGameBuf( IRAM, 128 );
}
}
+1 -2
View File
@@ -320,8 +320,7 @@ void UNLOneBus_Init(CartInfo *info) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
}
}
+1 -2
View File
@@ -54,8 +54,7 @@ void SA9602B_Init(CartInfo *info) {
GenMMC3_Init(info, 512, 0, 0, 0);
pwrap = SA9602BPW;
mmc3opts |= 2;
info->SaveGame[0] = UNIFchrrama;
info->SaveGameLen[0] = 32 * 1024;
info->addSaveGameBuf( UNIFchrrama, 32 * 1024 );
info->Power = SA9602BPower;
AddExState(EXPREGS, 2, 0, "EXPR");
}
+2 -3
View File
@@ -24,7 +24,7 @@ static uint8 preg[8];
static uint8 IRQa;
static int16 IRQCount, IRQLatch;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
/*
static uint8 *CHRRAM = NULL;
static uint32 CHRRAMSIZE;
@@ -187,8 +187,7 @@ void UNLSB2000_Init(CartInfo *info) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(&StateRegs, ~0, 0, 0);
+2 -3
View File
@@ -21,7 +21,7 @@
#include "mapinc.h"
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
unsigned int *GetKeyboard(void); // FIXME: 10/28 - now implemented in SDL as well. should we rename this to a FCEUI_* function?
@@ -90,8 +90,7 @@ void Transformer_Init(CartInfo *info) {
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
}
+24 -12
View File
@@ -168,6 +168,18 @@ static void UNROM512LatchClose(void) {
flash_data = NULL;
}
static void UNROM512_FlashReset(void)
{
if (flash_data)
{
size_t flash_size = PRGsize[ROM_CHIP];
// Copy ROM to flash data
for (size_t i = 0; i < flash_size; i++) {
flash_data[i] = PRGptr[ROM_CHIP][i];
}
}
}
void UNROM512_Init(CartInfo *info) {
info->Power = UNROM512LatchPower;
info->Close = UNROM512LatchClose;
@@ -198,26 +210,26 @@ void UNROM512_Init(CartInfo *info) {
if(flash_save)
{
// Allocate memory for flash
flash_data = (uint8*)FCEU_gmalloc(PRGsize[ROM_CHIP]);
size_t flash_size = PRGsize[ROM_CHIP];
flash_data = (uint8*)FCEU_gmalloc(flash_size);
// Copy ROM to flash data
for (unsigned int i = 0; i < PRGsize[ROM_CHIP]; i++) {
flash_data[i] = PRGptr[ROM_CHIP][i % PRGsize[ROM_CHIP]];
for (size_t i = 0; i < flash_size; i++) {
flash_data[i] = PRGptr[ROM_CHIP][i];
}
SetupCartPRGMapping(FLASH_CHIP, flash_data, PRGsize[ROM_CHIP], 1);
info->SaveGame[0] = flash_data;
info->SaveGameLen[0] = PRGsize[ROM_CHIP];
SetupCartPRGMapping(FLASH_CHIP, flash_data, flash_size, 1);
info->addSaveGameBuf( flash_data, flash_size, UNROM512_FlashReset );
flash_id[0] = 0xBF;
flash_id[1] = 0xB5 + (ROM_size >> 4);
SetupCartPRGMapping(CFI_CHIP, flash_id, sizeof(flash_id), 0);
AddExState(flash_data, PRGsize[ROM_CHIP], 0, "FLSH");
AddExState(&flash_state, 1, 0, "FLST");
AddExState(&flash_id_mode, 1, 0, "FLMD");
AddExState(flash_data, flash_size, 0, "FLSH");
AddExState(&flash_state, sizeof(flash_state), 0, "FLST");
AddExState(&flash_id_mode, sizeof(flash_id_mode), 0, "FLMD");
AddExState(flash_buffer_a, sizeof(flash_buffer_a), 0, "FLBA");
AddExState(flash_buffer_v, sizeof(flash_buffer_v), 0, "FLBV");
}
AddExState(&latcha, 2, 0, "LATA");
AddExState(&latche, 1, 0, "LATC");
AddExState(&bus_conflict, 1, 0, "BUSC");
AddExState(&latcha, sizeof(latcha), 0, "LATA");
AddExState(&latche, sizeof(latche), 0, "LATC");
AddExState(&bus_conflict, sizeof(bus_conflict), 0, "BUSC");
}
+1 -2
View File
@@ -185,8 +185,7 @@ static void VRC24_Init(CartInfo *info) {
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if(info->battery) {
info->SaveGame[0]=WRAM;
info->SaveGameLen[0]=WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(&StateRegs, ~0, 0, 0);
+1 -2
View File
@@ -254,11 +254,10 @@ void QTAi_Init(CartInfo *info) {
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
// note, only extrnal cart's SRAM is battery backed, the the part on the main cartridge is just
// an additional work ram. so we may save only half here, but I forgot what part is saved lol, will
// find out later.
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(&StateRegs, ~0, 0, 0);
+2 -3
View File
@@ -28,7 +28,7 @@ static uint8 prg[2], chr[8], mirr;
static uint8 IRQLatch, IRQa, IRQd, IRQMode;
static int32 IRQCount, CycleCount;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
static SFORMAT StateRegs[] =
{
@@ -379,8 +379,7 @@ void Mapper26_Init(CartInfo *info) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
AddExState(&StateRegs, ~0, 0, 0);
+2 -3
View File
@@ -24,7 +24,7 @@ static uint8 vrc7idx, preg[3], creg[8], mirr;
static uint8 IRQLatch, IRQa, IRQd, IRQMode;
static int32 IRQCount, CycleCount;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
#include "emu2413.h"
@@ -204,8 +204,7 @@ void Mapper85_Init(CartInfo *info) {
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
if (info->battery) {
info->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
info->addSaveGameBuf( WRAM, WRAMSIZE );
}
GameStateRestore = StateRestore;
VRC7_ESI();
+38 -18
View File
@@ -536,19 +536,27 @@ void FCEU_GeniePower(void) {
}
void FCEU_SaveGameSave(CartInfo *LocalHWInfo) {
if (LocalHWInfo->battery && LocalHWInfo->SaveGame[0]) {
void FCEU_SaveGameSave(CartInfo *LocalHWInfo)
{
if (LocalHWInfo->battery && !LocalHWInfo->SaveGame.empty())
{
FILE *sp;
std::string soot = FCEU_MakeFName(FCEUMKF_SAV, 0, "sav");
if ((sp = FCEUD_UTF8fopen(soot, "wb")) == NULL) {
if ((sp = FCEUD_UTF8fopen(soot, "wb")) == NULL)
{
FCEU_PrintError("WRAM file \"%s\" cannot be written to.\n", soot.c_str());
} else {
for (int x = 0; x < 4; x++)
if (LocalHWInfo->SaveGame[x]) {
fwrite(LocalHWInfo->SaveGame[x], 1,
LocalHWInfo->SaveGameLen[x], sp);
}
else
{
for (size_t x = 0; x < LocalHWInfo->SaveGame.size(); x++)
{
if (LocalHWInfo->SaveGame[x].bufptr)
{
fwrite(LocalHWInfo->SaveGame[x].bufptr, 1,
LocalHWInfo->SaveGame[x].buflen, sp);
}
}
}
}
}
@@ -556,19 +564,21 @@ void FCEU_SaveGameSave(CartInfo *LocalHWInfo) {
// hack, movie.cpp has to communicate with this function somehow
int disableBatteryLoading = 0;
void FCEU_LoadGameSave(CartInfo *LocalHWInfo) {
if (LocalHWInfo->battery && LocalHWInfo->SaveGame[0] && !disableBatteryLoading) {
void FCEU_LoadGameSave(CartInfo *LocalHWInfo)
{
if (LocalHWInfo->battery && !LocalHWInfo->SaveGame.empty() && !disableBatteryLoading)
{
FILE *sp;
std::string soot = FCEU_MakeFName(FCEUMKF_SAV, 0, "sav");
sp = FCEUD_UTF8fopen(soot, "rb");
if (sp != NULL)
{
for (int x = 0; x < 4; x++)
for (size_t x = 0; x < LocalHWInfo->SaveGame.size(); x++)
{
if (LocalHWInfo->SaveGame[x])
if (LocalHWInfo->SaveGame[x].bufptr)
{
if ( fread(LocalHWInfo->SaveGame[x], 1, LocalHWInfo->SaveGameLen[x], sp) != static_cast<size_t>(LocalHWInfo->SaveGameLen[x]) )
if ( fread(LocalHWInfo->SaveGame[x].bufptr, 1, LocalHWInfo->SaveGame[x].buflen, sp) != LocalHWInfo->SaveGame[x].buflen )
{
FCEU_printf("Warning save game data read came up short!\n");
}
@@ -579,10 +589,20 @@ void FCEU_LoadGameSave(CartInfo *LocalHWInfo) {
}
//clears all save memory. call this if you want to pretend the saveram has been reset (it doesnt touch what is on disk though)
void FCEU_ClearGameSave(CartInfo *LocalHWInfo) {
if (LocalHWInfo->battery && LocalHWInfo->SaveGame[0]) {
for (int x = 0; x < 4; x++)
if (LocalHWInfo->SaveGame[x])
memset(LocalHWInfo->SaveGame[x], 0, LocalHWInfo->SaveGameLen[x]);
void FCEU_ClearGameSave(CartInfo *LocalHWInfo)
{
if (LocalHWInfo->battery && !LocalHWInfo->SaveGame.empty())
{
for (size_t x = 0; x < LocalHWInfo->SaveGame.size(); x++)
{
if (LocalHWInfo->SaveGame[x].bufptr)
{
memset(LocalHWInfo->SaveGame[x].bufptr, 0, LocalHWInfo->SaveGame[x].buflen);
}
if (LocalHWInfo->SaveGame[x].resetFunc)
{
LocalHWInfo->SaveGame[x].resetFunc();
}
}
}
}
+59 -8
View File
@@ -1,20 +1,45 @@
#ifndef CART_H
#define CART_H
typedef struct {
#include <vector>
struct CartInfo
{
// Set by mapper/board code:
void (*Power)(void);
void (*Reset)(void);
void (*Close)(void);
uint8 *SaveGame[4]; // Pointers to memory to save/load.
uint32 SaveGameLen[4]; // How much memory to save/load.
struct SaveGame_t
{
uint8 *bufptr; // Pointer to memory to save/load.
uint32 buflen; // How much memory to save/load.
void (*resetFunc)(void); // Callback to reset save game memory
SaveGame_t(void)
: bufptr(nullptr), buflen(0), resetFunc(nullptr)
{
}
};
std::vector <SaveGame_t> SaveGame;
void addSaveGameBuf( uint8* bufptrIn, uint32 buflenIn, void (*resetFuncIn)(void) = nullptr )
{
SaveGame_t tmp;
tmp.bufptr = bufptrIn;
tmp.buflen = buflenIn;
tmp.resetFunc = resetFuncIn;
SaveGame.push_back( tmp );
}
// Set by iNES/UNIF loading code.
int mirror; // As set in the header or chunk.
// iNES/UNIF specific. Intended
// to help support games like "Karnov"
// that are not really MMC3 but are
// set to mapper 4.
// iNES/UNIF specific. Intended
// to help support games like "Karnov"
// that are not really MMC3 but are
// set to mapper 4.
int mirrorAs2Bits;
int battery; // Presence of an actual battery.
int ines2;
@@ -27,7 +52,33 @@ typedef struct {
uint32 CRC32; // Should be set by the iNES/UNIF loading
// code, used by mapper/board code, maybe
// other code in the future.
} CartInfo;
CartInfo(void)
{
clear();
}
void clear(void)
{
Power = nullptr;
Reset = nullptr;
Close = nullptr;
SaveGame.clear();
mirror = 0;
mirrorAs2Bits = 0;
battery = 0;
ines2 = 0;
submapper = 0;
wram_size = 0;
battery_wram_size = 0;
vram_size = 0;
battery_vram_size = 0;
memset( MD5, 0, sizeof(MD5));
CRC32 = 0;
};
};
extern CartInfo *currCartInfo;
+57 -55
View File
@@ -52,17 +52,17 @@
#include <cctype>
uint16 debugLastAddress = 0; // used by 'T' and 'R' conditions
uint8 debugLastOpcode; // used to evaluate 'W' condition
uint8 debugLastOpcode = 0; // used to evaluate 'W' condition
// Next non-whitespace character in string
char next;
static char next = 0;
int ishex(char c)
static int ishex(char c)
{
return isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}
void scan(const char** str)
static void scan(const char** str)
{
do
{
@@ -71,40 +71,37 @@ void scan(const char** str)
} while (isspace(next));
}
// Frees a condition and all of it's sub conditions
void freeTree(Condition* c)
{
if (c->lhs) freeTree(c->lhs);
if (c->rhs) freeTree(c->rhs);
free(c);
}
// Generic function to handle all infix operators but the last one in the precedence hierarchy. : '(' E ')'
Condition* InfixOperator(const char** str, Condition(*nextPart(const char**)), int(*operators)(const char**))
static Condition* InfixOperator(const char** str, Condition(*nextPart(const char**)), int(*operators)(const char**))
{
Condition* t = nextPart(str);
Condition* t1;
Condition* mid;
int op;
if (t == nullptr)
{
return nullptr;
}
while ((op = operators(str)))
{
scan(str);
t1 = nextPart(str);
if (t1 == 0)
if (t1 == nullptr)
{
if(t)
freeTree(t);
delete t;
return 0;
}
mid = (Condition*)FCEU_dmalloc(sizeof(Condition));
if (!mid)
return NULL;
memset(mid, 0, sizeof(Condition));
mid = new Condition();
if (mid == nullptr)
{
delete t;
delete t1;
return nullptr;
}
mid->lhs = t;
mid->rhs = t1;
@@ -117,7 +114,7 @@ Condition* InfixOperator(const char** str, Condition(*nextPart(const char**)), i
}
// Generic handler for two-character operators
int TwoCharOperator(const char** str, char c1, char c2, int op)
static int TwoCharOperator(const char** str, char c1, char c2, int op)
{
if (next == c1 && **str == c2)
{
@@ -131,43 +128,43 @@ int TwoCharOperator(const char** str, char c1, char c2, int op)
}
// Determines if a character is a flag
int isFlag(char c)
static int isFlag(char c)
{
return c == 'N' || c == 'I' || c == 'C' || c == 'V' || c == 'Z' || c == 'B' || c == 'U' || c == 'D';
}
// Determines if a character is a register
int isRegister(char c)
static int isRegister(char c)
{
return c == 'A' || c == 'X' || c == 'Y' || c == 'P' || c == 'S';
}
// Determines if a character is for PC bank
int isPCBank(char c)
static int isPCBank(char c)
{
return c == 'K';
}
// Determines if a character is for Data bank
int isDataBank(char c)
static int isDataBank(char c)
{
return c == 'T';
}
// Determines if a character is for value read
int isValueRead(char c)
static int isValueRead(char c)
{
return c == 'R';
}
// Determines if a character is for value write
int isValueWrite(char c)
static int isValueWrite(char c)
{
return c == 'W';
}
// Reads a hexadecimal number from str
int getNumber(unsigned int* number, const char** str)
static int getNumber(unsigned int* number, const char** str)
{
// char buffer[5];
@@ -185,10 +182,10 @@ int getNumber(unsigned int* number, const char** str)
return 1;
}
Condition* Connect(const char** str);
static Condition* Connect(const char** str);
// Handles the following part of the grammar: '(' E ')'
Condition* Parentheses(const char** str, Condition* c, char openPar, char closePar)
static Condition* Parentheses(const char** str, Condition* c, char openPar, char closePar)
{
if (next == openPar)
{
@@ -216,7 +213,7 @@ Condition* Parentheses(const char** str, Condition* c, char openPar, char closeP
* Check for primitives
* Flags, Registers, Numbers, Addresses and parentheses
*/
Condition* Primitive(const char** str, Condition* c)
static Condition* Primitive(const char** str, Condition* c)
{
if (isFlag(next)) /* Flags */
{
@@ -394,24 +391,22 @@ Condition* Primitive(const char** str, Condition* c)
}
/* Handle * and / operators */
Condition* Term(const char** str)
static Condition* Term(const char** str)
{
Condition* t;
Condition* t1;
Condition* mid;
t = (Condition*)FCEU_dmalloc(sizeof(Condition));
t = new Condition();
if (!t)
if (t == nullptr)
{
return NULL;
}
memset(t, 0, sizeof(Condition));
if (!Primitive(str, t))
{
freeTree(t);
delete t;
return 0;
}
@@ -421,22 +416,25 @@ Condition* Term(const char** str)
scan(str);
if (!(t1 = (Condition*)FCEU_dmalloc(sizeof(Condition))))
return NULL;
memset(t1, 0, sizeof(Condition));
if ((t1 = new Condition()) == nullptr)
{
delete t;
return nullptr;
}
if (!Primitive(str, t1))
{
freeTree(t);
freeTree(t1);
delete t;
delete t1;
return 0;
}
if (!(mid = (Condition*)FCEU_dmalloc(sizeof(Condition))))
return NULL;
memset(mid, 0, sizeof(Condition));
if ((mid = new Condition()) == nullptr)
{
delete t;
delete t1;
return nullptr;
}
mid->lhs = t;
mid->rhs = t1;
@@ -449,7 +447,7 @@ Condition* Term(const char** str)
}
/* Check for + and - operators */
int SumOperators(const char** str)
static int SumOperators(const char** str)
{
switch (next)
{
@@ -460,13 +458,13 @@ int SumOperators(const char** str)
}
/* Handle + and - operators */
Condition* Sum(const char** str)
static Condition* Sum(const char** str)
{
return InfixOperator(str, Term, SumOperators);
}
/* Check for <=, =>, ==, !=, > and < operators */
int CompareOperators(const char** str)
static int CompareOperators(const char** str)
{
int val = TwoCharOperator(str, '=', '=', OP_EQ);
if (val) return val;
@@ -490,13 +488,13 @@ int CompareOperators(const char** str)
}
/* Handle <=, =>, ==, !=, > and < operators */
Condition* Compare(const char** str)
static Condition* Compare(const char** str)
{
return InfixOperator(str, Sum, CompareOperators);
}
/* Check for || or && operators */
int ConnectOperators(const char** str)
static int ConnectOperators(const char** str)
{
int val = TwoCharOperator(str, '|', '|', OP_OR);
if(val) return val;
@@ -508,7 +506,7 @@ int ConnectOperators(const char** str)
}
/* Handle || and && operators */
Condition* Connect(const char** str)
static Condition* Connect(const char** str)
{
return InfixOperator(str, Compare, ConnectOperators);
}
@@ -521,6 +519,10 @@ Condition* generateCondition(const char* str)
scan(&str);
c = Connect(&str);
if (!c || next != 0) return 0;
if (!c || next != 0)
{
if (c) delete c;
return 0;
}
else return c;
}
+20 -1
View File
@@ -61,9 +61,28 @@ struct Condition
unsigned int type2;
unsigned int value2;
Condition(void)
{
op = 0;
lhs = rhs = nullptr;
type1 = value1 = 0;
type2 = value2 = 0;
};
~Condition(void)
{
if (lhs)
{
delete lhs;
}
if (rhs)
{
delete rhs;
}
}
};
void freeTree(Condition* c);
Condition* generateCondition(const char* str);
#endif
+45 -19
View File
@@ -19,10 +19,15 @@ unsigned int debuggerPageSize = 14;
int vblankScanLines = 0; //Used to calculate scanlines 240-261 (vblank)
int vblankPixel = 0; //Used to calculate the pixels in vblank
int offsetStringToInt(unsigned int type, const char* offsetBuffer)
int offsetStringToInt(unsigned int type, const char* offsetBuffer, bool *conversionOk)
{
int offset = -1;
if (conversionOk)
{
*conversionOk = false;
}
if (sscanf(offsetBuffer,"%7X",(unsigned int *)&offset) == EOF)
{
return -1;
@@ -30,14 +35,26 @@ int offsetStringToInt(unsigned int type, const char* offsetBuffer)
if (type & BT_P)
{
if (conversionOk)
{
*conversionOk = (offset >= 0) && (offset < 0x4000);
}
return offset & 0x3FFF;
}
else if (type & BT_S)
{
if (conversionOk)
{
*conversionOk = (offset >= 0) && (offset < 0x100);
}
return offset & 0x00FF;
}
else if (type & BT_R)
{
if (conversionOk)
{
*conversionOk = (offset >= 0);
}
return offset;
}
else // BT_C
@@ -46,6 +63,10 @@ int offsetStringToInt(unsigned int type, const char* offsetBuffer)
if (sym)
{
if (conversionOk)
{
*conversionOk = true;
}
return sym->offset() & 0xFFFF;
}
@@ -56,21 +77,26 @@ int offsetStringToInt(unsigned int type, const char* offsetBuffer)
type = GameInfo->type;
}
if (type == GIT_NSF) { //NSF Breakpoint keywords
if (strcmp(offsetBuffer,"LOAD") == 0) return (NSFHeader.LoadAddressLow | (NSFHeader.LoadAddressHigh<<8));
if (strcmp(offsetBuffer,"INIT") == 0) return (NSFHeader.InitAddressLow | (NSFHeader.InitAddressHigh<<8));
if (strcmp(offsetBuffer,"PLAY") == 0) return (NSFHeader.PlayAddressLow | (NSFHeader.PlayAddressHigh<<8));
if (strcmp(offsetBuffer,"LOAD") == 0) offset = (NSFHeader.LoadAddressLow | (NSFHeader.LoadAddressHigh<<8));
else if (strcmp(offsetBuffer,"INIT") == 0) offset = (NSFHeader.InitAddressLow | (NSFHeader.InitAddressHigh<<8));
else if (strcmp(offsetBuffer,"PLAY") == 0) offset = (NSFHeader.PlayAddressLow | (NSFHeader.PlayAddressHigh<<8));
}
else if (type == GIT_FDS) { //FDS Breakpoint keywords
if (strcmp(offsetBuffer,"NMI1") == 0) return (GetMem(0xDFF6) | (GetMem(0xDFF7)<<8));
if (strcmp(offsetBuffer,"NMI2") == 0) return (GetMem(0xDFF8) | (GetMem(0xDFF9)<<8));
if (strcmp(offsetBuffer,"NMI3") == 0) return (GetMem(0xDFFA) | (GetMem(0xDFFB)<<8));
if (strcmp(offsetBuffer,"RST") == 0) return (GetMem(0xDFFC) | (GetMem(0xDFFD)<<8));
if ((strcmp(offsetBuffer,"IRQ") == 0) || (strcmp(offsetBuffer,"BRK") == 0)) return (GetMem(0xDFFE) | (GetMem(0xDFFF)<<8));
if (strcmp(offsetBuffer,"NMI1") == 0) offset = (GetMem(0xDFF6) | (GetMem(0xDFF7)<<8));
else if (strcmp(offsetBuffer,"NMI2") == 0) offset = (GetMem(0xDFF8) | (GetMem(0xDFF9)<<8));
else if (strcmp(offsetBuffer,"NMI3") == 0) offset = (GetMem(0xDFFA) | (GetMem(0xDFFB)<<8));
else if (strcmp(offsetBuffer,"RST") == 0) offset = (GetMem(0xDFFC) | (GetMem(0xDFFD)<<8));
else if ((strcmp(offsetBuffer,"IRQ") == 0) || (strcmp(offsetBuffer,"BRK") == 0)) offset = (GetMem(0xDFFE) | (GetMem(0xDFFF)<<8));
}
else { //NES Breakpoint keywords
if ((strcmp(offsetBuffer,"NMI") == 0) || (strcmp(offsetBuffer,"VBL") == 0)) return (GetMem(0xFFFA) | (GetMem(0xFFFB)<<8));
if (strcmp(offsetBuffer,"RST") == 0) return (GetMem(0xFFFC) | (GetMem(0xFFFD)<<8));
if ((strcmp(offsetBuffer,"IRQ") == 0) || (strcmp(offsetBuffer,"BRK") == 0)) return (GetMem(0xFFFE) | (GetMem(0xFFFF)<<8));
if ((strcmp(offsetBuffer,"NMI") == 0) || (strcmp(offsetBuffer,"VBL") == 0)) offset = (GetMem(0xFFFA) | (GetMem(0xFFFB)<<8));
else if (strcmp(offsetBuffer,"RST") == 0) offset = (GetMem(0xFFFC) | (GetMem(0xFFFD)<<8));
else if ((strcmp(offsetBuffer,"IRQ") == 0) || (strcmp(offsetBuffer,"BRK") == 0)) offset = (GetMem(0xFFFE) | (GetMem(0xFFFF)<<8));
}
if (conversionOk)
{
*conversionOk = (offset >= 0) && (offset < 0x10000);
}
}
@@ -139,7 +165,7 @@ int checkCondition(const char* condition, int num)
// Remove the old breakpoint condition before adding a new condition.
if (watchpoint[num].cond)
{
freeTree(watchpoint[num].cond);
delete watchpoint[num].cond;
free(watchpoint[num].condText);
watchpoint[num].cond = 0;
watchpoint[num].condText = 0;
@@ -153,8 +179,8 @@ int checkCondition(const char* condition, int num)
{
watchpoint[num].cond = c;
watchpoint[num].condText = (char*)malloc(strlen(condition) + 1);
if (!watchpoint[num].condText)
return 0;
if (!watchpoint[num].condText)
return 0;
strcpy(watchpoint[num].condText, condition);
}
else
@@ -169,7 +195,7 @@ int checkCondition(const char* condition, int num)
// Remove the old breakpoint condition
if (watchpoint[num].cond)
{
freeTree(watchpoint[num].cond);
delete watchpoint[num].cond;
free(watchpoint[num].condText);
watchpoint[num].cond = 0;
watchpoint[num].condText = 0;
@@ -266,7 +292,7 @@ int getBank(int offs)
//Anything over FFFFF will kill it.
//GetNesFileAddress doesn't work well with Unif files
int addr = GetNesFileAddress(offs)-16;
int addr = GetNesFileAddress(offs)-NES_HEADER_SIZE;
if (GameInfo && GameInfo->type==GIT_NSF)
return addr != -1 ? addr / 0x1000 : -1;
@@ -278,12 +304,12 @@ int GetNesFileAddress(int A){
if((A < 0x6000) || (A > 0xFFFF))return -1;
result = &Page[A>>11][A]-PRGptr[0];
if((result > (int)(PRGsize[0])) || (result < 0))return -1;
else return result+16; //16 bytes for the header remember
else return result+NES_HEADER_SIZE; //16 bytes for the header remember
}
int GetRomAddress(int A){
int i;
uint8 *p = GetNesPRGPointer(A-=16);
uint8 *p = GetNesPRGPointer(A-=NES_HEADER_SIZE);
for(i = 16;i < 32;i++){
if((&Page[i][i<<11] <= p) && (&Page[i][(i+1)<<11] > p))break;
}
+1 -1
View File
@@ -172,7 +172,7 @@ DebuggerState &FCEUI_Debugger();
//#define WRITE_BREAKPOINT 16
//#define EXECUTE_BREAKPOINT 32
int offsetStringToInt(unsigned int type, const char* offsetBuffer);
int offsetStringToInt(unsigned int type, const char* offsetBuffer, bool *conversionOk = nullptr);
unsigned int NewBreak(const char* name, int start, int end, unsigned int type, const char* condition, unsigned int num, bool enable);
#endif
+93 -2
View File
@@ -7,6 +7,7 @@
#include "debug.h"
#include "fceu.h"
#include "cart.h"
#include "ld65dbg.h"
#ifdef __QT_DRIVER__
#include "Qt/ConsoleUtilities.h"
@@ -385,6 +386,18 @@ void debugSymbolTable_t::clear(void)
pageMap.clear();
}
//--------------------------------------------------------------
int debugSymbolTable_t::numSymbols(void)
{
int n = 0;
FCEU::autoScopedLock alock(cs);
for (auto it=pageMap.begin(); it!=pageMap.end(); it++)
{
n += it->second->size();
}
return n;
}
//--------------------------------------------------------------
static int generateNLFilenameForBank(int bank, std::string &NLfilename)
{
int i;
@@ -743,12 +756,11 @@ int debugSymbolTable_t::loadGameSymbols(void)
{
int nPages, pageSize, romSize = 0x10000;
this->save();
this->clear();
if ( GameInfo != nullptr )
{
romSize = 16 + CHRsize[0] + PRGsize[0];
romSize = NES_HEADER_SIZE + CHRsize[0] + PRGsize[0];
}
loadFileNL( -1 );
@@ -773,6 +785,7 @@ int debugSymbolTable_t::loadGameSymbols(void)
return 0;
}
//--------------------------------------------------------------
int debugSymbolTable_t::addSymbolAtBankOffset(int bank, int ofs, const char *name, const char *comment)
{
int result = -1;
@@ -909,3 +922,81 @@ const char *debugSymbolTable_t::errorMessage(void)
return dbgSymTblErrMsg;
}
//--------------------------------------------------------------
static void ld65_iterate_cb( void *userData, ld65::sym *s )
{
debugSymbolTable_t *tbl = static_cast<debugSymbolTable_t*>(userData);
if (tbl)
{
tbl->ld65_SymbolLoad(s);
}
}
//--------------------------------------------------------------
void debugSymbolTable_t::ld65_SymbolLoad( ld65::sym *s )
{
int bank = -1;
debugSymbol_t *sym;
debugSymbolPage_t *page;
ld65::scope *scope = s->getScope();
ld65::segment *seg = s->getSegment();
if ( s->type() == ld65::sym::LABEL )
{
//printf("Symbol Label Load: name:\"%s\" val:%i 0x%x\n", s->name(), s->value(), s->value() );
if (seg)
{
int romAddr = seg->ofs() - NES_HEADER_SIZE;
bank = romAddr >= 0 ? romAddr / (1<<debuggerPageSize) : -1;
//printf(" Seg: name:'%s' ofs:%i Bank:%x\n", seg->name(), romAddr, bank );
}
//printf("\n");
auto pageIt = pageMap.find(bank);
if (pageIt == pageMap.end() )
{
page = new debugSymbolPage_t(bank);
pageMap[bank] = page;
}
else
{
page = pageIt->second;
}
std::string name;
if (scope)
{
scope->getFullName(name);
}
name.append(s->name());
//printf("Creating Symbol: %s\n", name.c_str() );
sym = new debugSymbol_t( s->value(), name.c_str() );
if ( page->addSymbol( sym ) )
{
//printf("Failed to load sym: id:%i name:'%s' bank:%i \n", s->id(), s->name(), bank );
delete sym;
}
}
}
//--------------------------------------------------------------
int debugSymbolTable_t::ld65LoadDebugFile( const char *dbgFilePath )
{
ld65::database db;
if ( db.dbgFileLoad( dbgFilePath ) )
{
return -1;
}
FCEU::autoScopedLock alock(cs);
db.iterateSymbols( this, ld65_iterate_cb );
return 0;
}
//--------------------------------------------------------------
+8 -4
View File
@@ -5,6 +5,7 @@
#include <map>
#include "utils/mutex.h"
#include "ld65dbg.h"
class debugSymbolPage_t;
class debugSymbolTable_t;
@@ -91,7 +92,7 @@ class debugSymbolPage_t
int save(void);
void print(void);
int size(void){ return symMap.size(); }
int size(void){ return static_cast<int>(symMap.size()); }
int addSymbol( debugSymbol_t *sym );
@@ -130,8 +131,10 @@ class debugSymbolTable_t
~debugSymbolTable_t(void);
int loadFileNL( int addr );
int loadRegisterMap(void);
int loadGameSymbols(void);
int numPages(void){ return pageMap.size(); }
int numSymbols(void);
void save(void);
void clear(void);
@@ -153,12 +156,13 @@ class debugSymbolTable_t
const char *errorMessage(void);
int ld65LoadDebugFile( const char *dbgFilePath );
void ld65_SymbolLoad( ld65::sym *s );
private:
std::map <int, debugSymbolPage_t*> pageMap;
FCEU::mutex *cs;
int loadRegisterMap(void);
};
extern debugSymbolTable_t debugSymbolTable;
+1 -1
View File
@@ -346,7 +346,7 @@ void FCEU_DrawRecordingStatus(uint8* XBuf)
hasPlayRecIcon = true;
}
if(FCEUI_EmulationPaused())
if( EmulationPaused & (EMULATIONPAUSED_PAUSED | EMULATIONPAUSED_TIMER) )
drawstatus(XBuf-ClipSidesOffset,3,28,hasPlayRecIcon?-16:0);
}
}
+2
View File
@@ -273,6 +273,8 @@ void FCEUI_ClearEmulationFrameStepped();
void FCEUI_SetEmulationPaused(int val);
///toggles the paused bit (bit0) for EmulationPaused. caused FCEUD_DebugUpdate() to fire if the emulation pauses
void FCEUI_ToggleEmulationPause();
void FCEUI_PauseForDuration(int secs);
int FCEUI_PauseFramesRemaining();
//indicates whether input aids should be drawn (such as crosshairs, etc; usually in fullscreen mode)
bool FCEUD_ShouldDrawInputAids();
+4 -4
View File
@@ -191,7 +191,7 @@ size_t EMUFILE::read32le(u32* Bufo)
u32 EMUFILE::read32le()
{
u32 ret;
u32 ret=0;
read32le(&ret);
return ret;
}
@@ -230,7 +230,7 @@ size_t EMUFILE::read16le(u16* Bufo)
u16 EMUFILE::read16le()
{
u16 ret;
u16 ret=0;
read16le(&ret);
return ret;
}
@@ -269,14 +269,14 @@ void EMUFILE::writedouble(double val)
double EMUFILE::readdouble()
{
double temp;
double temp=0.0;
readdouble(&temp);
return temp;
}
size_t EMUFILE::readdouble(double* val)
{
u64 temp;
u64 temp=0;
size_t ret = read64le(&temp);
*val = u64_to_double(temp);
return ret;
+2 -2
View File
@@ -179,10 +179,10 @@ public:
va_start(argptr, format);
vsprintf(tempbuf,format,argptr);
fwrite(tempbuf,amt);
fwrite(tempbuf,amt);
delete[] tempbuf;
va_end(argptr);
va_end(argptr);
return amt;
};
+57 -3
View File
@@ -36,6 +36,7 @@
#include "unif.h"
#include "cheat.h"
#include "palette.h"
#include "profiler.h"
#include "state.h"
#include "movie.h"
#include "video.h"
@@ -116,6 +117,7 @@ bool movieSubtitles = true; //Toggle for displaying movie subtitles
bool DebuggerWasUpdated = false; //To prevent the debugger from updating things without being updated.
bool AutoResumePlay = false;
char romNameWhenClosingEmulator[2048] = {0};
static unsigned int pauseTimer = 0;
FCEUGI::FCEUGI()
@@ -208,6 +210,8 @@ static void FCEU_CloseGame(void)
GameInterface(GI_CLOSE);
FCEU_StateRecorderStop();
FCEUI_StopMovie();
ResetExState(0, 0);
@@ -592,6 +596,12 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
}
FCEU_fclose(fp);
if ( FCEU_StateRecorderIsEnabled() )
{
FCEU_StateRecorderStart();
}
return GameInfo;
}
@@ -725,6 +735,7 @@ extern unsigned int frameAdvHoldTimer;
///Skip may be passed in, if FRAMESKIP is #defined, to cause this to emulate more than one frame
void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int skip) {
FCEU_PROFILE_FUNC(prof, "Emulate Single Frame");
//skip initiates frame skip if 1, or frame skip and sound skip if 2
FCEU_MAYBE_UNUSED int r;
int ssize;
@@ -756,6 +767,22 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
#endif
}
if (EmulationPaused & EMULATIONPAUSED_TIMER)
{
if (pauseTimer > 0)
{
pauseTimer--;
}
else
{
EmulationPaused &= ~EMULATIONPAUSED_TIMER;
}
if (EmulationPaused & EMULATIONPAUSED_PAUSED)
{
EmulationPaused &= ~EMULATIONPAUSED_TIMER;
}
}
if (EmulationPaused & EMULATIONPAUSED_FA)
{
// the user is holding Frame Advance key
@@ -779,7 +806,7 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
RefreshThrottleFPS();
}
#endif
if (EmulationPaused & EMULATIONPAUSED_PAUSED)
if (EmulationPaused & (EMULATIONPAUSED_PAUSED | EMULATIONPAUSED_TIMER) )
{
// emulator is paused
memcpy(XBuf, XBackBuf, 256*256);
@@ -793,6 +820,7 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
AutoFire();
UpdateAutosave();
FCEU_StateRecorderUpdate();
#ifdef _S9XLUA_H
FCEU_LuaFrameBoundary();
@@ -892,8 +920,7 @@ void ResetNES(void) {
extern uint8 *XBackBuf;
memset(XBackBuf, 0, 256 * 256);
// OpenEmu
//FCEU_DispMessage("Reset", 0);
FCEU_DispMessage("Reset", 0);
}
@@ -1255,6 +1282,33 @@ void FCEUI_FrameAdvance(void) {
frameAdvanceRequested = true;
}
void FCEUI_PauseForDuration(int secs)
{
int framesPerSec;
// If already paused, do nothing
if (EmulationPaused & EMULATIONPAUSED_PAUSED)
{
return;
}
if (PAL || dendy)
{
framesPerSec = 50;
}
else
{
framesPerSec = 60;
}
pauseTimer = framesPerSec * secs;
EmulationPaused |= EMULATIONPAUSED_TIMER;
}
int FCEUI_PauseFramesRemaining(void)
{
return (EmulationPaused & EMULATIONPAUSED_TIMER) ? pauseTimer : 0;
}
static int AutosaveCounter = 0;
void UpdateAutosave(void) {
+4 -2
View File
@@ -181,8 +181,10 @@ extern uint8 vsdip;
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
#define EMULATIONPAUSED_PAUSED 1
#define EMULATIONPAUSED_FA 2
#define EMULATIONPAUSED_PAUSED 0x01
#define EMULATIONPAUSED_TIMER 0x02
#define EMULATIONPAUSED_FA 0x04
#define FRAMEADVANCE_DELAY_DEFAULT 10
#define NES_HEADER_SIZE 16
-3
View File
@@ -21,9 +21,6 @@ enum LuaMemHookType
LUAMEMHOOK_WRITE,
LUAMEMHOOK_READ,
LUAMEMHOOK_EXEC,
LUAMEMHOOK_WRITE_SUB,
LUAMEMHOOK_READ_SUB,
LUAMEMHOOK_EXEC_SUB,
LUAMEMHOOK_COUNT
};
+1 -1
View File
@@ -37,7 +37,7 @@ void SexyFilter2(int32 *in, int32 count)
while(count--)
{
int64 dropcurrent;
dropcurrent=((*in<<16)-acc)>>3;
dropcurrent=( int32(uint32(*in)<<16)-acc)>>3;
acc+=dropcurrent;
*in=acc>>16;
+15
View File
@@ -0,0 +1,15 @@
CC = gcc
%.h: %.coef
cat $< | ./toh > $@ || true
all: floogie c44100ntsc.h c48000ntsc.h c96000ntsc.h c44100pal.h c48000pal.h c96000pal.h
#c44100ntsc.h: c44100ntsc.coef
#c48000ntsc.h: c48000ntsc.coef
#c96000ntsc.h: c96000ntsc.coef
#c44100pal.h: c44100pal.coef
#c48000pal.h: c48000pal.coef
#c96000pal.h: c96000pal.coef
floogie: toh.o
gcc -o toh toh.o
+5 -3
View File
@@ -689,7 +689,7 @@ BMAPPINGLocal bmap[] = {
{"", 171, Mapper171_Init},
{"", 172, Mapper172_Init},
{"", 173, Mapper173_Init},
// {"", 174, Mapper174_Init},
{"NTDec 5-in-1", 174, Mapper174_Init},
{"", 175, Mapper175_Init},
{"BMCFK23C", 176, BMCFK23C_Init}, // zero 26-may-2012 - well, i have some WXN junk games that use 176 for instance ????. i dont know what game uses this BMCFK23C as mapper 176. we'll have to make a note when we find it.
{"", 177, Mapper177_Init},
@@ -720,7 +720,7 @@ BMAPPINGLocal bmap[] = {
{"", 202, Mapper202_Init},
{"", 203, Mapper203_Init},
{"", 204, Mapper204_Init},
{"", 205, Mapper205_Init},
{"JC-016-2", 205, Mapper205_Init},
{"NAMCOT 108 Rev. C", 206, Mapper206_Init}, // Deprecated, Used to be "DEIROM" whatever it means, but actually simple version of MMC3
{"TAITO X1-005 Rev. B", 207, Mapper207_Init},
{"", 208, Mapper208_Init},
@@ -788,6 +788,8 @@ BMAPPINGLocal bmap[] = {
{"HP10xx/H20xx Boards", 260, BMCHPxx_Init},
{"810544-CA-1", 261, BMC810544CA1_Init},
{"AA6023/AA6023B", 268, AA6023_Init},
{"OK-411", 361, GN45_Init},
{"GN-45", 366, GN45_Init},
{"COOLGIRL", 342, COOLGIRL_Init },
{"FAM250/81-01-39-C/SCHI-24", 354, Mapper354_Init },
@@ -810,7 +812,7 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
head.cleanup();
memset(&iNESCart, 0, sizeof(iNESCart));
iNESCart.clear();
iNES2 = ((head.ROM_type2 & 0x0C) == 0x08);
if(iNES2)
+2
View File
@@ -208,6 +208,7 @@ void Mapper170_Init(CartInfo *);
void Mapper171_Init(CartInfo *);
void Mapper172_Init(CartInfo *);
void Mapper173_Init(CartInfo *);
void Mapper174_Init(CartInfo *);
void Mapper175_Init(CartInfo *);
void Mapper177_Init(CartInfo *);
void Mapper178_Init(CartInfo *);
@@ -279,6 +280,7 @@ void Mapper354_Init(CartInfo *);
void Mapper406_Init(CartInfo *);
void INX_007T_Init(CartInfo* info);
void GN45_Init(CartInfo *info); /* previously mapper 205 */
typedef struct {
const char *name;
+419
View File
@@ -0,0 +1,419 @@
// ld65dbg.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "types.h"
#include "ld65dbg.h"
namespace ld65
{
//---------------------------------------------------------------------------------------------------
segment::segment( int id, const char *name, int startAddr, int size, int ofs, unsigned char type )
: _name(name ? name : ""), _id(id), _startAddr(startAddr), _size(size), _ofs(ofs), _type(type)
{
}
//---------------------------------------------------------------------------------------------------
scope::scope(int id, const char *name, int size, int parentID)
: _name(name ? name : ""), _id(id), _parentID(parentID), _size(size), _parent(nullptr)
{
}
//---------------------------------------------------------------------------------------------------
void scope::getFullName(std::string &out)
{
if ( _parent )
{
_parent->getFullName(out);
}
if (!_name.empty())
{
out.append(_name);
out.append("::");
}
}
//---------------------------------------------------------------------------------------------------
sym::sym(int id, const char *name, int size, int value, int type)
: _name(name ? name : ""), _id(id), _size(size), _value(value), _type(type), _scope(nullptr), _segment(nullptr)
{
}
//---------------------------------------------------------------------------------------------------
database::database(void)
{
}
//---------------------------------------------------------------------------------------------------
database::~database(void)
{
for (auto itSym = symMap.begin(); itSym != symMap.end(); itSym++)
{
delete itSym->second;
}
for (auto itScope = scopeMap.begin(); itScope != scopeMap.end(); itScope++)
{
delete itScope->second;
}
for (auto itSeg = segmentMap.begin(); itSeg != segmentMap.end(); itSeg++)
{
delete itSeg->second;
}
}
//---------------------------------------------------------------------------------------------------
database::dbgLine::dbgLine(size_t bufferSize)
{
buf = NULL;
bufSize = 0;
readPtr = 0;
allocBuffer( bufferSize );
}
//---------------------------------------------------------------------------------------------------
database::dbgLine::~dbgLine(void)
{
if (buf)
{
::free(buf); buf = NULL;
}
bufSize = 0;
readPtr = 0;
}
//---------------------------------------------------------------------------------------------------
void database::dbgLine::allocBuffer(size_t bufferSize)
{
if (buf)
{
::free(buf); buf = NULL;
}
bufSize = 0;
readPtr = 0;
buf = static_cast<char*>( ::malloc( bufferSize ) );
if (buf == NULL)
{
bufSize = 0;
}
else
{
buf[0] = 0;
bufSize = bufferSize;
}
readPtr = 0;
}
//---------------------------------------------------------------------------------------------------
const char *database::dbgLine::readFromFile( FILE *fp )
{
readPtr = 0;
return fgets(buf, bufSize, fp);
}
//---------------------------------------------------------------------------------------------------
int database::dbgLine::readToken( char *tk, size_t tkSize )
{
int charsRead = 0;
size_t i,j;
i=readPtr; j=0;
if ( buf[i] != 0 )
{
while (isspace(buf[i])) i++;
if ( isalpha(buf[i]) || (buf[i] == '_') )
{
while ( isalnum(buf[i]) || (buf[i] == '_') )
{
if (j < tkSize)
{
tk[j] = buf[i]; j++;
}
i++;
}
}
else if (buf[i] != 0)
{
if (j < tkSize)
{
tk[j] = buf[i]; j++;
}
i++;
}
}
charsRead = j;
readPtr = i;
if (j < tkSize)
{
tk[j] = 0;
}
else
{
tk[tkSize-1] = 0;
}
return charsRead;
}
//---------------------------------------------------------------------------------------------------
int database::dbgLine::readKeyValuePair( char *keyValueBuffer, size_t keyValueBufferSize )
{
int charsRead = 0;
size_t i,j;
bool isStringLiteral = false;
i=readPtr; j=0;
if ( buf[i] != 0 )
{
while (isspace(buf[i])) i++;
if ( isalpha(buf[i]) || (buf[i] == '_') )
{
while ( isalnum(buf[i]) || (buf[i] == '_') )
{
if (j < keyValueBufferSize)
{
keyValueBuffer[j] = buf[i]; j++;
}
i++;
}
}
else if (buf[i] != 0)
{
if (j < keyValueBufferSize)
{
keyValueBuffer[j] = buf[i]; j++;
}
i++;
}
while (isspace(buf[i])) i++;
}
if ( buf[i] == '=' )
{
if (j < keyValueBufferSize)
{
keyValueBuffer[j] = buf[i]; j++;
}
i++;
while (isspace(buf[i])) i++;
while ( buf[i] != 0 )
{
if ( !isStringLiteral && buf[i] == ',' )
{
break;
}
else if ( buf[i] == '\"' )
{
isStringLiteral = !isStringLiteral;
}
else
{
if (j < keyValueBufferSize)
{
if (!isspace(buf[i]))
{
keyValueBuffer[j] = buf[i]; j++;
}
}
}
i++;
}
if (buf[i] == ',')
{
i++;
}
}
charsRead = j;
readPtr = i;
if (j < keyValueBufferSize)
{
keyValueBuffer[j] = 0;
}
else
{
keyValueBuffer[keyValueBufferSize-1] = 0;
}
return charsRead;
}
//---------------------------------------------------------------------------------------------------
int database::dbgLine::splitKeyValuePair( char *keyValueBuffer, char **keyPtr, char **valuePtr )
{
size_t i=0;
if (keyPtr != nullptr)
{
*keyPtr = keyValueBuffer;
}
while (keyValueBuffer[i] != 0)
{
if (keyValueBuffer[i] == '=')
{
keyValueBuffer[i] = 0; i++; break;
}
i++;
}
if (valuePtr != nullptr)
{
*valuePtr = &keyValueBuffer[i];
}
return 0;
}
//---------------------------------------------------------------------------------------------------
int database::dbgFileLoad( const char *dbgFilePath )
{
static constexpr size_t lineSize = 4096;
FILE *fp;
dbgLine line( lineSize );
char lineType[64];
fceuScopedPtr <char> keyValueBuffer( new char[ lineSize ], FCEU_ALLOC_TYPE_NEW_ARRAY );
fp = ::fopen( dbgFilePath, "r");
if (fp == NULL)
{
return -1;
}
while ( line.readFromFile(fp) != NULL )
{
//printf("%s", line.getLine());
if ( line.readToken( lineType, sizeof(lineType) ) )
{
int id = -1, size = 0, startAddr = 0, ofs = -1, parentID = -1, scopeID = -1, segmentID = -1;
int value = 0;
unsigned char segType = segment::READ;
char name[256];
char type[32];
name[0] = 0;
type[0] = 0;
while ( line.readKeyValuePair( keyValueBuffer.get(), lineSize) )
{
char *key, *val;
line.splitKeyValuePair( keyValueBuffer.get(), &key, &val );
//printf(" Key '%s' -> Value '%s' \n", key, val );
if ( strcmp( key, "id") == 0 )
{
id = strtol( val, nullptr, 0 );
}
else if ( strcmp( key, "name") == 0 )
{
strncpy( name, val, sizeof(name));
}
else if ( strcmp( key, "size") == 0 )
{
size = strtol( val, nullptr, 0 );
}
else if ( strcmp( key, "val") == 0 )
{
value = strtol( val, nullptr, 0 );
}
else if ( strcmp( key, "scope") == 0 )
{
scopeID = strtol( val, nullptr, 0 );
}
else if ( strcmp( key, "parent") == 0 )
{
parentID = strtol( val, nullptr, 0 );
}
else if ( strcmp( key, "seg") == 0 )
{
segmentID = strtol( val, nullptr, 0 );
}
else if ( strcmp( key, "ooffs") == 0 )
{
ofs = strtol( val, nullptr, 0 );
}
else if ( strcmp( key, "type") == 0 )
{
strncpy( type, val, sizeof(type));
}
}
if ( strcmp( lineType, "seg" ) == 0 )
{
if ( id >= 0 )
{
segment *s = new segment( id, name, startAddr, size, ofs, segType );
segmentMap[id] = s;
}
}
else if ( strcmp( lineType, "scope" ) == 0 )
{
if ( id >= 0 )
{
scope *s = new scope( id, name, size, parentID );
scopeMap[id] = s;
auto it = scopeMap.find( parentID );
if ( it != scopeMap.end() )
{
//printf("Found Parent:%i for %i\n", parentID, id );
s->_parent = it->second;
}
}
}
else if ( strcmp( lineType, "sym") == 0 )
{
if ( id >= 0 )
{
int symType = sym::IMPORT;
if ( strcmp( type, "lab") == 0)
{
symType = sym::LABEL;
}
else if ( strcmp( type, "equ") == 0)
{
symType = sym::EQU;
}
sym *s = new sym( id, name, size, value, symType );
auto it = scopeMap.find( scopeID );
if ( it != scopeMap.end() )
{
//printf("Found Scope:%i for %s\n", scopeID, name );
s->_scope = it->second;
}
auto itSeg = segmentMap.find( segmentID );
if ( itSeg != segmentMap.end() )
{
//printf("Found Segment:%i for %s\n", segmentID, name );
s->_segment = itSeg->second;
}
symMap[id] = s;
}
}
}
}
::fclose(fp);
return 0;
}
//---------------------------------------------------------------------------------------------------
int database::iterateSymbols( void *userData, void (*cb)( void *userData, sym *s ) )
{
int numSyms = 0;
for (auto it = symMap.begin(); it != symMap.end(); it++)
{
cb( userData, it->second );
numSyms++;
}
return numSyms;
}
//---------------------------------------------------------------------------------------------------
}
+139
View File
@@ -0,0 +1,139 @@
// ld65dbg.h
//
#pragma once
#include <stdio.h>
#include <string>
#include <map>
namespace ld65
{
class database;
class segment
{
public:
static constexpr unsigned char READ = 0x01;
static constexpr unsigned char WRITE = 0x02;
segment( int id, const char *name = nullptr, int startAddr = 0, int size = 0, int ofs = -1, unsigned char type = READ );
const char *name(void){ return _name.c_str(); };
int addr(void){ return _startAddr; };
int ofs(void){ return _ofs; };
private:
std::string _name; // Segment Name
int _id; // Debug ID
int _startAddr; // Start Address CPU
int _size; // Memory region size
int _ofs; // ROM Offset
unsigned char _type; // ro or rw
friend class database;
};
class scope
{
public:
scope( int id, const char *name = nullptr, int size = 0, int parentID = -1);
const char *name(void){ return _name.c_str(); };
scope *getParent(void){ return _parent; };
void getFullName( std::string &out );
private:
std::string _name; // Scope Name
int _id; // Debug ID
int _parentID; // Parent ID
int _size;
scope *_parent;
friend class database;
};
class sym
{
public:
enum
{
IMPORT = 0,
LABEL,
EQU
};
sym( int id, const char *name = nullptr, int size = 0, int value = 0, int type = IMPORT);
int id(void){ return _id; };
const char *name(void){ return _name.c_str(); };
int size(void){ return _size; };
int value(void){ return _value; };
int type(void){ return _type; };
scope *getScope(void){ return _scope; };
segment *getSegment(void){ return _segment; };
private:
std::string _name; // Scope Name
int _id; // Debug ID
int _size;
int _value;
int _type;
scope *_scope;
segment *_segment;
friend class database;
};
class database
{
public:
database(void);
~database(void);
int dbgFileLoad( const char *dbgFilePath );
int iterateSymbols( void *userData, void (*cb)( void *userData, sym *s ) );
private:
std::map<int, scope*> scopeMap;
std::map<int, segment*> segmentMap;
std::map<int, sym*> symMap;
class dbgLine
{
public:
dbgLine(size_t bufferSize = 1024);
~dbgLine(void);
const char *readFromFile( FILE *fp );
const char *getLine(void){ return buf; };
int readToken( char *tk, size_t tkSize );
int readKeyValuePair( char *keyValueBuffer, size_t keyValueBufferSize );
static int splitKeyValuePair( char *keyValueBuffer, char **keyPtr, char **valuePtr );
private:
void allocBuffer(size_t bufferSize);
size_t readPtr;
size_t bufSize;
char *buf;
};
};
};
+4 -45
View File
@@ -26,7 +26,6 @@
#include "debug.h"
#include "debugsymboltable.h"
#include "sound.h"
#include "drawing.h"
#include "state.h"
#include "movie.h"
#include "driver.h"
@@ -319,10 +318,6 @@ static const char* luaMemHookTypeStrings [] =
"MEMHOOK_WRITE",
"MEMHOOK_READ",
"MEMHOOK_EXEC",
"MEMHOOK_WRITE_SUB",
"MEMHOOK_READ_SUB",
"MEMHOOK_EXEC_SUB",
};
//make sure we have the right number of strings
@@ -2431,53 +2426,17 @@ static int memory_registerHook(lua_State* L, LuaMemHookType hookType, int defaul
return 0;
}
LuaMemHookType MatchHookTypeToCPU(lua_State* L, LuaMemHookType hookType)
{
int cpuID = 0;
int cpunameIndex = 0;
if(lua_type(L,2) == LUA_TSTRING)
cpunameIndex = 2;
else if(lua_type(L,3) == LUA_TSTRING)
cpunameIndex = 3;
if(cpunameIndex)
{
const char* cpuName = lua_tostring(L, cpunameIndex);
if(!stricmp(cpuName, "sub"))
cpuID = 1;
lua_remove(L, cpunameIndex);
}
switch(cpuID)
{
case 0:
return hookType;
case 1:
switch(hookType)
{
case LUAMEMHOOK_WRITE: return LUAMEMHOOK_WRITE_SUB;
case LUAMEMHOOK_READ: return LUAMEMHOOK_READ_SUB;
case LUAMEMHOOK_EXEC: return LUAMEMHOOK_EXEC_SUB;
default: return hookType;
}
}
return hookType;
}
static int memory_registerwrite(lua_State *L)
{
return memory_registerHook(L, MatchHookTypeToCPU(L,LUAMEMHOOK_WRITE), 1);
return memory_registerHook(L, LUAMEMHOOK_WRITE, 1);
}
FCEU_MAYBE_UNUSED
static int memory_registerread(lua_State *L)
{
return memory_registerHook(L, MatchHookTypeToCPU(L,LUAMEMHOOK_READ), 1);
return memory_registerHook(L, LUAMEMHOOK_READ, 1);
}
static int memory_registerexec(lua_State *L)
{
return memory_registerHook(L, MatchHookTypeToCPU(L,LUAMEMHOOK_EXEC), 1);
return memory_registerHook(L, LUAMEMHOOK_EXEC, 1);
}
//adelikat: table pulled from GENS. credz nitsuja!
@@ -6137,7 +6096,7 @@ static const struct luaL_reg memorylib [] = {
// memory hooks
{"registerwrite", memory_registerwrite},
//{"registerread", memory_registerread}, TODO
{"registerread", memory_registerread},
{"registerexec", memory_registerexec},
// alternate names
{"register", memory_registerwrite},
+9 -10
View File
@@ -984,23 +984,23 @@ bool MovieData::loadSaveramFrom(std::vector<uint8>* buf)
return false;
}
for(int i=0;i<4;i++)
for (size_t i=0;i<currCartInfo->SaveGame.size();i++)
{
int len = ms.read32le();
if(!currCartInfo->SaveGame[i] && len!=0)
if( (currCartInfo->SaveGame[i].bufptr == nullptr) && (len!=0) )
{
FCEU_PrintError("movie battery load mismatch 2");
return false;
}
if(currCartInfo->SaveGameLen[i] != static_cast<unsigned int>(len))
if(currCartInfo->SaveGame[i].buflen != static_cast<size_t>(len))
{
FCEU_PrintError("movie battery load mismatch 3");
return false;
}
ms.fread(currCartInfo->SaveGame[i], len);
ms.fread(currCartInfo->SaveGame[i].bufptr, len);
}
return true;
@@ -1011,16 +1011,15 @@ void MovieData::dumpSaveramTo(std::vector<uint8>* buf, int compressionLevel)
EMUFILE_MEMORY ms(buf);
ms.write32le(currCartInfo->battery?1:0);
for(int i=0;i<4;i++)
for(size_t i=0;i<currCartInfo->SaveGame.size();i++)
{
if(!currCartInfo->SaveGame[i])
if (!currCartInfo->SaveGame[i].bufptr)
{
ms.write32le((u32)0);
continue;
}
ms.write32le(currCartInfo->SaveGameLen[i]);
ms.fwrite(currCartInfo->SaveGame[i], currCartInfo->SaveGameLen[i]);
ms.write32le( static_cast<uint32>(currCartInfo->SaveGame[i].buflen) );
ms.fwrite(currCartInfo->SaveGame[i].bufptr, currCartInfo->SaveGame[i].buflen);
}
}
@@ -1429,7 +1428,7 @@ int CheckTimelines(MovieData& stateMovie, MovieData& currMovie)
}
static bool load_successful;
static bool load_successful = false;
bool FCEUMOV_ReadState(EMUFILE* is, uint32 size)
{
+11 -4
View File
@@ -1734,10 +1734,17 @@ void FCEUPPU_Reset(void) {
void FCEUPPU_Power(void) {
int x;
memset(NTARAM, 0x00, 0x800);
memset(PALRAM, 0x00, 0x20);
memset(UPALRAM, 0x00, 0x03);
memset(SPRAM, 0x00, 0x100);
// initialize PPU memory regions according to settings
FCEU_MemoryRand(NTARAM, 0x800, true);
FCEU_MemoryRand(PALRAM, 0x20, true);
FCEU_MemoryRand(SPRAM, 0x100, true);
// palettes can only store values up to $3F, and PALRAM X4/X8/XC are mirrors of X0 for rendering purposes (UPALRAM is used for $2007 readback)
for (x = 0; x < 0x20; ++x) PALRAM[x] &= 0x3F;
UPALRAM[0] = PALRAM[0x04];
UPALRAM[1] = PALRAM[0x08];
UPALRAM[2] = PALRAM[0x0C];
PALRAM[0x0C] = PALRAM[0x08] = PALRAM[0x04] = PALRAM[0x00];
PALRAM[0x1C] = PALRAM[0x18] = PALRAM[0x14] = PALRAM[0x10];
FCEUPPU_Reset();
for (x = 0x2000; x < 0x4000; x += 8) {
+367
View File
@@ -0,0 +1,367 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
// profiler.cpp
//
#ifdef __FCEU_PROFILER_ENABLE__
#include <stdio.h>
#ifdef __QT_DRIVER__
#include <QThread>
#endif
#include "utils/mutex.h"
#include "fceu.h"
#include "profiler.h"
namespace FCEU
{
static thread_local profileExecVector execList;
static thread_local profilerFuncMap threadProfileMap;
FILE *profilerManager::pLog = nullptr;
static profilerManager pMgr;
//-------------------------------------------------------------------------
//---- Function Profile Record
//-------------------------------------------------------------------------
funcProfileRecord::funcProfileRecord(const char *fileNameStringLiteral,
const int fileLineNumber,
const char *funcNameStringLiteral,
const char *commentStringLiteral)
: fileLineNum(fileLineNumber), fileName(fileNameStringLiteral),
funcName(funcNameStringLiteral), comment(commentStringLiteral)
{
min.fromSeconds(9);
max.zero();
sum.zero();
numCalls = 0;
recursionCount = 0;
threadProfileMap.addRecord( fileNameStringLiteral, fileLineNumber,
funcNameStringLiteral, commentStringLiteral, this);
}
//-------------------------------------------------------------------------
void funcProfileRecord::reset(void)
{
min.fromSeconds(9);
max.zero();
sum.zero();
numCalls = 0;
}
//-------------------------------------------------------------------------
double funcProfileRecord::average(void)
{
double avg = 0.0;
if (numCalls)
{
avg = sum.toSeconds() / static_cast<double>(numCalls);
}
return avg;
}
//-------------------------------------------------------------------------
//---- Profile Scoped Function Class
//-------------------------------------------------------------------------
profileFuncScoped::profileFuncScoped( funcProfileRecord *recordIn )
{
rec = recordIn;
if (rec)
{
threadProfileMap.pushStack(rec);
start.readNew();
rec->numCalls++;
rec->recursionCount++;
}
}
//-------------------------------------------------------------------------
profileFuncScoped::~profileFuncScoped(void)
{
if (rec)
{
timeStampRecord ts, dt;
ts.readNew();
dt = ts - start;
rec->last = dt;
rec->sum += dt;
if (dt < rec->min) rec->min = dt;
if (dt > rec->max) rec->max = dt;
rec->recursionCount--;
execList._vec.push_back(*rec);
threadProfileMap.popStack(rec);
}
}
//-------------------------------------------------------------------------
//---- Profile Execution Vector
//-------------------------------------------------------------------------
profileExecVector::profileExecVector(void)
{
_vec.reserve( 10000 );
char threadName[128];
char fileName[256];
strcpy( threadName, "MainThread");
#ifdef __QT_DRIVER__
QThread *thread = QThread::currentThread();
if (thread)
{
//printf("Thread: %s\n", thread->objectName().toStdString().c_str());
strcpy( threadName, thread->objectName().toStdString().c_str());
}
#endif
sprintf( fileName, "fceux-profile-%s.log", threadName);
logFp = ::fopen(fileName, "w");
if (logFp == nullptr)
{
printf("Error: Failed to create profiler logfile: %s\n", fileName);
}
}
//-------------------------------------------------------------------------
profileExecVector::~profileExecVector(void)
{
if (logFp)
{
::fclose(logFp);
}
}
//-------------------------------------------------------------------------
void profileExecVector::update(void)
{
size_t n = _vec.size();
for (size_t i=0; i<n; i++)
{
funcProfileRecord &rec = _vec[i];
fprintf( logFp, "%s: %u %f %f %f %f\n", rec.funcName, rec.numCalls, rec.last.toSeconds(), rec.average(), rec.min.toSeconds(), rec.max.toSeconds());
}
_vec.clear();
}
//-------------------------------------------------------------------------
//---- Profile Function Record Map
//-------------------------------------------------------------------------
profilerFuncMap::profilerFuncMap(void)
{
//printf("profilerFuncMap Constructor: %p\n", this);
pMgr.addThreadProfiler(this);
_map_it = _map.begin();
}
//-------------------------------------------------------------------------
profilerFuncMap::~profilerFuncMap(void)
{
//printf("profilerFuncMap Destructor: %p\n", this);
pMgr.removeThreadProfiler(this);
//{
// autoScopedLock aLock(_mapMtx);
// for (auto it = _map.begin(); it != _map.end(); it++)
// {
// delete it->second;
// }
// _map.clear();
//}
}
//-------------------------------------------------------------------------
void profilerFuncMap::pushStack(funcProfileRecord *rec)
{
stack.push_back(rec);
}
//-------------------------------------------------------------------------
void profilerFuncMap::popStack(funcProfileRecord *rec)
{
stack.pop_back();
}
//-------------------------------------------------------------------------
int profilerFuncMap::addRecord(const char *fileNameStringLiteral,
const int fileLineNumber,
const char *funcNameStringLiteral,
const char *commentStringLiteral,
funcProfileRecord *rec )
{
autoScopedLock aLock(_mapMtx);
char lineString[64];
sprintf( lineString, ":%i", fileLineNumber);
std::string fname(fileNameStringLiteral);
fname.append( lineString );
_map[fname] = rec;
return 0;
}
//-------------------------------------------------------------------------
funcProfileRecord *profilerFuncMap::findRecord(const char *fileNameStringLiteral,
const int fileLineNumber,
const char *funcNameStringLiteral,
const char *commentStringLiteral,
bool create)
{
autoScopedLock aLock(_mapMtx);
char lineString[64];
funcProfileRecord *rec = nullptr;
sprintf( lineString, ":%i", fileLineNumber);
std::string fname(fileNameStringLiteral);
fname.append( lineString );
auto it = _map.find(fname);
if (it != _map.end())
{
rec = it->second;
}
else if (create)
{
fprintf( pMgr.pLog, "Creating Function Profile Record: %s %s\n", fname.c_str(), funcNameStringLiteral);
rec = new funcProfileRecord( fileNameStringLiteral, fileLineNumber,
funcNameStringLiteral, commentStringLiteral);
_map[fname] = rec;
}
return rec;
}
//-------------------------------------------------------------------------
funcProfileRecord *profilerFuncMap::iterateBegin(void)
{
autoScopedLock aLock(_mapMtx);
funcProfileRecord *rec = nullptr;
_map_it = _map.begin();
if (_map_it != _map.end())
{
rec = _map_it->second;
}
return rec;
}
//-------------------------------------------------------------------------
funcProfileRecord *profilerFuncMap::iterateNext(void)
{
autoScopedLock aLock(_mapMtx);
funcProfileRecord *rec = nullptr;
if (_map_it != _map.end())
{
_map_it++;
}
if (_map_it != _map.end())
{
rec = _map_it->second;
}
return rec;
}
//-------------------------------------------------------------------------
//----- profilerManager class
//-------------------------------------------------------------------------
profilerManager* profilerManager::instance = nullptr;
profilerManager* profilerManager::getInstance(void)
{
return instance;
}
//-------------------------------------------------------------------------
profilerManager::profilerManager(void)
{
//printf("profilerManager Constructor\n");
if (pLog == nullptr)
{
pLog = stdout;
}
if (instance == nullptr)
{
instance = this;
}
}
profilerManager::~profilerManager(void)
{
//printf("profilerManager Destructor\n");
{
autoScopedLock aLock(threadListMtx);
threadList.clear();
}
if (pLog && (pLog != stdout))
{
fclose(pLog); pLog = nullptr;
}
if (instance == this)
{
instance = nullptr;
}
}
int profilerManager::addThreadProfiler( profilerFuncMap *m )
{
autoScopedLock aLock(threadListMtx);
threadList.push_back(m);
return 0;
}
int profilerManager::removeThreadProfiler( profilerFuncMap *m, bool shouldDestroy )
{
int result = -1;
autoScopedLock aLock(threadListMtx);
for (auto it = threadList.begin(); it != threadList.end(); it++)
{
if (*it == m )
{
threadList.erase(it);
if (shouldDestroy)
{
delete m;
}
result = 0;
break;
}
}
return result;
}
//-------------------------------------------------------------------------
} // namespace FCEU
//-------------------------------------------------------------------------
int FCEU_profiler_log_thread_activity(void)
{
FCEU::execList.update();
return 0;
}
#endif // __FCEU_PROFILER_ENABLE__
+167
View File
@@ -0,0 +1,167 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
// profiler.h
#pragma once
/*
* This module is intended for debug use only. This allows for high precision timing of function
* execution. This functionality is not included in the build unless __FCEU_PROFILER_ENABLE__
* is defined. To check timing on a particular function, add FCEU_PROFILE_FUNC macro to the top
* of the function body in the following manner.
* FCEU_PROFILE_FUNC(prof, "String Literal comment, whatever I want it to say")
* When __FCEU_PROFILER_ENABLE__ is not defined, the FCEU_PROFILE_FUNC macro evaluates to nothing
* so it won't break the regular build by having it used in code.
*/
#ifdef __FCEU_PROFILER_ENABLE__
#include <stdio.h>
#include <stdint.h>
#include <string>
#include <vector>
#include <list>
#include <map>
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
#include <time.h>
#endif
#include "utils/mutex.h"
#include "utils/timeStamp.h"
namespace FCEU
{
struct funcProfileRecord
{
const int fileLineNum;
const char *fileName;
const char *funcName;
const char *comment;
timeStampRecord min;
timeStampRecord max;
timeStampRecord sum;
timeStampRecord last;
unsigned int numCalls;
unsigned int recursionCount;
funcProfileRecord(const char *fileNameStringLiteral,
const int fileLineNumber,
const char *funcNameStringLiteral,
const char *commentStringLiteral);
void reset(void);
double average(void);
};
struct profileFuncScoped
{
funcProfileRecord *rec;
timeStampRecord start;
profileFuncScoped( funcProfileRecord *recordIn );
~profileFuncScoped(void);
};
struct profileExecVector
{
profileExecVector(void);
~profileExecVector(void);
void update(void);
std::vector <funcProfileRecord> _vec;
FILE *logFp;
};
class profilerFuncMap
{
public:
profilerFuncMap();
~profilerFuncMap();
int addRecord(const char *fileNameStringLiteral,
const int fileLineNumber,
const char *funcNameStringLiteral,
const char *commentStringLiteral,
funcProfileRecord *rec );
funcProfileRecord *findRecord(const char *fileNameStringLiteral,
const int fileLineNumber,
const char *funcNameStringLiteral,
const char *commentStringLiteral,
bool create = false);
funcProfileRecord *iterateBegin(void);
funcProfileRecord *iterateNext(void);
void pushStack(funcProfileRecord *rec);
void popStack(funcProfileRecord *rec);
private:
mutex _mapMtx;
std::map<std::string, funcProfileRecord*> _map;
std::map<std::string, funcProfileRecord*>::iterator _map_it;
std::vector <funcProfileRecord*> stack;
};
class profilerManager
{
public:
profilerManager(void);
~profilerManager(void);
int addThreadProfiler( profilerFuncMap *m );
int removeThreadProfiler( profilerFuncMap *m, bool shouldDestroy = false );
static FILE *pLog;
static profilerManager *getInstance();
private:
mutex threadListMtx;
std::list <profilerFuncMap*> threadList;
static profilerManager *instance;
};
}
#if defined(__PRETTY_FUNCTION__)
#define __FCEU_PROFILE_FUNC_NAME__ __PRETTY_FUNCTION__
#else
#define __FCEU_PROFILE_FUNC_NAME__ __func__
#endif
#define FCEU_PROFILE_FUNC(id, comment) \
static thread_local FCEU::funcProfileRecord id( __FILE__, __LINE__, __FCEU_PROFILE_FUNC_NAME__, comment ); \
FCEU::profileFuncScoped id ## _unique_scope( &id )
int FCEU_profiler_log_thread_activity(void);
#else // __FCEU_PROFILER_ENABLE__ not defined
#define FCEU_PROFILE_FUNC(id, comment)
#endif // __FCEU_PROFILER_ENABLE__
+391 -5
View File
@@ -84,9 +84,9 @@ bool backupSavestates = true;
bool compressSavestates = true; //By default FCEUX compresses savestates when a movie is inactive.
// a temp memory stream. We'll be dumping some data here and then compress
EMUFILE_MEMORY memory_savestate;
static EMUFILE_MEMORY memory_savestate;
// temporary buffer for compressed data of a savestate
std::vector<uint8> compressed_buf;
static std::vector<uint8> compressed_buf;
#define SFMDATA_SIZE (128)
static SFORMAT SFMDATA[SFMDATA_SIZE];
@@ -152,7 +152,7 @@ static int SubWrite(EMUFILE* os, SFORMAT *sf)
os->fwrite(sf->desc,4);
write32le(sf->s&(~FCEUSTATE_FLAGS),os);
#ifndef LSB_FIRST
#ifdef FCEU_BIG_ENDIAN
if(sf->s&RLSB)
FlipByteOrder((uint8*)sf->v,sf->s&(~FCEUSTATE_FLAGS));
#endif
@@ -163,7 +163,7 @@ static int SubWrite(EMUFILE* os, SFORMAT *sf)
os->fwrite((char*)sf->v,sf->s&(~FCEUSTATE_FLAGS));
//Now restore the original byte order.
#ifndef LSB_FIRST
#ifdef FCEU_BIG_ENDIAN
if(sf->s&RLSB)
FlipByteOrder((uint8*)sf->v,sf->s&(~FCEUSTATE_FLAGS));
#endif
@@ -231,7 +231,7 @@ static bool ReadStateChunk(EMUFILE* is, SFORMAT *sf, int size)
else
is->fread((char *)tmp->v,tmp->s&(~FCEUSTATE_FLAGS));
#ifndef LSB_FIRST
#ifdef FCEU_BIG_ENDIAN
if(tmp->s&RLSB)
FlipByteOrder((uint8*)tmp->v,tmp->s&(~FCEUSTATE_FLAGS));
#endif
@@ -1179,3 +1179,389 @@ void RedoLoadState()
redoLS = false; //Flag that RedoLoadState can not be run again
undoLS = true; //Flag that LoadBackup can be run again
}
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//----------- Save State History ----------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
static StateRecorderConfigData stateRecorderConfig;
class StateRecorder
{
public:
StateRecorder(void)
{
loadConfig( stateRecorderConfig );
for (int i=0; i<ringBufSize; i++)
{
EMUFILE_MEMORY *em = new EMUFILE_MEMORY( 0x1000 );
ringBuf.push_back(em);
}
ringStart = ringHead = ringTail = 0;
frameCounter = 0;
lastState = ringHead;
loadIndexReset = false;
lastLoadFrame = 0;
}
~StateRecorder(void)
{
for (size_t i=0; i<ringBuf.size(); i++)
{
delete ringBuf[i];
}
ringBuf.clear();
}
void loadConfig( StateRecorderConfigData &config )
{
if (config.framesBetweenSnaps < 1)
{
config.framesBetweenSnaps = 1;
}
if (config.timeBetweenSnapsMinutes < 0.0)
{
config.timeBetweenSnapsMinutes = 3.0f / 60.0f;
}
if (config.timeBetweenSnapsMinutes > config.historyDurationMinutes)
{
config.historyDurationMinutes = config.timeBetweenSnapsMinutes;
}
if (config.timingMode)
{
const double fhistMin = config.historyDurationMinutes;
const double fsnapMin = config.timeBetweenSnapsMinutes;
const double fnumSnaps = fhistMin / fsnapMin;
ringBufSize = static_cast<int>( fnumSnaps + 0.5f );
int32_t fps = FCEUI_GetDesiredFPS(); // Do >> 24 to get in Hz
double hz = ( ((double)fps) / 16777216.0 );
double framesPerSnapf = hz * fsnapMin * 60.0;
framesPerSnap = static_cast<unsigned int>( framesPerSnapf + 0.50 );
}
else
{
const double fhistMin = config.historyDurationMinutes;
int32_t fps = FCEUI_GetDesiredFPS(); // Do >> 24 to get in Hz
double hz = ( ((double)fps) / 16777216.0 );
const double fsnapMin = static_cast<double>(config.framesBetweenSnaps) / (hz * 60.0);
const double fnumSnaps = fhistMin / fsnapMin;
ringBufSize = static_cast<int>( fnumSnaps + 0.5f );
framesPerSnap = config.framesBetweenSnaps;
}
printf("ringBufSize:%i framesPerSnap:%i\n", ringBufSize, framesPerSnap );
compressionLevel = config.compressionLevel;
loadPauseTime = config.loadPauseTimeSeconds;
pauseOnLoad = config.pauseOnLoad;
}
void update(void)
{
bool isPaused = EmulationPaused ? true : false;
unsigned int curFrame = static_cast<unsigned int>(currFrameCounter);
if (!isPaused && loadIndexReset)
{
ringHead = (lastState + 1) % ringBufSize;
frameCounter = curFrame;
loadIndexReset = false;
}
if (!isPaused && (curFrame > frameCounter) )
{
frameCounter = curFrame;
if ( (frameCounter % framesPerSnap) == 0 )
{
EMUFILE_MEMORY *em = ringBuf[ ringHead ];
em->set_len(0);
FCEUSS_SaveMS( em, compressionLevel );
//printf("Frame:%u Save:%i Size:%zu Total:%zukB \n", frameCounter, ringHead, em->size(), dataSize() / 1024 );
lastState = ringHead;
ringHead = (ringHead + 1) % ringBufSize;
if (ringStart == ringHead)
{
ringStart = (ringHead + 1) % ringBufSize;
}
}
}
}
int loadStateRelativeToEnd( int numSnapsFromLatest )
{
if (numSnapsFromLatest < 0)
{
numSnapsFromLatest = 0;
}
numSnapsFromLatest = numSnapsFromLatest % ringBufSize;
int snapIdx = ringHead - numSnapsFromLatest - 1;
loadStateByIndex(snapIdx);
return 0;
}
int loadStateByIndex( int snapIdx )
{
if (snapIdx < 0)
{
snapIdx = snapIdx + ringBufSize;
}
snapIdx = snapIdx % ringBufSize;
EMUFILE_MEMORY *em = ringBuf[ snapIdx ];
em->fseek(SEEK_SET, 0);
FCEUSS_LoadFP( em, SSLOADPARAM_NOBACKUP );
frameCounter = lastLoadFrame = static_cast<unsigned int>(currFrameCounter);
lastState = snapIdx;
loadIndexReset = true;
if (pauseOnLoad == StateRecorderConfigData::TEMPORARY_PAUSE)
{
if (loadPauseTime > 0)
{ // Temporary pause after loading new state for user to have time to process
FCEUI_PauseForDuration(loadPauseTime);
}
}
else if (pauseOnLoad == StateRecorderConfigData::FULL_PAUSE)
{
FCEUI_SetEmulationPaused( EMULATIONPAUSED_PAUSED );
}
return 0;
}
int loadPrevState(void)
{
int snapIdx = lastState;
if ( lastState == ringHead )
{ // No States to Load
return -1;
}
if ( lastState != ringStart )
{
if ( (lastLoadFrame+30) > frameCounter)
{
snapIdx--;
if (snapIdx < 0)
{
snapIdx += ringBufSize;
}
}
}
return loadStateByIndex( snapIdx );
}
int loadNextState(void)
{
int snapIdx = lastState;
int nextIdx = (lastState + 1) % ringBufSize;
if ( nextIdx != ringHead )
{
snapIdx = nextIdx;
}
return loadStateByIndex( snapIdx );
}
int getHeadIndex(void)
{
return ringHead;
}
int getStartIndex(void)
{
return ringStart;
}
int numSnapsSaved(void)
{
int numSnaps = ringHead - ringStart;
if (numSnaps < 0)
{
numSnaps = numSnaps + static_cast<int>( ringBuf.size() );
}
return numSnaps;
}
size_t dataSize(void)
{
return ringBuf.size() * ringBuf[0]->size();
}
size_t ringBufferSize(void)
{
return ringBuf.size();
}
static bool enabled;
static int lastState;
private:
void doSnap(void)
{
}
std::vector <EMUFILE_MEMORY*> ringBuf;
int ringHead;
int ringTail;
int ringStart;
int ringBufSize;
int compressionLevel;
int loadPauseTime;
StateRecorderConfigData::PauseType pauseOnLoad;
unsigned int frameCounter;
unsigned int framesPerSnap;
unsigned int lastLoadFrame;
bool loadIndexReset;
};
static StateRecorder *stateRecorder = nullptr;
bool StateRecorder::enabled = false;
int StateRecorder::lastState = 0;
int FCEU_StateRecorderStart(void)
{
if (stateRecorder == nullptr)
{
stateRecorder = new StateRecorder();
}
return stateRecorder == nullptr;
}
int FCEU_StateRecorderStop(void)
{
if (stateRecorder != nullptr)
{
delete stateRecorder; stateRecorder = nullptr;
}
return stateRecorder != nullptr;
}
int FCEU_StateRecorderUpdate(void)
{
if (stateRecorder != nullptr)
{
stateRecorder->update();
}
return 0;
}
bool FCEU_StateRecorderIsEnabled(void)
{
return StateRecorder::enabled;
}
void FCEU_StateRecorderSetEnabled(bool enabled)
{
StateRecorder::enabled = enabled;
}
bool FCEU_StateRecorderRunning(void)
{
return stateRecorder != nullptr;
}
int FCEU_StateRecorderGetMaxSnaps(void)
{
int size = 0;
if (stateRecorder != nullptr)
{
size = stateRecorder->ringBufferSize();
}
return size;
}
int FCEU_StateRecorderGetNumSnapsSaved(void)
{
int n = 0;
if (stateRecorder != nullptr)
{
n = stateRecorder->numSnapsSaved();
}
return n;
}
int FCEU_StateRecorderLoadState(int snapIndex)
{
int ret = -1;
if (stateRecorder != nullptr)
{
ret = stateRecorder->loadStateByIndex(snapIndex);
}
return ret;
}
int FCEU_StateRecorderGetStateIndex(void)
{
return StateRecorder::lastState;
}
int FCEU_StateRecorderLoadPrevState(void)
{
int ret = -1;
if (stateRecorder != nullptr)
{
ret = stateRecorder->loadPrevState();
}
return ret;
}
int FCEU_StateRecorderLoadNextState(void)
{
int ret = -1;
if (stateRecorder != nullptr)
{
ret = stateRecorder->loadNextState();
}
return ret;
}
const StateRecorderConfigData& FCEU_StateRecorderGetConfigData(void)
{
return stateRecorderConfig;
}
int FCEU_StateRecorderSetConfigData(const StateRecorderConfigData &newConfig)
{
stateRecorderConfig = newConfig;
if (stateRecorder != nullptr)
{
stateRecorder->loadConfig( stateRecorderConfig );
}
return 0;
}
+54
View File
@@ -17,6 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <string>
enum ENUM_SSLOADPARAMS
@@ -78,3 +79,56 @@ extern bool backupSavestates; //Whether or not to make backups, true by defaul
bool CheckBackupSaveStateExist(); //Checks if backupsavestate exists
extern bool compressSavestates; //Whether or not to compress non-movie savestates (by default, yes)
struct StateRecorderConfigData
{
float historyDurationMinutes;
float timeBetweenSnapsMinutes;
int framesBetweenSnaps;
int compressionLevel;
int loadPauseTimeSeconds;
enum TimingType
{
FRAMES = 0,
TIME,
} timingMode;
enum PauseType
{
NO_PAUSE = 0,
TEMPORARY_PAUSE,
FULL_PAUSE,
} pauseOnLoad;
StateRecorderConfigData(void)
{
framesBetweenSnaps = 60;
historyDurationMinutes = 15.0f;
timeBetweenSnapsMinutes = 3.0f / 60.0f;
compressionLevel = 0;
loadPauseTimeSeconds = 3;
pauseOnLoad = TEMPORARY_PAUSE;
timingMode = FRAMES;
}
bool compare( const StateRecorderConfigData &other )
{
return memcmp( this, &other, sizeof(StateRecorderConfigData) ) == 0;
}
};
int FCEU_StateRecorderStart(void);
int FCEU_StateRecorderStop(void);
int FCEU_StateRecorderUpdate(void);
bool FCEU_StateRecorderRunning(void);
bool FCEU_StateRecorderIsEnabled(void);
void FCEU_StateRecorderSetEnabled(bool enabled);
int FCEU_StateRecorderGetMaxSnaps(void);
int FCEU_StateRecorderGetNumSnapsSaved(void);
int FCEU_StateRecorderGetStateIndex(void);
int FCEU_StateRecorderLoadState(int snapIndex);
int FCEU_StateRecorderLoadPrevState(void);
int FCEU_StateRecorderLoadNextState(void);
int FCEU_StateRecorderSetConfigData(const StateRecorderConfigData &newConfig);
const StateRecorderConfigData& FCEU_StateRecorderGetConfigData(void);
+33 -7
View File
@@ -22,6 +22,9 @@
#ifndef __FCEU_TYPES
#define __FCEU_TYPES
#include <stdlib.h>
#include <new>
//enables a hack designed for debugging dragon warrior 3 which treats BRK as a 3-byte opcode
//#define BRK_3BYTE_HACK
@@ -182,24 +185,28 @@ typedef uint8 (*readfunc)(uint32 A);
// Scoped pointer ensures that memory pointed to by this object gets cleaned up
// and deallocated when this object goes out of scope. Helps prevent memory leaks
// on temporary memory allocations in functions with early outs.
enum fceuAllocType
{
FCEU_ALLOC_TYPE_NEW = 0,
FCEU_ALLOC_TYPE_NEW_ARRAY,
FCEU_ALLOC_TYPE_MALLOC
};
template <typename T>
class fceuScopedPtr
{
public:
fceuScopedPtr( T *ptrIn = nullptr )
fceuScopedPtr( T *ptrIn = nullptr, enum fceuAllocType allocType = FCEU_ALLOC_TYPE_NEW )
{
//printf("Scoped Pointer Constructor <%s>: %p\n", typeid(T).name(), ptrIn );
ptr = ptrIn;
_allocType = allocType;
}
~fceuScopedPtr(void)
{
//printf("Scoped Pointer Destructor <%s>: %p\n", typeid(T).name(), ptr );
if (ptr)
{
delete ptr;
ptr = nullptr;
}
Delete();
}
T* operator= (T *ptrIn)
@@ -217,13 +224,32 @@ class fceuScopedPtr
{
if (ptr)
{
delete ptr;
switch (_allocType)
{
case FCEU_ALLOC_TYPE_MALLOC:
{
::free(ptr);
}
break;
case FCEU_ALLOC_TYPE_NEW_ARRAY:
{
delete [] ptr;
}
break;
default:
case FCEU_ALLOC_TYPE_NEW:
{
delete ptr;
}
break;
}
ptr = nullptr;
}
}
private:
T *ptr;
enum fceuAllocType _allocType;
};
+3 -2
View File
@@ -104,7 +104,7 @@ static void ResetUNIF(void) {
vramo = 0;
boardname = 0;
mirrortodo = 0;
memset(&UNIFCart, 0, sizeof(UNIFCart));
UNIFCart.clear();
UNIFchrrama = 0;
}
@@ -475,7 +475,8 @@ static BMAPPING bmap[] = {
{ "FNS", FNS_Init, BMCFLAG_16KCHRR },
{ "BS-400R", BS400R_Init, 0 },
{ "BS-4040R", BS4040R_Init, 0 },
{ "COOLGIRL", COOLGIRL_Init, 0 },
{ "COOLGIRL", COOLGIRL_Init, BMCFLAG_256KCHRR },
{ "JC-016-2", Mapper205_Init, 0 },
{ 0, 0, 0 }
};
+9 -6
View File
@@ -28,8 +28,11 @@
#include "endian.h"
#include "../emufile.h"
//OMG ! configure this correctly
#ifdef FCEU_BIG_ENDIAN
#define LOCAL_BE
#else
#define LOCAL_LE
#endif
/* little endian to local endianess convert macros */
#ifdef LOCAL_BE /* local arch is big endian */
@@ -121,7 +124,7 @@ int read32le(uint32 *Bufo, FILE *fp)
uint32 buf;
if(fread(&buf,1,4,fp)<4)
return 0;
#ifdef LSB_FIRST
#ifdef FCEU_LITTLE_ENDIAN
*(uint32*)Bufo=buf;
#else
*(uint32*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24);
@@ -134,7 +137,7 @@ int read16le(uint16 *Bufo, std::istream *is)
uint16 buf;
if(is->read((char*)&buf,2).gcount() != 2)
return 0;
#ifdef LSB_FIRST
#ifdef FCEU_LITTLE_ENDIAN
*Bufo=buf;
#else
*Bufo = FCEU_de16lsb((uint8*)&buf);
@@ -148,7 +151,7 @@ int read64le(uint64 *Bufo, std::istream *is)
uint64 buf;
if(is->read((char*)&buf,8).gcount() != 8)
return 0;
#ifdef LSB_FIRST
#ifdef FCEU_LITTLE_ENDIAN
*Bufo=buf;
#else
*Bufo = FCEU_de64lsb((uint8*)&buf);
@@ -162,7 +165,7 @@ int read32le(uint32 *Bufo, std::istream *is)
uint32 buf;
if(is->read((char*)&buf,4).gcount() != 4)
return 0;
#ifdef LSB_FIRST
#ifdef FCEU_LITTLE_ENDIAN
*(uint32*)Bufo=buf;
#else
*(uint32*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24);
@@ -173,7 +176,7 @@ int read32le(uint32 *Bufo, std::istream *is)
///reads a little endian 16bit value from the specified file
int read16le(char *d, FILE *fp)
{
#ifdef LSB_FIRST
#ifdef FCEU_LITTLE_ENDIAN
return((fread(d,1,2,fp)<2)?0:2);
#else
int ret;
+8
View File
@@ -107,5 +107,13 @@ int writele(T *Bufo, EMUFILE*os)
}
}
#ifdef __BIG_ENDIAN__
# define FCEU_BIG_ENDIAN
#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
# define FCEU_BIG_ENDIAN
#else
# define FCEU_LITTLE_ENDIAN
#endif
#endif //__FCEU_ENDIAN
+4 -4
View File
@@ -53,7 +53,7 @@ void FCEU_afree(void* ptr)
#endif
}
static void *_FCEU_malloc(uint32 size)
static void *_FCEU_malloc(size_t size)
{
void* ret = malloc(size);
@@ -68,7 +68,7 @@ static void _FCEU_free(void* ptr)
free(ptr);
}
void *FCEU_gmalloc(uint32 size)
void *FCEU_gmalloc(size_t size)
{
void *ret = _FCEU_malloc(size);
@@ -78,7 +78,7 @@ void *FCEU_gmalloc(uint32 size)
return ret;
}
void *FCEU_malloc(uint32 size)
void *FCEU_malloc(size_t size)
{
void *ret = _FCEU_malloc(size);
memset(ret, 0, size);
@@ -95,7 +95,7 @@ void FCEU_free(void *ptr)
_FCEU_free(ptr);
}
void *FCEU_dmalloc(uint32 size)
void *FCEU_dmalloc(size_t size)
{
return FCEU_malloc(size);
}
+3 -3
View File
@@ -25,11 +25,11 @@
#define FCEU_dwmemset(d,c,n) {int _x; for(_x=n-4;_x>=0;_x-=4) *(uint32 *)&(d)[_x]=c;}
//returns a buffer initialized to 0
void *FCEU_malloc(uint32 size);
void *FCEU_malloc(size_t size);
//returns a buffer, with jumbled initial contents
//used by boards for WRAM etc, initialized to 0 (default) or other via RAMInitOption
void *FCEU_gmalloc(uint32 size);
void *FCEU_gmalloc(size_t size);
//free memory allocated with FCEU_gmalloc
void FCEU_gfree(void *ptr);
@@ -48,7 +48,7 @@ void FCEU_free(void *ptr);
void* FCEU_realloc(void* ptr, size_t size);
//don't use these. change them if you find them.
void *FCEU_dmalloc(uint32 size);
void *FCEU_dmalloc(size_t size);
//don't use these. change them if you find them.
void FCEU_dfree(void *ptr);
+9
View File
@@ -60,6 +60,15 @@ autoScopedLock::autoScopedLock( mutex *mtx )
}
}
autoScopedLock::autoScopedLock( mutex &mtx )
{
m = &mtx;
if (m)
{
m->lock();
}
}
autoScopedLock::~autoScopedLock(void)
{
if (m)
+2
View File
@@ -1,4 +1,5 @@
// mutex.h
#pragma once
#ifdef __QT_DRIVER__
#include <QMutex>
@@ -32,6 +33,7 @@ namespace FCEU
{
public:
autoScopedLock( mutex *mtx );
autoScopedLock( mutex &mtx );
~autoScopedLock(void);
private:
+117
View File
@@ -0,0 +1,117 @@
// timeStamp.cpp
#include <stdio.h>
#include "timeStamp.h"
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
#include <unistd.h>
#endif
#if defined(WIN32)
#include <windows.h>
#endif
//-------------------------------------------------------------------------
//---- Time Stamp Record
//-------------------------------------------------------------------------
#if defined(WIN32)
#include <intrin.h>
#pragma intrinsic(__rdtsc)
#else
#include <x86intrin.h>
#endif
static uint64_t rdtsc()
{
return __rdtsc();
}
namespace FCEU
{
uint64_t timeStampRecord::_tscFreq = 0;
#if defined(WIN32)
uint64_t timeStampRecord::qpcFreq = 0;
#endif
void timeStampRecord::readNew(void)
{
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
clock_gettime( CLOCK_REALTIME, &ts );
#else
QueryPerformanceCounter((LARGE_INTEGER*)&ts);
#endif
tsc = rdtsc();
}
#if defined(WIN32)
void timeStampRecord::qpcCalibrate(void)
{
if (QueryPerformanceFrequency((LARGE_INTEGER*)&timeStampRecord::qpcFreq) == 0)
{
printf("QueryPerformanceFrequency FAILED!\n");
}
}
#endif
class timeStampModule
{
public:
timeStampModule(void)
{
printf("timeStampModuleInit\n");
#if defined(WIN32)
timeStampRecord::qpcCalibrate();
#endif
}
};
static timeStampModule module;
bool timeStampModuleInitialized(void)
{
#if defined(WIN32)
bool initialized = timeStampRecord::countFreq() != 0;
#else
bool initialized = true;
#endif
return initialized;
}
void timeStampRecord::tscCalibrate(int numSamples)
{
timeStampRecord t1, t2, td;
uint64_t td_sum = 0;
double td_avg;
#if defined(WIN32)
if (QueryPerformanceFrequency((LARGE_INTEGER*)&timeStampRecord::qpcFreq) == 0)
{
printf("QueryPerformanceFrequency FAILED!\n");
}
#endif
printf("Running TSC Calibration: %i sec...\n", numSamples);
for (int i=0; i<numSamples; i++)
{
t1.readNew();
#if defined(WIN32)
Sleep(1000);
#else
sleep(1);
#endif
t2.readNew();
td += t2 - t1;
td_sum = td.tsc;
td_avg = static_cast<double>(td_sum);
timeStampRecord::_tscFreq = static_cast<uint64_t>( td_avg / td.toSeconds() );
printf("%i Calibration: %f sec TSC:%llu TSC Freq: %f MHz\n", i, td.toSeconds(),
static_cast<unsigned long long>(td.tsc), static_cast<double>(timeStampRecord::_tscFreq) * 1.0e-6 );
}
}
} // namespace FCEU
+384
View File
@@ -0,0 +1,384 @@
// timeStamp.h
#pragma once
#include <stdint.h>
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
#include <time.h>
#endif
namespace FCEU
{
class timeStampRecord
{
public:
static constexpr uint64_t ONE_SEC_TO_MILLI = 1000;
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
static constexpr long int ONE_SEC_TO_NANO = 1000000000;
static constexpr long int MILLI_TO_NANO = 1000000;
timeStampRecord(void)
{
ts.tv_sec = 0;
ts.tv_nsec = 0;
tsc = 0;
}
timeStampRecord& operator = (const timeStampRecord& in)
{
ts = in.ts;
tsc = in.tsc;
return *this;
}
timeStampRecord& operator += (const timeStampRecord& op)
{
ts.tv_sec += op.ts.tv_sec;
ts.tv_nsec += op.ts.tv_nsec;
if (ts.tv_nsec >= ONE_SEC_TO_NANO)
{
ts.tv_nsec -= ONE_SEC_TO_NANO;
ts.tv_sec++;
}
tsc += op.tsc;
return *this;
}
timeStampRecord operator + (const timeStampRecord& op)
{
timeStampRecord res;
res.ts.tv_sec = ts.tv_sec + op.ts.tv_sec;
res.ts.tv_nsec = ts.tv_nsec + op.ts.tv_nsec;
if (res.ts.tv_nsec >= ONE_SEC_TO_NANO)
{
res.ts.tv_nsec -= ONE_SEC_TO_NANO;
res.ts.tv_sec++;
}
res.tsc = tsc + op.tsc;
return res;
}
timeStampRecord operator - (const timeStampRecord& op)
{
timeStampRecord res;
res.ts.tv_sec = ts.tv_sec - op.ts.tv_sec;
res.ts.tv_nsec = ts.tv_nsec - op.ts.tv_nsec;
if (res.ts.tv_nsec < 0)
{
res.ts.tv_nsec += ONE_SEC_TO_NANO;
res.ts.tv_sec--;
}
res.tsc = tsc - op.tsc;
return res;
}
timeStampRecord operator * (const unsigned int multiplier)
{
timeStampRecord res;
res.ts.tv_sec = ts.tv_sec * multiplier;
res.ts.tv_nsec = ts.tv_nsec * multiplier;
if (res.ts.tv_nsec >= ONE_SEC_TO_NANO)
{
res.ts.tv_nsec -= ONE_SEC_TO_NANO;
res.ts.tv_sec++;
}
res.tsc = tsc * multiplier;
return res;
}
timeStampRecord operator / (const unsigned int divisor)
{
timeStampRecord res;
res.ts.tv_sec = ts.tv_sec / divisor;
res.ts.tv_nsec = ts.tv_nsec / divisor;
res.tsc = tsc / divisor;
return res;
}
bool operator > (const timeStampRecord& op)
{
bool res;
if (ts.tv_sec == op.ts.tv_sec)
{
res = (ts.tv_nsec > op.ts.tv_nsec);
}
else
{
res = (ts.tv_sec > op.ts.tv_sec);
}
return res;
}
bool operator >= (const timeStampRecord& op)
{
bool res;
if (ts.tv_sec == op.ts.tv_sec)
{
res = (ts.tv_nsec >= op.ts.tv_nsec);
}
else
{
res = (ts.tv_sec >= op.ts.tv_sec);
}
return res;
}
bool operator < (const timeStampRecord& op)
{
bool res;
if (ts.tv_sec == op.ts.tv_sec)
{
res = (ts.tv_nsec < op.ts.tv_nsec);
}
else
{
res = (ts.tv_sec < op.ts.tv_sec);
}
return res;
}
bool operator <= (const timeStampRecord& op)
{
bool res;
if (ts.tv_sec == op.ts.tv_sec)
{
res = (ts.tv_nsec <= op.ts.tv_nsec);
}
else
{
res = (ts.tv_sec <= op.ts.tv_sec);
}
return res;
}
void zero(void)
{
ts.tv_sec = 0;
ts.tv_nsec = 0;
tsc = 0;
}
bool isZero(void)
{
return (ts.tv_sec == 0) && (ts.tv_nsec == 0);
}
void fromSeconds(unsigned int sec)
{
ts.tv_sec = sec;
ts.tv_nsec = 0;
tsc = 0;
}
void fromSeconds(double sec)
{
double ns;
ts.tv_sec = static_cast<time_t>(sec);
ns = (sec - static_cast<double>(ts.tv_sec)) * 1.0e9;
ts.tv_nsec = static_cast<long>(ns);
tsc = 0;
}
double toSeconds(void)
{
double sec = static_cast<double>(ts.tv_sec) + ( static_cast<double>(ts.tv_nsec) * 1.0e-9 );
return sec;
}
void fromMilliSeconds(uint64_t ms)
{
ts.tv_sec = ms / ONE_SEC_TO_MILLI;
ts.tv_nsec = (ms * MILLI_TO_NANO) - (ts.tv_sec * ONE_SEC_TO_NANO);
}
uint64_t toMilliSeconds(void)
{
uint64_t ms = (ts.tv_sec * ONE_SEC_TO_MILLI) + (ts.tv_nsec / MILLI_TO_NANO );
return ms;
}
uint64_t toCounts(void)
{
return (ts.tv_sec * ONE_SEC_TO_NANO) + ts.tv_nsec;
}
static uint64_t countFreq(void)
{
return ONE_SEC_TO_NANO;
}
struct timespec toTimeSpec(void)
{
return ts;
}
#else // WIN32
timeStampRecord(void)
{
ts = 0;
tsc = 0;
}
timeStampRecord& operator = (const timeStampRecord& in)
{
ts = in.ts;
tsc = in.tsc;
return *this;
}
timeStampRecord& operator += (const timeStampRecord& op)
{
ts += op.ts;
tsc += op.tsc;
return *this;
}
timeStampRecord operator + (const timeStampRecord& op)
{
timeStampRecord res;
res.ts = ts + op.ts;
res.tsc = tsc + op.tsc;
return res;
}
timeStampRecord operator - (const timeStampRecord& op)
{
timeStampRecord res;
res.ts = ts - op.ts;
res.tsc = tsc - op.tsc;
return res;
}
timeStampRecord operator * (const unsigned int multiplier)
{
timeStampRecord res;
res.ts = ts * multiplier;
res.tsc = tsc * multiplier;
return res;
}
timeStampRecord operator / (const unsigned int divisor)
{
timeStampRecord res;
res.ts = ts / divisor;
res.tsc = tsc / divisor;
return res;
}
bool operator > (const timeStampRecord& op)
{
return ts > op.ts;
}
bool operator >= (const timeStampRecord& op)
{
return ts >= op.ts;
}
bool operator < (const timeStampRecord& op)
{
return ts < op.ts;
}
bool operator <= (const timeStampRecord& op)
{
return ts <= op.ts;
}
void zero(void)
{
ts = 0;
tsc = 0;
}
bool isZero(void)
{
return (ts == 0);
}
void fromSeconds(unsigned int sec)
{
ts = sec * qpcFreq;
tsc = 0;
}
void fromSeconds(double sec)
{
ts = static_cast<uint64_t>(sec * static_cast<double>(qpcFreq));
tsc = 0;
}
double toSeconds(void)
{
double sec = static_cast<double>(ts) / static_cast<double>(qpcFreq);
return sec;
}
void fromMilliSeconds(uint64_t ms)
{
ts = (ms * qpcFreq) / ONE_SEC_TO_MILLI;
}
uint64_t toMilliSeconds(void)
{
uint64_t ms = (ts * ONE_SEC_TO_MILLI) / qpcFreq;
return ms;
}
uint64_t toCounts(void)
{
return ts;
}
static uint64_t countFreq(void)
{
return qpcFreq;
}
static void qpcCalibrate(void);
#endif
uint64_t getTSC(void){ return tsc; };
static uint64_t tscFreq(void)
{
return _tscFreq;
}
static bool tscValid(void){ return _tscFreq != 0; };
// Call this function to calibrate the estimated TSC frequency
static void tscCalibrate(int numSamples = 0);
void readNew(void);
private:
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
struct timespec ts;
#else // Win32
uint64_t ts;
static uint64_t qpcFreq;
#endif
uint64_t tsc;
static uint64_t _tscFreq;
};
bool timeStampModuleInitialized(void);
} // namespace FCEU
+2 -2
View File
@@ -62,14 +62,14 @@
#define FCEU_VERSION_MAJOR 2
#define FCEU_VERSION_MINOR 6
#define FCEU_VERSION_PATCH 5
#define FCEU_VERSION_PATCH 6
#define FCEU_VERSION_NUMERIC ( (FCEU_VERSION_MAJOR*10000) + (FCEU_VERSION_MINOR*100) + (FCEU_VERSION_PATCH) )
#define FCEU_VERSION_MAJOR_DECODE(x) ( (x / 10000) )
#define FCEU_VERSION_MINOR_DECODE(x) ( (x / 100) % 100 )
#define FCEU_VERSION_PATCH_DECODE(x) (x % 100)
#define FCEU_VERSION_STRING "2.6.5" FCEU_SUBVERSION_STRING FCEU_FEATURE_STRING FCEU_COMPILER
#define FCEU_VERSION_STRING "2.6.6" FCEU_SUBVERSION_STRING FCEU_FEATURE_STRING FCEU_COMPILER
#define FCEU_NAME_AND_VERSION FCEU_NAME " " FCEU_VERSION_STRING
#endif
+37 -1
View File
@@ -72,7 +72,8 @@ static u8 *xbsave=NULL;
GUIMESSAGE guiMessage;
GUIMESSAGE subtitleMessage;
bool vidGuiMsgEna = true;
// OpenEmu
bool vidGuiMsgEna = false;
//for input display
extern int input_display;
@@ -87,6 +88,8 @@ std::string AsSnapshotName =""; //adelikat:this will set the snapshot name whe
void FCEUI_SetSnapshotAsName(std::string name) { AsSnapshotName = name; }
std::string FCEUI_GetSnapshotAsName() { return AsSnapshotName; }
static void FCEU_DrawPauseCountDown(uint8 *XBuf);
void FCEU_KillVirtualVideo(void)
{
if ( XBuf )
@@ -254,6 +257,7 @@ void FCEU_PutImage(void)
FCEU_DrawLagCounter(XBuf);
FCEU_DrawNTSCControlBars(XBuf);
FCEU_DrawRecordingStatus(XBuf);
FCEU_DrawPauseCountDown(XBuf);
ShowFPS();
}
@@ -771,3 +775,35 @@ void ShowFPS(void)
DrawTextTrans(XBuf + ((256 - ClipSidesOffset) - 40) + (FSettings.FirstSLine + 4) * 256, 256, (uint8*)fpsmsg, 0xA0);
}
bool showPauseCountDown = true;
static void FCEU_DrawPauseCountDown(uint8 *XBuf)
{
if (EmulationPaused & EMULATIONPAUSED_TIMER)
{
int pauseFramesLeft = FCEUI_PauseFramesRemaining();
if (showPauseCountDown && (pauseFramesLeft > 0) )
{
char text[32];
int framesPerSec;
if (PAL || dendy)
{
framesPerSec = 50;
}
else
{
framesPerSec = 60;
}
sprintf(text, "Unpausing in %d...", (pauseFramesLeft / framesPerSec) + 1);
if (text[0])
{
DrawTextTrans(XBuf + ClipSidesOffset + (FSettings.FirstSLine) * 256, 256, (uint8*)text, 0xA0);
}
}
}
}
+18 -3
View File
@@ -47,7 +47,11 @@ void (*MapIRQHook)(int a);
//normal memory read
static INLINE uint8 RdMem(unsigned int A)
{
return(_DB=ARead[A](A));
_DB=ARead[A](A);
#ifdef _S9XLUA_H
CallRegisteredLuaMemHook(A, 1, _DB, LUAMEMHOOK_READ);
#endif
return(_DB);
}
//normal memory write
@@ -57,13 +61,18 @@ static INLINE void WrMem(unsigned int A, uint8 V)
#ifdef _S9XLUA_H
CallRegisteredLuaMemHook(A, 1, V, LUAMEMHOOK_WRITE);
#endif
_DB = V;
}
static INLINE uint8 RdRAM(unsigned int A)
{
_DB=ARead[A](A);
#ifdef _S9XLUA_H
CallRegisteredLuaMemHook(A, 1, _DB, LUAMEMHOOK_READ);
#endif
//bbit edited: this was changed so cheat substituion would work
return(_DB=ARead[A](A));
// return(_DB=RAM[A]);
return(_DB);
}
static INLINE void WrRAM(unsigned int A, uint8 V)
@@ -72,12 +81,17 @@ static INLINE void WrRAM(unsigned int A, uint8 V)
#ifdef _S9XLUA_H
CallRegisteredLuaMemHook(A, 1, V, LUAMEMHOOK_WRITE);
#endif
_DB = V;
}
uint8 X6502_DMR(uint32 A)
{
ADDCYC(1);
return(X.DB=ARead[A](A));
_DB=ARead[A](A);
#ifdef _S9XLUA_H
CallRegisteredLuaMemHook(A, 1, _DB, LUAMEMHOOK_READ);
#endif
return(_DB);
}
void X6502_DMW(uint32 A, uint8 V)
@@ -87,6 +101,7 @@ void X6502_DMW(uint32 A, uint8 V)
#ifdef _S9XLUA_H
CallRegisteredLuaMemHook(A, 1, V, LUAMEMHOOK_WRITE);
#endif
_DB = V;
}
#define PUSH(V) \