Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 07de1ad746 | |||
| 23bc100386 | |||
| f2c6ba0c43 | |||
| 7e9cde361e | |||
| ee3ffeeacc | |||
| 8a1427db5c | |||
| 10724c5437 | |||
| 88b1044105 |
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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 ---------------------------
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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");
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -6,7 +6,7 @@ uint8 tmpd;
|
||||
#endif
|
||||
|
||||
#ifndef PPUT_MMC5SP
|
||||
uint8 zz;
|
||||
FCEU_MAYBE_UNUSED uint8 zz;
|
||||
#else
|
||||
uint8 xs, ys;
|
||||
xs = X1;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user