Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 07de1ad746 | |||
| 23bc100386 | |||
| f2c6ba0c43 | |||
| 7e9cde361e | |||
| ee3ffeeacc | |||
| 8a1427db5c | |||
| 10724c5437 | |||
| 88b1044105 | |||
| 1b76eae51e | |||
| 4db4639569 | |||
| 1e9dc7ee26 | |||
| e62374c88d | |||
| c4ea492891 | |||
| 4b460d1cb8 | |||
| 14cfd5c93c | |||
| 14a65ab35d | |||
| 46d186d251 | |||
| b1a06da5ba | |||
| 7bd6e5ea8b | |||
| 9d79c1a4a5 | |||
| c1271716eb |
Binary file not shown.
+88
-1079
File diff suppressed because it is too large
Load Diff
+24
-2
@@ -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
|
||||
@@ -479,8 +479,25 @@ const int NESMap[] = {JOY_UP, JOY_DOWN, JOY_LEFT, JOY_RIGHT, JOY_A, JOY_B, JOY_S
|
||||
int address, value, compare;
|
||||
int type = 1;
|
||||
|
||||
if (FCEUI_DecodeGG(cCode, &address, &value, &compare))
|
||||
if (singleCode.length == 7 && [singleCode characterAtIndex:4] == ':')
|
||||
{
|
||||
address = (int)strtoul([singleCode substringToIndex:4].UTF8String, NULL, 16);
|
||||
value = (int)strtoul([singleCode substringFromIndex:5].UTF8String, NULL, 16);
|
||||
compare = -1;
|
||||
FCEUI_AddCheat(cCode, address, value, compare, type);
|
||||
}
|
||||
else if (singleCode.length == 10 && [singleCode characterAtIndex:4] == '?' && [singleCode characterAtIndex:7] == ':')
|
||||
{
|
||||
address = (int)strtoul([singleCode substringToIndex:4].UTF8String, NULL, 16);
|
||||
compare = (int)strtoul([singleCode substringWithRange:NSMakeRange(5, 2)].UTF8String, NULL, 16);
|
||||
value = (int)strtoul([singleCode substringFromIndex:8].UTF8String, NULL, 16);
|
||||
FCEUI_AddCheat(cCode, address, value, compare, type);
|
||||
}
|
||||
else if (FCEUI_DecodeGG(cCode, &address, &value, &compare))
|
||||
FCEUI_AddCheat(cCode, address, value, compare, type);
|
||||
// Does not work
|
||||
// else if (FCEUI_DecodePAR(cCode, &address, &value, &compare, &type))
|
||||
// FCEUI_AddCheat(cCode, address, value, compare, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -778,7 +795,9 @@ 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;}
|
||||
int FCEUD_SendData(void *data, uint32 len) {return 1;}
|
||||
int FCEUD_RecvData(void *data, uint32 len) {return 1;}
|
||||
@@ -806,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;}
|
||||
@@ -815,6 +835,8 @@ bool FCEUI_AviIsRecording(void) {return false;}
|
||||
bool FCEUI_AviDisableMovieMessages() {return true;}
|
||||
FCEUFILE *FCEUD_OpenArchiveIndex(ArchiveScanRecord &asr, std::string &fname, int innerIndex) {return 0;}
|
||||
FCEUFILE *FCEUD_OpenArchive(ArchiveScanRecord &asr, std::string &fname, std::string *innerFilename) {return 0;}
|
||||
FCEUFILE *FCEUD_OpenArchiveIndex(ArchiveScanRecord &asr, std::string &fname, int innerIndex, int *userCancel) {return 0;}
|
||||
FCEUFILE *FCEUD_OpenArchive(ArchiveScanRecord &asr, std::string &fname, std::string *innerFilename, int *userCancel) {return 0;}
|
||||
ArchiveScanRecord FCEUD_ScanArchive(std::string fname) { return ArchiveScanRecord(); }
|
||||
void GetMouseData(uint32 (&md)[3]) {}
|
||||
void FCEUD_PrintError(const char *s)
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.2.3.1</string>
|
||||
<string>2.6.6</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>OEGameCoreController</string>
|
||||
<key>OEGameCoreClass</key>
|
||||
@@ -41,7 +41,7 @@
|
||||
<key>OEGameCorePlayerCount</key>
|
||||
<string>4</string>
|
||||
<key>OEProjectURL</key>
|
||||
<string>http://sourceforge.net/projects/fceultra/</string>
|
||||
<string>https://github.com/TASEmulators/fceux</string>
|
||||
<key>OESystemIdentifiers</key>
|
||||
<array>
|
||||
<string>openemu.system.nes</string>
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
@@ -0,0 +1,731 @@
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set( APP_NAME fceux)
|
||||
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 )
|
||||
else()
|
||||
message( STATUS "GUI Frontend: Qt5")
|
||||
set( Qt Qt5 )
|
||||
endif()
|
||||
|
||||
if ( ${QHELP} )
|
||||
set(QtHelpModule Help)
|
||||
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} )
|
||||
include_directories( ${Qt6Widgets_INCLUDE_DIRS} ${Qt6Help_INCLUDE_DIRS} ${Qt6OpenGLWidgets_INCLUDE_DIRS} )
|
||||
else()
|
||||
find_package( Qt5 REQUIRED COMPONENTS Widgets OpenGL ${QtHelpModule})
|
||||
add_definitions( ${Qt5Widgets_DEFINITIONS} ${Qt5Help_DEFINITIONS} )
|
||||
include_directories( ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Help_INCLUDE_DIRS} )
|
||||
endif()
|
||||
|
||||
|
||||
if(WIN32)
|
||||
find_package(OpenGL REQUIRED)
|
||||
#find_package(Qt5 COMPONENTS Widgets OpenGL REQUIRED)
|
||||
#add_definitions( ${Qt5Widgets_DEFINITIONS} )
|
||||
#include_directories( ${Qt5Widgets_INCLUDE_DIRS} )
|
||||
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 )
|
||||
|
||||
if ( ${USE_LIBAV} )
|
||||
add_definitions( -D_USE_LIBAV ${LIBAV_CFLAGS} )
|
||||
include_directories( ${FFMPEG_INSTALL_PREFIX}/ffmpeg/include )
|
||||
set( LIBAV_LDFLAGS ${FFMPEG_INSTALL_PREFIX}/ffmpeg/lib/avcodec.lib
|
||||
${FFMPEG_INSTALL_PREFIX}/ffmpeg/lib/avformat.lib
|
||||
${FFMPEG_INSTALL_PREFIX}/ffmpeg/lib/avutil.lib
|
||||
${FFMPEG_INSTALL_PREFIX}/ffmpeg/lib/swscale.lib
|
||||
${FFMPEG_INSTALL_PREFIX}/ffmpeg/lib/swresample.lib )
|
||||
endif()
|
||||
|
||||
else(WIN32)
|
||||
# Non Windows System
|
||||
# UNIX (Linux or Mac OSX)
|
||||
|
||||
if ( ${GLVND} )
|
||||
message( STATUS "OpenGL preference: GLVND")
|
||||
set (OpenGL_GL_PREFERENCE GLVND)
|
||||
else()
|
||||
message( STATUS "OpenGL preference: LEGACY")
|
||||
set (OpenGL_GL_PREFERENCE LEGACY)
|
||||
endif()
|
||||
|
||||
# Use the built-in cmake find_package functions to find dependencies
|
||||
# Use package PkgConfig to detect headers/library what find_package cannot find.
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
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} )
|
||||
# find_package( Qt6 COMPONENTS Widgets OpenGL OpenGLWidgets REQUIRED)
|
||||
# add_definitions( ${Qt6Widgets_DEFINITIONS} ${Qt6OpenGLWidgets_DEFINITIONS} )
|
||||
# include_directories( ${Qt6Widgets_INCLUDE_DIRS} ${QtOpenGLWidgets_INCLUDE_DIRS} )
|
||||
#else()
|
||||
# find_package( Qt5 COMPONENTS Widgets OpenGL REQUIRED)
|
||||
# add_definitions( ${Qt5Widgets_DEFINITIONS} )
|
||||
# include_directories( ${Qt5Widgets_INCLUDE_DIRS} )
|
||||
#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)
|
||||
|
||||
if ( ${MINIZIP_FOUND} )
|
||||
message( STATUS "Using System minizip ${MINIZIP_VERSION}" )
|
||||
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} )
|
||||
message( STATUS "Using System X264 Encoder Library ${X264_VERSION}" )
|
||||
add_definitions( -D_USE_X264 ${X264_CFLAGS} )
|
||||
endif()
|
||||
|
||||
pkg_check_modules( X265 x265)
|
||||
|
||||
if ( ${X265_FOUND} )
|
||||
message( STATUS "Using System X265 Encoder Library ${X265_VERSION}" )
|
||||
add_definitions( -D_USE_X265 ${X265_CFLAGS} )
|
||||
endif()
|
||||
|
||||
pkg_check_modules( LIBAV libavcodec libavformat libavutil libswresample libswscale)
|
||||
|
||||
if ( ${LIBAV_FOUND} )
|
||||
message( STATUS "Using System Libav Library ${LIBAV_VERSION}" )
|
||||
add_definitions( -D_USE_LIBAV ${LIBAV_CFLAGS} )
|
||||
endif()
|
||||
|
||||
#find_package(X11)
|
||||
pkg_check_modules( X11 x11)
|
||||
|
||||
if ( ${X11_FOUND} )
|
||||
message( STATUS "Has X11 Library ${X11_VERSION}" )
|
||||
add_definitions( -D_HAS_X11 )
|
||||
include_directories( ${X11_INCLUDE_DIR} )
|
||||
endif()
|
||||
|
||||
pkg_check_modules( XKB xkbcommon)
|
||||
|
||||
if ( ${XKB_FOUND} )
|
||||
message( STATUS "Has XKB Library ${XKB_VERSION}" )
|
||||
add_definitions( -D_HAS_XKB ${XKB_CFLAGS} )
|
||||
endif()
|
||||
|
||||
#pkg_check_modules( GL gl) # Use built in find package instead for OpenGL
|
||||
|
||||
# Check for OpenGL
|
||||
if ( ${OPENGL_FOUND} )
|
||||
include_directories( ${OPENGL_INCLUDE_DIR} )
|
||||
endif()
|
||||
|
||||
# Check for SDL2
|
||||
pkg_check_modules( SDL2 REQUIRED sdl2)
|
||||
|
||||
if ( ${SDL2_FOUND} )
|
||||
add_definitions( ${SDL2_CFLAGS} -D__SDL__ )
|
||||
endif()
|
||||
|
||||
# Check for LUA
|
||||
pkg_search_module( LUA lua5.1 lua-5.1 )
|
||||
|
||||
add_definitions( -DHAVE_ASPRINTF ) # What system wouldn't have this?
|
||||
add_definitions( -DLUA_USE_LINUX ) # This needs to be set when link LUA internally for linux and macosx
|
||||
|
||||
if(APPLE)
|
||||
set( OPENGL_LDFLAGS "-framework OpenGL" )
|
||||
else()
|
||||
set( OPENGL_LDFLAGS ${OPENGL_LIBRARIES} )
|
||||
# OpenBSD refuses to implement the POSIX realtime interface and
|
||||
# refuses to provide a stub library for -ldl
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
|
||||
set( SYS_LIBS -lpthread)
|
||||
else()
|
||||
set( SYS_LIBS -lrt -lpthread -ldl)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endif(WIN32)
|
||||
|
||||
if ( ${LUA_FOUND} )
|
||||
# Use System LUA
|
||||
message( STATUS "Using System Lua ${LUA_VERSION}" )
|
||||
|
||||
add_definitions( -D_S9XLUA_H ${LUA_CFLAGS} )
|
||||
|
||||
set( LUA_ENGINE_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/lua-engine.cpp )
|
||||
|
||||
else ()
|
||||
|
||||
# Use Internal LUA
|
||||
message( STATUS "Using Internal Lua" )
|
||||
|
||||
add_definitions( -D_S9XLUA_H -I${CMAKE_CURRENT_SOURCE_DIR}/lua/src )
|
||||
|
||||
set( LUA_ENGINE_SOURCE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lapi.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lauxlib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lbaselib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lcode.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/ldblib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/ldebug.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/ldo.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/ldump.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lfunc.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lgc.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/linit.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/liolib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/llex.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lmathlib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lmem.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/loadlib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lobject.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lopcodes.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/loslib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lparser.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lstate.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lstring.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lstrlib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/ltable.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/ltablib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/ltm.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lundump.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lvm.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/lzio.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua/src/print.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lua-engine.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if ( ${ZLIB_FOUND} )
|
||||
|
||||
message( STATUS "Using System zlib ${ZLIB_VERSION_STRING}" )
|
||||
#add_definitions( ${ZLIB_CFLAGS} )
|
||||
include_directories( ${ZLIB_INCLUDE_DIRS} )
|
||||
else()
|
||||
|
||||
message( STATUS "Using Internal zlib" )
|
||||
|
||||
set( ZLIB_SOURCE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/adler32.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/compress.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/crc32.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/deflate.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/gzio.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/infblock.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/infcodes.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/inffast.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/inflate.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/inftrees.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/infutil.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/trees.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/uncompr.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/unzip.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib/zutil.c
|
||||
)
|
||||
endif()
|
||||
|
||||
include_directories( ${CMAKE_SOURCE_DIR}/src )
|
||||
include_directories( ${CMAKE_SOURCE_DIR}/src/drivers )
|
||||
|
||||
if(APPLE)
|
||||
add_definitions( -DPSS_STYLE=1 )
|
||||
else(APPLE)
|
||||
if(UNIX)
|
||||
add_definitions( -DPSS_STYLE=1 )
|
||||
endif(UNIX)
|
||||
endif(APPLE)
|
||||
|
||||
set(SRC_CORE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/asm.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cart.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cheat.cpp
|
||||
${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
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/file.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/emufile.cpp
|
||||
${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
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/unif.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/video.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vsuni.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wave.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/x6502.cpp
|
||||
${LUA_ENGINE_SOURCE}
|
||||
${ZLIB_SOURCE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/01-222.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/09-034a.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/103.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/106.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/108.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/112.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/116.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/117.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/120.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/121.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/12in1.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/151.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/156.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/158B.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/15.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/164.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/168.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/170.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/175.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/176.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/177.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/178.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/183.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/185.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/186.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/187.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/189.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/18.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/190.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/193.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/199.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/206.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/208.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/222.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/225.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/228.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/230.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/232.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/234.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/235.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/244.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/246.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/252.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/253.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/28.cpp
|
||||
${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
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/411120-c.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/41.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/42.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/43.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/46.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/50.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/51.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/57.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/603-5052.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/62.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/65.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/67.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/68.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/69.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/71.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/72.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/77.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/79.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/80013-B.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/80.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/8157.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/8237.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/82.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/830118C.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/88.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/8in1.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/90.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/91.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/96.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/99.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/a9746.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ac-08.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/addrlatch.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ax5705.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bandai.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bb.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bmc13in1jy110.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bmc42in1r.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bmc64in1nr.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bmc70in1.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/BMW8544.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bonza.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bs-5.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/bs4xxxr.cpp
|
||||
${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
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/__dummy_mapper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/edu2000.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/eh8813a.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/emu2413.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/et-100.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/et-4320.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/F-15.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/famicombox.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ffe.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/fk23c.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/fns.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ghostbusters63in1.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/gs-2004.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/gs-2013.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/h2288.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/hp10xx_hp20xx.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/hp898f.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/inlnsf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/karaoke.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/kof97.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7010.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7012.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7013.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7016.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7017.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7030.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7031.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7032.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7037.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/ks7057.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/le05.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/lh32.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/lh53.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/malee.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/mihunche.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/mmc1.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/mmc2and4.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/mmc3.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/mmc5.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/n106.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/n625092.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/novel.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/onebus.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/pec-586.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/rt-01.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/sa-9602b.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/sachen.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/sb-2000.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/sc-127.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/sheroes.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/sl1632.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/subor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/super24.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/supervision.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/t-227-1.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/t-262.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/tengen.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/tf-1201.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/transformer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/unrom512.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc1.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc2and4.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc3.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc5.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc6.cpp
|
||||
${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
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/fkb.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/fns.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/ftrainer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/hypershot.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/mahjong.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/mouse.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/oekakids.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/pec586kb.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/powerpad.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/quiz.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/shadow.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/snesmouse.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/suborkb.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/toprider.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/virtualboy.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/lcdcompzapper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/input/zapper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils/backward.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils/xstring.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils/crc32.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils/endian.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils/general.cpp
|
||||
${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/configSys.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/hq2x.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/hq3x.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/scale2x.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/scale3x.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/scalebit.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/vidblit.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/os_utils.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/nes_ntsc.c
|
||||
)
|
||||
|
||||
set(SRC_DRIVERS_SDL
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/main.cpp
|
||||
${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
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HotKeyConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TimingConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/FrameTimingStats.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/PaletteConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/PaletteEditor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ColorMenu.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GuiConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HelpPages.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/MoviePlay.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/MovieRecord.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/MovieOptions.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/LuaControl.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/CheatsConf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GameGenie.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HexEditor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/MsgLogViewer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/CodeDataLogger.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/SymbolicDebug.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleDebugger.cpp
|
||||
${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
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/AboutWindow.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/fceuWrapper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ppuViewer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/NameTableViewer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/RamWatch.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/RamSearch.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/config.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/input.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/nes_shm.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/keyscan.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/sdl-sound.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/sdl-video.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/sdl-joystick.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/sdl-throttle.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/unix-netplay.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/AviRecord.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/AviRiffViewer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/avi/avi-utils.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/avi/fileio.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/avi/gwavi.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/TasEditorWindow.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/taseditor_project.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/taseditor_config.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/taseditor_lua.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/markers_manager.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/greenzone.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/selection.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/playback.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/recorder.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/history.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/splicer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/inputlog.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/laglog.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/branches.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/bookmarks.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/bookmark.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/snapshot.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TasEditor/markers.cpp
|
||||
)
|
||||
|
||||
set(SOURCES ${SRC_CORE} ${SRC_DRIVERS_COMMON} ${SRC_DRIVERS_SDL})
|
||||
|
||||
# Put build timestamp into BUILD_TS environment variable and from there into
|
||||
# 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" UTC)
|
||||
add_definitions( -DFCEUX_BUILD_TIMESTAMP=\"${BUILD_TS}\" )
|
||||
|
||||
if (WIN32)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/scripts/genGitHdr.bat ${CMAKE_CURRENT_BINARY_DIR}
|
||||
VERBATIM )
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/scripts/genGitHdr.sh ${CMAKE_CURRENT_BINARY_DIR}
|
||||
VERBATIM )
|
||||
endif()
|
||||
|
||||
set_property(SOURCE ${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp PROPERTY SKIP_AUTOGEN ON)
|
||||
|
||||
if (APPLE)
|
||||
|
||||
set(MACOSX_BUNDLE_ICON_FILE fceux.icns)
|
||||
set(APP_ICON ${CMAKE_SOURCE_DIR}/fceux.icns )
|
||||
set_source_files_properties( ${APP_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources" )
|
||||
|
||||
add_executable( ${APP_NAME} MACOSX_BUNDLE ${APP_ICON} ${SOURCES} ../resources.qrc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp)
|
||||
elseif (WIN32)
|
||||
|
||||
add_executable( ${APP_NAME} ${SOURCES} ../resources.qrc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp
|
||||
${APP_ICON_RESOURCES_WINDOWS} )
|
||||
else()
|
||||
add_executable( ${APP_NAME} ${SOURCES} ../resources.qrc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp)
|
||||
endif()
|
||||
|
||||
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} ${LIBARCHIVE_LDFLAGS}
|
||||
${LUA_LDFLAGS} ${X264_LDFLAGS} ${X265_LDFLAGS} ${LIBAV_LDFLAGS}
|
||||
${SYS_LIBS}
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
# target_link_libraries( ${APP_NAME} wsock32 ws2_32 )
|
||||
|
||||
set_target_properties(${APP_NAME} PROPERTIES WIN32_EXECUTABLE TRUE)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
|
||||
install( TARGETS ${APP_NAME}
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION bin COMPONENT Runtime )
|
||||
|
||||
# Use \$ to defer expansion until install script is called; CPack will call it with its own CMAKE_INSTALL_PREFIX
|
||||
set(APP \${CMAKE_INSTALL_PREFIX}/${APP_NAME}.app)
|
||||
|
||||
install( DIRECTORY ${CMAKE_SOURCE_DIR}/output/.
|
||||
DESTINATION ${APP_NAME}.app/Contents/Resources COMPONENT Extra )
|
||||
|
||||
set(CPACK_PACKAGE_ICON ${CMAKE_SOURCE_DIR}/fceux.icns )
|
||||
set(CPACK_GENERATOR "DragNDrop")
|
||||
include(CPACK)
|
||||
|
||||
# macdeployqt tool that comes with Qt: https://doc.qt.io/qt-5/macos-deployment.html#macdeploy
|
||||
# Compared to fixup_bundle, correctly finds and installs Qt-specific resources as well as non-Qt dependencies
|
||||
find_program(MACDEPLOYQT macdeployqt)
|
||||
if(NOT MACDEPLOYQT)
|
||||
message(FATAL_ERROR "Could not find macdeployqt executable")
|
||||
endif()
|
||||
|
||||
find_package(Perl REQUIRED)
|
||||
|
||||
install( CODE "
|
||||
message(STATUS \"Deploying and fixing up dependencies in app: ${APP}\")
|
||||
execute_process(COMMAND \"${MACDEPLOYQT}\" \"${APP}\" -verbose=1)
|
||||
execute_process(COMMAND \"${PERL_EXECUTABLE}\"
|
||||
\"${CMAKE_SOURCE_DIR}/scripts/macOSX_BundleFix.pl\"
|
||||
\"${CMAKE_BINARY_DIR}/_CPack_Packages\")
|
||||
"
|
||||
COMPONENT Runtime
|
||||
)
|
||||
|
||||
else(APPLE)
|
||||
|
||||
install( TARGETS ${APP_NAME}
|
||||
RUNTIME DESTINATION bin )
|
||||
|
||||
install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/auxlib.lua DESTINATION share/fceux/luaScripts )
|
||||
install( DIRECTORY ${CMAKE_SOURCE_DIR}/output/. DESTINATION share/fceux )
|
||||
install( FILES ${CMAKE_SOURCE_DIR}/fceux1.png DESTINATION share/pixmaps )
|
||||
install( FILES ${CMAKE_SOURCE_DIR}/fceux.desktop DESTINATION share/applications )
|
||||
install( FILES ${CMAKE_SOURCE_DIR}/documentation/fceux.6 DESTINATION ${CMAKE_INSTALL_MANDIR}/man6 )
|
||||
install( FILES ${CMAKE_SOURCE_DIR}/documentation/fceux-net-server.6 DESTINATION ${CMAKE_INSTALL_MANDIR}/man6 )
|
||||
|
||||
endif(APPLE)
|
||||
@@ -1,42 +0,0 @@
|
||||
import glob
|
||||
file_list = glob.glob('*.cpp')
|
||||
file_list.remove('lua-engine.cpp') # use logic below for this
|
||||
|
||||
subdirs = Split("""
|
||||
boards
|
||||
drivers/common
|
||||
fir
|
||||
input
|
||||
utils
|
||||
""")
|
||||
#palettes
|
||||
|
||||
Import('env')
|
||||
Export('env')
|
||||
|
||||
if env['LUA']:
|
||||
file_list.append('lua-engine.cpp')
|
||||
if env['SYSTEM_LUA'] == 0:
|
||||
subdirs.append('lua')
|
||||
|
||||
if env['CREATE_AVI']:
|
||||
subdirs.append('drivers/videolog')
|
||||
|
||||
|
||||
|
||||
for dir in subdirs:
|
||||
subdir_files = SConscript('%s/SConscript' % dir)
|
||||
file_list.append(subdir_files)
|
||||
if env['PLATFORM'] == 'win32':
|
||||
platform_files = SConscript('drivers/win/SConscript')
|
||||
else:
|
||||
platform_files = SConscript('drivers/sdl/SConscript')
|
||||
file_list.append(platform_files)
|
||||
|
||||
print env['LINKFLAGS']
|
||||
|
||||
if env['PLATFORM'] == 'win32':
|
||||
fceux = env.Program('fceux.exe', file_list)
|
||||
else:
|
||||
fceux = env.Program('fceux', file_list)
|
||||
Return('fceux')
|
||||
+7
-7
@@ -16,7 +16,7 @@ int Assemble(unsigned char *output, int addr, char *str) {
|
||||
output[0] = output[1] = output[2] = 0;
|
||||
char astr[128],ins[4];
|
||||
int len = strlen(str);
|
||||
if ((!len) || (len > 0x127)) return 1;
|
||||
if ((!len) || (len > 127)) return 1;
|
||||
|
||||
strcpy(astr,str);
|
||||
str_ucase(astr);
|
||||
@@ -272,7 +272,7 @@ char *Disassemble(int addr, uint8 *opcode) {
|
||||
(a) = opcode[1] | opcode[2]<<8; \
|
||||
}
|
||||
#define zpIndex(a,i) { \
|
||||
(a) = opcode[1]+(i); \
|
||||
(a) = (opcode[1]+(i))&0xFF; \
|
||||
}
|
||||
#define indirectX(a) { \
|
||||
(a) = (opcode[1]+RX)&0xFF; \
|
||||
@@ -360,8 +360,8 @@ char *Disassemble(int addr, uint8 *opcode) {
|
||||
case 0xE6: strcpy(chr,"INC"); goto _zeropage;
|
||||
_zeropage:
|
||||
// ################################## Start of SP CODE ###########################
|
||||
// Change width to %04X
|
||||
sprintf(str,"%s $%04X = #$%02X", chr,opcode[1],GetMem(opcode[1]));
|
||||
// Change width to %04X // don't!
|
||||
sprintf(str,"%s $%02X = #$%02X", chr,opcode[1],GetMem(opcode[1]));
|
||||
// ################################## End of SP CODE ###########################
|
||||
break;
|
||||
|
||||
@@ -457,7 +457,7 @@ char *Disassemble(int addr, uint8 *opcode) {
|
||||
_zeropagex:
|
||||
zpIndex(tmp,RX);
|
||||
// ################################## Start of SP CODE ###########################
|
||||
// Change width to %04X
|
||||
// Change width to %04X // don't!
|
||||
sprintf(str,"%s $%02X,X @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
||||
// ################################## End of SP CODE ###########################
|
||||
break;
|
||||
@@ -515,8 +515,8 @@ char *Disassemble(int addr, uint8 *opcode) {
|
||||
_zeropagey:
|
||||
zpIndex(tmp,RY);
|
||||
// ################################## Start of SP CODE ###########################
|
||||
// Change width to %04X
|
||||
sprintf(str,"%s $%04X,Y @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
||||
// Change width to %04X // don't!
|
||||
sprintf(str,"%s $%02X,Y @ $%04X = #$%02X", chr,opcode[1],tmp,GetMem(tmp));
|
||||
// ################################## End of SP CODE ###########################
|
||||
break;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*
|
||||
* TXC mappers, originally much complex banksitching
|
||||
*
|
||||
* P/N PRG MAP, UNIF Name
|
||||
* 01-22111-000 (05-00002-010) (132, 22211) - MGC-001 Qi Wang
|
||||
* 01-22110-000 (52S ) - MGC-002 2-in-1 Gun
|
||||
* 01-22111-100 (02-00002-010) (173 ) - MGC-008 Mahjong Block
|
||||
@@ -27,6 +28,7 @@
|
||||
* 01-22000-400 (05-00002-010) (036 ) - MGC-015 Policeman
|
||||
* 01-22017-000 (05-PT017-080) (189 ) - MGC-017 Thunder Warrior
|
||||
* 01-11160-000 (04-02310-000) ( , 11160) - MGC-023 6-in-1
|
||||
* 01-22026-000 (05-04010-090) ( ) - MGC-026 4-in-1
|
||||
* 01-22270-000 (05-00002-010) (132, 22211) - MGC-xxx Creatom
|
||||
* 01-22200-400 (------------) (079 ) - ET.03 F-15 City War
|
||||
* (172 ) - 1991 Du Ma Racing
|
||||
|
||||
+89
-89
@@ -1,90 +1,90 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 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
|
||||
*
|
||||
* NTDEC, ASDER games
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 reg[8];
|
||||
static uint8 mirror, cmd, bank;
|
||||
static uint8 *WRAM = NULL;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &cmd, 1, "CMD" },
|
||||
{ &mirror, 1, "MIRR" },
|
||||
{ &bank, 1, "BANK" },
|
||||
{ reg, 8, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setmirror(mirror ^ 1);
|
||||
setprg8(0x8000, reg[0]);
|
||||
setprg8(0xA000, reg[1]);
|
||||
setchr2(0x0000, (reg[2] >> 1));
|
||||
setchr2(0x0800, (reg[3] >> 1));
|
||||
setchr1(0x1000, ((bank & 0x10) << 4) | reg[4]);
|
||||
setchr1(0x1400, ((bank & 0x20) << 3) | reg[5]);
|
||||
setchr1(0x1800, ((bank & 0x40) << 2) | reg[6]);
|
||||
setchr1(0x1C00, ((bank & 0x80) << 1) | reg[7]);
|
||||
}
|
||||
|
||||
static DECLFW(M112Write) {
|
||||
switch (A) {
|
||||
case 0xe000: mirror = V & 1; Sync();; break;
|
||||
case 0x8000: cmd = V & 7; break;
|
||||
case 0xa000: reg[cmd] = V; Sync(); break;
|
||||
case 0xc000: bank = V; Sync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void M112Close(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
static void M112Power(void) {
|
||||
bank = 0;
|
||||
setprg16(0xC000, ~0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M112Write);
|
||||
SetWriteHandler(0x4020, 0x5FFF, M112Write);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 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
|
||||
*
|
||||
* NTDEC, ASDER games
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 reg[8];
|
||||
static uint8 mirror, cmd, bank;
|
||||
static uint8 *WRAM = NULL;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &cmd, 1, "CMD" },
|
||||
{ &mirror, 1, "MIRR" },
|
||||
{ &bank, 1, "BANK" },
|
||||
{ reg, 8, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setmirror(mirror ^ 1);
|
||||
setprg8(0x8000, reg[0]);
|
||||
setprg8(0xA000, reg[1]);
|
||||
setchr2(0x0000, (reg[2] >> 1));
|
||||
setchr2(0x0800, (reg[3] >> 1));
|
||||
setchr1(0x1000, ((bank & 0x10) << 4) | reg[4]);
|
||||
setchr1(0x1400, ((bank & 0x20) << 3) | reg[5]);
|
||||
setchr1(0x1800, ((bank & 0x40) << 2) | reg[6]);
|
||||
setchr1(0x1C00, ((bank & 0x80) << 1) | reg[7]);
|
||||
}
|
||||
|
||||
static DECLFW(M112Write) {
|
||||
switch (A) {
|
||||
case 0xe000: mirror = V & 1; Sync();; break;
|
||||
case 0x8000: cmd = V & 7; break;
|
||||
case 0xa000: reg[cmd] = V; Sync(); break;
|
||||
case 0xc000: bank = V; Sync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void M112Close(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
static void M112Power(void) {
|
||||
bank = 0;
|
||||
setprg16(0xC000, ~0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M112Write);
|
||||
SetWriteHandler(0x4020, 0x5FFF, M112Write);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(8, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper112_Init(CartInfo *info) {
|
||||
info->Power = M112Power;
|
||||
info->Close = M112Close;
|
||||
GameStateRestore = StateRestore;
|
||||
WRAM = (uint8*)FCEU_gmalloc(8192);
|
||||
SetupCartPRGMapping(0x10, WRAM, 8192, 1);
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper112_Init(CartInfo *info) {
|
||||
info->Power = M112Power;
|
||||
info->Close = M112Close;
|
||||
GameStateRestore = StateRestore;
|
||||
WRAM = (uint8*)FCEU_gmalloc(8192);
|
||||
SetupCartPRGMapping(0x10, WRAM, 8192, 1);
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
+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);
|
||||
|
||||
+20
-14
@@ -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" },
|
||||
@@ -35,31 +35,39 @@ static SFORMAT StateRegs[] =
|
||||
static void Sync(void) {
|
||||
int i;
|
||||
setmirror(((latched >> 6) & 1) ^ 1);
|
||||
switch (latchea) {
|
||||
case 0x8000:
|
||||
switch (latchea & 3) {
|
||||
case 0:
|
||||
for (i = 0; i < 4; i++)
|
||||
setprg8(0x8000 + (i << 13), (((latched & 0x7F) << 1) + i) ^ (latched >> 7));
|
||||
setprg8(0x8000 + (i << 13), ((latched & 0x3F) << 1) + i);
|
||||
break;
|
||||
case 0x8002:
|
||||
case 2:
|
||||
for (i = 0; i < 4; i++)
|
||||
setprg8(0x8000 + (i << 13), ((latched & 0x7F) << 1) + (latched >> 7));
|
||||
setprg8(0x8000 + (i << 13), ((latched & 0x3F) << 1) + (latched >> 7));
|
||||
break;
|
||||
case 0x8001:
|
||||
case 0x8003:
|
||||
case 1:
|
||||
case 3:
|
||||
for (i = 0; i < 4; i++) {
|
||||
unsigned int b;
|
||||
b = latched & 0x7F;
|
||||
b = latched & 0x3F;
|
||||
if (i >= 2 && !(latchea & 0x2))
|
||||
b = 0x7F;
|
||||
setprg8(0x8000 + (i << 13), (i & 1) + ((b << 1) ^ (latched >> 7)));
|
||||
b = b | 0x07;
|
||||
setprg8(0x8000 + (i << 13), (i & 1) + (b << 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static DECLFW(M15Write) {
|
||||
latchea = A;
|
||||
latched = V;
|
||||
// cah4e3 02.10.19 once again, there may be either two similar mapper 15 exist. the one for 110in1 or 168in1 carts with complex multi game features.
|
||||
// and another implified version for subor/waixing chinese originals and hacks with no different modes, working only in mode 0 and which does not
|
||||
// expect there is any CHR write protection. protecting CHR writes only for mode 3 fixes the problem, all roms may be run on the same source again.
|
||||
if((latchea & 3) == 3)
|
||||
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0);
|
||||
else
|
||||
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1);
|
||||
Sync();
|
||||
}
|
||||
|
||||
@@ -70,7 +78,6 @@ static void StateRestore(int version) {
|
||||
static void M15Power(void) {
|
||||
latchea = 0x8000;
|
||||
latched = 0;
|
||||
setchr8(0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
@@ -101,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);
|
||||
|
||||
+226
-229
@@ -1,232 +1,229 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel 2006 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
|
||||
*
|
||||
* It seems that 162/163/164 mappers are the same mapper with just different
|
||||
* mapper modes enabled or disabled in software or hardware, need more nanjing
|
||||
* carts
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 laststrobe, trigger;
|
||||
static uint8 reg[8];
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
|
||||
static writefunc pcmwrite;
|
||||
|
||||
static void (*WSync)(void);
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &laststrobe, 1, "STB" },
|
||||
{ &trigger, 1, "TRG" },
|
||||
{ reg, 8, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
setprg32(0x8000, (reg[0] << 4) | (reg[1] & 0xF));
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
WSync();
|
||||
}
|
||||
|
||||
static DECLFR(ReadLow) {
|
||||
switch (A & 0x7700) {
|
||||
case 0x5100: return reg[2] | reg[0] | reg[1] | reg[3] ^ 0xff; break;
|
||||
case 0x5500:
|
||||
if (trigger)
|
||||
return reg[2] | reg[1]; // Lei Dian Huang Bi Ka Qiu Chuan Shuo (NJ046) may broke other games
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
static void M163HB(void) {
|
||||
if (reg[1] & 0x80) {
|
||||
if (scanline == 239) {
|
||||
setchr4(0x0000, 0);
|
||||
setchr4(0x1000, 0);
|
||||
} else if (scanline == 127) {
|
||||
setchr4(0x0000, 1);
|
||||
setchr4(0x1000, 1);
|
||||
}
|
||||
/*
|
||||
if(scanline>=127) // Hu Lu Jin Gang (NJ039) (Ch) [!] don't like it
|
||||
{
|
||||
setchr4(0x0000,1);
|
||||
setchr4(0x1000,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
setchr4(0x0000,0);
|
||||
setchr4(0x1000,0);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Write) {
|
||||
switch (A & 0x7300) {
|
||||
case 0x5100: reg[0] = V; WSync(); break;
|
||||
case 0x5000: reg[1] = V; WSync(); break;
|
||||
case 0x5300: reg[2] = V; break;
|
||||
case 0x5200: reg[3] = V; WSync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Power(void) {
|
||||
memset(reg, 0, 8);
|
||||
reg[1] = 0xFF;
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel 2006 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
|
||||
*
|
||||
* It seems that 162/163/164 mappers are the same mapper with just different
|
||||
* mapper modes enabled or disabled in software or hardware, need more nanjing
|
||||
* carts
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 laststrobe, trigger;
|
||||
static uint8 reg[8];
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE=0;
|
||||
|
||||
static writefunc pcmwrite;
|
||||
|
||||
static void (*WSync)(void);
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &laststrobe, 1, "STB" },
|
||||
{ &trigger, 1, "TRG" },
|
||||
{ reg, 8, "REGS" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
setprg32(0x8000, (reg[0] << 4) | (reg[1] & 0xF));
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
WSync();
|
||||
}
|
||||
|
||||
static DECLFR(ReadLow) {
|
||||
switch (A & 0x7700) {
|
||||
case 0x5100: return reg[2] | reg[0] | reg[1] | reg[3] ^ 0xff; break;
|
||||
case 0x5500:
|
||||
if (trigger)
|
||||
return reg[2] | reg[1]; // Lei Dian Huang Bi Ka Qiu Chuan Shuo (NJ046) may broke other games
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
static void M163HB(void) {
|
||||
if (reg[1] & 0x80) {
|
||||
if (scanline == 239) {
|
||||
setchr4(0x0000, 0);
|
||||
setchr4(0x1000, 0);
|
||||
} else if (scanline == 127) {
|
||||
setchr4(0x0000, 1);
|
||||
setchr4(0x1000, 1);
|
||||
}
|
||||
/*
|
||||
if(scanline>=127) // Hu Lu Jin Gang (NJ039) (Ch) [!] don't like it
|
||||
{
|
||||
setchr4(0x0000,1);
|
||||
setchr4(0x1000,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
setchr4(0x0000,0);
|
||||
setchr4(0x1000,0);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Write) {
|
||||
switch (A & 0x7300) {
|
||||
case 0x5100: reg[0] = V; WSync(); break;
|
||||
case 0x5000: reg[1] = V; WSync(); break;
|
||||
case 0x5300: reg[2] = V; break;
|
||||
case 0x5200: reg[3] = V; WSync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Power(void) {
|
||||
memset(reg, 0, 8);
|
||||
reg[1] = 0xFF;
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
WSync();
|
||||
}
|
||||
|
||||
static void Close(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
void Mapper164_Init(CartInfo *info) {
|
||||
info->Power = Power;
|
||||
info->Close = Close;
|
||||
WSync = Sync;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
static DECLFW(Write2) {
|
||||
if (A == 0x5101) {
|
||||
if (laststrobe && !V) {
|
||||
trigger ^= 1;
|
||||
}
|
||||
laststrobe = V;
|
||||
} else if (A == 0x5100 && V == 6) //damn thoose protected games
|
||||
setprg32(0x8000, 3);
|
||||
else
|
||||
switch (A & 0x7300) {
|
||||
case 0x5200: reg[0] = V; WSync(); break;
|
||||
case 0x5000: reg[1] = V; WSync(); if (!(reg[1] & 0x80) && (scanline < 128)) setchr8(0); /* setchr8(0); */ break;
|
||||
case 0x5300: reg[2] = V; break;
|
||||
case 0x5100: reg[3] = V; WSync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Power2(void) {
|
||||
memset(reg, 0, 8);
|
||||
laststrobe = 1;
|
||||
pcmwrite = GetWriteHandler(0x4011);
|
||||
SetReadHandler(0x5000, 0x5FFF, ReadLow);
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write2);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
WSync();
|
||||
}
|
||||
|
||||
static void Close(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
void Mapper164_Init(CartInfo *info) {
|
||||
info->Power = Power;
|
||||
info->Close = Close;
|
||||
WSync = Sync;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->addSaveGameBuf( WRAM, WRAMSIZE );
|
||||
}
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
static DECLFW(Write2) {
|
||||
if (A == 0x5101) {
|
||||
if (laststrobe && !V) {
|
||||
trigger ^= 1;
|
||||
}
|
||||
laststrobe = V;
|
||||
} else if (A == 0x5100 && V == 6) //damn thoose protected games
|
||||
setprg32(0x8000, 3);
|
||||
else
|
||||
switch (A & 0x7300) {
|
||||
case 0x5200: reg[0] = V; WSync(); break;
|
||||
case 0x5000: reg[1] = V; WSync(); if (!(reg[1] & 0x80) && (scanline < 128)) setchr8(0); /* setchr8(0); */ break;
|
||||
case 0x5300: reg[2] = V; break;
|
||||
case 0x5100: reg[3] = V; WSync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Power2(void) {
|
||||
memset(reg, 0, 8);
|
||||
laststrobe = 1;
|
||||
pcmwrite = GetWriteHandler(0x4011);
|
||||
SetReadHandler(0x5000, 0x5FFF, ReadLow);
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write2);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
WSync();
|
||||
}
|
||||
|
||||
void Mapper163_Init(CartInfo *info) {
|
||||
info->Power = Power2;
|
||||
info->Close = Close;
|
||||
WSync = Sync;
|
||||
GameHBIRQHook = M163HB;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
static void Sync3(void) {
|
||||
setchr8(0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
switch (reg[3] & 7) {
|
||||
case 0:
|
||||
case 2: setprg32(0x8000, (reg[0] & 0xc) | (reg[1] & 2) | ((reg[2] & 0xf) << 4)); break;
|
||||
case 1:
|
||||
case 3: setprg32(0x8000, (reg[0] & 0xc) | (reg[2] & 0xf) << 4); break;
|
||||
case 4:
|
||||
case 6: setprg32(0x8000, (reg[0] & 0xe) | ((reg[1] >> 1) & 1) | ((reg[2] & 0xf) << 4)); break;
|
||||
case 5:
|
||||
case 7: setprg32(0x8000, (reg[0] & 0xf) | ((reg[2] & 0xf) << 4)); break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Write3) {
|
||||
// FCEU_printf("bs %04x %02x\n",A,V);
|
||||
reg[(A >> 8) & 3] = V;
|
||||
WSync();
|
||||
}
|
||||
|
||||
static void Power3(void) {
|
||||
reg[0] = 3;
|
||||
reg[1] = 0;
|
||||
reg[2] = 0;
|
||||
reg[3] = 7;
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write3);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
WSync();
|
||||
}
|
||||
|
||||
void Mapper163_Init(CartInfo *info) {
|
||||
info->Power = Power2;
|
||||
info->Close = Close;
|
||||
WSync = Sync;
|
||||
GameHBIRQHook = M163HB;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->addSaveGameBuf( WRAM, WRAMSIZE );
|
||||
}
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
static void Sync3(void) {
|
||||
setchr8(0);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
switch (reg[3] & 7) {
|
||||
case 0:
|
||||
case 2: setprg32(0x8000, (reg[0] & 0xc) | (reg[1] & 2) | ((reg[2] & 0xf) << 4)); break;
|
||||
case 1:
|
||||
case 3: setprg32(0x8000, (reg[0] & 0xc) | (reg[2] & 0xf) << 4); break;
|
||||
case 4:
|
||||
case 6: setprg32(0x8000, (reg[0] & 0xe) | ((reg[1] >> 1) & 1) | ((reg[2] & 0xf) << 4)); break;
|
||||
case 5:
|
||||
case 7: setprg32(0x8000, (reg[0] & 0xf) | ((reg[2] & 0xf) << 4)); break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Write3) {
|
||||
// FCEU_printf("bs %04x %02x\n",A,V);
|
||||
reg[(A >> 8) & 3] = V;
|
||||
WSync();
|
||||
}
|
||||
|
||||
static void Power3(void) {
|
||||
reg[0] = 3;
|
||||
reg[1] = 0;
|
||||
reg[2] = 0;
|
||||
reg[3] = 7;
|
||||
SetWriteHandler(0x5000, 0x5FFF, Write3);
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
WSync();
|
||||
}
|
||||
|
||||
void UNLFS304_Init(CartInfo *info) {
|
||||
info->Power = Power3;
|
||||
info->Close = Close;
|
||||
WSync = Sync3;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
WSync();
|
||||
}
|
||||
|
||||
void UNLFS304_Init(CartInfo *info) {
|
||||
info->Power = Power3;
|
||||
info->Close = Close;
|
||||
WSync = Sync3;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->addSaveGameBuf( WRAM, WRAMSIZE );
|
||||
}
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
+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);
|
||||
|
||||
+4
-5
@@ -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]);
|
||||
@@ -37,8 +37,8 @@ static int32 SensorDelay;
|
||||
// highly experimental, not actually working, just curious if it hapen to work with some other decoder
|
||||
// SND Registers
|
||||
static uint8 pcm_enable = 0;
|
||||
static int16 pcm_latch = 0x3F6, pcm_clock = 0x3F6;
|
||||
static writefunc pcmwrite;
|
||||
//static int16 pcm_latch = 0x3F6, pcm_clock = 0x3F6;
|
||||
//static writefunc pcmwrite;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
@@ -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);
|
||||
|
||||
@@ -18,6 +18,33 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Family Study Box by Fukutake Shoten
|
||||
*
|
||||
* REG[0] R dddddddd / W ww---sss
|
||||
* ddd - TAPE DATA BYTE (ready when IRQ occurs)
|
||||
* sss - BRAM hi-bank
|
||||
* ww - PRAM bank
|
||||
* REG[1] R 0123---- / W ----PPPP
|
||||
* 0 - ?
|
||||
* 1 - ?
|
||||
* 2 - ?
|
||||
* 3 - ?
|
||||
* PPPP- PROM bank
|
||||
* REG[2] R -?--R--- / W A-BC-DEF
|
||||
* 4 - ?
|
||||
* R - sb4x power supply status (active low)
|
||||
* A - ?
|
||||
* B - ?
|
||||
* C - ?
|
||||
* D - ?
|
||||
* E - ?
|
||||
* F - ?
|
||||
*
|
||||
* BRAM0 4400-4FFF, 3K bank 0 (32K SWRAM) [hardwired]
|
||||
* BRAMB 5000-5FFF, 4K banks 1-7 (32K SWRAM) [REG[0] W -----sss]
|
||||
* PRAMB 6000-7FFF, 8K banks 1-3 (32K PRAM) [REG[0] W ww------]
|
||||
* PROMB 8000-BFFF, 16K banks 1-15 (256K PROM)[REG[1] W ----PPPP]
|
||||
* PROM0 C000-FFFF, 16K bank 0 (256K PROM) [hardwired]
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
+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);
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright (C) 2017 FCEUX Team
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Magic Kid GooGoo
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 prgr, chrr[4];
|
||||
static uint8 *WRAM = NULL;
|
||||
|
||||
static void Mapper190_Sync(void) {
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
|
||||
setprg16(0x8000, prgr);
|
||||
setprg16(0xC000, 0);
|
||||
setchr2(0x0000, chrr[0]);
|
||||
setchr2(0x0800, chrr[1]);
|
||||
setchr2(0x1000, chrr[2]);
|
||||
setchr2(0x1800, chrr[3]);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper190_Write89) { prgr = V&7; Mapper190_Sync(); }
|
||||
static DECLFW(Mapper190_WriteCD) { prgr = 8|(V&7); Mapper190_Sync(); }
|
||||
|
||||
static DECLFW(Mapper190_WriteAB) {
|
||||
int bank = A&3;
|
||||
chrr[bank] = V&63;
|
||||
Mapper190_Sync();
|
||||
}
|
||||
|
||||
|
||||
static void Mapper190_Power(void) {
|
||||
FCEU_CheatAddRAM(0x2000 >> 10, 0x6000, WRAM);
|
||||
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetWriteHandler(0x8000, 0x9FFF, Mapper190_Write89);
|
||||
SetWriteHandler(0xA000, 0xBFFF, Mapper190_WriteAB);
|
||||
SetWriteHandler(0xC000, 0xDFFF, Mapper190_WriteCD);
|
||||
Mapper190_Sync();
|
||||
|
||||
setmirror(MI_V);
|
||||
}
|
||||
|
||||
static void Mapper190_Close(void) {
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
static void Mapper190_Restore(int) {
|
||||
Mapper190_Sync();
|
||||
}
|
||||
|
||||
|
||||
void Mapper190_Init(CartInfo *info) {
|
||||
info->Power = Mapper190_Power;
|
||||
info->Close = Mapper190_Close;
|
||||
GameStateRestore = Mapper190_Restore;
|
||||
|
||||
WRAM = (uint8*)FCEU_gmalloc(0x2000);
|
||||
SetupCartPRGMapping(0x10, WRAM, 0x2000, 1);
|
||||
|
||||
chrr[0] = chrr[1] = chrr[2] = chrr[3] = prgr = 0;
|
||||
|
||||
AddExState(&prgr, 1, 0, "PRGR");
|
||||
AddExState(chrr, 4, 0, "CHRR");
|
||||
AddExState(WRAM, 0x2000, 0, "WRAM");
|
||||
}
|
||||
+43
-25
@@ -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,18 +63,21 @@ static DECLFW(M225Write) {
|
||||
}
|
||||
|
||||
static DECLFW(M225LoWrite) {
|
||||
/* e.g. 115-in-1 [p1][!] CRC32 0xb39d30b4 */
|
||||
if (A & 0x800) extraRAM[A & 3] = V & 0x0F;
|
||||
}
|
||||
|
||||
static DECLFR(M225LoRead) {
|
||||
return 0;
|
||||
if (A & 0x800) return extraRAM[A & 3];
|
||||
return X.DB;
|
||||
}
|
||||
|
||||
static void M225Power(void) {
|
||||
prg = 0;
|
||||
mode = 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);
|
||||
}
|
||||
@@ -84,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);
|
||||
|
||||
+6
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2012 FCEUX team
|
||||
Copyright (C) 2012-2017 FCEUX team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -53,8 +53,8 @@ void Mirror(uint8 value)
|
||||
|
||||
static void Sync()
|
||||
{
|
||||
int prglo;
|
||||
int prghi;
|
||||
int prglo = 0;
|
||||
int prghi = 0;
|
||||
|
||||
int outb = outer << 1;
|
||||
//this can probably be rolled up, but i have no motivation to do so
|
||||
@@ -127,20 +127,21 @@ static void Sync()
|
||||
|
||||
static DECLFW(WriteEXP)
|
||||
{
|
||||
uint32 addr = A;
|
||||
//uint32 addr = A;
|
||||
uint8 value = V;
|
||||
reg = value & 0x81;
|
||||
}
|
||||
|
||||
static DECLFW(WritePRG)
|
||||
{
|
||||
uint32 addr = A;
|
||||
//uint32 addr = A;
|
||||
uint8 value = V;
|
||||
switch (reg)
|
||||
{
|
||||
case 0x00:
|
||||
chr = value & 3;
|
||||
Mirror(value);
|
||||
Sync();
|
||||
break;
|
||||
case 0x01:
|
||||
prg = value & 15;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
+7
-1
@@ -22,11 +22,12 @@
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 latche;
|
||||
static uint8 latche, mirr;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &latche, 1, "LATC" },
|
||||
{ &mirr, 1, "MIRR" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -36,6 +37,11 @@ static void Sync(void) {
|
||||
}
|
||||
|
||||
static DECLFW(M36Write) {
|
||||
|
||||
switch((A>>12)&7) { // need to 4-in-1 MGC-26 BMC, doesnt break other games though
|
||||
case 0: mirr = MI_V; setmirror(mirr); break;
|
||||
case 4: mirr = MI_H; setmirror(mirr); break;
|
||||
}
|
||||
latche = V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
+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();
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 preg, mirr;
|
||||
static int hardmirr;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
@@ -35,6 +36,8 @@ static void Sync(void) {
|
||||
setchr8(0);
|
||||
if(mirr)
|
||||
setmirror(mirr);
|
||||
else
|
||||
setmirror(hardmirr); // restore hardwired mirroring
|
||||
}
|
||||
|
||||
static DECLFW(M71Write) {
|
||||
@@ -46,6 +49,7 @@ static DECLFW(M71Write) {
|
||||
}
|
||||
|
||||
static void M71Power(void) {
|
||||
preg = 0;
|
||||
mirr = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
@@ -57,6 +61,7 @@ static void StateRestore(int version) {
|
||||
}
|
||||
|
||||
void Mapper71_Init(CartInfo *info) {
|
||||
hardmirr = info->mirror;
|
||||
info->Power = M71Power;
|
||||
GameStateRestore = StateRestore;
|
||||
|
||||
|
||||
+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);
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2017 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
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 bios_prg, rom_prg, rom_mode, mirror;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &bios_prg, 1, "BREG" },
|
||||
{ &rom_prg, 1, "RREG" },
|
||||
{ &rom_mode, 1, "RMODE" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
setchr8(0);
|
||||
if(rom_mode&2) {
|
||||
setprg16r(0,0x8000,(bios_prg&0xF)|(rom_prg&0x70));
|
||||
} else {
|
||||
setprg16r(1,0x8000,bios_prg&3);
|
||||
}
|
||||
setprg16r(0,0xC000,rom_prg&0x7F);
|
||||
setmirror(((bios_prg>>4)&1)^1);
|
||||
}
|
||||
|
||||
static DECLFW(BMC80013BWrite) {
|
||||
uint8 reg = (A>>13)&3;
|
||||
if(reg == 0) {
|
||||
bios_prg = V;
|
||||
} else {
|
||||
rom_prg = V;
|
||||
rom_mode = reg;
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void BMC80013BPower(void) {
|
||||
bios_prg=rom_prg=rom_mode=mirror=0;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, BMC80013BWrite);
|
||||
}
|
||||
|
||||
static void BMC80013BReset(void) {
|
||||
bios_prg=rom_prg=rom_mode=mirror=0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void BMC80013B_Init(CartInfo *info) {
|
||||
info->Reset = BMC80013BReset;
|
||||
info->Power = BMC80013BPower;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~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);
|
||||
|
||||
+1
-2
@@ -19,7 +19,6 @@
|
||||
*
|
||||
* Super Game (Sugar Softec) protected mapper
|
||||
* Pocahontas 2 (Unl) [U][!], etc.
|
||||
* TODO: 9in1 LION KING HANGS!
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
@@ -139,7 +138,7 @@ static DECLFW(UNL8237Write) {
|
||||
}
|
||||
|
||||
static DECLFW(UNL8237ExWrite) {
|
||||
switch (A) {
|
||||
switch (A & 0xF007) {
|
||||
case 0x5000: EXPREGS[0] = V; FixMMC3PRG(MMC3_cmd); break;
|
||||
case 0x5001: EXPREGS[1] = V; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); break;
|
||||
case 0x5007: EXPREGS[2] = V; break;
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import glob
|
||||
source_list = glob.glob('*.cpp')+glob.glob('*.c')
|
||||
|
||||
for x in range(len(source_list)):
|
||||
source_list[x] = 'boards/' + source_list[x]
|
||||
Return('source_list')
|
||||
@@ -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);
|
||||
|
||||
+40
-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) {
|
||||
@@ -237,13 +254,8 @@ void Mapper200_Init(CartInfo *info) {
|
||||
//------------------ Map 201 ---------------------------
|
||||
|
||||
static void M201Sync(void) {
|
||||
if (latche & 8) {
|
||||
setprg32(0x8000, latche & 3);
|
||||
setchr8(latche & 3);
|
||||
} else {
|
||||
setprg32(0x8000, 0);
|
||||
setchr8(0);
|
||||
}
|
||||
setprg32(0x8000, latche & 3);
|
||||
setchr8(latche & 3);
|
||||
}
|
||||
|
||||
void Mapper201_Init(CartInfo *info) {
|
||||
@@ -309,8 +321,14 @@ void Mapper212_Init(CartInfo *info) {
|
||||
//------------------ Map 213 ---------------------------
|
||||
|
||||
static void M213Sync(void) {
|
||||
setprg32(0x8000, (latche >> 1) & 3);
|
||||
if(latche & 0x40) {
|
||||
setprg16(0x8000, (latche & 7));
|
||||
setprg16(0xC000, (latche & 7));
|
||||
} else {
|
||||
setprg32(0x8000, (latche >> 1) & 3);
|
||||
}
|
||||
setchr8((latche >> 3) & 7);
|
||||
setmirror(((latche & 1)^((latche >> 6) & 1)) ^ 1);
|
||||
}
|
||||
|
||||
void Mapper213_Init(CartInfo *info) {
|
||||
@@ -341,12 +359,20 @@ 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;
|
||||
|
||||
// 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);
|
||||
|
||||
if ((latche >> 7) & 1) {
|
||||
if (S) {
|
||||
setprg32(0x8000, p >> 1);
|
||||
@@ -381,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 ---------------------------
|
||||
|
||||
+276
-134
@@ -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[] =
|
||||
{
|
||||
@@ -48,120 +48,205 @@ static SFORMAT StateRegs[] =
|
||||
#define X24C0X_READ 3
|
||||
#define X24C0X_WRITE 4
|
||||
|
||||
static uint8 x24c0x_data[256], x24c0x_state;
|
||||
static uint8 x24c0x_addr, x24c0x_word, x24c0x_latch, x24c0x_bitcount;
|
||||
static uint8 x24c0x_sda, x24c0x_scl, x24c0x_out, x24c0x_oe;
|
||||
static uint8 x24c0x_data[512];
|
||||
|
||||
static SFORMAT x24c0xStateRegs[] =
|
||||
static uint8 x24c01_state;
|
||||
static uint8 x24c01_addr, x24c01_word, x24c01_latch, x24c01_bitcount;
|
||||
static uint8 x24c01_sda, x24c01_scl, x24c01_out;
|
||||
|
||||
static uint8 x24c02_state;
|
||||
static uint8 x24c02_addr, x24c02_word, x24c02_latch, x24c02_bitcount;
|
||||
static uint8 x24c02_sda, x24c02_scl, x24c02_out;
|
||||
|
||||
static SFORMAT x24c01StateRegs[] =
|
||||
{
|
||||
{ &x24c0x_addr, 1, "ADDR" },
|
||||
{ &x24c0x_word, 1, "WORD" },
|
||||
{ &x24c0x_latch, 1, "LATC" },
|
||||
{ &x24c0x_bitcount, 1, "BITC" },
|
||||
{ &x24c0x_sda, 1, "SDA" },
|
||||
{ &x24c0x_scl, 1, "SCL" },
|
||||
{ &x24c0x_out, 1, "OUT" },
|
||||
{ &x24c0x_oe, 1, "OE" },
|
||||
{ &x24c0x_state, 1, "STAT" },
|
||||
{ &x24c01_addr, 1, "ADDR" },
|
||||
{ &x24c01_word, 1, "WORD" },
|
||||
{ &x24c01_latch, 1, "LATC" },
|
||||
{ &x24c01_bitcount, 1, "BITC" },
|
||||
{ &x24c01_sda, 1, "SDA" },
|
||||
{ &x24c01_scl, 1, "SCL" },
|
||||
{ &x24c01_out, 1, "OUT" },
|
||||
{ &x24c01_state, 1, "STAT" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void x24c0x_init() {
|
||||
x24c0x_addr = x24c0x_word = x24c0x_latch = x24c0x_bitcount = x24c0x_sda = x24c0x_scl = x24c0x_oe = 0;
|
||||
x24c0x_state = X24C0X_STANDBY;
|
||||
static SFORMAT x24c02StateRegs[] =
|
||||
{
|
||||
{ &x24c02_addr, 1, "ADDR" },
|
||||
{ &x24c02_word, 1, "WORD" },
|
||||
{ &x24c02_latch, 1, "LATC" },
|
||||
{ &x24c02_bitcount, 1, "BITC" },
|
||||
{ &x24c02_sda, 1, "SDA" },
|
||||
{ &x24c02_scl, 1, "SCL" },
|
||||
{ &x24c02_out, 1, "OUT" },
|
||||
{ &x24c02_state, 1, "STAT" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void x24c01_init() {
|
||||
x24c01_addr = x24c01_word = x24c01_latch = x24c01_bitcount = x24c01_sda = x24c01_scl = 0;
|
||||
x24c01_state = X24C0X_STANDBY;
|
||||
}
|
||||
|
||||
static void x24c0x_write(uint8 data) {
|
||||
uint8 sda = (data >> 6) & 1;
|
||||
uint8 scl = (data >> 5) & 1;
|
||||
x24c0x_oe = (data >> 7);
|
||||
static void x24c02_init() {
|
||||
x24c02_addr = x24c02_word = x24c02_latch = x24c02_bitcount = x24c02_sda = x24c02_scl = 0;
|
||||
x24c02_state = X24C0X_STANDBY;
|
||||
}
|
||||
|
||||
if(x24c0x_scl && scl) {
|
||||
if(x24c0x_sda && !sda) { // START
|
||||
x24c0x_state = X24C0X_ADDRESS;
|
||||
x24c0x_bitcount = 0;
|
||||
x24c0x_addr = 0;
|
||||
} else if(!x24c0x_sda && sda) { //STOP
|
||||
x24c0x_state = X24C0X_STANDBY;
|
||||
static void x24c01_write(uint8 data) {
|
||||
uint8 scl = (data >> 5) & 1;
|
||||
uint8 sda = (data >> 6) & 1;
|
||||
|
||||
if(x24c01_scl && scl) {
|
||||
if(x24c01_sda && !sda) { // START
|
||||
x24c01_state = X24C0X_ADDRESS;
|
||||
x24c01_bitcount = 0;
|
||||
x24c01_addr = 0;
|
||||
} else if(!x24c01_sda && sda) { //STOP
|
||||
x24c01_state = X24C0X_STANDBY;
|
||||
}
|
||||
} else if(!x24c0x_scl && scl) { // RISING EDGE
|
||||
switch(x24c0x_state) {
|
||||
} else if(!x24c01_scl && scl) { // RISING EDGE
|
||||
switch(x24c01_state) {
|
||||
case X24C0X_ADDRESS:
|
||||
if(x24c0x_bitcount < 7) {
|
||||
x24c0x_addr <<= 1;
|
||||
x24c0x_addr |= sda;
|
||||
if(x24c01_bitcount < 7) {
|
||||
x24c01_addr <<= 1;
|
||||
x24c01_addr |= sda;
|
||||
} else {
|
||||
if(!x24c02) // X24C01 mode
|
||||
x24c0x_word = x24c0x_addr;
|
||||
if(sda) { // READ COMMAND
|
||||
x24c0x_state = X24C0X_READ;
|
||||
} else { // WRITE COMMAND
|
||||
if(x24c02) // X24C02 mode
|
||||
x24c0x_state = X24C0X_WORD;
|
||||
else
|
||||
x24c0x_state = X24C0X_WRITE;
|
||||
}
|
||||
x24c01_word = x24c01_addr;
|
||||
if(sda) // READ COMMAND
|
||||
x24c01_state = X24C0X_READ;
|
||||
else // WRITE COMMAND
|
||||
x24c01_state = X24C0X_WRITE;
|
||||
}
|
||||
x24c0x_bitcount++;
|
||||
break;
|
||||
case X24C0X_WORD:
|
||||
if(x24c0x_bitcount == 8) { // ACK
|
||||
x24c0x_word = 0;
|
||||
x24c0x_out = 0;
|
||||
} else { // WORD ADDRESS INPUT
|
||||
x24c0x_word <<= 1;
|
||||
x24c0x_word |= sda;
|
||||
if(x24c0x_bitcount == 16) { // END OF ADDRESS INPUT
|
||||
x24c0x_bitcount = 7;
|
||||
x24c0x_state = X24C0X_WRITE;
|
||||
}
|
||||
}
|
||||
x24c0x_bitcount++;
|
||||
x24c01_bitcount++;
|
||||
break;
|
||||
case X24C0X_READ:
|
||||
if (x24c0x_bitcount == 8) { // ACK
|
||||
x24c0x_out = 0;
|
||||
x24c0x_latch = x24c0x_data[x24c0x_word];
|
||||
x24c0x_bitcount = 0;
|
||||
} else { // REAL OUTPUT
|
||||
x24c0x_out = x24c0x_latch >> 7;
|
||||
x24c0x_latch <<= 1;
|
||||
x24c0x_bitcount++;
|
||||
if(x24c0x_bitcount == 8) {
|
||||
x24c0x_word++;
|
||||
x24c0x_word &= 0xff;
|
||||
if (x24c01_bitcount == 8) { // ACK
|
||||
x24c01_out = 0;
|
||||
x24c01_latch = x24c0x_data[x24c01_word];
|
||||
x24c01_bitcount = 0;
|
||||
} else { // REAL OUTPUT
|
||||
x24c01_out = x24c01_latch >> 7;
|
||||
x24c01_latch <<= 1;
|
||||
x24c01_bitcount++;
|
||||
if(x24c01_bitcount == 8) {
|
||||
x24c01_word++;
|
||||
x24c01_word &= 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case X24C0X_WRITE:
|
||||
if (x24c0x_bitcount == 8) { // ACK
|
||||
x24c0x_out = 0;
|
||||
x24c0x_latch = 0;
|
||||
x24c0x_bitcount = 0;
|
||||
} else { // REAL INPUT
|
||||
x24c0x_latch <<= 1;
|
||||
x24c0x_latch |= sda;
|
||||
x24c0x_bitcount++;
|
||||
if(x24c0x_bitcount == 8) {
|
||||
x24c0x_data[x24c0x_word] = x24c0x_latch;
|
||||
x24c0x_word++;
|
||||
x24c0x_word &= 0xff;
|
||||
if (x24c01_bitcount == 8) { // ACK
|
||||
x24c01_out = 0;
|
||||
x24c01_latch = 0;
|
||||
x24c01_bitcount = 0;
|
||||
} else { // REAL INPUT
|
||||
x24c01_latch <<= 1;
|
||||
x24c01_latch |= sda;
|
||||
x24c01_bitcount++;
|
||||
if(x24c01_bitcount == 8) {
|
||||
x24c0x_data[x24c01_word] = x24c01_latch;
|
||||
x24c01_word++;
|
||||
x24c01_word &= 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
x24c0x_sda = sda;
|
||||
x24c0x_scl = scl;
|
||||
x24c01_sda = sda;
|
||||
x24c01_scl = scl;
|
||||
}
|
||||
|
||||
static uint8 x24c0x_read() {
|
||||
return x24c0x_out << 4;
|
||||
static void x24c02_write(uint8 data) {
|
||||
uint8 scl = (data >> 5) & 1;
|
||||
uint8 sda = (data >> 6) & 1;
|
||||
|
||||
if (x24c02_scl && scl) {
|
||||
if (x24c02_sda && !sda) { // START
|
||||
x24c02_state = X24C0X_ADDRESS;
|
||||
x24c02_bitcount = 0;
|
||||
x24c02_addr = 0;
|
||||
} else if (!x24c02_sda && sda) { //STOP
|
||||
x24c02_state = X24C0X_STANDBY;
|
||||
}
|
||||
} else if (!x24c02_scl && scl) { // RISING EDGE
|
||||
switch (x24c02_state) {
|
||||
case X24C0X_ADDRESS:
|
||||
if (x24c02_bitcount < 7) {
|
||||
x24c02_addr <<= 1;
|
||||
x24c02_addr |= sda;
|
||||
} else {
|
||||
if (sda) // READ COMMAND
|
||||
x24c02_state = X24C0X_READ;
|
||||
else // WRITE COMMAND
|
||||
x24c02_state = X24C0X_WORD;
|
||||
}
|
||||
x24c02_bitcount++;
|
||||
break;
|
||||
case X24C0X_WORD:
|
||||
if (x24c02_bitcount == 8) { // ACK
|
||||
x24c02_word = 0;
|
||||
x24c02_out = 0;
|
||||
} else { // WORD ADDRESS INPUT
|
||||
x24c02_word <<= 1;
|
||||
x24c02_word |= sda;
|
||||
if (x24c02_bitcount == 16) {// END OF ADDRESS INPUT
|
||||
x24c02_bitcount = 7;
|
||||
x24c02_state = X24C0X_WRITE;
|
||||
}
|
||||
}
|
||||
x24c02_bitcount++;
|
||||
break;
|
||||
case X24C0X_READ:
|
||||
if (x24c02_bitcount == 8) { // ACK
|
||||
x24c02_out = 0;
|
||||
x24c02_latch = x24c0x_data[x24c02_word|0x100];
|
||||
x24c02_bitcount = 0;
|
||||
} else { // REAL OUTPUT
|
||||
x24c02_out = x24c02_latch >> 7;
|
||||
x24c02_latch <<= 1;
|
||||
x24c02_bitcount++;
|
||||
if (x24c02_bitcount == 8) {
|
||||
x24c02_word++;
|
||||
x24c02_word &= 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case X24C0X_WRITE:
|
||||
if (x24c02_bitcount == 8) { // ACK
|
||||
x24c02_out = 0;
|
||||
x24c02_latch = 0;
|
||||
x24c02_bitcount = 0;
|
||||
} else { // REAL INPUT
|
||||
x24c02_latch <<= 1;
|
||||
x24c02_latch |= sda;
|
||||
x24c02_bitcount++;
|
||||
if (x24c02_bitcount == 8) {
|
||||
x24c0x_data[x24c02_word|0x100] = x24c02_latch;
|
||||
x24c02_word++;
|
||||
x24c02_word &= 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
x24c02_sda = sda;
|
||||
x24c02_scl = scl;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
static void SyncMirror(void) {
|
||||
switch (reg[9] & 3) {
|
||||
case 0: setmirror(MI_V); break;
|
||||
case 1: setmirror(MI_H); break;
|
||||
case 2: setmirror(MI_0); break;
|
||||
case 3: setmirror(MI_1); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Sync(void) {
|
||||
if (is153) {
|
||||
int base = (reg[0] & 1) << 4;
|
||||
@@ -174,12 +259,7 @@ static void Sync(void) {
|
||||
setprg16(0x8000, reg[8]);
|
||||
setprg16(0xC000, ~0);
|
||||
}
|
||||
switch (reg[9] & 3) {
|
||||
case 0: setmirror(MI_V); break;
|
||||
case 1: setmirror(MI_H); break;
|
||||
case 2: setmirror(MI_0); break;
|
||||
case 3: setmirror(MI_1); break;
|
||||
}
|
||||
SyncMirror();
|
||||
}
|
||||
|
||||
static DECLFW(BandaiWrite) {
|
||||
@@ -192,12 +272,15 @@ static DECLFW(BandaiWrite) {
|
||||
case 0x0A: X6502_IRQEnd(FCEU_IQEXT); IRQa = V & 1; IRQCount = IRQLatch; break;
|
||||
case 0x0B: IRQLatch &= 0xFF00; IRQLatch |= V; break;
|
||||
case 0x0C: IRQLatch &= 0xFF; IRQLatch |= V << 8; break;
|
||||
case 0x0D: x24c0x_write(V); break;
|
||||
case 0x0D: if(x24c02) x24c02_write(V); else x24c01_write(V); break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(BandaiRead) {
|
||||
return (X.DB & 0xEF) | x24c0x_read();
|
||||
if(x24c02)
|
||||
return (X.DB & 0xEF) | (x24c02_out << 4);
|
||||
else
|
||||
return (X.DB & 0xEF) | (x24c01_out << 4);
|
||||
}
|
||||
|
||||
static void BandaiIRQHook(int a) {
|
||||
@@ -213,7 +296,10 @@ static void BandaiIRQHook(int a) {
|
||||
|
||||
static void BandaiPower(void) {
|
||||
IRQa = 0;
|
||||
x24c0x_init();
|
||||
if(x24c02)
|
||||
x24c02_init();
|
||||
else
|
||||
x24c01_init();
|
||||
Sync();
|
||||
SetReadHandler(0x6000, 0x7FFF, BandaiRead);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
@@ -231,12 +317,11 @@ void Mapper16_Init(CartInfo *info) {
|
||||
MapIRQHook = BandaiIRQHook;
|
||||
|
||||
info->battery = 1;
|
||||
info->SaveGame[0] = x24c0x_data;
|
||||
info->SaveGameLen[0] = 256;
|
||||
info->addSaveGameBuf( x24c0x_data + 256, 256 );
|
||||
AddExState(x24c0x_data, 256, 0, "DATA");
|
||||
AddExState(&x24c02StateRegs, ~0, 0, 0);
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&x24c0xStateRegs, ~0, 0, 0);
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -247,12 +332,11 @@ 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);
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&x24c0xStateRegs, ~0, 0, 0);
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -292,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;
|
||||
@@ -307,7 +390,9 @@ static int BarcodeReadPos;
|
||||
static int BarcodeCycleCount;
|
||||
static uint32 BarcodeOut;
|
||||
|
||||
int FCEUI_DatachSet(const uint8 *rcode) {
|
||||
// #define INTERL2OF5
|
||||
|
||||
int FCEUI_DatachSet(uint8 *rcode) {
|
||||
int prefix_parity_type[10][6] = {
|
||||
{ 0, 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 1, 1 }, { 0, 0, 1, 1, 0, 1 }, { 0, 0, 1, 1, 1, 0 },
|
||||
{ 0, 1, 0, 0, 1, 1 }, { 0, 1, 1, 0, 0, 1 }, { 0, 1, 1, 1, 0, 0 }, { 0, 1, 0, 1, 0, 1 },
|
||||
@@ -330,6 +415,7 @@ int FCEUI_DatachSet(const uint8 *rcode) {
|
||||
};
|
||||
uint8 code[13 + 1];
|
||||
uint32 tmp_p = 0;
|
||||
uint32 csum = 0;
|
||||
int i, j;
|
||||
int len;
|
||||
|
||||
@@ -341,18 +427,46 @@ int FCEUI_DatachSet(const uint8 *rcode) {
|
||||
}
|
||||
if (len != 13 && len != 12 && len != 8 && len != 7) return(0);
|
||||
|
||||
#define BS(x) BarcodeData[tmp_p] = x; tmp_p++
|
||||
#define BS(x) BarcodeData[tmp_p] = x; tmp_p++
|
||||
|
||||
for (j = 0; j < 32; j++) {
|
||||
for (j = 0; j < 32; j++) { // delay before sending a code
|
||||
BS(0x00);
|
||||
}
|
||||
|
||||
/* Left guard bars */
|
||||
#ifdef INTERL2OF5
|
||||
|
||||
BS(1); BS(1); BS(0); BS(0); // 1
|
||||
BS(1); BS(1); BS(0); BS(0); // 1
|
||||
BS(1); BS(1); BS(0); BS(0); // 1
|
||||
BS(1); BS(1); BS(0); BS(0); // 1
|
||||
BS(1); BS(1); BS(0); BS(0); // 1
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0
|
||||
BS(1); BS(0); BS(0); // 0 cs
|
||||
BS(1); BS(1); BS(0); BS(0); // 1
|
||||
|
||||
#else
|
||||
// Left guard bars
|
||||
BS(1); BS(0); BS(1);
|
||||
|
||||
if (len == 13 || len == 12) {
|
||||
uint32 csum;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
if (prefix_parity_type[code[0]][i]) {
|
||||
for (j = 0; j < 7; j++) {
|
||||
@@ -362,53 +476,53 @@ int FCEUI_DatachSet(const uint8 *rcode) {
|
||||
for (j = 0; j < 7; j++) {
|
||||
BS(data_left_odd[code[i + 1]][j]);
|
||||
}
|
||||
|
||||
/* Center guard bars */
|
||||
// Center guard bars
|
||||
BS(0); BS(1); BS(0); BS(1); BS(0);
|
||||
|
||||
for (i = 7; i < 12; i++)
|
||||
for (j = 0; j < 7; j++) {
|
||||
BS(data_right[code[i]][j]);
|
||||
}
|
||||
csum = 0;
|
||||
for (i = 0; i < 12; i++) csum += code[i] * ((i & 1) ? 3 : 1);
|
||||
csum = (10 - (csum % 10)) % 10;
|
||||
// Calc and write down the control code if not assigned, instead, send code as is
|
||||
// Battle Rush uses modified type of codes with different control code calculation
|
||||
if (len == 12) {
|
||||
for (i = 0; i < 12; i++)
|
||||
csum += code[i] * ((i & 1) ? 3 : 1);
|
||||
csum = (10 - (csum % 10)) % 10;
|
||||
rcode[12] = csum + 0x30; // update check code to the input string as well
|
||||
rcode[13] = 0;
|
||||
code[12] = csum;
|
||||
}
|
||||
for (j = 0; j < 7; j++) {
|
||||
BS(data_right[csum][j]);
|
||||
BS(data_right[code[12]][j]);
|
||||
}
|
||||
} else if (len == 8 || len == 7) {
|
||||
uint32 csum = 0;
|
||||
|
||||
for (i = 0; i < 7; i++) csum += (i & 1) ? code[i] : (code[i] * 3);
|
||||
|
||||
csum = (10 - (csum % 10)) % 10;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 7; j++) {
|
||||
BS(data_left_odd[code[i]][j]);
|
||||
}
|
||||
|
||||
|
||||
/* Center guard bars */
|
||||
// Center guard bars
|
||||
BS(0); BS(1); BS(0); BS(1); BS(0);
|
||||
|
||||
for (i = 4; i < 7; i++)
|
||||
for (j = 0; j < 7; j++) {
|
||||
BS(data_right[code[i]][j]);
|
||||
}
|
||||
|
||||
csum = 0;
|
||||
for (i = 0; i < 7; i++)
|
||||
csum += (i & 1) ? code[i] : (code[i] * 3);
|
||||
csum = (10 - (csum % 10)) % 10;
|
||||
rcode[7] = csum + 0x30; // update check code to the input string as well
|
||||
rcode[8] = 0;
|
||||
for (j = 0; j < 7; j++) {
|
||||
BS(data_right[csum][j]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Right guard bars */
|
||||
// Right guard bars
|
||||
BS(1); BS(0); BS(1);
|
||||
#endif
|
||||
|
||||
for (j = 0; j < 32; j++) {
|
||||
BS(0x00);
|
||||
}
|
||||
|
||||
BS(0xFF);
|
||||
|
||||
#undef BS
|
||||
@@ -419,6 +533,26 @@ int FCEUI_DatachSet(const uint8 *rcode) {
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void BarcodeSync(void) {
|
||||
setchr8(0);
|
||||
setprg16(0x8000, (reg[8] & 0x0F));
|
||||
setprg16(0xC000, 0x0F);
|
||||
SyncMirror();
|
||||
}
|
||||
|
||||
static DECLFW(BarcodeWrite) {
|
||||
A &= 0x0F;
|
||||
switch (A) {
|
||||
case 0x00: reg[0] = (V & 8) << 2; x24c01_write(reg[0xD] | reg[0]); break; // extra EEPROM x24C01 used in Battle Rush mini-cart
|
||||
case 0x08:
|
||||
case 0x09: reg[A] = V; BarcodeSync(); break;
|
||||
case 0x0A: X6502_IRQEnd(FCEU_IQEXT); IRQa = V & 1; IRQCount = IRQLatch; break;
|
||||
case 0x0B: IRQLatch &= 0xFF00; IRQLatch |= V; break;
|
||||
case 0x0C: IRQLatch &= 0xFF; IRQLatch |= V << 8; break;
|
||||
case 0x0D: reg[0xD] = V & (~0x20); x24c01_write(reg[0xD] | reg[0]); x24c02_write(V); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void BarcodeIRQHook(int a) {
|
||||
BandaiIRQHook(a);
|
||||
|
||||
@@ -436,7 +570,7 @@ static void BarcodeIRQHook(int a) {
|
||||
}
|
||||
|
||||
static DECLFR(BarcodeRead) {
|
||||
return BarcodeOut;
|
||||
return (X.DB & 0xE7) | ((x24c02_out | x24c01_out) << 4) | BarcodeOut;
|
||||
}
|
||||
|
||||
static void M157Power(void) {
|
||||
@@ -446,20 +580,28 @@ static void M157Power(void) {
|
||||
BarcodeOut = 0;
|
||||
BarcodeCycleCount = 0;
|
||||
|
||||
Sync();
|
||||
x24c01_init();
|
||||
x24c02_init();
|
||||
BarcodeSync();
|
||||
|
||||
SetWriteHandler(0x6000, 0xFFFF, BandaiWrite);
|
||||
SetReadHandler(0x6000, 0x7FFF, BarcodeRead);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, BarcodeWrite);
|
||||
}
|
||||
|
||||
void Mapper157_Init(CartInfo *info) {
|
||||
is153 = 1;
|
||||
x24c02 = 1;
|
||||
info->Power = M157Power;
|
||||
MapIRQHook = BarcodeIRQHook;
|
||||
|
||||
GameInfo->cspecial = SIS_DATACH;
|
||||
info->battery = 1;
|
||||
info->addSaveGameBuf( x24c0x_data, 512 );
|
||||
AddExState(x24c0x_data, 512, 0, "DATA");
|
||||
AddExState(&x24c01StateRegs, ~0, 0, 0);
|
||||
AddExState(&x24c02StateRegs, ~0, 0, 0);
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -84,12 +84,12 @@ byte_8C29: .BYTE 0,$76, 0, 0, 8
|
||||
byte_8CC6: .BYTE 0,$78, 0, 0,$12
|
||||
*/
|
||||
|
||||
static uint8 sim0reset[0x1F] = {
|
||||
0x3B, 0xE9, 0x00, 0xFF, 0xC1, 0x10, 0x31, 0xFE,
|
||||
0x55, 0xC8, 0x10, 0x20, 0x55, 0x47, 0x4F, 0x53,
|
||||
0x56, 0x53, 0x43, 0xAD, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
|
||||
};
|
||||
//static uint8 sim0reset[0x1F] = {
|
||||
// 0x3B, 0xE9, 0x00, 0xFF, 0xC1, 0x10, 0x31, 0xFE,
|
||||
// 0x55, 0xC8, 0x10, 0x20, 0x55, 0x47, 0x4F, 0x53,
|
||||
// 0x56, 0x53, 0x43, 0xAD, 0x10, 0x10, 0x10, 0x10,
|
||||
// 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
|
||||
//};
|
||||
|
||||
static void Sync(void) {
|
||||
setprg32(0x8000, prg_reg);
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2020 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
|
||||
*
|
||||
* Double Dragon 310000-in-1 (4040R)
|
||||
* 700000-in-1 (BS-400R)(Unl)
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 pointer;
|
||||
static uint8 offset;
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
|
||||
static int getPRGBankBS4XXXR(int bank)
|
||||
{
|
||||
if (((~bank) & 1) && (pointer & 0x40))
|
||||
bank ^= 2;
|
||||
return (bank & 2) ? (0xFE | (bank & 1)) : EXPREGS[4 | (bank & 1)];
|
||||
}
|
||||
|
||||
static void BS4XXXRPW(uint32 A, uint8 V) {
|
||||
|
||||
if ((EXPREGS[3] >> 4) & 0x01)
|
||||
{
|
||||
int AND = ((EXPREGS[0] >> 1) & 1) ? 0x0F : 0x0F;
|
||||
int OR = (EXPREGS[0] & 7) << 4;
|
||||
int bank0 = getPRGBankBS4XXXR(0);
|
||||
int bank1 = getPRGBankBS4XXXR(1);
|
||||
if (!((EXPREGS[3] >> 1) & 1)) //16K Mode
|
||||
{
|
||||
setprg8(0x8000, ((bank0) & AND) | OR);
|
||||
setprg8(0xA000, ((bank1) & AND) | OR);
|
||||
setprg8(0xC000, ((bank0) & AND) | OR);
|
||||
setprg8(0xE000, ((bank1) & AND) | OR);
|
||||
}
|
||||
else // 32K Mode
|
||||
{
|
||||
setprg8(0x8000, ((bank0) & AND) | OR);
|
||||
setprg8(0xA000, ((bank1) & AND) | OR);
|
||||
setprg8(0xC000, ((bank0 | 2) & AND) | OR);
|
||||
setprg8(0xE000, ((bank1 | 2) & AND) | OR);
|
||||
}
|
||||
}
|
||||
else // MMC3 Mode
|
||||
{
|
||||
int prgAND = ((EXPREGS[0] >> offset) & 1) ? 0x0F : 0x1F;
|
||||
int prgOR = (EXPREGS[0] & 7) << 4;
|
||||
setprg8(A, (V & prgAND) | (prgOR));
|
||||
}
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
}
|
||||
|
||||
static void BS4XXXRCW(uint32 A, uint8 V) {
|
||||
if ((EXPREGS[3] >> 4) & 1)
|
||||
{
|
||||
int AND = ((EXPREGS[0] >> 1) & 1) ? 0x0F : 0x0F;
|
||||
int bank = EXPREGS[2] & AND;
|
||||
int chrOR = ((EXPREGS[0] >> 3) & 7) << 4;
|
||||
setchr8((bank) | (chrOR));
|
||||
}
|
||||
else
|
||||
{
|
||||
int chrAND = ((EXPREGS[0] >> 1) & 1) ? 0xFF : 0xFF;
|
||||
int chrOR = ((EXPREGS[0] >> 3) & 7) << 7;
|
||||
setchr1(A, (V & chrAND) | (chrOR));
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(BS4XXXRHiWrite) {
|
||||
// FCEU_printf("w: %04x-%02x\n",A,V)
|
||||
if (A==0x8000)
|
||||
{
|
||||
pointer = MMC3_cmd ^ V;
|
||||
}
|
||||
else if (A == 0x8001)
|
||||
{
|
||||
if((MMC3_cmd & 7) > 5)
|
||||
EXPREGS[4|(MMC3_cmd & 1)] = V;
|
||||
}
|
||||
MMC3_CMDWrite(A, V);
|
||||
}
|
||||
|
||||
static DECLFW(BS4XXXRLoWrite) {
|
||||
// FCEU_printf("w: %04x-%02x\n", A, V);
|
||||
if (A & 0x800)
|
||||
{
|
||||
if (!(EXPREGS[3] & 0x80)) {
|
||||
EXPREGS[A & 0x03] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
else if (EXPREGS[3] & 0x10)
|
||||
{
|
||||
EXPREGS[A & 0x03] = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
else
|
||||
WRAM[A - 0x6000] = V;
|
||||
}
|
||||
else
|
||||
WRAM[A - 0x6000] = V;
|
||||
}
|
||||
|
||||
|
||||
static void BSXXXXRPower(void) {
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = EXPREGS[4] = EXPREGS[5] = 0;
|
||||
GenMMC3Power();
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, BS4XXXRLoWrite);
|
||||
SetWriteHandler(0x8000, 0x9FFF, BS4XXXRHiWrite);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void BS4XXXRClose(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
void BSXXXXR_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap = BS4XXXRCW;
|
||||
pwrap = BS4XXXRPW;
|
||||
|
||||
info->Power = BSXXXXRPower;
|
||||
info->Close = BS4XXXRClose;
|
||||
|
||||
WRAMSIZE = 8192;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
}
|
||||
|
||||
void BS400R_Init(CartInfo *info) {
|
||||
offset = 1;
|
||||
BSXXXXR_Init(info);
|
||||
}
|
||||
|
||||
void BS4040R_Init(CartInfo *info) {
|
||||
offset = 6;
|
||||
BSXXXXR_Init(info);
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
// mapper 111 - Cheapocabra board by Memblers
|
||||
// http://forums.nesdev.com/viewtopic.php?p=146039
|
||||
//
|
||||
// 512k PRG-ROM in 32k pages (flashable if battery backed is specified)
|
||||
// 32k CHR-RAM used as:
|
||||
// 2 x 8k pattern pages
|
||||
// 2 x 8k nametable pages
|
||||
//
|
||||
// Notes:
|
||||
// - CHR-RAM for nametables maps to $3000-3FFF as well, but FCEUX internally mirrors to 4k?
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "../ines.h"
|
||||
|
||||
static uint8 reg;
|
||||
static uint8 *CHRRAM = NULL;
|
||||
const uint32 CHRRAMSIZE = 1024 * 32;
|
||||
|
||||
static bool flash = false;
|
||||
static uint8 flash_mode;
|
||||
static uint8 flash_sequence;
|
||||
static uint8 flash_id;
|
||||
static uint8 *FLASHROM = NULL;
|
||||
const uint32 FLASHROMSIZE = 1024 * 512;
|
||||
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ ®, 1, "REG" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static SFORMAT FlashRegs[] =
|
||||
{
|
||||
{ &flash_mode, 1, "FMOD" },
|
||||
{ &flash_sequence, 1, "FSEQ" },
|
||||
{ &flash_id, 1, "FMID" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void Sync(void) {
|
||||
// bit 7 controls green LED
|
||||
// bit 6 controls red LED
|
||||
int nt = (reg & 0x20) ? 8192 : 0; // bit 5 controls 8k nametable page
|
||||
int chr = (reg & 0x10) ? 1 : 0; // bit 4 selects 8k CHR page
|
||||
int prg = (reg & 0x0F); // bits 0-3 select 32k PRG page
|
||||
|
||||
nt += (16 * 1024);
|
||||
for (int n=0; n<4; ++n)
|
||||
{
|
||||
setntamem(CHRRAM + nt + (1024 * n),1,n);
|
||||
}
|
||||
setchr8r(0x10, chr);
|
||||
|
||||
uint32 prg_chip = flash ? 0x10 : 0;
|
||||
setprg32r(prg_chip,0x8000,prg);
|
||||
}
|
||||
|
||||
static DECLFW(M111Write) {
|
||||
if ((A >= 0x5000 && A <= 0x5FFF) || (A >= 0x7000 && A <= 0x7FFF))
|
||||
{
|
||||
reg = V;
|
||||
Sync();
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(M111FlashID)
|
||||
{
|
||||
// Software ID mode is undefined by the datasheet for all but the lowest 2 addressable bytes,
|
||||
// but some tests of the chip currently being used found it repeats in 512-byte patterns.
|
||||
// http://forums.nesdev.com/viewtopic.php?p=178728#p178728
|
||||
|
||||
uint32 aid = A & 0x1FF;
|
||||
switch (aid)
|
||||
{
|
||||
case 0: return 0xBF;
|
||||
case 1: return 0xB7;
|
||||
default: return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void M111FlashIDEnter()
|
||||
{
|
||||
if (flash_id) return;
|
||||
flash_id = 1;
|
||||
SetReadHandler(0x8000,0xFFFF,M111FlashID);
|
||||
}
|
||||
|
||||
void M111FlashIDExit()
|
||||
{
|
||||
if (!flash_id) return;
|
||||
flash_id = 0;
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
}
|
||||
|
||||
static DECLFW(M111Flash) {
|
||||
if (A < 0x8000 || A > 0xFFFF) return;
|
||||
|
||||
uint32 flash_addr = ((reg & 0x0F) << 15) | (A & 0x7FFF);
|
||||
uint32 command_addr = flash_addr & 0x7FFF;
|
||||
|
||||
enum
|
||||
{
|
||||
FLASH_MODE_READY = 0,
|
||||
FLASH_MODE_COMMAND,
|
||||
FLASH_MODE_BYTE_WRITE,
|
||||
FLASH_MODE_ERASE,
|
||||
};
|
||||
|
||||
switch (flash_mode)
|
||||
{
|
||||
default:
|
||||
case FLASH_MODE_READY:
|
||||
if (command_addr == 0x5555 && V == 0xAA)
|
||||
{
|
||||
flash_mode = FLASH_MODE_COMMAND;
|
||||
flash_sequence = 0;
|
||||
}
|
||||
else if (V == 0xF0)
|
||||
{
|
||||
M111FlashIDExit();
|
||||
}
|
||||
break;
|
||||
case FLASH_MODE_COMMAND:
|
||||
if (flash_sequence == 0)
|
||||
{
|
||||
if (command_addr == 0x2AAA && V == 0x55)
|
||||
flash_sequence = 1;
|
||||
else
|
||||
flash_mode = FLASH_MODE_READY;
|
||||
}
|
||||
else if (flash_sequence == 1)
|
||||
{
|
||||
if (command_addr == 0x5555)
|
||||
{
|
||||
flash_sequence = 0;
|
||||
switch (V)
|
||||
{
|
||||
default: flash_mode = FLASH_MODE_READY; break;
|
||||
case 0xA0: flash_mode = FLASH_MODE_BYTE_WRITE; break;
|
||||
case 0x80: flash_mode = FLASH_MODE_ERASE; break;
|
||||
case 0x90: M111FlashIDEnter(); flash_mode = FLASH_MODE_READY; break;
|
||||
case 0xF0: M111FlashIDExit(); flash_mode = FLASH_MODE_READY; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
flash_mode = FLASH_MODE_READY;
|
||||
}
|
||||
else
|
||||
flash_mode = FLASH_MODE_READY; // should be unreachable
|
||||
break;
|
||||
case FLASH_MODE_BYTE_WRITE:
|
||||
FLASHROM[flash_addr] &= V;
|
||||
flash_mode = FLASH_MODE_READY;
|
||||
break;
|
||||
case FLASH_MODE_ERASE:
|
||||
if (flash_sequence == 0)
|
||||
{
|
||||
if (command_addr == 0x5555 && V == 0xAA)
|
||||
flash_sequence = 1;
|
||||
else
|
||||
flash_mode = FLASH_MODE_READY;
|
||||
}
|
||||
else if (flash_sequence == 1)
|
||||
{
|
||||
if (command_addr == 0x2AAA && V == 0x55)
|
||||
flash_sequence = 2;
|
||||
else
|
||||
flash_mode = FLASH_MODE_READY;
|
||||
}
|
||||
else if (flash_sequence == 2)
|
||||
{
|
||||
if (command_addr == 0x5555 && V == 0x10) // erase chip
|
||||
{
|
||||
memset(FLASHROM, 0xFF, FLASHROMSIZE);
|
||||
}
|
||||
else if (V == 0x30) // erase 4k sector
|
||||
{
|
||||
uint32 sector = flash_addr & 0x7F000;
|
||||
memset(FLASHROM + sector, 0xFF, 1024 * 4);
|
||||
}
|
||||
flash_mode = FLASH_MODE_READY;
|
||||
}
|
||||
else
|
||||
flash_mode = FLASH_MODE_READY; // should be unreachable
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void M111Power(void) {
|
||||
reg = 0xFF;
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xffff, CartBR);
|
||||
SetWriteHandler(0x5000, 0x5fff, M111Write);
|
||||
SetWriteHandler(0x7000, 0x7fff, M111Write);
|
||||
|
||||
if (flash)
|
||||
{
|
||||
flash_mode = 0;
|
||||
flash_sequence = 0;
|
||||
flash_id = false;
|
||||
SetWriteHandler(0x8000, 0xFFFF, M111Flash);
|
||||
}
|
||||
}
|
||||
|
||||
static void M111Close(void) {
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
|
||||
if (FLASHROM)
|
||||
FCEU_gfree(FLASHROM);
|
||||
FLASHROM = NULL;
|
||||
}
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper111_Init(CartInfo *info) {
|
||||
info->Power = M111Power;
|
||||
info->Close = M111Close;
|
||||
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1);
|
||||
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM");
|
||||
|
||||
flash = (info->battery != 0);
|
||||
if (flash)
|
||||
{
|
||||
FLASHROM = (uint8*)FCEU_gmalloc(FLASHROMSIZE);
|
||||
info->addSaveGameBuf( FLASHROM, FLASHROMSIZE );
|
||||
AddExState(FLASHROM, FLASHROMSIZE, 0, "FROM");
|
||||
AddExState(&FlashRegs, ~0, 0, 0);
|
||||
|
||||
// copy PRG ROM into FLASHROM, use it instead of PRG ROM
|
||||
const uint32 PRGSIZE = ROM_size * 16 * 1024;
|
||||
for (uint32 w=0, r=0; w<FLASHROMSIZE; ++w)
|
||||
{
|
||||
FLASHROM[w] = ROM[r];
|
||||
++r;
|
||||
if (r >= PRGSIZE) r = 0;
|
||||
}
|
||||
SetupCartPRGMapping(0x10, FLASHROM, FLASHROMSIZE, 0);
|
||||
}
|
||||
}
|
||||
+409
-71
@@ -1,7 +1,7 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2015 CaH4e3, ClusteR
|
||||
* Copyright (C) 2018 CaH4e3, 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
|
||||
@@ -17,38 +17,148 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* CoolBoy 400-in-1 FK23C-mimic mapper 16Mb/32Mb PROM + 128K/256K CHR RAM, optional SRAM, optional NTRAM
|
||||
* only MMC3 mode
|
||||
* SMD132 and SMD133 ASICs, MMC3 clones that can address up to 32 MiB of PRG-ROM, 256 KiB of CHR-RAM, and 8 KiB of WRAM.
|
||||
*
|
||||
* 6000 (xx76x210) | 0xC0
|
||||
* 6001 (xxx354x)
|
||||
* 6002 = 0
|
||||
* 6003 = 0
|
||||
* 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
|
||||
* ---- ----
|
||||
* ABCC DEEE
|
||||
* |||| ||||
|
||||
* |||| |+++-- PRG offset (PRG A19, A18, A17)
|
||||
* |||| +----- Alternate CHR A17
|
||||
* ||++------- 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
|
||||
* |||| |||
|
||||
* |||| ||+--- GNROM mode bank PRG size (1: 32 KiB bank, PRG A14=CPU A14; 0: 16 KiB bank, PRG A14=offset A14)
|
||||
* |||+-++---- PRG offset (in order: PRG A20, A22, A21)
|
||||
* ||+-------- 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)
|
||||
*
|
||||
* $xxx2
|
||||
* 7 bit 0
|
||||
* ---- ----
|
||||
* xxxx MMMM
|
||||
* ||||
|
||||
* ++++-- CHR offset for GNROM mode (CHR A16, A15, A14, A13)
|
||||
*
|
||||
* $xxx3
|
||||
* 7 bit 0
|
||||
* ---- ----
|
||||
* 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 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.
|
||||
* This also allows console to write data to the cartridge.
|
||||
* This behavior is not emulated.
|
||||
* No cart has been discovered so far that makes use of this feature, but this can be used for homebrew.
|
||||
*
|
||||
* hardware tested logic, don't try to understand lol
|
||||
*/
|
||||
|
||||
#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;
|
||||
@@ -58,89 +168,317 @@ 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 0xA000:
|
||||
if ((MMC3_cmd & 0x40)) V = 0;
|
||||
break;
|
||||
case 0xC000:
|
||||
if (!(MMC3_cmd & 0x40)) V = 0;
|
||||
break;
|
||||
case 0xE000:
|
||||
V = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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 AA6023Power(void) {
|
||||
GenMMC3Power();
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
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 AA6023Restore(int version) {
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
static void COOLBOYReset(void) {
|
||||
MMC3RegReset();
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||
// EXPREGS[0] = 0;
|
||||
// EXPREGS[1] = 0x60;
|
||||
// EXPREGS[2] = 0;
|
||||
// EXPREGS[3] = 0;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
// Registers at $6xxx
|
||||
void COOLBOY_Init(CartInfo* info) {
|
||||
CommonInit(info, 0);
|
||||
}
|
||||
|
||||
static void COOLBOYPower(void) {
|
||||
GenMMC3Power();
|
||||
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
|
||||
// EXPREGS[0] = 0;
|
||||
// EXPREGS[1] = 0x60;
|
||||
// EXPREGS[2] = 0;
|
||||
// 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, 0x7fff, COOLBOYWrite);
|
||||
// Registers at $5xxx
|
||||
void MINDKIDS_Init(CartInfo* info) {
|
||||
CommonInit(info, 1);
|
||||
}
|
||||
|
||||
void COOLBOY_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
pwrap = COOLBOYPW;
|
||||
cwrap = COOLBOYCW;
|
||||
info->Power = COOLBOYPower;
|
||||
info->Reset = COOLBOYReset;
|
||||
AddExState(EXPREGS, 4, 0, "EXPR");
|
||||
}
|
||||
// For NES 2.0 loader
|
||||
void AA6023_Init(CartInfo* info) {
|
||||
CommonInit(info, info->submapper);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+574
-498
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
+18
-18
@@ -53,22 +53,22 @@
|
||||
#include "emu2413.h"
|
||||
|
||||
static const unsigned char default_inst[15][8] = {
|
||||
/* VRC7 instruments, January 17, 2004 update -Xodnizel */
|
||||
{ 0x03, 0x21, 0x04, 0x06, 0x8D, 0xF2, 0x42, 0x17 },
|
||||
{ 0x13, 0x41, 0x05, 0x0E, 0x99, 0x96, 0x63, 0x12 },
|
||||
{ 0x31, 0x11, 0x10, 0x0A, 0xF0, 0x9C, 0x32, 0x02 },
|
||||
{ 0x21, 0x61, 0x1D, 0x07, 0x9F, 0x64, 0x20, 0x27 },
|
||||
{ 0x22, 0x21, 0x1E, 0x06, 0xF0, 0x76, 0x08, 0x28 },
|
||||
{ 0x02, 0x01, 0x06, 0x00, 0xF0, 0xF2, 0x03, 0x95 },
|
||||
{ 0x21, 0x61, 0x1C, 0x07, 0x82, 0x81, 0x16, 0x07 },
|
||||
{ 0x23, 0x21, 0x1A, 0x17, 0xEF, 0x82, 0x25, 0x15 },
|
||||
{ 0x25, 0x11, 0x1F, 0x00, 0x86, 0x41, 0x20, 0x11 },
|
||||
{ 0x85, 0x01, 0x1F, 0x0F, 0xE4, 0xA2, 0x11, 0x12 },
|
||||
{ 0x07, 0xC1, 0x2B, 0x45, 0xB4, 0xF1, 0x24, 0xF4 },
|
||||
{ 0x61, 0x23, 0x11, 0x06, 0x96, 0x96, 0x13, 0x16 },
|
||||
{ 0x01, 0x02, 0xD3, 0x05, 0x82, 0xA2, 0x31, 0x51 },
|
||||
{ 0x61, 0x22, 0x0D, 0x02, 0xC3, 0x7F, 0x24, 0x05 },
|
||||
{ 0x21, 0x62, 0x0E, 0x00, 0xA1, 0xA0, 0x44, 0x17 },
|
||||
/* VRC7 instruments, March 15, 2019 dumped by Nuke.YKT */
|
||||
{ 0x03, 0x21, 0x05, 0x06, 0xE8, 0x81, 0x42, 0x27 },
|
||||
{ 0x13, 0x41, 0x14, 0x0D, 0xD8, 0xF6, 0x23, 0x12 },
|
||||
{ 0x11, 0x11, 0x08, 0x08, 0xFA, 0xB2, 0x20, 0x12 },
|
||||
{ 0x31, 0x61, 0x0C, 0x07, 0xA8, 0x64, 0x61, 0x27 },
|
||||
{ 0x32, 0x21, 0x1E, 0x06, 0xE1, 0x76, 0x01, 0x28 },
|
||||
{ 0x02, 0x01, 0x06, 0x00, 0xA3, 0xE2, 0xF4, 0xF4 },
|
||||
{ 0x21, 0x61, 0x1D, 0x07, 0x82, 0x81, 0x11, 0x07 },
|
||||
{ 0x23, 0x21, 0x22, 0x17, 0xA2, 0x72, 0x01, 0x17 },
|
||||
{ 0x35, 0x11, 0x25, 0x00, 0x40, 0x73, 0x72, 0x01 },
|
||||
{ 0xB5, 0x01, 0x0F, 0x0F, 0xA8, 0xA5, 0x51, 0x02 },
|
||||
{ 0x17, 0xC1, 0x24, 0x07, 0xF8, 0xF8, 0x22, 0x12 },
|
||||
{ 0x71, 0x23, 0x11, 0x06, 0x65, 0x74, 0x18, 0x16 },
|
||||
{ 0x01, 0x02, 0xD3, 0x05, 0xC9, 0x95, 0x03, 0x02 },
|
||||
{ 0x61, 0x63, 0x0C, 0x00, 0x94, 0xC0, 0x33, 0xF6 },
|
||||
{ 0x21, 0x72, 0x0D, 0x00, 0xC1, 0xD5, 0x56, 0x06 },
|
||||
};
|
||||
|
||||
/* Size of Sintable ( 8 -- 18 can be used. 9 recommended.)*/
|
||||
@@ -604,8 +604,8 @@ void OPLL_reset(OPLL * opll) {
|
||||
for (i = 0; i < 0x40; i++)
|
||||
OPLL_writeReg(opll, i, 0);
|
||||
|
||||
opll->realstep = (uint32)((1 << 31) / rate);
|
||||
opll->opllstep = (uint32)((1 << 31) / (clk / 72));
|
||||
opll->realstep = (uint32)((1u << 31) / rate);
|
||||
opll->opllstep = (uint32)((1u << 31) / (clk / 72));
|
||||
opll->oplltime = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ static void SSSNROMPower(void) {
|
||||
regs[0] = regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0;
|
||||
regs[7] = 0xff;
|
||||
Sync();
|
||||
memset(WRAM, 0x00, WRAMSIZE);
|
||||
FCEU_MemoryRand(WRAM, WRAMSIZE, true);
|
||||
// SetWriteHandler(0x0000,0x1FFF,SSSNROMRamWrite);
|
||||
SetReadHandler(0x0800, 0x1FFF, CartBR);
|
||||
SetWriteHandler(0x0800, 0x1FFF, CartBW);
|
||||
|
||||
+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);
|
||||
|
||||
+130
-131
@@ -30,26 +30,22 @@ static uint32 CHRRAMSize;
|
||||
|
||||
static void BMCFK23CCW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&0x40)
|
||||
setchr8(EXPREGS[2]|unromchr);
|
||||
else if(EXPREGS[0]&0x20) {
|
||||
setchr1r(0x10, A, V);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16 base=(EXPREGS[2]&0x7F)<<3;
|
||||
if(EXPREGS[3]&2)
|
||||
{
|
||||
int cbase=(MMC3_cmd&0x80)<<5;
|
||||
setchr1(A,V|base);
|
||||
setchr1(0x0000^cbase,DRegBuf[0]|base);
|
||||
setchr1(0x0400^cbase,EXPREGS[6]|base);
|
||||
setchr1(0x0800^cbase,DRegBuf[1]|base);
|
||||
setchr1(0x0c00^cbase,EXPREGS[7]|base);
|
||||
}
|
||||
else
|
||||
setchr1(A,V|base);
|
||||
}
|
||||
if(EXPREGS[0]&0x40)
|
||||
setchr8(EXPREGS[2]|unromchr);
|
||||
else if(EXPREGS[0]&0x20) {
|
||||
setchr1r(0x10, A, V);
|
||||
} else {
|
||||
uint16 base=(EXPREGS[2]&0x7F)<<3;
|
||||
if(EXPREGS[3]&2) {
|
||||
int cbase=(MMC3_cmd&0x80)<<5;
|
||||
setchr1(A,V|base);
|
||||
setchr1(0x0000^cbase,DRegBuf[0]|base);
|
||||
setchr1(0x0400^cbase,EXPREGS[6]|base);
|
||||
setchr1(0x0800^cbase,DRegBuf[1]|base);
|
||||
setchr1(0x0c00^cbase,EXPREGS[7]|base);
|
||||
} else
|
||||
setchr1(A,V|base);
|
||||
}
|
||||
}
|
||||
|
||||
//some games are wired differently, and this will need to be changed.
|
||||
@@ -86,110 +82,110 @@ static int prg_mask;
|
||||
//PRG wrapper
|
||||
static void BMCFK23CPW(uint32 A, uint8 V)
|
||||
{
|
||||
uint32 bank = (EXPREGS[1] & 0x1F);
|
||||
uint32 hiblock = ((EXPREGS[0] & 8) << 4)|((EXPREGS[0] & 0x80) << 1)|(UNIFchrrama?((EXPREGS[2] & 0x40)<<3):0);
|
||||
uint32 block = (EXPREGS[1] & 0x60) | hiblock;
|
||||
uint32 extra = (EXPREGS[3] & 2);
|
||||
//uint32 bank = (EXPREGS[1] & 0x1F);
|
||||
//uint32 hiblock = ((EXPREGS[0] & 8) << 4)|((EXPREGS[0] & 0x80) << 1)|(UNIFchrrama?((EXPREGS[2] & 0x40)<<3):0);
|
||||
//uint32 block = (EXPREGS[1] & 0x60) | hiblock;
|
||||
//uint32 extra = (EXPREGS[3] & 2);
|
||||
// FCEU_printf("0:%04X:%02X\n",A,V);
|
||||
|
||||
if((EXPREGS[0]&7)==4)
|
||||
setprg32(0x8000,EXPREGS[1]>>1);
|
||||
else if ((EXPREGS[0]&7)==3)
|
||||
{
|
||||
setprg16(0x8000,EXPREGS[1]);
|
||||
setprg16(0xC000,EXPREGS[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(EXPREGS[0]&3)
|
||||
{
|
||||
if((EXPREGS[0]&7)==4)
|
||||
setprg32(0x8000,EXPREGS[1]>>1);
|
||||
else if ((EXPREGS[0]&7)==3) {
|
||||
setprg16(0x8000,EXPREGS[1]);
|
||||
setprg16(0xC000,EXPREGS[1]);
|
||||
} else {
|
||||
if(EXPREGS[0]&3) {
|
||||
uint32 blocksize = (6)-(EXPREGS[0]&3);
|
||||
uint32 mask = (1<<blocksize)-1;
|
||||
V &= mask;
|
||||
//V &= 63; //? is this a good idea?
|
||||
V |= (EXPREGS[1]<<1);
|
||||
setprg8(A,V);
|
||||
// FCEU_printf("1:%04X:%02X\n",A,V);
|
||||
setprg8(A,V);
|
||||
} else {
|
||||
setprg8(A,V & prg_mask);
|
||||
// FCEU_printf("2:%04X:%02X\n",A,V);
|
||||
}
|
||||
else
|
||||
setprg8(A,V & prg_mask);
|
||||
|
||||
if(EXPREGS[3]&2)
|
||||
{
|
||||
setprg8(0xC000,EXPREGS[4]);
|
||||
setprg8(0xE000,EXPREGS[5]);
|
||||
}
|
||||
}
|
||||
if(EXPREGS[3]&2) {
|
||||
setprg8(0xC000,EXPREGS[4]);
|
||||
setprg8(0xE000,EXPREGS[5]);
|
||||
}
|
||||
}
|
||||
setprg8r(0x10,0x6000,A001B&3);
|
||||
}
|
||||
|
||||
//PRG handler ($8000-$FFFF)
|
||||
static DECLFW(BMCFK23CHiWrite)
|
||||
{
|
||||
if(EXPREGS[0]&0x40)
|
||||
{
|
||||
// FCEU_printf("K4:(exp0=%02x)\n",EXPREGS[0]);
|
||||
// FCEU_printf("W0:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
|
||||
if((EXPREGS[0]&0x60)==0x40) {
|
||||
// FCEU_printf("W2:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
|
||||
if(EXPREGS[0]&0x30)
|
||||
unromchr=0;
|
||||
else
|
||||
{
|
||||
else {
|
||||
unromchr=V&3;
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if((A==0x8001)&&(EXPREGS[3]&2&&MMC3_cmd&8))
|
||||
{
|
||||
} else {
|
||||
if((A==0x8001)&&(EXPREGS[3]&2)&&(MMC3_cmd&8)) {
|
||||
// FCEU_printf("W3:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
|
||||
EXPREGS[4|(MMC3_cmd&3)]=V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
else
|
||||
if(A<0xC000) {
|
||||
if(UNIFchrrama) { // hacky... strange behaviour, must be bit scramble due to pcb layot restrictions
|
||||
// check if it not interfer with other dumps
|
||||
if((A==0x8000)&&(V==0x46))
|
||||
V=0x47;
|
||||
else if((A==0x8000)&&(V==0x47))
|
||||
V=0x46;
|
||||
}
|
||||
MMC3_CMDWrite(A,V);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
else
|
||||
MMC3_IRQWrite(A,V);
|
||||
}
|
||||
} else
|
||||
if(A<0xC000) {
|
||||
if(UNIFchrrama) { // hacky... strange behaviour, must be bit scramble due to pcb layot restrictions
|
||||
// check if it not interfer with other dumps
|
||||
if((A==0x8000)&&(V==0x46))
|
||||
V=0x47;
|
||||
else if((A==0x8000)&&(V==0x47))
|
||||
V=0x46;
|
||||
}
|
||||
// FCEU_printf("W1:%04X:%02X\n",A,V);
|
||||
MMC3_CMDWrite(A,V);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
} else {
|
||||
MMC3_IRQWrite(A,V);
|
||||
// FCEU_printf("W4:%04X:%02X (exp0=%02x)\n",A,V,EXPREGS[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//EXP handler ($5000-$5FFF)
|
||||
static DECLFW(BMCFK23CWrite)
|
||||
{
|
||||
if(A&(1<<(dipswitch+4)))
|
||||
{
|
||||
if(A&(1<<(dipswitch+4))) {
|
||||
//printf("+ ");
|
||||
EXPREGS[A&3]=V;
|
||||
EXPREGS[A&3]=V;
|
||||
|
||||
bool remap = false;
|
||||
// BUT WHY is there any rom that need it actually?
|
||||
// bool remap = false;
|
||||
// FCEU_printf("K3:(exp0=%02x)\n",EXPREGS[0]);
|
||||
// FCEU_printf("WH0:%04X:%02X\n",A,V);
|
||||
|
||||
//sometimes writing to reg0 causes remappings to occur. we think the 2 signifies this.
|
||||
//sometimes writing to reg0 causes remappings to occur. we think the 2 signifies this.
|
||||
//if not, 0x24 is a value that is known to work
|
||||
//however, the low 4 bits are known to control the mapping mode, so 0x20 is more likely to be the immediate remap flag
|
||||
remap |= ((EXPREGS[0]&0xF0)==0x20);
|
||||
// remap |= ((EXPREGS[0]&0xF0)==0x20);
|
||||
|
||||
//this is an actual mapping reg. i think reg0 controls what happens when reg1 is written. anyway, we have to immediately remap these
|
||||
remap |= (A&3)==1;
|
||||
// remap |= (A&3)==1;
|
||||
//this too.
|
||||
remap |= (A&3)==2;
|
||||
// remap |= (A&3)==2;
|
||||
|
||||
if(remap)
|
||||
{
|
||||
// if(remap) {
|
||||
// FCEU_printf("WH1:%04X:%02X\n",A,V);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
if(is_BMCFK23CA)
|
||||
{
|
||||
if(is_BMCFK23CA) {
|
||||
if(EXPREGS[3]&2)
|
||||
EXPREGS[0] &= ~7; // hacky hacky! if someone wants extra banking, then for sure doesn't want mode 4 for it! (allow to run A version boards on normal mapper)
|
||||
// FCEU_printf("EXTRA!\n",A);
|
||||
EXPREGS[0] &= ~7; // hacky hacky! if someone wants extra banking, then for sure doesn't want mode 4 for it! (allow to run A version boards on normal mapper)
|
||||
}
|
||||
|
||||
//printf("%04X = $%02X\n",A,V);
|
||||
@@ -199,62 +195,65 @@ static DECLFW(BMCFK23CWrite)
|
||||
static void BMCFK23CReset(void)
|
||||
{
|
||||
//NOT NECESSARY ANYMORE
|
||||
// BUT WHY?
|
||||
//this little hack makes sure that we try all the dip switch settings eventually, if we reset enough
|
||||
// dipswitch++;
|
||||
// dipswitch&=7;
|
||||
//printf("BMCFK23C dipswitch set to %d\n",dipswitch);
|
||||
dipswitch++;
|
||||
dipswitch&=7;
|
||||
printf("BMCFK23C dipswitch set to %u\n",dipswitch);
|
||||
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
MMC3RegReset();
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
// FCEU_printf("K0:(exp0=%02x)\n",EXPREGS[0]);
|
||||
MMC3RegReset();
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void BMCFK23CPower(void)
|
||||
{
|
||||
GenMMC3Power();
|
||||
dipswitch = 0;
|
||||
GenMMC3Power();
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
// FCEU_printf("K1:(exp0=%02x)\n",EXPREGS[0]);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
||||
}
|
||||
|
||||
static void BMCFK23CAPower(void)
|
||||
{
|
||||
GenMMC3Power();
|
||||
dipswitch = 0;
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
GenMMC3Power();
|
||||
dipswitch = 0;
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
// FCEU_printf("K2:(exp0=%02x)\n",EXPREGS[0]);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
|
||||
}
|
||||
|
||||
static void BMCFK23CAClose(void)
|
||||
{
|
||||
if(CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM=NULL;
|
||||
if(CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM=NULL;
|
||||
}
|
||||
|
||||
void BMCFK23C_Init(CartInfo *info)
|
||||
{
|
||||
is_BMCFK23CA = false;
|
||||
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap=BMCFK23CCW;
|
||||
pwrap=BMCFK23CPW;
|
||||
info->Power=BMCFK23CPower;
|
||||
info->Reset=BMCFK23CReset;
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UCHR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap=BMCFK23CCW;
|
||||
pwrap=BMCFK23CPW;
|
||||
info->Power=BMCFK23CPower;
|
||||
info->Reset=BMCFK23CReset;
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UCHR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
|
||||
prg_bonus = 1;
|
||||
if(MasterRomInfoParams.find("bonus") != MasterRomInfoParams.end())
|
||||
@@ -267,21 +266,21 @@ void BMCFK23CA_Init(CartInfo *info)
|
||||
{
|
||||
is_BMCFK23CA = true;
|
||||
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap=BMCFK23CCW;
|
||||
pwrap=BMCFK23CPW;
|
||||
info->Power=BMCFK23CAPower;
|
||||
info->Reset=BMCFK23CReset;
|
||||
info->Close=BMCFK23CAClose;
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap=BMCFK23CCW;
|
||||
pwrap=BMCFK23CPW;
|
||||
info->Power=BMCFK23CAPower;
|
||||
info->Reset=BMCFK23CReset;
|
||||
info->Close=BMCFK23CAClose;
|
||||
|
||||
CHRRAMSize=8192;
|
||||
CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
|
||||
AddExState(CHRRAM, CHRRAMSize, 0, "CRAM");
|
||||
CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
|
||||
AddExState(CHRRAM, CHRRAMSize, 0, "CRAM");
|
||||
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UCHR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UCHR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
|
||||
prg_bonus = 1;
|
||||
if(MasterRomInfoParams.find("bonus") != MasterRomInfoParams.end())
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 1998 BERO
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
* Copyright (C) 2020 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
|
||||
*
|
||||
* Famicom Network System Base Unit + MMC1 cartridge board
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 DRegs[4];
|
||||
static uint8 Buffer, BufferShift;
|
||||
|
||||
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;
|
||||
return(Page[A >> 11][A]);
|
||||
}
|
||||
|
||||
static void MMC1CHR(void) {
|
||||
setchr8((r40C0 >> 3) & 1);
|
||||
}
|
||||
|
||||
static void MMC1PRG(void) {
|
||||
uint8 offs_16banks = DRegs[1] & 0x10;
|
||||
uint8 prg_reg = DRegs[3] & 0xF;
|
||||
|
||||
setprg8r(0x10, 0x6000, DRegs[1] & 3);
|
||||
|
||||
switch (DRegs[0] & 0xC) {
|
||||
case 0xC:
|
||||
setprg16(0x8000, (prg_reg + offs_16banks));
|
||||
setprg16(0xC000, 0xF + offs_16banks);
|
||||
break;
|
||||
case 0x8:
|
||||
setprg16(0xC000, (prg_reg + offs_16banks));
|
||||
setprg16(0x8000, offs_16banks);
|
||||
break;
|
||||
case 0x0:
|
||||
case 0x4:
|
||||
setprg16(0x8000, ((prg_reg & ~1) + offs_16banks));
|
||||
setprg16(0xc000, ((prg_reg & ~1) + offs_16banks + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void MMC1MIRROR(void) {
|
||||
switch (DRegs[0] & 3) {
|
||||
case 2: setmirror(MI_V); break;
|
||||
case 3: setmirror(MI_H); break;
|
||||
case 0: setmirror(MI_0); break;
|
||||
case 1: setmirror(MI_1); break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64 lreset;
|
||||
static DECLFW(MMC1_write) {
|
||||
int n = (A >> 13) - 4;
|
||||
if ((timestampbase + timestamp) < (lreset + 2))
|
||||
return;
|
||||
|
||||
if (V & 0x80) {
|
||||
DRegs[0] |= 0xC;
|
||||
BufferShift = Buffer = 0;
|
||||
MMC1PRG();
|
||||
lreset = timestampbase + timestamp;
|
||||
return;
|
||||
}
|
||||
|
||||
Buffer |= (V & 1) << (BufferShift++);
|
||||
|
||||
if (BufferShift == 5) {
|
||||
FCEU_printf("MMC1 REG%d:%02x (PC %04x)\n", n, Buffer, X.PC);
|
||||
DRegs[n] = Buffer;
|
||||
BufferShift = Buffer = 0;
|
||||
switch (n) {
|
||||
case 0: MMC1MIRROR();
|
||||
case 1:
|
||||
case 2:
|
||||
case 3: MMC1PRG(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MMC1_Restore(int version) {
|
||||
MMC1MIRROR();
|
||||
MMC1CHR();
|
||||
MMC1PRG();
|
||||
lreset = 0;
|
||||
}
|
||||
|
||||
static void MMC1CMReset(void) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
DRegs[i] = 0;
|
||||
Buffer = BufferShift = 0;
|
||||
DRegs[0] = 0x1F;
|
||||
|
||||
DRegs[1] = 0;
|
||||
DRegs[2] = 0;
|
||||
DRegs[3] = 0;
|
||||
|
||||
MMC1MIRROR();
|
||||
MMC1CHR();
|
||||
MMC1PRG();
|
||||
}
|
||||
|
||||
static DECLFW(FNC_cmd_write) {
|
||||
switch (A) {
|
||||
case 0x40A6: {
|
||||
IRQCount = (IRQCount & 0xFF00) | V;
|
||||
break;
|
||||
}
|
||||
case 0x40A7: {
|
||||
IRQCount = (IRQCount & 0x00FF) | (V << 8);
|
||||
break;
|
||||
}
|
||||
case 0x40A8: {
|
||||
IRQa = V;
|
||||
break;
|
||||
}
|
||||
case 0x40B0: {
|
||||
kanji_page = V & 1;
|
||||
break;
|
||||
}
|
||||
case 0x40C0: {
|
||||
FCEU_printf("FNS W %04x:%02x (PC %04x)\n", A, V, X.PC);
|
||||
r40C0 = V;
|
||||
MMC1CHR();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FCEU_printf("FNS W %04x:%02x (PC %04x)\n", A, V, X.PC);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(FNC_stat_read) {
|
||||
switch (A) {
|
||||
case 0x40A2: {
|
||||
int ret = (IRQa >> 1);
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
IRQa = 0;
|
||||
return ret;
|
||||
}
|
||||
case 0x40AC: { // NMI/IRQ state reset (lookalike)
|
||||
return 0;
|
||||
}
|
||||
case 0x40B0: {
|
||||
kanji_pos = 0;
|
||||
return 0;
|
||||
}
|
||||
case 0x40C0: {
|
||||
FCEU_printf("FNS R %04x (PC %04x)\n", A, X.PC);
|
||||
int ret = r40C0;
|
||||
r40C0 &= 0;
|
||||
return ret;
|
||||
}
|
||||
default: {
|
||||
FCEU_printf("FNS R %04x (PC %04x)\n", A, X.PC);
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(FNC_cart_i2c_read) {
|
||||
FCEU_printf("I2C R %04x (PC %04x)\n", A, X.PC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static DECLFR(FNC_kanji_read) {
|
||||
int32 ofs = ((A & 0xFFF) << 5) + kanji_pos;
|
||||
kanji_pos++;
|
||||
kanji_pos &= 0x1F;
|
||||
// if (PRGptr[1] != NULL) // iNES debug
|
||||
return PRGptr[1][ofs];
|
||||
// else
|
||||
// return CHRptr[0][ofs];
|
||||
}
|
||||
|
||||
void NFC_IRQ(int a) {
|
||||
if (IRQa) {
|
||||
IRQCount -= a;
|
||||
if (IRQCount <= 0)
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
|
||||
static void FNS_Power(void) {
|
||||
lreset = 0;
|
||||
SetWriteHandler(0x8000, 0xFFFF, MMC1_write);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
|
||||
kanji_page = 0;
|
||||
kanji_pos = 0;
|
||||
r40C0 = 0xC0;
|
||||
|
||||
SetWriteHandler(0x4080, 0x40FF, FNC_cmd_write);
|
||||
SetReadHandler(0x4080, 0x40FF, FNC_stat_read);
|
||||
SetReadHandler(0x5000, 0x5FFF, FNC_kanji_read);
|
||||
|
||||
SetReadHandler(0x6000, 0x6000, FNC_cart_i2c_read);
|
||||
SetReadHandler(0x6001, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
|
||||
FCEU_CheatAddRAM(8, 0x6000, WRAM);
|
||||
MMC1CMReset();
|
||||
}
|
||||
|
||||
static void FNS_Close(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
void FNS_Init(CartInfo *info) {
|
||||
info->Close = FNS_Close;
|
||||
info->Power = FNS_Power;
|
||||
|
||||
GameStateRestore = MMC1_Restore;
|
||||
MapIRQHook = NFC_IRQ;
|
||||
|
||||
WRAMSIZE = (8 + 32) * 1024;
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
info->addSaveGameBuf( WRAM, WRAMSIZE );
|
||||
|
||||
AddExState(DRegs, 4, 0, "DREG");
|
||||
AddExState(&lreset, 8, 1, "LRST");
|
||||
AddExState(&Buffer, 1, 1, "BFFR");
|
||||
AddExState(&BufferShift, 1, 1, "BFRS");
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2017 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
|
||||
*
|
||||
* HP10xx/HP20xx - a simplified version of FK23C mapper with pretty strict and better
|
||||
* organized banking behaviour. It seems that some 176 mapper assigned game may be
|
||||
* actually this kind of board instead but in common they aren't compatible at all,
|
||||
* the games on the regular FK23C boards couldn't run on this mapper and vice versa...
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
#include "../ines.h"
|
||||
|
||||
static uint8 unromchr, lock;
|
||||
static uint32 dipswitch;
|
||||
|
||||
static void BMCHPxxCW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&4) { // custom banking
|
||||
switch(EXPREGS[0]&3) {
|
||||
case 0:
|
||||
case 1:
|
||||
setchr8(EXPREGS[2]&0x3F);
|
||||
// FCEU_printf("\tCHR8 %02X\n",EXPREGS[2]&0x3F);
|
||||
break;
|
||||
case 2:
|
||||
setchr8((EXPREGS[2]&0x3E)|(unromchr&1));
|
||||
// FCEU_printf("\tCHR8 %02X\n",(EXPREGS[2]&0x3E)|(unromchr&1));
|
||||
break;
|
||||
case 3:
|
||||
setchr8((EXPREGS[2]&0x3C)|(unromchr&3));
|
||||
// FCEU_printf("\tCHR8 %02X\n",(EXPREGS[2]&0x3C)|(unromchr&3));
|
||||
break;
|
||||
}
|
||||
} else { // mmc3 banking
|
||||
int base, mask;
|
||||
if(EXPREGS[0]&1) { // 128K mode
|
||||
base=EXPREGS[2]&0x30;
|
||||
mask=0x7F;
|
||||
} else { // 256K mode
|
||||
base=EXPREGS[2]&0x20;
|
||||
mask=0xFF;
|
||||
}
|
||||
// FCEU_printf("\tCHR1 %04x:%02X\n",A,(V&mask)|(base<<3));
|
||||
setchr1(A,(V&mask)|(base<<3));
|
||||
}
|
||||
}
|
||||
|
||||
//PRG wrapper
|
||||
static void BMCHPxxPW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&4) { // custom banking
|
||||
if((EXPREGS[0]&0xF)==4) { // 16K mode
|
||||
// FCEU_printf("\tPRG16 %02X\n",EXPREGS[1]&0x1F);
|
||||
setprg16(0x8000,EXPREGS[1]&0x1F);
|
||||
setprg16(0xC000,EXPREGS[1]&0x1F);
|
||||
} else { // 32K modes
|
||||
// FCEU_printf("\tPRG32 %02X\n",(EXPREGS[1]&0x1F)>>1);
|
||||
setprg32(0x8000,(EXPREGS[1]&0x1F)>>1);
|
||||
}
|
||||
} else { // mmc3 banking
|
||||
int base, mask;
|
||||
if(EXPREGS[0]&2) { // 128K mode
|
||||
base=EXPREGS[1]&0x18;
|
||||
mask=0x0F;
|
||||
} else { // 256K mode
|
||||
base=EXPREGS[1]&0x10;
|
||||
mask=0x1F;
|
||||
}
|
||||
// FCEU_printf("\tPRG8 %02X\n",(V&mask)|(base<<1));
|
||||
setprg8(A,(V&mask)|(base<<1));
|
||||
setprg8r(0x10,0x6000,A001B&3);
|
||||
}
|
||||
}
|
||||
|
||||
//MIRROR wrapper
|
||||
static void BMCHPxxMW(uint8 V) {
|
||||
if(EXPREGS[0]&4) { // custom banking
|
||||
// FCEU_printf("CUSTOM MIRR: %d\n",(unromchr>>2)&1);
|
||||
setmirror(((unromchr>>2)&1)^1);
|
||||
} else { // mmc3 banking
|
||||
// FCEU_printf("MMC3 MIRR: %d\n",(V&1)^1);
|
||||
A000B = V;
|
||||
setmirror((A000B & 1) ^ 1);
|
||||
}
|
||||
}
|
||||
|
||||
//PRG handler ($8000-$FFFF)
|
||||
static DECLFW(BMCHPxxHiWrite)
|
||||
{
|
||||
// FCEU_printf("HI WRITE %04X:%02X\n",A,V);
|
||||
if(EXPREGS[0]&4) { // custom banking
|
||||
// FCEU_printf("CUSTOM\n");
|
||||
unromchr=V;
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
} else { // mmc3 banking
|
||||
// FCEU_printf("MMC3\n");
|
||||
if(A<0xC000) {
|
||||
MMC3_CMDWrite(A,V);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
} else {
|
||||
MMC3_IRQWrite(A,V);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//EXP handler ($5000-$5FFF)
|
||||
static DECLFW(BMCHPxxWrite)
|
||||
{
|
||||
if(!lock) {
|
||||
// FCEU_printf("LO WRITE %04X:%02X\n",A,V);
|
||||
EXPREGS[A&3]=V;
|
||||
lock=V&0x80;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(BMCHPxxRead) {
|
||||
return dipswitch;
|
||||
}
|
||||
|
||||
static void BMCHPxxReset(void)
|
||||
{
|
||||
dipswitch++;
|
||||
dipswitch&=0xF;
|
||||
lock=0;
|
||||
// FCEU_printf("BMCHPxx dipswitch set to %d\n",dipswitch);
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
MMC3RegReset();
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void BMCHPxxPower(void)
|
||||
{
|
||||
GenMMC3Power();
|
||||
dipswitch=lock=0;
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
SetReadHandler(0x5000,0x5fff,BMCHPxxRead);
|
||||
SetWriteHandler(0x5000,0x5fff,BMCHPxxWrite);
|
||||
SetWriteHandler(0x8000,0xffff,BMCHPxxHiWrite);
|
||||
}
|
||||
|
||||
void BMCHPxx_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC3_Init(info, 256, 256, 8, 0);
|
||||
cwrap=BMCHPxxCW;
|
||||
pwrap=BMCHPxxPW;
|
||||
mwrap=BMCHPxxMW;
|
||||
info->Power=BMCHPxxPower;
|
||||
info->Reset=BMCHPxxReset;
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UCHR");
|
||||
AddExState(&dipswitch, 1, 0, "DPSW");
|
||||
AddExState(&lock, 1, 0, "LOCK");
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -35,6 +35,7 @@ static void MALEEPower(void) {
|
||||
|
||||
void MALEE_Init(CartInfo *info) {
|
||||
info->Power = MALEEPower;
|
||||
FCEU_MemoryRand(WRAM,sizeof(WRAM),true);
|
||||
SetupCartPRGMapping(0x10, WRAM, 2048, 1);
|
||||
AddExState(WRAM, 2048, 0, "WRAM");
|
||||
}
|
||||
|
||||
+58
-48
@@ -22,12 +22,13 @@
|
||||
#include "mapinc.h"
|
||||
|
||||
static void GenMMC1Power(void);
|
||||
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery);
|
||||
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int bram);
|
||||
|
||||
static uint8 DRegs[4];
|
||||
static uint8 Buffer, BufferShift;
|
||||
|
||||
static int mmc1opts;
|
||||
static uint32 WRAMSIZE;
|
||||
static uint32 NONBRAMSIZE; // size of non-battery-backed portion of WRAM
|
||||
|
||||
static void (*MMC1CHRHook4)(uint32 A, uint8 V);
|
||||
static void (*MMC1PRGHook16)(uint32 A, uint8 V);
|
||||
@@ -48,9 +49,9 @@ static DECLFR(MAWRAM) {
|
||||
}
|
||||
|
||||
static void MMC1CHR(void) {
|
||||
if (mmc1opts & 4) {
|
||||
if (DRegs[0] & 0x10)
|
||||
setprg8r(0x10, 0x6000, (DRegs[1] >> 4) & 1);
|
||||
if (WRAMSIZE > 0x2000) {
|
||||
if (WRAMSIZE > 0x4000)
|
||||
setprg8r(0x10, 0x6000, (DRegs[1] >> 2) & 3);
|
||||
else
|
||||
setprg8r(0x10, 0x6000, (DRegs[1] >> 3) & 1);
|
||||
}
|
||||
@@ -179,20 +180,39 @@ static void MMC1CMReset(void) {
|
||||
MMC1PRG();
|
||||
}
|
||||
|
||||
static int DetectMMC1WRAMSize(uint32 crc32) {
|
||||
switch (crc32) {
|
||||
static int DetectMMC1WRAMSize(CartInfo *info, int *bs) {
|
||||
int ws = 8;
|
||||
switch (info->CRC32) {
|
||||
case 0xc6182024: // Romance of the 3 Kingdoms
|
||||
case 0xabbf7217: // "" "" (J) (PRG0)
|
||||
case 0xccf35c02: // "" "" (J) (PRG1)
|
||||
case 0x2225c20f: // Genghis Khan
|
||||
case 0xfb69743a: // "" "" (J)
|
||||
case 0x4642dda6: // Nobunaga's Ambition
|
||||
case 0x29449ba9: // "" "" (J)
|
||||
case 0x2b11e0b0: // "" "" (J)
|
||||
case 0xb8747abf: // Best Play Pro Yakyuu Special (J)
|
||||
case 0xc9556b36: // Final Fantasy I & II (J) [!]
|
||||
FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n");
|
||||
return(16);
|
||||
case 0x3f7ad415: // "" "" (J) (PRG0)
|
||||
case 0x2b11e0b0: // "" "" (J) (PRG1)
|
||||
*bs = 8;
|
||||
ws = 16;
|
||||
break;
|
||||
default: return(8);
|
||||
case 0xb8747abf: // Best Play Pro Yakyuu Special (J) (PRG0)
|
||||
case 0xc3de7c69: // "" "" (J) (PRG1)
|
||||
case 0xc9556b36: // Final Fantasy I & II (J) [!]
|
||||
*bs = 32;
|
||||
ws = 32;
|
||||
break;
|
||||
default:
|
||||
if(info->ines2) {
|
||||
ws = (info->wram_size + info->battery_wram_size) / 1024;
|
||||
*bs = info->battery_wram_size / 1024;
|
||||
// we only support sizes between 8K and 32K
|
||||
if (ws > 0 && ws < 8) ws = 8;
|
||||
if (ws > 32) ws = 32;
|
||||
if (*bs > ws) *bs = ws;
|
||||
}
|
||||
}
|
||||
if (ws > 8)
|
||||
FCEU_printf(" >8KB external WRAM present. Use NES 2.0 if you hack the ROM image.\n");
|
||||
return ws;
|
||||
}
|
||||
|
||||
static uint32 NWCIRQCount;
|
||||
@@ -244,17 +264,16 @@ void Mapper105_Init(CartInfo *info) {
|
||||
|
||||
static void GenMMC1Power(void) {
|
||||
lreset = 0;
|
||||
if (mmc1opts & 1) {
|
||||
FCEU_CheatAddRAM(8, 0x6000, WRAM);
|
||||
if (mmc1opts & 4)
|
||||
FCEU_dwmemset(WRAM, 0, 8192)
|
||||
else if (!(mmc1opts & 2))
|
||||
FCEU_dwmemset(WRAM, 0, 8192); // wtf?
|
||||
}
|
||||
SetWriteHandler(0x8000, 0xFFFF, MMC1_write);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
|
||||
if (mmc1opts & 1) {
|
||||
if (WRAMSIZE) {
|
||||
FCEU_CheatAddRAM(8, 0x6000, WRAM);
|
||||
|
||||
// clear non-battery-backed portion of WRAM
|
||||
if (NONBRAMSIZE)
|
||||
FCEU_MemoryRand(WRAM, NONBRAMSIZE, true);
|
||||
|
||||
SetReadHandler(0x6000, 0x7FFF, MAWRAM);
|
||||
SetWriteHandler(0x6000, 0x7FFF, MBWRAM);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
@@ -271,31 +290,23 @@ static void GenMMC1Close(void) {
|
||||
CHRRAM = WRAM = NULL;
|
||||
}
|
||||
|
||||
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery) {
|
||||
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int bram) {
|
||||
is155 = 0;
|
||||
|
||||
info->Close = GenMMC1Close;
|
||||
MMC1PRGHook16 = MMC1CHRHook4 = 0;
|
||||
mmc1opts = 0;
|
||||
WRAMSIZE = wram * 1024;
|
||||
NONBRAMSIZE = (wram - bram) * 1024;
|
||||
PRGmask16[0] &= (prg >> 14) - 1;
|
||||
CHRmask4[0] &= (chr >> 12) - 1;
|
||||
CHRmask8[0] &= (chr >> 13) - 1;
|
||||
|
||||
if (wram) {
|
||||
WRAM = (uint8*)FCEU_gmalloc(wram * 1024);
|
||||
//mbg 17-jun-08 - this shouldve been cleared to re-initialize save ram
|
||||
//ch4 10-dec-08 - nope, this souldn't
|
||||
//mbg 29-mar-09 - no time to debate this, we need to keep from breaking some old stuff.
|
||||
//we really need to make up a policy for how compatibility and accuracy can be resolved.
|
||||
memset(WRAM, 0, wram * 1024);
|
||||
mmc1opts |= 1;
|
||||
if (wram > 8) mmc1opts |= 4;
|
||||
SetupCartPRGMapping(0x10, WRAM, wram * 1024, 1);
|
||||
AddExState(WRAM, wram * 1024, 0, "WRAM");
|
||||
if (battery) {
|
||||
mmc1opts |= 2;
|
||||
info->SaveGame[0] = WRAM + ((mmc1opts & 4) ? 8192 : 0);
|
||||
info->SaveGameLen[0] = 8192;
|
||||
if (WRAMSIZE) {
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
if (bram) {
|
||||
info->addSaveGameBuf( WRAM + NONBRAMSIZE, bram * 1024 );
|
||||
}
|
||||
}
|
||||
if (!chr) {
|
||||
@@ -313,13 +324,14 @@ static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery)
|
||||
}
|
||||
|
||||
void Mapper1_Init(CartInfo *info) {
|
||||
int ws = DetectMMC1WRAMSize(info->CRC32);
|
||||
GenMMC1Init(info, 512, 256, ws, info->battery);
|
||||
int bs = info->battery ? 8 : 0;
|
||||
int ws = DetectMMC1WRAMSize(info, &bs);
|
||||
GenMMC1Init(info, 512, 256, ws, bs);
|
||||
}
|
||||
|
||||
/* Same as mapper 1, without respect for WRAM enable bit. */
|
||||
void Mapper155_Init(CartInfo *info) {
|
||||
GenMMC1Init(info, 512, 256, 8, info->battery);
|
||||
GenMMC1Init(info, 512, 256, 8, info->battery ? 8 : 0);
|
||||
is155 = 1;
|
||||
}
|
||||
|
||||
@@ -331,7 +343,7 @@ void Mapper171_Init(CartInfo *info) {
|
||||
}
|
||||
|
||||
void SAROM_Init(CartInfo *info) {
|
||||
GenMMC1Init(info, 128, 64, 8, info->battery);
|
||||
GenMMC1Init(info, 128, 64, 8, info->battery ? 8 : 0);
|
||||
}
|
||||
|
||||
void SBROM_Init(CartInfo *info) {
|
||||
@@ -351,7 +363,7 @@ void SGROM_Init(CartInfo *info) {
|
||||
}
|
||||
|
||||
void SKROM_Init(CartInfo *info) {
|
||||
GenMMC1Init(info, 256, 64, 8, info->battery);
|
||||
GenMMC1Init(info, 256, 64, 8, info->battery ? 8 : 0);
|
||||
}
|
||||
|
||||
void SLROM_Init(CartInfo *info) {
|
||||
@@ -383,11 +395,9 @@ void SHROM_Init(CartInfo *info) {
|
||||
/* */
|
||||
|
||||
void SNROM_Init(CartInfo *info) {
|
||||
GenMMC1Init(info, 256, 0, 8, info->battery);
|
||||
GenMMC1Init(info, 256, 0, 8, info->battery ? 8 : 0);
|
||||
}
|
||||
|
||||
void SOROM_Init(CartInfo *info) {
|
||||
GenMMC1Init(info, 256, 0, 16, info->battery);
|
||||
GenMMC1Init(info, 256, 0, 16, info->battery ? 8 : 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
+111
-21
@@ -113,6 +113,9 @@ void MMC3RegReset(void) {
|
||||
DRegBuf[6] = 0;
|
||||
DRegBuf[7] = 1;
|
||||
|
||||
// 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
|
||||
kt_extra = 0;
|
||||
|
||||
FixMMC3PRG(0);
|
||||
FixMMC3CHR(0);
|
||||
}
|
||||
@@ -187,7 +190,14 @@ DECLFW(MMC3_IRQWrite) {
|
||||
DECLFW(KT008HackWrite) {
|
||||
// FCEU_printf("%04x:%04x\n",A,V);
|
||||
switch (A & 3) {
|
||||
case 0: kt_extra = V; FixMMC3PRG(MMC3_cmd); break;
|
||||
case 0: {
|
||||
if (V == 0x27) // FF Xn hack! one more mapper in one
|
||||
kt_extra = 0;
|
||||
else
|
||||
kt_extra = V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
break;
|
||||
}
|
||||
case 1: break; // unk
|
||||
case 2: break; // unk
|
||||
case 3: break; // unk
|
||||
@@ -279,11 +289,11 @@ void GenMMC3Power(void) {
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
}
|
||||
if (!(mmc3opts & 2))
|
||||
FCEU_dwmemset(WRAM, 0, WRAMSIZE);
|
||||
FCEU_MemoryRand(WRAM, WRAMSIZE, true);
|
||||
}
|
||||
MMC3RegReset();
|
||||
if (CHRRAM)
|
||||
FCEU_dwmemset(CHRRAM, 0, CHRRAMSIZE);
|
||||
FCEU_MemoryRand(CHRRAM, CHRRAMSIZE, true);
|
||||
}
|
||||
|
||||
static void GenMMC3Close(void) {
|
||||
@@ -314,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
|
||||
@@ -1127,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;
|
||||
@@ -1150,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);
|
||||
@@ -1159,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");
|
||||
}
|
||||
|
||||
@@ -1353,3 +1415,31 @@ void TQROM_Init(CartInfo *info) {
|
||||
void HKROM_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 512, 1, info->battery);
|
||||
}
|
||||
|
||||
// -------------------------------- iNES 2.0 ----------------------------
|
||||
|
||||
// ---------------------------- Mapper 406 ------------------------------
|
||||
|
||||
static DECLFW(M406CMDWrite) {
|
||||
MMC3_CMDWrite((A & 0xFFFE) | ((A & 2) >> 1), V);
|
||||
}
|
||||
|
||||
static DECLFW(M406IRQWrite) {
|
||||
MMC3_IRQWrite((A & 0xFFFE) | ((A & 2) >> 1), V);
|
||||
}
|
||||
|
||||
FCEU_MAYBE_UNUSED
|
||||
static DECLFW(M406Write) {
|
||||
}
|
||||
|
||||
static void M406_Power(void) {
|
||||
GenMMC3Power();
|
||||
// TODO : FLASH
|
||||
SetWriteHandler(0x8000, 0xBFFF, M406CMDWrite);
|
||||
SetWriteHandler(0xC000, 0xFFFF, M406IRQWrite);
|
||||
}
|
||||
|
||||
void Mapper406_Init(CartInfo *info) {
|
||||
GenMMC3_Init(info, 512, 256, 0, 0);
|
||||
info->Power = M406_Power;
|
||||
}
|
||||
|
||||
+249
-66
@@ -22,6 +22,15 @@
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
#define ABANKS MMC5SPRVPage
|
||||
#define BBANKS MMC5BGVPage
|
||||
#define SpriteON (PPU[1] & 0x10) //Show Sprite
|
||||
#define ScreenON (PPU[1] & 0x08) //Show screen
|
||||
#define PPUON (PPU[1] & 0x18) //PPU should operate
|
||||
#define Sprite16 (PPU[0] & 0x20) //Sprites 8x16/8x8
|
||||
|
||||
static void (*sfun)(int P);
|
||||
static void (*psfun)(void);
|
||||
|
||||
@@ -74,10 +83,11 @@ static INLINE void MMC5BGVROM_BANK8(uint32 V) {
|
||||
}
|
||||
}
|
||||
|
||||
static uint8 PRGBanks[4];
|
||||
static std::array<uint8,4> PRGBanks;
|
||||
static uint8 WRAMPage;
|
||||
static uint16 CHRBanksA[8], CHRBanksB[4];
|
||||
static uint8 WRAMMaskEnable[2];
|
||||
static std::array<uint16,8> CHRBanksA;
|
||||
static std::array<uint16,4> CHRBanksB;
|
||||
static std::array<uint8,2> WRAMMaskEnable;
|
||||
uint8 mmc5ABMode; /* A=0, B=1 */
|
||||
|
||||
static uint8 IRQScanline, IRQEnable;
|
||||
@@ -86,18 +96,20 @@ static uint8 CHRMode, NTAMirroring, NTFill, ATFill;
|
||||
static uint8 MMC5IRQR;
|
||||
static uint8 MMC5LineCounter;
|
||||
static uint8 mmc5psize, mmc5vsize;
|
||||
static uint8 mul[2];
|
||||
static std::array<uint8,2> mul;
|
||||
|
||||
static uint32 WRAMSIZE = 0;
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint8 *MMC5fill = NULL;
|
||||
static uint8 *ExRAM = NULL;
|
||||
static uint8 MMC5battery = 0;
|
||||
|
||||
static uint8 MMC5WRAMsize; //configuration, not state
|
||||
static uint8 MMC5WRAMIndex[8]; //configuration, not state
|
||||
const int MMC5WRAMMAX = 1<<7; // 7 bits in register interface (real MMC5 has only 4 pins, however)
|
||||
static uint8 MMC5WRAMsize=0; //configuration, not state
|
||||
static uint8 MMC5WRAMIndex[MMC5WRAMMAX]; //configuration, not state
|
||||
|
||||
static uint8 MMC5ROMWrProtect[4];
|
||||
static uint8 MMC5MemIn[5];
|
||||
static std::array<uint8,4> MMC5ROMWrProtect;
|
||||
static std::array<uint8,5> MMC5MemIn;
|
||||
|
||||
static void MMC5CHRA(void);
|
||||
static void MMC5CHRB(void);
|
||||
@@ -107,26 +119,50 @@ typedef struct __cartdata {
|
||||
uint8 size;
|
||||
} cartdata;
|
||||
|
||||
#define Sprite16 (PPU[0]& 0x20) //Sprites 8x16/8x8
|
||||
//#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V)>>10][(V)]
|
||||
static inline uint8 * MMC5BGVRAMADR(uint32 A) {
|
||||
#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)]
|
||||
|
||||
uint8* MMC5BGVRAMADR(uint32 A)
|
||||
{
|
||||
if(newppu)
|
||||
{
|
||||
if(Sprite16)
|
||||
{
|
||||
bool isPattern = PPUON != 0;
|
||||
if (ppuphase == PPUPHASE_OBJ && isPattern)
|
||||
return &ABANKS[(A) >> 10][(A)];
|
||||
if (ppuphase == PPUPHASE_BG && isPattern)
|
||||
return &BBANKS[(A) >> 10][(A)];
|
||||
else if(mmc5ABMode == 0)
|
||||
return &ABANKS[(A) >> 10][(A)];
|
||||
else
|
||||
return &BBANKS[(A) >> 10][(A)];
|
||||
}
|
||||
else return &ABANKS[(A) >> 10][(A)];;
|
||||
}
|
||||
|
||||
if (!Sprite16) {
|
||||
if (mmc5ABMode == 0)
|
||||
return &MMC5SPRVPage[(A) >> 10][(A)];
|
||||
return &ABANKS[(A) >> 10][(A)];
|
||||
else
|
||||
return &MMC5BGVPage[(A) >> 10][(A)];
|
||||
} else return &MMC5BGVPage[(A) >> 10][(A)];
|
||||
return &BBANKS[(A) >> 10][(A)];
|
||||
} else return &BBANKS[(A) >> 10][(A)];
|
||||
}
|
||||
|
||||
static void mmc5_PPUWrite(uint32 A, uint8 V) {
|
||||
uint32 tmp = A;
|
||||
extern uint8 PALRAM[0x20];
|
||||
extern uint8 UPALRAM[0x03];
|
||||
|
||||
if (tmp >= 0x3F00) {
|
||||
// hmmm....
|
||||
if (!(tmp & 0xf))
|
||||
PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = V & 0x3F;
|
||||
else if (tmp & 3) PALRAM[(tmp & 0x1f)] = V & 0x3f;
|
||||
if (!(tmp & 3)) {
|
||||
if (!(tmp & 0xC)) {
|
||||
PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = V & 0x3F;
|
||||
PALRAM[0x10] = PALRAM[0x14] = PALRAM[0x18] = PALRAM[0x1C] = V & 0x3F;
|
||||
}
|
||||
else
|
||||
UPALRAM[((tmp & 0xC) >> 2) - 1] = V & 0x3F;
|
||||
} else
|
||||
PALRAM[tmp & 0x1F] = V & 0x3F;
|
||||
} else if (tmp < 0x2000) {
|
||||
if (PPUCHRRAM & (1 << (tmp >> 10)))
|
||||
VPage[tmp >> 10][tmp] = V;
|
||||
@@ -136,16 +172,105 @@ static void mmc5_PPUWrite(uint32 A, uint8 V) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8 FASTCALL mmc5_PPURead(uint32 A) {
|
||||
if (A < 0x2000) {
|
||||
if (ppuphase == PPUPHASE_BG
|
||||
//zero 03-aug-2014 - added this to fix Uchuu Keibitai SDF. The game reads NT entries from CHR rom while PPU is disabled.
|
||||
//obviously we have enormous numbers of bugs springing from our terrible emulation of ppu-disabled states, but this does the job for fixing this one
|
||||
&& (PPU[1] & 0x10)
|
||||
)
|
||||
return *MMC5BGVRAMADR(A);
|
||||
else return MMC5SPRVPage[(A) >> 10][(A)];
|
||||
} else {
|
||||
extern uint32 NTRefreshAddr;
|
||||
uint8 FASTCALL mmc5_PPURead(uint32 A)
|
||||
{
|
||||
bool split = false;
|
||||
if(newppu)
|
||||
{
|
||||
if((MMC5HackSPMode&0x80) && !(MMC5HackCHRMode&2))
|
||||
{
|
||||
int target = MMC5HackSPMode&0x1f;
|
||||
int side = MMC5HackSPMode&0x40;
|
||||
int ht = NTRefreshAddr&31;
|
||||
|
||||
if(side==0)
|
||||
{
|
||||
if(ht<target) split = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ht>=target) split = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (A < 0x2000)
|
||||
{
|
||||
if(Sprite16)
|
||||
{
|
||||
bool isPattern = !!PPUON;
|
||||
if (ppuphase == PPUPHASE_OBJ && isPattern)
|
||||
return ABANKS[(A) >> 10][(A)];
|
||||
if (ppuphase == PPUPHASE_BG && isPattern)
|
||||
{
|
||||
if(split)
|
||||
return MMC5HackVROMPTR[MMC5HackSPPage*0x1000 + (A&0xFFF)];
|
||||
|
||||
//uhhh call through to this more sophisticated function, only if it's really needed?
|
||||
//we should probably reuse it completely, if we can
|
||||
if (MMC5HackCHRMode == 1)
|
||||
return *FCEUPPU_GetCHR(A,NTRefreshAddr);
|
||||
|
||||
return BBANKS[(A) >> 10][(A)];
|
||||
}
|
||||
else if(mmc5ABMode == 0)
|
||||
return ABANKS[(A) >> 10][(A)];
|
||||
else
|
||||
return BBANKS[(A) >> 10][(A)];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ppuphase == PPUPHASE_BG && ScreenON)
|
||||
{
|
||||
if(split)
|
||||
return MMC5HackVROMPTR[MMC5HackSPPage*0x1000 + (A&0xFFF)];
|
||||
|
||||
//uhhh call through to this more sophisticated function, only if it's really needed?
|
||||
//we should probably reuse it completely, if we can
|
||||
if (MMC5HackCHRMode == 1)
|
||||
return *FCEUPPU_GetCHR(A,NTRefreshAddr);
|
||||
}
|
||||
|
||||
return ABANKS[(A) >> 10][(A)];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(split)
|
||||
{
|
||||
static const int kHack = -1; //dunno if theres science to this or if it just fixes SDF (cant be bothered to think about it)
|
||||
int linetile = (newppu_get_scanline()+kHack)/8 + MMC5HackSPScroll;
|
||||
|
||||
//REF NT: return 0x2000 | (v << 0xB) | (h << 0xA) | (vt << 5) | ht;
|
||||
//REF AT: return 0x2000 | (v << 0xB) | (h << 0xA) | 0x3C0 | ((vt & 0x1C) << 1) | ((ht & 0x1C) >> 2);
|
||||
|
||||
if((A&0x3FF)>=0x3C0)
|
||||
{
|
||||
A &= ~(0x1C<<1); //mask off VT
|
||||
A |= (linetile&0x1C)<<1; //mask on adjusted VT
|
||||
return ExRAM[A & 0x3FF];
|
||||
}
|
||||
else
|
||||
{
|
||||
A &= ~((0x1F<<5) | (1<<0xB)); //mask off VT and V
|
||||
A |= (linetile&31)<<5; //mask on adjusted VT (V doesnt make any sense, I think)
|
||||
return ExRAM[A & 0x3FF];
|
||||
}
|
||||
}
|
||||
|
||||
if (MMC5HackCHRMode == 1)
|
||||
{
|
||||
if((A&0x3FF)>=0x3C0)
|
||||
{
|
||||
uint8 byte = ExRAM[NTRefreshAddr & 0x3ff];
|
||||
//get attribute part and paste it 4x across the byte
|
||||
byte >>= 6;
|
||||
byte *= 0x55;
|
||||
return byte;
|
||||
}
|
||||
}
|
||||
|
||||
return vnapage[(A >> 10) & 0x3][A & 0x3FF];
|
||||
}
|
||||
}
|
||||
@@ -182,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");
|
||||
@@ -194,6 +318,8 @@ int DetectMMC5WRAMSize(uint32 crc32) {
|
||||
}
|
||||
|
||||
static void BuildWRAMSizeTable(void) {
|
||||
bool other = false; // non-standard configuration
|
||||
// fill first 8 entries
|
||||
int x;
|
||||
for (x = 0; x < 8; x++) {
|
||||
switch (MMC5WRAMsize) {
|
||||
@@ -201,9 +327,22 @@ static void BuildWRAMSizeTable(void) {
|
||||
case 1: MMC5WRAMIndex[x] = (x > 3) ? 255 : 0; break; //0,0,0,0,X,X,X,X
|
||||
case 2: MMC5WRAMIndex[x] = (x & 4) >> 2; break; //0,0,0,0,1,1,1,1
|
||||
case 4: MMC5WRAMIndex[x] = (x > 3) ? 255 : (x & 3); break; //0,1,2,3,X,X,X,X
|
||||
case 8: MMC5WRAMIndex[x] = x; break; //0,1,2,3,4,5,6,7
|
||||
case 8: MMC5WRAMIndex[x] = x; break; //0,1,2,3,4,5,6,7
|
||||
default: MMC5WRAMIndex[x] = x; other = true; break; //0,1,2...
|
||||
}
|
||||
}
|
||||
// extend to fill complete table
|
||||
if (other)
|
||||
{
|
||||
for (x = 0; x < MMC5WRAMMAX && x < MMC5WRAMsize; ++x) MMC5WRAMIndex[x] = x; // linear mapping
|
||||
for (x = MMC5WRAMsize; x < MMC5WRAMMAX; ++x) MMC5WRAMIndex[x] = MMC5WRAMIndex[x-MMC5WRAMsize]; // repeat to fill table
|
||||
// theoretically the table fill should decompose into powers of two for possible mismatched SRAM combos,
|
||||
// but I don't want to complicate the code with unnecessary hypotheticals
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = 8; x < MMC5WRAMMAX; ++x) MMC5WRAMIndex[x] = MMC5WRAMIndex[x & 7]; // fill table, repeating groups of 8
|
||||
}
|
||||
}
|
||||
|
||||
static void MMC5CHRA(void) {
|
||||
@@ -271,7 +410,7 @@ static void MMC5CHRB(void) {
|
||||
}
|
||||
|
||||
static void MMC5WRAM(uint32 A, uint32 V) {
|
||||
V = MMC5WRAMIndex[V & 7];
|
||||
V = MMC5WRAMIndex[V & (MMC5WRAMMAX-1)];
|
||||
if (V != 255) {
|
||||
setprg8r(0x10, A, V);
|
||||
FCEU_CheatAddRAM(8, 0x6000, (WRAM + ((V * 8192) & (WRAMSIZE - 1))));
|
||||
@@ -285,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;
|
||||
@@ -296,8 +435,8 @@ static void MMC5PRG(void) {
|
||||
MMC5MemIn[1] = MMC5MemIn[2] = 1;
|
||||
} else {
|
||||
MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0;
|
||||
MMC5WRAM(0x8000, PRGBanks[1] & 7 & 0xFE);
|
||||
MMC5WRAM(0xA000, (PRGBanks[1] & 7 & 0xFE) + 1);
|
||||
MMC5WRAM(0x8000, PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE);
|
||||
MMC5WRAM(0xA000, (PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE) + 1);
|
||||
}
|
||||
MMC5MemIn[3] = MMC5MemIn[4] = 1;
|
||||
MMC5ROMWrProtect[2] = MMC5ROMWrProtect[3] = 1;
|
||||
@@ -310,8 +449,8 @@ static void MMC5PRG(void) {
|
||||
setprg16(0x8000, (PRGBanks[1] & 0x7F) >> 1);
|
||||
} else {
|
||||
MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0;
|
||||
MMC5WRAM(0x8000, PRGBanks[1] & 7 & 0xFE);
|
||||
MMC5WRAM(0xA000, (PRGBanks[1] & 7 & 0xFE) + 1);
|
||||
MMC5WRAM(0x8000, PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE);
|
||||
MMC5WRAM(0xA000, (PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE) + 1);
|
||||
}
|
||||
if (PRGBanks[2] & 0x80) {
|
||||
MMC5ROMWrProtect[2] = 1;
|
||||
@@ -319,7 +458,7 @@ static void MMC5PRG(void) {
|
||||
setprg8(0xC000, PRGBanks[2] & 0x7F);
|
||||
} else {
|
||||
MMC5ROMWrProtect[2] = 0;
|
||||
MMC5WRAM(0xC000, PRGBanks[2] & 7);
|
||||
MMC5WRAM(0xC000, PRGBanks[2] & (MMC5WRAMMAX-1));
|
||||
}
|
||||
MMC5MemIn[4] = 1;
|
||||
MMC5ROMWrProtect[3] = 1;
|
||||
@@ -333,7 +472,7 @@ static void MMC5PRG(void) {
|
||||
MMC5MemIn[1 + x] = 1;
|
||||
} else {
|
||||
MMC5ROMWrProtect[x] = 0;
|
||||
MMC5WRAM(0x8000 + (x << 13), PRGBanks[x] & 7);
|
||||
MMC5WRAM(0x8000 + (x << 13), PRGBanks[x] & (MMC5WRAMMAX-1));
|
||||
}
|
||||
MMC5MemIn[4] = 1;
|
||||
MMC5ROMWrProtect[3] = 1;
|
||||
@@ -396,7 +535,7 @@ static DECLFW(Mapper5_write) {
|
||||
break;
|
||||
case 0x5113:
|
||||
WRAMPage = V;
|
||||
MMC5WRAM(0x6000, V & 7);
|
||||
MMC5WRAM(0x6000, V & (MMC5WRAMMAX-1));
|
||||
break;
|
||||
case 0x5114:
|
||||
case 0x5115:
|
||||
@@ -492,7 +631,7 @@ void MMC5Synco(void) {
|
||||
case 3: PPUNTARAM &= ~(1 << x); vnapage[x] = MMC5fill; break;
|
||||
}
|
||||
}
|
||||
MMC5WRAM(0x6000, WRAMPage & 7);
|
||||
MMC5WRAM(0x6000, WRAMPage & (MMC5WRAMMAX-1));
|
||||
if (!mmc5ABMode) {
|
||||
MMC5CHRB();
|
||||
MMC5CHRA();
|
||||
@@ -755,22 +894,42 @@ void NSFMMC5_Close(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
MMC5WRAMsize = 0;
|
||||
FCEU_gfree(ExRAM);
|
||||
ExRAM = NULL;
|
||||
}
|
||||
|
||||
static void GenMMC5Reset(void) {
|
||||
int x;
|
||||
static void GenMMC5Power(void) {
|
||||
|
||||
for (x = 0; x < 4; x++) PRGBanks[x] = ~0;
|
||||
for (x = 0; x < 8; x++) CHRBanksA[x] = ~0;
|
||||
for (x = 0; x < 4; x++) CHRBanksB[x] = ~0;
|
||||
WRAMMaskEnable[0] = WRAMMaskEnable[1] = ~0;
|
||||
|
||||
mmc5psize = mmc5vsize = 3;
|
||||
PRGBanks.fill(0xFF);
|
||||
WRAMPage = 0;
|
||||
CHRBanksA.fill(0xFF);
|
||||
CHRBanksB.fill(0xFF);
|
||||
WRAMMaskEnable.fill(0xFF);
|
||||
mmc5ABMode = 0;
|
||||
IRQScanline = 0;
|
||||
IRQEnable = 0;
|
||||
CHRMode = 0;
|
||||
|
||||
NTAMirroring = NTFill = ATFill = 0xFF;
|
||||
MMC5IRQR = 0;
|
||||
MMC5LineCounter = 0;
|
||||
mmc5psize = mmc5vsize = 3;
|
||||
mul.fill(0);
|
||||
|
||||
MMC5ROMWrProtect.fill(0);
|
||||
MMC5MemIn.fill(0);
|
||||
|
||||
// MMC5fill is and 8-bit tile index, and a 2-bit attribute implented as a mirrored nametable
|
||||
u8 nval = MMC5fill[0x000];
|
||||
u8 aval = MMC5fill[0x3C0] & 3; aval = aval | (aval << 2) | (aval << 4) | (aval << 6);
|
||||
FCEU_dwmemset(MMC5fill + 0x000, nval | (nval<<8) | (nval<<16) | (nval<<24), 0x3C0);
|
||||
FCEU_dwmemset(MMC5fill + 0x3C0, aval | (aval<<8) | (aval<<16) | (aval<<24), 0x040);
|
||||
|
||||
if(MMC5battery == 0) {
|
||||
FCEU_MemoryRand(WRAM, MMC5WRAMsize * 8 * 1024);
|
||||
FCEU_MemoryRand(MMC5fill,1024);
|
||||
FCEU_MemoryRand(ExRAM,1024);
|
||||
}
|
||||
|
||||
MMC5Synco();
|
||||
|
||||
@@ -793,11 +952,11 @@ static void GenMMC5Reset(void) {
|
||||
}
|
||||
|
||||
static SFORMAT MMC5_StateRegs[] = {
|
||||
{ PRGBanks, 4, "PRGB" },
|
||||
{ CHRBanksA, 16, "CHRA" },
|
||||
{ CHRBanksB, 8, "CHRB" },
|
||||
{ &PRGBanks, 4, "PRGB" },
|
||||
{ &CHRBanksA, 16, "CHRA" },
|
||||
{ &CHRBanksB, 8, "CHRB" },
|
||||
{ &WRAMPage, 1, "WRMP" },
|
||||
{ WRAMMaskEnable, 2, "WRME" },
|
||||
{ &WRAMMaskEnable, 2, "WRME" },
|
||||
{ &mmc5ABMode, 1, "ABMD" },
|
||||
{ &IRQScanline, 1, "IRQS" },
|
||||
{ &IRQEnable, 1, "IRQE" },
|
||||
@@ -811,9 +970,9 @@ static SFORMAT MMC5_StateRegs[] = {
|
||||
{ &MMC5LineCounter, 1, "LCTR" },
|
||||
{ &mmc5psize, 1, "PSIZ" },
|
||||
{ &mmc5vsize, 1, "VSIZ" },
|
||||
{ mul, 2, "MUL2" },
|
||||
{ MMC5ROMWrProtect, 4, "WRPR" },
|
||||
{ MMC5MemIn, 5, "MEMI" },
|
||||
{ &mul, 2, "MUL2" },
|
||||
{ &MMC5ROMWrProtect, 4, "WRPR" },
|
||||
{ &MMC5MemIn, 5, "MEMI" },
|
||||
|
||||
{ &MMC5Sound.wl[0], 2 | FCEUSTATE_RLSB, "SDW0" },
|
||||
{ &MMC5Sound.wl[1], 2 | FCEUSTATE_RLSB, "SDW1" },
|
||||
@@ -836,13 +995,17 @@ static SFORMAT MMC5_StateRegs[] = {
|
||||
|
||||
static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
|
||||
if (wsize) {
|
||||
WRAM = (uint8*)FCEU_gmalloc(wsize * 1024);
|
||||
WRAM = (uint8*)FCEU_malloc(wsize * 1024);
|
||||
FCEU_MemoryRand(WRAM, wsize * 1024);
|
||||
SetupCartPRGMapping(0x10, WRAM, wsize * 1024, 1);
|
||||
AddExState(WRAM, wsize * 1024, 0, "WRAM");
|
||||
}
|
||||
|
||||
MMC5fill = (uint8*)FCEU_gmalloc(1024);
|
||||
ExRAM = (uint8*)FCEU_gmalloc(1024);
|
||||
MMC5fill = (uint8*)FCEU_malloc(1024);
|
||||
ExRAM = (uint8*)FCEU_malloc(1024);
|
||||
|
||||
FCEU_MemoryRand(MMC5fill,1024);
|
||||
FCEU_MemoryRand(ExRAM,1024);
|
||||
|
||||
AddExState(ExRAM, 1024, 0, "ERAM");
|
||||
AddExState(&MMC5HackSPMode, 1, 0, "SPLM");
|
||||
@@ -854,14 +1017,27 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
|
||||
MMC5WRAMsize = wsize / 8;
|
||||
BuildWRAMSizeTable();
|
||||
GameStateRestore = MMC5_StateRestore;
|
||||
info->Power = GenMMC5Reset;
|
||||
info->Power = GenMMC5Power;
|
||||
|
||||
MMC5battery = battery;
|
||||
if (battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
if (wsize <= 16)
|
||||
info->SaveGameLen[0] = 8192;
|
||||
uint32 saveGameSize = 0;
|
||||
if (info->ines2)
|
||||
{
|
||||
saveGameSize = info->battery_wram_size;
|
||||
}
|
||||
else
|
||||
info->SaveGameLen[0] = 32768;
|
||||
{
|
||||
//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)
|
||||
saveGameSize = 8192;
|
||||
else if(wsize == 64)
|
||||
saveGameSize = 64*1024;
|
||||
else
|
||||
saveGameSize = 32768;
|
||||
}
|
||||
info->addSaveGameBuf( WRAM, saveGameSize );
|
||||
}
|
||||
|
||||
MMC5HackVROMMask = CHRmask4[0];
|
||||
@@ -877,7 +1053,14 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
|
||||
}
|
||||
|
||||
void Mapper5_Init(CartInfo *info) {
|
||||
WRAMSIZE = DetectMMC5WRAMSize(info->CRC32);
|
||||
if (info->ines2)
|
||||
{
|
||||
WRAMSIZE = (info->wram_size + info->battery_wram_size) / 1024;
|
||||
}
|
||||
else
|
||||
{
|
||||
WRAMSIZE = DetectMMC5WRAMSize(info->CRC32);
|
||||
}
|
||||
GenMMC5_Init(info, WRAMSIZE, info->battery);
|
||||
}
|
||||
|
||||
|
||||
+30
-8
@@ -57,9 +57,23 @@ static SFORMAT N106_StateRegs[] = {
|
||||
{ PRG, 3, "PRG" },
|
||||
{ CHR, 8, "CHR" },
|
||||
{ NTAPage, 4, "NTA" },
|
||||
{ &gorfus, 1, "GORF" },
|
||||
{ &dopol, 1, "DOPO" },
|
||||
{ &gorko, 1, "GORK" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void SyncMirror()
|
||||
{
|
||||
switch(gorko) {
|
||||
case 0: setmirror(MI_0); break;
|
||||
case 1: setmirror(MI_V); break;
|
||||
case 2: setmirror(MI_H); break;
|
||||
case 3: setmirror(MI_0); break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void SyncPRG(void) {
|
||||
setprg8(0x8000, PRG[0]);
|
||||
setprg8(0xa000, PRG[1]);
|
||||
@@ -143,7 +157,10 @@ static void FixCache(int a, int V) {
|
||||
case 0x02: FreqCache[w] &= ~0x0000FF00; FreqCache[w] |= V << 8; break;
|
||||
case 0x04:
|
||||
FreqCache[w] &= ~0x00030000; FreqCache[w] |= (V & 3) << 16;
|
||||
LengthCache[w] = (8 - ((V >> 2) & 7)) << 2;
|
||||
// something wrong here http://www.romhacking.net/forum/index.php?topic=21907.msg306903#msg306903
|
||||
// LengthCache[w] = (8 - ((V >> 2) & 7)) << 2;
|
||||
// fix be like in https://github.com/SourMesen/Mesen/blob/cda0a0bdcb5525480784f4b8c71de6fc7273b570/Core/Namco163Audio.h#L61
|
||||
LengthCache[w] = 256 - (V & 0xFC);
|
||||
break;
|
||||
case 0x07: EnvCache[w] = (double)(V & 0xF) * 576716; break;
|
||||
}
|
||||
@@ -179,8 +196,11 @@ static DECLFW(Mapper19_write) {
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 0xE000:
|
||||
gorko = V & 0xC0;
|
||||
PRG[0] = V & 0x3F;
|
||||
if(is210) {
|
||||
gorko = V>>6;
|
||||
SyncMirror();
|
||||
}
|
||||
SyncPRG();
|
||||
break;
|
||||
case 0xE800:
|
||||
@@ -331,6 +351,7 @@ static void DoNamcoSound(int32 *Wave, int Count) {
|
||||
|
||||
static void Mapper19_StateRestore(int version) {
|
||||
SyncPRG();
|
||||
SyncMirror();
|
||||
FixNTAR();
|
||||
FixCRR();
|
||||
int x;
|
||||
@@ -382,8 +403,8 @@ static void N106_Power(void) {
|
||||
FixCRR();
|
||||
|
||||
if (!battery) {
|
||||
FCEU_dwmemset(WRAM, 0, 8192);
|
||||
FCEU_dwmemset(IRAM, 0, 128);
|
||||
FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
|
||||
FCEU_MemoryRand(IRAM, sizeof(IRAM), true);
|
||||
}
|
||||
for (x = 0x40; x < 0x80; x++)
|
||||
FixCache(x, IRAM[x]);
|
||||
@@ -401,15 +422,15 @@ void Mapper19_Init(CartInfo *info) {
|
||||
if (FSettings.SndRate)
|
||||
Mapper19_ESI();
|
||||
|
||||
FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
|
||||
FCEU_MemoryRand(IRAM, sizeof(IRAM), true);
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
AddExState(IRAM, 128, 0, "IRAM");
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,6 +443,7 @@ void Mapper210_Init(CartInfo *info) {
|
||||
is210 = 1;
|
||||
GameStateRestore = Mapper210_StateRestore;
|
||||
info->Power = N106_Power;
|
||||
FCEU_MemoryRand(WRAM, sizeof(WRAM), true);
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
AddExState(N106_StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ static int16 pcm_addr, pcm_size, pcm_latch, pcm_clock = 0xE1;
|
||||
static writefunc defapuwrite[64];
|
||||
static readfunc defapuread[64];
|
||||
|
||||
static uint32 WRAMSIZE;
|
||||
static uint8 *WRAM = NULL;
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ cpu410x, 16, "REGC" },
|
||||
@@ -265,6 +268,13 @@ static void UNLOneBusPower(void) {
|
||||
SetWriteHandler(0x4100, 0x410f, UNLOneBusWriteCPU410X);
|
||||
SetWriteHandler(0x8000, 0xffff, UNLOneBusWriteMMC3);
|
||||
|
||||
if (WRAMSIZE) {
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
SetWriteHandler(0x6000, 0x6000 + ((WRAMSIZE - 1) & 0x1fff), CartBW);
|
||||
SetReadHandler(0x6000, 0x6000 + ((WRAMSIZE - 1) & 0x1fff), CartBR);
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
}
|
||||
|
||||
Sync();
|
||||
}
|
||||
|
||||
@@ -282,9 +292,16 @@ static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void UNLOneBusClose(void) {
|
||||
if (WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
void UNLOneBus_Init(CartInfo *info) {
|
||||
info->Power = UNLOneBusPower;
|
||||
info->Reset = UNLOneBusReset;
|
||||
info->Close = UNLOneBusClose;
|
||||
|
||||
if (((*(uint32*)&(info->MD5)) == 0x305fcdc3) || // PowerJoy Supermax Carts
|
||||
((*(uint32*)&(info->MD5)) == 0x6abfce8e))
|
||||
@@ -294,4 +311,16 @@ void UNLOneBus_Init(CartInfo *info) {
|
||||
MapIRQHook = UNLOneBusCpuHook;
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
|
||||
WRAMSIZE = 8 * 1024;
|
||||
if (info->ines2)
|
||||
WRAMSIZE = info->wram_size + info->battery_wram_size;
|
||||
if (WRAMSIZE) {
|
||||
WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
if (info->battery) {
|
||||
info->addSaveGameBuf( WRAM, WRAMSIZE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
* 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
|
||||
*
|
||||
* PEC-586 FC based computer series by DUNDA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
extern u64 xoroshiro128plus_next(); // deterministic random
|
||||
|
||||
static DECLFR(UNLRT01Read) {
|
||||
// u16 i, prot_areas[2][2] = {
|
||||
// { 0x8E80, 0x8EFF },
|
||||
@@ -33,7 +35,7 @@ static DECLFR(UNLRT01Read) {
|
||||
// };
|
||||
if(((A >= 0xCE80) && (A < 0xCF00)) ||
|
||||
((A >= 0xFE80) && (A < 0xFF00))) {
|
||||
return 0xF2 | (rand() & 0x0D);
|
||||
return 0xF2 | (xoroshiro128plus_next() & 0x0D);
|
||||
} else
|
||||
return CartBR(A);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
+160
-194
@@ -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,235 +36,200 @@
|
||||
#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;
|
||||
}
|
||||
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)];
|
||||
static void UNROM512_Sync() {
|
||||
int chip;
|
||||
if (flash_save)
|
||||
chip = !flash_id_mode ? FLASH_CHIP : CFI_CHIP;
|
||||
else
|
||||
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;
|
||||
|
||||
if(info->vram_size == 8192)
|
||||
chrram_mask = 0;
|
||||
else if (info->vram_size == 16384)
|
||||
chrram_mask = 0x20;
|
||||
else
|
||||
chrram_mask = 0x60;
|
||||
|
||||
SetupCartMirroring(info->mirror,(info->mirror>=MI_0)?0:1,0);
|
||||
bus_conflict = !info->battery;
|
||||
latcheinit = 0;
|
||||
WLSync = UNROM512LSync;
|
||||
WHSync = UNROM512HSync;
|
||||
info->Power = UNROM512LatchPower;
|
||||
info->Close = UNROM512LatchClose;
|
||||
GameStateRestore = StateRestore;
|
||||
|
||||
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)
|
||||
{
|
||||
case 0: // hard horizontal, internal
|
||||
SetupCartMirroring(MI_H, 1, NULL);
|
||||
break;
|
||||
case 1: // hard vertical, internal
|
||||
SetupCartMirroring(MI_V, 1, NULL);
|
||||
break;
|
||||
case 2: // switchable 1-screen, internal (flags: 4-screen + horizontal)
|
||||
SetupCartMirroring(MI_0, 0, NULL);
|
||||
break;
|
||||
case 3: // hard four screen, last 8k of 32k RAM (flags: 4-screen + vertical)
|
||||
SetupCartMirroring( 4, 1, VROM + (info->vram_size - 8192));
|
||||
break;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
+69
-100
@@ -20,14 +20,14 @@
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 isPirate, is22;
|
||||
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;
|
||||
static uint16 acount = 0;
|
||||
static uint16 weirdo = 0;
|
||||
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
@@ -37,6 +37,7 @@ static SFORMAT StateRegs[] =
|
||||
{ prgreg, 2, "PREG" },
|
||||
{ chrreg, 8, "CREG" },
|
||||
{ chrhi, 16, "CRGH" },
|
||||
{ &acount, 2, "ACNT" },
|
||||
{ ®cmd, 1, "CMDR" },
|
||||
{ &irqcmd, 1, "CMDI" },
|
||||
{ &mirr, 1, "MIRR" },
|
||||
@@ -44,6 +45,7 @@ static SFORMAT StateRegs[] =
|
||||
{ &IRQCount, 2, "IRQC" },
|
||||
{ &IRQLatch, 1, "IRQL" },
|
||||
{ &IRQa, 1, "IRQA" },
|
||||
{ &IRQMode, 1, "IRQM" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -61,15 +63,8 @@ static void Sync(void) {
|
||||
setchr8(0);
|
||||
else{
|
||||
uint8 i;
|
||||
if(!weirdo)
|
||||
for (i = 0; i < 8; i++)
|
||||
setchr1(i << 10, (chrhi[i] | chrreg[i]) >> is22);
|
||||
else {
|
||||
setchr1(0x0000, 0xFC);
|
||||
setchr1(0x0400, 0xFD);
|
||||
setchr1(0x0800, 0xFF);
|
||||
weirdo--;
|
||||
}
|
||||
for (i = 0; i < 8; i++)
|
||||
setchr1(i << 10, (chrhi[i] | chrreg[i]) >> is22);
|
||||
}
|
||||
switch (mirr & 0x3) {
|
||||
case 0: setmirror(MI_V); break;
|
||||
@@ -80,7 +75,7 @@ static void Sync(void) {
|
||||
}
|
||||
|
||||
static DECLFW(VRC24Write) {
|
||||
A &= 0xF003;
|
||||
A = A & 0xF000 | !!(A & reg2mask) << 1 | !!(A & reg1mask);
|
||||
if ((A >= 0xB000) && (A <= 0xE003)) {
|
||||
if (UNIFchrrama)
|
||||
big_bank = (V & 8) << 2; // my personally many-in-one feature ;) just for support pirate cart 2-in-1
|
||||
@@ -121,81 +116,49 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(M21Write) {
|
||||
A = (A & 0xF000) | ((A >> 1) & 0x3); // Ganbare Goemon Gaiden 2 - Tenka no Zaihou (J) [!] isn't mapper 21 actually,
|
||||
// it's mapper 23 by wirings
|
||||
VRC24Write(A, V);
|
||||
}
|
||||
|
||||
static DECLFW(M22Write) {
|
||||
if (A == 0xC007) { // Ganbare Goemon Gaiden does strange things!!! at the end credits
|
||||
weirdo = 8; // quick dirty hack, seems there is no other games with such PCB, so
|
||||
// we never know if it will not work for something else lol
|
||||
static void VRC24Power(void) {
|
||||
big_bank = 0x20;
|
||||
Sync();
|
||||
if (WRAM) {
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
A |= ((A >> 2) & 0x3); // It's just swapped lines from 21 mapper
|
||||
//
|
||||
VRC24Write((A & 0xF000) | ((A >> 1) & 1) | ((A << 1) & 2), V);
|
||||
}
|
||||
|
||||
static DECLFW(M23Write) {
|
||||
A |= ((A >> 2) & 0x3) | ((A >> 4) & 0x3) | ((A >> 6) & 0x3);// actually there is many-in-one mapper source, some pirate or
|
||||
// licensed games use various address bits for registers
|
||||
VRC24Write(A, V);
|
||||
}
|
||||
|
||||
static void M21Power(void) {
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M21Write);
|
||||
}
|
||||
|
||||
static void M22Power(void) {
|
||||
Sync();
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M22Write);
|
||||
}
|
||||
|
||||
static void M23Power(void) {
|
||||
big_bank = 0x20;
|
||||
Sync();
|
||||
setprg8r(0x10, 0x6000, 0); // Only two Goemon games are have battery backed RAM, three more shooters
|
||||
// (Parodius Da!, Gradius 2 and Crisis Force uses 2k or SRAM at 6000-67FF only
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M23Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
}
|
||||
|
||||
static void M25Power(void) {
|
||||
big_bank = 0x20;
|
||||
Sync();
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
SetReadHandler(0x6000, 0x7FFF, CartBR);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetReadHandler(0x8000, 0xFFFF, CartBR);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M22Write);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
SetWriteHandler(0x8000, 0xFFFF, VRC24Write);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,26 +173,8 @@ static void VRC24Close(void) {
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
void Mapper21_Init(CartInfo *info) {
|
||||
isPirate = 0;
|
||||
is22 = 0;
|
||||
info->Power = M21Power;
|
||||
MapIRQHook = VRC24IRQHook;
|
||||
GameStateRestore = StateRestore;
|
||||
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void Mapper22_Init(CartInfo *info) {
|
||||
isPirate = 0;
|
||||
is22 = 1;
|
||||
info->Power = M22Power;
|
||||
GameStateRestore = StateRestore;
|
||||
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void VRC24_Init(CartInfo *info) {
|
||||
static void VRC24_Init(CartInfo *info) {
|
||||
info->Power = VRC24Power;
|
||||
info->Close = VRC24Close;
|
||||
MapIRQHook = VRC24IRQHook;
|
||||
GameStateRestore = StateRestore;
|
||||
@@ -240,30 +185,54 @@ 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);
|
||||
}
|
||||
|
||||
void Mapper23_Init(CartInfo *info) {
|
||||
isPirate = 0;
|
||||
void Mapper21_Init(CartInfo *info) {
|
||||
isPirate = false;
|
||||
is22 = 0;
|
||||
info->Power = M23Power;
|
||||
reg1mask = 0x42;
|
||||
reg2mask = 0x84;
|
||||
VRC24_Init(info);
|
||||
}
|
||||
|
||||
void Mapper22_Init(CartInfo *info) {
|
||||
isPirate = false;
|
||||
is22 = 1;
|
||||
reg1mask = 2;
|
||||
reg2mask = 1;
|
||||
|
||||
// no IRQ (all mapper 22 games are VRC2)
|
||||
// no WRAM
|
||||
info->Power = VRC24Power;
|
||||
GameStateRestore = StateRestore;
|
||||
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void Mapper23_Init(CartInfo *info) {
|
||||
isPirate = false;
|
||||
is22 = 0;
|
||||
reg1mask = 0x15;
|
||||
reg2mask = 0x2a;
|
||||
VRC24_Init(info);
|
||||
}
|
||||
|
||||
void Mapper25_Init(CartInfo *info) {
|
||||
isPirate = 0;
|
||||
isPirate = false;
|
||||
is22 = 0;
|
||||
info->Power = M25Power;
|
||||
reg1mask = 0xa;
|
||||
reg2mask = 0x5;
|
||||
VRC24_Init(info);
|
||||
}
|
||||
|
||||
void UNLT230_Init(CartInfo *info) {
|
||||
isPirate = 1;
|
||||
isPirate = true;
|
||||
is22 = 0;
|
||||
info->Power = M23Power;
|
||||
reg1mask = 0x15;
|
||||
reg2mask = 0x2a;
|
||||
VRC24_Init(info);
|
||||
}
|
||||
|
||||
+159
-121
@@ -1,7 +1,7 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
* Copyright (C) 2005-2019 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
|
||||
@@ -17,25 +17,118 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* VRC-5 (CAI Shogakko no Sansu)
|
||||
* VRC-V (CAI Shogakko no Sansu)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 QTAINTRAM[2048];
|
||||
static writefunc old2007wrap;
|
||||
//#define CAI_DEBUG
|
||||
|
||||
// main tiles RAM is 8K in size, but unless other non-CHR ROM type carts,
|
||||
// this one accesses the $0000 and $1000 pages based on extra NT RAM on board
|
||||
// which is similar to MMC5 but much simpler because there are no additional
|
||||
// bankings here.
|
||||
// extra NT RAM handling is in PPU code now.
|
||||
|
||||
static uint16 CHRSIZE = 8192;
|
||||
static uint16 WRAMSIZE = 8192 + 4096;
|
||||
// there are two separate WRAMs 8K each, on main system cartridge (not battery
|
||||
// backed), and one on the daughter cart (with battery). both are accessed
|
||||
// via the same registers with additional selector flags.
|
||||
static uint16 WRAMSIZE = 8192 + 8192;
|
||||
static uint8 *CHRRAM = NULL;
|
||||
static uint8 *WRAM = NULL;
|
||||
|
||||
static uint8 IRQa, K4IRQ;
|
||||
static uint32 IRQLatch, IRQCount;
|
||||
|
||||
// some kind of 16-bit text encoding (actually 14-bit) used in game resources
|
||||
// may be converted by the hardware into the tile indexes for internal CHR ROM
|
||||
// not sure whey they made it hardware, because most of calculations are just
|
||||
// bit shifting. the main purpose of this table is to calculate actual CHR ROM
|
||||
// bank for every character. there is a some kind of regularity, so this table
|
||||
// may be calculated in software easily.
|
||||
|
||||
// table read out from hardware registers as is
|
||||
|
||||
///*
|
||||
static uint8 conv_tbl[4][8] = {
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x40, 0x10, 0x28, 0x00, 0x18, 0x30 },
|
||||
{ 0x00, 0x00, 0x48, 0x18, 0x30, 0x08, 0x20, 0x38 },
|
||||
{ 0x00, 0x00, 0x80, 0x20, 0x38, 0x10, 0x28, 0xB0 }
|
||||
};
|
||||
//*/
|
||||
/*
|
||||
static uint8 conv_tbl[64][4] = {
|
||||
{ 0x40, 0x40, 0x40, 0x40 }, // 00 | A - 40 41 42 43 44 45 46 47
|
||||
{ 0x41, 0x41, 0x41, 0x41 }, // 02 | B - 48 49 4A 4B 4C 4D 4E 4F
|
||||
{ 0x42, 0x42, 0x42, 0x42 }, // 04 | C - 50 51 52 53 54 55 56 57
|
||||
{ 0x43, 0x43, 0x43, 0x43 }, // 06 | D - 58 59 5A 5B 5C 5D 5E 5F
|
||||
{ 0x44, 0x44, 0x44, 0x44 }, // 08 | E - 60 61 62 63 64 65 66 67
|
||||
{ 0x45, 0x45, 0x45, 0x45 }, // 0A | F - 68 69 6A 6B 6C 6D 6E 6F
|
||||
{ 0x46, 0x46, 0x46, 0x46 }, // 0C | G - 70 71 72 73 74 75 76 77
|
||||
{ 0x47, 0x47, 0x47, 0x47 }, // 0E | H - 78 79 7A 7B 7C 7D 7E 7F
|
||||
{ 0x40, 0x40, 0x40, 0x40 }, // 10 |
|
||||
{ 0x41, 0x41, 0x41, 0x41 }, // 12 +----------------------------
|
||||
{ 0x42, 0x42, 0x42, 0x42 }, // 14 | A A A A
|
||||
{ 0x43, 0x43, 0x43, 0x43 }, // 16 | A A A A
|
||||
{ 0x44, 0x44, 0x44, 0x44 }, // 18 | A A' B' A"
|
||||
{ 0x45, 0x45, 0x45, 0x45 }, // 1A | A C D E
|
||||
{ 0x46, 0x46, 0x46, 0x46 }, // 1C | A F G H
|
||||
{ 0x47, 0x47, 0x47, 0x47 }, // 1E | A A B C
|
||||
{ 0x40, 0x40, 0x48, 0x44 }, // 20 | A D E F
|
||||
{ 0x41, 0x41, 0x49, 0x45 }, // 22 | A G H G"
|
||||
{ 0x42, 0x42, 0x4A, 0x46 }, // 24 +----------------------------
|
||||
{ 0x43, 0x43, 0x4B, 0x47 }, // 26 | A' - 40 41 42 43 40 41 42 43
|
||||
{ 0x44, 0x40, 0x48, 0x44 }, // 28 | A" - 44 45 46 47 44 45 46 47
|
||||
{ 0x45, 0x41, 0x49, 0x45 }, // 2A | B' - 48 49 4A 4B 48 49 4A 4B
|
||||
{ 0x46, 0x42, 0x4A, 0x46 }, // 2C | G" - 74 75 76 77 74 75 76 77
|
||||
{ 0x47, 0x43, 0x4B, 0x47 }, // 2E
|
||||
{ 0x40, 0x50, 0x58, 0x60 }, // 30
|
||||
{ 0x41, 0x51, 0x59, 0x61 }, // 32
|
||||
{ 0x42, 0x52, 0x5A, 0x62 }, // 34
|
||||
{ 0x43, 0x53, 0x5B, 0x63 }, // 36
|
||||
{ 0x44, 0x54, 0x5C, 0x64 }, // 38
|
||||
{ 0x45, 0x55, 0x5D, 0x65 }, // 3A
|
||||
{ 0x46, 0x56, 0x5E, 0x66 }, // 3C
|
||||
{ 0x47, 0x57, 0x5F, 0x67 }, // 3E
|
||||
{ 0x40, 0x68, 0x70, 0x78 }, // 40
|
||||
{ 0x41, 0x69, 0x71, 0x79 }, // 42
|
||||
{ 0x42, 0x6A, 0x72, 0x7A }, // 44
|
||||
{ 0x43, 0x6B, 0x73, 0x7B }, // 46
|
||||
{ 0x44, 0x6C, 0x74, 0x7C }, // 48
|
||||
{ 0x45, 0x6D, 0x75, 0x7D }, // 4A
|
||||
{ 0x46, 0x6E, 0x76, 0x7E }, // 4C
|
||||
{ 0x47, 0x6F, 0x77, 0x7F }, // 4E
|
||||
{ 0x40, 0x40, 0x48, 0x50 }, // 50
|
||||
{ 0x41, 0x41, 0x49, 0x51 }, // 52
|
||||
{ 0x42, 0x42, 0x4A, 0x52 }, // 54
|
||||
{ 0x43, 0x43, 0x4B, 0x53 }, // 56
|
||||
{ 0x44, 0x44, 0x4C, 0x54 }, // 58
|
||||
{ 0x45, 0x45, 0x4D, 0x55 }, // 5A
|
||||
{ 0x46, 0x46, 0x4E, 0x56 }, // 5C
|
||||
{ 0x47, 0x47, 0x4F, 0x57 }, // 5E
|
||||
{ 0x40, 0x58, 0x60, 0x68 }, // 60
|
||||
{ 0x41, 0x59, 0x61, 0x69 }, // 62
|
||||
{ 0x42, 0x5A, 0x62, 0x6A }, // 64
|
||||
{ 0x43, 0x5B, 0x63, 0x6B }, // 66
|
||||
{ 0x44, 0x5C, 0x64, 0x6C }, // 68
|
||||
{ 0x45, 0x5D, 0x65, 0x6D }, // 6A
|
||||
{ 0x46, 0x5E, 0x66, 0x6E }, // 6C
|
||||
{ 0x47, 0x5F, 0x67, 0x6F }, // 6E
|
||||
{ 0x40, 0x70, 0x78, 0x74 }, // 70
|
||||
{ 0x41, 0x71, 0x79, 0x75 }, // 72
|
||||
{ 0x42, 0x72, 0x7A, 0x76 }, // 74
|
||||
{ 0x43, 0x73, 0x7B, 0x77 }, // 76
|
||||
{ 0x44, 0x74, 0x7C, 0x74 }, // 78
|
||||
{ 0x45, 0x75, 0x7D, 0x75 }, // 7A
|
||||
{ 0x46, 0x76, 0x7E, 0x76 }, // 7C
|
||||
{ 0x47, 0x77, 0x7F, 0x77 }, // 7E
|
||||
};
|
||||
*/
|
||||
|
||||
static uint8 regs[16];
|
||||
//static uint8 test[8];
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &IRQCount, 1, "IRQC" },
|
||||
@@ -48,93 +141,68 @@ static SFORMAT StateRegs[] =
|
||||
|
||||
static void chrSync(void) {
|
||||
setchr4r(0x10, 0x0000, regs[5] & 1);
|
||||
setchr4r(0x10, 0x1000, 0);
|
||||
// 30.06.19 CaH4e3 there is much more complicated behaviour with second banking register, you may actually
|
||||
// view the content of the internal character CHR rom via this window, but it is useless because hardware
|
||||
// does not use this area to access the internal ROM. not sure why they did this, but I see no need to
|
||||
// emulate this behaviour carefully, unless I find something that I missed...
|
||||
setchr4r(0x10, 0x1000, 1);
|
||||
}
|
||||
|
||||
static void Sync(void) {
|
||||
chrSync();
|
||||
// if(regs[0xA]&0x10)
|
||||
// {
|
||||
/* setchr1r(0x10,0x0000,(((regs[5]&1))<<2)+0);
|
||||
setchr1r(0x10,0x0400,(((regs[5]&1))<<2)+1);
|
||||
setchr1r(0x10,0x0800,(((regs[5]&1))<<2)+2);
|
||||
setchr1r(0x10,0x0c00,(((regs[5]&1))<<2)+3);
|
||||
setchr1r(0x10,0x1000,0);
|
||||
setchr1r(0x10,0x1400,1);
|
||||
setchr1r(0x10,0x1800,2);
|
||||
setchr1r(0x10,0x1c00,3);*/
|
||||
/* setchr1r(0x10,0x0000,(((regs[5]&1))<<2)+0);
|
||||
setchr1r(0x10,0x0400,(((regs[5]&1))<<2)+1);
|
||||
setchr1r(0x10,0x0800,(((regs[5]&1))<<2)+2);
|
||||
setchr1r(0x10,0x0c00,(((regs[5]&1))<<2)+3);
|
||||
setchr1r(0x10,0x1000,(((regs[5]&1)^1)<<2)+4);
|
||||
setchr1r(0x10,0x1400,(((regs[5]&1)^1)<<2)+5);
|
||||
setchr1r(0x10,0x1800,(((regs[5]&1)^1)<<2)+6);
|
||||
setchr1r(0x10,0x1c00,(((regs[5]&1)^1)<<2)+7);
|
||||
*/
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
/*
|
||||
setchr1r(0x10,0x0000,(((regs[5]&1)^1)<<2)+0);
|
||||
setchr1r(0x10,0x0400,(((regs[5]&1)^1)<<2)+1);
|
||||
setchr1r(0x10,0x0800,(((regs[5]&1)^1)<<2)+2);
|
||||
setchr1r(0x10,0x0c00,(((regs[5]&1)^1)<<2)+3);
|
||||
setchr1r(0x10,0x1000,(((regs[5]&1))<<2)+4);
|
||||
setchr1r(0x10,0x1400,(((regs[5]&1))<<2)+5);
|
||||
setchr1r(0x10,0x1800,(((regs[5]&1))<<2)+6);
|
||||
setchr1r(0x10,0x1c00,(((regs[5]&1))<<2)+7);
|
||||
// }
|
||||
//*/
|
||||
/* setchr1r(1,0x0000,test[0]);
|
||||
setchr1r(1,0x0400,test[1]);
|
||||
setchr1r(1,0x0800,test[2]);
|
||||
setchr1r(1,0x0c00,test[3]);
|
||||
setchr1r(1,0x1000,test[4]);
|
||||
setchr1r(1,0x1400,test[5]);
|
||||
setchr1r(1,0x1800,test[6]);
|
||||
setchr1r(1,0x1c00,test[7]);
|
||||
*/
|
||||
setprg4r(0x10, 0x6000, regs[0] & 1);
|
||||
if (regs[2] >= 0x40)
|
||||
setprg8r(1, 0x8000, (regs[2] - 0x40));
|
||||
else
|
||||
setprg8r(0, 0x8000, (regs[2] & 0x3F));
|
||||
if (regs[3] >= 0x40)
|
||||
setprg8r(1, 0xA000, (regs[3] - 0x40));
|
||||
else
|
||||
setprg8r(0, 0xA000, (regs[3] & 0x3F));
|
||||
if (regs[4] >= 0x40)
|
||||
setprg8r(1, 0xC000, (regs[4] - 0x40));
|
||||
else
|
||||
setprg8r(0, 0xC000, (regs[4] & 0x3F));
|
||||
|
||||
setprg8r(1, 0xE000, ~0);
|
||||
setmirror(MI_V);
|
||||
setprg4r(0x10, 0x6000, (regs[0] & 1) | (regs[0] >> 2)); // two 4K banks are identical, either internal or excernal
|
||||
setprg4r(0x10, 0x7000, (regs[1] & 1) | (regs[1] >> 2)); // SRAMs may be mapped in any bank independently
|
||||
if (PRGptr[1] == NULL) { // for iNES 2.0 version it even more hacky lol
|
||||
setprg8(0x8000, (regs[2] & 0x3F) + ((regs[2] & 0x40) >> 2));
|
||||
setprg8(0xA000, (regs[3] & 0x3F) + ((regs[3] & 0x40) >> 2));
|
||||
setprg8(0xC000, (regs[4] & 0x3F) + ((regs[4] & 0x40) >> 2));
|
||||
setprg8(0xE000, 0x10 + 0x3F);
|
||||
} else {
|
||||
setprg8r((regs[2] >> 6) & 1, 0x8000, (regs[2] & 0x3F));
|
||||
setprg8r((regs[3] >> 6) & 1, 0xA000, (regs[3] & 0x3F));
|
||||
setprg8r((regs[4] >> 6) & 1, 0xC000, (regs[4] & 0x3F));
|
||||
setprg8r(1, 0xE000, ~0); // always sees the last bank of the external cart, so can't be booted without it.
|
||||
}
|
||||
setmirror(((regs[0xA]&2)>>1)^1);
|
||||
}
|
||||
|
||||
/*static DECLFW(TestWrite)
|
||||
{
|
||||
test[A&7] = V;
|
||||
Sync();
|
||||
}*/
|
||||
|
||||
static DECLFW(M190Write) {
|
||||
// FCEU_printf("write %04x:%04x %d, %d\n",A,V,scanline,timestamp);
|
||||
regs[(A & 0x0F00) >> 8] = V;
|
||||
static DECLFW(QTAiWrite) {
|
||||
regs[(A & 0x0F00) >> 8] = V; // IRQ pretty the same as in other VRC mappers by Konami
|
||||
switch (A) {
|
||||
case 0xd600: IRQLatch &= 0xFF00; IRQLatch |= V; break;
|
||||
case 0xd700: IRQLatch &= 0x00FF; IRQLatch |= V << 8; break;
|
||||
case 0xd900: IRQCount = IRQLatch; IRQa = V & 2; K4IRQ = V & 1; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
case 0xd800: IRQa = K4IRQ; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
case 0xda00: qtaintramreg = regs[0xA] & 3; break; // register shadow to share it with ppu
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFR(M190Read) {
|
||||
// FCEU_printf("read %04x:%04x %d, %d\n",A,regs[(A&0x0F00)>>8],scanline,timestamp);
|
||||
return regs[(A & 0x0F00) >> 8] + regs[0x0B];
|
||||
static DECLFR(QTAiRead) {
|
||||
|
||||
// uint8 res1 = conv_tbl[(regs[0xD] & 0x7F) >> 1][(regs[0xC] >> 5) & 3];
|
||||
// uint8 res2 = ((regs[0xD] & 1) << 7) | ((regs[0xC] & 0x1F) << 2) | (regs[0xB] & 3);
|
||||
|
||||
uint8 tabl = conv_tbl[(regs[0xC] >> 5) & 3][(regs[0xD] & 0x7F) >> 4];
|
||||
uint8 res1 = 0x40 | (tabl & 0x3F) | ((regs[0xD] >> 1) & 7) | ((regs[0xB] & 4) << 5);
|
||||
uint8 res2 = ((regs[0xD] & 1) << 7) | ((regs[0xC] & 0x1F) << 2) | (regs[0xB] & 3);
|
||||
|
||||
if (tabl & 0x40)
|
||||
res1 &= 0xFB;
|
||||
else if (tabl & 0x80)
|
||||
res1 |= 0x04;
|
||||
|
||||
if (A == 0xDD00) {
|
||||
return res1;
|
||||
} else if (A == 0xDC00) {
|
||||
#ifdef CAI_DEBUG
|
||||
FCEU_printf("%02x:%02x+%d -> %02x:%02x\n", regs[0xD], regs[0xC], regs[0xB], res1, res2);
|
||||
#endif
|
||||
return res2;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void VRC5IRQ(int a) {
|
||||
if (IRQa) {
|
||||
IRQCount += a;
|
||||
@@ -145,50 +213,17 @@ static void VRC5IRQ(int a) {
|
||||
}
|
||||
}
|
||||
|
||||
//static void Mapper190_PPU(uint32 A)
|
||||
//{
|
||||
// if(A<0x2000)
|
||||
// setchr4r(0x10,0x1000,QTAINTRAM[A&0x1FFF]&1);
|
||||
// else
|
||||
// chrSync();
|
||||
//}
|
||||
|
||||
static DECLFW(M1902007Wrap) {
|
||||
if (A >= 0x2000) {
|
||||
if (regs[0xA] & 1)
|
||||
QTAINTRAM[A & 0x1FFF] = V;
|
||||
else
|
||||
old2007wrap(A, V);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void M190Power(void) {
|
||||
/* test[0]=0;
|
||||
test[1]=1;
|
||||
test[2]=2;
|
||||
test[3]=3;
|
||||
test[4]=4;
|
||||
test[5]=5;
|
||||
test[6]=6;
|
||||
test[7]=7;
|
||||
*/
|
||||
setprg4r(0x10, 0x7000, 2);
|
||||
|
||||
old2007wrap = GetWriteHandler(0x2007);
|
||||
SetWriteHandler(0x2007, 0x2007, M1902007Wrap);
|
||||
|
||||
static void QTAiPower(void) {
|
||||
SetReadHandler(0x6000, 0xFFFF, CartBR);
|
||||
// SetWriteHandler(0x5000,0x5007,TestWrite);
|
||||
SetWriteHandler(0x6000, 0x7FFF, CartBW);
|
||||
SetWriteHandler(0x8000, 0xFFFF, M190Write);
|
||||
SetReadHandler(0xDC00, 0xDC00, M190Read);
|
||||
SetReadHandler(0xDD00, 0xDD00, M190Read);
|
||||
SetWriteHandler(0x8000, 0xFFFF, QTAiWrite);
|
||||
SetReadHandler(0xDC00, 0xDC00, QTAiRead);
|
||||
SetReadHandler(0xDD00, 0xDD00, QTAiRead);
|
||||
FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM);
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M190Close(void) {
|
||||
static void QTAiClose(void) {
|
||||
if (CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
@@ -201,13 +236,14 @@ static void StateRestore(int version) {
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper190_Init(CartInfo *info) {
|
||||
info->Power = M190Power;
|
||||
info->Close = M190Close;
|
||||
void QTAi_Init(CartInfo *info) {
|
||||
QTAIHack = 1;
|
||||
|
||||
info->Power = QTAiPower;
|
||||
info->Close = QTAiClose;
|
||||
GameStateRestore = StateRestore;
|
||||
|
||||
MapIRQHook = VRC5IRQ;
|
||||
// PPU_hook=Mapper190_PPU;
|
||||
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRSIZE);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, CHRSIZE, 1);
|
||||
@@ -218,8 +254,10 @@ void Mapper190_Init(CartInfo *info) {
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE - 4096;
|
||||
// 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->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);
|
||||
|
||||
+25
-12
@@ -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}
|
||||
};
|
||||
|
||||
@@ -86,7 +87,7 @@ static void VRC7SKill(void) {
|
||||
static void VRC7_ESI(void) {
|
||||
GameExpSound.RChange = VRC7SC;
|
||||
GameExpSound.Kill = VRC7SKill;
|
||||
VRC7Sound = OPLL_new(3579545, FSettings.SndRate ? FSettings.SndRate : 44100);
|
||||
VRC7Sound = OPLL_new(3579545, FSettings.SndRate ? FSettings.SndRate : 48000);
|
||||
OPLL_reset(VRC7Sound);
|
||||
OPLL_reset(VRC7Sound);
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
+54
-19
@@ -76,6 +76,8 @@ uint8 geniech[3];
|
||||
|
||||
uint32 genieaddr[3];
|
||||
|
||||
CartInfo *currCartInfo;
|
||||
|
||||
static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram) {
|
||||
uint32 AB = A >> 11;
|
||||
int x;
|
||||
@@ -130,6 +132,11 @@ void SetupCartCHRMapping(int chip, uint8 *p, uint32 size, int ram) {
|
||||
CHRmask4[chip] = (size >> 12) - 1;
|
||||
CHRmask8[chip] = (size >> 13) - 1;
|
||||
|
||||
if (CHRmask1[chip] >= (unsigned int)(-1)) CHRmask1[chip] = 0;
|
||||
if (CHRmask2[chip] >= (unsigned int)(-1)) CHRmask2[chip] = 0;
|
||||
if (CHRmask4[chip] >= (unsigned int)(-1)) CHRmask4[chip] = 0;
|
||||
if (CHRmask8[chip] >= (unsigned int)(-1)) CHRmask8[chip] = 0;
|
||||
|
||||
CHRram[chip] = ram;
|
||||
}
|
||||
|
||||
@@ -529,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -549,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+67
-8
@@ -1,17 +1,46 @@
|
||||
typedef struct {
|
||||
#ifndef CART_H
|
||||
#define CART_H
|
||||
|
||||
#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
|
||||
@@ -23,7 +52,35 @@ 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;
|
||||
|
||||
void FCEU_SaveGameSave(CartInfo *LocalHWInfo);
|
||||
void FCEU_LoadGameSave(CartInfo *LocalHWInfo);
|
||||
@@ -98,3 +155,5 @@ void FCEU_GeniePower(void);
|
||||
bool FCEU_OpenGenie(void);
|
||||
void FCEU_CloseGenie(void);
|
||||
void FCEU_KillGenie(void);
|
||||
|
||||
#endif
|
||||
|
||||
+286
-315
@@ -39,8 +39,7 @@ using namespace std;
|
||||
static uint8 *CheatRPtrs[64];
|
||||
|
||||
vector<uint16> FrozenAddresses; //List of addresses that are currently frozen
|
||||
void UpdateFrozenList(void); //Function that populates the list of frozen addresses
|
||||
unsigned int FrozenAddressCount=0; //Keeps up with the Frozen address count, necessary for using in other dialogs (such as hex editor)
|
||||
unsigned int FrozenAddressCount = 0; //Keeps up with the Frozen address count, necessary for using in other dialogs (such as hex editor)
|
||||
|
||||
void FCEU_CheatResetRAM(void)
|
||||
{
|
||||
@@ -60,27 +59,13 @@ void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p)
|
||||
}
|
||||
|
||||
|
||||
struct CHEATF {
|
||||
struct CHEATF *next;
|
||||
char *name;
|
||||
uint16 addr;
|
||||
uint8 val;
|
||||
int compare; /* -1 for no compare. */
|
||||
int type; /* 0 for replace, 1 for substitute(GG). */
|
||||
int status;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint16 addr;
|
||||
uint8 val;
|
||||
int compare;
|
||||
readfunc PrevRead;
|
||||
} CHEATF_SUBFAST;
|
||||
|
||||
|
||||
static CHEATF_SUBFAST SubCheats[256];
|
||||
static int numsubcheats=0;
|
||||
struct CHEATF *cheats=0,*cheatsl=0;
|
||||
CHEATF_SUBFAST SubCheats[256];
|
||||
uint32 numsubcheats = 0;
|
||||
int globalCheatDisabled = 0;
|
||||
int disableAutoLSCheats = 0;
|
||||
bool disableShowGG = 0;
|
||||
static _8BYTECHEATMAP* cheatMap = NULL;
|
||||
struct CHEATF *cheats = 0, *cheatsl = 0;
|
||||
|
||||
|
||||
#define CHEATC_NONE 0x8000
|
||||
@@ -92,7 +77,7 @@ int savecheats = 0;
|
||||
|
||||
static DECLFR(SubCheatsRead)
|
||||
{
|
||||
CHEATF_SUBFAST *s=SubCheats;
|
||||
CHEATF_SUBFAST *s = SubCheats;
|
||||
int x=numsubcheats;
|
||||
|
||||
do
|
||||
@@ -116,79 +101,91 @@ static DECLFR(SubCheatsRead)
|
||||
|
||||
void RebuildSubCheats(void)
|
||||
{
|
||||
int x;
|
||||
struct CHEATF *c=cheats;
|
||||
for(x=0;x<numsubcheats;x++)
|
||||
SetReadHandler(SubCheats[x].addr,SubCheats[x].addr,SubCheats[x].PrevRead);
|
||||
|
||||
numsubcheats=0;
|
||||
while(c)
|
||||
uint32 x;
|
||||
struct CHEATF *c = cheats;
|
||||
for (x = 0; x < numsubcheats; x++)
|
||||
{
|
||||
if(c->type==1 && c->status)
|
||||
SetReadHandler(SubCheats[x].addr, SubCheats[x].addr, SubCheats[x].PrevRead);
|
||||
if (cheatMap)
|
||||
FCEUI_SetCheatMapByte(SubCheats[x].addr, false);
|
||||
}
|
||||
|
||||
numsubcheats = 0;
|
||||
|
||||
if (!globalCheatDisabled)
|
||||
{
|
||||
while(c)
|
||||
{
|
||||
if(GetReadHandler(c->addr)==SubCheatsRead)
|
||||
if(c->type == 1 && c->status && GetReadHandler(c->addr) != SubCheatsRead)
|
||||
{
|
||||
/* Prevent a catastrophe by this check. */
|
||||
//FCEU_DispMessage("oops",0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SubCheats[numsubcheats].PrevRead=GetReadHandler(c->addr);
|
||||
SubCheats[numsubcheats].addr=c->addr;
|
||||
SubCheats[numsubcheats].val=c->val;
|
||||
SubCheats[numsubcheats].compare=c->compare;
|
||||
SetReadHandler(c->addr,c->addr,SubCheatsRead);
|
||||
SubCheats[numsubcheats].PrevRead = GetReadHandler(c->addr);
|
||||
SubCheats[numsubcheats].addr = c->addr;
|
||||
SubCheats[numsubcheats].val = c->val;
|
||||
SubCheats[numsubcheats].compare = c->compare;
|
||||
SetReadHandler(c->addr, c->addr, SubCheatsRead);
|
||||
if (cheatMap)
|
||||
FCEUI_SetCheatMapByte(SubCheats[numsubcheats].addr, true);
|
||||
numsubcheats++;
|
||||
}
|
||||
c = c->next;
|
||||
}
|
||||
c=c->next;
|
||||
}
|
||||
FrozenAddressCount = numsubcheats; //Update the frozen address list
|
||||
UpdateFrozenList();
|
||||
//FCEUI_DispMessage("Active Cheats: %d",0, FrozenAddresses.size()/*FrozenAddressCount*/); //Debug
|
||||
|
||||
}
|
||||
|
||||
void FCEU_PowerCheats()
|
||||
{
|
||||
numsubcheats=0; /* Quick hack to prevent setting of ancient read addresses. */
|
||||
numsubcheats = 0; /* Quick hack to prevent setting of ancient read addresses. */
|
||||
if (cheatMap)
|
||||
FCEUI_RefreshCheatMap();
|
||||
RebuildSubCheats();
|
||||
}
|
||||
|
||||
static int AddCheatEntry(char *name, uint32 addr, uint8 val, int compare, int status, int type);
|
||||
int FCEU_CalcCheatAffectedBytes(uint32 address, uint32 size) {
|
||||
|
||||
uint32 count = 0;
|
||||
if (cheatMap)
|
||||
for (uint32 i = 0; i < size; ++i)
|
||||
if (FCEUI_FindCheatMapByte(address + i))
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
/* This function doesn't allocate any memory for "name" */
|
||||
static int AddCheatEntry(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);
|
||||
}
|
||||
temp->name=name;
|
||||
temp->addr=addr;
|
||||
temp->val=val;
|
||||
temp->status=status;
|
||||
temp->compare=compare;
|
||||
temp->type=type;
|
||||
temp->next=0;
|
||||
CHEATF *temp = new CHEATF();
|
||||
|
||||
temp->name = name;
|
||||
temp->addr = addr;
|
||||
temp->val = val;
|
||||
temp->status = status;
|
||||
temp->compare = compare;
|
||||
temp->type = type;
|
||||
temp->next = nullptr;
|
||||
|
||||
if(cheats)
|
||||
{
|
||||
cheatsl->next=temp;
|
||||
cheatsl=temp;
|
||||
cheatsl->next = temp;
|
||||
cheatsl = temp;
|
||||
}
|
||||
else
|
||||
cheats=cheatsl=temp;
|
||||
|
||||
return(1);
|
||||
cheats = cheatsl = temp;
|
||||
}
|
||||
|
||||
void FCEU_LoadGameCheats(FILE *override)
|
||||
/* The "override_existing" parameter is used only in cheat dialog import.
|
||||
Since the default behaviour will reset numsubcheats to 0 everytime,
|
||||
In game loading, this is absolutely right, but when importing in cheat window,
|
||||
resetting numsubcheats to 0 will override existed cheat items to make them
|
||||
invalid.
|
||||
*/
|
||||
void FCEU_LoadGameCheats(FILE *override, int override_existing)
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned int addr;
|
||||
@@ -198,89 +195,120 @@ void FCEU_LoadGameCheats(FILE *override)
|
||||
unsigned int compare;
|
||||
int x;
|
||||
|
||||
char linebuf[2048];
|
||||
char *namebuf;
|
||||
int tc=0;
|
||||
char linebuf[2048] = { 0 };
|
||||
char namebuf[128] = { 0 };
|
||||
int tc = 0;
|
||||
char *fn;
|
||||
|
||||
numsubcheats=savecheats=0;
|
||||
if (override_existing)
|
||||
{
|
||||
numsubcheats = 0;
|
||||
if (cheatMap)
|
||||
FCEUI_RefreshCheatMap();
|
||||
}
|
||||
|
||||
if(override)
|
||||
fp = override;
|
||||
else
|
||||
{
|
||||
fn=strdup(FCEU_MakeFName(FCEUMKF_CHEAT,0,0).c_str());
|
||||
fp=FCEUD_UTF8fopen(fn,"rb");
|
||||
fn = strdup(FCEU_MakeFName(FCEUMKF_CHEAT, 0, 0).c_str());
|
||||
fp = FCEUD_UTF8fopen(fn, "rb");
|
||||
free(fn);
|
||||
if(!fp) return;
|
||||
if (!fp) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
FCEU_DispMessage("Cheats file loaded.",0); //Tells user a cheats file was loaded.
|
||||
while(fgets(linebuf,2048,fp) != nullptr)
|
||||
while(fgets(linebuf, 2048, fp) != nullptr)
|
||||
{
|
||||
char *tbuf=linebuf;
|
||||
int doc=0;
|
||||
char *tbuf = linebuf;
|
||||
int doc = 0;
|
||||
|
||||
addr=val=compare=status=type=0;
|
||||
addr = val = compare = status = type = 0;
|
||||
|
||||
if(tbuf[0]=='S')
|
||||
if(tbuf[0] == 'S')
|
||||
{
|
||||
tbuf++;
|
||||
type=1;
|
||||
type = 1;
|
||||
}
|
||||
else type=0;
|
||||
else
|
||||
type = 0;
|
||||
|
||||
if(tbuf[0]=='C')
|
||||
if(tbuf[0] == 'C')
|
||||
{
|
||||
tbuf++;
|
||||
doc=1;
|
||||
doc = 1;
|
||||
}
|
||||
|
||||
if(tbuf[0]==':')
|
||||
if(tbuf[0] == ':')
|
||||
{
|
||||
tbuf++;
|
||||
status=0;
|
||||
status = 0;
|
||||
}
|
||||
else status=1;
|
||||
else status = 1;
|
||||
|
||||
if(doc)
|
||||
{
|
||||
char *neo=&tbuf[4+2+2+1+1+1];
|
||||
if(sscanf(tbuf,"%04x%*[:]%02x%*[:]%02x",&addr,&val,&compare)!=3)
|
||||
char *neo = &tbuf[4+2+2+1+1+1];
|
||||
if(sscanf(tbuf, "%04x%*[:]%02x%*[:]%02x", &addr, &val, &compare) != 3)
|
||||
continue;
|
||||
if (!(namebuf=(char *)FCEU_dmalloc(strlen(neo)+1)))
|
||||
return;
|
||||
strcpy(namebuf,neo);
|
||||
strcpy(namebuf, neo);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *neo=&tbuf[4+2+1+1];
|
||||
if(sscanf(tbuf,"%04x%*[:]%02x",&addr,&val)!=2)
|
||||
char *neo = &tbuf[4+2+1+1];
|
||||
if(sscanf(tbuf, "%04x%*[:]%02x", &addr, &val) != 2)
|
||||
continue;
|
||||
if (!(namebuf=(char *)FCEU_dmalloc(strlen(neo)+1)))
|
||||
return;
|
||||
strcpy(namebuf,neo);
|
||||
strcpy(namebuf, neo);
|
||||
}
|
||||
|
||||
for(x=0;x<(int)strlen(namebuf);x++)
|
||||
for(x = 0; x < (int)strlen(namebuf); x++)
|
||||
{
|
||||
if(namebuf[x]==10 || namebuf[x]==13)
|
||||
if(namebuf[x] == 10 || namebuf[x] == 13)
|
||||
{
|
||||
namebuf[x]=0;
|
||||
namebuf[x] = 0;
|
||||
break;
|
||||
}
|
||||
else if(namebuf[x] > 0x00 && namebuf[x] < 0x20)
|
||||
namebuf[x]=0x20;
|
||||
namebuf[x] = 0x20;
|
||||
}
|
||||
|
||||
AddCheatEntry(namebuf,addr,val,doc?compare:-1,status,type);
|
||||
AddCheatEntry(namebuf, addr, val, doc ? compare : -1, status, type);
|
||||
tc++;
|
||||
}
|
||||
|
||||
RebuildSubCheats();
|
||||
|
||||
FCEU_DispMessage("Cheats file loaded.", 0); //Tells user a cheats file was loaded.
|
||||
|
||||
if(!override)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void FCEU_SaveGameCheats(FILE* fp, int release)
|
||||
{
|
||||
struct CHEATF *next = cheats;
|
||||
while (next)
|
||||
{
|
||||
if (next->type)
|
||||
fputc('S', fp);
|
||||
if (next->compare >= 0)
|
||||
fputc('C', fp);
|
||||
|
||||
if (!next->status)
|
||||
fputc(':', fp);
|
||||
|
||||
if (next->compare >= 0)
|
||||
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.c_str());
|
||||
|
||||
struct CHEATF *t = next;
|
||||
next = next->next;
|
||||
if (release) delete t;
|
||||
}
|
||||
}
|
||||
|
||||
void FCEU_FlushGameCheats(FILE *override, int nosave)
|
||||
{
|
||||
if(CheatComp)
|
||||
@@ -297,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;
|
||||
@@ -313,7 +340,6 @@ void FCEU_FlushGameCheats(FILE *override, int nosave)
|
||||
|
||||
if(cheats)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
FILE *fp;
|
||||
|
||||
if(override)
|
||||
@@ -323,28 +349,7 @@ void FCEU_FlushGameCheats(FILE *override, int nosave)
|
||||
|
||||
if(fp)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
struct CHEATF *t;
|
||||
if(next->type)
|
||||
fputc('S',fp);
|
||||
if(next->compare>=0)
|
||||
fputc('C',fp);
|
||||
|
||||
if(!next->status)
|
||||
fputc(':',fp);
|
||||
|
||||
if(next->compare>=0)
|
||||
fprintf(fp,"%04x:%02x:%02x:%s\n",next->addr,next->val,next->compare,next->name);
|
||||
else
|
||||
fprintf(fp,"%04x:%02x:%s\n",next->addr,next->val,next->name);
|
||||
|
||||
free(next->name);
|
||||
t=next;
|
||||
next=next->next;
|
||||
free(t);
|
||||
if(!next) break;
|
||||
}
|
||||
FCEU_SaveGameCheats(fp, 1);
|
||||
if(!override)
|
||||
fclose(fp);
|
||||
}
|
||||
@@ -365,23 +370,11 @@ void FCEU_FlushGameCheats(FILE *override, int nosave)
|
||||
|
||||
int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type)
|
||||
{
|
||||
char *t;
|
||||
|
||||
if(!(t=(char *)FCEU_dmalloc(strlen(name)+1)))
|
||||
{
|
||||
CheatMemErr();
|
||||
return(0);
|
||||
}
|
||||
strcpy(t,name);
|
||||
if(!AddCheatEntry(t,addr,val,compare,1,type))
|
||||
{
|
||||
free(t);
|
||||
return(0);
|
||||
}
|
||||
savecheats=1;
|
||||
AddCheatEntry(name, addr, val, compare, 1, type);
|
||||
savecheats = 1;
|
||||
RebuildSubCheats();
|
||||
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int FCEUI_DelCheat(uint32 which)
|
||||
@@ -411,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*
|
||||
|
||||
@@ -447,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;
|
||||
@@ -566,7 +558,7 @@ int FCEUI_DecodeGG(const char *str, int *a, int *v, int *c)
|
||||
|
||||
int FCEUI_DecodePAR(const char *str, int *a, int *v, int *c, int *type)
|
||||
{
|
||||
int boo[4];
|
||||
unsigned int boo[4];
|
||||
if(strlen(str)!=8) return(0);
|
||||
|
||||
sscanf(str,"%02x%02x%02x%02x",boo,boo+1,boo+2,boo+3);
|
||||
@@ -596,45 +588,36 @@ 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;
|
||||
struct CHEATF *next = cheats;
|
||||
uint32 x = 0;
|
||||
|
||||
while(next)
|
||||
{
|
||||
if(x==which)
|
||||
if(x == which)
|
||||
{
|
||||
if(name)
|
||||
{
|
||||
char *t;
|
||||
if((t=(char *)realloc(next->name, strlen(name)+1)))
|
||||
{
|
||||
next->name=t;
|
||||
strcpy(next->name,name);
|
||||
}
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
if(a>=0)
|
||||
next->addr=a;
|
||||
if(v>=0)
|
||||
next->val=v;
|
||||
if(s>=0)
|
||||
next->status=s;
|
||||
if(c>=-1)
|
||||
next->compare=c;
|
||||
next->type=type;
|
||||
next->name = *name;
|
||||
if(a >= 0)
|
||||
next->addr = a;
|
||||
if(v >= 0)
|
||||
next->val = v;
|
||||
if(s >= 0)
|
||||
next->status = s;
|
||||
if(c >= -1)
|
||||
next->compare = c;
|
||||
next->type = type;
|
||||
|
||||
savecheats=1;
|
||||
savecheats = 1;
|
||||
RebuildSubCheats();
|
||||
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
next=next->next;
|
||||
next = next->next;
|
||||
x++;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convenience function. */
|
||||
@@ -659,6 +642,14 @@ int FCEUI_ToggleCheat(uint32 which)
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int FCEUI_GlobalToggleCheat(int global_enabled)
|
||||
{
|
||||
unsigned int _numsubcheats = numsubcheats;
|
||||
globalCheatDisabled = !global_enabled;
|
||||
RebuildSubCheats();
|
||||
return _numsubcheats != numsubcheats;
|
||||
}
|
||||
|
||||
static int InitCheatComp(void)
|
||||
{
|
||||
uint32 x;
|
||||
@@ -741,7 +732,7 @@ void FCEUI_CheatSearchGet(int (*callb)(uint32 a, uint8 last, uint8 current, void
|
||||
void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a, uint8 last, uint8 current))
|
||||
{
|
||||
uint32 x;
|
||||
uint32 in=0;
|
||||
uint32 in = 0;
|
||||
|
||||
if(!CheatComp)
|
||||
{
|
||||
@@ -750,14 +741,15 @@ void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a,
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
|
||||
for(x = 0; x < 0x10000; x++)
|
||||
if(!(CheatComp[x] & CHEATC_NOSHOW) && CheatRPtrs[x >> 10])
|
||||
{
|
||||
if(in>=first)
|
||||
if(!callb(x,CheatComp[x],CheatRPtrs[x>>10][x]))
|
||||
if(in >= first)
|
||||
if(!callb(x, CheatComp[x], CheatRPtrs[x >> 10][x]))
|
||||
break;
|
||||
in++;
|
||||
if(in>last) return;
|
||||
if(in > last)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -803,130 +795,56 @@ void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!type) // Change to a specific value.
|
||||
switch (type)
|
||||
{
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]==v1 && CheatRPtrs[x>>10][x]==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
default:
|
||||
case FCEU_SEARCH_SPECIFIC_CHANGE: // Change to a specific value
|
||||
for (x = 0; x < 0x10000; ++x)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && (CheatComp[x] != v1 || CheatRPtrs[x >> 10][x] != v2))
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_RELATIVE_CHANGE: // Search for relative change (between values).
|
||||
for (x = 0; x < 0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && (CheatComp[x] != v1 || CAbs(CheatComp[x] - CheatRPtrs[x >> 10][x]) != v2))
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_PUERLY_RELATIVE_CHANGE: // Purely relative change.
|
||||
for (x = 0x000; x<0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && CAbs(CheatComp[x] - CheatRPtrs[x >> 10][x]) != v2)
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_ANY_CHANGE: // Any change.
|
||||
for (x = 0x000; x < 0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && CheatComp[x] == CheatRPtrs[x >> 10][x])
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_NEWVAL_KNOWN: // new value = known
|
||||
for (x = 0x000; x < 0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && CheatRPtrs[x >> 10][x] != v1)
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_NEWVAL_GT: // new value greater than
|
||||
for (x = 0x000; x < 0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && CheatComp[x] >= CheatRPtrs[x >> 10][x])
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_NEWVAL_LT: // new value less than
|
||||
for (x = 0x000; x < 0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && CheatComp[x] <= CheatRPtrs[x >> 10][x])
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_NEWVAL_GT_KNOWN: // new value greater than by known value
|
||||
for (x = 0x000; x < 0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && CheatRPtrs[x >> 10][x] - CheatComp[x] != v2)
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
case FCEU_SEARCH_NEWVAL_LT_KNOWN: // new value less than by known value
|
||||
for (x = 0x000; x < 0x10000; x++)
|
||||
if (!(CheatComp[x] & CHEATC_NOSHOW) && (CheatComp[x] - CheatRPtrs[x >> 10][x]) != v2)
|
||||
CheatComp[x] |= CHEATC_EXCLUDED;
|
||||
break;
|
||||
}
|
||||
else if(type==1) // Search for relative change(between values).
|
||||
{
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]==v1 && CAbs(CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
else if(type==2) // Purely relative change.
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CAbs(CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
else if(type==3) // Any change.
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]!=CheatRPtrs[x>>10][x])
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
|
||||
}
|
||||
else if(type==4) // new value = known
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatRPtrs[x>>10][x]==v1)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
|
||||
}
|
||||
else if(type==5) // new value greater than
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]<CheatRPtrs[x>>10][x])
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
|
||||
}
|
||||
else if(type==6) // new value less than
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]>CheatRPtrs[x>>10][x])
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
|
||||
}
|
||||
else if(type==7) // new value greater than by known value
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if((CheatRPtrs[x>>10][x]-CheatComp[x])==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
|
||||
}
|
||||
else if(type==8) // new value less than by known value
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if((CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int FCEU_CheatGetByte(uint32 A)
|
||||
@@ -949,18 +867,71 @@ void FCEU_CheatSetByte(uint32 A, uint8 V)
|
||||
BWrite[A](A, V);
|
||||
}
|
||||
|
||||
void UpdateFrozenList(void)
|
||||
// disable all cheats
|
||||
int FCEU_DisableAllCheats(void)
|
||||
{
|
||||
//The purpose of this function is to keep an up to date list of addresses that are currently frozen
|
||||
//and make these accessible to other dialogs that deal with memory addresses such as
|
||||
//memwatch, hex editor, ramfilter, etc.
|
||||
|
||||
int x;
|
||||
FrozenAddresses.clear(); //Clear vector and repopulate
|
||||
for(x=0;x<numsubcheats;x++)
|
||||
int count = 0;
|
||||
struct CHEATF *next = cheats;
|
||||
while(next)
|
||||
{
|
||||
FrozenAddresses.push_back(SubCheats[x].addr);
|
||||
//FCEU_printf("Address %d: %d \n",x,FrozenAddresses[x]); //Debug
|
||||
if(next->status){
|
||||
count++;
|
||||
}
|
||||
next->status = 0;
|
||||
next = next->next;
|
||||
}
|
||||
savecheats = 1;
|
||||
RebuildSubCheats();
|
||||
return count;
|
||||
}
|
||||
|
||||
// delete all cheats
|
||||
int FCEU_DeleteAllCheats(void)
|
||||
{
|
||||
struct CHEATF *cur = cheats;
|
||||
struct CHEATF *next = NULL;
|
||||
while (cur)
|
||||
{
|
||||
next = cur->next;
|
||||
delete cur;
|
||||
cur = next;
|
||||
}
|
||||
cheats = cheatsl = 0;
|
||||
savecheats = 1;
|
||||
RebuildSubCheats();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FCEUI_FindCheatMapByte(uint16 address)
|
||||
{
|
||||
return cheatMap[address / 8] >> (address % 8) & 1;
|
||||
}
|
||||
|
||||
void FCEUI_SetCheatMapByte(uint16 address, bool cheat)
|
||||
{
|
||||
cheat ? cheatMap[address / 8] |= (1 << address % 8) : cheatMap[address / 8] ^= (1 << address % 8);
|
||||
}
|
||||
|
||||
void FCEUI_CreateCheatMap(void)
|
||||
{
|
||||
if (!cheatMap)
|
||||
cheatMap = (unsigned char*)malloc(CHEATMAP_SIZE);
|
||||
FCEUI_RefreshCheatMap();
|
||||
}
|
||||
|
||||
void FCEUI_RefreshCheatMap(void)
|
||||
{
|
||||
memset(cheatMap, 0, CHEATMAP_SIZE);
|
||||
for (uint32 i = 0; i < numsubcheats; ++i)
|
||||
FCEUI_SetCheatMapByte(SubCheats[i].addr, true);
|
||||
}
|
||||
|
||||
void FCEUI_ReleaseCheatMap(void)
|
||||
{
|
||||
if (cheatMap)
|
||||
{
|
||||
free(cheatMap);
|
||||
cheatMap = NULL;
|
||||
}
|
||||
//FCEUI_DispMessage("FrozenCount: %d",0,FrozenAddressCount);//Debug
|
||||
}
|
||||
|
||||
+66
-2
@@ -1,12 +1,76 @@
|
||||
#ifndef CHEAT_H
|
||||
#define CHEAT_H
|
||||
void FCEU_CheatResetRAM(void);
|
||||
void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p);
|
||||
|
||||
void FCEU_LoadGameCheats(FILE *override);
|
||||
void FCEU_LoadGameCheats(FILE *override, int override_existing = 1);
|
||||
void FCEU_FlushGameCheats(FILE *override, int nosave);
|
||||
void FCEU_SaveGameCheats(FILE *fp, int release = 0);
|
||||
int FCEUI_GlobalToggleCheat(int global_enabled);
|
||||
void FCEU_ApplyPeriodicCheats(void);
|
||||
void FCEU_PowerCheats(void);
|
||||
int FCEU_CalcCheatAffectedBytes(uint32 address, uint32 size);
|
||||
|
||||
// Trying to find a more efficient way for determining if an address has a cheat
|
||||
// each bit of 1 byte represents to 8 bytes in NES
|
||||
typedef unsigned char _8BYTECHEATMAP;
|
||||
#define CHEATMAP_SIZE 0x10000 / 8
|
||||
|
||||
extern int FCEUI_FindCheatMapByte(uint16 address);
|
||||
extern void FCEUI_SetCheatMapByte(uint16 address, bool cheat);
|
||||
extern void FCEUI_CreateCheatMap(void);
|
||||
extern void FCEUI_RefreshCheatMap(void);
|
||||
extern void FCEUI_ReleaseCheatMap(void);
|
||||
extern unsigned int FrozenAddressCount;
|
||||
|
||||
int FCEU_CheatGetByte(uint32 A);
|
||||
void FCEU_CheatSetByte(uint32 A, uint8 V);
|
||||
|
||||
extern int savecheats;
|
||||
extern int savecheats;
|
||||
extern int globalCheatDisabled;
|
||||
extern int disableAutoLSCheats;
|
||||
|
||||
int FCEU_DisableAllCheats(void);
|
||||
int FCEU_DeleteAllCheats(void);
|
||||
|
||||
struct CHEATF_SUBFAST
|
||||
{
|
||||
uint16 addr;
|
||||
uint8 val;
|
||||
int compare;
|
||||
readfunc PrevRead;
|
||||
|
||||
CHEATF_SUBFAST(void)
|
||||
{
|
||||
addr = 0; val = 0; compare = 0; PrevRead = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
struct CHEATF {
|
||||
struct CHEATF *next;
|
||||
std::string name;
|
||||
uint16 addr;
|
||||
uint8 val;
|
||||
int compare; /* -1 for no compare. */
|
||||
int type; /* 0 for replace, 1 for substitute(GG). */
|
||||
int status;
|
||||
};
|
||||
|
||||
struct SEARCHPOSSIBLE {
|
||||
uint16 addr;
|
||||
uint8 previous;
|
||||
uint8 current;
|
||||
bool update;
|
||||
};
|
||||
|
||||
#define FCEU_SEARCH_SPECIFIC_CHANGE 0
|
||||
#define FCEU_SEARCH_RELATIVE_CHANGE 1
|
||||
#define FCEU_SEARCH_PUERLY_RELATIVE_CHANGE 2
|
||||
#define FCEU_SEARCH_ANY_CHANGE 3
|
||||
#define FCEU_SEARCH_NEWVAL_KNOWN 4
|
||||
#define FCEU_SEARCH_NEWVAL_GT 5
|
||||
#define FCEU_SEARCH_NEWVAL_LT 6
|
||||
#define FCEU_SEARCH_NEWVAL_GT_KNOWN 7
|
||||
#define FCEU_SEARCH_NEWVAL_LT_KNOWN 8
|
||||
|
||||
#endif
|
||||
|
||||
+114
-61
@@ -34,10 +34,11 @@
|
||||
* Primitive -> Number | Address | Register | Flag | PC Bank | '(' Connect ')'
|
||||
* Number -> '#' [1-9A-F]*
|
||||
* Address -> '$' [1-9A-F]* | '$' '[' Connect ']'
|
||||
* Register -> 'A' | 'X' | 'Y' | 'P'
|
||||
* Flag -> 'N' | 'C' | 'Z' | 'I' | 'B' | 'V'
|
||||
* Register -> 'A' | 'X' | 'Y' | 'P' | 'S'
|
||||
* Flag -> 'N' | 'C' | 'Z' | 'I' | 'B' | 'V' | 'U' | 'D'
|
||||
* PC Bank -> 'K'
|
||||
* Data Bank -> 'T'
|
||||
* Data Bank -> 'T'
|
||||
* Value -> 'R' | 'W'
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
@@ -50,17 +51,18 @@
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
|
||||
// hack: this address is used by 'T' condition
|
||||
uint16 addressOfTheLastAccessedData = 0;
|
||||
// Next non-whitespace character in string
|
||||
char next;
|
||||
uint16 debugLastAddress = 0; // used by 'T' and 'R' conditions
|
||||
uint8 debugLastOpcode = 0; // used to evaluate 'W' condition
|
||||
|
||||
int ishex(char c)
|
||||
// Next non-whitespace character in string
|
||||
static char next = 0;
|
||||
|
||||
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
|
||||
{
|
||||
@@ -69,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;
|
||||
@@ -115,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)
|
||||
{
|
||||
@@ -129,31 +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';
|
||||
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
|
||||
static int isValueRead(char c)
|
||||
{
|
||||
return c == 'R';
|
||||
}
|
||||
|
||||
// Determines if a character is for value write
|
||||
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];
|
||||
|
||||
@@ -171,19 +182,19 @@ 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)
|
||||
{
|
||||
scan(str);
|
||||
|
||||
c->lhs = Connect(str);
|
||||
|
||||
if (!c) return 0;
|
||||
|
||||
c->lhs = Connect(str);
|
||||
|
||||
if (next == closePar)
|
||||
{
|
||||
scan(str);
|
||||
@@ -202,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 */
|
||||
{
|
||||
@@ -272,6 +283,40 @@ Condition* Primitive(const char** str, Condition* c)
|
||||
|
||||
return c;
|
||||
}
|
||||
else if (isValueRead(next))
|
||||
{
|
||||
if (c->type1 == TYPE_NO)
|
||||
{
|
||||
c->type1 = TYPE_VALUE_READ;
|
||||
c->value1 = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->type2 = TYPE_VALUE_READ;
|
||||
c->value2 = next;
|
||||
}
|
||||
|
||||
scan(str);
|
||||
|
||||
return c;
|
||||
}
|
||||
else if (isValueWrite(next))
|
||||
{
|
||||
if (c->type1 == TYPE_NO)
|
||||
{
|
||||
c->type1 = TYPE_VALUE_WRITE;
|
||||
c->value1 = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->type2 = TYPE_VALUE_WRITE;
|
||||
c->value2 = next;
|
||||
}
|
||||
|
||||
scan(str);
|
||||
|
||||
return c;
|
||||
}
|
||||
else if (next == '#') /* Numbers */
|
||||
{
|
||||
unsigned int number = 0;
|
||||
@@ -346,21 +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));
|
||||
if (!t)
|
||||
return NULL;
|
||||
t = new Condition();
|
||||
|
||||
memset(t, 0, sizeof(Condition));
|
||||
if (t == nullptr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!Primitive(str, t))
|
||||
{
|
||||
freeTree(t);
|
||||
delete t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -370,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;
|
||||
@@ -398,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)
|
||||
{
|
||||
@@ -409,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;
|
||||
@@ -439,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;
|
||||
@@ -457,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);
|
||||
}
|
||||
@@ -470,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;
|
||||
}
|
||||
|
||||
+25
-2
@@ -28,6 +28,8 @@
|
||||
#define TYPE_ADDR 4
|
||||
#define TYPE_PC_BANK 5
|
||||
#define TYPE_DATA_BANK 6
|
||||
#define TYPE_VALUE_READ 7
|
||||
#define TYPE_VALUE_WRITE 8
|
||||
|
||||
#define OP_NO 0
|
||||
#define OP_EQ 1
|
||||
@@ -43,7 +45,9 @@
|
||||
#define OP_OR 11
|
||||
#define OP_AND 12
|
||||
|
||||
extern uint16 addressOfTheLastAccessedData;
|
||||
extern uint16 debugLastAddress;
|
||||
extern uint8 debugLastOpcode;
|
||||
|
||||
//mbg merge 7/18/06 turned into sane c++
|
||||
struct Condition
|
||||
{
|
||||
@@ -57,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
|
||||
|
||||
+26
-12
@@ -11,20 +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
|
||||
char *FCEUI_GetAboutString() {
|
||||
const char *FCEUI_GetAboutString(void)
|
||||
{
|
||||
const char *aboutTemplate =
|
||||
FCEU_NAME_AND_VERSION "\n\n"
|
||||
"Administrators:\n"
|
||||
"zeromus, punkrockguy318 (Lukas Sabota), feos\n"
|
||||
"zeromus, feos\n"
|
||||
"\n"
|
||||
"Current Contributors:\n"
|
||||
"CaH4e3, rainwarrior\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"
|
||||
@@ -40,20 +47,27 @@ char *FCEUI_GetAboutString() {
|
||||
"FCEU TAS - blip & nitsuja\n"
|
||||
"FCEU TAS+ - Luke Gustafson\n"
|
||||
"\n"
|
||||
"Logo/icon:\n"
|
||||
"Terwilf\n"
|
||||
"\n"
|
||||
"FCEUX is dedicated to the fallen heroes\n"
|
||||
"of NES emulation. In Memoriam --\n"
|
||||
"ugetab\n"
|
||||
"\n"
|
||||
__TIME__ " " __DATE__ "\n";
|
||||
"\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();
|
||||
}
|
||||
|
||||
+286
-117
@@ -6,6 +6,7 @@
|
||||
#include "cart.h"
|
||||
#include "ines.h"
|
||||
#include "debug.h"
|
||||
#include "debugsymboltable.h"
|
||||
#include "driver.h"
|
||||
#include "ppu.h"
|
||||
|
||||
@@ -18,45 +19,88 @@ 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 (sscanf(offsetBuffer,"%4X",&offset) == EOF)
|
||||
if (conversionOk)
|
||||
{
|
||||
*conversionOk = false;
|
||||
}
|
||||
|
||||
if (sscanf(offsetBuffer,"%7X",(unsigned int *)&offset) == EOF)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
if (GameInfo->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));
|
||||
auto sym = debugSymbolTable.getSymbolAtAnyBank(offsetBuffer);
|
||||
|
||||
if (sym)
|
||||
{
|
||||
if (conversionOk)
|
||||
{
|
||||
*conversionOk = true;
|
||||
}
|
||||
return sym->offset() & 0xFFFF;
|
||||
}
|
||||
else if (GameInfo->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));
|
||||
|
||||
int type = GIT_CART;
|
||||
|
||||
if (GameInfo)
|
||||
{
|
||||
type = GameInfo->type;
|
||||
}
|
||||
if (type == GIT_NSF) { //NSF Breakpoint keywords
|
||||
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) 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);
|
||||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
return offset & 0xFFFF;
|
||||
}
|
||||
|
||||
// Returns the value of a given type or register
|
||||
@@ -77,6 +121,7 @@ int getValue(int type)
|
||||
case 'Z': return _P & Z_FLAG ? 1 : 0;
|
||||
case 'C': return _P & C_FLAG ? 1 : 0;
|
||||
case 'P': return _PC;
|
||||
case 'S': return _S;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -120,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;
|
||||
@@ -134,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
|
||||
@@ -150,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;
|
||||
@@ -193,6 +238,9 @@ unsigned int NewBreak(const char* name, int start, int end, unsigned int type, c
|
||||
watchpoint[num].flags|=BT_S;
|
||||
watchpoint[num].flags&=~WP_X; //disable execute flag!
|
||||
}
|
||||
if (type & BT_R) {
|
||||
watchpoint[num].flags|=BT_R;
|
||||
}
|
||||
|
||||
if (watchpoint[num].desc)
|
||||
free(watchpoint[num].desc);
|
||||
@@ -207,11 +255,27 @@ int GetPRGAddress(int A){
|
||||
int result;
|
||||
if(A > 0xFFFF)
|
||||
return -1;
|
||||
result = &Page[A>>11][A]-PRGptr[0];
|
||||
if((result > (int)PRGsize[0]) || (result < 0))
|
||||
return -1;
|
||||
else
|
||||
return result;
|
||||
if (GameInfo->type == GIT_FDS) {
|
||||
if (A < 0xE000) {
|
||||
result = &Page[A >> 11][A] - PRGptr[1];
|
||||
if ((result > (int)PRGsize[1]) || (result < 0))
|
||||
return -1;
|
||||
else
|
||||
return result;
|
||||
} else {
|
||||
result = &Page[A >> 11][A] - PRGptr[0];
|
||||
if ((result > (int)PRGsize[0]) || (result < 0))
|
||||
return -1;
|
||||
else
|
||||
return result + PRGsize[1];
|
||||
}
|
||||
} else {
|
||||
result = &Page[A >> 11][A] - PRGptr[0];
|
||||
if ((result > (int)PRGsize[0]) || (result < 0))
|
||||
return -1;
|
||||
else
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,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;
|
||||
@@ -240,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;
|
||||
}
|
||||
@@ -309,6 +373,32 @@ uint8 GetPPUMem(uint8 A) {
|
||||
|
||||
//---------------------
|
||||
|
||||
uint8 evaluateWrite(uint8 opcode, uint16 address)
|
||||
{
|
||||
// predicts value written by this opcode
|
||||
switch (opwrite[opcode])
|
||||
{
|
||||
default:
|
||||
case 0: return 0; // no write
|
||||
case 1: return _A; // STA, PHA
|
||||
case 2: return _X; // STX
|
||||
case 3: return _Y; // STY
|
||||
case 4: return _P; // PHP
|
||||
case 5: return GetMem(address) << 1; // ASL (SLO)
|
||||
case 6: return GetMem(address) >> 1; // LSR (SRE)
|
||||
case 7: return (GetMem(address) << 1) | (_P & 1); // ROL (RLA)
|
||||
case 8: return (GetMem(address) >> 1) | ((_P & 1) << 7); // ROL (RRA)
|
||||
case 9: return GetMem(address) + 1; // INC (ISC)
|
||||
case 10: return GetMem(address) - 1; // DEC (DCP)
|
||||
case 11: return _A & _X; // (SAX)
|
||||
case 12: return _A&_X&(((address-_Y)>>8)+1); // (AHX)
|
||||
case 13: return _Y&(((address-_X)>>8)+1); // (SHY)
|
||||
case 14: return _X&(((address-_Y)>>8)+1); // (SHX)
|
||||
case 15: return _S& (((address-_Y)>>8)+1); // (TAS)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Evaluates a condition
|
||||
int evaluate(Condition* c)
|
||||
{
|
||||
@@ -334,7 +424,9 @@ int evaluate(Condition* c)
|
||||
{
|
||||
case TYPE_ADDR: value1 = GetMem(value1); break;
|
||||
case TYPE_PC_BANK: value1 = getBank(_PC); break;
|
||||
case TYPE_DATA_BANK: value1 = getBank(addressOfTheLastAccessedData); break;
|
||||
case TYPE_DATA_BANK: value1 = getBank(debugLastAddress); break;
|
||||
case TYPE_VALUE_READ: value1 = GetMem(debugLastAddress); break;
|
||||
case TYPE_VALUE_WRITE: value1 = evaluateWrite(debugLastOpcode, debugLastAddress); break;
|
||||
}
|
||||
|
||||
f = value1;
|
||||
@@ -359,7 +451,9 @@ int evaluate(Condition* c)
|
||||
{
|
||||
case TYPE_ADDR: value2 = GetMem(value2); break;
|
||||
case TYPE_PC_BANK: value2 = getBank(_PC); break;
|
||||
case TYPE_DATA_BANK: value2 = getBank(addressOfTheLastAccessedData); break;
|
||||
case TYPE_DATA_BANK: value2 = getBank(debugLastAddress); break;
|
||||
case TYPE_VALUE_READ: value2 = GetMem(debugLastAddress); break;
|
||||
case TYPE_VALUE_WRITE: value2 = evaluateWrite(debugLastOpcode, debugLastAddress); break;
|
||||
}
|
||||
|
||||
switch (c->op)
|
||||
@@ -371,7 +465,7 @@ int evaluate(Condition* c)
|
||||
case OP_G: f = value1 > value2; break;
|
||||
case OP_L: f = value1 < value2; break;
|
||||
case OP_MULT: f = value1 * value2; break;
|
||||
case OP_DIV: f = value1 / value2; break;
|
||||
case OP_DIV: f = (value2==0) ? 0 : (value1 / value2); break;
|
||||
case OP_PLUS: f = value1 + value2; break;
|
||||
case OP_MINUS: f = value1 - value2; break;
|
||||
case OP_OR: f = value1 || value2; break;
|
||||
@@ -390,12 +484,12 @@ int condition(watchpointinfo* wp)
|
||||
|
||||
//---------------------
|
||||
|
||||
volatile int codecount, datacount, undefinedcount;
|
||||
unsigned char *cdloggerdata;
|
||||
volatile int codecount = 0, datacount = 0, undefinedcount = 0;
|
||||
unsigned char *cdloggerdata = NULL;
|
||||
unsigned int cdloggerdataSize = 0;
|
||||
static int indirectnext;
|
||||
static int indirectnext = 0;
|
||||
|
||||
int debug_loggingCD;
|
||||
int debug_loggingCD = 0;
|
||||
|
||||
//called by the cpu to perform logging if CDLogging is enabled
|
||||
void LogCDVectors(int which){
|
||||
@@ -417,20 +511,29 @@ void LogCDVectors(int which){
|
||||
}
|
||||
}
|
||||
|
||||
void LogCDData(uint8 *opcode, uint16 A, int size) {
|
||||
bool break_on_unlogged_code = false;
|
||||
bool break_on_unlogged_data = false;
|
||||
|
||||
void LogCDData(uint8 *opcode, uint16 A, int size)
|
||||
{
|
||||
int i, j;
|
||||
uint8 memop = 0;
|
||||
bool newCodeHit = false, newDataHit = false;
|
||||
|
||||
if((j = GetPRGAddress(_PC)) != -1)
|
||||
for (i = 0; i < size; i++) {
|
||||
if(cdloggerdata[j+i] & 1)continue; //this has been logged so skip
|
||||
if ((j = GetPRGAddress(_PC)) != -1)
|
||||
{
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (cdloggerdata[j+i] & 1) continue; //this has been logged so skip
|
||||
cdloggerdata[j+i] |= 1;
|
||||
cdloggerdata[j+i] |= ((_PC + i) >> 11) & 0x0c;
|
||||
cdloggerdata[j+i] |= ((_PC & 0x8000) >> 8) ^ 0x80; // 19/07/14 used last reserved bit, if bit 7 is 1, then code is running from lowe area (6000)
|
||||
if(indirectnext)cdloggerdata[j+i] |= 0x10;
|
||||
if (indirectnext)cdloggerdata[j+i] |= 0x10;
|
||||
codecount++;
|
||||
if(!(cdloggerdata[j+i] & 2))undefinedcount--;
|
||||
if (!(cdloggerdata[j+i] & 2))undefinedcount--;
|
||||
newCodeHit = true;
|
||||
}
|
||||
}
|
||||
|
||||
//log instruction jumped to in an indirect jump
|
||||
if(opcode[0] == 0x6c)
|
||||
@@ -443,14 +546,43 @@ void LogCDData(uint8 *opcode, uint16 A, int size) {
|
||||
case 4: memop = 0x20; break;
|
||||
}
|
||||
|
||||
if((j = GetPRGAddress(A)) != -1) {
|
||||
if(!(cdloggerdata[j] & 2)) {
|
||||
cdloggerdata[j] |= 2;
|
||||
cdloggerdata[j] |=(A>>11)&0x0c;
|
||||
cdloggerdata[j] |= memop;
|
||||
datacount++;
|
||||
if(!(cdloggerdata[j] & 1))undefinedcount--;
|
||||
if ((j = GetPRGAddress(A)) != -1)
|
||||
{
|
||||
if (opwrite[opcode[0]] == 0)
|
||||
{
|
||||
if (!(cdloggerdata[j] & 2))
|
||||
{
|
||||
cdloggerdata[j] |= 2;
|
||||
cdloggerdata[j] |= (A >> 11) & 0x0c;
|
||||
cdloggerdata[j] |= memop;
|
||||
cdloggerdata[j] |= ((A & 0x8000) >> 8) ^ 0x80;
|
||||
datacount++;
|
||||
if (!(cdloggerdata[j] & 1))undefinedcount--;
|
||||
newDataHit = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cdloggerdata[j] & 1)
|
||||
{
|
||||
codecount--;
|
||||
}
|
||||
if (cdloggerdata[j] & 2)
|
||||
{
|
||||
datacount--;
|
||||
}
|
||||
if ((cdloggerdata[j] & 3) != 0) undefinedcount++;
|
||||
cdloggerdata[j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( break_on_unlogged_code && newCodeHit )
|
||||
{
|
||||
BreakHit( BREAK_TYPE_UNLOGGED_CODE );
|
||||
}
|
||||
else if ( break_on_unlogged_data && newDataHit )
|
||||
{
|
||||
BreakHit( BREAK_TYPE_UNLOGGED_DATA );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,61 +634,71 @@ void IncrementInstructionsCounters()
|
||||
delta_instructions++;
|
||||
}
|
||||
|
||||
void BreakHit(int bp_num, bool force)
|
||||
{
|
||||
if(!force)
|
||||
bool CondForbidTest(int bp_num) {
|
||||
if (bp_num >= 0 && !condition(&watchpoint[bp_num]))
|
||||
{
|
||||
//check to see whether we fall in any forbid zone
|
||||
for (int i = 0; i < numWPs; i++)
|
||||
{
|
||||
watchpointinfo& wp = watchpoint[i];
|
||||
if(!(wp.flags & WP_F) || !(wp.flags & WP_E))
|
||||
continue;
|
||||
return false; // condition rejected
|
||||
}
|
||||
|
||||
if (condition(&wp))
|
||||
{
|
||||
if (wp.endaddress) {
|
||||
if( (wp.address <= _PC) && (wp.endaddress >= _PC) )
|
||||
return; //forbid
|
||||
} else {
|
||||
if(wp.address == _PC)
|
||||
return; //forbid
|
||||
}
|
||||
//check to see whether we fall in any forbid zone
|
||||
for (int i = 0; i < numWPs; i++)
|
||||
{
|
||||
watchpointinfo& wp = watchpoint[i];
|
||||
if (!(wp.flags & WP_F) || !(wp.flags & WP_E))
|
||||
continue;
|
||||
|
||||
if (condition(&wp))
|
||||
{
|
||||
if (wp.endaddress) {
|
||||
if ((wp.address <= _PC) && (wp.endaddress >= _PC))
|
||||
return false; // forbid
|
||||
}
|
||||
else {
|
||||
if (wp.address == _PC)
|
||||
return false; // forbid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FCEUI_SetEmulationPaused(EMULATIONPAUSED_PAUSED); //mbg merge 7/19/06 changed to use EmulationPaused()
|
||||
|
||||
#ifdef WIN32
|
||||
FCEUD_DebugBreakpoint(bp_num);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8 StackAddrBackup = X.S;
|
||||
void BreakHit(int bp_num)
|
||||
{
|
||||
FCEUI_SetEmulationPaused(EMULATIONPAUSED_PAUSED); //mbg merge 7/19/06 changed to use EmulationPaused()
|
||||
|
||||
//#ifdef WIN32
|
||||
FCEUD_DebugBreakpoint(bp_num);
|
||||
//#endif
|
||||
}
|
||||
|
||||
int StackAddrBackup;
|
||||
uint16 StackNextIgnorePC = 0xFFFF;
|
||||
|
||||
///fires a breakpoint
|
||||
static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
int i, j;
|
||||
int i, romAddrPC;
|
||||
unsigned int j;
|
||||
uint8 brk_type;
|
||||
uint8 stackop=0;
|
||||
uint8 stackopstartaddr,stackopendaddr;
|
||||
uint8 stackopstartaddr=0,stackopendaddr=0;
|
||||
|
||||
debugLastAddress = A;
|
||||
debugLastOpcode = opcode[0];
|
||||
|
||||
if (break_asap)
|
||||
{
|
||||
break_asap = false;
|
||||
BreakHit(BREAK_TYPE_LUA, true);
|
||||
BreakHit(BREAK_TYPE_LUA);
|
||||
}
|
||||
|
||||
if (break_on_cycles && ((timestampbase + (uint64)timestamp - total_cycles_base) > break_cycles_limit))
|
||||
BreakHit(BREAK_TYPE_CYCLES_EXCEED, true);
|
||||
BreakHit(BREAK_TYPE_CYCLES_EXCEED);
|
||||
if (break_on_instructions && (total_instructions > break_instructions_limit))
|
||||
BreakHit(BREAK_TYPE_INSTRUCTIONS_EXCEED, true);
|
||||
BreakHit(BREAK_TYPE_INSTRUCTIONS_EXCEED);
|
||||
|
||||
//if the current instruction is bad, and we are breaking on bad opcodes, then hit the breakpoint
|
||||
if(dbgstate.badopbreak && (size == 0))
|
||||
BreakHit(BREAK_TYPE_BADOP, true);
|
||||
BreakHit(BREAK_TYPE_BADOP);
|
||||
|
||||
//if we're stepping out, track the nest level
|
||||
if (dbgstate.stepout) {
|
||||
@@ -575,7 +717,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
//if we're stepping, then we'll always want to break
|
||||
if (dbgstate.step) {
|
||||
dbgstate.step = false;
|
||||
BreakHit(BREAK_TYPE_STEP, true);
|
||||
BreakHit(BREAK_TYPE_STEP);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -587,7 +729,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
if (diff<=0)
|
||||
{
|
||||
dbgstate.runline=false;
|
||||
BreakHit(BREAK_TYPE_STEP, true);
|
||||
BreakHit(BREAK_TYPE_STEP);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -596,33 +738,36 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
if ((watchpoint[64].address == _PC) && (watchpoint[64].flags)) {
|
||||
watchpoint[64].address = 0;
|
||||
watchpoint[64].flags = 0;
|
||||
BreakHit(BREAK_TYPE_STEP, true);
|
||||
BreakHit(BREAK_TYPE_STEP);
|
||||
return;
|
||||
}
|
||||
|
||||
romAddrPC = GetNesFileAddress(_PC);
|
||||
|
||||
brk_type = opbrktype[opcode[0]] | WP_X;
|
||||
|
||||
switch (opcode[0]) {
|
||||
//Push Ops
|
||||
case 0x08: //Fall to next
|
||||
case 0x48: stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
||||
case 0x48: debugLastAddress=stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
||||
//Pull Ops
|
||||
case 0x28: //Fall to next
|
||||
case 0x68: stackopstartaddr=stackopendaddr=X.S+1; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
||||
case 0x68: debugLastAddress=stackopstartaddr=stackopendaddr=X.S+1; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=_PC+1; break;
|
||||
//JSR (Includes return address - 1)
|
||||
case 0x20: stackopstartaddr=stackopendaddr=X.S-1; stackop=WP_W; StackAddrBackup = X.S; StackNextIgnorePC=(opcode[1]|opcode[2]<<8); break;
|
||||
//RTI (Includes processor status, and exact return address)
|
||||
case 0x40: stackopstartaddr=X.S+1; stackopendaddr=X.S+3; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=(GetMem(X.S+2|0x0100)|GetMem(X.S+3|0x0100)<<8); break;
|
||||
//RTS (Includes return address - 1)
|
||||
case 0x60: stackopstartaddr=X.S+1; stackopendaddr=X.S+2; stackop=WP_R; StackAddrBackup = X.S; StackNextIgnorePC=(GetMem(stackopstartaddr|0x0100)|GetMem(stackopendaddr|0x0100)<<8)+1; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
#define BREAKHIT(x) { if (CondForbidTest(x)) { breakHit = (x); goto STOPCHECKING; } }
|
||||
int breakHit = -1;
|
||||
for (i = 0; i < numWPs; i++)
|
||||
{
|
||||
// ################################## Start of SP CODE ###########################
|
||||
if ((watchpoint[i].flags & WP_E) && condition(&watchpoint[i]))
|
||||
if ((watchpoint[i].flags & WP_E))
|
||||
{
|
||||
// ################################## End of SP CODE ###########################
|
||||
if (watchpoint[i].flags & BT_P)
|
||||
{
|
||||
// PPU Mem breaks
|
||||
@@ -632,11 +777,11 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
if (watchpoint[i].endaddress)
|
||||
{
|
||||
if ((watchpoint[i].address <= PPUAddr) && (watchpoint[i].endaddress >= PPUAddr))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (watchpoint[i].address == PPUAddr)
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
}
|
||||
} else if (watchpoint[i].flags & BT_S)
|
||||
@@ -647,16 +792,16 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
if (watchpoint[i].endaddress)
|
||||
{
|
||||
if ((watchpoint[i].address <= PPU[3]) && (watchpoint[i].endaddress >= PPU[3]))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (watchpoint[i].address == PPU[3])
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
} else if ((watchpoint[i].flags & WP_W) && (A == 0x4014))
|
||||
{
|
||||
// Sprite DMA! :P
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
} else
|
||||
{
|
||||
@@ -667,12 +812,32 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
{
|
||||
if (((watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address <= A) && (watchpoint[i].endaddress >= A)) ||
|
||||
((watchpoint[i].flags & WP_X) && (watchpoint[i].address <= _PC) && (watchpoint[i].endaddress >= _PC)))
|
||||
BreakHit(i);
|
||||
} else
|
||||
BREAKHIT(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address == A)) ||
|
||||
((watchpoint[i].flags & WP_X) && (watchpoint[i].address == _PC)))
|
||||
BreakHit(i);
|
||||
if (watchpoint[i].flags & BT_R)
|
||||
{
|
||||
if ( (watchpoint[i].flags & WP_X) && (watchpoint[i].address == static_cast<unsigned int>(romAddrPC)) )
|
||||
{
|
||||
BREAKHIT(i);
|
||||
}
|
||||
//else if ( (watchpoint[i].flags & WP_R) && (watchpoint[i].address == A) )
|
||||
//{
|
||||
// BREAKHIT(i);
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (watchpoint[i].flags & (WP_R | WP_W)) && (watchpoint[i].address == A))
|
||||
{
|
||||
BREAKHIT(i);
|
||||
}
|
||||
else if ( (watchpoint[i].flags & WP_X) && (watchpoint[i].address == _PC) )
|
||||
{
|
||||
BREAKHIT(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
@@ -684,16 +849,16 @@ 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)
|
||||
{
|
||||
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (watchpoint[i].address == j)
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -704,40 +869,40 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
StackNextIgnorePC = 0xFFFF;
|
||||
} else
|
||||
{
|
||||
if ((X.S < StackAddrBackup) && (stackop==0))
|
||||
if (StackAddrBackup != -1 && (X.S < StackAddrBackup) && (stackop==0))
|
||||
{
|
||||
// Unannounced stack mem breaks
|
||||
// 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)
|
||||
{
|
||||
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (watchpoint[i].address == j)
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ((StackAddrBackup < X.S) && (stackop==0))
|
||||
} else if (StackAddrBackup != -1 && (StackAddrBackup < X.S) && (stackop==0))
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
if ((watchpoint[i].address <= j) && (watchpoint[i].endaddress >= j))
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
} else
|
||||
{
|
||||
if (watchpoint[i].address == j)
|
||||
BreakHit(i);
|
||||
BREAKHIT(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -746,13 +911,20 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
|
||||
|
||||
}
|
||||
}
|
||||
// ################################## Start of SP CODE ###########################
|
||||
}
|
||||
// ################################## End of SP CODE ###########################
|
||||
}
|
||||
} //loop across all breakpoints
|
||||
|
||||
STOPCHECKING:
|
||||
|
||||
//Update the stack address with the current one, now that changes have registered.
|
||||
//ZEROMUS THINKS IT MAKES MORE SENSE HERE
|
||||
StackAddrBackup = X.S;
|
||||
|
||||
if(breakHit != -1)
|
||||
BreakHit(i);
|
||||
|
||||
////Update the stack address with the current one, now that changes have registered.
|
||||
//StackAddrBackup = X.S;
|
||||
}
|
||||
//bbit edited: this is the end of the inserted code
|
||||
|
||||
@@ -781,9 +953,12 @@ void DebugCycle()
|
||||
size = opsize[opcode[0]];
|
||||
switch (size)
|
||||
{
|
||||
default:
|
||||
case 1: break;
|
||||
case 2:
|
||||
opcode[1] = GetMem(_PC + 1);
|
||||
break;
|
||||
case 0: // illegal instructions may have operands
|
||||
case 3:
|
||||
opcode[1] = GetMem(_PC + 1);
|
||||
opcode[2] = GetMem(_PC + 2);
|
||||
@@ -807,7 +982,6 @@ void DebugCycle()
|
||||
case 7: A = (opcode[1] | (opcode[2] << 8)) + _X; break;
|
||||
case 8: A = opcode[1] + _Y; break;
|
||||
}
|
||||
addressOfTheLastAccessedData = A;
|
||||
|
||||
if (numWPs || dbgstate.step || dbgstate.runline || dbgstate.stepout || watchpoint[64].flags || dbgstate.badopbreak || break_on_cycles || break_on_instructions || break_asap)
|
||||
breakpoint(opcode, A, size);
|
||||
@@ -815,10 +989,5 @@ void DebugCycle()
|
||||
if(debug_loggingCD)
|
||||
LogCDData(opcode, A, size);
|
||||
|
||||
#ifdef WIN32
|
||||
//This needs to be windows only or else the linux build system will fail since logging is declared in a
|
||||
//windows source file
|
||||
FCEUD_TraceInstruction(opcode, size);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
+14
-8
@@ -15,12 +15,15 @@
|
||||
#define BT_C 0x00 //break type, cpu mem
|
||||
#define BT_P 0x20 //break type, ppu mem
|
||||
#define BT_S 0x40 //break type, sprite mem
|
||||
#define BT_R 0x80 //break type, rom mem
|
||||
|
||||
#define BREAK_TYPE_STEP -1
|
||||
#define BREAK_TYPE_BADOP -2
|
||||
#define BREAK_TYPE_CYCLES_EXCEED -3
|
||||
#define BREAK_TYPE_INSTRUCTIONS_EXCEED -4
|
||||
#define BREAK_TYPE_LUA -5
|
||||
#define BREAK_TYPE_UNLOGGED_CODE -6
|
||||
#define BREAK_TYPE_UNLOGGED_DATA -7
|
||||
|
||||
//opbrktype is used to grab the breakpoint type that each instruction will cause.
|
||||
//WP_X is not used because ALL opcodes will have the execute bit set.
|
||||
@@ -46,21 +49,20 @@ static const uint8 opbrktype[256] = {
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16 address;
|
||||
uint16 endaddress;
|
||||
uint8 flags;
|
||||
// ################################## Start of SP CODE ###########################
|
||||
uint32 address;
|
||||
uint32 endaddress;
|
||||
uint16 flags;
|
||||
|
||||
Condition* cond;
|
||||
char* condText;
|
||||
char* desc;
|
||||
|
||||
// ################################## End of SP CODE ###########################
|
||||
} watchpointinfo;
|
||||
|
||||
//mbg merge 7/18/06 had to make this extern
|
||||
extern watchpointinfo watchpoint[65]; //64 watchpoints, + 1 reserved for step over
|
||||
|
||||
extern unsigned int debuggerPageSize;
|
||||
int getBank(int offs);
|
||||
int GetNesFileAddress(int A);
|
||||
int GetPRGAddress(int A);
|
||||
@@ -95,9 +97,12 @@ static INLINE int FCEUI_GetLoggingCD() { return debug_loggingCD; }
|
||||
extern int iaPC;
|
||||
extern uint32 iapoffset; //mbg merge 7/18/06 changed from int
|
||||
void DebugCycle();
|
||||
void BreakHit(int bp_num, bool force = false);
|
||||
bool CondForbidTest(int bp_num);
|
||||
void BreakHit(int bp_num);
|
||||
|
||||
extern bool break_asap;
|
||||
extern bool break_on_unlogged_code;
|
||||
extern bool break_on_unlogged_data;
|
||||
extern uint64 total_cycles_base;
|
||||
extern uint64 delta_cycles_base;
|
||||
extern bool break_on_cycles;
|
||||
@@ -115,8 +120,9 @@ extern void IncrementInstructionsCounters();
|
||||
|
||||
//internal variables that debuggers will want access to
|
||||
extern uint8 *vnapage[4],*VPage[8];
|
||||
extern uint8 PPU[4],PALRAM[0x20],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset;
|
||||
extern uint8 PPU[4],PALRAM[0x20],UPALRAM[3],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset;
|
||||
extern uint32 FCEUPPU_PeekAddress();
|
||||
extern uint8 READPAL_MOTHEROFALL(uint32 A);
|
||||
extern int numWPs;
|
||||
|
||||
///encapsulates the operational state of the debugger core
|
||||
@@ -166,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
|
||||
+5
-5
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -395,10 +395,10 @@ static int FixJoedChar(uint8 ch)
|
||||
int c = ch - 32;
|
||||
return (c < 0 || c > 98) ? 0 : c;
|
||||
}
|
||||
static int JoedCharWidth(uint8 ch)
|
||||
{
|
||||
return Font6x7[FixJoedChar(ch)*8];
|
||||
}
|
||||
//static int JoedCharWidth(uint8 ch)
|
||||
//{
|
||||
// return Font6x7[FixJoedChar(ch)*8];
|
||||
//}
|
||||
|
||||
char target[64][256];
|
||||
|
||||
|
||||
+28
-8
@@ -14,14 +14,16 @@ inline FILE *FCEUD_UTF8fopen(const std::string &n, const char *mode) { return FC
|
||||
EMUFILE_FILE* FCEUD_UTF8_fstream(const char *n, const char *m);
|
||||
inline EMUFILE_FILE* FCEUD_UTF8_fstream(const std::string &n, const char *m) { return FCEUD_UTF8_fstream(n.c_str(),m); }
|
||||
FCEUFILE* FCEUD_OpenArchiveIndex(ArchiveScanRecord& asr, std::string& fname, int innerIndex);
|
||||
FCEUFILE* FCEUD_OpenArchiveIndex(ArchiveScanRecord& asr, std::string& fname, int innerIndex, int* userCancel);
|
||||
FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename);
|
||||
FCEUFILE* FCEUD_OpenArchive(ArchiveScanRecord& asr, std::string& fname, std::string* innerFilename, int* userCancel);
|
||||
ArchiveScanRecord FCEUD_ScanArchive(std::string fname);
|
||||
|
||||
//mbg 7/23/06
|
||||
const char *FCEUD_GetCompilerString();
|
||||
|
||||
//This makes me feel dirty for some reason.
|
||||
void FCEU_printf(char *format, ...);
|
||||
void FCEU_printf( __FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 2 );
|
||||
#define FCEUI_printf FCEU_printf
|
||||
|
||||
//Video interface
|
||||
@@ -122,7 +124,8 @@ void FCEUI_SetVidSystem(int a);
|
||||
|
||||
//Set variables for NTSC(0) / PAL(1) / Dendy(2)
|
||||
//Dendy has PAL framerate and resolution, but ~NTSC timings, and has 50 dummy scanlines to force 50 fps
|
||||
void FCEUI_SetRegion(int region);
|
||||
void FCEUI_SetRegion(int region, int notify = 1);
|
||||
int FCEUI_GetRegion(void);
|
||||
|
||||
//Convenience function; returns currently emulated video system(0=NTSC, 1=PAL).
|
||||
int FCEUI_GetCurrentVidSystem(int *slstart, int *slend);
|
||||
@@ -140,7 +143,9 @@ void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall);
|
||||
|
||||
//Sets the base directory(save states, snapshots, etc. are saved in directories below this directory.
|
||||
void FCEUI_SetBaseDirectory(std::string const & dir);
|
||||
const char *FCEUI_GetBaseDirectory(void);
|
||||
|
||||
bool FCEUI_GetUserPaletteAvail(void);
|
||||
void FCEUI_SetUserPalette(uint8 *pal, int nEntries);
|
||||
|
||||
//Sets up sound code to render sound at the specified rate, in samples
|
||||
@@ -178,10 +183,16 @@ void FCEUD_MovieRecordTo(void);
|
||||
void FCEUD_MovieReplayFrom(void);
|
||||
void FCEUD_LuaRunFrom(void);
|
||||
|
||||
#ifdef _S9XLUA_H
|
||||
// lua engine
|
||||
void TaseditorAutoFunction(void);
|
||||
void TaseditorManualFunction(void);
|
||||
#endif
|
||||
|
||||
int32 FCEUI_GetDesiredFPS(void);
|
||||
void FCEUI_SaveSnapshot(void);
|
||||
void FCEUI_SaveSnapshotAs(void);
|
||||
void FCEU_DispMessage(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);
|
||||
@@ -189,16 +200,17 @@ int FCEUI_DecodeGG(const char *str, int *a, int *v, int *c);
|
||||
int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type);
|
||||
int FCEUI_DelCheat(uint32 which);
|
||||
int FCEUI_ToggleCheat(uint32 which);
|
||||
int FCEUI_GlobalToggleCheat(int global_enable);
|
||||
|
||||
int32 FCEUI_CheatSearchGetCount(void);
|
||||
void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a, uint8 last, uint8 current));
|
||||
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);
|
||||
@@ -242,12 +254,14 @@ 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);
|
||||
void FCEUI_FDSSelect(void);
|
||||
|
||||
int FCEUI_DatachSet(const uint8 *rcode);
|
||||
int FCEUI_DatachSet(uint8 *rcode);
|
||||
|
||||
///returns a flag indicating whether emulation is paused
|
||||
int FCEUI_EmulationPaused();
|
||||
@@ -259,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();
|
||||
@@ -318,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);
|
||||
|
||||
@@ -337,7 +356,8 @@ enum EFCEUI
|
||||
FCEUI_STOPMOVIE, FCEUI_RECORDMOVIE, FCEUI_PLAYMOVIE,
|
||||
FCEUI_OPENGAME, FCEUI_CLOSEGAME,
|
||||
FCEUI_TASEDITOR,
|
||||
FCEUI_RESET, FCEUI_POWER, FCEUI_PLAYFROMBEGINNING, FCEUI_EJECT_DISK, FCEUI_SWITCH_DISK, FCEUI_INSERT_COIN
|
||||
FCEUI_RESET, FCEUI_POWER, FCEUI_PLAYFROMBEGINNING, FCEUI_EJECT_DISK, FCEUI_SWITCH_DISK, FCEUI_INSERT_COIN, FCEUI_INPUT_BARCODE,
|
||||
FCEUI_TOGGLERECORDINGMOVIE, FCEUI_TRUNCATEMOVIE, FCEUI_INSERT1FRAME, FCEUI_DELETE1FRAME
|
||||
};
|
||||
|
||||
//checks whether an EFCEUI is valid right now
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import glob
|
||||
source_list = glob.glob('*.cpp') + glob.glob('*.c')
|
||||
|
||||
for x in range(len(source_list)):
|
||||
source_list[x] = 'drivers/common/' + source_list[x]
|
||||
Return('source_list')
|
||||
@@ -19,11 +19,11 @@
|
||||
*/
|
||||
|
||||
/****************************************************************/
|
||||
/* FCE Ultra */
|
||||
/* */
|
||||
/* This file contains code for parsing command-line */
|
||||
/* options. */
|
||||
/* */
|
||||
/* FCE Ultra */
|
||||
/* */
|
||||
/* This file contains code for parsing command-line */
|
||||
/* options. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -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);
|
||||
@@ -176,7 +198,7 @@ int AddToList(char *text, uint32 id)
|
||||
**/
|
||||
|
||||
typedef struct MENU {
|
||||
char *text;
|
||||
const char *text;
|
||||
void *action;
|
||||
int type; // 0 for menu, 1 for function.
|
||||
} MENU;
|
||||
@@ -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,14 +242,14 @@ 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);
|
||||
|
||||
printf("Value [%03d]: ",(unsigned int)V);
|
||||
printf("Value [%03u]: ",(unsigned int)V);
|
||||
V=Get8(V);
|
||||
|
||||
printf("Compare [%3d]: ",compare);
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -302,9 +325,9 @@ static void AddCheatParam(uint32 A, uint8 V)
|
||||
GetString(name,256);
|
||||
printf("Address [$%04x]: ",(unsigned int)A);
|
||||
A=GetH16(A);
|
||||
printf("Value [%03d]: ",(unsigned int)V);
|
||||
printf("Value [%03u]: ",(unsigned int)V);
|
||||
V=Get8(V);
|
||||
printf("Add cheat \"%s\" for address $%04x with value %03d?",name,(unsigned int)A,(unsigned int)V);
|
||||
printf("Add cheat \"%s\" for address $%04x with value %03u?",name,(unsigned int)A,(unsigned int)V);
|
||||
if(GetYN(0))
|
||||
{
|
||||
if(FCEUI_AddCheat(name,A,V,-1,0))
|
||||
@@ -320,15 +343,15 @@ 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;
|
||||
|
||||
if(compare>=0)
|
||||
sprintf(tmp,"%s $%04x:%03d:%03d - %s",s?"*":" ",(unsigned int)a,(unsigned int)v,compare,name);
|
||||
sprintf(tmp,"%s $%04x:%03u:%03d - %s",s?"*":" ",(unsigned int)a,(unsigned int)v,compare,name);
|
||||
else
|
||||
sprintf(tmp,"%s $%04x:%03d - %s",s?"*":" ",(unsigned int)a,(unsigned int)v,name);
|
||||
sprintf(tmp,"%s $%04x:%03u - %s",s?"*":" ",(unsigned int)a,(unsigned int)v,name);
|
||||
if(type==1)
|
||||
tmp[2]='S';
|
||||
ret=AddToList(tmp,lid);
|
||||
@@ -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);
|
||||
@@ -373,7 +399,7 @@ static void ResetSearch(void)
|
||||
static int srescallb(uint32 a, uint8 last, uint8 current, void *data)
|
||||
{
|
||||
char tmp[14];
|
||||
sprintf(tmp, "$%04x:%03d:%03d",(unsigned int)a,(unsigned int)last,(unsigned int)current);
|
||||
sprintf(tmp, "$%04x:%03u:%03u",(unsigned int)a,(unsigned int)last,(unsigned int)current);
|
||||
return(AddToList(tmp,a));
|
||||
}
|
||||
|
||||
@@ -392,7 +418,7 @@ static void ShowRes(void)
|
||||
}
|
||||
}
|
||||
|
||||
static int ShowShortList(char *moe[], int n, int def)
|
||||
static int ShowShortList(const char *moe[], int n, int def)
|
||||
{
|
||||
int x,c;
|
||||
int baa; //mbg merge 7/17/06 made to normal int
|
||||
@@ -405,7 +431,10 @@ static int ShowShortList(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]);
|
||||
@@ -430,7 +459,7 @@ static void DoSearch(void)
|
||||
{
|
||||
static int v1=0,v2=0;
|
||||
static int method=0;
|
||||
char *m[9]={"O==V1 && C==V2",
|
||||
const char *m[9]={"O==V1 && C==V2",
|
||||
"O==V1 && |O-C|==V2",
|
||||
"|O-C|==V2",
|
||||
"O!=C",
|
||||
@@ -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;
|
||||
|
||||
@@ -17,5 +17,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef COMMON_CHEAT_H
|
||||
#define COMMON_CHEAT_H
|
||||
void DoConsoleCheatConfig(void);
|
||||
#endif
|
||||
@@ -125,7 +125,7 @@ static void cfg_Save(FILE *fp)
|
||||
{
|
||||
if(it->first.size()>30 || it->second.size()>30)
|
||||
{
|
||||
int zzz=9;
|
||||
//int zzz=9;
|
||||
}
|
||||
fprintf(fp,"%s %s\n",it->first.c_str(),it->second.c_str());
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,16 +23,21 @@ void LoadFCEUConfig(const char *filename, CFGSTRUCT *cfgst);
|
||||
// isn't really hurting much.
|
||||
|
||||
// Single piece of data(integer).
|
||||
#define AC(x) { #x,&x,sizeof(x)}
|
||||
#define NAC(w,x) { #w,&x,sizeof(x)}
|
||||
#define AC(x) {#x,&x,sizeof(x)}
|
||||
#define NAC(w,x) {#w,&x,sizeof(x)}
|
||||
// VAC intruduced for backward compatibility with
|
||||
// configuration files of previous versions
|
||||
#define VAC(x,version) {#x "_V" #version,&x,sizeof(x)}
|
||||
|
||||
// Array.
|
||||
#define ACA(x) {#x,x,sizeof(x)}
|
||||
#define NACA(w,x) {#w,x,sizeof(x)}
|
||||
#define VACA(x,version) {#x "_V" #version,x,sizeof(x)}
|
||||
|
||||
// String(pointer) with automatic memory allocation.
|
||||
#define ACS(x) {#x,&x,0}
|
||||
#define NACS(w,x) {#w,&x,0}
|
||||
#define VACS(x,version) {#x "_V" #version,&x,0}
|
||||
|
||||
#define _DRIVERS_CONFIGH
|
||||
#endif
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#include "../../types.h"
|
||||
#include "configSys.h"
|
||||
@@ -444,6 +447,23 @@ Config::getOption(const std::string &name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Config::getOption(const std::string &name,
|
||||
bool *value) const
|
||||
{
|
||||
std::map<std::string, int>::const_iterator opt_i;
|
||||
|
||||
// confirm that the option exists
|
||||
opt_i = _intOptMap.find(name);
|
||||
if(opt_i == _intOptMap.end()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get the option
|
||||
(*value) = opt_i->second ? true : false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Config::getOption(const std::string &name,
|
||||
double *value) const
|
||||
@@ -559,6 +579,7 @@ Config::parse(int argc,
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
// try to read cfg.d/*
|
||||
std::string cfgd_dir_name = _dir + "/" + "cfg.d/";
|
||||
DIR *d;
|
||||
@@ -576,7 +597,7 @@ Config::parse(int argc,
|
||||
|
||||
// TODO 0 = good -1 = bad
|
||||
std::string fname = cfgd_dir_name + dir->d_name;
|
||||
printf("Loading auxilary configuration file at %s...\n", fname.c_str());
|
||||
printf("Loading auxiliary configuration file at %s...\n", fname.c_str());
|
||||
if (_loadFile(fname.c_str()) != 0)
|
||||
{
|
||||
printf("Failed to parse configuration at %s\n", fname.c_str());
|
||||
@@ -585,7 +606,9 @@ Config::parse(int argc,
|
||||
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
#else
|
||||
// FIXME TODO WIN32
|
||||
#endif
|
||||
// parse the arguments
|
||||
return _parseArgs(argc, argv);
|
||||
}
|
||||
@@ -618,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;
|
||||
@@ -633,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);
|
||||
@@ -648,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
|
||||
@@ -681,7 +704,7 @@ Config::_loadFile(const char* fname)
|
||||
|
||||
// close the file
|
||||
config.close();
|
||||
} catch(std::fstream::failure e) {
|
||||
} catch(std::fstream::failure &e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
@@ -700,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);
|
||||
@@ -718,26 +741,26 @@ 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));
|
||||
}
|
||||
|
||||
// close the file
|
||||
config.close();
|
||||
} catch(std::fstream::failure e)
|
||||
} catch(std::fstream::failure &e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
return -1;
|
||||
|
||||
@@ -69,6 +69,7 @@ public:
|
||||
int getOption(const std::string &, std::string *) const;
|
||||
int getOption(const std::string &, const char **) const;
|
||||
int getOption(const std::string &, int *) const;
|
||||
int getOption(const std::string &, bool *) const;
|
||||
int getOption(const std::string &, double *) const;
|
||||
|
||||
/**
|
||||
|
||||
@@ -242,15 +242,16 @@ void nes_ntsc_init( nes_ntsc_t* ntsc, nes_ntsc_setup_t const* setup, int bpp )
|
||||
|
||||
#ifndef NES_NTSC_NO_BLITTERS
|
||||
|
||||
void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, long in_row_width,
|
||||
int burst_phase, int emphasis, int in_width, int in_height, void* rgb_out, long out_pitch )
|
||||
void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, NES_NTSC_IN_T const* inputD, long in_row_width,
|
||||
int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch )
|
||||
{
|
||||
int chunk_count = (in_width - 1) / nes_ntsc_in_chunk;
|
||||
|
||||
for ( ; in_height; --in_height )
|
||||
{
|
||||
NES_NTSC_IN_T const* line_in = input;
|
||||
NES_NTSC_BEGIN_ROW( ntsc, burst_phase, nes_ntsc_black, nes_ntsc_black, NES_NTSC_ADJ_IN( *line_in ) );
|
||||
NES_NTSC_IN_T const* line_inD = inputD;
|
||||
NES_NTSC_BEGIN_ROW( ntsc, burst_phase, nes_ntsc_black, nes_ntsc_black, NES_NTSC_ADJ_IN( *line_in, *line_inD ) );
|
||||
nes_ntsc_out_t* restrict line_out = (nes_ntsc_out_t*) rgb_out;
|
||||
int n;
|
||||
++line_in;
|
||||
@@ -259,20 +260,21 @@ void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, long in_
|
||||
{
|
||||
|
||||
/* order of input and output pixels must not be altered */
|
||||
NES_NTSC_COLOR_IN( 0, NES_NTSC_ADJ_IN( line_in [0] ) );
|
||||
NES_NTSC_COLOR_IN( 0, NES_NTSC_ADJ_IN( line_in [0], line_inD [0] ) );
|
||||
NES_NTSC_RGB_OUT( 0, line_out [0], OutputDepth );
|
||||
NES_NTSC_RGB_OUT( 1, line_out [1], OutputDepth );
|
||||
|
||||
NES_NTSC_COLOR_IN( 1, NES_NTSC_ADJ_IN( line_in [1] ) );
|
||||
NES_NTSC_COLOR_IN( 1, NES_NTSC_ADJ_IN( line_in [1], line_inD [1] ) );
|
||||
NES_NTSC_RGB_OUT( 2, line_out [2], OutputDepth );
|
||||
NES_NTSC_RGB_OUT( 3, line_out [3], OutputDepth );
|
||||
|
||||
NES_NTSC_COLOR_IN( 2, NES_NTSC_ADJ_IN( line_in [2] ) );
|
||||
NES_NTSC_COLOR_IN( 2, NES_NTSC_ADJ_IN( line_in [2], line_inD [2] ) );
|
||||
NES_NTSC_RGB_OUT( 4, line_out [4], OutputDepth );
|
||||
NES_NTSC_RGB_OUT( 5, line_out [5], OutputDepth );
|
||||
NES_NTSC_RGB_OUT( 6, line_out [6], OutputDepth );
|
||||
|
||||
line_in += 3;
|
||||
line_inD += 3;
|
||||
line_out += rescale_out;
|
||||
}
|
||||
|
||||
@@ -293,6 +295,7 @@ void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, long in_
|
||||
|
||||
burst_phase = (burst_phase + 1) % nes_ntsc_burst_count;
|
||||
input += in_row_width;
|
||||
inputD += in_row_width;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,8 +61,8 @@ In_row_width is the number of pixels to get to the next input row. Emphasis is
|
||||
the emphasis bits to bitwise-OR with all pixels in the input data. Out_pitch
|
||||
is the number of *bytes* to get to the next output row. Output pixel format
|
||||
is set by NES_NTSC_OUT_DEPTH (defaults to 16-bit RGB). */
|
||||
void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* nes_in,
|
||||
long in_row_width, int burst_phase, int emphasis, int in_width,
|
||||
void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* nes_in, NES_NTSC_IN_T const* nes_inD,
|
||||
long in_row_width, int burst_phase, int in_width,
|
||||
int in_height, void* rgb_out, long out_pitch );
|
||||
|
||||
/* Number of output pixels written by blitter for given input width. Width might
|
||||
|
||||
@@ -21,7 +21,7 @@ if you enable emphasis above. */
|
||||
// CUSTOM: (XBuf uses bit 0x80, and has palettes above 0x3f for LUA)
|
||||
/* Each raw pixel input value is passed through this. You might want to mask
|
||||
the pixel index if you use the high bits as flags, etc. */
|
||||
#define NES_NTSC_ADJ_IN( in ) ((in & 0x3f) | emphasis)
|
||||
#define NES_NTSC_ADJ_IN( in, inD ) ((in & 0x3F) | (inD << 6))
|
||||
|
||||
/* For each pixel, this is the basic operation:
|
||||
output_color = color_palette [NES_NTSC_ADJ_IN( NES_NTSC_IN_T )] */
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
// os_util.cpp
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include "common/os_utils.h"
|
||||
//************************************************************
|
||||
int fceu_mkdir( const char *path )
|
||||
{
|
||||
int retval;
|
||||
#if defined(WIN32)
|
||||
retval = _mkdir(path);
|
||||
_chmod(path, 755);
|
||||
#else
|
||||
retval = mkdir(path, S_IRWXU);
|
||||
|
||||
if ( retval != 0 )
|
||||
{
|
||||
if ( errno == EEXIST )
|
||||
{
|
||||
//printf("Path Exists: '%s'\n", path);
|
||||
retval = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
//************************************************************
|
||||
int fceu_mkpath( const char *path )
|
||||
{
|
||||
int i, retval = 0;
|
||||
char p[512];
|
||||
|
||||
i=0;
|
||||
while ( path[i] != 0 )
|
||||
{
|
||||
if ( path[i] == '/' )
|
||||
{
|
||||
if ( i > 0 )
|
||||
{
|
||||
p[i] = 0;
|
||||
|
||||
retval = fceu_mkdir( p );
|
||||
|
||||
if ( retval )
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
p[i] = path[i]; i++;
|
||||
}
|
||||
p[i] = 0;
|
||||
|
||||
retval = fceu_mkdir( p );
|
||||
|
||||
return retval;
|
||||
}
|
||||
//************************************************************
|
||||
bool fceu_file_exists( const char *filepath )
|
||||
{
|
||||
#ifdef WIN32
|
||||
FILE *fp;
|
||||
fp = ::fopen( filepath, "r" );
|
||||
|
||||
if ( fp != NULL )
|
||||
{
|
||||
::fclose(fp);
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
struct stat sb;
|
||||
|
||||
if ( stat( filepath, &sb ) == 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
//************************************************************
|
||||
int msleep( int ms )
|
||||
{
|
||||
int ret = 0;
|
||||
#ifdef WIN32
|
||||
Sleep(ms);
|
||||
#else
|
||||
ret = usleep(ms*1000);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
//************************************************************
|
||||
@@ -0,0 +1,10 @@
|
||||
// os_utils.h
|
||||
//
|
||||
|
||||
int fceu_mkdir( const char *path );
|
||||
|
||||
int fceu_mkpath( const char *path );
|
||||
|
||||
bool fceu_file_exists( const char *filepath );
|
||||
|
||||
int msleep( int ms );
|
||||
@@ -65,9 +65,9 @@ static float *moire = NULL; // modulated signal
|
||||
const float phasex = (float) 5/18*2;
|
||||
const float phasey = (float) 1/ 6*2;
|
||||
const float pi = 3.14f;
|
||||
int palnotch = 90;
|
||||
int palnotch = 100;
|
||||
int palsaturation = 100;
|
||||
int palsharpness = 50;
|
||||
int palsharpness = 0;
|
||||
int palcontrast = 100;
|
||||
int palbrightness = 50;
|
||||
bool palupdate = 1;
|
||||
@@ -88,13 +88,13 @@ static int PAL_LUT(uint32 *buffer, int index, int x, int y)
|
||||
|
||||
static void CalculateShift(uint32 *CBM, int *cshiftr, int *cshiftl)
|
||||
{
|
||||
int a,x,z,y;
|
||||
int a,x,z;
|
||||
cshiftl[0]=cshiftl[1]=cshiftl[2]=-1;
|
||||
for(a=0;a<3;a++)
|
||||
{
|
||||
for(x=0,y=-1,z=0;x<32;x++)
|
||||
for(x=0,z=0;x<32;x++)
|
||||
{
|
||||
if(CBM[a]&(1<<x))
|
||||
if(CBM[a]&(1u<<x))
|
||||
{
|
||||
if(cshiftl[a]==-1) cshiftl[a]=x;
|
||||
z++;
|
||||
@@ -107,8 +107,6 @@ static void CalculateShift(uint32 *CBM, int *cshiftr, int *cshiftl)
|
||||
|
||||
int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int specfilt, int specfilteropt)
|
||||
{
|
||||
//paldeemphswap = 0; // determine this in FCEUPPU_SetVideoSystem() instead
|
||||
|
||||
// -Video Modes Tag-
|
||||
if(specfilt == 3) // NTSC 2x
|
||||
{
|
||||
@@ -208,6 +206,7 @@ int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int
|
||||
palrgb = (uint32 *)FCEU_dmalloc((256+512)*PAL_PHASES*sizeof(uint32));
|
||||
palrgb2 = (uint32 *)FCEU_dmalloc((256+512)*PAL_PHASES*sizeof(uint32));
|
||||
moire = (float *)FCEU_dmalloc( PAL_PHASES*sizeof(float));
|
||||
palupdate = 1;
|
||||
}
|
||||
|
||||
silt = specfilt;
|
||||
@@ -218,6 +217,11 @@ int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int
|
||||
return(0);
|
||||
|
||||
//allocate adequate room for 32bpp palette
|
||||
if ( palettetranslate )
|
||||
{
|
||||
free(palettetranslate);
|
||||
palettetranslate=NULL;
|
||||
}
|
||||
palettetranslate=(uint32*)FCEU_dmalloc(256*4 + 512*4);
|
||||
|
||||
if(!palettetranslate)
|
||||
@@ -234,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)
|
||||
@@ -255,10 +259,11 @@ void KillBlitToHigh(void)
|
||||
hq3x_Kill();
|
||||
else
|
||||
hq2x_Kill();
|
||||
FCEU_free(specbuf);
|
||||
specbuf=NULL;
|
||||
}
|
||||
if (nes_ntsc) {
|
||||
free(nes_ntsc);
|
||||
FCEU_free(nes_ntsc);
|
||||
nes_ntsc = NULL;
|
||||
}
|
||||
if (ntscblit) {
|
||||
@@ -461,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
|
||||
u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int xscale, int yscale)
|
||||
template<int SCALE> static u32 _ModernDeemphColorMap(const u8* src, const u8* srcbuf)
|
||||
{
|
||||
u8 pixel = *src;
|
||||
|
||||
@@ -471,8 +476,8 @@ u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int xscale, int yscale)
|
||||
int ofs = src-srcbuf;
|
||||
int xofs = ofs&255;
|
||||
int yofs = ofs>>8;
|
||||
if(xscale!=1) xofs /= xscale; //untested optimization
|
||||
if(yscale!=1) yofs /= yscale; //untested optimization
|
||||
xofs /= SCALE;
|
||||
yofs /= SCALE;
|
||||
ofs = xofs+yofs*256;
|
||||
|
||||
//find out which deemph bitplane value we're on
|
||||
@@ -480,11 +485,47 @@ u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int xscale, int yscale)
|
||||
|
||||
//if it was a deemph'd value, grab it from the deemph palette
|
||||
if(deemph != 0)
|
||||
color = palettetranslate[256+(pixel&0x3F)+deemph*64];
|
||||
{
|
||||
color = palettetranslate[256+(pixel&0x3F)+(deemph*64)];
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
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);
|
||||
else if(scale == 3) return _ModernDeemphColorMap<3>(src,srcbuf);
|
||||
else if(scale == 4) return _ModernDeemphColorMap<4>(src,srcbuf);
|
||||
else if(scale == 5) return _ModernDeemphColorMap<5>(src,srcbuf);
|
||||
else if(scale == 6) return _ModernDeemphColorMap<6>(src,srcbuf);
|
||||
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 { FCEU_abort("unhandled ModernDeemphColorMap scale"); return 0; }
|
||||
}
|
||||
|
||||
typedef u32 (*ModernDeemphColorMapFuncPtr)( const u8*, const u8* );
|
||||
|
||||
static ModernDeemphColorMapFuncPtr getModernDeemphColorMapFunc(int scale)
|
||||
{
|
||||
ModernDeemphColorMapFuncPtr ptr;
|
||||
|
||||
if(scale == 1) ptr = &_ModernDeemphColorMap<1>;
|
||||
else if(scale == 2) ptr = &_ModernDeemphColorMap<2>;
|
||||
else if(scale == 3) ptr = &_ModernDeemphColorMap<3>;
|
||||
else if(scale == 4) ptr = &_ModernDeemphColorMap<4>;
|
||||
else if(scale == 5) ptr = &_ModernDeemphColorMap<5>;
|
||||
else if(scale == 6) ptr = &_ModernDeemphColorMap<6>;
|
||||
else if(scale == 7) ptr = &_ModernDeemphColorMap<7>;
|
||||
else if(scale == 8) ptr = &_ModernDeemphColorMap<8>;
|
||||
else if(scale == 9) ptr = &_ModernDeemphColorMap<9>;
|
||||
else { FCEU_abort("unhandled ModernDeemphColorMap scale"); ptr = nullptr; }
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale)
|
||||
{
|
||||
int x,y;
|
||||
@@ -500,6 +541,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
{
|
||||
int mult;
|
||||
int base;
|
||||
ModernDeemphColorMapFuncPtr ModernDeemphColorMapFunc = NULL;
|
||||
|
||||
// -Video Modes Tag-
|
||||
if(silt == 2) mult = 2;
|
||||
@@ -508,7 +550,12 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
Blit8To8(src, specbuf8bpp, xr, yr, 256*mult, xscale, yscale, 0, silt);
|
||||
int mdcmxs = xscale*mult;
|
||||
int mdcmys = yscale*mult;
|
||||
|
||||
if(mdcmxs != mdcmys)
|
||||
abort();
|
||||
|
||||
ModernDeemphColorMapFunc = getModernDeemphColorMapFunc( mdcmxs );
|
||||
|
||||
xr *= mult;
|
||||
yr *= mult;
|
||||
xscale=yscale=1;
|
||||
@@ -523,7 +570,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
*(uint32 *)dest=ModernDeemphColorMap(src,specbuf8bpp,mdcmxs, mdcmys);
|
||||
*(uint32 *)dest=ModernDeemphColorMapFunc(src,specbuf8bpp);
|
||||
dest+=4;
|
||||
src++;
|
||||
}
|
||||
@@ -536,7 +583,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
uint32 tmp=ModernDeemphColorMap(src,specbuf8bpp,mdcmxs, mdcmys);
|
||||
uint32 tmp=ModernDeemphColorMapFunc(src,specbuf8bpp);
|
||||
*(uint8 *)dest=tmp;
|
||||
*((uint8 *)dest+1)=tmp>>8;
|
||||
*((uint8 *)dest+2)=tmp>>16;
|
||||
@@ -576,7 +623,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
{
|
||||
for(x=xr; x; x--)
|
||||
{
|
||||
*(uint32 *)dest = ModernDeemphColorMap(src,XBuf,1,1);
|
||||
*(uint32 *)dest = _ModernDeemphColorMap<1>(src,XBuf);
|
||||
dest += 4;
|
||||
src++;
|
||||
}
|
||||
@@ -587,9 +634,11 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
{
|
||||
uint32 *s = prescalebuf;
|
||||
uint32 *d = (uint32 *)destbackup; // use 32-bit pointers ftw
|
||||
int subpixel;
|
||||
int subpixel,yend;
|
||||
|
||||
for (y=0; y<yr*yscale; y++)
|
||||
yend = yr*yscale;
|
||||
|
||||
for (y=0; y<yend; y++)
|
||||
{
|
||||
int back = xr*(y%yscale>0); // bool as multiplier
|
||||
for (x=0; x<xr; x++)
|
||||
@@ -715,7 +764,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
newindex = (*src&63) | (deemph*64);
|
||||
newindex += 256;
|
||||
|
||||
if(GameInfo->type==GIT_NSF)
|
||||
if(GameInfo && GameInfo->type==GIT_NSF)
|
||||
{
|
||||
*d++ = palettetranslate[temp];
|
||||
*d++ = palettetranslate[temp];
|
||||
@@ -785,6 +834,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
lastindex = index;
|
||||
}
|
||||
}
|
||||
src += (256-xr);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -807,11 +857,13 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
switch(Bpp)
|
||||
{
|
||||
case 4:
|
||||
if ( nes_ntsc && GameInfo->type!=GIT_NSF) {
|
||||
if ( nes_ntsc && GameInfo && GameInfo->type!=GIT_NSF) {
|
||||
int outxr = 301;
|
||||
//if(xr == 282) outxr = 282; //hack for windows
|
||||
burst_phase ^= 1;
|
||||
nes_ntsc_blit( nes_ntsc, (unsigned char*)src, xr, burst_phase, (PPU[1] >> 5) << 6, xr, yr, ntscblit, (2*outxr) * Bpp );
|
||||
|
||||
u8* srcD = XDBuf + (src-XBuf); // get deemphasis buffer
|
||||
nes_ntsc_blit( nes_ntsc, (unsigned char*)src, (unsigned char*)srcD, xr, burst_phase, xr, yr, ntscblit, (2*outxr) * Bpp );
|
||||
|
||||
const uint8 *in = ntscblit + (Bpp * xscale);
|
||||
uint8 *out = dest;
|
||||
@@ -912,7 +964,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
//THE MAIN BLITTING CODEPATH (there may be others that are important)
|
||||
*(uint32 *)dest = ModernDeemphColorMap(src,XBuf,1,1);
|
||||
*(uint32 *)dest = _ModernDeemphColorMap<1>(src,XBuf);
|
||||
dest+=4;
|
||||
src++;
|
||||
}
|
||||
@@ -925,7 +977,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
uint32 tmp = ModernDeemphColorMap(src,XBuf,1,1);
|
||||
uint32 tmp = _ModernDeemphColorMap<1>(src,XBuf);
|
||||
*(uint8 *)dest=tmp;
|
||||
*((uint8 *)dest+1)=tmp>>8;
|
||||
*((uint8 *)dest+2)=tmp>>16;
|
||||
@@ -941,7 +993,7 @@ void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale,
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
*(uint16 *)dest = ModernDeemphColorMap(src,XBuf,1,1);
|
||||
*(uint16 *)dest = _ModernDeemphColorMap<1>(src,XBuf);
|
||||
dest+=2;
|
||||
src++;
|
||||
}
|
||||
|
||||
@@ -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 xscale, int yscale);
|
||||
u32 ModernDeemphColorMap(const u8* src, const u8* srcbuf, int scale);
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
# Fix compliation error about 'XKeysymToString' by linking X11 explicitly
|
||||
# Thanks Antonio Ospite!
|
||||
Import('env')
|
||||
config_string = 'pkg-config --cflags --libs x11'
|
||||
env.ParseConfig(config_string)
|
||||
Export('env')
|
||||
|
||||
source_list = Split(
|
||||
"""
|
||||
input.cpp
|
||||
config.cpp
|
||||
sdl.cpp
|
||||
sdl-joystick.cpp
|
||||
sdl-sound.cpp
|
||||
sdl-throttle.cpp
|
||||
sdl-video.cpp
|
||||
unix-netplay.cpp
|
||||
""")
|
||||
|
||||
Import('env')
|
||||
if 'GL' in env['LIBS']:
|
||||
source_list.append('sdl-opengl.cpp')
|
||||
|
||||
if env['GTK'] or env['GTK3']:
|
||||
source_list.append('gui.cpp')
|
||||
|
||||
source_list = ['drivers/sdl/' + source for source in source_list]
|
||||
Return('source_list')
|
||||
@@ -1,443 +0,0 @@
|
||||
#include "main.h"
|
||||
#include "throttle.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "../common/cheat.h"
|
||||
|
||||
#include "input.h"
|
||||
#include "dface.h"
|
||||
|
||||
#include "sdl.h"
|
||||
#include "sdl-video.h"
|
||||
#include "unix-netplay.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <csignal>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/**
|
||||
* Read a custom pallete from a file and load it into the core.
|
||||
*/
|
||||
int
|
||||
LoadCPalette(const std::string &file)
|
||||
{
|
||||
uint8 tmpp[192];
|
||||
FILE *fp;
|
||||
|
||||
if(!(fp = FCEUD_UTF8fopen(file.c_str(), "rb"))) {
|
||||
char errorMsg[256];
|
||||
strcpy(errorMsg, "Error loading custom palette from file: ");
|
||||
strcat(errorMsg, file.c_str());
|
||||
FCEUD_PrintError(errorMsg);
|
||||
return 0;
|
||||
}
|
||||
size_t result = fread(tmpp, 1, 192, fp);
|
||||
if(result != 192) {
|
||||
char errorMsg[256];
|
||||
strcpy(errorMsg, "Error loading custom palette from file: ");
|
||||
strcat(errorMsg, file.c_str());
|
||||
FCEUD_PrintError(errorMsg);
|
||||
return 0;
|
||||
}
|
||||
FCEUI_SetUserPalette(tmpp, result/3);
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the subdirectories used for saving snapshots, movies, game
|
||||
* saves, etc. Hopefully obsolete with new configuration system.
|
||||
*/
|
||||
static void
|
||||
CreateDirs(const std::string &dir)
|
||||
{
|
||||
char *subs[8]={"fcs","snaps","gameinfo","sav","cheats","movies","cfg.d"};
|
||||
std::string subdir;
|
||||
int x;
|
||||
|
||||
#if defined(WIN32) || defined(NEED_MINGW_HACKS)
|
||||
mkdir(dir.c_str());
|
||||
chmod(dir.c_str(), 755);
|
||||
for(x = 0; x < 6; x++) {
|
||||
subdir = dir + PSS + subs[x];
|
||||
mkdir(subdir.c_str());
|
||||
}
|
||||
#else
|
||||
mkdir(dir.c_str(), S_IRWXU);
|
||||
for(x = 0; x < 6; x++) {
|
||||
subdir = dir + PSS + subs[x];
|
||||
mkdir(subdir.c_str(), S_IRWXU);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to locate FCEU's application directory. This will
|
||||
* hopefully become obsolete once the new configuration system is in
|
||||
* place.
|
||||
*/
|
||||
static void
|
||||
GetBaseDirectory(std::string &dir)
|
||||
{
|
||||
char *home = getenv("HOME");
|
||||
if(home) {
|
||||
dir = std::string(home) + "/.fceux";
|
||||
} else {
|
||||
#ifdef WIN32
|
||||
home = new char[MAX_PATH + 1];
|
||||
GetModuleFileName(NULL, home, MAX_PATH + 1);
|
||||
|
||||
char *lastBS = strrchr(home,'\\');
|
||||
if(lastBS) {
|
||||
*lastBS = 0;
|
||||
}
|
||||
|
||||
dir = std::string(home);
|
||||
delete[] home;
|
||||
#else
|
||||
dir = "";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// returns a config structure with default options
|
||||
// also creates config base directory (ie: /home/user/.fceux as well as subdirs
|
||||
Config *
|
||||
InitConfig()
|
||||
{
|
||||
std::string dir, prefix;
|
||||
Config *config;
|
||||
|
||||
GetBaseDirectory(dir);
|
||||
|
||||
FCEUI_SetBaseDirectory(dir.c_str());
|
||||
CreateDirs(dir);
|
||||
|
||||
config = new Config(dir);
|
||||
|
||||
// sound options
|
||||
config->addOption('s', "sound", "SDL.Sound", 1);
|
||||
config->addOption("volume", "SDL.Sound.Volume", 150);
|
||||
config->addOption("trianglevol", "SDL.Sound.TriangleVolume", 256);
|
||||
config->addOption("square1vol", "SDL.Sound.Square1Volume", 256);
|
||||
config->addOption("square2vol", "SDL.Sound.Square2Volume", 256);
|
||||
config->addOption("noisevol", "SDL.Sound.NoiseVolume", 256);
|
||||
config->addOption("pcmvol", "SDL.Sound.PCMVolume", 256);
|
||||
config->addOption("soundrate", "SDL.Sound.Rate", 44100);
|
||||
config->addOption("soundq", "SDL.Sound.Quality", 1);
|
||||
config->addOption("soundrecord", "SDL.Sound.RecordFile", "");
|
||||
config->addOption("soundbufsize", "SDL.Sound.BufSize", 128);
|
||||
config->addOption("lowpass", "SDL.Sound.LowPass", 0);
|
||||
|
||||
config->addOption('g', "gamegenie", "SDL.GameGenie", 0);
|
||||
config->addOption("pal", "SDL.PAL", 0);
|
||||
config->addOption("frameskip", "SDL.Frameskip", 0);
|
||||
config->addOption("clipsides", "SDL.ClipSides", 0);
|
||||
config->addOption("nospritelim", "SDL.DisableSpriteLimit", 1);
|
||||
config->addOption("swapduty", "SDL.SwapDuty", 0);
|
||||
|
||||
// color control
|
||||
config->addOption('p', "palette", "SDL.Palette", "");
|
||||
config->addOption("tint", "SDL.Tint", 56);
|
||||
config->addOption("hue", "SDL.Hue", 72);
|
||||
config->addOption("ntsccolor", "SDL.NTSCpalette", 0);
|
||||
|
||||
// scanline settings
|
||||
config->addOption("slstart", "SDL.ScanLineStart", 0);
|
||||
config->addOption("slend", "SDL.ScanLineEnd", 239);
|
||||
|
||||
// video controls
|
||||
config->addOption('f', "fullscreen", "SDL.Fullscreen", 0);
|
||||
|
||||
// set x/y res to 0 for automatic fullscreen resolution detection (no change)
|
||||
config->addOption('x', "xres", "SDL.XResolution", 0);
|
||||
config->addOption('y', "yres", "SDL.YResolution", 0);
|
||||
config->addOption("SDL.LastXRes", 0);
|
||||
config->addOption("SDL.LastYRes", 0);
|
||||
config->addOption('b', "bpp", "SDL.BitsPerPixel", 32);
|
||||
config->addOption("doublebuf", "SDL.DoubleBuffering", 0);
|
||||
config->addOption("autoscale", "SDL.AutoScale", 1);
|
||||
config->addOption("keepratio", "SDL.KeepRatio", 1);
|
||||
config->addOption("xscale", "SDL.XScale", 1.0);
|
||||
config->addOption("yscale", "SDL.YScale", 1.0);
|
||||
config->addOption("xstretch", "SDL.XStretch", 0);
|
||||
config->addOption("ystretch", "SDL.YStretch", 0);
|
||||
config->addOption("noframe", "SDL.NoFrame", 0);
|
||||
config->addOption("special", "SDL.SpecialFilter", 0);
|
||||
config->addOption("showfps", "SDL.ShowFPS", 0);
|
||||
config->addOption("togglemenu", "SDL.ToggleMenu", 0);
|
||||
|
||||
// OpenGL options
|
||||
config->addOption("opengl", "SDL.OpenGL", 0);
|
||||
config->addOption("openglip", "SDL.OpenGLip", 0);
|
||||
config->addOption("SDL.SpecialFilter", 0);
|
||||
config->addOption("SDL.SpecialFX", 0);
|
||||
config->addOption("SDL.Vsync", 1);
|
||||
|
||||
// network play options - netplay is broken
|
||||
config->addOption("server", "SDL.NetworkIsServer", 0);
|
||||
config->addOption('n', "net", "SDL.NetworkIP", "");
|
||||
config->addOption('u', "user", "SDL.NetworkUsername", "");
|
||||
config->addOption('w', "pass", "SDL.NetworkPassword", "");
|
||||
config->addOption('k', "netkey", "SDL.NetworkGameKey", "");
|
||||
config->addOption("port", "SDL.NetworkPort", 4046);
|
||||
config->addOption("players", "SDL.NetworkPlayers", 1);
|
||||
|
||||
// input configuration options
|
||||
config->addOption("input1", "SDL.Input.0", "GamePad.0");
|
||||
config->addOption("input2", "SDL.Input.1", "GamePad.1");
|
||||
config->addOption("input3", "SDL.Input.2", "Gamepad.2");
|
||||
config->addOption("input4", "SDL.Input.3", "Gamepad.3");
|
||||
|
||||
// allow for input configuration
|
||||
config->addOption('i', "inputcfg", "SDL.InputCfg", InputCfg);
|
||||
|
||||
// display input
|
||||
config->addOption("inputdisplay", "SDL.InputDisplay", 0);
|
||||
|
||||
// enable / disable opposite directionals (left + right or up + down simultaneously)
|
||||
config->addOption("opposite-directionals", "SDL.Input.EnableOppositeDirectionals", 1);
|
||||
|
||||
// pause movie playback at frame x
|
||||
config->addOption("pauseframe", "SDL.PauseFrame", 0);
|
||||
config->addOption("recordhud", "SDL.RecordHUD", 1);
|
||||
config->addOption("moviemsg", "SDL.MovieMsg", 1);
|
||||
|
||||
// overwrite the config file?
|
||||
config->addOption("no-config", "SDL.NoConfig", 0);
|
||||
|
||||
config->addOption("autoresume", "SDL.AutoResume", 0);
|
||||
|
||||
// video playback
|
||||
config->addOption("playmov", "SDL.Movie", "");
|
||||
config->addOption("subtitles", "SDL.SubtitleDisplay", 1);
|
||||
|
||||
config->addOption("fourscore", "SDL.FourScore", 0);
|
||||
|
||||
config->addOption("nofscursor", "SDL.NoFullscreenCursor", 1);
|
||||
|
||||
#ifdef _S9XLUA_H
|
||||
// load lua script
|
||||
config->addOption("loadlua", "SDL.LuaScript", "");
|
||||
#endif
|
||||
|
||||
#ifdef CREATE_AVI
|
||||
config->addOption("videolog", "SDL.VideoLog", "");
|
||||
config->addOption("mute", "SDL.MuteCapture", 0);
|
||||
#endif
|
||||
|
||||
// auto load/save on gameload/close
|
||||
config->addOption("loadstate", "SDL.AutoLoadState", INVALID_STATE);
|
||||
config->addOption("savestate", "SDL.AutoSaveState", INVALID_STATE);
|
||||
|
||||
//TODO implement this
|
||||
config->addOption("periodicsaves", "SDL.PeriodicSaves", 0);
|
||||
|
||||
|
||||
#ifdef _GTK
|
||||
char* home_dir = getenv("HOME");
|
||||
// prefixed with _ because they are internal (not cli options)
|
||||
config->addOption("_lastopenfile", "SDL.LastOpenFile", home_dir);
|
||||
config->addOption("_laststatefrom", "SDL.LastLoadStateFrom", home_dir);
|
||||
config->addOption("_lastopennsf", "SDL.LastOpenNSF", home_dir);
|
||||
config->addOption("_lastsavestateas", "SDL.LastSaveStateAs", home_dir);
|
||||
config->addOption("_lastloadlua", "SDL.LastLoadLua", "");
|
||||
#endif
|
||||
|
||||
// fcm -> fm2 conversion
|
||||
config->addOption("fcmconvert", "SDL.FCMConvert", "");
|
||||
|
||||
// fm2 -> srt conversion
|
||||
config->addOption("ripsubs", "SDL.RipSubs", "");
|
||||
|
||||
// enable new PPU core
|
||||
config->addOption("newppu", "SDL.NewPPU", 0);
|
||||
|
||||
// quit when a+b+select+start is pressed
|
||||
config->addOption("4buttonexit", "SDL.ABStartSelectExit", 0);
|
||||
|
||||
// GamePad 0 - 3
|
||||
for(unsigned int i = 0; i < GAMEPAD_NUM_DEVICES; i++) {
|
||||
char buf[64];
|
||||
snprintf(buf, 20, "SDL.Input.GamePad.%d.", i);
|
||||
prefix = buf;
|
||||
|
||||
config->addOption(prefix + "DeviceType", DefaultGamePadDevice[i]);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < GAMEPAD_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix + GamePadNames[j], DefaultGamePad[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
// PowerPad 0 - 1
|
||||
for(unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++) {
|
||||
char buf[64];
|
||||
snprintf(buf, 20, "SDL.Input.PowerPad.%d.", i);
|
||||
prefix = buf;
|
||||
|
||||
config->addOption(prefix + "DeviceType", DefaultPowerPadDevice[i]);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < POWERPAD_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix +PowerPadNames[j], DefaultPowerPad[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
// QuizKing
|
||||
prefix = "SDL.Input.QuizKing.";
|
||||
config->addOption(prefix + "DeviceType", DefaultQuizKingDevice);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < QUIZKING_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix + QuizKingNames[j], DefaultQuizKing[j]);
|
||||
}
|
||||
|
||||
// HyperShot
|
||||
prefix = "SDL.Input.HyperShot.";
|
||||
config->addOption(prefix + "DeviceType", DefaultHyperShotDevice);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < HYPERSHOT_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix + HyperShotNames[j], DefaultHyperShot[j]);
|
||||
}
|
||||
|
||||
// Mahjong
|
||||
prefix = "SDL.Input.Mahjong.";
|
||||
config->addOption(prefix + "DeviceType", DefaultMahjongDevice);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < MAHJONG_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix + MahjongNames[j], DefaultMahjong[j]);
|
||||
}
|
||||
|
||||
// TopRider
|
||||
prefix = "SDL.Input.TopRider.";
|
||||
config->addOption(prefix + "DeviceType", DefaultTopRiderDevice);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < TOPRIDER_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix + TopRiderNames[j], DefaultTopRider[j]);
|
||||
}
|
||||
|
||||
// FTrainer
|
||||
prefix = "SDL.Input.FTrainer.";
|
||||
config->addOption(prefix + "DeviceType", DefaultFTrainerDevice);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < FTRAINER_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix + FTrainerNames[j], DefaultFTrainer[j]);
|
||||
}
|
||||
|
||||
// FamilyKeyBoard
|
||||
prefix = "SDL.Input.FamilyKeyBoard.";
|
||||
config->addOption(prefix + "DeviceType", DefaultFamilyKeyBoardDevice);
|
||||
config->addOption(prefix + "DeviceNum", 0);
|
||||
for(unsigned int j = 0; j < FAMILYKEYBOARD_NUM_BUTTONS; j++) {
|
||||
config->addOption(prefix + FamilyKeyBoardNames[j],
|
||||
DefaultFamilyKeyBoard[j]);
|
||||
}
|
||||
|
||||
// for FAMICOM microphone in pad 2 pad 1 didn't have it
|
||||
// Takeshi no Chousenjou uses it for example.
|
||||
prefix = "SDL.Input.FamicomPad2.";
|
||||
config->addOption("rp2mic", prefix + "EnableMic", 0);
|
||||
|
||||
// TODO: use a better data structure to store the hotkeys or something
|
||||
// improve this code overall in the future to make it
|
||||
// easier to maintain
|
||||
const int Hotkeys[HK_MAX] = {
|
||||
SDLK_F1, // cheat menu
|
||||
SDLK_F2, // bind state
|
||||
SDLK_F3, // load lua
|
||||
SDLK_F4, // toggleBG
|
||||
SDLK_F5, // save state
|
||||
SDLK_F6, // fds select
|
||||
SDLK_F7, // load state
|
||||
SDLK_F8, // fds eject
|
||||
SDLK_F6, // VS insert coin
|
||||
SDLK_F8, // VS toggle dipswitch
|
||||
SDLK_PERIOD, // toggle frame display
|
||||
SDLK_F10, // toggle subtitle
|
||||
SDLK_F11, // reset
|
||||
SDLK_F12, // screenshot
|
||||
SDLK_PAUSE, // pause
|
||||
SDLK_MINUS, // speed++
|
||||
SDLK_EQUALS, // speed--
|
||||
SDLK_BACKSLASH, //frame advnace
|
||||
SDLK_TAB, // turbo
|
||||
SDLK_COMMA, // toggle input display
|
||||
SDLK_q, // toggle movie RW
|
||||
SDLK_QUOTE, // toggle mute capture
|
||||
0, // quit // edit 10/11/11 - don't map to escape, it causes ugly things to happen to sdl. can be manually appended to config
|
||||
SDLK_DELETE, // frame advance lag skip
|
||||
SDLK_SLASH, // lag counter display
|
||||
SDLK_0, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5,
|
||||
SDLK_6, SDLK_7, SDLK_8, SDLK_9,
|
||||
SDLK_PAGEUP, // select state next
|
||||
SDLK_PAGEDOWN}; // select state prev
|
||||
|
||||
prefix = "SDL.Hotkeys.";
|
||||
for(int i=0; i < HK_MAX; i++)
|
||||
config->addOption(prefix + HotkeyStrings[i], Hotkeys[i]);
|
||||
// All mouse devices
|
||||
config->addOption("SDL.OekaKids.0.DeviceType", "Mouse");
|
||||
config->addOption("SDL.OekaKids.0.DeviceNum", 0);
|
||||
|
||||
config->addOption("SDL.Arkanoid.0.DeviceType", "Mouse");
|
||||
config->addOption("SDL.Arkanoid.0.DeviceNum", 0);
|
||||
|
||||
config->addOption("SDL.Shadow.0.DeviceType", "Mouse");
|
||||
config->addOption("SDL.Shadow.0.DeviceNum", 0);
|
||||
|
||||
config->addOption("SDL.Zapper.0.DeviceType", "Mouse");
|
||||
config->addOption("SDL.Zapper.0.DeviceNum", 0);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
void
|
||||
UpdateEMUCore(Config *config)
|
||||
{
|
||||
int ntsccol, ntsctint, ntschue, flag, region, start, end;
|
||||
std::string cpalette;
|
||||
|
||||
config->getOption("SDL.NTSCpalette", &ntsccol);
|
||||
config->getOption("SDL.Tint", &ntsctint);
|
||||
config->getOption("SDL.Hue", &ntschue);
|
||||
FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
|
||||
|
||||
config->getOption("SDL.Palette", &cpalette);
|
||||
if(cpalette.size()) {
|
||||
LoadCPalette(cpalette);
|
||||
}
|
||||
|
||||
config->getOption("SDL.PAL", ®ion);
|
||||
FCEUI_SetRegion(region);
|
||||
|
||||
config->getOption("SDL.GameGenie", &flag);
|
||||
FCEUI_SetGameGenie(flag ? 1 : 0);
|
||||
|
||||
config->getOption("SDL.Sound.LowPass", &flag);
|
||||
FCEUI_SetLowPass(flag ? 1 : 0);
|
||||
|
||||
config->getOption("SDL.DisableSpriteLimit", &flag);
|
||||
FCEUI_DisableSpriteLimitation(flag ? 1 : 0);
|
||||
|
||||
config->getOption("SDL.ScanLineStart", &start);
|
||||
config->getOption("SDL.ScanLineEnd", &end);
|
||||
|
||||
#if DOING_SCANLINE_CHECKS
|
||||
for(int i = 0; i < 2; x++) {
|
||||
if(srendlinev[x]<0 || srendlinev[x]>239) srendlinev[x]=0;
|
||||
if(erendlinev[x]<srendlinev[x] || erendlinev[x]>239) erendlinev[x]=239;
|
||||
}
|
||||
#endif
|
||||
|
||||
FCEUI_SetRenderedLines(start + 8, end - 8, start, end);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user