8 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
clobber 7e9cde361e Build fix
Now requires a minimum of C++11: Use of undeclared identifier 'nullptr'
2023-06-20 20:07:39 -06:00
clobber ee3ffeeacc Merge pull request #12 from ShutOstrich/master
Update to FCEUX 2.6.5
2023-04-29 20:40:56 -06:00
ShutOstrich 8a1427db5c Update to FCEUX 2.6.5 2023-04-30 00:37:54 +02:00
ShutOstrich 10724c5437 Disable "Reset" message 2023-04-30 00:32:10 +02:00
clobber 88b1044105 Fix -ringBufferAtIndex: deprecation warning. 2022-12-24 17:10:23 -07:00
120 changed files with 8962 additions and 1625 deletions
+40
View File
@@ -67,6 +67,12 @@
87709EE3294D2B0D0084AEE0 /* lcdcompzapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 87709EE2294D2B0D0084AEE0 /* lcdcompzapper.cpp */; };
8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
8F28FD5029FD3E7D008FC4A9 /* 354.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F28FD4D29FD3E7D008FC4A9 /* 354.cpp */; };
8F28FD5129FD3E7D008FC4A9 /* coolgirl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F28FD4E29FD3E7D008FC4A9 /* coolgirl.cpp */; };
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 */; };
@@ -334,6 +340,19 @@
87709EE2294D2B0D0084AEE0 /* lcdcompzapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lcdcompzapper.cpp; sourceTree = "<group>"; };
8D5B49B6048680CD000E48DA /* FCEU.oecoreplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FCEU.oecoreplugin; sourceTree = BUILT_PRODUCTS_DIR; };
8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8F28FD4D29FD3E7D008FC4A9 /* 354.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 354.cpp; sourceTree = "<group>"; };
8F28FD4E29FD3E7D008FC4A9 /* coolgirl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coolgirl.cpp; sourceTree = "<group>"; };
8F28FD4F29FD3E7D008FC4A9 /* inx007t.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inx007t.cpp; sourceTree = "<group>"; };
8F28FD5329FD3EA4008FC4A9 /* debugsymboltable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debugsymboltable.cpp; sourceTree = "<group>"; };
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>"; };
@@ -776,6 +795,8 @@
949BB7F01A9EED56007B49CC /* config.cpp */,
949BB7F21A9EED56007B49CC /* debug.cpp */,
949BB7F31A9EED56007B49CC /* debug.h */,
8F28FD5329FD3EA4008FC4A9 /* debugsymboltable.cpp */,
8F28FD5429FD3EA4008FC4A9 /* debugsymboltable.h */,
949BB7F41A9EED56007B49CC /* drawing.cpp */,
949BB7F51A9EED56007B49CC /* drawing.h */,
949BB7F61A9EED56007B49CC /* driver.h */,
@@ -802,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 */,
@@ -818,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 */,
@@ -893,6 +918,7 @@
949BB77D1A9EED56007B49CC /* 32.cpp */,
949BB77E1A9EED56007B49CC /* 33.cpp */,
949BB77F1A9EED56007B49CC /* 34.cpp */,
8F28FD4D29FD3E7D008FC4A9 /* 354.cpp */,
949BB7801A9EED56007B49CC /* 36.cpp */,
949BB7811A9EED56007B49CC /* 3d-block.cpp */,
949BB7821A9EED56007B49CC /* 40.cpp */,
@@ -944,6 +970,7 @@
87709ED8294D24F10084AEE0 /* cheapocabra.cpp */,
949BB7AC1A9EED56007B49CC /* cityfighter.cpp */,
870D6EA71D4C1F93001E8FC6 /* coolboy.cpp */,
8F28FD4E29FD3E7D008FC4A9 /* coolgirl.cpp */,
949BB7AD1A9EED56007B49CC /* dance2000.cpp */,
949BB7AE1A9EED56007B49CC /* datalatch.cpp */,
949BB7AF1A9EED56007B49CC /* dream.cpp */,
@@ -965,6 +992,7 @@
87709EDC294D252B0084AEE0 /* hp10xx_hp20xx.cpp */,
870D6EB11D4C20B3001E8FC6 /* hp898f.cpp */,
870D6EB21D4C20B3001E8FC6 /* inlnsf.cpp */,
8F28FD4F29FD3E7D008FC4A9 /* inx007t.cpp */,
949BB7BA1A9EED56007B49CC /* karaoke.cpp */,
949BB7BB1A9EED56007B49CC /* kof97.cpp */,
870D6EB51D4C20F8001E8FC6 /* ks7010.cpp */,
@@ -1166,6 +1194,10 @@
949BBA271A9EED5B007B49CC /* md5.h */,
949BBA281A9EED5B007B49CC /* memory.cpp */,
949BBA291A9EED5B007B49CC /* memory.h */,
8F28FD5629FD3EB8008FC4A9 /* mutex.cpp */,
8F28FD5729FD3EB8008FC4A9 /* mutex.h */,
8F5A69C72A9BF26400B405DB /* timeStamp.cpp */,
8F5A69CA2A9BF26400B405DB /* timeStamp.h */,
949BBA2B1A9EED5B007B49CC /* unzip.cpp */,
949BBA2C1A9EED5B007B49CC /* unzip.h */,
949BBA2D1A9EED5B007B49CC /* valuearray.h */,
@@ -1270,6 +1302,7 @@
files = (
82EC40A30FD9EC5A0017FC19 /* FCEUGameCore.mm in Sources */,
949BBB381A9EFF4A007B49CC /* asm.cpp in Sources */,
8F28FD5129FD3E7D008FC4A9 /* coolgirl.cpp in Sources */,
949BBB391A9EFF4A007B49CC /* cart.cpp in Sources */,
870D6EA81D4C1F93001E8FC6 /* coolboy.cpp in Sources */,
949BBB3A1A9EFF4A007B49CC /* cheat.cpp in Sources */,
@@ -1296,6 +1329,7 @@
949BBB501A9EFF4B007B49CC /* video.cpp in Sources */,
949BBB511A9EFF4B007B49CC /* vsuni.cpp in Sources */,
949BBB521A9EFF4B007B49CC /* wave.cpp in Sources */,
8F28FD5829FD3EB8008FC4A9 /* mutex.cpp in Sources */,
949BBB531A9EFF4B007B49CC /* x6502.cpp in Sources */,
949BBA741A9EF079007B49CC /* 01-222.cpp in Sources */,
949BBA751A9EF079007B49CC /* 09-034a.cpp in Sources */,
@@ -1336,6 +1370,7 @@
949BBA961A9EF079007B49CC /* 230.cpp in Sources */,
949BBA971A9EF079007B49CC /* 232.cpp in Sources */,
949BBA981A9EF079007B49CC /* 234.cpp in Sources */,
8F28FD5029FD3E7D008FC4A9 /* 354.cpp in Sources */,
949BBA991A9EF079007B49CC /* 235.cpp in Sources */,
949BBA9A1A9EF079007B49CC /* 244.cpp in Sources */,
949BBA9B1A9EF079007B49CC /* 246.cpp in Sources */,
@@ -1401,6 +1436,7 @@
949BBAD01A9EF07A007B49CC /* datalatch.cpp in Sources */,
949BBAD11A9EF07A007B49CC /* dream.cpp in Sources */,
949BBAD21A9EF07A007B49CC /* edu2000.cpp in Sources */,
8F28FD5529FD3EA4008FC4A9 /* debugsymboltable.cpp in Sources */,
949BBAD31A9EF07A007B49CC /* emu2413.c in Sources */,
949BBAD51A9EF07A007B49CC /* famicombox.cpp in Sources */,
949BBAD61A9EF07A007B49CC /* ffe.cpp in Sources */,
@@ -1440,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 */,
@@ -1448,6 +1485,7 @@
870D6EC21D4C2BF4001E8FC6 /* snesmouse.cpp in Sources */,
949BBAFB1A9EF07A007B49CC /* sl1632.cpp in Sources */,
949BBAFC1A9EF07A007B49CC /* subor.cpp in Sources */,
8F28FD5229FD3E7D008FC4A9 /* inx007t.cpp in Sources */,
949BBAFD1A9EF07A007B49CC /* super24.cpp in Sources */,
870D6EAF1D4C1FE7001E8FC6 /* et-4320.cpp in Sources */,
949BBAFE1A9EF07A007B49CC /* supervision.cpp in Sources */,
@@ -1576,6 +1614,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
@@ -1611,6 +1650,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+3 -1
View File
@@ -233,7 +233,7 @@ static __weak FCEUGameCore *_current;
for (int i = 0; i < _soundSize; i++)
_soundBuffer[i] = (_soundBuffer[i] << 16) | (_soundBuffer[i] & 0xffff);
[[self ringBufferAtIndex:0] write:_soundBuffer maxLength:_soundSize << 2];
[[self audioBufferAtIndex:0] write:_soundBuffer maxLength:_soundSize << 2];
}
- (void)resetEmulation
@@ -795,6 +795,7 @@ const char *GetKeyboard(void) {return "";}
bool turbo = false;
bool swapDuty = 0; // some Famicom and NES clones had duty cycle bits swapped
int dendy = 0;
int eoptions = 0;
int closeFinishedMovie = 0;
int KillFCEUXonFrame = 0;
int FCEUD_ShowStatusIcon(void) {return 0;}
@@ -824,6 +825,7 @@ EMUFILE_FILE *FCEUD_UTF8_fstream(const char *fn, const char *m)
}
void FCEUD_NetplayText(uint8 *text) {};
void FCEUD_NetworkClose(void) {}
void FCEUD_FlushTrace(void) {}
void FCEUD_VideoChanged (void) {}
bool FCEUD_ShouldDrawInputAids() {return false;}
bool FCEUD_PauseAfterPlayback() {return false;}
+1 -1
View File
@@ -17,7 +17,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>2.6.3</string>
<string>2.6.6</string>
<key>NSPrincipalClass</key>
<string>OEGameCoreController</string>
<key>OEGameCoreClass</key>
+55 -5
View File
@@ -5,6 +5,10 @@ set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
if (${PUBLIC_RELEASE})
add_definitions( -DPUBLIC_RELEASE=1 )
endif()
if ( ${QT6} )
message( STATUS "GUI Frontend: Qt6")
set( Qt Qt6 )
@@ -18,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} )
@@ -28,6 +38,7 @@ else()
include_directories( ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Help_INCLUDE_DIRS} )
endif()
if(WIN32)
find_package(OpenGL REQUIRED)
#find_package(Qt5 COMPONENTS Widgets OpenGL REQUIRED)
@@ -36,10 +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 )
@@ -71,7 +87,8 @@ else(WIN32)
find_package(OpenGL REQUIRED)
find_package(ZLIB REQUIRED)
add_definitions( -Wall -Wno-write-strings -Wno-sign-compare -Wno-parentheses -Wno-unused-local-typedefs -fPIC )
add_definitions( -Wall -Wno-write-strings -Wno-parentheses -Wno-unused-local-typedefs -fPIC )
#add_definitions( -Wno-sign-compare ) # Integer comparison sign mismatch warnings
add_definitions( -DFCEUDEF_DEBUGGER )
#if ( ${QT6} )
@@ -85,6 +102,21 @@ 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 )
set( ASAN_LDFLAGS -lasan -lubsan)
message( STATUS "Address Sanitizer Enabled" )
else()
message( STATUS "Address Sanitizer Disabled" )
endif()
# Check for libminizip
pkg_check_modules( MINIZIP REQUIRED minizip)
@@ -93,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} )
@@ -261,6 +300,7 @@ set(SRC_CORE
${CMAKE_CURRENT_SOURCE_DIR}/conddebug.cpp
${CMAKE_CURRENT_SOURCE_DIR}/config.cpp
${CMAKE_CURRENT_SOURCE_DIR}/debug.cpp
${CMAKE_CURRENT_SOURCE_DIR}/debugsymboltable.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drawing.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fceu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fds.cpp
@@ -269,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
@@ -332,6 +374,7 @@ set(SRC_CORE
${CMAKE_CURRENT_SOURCE_DIR}/boards/32.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/33.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/34.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/354.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/36.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/3d-block.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/40.cpp
@@ -382,6 +425,7 @@ set(SRC_CORE
${CMAKE_CURRENT_SOURCE_DIR}/boards/cheapocabra.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/cityfighter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/coolboy.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/coolgirl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/dance2000.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/datalatch.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/dream.cpp
@@ -453,6 +497,7 @@ set(SRC_CORE
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc7.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc7p.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/yoko.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boards/inx007t.cpp
${CMAKE_CURRENT_SOURCE_DIR}/input/arkanoid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/input/bworld.cpp
${CMAKE_CURRENT_SOURCE_DIR}/input/cursor.cpp
@@ -481,13 +526,14 @@ set(SRC_CORE
${CMAKE_CURRENT_SOURCE_DIR}/utils/guid.cpp
${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
)
set(SRC_DRIVERS_COMMON
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/args.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/cheat.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/config.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/configSys.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/hq2x.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/hq3x.cpp
@@ -504,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
@@ -529,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
@@ -578,7 +627,7 @@ set(SOURCES ${SRC_CORE} ${SRC_DRIVERS_COMMON} ${SRC_DRIVERS_SDL})
# the FCEUX_BUILD_TIMESTAMP preprocessor definition.
# Note: with CMake >= 3.8.0, this will respect SOURCE_DATE_EPOCH. For more info,
# see <https://reproducible-builds.org/docs/source-date-epoch/>.
string(TIMESTAMP BUILD_TS "%H:%M:%S %b %d %Y")
string(TIMESTAMP BUILD_TS "%H:%M:%S %b %d %Y" UTC)
add_definitions( -DFCEUX_BUILD_TIMESTAMP=\"${BUILD_TS}\" )
if (WIN32)
@@ -613,14 +662,15 @@ add_executable( ${APP_NAME} ${SOURCES} ../resources.qrc
${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp)
endif()
target_link_libraries( ${APP_NAME}
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}
)
+1 -1
View File
@@ -48,7 +48,7 @@ static void M121CW(uint32 A, uint8 V) {
if (PRGsize[0] == CHRsize[0]) { // A9713 multigame extension hack!
setchr1(A, V | ((EXPREGS[3] & 0x80) << 1));
} else {
if ((A & 0x1000) == ((MMC3_cmd & 0x80) << 5))
if ((A & 0x1000) == static_cast<uint32>((MMC3_cmd & 0x80) << 5))
setchr1(A, V | 0x100);
else
setchr1(A, V);
+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);
+1 -1
View File
@@ -22,7 +22,7 @@
#include "mmc3.h"
static void M187CW(uint32 A, uint8 V) {
if ((A & 0x1000) == ((MMC3_cmd & 0x80) << 5))
if ((A & 0x1000) == static_cast<uint32>((MMC3_cmd & 0x80) << 5))
setchr1(A, V | 0x100);
else
setchr1(A, V);
+42 -34
View File
@@ -1,30 +1,40 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2011 CaH4e3
*
* 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
*/
*
* Copyright notice for this file:
* Copyright (C) 2011 CaH4e3
* Copyright (C) 2019 Libretro Team
* Copyright (C) 2020
*
* 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
*
* PCB-018 board, discrete multigame cart 110-in-1
*
* Mapper 225
* Mapper 255
*
*/
/* 2020-2-20 - merge mapper 255, re-implement extra RAM */
#include "mapinc.h"
static uint8 prot[4], prg, mode, chr, mirr;
static uint8 extraRAM[4], prg, mode, chr, mirr;
static SFORMAT StateRegs[] =
{
{ prot, 4, "PROT" },
{ extraRAM, 4, "PROT" },
{ &prg, 1, "PRG" },
{ &chr, 1, "CHR" },
{ &mode, 1, "MODE" },
@@ -36,14 +46,15 @@ static void Sync(void) {
if (mode) {
setprg16(0x8000, prg);
setprg16(0xC000, prg);
} else
}
else
setprg32(0x8000, prg >> 1);
setchr8(chr);
setmirror(mirr ^ 1);
}
static DECLFW(M225Write) {
uint32 bank = (A >> 14) & 1;
uint8 bank = (A >> 14) & 1;
mirr = (A >> 13) & 1;
mode = (A >> 12) & 1;
chr = (A & 0x3f) | (bank << 6);
@@ -52,35 +63,28 @@ static DECLFW(M225Write) {
}
static DECLFW(M225LoWrite) {
if (A & 0x800) {
prot[A & 0x03] = V;
}
/* e.g. 115-in-1 [p1][!] CRC32 0xb39d30b4 */
if (A & 0x800) extraRAM[A & 3] = V & 0x0F;
}
static DECLFR(M225LoRead) {
if (A & 0x800) {
return prot[A & 3] & 0x0F;
}
if (A & 0x800) return extraRAM[A & 3];
return X.DB;
}
static void M225Power(void) {
prg = 0;
chr = 0;
mode = 0;
mirr = 0;
Sync();
SetReadHandler(0x5000, 0x5FFF, M225LoRead);
SetWriteHandler(0x5000, 0x5FFF, M225LoWrite);
SetReadHandler(0x5000, 0x5fff, M225LoRead);
SetWriteHandler(0x5000, 0x5fff, M225LoWrite);
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x8000, 0xFFFF, M225Write);
}
static void M225Reset(void) {
prg = 0;
chr = 0;
mode = 0;
mirr = 0;
Sync();
}
@@ -94,3 +98,7 @@ void Mapper225_Init(CartInfo *info) {
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
}
void Mapper255_Init(CartInfo *info) {
Mapper225_Init(info);
}
+58 -11
View File
@@ -19,36 +19,79 @@
*/
#include "mapinc.h"
#include "ines.h"
static uint16 cmdreg = 0;
static uint8 openbus = 0;
// For carts with extra 128K prg rom (Contra)
static uint8 unrom = 0;
static uint8 unromData = 0;
static uint32 PRGROMSize = 0;
static uint16 cmdreg;
static SFORMAT StateRegs[] =
{
{ &cmdreg, 2, "CREG" },
{ &openbus, 1, "OB" },
{ &unrom, 1, "UROM" },
{ &unromData, 1, "UDTA" },
{ 0 }
};
static void Sync(void) {
if (cmdreg & 0x400)
setmirror(MI_0);
else
setmirror(((cmdreg >> 13) & 1) ^ 1);
if (cmdreg & 0x800) {
setprg16(0x8000, ((cmdreg & 0x300) >> 3) | ((cmdreg & 0x1F) << 1) | ((cmdreg >> 12) & 1));
setprg16(0xC000, ((cmdreg & 0x300) >> 3) | ((cmdreg & 0x1F) << 1) | ((cmdreg >> 12) & 1));
} else
setprg32(0x8000, ((cmdreg & 0x300) >> 4) | (cmdreg & 0x1F));
if (unrom) {
int PRGPageCount = PRGROMSize / (16 * 1024);
setprg16(0x8000, PRGPageCount & 0xC0 | (unromData & 7));
setprg16(0xC000, PRGPageCount & 0xC0 | 7);
setmirror(MI_V);
} else {
uint8 bank = ((cmdreg & 0x300) >> 3) | (cmdreg & 0x1F);
if (bank >= (PRGROMSize / (32 * 1024))) {
openbus = 1;
} else {
if (cmdreg & 0x400)
setmirror(MI_0);
else
setmirror(((cmdreg >> 13) & 1) ^ 1);
if (cmdreg & 0x800) {
setprg16(0x8000, (bank << 1) | ((cmdreg >> 12) & 1));
setprg16(0xC000, (bank << 1) | ((cmdreg >> 12) & 1));
} else
setprg32(0x8000, bank);
}
}
}
static DECLFR(M235Read) {
if (openbus) {
openbus = 0;
return X.DB;
}
return CartBR(A);
}
static DECLFW(M235Write) {
cmdreg = A;
unromData = V;
Sync();
}
static void M235Reset(void) {
cmdreg = 0;
unromData = 0;
if (PRGROMSize & 0x20000)
unrom = (unrom + 1) & 1;
Sync();
}
static void M235Power(void) {
setchr8(0);
SetWriteHandler(0x8000, 0xFFFF, M235Write);
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetReadHandler(0x8000, 0xFFFF, M235Read);
cmdreg = 0;
unromData = 0;
unrom = 0;
Sync();
}
@@ -57,7 +100,11 @@ static void M235Restore(int version) {
}
void Mapper235_Init(CartInfo *info) {
info->Reset = M235Reset;
info->Power = M235Power;
GameStateRestore = M235Restore;
AddExState(&StateRegs, ~0, 0, 0);
// needs raw, non-pow2 PRGROM size for comparison
PRGROMSize = head.ROM_size * 16384;
}
+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);
+98
View File
@@ -0,0 +1,98 @@
/* FCEUmm - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2022
*
* 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
*/
#include "mapinc.h"
static uint16 latchAddr;
static uint8 latchData;
static uint8 submapper;
static SFORMAT StateRegs[] =
{
{ &latchAddr, 2, "ADDR" },
{ &latchData, 1, "DATA" },
{ 0 }
};
static void Mapper354_Sync(void)
{
int prg = latchData & 0x3F | latchAddr << 2 & 0x40 | latchAddr >> 5 & 0x80;
switch (latchAddr & 7)
{
case 0: case 4:
setprg32(0x8000, prg >> 1);
break;
case 1:
setprg16(0x8000, prg);
setprg16(0xC000, prg | 7);
break;
case 2: case 6:
setprg8(0x8000, prg << 1 | latchData >> 7);
setprg8(0xA000, prg << 1 | latchData >> 7);
setprg8(0xC000, prg << 1 | latchData >> 7);
setprg8(0xE000, prg << 1 | latchData >> 7);
break;
case 3: case 7:
setprg16(0x8000, prg);
setprg16(0xC000, prg);
break;
case 5:
setprg8(0x6000, prg << 1 | latchData >> 7);
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);
}
static DECLFW(Mapper354_WriteLatch)
{
latchData = V;
latchAddr = A & 0xFFFF;
Mapper354_Sync();
}
static void Mapper354_Reset(void)
{
latchAddr = latchData = 0;
Mapper354_Sync();
}
static void Mapper354_Power(void)
{
latchAddr = latchData = 0;
SetReadHandler(0x6000, 0xFFFF, CartBR);
SetWriteHandler(submapper == 1 ? 0xE000 : 0xF000, 0xFFFF, Mapper354_WriteLatch);
Mapper354_Sync();
}
static void StateRestore(int version) {
Mapper354_Sync();
}
void Mapper354_Init(CartInfo *info)
{
submapper = info->submapper;
info->Power = Mapper354_Power;
info->Reset = Mapper354_Reset;
GameStateRestore = StateRestore;
AddExState(StateRegs, ~0, 0, 0);
}
+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);
+28 -13
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");
}
@@ -122,7 +122,7 @@ static void UNL43272Sync(void) {
if ((latche & 0x81) == 0x81) {
setprg32(0x8000, (latche & 0x38) >> 3);
} else
FCEU_printf("unrecognized command %04!\n", latche);
FCEU_printf("unrecognized command %04x!\n", latche);
setchr8(0);
setmirror(0);
}
@@ -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);
+346 -75
View File
@@ -21,7 +21,7 @@
*
* COOLBOY cartridges use registers at address $6xxx
* MINDKIDS cartridges use a solder pad labelled "5/6K" to select between $5000 and $6000
*
*
* $xxx0
* 7 bit 0
* ---- ----
@@ -29,12 +29,11 @@
* |||| ||||
* |||| |+++-- PRG offset (PRG A19, A18, A17)
* |||| +----- Alternate CHR A17
* ||++------- PRG offset (PRG A24, A23)
* ||++------- PRG offset (PRG A24, A23), CHR offset (CHR A19, A18)
* |+--------- PRG mask (PRG A17 from 0: MMC3; 1: offset)
* +---------- CHR mask (CHR A17 from 0: MMC3; 1: alternate)
*
* $xxx1
*
* 7 bit 0
* ---- ----
* GHIJ KKLx
@@ -55,15 +54,16 @@
* $xxx3
* 7 bit 0
* ---- ----
* NPxP QQRx
* || | |||
* || | +++--- PRG offset for GNROM mode (PRG A16, A15, A14)
* || +------- 1: GNROM mode; 0: MMC3 mode
* || | (1: PRG A16...13 from QQ, L, R, CPU A14, A13 + CHR A16...10 from MMMM, PPU A12...10;
* || | 0: PRG A16...13 from MMC3 + CHR A16...A10 from MMC3 )
* NPZP QQRx
* |||| |||
* |||| +++--- PRG offset for GNROM mode (PRG A16, A15, A14)
* |||+------- 1: GNROM mode; 0: MMC3 mode
* |||| (1: PRG A16...13 from QQ, L, R, CPU A14, A13 + CHR A16...10 from MMMM, PPU A12...10;
* |||| 0: PRG A16...13 from MMC3 + CHR A16...A10 from MMC3 )
* ||+-------- 1: Also enable PRG RAM in $5000-$5FFF
* |+-+------- Banking mode
* |+--------- "Weird MMC3 mode"
* +---------- Lockout (prevent further writes to these four registers, only works in MMC3 mode)
* +---------- Lockout (prevent further writes to all registers but the one at $xxx2, only works in MMC3 mode)
*
* Also some new cartridges from MINDKIDS have /WE and /OE pins connected to mapper,
* which allows you to rewrite flash memory without soldering.
@@ -75,25 +75,90 @@
#include "mapinc.h"
#include "mmc3.h"
#include "../ines.h"
static void COOLBOYCW(uint32 A, uint8 V) {
uint32 mask = 0xFF ^ (EXPREGS[0] & 0x80);
if (EXPREGS[3] & 0x10) {
if (EXPREGS[3] & 0x40) { // Weird mode
const int ROM_CHIP = 0x00;
const int CFI_CHIP = 0x11;
const int FLASH_CHIP = 0x12;
const uint32 FLASH_SECTOR_SIZE = 128 * 1024;
extern uint8* WRAM;
static uint8* CFI = NULL;
static uint8* Flash = NULL;
static uint8 flash_save = 0;
static uint8 flash_state = 0;
static uint16 flash_buffer_a[10];
static uint8 flash_buffer_v[10];
static uint8 cfi_mode = 0;
static uint16 regs_base = 0;
static uint8 flag23 = 0;
static uint8 flag45 = 0;
static uint8 flag67 = 0;
static uint8 flag89 = 0;
// Macronix 256-mbit memory CFI data
const uint8 cfi_data[] =
{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x51, 0x52, 0x59, 0x02, 0x00, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x27, 0x36, 0x00, 0x00, 0x03,
0x06, 0x09, 0x13, 0x03, 0x05, 0x03, 0x02, 0x19,
0x02, 0x00, 0x06, 0x00, 0x01, 0xFF, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
0x50, 0x52, 0x49, 0x31, 0x33, 0x14, 0x02, 0x01,
0x00, 0x08, 0x00, 0x00, 0x02, 0x95, 0xA5, 0x05,
0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
static void AA6023CW(uint32 A, uint8 V) {
if (flag89) {
/*
$xxx0
7 bit 0
---- ----
AB.C DEEE
|| | ||||
|| | |+++-- PRG offset (PRG A19, A18, A17)
|| | +----- Alternate CHR A17
|| +------- 1=Write-protect CHR-RAM
|+--------- PRG mask (PRG A17 from 0: MMC3; 1: offset)
+---------- CHR mask (CHR A17 from 0: MMC3; 1: alternate)
*/
if (EXPREGS[0] & 0b00010000)
SetupCartCHRMapping(0, VROM, CHRsize[0], 0); // write-protect CHR-RAM
else
SetupCartCHRMapping(0, VROM, CHRsize[0], 1); // allow CHR writes
}
uint32 mask = 0xFF ^ (EXPREGS[0] & 0b10000000);
if (EXPREGS[3] & 0b00010000) {
if (EXPREGS[3] & 0b01000000) { // Weird mode
int cbase = (MMC3_cmd & 0x80) << 5;
switch (cbase ^ A) { // Don't even try do understand
case 0x0400:
case 0x0C00: V &= 0x7F; break;
}
}
// Highest bit goes from MMC3 registers when EXPREGS[3]&0x80==0 or from EXPREGS[0]&0x08 otherwise
// Highest bit goes from MMC3 registers when EXPREGS[0]&0x80==0 or from EXPREGS[0]&0x08 otherwise
setchr1(A,
(V & 0x80 & mask) | ((((EXPREGS[0] & 0x08) << 4) & ~mask)) // 7th bit
(V & 0x80 & mask) | ((((EXPREGS[0] & 0b00001000) << 4) & ~mask)) // 7th bit
| ((EXPREGS[2] & 0x0F) << 3) // 6-3 bits
| ((A >> 10) & 7) // 2-0 bits
| ((EXPREGS[0] & 0b00110000) << 4) // There are some ROMs with 1 MiB CHR-ROM
);
} else {
if (EXPREGS[3] & 0x40) { // Weird mode, again
}
else {
if (EXPREGS[3] & 0b01000000) { // Weird mode, again
int cbase = (MMC3_cmd & 0x80) << 5;
switch (cbase ^ A) { // Don't even try do understand
case 0x0000: V = DRegBuf[0]; break;
@@ -103,18 +168,81 @@ static void COOLBOYCW(uint32 A, uint8 V) {
}
}
// Simple MMC3 mode
// Highest bit goes from MMC3 registers when EXPREGS[3]&0x80==0 or from EXPREGS[0]&0x08 otherwise
setchr1(A, (V & mask) | (((EXPREGS[0] & 0x08) << 4) & ~mask));
// Highest bit goes from MMC3 registers when EXPREGS[0]&0x80==0 or from EXPREGS[0]&0x08 otherwise
setchr1(A,
(V & mask)
| (((EXPREGS[0] & 0x08) << 4) & ~mask)
| ((EXPREGS[0] & 0b00110000) << 4)); // There are some ROMs with 1 MiB CHR-ROM
}
}
static void COOLBOYPW(uint32 A, uint8 V) {
uint32 mask = ((0x3F | (EXPREGS[1] & 0x40) | ((EXPREGS[1] & 0x20) << 2)) ^ ((EXPREGS[0] & 0x40) >> 2)) ^ ((EXPREGS[1] & 0x80) >> 2);
uint32 base = ((EXPREGS[0] & 0x07) >> 0) | ((EXPREGS[1] & 0x10) >> 1) | ((EXPREGS[1] & 0x0C) << 2) | ((EXPREGS[0] & 0x30) << 2);
static void AA6023PW(uint32 A, uint8 V) {
uint8 CREGS[] = {EXPREGS[0], EXPREGS[1], EXPREGS[2], EXPREGS[3]};
// Submappers has scrambled bits
if (flag23) {
/*
$xxx1
7 bit 0
---- ----
GHIL JKKx
|||| |||
|||| +++--- PRG offset (in order: PRG A20, A21, A22)
|||+------- GNROM mode bank PRG size (0: 32 KiB bank, PRG A14=CPU A14; 1: 16 KiB bank, PRG A14=offset A14)
||+-------- PRG mask (PRG A20 from 0: offset; 1: MMC3)
|+--------- PRG mask (PRG A19 from 0: offset; 1: MMC3)
+---------- PRG mask (PRG A18 from 0: MMC3; 1: offset)
*/
CREGS[1] = (CREGS[1] & 0b11100101)
| ((CREGS[1] & 0b00001000) << 1) // PRG A20
| ((CREGS[1] & 0b00000010) << 2) // PRG A22
| ((((CREGS[1] ^ 0b00010000) & 0b00010000) >> 3)); // GNROM mode bank PRG size
}
if (flag45) {
/*
$xxx0
7 bit 0
---- ----
ABCC DEEE
|||| ||||
|||| |+++-- PRG offset (PRG A19, A18, A17)
|||| +----- Alternate CHR A17
||++------- PRG offset (PRG A21, A20)
|+--------- PRG mask (PRG A17 from 0: MMC3; 1: offset)
+---------- CHR mask (CHR A17 from 0: MMC3; 1: alternate)
$xxx1
7 bit 0
---- ----
GHIx xxLx
||| |
||| +--- GNROM mode bank PRG size (1: 32 KiB bank, PRG A14=CPU A14; 0: 16 KiB bank, PRG A14=offset A14)
||+-------- PRG mask (PRG A20 from 0: offset; 1: MMC3)
|+--------- PRG mask (PRG A19 from 0: offset; 1: MMC3)
+---------- PRG mask (PRG A18 from 0: MMC3; 1: offset)
*/
CREGS[1] = (CREGS[1] & 0b11100011)
| ((CREGS[0] & 0b00100000) >> 3) // PRG A21
| (CREGS[0] & 0b00010000); // PRG A20
CREGS[0] &= 0b11001111;
}
uint32 mask = ((0b00111111 | (CREGS[1] & 0b01000000) | ((CREGS[1] & 0b00100000) << 2)) ^ ((CREGS[0] & 0b01000000) >> 2)) ^ ((CREGS[1] & 0b10000000) >> 2);
uint32 base = ((CREGS[0] & 0b00000111) >> 0) | ((CREGS[1] & 0b00010000) >> 1) | ((CREGS[1] & 0b00001100) << 2) | ((CREGS[0] & 0b00110000) << 2);
if (flash_save && cfi_mode) {
setprg32r(CFI_CHIP, 0x8000, 0);
return;
}
int chip = !flash_save ? ROM_CHIP : FLASH_CHIP;
// There are ROMs with multiple PRG ROM chips
int chip_offset = 0;
if (flag67 && EXPREGS[0] & 0b00001000) {
chip_offset += ROM_size;
}
// Very weird mode
// Last banks are first in this mode, ignored when MMC3_cmd&0x40
if ((EXPREGS[3] & 0x40) && (V >= 0xFE) && !((MMC3_cmd & 0x40) != 0)) {
if ((CREGS[3] & 0b01000000) && (V >= 0xFE) && !((MMC3_cmd & 0x40) != 0)) {
switch (A & 0xE000) {
case 0xC000:
case 0xE000:
@@ -123,91 +251,234 @@ static void COOLBOYPW(uint32 A, uint8 V) {
}
}
// Regular MMC3 mode, internal ROM size can be up to 2048kb!
if (!(EXPREGS[3] & 0x10))
setprg8(A, (((base << 4) & ~mask)) | (V & mask));
else { // NROM mode
if (!(CREGS[3] & 0x10)) {
// Regular MMC3 mode but can be extended to 2MiB
setprg8r(chip, A, ((((base << 4) & ~mask)) | (V & mask)) + chip_offset);
}
else {
// NROM mode
mask &= 0xF0;
uint8 emask;
if ((((EXPREGS[1] & 2) != 0))) // 32kb mode
emask = (EXPREGS[3] & 0x0C) | ((A & 0x4000) >> 13);
if (CREGS[1] & 0b00000010) // 32kb mode
emask = (CREGS[3] & 0b00001100) | ((A & 0x4000) >> 13);
else // 16kb mode
emask = EXPREGS[3] & 0x0E;
setprg8(A, ((base << 4) & ~mask) // 7-4 bits are from base (see below)
| (V & mask) // ... or from MM3 internal regs, depends on mask
| emask // 3-1 (or 3-2 when (EXPREGS[3]&0x0C is set) from EXPREGS[3]
| ((A & 0x2000) >> 13)); // 0th just as is
emask = CREGS[3] & 0b00001110;
setprg8r(chip, A, (
((base << 4) & ~mask) // 7-4 bits are from base
| (V & mask) // ... or from MM3 internal regs, depends on mask
| emask // 3-1 (or 3-2 when (EXPREGS[3]&0x0C is set) from EXPREGS[3]
| ((A & 0x2000) >> 13) // 0th just as is
) + chip_offset); // For multi-chip ROMs
}
}
static DECLFW(COOLBOYWrite) {
if(A001B & 0x80)
CartBW(A,V);
static DECLFW(AA6023WramWrite) {
if (A001B & 0x80)
CartBW(A, V);
}
static DECLFW(AA6023Write) {
if (A >= 0x6000) {
AA6023WramWrite(A, V);
}
// Deny any further writes when 7th bit is 1 AND 4th is 0
if ((EXPREGS[3] & 0x90) != 0x80) {
EXPREGS[A & 3] = V;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
static void COOLBOYReset(void) {
static DECLFW(AA6023FlashWrite) {
if (A < 0xC000)
MMC3_CMDWrite(A, V);
else
MMC3_IRQWrite(A, V);
if (!flash_save) return;
if (flash_state < sizeof(flash_buffer_a) / sizeof(flash_buffer_a[0])) {
flash_buffer_a[flash_state] = A & 0xFFF;
flash_buffer_v[flash_state] = V;
flash_state++;
// enter CFI mode
if ((flash_state == 1) &&
(flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0x98)) {
cfi_mode = 1;
flash_state = 0;
}
// erase sector
if ((flash_state == 6) &&
(flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0xAA) &&
(flash_buffer_a[1] == 0x0555) && (flash_buffer_v[1] == 0x55) &&
(flash_buffer_a[2] == 0x0AAA) && (flash_buffer_v[2] == 0x80) &&
(flash_buffer_a[3] == 0x0AAA) && (flash_buffer_v[3] == 0xAA) &&
(flash_buffer_a[4] == 0x0555) && (flash_buffer_v[4] == 0x55) &&
(flash_buffer_v[5] == 0x30)) {
int offset = &Page[A >> 11][A] - Flash;
int sector = offset / FLASH_SECTOR_SIZE;
for (uint32 i = sector * FLASH_SECTOR_SIZE; i < (sector + 1) * FLASH_SECTOR_SIZE; i++)
Flash[i % PRGsize[ROM_CHIP]] = 0xFF;
FCEU_printf("Flash sector #%d is erased (0x%08x - 0x%08x).\n", sector, offset, offset + FLASH_SECTOR_SIZE);
flash_state = 0;
}
// erase chip, lol
if ((flash_state == 6) &&
(flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0xAA) &&
(flash_buffer_a[1] == 0x0555) && (flash_buffer_v[1] == 0x55) &&
(flash_buffer_a[2] == 0x0AAA) && (flash_buffer_v[2] == 0x80) &&
(flash_buffer_a[3] == 0x0AAA) && (flash_buffer_v[3] == 0xAA) &&
(flash_buffer_a[4] == 0x0555) && (flash_buffer_v[4] == 0x55) &&
(flash_buffer_v[5] == 0x10)) {
memset(Flash, 0xFF, PRGsize[ROM_CHIP]);
FCEU_printf("Flash chip erased.\n");
flash_state = 0;
}
// write byte
if ((flash_state == 4) &&
(flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0xAA) &&
(flash_buffer_a[1] == 0x0555) && (flash_buffer_v[1] == 0x55) &&
(flash_buffer_a[2] == 0x0AAA) && (flash_buffer_v[2] == 0xA0)) {
int offset = &Page[A >> 11][A] - Flash;
if (CartBR(A) != 0xFF) {
FCEU_PrintError("Error: can't write to 0x%08x, flash sector is not erased.\n", offset);
}
else {
CartBW(A, V);
}
flash_state = 0;
}
}
// not a command
if (((A & 0xFFF) != 0x0AAA) && ((A & 0xFFF) != 0x0555)) {
flash_state = 0;
}
// reset
if (V == 0xF0) {
flash_state = 0;
cfi_mode = 0;
}
FixMMC3PRG(MMC3_cmd);
}
static void AA6023Reset(void) {
MMC3RegReset();
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
flash_state = 0;
cfi_mode = 0;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
}
static void COOLBOYPower(void) {
static void AA6023Power(void) {
GenMMC3Power();
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
SetWriteHandler(0x5000, 0x5fff, CartBW); // some games access random unmapped areas and crashes because of KT-008 PCB hack in MMC3 source lol
SetWriteHandler(0x6000, 0x6fff, COOLBOYWrite);
if (regs_base != 0x5000)
SetWriteHandler(0x5000, 0x5fff, CartBW); // some games access random unmapped areas and crashes because of KT-008 PCB hack in MMC3 source lol
SetWriteHandler(0x6000, 0x7fff, AA6023WramWrite);
SetWriteHandler(regs_base, regs_base + 0x0fff, AA6023Write);
SetWriteHandler(0x8000, 0xFFFF, AA6023FlashWrite);
SetReadHandler(0x8000, 0xFFFF, CartBR);
}
static void MINDKIDSPower(void) {
GenMMC3Power();
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
static void AA6023Restore(int version) {
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
SetWriteHandler(0x5000, 0x5fff, COOLBOYWrite);
}
static void AA6023Close(void) {
if (WRAM)
FCEU_gfree(WRAM);
if (Flash)
FCEU_gfree(Flash);
if (CFI)
FCEU_gfree(CFI);
WRAM = Flash = CFI = NULL;
}
void CommonInit(CartInfo* info, int submapper)
{
GenMMC3_Init(info, 2048, info->vram_size / 1024, !info->ines2 ? 8 : (info->wram_size + info->battery_wram_size) / 1024, info->battery);
pwrap = AA6023PW;
cwrap = AA6023CW;
switch (submapper)
{
case 2:
regs_base = 0x7000;
break;
case 0:
case 4:
case 6:
case 8:
regs_base = 0x6000;
break;
case 1:
case 3:
case 5:
case 7:
case 9:
regs_base = 0x5000;
break;
default:
FCEU_PrintError("Submapper #%d is not supported", submapper);
}
flag23 = (submapper == 2) || (submapper == 3);
flag45 = (submapper == 4) || (submapper == 5);
flag67 = (submapper == 6) || (submapper == 7);
flag89 = (submapper == 8) || (submapper == 9);
info->Power = AA6023Power;
info->Reset = AA6023Reset;
info->Close = AA6023Close;
GameStateRestore = AA6023Restore;
flash_save = info->battery;
if (flash_save) {
CFI = (uint8*)FCEU_gmalloc(sizeof(cfi_data) * 2);
for (size_t i = 0; i < sizeof(cfi_data); i++) {
CFI[i * 2] = CFI[i * 2 + 1] = cfi_data[i];
}
SetupCartPRGMapping(CFI_CHIP, CFI, sizeof(cfi_data) * 2, 0);
Flash = (uint8*)FCEU_gmalloc(PRGsize[ROM_CHIP]);
for (unsigned int i = 0; i < PRGsize[ROM_CHIP]; i++) {
Flash[i] = PRGptr[ROM_CHIP][i % PRGsize[ROM_CHIP]];
}
SetupCartPRGMapping(FLASH_CHIP, Flash, PRGsize[ROM_CHIP], 1);
info->addSaveGameBuf( Flash, PRGsize[ROM_CHIP] );
}
AddExState(EXPREGS, 4, 0, "EXPR");
if (flash_save)
{
AddExState(&flash_state, sizeof(flash_state), 0, "FLST");
AddExState(flash_buffer_a, sizeof(flash_buffer_a), 0, "FLBA");
AddExState(flash_buffer_v, sizeof(flash_buffer_v), 0, "FLBV");
AddExState(&cfi_mode, sizeof(cfi_mode), 0, "CFIM");
AddExState(Flash, PRGsize[ROM_CHIP], 0, "FLAS");
}
}
// Registers at $6xxx
void COOLBOY_Init(CartInfo *info) {
GenMMC3_Init(info, 2048, 256, 8, 1);
pwrap = COOLBOYPW;
cwrap = COOLBOYCW;
info->Power = COOLBOYPower;
info->Reset = COOLBOYReset;
AddExState(EXPREGS, 4, 0, "EXPR");
void COOLBOY_Init(CartInfo* info) {
CommonInit(info, 0);
}
// Registers at $5xxx
void MINDKIDS_Init(CartInfo *info) {
GenMMC3_Init(info, 2048, 256, 8, 1);
pwrap = COOLBOYPW;
cwrap = COOLBOYCW;
info->Power = MINDKIDSPower;
info->Reset = COOLBOYReset;
AddExState(EXPREGS, 4, 0, "EXPR");
void MINDKIDS_Init(CartInfo* info) {
CommonInit(info, 1);
}
// For NES 2.0 loader
void SMD132_SMD133_Init(CartInfo *info) {
switch (info->submapper)
{
case 0:
COOLBOY_Init(info);
break;
case 1:
MINDKIDS_Init(info);
break;
default:
FCEU_PrintError("Unknown submapper: #%d.", info->submapper);
break;
}
void AA6023_Init(CartInfo* info) {
CommonInit(info, info->submapper);
}
File diff suppressed because it is too large Load Diff
+49 -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) {
@@ -474,6 +475,39 @@ void Mapper203_Init(CartInfo *info) {
Latch_Init(info, M203Sync, 0, 0x8000, 0xFFFF, 0, 0);
}
//------------------ Map 218 ---------------------------
static void Mapper218_Power()
{
//doesn't really matter
SetReadHandler(0x6000, 0xFFFF, &CartBROB);
}
void Mapper218_Init(CartInfo *info)
{
info->Power = &Mapper218_Power;
//fixed PRG mapping
setprg32(0x8000, 0);
//this mapper is supposed to interpret the iNES header bits specially
static const uint8 mirrorings[] = {MI_V,MI_H,MI_0,MI_1};
SetupCartMirroring(mirrorings[info->mirrorAs2Bits],1,nullptr);
//cryptic logic to effect the CHR RAM mappings by mapping 1k blocks to NTARAM according to how the pins are wired
//this could be done by bit logic, but this is self-documenting
static const uint8 mapping[] = {
0,1,0,1,0,1,0,1, //mirrorAs2Bits==0
0,0,1,1,0,0,1,1, //mirrorAs2Bits==1
0,0,0,0,1,1,1,1, //mirrorAs2Bits==2
0,0,0,0,0,0,0,0 //mirrorAs2Bits==3
};
for(int i=0;i<8;i++)
VPageR[i] = &NTARAM[mapping[info->mirrorAs2Bits*8+i]];
PPUCHRRAM = 0xFF;
}
//------------------ Map 240 ---------------------------
static void M240Sync(void) {
+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);
+4 -3
View File
@@ -28,17 +28,19 @@
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;
static int IRQa, IRQCount;
FCEU_MAYBE_UNUSED
static DECLFW(MBWRAM) {
if (!(DRegs[3] & 0x10))
Page[A >> 11][A] = V;
}
FCEU_MAYBE_UNUSED
static DECLFR(MAWRAM) {
if (DRegs[3] & 0x10)
return X.DB;
@@ -254,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");
+88
View File
@@ -0,0 +1,88 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2022 Cluster
*
* 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
*
* NES 2.0 Mapper 470 denotes the INX_007T_V01 multicart circuit board,
* used for the Retro-Bit re-release of Battletoads and Double Dragon.
* It is basically AOROM with an additional outer bank register at $5000-$5FFF
* whose data selects the 256 KiB outer bank.
*
* $5000-$5FFF
* 7 bit 0
* ---- ----
* xxxx xxOO
* ||
* ++- Select outer 256 KB PRG ROM bank for CPU $8000-$FFFF
*
* $8000-$FFFF
* 7 bit 0
* ---- ----
* xxxM xPPP
* | |||
* | +++- Select inner 32 KB PRG ROM bank for CPU $8000-$FFFF
* +------ Select 1 KB VRAM page for all 4 nametables
*
*/
#include "mapinc.h"
static uint8 latch_out, latch_in;
static void INX_007T_Sync() {
setprg32(0x8000, (latch_in & 0b111) | (latch_out << 3));
setmirror(MI_0 + ((latch_in >> 4) & 1));
setchr8(0);
}
static void StateRestore(int version) {
INX_007T_Sync();
}
static DECLFW(INX_007T_WriteLow)
{
latch_out = V;
INX_007T_Sync();
}
static DECLFW(INX_007T_WriteHi)
{
latch_in = V;
INX_007T_Sync();
}
static void INX_007T_Power(void) {
latch_in = latch_out = 0;
INX_007T_Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
SetWriteHandler(0x5000,0x5FFF, INX_007T_WriteLow);
SetWriteHandler(0x8000, 0xFFFF, INX_007T_WriteHi);
}
static void INX_007T_Reset(void) {
latch_in = latch_out = 0;
INX_007T_Sync();
}
void INX_007T_Init(CartInfo *info) {
info->Power = INX_007T_Power;
info->Reset = INX_007T_Reset;
GameStateRestore = StateRestore;
SetupCartMirroring(MI_0, 0, NULL);
AddExState(&latch_out, 1, 0, "LATO");
AddExState(&latch_in, 1, 0, "LATI");
}
+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);
+71 -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");
}
@@ -1376,6 +1428,7 @@ static DECLFW(M406IRQWrite) {
MMC3_IRQWrite((A & 0xFFFE) | ((A & 2) >> 1), V);
}
FCEU_MAYBE_UNUSED
static DECLFW(M406Write) {
}
+8 -8
View File
@@ -307,8 +307,7 @@ cartdata MMC5CartList[] =
#define MMC5_NOCARTS (sizeof(MMC5CartList) / sizeof(MMC5CartList[0]))
int DetectMMC5WRAMSize(uint32 crc32) {
int x;
for (x = 0; x < MMC5_NOCARTS; x++) {
for (size_t x = 0; x < MMC5_NOCARTS; x++) {
if (crc32 == MMC5CartList[x].crc32) {
if(MMC5CartList[x].size > 1)
FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n");
@@ -425,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;
@@ -1022,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");
}
+142 -192
View File
@@ -1,7 +1,7 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2014 CaitSith2
* Copyright (C) 2014 CaitSith2, 2022 Cluster
*
* 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
@@ -19,7 +19,7 @@
*/
/*
* Roms still using NES 1.0 format should be loaded as 32K CHR RAM.
* Roms still using NES 1.0 format should be loaded as 8K CHR RAM.
* Roms defined under NES 2.0 should use the VRAM size field, defining 7, 8 or 9, based on how much VRAM should be present.
* UNIF doesn't have this problem, because unique board names can define this information.
* The UNIF names are UNROM-512-8K, UNROM-512-16K and UNROM-512-32K
@@ -28,6 +28,7 @@
* Known games to use this board are:
* Battle Kid 2: Mountain of Torment (512K PRG, 8K CHR RAM, Horizontal Mirroring, Flash disabled)
* Study Hall (128K PRG (in 512K flash chip), 8K CHR RAM, Horizontal Mirroring, Flash enabled)
* Nix: The Paradox Relic (512 PRG, 8K CHR RAM, Vertical Mirroring, Flash enabled)
* Although Xmas 2013 uses a different board, where LEDs can be controlled (with writes to the $8000-BFFF space),
* it otherwise functions identically.
*/
@@ -35,211 +36,159 @@
#include "mapinc.h"
#include "../ines.h"
static uint8 latche, latcheinit, bus_conflict, chrram_mask, software_id=false;
const int ROM_CHIP = 0x00;
const int CFI_CHIP = 0x10;
const int FLASH_CHIP = 0x11;
const int FLASH_SECTOR_SIZE = 4 * 1024;
static uint8 flash_save, flash_state, flash_id_mode, latche, bus_conflict;
static uint16 latcha;
static uint8 *flashdata;
static uint32 *flash_write_count;
static uint8 *FlashPage[32];
//static uint32 *FlashWriteCountPage[32];
//static uint8 flashloaded = false;
static uint8 *flash_data;
static uint16 flash_buffer_a[10];
static uint8 flash_buffer_v[10];
static uint8 flash_id[2];
static uint8 flash_save=0, flash_state=0, flash_mode=0, flash_bank;
static void (*WLSync)(void);
static void (*WHSync)(void);
static INLINE void setfpageptr(int s, uint32 A, uint8 *p) {
uint32 AB = A >> 11;
int x;
if (p)
for (x = (s >> 1) - 1; x >= 0; x--) {
FlashPage[AB + x] = p - A;
}
static void UNROM512_Sync() {
int chip;
if (flash_save)
chip = !flash_id_mode ? FLASH_CHIP : CFI_CHIP;
else
for (x = (s >> 1) - 1; x >= 0; x--) {
FlashPage[AB + x] = 0;
}
}
void setfprg16(uint32 A, uint32 V) {
if (PRGsize[0] >= 16384) {
V &= PRGmask16[0];
setfpageptr(16, A, flashdata ? (&flashdata[V << 14]) : 0);
} else {
uint32 VA = V << 3;
int x;
for (x = 0; x < 8; x++)
setfpageptr(2, A + (x << 11), flashdata ? (&flashdata[((VA + x) & PRGmask2[0]) << 11]) : 0);
}
}
void inc_flash_write_count(uint8 bank, uint32 A)
{
flash_write_count[(bank*4) + ((A&0x3000)>>12)]++;
if(!flash_write_count[(bank*4) + ((A&0x3000)>>12)])
flash_write_count[(bank*4) + ((A&0x3000)>>12)]++;
}
uint32 GetFlashWriteCount(uint8 bank, uint32 A)
{
return flash_write_count[(bank*4) + ((A&0x3000)>>12)];
chip = ROM_CHIP;
setprg16r(chip, 0x8000, latche & 0b11111);
setprg16r(chip, 0xc000, ~0);
setchr8((latche >> 5) & 0b11);
setmirror(MI_0 + ((latche >> 7) & 1));
}
static void StateRestore(int version) {
WHSync();
UNROM512_Sync();
}
static DECLFW(UNROM512LLatchWrite)
static DECLFW(UNROM512FlashWrite)
{
latche = V;
latcha = A;
WLSync();
if (flash_state < sizeof(flash_buffer_a) / sizeof(flash_buffer_a[0])) {
flash_buffer_a[flash_state] = (A & 0x3FFF) | ((latche & 1) << 14);
flash_buffer_v[flash_state] = V;
flash_state++;
// enter flash ID mode
if ((flash_state == 2) &&
(flash_buffer_a[0] == 0x5555) && (flash_buffer_v[0] == 0xAA) &&
(flash_buffer_a[1] == 0x2AAA) && (flash_buffer_v[1] == 0x55) &&
(flash_buffer_a[1] == 0x5555) && (flash_buffer_v[1] == 0x90)) {
flash_id_mode = 0;
flash_state = 0;
}
// erase sector
if ((flash_state == 6) &&
(flash_buffer_a[0] == 0x5555) && (flash_buffer_v[0] == 0xAA) &&
(flash_buffer_a[1] == 0x2AAA) && (flash_buffer_v[1] == 0x55) &&
(flash_buffer_a[2] == 0x5555) && (flash_buffer_v[2] == 0x80) &&
(flash_buffer_a[3] == 0x5555) && (flash_buffer_v[3] == 0xAA) &&
(flash_buffer_a[4] == 0x2AAA) && (flash_buffer_v[4] == 0x55) &&
(flash_buffer_v[5] == 0x30)) {
int offset = &Page[A >> 11][A] - flash_data;
int sector = offset / FLASH_SECTOR_SIZE;
for (int i = sector * FLASH_SECTOR_SIZE; i < (sector + 1) * FLASH_SECTOR_SIZE; i++)
flash_data[i % PRGsize[ROM_CHIP]] = 0xFF;
FCEU_printf("Flash sector #%d is erased (0x%08x - 0x%08x).\n", sector, offset, offset + FLASH_SECTOR_SIZE);
}
// erase chip
if ((flash_state == 6) &&
(flash_buffer_a[0] == 0x5555) && (flash_buffer_v[0] == 0xAA) &&
(flash_buffer_a[1] == 0x2AAA) && (flash_buffer_v[1] == 0x55) &&
(flash_buffer_a[2] == 0x5555) && (flash_buffer_v[2] == 0x80) &&
(flash_buffer_a[3] == 0x5555) && (flash_buffer_v[3] == 0xAA) &&
(flash_buffer_a[4] == 0x2AAA) && (flash_buffer_v[4] == 0x55) &&
(flash_buffer_a[4] == 0x5555) && (flash_buffer_v[4] == 0x10)) {
memset(flash_data, 0xFF, PRGsize[ROM_CHIP]);
FCEU_printf("Flash chip erased.\n");
flash_state = 0;
}
// write byte
if ((flash_state == 4) &&
(flash_buffer_a[0] == 0x5555) && (flash_buffer_v[0] == 0xAA) &&
(flash_buffer_a[1] == 0x2AAA) && (flash_buffer_v[1] == 0x55) &&
(flash_buffer_a[2] == 0x5555) && (flash_buffer_v[2] == 0xA0)) {
int offset = &Page[A >> 11][A] - flash_data;
if (CartBR(A) != 0xFF) {
FCEU_PrintError("Error: can't write to 0x%08x, flash sector is not erased.\n", offset);
}
else {
CartBW(A, V);
}
flash_state = 0;
}
}
// not a command
if (((A & 0xFFF) != 0x0AAA) && ((A & 0xFFF) != 0x0555)) {
flash_state = 0;
}
// reset
if (V == 0xF0) {
flash_state = 0;
flash_id_mode = 0;
}
UNROM512_Sync();
}
static DECLFW(UNROM512HLatchWrite)
{
if (bus_conflict)
latche = (V == CartBR(A)) ? V : 0;
latche = V & CartBR(A);
else
latche = V;
latcha = A;
WHSync();
}
static DECLFR(UNROM512LatchRead)
{
uint8 flash_id[3]={0xB5,0xB6,0xB7};
if(software_id)
{
if(A&1)
return flash_id[ROM_size>>4];
else
return 0xBF;
}
if(flash_save)
{
if(A < 0xC000)
{
if(GetFlashWriteCount(flash_bank,A))
return FlashPage[A >> 11][A];
}
else
{
if(GetFlashWriteCount(ROM_size-1,A))
return FlashPage[A >> 11][A];
}
}
return Page[A >> 11][A];
UNROM512_Sync();
}
static void UNROM512LatchPower(void) {
latche = latcheinit;
WHSync();
SetReadHandler(0x8000, 0xFFFF, UNROM512LatchRead);
latche = 0;
UNROM512_Sync();
SetReadHandler(0x8000, 0xFFFF, CartBR);
if(!flash_save)
SetWriteHandler(0x8000, 0xFFFF, UNROM512HLatchWrite);
else
{
SetWriteHandler(0x8000,0xBFFF,UNROM512LLatchWrite);
SetWriteHandler(0x8000,0xBFFF,UNROM512FlashWrite);
SetWriteHandler(0xC000,0xFFFF,UNROM512HLatchWrite);
}
}
static void UNROM512LatchClose(void) {
if(flash_write_count)
FCEU_gfree(flash_write_count);
if(flashdata)
FCEU_gfree(flashdata);
flash_write_count = NULL;
flashdata = NULL;
if(flash_data)
FCEU_gfree(flash_data);
flash_data = NULL;
}
static void UNROM512LSync() {
int erase_a[5]={0x9555,0xAAAA,0x9555,0x9555,0xAAAA};
int erase_d[5]={0xAA,0x55,0x80,0xAA,0x55};
int erase_b[5]={1,0,1,1,0};
if(flash_mode==0)
{
if((latcha == erase_a[flash_state]) && (latche == erase_d[flash_state]) && (flash_bank == erase_b[flash_state]))
{
flash_state++;
if(flash_state == 5)
{
flash_mode=1;
}
}
else if ((flash_state==2)&&(latcha==0x9555)&&(latche==0xA0)&&(flash_bank==1))
{
flash_state++;
flash_mode=2;
}
else if ((flash_state==2)&&(latcha==0x9555)&&(latche==0x90)&&(flash_bank==1))
{
flash_state=0;
software_id=true;
}
else
{
if(latche==0xF0)
software_id=false;
flash_state=0;
}
}
else if(flash_mode==1) //Chip Erase or Sector Erase
{
if(latche==0x30)
{
inc_flash_write_count(flash_bank,latcha);
memset(&FlashPage[(latcha & 0xF000) >> 11][latcha & 0xF000],0xFF,0x1000);
}
else if (latche==0x10)
{
for(uint32 i=0;i<(ROM_size*4);i++)
inc_flash_write_count(i>>2,i<<12);
memset(flashdata,0xFF,ROM_size*0x4000); //Erasing the rom chip as instructed. Crash rate calulated to be 99.9% :)
}
flash_state=0;
flash_mode=0;
}
else if(flash_mode==2) //Byte Program
{
if(!GetFlashWriteCount(flash_bank,latcha))
{
inc_flash_write_count(flash_bank,latcha);
memcpy(&FlashPage[(latcha & 0xF000) >> 11][latcha & 0xF000],&Page[(latcha & 0xF000)>>11][latcha & 0xF000],0x1000);
}
FlashPage[latcha>>11][latcha]&=latche;
flash_state=0;
flash_mode=0;
}
}
static void UNROM512HSync()
static void UNROM512_FlashReset(void)
{
flash_bank=latche&(ROM_size-1);
setprg16(0x8000, flash_bank);
setprg16(0xc000, ~0);
setfprg16(0x8000, flash_bank);
setfprg16(0xC000, ~0);
setchr8r(0, (latche & chrram_mask) >> 5);
setmirror(MI_0+(latche>>7));
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) {
flash_state=0;
flash_bank=0;
flash_save=info->battery;
info->Power = UNROM512LatchPower;
info->Close = UNROM512LatchClose;
GameStateRestore = StateRestore;
if(info->vram_size == 8192)
chrram_mask = 0;
else if (info->vram_size == 16384)
chrram_mask = 0x20;
else
chrram_mask = 0x60;
flash_state = 0;
flash_id_mode = 0;
flash_save = info->battery;
bus_conflict = !info->battery; // Is it required by any game?
int mirror = (head.ROM_type & 1) | ((head.ROM_type & 8) >> 2);
switch (mirror)
@@ -258,28 +207,29 @@ void UNROM512_Init(CartInfo *info) {
break;
}
bus_conflict = !info->battery;
latcheinit = 0;
WLSync = UNROM512LSync;
WHSync = UNROM512HSync;
info->Power = UNROM512LatchPower;
info->Close = UNROM512LatchClose;
GameStateRestore = StateRestore;
if(flash_save)
{
flashdata = (uint8*)FCEU_gmalloc(ROM_size*0x4000);
flash_write_count = (uint32*)FCEU_gmalloc(ROM_size*4*sizeof(uint32));
info->SaveGame[0] = (uint8*)flash_write_count;
info->SaveGame[1] = flashdata;
info->SaveGameLen[0] = ROM_size*4*sizeof(uint32);
info->SaveGameLen[1] = ROM_size*0x4000;
AddExState(flash_write_count,ROM_size*4*sizeof(uint32),0,"FLASH_WRITE_COUNT");
AddExState(flashdata,ROM_size*0x4000,0,"FLASH_DATA");
AddExState(&flash_state,1,0,"FLASH_STATE");
AddExState(&flash_mode,1,0,"FLASH_MODE");
AddExState(&flash_bank,1,0,"FLASH_BANK");
AddExState(&latcha,2,0,"LATA");
// Allocate memory for flash
size_t flash_size = PRGsize[ROM_CHIP];
flash_data = (uint8*)FCEU_gmalloc(flash_size);
// Copy ROM to flash data
for (size_t i = 0; i < flash_size; i++) {
flash_data[i] = PRGptr[ROM_CHIP][i];
}
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, 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(&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");
}
+20 -8
View File
@@ -23,7 +23,7 @@
static bool isPirate;
static uint8 is22, reg1mask, reg2mask;
static uint16 IRQCount;
static uint8 IRQLatch, IRQa;
static uint8 IRQLatch, IRQa, IRQMode;
static uint8 prgreg[2], chrreg[8];
static uint16 chrhi[8];
static uint8 regcmd, irqcmd, mirr, big_bank;
@@ -45,6 +45,7 @@ static SFORMAT StateRegs[] =
{ &IRQCount, 2, "IRQC" },
{ &IRQLatch, 1, "IRQL" },
{ &IRQa, 1, "IRQA" },
{ &IRQMode, 1, "IRQM" },
{ 0 }
};
@@ -115,7 +116,7 @@ static DECLFW(VRC24Write) {
case 0x9003: regcmd = V; Sync(); break;
case 0xF000: X6502_IRQEnd(FCEU_IQEXT); IRQLatch &= 0xF0; IRQLatch |= V & 0xF; break;
case 0xF001: X6502_IRQEnd(FCEU_IQEXT); IRQLatch &= 0x0F; IRQLatch |= V << 4; break;
case 0xF002: X6502_IRQEnd(FCEU_IQEXT); acount = 0; IRQCount = IRQLatch; IRQa = V & 2; irqcmd = V & 1; break;
case 0xF002: X6502_IRQEnd(FCEU_IQEXT); acount = 0; IRQCount = IRQLatch; IRQMode = V & 4; IRQa = V & 2; irqcmd = V & 1; break;
case 0xF003: X6502_IRQEnd(FCEU_IQEXT); IRQa = irqcmd; break;
}
}
@@ -136,16 +137,28 @@ static void VRC24Power(void) {
void VRC24IRQHook(int a) {
#define LCYCS 341
if (IRQa) {
acount += a * 3;
if (acount >= LCYCS) {
while (acount >= LCYCS) {
acount -= LCYCS;
if (IRQMode) {
acount += a;
while (acount > 0) {
acount--;
IRQCount++;
if (IRQCount & 0x100) {
X6502_IRQBegin(FCEU_IQEXT);
IRQCount = IRQLatch;
}
}
} else {
acount += a * 3;
if (acount >= LCYCS) {
while (acount >= LCYCS) {
acount -= LCYCS;
IRQCount++;
if (IRQCount & 0x100) {
X6502_IRQBegin(FCEU_IQEXT);
IRQCount = IRQLatch;
}
}
}
}
}
}
@@ -172,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);
+24 -11
View File
@@ -25,10 +25,10 @@
static uint8 is26;
static uint8 prg[2], chr[8], mirr;
static uint8 IRQLatch, IRQa, IRQd;
static uint8 IRQLatch, IRQa, IRQd, IRQMode;
static int32 IRQCount, CycleCount;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
static SFORMAT StateRegs[] =
{
@@ -40,6 +40,7 @@ static SFORMAT StateRegs[] =
{ &IRQLatch, 1, "IRQL" },
{ &IRQCount, 4, "IRQC" },
{ &CycleCount, 4, "CYCC" },
{ &IRQMode, 1, "IRQM" },
{ 0 }
};
@@ -109,6 +110,7 @@ static DECLFW(VRC6Write) {
case 0xE003: chr[7] = V; Sync(); break;
case 0xF000: IRQLatch = V; X6502_IRQEnd(FCEU_IQEXT); break;
case 0xF001:
IRQMode = V & 4;
IRQa = V & 2;
IRQd = V & 1;
if (V & 2)
@@ -132,13 +134,25 @@ static void VRC6Power(void) {
static void VRC6IRQHook(int a) {
if (IRQa) {
CycleCount += a * 3;
while(CycleCount >= 341) {
CycleCount -= 341;
IRQCount++;
if (IRQCount == 0x100) {
IRQCount = IRQLatch;
X6502_IRQBegin(FCEU_IQEXT);
if (IRQMode) {
CycleCount += a;
while (CycleCount > 0) {
CycleCount--;
IRQCount++;
if (IRQCount & 0x100) {
X6502_IRQBegin(FCEU_IQEXT);
IRQCount = IRQLatch;
}
}
} else {
CycleCount += a * 3;
while(CycleCount >= 341) {
CycleCount -= 341;
IRQCount++;
if (IRQCount == 0x100) {
IRQCount = IRQLatch;
X6502_IRQBegin(FCEU_IQEXT);
}
}
}
}
@@ -365,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);
+24 -11
View File
@@ -21,10 +21,10 @@
#include "mapinc.h"
static uint8 vrc7idx, preg[3], creg[8], mirr;
static uint8 IRQLatch, IRQa, IRQd;
static uint8 IRQLatch, IRQa, IRQd, IRQMode;
static int32 IRQCount, CycleCount;
static uint8 *WRAM = NULL;
static uint32 WRAMSIZE;
static uint32 WRAMSIZE=0;
#include "emu2413.h"
@@ -44,6 +44,7 @@ static SFORMAT StateRegs[] =
{ &IRQCount, 4, "IRQC" },
{ &CycleCount, 4, "CYCC" },
{ (void**)VRC7Sound_saveptr, sizeof(*VRC7Sound) | FCEUSTATE_INDIRECT, "VRC7" },
{ &IRQMode, 1, "IRQM" },
{0}
};
@@ -134,6 +135,7 @@ static DECLFW(VRC7Write) {
case 0xE000: mirr = V & 3; Sync(); break;
case 0xE010: IRQLatch = V; X6502_IRQEnd(FCEU_IQEXT); break;
case 0xF000:
IRQMode = V & 4;
IRQa = V & 2;
IRQd = V & 1;
if (V & 2)
@@ -165,13 +167,25 @@ static void VRC7Close(void)
static void VRC7IRQHook(int a) {
if (IRQa) {
CycleCount += a * 3;
while(CycleCount >= 341) {
CycleCount -= 341;
IRQCount++;
if (IRQCount == 0x100) {
IRQCount = IRQLatch;
X6502_IRQBegin(FCEU_IQEXT);
if (IRQMode) {
CycleCount += a;
while (CycleCount > 0) {
CycleCount--;
IRQCount++;
if (IRQCount & 0x100) {
X6502_IRQBegin(FCEU_IQEXT);
IRQCount = IRQLatch;
}
}
} else {
CycleCount += a * 3;
while(CycleCount >= 341) {
CycleCount -= 341;
IRQCount++;
if (IRQCount == 0x100) {
IRQCount = IRQLatch;
X6502_IRQBegin(FCEU_IQEXT);
}
}
}
}
@@ -190,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();
+47 -19
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,25 +564,45 @@ 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++)
if (LocalHWInfo->SaveGame[x])
fread(LocalHWInfo->SaveGame[x], 1, LocalHWInfo->SaveGameLen[x], sp);
if (sp != NULL)
{
for (size_t x = 0; x < LocalHWInfo->SaveGame.size(); x++)
{
if (LocalHWInfo->SaveGame[x].bufptr)
{
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");
}
}
}
}
}
}
//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();
}
}
}
}
+60 -8
View File
@@ -1,20 +1,46 @@
#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;
int submapper; // Submappers as defined by NES 2.0
@@ -26,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;
+19 -41
View File
@@ -59,7 +59,7 @@ void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p)
}
CHEATF_SUBFAST SubCheats[256] = { 0 };
CHEATF_SUBFAST SubCheats[256];
uint32 numsubcheats = 0;
int globalCheatDisabled = 0;
int disableAutoLSCheats = 0;
@@ -152,28 +152,23 @@ int FCEU_CalcCheatAffectedBytes(uint32 address, uint32 size) {
return count;
}
static int AddCheatEntry(const char *name, uint32 addr, uint8 val, int compare, int status, int type);
static void AddCheatEntry(const char *name, uint32 addr, uint8 val, int compare, int status, int type);
static void CheatMemErr(void)
{
FCEUD_PrintError("Error allocating memory for cheat data.");
}
static int AddCheatEntry(const char *name, uint32 addr, uint8 val, int compare, int status, int type)
static void AddCheatEntry(const char *name, uint32 addr, uint8 val, int compare, int status, int type)
{
struct CHEATF *temp;
if(!(temp = (struct CHEATF *)FCEU_dmalloc(sizeof(struct CHEATF))))
{
CheatMemErr();
return(0);
}
CHEATF *temp = new CHEATF();
temp->name = strcpy((char*) FCEU_dmalloc(strlen(name) + 1), name);
temp->name = name;
temp->addr = addr;
temp->val = val;
temp->status = status;
temp->compare = compare;
temp->type = type;
temp->next = 0;
temp->next = nullptr;
if(cheats)
{
@@ -182,8 +177,6 @@ static int AddCheatEntry(const char *name, uint32 addr, uint8 val, int compare,
}
else
cheats = cheatsl = temp;
return (1);
}
/* The "override_existing" parameter is used only in cheat dialog import.
@@ -306,14 +299,13 @@ void FCEU_SaveGameCheats(FILE* fp, int release)
fputc(':', fp);
if (next->compare >= 0)
fprintf(fp, "%04x:%02x:%02x:%s\n", next->addr, next->val, next->compare, next->name);
fprintf(fp, "%04x:%02x:%02x:%s\n", next->addr, next->val, next->compare, next->name.c_str());
else
fprintf(fp, "%04x:%02x:%s\n", next->addr, next->val, next->name);
fprintf(fp, "%04x:%02x:%s\n", next->addr, next->val, next->name.c_str());
if (release) free(next->name);
struct CHEATF *t = next;
next = next->next;
if (release) free(t);
if (release) delete t;
}
}
@@ -333,8 +325,7 @@ void FCEU_FlushGameCheats(FILE *override, int nosave)
{
struct CHEATF *last=next;
next=next->next;
free(last->name);
free(last);
delete last;
if(!next) break;
}
cheats=cheatsl=0;
@@ -379,9 +370,7 @@ void FCEU_FlushGameCheats(FILE *override, int nosave)
int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type)
{
if(!AddCheatEntry(name, addr, val, compare, 1, type))
return 0;
AddCheatEntry(name, addr, val, compare, 1, type);
savecheats = 1;
RebuildSubCheats();
@@ -415,8 +404,7 @@ int FCEUI_DelCheat(uint32 which)
else
cheats=cheatsl=0; // No (more) cheats.
}
free(cur->name); // Now that all references to this cheat are removed,
free(cur); // free the memory.
delete cur; // free the memory.
break;
} // *END REMOVE THIS CHEAT*
@@ -451,18 +439,18 @@ void FCEU_ApplyPeriodicCheats(void)
}
void FCEUI_ListCheats(int (*callb)(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data)
void FCEUI_ListCheats(int (*callb)(const char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data)
{
struct CHEATF *next=cheats;
while(next)
{
if(!callb(next->name,next->addr,next->val,next->compare,next->status,next->type,data)) break;
if(!callb(next->name.c_str(),next->addr,next->val,next->compare,next->status,next->type,data)) break;
next=next->next;
}
}
int FCEUI_GetCheat(uint32 which, char **name, uint32 *a, uint8 *v, int *compare, int *s, int *type)
int FCEUI_GetCheat(uint32 which, std::string *name, uint32 *a, uint8 *v, int *compare, int *s, int *type)
{
struct CHEATF *next=cheats;
uint32 x=0;
@@ -600,7 +588,7 @@ int FCEUI_DecodePAR(const char *str, int *a, int *v, int *c, int *type)
/* name can be NULL if the name isn't going to be changed. */
/* same goes for a, v, and s(except the values of each one must be <0) */
int FCEUI_SetCheat(uint32 which, const char *name, int32 a, int32 v, int c, int s, int type)
int FCEUI_SetCheat(uint32 which, const std::string *name, int32 a, int32 v, int c, int s, int type)
{
struct CHEATF *next = cheats;
uint32 x = 0;
@@ -610,13 +598,7 @@ int FCEUI_SetCheat(uint32 which, const char *name, int32 a, int32 v, int c, int
if(x == which)
{
if(name)
{
char *t;
if((t = (char *)realloc(next->name, strlen(name) + 1)))
strcpy(next->name = t, name);
else
return 0;
}
next->name = *name;
if(a >= 0)
next->addr = a;
if(v >= 0)
@@ -662,7 +644,7 @@ int FCEUI_ToggleCheat(uint32 which)
int FCEUI_GlobalToggleCheat(int global_enabled)
{
int _numsubcheats = numsubcheats;
unsigned int _numsubcheats = numsubcheats;
globalCheatDisabled = !global_enabled;
RebuildSubCheats();
return _numsubcheats != numsubcheats;
@@ -911,11 +893,7 @@ int FCEU_DeleteAllCheats(void)
while (cur)
{
next = cur->next;
if ( cur->name )
{
free(cur->name);
}
free(cur);
delete cur;
cur = next;
}
cheats = cheatsl = 0;
+9 -3
View File
@@ -33,16 +33,22 @@ extern int disableAutoLSCheats;
int FCEU_DisableAllCheats(void);
int FCEU_DeleteAllCheats(void);
typedef struct {
struct CHEATF_SUBFAST
{
uint16 addr;
uint8 val;
int compare;
readfunc PrevRead;
} CHEATF_SUBFAST;
CHEATF_SUBFAST(void)
{
addr = 0; val = 0; compare = 0; PrevRead = nullptr;
}
};
struct CHEATF {
struct CHEATF *next;
char *name;
std::string name;
uint16 addr;
uint8 val;
int compare; /* -1 for no compare. */
+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
+15 -10
View File
@@ -11,25 +11,27 @@
#include <cstdio>
#include <cstdlib>
static char *aboutString = 0;
static std::string aboutString;
#ifndef FCEUX_BUILD_TIMESTAMP
#define FCEUX_BUILD_TIMESTAMP __TIME__ " " __DATE__
#endif
//#pragma message( "Compiling using C++ Std: " __FCEU_STRINGIZE(__cplusplus) )
// returns a string suitable for use in an aboutbox
const char *FCEUI_GetAboutString(void)
{
const char *aboutTemplate =
FCEU_NAME_AND_VERSION "\n\n"
"Administrators:\n"
"zeromus, mjbudd77, feos\n"
"zeromus, feos\n"
"\n"
"Current Contributors:\n"
"CaH4e3, rainwarrior, owomomo, punkrockguy318\n"
"CaH4e3, rainwarrior, owomomo, punkrockguy318, Cluster\n"
"\n"
"Past Contributors:\n"
"xhainingx, gocha, AnS\n"
"xhainingx, gocha, AnS, mjbudd77\n"
"\n"
"FCEUX 2.0:\n"
"mz, nitsujrehtona, SP, Ugly Joe,\n"
@@ -55,14 +57,17 @@ const char *FCEUI_GetAboutString(void)
"\n"
FCEUX_BUILD_TIMESTAMP "\n";
if (aboutString) return aboutString;
if (aboutString.size() > 0) return aboutString.c_str();
const char *compilerString = FCEUD_GetCompilerString();
//allocate the string and concatenate the template with the compiler string
if (!(aboutString = (char*)FCEU_dmalloc(strlen(aboutTemplate) + strlen(compilerString) + 1)))
return NULL;
char cppVersion[128];
sprintf(aboutString,"%s%s",aboutTemplate,compilerString);
return aboutString;
snprintf( cppVersion, sizeof(cppVersion), "\nCompiled using C++ Language Standard: %li\n", __cplusplus);
aboutString.assign( aboutTemplate );
aboutString.append( compilerString );
aboutString.append( cppVersion );
return aboutString.c_str();
}
+59 -24
View File
@@ -6,6 +6,7 @@
#include "cart.h"
#include "ines.h"
#include "debug.h"
#include "debugsymboltable.h"
#include "driver.h"
#include "ppu.h"
@@ -18,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;
@@ -29,18 +35,41 @@ 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
{
auto sym = debugSymbolTable.getSymbolAtAnyBank(offsetBuffer);
if (sym)
{
if (conversionOk)
{
*conversionOk = true;
}
return sym->offset() & 0xFFFF;
}
int type = GIT_CART;
if (GameInfo)
@@ -48,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);
}
}
@@ -131,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;
@@ -145,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
@@ -161,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;
@@ -258,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;
@@ -270,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;
}
@@ -642,7 +676,8 @@ uint16 StackNextIgnorePC = 0xFFFF;
///fires a breakpoint
static void breakpoint(uint8 *opcode, uint16 A, int size) {
int i, j, romAddrPC;
int i, romAddrPC;
unsigned int j;
uint8 brk_type;
uint8 stackop=0;
uint8 stackopstartaddr=0,stackopendaddr=0;
@@ -783,7 +818,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
{
if (watchpoint[i].flags & BT_R)
{
if ( (watchpoint[i].flags & WP_X) && (watchpoint[i].address == romAddrPC) )
if ( (watchpoint[i].flags & WP_X) && (watchpoint[i].address == static_cast<unsigned int>(romAddrPC)) )
{
BREAKHIT(i);
}
@@ -814,7 +849,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
// TXS and TSX only deal with the pointer.
if (watchpoint[i].flags & stackop)
{
for (j = (stackopstartaddr|0x0100); j <= (stackopendaddr|0x0100); j++)
for (j = (stackopstartaddr|0x0100); j <= (static_cast<unsigned int>(stackopendaddr)|0x0100); j++)
{
if (watchpoint[i].endaddress)
{
@@ -840,7 +875,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
// Pushes to stack
if (watchpoint[i].flags & WP_W)
{
for (j = (X.S|0x0100); j < (StackAddrBackup|0x0100); j++)
for (j = (X.S|0x0100); j < (static_cast<unsigned int>(StackAddrBackup)|0x0100); j++)
{
if (watchpoint[i].endaddress)
{
@@ -858,7 +893,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
// Pulls from stack
if (watchpoint[i].flags & WP_R)
{
for (j = (StackAddrBackup|0x0100); j < (X.S|0x0100); j++)
for (j = (StackAddrBackup|0x0100); j < (static_cast<unsigned int>(X.S)|0x0100); j++)
{
if (watchpoint[i].endaddress)
{
+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
File diff suppressed because it is too large Load Diff
+170
View File
@@ -0,0 +1,170 @@
#ifndef _DEBUGSYMBOLTABLE_H_
#define _DEBUGSYMBOLTABLE_H_
#include <string>
#include <map>
#include "utils/mutex.h"
#include "ld65dbg.h"
class debugSymbolPage_t;
class debugSymbolTable_t;
class debugSymbol_t
{
public:
debugSymbol_t(void)
{
ofs = 0;
page = nullptr;
};
debugSymbol_t( int ofs, const char *name = nullptr, const char *comment = nullptr )
{
this->ofs = ofs;
if (name)
{
this->_name.assign(name);
}
if ( comment )
{
this->_comment.assign( comment );
}
page = nullptr;
}
const std::string &name(void)
{
return _name;
}
const std::string &comment(void)
{
return _comment;
}
void commentAssign( std::string str )
{
_comment.assign(str);
return;
}
void commentAssign( const char *str )
{
_comment.assign(str);
return;
}
int offset(void)
{
return ofs;
}
void setOffset( int o )
{
if (o != ofs)
{
ofs = o;
}
}
int updateName( const char *name, int arrayIndex = -1 );
void trimTrailingSpaces(void);
private:
int ofs;
std::string _name;
std::string _comment;
debugSymbolPage_t *page;
friend class debugSymbolPage_t;
friend class debugSymbolTable_t;
};
class debugSymbolPage_t
{
public:
debugSymbolPage_t(int page);
~debugSymbolPage_t(void);
int save(void);
void print(void);
int size(void){ return static_cast<int>(symMap.size()); }
int addSymbol( debugSymbol_t *sym );
int deleteSymbolAtOffset( int ofs );
int updateSymbol( debugSymbol_t *sym );
debugSymbol_t *getSymbolAtOffset( int ofs );
debugSymbol_t *getSymbol( const std::string &name );
int pageNum(void)
{
return _pageNum;
}
const char *pageName(void)
{
return _pageName;
}
private:
int _pageNum;
char _pageName[8];
std::map <int, debugSymbol_t*> symMap;
std::map <std::string, debugSymbol_t*> symNameMap;
friend class debugSymbolTable_t;
};
class debugSymbolTable_t
{
public:
debugSymbolTable_t(void);
~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);
void print(void);
debugSymbol_t *getSymbolAtBankOffset( int bank, int ofs );
debugSymbol_t *getSymbol( int bank, const std::string& name);
debugSymbol_t *getSymbolAtAnyBank( const std::string& name);
int addSymbolAtBankOffset( int bank, int ofs, debugSymbol_t *sym );
int addSymbolAtBankOffset(int bank, int ofs, const char* name, const char* comment = nullptr);
int deleteSymbolAtBankOffset( int bank, int ofs );
int updateSymbol( debugSymbol_t *sym );
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;
};
extern debugSymbolTable_t debugSymbolTable;
#endif
+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);
}
}
+12 -5
View File
@@ -23,7 +23,7 @@ ArchiveScanRecord FCEUD_ScanArchive(std::string fname);
const char *FCEUD_GetCompilerString();
//This makes me feel dirty for some reason.
void FCEU_printf(const char *format, ...);
void FCEU_printf( __FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 2 );
#define FCEUI_printf FCEU_printf
//Video interface
@@ -192,7 +192,7 @@ void TaseditorManualFunction(void);
int32 FCEUI_GetDesiredFPS(void);
void FCEUI_SaveSnapshot(void);
void FCEUI_SaveSnapshotAs(void);
void FCEU_DispMessage(const char *format, int disppos, ...);
void FCEU_DispMessage( __FCEU_PRINTF_FORMAT const char *format, int disppos, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 3 );
#define FCEUI_DispMessage FCEU_DispMessage
int FCEUI_DecodePAR(const char *code, int *a, int *v, int *c, int *type);
@@ -207,10 +207,10 @@ void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a,
void FCEUI_CheatSearchGet(int (*callb)(uint32 a, uint8 last, uint8 current, void *data), void *data);
void FCEUI_CheatSearchBegin(void);
void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2);
void FCEUI_ListCheats(int (*callb)(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data);
void FCEUI_ListCheats(int (*callb)(const char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data);
int FCEUI_GetCheat(uint32 which, char **name, uint32 *a, uint8 *v, int *compare, int *s, int *type);
int FCEUI_SetCheat(uint32 which, const char *name, int32 a, int32 v, int compare,int s, int type);
int FCEUI_GetCheat(uint32 which, std::string *name, uint32 *a, uint8 *v, int *compare, int *s, int *type);
int FCEUI_SetCheat(uint32 which, const std::string *name, int32 a, int32 v, int compare,int s, int type);
void FCEUI_CheatSearchShowExcluded(void);
void FCEUI_CheatSearchSetCurrentAsOriginal(void);
@@ -254,6 +254,8 @@ void FCEUI_VSUniToggleDIP(int w);
uint8 FCEUI_VSUniGetDIPs(void);
void FCEUI_VSUniSetDIP(int w, int state);
void FCEUI_VSUniCoin(void);
void FCEUI_VSUniCoin2(void);
void FCEUI_VSUniService(void);
void FCEUI_FDSInsert(void); //mbg merge 7/17/06 changed to void fn(void) to make it an EMUCMDFN
//int FCEUI_FDSEject(void);
@@ -271,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();
@@ -330,6 +334,9 @@ void FCEUD_DebugBreakpoint(int bp_num);
///the driver should log the current instruction, if it wants (we should move the code in the win driver that does this to the shared area)
void FCEUD_TraceInstruction(uint8 *opcode, int size);
///the driver should flush its trace log
void FCEUD_FlushTrace();
///the driver might should update its NTView (only used if debugging support is compiled in)
void FCEUD_UpdateNTView(int scanline, bool drawall);
+48 -16
View File
@@ -26,7 +26,11 @@
static void GetString(char *s, int max)
{
int x;
fgets(s,max,stdin);
if ( fgets(s,max,stdin) == nullptr )
{
s[0] = 0;
return;
}
for(x=0;x<max;x++)
if(s[x]=='\n')
@@ -41,7 +45,10 @@ static uint32 GetH16(unsigned int def)
{
char buf[32];
fgets(buf,ARRAY_SIZE(buf),stdin);
if ( fgets(buf,ARRAY_SIZE(buf),stdin) == nullptr )
{
return def;
}
if(buf[0]=='\n')
return(def);
if(buf[0]=='$')
@@ -56,7 +63,10 @@ static uint8 Get8(unsigned int def)
{
char buf[32];
fgets(buf,ARRAY_SIZE(buf),stdin);
if ( fgets(buf,ARRAY_SIZE(buf),stdin) == nullptr )
{
return def;
}
if(buf[0]=='\n')
return(def);
sscanf(buf,"%u",&def);
@@ -67,7 +77,10 @@ static int GetI(int def)
{
char buf[32];
fgets(buf,ARRAY_SIZE(buf),stdin);
if ( fgets(buf,ARRAY_SIZE(buf),stdin) == nullptr )
{
return def;
}
if(buf[0]=='\n')
return(def);
sscanf(buf,"%d",&def);
@@ -78,7 +91,10 @@ static int GetYN(int def)
{
char buf[32];
printf("(Y/N)[%s]: ",def?"Y":"N");
fgets(buf,ARRAY_SIZE(buf),stdin);
if ( fgets(buf,ARRAY_SIZE(buf),stdin) == nullptr )
{
return def;
}
if(buf[0]=='y' || buf[0]=='Y')
return(1);
if(buf[0]=='n' || buf[0]=='N')
@@ -114,7 +130,10 @@ int ListChoice(int hmm)
tryagain:
printf(" <'Enter' to continue, (S)top, or enter a number.> ");
fgets(buf,ARRAY_SIZE(buf),stdin);
if ( fgets(buf,ARRAY_SIZE(buf),stdin) == nullptr )
{
return -1;
}
if(buf[0]=='s' || buf[0]=='S') return(-1);
if(buf[0]=='\n') return(0);
if(!sscanf(buf,"%d",&num))
@@ -128,7 +147,10 @@ int ListChoice(int hmm)
tryagain2:
printf(" <'Enter' to make no selection or enter a number.> ");
fgets(buf,ARRAY_SIZE(buf),stdin);
if ( fgets(buf,ARRAY_SIZE(buf),stdin) == nullptr )
{
return -1;
}
if(buf[0]=='\n') return(0);
if(!sscanf(buf,"%d",&num))
return(0);
@@ -199,7 +221,8 @@ static void ToggleCheat(int num)
static void ModifyCheat(int num)
{
char *name;
std::string name;
std::string *pName;
char buf[256];
uint32 A;
uint8 V;
@@ -211,7 +234,7 @@ static void ModifyCheat(int num)
FCEUI_GetCheat(num, &name, &A, &V, &compare, &s, &type);
printf("Name [%s]: ",name);
printf("Name [%s]: ",name.c_str());
GetString(buf,256);
/* This obviously doesn't allow for cheats with no names. Bah. Who wants
@@ -219,9 +242,9 @@ static void ModifyCheat(int num)
*/
if(buf[0])
name=buf; // Change name when FCEUI_SetCheat() is called.
pName=&name; // Change name when FCEUI_SetCheat() is called.
else
name=0; // Don't change name when FCEUI_SetCheat() is called.
pName=nullptr; // Don't change name when FCEUI_SetCheat() is called.
printf("Address [$%04x]: ",(unsigned int)A);
A=GetH16(A);
@@ -240,7 +263,7 @@ static void ModifyCheat(int num)
if(t=='Y' || t=='y') s=1;
else if(t=='N' || t=='n') s=0;
FCEUI_SetCheat(num,name,A,V,compare,s,type);
FCEUI_SetCheat(num,pName,A,V,compare,s,type);
}
@@ -320,7 +343,7 @@ static void AddCheat(void)
}
static int lid;
static int clistcallb(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data)
static int clistcallb(const char *name, uint32 a, uint8 v, int compare, int s, int type, void *data)
{
char tmp[512];
int ret;
@@ -348,7 +371,10 @@ static void ListCheats(void)
{
char tmp[32];
printf(" <(T)oggle status, (M)odify, or (D)elete this cheat.> ");
fgets(tmp,ARRAY_SIZE(tmp),stdin);
if ( fgets(tmp,ARRAY_SIZE(tmp),stdin) == nullptr )
{
tmp[0] = 0;
}
switch(tolower(tmp[0]))
{
case 't':ToggleCheat(which);
@@ -405,7 +431,10 @@ static int ShowShortList(const char *moe[], int n, int def)
clo:
printf("\nSelection [%d]> ",def+1);
fgets(tmp,ARRAY_SIZE(tmp),stdin);
if ( fgets(tmp,ARRAY_SIZE(tmp),stdin) == nullptr )
{
return def;
}
if(tmp[0]=='\n')
return def;
c=tolower(tmp[0]);
@@ -504,7 +533,10 @@ static void DoMenu(MENU *men)
recommand:
printf("Command> ");
fgets(buf,ARRAY_SIZE(buf),stdin);
if ( fgets(buf,ARRAY_SIZE(buf),stdin) == nullptr )
{
return;
}
c=tolower(buf[0]);
if(c=='\n')
goto recommand;
+6 -1
View File
@@ -145,6 +145,11 @@ static void GetValueR(FILE *fp, char *str, void *v, int c)
{
if(!c) // String, allocate some memory.
{
// Windows enforces a 32767 character limit for text boxes by default
// If a string exceeds this length, it's probably a corrupt file
if (s > 32768)
goto gogl;
if(!(*(char **)v=(char*)malloc(s)))
goto gogl;
@@ -208,7 +213,7 @@ void SaveParse(const CFGSTRUCT *cfgst, FILE *fp)
if(*(char **)cfgst[x].ptr)
{
// Only save it if there IS a string.
unsigned int len = strlen(*(char **)cfgst[x].ptr);
size_t len = strlen(*(char **)cfgst[x].ptr);
SetValueR(fp,cfgst[x].name,*(char **)cfgst[x].ptr, len + 1);
}
}
+7 -7
View File
@@ -641,7 +641,7 @@ Config::_load()
int
Config::_loadFile(const char* fname)
{
signed int pos, eqPos;
size_t pos=0, eqPos=0;
std::fstream config;
std::map<std::string, int>::iterator int_i;
std::map<std::string, double>::iterator dbl_i;
@@ -656,7 +656,7 @@ Config::_loadFile(const char* fname)
configFile = fname;
}
std::string line, name, value;
char buf[1024];
char buf[4096];
// set the exception handling to catch i/o errors
config.exceptions(std::fstream::badbit);
@@ -671,7 +671,7 @@ Config::_loadFile(const char* fname)
while(!config.eof()) {
// read a line
config.getline(buf, 1024);
config.getline(buf, sizeof(buf));
line = buf;
// check line validity
@@ -723,7 +723,7 @@ Config::save()
std::map<std::string, double>::iterator dbl_i;
std::map<std::string, std::string>::iterator str_i;
std::string configFile = _dir + "/" + cfgFile;
char buf[1024];
char buf[4096];
// set the exception handling to catch i/o errors
config.exceptions(std::ios::failbit | std::ios::badbit);
@@ -741,19 +741,19 @@ Config::save()
// write each configuration setting
for(int_i = _intOptMap.begin(); int_i != _intOptMap.end(); int_i++)
{
snprintf(buf, 1024, "%s = %d\n",
snprintf(buf, sizeof(buf), "%s = %d\n",
int_i->first.c_str(), int_i->second);
config.write(buf, strlen(buf));
}
for(dbl_i = _dblOptMap.begin(); dbl_i != _dblOptMap.end(); dbl_i++)
{
snprintf(buf, 1024, "%s = %f\n",
snprintf(buf, sizeof(buf), "%s = %f\n",
dbl_i->first.c_str(), dbl_i->second);
config.write(buf, strlen(buf));
}
for(str_i = _strOptMap.begin(); str_i != _strOptMap.end(); str_i++)
{
snprintf(buf, 1024, "%s = %s\n",
snprintf(buf, sizeof(buf), "%s = %s\n",
str_i->first.c_str(), str_i->second.c_str());
config.write(buf, strlen(buf));
}
+11 -11
View File
@@ -238,18 +238,18 @@ void KillBlitToHigh(void)
{
if(palettetranslate)
{
free(palettetranslate);
FCEU_free(palettetranslate);
palettetranslate=NULL;
}
if(specbuf8bpp)
{
free(specbuf8bpp);
FCEU_free(specbuf8bpp);
specbuf8bpp = NULL;
}
if(specbuf32bpp)
{
free(specbuf32bpp);
FCEU_free(specbuf32bpp);
specbuf32bpp = NULL;
}
if(specbuf)
@@ -259,11 +259,11 @@ void KillBlitToHigh(void)
hq3x_Kill();
else
hq2x_Kill();
free(specbuf);
FCEU_free(specbuf);
specbuf=NULL;
}
if (nes_ntsc) {
free(nes_ntsc);
FCEU_free(nes_ntsc);
nes_ntsc = NULL;
}
if (ntscblit) {
@@ -466,7 +466,7 @@ void Blit8To8(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, in
/* Todo: Make sure 24bpp code works right with big-endian cpus */
//takes a pointer to XBuf and applies fully modern deemph palettizing
template<int SCALE> static u32 _ModernDeemphColorMap(u8* src, u8* srcbuf)
template<int SCALE> static u32 _ModernDeemphColorMap(const u8* src, const u8* srcbuf)
{
u8 pixel = *src;
@@ -492,7 +492,7 @@ template<int SCALE> static u32 _ModernDeemphColorMap(u8* src, u8* srcbuf)
return color;
}
u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int scale)
u32 ModernDeemphColorMap(const u8* src, const u8* srcbuf, int scale)
{
if(scale == 1) return _ModernDeemphColorMap<1>(src,srcbuf);
else if(scale == 2) return _ModernDeemphColorMap<2>(src,srcbuf);
@@ -503,14 +503,14 @@ u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int scale)
else if(scale == 7) return _ModernDeemphColorMap<7>(src,srcbuf);
else if(scale == 8) return _ModernDeemphColorMap<8>(src,srcbuf);
else if(scale == 9) return _ModernDeemphColorMap<9>(src,srcbuf);
else { abort(); return 0; }
else { FCEU_abort("unhandled ModernDeemphColorMap scale"); return 0; }
}
typedef u32 (*ModernDeemphColorMapFuncPtr)( u8*, u8* );
typedef u32 (*ModernDeemphColorMapFuncPtr)( const u8*, const u8* );
static ModernDeemphColorMapFuncPtr getModernDeemphColorMapFunc(int scale)
{
ModernDeemphColorMapFuncPtr ptr = NULL;
ModernDeemphColorMapFuncPtr ptr;
if(scale == 1) ptr = &_ModernDeemphColorMap<1>;
else if(scale == 2) ptr = &_ModernDeemphColorMap<2>;
@@ -521,7 +521,7 @@ static ModernDeemphColorMapFuncPtr getModernDeemphColorMapFunc(int scale)
else if(scale == 7) ptr = &_ModernDeemphColorMap<7>;
else if(scale == 8) ptr = &_ModernDeemphColorMap<8>;
else if(scale == 9) ptr = &_ModernDeemphColorMap<9>;
else { abort(); ptr = NULL; }
else { FCEU_abort("unhandled ModernDeemphColorMap scale"); ptr = nullptr; }
return ptr;
}
+1 -1
View File
@@ -29,4 +29,4 @@ void Blit32to16(uint32 *src, uint16 *dest, int xr, int yr, int dpitch,
int shiftr[3], int shiftl[3]);
u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int scale);
u32 ModernDeemphColorMap(const u8* src, const u8* srcbuf, int scale);
+13 -9
View File
@@ -23,21 +23,22 @@ THE SOFTWARE.
#include "emufile.h"
#include "utils/xstring.h"
#include <stdio.h>
#include <vector>
bool EMUFILE::readAllBytes(std::vector<u8>* dstbuf, const std::string& fname)
{
EMUFILE_FILE file(fname.c_str(),"rb");
if(file.fail()) return false;
int size = file.size();
size_t size = file.size();
dstbuf->resize(size);
file.fread(&dstbuf->at(0),size);
return true;
}
size_t EMUFILE_MEMORY::_fread(const void *ptr, size_t bytes){
u32 remain = len-pos;
u32 todo = std::min<u32>(remain,(u32)bytes);
size_t remain = len-pos;
size_t todo = std::min<size_t>(remain,bytes);
if(len==0)
{
failbit = true;
@@ -78,13 +79,16 @@ void EMUFILE_FILE::open(const char* fname, const char* mode)
}
void EMUFILE_FILE::truncate(s32 length)
void EMUFILE_FILE::truncate(size_t length)
{
::fflush(fp);
#ifdef _MSC_VER
_chsize(_fileno(fp),length);
#else
ftruncate(fileno(fp),length);
if ( ftruncate(fileno(fp),length) != 0 )
{
printf("Warning: EMUFILE_FILE::truncate failed\n");
}
#endif
// this is probably wrong if mode is "wb"
fclose(fp);
@@ -187,7 +191,7 @@ size_t EMUFILE::read32le(u32* Bufo)
u32 EMUFILE::read32le()
{
u32 ret;
u32 ret=0;
read32le(&ret);
return ret;
}
@@ -226,7 +230,7 @@ size_t EMUFILE::read16le(u16* Bufo)
u16 EMUFILE::read16le()
{
u16 ret;
u16 ret=0;
read16le(&ret);
return ret;
}
@@ -265,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;
+33 -32
View File
@@ -59,7 +59,7 @@ public:
bool fail(bool unset=false) { bool ret = failbit; if(unset) unfail(); return ret; }
void unfail() { failbit=false; }
bool eof() { return size()==ftell(); }
bool eof() { return size() == static_cast<size_t>(ftell()); }
size_t fread(const void *ptr, size_t bytes){
return _fread(ptr,bytes);
@@ -109,13 +109,13 @@ public:
double readdouble();
size_t readdouble(double* val);
virtual int fseek(int offset, int origin) = 0;
virtual int fseek(long int offset, int origin) = 0;
virtual int ftell() = 0;
virtual int size() = 0;
virtual long int ftell() = 0;
virtual size_t size() = 0;
virtual void fflush() = 0;
virtual void truncate(s32 length) = 0;
virtual void truncate(size_t length) = 0;
};
//todo - handle read-only specially?
@@ -123,9 +123,10 @@ class EMUFILE_MEMORY : public EMUFILE {
protected:
std::vector<u8> *vec;
bool ownvec;
s32 pos, len;
long int pos;
size_t len;
void reserve(u32 amt) {
void reserve(size_t amt) {
if(vec->size() < amt)
vec->resize(amt);
}
@@ -133,12 +134,12 @@ protected:
public:
EMUFILE_MEMORY(std::vector<u8> *underlying) : vec(underlying), ownvec(false), pos(0), len((s32)underlying->size()) { }
EMUFILE_MEMORY(u32 preallocate) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) {
EMUFILE_MEMORY(size_t preallocate) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) {
vec->resize(preallocate);
len = preallocate;
}
EMUFILE_MEMORY() : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) { vec->reserve(1024); }
EMUFILE_MEMORY(void* buf, s32 size) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(size) {
EMUFILE_MEMORY(void* buf, size_t size) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(size) {
vec->resize(size);
if(size != 0)
memcpy(&vec->front(),buf,size);
@@ -150,11 +151,11 @@ public:
virtual EMUFILE* memwrap();
virtual void truncate(s32 length)
virtual void truncate(size_t length)
{
vec->resize(length);
len = length;
if(pos>length) pos=length;
if (static_cast<size_t>(pos) > length) pos=static_cast<long int>(length);
}
u8* buf() {
@@ -178,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;
};
@@ -192,7 +193,7 @@ public:
//if(_fread(&temp,1) != 1)
// return EOF;
//else return temp;
u32 remain = len-pos;
size_t remain = len-pos;
if(remain<1) {
failbit = true;
return -1;
@@ -216,13 +217,13 @@ public:
//they handle the return values correctly
virtual void fwrite(const void *ptr, size_t bytes){
reserve(pos+(s32)bytes);
reserve(pos+bytes);
memcpy(buf()+pos,ptr,bytes);
pos += (s32)bytes;
len = std::max<int>(pos,len);
pos += static_cast<long>(bytes);
len = std::max<size_t>(pos,len);
}
virtual int fseek(int offset, int origin){
virtual int fseek(long int offset, int origin){
//work differently for read-only...?
switch(origin) {
case SEEK_SET:
@@ -232,7 +233,7 @@ public:
pos += offset;
break;
case SEEK_END:
pos = size()+offset;
pos = (long int)(size()+offset);
break;
default:
assert(false);
@@ -241,24 +242,24 @@ public:
return 0;
}
virtual int ftell() {
virtual long int ftell() {
return pos;
}
virtual void fflush() {}
void set_len(s32 length)
void set_len(size_t length)
{
len = length;
if(pos > length)
pos = length;
if (static_cast<size_t>(pos) > length)
pos = static_cast<long>(length);
}
void trim()
{
vec->resize(len);
}
virtual int size() { return (int)len; }
virtual size_t size() { return len; }
};
class EMUFILE_FILE : public EMUFILE {
@@ -288,7 +289,7 @@ public:
bool is_open() { return fp != NULL; }
virtual void truncate(s32 length);
virtual void truncate(size_t length);
virtual int fprintf(const char *format, ...) {
va_list argptr;
@@ -321,20 +322,20 @@ public:
failbit = true;
}
virtual int fseek(int offset, int origin) {
virtual int fseek(long int offset, int origin) {
return ::fseek(fp, offset, origin);
}
virtual int ftell() {
return (u32)::ftell(fp);
virtual long int ftell() {
return ::ftell(fp);
}
virtual int size() {
int oldpos = ftell();
virtual size_t size() {
long int oldpos = ftell();
fseek(0,SEEK_END);
int len = ftell();
long int len = ftell();
fseek(oldpos,SEEK_SET);
return len;
return static_cast<size_t>(len);
}
virtual void fflush() {
+87 -23
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()
@@ -181,7 +183,6 @@ static void FCEU_CloseGame(void)
}
#ifdef __WIN_DRIVER__
extern char LoadedRomFName[2048];
if (storePreferences(mass_replace(LoadedRomFName, "|", ".").c_str()))
FCEUD_PrintError("Couldn't store debugging data");
CDLoggerROMClosed();
@@ -209,6 +210,8 @@ static void FCEU_CloseGame(void)
GameInterface(GI_CLOSE);
FCEU_StateRecorderStop();
FCEUI_StopMovie();
ResetExState(0, 0);
@@ -226,10 +229,10 @@ static void FCEU_CloseGame(void)
currFrameCounter = 0;
//Reset flags for Undo/Redo/Auto Savestating //adelikat: TODO: maybe this stuff would be cleaner as a struct or class
lastSavestateMade[0] = 0;
lastSavestateMade.clear();
undoSS = false;
redoSS = false;
lastLoadstateMade[0] = 0;
lastLoadstateMade.clear();
undoLS = false;
redoLS = false;
AutoSS = false;
@@ -421,7 +424,7 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
//----------
//attempt to open the files
FCEUFILE *fp;
char fullname[2048]; // this name contains both archive name and ROM file name
std::string fullname; // this name contains both archive name and ROM file name
int lastpal = PAL;
int lastdendy = dendy;
@@ -431,7 +434,7 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
// currently there's only one situation:
// the user clicked cancel form the open from archive dialog
int userCancel = 0;
fp = FCEU_fopen(name, 0, "rb", 0, -1, romextensions, &userCancel);
fp = FCEU_fopen(name, LoadedRomFNamePatchToUse[0] ? LoadedRomFNamePatchToUse : nullptr, "rb", 0, -1, romextensions, &userCancel);
if (!fp)
{
@@ -443,16 +446,19 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
}
else if (fp->archiveFilename != "")
{
strcpy(fullname, fp->archiveFilename.c_str());
strcat(fullname, "|");
strcat(fullname, fp->filename.c_str());
} else
strcpy(fullname, name);
fullname.assign(fp->archiveFilename.c_str());
fullname.append("|");
fullname.append(fp->filename.c_str());
}
else
{
fullname.assign(name);
}
// reset loaded game BEFORE it's loading.
ResetGameLoaded();
//file opened ok. start loading.
FCEU_printf("Loading %s...\n\n", fullname);
FCEU_printf("Loading %s...\n\n", fullname.c_str());
GetFileBase(fp->filename.c_str());
//reset parameters so they're cleared just in case a format's loader doesn't know to do the clearing
MasterRomInfoParams = TMasterRomInfoParams();
@@ -484,16 +490,16 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
bool FCEUXLoad(const char *name, FCEUFILE * fp);
int load_result;
load_result = iNESLoad(fullname, fp, OverwriteVidMode);
load_result = iNESLoad(fullname.c_str(), fp, OverwriteVidMode);
if (load_result == LOADER_INVALID_FORMAT)
{
load_result = NSFLoad(fullname, fp);
load_result = NSFLoad(fullname.c_str(), fp);
if (load_result == LOADER_INVALID_FORMAT)
{
load_result = UNIFLoad(fullname, fp);
load_result = UNIFLoad(fullname.c_str(), fp);
if (load_result == LOADER_INVALID_FORMAT)
{
load_result = FDSLoad(fullname, fp);
load_result = FDSLoad(fullname.c_str(), fp);
}
}
}
@@ -502,7 +508,6 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
#ifdef __WIN_DRIVER__
// ################################## Start of SP CODE ###########################
extern char LoadedRomFName[2048];
extern int loadDebugDataFailed;
if ((loadDebugDataFailed = loadPreferences(mass_replace(LoadedRomFName, "|", ".").c_str())))
@@ -591,6 +596,12 @@ FCEUGI *FCEUI_LoadGameVirtual(const char *name, int OverwriteVidMode, bool silen
}
FCEU_fclose(fp);
if ( FCEU_StateRecorderIsEnabled() )
{
FCEU_StateRecorderStart();
}
return GameInfo;
}
@@ -724,8 +735,10 @@ 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
int r, ssize;
FCEU_MAYBE_UNUSED int r;
int ssize;
JustFrameAdvanced = false;
@@ -742,7 +755,7 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
{
EmulationPaused = EMULATIONPAUSED_FA;
}
if (frameAdvance_Delay_count < frameAdvanceDelayScaled)
if ( static_cast<unsigned int>(frameAdvance_Delay_count) < frameAdvanceDelayScaled)
{
frameAdvance_Delay_count++;
}
@@ -754,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
@@ -777,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);
@@ -791,6 +820,7 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
AutoFire();
UpdateAutosave();
FCEU_StateRecorderUpdate();
#ifdef _S9XLUA_H
FCEU_LuaFrameBoundary();
@@ -808,6 +838,9 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
if (skip != 2) ssize = FlushEmulateSound(); //If skip = 2 we are skipping sound processing
//flush tracer once a frame, since we're likely to end up back at a user interaction loop after this with emulation paused
FCEUD_FlushTrace();
#ifdef _S9XLUA_H
CallRegisteredLuaFunctions(LUACALL_AFTEREMULATION);
#endif
@@ -1061,7 +1094,7 @@ void FCEU_ResetVidSys(void) {
FCEUS FSettings;
void FCEU_printf(const char *format, ...)
void FCEU_printf( __FCEU_PRINTF_FORMAT const char *format, ...)
{
char temp[2048];
@@ -1081,7 +1114,7 @@ void FCEU_printf(const char *format, ...)
va_end(ap);
}
void FCEU_PrintError(const char *format, ...)
void FCEU_PrintError( __FCEU_PRINTF_FORMAT const char *format, ...)
{
char temp[2048];
@@ -1228,12 +1261,16 @@ void FCEUI_ClearEmulationFrameStepped()
//ideally maybe we shouldnt be using this, but i need it for quick merging
void FCEUI_SetEmulationPaused(int val) {
EmulationPaused = val;
if(EmulationPaused)
FCEUD_FlushTrace();
}
void FCEUI_ToggleEmulationPause(void)
{
EmulationPaused = (EmulationPaused & EMULATIONPAUSED_PAUSED) ^ EMULATIONPAUSED_PAUSED;
DebuggerWasUpdated = false;
if(EmulationPaused)
FCEUD_FlushTrace();
}
void FCEUI_FrameAdvanceEnd(void) {
@@ -1241,8 +1278,35 @@ void FCEUI_FrameAdvanceEnd(void) {
}
void FCEUI_FrameAdvance(void) {
frameAdvanceRequested = true;
frameAdvance_Delay_count = 0;
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;
@@ -1259,7 +1323,7 @@ void UpdateAutosave(void) {
FCEUSS_Save(f, false);
AutoSS = true; //Flag that an auto-savestate was made
free(f);
f = NULL;
f = NULL;
AutosaveStatus[AutosaveIndex] = 1;
}
}
+8 -6
View File
@@ -139,10 +139,10 @@ extern FCEUS FSettings;
bool CheckFileExists(const char* filename); //Receives a filename (fullpath) and checks to see if that file exists
void FCEU_PrintError(const char *format, ...);
void FCEU_printf(const char *format, ...);
void FCEU_DispMessage(const char *format, int disppos, ...);
void FCEU_DispMessageOnMovie(const char *format, ...);
void FCEU_PrintError( __FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 2 );
void FCEU_printf( __FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 2 );
void FCEU_DispMessage( __FCEU_PRINTF_FORMAT const char *format, int disppos, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 3 );
void FCEU_DispMessageOnMovie( __FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 2 );
void FCEU_TogglePPU();
void SetNESDeemph_OldHacky(uint8 d, int force);
@@ -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
};
+28 -10
View File
@@ -29,6 +29,7 @@
#include "state.h"
#include "file.h"
#include "cart.h"
#include "ines.h"
#include "netplay.h"
#include "driver.h"
#include "movie.h"
@@ -223,14 +224,23 @@ void FCEU_FDSSelect(void)
FCEU_DispMessage("Disk %d Side %c Selected", 0, SelectDisk >> 1, (SelectDisk & 1) ? 'B' : 'A');
}
#define IRQ_Repeat (IRQa & 0x01)
#define IRQ_Enabled (IRQa & 0x02)
#define IRQ_Repeat 0x01
#define IRQ_Enabled 0x02
static void FDSFix(int a) {
if ((IRQa & IRQ_Enabled) && IRQCount) {
if (IRQa & IRQ_Enabled) {
IRQCount -= a;
if (IRQCount <= 0) {
IRQCount = IRQLatch;
/* Puff Puff Golf notes:
Game freezes while music playing ingame after inserting Disk Side B.
IRQ is usually fired at scanline 169 and 183 for music to work.
At some point after inserting disk B, an IRQ is fired at scanline 174 which
will just freeze game while music plays.
If you ignore triggering IRQ altogether, game plays but no music
*/
X6502_IRQBegin(FCEU_IQEXT);
if (!(IRQa & IRQ_Repeat)) {
IRQa &= ~IRQ_Enabled;
@@ -574,21 +584,30 @@ void FDSSoundReset(void) {
static DECLFW(FDSWrite) {
switch (A) {
case 0x4020:
X6502_IRQEnd(FCEU_IQEXT);
IRQLatch &= 0xFF00;
IRQLatch |= V;
break;
case 0x4021:
X6502_IRQEnd(FCEU_IQEXT);
IRQLatch &= 0xFF;
IRQLatch |= V << 8;
break;
case 0x4022:
X6502_IRQEnd(FCEU_IQEXT);
IRQCount = IRQLatch;
IRQa = V & 3;
if (FDSRegs[3] & 1) {
IRQa = V & 0x03;
if (IRQa & IRQ_Enabled) {
IRQCount = IRQLatch;
} else {
X6502_IRQEnd(FCEU_IQEXT);
}
}
break;
case 0x4023:
if (!(V & 0x01)) {
IRQa &= ~IRQ_Enabled;
X6502_IRQEnd(FCEU_IQEXT);
X6502_IRQEnd(FCEU_IQEXT2);
}
break;
case 0x4023: break;
case 0x4024:
if (mapperFDS_diskinsert && ~mapperFDS_control & 0x04) {
@@ -834,7 +853,6 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
free(fn);
}
extern char LoadedRomFName[2048];
strcpy(LoadedRomFName, name); //For the debugger list
GameInfo->type = GIT_FDS;
+17 -26
View File
@@ -69,7 +69,7 @@ void ApplyIPS(FILE *ips, FCEUFILE* fp)
if(!ips) return;
char* buf = (char*)FCEU_dmalloc(fp->size);
char* buf = (char*)FCEU_malloc(fp->size);
memcpy(buf,fp->EnsureMemorystream()->buf(),fp->size);
@@ -108,13 +108,7 @@ void ApplyIPS(FILE *ips, FCEUFILE* fp)
if((offset+size)>(uint32)fp->size)
{
// Probably a little slow.
char *newbuf=(char *)realloc(buf,offset+size);
if(!newbuf)
{
free(buf); buf=NULL;
FCEU_printf(" Oops. IPS patch %d(type RLE) goes beyond end of file. Could not allocate memory.\n",count);
goto end;
}
char *newbuf=(char *)FCEU_realloc(buf,offset+size);
buf=newbuf;
memset(buf+fp->size,0,offset+size-fp->size);
fp->size=offset+size;
@@ -133,17 +127,15 @@ void ApplyIPS(FILE *ips, FCEUFILE* fp)
if((offset+size)>(uint32)fp->size)
{
// Probably a little slow.
char *newbuf=(char *)realloc(buf,offset+size);
if(!newbuf)
{
free(buf); buf=NULL;
FCEU_printf(" Oops. IPS patch %d(type normal) goes beyond end of file. Could not allocate memory.\n",count);
goto end;
}
char *newbuf=(char *)FCEU_realloc(buf,offset+size);
buf=newbuf;
memset(buf+fp->size,0,offset+size-fp->size);
fp->size=offset+size;
}
if ( fread(buf+offset,1,size,ips) != static_cast<size_t>(size) )
{
FCEU_printf(" Warn IPS data read came up short!\n");
}
fread(buf+offset,1,size,ips);
}
count++;
}
@@ -326,9 +318,9 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, const char *mode, cha
{
uint32 magic;
magic = fp->fgetc();
magic|=fp->fgetc()<<8;
magic|=fp->fgetc()<<16;
magic = (fp->fgetc() & 0x00ff);
magic|= (fp->fgetc() & 0x00ff) << 8;
magic|= (fp->fgetc() & 0x00ff) << 16;
fp->fseek(0,SEEK_SET);
if(magic==0x088b1f) {
@@ -338,7 +330,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, const char *mode, cha
if(gzfile) {
delete fp;
int size;
size_t size;
for(size=0; gzgetc(gzfile) != EOF; size++) {}
EMUFILE_MEMORY* ms = new EMUFILE_MEMORY(size);
gzseek(gzfile,0,SEEK_SET);
@@ -457,13 +449,12 @@ int FCEU_fisarchive(FCEUFILE *fp)
std::string GetMfn() //Retrieves the movie filename from curMovieFilename (for adding to savestate and auto-save files)
{
std::string movieFilenamePart;
extern char curMovieFilename[512];
if(*curMovieFilename)
{
if (!curMovieFilename.empty())
{
char drv[PATH_MAX], dir[PATH_MAX], name[PATH_MAX], ext[PATH_MAX];
splitpath(curMovieFilename,drv,dir,name,ext);
splitpath(curMovieFilename.c_str(),drv,dir,name,ext);
movieFilenamePart = std::string(".") + name;
}
}
return movieFilenamePart;
}
@@ -495,7 +486,7 @@ void FCEUI_SetDirOverride(int which, char *n)
va_list ap;
int ret;
if(!(*strp=(char*)FCEU_dmalloc(2048))) //mbg merge 7/17/06 cast to char*
if(!(*strp=(char*)FCEU_malloc(2048))) //mbg merge 7/17/06 cast to char*
return(0);
va_start(ap,fmt);
ret=vsnprintf(*strp,2048,fmt,ap);
+1 -1
View File
@@ -35,7 +35,7 @@ struct FCEUFILE {
int archiveIndex;
//the size of the file
int size;
size_t size;
//whether the file is contained in an archive
bool isArchive() { return archiveCount > 0; }
+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
+28 -1
View File
@@ -16,12 +16,34 @@ enum EGIV
GIV_USER = 2, //What was set by FCEUI_SetVidSys().
};
enum EGIPPU
{
GIPPU_USER = 0,
GIPPU_RP2C04_0001 = 1,
GIPPU_RP2C04_0002 = 2,
GIPPU_RP2C04_0003 = 3,
GIPPU_RP2C04_0004 = 4,
GIPPU_RC2C03B = 5,
GIPPU_RC2C05_01 = 6,
GIPPU_RC2C05_02 = 7,
GIPPU_RC2C05_03 = 8,
GIPPU_RC2C05_04 = 9,
};
enum EGIVS
{
EGIVS_NORMAL = 0,
EGIVS_RBI = 1, // RBI Baseball protection
EGIVS_TKO = 2, // TKO Boxing protection
EGIVS_XEVIOUS = 3, // Super Xevious protection
};
enum ESIS
{
SIS_NONE = 0,
SIS_DATACH = 1,
SIS_NWC = 2,
SIS_VSUNISYSTEM = 3,
SIS_VSUNISYSTEM = 3, // Is it used?
SIS_NSF = 4,
};
@@ -44,6 +66,8 @@ enum ESI
SI_COUNT = SI_LCDCOMP_ZAPPER
};
inline const char* ESI_Name(ESI esi)
{
static const char * const names[] =
@@ -137,6 +161,9 @@ struct FCEUGI
ESI input[2]; //Desired input for emulated input ports 1 and 2; -1 for unknown desired input.
ESIFC inputfc; //Desired Famicom expansion port device. -1 for unknown desired input.
ESIS cspecial; //Special cart expansion: DIP switches, barcode reader, etc.
EGIPPU vs_ppu; //PPU type for Vs. System
EGIVS vs_type; //Vs. System type
uint8 vs_cswitch; // Switch first and second controllers for Vs. System
MD5DATA MD5;
+157 -44
View File
@@ -37,6 +37,7 @@
#include "cheat.h"
#include "vsuni.h"
#include "driver.h"
#include "input.h"
#include <cstdio>
#include <cstdlib>
@@ -54,9 +55,11 @@ iNES_HEADER head;
static CartInfo iNESCart;
uint8 Mirroring = 0;
uint8 MirroringAs2bits = 0;
uint32 ROM_size = 0;
uint32 VROM_size = 0;
char LoadedRomFName[2048]; //mbg merge 7/17/06 added
char LoadedRomFName[4096]; //mbg merge 7/17/06 added
char LoadedRomFNamePatchToUse[4096];
static int CHRRAMSize = -1;
static int iNES_Init(int num);
@@ -107,11 +110,11 @@ void iNESGI(GI h) { //bbit edited: removed static keyword
if (iNESCart.Close)
iNESCart.Close();
if (ROM) {
free(ROM);
FCEU_free(ROM);
ROM = NULL;
}
if (VROM) {
free(VROM);
FCEU_free(VROM);
VROM = NULL;
}
if (trainerpoo) {
@@ -141,6 +144,9 @@ struct INPSEL {
ESIFC inputfc;
};
/*
* Function to set input controllers based on CRC
*/
static void SetInput(void) {
static struct INPSEL moo[] =
{
@@ -153,9 +159,9 @@ static void SetInput(void) {
{0x48ca0ee1, SI_GAMEPAD, SI_GAMEPAD, SIFC_BWORLD }, // Barcode World
{0x4318a2f8, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Barker Bill's Trick Shooting
{0x6cca1c1f, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Dai Undoukai
{0x24598791, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Duck Hunt
{0x24598791, SI_GAMEPAD, SI_ZAPPER, SIFC_NONE }, // Duck Hunt
{0xd5d6eac4, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Edu (As)
{0xe9a7fe9e, SI_UNSET, SI_MOUSE, SIFC_NONE }, // Educational Computer 2000
{0xe9a7fe9e, SI_UNSET, SI_MOUSE, SIFC_SUBORKB }, // Educational Computer 2000
{0x8f7b1669, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // FP BASIC 3.3 by maxzhou88
{0xf7606810, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC 2.0A
{0x895037bc, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC 2.1a
@@ -215,6 +221,7 @@ static void SetInput(void) {
{0x67b126b9, SI_GAMEPAD, SI_GAMEPAD, SIFC_FAMINETSYS }, // Famicom Network System
{0x00000000, SI_UNSET, SI_UNSET, SIFC_UNSET }
};
int x = 0;
while (moo[x].input1 >= 0 || moo[x].input2 >= 0 || moo[x].inputfc >= 0) {
@@ -228,6 +235,64 @@ static void SetInput(void) {
}
}
struct INPSEL_NES20 {
uint8 expansion_id;
ESI input1;
ESI input2;
ESIFC inputfc;
};
/*
* Function to set input controllers based on NES 2.0 header
*/
extern int eoptions;
static void SetInputNes20(uint8 expansion) {
static struct INPSEL_NES20 moo[] =
{
{0x01, SI_GAMEPAD, SI_GAMEPAD, SIFC_UNSET }, // Standard NES/Famicom controllers
{0x02, SI_GAMEPAD, SI_GAMEPAD, SIFC_NONE }, // NES Four Score/Satellite with two additional standard controllers
{0x03, SI_GAMEPAD, SI_GAMEPAD, SIFC_4PLAYER }, // Famicom Four Players Adapter with two additional standard controllers using the "simple" protocol
{0x04, SI_GAMEPAD, SI_GAMEPAD, SIFC_NONE }, // Vs. System (1P via $4016)
{0x05, SI_GAMEPAD, SI_GAMEPAD, SIFC_NONE }, // Vs. System (1P via $4017)
{0x07, SI_ZAPPER, SI_NONE, SIFC_NONE }, // Vs. Zapper
{0x08, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Zapper ($4017)
{0x0A, SI_UNSET, SI_UNSET, SIFC_SHADOW }, // Bandai Hyper Shot Lightgun
{0x0B, SI_UNSET, SI_POWERPADA, SIFC_UNSET }, // Power Pad Side A
{0x0C, SI_UNSET, SI_POWERPADB, SIFC_UNSET }, // Power Pad Side B
{0x0D, SI_UNSET, SI_UNSET, SIFC_FTRAINERA }, // Family Trainer Side A
{0x0E, SI_UNSET, SI_UNSET, SIFC_FTRAINERB }, // Family Trainer Side B
{0x0F, SI_UNSET, SI_ARKANOID, SIFC_UNSET }, // Arkanoid Vaus Controller (NES)
{0x10, SI_UNSET, SI_UNSET, SIFC_ARKANOID }, // Arkanoid Vaus Controller (Famicom)
{0x12, SI_UNSET, SI_UNSET, SIFC_HYPERSHOT }, // Konami Hyper Shot Controller
{0x15, SI_UNSET, SI_UNSET, SIFC_MAHJONG }, // Jissen Mahjong Controller
{0x17, SI_UNSET, SI_UNSET, SIFC_OEKAKIDS }, // Oeka Kids Tablet
{0x18, SI_UNSET, SI_UNSET, SIFC_BWORLD }, // Sunsoft Barcode Battler
{0x1B, SI_UNSET, SI_UNSET, SIFC_TOPRIDER }, // Top Rider (Inflatable Bicycle)
{0x23, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC Keyboard plus Famicom Data Recorder
{0x24, SI_UNSET, SI_UNSET, SIFC_PEC586KB }, // Dongda PEC-586 Keyboard
{0x26, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Subor Keyboard
//{0x27, SI_UNSET, SI_MOUSE, SIFC_SUBORKB }, // Subor Keyboard plus mouse (3x8-bit protocol)
{0x28, SI_UNSET, SI_MOUSE, SIFC_SUBORKB }, // Subor Keyboard plus mouse (24-bit protocol)
{0x29, SI_UNSET, SI_SNES_MOUSE, SIFC_UNSET }, // SNES Mouse
{0, SI_UNSET, SI_UNSET, SIFC_UNSET }
};
int x = 0;
if (expansion == 0x02)
eoptions |= 32768; // dirty hack to enable Four-Score
GameInfo->vs_cswitch = expansion == 0x05;
while (moo[x].expansion_id) {
if (moo[x].expansion_id == expansion) {
GameInfo->input[0] = moo[x].input1;
GameInfo->input[1] = moo[x].input2;
GameInfo->inputfc = moo[x].inputfc;
break; }
x++;
}
}
#define INESB_INCOMPLETE 1
#define INESB_CORRUPT 2
#define INESB_HACKED 4
@@ -276,7 +341,7 @@ static const TMasterRomInfo sMasterRomInfo[] = {
const TMasterRomInfo* MasterRomInfo;
TMasterRomInfoParams MasterRomInfoParams;
static void CheckHInfo(void) {
static void CheckHInfo(uint64 partialmd5) {
/* ROM images that have the battery-backed bit set in the header that really
don't have battery-backed RAM is not that big of a problem, so I'll
treat this differently by only listing games that should have battery-backed RAM.
@@ -327,14 +392,9 @@ static void CheckHInfo(void) {
#include "ines-correct.h"
};
int32 tofix = 0, x, mask;
uint64 partialmd5 = 0;
for (x = 0; x < 8; x++)
partialmd5 |= (uint64)iNESCart.MD5[15 - x] << (x * 8);
CheckBad(partialmd5);
MasterRomInfo = NULL;
for (int i = 0; i < ARRAY_SIZE(sMasterRomInfo); i++) {
for (size_t i = 0; i < ARRAY_SIZE(sMasterRomInfo); i++) {
const TMasterRomInfo& info = sMasterRomInfo[i];
if (info.md5lower != partialmd5)
continue;
@@ -343,7 +403,7 @@ static void CheckHInfo(void) {
if (!info.params) break;
std::vector<std::string> toks = tokenize_str(info.params, ",");
for (int j = 0; j < (int)toks.size(); j++) {
for (size_t j = 0; j < toks.size(); j++) {
std::vector<std::string> parts = tokenize_str(toks[j], "=");
MasterRomInfoParams[parts[0]] = parts[1];
}
@@ -629,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},
@@ -660,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},
@@ -673,7 +733,7 @@ BMAPPINGLocal bmap[] = {
{"", 215, UNL8237_Init},
{"", 216, Mapper216_Init},
{"", 217, Mapper217_Init}, // Redefined to a new Discrete BMC mapper
// {"", 218, Mapper218_Init},
{"", 218, Mapper218_Init},
{"UNLA9746", 219, UNLA9746_Init},
{"Debug Mapper", 220, QTAi_Init},
{"UNLN625092", 221, UNLN625092_Init},
@@ -710,7 +770,7 @@ BMAPPINGLocal bmap[] = {
{"SAN GUO ZHI PIRATE", 252, Mapper252_Init},
{"DRAGON BALL PIRATE", 253, Mapper253_Init},
{"", 254, Mapper254_Init},
// {"", 255, Mapper255_Init}, // No good dumps for this mapper
{"", 255, Mapper255_Init}, // dupe of 225
//-------- Mappers 256-511 is the Supplementary Multilingual Plane ----------
//-------- Mappers 512-767 is the Supplementary Ideographic Plane -----------
@@ -727,9 +787,14 @@ BMAPPINGLocal bmap[] = {
{"F-15 MMC3 Based", 259, BMCF15_Init},
{"HP10xx/H20xx Boards", 260, BMCHPxx_Init},
{"810544-CA-1", 261, BMC810544CA1_Init},
{"SMD132/SMD133", 268, SMD132_SMD133_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 },
{"Impact Soft MMC3 Flash Board", 406, Mapper406_Init },
{"INX_007T_V01", 470, INX_007T_Init },
{"KONAMI QTAi Board", 547, QTAi_Init },
@@ -737,14 +802,17 @@ BMAPPINGLocal bmap[] = {
};
int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
int result;
struct md5_context md5;
uint64 partialmd5 = 0;
const char* mappername = "Not Listed";
if (FCEU_fread(&head, 1, 16, fp) != 16 || memcmp(&head, "NES\x1A", 4))
return LOADER_INVALID_FORMAT;
head.cleanup();
memset(&iNESCart, 0, sizeof(iNESCart));
iNESCart.clear();
iNES2 = ((head.ROM_type2 & 0x0C) == 0x08);
if(iNES2)
@@ -766,6 +834,9 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
} else
Mirroring = (head.ROM_type & 1);
MirroringAs2bits = head.ROM_type & 1;
if (head.ROM_type & 8) MirroringAs2bits |= 2;
int not_round_size;
if (!iNES2) {
not_round_size = head.ROM_size;
@@ -809,20 +880,64 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
}
}
if ((ROM = (uint8*)FCEU_malloc(ROM_size << 14)) == NULL)
return 0;
ROM = (uint8*)FCEU_malloc(ROM_size << 14);
memset(ROM, 0xFF, ROM_size << 14);
if (VROM_size) {
if ((VROM = (uint8*)FCEU_malloc(VROM_size << 13)) == NULL) {
free(ROM);
ROM = NULL;
FCEU_PrintError("Unable to allocate memory.");
return LOADER_HANDLED_ERROR;
}
VROM = (uint8*)FCEU_malloc(VROM_size << 13);
memset(VROM, 0xFF, VROM_size << 13);
}
// Set Vs. System flag if need
if (!iNES2) {
GameInfo->type = !(head.ROM_type2 & 1) ? GIT_CART : GIT_VSUNI;
}
else {
switch (!(head.ROM_type2 & 2) ? (head.ROM_type2 & 3) : (head.VS_hardware & 0xF)) {
case 0:
GameInfo->type = GIT_CART;
break;
case 1:
GameInfo->type = GIT_VSUNI;
break;
default:
FCEU_PrintError("Game type is not supported at all.");
goto init_error;
}
}
// Set Vs. System PPU type if need
if (GameInfo->type == GIT_VSUNI && !(head.ROM_type2 & 2)) {
switch (head.VS_hardware & 0xF) {
case 0x0: GameInfo->vs_ppu = GIPPU_RC2C03B; break;
//case 0x1: GameInfo->vs_ppu = GIPPU_RPC2C03C; break;
case 0x2: GameInfo->vs_ppu = GIPPU_RP2C04_0001; break;
case 0x3: GameInfo->vs_ppu = GIPPU_RP2C04_0002; break;
case 0x4: GameInfo->vs_ppu = GIPPU_RP2C04_0003; break;
case 0x5: GameInfo->vs_ppu = GIPPU_RP2C04_0004; break;
case 0x6: GameInfo->vs_ppu = GIPPU_RC2C03B; break;
//case 0x7: GameInfo->ppu = GIPPU_RPC2C03C; break;
case 0x8: GameInfo->vs_ppu = GIPPU_RC2C05_01; break;
case 0x9: GameInfo->vs_ppu = GIPPU_RC2C05_02; break;
case 0xA: GameInfo->vs_ppu = GIPPU_RC2C05_03; break;
case 0xB: GameInfo->vs_ppu = GIPPU_RC2C05_04; break;
//case 0xC: GameInfo->ppu = GIPPU_RPC2C05_05; break;
default:
FCEU_PrintError("Vs. System PPU type is not supported at all.");
goto init_error;
}
switch (head.VS_hardware >> 4) {
case 0x0: GameInfo->vs_type = EGIVS_NORMAL; break;
case 0x1: GameInfo->vs_type = EGIVS_RBI; break;
case 0x2: GameInfo->vs_type = EGIVS_TKO; break;
case 0x3: GameInfo->vs_type = EGIVS_XEVIOUS; break;
default:
FCEU_PrintError("Vs. System type is not supported at all.");
goto init_error;
}
}
if (head.ROM_type & 4) { /* Trainer */
trainerpoo = (uint8*)FCEU_gmalloc(512);
FCEU_fread(trainerpoo, 512, 1, fp);
@@ -838,7 +953,7 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
if (VROM_size)
FCEU_fread(VROM, 0x2000, VROM_size, fp);
md5_starts(&md5);
md5_starts(&md5);
md5_update(&md5, ROM, ROM_size << 14);
iNESGameCRC32 = CalcCRC32(0, ROM, ROM_size << 14);
@@ -849,12 +964,14 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
}
md5_finish(&md5, iNESCart.MD5);
memcpy(&GameInfo->MD5, &iNESCart.MD5, sizeof(iNESCart.MD5));
for (int x = 0; x < 8; x++)
partialmd5 |= (uint64)iNESCart.MD5[7 - x] << (x * 8);
iNESCart.CRC32 = iNESGameCRC32;
FCEU_printf(" PRG ROM: %d x 16KiB = %d KiB\n", round ? ROM_size : not_round_size, (round ? ROM_size : not_round_size) * 16);
FCEU_printf(" CHR ROM: %d x 8KiB = %d KiB\n", VROM_size, VROM_size * 8);
FCEU_printf(" ROM CRC32: 0x%08lx\n", iNESGameCRC32);
FCEU_printf(" ROM CRC32: 0x%08x\n", iNESGameCRC32);
{
int x;
FCEU_printf(" ROM MD5: 0x");
@@ -863,9 +980,7 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
FCEU_printf("\n");
}
const char* mappername = "Not Listed";
for (int mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) {
for (size_t mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) {
if (bmap[mappertest].number == MapperNo) {
mappername = bmap[mappertest].name;
break;
@@ -891,17 +1006,12 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
}
SetInput();
CheckHInfo();
{
int x;
uint64 partialmd5 = 0;
// Input can be overriden by NES 2.0 header
if (iNES2) SetInputNes20(head.expansion);
CheckHInfo(partialmd5);
FCEU_VSUniCheck(partialmd5, &MapperNo, &Mirroring);
CheckBad(partialmd5);
for (x = 0; x < 8; x++) {
partialmd5 |= (uint64)iNESCart.MD5[7 - x] << (x * 8);
}
FCEU_VSUniCheck(partialmd5, &MapperNo, &Mirroring);
}
/* Must remain here because above functions might change value of
VROM_size and free(VROM).
*/
@@ -918,8 +1028,9 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
iNESCart.battery = (head.ROM_type & 2) ? 1 : 0;
iNESCart.mirror = Mirroring;
iNESCart.mirrorAs2Bits = MirroringAs2bits;
int result = iNES_Init(MapperNo);
result = iNES_Init(MapperNo);
switch(result)
{
case 0:
@@ -931,6 +1042,8 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) {
FCEU_PrintError("Unable to allocate CHR-RAM.");
break;
}
init_error:
if (ROM) free(ROM);
if (VROM) free(VROM);
if (trainerpoo) free(trainerpoo);
@@ -995,7 +1108,7 @@ int iNesSaveAs(const char* name)
//caitsith2: done. iNesSave() now gets filename and calls iNesSaveAs with that filename.
FILE *fp;
if (GameInfo->type != GIT_CART) return 0;
if ((GameInfo->type != GIT_CART) && (GameInfo->type != GIT_VSUNI)) return 0;
if (GameInterface != iNESGI) return 0;
fp = fopen(name, "wb");
+25 -13
View File
@@ -25,6 +25,8 @@
#include <string.h>
#include <map>
#include "cart.h"
struct TMasterRomInfo
{
uint64 md5lower;
@@ -43,27 +45,30 @@ extern uint8 *VROM;
extern uint32 VROM_size;
extern uint32 ROM_size;
extern uint8 *ExtraNTARAM;
extern uint8 **VPageR;
extern int iNesSave(void); //bbit Edited: line added
extern int iNesSaveAs(const char* name);
extern char LoadedRomFName[2048]; //bbit Edited: line added
extern char LoadedRomFName[4096]; //bbit Edited: line added
extern char LoadedRomFNamePatchToUse[4096];
extern char *iNesShortFName(void);
extern const TMasterRomInfo* MasterRomInfo;
extern TMasterRomInfoParams MasterRomInfoParams;
//mbg merge 7/19/06 changed to c++ decl format
struct iNES_HEADER {
char ID[4]; /*NES^Z*/ // 0-3
uint8 ROM_size; // 4
uint8 VROM_size; // 5
uint8 ROM_type; // 6
uint8 ROM_type2; // 7
uint8 ROM_type3; // 8
uint8 Upper_ROM_VROM_size; // 9
uint8 RAM_size; // 10
uint8 VRAM_size; // 11
uint8 TV_system; // 12
uint8 VS_hardware; // 13
uint8 reserved[2]; // 14, 15
char ID[4]; /*NES^Z*/ // 0-3
uint8 ROM_size; // 4
uint8 VROM_size; // 5
uint8 ROM_type; // 6
uint8 ROM_type2; // 7
uint8 ROM_type3; // 8
uint8 Upper_ROM_VROM_size; // 9
uint8 RAM_size; // 10
uint8 VRAM_size; // 11
uint8 TV_system; // 12
uint8 VS_hardware; // 13
uint8 misc_roms; // 14
uint8 expansion; // 15
void cleanup()
{
@@ -203,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 *);
@@ -242,6 +248,7 @@ void Mapper213_Init(CartInfo *);
void Mapper214_Init(CartInfo *);
void Mapper216_Init(CartInfo *);
void Mapper217_Init(CartInfo *);
void Mapper218_Init(CartInfo *);
void Mapper220_Init(CartInfo *);
void Mapper222_Init(CartInfo *);
void Mapper225_Init(CartInfo *);
@@ -268,8 +275,13 @@ void Mapper250_Init(CartInfo *);
void Mapper252_Init(CartInfo *);
void Mapper253_Init(CartInfo *);
void Mapper254_Init(CartInfo *);
void Mapper255_Init(CartInfo *);
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;
int32 number;
+60 -22
View File
@@ -106,6 +106,8 @@ uint8 FCEU_GetJoyJoy(void)
}
extern uint8 coinon;
extern uint8 coinon2;
extern uint8 service;
//set to true if the fourscore is attached
static bool FSAttached = false;
@@ -431,8 +433,11 @@ void FCEU_UpdateInput(void)
portFC.driver->Update(portFC.ptr,portFC.attrib);
}
if(GameInfo->type==GIT_VSUNI)
if(coinon) coinon--;
if (GameInfo->type == GIT_VSUNI) {
if (coinon) coinon--;
if (coinon2) coinon2--;
if (service) service--;
}
if(FCEUnetplay)
NetplayUpdate(joy);
@@ -454,7 +459,11 @@ static DECLFR(VSUNIRead0)
ret|=(vsdip&3)<<3;
if(coinon)
ret|=0x4;
ret |= 0x20;
if (coinon2)
ret |= 0x40;
if (service)
ret |= 0x04;
return ret;
}
@@ -668,7 +677,9 @@ void FCEU_DoSimpleCommand(int cmd)
{
case FCEUNPCMD_FDSINSERT: FCEU_FDSInsert();break;
case FCEUNPCMD_FDSSELECT: FCEU_FDSSelect();break;
case FCEUNPCMD_VSUNICOIN: FCEU_VSUniCoin(); break;
case FCEUNPCMD_VSUNICOIN: FCEU_VSUniCoin(0); break;
case FCEUNPCMD_VSUNICOIN2: FCEU_VSUniCoin(1); break;
case FCEUNPCMD_VSUNISERVICE: FCEU_VSUniService(); break;
case FCEUNPCMD_VSUNIDIP0:
case FCEUNPCMD_VSUNIDIP0+1:
case FCEUNPCMD_VSUNIDIP0+2:
@@ -726,6 +737,22 @@ void FCEUI_VSUniCoin(void)
FCEU_QSimpleCommand(FCEUNPCMD_VSUNICOIN);
}
void FCEUI_VSUniCoin2(void)
{
if (!FCEU_IsValidUI(FCEUI_INSERT_COIN))
return;
FCEU_QSimpleCommand(FCEUNPCMD_VSUNICOIN2);
}
void FCEUI_VSUniService(void)
{
if (!FCEU_IsValidUI(FCEUI_INSERT_COIN))
return;
FCEU_QSimpleCommand(FCEUNPCMD_VSUNISERVICE);
}
//Resets the frame counter if movie inactive and rom is reset or power-cycle
void ResetFrameCounter()
{
@@ -798,6 +825,7 @@ static void RamSearchOpLTE(void);
static void RamSearchOpGTE(void);
static void RamSearchOpEQ(void);
static void RamSearchOpNE(void);
static void ToggleCheats(void);
static void DebuggerStepInto(void);
static void FA_SkipLag(void);
static void OpenRom(void);
@@ -900,17 +928,17 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
{ EMUCMD_FDS_EJECT_INSERT, EMUCMDTYPE_FDS, FCEUI_FDSInsert, 0, 0, "Eject or Insert FDS Disk", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_FDS_SIDE_SELECT, EMUCMDTYPE_FDS, FCEUI_FDSSelect, 0, 0, "Switch FDS Disk Side", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_VSUNI_COIN, EMUCMDTYPE_VSUNI, FCEUI_VSUniCoin, 0, 0, "Insert Coin", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_VSUNI_TOGGLE_DIP_0, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 0", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_1, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 1", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_2, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 2", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_3, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 3", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_4, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 4", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_5, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 5", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_6, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 6", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_7, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 7", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_8, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 8", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_9, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 9", 0 },
{ EMUCMD_VSUNI_COIN, EMUCMDTYPE_VSUNI, FCEUI_VSUniCoin, 0, 0, "Insert Coin #1", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_VSUNI_COIN_2, EMUCMDTYPE_VSUNI, FCEUI_VSUniCoin2, 0, 0, "Insert Coin #2", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_VSUNI_SERVICE_BUTTON, EMUCMDTYPE_VSUNI, FCEUI_VSUniService, 0, 0, "Service Button", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_VSUNI_TOGGLE_DIP_0, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 0", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_1, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 1", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_2, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 2", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_3, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 3", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_4, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 4", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_5, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 5", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_6, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 6", 0 },
{ EMUCMD_VSUNI_TOGGLE_DIP_7, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dip Switch 7", 0 },
{ EMUCMD_MISC_AUTOSAVE, EMUCMDTYPE_MISC, FCEUI_RewindToLastAutosave, 0, 0, "Load Last Auto-save", 0},
{ EMUCMD_MISC_SHOWSTATES, EMUCMDTYPE_MISC, ViewSlots, 0, 0, "View save slots", 0 },
@@ -945,6 +973,7 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
{ EMUCMD_TOOL_RAMSEARCHGTE, EMUCMDTYPE_TOOL, RamSearchOpGTE, 0, 0, "Ram Search - Greater Than or Equal", 0},
{ EMUCMD_TOOL_RAMSEARCHEQ, EMUCMDTYPE_TOOL, RamSearchOpEQ, 0, 0, "Ram Search - Equal", 0},
{ EMUCMD_TOOL_RAMSEARCHNE, EMUCMDTYPE_TOOL, RamSearchOpNE, 0, 0, "Ram Search - Not Equal", 0},
{ EMUCMD_TOOL_TOGGLECHEATS, EMUCMDTYPE_TOOL, ToggleCheats, 0, 0, "Toggle Cheats", 0},
{ EMUCMD_RERECORD_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_MovieToggleRerecordDisplay,0, 0, "Toggle Rerecord Display", EMUCMDFLAG_TASEDITOR },
{ EMUCMD_TASEDITOR_REWIND, EMUCMDTYPE_TASEDITOR, TaseditorRewindOn, TaseditorRewindOff, 0, "Frame Rewind", EMUCMDFLAG_TASEDITOR },
@@ -960,12 +989,12 @@ struct EMUCMDTABLE FCEUI_CommandTable[]=
#define NUM_EMU_CMDS (sizeof(FCEUI_CommandTable)/sizeof(FCEUI_CommandTable[0]))
static int execcmd, i;
static int execcmd;
void FCEUI_HandleEmuCommands(TestCommandState* testfn)
{
bool taseditor = FCEUMOV_Mode(MOVIEMODE_TASEDITOR);
for(i=0; i<NUM_EMU_CMDS; ++i)
for(size_t i=0; i<NUM_EMU_CMDS; ++i)
{
int new_state;
int old_state = FCEUI_CommandTable[i].state;
@@ -1268,6 +1297,18 @@ static void RamSearchOpNE(void) {
#endif
}
extern int globalCheatDisabled;
extern unsigned int FrozenAddressCount;
static void ToggleCheats()
{
FCEUI_GlobalToggleCheat(globalCheatDisabled);
FCEU_DispMessage("%d cheats active", 0, FrozenAddressCount);
#ifdef __WIN_DRIVER__
UpdateCheatRelatedWindow();
UpdateCheatListGroupBoxUI();
#endif
}
static void DebuggerStepInto()
{
#ifdef __WIN_DRIVER__
@@ -1324,10 +1365,7 @@ static void MovieSubtitleToggle(void)
static void UndoRedoSavestate(void)
{
// FIXME this will always evaluate to true, should this be
// if (*lastSavestateMade...) to check if it holds a string or just
// a '\0'?
if (lastSavestateMade && (undoSS || redoSS))
if ( !lastSavestateMade.empty() && (undoSS || redoSS))
SwapSaveState();
}
@@ -1380,7 +1418,7 @@ static void TaseditorCommand(void)
**/
EMUCMDTABLE* GetEmuCommandById(int cmd)
{
for (i = 0; i<NUM_EMU_CMDS; ++i)
for (size_t i = 0; i<NUM_EMU_CMDS; ++i)
{
if (FCEUI_CommandTable[i].cmd == cmd)
return &FCEUI_CommandTable[i];
+4 -2
View File
@@ -197,8 +197,8 @@ enum EMUCMD
EMUCMD_VSUNI_TOGGLE_DIP_5,
EMUCMD_VSUNI_TOGGLE_DIP_6,
EMUCMD_VSUNI_TOGGLE_DIP_7,
EMUCMD_VSUNI_TOGGLE_DIP_8,
EMUCMD_VSUNI_TOGGLE_DIP_9,
EMUCMD_VSUNI_COIN_2,
EMUCMD_VSUNI_SERVICE_BUTTON,
EMUCMD_MISC_AUTOSAVE,
EMUCMD_MISC_SHOWSTATES,
EMUCMD_MISC_USE_INPUT_PRESET_1,
@@ -259,6 +259,8 @@ enum EMUCMD
EMUCMD_MOVIE_RECORD_MODE_OVERWRITE,
EMUCMD_MOVIE_RECORD_MODE_INSERT,
EMUCMD_TOOL_TOGGLECHEATS,
EMUCMD_MAX
};
+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;
};
};
};
+191 -74
View File
@@ -24,8 +24,8 @@
#include "file.h"
#include "video.h"
#include "debug.h"
#include "debugsymboltable.h"
#include "sound.h"
#include "drawing.h"
#include "state.h"
#include "movie.h"
#include "driver.h"
@@ -54,6 +54,9 @@ extern TASEDITOR_LUA taseditor_lua;
#ifdef __SDL__
#ifdef __QT_DRIVER__
#include "drivers/Qt/sdl.h"
#include "drivers/Qt/main.h"
#include "drivers/Qt/input.h"
#include "drivers/Qt/fceuWrapper.h"
#include "drivers/Qt/TasEditor/selection.h"
#include "drivers/Qt/TasEditor/laglog.h"
@@ -182,10 +185,13 @@ struct LuaSaveState {
persisted = true;
FILE* inf = fopen(filename.c_str(),"rb");
fseek(inf,0,SEEK_END);
int len = ftell(inf);
long int len = ftell(inf);
fseek(inf,0,SEEK_SET);
data = new EMUFILE_MEMORY(len);
fread(data->buf(),1,len,inf);
if ( fread(data->buf(),1,len,inf) != static_cast<size_t>(len) )
{
FCEU_printf("Warning: LuaSaveState::ensureLoad failed to load full buffer.\n");
}
fclose(inf);
}
};
@@ -250,7 +256,7 @@ static const char *guiCallbackTable = "FCEU.GUI";
static int frameAdvanceWaiting = FALSE;
// We save our pause status in the case of a natural death.
static int wasPaused = FALSE;
//static int wasPaused = FALSE;
// Transparency strength. 255=opaque, 0=so transparent it's invisible
static int transparencyModifier = 255;
@@ -312,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
@@ -656,12 +658,11 @@ static int emu_loadrom(lua_State *L)
return 0;
#elif defined(__QT_DRIVER__)
const char *nameo2 = luaL_checkstring(L,1);
char nameo[2048];
std::string nameo;
strncpy(nameo, nameo2, sizeof(nameo));
nameo[sizeof(nameo)-1] = 0;
nameo.assign( nameo2 );
LoadGameFromLua( nameo );
LoadGameFromLua( nameo.c_str() );
//lua_cpcall(L, emu_wait_for_rom_load, NULL);
//printf("Attempting to Load ROM: '%s'\n", nameo );
@@ -743,7 +744,7 @@ static int emu_addgamegenie(lua_State *L) {
while (FCEUI_GetCheat(i,NULL,&Caddr,&Cval,&Ccompare,NULL,&Ctype)) {
if ((GGaddr == Caddr) && (GGval == Cval) && (GGcomp == Ccompare) && (Ctype == 1)) {
if ((static_cast<uint32>(GGaddr) == Caddr) && (GGval == static_cast<int>(Cval)) && (GGcomp == Ccompare) && (Ctype == 1)) {
// Already Added, so consider it a success
lua_pushboolean(L, true);
return 1;
@@ -773,7 +774,7 @@ static int emu_delgamegenie(lua_State *L) {
int GGaddr, GGcomp, GGval;
uint32 i=0;
char * Cname;
std::string Cname;
uint32 Caddr;
uint8 Cval;
int Ccompare, Ctype;
@@ -786,7 +787,7 @@ static int emu_delgamegenie(lua_State *L) {
while (FCEUI_GetCheat(i,&Cname,&Caddr,&Cval,&Ccompare,NULL,&Ctype)) {
if ((!strcmp(msg,Cname)) && (GGaddr == Caddr) && (GGval == Cval) && (GGcomp == Ccompare) && (Ctype == 1)) {
if ((Cname == msg) && (static_cast<uint32>(GGaddr) == Caddr) && (GGval == static_cast<int>(Cval)) && (GGcomp == Ccompare) && (Ctype == 1)) {
// Delete cheat code
if (FCEUI_DelCheat(i)) {
lua_pushboolean(L, true);
@@ -1302,7 +1303,10 @@ void freadint(unsigned int& value, FILE* file)
for(int i=0;i<4;i++)
{
int r = 0;
fread(&r, 1, 1, file);
if ( fread(&r, 1, 1, file) == 0)
{
break;
}
rv |= r << (i*8);
}
value = rv;
@@ -1346,7 +1350,10 @@ void LuaSaveData::ImportRecords(void* fileV)
break;
cur->data = new unsigned char [cur->size];
fread(cur->data, cur->size, 1, file);
if ( fread(cur->data, cur->size, 1, file) == 0 )
{
memset( cur->data, 0, cur->size );
}
Record* next = new Record();
memcpy(next, cur, sizeof(Record));
@@ -1632,7 +1639,7 @@ static void toCStringConverter(lua_State* L, int i, char*& ptr, int& remaining)
if(remaining <= 0)
return;
const char* str = ptr; // for debugging
//const char* str = ptr; // for debugging
// if there is a __tostring metamethod then call it
int usedMeta = luaL_callmeta(L, i, "__tostring");
@@ -1994,7 +2001,7 @@ static int memory_getregister(lua_State *L)
{
const char* qualifiedRegisterName = luaL_checkstring(L,1);
lua_settop(L,0);
for(int cpu = 0; cpu < sizeof(cpuToRegisterMaps)/sizeof(*cpuToRegisterMaps); cpu++)
for(size_t cpu = 0; cpu < sizeof(cpuToRegisterMaps)/sizeof(*cpuToRegisterMaps); cpu++)
{
cpuToRegisterMap ctrm = cpuToRegisterMaps[cpu];
int cpuNameLen = strlen(ctrm.cpuName);
@@ -2028,7 +2035,7 @@ static int memory_setregister(lua_State *L)
const char* qualifiedRegisterName = luaL_checkstring(L,1);
unsigned long value = (unsigned long)(luaL_checkinteger(L,2));
lua_settop(L,0);
for(int cpu = 0; cpu < sizeof(cpuToRegisterMaps)/sizeof(*cpuToRegisterMaps); cpu++)
for(size_t cpu = 0; cpu < sizeof(cpuToRegisterMaps)/sizeof(*cpuToRegisterMaps); cpu++)
{
cpuToRegisterMap ctrm = cpuToRegisterMaps[cpu];
int cpuNameLen = strlen(ctrm.cpuName);
@@ -2244,7 +2251,7 @@ static void CallRegisteredLuaMemHook_LuaMatch(unsigned int address, int size, un
#endif
lua_settop(L, 0);
lua_getfield(L, LUA_REGISTRYINDEX, luaMemHookTypeStrings[hookType]);
for(int i = address; i != address+size; i++)
for(unsigned int i = address; i != address+size; i++)
{
lua_rawgeti(L, -1, i);
if (lua_isfunction(L, -1))
@@ -2419,51 +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;
}
}
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);
}
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!
@@ -2638,6 +2611,112 @@ static int input_get(lua_State *L) {
}
}
}
#elif defined(__QT_DRIVER__)
// Qt/SDL
{
const uint8_t *keyBuf = QtSDL_getKeyboardState(nullptr);
if (keyBuf)
{
char keyName[64];
const char *keyOut = nullptr;
for (int i=0; i<SDL_NUM_SCANCODES; i++)
{
if (keyBuf[i])
{
SDL_Keycode k = SDL_GetKeyFromScancode( static_cast<SDL_Scancode>(i) );
const char* name = SDL_GetKeyName(k);
//printf("Key:%i '%s'\n", i, name);
if ( isalpha(name[0]) || isdigit(name[0]) )
{ // If name starts with letters or number, copy name without spaces
int ii=0, jj=0;
while (name[ii] != 0)
{
if ( isalpha(name[ii]) || isdigit(name[ii]) || (name[ii] == '_') )
{
keyName[jj] = name[ii]; jj++;
}
ii++;
}
keyName[jj] = 0;
keyOut = keyName;
}
else
{ // Handle special char names
switch (name[0])
{
case '[':
keyOut = "LeftBracket";
break;
case ']':
keyOut = "RightBracket";
break;
case '{':
keyOut = "LeftBrace";
break;
case '}':
keyOut = "RightBrace";
break;
case ',':
keyOut = "Comma";
break;
case '.':
keyOut = "Period";
break;
case '~':
keyOut = "Tilde";
break;
case '`':
keyOut = "Backtick";
break;
case '|':
keyOut = "VerticalBar";
break;
case '/':
keyOut = "Slash";
break;
case '\\':
keyOut = "BackSlash";
break;
case '+':
keyOut = "Plus";
break;
case '=':
keyOut = "Equals";
break;
case '_':
keyOut = "Underscore";
break;
case '-':
keyOut = "Minus";
break;
case ';':
keyOut = "SemiColon";
break;
case ':':
keyOut = "Colon";
break;
case '\'':
case '\"':
keyOut = "Quote";
break;
default:
keyOut = name;
break;
}
}
lua_pushboolean(L, true);
lua_setfield(L, -2, keyOut);
}
}
}
}
#else
//SDL TODO: implement this for keyboard!!
#endif
@@ -3117,11 +3196,10 @@ static int savestate_loadscriptdata(lua_State *L) {
{
LuaSaveData saveData;
char luaSaveFilename [512];
strncpy(luaSaveFilename, filename, 512);
luaSaveFilename[512-(1+7/*strlen(".luasav")*/)] = '\0';
strcat(luaSaveFilename, ".luasav");
FILE* luaSaveFile = fopen(luaSaveFilename, "rb");
std::string luaSaveFilename;
luaSaveFilename.assign( filename );
luaSaveFilename.append( ".luasav");
FILE* luaSaveFile = fopen(luaSaveFilename.c_str(), "rb");
if(luaSaveFile)
{
saveData.ImportRecords(luaSaveFile);
@@ -3743,7 +3821,7 @@ static inline bool str2colour(uint32 *colour, lua_State *L, const char *str) {
*colour = ((rand()*255/RAND_MAX) << 8) | ((rand()*255/RAND_MAX) << 16) | ((rand()*255/RAND_MAX) << 24) | 0xFF;
return true;
}
for(int i = 0; i < sizeof(s_colorMapping)/sizeof(*s_colorMapping); i++) {
for(size_t i = 0; i < sizeof(s_colorMapping)/sizeof(*s_colorMapping); i++) {
if(!stricmp(str,s_colorMapping[i].name)) {
*colour = s_colorMapping[i].value;
return true;
@@ -3779,7 +3857,6 @@ static inline uint32 gui_getcolour_wrapped(lua_State *L, int offset, bool hasDef
lua_pushnil(L); // first key
int keyIndex = lua_gettop(L);
int valueIndex = keyIndex + 1;
bool first = true;
while(lua_next(L, offset))
{
bool keyIsString = (lua_type(L, keyIndex) == LUA_TSTRING);
@@ -3985,6 +4062,7 @@ static int gui_box(lua_State *L) {
}
// (old) gui.box(x1, y1, x2, y2, color)
FCEU_MAYBE_UNUSED
static int gui_box_old(lua_State *L) {
int x1,y1,x2,y2;
@@ -4314,6 +4392,7 @@ draw_outline:
}
}
FCEU_MAYBE_UNUSED
static int strlinelen(const char* string)
{
const char* s = string;
@@ -4324,6 +4403,7 @@ static int strlinelen(const char* string)
return s - string;
}
FCEU_MAYBE_UNUSED
static void LuaDisplayString (const char *string, int y, int x, uint32 color, uint32 outlineColor)
{
if(!string)
@@ -4491,7 +4571,7 @@ void LuaDrawTextTransWH(const char *str, size_t l, int &x, int y, uint32 color,
return;
size_t len = l;
int defaultAlpha = std::max<int>(0, std::min<int>(transparencyModifier, 255));
//int defaultAlpha = std::max<int>(0, std::min<int>(transparencyModifier, 255));
int diffx;
int diffy = std::max<int>(0, std::min<int>(7, LUA_SCREEN_HEIGHT - y));
@@ -4560,7 +4640,7 @@ void LuaDrawTextTransWH(const char *str, size_t l, int &x, int y, uint32 color,
// main HUD.
static int gui_text(lua_State *L) {
extern int font_height;
//extern int font_height;
const char *msg;
int x, y;
size_t l;
@@ -4957,6 +5037,27 @@ static int debugger_resetinstructionscount(lua_State *L)
return 0;
}
// debugger.getsymboloffset()
static int debugger_getsymboloffset(lua_State *L)
{
debugSymbol_t *sym = NULL;
const char *name = luaL_checkstring(L, 1);
if (lua_type(L, 2) == LUA_TNUMBER)
{
int bank = luaL_checkinteger(L, 2);
sym = debugSymbolTable.getSymbol(bank, name);
}
else
{
sym = debugSymbolTable.getSymbolAtAnyBank(name);
}
lua_pushinteger(L, sym ? sym->offset() : -1);
return 1;
}
// TAS Editor functions library
// bool taseditor.registerauto()
@@ -4978,7 +5079,7 @@ static int taseditor_registermanual(lua_State *L)
if (!lua_isnil(L,1))
luaL_checktype(L, 1, LUA_TFUNCTION);
const char* caption = NULL;
FCEU_MAYBE_UNUSED const char* caption = NULL;
if (!lua_isnil(L, 2))
caption = lua_tostring(L, 2);
@@ -5364,10 +5465,10 @@ static int doPopup(lua_State *L, const char* deftype, const char* deficon) {
assert(iicon >= 0 && iicon <= 3);
if(!(iicon >= 0 && iicon <= 3)) iicon = 0;
#ifdef __WIN_DRIVER__
static const char * const titles [] = {"Notice", "Question", "Warning", "Error"};
const char* answer = "ok";
#ifdef __WIN_DRIVER__
static const int etypes [] = {MB_OK, MB_YESNO, MB_YESNOCANCEL, MB_OKCANCEL, MB_ABORTRETRYIGNORE};
static const int eicons [] = {MB_ICONINFORMATION, MB_ICONQUESTION, MB_ICONWARNING, MB_ICONERROR};
//StopSound(); //mbg merge 7/27/08
@@ -5512,13 +5613,20 @@ use_console:
// We don't want parameters
if (!t[0]) {
fprintf(stderr, "[Press Enter]");
fgets(buffer, sizeof(buffer), stdin);
if ( fgets(buffer, sizeof(buffer), stdin) == nullptr )
{
FCEU_printf("Error: fgets from stdin failed\n");
}
// We're done
return 0;
}
fprintf(stderr, "(%s): ", t);
fgets(buffer, sizeof(buffer), stdin);
if ( fgets(buffer, sizeof(buffer), stdin) == nullptr )
{
FCEU_printf("Error: fgets from stdin failed\n");
buffer[0] = 0;
}
// Check if the option is in the list
if (strchr(t, tolower(buffer[0]))) {
@@ -5571,7 +5679,11 @@ static int doOpenFilePopup(lua_State *L, bool saveFile) {
// TODO: more sophisticated interface
char filename[PATH_MAX];
printf("Enter %s filename: ", saveFile ? "save" : "open");
fgets(filename, PATH_MAX, stdin);
if ( fgets(filename, PATH_MAX, stdin) == nullptr )
{
FCEU_printf("Warning: fgets from stdin failed\n");
filename[0] = 0;
}
lua_newtable(L);
lua_pushstring(L, filename);
lua_rawseti(L, -2, 1);
@@ -5802,6 +5914,7 @@ static int bitbit(lua_State *L)
}
// The function called periodically to ensure Lua doesn't run amok.
FCEU_MAYBE_UNUSED
static void FCEU_LuaHookFunction(lua_State *L, lua_Debug *dbg) {
if (numTries-- == 0) {
@@ -5983,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},
@@ -6127,6 +6240,7 @@ static const struct luaL_reg debuggerlib[] = {
{"getinstructionscount", debugger_getinstructionscount},
{"resetcyclescount", debugger_resetcyclescount},
{"resetinstructionscount", debugger_resetinstructionscount},
{"getsymboloffset", debugger_getsymboloffset},
{NULL,NULL}
};
@@ -6288,7 +6402,10 @@ int FCEU_LoadLuaCode(const char *filename, const char *arg)
getfilepath = getfilepath.substr(0,getfilepath.find_last_of("/\\") + 1);
SetCurrentDir(getfilepath.c_str());
if ( SetCurrentDir(getfilepath.c_str()) != 0 )
{
FCEU_printf("Warning: Failed chdir failed to set current dir to: %s\n", getfilepath.c_str() );
}
//stop any lua we might already have had running
FCEU_LuaStop();
+44 -31
View File
@@ -114,7 +114,7 @@ SFORMAT FCEUMOV_STATEINFO[]={
{ 0 }
};
char curMovieFilename[512] = {0};
std::string curMovieFilename;
MovieData currMovieData;
MovieData defaultMovieData;
int currRerecordCount; // Keep the global value
@@ -409,6 +409,7 @@ MovieData::MovieData()
, rerecordCount(0)
, binaryFlag(false)
, loadFrameCount(-1)
, fourscore(false)
, microphone(false)
, RAMInitOption(0)
, RAMInitSeed(0)
@@ -692,7 +693,7 @@ bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader)
{
LoadFM2_binarychunk(movieData, fp, size);
return true;
} else if (isnewline && movieData.loadFrameCount == movieData.records.size())
} else if (isnewline && static_cast<size_t>(movieData.loadFrameCount) == movieData.records.size())
// exit prematurely if loaded the specified amound of records
return true;
switch(state)
@@ -806,7 +807,10 @@ static EMUFILE *openRecordingMovie(const char* fname)
FCEU_PrintError("Error opening movie output file: %s", fname);
return NULL;
}
strcpy(curMovieFilename, fname);
if ( fname != curMovieFilename.c_str() )
{
curMovieFilename.assign(fname);
}
return osRecordingMovie;
}
@@ -826,7 +830,7 @@ static void RedumpWholeMovieFile(bool justToggledRecording = false)
bool recording = (movieMode == MOVIEMODE_RECORD);
assert((NULL != osRecordingMovie) == (recording != justToggledRecording) && "osRecordingMovie should be consistent with movie mode!");
if (NULL == openRecordingMovie(curMovieFilename))
if (NULL == openRecordingMovie(curMovieFilename.c_str()))
return;
currMovieData.dump(osRecordingMovie, false/*currMovieData.binaryFlag*/, recording);
@@ -874,7 +878,7 @@ static void OnMovieClosed()
{
assert(movieMode == MOVIEMODE_INACTIVE);
curMovieFilename[0] = 0; //No longer a current movie filename
curMovieFilename.clear(); //No longer a current movie filename
freshMovie = false; //No longer a fresh movie loaded
if (bindSavestate) AutoSS = false; //If bind movies to savestates is true, then there is no longer a valid auto-save to load
@@ -980,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] != 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;
@@ -1007,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);
}
}
@@ -1039,7 +1042,7 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, int _pauseframe)
currMovieData = MovieData();
strcpy(curMovieFilename, fname);
curMovieFilename.assign(fname);
FCEUFILE *fp = FCEU_fopen(fname,0,"rb",0);
if (!fp) return false;
if(fp->isArchive() && !_read_only) {
@@ -1220,7 +1223,11 @@ void FCEUMOV_AddInputState()
if (mr->command_fds_select())
FCEU_FDSSelect();
if (mr->command_vs_insertcoin())
FCEU_VSUniCoin();
FCEU_VSUniCoin(0);
if (mr->command_vs_insertcoin2())
FCEU_VSUniCoin(1);
if (mr->command_vs_service())
FCEU_VSUniService();
_currCommand = 0;
} else
#endif
@@ -1248,14 +1255,18 @@ void FCEUMOV_AddInputState()
if(mr->command_fds_select())
FCEU_FDSSelect();
if (mr->command_vs_insertcoin())
FCEU_VSUniCoin();
FCEU_VSUniCoin(0);
if (mr->command_vs_insertcoin2())
FCEU_VSUniCoin(1);
if (mr->command_vs_service())
FCEU_VSUniService();
joyports[0].load(mr);
joyports[1].load(mr);
}
//if we are on the last frame, then pause the emulator if the player requested it
if (currFrameCounter == currMovieData.records.size()-1)
if ( static_cast<size_t>(currFrameCounter) == currMovieData.records.size()-1)
{
if(FCEUD_PauseAfterPlayback())
{
@@ -1326,6 +1337,8 @@ void FCEUMOV_AddCommand(int cmd)
case FCEUNPCMD_FDSINSERT: cmd = MOVIECMD_FDS_INSERT; break;
case FCEUNPCMD_FDSSELECT: cmd = MOVIECMD_FDS_SELECT; break;
case FCEUNPCMD_VSUNICOIN: cmd = MOVIECMD_VS_INSERTCOIN; break;
case FCEUNPCMD_VSUNICOIN2: cmd = MOVIECMD_VS_INSERTCOIN2; break;
case FCEUNPCMD_VSUNISERVICE: cmd = MOVIECMD_VS_SERVICE; break;
// all other netplay commands (e.g. FCEUNPCMD_VSUNIDIP0) are not supported by movie recorder for now
default: return;
}
@@ -1415,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)
{
@@ -1434,7 +1447,7 @@ bool FCEUMOV_ReadState(EMUFILE* is, uint32 size)
#endif
movie_readonly = true;
}
if (FCEU_isFileInArchive(curMovieFilename))
if (FCEU_isFileInArchive(curMovieFilename.c_str()))
{
//a little rule: cant load states in read+write mode with a movie from an archive.
//so we are going to switch it to readonly mode in that case
@@ -1569,10 +1582,10 @@ bool FCEUMOV_ReadState(EMUFILE* is, uint32 size)
//TODO: turn frame counter to red to get attention
if (!backupSavestates) //If backups are disabled we can just resume normally since we can't restore so stop movie and inform user
{
FCEU_PrintError("Error: Savestate taken from a frame (%d) after the final frame in the savestated movie (%d) cannot be verified against current movie (%d). This is not permitted.\nUnable to restore backup, movie playback stopped.", currFrameCounter, tempMovieData.records.size() - 1, currMovieData.records.size() - 1);
FCEU_PrintError("Error: Savestate taken from a frame (%d) after the final frame in the savestated movie (%zi) cannot be verified against current movie (%zi). This is not permitted.\nUnable to restore backup, movie playback stopped.", currFrameCounter, tempMovieData.records.size() - 1, currMovieData.records.size() - 1);
FCEUI_StopMovie();
} else
FCEU_PrintError("Savestate taken from a frame (%d) after the final frame in the savestated movie (%d) cannot be verified against current movie (%d). This is not permitted.", currFrameCounter, tempMovieData.records.size() - 1, currMovieData.records.size() - 1);
FCEU_PrintError("Savestate taken from a frame (%d) after the final frame in the savestated movie (%zi) cannot be verified against current movie (%zi). This is not permitted.", currFrameCounter, tempMovieData.records.size() - 1, currMovieData.records.size() - 1);
return false;
}
}
@@ -1728,7 +1741,7 @@ void FCEUI_MovieToggleReadOnly()
strcpy(message, "Movie is now Read+Write");
strcat(message, GetMovieModeStr());
FCEU_DispMessage(message,0);
FCEU_DispMessage("%s",0,message);
}
void FCEUI_MovieToggleRecording()
@@ -1772,7 +1785,7 @@ void FCEUI_MovieToggleRecording()
strcat(message, GetMovieModeStr());
FCEU_DispMessage(message, 0);
FCEU_DispMessage("%s",0,message);
}
void FCEUI_MovieInsertFrame()
@@ -1799,7 +1812,7 @@ void FCEUI_MovieInsertFrame()
strcat(message, GetMovieModeStr());
}
FCEU_DispMessage(message, 0);
FCEU_DispMessage("%s",0,message);
}
void FCEUI_MovieDeleteFrame()
@@ -1837,7 +1850,7 @@ void FCEUI_MovieDeleteFrame()
strcat(message, GetMovieModeStr());
}
FCEU_DispMessage(message, 0);
FCEU_DispMessage("%s",0,message);
}
void FCEUI_MovieTruncate()
@@ -1875,7 +1888,7 @@ void FCEUI_MovieTruncate()
strcat(message, GetMovieModeStr());
}
FCEU_DispMessage(message, 0);
FCEU_DispMessage("%s",0,message);
}
void FCEUI_MovieNextRecordMode()
@@ -1945,7 +1958,7 @@ void FCEUI_MoviePlayFromBeginning(void)
#endif
}
string FCEUI_GetMovieName(void)
std::string FCEUI_GetMovieName(void)
{
return curMovieFilename;
}
@@ -2039,9 +2052,9 @@ void FCEUI_CreateMovieFile(std::string fn)
void FCEUI_MakeBackupMovie(bool dispMessage)
{
//This function generates backup movie files
string currentFn; //Current movie fillename
string backupFn; //Target backup filename
string tempFn; //temp used in back filename creation
std::string currentFn; //Current movie fillename
std::string backupFn; //Target backup filename
std::string tempFn; //temp used in back filename creation
stringstream stream;
int x; //Temp variable for string manip
bool exist = false; //Used to test if filename exists
+7 -3
View File
@@ -81,7 +81,9 @@ enum EMOVIECMD
MOVIECMD_POWER = 2,
MOVIECMD_FDS_INSERT = 4,
MOVIECMD_FDS_SELECT = 8,
MOVIECMD_VS_INSERTCOIN = 16
MOVIECMD_VS_INSERTCOIN = 16,
MOVIECMD_VS_INSERTCOIN2 = 32,
MOVIECMD_VS_SERVICE = 64
};
EMOVIEMODE FCEUMOV_Mode();
@@ -131,6 +133,8 @@ public:
bool command_fds_insert() { return (commands & MOVIECMD_FDS_INSERT) != 0; }
bool command_fds_select() { return (commands & MOVIECMD_FDS_SELECT) != 0; }
bool command_vs_insertcoin() { return (commands & MOVIECMD_VS_INSERTCOIN) != 0; }
bool command_vs_insertcoin2() { return (commands & MOVIECMD_VS_INSERTCOIN2) != 0; }
bool command_vs_service() { return (commands & MOVIECMD_VS_SERVICE) != 0; }
void toggleBit(int joy, int bit)
{
@@ -210,7 +214,7 @@ public:
//whether microphone is enabled
bool microphone;
int getNumRecords() { return (int)records.size(); }
int getNumRecords() { return static_cast<int>( records.size() ); }
int RAMInitOption, RAMInitSeed;
@@ -272,7 +276,7 @@ private:
extern EMOVIEMODE movieMode;
extern MovieData currMovieData;
extern int currFrameCounter;
extern char curMovieFilename[512];
extern std::string curMovieFilename;
extern bool subtitlesOnAVI;
extern bool freshMovie;
extern bool movie_readonly;
+4 -1
View File
@@ -122,7 +122,10 @@ int FCEUNET_SendFile(uint8 cmd, char *fn)
FCEUX_fstat(fileno(fp),&sb);
len = sb.st_size;
buf = (char*)FCEU_dmalloc(len); //mbg merge 7/17/06 added cast
fread(buf, 1, len, fp);
if ( fread(buf, 1, len, fp) != static_cast<size_t>(len) )
{
FCEU_printf("Warning: FCEUNET_SendFile failed to load complete file.\n");
}
fclose(fp);
cbuf = (char*)FCEU_dmalloc(4 + len + len / 1000 + 12); //mbg merge 7/17/06 added cast
+4 -1
View File
@@ -7,7 +7,10 @@ extern int FCEUnetplay;
#define FCEUNPCMD_POWER 0x02
#define FCEUNPCMD_VSUNICOIN 0x07
#define FCEUNPCMD_VSUNIDIP0 0x08
#define FCEUNPCMD_VSUNIDIP0 0x08
#define FCEUNPCMD_VSUNICOIN2 0x20
#define FCEUNPCMD_VSUNISERVICE 0x21
#define FCEUNPCMD_FDSINSERTx 0x10
#define FCEUNPCMD_FDSINSERT 0x18
//#define FCEUNPCMD_FDSEJECT 0x19
+1 -2
View File
@@ -32,6 +32,7 @@
#include "file.h"
#include "fds.h"
#include "cart.h"
#include "ines.h"
#include "input.h"
#include "state.h"
#include "driver.h"
@@ -123,8 +124,6 @@ static uint16 PlayAddr; //configuration
static uint16 InitAddr; //configuration
static uint16 LoadAddr; //configuration
extern char LoadedRomFName[2048];
NSF_HEADER NSFHeader; //mbg merge 6/29/06 - needs to be global
void NSFMMC5_Close(void);
+19 -4
View File
@@ -48,7 +48,7 @@ static uint8 joop[4];
static uint8 joopcmd;
static uint32 framets = 0;
static uint32 frameptr = 0;
static uint8* moviedata = NULL;
static uint8* moviedata = nullptr;
static uint32 moviedatasize = 0;
static uint32 firstframeoffset = 0;
static uint32 savestate_offset = 0;
@@ -626,7 +626,19 @@ EFCM_CONVERTRESULT convert_fcm(MovieData& md, std::string fname)
//ResetInputTypes();
fp->fseek(firstframeoffset,SEEK_SET);
moviedata = (uint8*)realloc(moviedata, moviedatasize);
uint8 *newMovieData = (uint8*)realloc(moviedata, moviedatasize);
if (newMovieData)
{
moviedata = newMovieData;
}
else
{
if (moviedata)
{
free(moviedata); moviedata = nullptr;
}
return FCM_CONVERTRESULT_REALLOC_FAIL;
}
fp->fread((char*)moviedata,moviedatasize);
frameptr = 0;
@@ -669,8 +681,11 @@ EFCM_CONVERTRESULT convert_fcm(MovieData& md, std::string fname)
md.ports[0] = md.ports[1] = SI_GAMEPAD;
}
free(moviedata);
moviedata = 0;
if (moviedata)
{
free(moviedata);
moviedata = nullptr;
}
delete fp;
return FCM_CONVERTRESULT_SUCCESS;
+1
View File
@@ -10,6 +10,7 @@ enum EFCM_CONVERTRESULT
FCM_CONVERTRESULT_OLDVERSION,
FCM_CONVERTRESULT_UNSUPPORTEDVERSION,
FCM_CONVERTRESULT_STARTFROMSAVESTATENOTSUPPORTED,
FCM_CONVERTRESULT_REALLOC_FAIL,
};
inline const char * EFCM_CONVERTRESULT_message(EFCM_CONVERTRESULT e)
+2
View File
@@ -87,6 +87,7 @@ pal *palo = NULL;
(type) (y + to_rgb [4] * i + to_rgb [5] * q)\
)
FCEU_MAYBE_UNUSED
static void ApplyDeemphasisNTSC(int entry, u8& r, u8& g, u8& b)
{
static float const to_float = 1.0f / 0xFF;
@@ -252,6 +253,7 @@ static void ApplyDeemphasisBisqwit(int entry, u8& r, u8& g, u8& b)
}
//classic algorithm
FCEU_MAYBE_UNUSED
static void ApplyDeemphasisClassic(int entry, u8& r, u8& g, u8& b)
{
//DEEMPH BITS MAY BE ORDERED WRONG. PLEASE CHECK
+76 -68
View File
@@ -4,6 +4,9 @@
#define EMPTY_PALETTE_64 EMPTY_PALETTE_16 EMPTY_PALETTE_16 EMPTY_PALETTE_16 EMPTY_PALETTE_16
#define EMPTY_PALETTE_DEEMPH_X_7 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64 EMPTY_PALETTE_64
//this assumes the color is already shifted <<2, as it is in these cases
#define P64RPC(x) ( ((x)&~3) | (((x)>>6)&3))
pal rp2c04001[512] = {
#include "rp2c04001.h"
EMPTY_PALETTE_DEEMPH_X_7
@@ -23,12 +26,14 @@ pal rp2c05004[512] = {
EMPTY_PALETTE_DEEMPH_X_7
};
#undef P64RPC
// Fixed palette entries used by the GUI
pal palette_unvarying[] = {
{ 0x00<<2,0x00<<2,0x00<<2}, // 0 = Black
{ 0x3F<<2,0x3F<<2,0x34<<2}, // 1 = White
{ 0x00<<2,0x00<<2,0x00<<2}, // 2 = Black
{ 0x1d<<2,0x1d<<2,0x24<<2}, // 3 = Greyish
{ 0x00,0x00,0x00}, // 0 = Black
{ 0xFF,0xFF,0xD3}, // 1 = White
{ 0x00,0x00,0x00}, // 2 = Black
{ 0x75,0x75,0x92}, // 3 = Greyish
{ 190, 0, 0}, // 4 = Reddish
{ 51,255, 51}, // 5 = Bright green
{ 49, 14,200}, // 6 = Ultramarine Blue
@@ -52,73 +57,76 @@ pal palette_unvarying[] = {
};
#define P64(x) (((x)<<2)|((x>>4)&3))
// Default palette
pal palette[512] = {
{ P64(0x1D), P64(0x1D), P64(0x1D)}, /* Value 0 */
{ P64(0x09), P64(0x06), P64(0x23)}, /* Value 1 */
{ P64(0x00), P64(0x00), P64(0x2A)}, /* Value 2 */
{ P64(0x11), P64(0x00), P64(0x27)}, /* Value 3 */
{ P64(0x23), P64(0x00), P64(0x1D)}, /* Value 4 */
{ P64(0x2A), P64(0x00), P64(0x04)}, /* Value 5 */
{ P64(0x29), P64(0x00), P64(0x00)}, /* Value 6 */
{ P64(0x1F), P64(0x02), P64(0x00)}, /* Value 7 */
{ P64(0x10), P64(0x0B), P64(0x00)}, /* Value 8 */
{ P64(0x00), P64(0x11), P64(0x00)}, /* Value 9 */
{ P64(0x00), P64(0x14), P64(0x00)}, /* Value 10 */
{ P64(0x00), P64(0x0F), P64(0x05)}, /* Value 11 */
{ P64(0x06), P64(0x0F), P64(0x17)}, /* Value 12 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 13 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 14 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 15 */
{ P64(0x2F), P64(0x2F), P64(0x2F)}, /* Value 16 */
{ P64(0x00), P64(0x1C), P64(0x3B)}, /* Value 17 */
{ P64(0x08), P64(0x0E), P64(0x3B)}, /* Value 18 */
{ P64(0x20), P64(0x00), P64(0x3C)}, /* Value 19 */
{ P64(0x2F), P64(0x00), P64(0x2F)}, /* Value 20 */
{ P64(0x39), P64(0x00), P64(0x16)}, /* Value 21 */
{ P64(0x36), P64(0x0A), P64(0x00)}, /* Value 22 */
{ P64(0x32), P64(0x13), P64(0x03)}, /* Value 23 */
{ P64(0x22), P64(0x1C), P64(0x00)}, /* Value 24 */
{ P64(0x00), P64(0x25), P64(0x00)}, /* Value 25 */
{ P64(0x00), P64(0x2A), P64(0x00)}, /* Value 26 */
{ P64(0x00), P64(0x24), P64(0x0E)}, /* Value 27 */
{ P64(0x00), P64(0x20), P64(0x22)}, /* Value 28 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 29 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 30 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 31 */
{ P64(0x3F), P64(0x3F), P64(0x3F)}, /* Value 32 */
{ P64(0x0F), P64(0x2F), P64(0x3F)}, /* Value 33 */
{ P64(0x17), P64(0x25), P64(0x3F)}, /* Value 34 */
{ P64(0x33), P64(0x22), P64(0x3F)}, /* Value 35 */
{ P64(0x3D), P64(0x1E), P64(0x3F)}, /* Value 36 */
{ P64(0x3F), P64(0x1D), P64(0x2D)}, /* Value 37 */
{ P64(0x3F), P64(0x1D), P64(0x18)}, /* Value 38 */
{ P64(0x3F), P64(0x26), P64(0x0E)}, /* Value 39 */
{ P64(0x3C), P64(0x2F), P64(0x0F)}, /* Value 40 */
{ P64(0x20), P64(0x34), P64(0x04)}, /* Value 41 */
{ P64(0x13), P64(0x37), P64(0x12)}, /* Value 42 */
{ P64(0x16), P64(0x3E), P64(0x26)}, /* Value 43 */
{ P64(0x00), P64(0x3A), P64(0x36)}, /* Value 44 */
{ P64(0x1E), P64(0x1E), P64(0x1E)}, /* Value 45 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 46 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 47 */
{ P64(0x3F), P64(0x3F), P64(0x3F)}, /* Value 48 */
{ P64(0x2A), P64(0x39), P64(0x3F)}, /* Value 49 */
{ P64(0x31), P64(0x35), P64(0x3F)}, /* Value 50 */
{ P64(0x35), P64(0x32), P64(0x3F)}, /* Value 51 */
{ P64(0x3F), P64(0x31), P64(0x3F)}, /* Value 52 */
{ P64(0x3F), P64(0x31), P64(0x36)}, /* Value 53 */
{ P64(0x3F), P64(0x2F), P64(0x2C)}, /* Value 54 */
{ P64(0x3F), P64(0x36), P64(0x2A)}, /* Value 55 */
{ P64(0x3F), P64(0x39), P64(0x28)}, /* Value 56 */
{ P64(0x38), P64(0x3F), P64(0x28)}, /* Value 57 */
{ P64(0x2A), P64(0x3C), P64(0x2F)}, /* Value 58 */
{ P64(0x2C), P64(0x3F), P64(0x33)}, /* Value 59 */
{ P64(0x27), P64(0x3F), P64(0x3C)}, /* Value 60 */
{ P64(0x31), P64(0x31), P64(0x31)}, /* Value 61 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 62 */
{ P64(0x00), P64(0x00), P64(0x00)}, /* Value 63 */
{ 0x1D<<2, 0x1D<<2, 0x1D<<2 }, /* Value 0 */
{ 0x09<<2, 0x06<<2, 0x23<<2 }, /* Value 1 */
{ 0x00<<2, 0x00<<2, 0x2A<<2 }, /* Value 2 */
{ 0x11<<2, 0x00<<2, 0x27<<2 }, /* Value 3 */
{ 0x23<<2, 0x00<<2, 0x1D<<2 }, /* Value 4 */
{ 0x2A<<2, 0x00<<2, 0x04<<2 }, /* Value 5 */
{ 0x29<<2, 0x00<<2, 0x00<<2 }, /* Value 6 */
{ 0x1F<<2, 0x02<<2, 0x00<<2 }, /* Value 7 */
{ 0x10<<2, 0x0B<<2, 0x00<<2 }, /* Value 8 */
{ 0x00<<2, 0x11<<2, 0x00<<2 }, /* Value 9 */
{ 0x00<<2, 0x14<<2, 0x00<<2 }, /* Value 10 */
{ 0x00<<2, 0x0F<<2, 0x05<<2 }, /* Value 11 */
{ 0x06<<2, 0x0F<<2, 0x17<<2 }, /* Value 12 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 13 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 14 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 15 */
{ 0x2F<<2, 0x2F<<2, 0x2F<<2 }, /* Value 16 */
{ 0x00<<2, 0x1C<<2, 0x3B<<2 }, /* Value 17 */
{ 0x08<<2, 0x0E<<2, 0x3B<<2 }, /* Value 18 */
{ 0x20<<2, 0x00<<2, 0x3C<<2 }, /* Value 19 */
{ 0x2F<<2, 0x00<<2, 0x2F<<2 }, /* Value 20 */
{ 0x39<<2, 0x00<<2, 0x16<<2 }, /* Value 21 */
{ 0x36<<2, 0x0A<<2, 0x00<<2 }, /* Value 22 */
{ 0x32<<2, 0x13<<2, 0x03<<2 }, /* Value 23 */
{ 0x22<<2, 0x1C<<2, 0x00<<2 }, /* Value 24 */
{ 0x00<<2, 0x25<<2, 0x00<<2 }, /* Value 25 */
{ 0x00<<2, 0x2A<<2, 0x00<<2 }, /* Value 26 */
{ 0x00<<2, 0x24<<2, 0x0E<<2 }, /* Value 27 */
{ 0x00<<2, 0x20<<2, 0x22<<2 }, /* Value 28 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 29 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 30 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 31 */
{ 0x3F<<2, 0x3F<<2, 0x3F<<2 }, /* Value 32 */
{ 0x0F<<2, 0x2F<<2, 0x3F<<2 }, /* Value 33 */
{ 0x17<<2, 0x25<<2, 0x3F<<2 }, /* Value 34 */
{ 0x33<<2, 0x22<<2, 0x3F<<2 }, /* Value 35 */
{ 0x3D<<2, 0x1E<<2, 0x3F<<2 }, /* Value 36 */
{ 0x3F<<2, 0x1D<<2, 0x2D<<2 }, /* Value 37 */
{ 0x3F<<2, 0x1D<<2, 0x18<<2 }, /* Value 38 */
{ 0x3F<<2, 0x26<<2, 0x0E<<2 }, /* Value 39 */
{ 0x3C<<2, 0x2F<<2, 0x0F<<2 }, /* Value 40 */
{ 0x20<<2, 0x34<<2, 0x04<<2 }, /* Value 41 */
{ 0x13<<2, 0x37<<2, 0x12<<2 }, /* Value 42 */
{ 0x16<<2, 0x3E<<2, 0x26<<2 }, /* Value 43 */
{ 0x00<<2, 0x3A<<2, 0x36<<2 }, /* Value 44 */
{ 0x1E<<2, 0x1E<<2, 0x1E<<2 }, /* Value 45 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 46 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 47 */
{ 0x3F<<2, 0x3F<<2, 0x3F<<2 }, /* Value 48 */
{ 0x2A<<2, 0x39<<2, 0x3F<<2 }, /* Value 49 */
{ 0x31<<2, 0x35<<2, 0x3F<<2 }, /* Value 50 */
{ 0x35<<2, 0x32<<2, 0x3F<<2 }, /* Value 51 */
{ 0x3F<<2, 0x31<<2, 0x3F<<2 }, /* Value 52 */
{ 0x3F<<2, 0x31<<2, 0x36<<2 }, /* Value 53 */
{ 0x3F<<2, 0x2F<<2, 0x2C<<2 }, /* Value 54 */
{ 0x3F<<2, 0x36<<2, 0x2A<<2 }, /* Value 55 */
{ 0x3F<<2, 0x39<<2, 0x28<<2 }, /* Value 56 */
{ 0x38<<2, 0x3F<<2, 0x28<<2 }, /* Value 57 */
{ 0x2A<<2, 0x3C<<2, 0x2F<<2 }, /* Value 58 */
{ 0x2C<<2, 0x3F<<2, 0x33<<2 }, /* Value 59 */
{ 0x27<<2, 0x3F<<2, 0x3C<<2 }, /* Value 60 */
{ 0x31<<2, 0x31<<2, 0x31<<2 }, /* Value 61 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 62 */
{ 0x00<<2, 0x00<<2, 0x00<<2 }, /* Value 63 */
#undef P64
//luke's .16+ palette
//{0x60, 0x60, 0x60}, /* Value 0 */
+64 -64
View File
@@ -1,64 +1,64 @@
{0xfc, 0xc4, 0xd8},
{0x40, 0x88, 0xfc},
{0xd8, 0x28, 0x00},
{0x5c, 0x94, 0xfc},
{0x00, 0x80, 0x88},
{0x00, 0x44, 0x00},
{0x00, 0x00, 0x00},
{0xe4, 0x00, 0x58},
{0xfc, 0xfc, 0xfc},
{0x74, 0x74, 0x74},
{0xfc, 0x98, 0x38},
{0xa8, 0x00, 0x10},
{0x8c, 0x00, 0x74},
{0xfc, 0x98, 0x38},
{0x40, 0x2c, 0x00},
{0xfc, 0xfc, 0xfc},
{0x3c, 0xbc, 0xfc},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x80, 0xd0, 0x10},
{0x9c, 0xfc, 0xf0},
{0xc4, 0xd4, 0xfc},
{0xfc, 0xbc, 0xb0},
{0x20, 0x38, 0xec},
{0x00, 0x00, 0x00},
{0x58, 0xf8, 0x98},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0xfc, 0xfc},
{0xbc, 0xbc, 0xbc},
{0xf4, 0x78, 0xfc},
{0x24, 0x18, 0x8c},
{0x00, 0x00, 0x00},
{0xa8, 0xe4, 0xfc},
{0x00, 0x00, 0x00},
{0x4c, 0xdc, 0x48},
{0x00, 0xe8, 0xd8},
{0x18, 0x3c, 0x5c},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x7c, 0x08, 0x00},
{0xfc, 0xc4, 0xfc},
{0xa4, 0x00, 0x00},
{0x80, 0x00, 0xf0},
{0x00, 0x00, 0xa8},
{0xfc, 0x74, 0x60},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x94, 0x00},
{0xbc, 0xbc, 0xbc},
{0x00, 0x50, 0x00},
{0xe0, 0xfc, 0xa0},
{0x00, 0x00, 0x00},
{0xfc, 0xd8, 0xa8},
{0xc8, 0x4c, 0x0c},
{0x00, 0x00, 0x00},
{0x00, 0x70, 0xec},
{0x00, 0x44, 0x00},
{0x00, 0x00, 0x00},
{0xe0, 0xfc, 0xa0},
{0xfc, 0x74, 0xb4},
{0x88, 0x70, 0x00},
{0x00, 0x00, 0x00},
{P64RPC(0xfc), P64RPC(0xc4), P64RPC(0xd8)},
{P64RPC(0x40), P64RPC(0x88), P64RPC(0xfc)},
{P64RPC(0xd8), P64RPC(0x28), P64RPC(0x00)},
{P64RPC(0x5c), P64RPC(0x94), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x80), P64RPC(0x88)},
{P64RPC(0x00), P64RPC(0x44), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xe4), P64RPC(0x00), P64RPC(0x58)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x74), P64RPC(0x74), P64RPC(0x74)},
{P64RPC(0xfc), P64RPC(0x98), P64RPC(0x38)},
{P64RPC(0xa8), P64RPC(0x00), P64RPC(0x10)},
{P64RPC(0x8c), P64RPC(0x00), P64RPC(0x74)},
{P64RPC(0xfc), P64RPC(0x98), P64RPC(0x38)},
{P64RPC(0x40), P64RPC(0x2c), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x3c), P64RPC(0xbc), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x80), P64RPC(0xd0), P64RPC(0x10)},
{P64RPC(0x9c), P64RPC(0xfc), P64RPC(0xf0)},
{P64RPC(0xc4), P64RPC(0xd4), P64RPC(0xfc)},
{P64RPC(0xfc), P64RPC(0xbc), P64RPC(0xb0)},
{P64RPC(0x20), P64RPC(0x38), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x58), P64RPC(0xf8), P64RPC(0x98)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0xbc), P64RPC(0xbc), P64RPC(0xbc)},
{P64RPC(0xf4), P64RPC(0x78), P64RPC(0xfc)},
{P64RPC(0x24), P64RPC(0x18), P64RPC(0x8c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xa8), P64RPC(0xe4), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x4c), P64RPC(0xdc), P64RPC(0x48)},
{P64RPC(0x00), P64RPC(0xe8), P64RPC(0xd8)},
{P64RPC(0x18), P64RPC(0x3c), P64RPC(0x5c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x7c), P64RPC(0x08), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xc4), P64RPC(0xfc)},
{P64RPC(0xa4), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x80), P64RPC(0x00), P64RPC(0xf0)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0xa8)},
{P64RPC(0xfc), P64RPC(0x74), P64RPC(0x60)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x94), P64RPC(0x00)},
{P64RPC(0xbc), P64RPC(0xbc), P64RPC(0xbc)},
{P64RPC(0x00), P64RPC(0x50), P64RPC(0x00)},
{P64RPC(0xe0), P64RPC(0xfc), P64RPC(0xa0)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xd8), P64RPC(0xa8)},
{P64RPC(0xc8), P64RPC(0x4c), P64RPC(0x0c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x70), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x44), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xe0), P64RPC(0xfc), P64RPC(0xa0)},
{P64RPC(0xfc), P64RPC(0x74), P64RPC(0xb4)},
{P64RPC(0x88), P64RPC(0x70), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
+64 -64
View File
@@ -1,64 +1,64 @@
{0x00, 0x00, 0x00},
{0xfc, 0x98, 0x38},
{0x88, 0x70, 0x00},
{0x00, 0x00, 0x00},
{0xa8, 0xf0, 0xbc},
{0xfc, 0x74, 0xb4},
{0x00, 0x00, 0x00},
{0xa8, 0xe4, 0xfc},
{0xd8, 0x28, 0x00},
{0x80, 0x00, 0xf0},
{0xfc, 0xe4, 0xa0},
{0xfc, 0xc4, 0xfc},
{0xfc, 0xfc, 0xfc},
{0x40, 0x88, 0xfc},
{0x00, 0x00, 0x00},
{0x00, 0x3c, 0x14},
{0x00, 0x00, 0x00},
{0x3c, 0xbc, 0xfc},
{0xa4, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x90, 0x38},
{0x80, 0xd0, 0x10},
{0x00, 0x00, 0x00},
{0x5c, 0x94, 0xfc},
{0x00, 0x00, 0x00},
{0xf4, 0x78, 0xfc},
{0x00, 0x00, 0x00},
{0x58, 0xf8, 0x98},
{0x00, 0x00, 0x00},
{0x40, 0x2c, 0x00},
{0x00, 0x00, 0x00},
{0x44, 0x00, 0x9c},
{0x00, 0x00, 0x00},
{0xfc, 0xbc, 0xb0},
{0xfc, 0x74, 0x60},
{0xd4, 0xc8, 0xfc},
{0x00, 0x70, 0xec},
{0x00, 0x00, 0x00},
{0xbc, 0xbc, 0xbc},
{0x00, 0x00, 0xa8},
{0xbc, 0x00, 0xbc},
{0x00, 0x00, 0x00},
{0x74, 0x74, 0x74},
{0x00, 0x44, 0x00},
{0x20, 0x38, 0xec},
{0x00, 0x00, 0x00},
{0xfc, 0xd8, 0xa8},
{0xfc, 0xfc, 0xfc},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x4c, 0xdc, 0x48},
{0xc8, 0x4c, 0x0c},
{0x18, 0x3c, 0x5c},
{0x24, 0x18, 0x8c},
{0xe4, 0x00, 0x58},
{0x00, 0x94, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0xe8, 0xd8},
{0x7c, 0x08, 0x00},
{0xfc, 0xd8, 0xa8},
{0x00, 0x00, 0x00},
{0xa8, 0x00, 0x10},
{0x00, 0x50, 0x00},
{0x74, 0x74, 0x74},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0x98), P64RPC(0x38)},
{P64RPC(0x88), P64RPC(0x70), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xa8), P64RPC(0xf0), P64RPC(0xbc)},
{P64RPC(0xfc), P64RPC(0x74), P64RPC(0xb4)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xa8), P64RPC(0xe4), P64RPC(0xfc)},
{P64RPC(0xd8), P64RPC(0x28), P64RPC(0x00)},
{P64RPC(0x80), P64RPC(0x00), P64RPC(0xf0)},
{P64RPC(0xfc), P64RPC(0xe4), P64RPC(0xa0)},
{P64RPC(0xfc), P64RPC(0xc4), P64RPC(0xfc)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x40), P64RPC(0x88), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x3c), P64RPC(0x14)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x3c), P64RPC(0xbc), P64RPC(0xfc)},
{P64RPC(0xa4), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x90), P64RPC(0x38)},
{P64RPC(0x80), P64RPC(0xd0), P64RPC(0x10)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x5c), P64RPC(0x94), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xf4), P64RPC(0x78), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x58), P64RPC(0xf8), P64RPC(0x98)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x40), P64RPC(0x2c), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x44), P64RPC(0x00), P64RPC(0x9c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xbc), P64RPC(0xb0)},
{P64RPC(0xfc), P64RPC(0x74), P64RPC(0x60)},
{P64RPC(0xd4), P64RPC(0xc8), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x70), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xbc), P64RPC(0xbc), P64RPC(0xbc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0xa8)},
{P64RPC(0xbc), P64RPC(0x00), P64RPC(0xbc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x74), P64RPC(0x74), P64RPC(0x74)},
{P64RPC(0x00), P64RPC(0x44), P64RPC(0x00)},
{P64RPC(0x20), P64RPC(0x38), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xd8), P64RPC(0xa8)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x4c), P64RPC(0xdc), P64RPC(0x48)},
{P64RPC(0xc8), P64RPC(0x4c), P64RPC(0x0c)},
{P64RPC(0x18), P64RPC(0x3c), P64RPC(0x5c)},
{P64RPC(0x24), P64RPC(0x18), P64RPC(0x8c)},
{P64RPC(0xe4), P64RPC(0x00), P64RPC(0x58)},
{P64RPC(0x00), P64RPC(0x94), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0xe8), P64RPC(0xd8)},
{P64RPC(0x7c), P64RPC(0x08), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xd8), P64RPC(0xa8)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xa8), P64RPC(0x00), P64RPC(0x10)},
{P64RPC(0x00), P64RPC(0x50), P64RPC(0x00)},
{P64RPC(0x74), P64RPC(0x74), P64RPC(0x74)},
+64 -64
View File
@@ -1,64 +1,64 @@
{0x44, 0x00, 0x9c},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x74, 0x74, 0x74},
{0x00, 0xa8, 0x00},
{0xfc, 0xfc, 0xfc},
{0xa8, 0xe4, 0xfc},
{0x00, 0x44, 0x00},
{0x24, 0x18, 0x8c},
{0x00, 0x00, 0x00},
{0xfc, 0xbc, 0xb0},
{0x40, 0x2c, 0x00},
{0xe4, 0x00, 0x58},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0xfc, 0xfc},
{0x5c, 0x94, 0xfc},
{0x00, 0x80, 0x88},
{0x00, 0x00, 0x00},
{0x20, 0x38, 0xec},
{0x00, 0x94, 0x00},
{0x88, 0x70, 0x00},
{0xc8, 0x4c, 0x0c},
{0x00, 0x90, 0x38},
{0x74, 0x74, 0x74},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0xa8},
{0xd8, 0x28, 0x00},
{0xa4, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0xc4, 0xd8},
{0x40, 0x88, 0xfc},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0xd8, 0xa8},
{0x00, 0x00, 0x00},
{0xfc, 0x98, 0x38},
{0xfc, 0x74, 0x60},
{0xfc, 0xfc, 0xfc},
{0x80, 0xd0, 0x10},
{0x00, 0x00, 0x00},
{0x3c, 0xbc, 0xfc},
{0xf4, 0x78, 0xfc},
{0x00, 0x70, 0xec},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0xe8, 0xd8},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x7c, 0x08, 0x00},
{0x4c, 0xdc, 0x48},
{0xf0, 0xbc, 0x3c},
{0x00, 0x00, 0x00},
{0x00, 0x50, 0x00},
{0x00, 0x00, 0x00},
{0xc4, 0xd4, 0xfc},
{0xfc, 0xd8, 0xa8},
{0x80, 0x00, 0xf0},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x18, 0x3c, 0x5c},
{P64RPC(0x44), P64RPC(0x00), P64RPC(0x9c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x74), P64RPC(0x74), P64RPC(0x74)},
{P64RPC(0x00), P64RPC(0xa8), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0xa8), P64RPC(0xe4), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x44), P64RPC(0x00)},
{P64RPC(0x24), P64RPC(0x18), P64RPC(0x8c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xbc), P64RPC(0xb0)},
{P64RPC(0x40), P64RPC(0x2c), P64RPC(0x00)},
{P64RPC(0xe4), P64RPC(0x00), P64RPC(0x58)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x5c), P64RPC(0x94), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x80), P64RPC(0x88)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x20), P64RPC(0x38), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x94), P64RPC(0x00)},
{P64RPC(0x88), P64RPC(0x70), P64RPC(0x00)},
{P64RPC(0xc8), P64RPC(0x4c), P64RPC(0x0c)},
{P64RPC(0x00), P64RPC(0x90), P64RPC(0x38)},
{P64RPC(0x74), P64RPC(0x74), P64RPC(0x74)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0xa8)},
{P64RPC(0xd8), P64RPC(0x28), P64RPC(0x00)},
{P64RPC(0xa4), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xc4), P64RPC(0xd8)},
{P64RPC(0x40), P64RPC(0x88), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xd8), P64RPC(0xa8)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0x98), P64RPC(0x38)},
{P64RPC(0xfc), P64RPC(0x74), P64RPC(0x60)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x80), P64RPC(0xd0), P64RPC(0x10)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x3c), P64RPC(0xbc), P64RPC(0xfc)},
{P64RPC(0xf4), P64RPC(0x78), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x70), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0xe8), P64RPC(0xd8)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x7c), P64RPC(0x08), P64RPC(0x00)},
{P64RPC(0x4c), P64RPC(0xdc), P64RPC(0x48)},
{P64RPC(0xf0), P64RPC(0xbc), P64RPC(0x3c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x50), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xc4), P64RPC(0xd4), P64RPC(0xfc)},
{P64RPC(0xfc), P64RPC(0xd8), P64RPC(0xa8)},
{P64RPC(0x80), P64RPC(0x00), P64RPC(0xf0)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x18), P64RPC(0x3c), P64RPC(0x5c)},
+64 -64
View File
@@ -1,64 +1,64 @@
{0x88, 0x70, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x80, 0x88},
{0xf0, 0xbc, 0x3c},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x24, 0x18, 0x8c},
{0xc8, 0x4c, 0x0c},
{0xbc, 0xbc, 0xbc},
{0x00, 0x00, 0x00},
{0x4c, 0xdc, 0x48},
{0x00, 0x00, 0x00},
{0xfc, 0xbc, 0xb0},
{0xfc, 0xd8, 0xa8},
{0x00, 0xa8, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0x74, 0xb4},
{0x00, 0x00, 0x00},
{0x20, 0x38, 0xec},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0x74, 0x60},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x5c, 0x94, 0xfc},
{0x00, 0x94, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xa8, 0xf0, 0xbc},
{0x3c, 0xbc, 0xfc},
{0xa8, 0x00, 0x10},
{0x00, 0x50, 0x00},
{0x7c, 0x08, 0x00},
{0x00, 0x00, 0xa8},
{0x80, 0x00, 0xf0},
{0x00, 0x00, 0x00},
{0x74, 0x74, 0x74},
{0xe4, 0x00, 0x58},
{0x18, 0x3c, 0x5c},
{0x00, 0x00, 0x00},
{0x00, 0x70, 0xec},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0xe4, 0xa0},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x40, 0x2c, 0x00},
{0xd8, 0x28, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0xfc, 0xfc, 0xfc},
{0x9c, 0xfc, 0xf0},
{0x00, 0x00, 0x00},
{0xfc, 0x98, 0x38},
{0x00, 0x00, 0x00},
{0xa8, 0xe4, 0xfc},
{0x80, 0xd0, 0x10},
{0x00, 0x00, 0x00},
{0xfc, 0xfc, 0xfc},
{0x00, 0x44, 0x00},
{P64RPC(0x88), P64RPC(0x70), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x80), P64RPC(0x88)},
{P64RPC(0xf0), P64RPC(0xbc), P64RPC(0x3c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x24), P64RPC(0x18), P64RPC(0x8c)},
{P64RPC(0xc8), P64RPC(0x4c), P64RPC(0x0c)},
{P64RPC(0xbc), P64RPC(0xbc), P64RPC(0xbc)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x4c), P64RPC(0xdc), P64RPC(0x48)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xbc), P64RPC(0xb0)},
{P64RPC(0xfc), P64RPC(0xd8), P64RPC(0xa8)},
{P64RPC(0x00), P64RPC(0xa8), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0x74), P64RPC(0xb4)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x20), P64RPC(0x38), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0x74), P64RPC(0x60)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x5c), P64RPC(0x94), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x94), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xa8), P64RPC(0xf0), P64RPC(0xbc)},
{P64RPC(0x3c), P64RPC(0xbc), P64RPC(0xfc)},
{P64RPC(0xa8), P64RPC(0x00), P64RPC(0x10)},
{P64RPC(0x00), P64RPC(0x50), P64RPC(0x00)},
{P64RPC(0x7c), P64RPC(0x08), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0xa8)},
{P64RPC(0x80), P64RPC(0x00), P64RPC(0xf0)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x74), P64RPC(0x74), P64RPC(0x74)},
{P64RPC(0xe4), P64RPC(0x00), P64RPC(0x58)},
{P64RPC(0x18), P64RPC(0x3c), P64RPC(0x5c)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x70), P64RPC(0xec)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xe4), P64RPC(0xa0)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x40), P64RPC(0x2c), P64RPC(0x00)},
{P64RPC(0xd8), P64RPC(0x28), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x9c), P64RPC(0xfc), P64RPC(0xf0)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0x98), P64RPC(0x38)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xa8), P64RPC(0xe4), P64RPC(0xfc)},
{P64RPC(0x80), P64RPC(0xd0), P64RPC(0x10)},
{P64RPC(0x00), P64RPC(0x00), P64RPC(0x00)},
{P64RPC(0xfc), P64RPC(0xfc), P64RPC(0xfc)},
{P64RPC(0x00), P64RPC(0x44), P64RPC(0x00)},
+78 -20
View File
@@ -57,6 +57,7 @@
#define PPU_status (PPU[2])
#define READPALNOGS(ofs) (PALRAM[(ofs)])
#define READPAL(ofs) (PALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF))
#define READUPAL(ofs) (UPALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF))
@@ -455,13 +456,24 @@ volatile int rendercount, vromreadcount, undefinedvromcount, LogAddress = -1;
unsigned char *cdloggervdata = NULL;
unsigned int cdloggerVideoDataSize = 0;
int GetCHRAddress(int A) {
if (cdloggerVideoDataSize) {
int result = &VPage[A >> 10][A] - CHRptr[0];
int GetCHRAddress(int A)
{
if (cdloggerVideoDataSize)
{
int result = -1;
if ( (A >= 0) && (A < 0x2000) )
{
result = &VPage[A >> 10][A] - CHRptr[0];
}
if ((result >= 0) && (result < (int)cdloggerVideoDataSize))
{
return result;
} else
if(A < 0x2000) return A;
}
}
else
{
if ( (A >= 0) && (A < 0x2000) ) return A;
}
return -1;
}
@@ -1722,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) {
@@ -1987,6 +2006,7 @@ void runppu(int x) {
struct BGData {
struct Record {
uint8 nt, pecnt, at, pt[2], qtnt;
uint8 ppu1[8];
INLINE void Read() {
NTRefreshAddr = RefreshAddr = ppur.get_ntread();
@@ -1998,7 +2018,12 @@ struct BGData {
}
pecnt = (RefreshAddr & 1) << 3;
nt = CALL_PPUREAD(RefreshAddr);
runppu(kFetchTime);
ppu1[0] = PPU[1];
runppu(1);
ppu1[1] = PPU[1];
runppu(1);
RefreshAddr = ppur.get_atread();
at = CALL_PPUREAD(RefreshAddr);
@@ -2010,37 +2035,57 @@ struct BGData {
at <<= 2;
//horizontal scroll clocked at cycle 3 and then
//vertical scroll at 251
ppu1[2] = PPU[1];
runppu(1);
if (PPUON) {
ppur.increment_hsc();
if (ppur.status.cycle == 251)
ppur.increment_vs();
}
ppu1[3] = PPU[1];
runppu(1);
ppur.par = nt;
RefreshAddr = ppur.get_ptread();
if (PEC586Hack) {
pt[0] = CALL_PPUREAD(RefreshAddr | pecnt);
runppu(kFetchTime);
ppu1[4] = PPU[1];
runppu(1);
ppu1[5] = PPU[1];
runppu(1);
pt[1] = CALL_PPUREAD(RefreshAddr | pecnt);
runppu(kFetchTime);
ppu1[6] = PPU[1];
runppu(1);
ppu1[7] = PPU[1];
runppu(1);
} else if (QTAIHack && (qtnt & 0x40)) {
pt[0] = *(CHRptr[0] + RefreshAddr);
runppu(kFetchTime);
ppu1[4] = PPU[1];
runppu(1);
ppu1[5] = PPU[1];
runppu(1);
RefreshAddr |= 8;
pt[1] = *(CHRptr[0] + RefreshAddr);
runppu(kFetchTime);
ppu1[6] = PPU[1];
runppu(1);
ppu1[7] = PPU[1];
runppu(1);
} else {
if (ScreenON)
RENDER_LOG(RefreshAddr);
pt[0] = CALL_PPUREAD(RefreshAddr);
runppu(kFetchTime);
ppu1[4] = PPU[1];
runppu(1);
ppu1[5] = PPU[1];
runppu(1);
RefreshAddr |= 8;
if (ScreenON)
RENDER_LOG(RefreshAddr);
pt[1] = CALL_PPUREAD(RefreshAddr);
runppu(kFetchTime);
ppu1[6] = PPU[1];
runppu(1);
ppu1[7] = PPU[1];
runppu(1);
}
}
};
@@ -2216,7 +2261,7 @@ int FCEUX_PPU_Loop(int skip) {
pixel = ((pt[0] >> (7 - bgpx)) & 1) | (((pt[1] >> (7 - bgpx)) & 1) << 1) | bgdata.main[bgtile].at;
}
if (renderbg)
pixelcolor = READPAL(pixel);
pixelcolor = READPALNOGS(pixel);
//look for a sprite to be drawn
bool havepixel = false;
@@ -2261,12 +2306,25 @@ int FCEUX_PPU_Loop(int skip) {
spixel |= (oam[2] & 3) << 2;
if (rendersprites)
pixelcolor = READPAL(0x10 + spixel);
pixelcolor = READPALNOGS(0x10 + spixel);
}
}
*ptr++ = PaletteAdjustPixel(pixelcolor);
*dptr++= PPU[1]>>5; //grab deemph
//apply grayscale.. kind of clunky
//really we need to read the entire palette instead of just ppu1
//this will be needed for special color effects probably (very fine rainbows and whatnot?)
//are you allowed to chang the palette mid-line anyway? well you can definitely change the grayscale flag as we know from the FF1 "polygon" effect
if(bgdata.main[xt+2].ppu1[xp]&1)
pixelcolor &= 0x30;
//this does deemph stuff inside it.. which is probably wrong...
*ptr = PaletteAdjustPixel(pixelcolor);
ptr++;
//grab deemph..
//I guess this works the same way as the grayscale, ideally?
*dptr++ = bgdata.main[xt+2].ppu1[xp]>>5;
}
}
}
+1 -1
View File
@@ -6,7 +6,7 @@ uint8 tmpd;
#endif
#ifndef PPUT_MMC5SP
uint8 zz;
FCEU_MAYBE_UNUSED uint8 zz;
#else
uint8 xs, ys;
xs = X1;
+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__
+3 -2
View File
@@ -534,9 +534,10 @@ static INLINE void DMCDMA(void)
PrepDPCM();
else
{
SIRQStat|=0x80;
if(DMCFormat&0x80)
if(DMCFormat&0x80) {
SIRQStat|=0x80;
X6502_IRQBegin(FCEU_IQDPCM);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More