11 Commits

Author SHA1 Message Date
clobber 1b76eae51e Update to FCEUX 2.6.3 2022-12-16 17:49:38 -07:00
clobber 4db4639569 Update to FCEUX 2.6.2 2022-12-16 17:34:24 -07:00
clobber 1e9dc7ee26 Update to FCEUX 2.6.1 2022-12-16 17:28:16 -07:00
clobber e62374c88d Update to FCEUX 2.6.0 2022-12-16 17:23:14 -07:00
clobber c4ea492891 Update to FCEUX 2.5.0 2022-12-16 16:58:06 -07:00
clobber 4b460d1cb8 Update to FCEUX 2.4.0 2022-12-16 16:44:41 -07:00
clobber 14cfd5c93c Update to FCEUX 2.3.0 2022-12-16 16:32:10 -07:00
C.W. Betts 14a65ab35d Minor Xcode maintenance.
Remove the ~attic directory.
2021-03-22 01:02:58 -06:00
C.W. Betts 46d186d251 Poke the plists: get the development language from Xcode build. 2020-10-01 01:51:37 -06:00
C.W. Betts b1a06da5ba Fix locations of the system plugin headers.
Minor Xcode maintenance.
2020-10-01 01:26:41 -06:00
C.W. Betts 7bd6e5ea8b Update language resources.
This quiets warnings in newer Xcode releases.

Also update framework locations.
2020-01-07 16:36:20 -07:00
583 changed files with 8200 additions and 140712 deletions
Binary file not shown.
File diff suppressed because it is too large Load Diff
+3
View File
@@ -796,6 +796,7 @@ bool turbo = false;
bool swapDuty = 0; // some Famicom and NES clones had duty cycle bits swapped
int dendy = 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;}
@@ -832,6 +833,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
View File
@@ -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.2</string>
<string>2.6.3</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>
+2
View File
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */
+681
View File
@@ -0,0 +1,681 @@
include(GNUInstallDirs)
set( APP_NAME fceux)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
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 ( ${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 )
include_directories( ${SDL_INSTALL_PREFIX}/SDL2/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( 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-sign-compare -Wno-parentheses -Wno-unused-local-typedefs -fPIC )
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 )
# 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( 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}/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}/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}/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/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/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}/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
)
set(SRC_DRIVERS_COMMON
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/args.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/cheat.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/config.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/configSys.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/hq2x.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/common/hq3x.cpp
${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/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/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")
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}
${${Qt}Widgets_LIBRARIES}
${${Qt}Help_LIBRARIES}
${${Qt}OpenGL_LIBRARIES}
${${Qt}OpenGLWidgets_LIBRARIES}
${OPENGL_LDFLAGS}
${SDL2_LDFLAGS}
${MINIZIP_LDFLAGS} ${ZLIB_LIBRARIES}
${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)
-42
View File
@@ -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
View File
@@ -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;
+2
View File
@@ -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
View File
@@ -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);
}
+18 -11
View File
@@ -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);
+229 -229
View File
@@ -1,232 +1,232 @@
/* 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;
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->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);
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->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);
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->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
}
GameStateRestore = StateRestore;
AddExState(&StateRegs, ~0, 0, 0);
}
+2 -2
View File
@@ -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[] =
{
+27
View File
@@ -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"
+85
View File
@@ -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");
}
+11 -1
View File
@@ -52,15 +52,23 @@ static DECLFW(M225Write) {
}
static DECLFW(M225LoWrite) {
if (A & 0x800) {
prot[A & 0x03] = V;
}
}
static DECLFR(M225LoRead) {
return 0;
if (A & 0x800) {
return prot[A & 3] & 0x0F;
}
return X.DB;
}
static void M225Power(void) {
prg = 0;
chr = 0;
mode = 0;
mirr = 0;
Sync();
SetReadHandler(0x5000, 0x5FFF, M225LoRead);
SetWriteHandler(0x5000, 0x5FFF, M225LoWrite);
@@ -70,7 +78,9 @@ static void M225Power(void) {
static void M225Reset(void) {
prg = 0;
chr = 0;
mode = 0;
mirr = 0;
Sync();
}
+6 -5
View File
@@ -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;
+7 -1
View File
@@ -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();
}
+5
View File
@@ -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;
+76
View File
@@ -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);
}
+1 -2
View File
@@ -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;
-6
View File
@@ -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')
+20 -8
View File
@@ -237,13 +237,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 +304,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) {
@@ -347,6 +348,17 @@ static void M227Sync(void) {
uint32 p = ((latche >> 2) & 0x1F) + ((latche & 0x100) >> 3);
uint32 L = (latche >> 9) & 1;
// ok, according to nesdev wiki (refrenced to the nesdev dumping thread) there is a CHR write protection bit7.
// however, this bit clearly determined a specific PRG layout for some game but does not meant to have additional
// functionality. as I see from the menu code, it disables the chr writing before run an actual game.
// this fix here makes happy both waixing rpgs and multigame menus at once. can't veryfy it on a hardware
// but if I find some i'll definitly do this.
if ((latche & 0xF000) == 0xF000)
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0);
else
SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1);
if ((latche >> 7) & 1) {
if (S) {
setprg32(0x8000, p >> 1);
+274 -128
View File
@@ -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,12 @@ void Mapper16_Init(CartInfo *info) {
MapIRQHook = BandaiIRQHook;
info->battery = 1;
info->SaveGame[0] = x24c0x_data;
info->SaveGame[0] = x24c0x_data + 256;
info->SaveGameLen[0] = 256;
AddExState(x24c0x_data, 256, 0, "DATA");
AddExState(&x24c02StateRegs, ~0, 0, 0);
GameStateRestore = StateRestore;
AddExState(&x24c0xStateRegs, ~0, 0, 0);
AddExState(&StateRegs, ~0, 0, 0);
}
@@ -250,9 +336,9 @@ void Mapper159_Init(CartInfo *info) {
info->SaveGame[0] = x24c0x_data;
info->SaveGameLen[0] = 128;
AddExState(x24c0x_data, 128, 0, "DATA");
AddExState(&x24c01StateRegs, ~0, 0, 0);
GameStateRestore = StateRestore;
AddExState(&x24c0xStateRegs, ~0, 0, 0);
AddExState(&StateRegs, ~0, 0, 0);
}
@@ -307,7 +393,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 +418,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 +430,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 +479,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 +536,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 +573,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 +583,29 @@ 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->SaveGame[0] = x24c0x_data;
info->SaveGameLen[0] = 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);
}
+6 -6
View File
@@ -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);
+164
View File
@@ -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);
}
+270
View File
@@ -0,0 +1,270 @@
/* 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[] =
{
{ &reg, 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->SaveGame[0] = FLASHROM;
info->SaveGameLen[0] = 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);
}
}
+91 -24
View File
@@ -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,15 +17,60 @@
* 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)
* |+--------- 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
* ---- ----
* NPxP QQRx
* || | |||
* || | +++--- PRG offset for GNROM mode (PRG A16, A15, A14)
* || +------- 1: GNROM mode; 0: MMC3 mode
* || | (1: PRG A16...13 from QQ, L, R, CPU A14, A13 + CHR A16...10 from MMMM, PPU A12...10;
* || | 0: PRG A16...13 from MMC3 + CHR A16...A10 from MMC3 )
* |+-+------- Banking mode
* |+--------- "Weird MMC3 mode"
* +---------- Lockout (prevent further writes to these four registers, 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"
@@ -71,12 +116,7 @@ static void COOLBOYPW(uint32 A, uint8 V) {
// Last banks are first in this mode, ignored when MMC3_cmd&0x40
if ((EXPREGS[3] & 0x40) && (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;
@@ -115,10 +155,6 @@ static DECLFW(COOLBOYWrite) {
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);
}
@@ -126,21 +162,52 @@ static void COOLBOYReset(void) {
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);
SetWriteHandler(0x6000, 0x6fff, COOLBOYWrite);
}
static void MINDKIDSPower(void) {
GenMMC3Power();
EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
SetWriteHandler(0x5000, 0x5fff, COOLBOYWrite);
}
// Registers at $6xxx
void COOLBOY_Init(CartInfo *info) {
GenMMC3_Init(info, 512, 256, 8, 0);
GenMMC3_Init(info, 2048, 256, 8, 1);
pwrap = COOLBOYPW;
cwrap = COOLBOYCW;
info->Power = COOLBOYPower;
info->Reset = COOLBOYReset;
AddExState(EXPREGS, 4, 0, "EXPR");
}
}
// Registers at $5xxx
void MINDKIDS_Init(CartInfo *info) {
GenMMC3_Init(info, 2048, 256, 8, 1);
pwrap = COOLBOYPW;
cwrap = COOLBOYCW;
info->Power = MINDKIDSPower;
info->Reset = COOLBOYReset;
AddExState(EXPREGS, 4, 0, "EXPR");
}
// For NES 2.0 loader
void SMD132_SMD133_Init(CartInfo *info) {
switch (info->submapper)
{
case 0:
COOLBOY_Init(info);
break;
case 1:
MINDKIDS_Init(info);
break;
default:
FCEU_PrintError("Unknown submapper: #%d.", info->submapper);
break;
}
}
+540 -498
View File
File diff suppressed because it is too large Load Diff
+18 -18
View File
@@ -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;
}
+1 -1
View File
@@ -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);
+130 -131
View File
@@ -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())
+264
View File
@@ -0,0 +1,264 @@
/* 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;
static uint8 *WRAM = NULL;
static int kanji_pos, kanji_page, r40C0;
static int IRQa, IRQCount;
static DECLFW(MBWRAM) {
if (!(DRegs[3] & 0x10))
Page[A >> 11][A] = V;
}
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->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
AddExState(DRegs, 4, 0, "DREG");
AddExState(&lreset, 8, 1, "LRST");
AddExState(&Buffer, 1, 1, "BFFR");
AddExState(&BufferShift, 1, 1, "BFRS");
}
+177
View File
@@ -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");
}
+1
View File
@@ -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");
}
+59 -48
View File
@@ -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,24 @@ 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->SaveGame[0] = WRAM + NONBRAMSIZE;
info->SaveGameLen[0] = bram * 1024;
}
}
if (!chr) {
@@ -313,13 +325,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 +344,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 +364,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 +396,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);
}
+40 -3
View File
@@ -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) {
@@ -1353,3 +1363,30 @@ 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);
}
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;
}
+245 -62
View File
@@ -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];
}
}
@@ -194,6 +319,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 +328,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 +411,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))));
@@ -296,8 +436,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 +450,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 +459,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 +473,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 +536,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 +632,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 +895,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 +953,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 +971,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 +996,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 +1018,26 @@ 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;
if (info->ines2)
{
info->SaveGameLen[0] = 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)
info->SaveGameLen[0] = 8192;
else if(wsize == 64)
info->SaveGameLen[0] = 64*1024;
else
info->SaveGameLen[0] = 32768;
}
}
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);
}
+28 -4
View File
@@ -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,6 +422,8 @@ 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);
@@ -422,6 +445,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);
}
+30
View File
@@ -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,17 @@ 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->SaveGame[0] = WRAM;
info->SaveGameLen[0] = WRAMSIZE;
}
}
}
+3
View File
@@ -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"
+3 -1
View File
@@ -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);
}
+44 -28
View File
@@ -40,38 +40,38 @@ static uint16 latcha;
static uint8 *flashdata;
static uint32 *flash_write_count;
static uint8 *FlashPage[32];
static uint32 *FlashWriteCountPage[32];
static uint8 flashloaded = false;
//static uint32 *FlashWriteCountPage[32];
//static uint8 flashloaded = false;
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;
}
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 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)
@@ -240,8 +240,24 @@ void UNROM512_Init(CartInfo *info) {
chrram_mask = 0x20;
else
chrram_mask = 0x60;
SetupCartMirroring(info->mirror,(info->mirror>=MI_0)?0:1,0);
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;
}
bus_conflict = !info->battery;
latcheinit = 0;
WLSync = UNROM512LSync;
@@ -266,4 +282,4 @@ void UNROM512_Init(CartInfo *info) {
}
AddExState(&latche, 1, 0, "LATC");
AddExState(&bus_conflict, 1, 0, "BUSC");
}
}
+49 -92
View File
@@ -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 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" },
{ &regcmd, 1, "CMDR" },
{ &irqcmd, 1, "CMDI" },
{ &mirr, 1, "MIRR" },
@@ -61,15 +62,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 +74,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
@@ -126,61 +120,17 @@ static DECLFW(VRC24Write) {
}
}
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) {
@@ -210,26 +160,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;
@@ -247,23 +179,48 @@ void VRC24_Init(CartInfo *info) {
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 -120
View File
@@ -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);
@@ -219,7 +255,10 @@ void Mapper190_Init(CartInfo *info) {
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->SaveGameLen[0] = WRAMSIZE;
}
AddExState(&StateRegs, ~0, 0, 0);
+1 -1
View File
@@ -86,7 +86,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);
}
+7
View File
@@ -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;
}
+7
View File
@@ -1,3 +1,6 @@
#ifndef CART_H
#define CART_H
typedef struct {
// Set by mapper/board code:
void (*Power)(void);
@@ -25,6 +28,8 @@ typedef struct {
// other code in the future.
} CartInfo;
extern CartInfo *currCartInfo;
void FCEU_SaveGameSave(CartInfo *LocalHWInfo);
void FCEU_LoadGameSave(CartInfo *LocalHWInfo);
void FCEU_ClearGameSave(CartInfo *LocalHWInfo);
@@ -98,3 +103,5 @@ void FCEU_GeniePower(void);
bool FCEU_OpenGenie(void);
void FCEU_CloseGenie(void);
void FCEU_KillGenie(void);
#endif
+289 -296
View File
@@ -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] = { 0 };
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,98 @@ 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 int 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 int 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))))
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;
temp->name = strcpy((char*) FCEU_dmalloc(strlen(name) + 1), name);
temp->addr = addr;
temp->val = val;
temp->status = status;
temp->compare = compare;
temp->type = type;
temp->next = 0;
if(cheats)
{
cheatsl->next=temp;
cheatsl=temp;
cheatsl->next = temp;
cheatsl = temp;
}
else
cheats=cheatsl=temp;
cheats = cheatsl = temp;
return(1);
return (1);
}
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 +202,121 @@ 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);
else
fprintf(fp, "%04x:%02x:%s\n", next->addr, next->val, next->name);
if (release) free(next->name);
struct CHEATF *t = next;
next = next->next;
if (release) free(t);
}
}
void FCEU_FlushGameCheats(FILE *override, int nosave)
{
if(CheatComp)
@@ -313,7 +349,6 @@ void FCEU_FlushGameCheats(FILE *override, int nosave)
if(cheats)
{
struct CHEATF *next=cheats;
FILE *fp;
if(override)
@@ -323,28 +358,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 +379,13 @@ 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;
if(!AddCheatEntry(name, addr, val, compare, 1, type))
return 0;
savecheats = 1;
RebuildSubCheats();
return(1);
return 1;
}
int FCEUI_DelCheat(uint32 which)
@@ -566,7 +570,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);
@@ -598,43 +602,40 @@ int FCEUI_DecodePAR(const char *str, int *a, int *v, int *c, int *type)
int FCEUI_SetCheat(uint32 which, const char *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);
}
if((t = (char *)realloc(next->name, strlen(name) + 1)))
strcpy(next->name = t, name);
else
return(0);
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;
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 +660,14 @@ int FCEUI_ToggleCheat(uint32 which)
return(-1);
}
int FCEUI_GlobalToggleCheat(int global_enabled)
{
int _numsubcheats = numsubcheats;
globalCheatDisabled = !global_enabled;
RebuildSubCheats();
return _numsubcheats != numsubcheats;
}
static int InitCheatComp(void)
{
uint32 x;
@@ -741,7 +750,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 +759,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 +813,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 +885,75 @@ 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;
if ( cur->name )
{
free(cur->name);
}
free(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
}
+60 -2
View File
@@ -1,12 +1,70 @@
#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);
typedef struct {
uint16 addr;
uint8 val;
int compare;
readfunc PrevRead;
} CHEATF_SUBFAST;
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;
};
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
+62 -11
View File
@@ -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,8 +51,9 @@
#include <cassert>
#include <cctype>
// hack: this address is used by 'T' condition
uint16 addressOfTheLastAccessedData = 0;
uint16 debugLastAddress = 0; // used by 'T' and 'R' conditions
uint8 debugLastOpcode; // used to evaluate 'W' condition
// Next non-whitespace character in string
char next;
@@ -137,7 +139,7 @@ int isFlag(char c)
// Determines if a character is a register
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
@@ -152,6 +154,18 @@ int isDataBank(char c)
return c == 'T';
}
// Determines if a character is for value read
int isValueRead(char c)
{
return c == 'R';
}
// Determines if a character is for value write
int isValueWrite(char c)
{
return c == 'W';
}
// Reads a hexadecimal number from str
int getNumber(unsigned int* number, const char** str)
{
@@ -180,10 +194,10 @@ Condition* Parentheses(const char** str, Condition* c, char openPar, char closeP
{
scan(str);
c->lhs = Connect(str);
if (!c) return 0;
c->lhs = Connect(str);
if (next == closePar)
{
scan(str);
@@ -272,6 +286,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;
@@ -352,9 +400,12 @@ Condition* Term(const char** str)
Condition* t1;
Condition* mid;
t = (Condition*)FCEU_dmalloc(sizeof(Condition));
if (!t)
return NULL;
t = (Condition*)FCEU_dmalloc(sizeof(Condition));
if (!t)
{
return NULL;
}
memset(t, 0, sizeof(Condition));
+5 -1
View File
@@ -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
{
+15 -6
View File
@@ -13,15 +13,20 @@
static char *aboutString = 0;
#ifndef FCEUX_BUILD_TIMESTAMP
#define FCEUX_BUILD_TIMESTAMP __TIME__ " " __DATE__
#endif
// 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, mjbudd77, feos\n"
"\n"
"Current Contributors:\n"
"CaH4e3, rainwarrior\n"
"CaH4e3, rainwarrior, owomomo, punkrockguy318\n"
"\n"
"Past Contributors:\n"
"xhainingx, gocha, AnS\n"
@@ -40,13 +45,17 @@ 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) return aboutString;
const char *compilerString = FCEUD_GetCompilerString();
@@ -54,6 +63,6 @@ char *FCEUI_GetAboutString() {
if (!(aboutString = (char*)FCEU_dmalloc(strlen(aboutTemplate) + strlen(compilerString) + 1)))
return NULL;
sprintf(aboutString,"%s%s",aboutTemplate,compilerString);
sprintf(aboutString,"%s%s",aboutTemplate,compilerString);
return aboutString;
}
View File
+229 -95
View File
@@ -22,7 +22,7 @@ int offsetStringToInt(unsigned int type, const char* offsetBuffer)
{
int offset = -1;
if (sscanf(offsetBuffer,"%4X",&offset) == EOF)
if (sscanf(offsetBuffer,"%7X",(unsigned int *)&offset) == EOF)
{
return -1;
}
@@ -35,14 +35,24 @@ int offsetStringToInt(unsigned int type, const char* offsetBuffer)
{
return offset & 0x00FF;
}
else if (type & BT_R)
{
return offset;
}
else // BT_C
{
if (GameInfo->type == GIT_NSF) { //NSF Breakpoint keywords
int type = GIT_CART;
if (GameInfo)
{
type = GameInfo->type;
}
if (type == GIT_NSF) { //NSF Breakpoint keywords
if (strcmp(offsetBuffer,"LOAD") == 0) return (NSFHeader.LoadAddressLow | (NSFHeader.LoadAddressHigh<<8));
if (strcmp(offsetBuffer,"INIT") == 0) return (NSFHeader.InitAddressLow | (NSFHeader.InitAddressHigh<<8));
if (strcmp(offsetBuffer,"PLAY") == 0) return (NSFHeader.PlayAddressLow | (NSFHeader.PlayAddressHigh<<8));
}
else if (GameInfo->type == GIT_FDS) { //FDS Breakpoint keywords
else if (type == GIT_FDS) { //FDS Breakpoint keywords
if (strcmp(offsetBuffer,"NMI1") == 0) return (GetMem(0xDFF6) | (GetMem(0xDFF7)<<8));
if (strcmp(offsetBuffer,"NMI2") == 0) return (GetMem(0xDFF8) | (GetMem(0xDFF9)<<8));
if (strcmp(offsetBuffer,"NMI3") == 0) return (GetMem(0xDFFA) | (GetMem(0xDFFB)<<8));
@@ -56,7 +66,7 @@ int offsetStringToInt(unsigned int type, const char* offsetBuffer)
}
}
return offset;
return offset & 0xFFFF;
}
// Returns the value of a given type or register
@@ -77,6 +87,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;
@@ -193,6 +204,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 +221,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;
}
}
/**
@@ -309,6 +339,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 +390,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 +417,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 +431,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 +450,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 +477,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 +512,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 +600,70 @@ 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, j, romAddrPC;
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 +682,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 +694,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 +703,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 +742,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 +757,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 +777,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 == 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
{
@@ -689,11 +819,11 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
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,7 +834,7 @@ 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
@@ -715,15 +845,15 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
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)
@@ -733,11 +863,11 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) {
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 +876,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 +918,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 +947,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 +954,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
}
+13 -7
View File
@@ -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
+4 -4
View File
@@ -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];
+18 -5
View File
@@ -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(const char *format, ...);
#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(const char *format, int disppos, ...);
#define FCEUI_DispMessage FCEU_DispMessage
int FCEUI_DecodePAR(const char *code, int *a, int *v, int *c, int *type);
@@ -189,6 +200,7 @@ 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));
@@ -247,7 +259,7 @@ void FCEUI_FDSInsert(void); //mbg merge 7/17/06 changed to void fn(void) to make
//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();
@@ -337,7 +349,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
-6
View File
@@ -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')
+5 -5
View File
@@ -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>
+9 -9
View File
@@ -176,7 +176,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;
@@ -226,7 +226,7 @@ static void ModifyCheat(int num)
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);
@@ -302,9 +302,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))
@@ -326,9 +326,9 @@ static int clistcallb(char *name, uint32 a, uint8 v, int compare, int s, int typ
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);
@@ -373,7 +373,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 +392,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
@@ -430,7 +430,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",
+3 -1
View File
@@ -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
+1 -1
View File
@@ -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());
}
+7 -2
View File
@@ -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
+27 -4
View File
@@ -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);
}
@@ -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;
}
@@ -737,7 +760,7 @@ Config::save()
// close the file
config.close();
} catch(std::fstream::failure e)
} catch(std::fstream::failure &e)
{
std::cerr << e.what() << std::endl;
return -1;
+1
View File
@@ -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;
/**
+9 -6
View File
@@ -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;
}
}
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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 )] */
+101
View File
@@ -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;
}
//************************************************************
+10
View File
@@ -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 );
+74 -22
View File
@@ -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)
@@ -255,6 +259,7 @@ void KillBlitToHigh(void)
hq3x_Kill();
else
hq2x_Kill();
free(specbuf);
specbuf=NULL;
}
if (nes_ntsc) {
@@ -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(u8* src, 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(u8* src, 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 { abort(); return 0; }
}
typedef u32 (*ModernDeemphColorMapFuncPtr)( u8*, u8* );
static ModernDeemphColorMapFuncPtr getModernDeemphColorMapFunc(int scale)
{
ModernDeemphColorMapFuncPtr ptr = NULL;
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 { abort(); ptr = NULL; }
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++;
}
+1 -1
View File
@@ -29,4 +29,4 @@ void Blit32to16(uint32 *src, uint16 *dest, int xr, int yr, int dpitch,
int shiftr[3], int shiftl[3]);
u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int xscale, int yscale);
u32 ModernDeemphColorMap(u8* src, u8* srcbuf, int scale);
-28
View File
@@ -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')
-443
View File
@@ -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", &region);
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);
}
-57
View File
@@ -1,57 +0,0 @@
#ifndef CONFIG_H_HF128
#define CONFIG_H_HF128
#include "../common/configSys.h"
Config *InitConfig(void);
void UpdateEMUCore(Config *);
int LoadCPalette(const std::string &file);
// hotkey definitions
// TODO: encapsulate this in an improved data structure
enum HOTKEY { HK_CHEAT_MENU=0, HK_BIND_STATE, HK_LOAD_LUA, HK_TOGGLE_BG,
HK_SAVE_STATE, HK_FDS_SELECT, HK_LOAD_STATE, HK_FDS_EJECT ,
HK_VS_INSERT_COIN, HK_VS_TOGGLE_DIPSWITCH,
HK_TOGGLE_FRAME_DISPLAY, HK_TOGGLE_SUBTITLE, HK_RESET, HK_SCREENSHOT,
HK_PAUSE, HK_DECREASE_SPEED, HK_INCREASE_SPEED, HK_FRAME_ADVANCE, HK_TURBO,
HK_TOGGLE_INPUT_DISPLAY, HK_MOVIE_TOGGLE_RW, HK_MUTE_CAPTURE, HK_QUIT,
HK_FA_LAG_SKIP, HK_LAG_COUNTER_DISPLAY,
HK_SELECT_STATE_0, HK_SELECT_STATE_1, HK_SELECT_STATE_2, HK_SELECT_STATE_3,
HK_SELECT_STATE_4, HK_SELECT_STATE_5, HK_SELECT_STATE_6, HK_SELECT_STATE_7,
HK_SELECT_STATE_8, HK_SELECT_STATE_9,
HK_SELECT_STATE_NEXT, HK_SELECT_STATE_PREV, HK_VOLUME_DOWN, HK_VOLUME_UP,
HK_MAX};
static const char* HotkeyStrings[HK_MAX] = {
"CheatMenu",
"BindState",
"LoadLua",
"ToggleBG",
"SaveState",
"FDSSelect",
"LoadState",
"FDSEject",
"VSInsertCoin",
"VSToggleDip",
"MovieToggleFrameDisplay",
"SubtitleDisplay",
"Reset",
"Screenshot",
"Pause",
"DecreaseSpeed",
"IncreaseSpeed",
"FrameAdvance",
"Turbo",
"ToggleInputDisplay",
"ToggleMovieRW",
"MuteCapture",
"Quit",
"FrameAdvanceLagSkip",
"LagCounterDisplay",
"SelectState0", "SelectState1", "SelectState2", "SelectState3",
"SelectState4", "SelectState5", "SelectState6", "SelectState7",
"SelectState8", "SelectState9", "SelectStateNext", "SelectStatePrev",
"VolumeDown", "VolumeUp" };
#endif
-37
View File
@@ -1,37 +0,0 @@
#include "../common/args.h"
#include "../common/config.h"
#include "input.h"
extern CFGSTRUCT DriverConfig[];
extern ARGPSTRUCT DriverArgs[];
void DoDriverArgs(void);
int InitSound();
void WriteSound(int32 *Buffer, int Count);
int KillSound(void);
uint32 GetMaxSound(void);
uint32 GetWriteSound(void);
void SilenceSound(int s); /* DOS and SDL */
int InitJoysticks(void);
int KillJoysticks(void);
uint32 *GetJSOr(void);
int InitVideo(FCEUGI *gi);
int KillVideo(void);
void BlitScreen(uint8 *XBuf);
void LockConsole(void);
void UnlockConsole(void);
void ToggleFS(); /* SDL */
int LoadGame(const char *path);
//int CloseGame(void);
void Giggles(int);
void DoFun(void);
int FCEUD_NetworkConnect(void);
File diff suppressed because it is too large Load Diff
-88
View File
@@ -1,88 +0,0 @@
// gui.h
//
// Copyright 2009 Lukas <lukas@LTx3-64>
//
// 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.
#ifndef FCEUX_GUI_H
#define FCEUX_GUI_H
#define GTK
#ifdef _GTK
#include <gtk/gtk.h>
#endif
extern GtkWidget* MainWindow;
extern GtkWidget* evbox;
extern GtkRadioAction* stateSlot;
extern int GtkMouseData[3];
extern bool gtkIsStarted;
int InitGTKSubsystem(int argc, char** argv);
void pushOutputToGTK(const char* str);
void showGui(bool b);
bool checkGTKVersion(int major_required, int minor_required);
int configHotkey(char* hotkeyString);
void resetVideo();
void openPaletteConfig();
void openNetworkConfig();
void flushGtkEvents();
void openHotkeyConfig();
void openGamepadConfig();
void resizeGtkWindow();
#ifdef OPENGL
void setGl(GtkWidget* w, gpointer p);
void setDoubleBuffering(GtkWidget* w, gpointer p);
#endif
void openVideoConfig();
void openSoundConfig();
void quit ();
void openAbout ();
void emuReset ();
void hardReset ();
void enableFullscreen ();
void recordMovie();
void recordMovieAs ();
void loadMovie ();
#ifdef _S9XLUA_H
void loadLua ();
#endif
void loadFdsBios ();
void enableGameGenie(int enabled);
void loadGameGenie ();
void loadNSF ();
void closeGame();
void loadGame ();
void saveStateAs();
void loadStateFrom();
void quickLoad();
void quickSave();
unsigned short GDKToSDLKeyval(int gdk_key);
int InitGTKSubsystem(int argc, char** argv);
#endif // ifndef FCEUX_GUI_H
-55
View File
@@ -1,55 +0,0 @@
/* XPM */
static const char * icon_xpm[] = {
"32 32 20 1",
" c None",
". c #040204",
"+ c #84A284",
"@ c #C42204",
"# c #8482C4",
"$ c #FCFEFC",
"% c #848284",
"& c #648284",
"* c #646284",
"= c #444244",
"- c #A4A284",
"; c #C4A284",
"> c #C48284",
", c #A4CAF4",
"' c #244244",
") c #444204",
"! c #442204",
"~ c #446244",
"{ c #646244",
"] c #644244",
" ",
" ........ ",
" ............... ",
" ........................ ",
" ...........................+ ",
" ............@@..@@........... ",
" .#............@@............$$ ",
" .##..........@@.@.....$$%%%%$$ ",
" &...........@....@$$$$$$%%&%$$ ",
" *&...............$$$$$$$%%&%$$ ",
" =&*.......-;;>;...$$,$$$%**&.. ",
" '&&..............$$,,,%=)!~.. ",
" ~&&............-%%##%*.~'=%& ",
" *&&.....+%%****&&%%&*.&!!' ",
" **&%&***********&&&*~{'= ",
" ********=**~**~**~ ",
" *****~******] ",
" **~***]' ",
" ~]== ",
" ",
" ..... .... .... .. ..@@ @@",
" ..... .... .... .. ..@@@ @@@",
" .. .. .. .. .. @@@ @@@ ",
" .... .. .. .. .. @@@@@@ ",
" .... .. ... .. .. @@@@ ",
" .. .. ... .. .. @@@@ ",
" .. .. .. .. .. @@@@@@ ",
" .. .. .. .. .. @@@ @@@ ",
" .. .... .... .....@@@ @@@",
" .. .... .... ... @@ @@",
" ",
" "};
File diff suppressed because it is too large Load Diff
-60
View File
@@ -1,60 +0,0 @@
#ifndef _aosdfjk02fmasf
#define _aosdfjk02fmasf
#include "../common/configSys.h"
#define MAXBUTTCONFIG 4
typedef struct {
uint8 ButtType[MAXBUTTCONFIG];
uint8 DeviceNum[MAXBUTTCONFIG];
uint16 ButtonNum[MAXBUTTCONFIG];
uint32 NumC;
//uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */
} ButtConfig;
extern int NoWaiting;
extern CFGSTRUCT InputConfig[];
extern ARGPSTRUCT InputArgs[];
extern int Hotkeys[];
void ParseGIInput(FCEUGI *GI);
void setHotKeys();
int ButtonConfigBegin();
void ButtonConfigEnd();
void ConfigButton(char *text, ButtConfig *bc);
int DWaitButton(const uint8 *text, ButtConfig *bc, int wb);
#define BUTTC_KEYBOARD 0x00
#define BUTTC_JOYSTICK 0x01
#define BUTTC_MOUSE 0x02
#define FCFGD_GAMEPAD 1
#define FCFGD_POWERPAD 2
#define FCFGD_HYPERSHOT 3
#define FCFGD_QUIZKING 4
#define SDL_FCEU_HOTKEY_EVENT SDL_USEREVENT
void InitInputInterface(void);
void InputUserActiveFix(void);
extern bool replaceP2StartWithMicrophone;
extern ButtConfig GamePadConfig[4][10];
//extern ButtConfig powerpadsc[2][12];
//extern ButtConfig QuizKingButtons[6];
//extern ButtConfig FTrainerButtons[12];
void IncreaseEmulationSpeed(void);
void DecreaseEmulationSpeed(void);
int DTestButtonJoy(ButtConfig *bc);
void FCEUD_UpdateInput(void);
void UpdateInput(Config *config);
void InputCfg(const std::string &);
std::string GetUserText(const char* title);
const char* ButtonName(const ButtConfig* bc, int which);
#endif
-48
View File
@@ -1,48 +0,0 @@
#define SDLK_A SDLK_a
#define SDLK_B SDLK_b
#define SDLK_C SDLK_c
#define SDLK_D SDLK_d
#define SDLK_E SDLK_e
#define SDLK_F SDLK_f
#define SDLK_G SDLK_g
#define SDLK_H SDLK_h
#define SDLK_I SDLK_i
#define SDLK_J SDLK_j
#define SDLK_K SDLK_k
#define SDLK_L SDLK_l
#define SDLK_M SDLK_m
#define SDLK_N SDLK_n
#define SDLK_O SDLK_o
#define SDLK_P SDLK_p
#define SDLK_Q SDLK_q
#define SDLK_R SDLK_r
#define SDLK_S SDLK_s
#define SDLK_T SDLK_t
#define SDLK_U SDLK_u
#define SDLK_V SDLK_v
#define SDLK_W SDLK_w
#define SDLK_X SDLK_x
#define SDLK_Y SDLK_y
#define SDLK_Z SDLK_z
#define SDLK_LEFTCONTROL SDLK_LCTRL
#define SDLK_RIGHTCONTROL SDLK_RCTRL
#define SDLK_LEFTALT SDLK_LALT
#define SDLK_RIGHTALT SDLK_RALT
#define SDLK_LEFTSHIFT SDLK_LSHIFT
#define SDLK_RIGHTSHIFT SDLK_RSHIFT
#define SDLK_CURSORDOWN SDLK_DOWN
#define SDLK_CURSORUP SDLK_UP
#define SDLK_CURSORLEFT SDLK_LEFT
#define SDLK_CURSORRIGHT SDLK_RIGHT
#define SDLK_ENTER SDLK_RETURN
#define SDLK_EQUAL SDLK_EQUALS
#define SDLK_APOSTROPHE SDLK_QUOTE
#define SDLK_BRACKET_LEFT SDLK_LEFTBRACKET
#define SDLK_BRACKET_RIGHT SDLK_RIGHTBRACKET
#define SDLK_SCROLLLOCK SDLK_SCROLLOCK /* I guess the SDL people don't like lots of Ls... */
#define SDLK_GRAVE SDLK_BACKQUOTE
#define MKK(k) SDLK_##k
#if SDL_VERSION_ATLEAST(2, 0, 0)
#define SDLK_LAST SDL_NUM_SCANCODES
#endif
#define MKK_COUNT (SDLK_LAST+1)
-134
View File
@@ -1,134 +0,0 @@
static const struct {
unsigned int width;
unsigned int height;
unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */
uint8 pixel_data[32 * 32 * 3 + 1];
} fceu_playicon = {
32, 32, 3,
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\0\0\0\0\0\0\0\0\0\\\223\373\\\223\373\267\317\373"
"\246\304\373\260\312\373\222\267\373\246\304\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\267\317\373\246\304\373\260\312\373\210\261\373\246\304\373\\\223\373\\"
"\223\373\210\261\373\222\267\373\267\317\373\241\301\373\\\223\373\\\223"
"\373\0\0\0\0\0\0\\\223\373\\\223\373\227\272\373\227\272\373\227\272\373"
"\227\272\373\227\272\373\227\272\373\\\223\373\\\223\373z`sr\242\373\227"
"\272\373\227\272\373\\\223\373\\\223\373\\\223\373\\\223\373\213\261\373"
"z\247\373\213\261\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\"
"\223\373\\\223\373\313i=\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40"
"\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40"
"\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\257T*\\\223\373\\\223\373\\\223"
"\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40"
"\355\235\203\355\235\203\341\232\205\341\232\205\365\255\233\355\235\203"
"\355\235\203\350\250\232\365\255\233\355\235\203\307L\14\307L\14\307L\14"
"\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256B\12\\\223\373"
"\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373"
"\\\223\373\315Z\40\273zc\233l_\325\225\205\325\225\205\325\225\205\273\212"
"\201\325\225\205\237qd\325\225\205\317\231\216\307L\14\307L\14\307L\14\307"
"L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256B\12\\\223\373\\"
"\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\"
"\223\373\315Z\40\344\232\203\301\215\201\344\232\203\273\212\201\325\225"
"\205\2114\10\344\232\203\350\250\232\325\225\205\333\230\205\307L\14\307"
"L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256"
"B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223"
"\373\\\223\373\\\223\373\315Z\40\2259\11}0\10\2259\11}0\10}0\10\307L\14\225"
"9\11d&\6}0\10}0\10\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14"
"\307L\14\307L\14\307L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373"
"\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40\355\235\203"
"\355\233\201\355\235\203\355\235\203\355\235\203\365\255\233\355\235\203"
"\341\232\205\355\235\203\355\235\203\307L\14\365\255\233\355\235\203\365"
"\255\233\355\235\203\355\235\203\355\235\203\355\235\203\355\235\203\307"
"L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
"\\\223\373\\\223\373\\\223\373\315Z\40\325\225\205\311\221\204\311\221\204"
"\325\225\205\311\221\204\325\225\205\311\221\204\325\225\205\325\225\205"
"\311\221\204\307L\14\325\225\205\311\221\204\325\225\205\311\221\204\325"
"\225\205\311\221\204\325\225\205\311\221\204\307L\14\256B\12\\\223\373\\"
"\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\"
"\223\373\315Z\40\325\225\205\325\225\205\325\225\205\325\225\205\325\225"
"\205\325\225\205\317\231\216\325\225\205\325\225\205\325\225\205\307L\14"
"\325\225\205\317\231\216\325\225\205\317\231\216\325\225\205\325\225\205"
"\273zc\241n_\307L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0"
"\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40\325\225\205\325"
"\225\205\325\225\205\365\255\233\333\243\231\325\225\205\333\230\205\325"
"\225\205\325\225\205\325\225\205\307L\14\325\225\205\317\223\204\325\225"
"\205\333\230\205\325\225\205\325\225\205\333\230\205\317\223\204\307L\14"
"\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\"
"\223\373\\\223\373\\\223\373\315Z\40\325\225\205\325\225\205\325\225\205"
"\325\225\205\311\221\204\325\225\205\325\225\205\325\225\205\344\232\203"
"\273\212\201\307L\14\325\225\205\273\212\201\325\225\205\325\225\205\344"
"\232\203\273\212\201\344\232\203\273\212\201\341\232\205\256B\12\\\223\373"
"\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373"
"\\\223\373\257T*d&\6d&\6d&\6d&\6d&\6d&\6d&\6d&\6}0\10d&\6\256B\12d&\6p+\7"
"d&\6d&\6}0\10d&\6}0\10d&\6d&\6\223@\26\\\223\373\\\223\373\\\223\373\\\223"
"\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\234\243"
"\335\213\237\344\237\244\333\251\247\326\237\244\333\\\223\373\267\252\317"
"\222\241\341\267\252\317\210\237\346\241\245\332\267\252\317\246\246\327"
"\246\246\327\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0"
"\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\257hT\\\223\373\213\261\373\\\223"
"\373\241\301\373\210\261\373\246\304\373\222\267\373\241\301\373\260\312"
"\373\\\223\373\237\277\373\246\304\373\267\317\373\241\301\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\246\304\373\\\223\373\241"
"\301\373\210\261\373\246\304\373\222\267\373\241\301\373\260\312\373\\\223"
"\373\237\277\373\246\304\373\267\317\373\241\301\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
"\\\223\373\\\223\373D\203\270D\203\270\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0"
"\0\0\0\0\\\223\373\\\223\373(\211n\0\247\0\0n\0(\211n\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\0\0\0\0\0\0\\\223\373(\211n\0\247\0\0\247\0\0\247\0\0\247\0(\211n\\\223"
"\373\\\223\373\\\223\373\\\223\373\210\261\373\246\304\373\241\301\373z\247"
"\373\\\223\373\227\272\373\227\272\373\227\272\373\227\272\373\227\272\373"
"\227\272\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\0\0\0\0\0\0(\211n\0\247\0\0n\0\0\247\0\\\215\12fs\16"
"\0\247\0(\211n\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373Z\231Z[\230SZ\231Z[\230SZ\231Z[\230S\\\223\373\0\0\0\0"
"\0\0\0\247\0\0\247\0\0\247\0\0\247\0vy\7p|\7\0\247\0\0\247\0(\211n\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373b\237L\200\317\20\200\317"
"\20\200\317\20\200\317\20\200\317\20\200\317\20[\223H\0\0\0\0\0\0\230P.\323"
"d0\230P.\323d0\221M&\313`%\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323"
"d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323"
"d0\230P.\323d0\230P.\323d0\0\0\0\0\0\0\0\0\0\237N(\225E\35\237N(\225E\35"
"\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237"
"N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N("
"\225E\35\237N(\225E\35\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
};
-123
View File
@@ -1,123 +0,0 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
* Copyright (C) 2002 Paul Kuliniewicz
*
* 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
*/
/// \file
/// \brief Handles joystick input using the SDL.
#include "sdl.h"
#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
#include <cerrno>
#define MAX_JOYSTICKS 32
static SDL_Joystick *s_Joysticks[MAX_JOYSTICKS] = {NULL};
static int s_jinited = 0;
/**
* Tests if the given button is active on the joystick.
*/
int
DTestButtonJoy(ButtConfig *bc)
{
int x;
for(x = 0; x < bc->NumC; x++)
{
if(bc->ButtonNum[x] & 0x2000)
{
/* Hat "button" */
if(SDL_JoystickGetHat(s_Joysticks[bc->DeviceNum[x]],
((bc->ButtonNum[x] >> 8) & 0x1F)) &
(bc->ButtonNum[x]&0xFF))
return 1;
}
else if(bc->ButtonNum[x] & 0x8000)
{
/* Axis "button" */
int pos;
pos = SDL_JoystickGetAxis(s_Joysticks[bc->DeviceNum[x]],
bc->ButtonNum[x] & 16383);
if ((bc->ButtonNum[x] & 0x4000) && pos <= -16383) {
return 1;
} else if (!(bc->ButtonNum[x] & 0x4000) && pos >= 16363) {
return 1;
}
}
else if(SDL_JoystickGetButton(s_Joysticks[bc->DeviceNum[x]],
bc->ButtonNum[x]))
return 1;
}
return 0;
}
/**
* Shutdown the SDL joystick subsystem.
*/
int
KillJoysticks()
{
int n; /* joystick index */
if(!s_jinited) {
return -1;
}
for(n = 0; n < MAX_JOYSTICKS; n++) {
if (s_Joysticks[n] != 0) {
SDL_JoystickClose(s_Joysticks[n]);
}
s_Joysticks[n]=0;
}
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
return 0;
}
/**
* Initialize the SDL joystick subsystem.
*/
int
InitJoysticks()
{
int n; /* joystick index */
int total;
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
total = SDL_NumJoysticks();
if(total>MAX_JOYSTICKS) {
total = MAX_JOYSTICKS;
}
for(n = 0; n < total; n++) {
/* Open the joystick under SDL. */
s_Joysticks[n] = SDL_JoystickOpen(n);
//printf("Could not open joystick %d: %s.\n",
//joy[n] - 1, SDL_GetError());
continue;
}
s_jinited = 1;
return 1;
}
-224
View File
@@ -1,224 +0,0 @@
#include "sdl.h"
#include "input.h"
#include <SDL_net.h>
#include "sdl-netplay.h"
char *ServerHost;
int magic;
static int LocalPortTCP=0xFCE;
static int LocalPortUDP=0xFCE;
static int RemotePortTCP=0xFCE;
static int RemotePortUDP; /* Not configurable, figured out during handshake. */
static TCPsocket Socket;
static UDPsocket UDPSocket;
static SDLNet_SocketSet set;
static void en32(uint8 *buf, uint32 morp)
{
buf[0]=morp;
buf[1]=morp>>8;
buf[2]=morp>>16;
buf[3]=morp>>24;
}
static uint32 de32(uint8 *morp)
{
return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24));
}
int FCEUD_NetworkConnect(void)
{
IPaddress rip;
SDLNet_Init();
int netplay =1;
if(netplay==1) /* Be a server. */
{
TCPsocket tmp;
Uint16 p=LocalPortUDP;
SDLNet_ResolveHost(&rip,NULL,LocalPortTCP);
UDPSocket=SDLNet_UDP_Open(p);
tmp=SDLNet_TCP_Open(&rip);
Socket=SDLNet_TCP_Accept(tmp);
memcpy(&rip,SDLNet_TCP_GetPeerAddress(Socket),sizeof(IPaddress));
{
Uint32 buf[12];
uint32 player=1;
magic=SDL_GetTicks();
SDLNet_Write32(buf,uport);
SDLNet_Write32(buf+4,1);
SDLNet_Write32(buf+8,magic);
SDLNet_TCP_Send(Socket, buf, 12);
/* Get the UDP port the client is waiting for data on. */
SDLNet_TCP_Recv(Socket, buf, 2);
RemotePortUDP=de32(buf);
}
}
else /* Be a client */
{
SDLNet_ResolveHost(&rip,ServerHost,RemotePortTCP);
Socket=SDLNet_TCP_Open(&rip);
{
Uint16 p=LocalPortUDP;
uint8 buf[12];
UDPSocket=SDLNet_UDP_Open(p);
/* Now, tell the server what local UDP port it should send to. */
en32(buf,p);
SDLNet_TCP_Send(Socket, buf, 4);
/* Get the UDP port from the server we should send data to. */
SDLNet_TCP_Recv(Socket, buf, 12);
RemotePortUDP=de32(buf);
magic=de32(buf+8);
}
set=SDLNet_AllocSocketSet(1);
SDLNet_TCP_AddSocket(set,Socket);
SDLNet_UDP_AddSocket(set,UDPSocket);
} // End client connect code.
rip.port=RemotePortUDP;
SDLNet_UDP_Bind(UDPSocket, 0, &rip);
}
static int CheckUDP(uint8 *packet, int32 len, int32 alt)
{
uint32 crc;
uint32 repcrc;
crc=FCEUI_CRC32(0,packet+4,len+8);
repcrc=de32(packet);
if(crc!=repcrc) return(0); /* CRC32 mismatch, bad packet. */
packet+=4;
if(de32(packet)!=magic) /* Magic number mismatch, bad or spoofed packet. */
return(0);
packet+=4;
if(alt)
{
if(de32(packet)<incounter) /* Time warped packet. */
return(0);
}
else
if(de32(packet)!=incounter) /* Time warped packet. */
return(0);
return(1);
}
/* Be careful where these MakeXXX() functions are used. */
static uint8 *MakeUDP(uint8 *data, int32 len)
{
/* UDP packet data header is 12 bytes in length. */
static uint8 buf[12+32]; // arbitrary 32.
en32(buf+4,magic);
en32(buf+8,outcounter);
memcpy(buf+12,data,len);
en32(buf,FCEUI_CRC32(0,buf+4,8+len));
return(buf);
}
static uint8 *MakeTCP(uint8 *data, int32 len)
{
/* TCP packet data header is 4 bytes in length. */
static uint8 buf[4+32]; // arbitrary 32.
en32(buf,outcounter);
memcpy(buf+4,data,len);
return(buf);
}
#define UDPHEADSIZE 12
#define TCPHEADSIZE 4
void FCEUD_NetworkClose(void)
{
SDLNet_Quit();
}
/* 1 byte to server */
int FCEUD_SendDataToServer(uint8 v,uint8 cmd)
{
UDPpacket upack;
upack.channel=0;
upack.data=MakeUDP(data,1);
upack.len=upack.maxlen=UDPHEADSIZE+1;
upack.status=0;
SDLNet_UDP_Send(UDPSocket,0,&upack);
outcounter++;
return(1);
}
void FCEUD_SendDataToClients(uint8 *data)
{
UDPpacket upack;
SDLNet_TCP_Send(Socket,MakeTCP(data,5),TCPHEADSIZE+5);
upack.channel=0;
upack.data=MakeUDP(data,5);
upack.len=upack.maxlen=UDPHEADSIZE+5;
upack.status=0;
SDLNet_UDP_Send(UDPSocket,0,&upack);
outcounter++;
return(1);
}
int FCEUD_GetDataFromServer(uint8 *data)
{
uint8 buf[128];
NoWaiting&=~2;
while(SDLNet_CheckSockets(set,1)==0)
{
// do something here.
}
if(SDLNet_SocketReady(Socket))
{
if(de32(buf)==incounter) /* New packet, keep. */
{
unsigned long beefie;
memcpy(data,buf+TCPHEADSIZE,5);
incounter++;
if(!ioctl(Socket,FIONREAD,&beefie))
if(beefie)
NoWaiting|=2;
return(1);
}
}
if(SDLNet_SocketReady(UDPSocket)
{
}
}
-251
View File
@@ -1,251 +0,0 @@
#define GL_GLEXT_LEGACY
#include "sdl.h"
#include "sdl-opengl.h"
#include "../common/vidblit.h"
#include "../../utils/memory.h"
#ifdef APPLEOPENGL
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <OpenGL/glext.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#endif
#include <cstring>
#include <cstdlib>
#ifndef APIENTRY
#define APIENTRY
#endif
static GLuint textures[2]={0,0}; // Normal image, scanline overlay.
static int left,right,top,bottom; // right and bottom are not inclusive.
static int scanlines;
static void *HiBuffer;
typedef void APIENTRY (*glColorTableEXT_Func)(GLenum target,
GLenum internalformat, GLsizei width, GLenum format, GLenum type,
const GLvoid *table);
glColorTableEXT_Func p_glColorTableEXT;
void
SetOpenGLPalette(uint8 *data)
{
if(!HiBuffer) {
glBindTexture(GL_TEXTURE_2D, textures[0]);
p_glColorTableEXT(GL_TEXTURE_2D, GL_RGB, 256,
GL_RGBA, GL_UNSIGNED_BYTE, data);
} else {
SetPaletteBlitToHigh((uint8*)data);
}
}
void
BlitOpenGL(uint8 *buf)
{
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, textures[0]);
if(HiBuffer) {
Blit8ToHigh(buf, (uint8*)HiBuffer, 256, 240, 256*4, 1, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0,
GL_RGBA, GL_UNSIGNED_BYTE, HiBuffer);
}
else {
//glPixelStorei(GL_UNPACK_ROW_LENGTH, 256);
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, 256, 256, 0,
GL_COLOR_INDEX,GL_UNSIGNED_BYTE,buf);
}
glBegin(GL_QUADS);
glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of picture.
glVertex2f(-1.0f, -1.0f); // Bottom left of target.
glTexCoord2f(1.0f*right/256, 1.0f*bottom/256);// Bottom right of picture.
glVertex2f( 1.0f, -1.0f); // Bottom right of target.
glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture.
glVertex2f( 1.0f, 1.0f); // Top right of target.
glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture.
glVertex2f(-1.0f, 1.0f); // Top left of target.
glEnd();
//glDisable(GL_BLEND);
if(scanlines) {
glEnable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, textures[1]);
glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
glBegin(GL_QUADS);
glTexCoord2f(1.0f*left/256,
1.0f*bottom/256); // Bottom left of our picture.
glVertex2f(-1.0f, -1.0f); // Bottom left of target.
glTexCoord2f(1.0f*right/256,
1.0f*bottom/256); // Bottom right of our picture.
glVertex2f( 1.0f, -1.0f); // Bottom right of target.
glTexCoord2f(1.0f*right/256,
1.0f*top/256); // Top right of our picture.
glVertex2f( 1.0f, 1.0f); // Top right of target.
glTexCoord2f(1.0f*left/256,
1.0f*top/256); // Top left of our picture.
glVertex2f(-1.0f, 1.0f); // Top left of target.
glEnd();
glDisable(GL_BLEND);
}
SDL_GL_SwapBuffers();
}
void
KillOpenGL(void)
{
if(textures[0]) {
glDeleteTextures(2, &textures[0]);
}
textures[0]=0;
if(HiBuffer) {
free(HiBuffer);
HiBuffer=0;
}
}
/* Rectangle, left, right(not inclusive), top, bottom(not inclusive). */
int
InitOpenGL(int l,
int r,
int t,
int b,
double xscale,
double yscale,
int efx,
int ipolate,
int stretchx,
int stretchy,
SDL_Surface *screen)
{
const char *extensions;
#define LFG(x) if(!(##x = (x##_Func) SDL_GL_GetProcAddress(#x))) return(0);
#define LFGN(x) p_##x = (x##_Func) SDL_GL_GetProcAddress(#x)
// LFG(glBindTexture);
LFGN(glColorTableEXT);
// LFG(glTexImage2D);
// LFG(glBegin);
// LFG(glVertex2f);
// LFG(glTexCoord2f);
// LFG(glEnd);
// LFG(glEnable);
// LFG(glBlendFunc);
// LFG(glGetString);
// LFG(glViewport);
// LFG(glGenTextures);
// LFG(glDeleteTextures);
// LFG(glTexParameteri);
// LFG(glClearColor);
// LFG(glLoadIdentity);
// LFG(glClear);
// LFG(glMatrixMode);
// LFG(glDisable);
left=l;
right=r;
top=t;
bottom=b;
HiBuffer=0;
extensions=(const char*)glGetString(GL_EXTENSIONS);
if((efx&2) || !extensions || !p_glColorTableEXT || !strstr(extensions,"GL_EXT_paletted_texture"))
{
if(!(efx&2)) // Don't want to print out a warning message in this case...
FCEU_printf("Paletted texture extension not found. Using slower texture format...\n");
HiBuffer=FCEU_malloc(4*256*256);
memset(HiBuffer,0x00,4*256*256);
#ifndef LSB_FIRST
InitBlitToHigh(4,0xFF000000,0xFF0000,0xFF00,efx&2,0,0);
#else
InitBlitToHigh(4,0xFF,0xFF00,0xFF0000,efx&2,0,0);
#endif
}
if(screen->flags & SDL_FULLSCREEN)
{
xscale=(double)screen->w / (double)(r-l);
yscale=(double)screen->h / (double)(b-t);
if(xscale<yscale) yscale = xscale;
if(yscale<xscale) xscale = yscale;
}
{
int rw=(int)((r-l)*xscale);
int rh=(int)((b-t)*yscale);
int sx=(screen->w-rw)/2; // Start x
int sy=(screen->h-rh)/2; // Start y
if(stretchx) { sx=0; rw=screen->w; }
if(stretchy) { sy=0; rh=screen->h; }
glViewport(sx, sy, rw, rh);
}
glGenTextures(2, &textures[0]);
scanlines=0;
if(efx&1)
{
uint8 *buf;
int x,y;
scanlines=1;
glBindTexture(GL_TEXTURE_2D, textures[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
buf=(uint8*)FCEU_dmalloc(256*(256*2)*4);
for(y=0;y<(256*2);y++)
for(x=0;x<256;x++)
{
buf[y*256*4+x*4]=0;
buf[y*256*4+x*4+1]=0;
buf[y*256*4+x*4+2]=0;
buf[y*256*4+x*4+3]=(y&1)?0x00:0xFF; //?0xa0:0xFF; // <-- Pretty
//buf[y*256+x]=(y&1)?0x00:0xFF;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, (scanlines==2)?256*4:512, 0,
GL_RGBA,GL_UNSIGNED_BYTE,buf);
FCEU_dfree(buf);
}
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Background color to black.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// In a double buffered setup with page flipping, be sure to clear both buffers.
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapBuffers();
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapBuffers();
return 1;
}
-6
View File
@@ -1,6 +0,0 @@
void SetOpenGLPalette(uint8 *data);
void BlitOpenGL(uint8 *buf);
void KillOpenGL(void);
int InitOpenGL(int l, int r, int t, int b, double xscale,double yscale, int efx, int ipolate,
int stretchx, int stretchy, SDL_Surface *screen);
-272
View File
@@ -1,272 +0,0 @@
/* 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
*/
/// \file
/// \brief Handles sound emulation using the SDL.
#include "sdl.h"
#include "../common/configSys.h"
#include "../../utils/memory.h"
#include <cstdio>
#include <cstring>
#include <cstdlib>
extern Config *g_config;
static volatile int *s_Buffer = 0;
static unsigned int s_BufferSize;
static unsigned int s_BufferRead;
static unsigned int s_BufferWrite;
static volatile unsigned int s_BufferIn;
static int s_mute = 0;
/**
* Callback from the SDL to get and play audio data.
*/
static void
fillaudio(void *udata,
uint8 *stream,
int len)
{
int16 *tmps = (int16*)stream;
len >>= 1;
while(len) {
int16 sample = 0;
if(s_BufferIn) {
sample = s_Buffer[s_BufferRead];
s_BufferRead = (s_BufferRead + 1) % s_BufferSize;
s_BufferIn--;
} else {
sample = 0;
}
*tmps = sample;
tmps++;
len--;
}
}
/**
* Initialize the audio subsystem.
*/
int
InitSound()
{
int sound, soundrate, soundbufsize, soundvolume, soundtrianglevolume, soundsquare1volume, soundsquare2volume, soundnoisevolume, soundpcmvolume, soundq;
SDL_AudioSpec spec;
g_config->getOption("SDL.Sound", &sound);
if(!sound) {
return 0;
}
memset(&spec, 0, sizeof(spec));
if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
puts(SDL_GetError());
KillSound();
return 0;
}
char driverName[8];
#if SDL_VERSION_ATLEAST(2, 0, 0)
// TODO - SDL 2
#else
SDL_AudioDriverName(driverName, 8);
fprintf(stderr, "Loading SDL sound with %s driver...\n", driverName);
#endif
// load configuration variables
g_config->getOption("SDL.Sound.Rate", &soundrate);
g_config->getOption("SDL.Sound.BufSize", &soundbufsize);
g_config->getOption("SDL.Sound.Volume", &soundvolume);
g_config->getOption("SDL.Sound.Quality", &soundq);
g_config->getOption("SDL.Sound.TriangleVolume", &soundtrianglevolume);
g_config->getOption("SDL.Sound.Square1Volume", &soundsquare1volume);
g_config->getOption("SDL.Sound.Square2Volume", &soundsquare2volume);
g_config->getOption("SDL.Sound.NoiseVolume", &soundnoisevolume);
g_config->getOption("SDL.Sound.PCMVolume", &soundpcmvolume);
spec.freq = soundrate;
spec.format = AUDIO_S16SYS;
spec.channels = 1;
spec.samples = 512;
spec.callback = fillaudio;
spec.userdata = 0;
s_BufferSize = soundbufsize * soundrate / 1000;
// For safety, set a bare minimum:
if (s_BufferSize < spec.samples * 2)
s_BufferSize = spec.samples * 2;
s_Buffer = (int *)FCEU_dmalloc(sizeof(int) * s_BufferSize);
if (!s_Buffer)
return 0;
s_BufferRead = s_BufferWrite = s_BufferIn = 0;
if(SDL_OpenAudio(&spec, 0) < 0)
{
puts(SDL_GetError());
KillSound();
return 0;
}
SDL_PauseAudio(0);
FCEUI_SetSoundVolume(soundvolume);
FCEUI_SetSoundQuality(soundq);
FCEUI_Sound(soundrate);
FCEUI_SetTriangleVolume(soundtrianglevolume);
FCEUI_SetSquare1Volume(soundsquare1volume);
FCEUI_SetSquare2Volume(soundsquare2volume);
FCEUI_SetNoiseVolume(soundnoisevolume);
FCEUI_SetPCMVolume(soundpcmvolume);
return 1;
}
/**
* Returns the size of the audio buffer.
*/
uint32
GetMaxSound(void)
{
return(s_BufferSize);
}
/**
* Returns the amount of free space in the audio buffer.
*/
uint32
GetWriteSound(void)
{
return(s_BufferSize - s_BufferIn);
}
/**
* Send a sound clip to the audio subsystem.
*/
void
WriteSound(int32 *buf,
int Count)
{
extern int EmulationPaused;
if (EmulationPaused == 0)
while(Count)
{
while(s_BufferIn == s_BufferSize)
{
SDL_Delay(1);
}
s_Buffer[s_BufferWrite] = *buf;
Count--;
s_BufferWrite = (s_BufferWrite + 1) % s_BufferSize;
SDL_LockAudio();
s_BufferIn++;
SDL_UnlockAudio();
buf++;
}
}
/**
* Pause (1) or unpause (0) the audio output.
*/
void
SilenceSound(int n)
{
SDL_PauseAudio(n);
}
/**
* Shut down the audio subsystem.
*/
int
KillSound(void)
{
FCEUI_Sound(0);
SDL_CloseAudio();
SDL_QuitSubSystem(SDL_INIT_AUDIO);
if(s_Buffer) {
free((void *)s_Buffer);
s_Buffer = 0;
}
return 0;
}
/**
* Adjust the volume either down (-1), up (1), or to the default (0).
* Unmutes if mute was active before.
*/
void
FCEUD_SoundVolumeAdjust(int n)
{
int soundvolume;
g_config->getOption("SDL.Sound.Volume", &soundvolume);
switch(n) {
case -1:
soundvolume -= 10;
if(soundvolume < 0) {
soundvolume = 0;
}
break;
case 0:
soundvolume = 100;
break;
case 1:
soundvolume += 10;
if(soundvolume > 150) {
soundvolume = 150;
}
break;
}
s_mute = 0;
FCEUI_SetSoundVolume(soundvolume);
g_config->setOption("SDL.Sound.Volume", soundvolume);
FCEU_DispMessage("Sound volume %d.",0, soundvolume);
}
/**
* Toggles the sound on or off.
*/
void
FCEUD_SoundToggle(void)
{
if(s_mute) {
int soundvolume;
g_config->getOption("SDL.SoundVolume", &soundvolume);
s_mute = 0;
FCEUI_SetSoundVolume(soundvolume);
FCEU_DispMessage("Sound mute off.",0);
} else {
s_mute = 1;
FCEUI_SetSoundVolume(0);
FCEU_DispMessage("Sound mute on.",0);
}
}
-150
View File
@@ -1,150 +0,0 @@
/// \file
/// \brief Handles emulation speed throttling using the SDL timing functions.
#include "sdl.h"
#include "throttle.h"
static const double Slowest = 0.015625; // 1/64x speed (around 1 fps on NTSC)
static const double Fastest = 32; // 32x speed (around 1920 fps on NTSC)
static const double Normal = 1.0; // 1x speed (around 60 fps on NTSC)
static uint64 Lasttime, Nexttime;
static long double desired_frametime;
static int InFrame;
double g_fpsScale = Normal; // used by sdl.cpp
bool MaxSpeed = false;
/* LOGMUL = exp(log(2) / 3)
*
* This gives us a value such that if we do x*=LOGMUL three times,
* then after that, x is twice the value it was before.
*
* This gives us three speed steps per order of magnitude.
*
*/
#define LOGMUL 1.259921049894873
/**
* Refreshes the FPS throttling variables.
*/
void
RefreshThrottleFPS()
{
uint64 fps = FCEUI_GetDesiredFPS(); // Do >> 24 to get in Hz
desired_frametime = 16777216.0l / (fps * g_fpsScale);
Lasttime=0;
Nexttime=0;
InFrame=0;
}
/**
* Perform FPS speed throttling by delaying until the next time slot.
*/
int
SpeedThrottle()
{
if(g_fpsScale >= 32)
{
return 0; /* Done waiting */
}
uint64 time_left;
uint64 cur_time;
if(!Lasttime)
Lasttime = SDL_GetTicks();
if(!InFrame)
{
InFrame = 1;
Nexttime = Lasttime + desired_frametime * 1000;
}
cur_time = SDL_GetTicks();
if(cur_time >= Nexttime)
time_left = 0;
else
time_left = Nexttime - cur_time;
if(time_left > 50)
{
time_left = 50;
/* In order to keep input responsive, don't wait too long at once */
/* 50 ms wait gives us a 20 Hz responsetime which is nice. */
}
else
InFrame = 0;
/*fprintf(stderr, "attempting to sleep %Ld ms, frame complete=%s\n",
time_left, InFrame?"no":"yes");*/
SDL_Delay(time_left);
if(!InFrame)
{
Lasttime = SDL_GetTicks();
return 0; /* Done waiting */
}
return 1; /* Must still wait some more */
}
/**
* Set the emulation speed throttling to the next entry in the speed table.
*/
void IncreaseEmulationSpeed(void)
{
g_fpsScale *= LOGMUL;
if(g_fpsScale > Fastest) g_fpsScale = Fastest;
RefreshThrottleFPS();
FCEU_DispMessage("Emulation speed %.1f%%",0, g_fpsScale*100.0);
}
/**
* Set the emulation speed throttling to the previous entry in the speed table.
*/
void DecreaseEmulationSpeed(void)
{
g_fpsScale /= LOGMUL;
if(g_fpsScale < Slowest)
g_fpsScale = Slowest;
RefreshThrottleFPS();
FCEU_DispMessage("Emulation speed %.1f%%",0, g_fpsScale*100.0);
}
/**
* Set the emulation speed throttling to a specific value.
*/
void
FCEUD_SetEmulationSpeed(int cmd)
{
MaxSpeed = false;
switch(cmd) {
case EMUSPEED_SLOWEST:
g_fpsScale = Slowest;
break;
case EMUSPEED_SLOWER:
DecreaseEmulationSpeed();
break;
case EMUSPEED_NORMAL:
g_fpsScale = Normal;
break;
case EMUSPEED_FASTER:
IncreaseEmulationSpeed();
break;
case EMUSPEED_FASTEST:
g_fpsScale = Fastest;
MaxSpeed = true;
break;
default:
return;
}
RefreshThrottleFPS();
FCEU_DispMessage("Emulation speed %.1f%%",0, g_fpsScale*100.0);
}
-861
View File
@@ -1,861 +0,0 @@
/* 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
*/
/// \file
/// \brief Handles the graphical game display for the SDL implementation.
#include "sdl.h"
#include "sdl-opengl.h"
#include "../common/vidblit.h"
#include "../../fceu.h"
#include "../../version.h"
#include "../../video.h"
#include "../../utils/memory.h"
#include "sdl-icon.h"
#include "dface.h"
#include "../common/configSys.h"
#include "sdl-video.h"
#ifdef CREATE_AVI
#include "../videolog/nesvideos-piece.h"
#endif
#ifdef _GTK
#include "gui.h"
#endif
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#include <cstdio>
#include <cstring>
#include <cstdlib>
// GLOBALS
extern Config *g_config;
// STATIC GLOBALS
extern SDL_Surface *s_screen;
static SDL_Surface *s_BlitBuf; // Buffer when using hardware-accelerated blits.
static SDL_Surface *s_IconSurface = NULL;
static int s_curbpp;
static int s_srendline, s_erendline;
static int s_tlines;
static int s_inited;
#ifdef OPENGL
static int s_useOpenGL;
#endif
static double s_exs, s_eys;
static int s_eefx;
static int s_clipSides;
static int s_fullscreen;
static int noframe;
static int s_nativeWidth = -1;
static int s_nativeHeight = -1;
#define NWIDTH (256 - (s_clipSides ? 16 : 0))
#define NOFFSET (s_clipSides ? 8 : 0)
static int s_paletterefresh;
extern bool MaxSpeed;
/**
* Attempts to destroy the graphical video display. Returns 0 on
* success, -1 on failure.
*/
//draw input aids if we are fullscreen
bool FCEUD_ShouldDrawInputAids()
{
return s_fullscreen!=0;
}
int
KillVideo()
{
// if the IconSurface has been initialized, destroy it
if(s_IconSurface) {
SDL_FreeSurface(s_IconSurface);
s_IconSurface=0;
}
// return failure if the video system was not initialized
if(s_inited == 0)
return -1;
// if the rest of the system has been initialized, shut it down
#ifdef OPENGL
// check for OpenGL and shut it down
if(s_useOpenGL)
KillOpenGL();
else
#endif
// shut down the system that converts from 8 to 16/32 bpp
if(s_curbpp > 8)
KillBlitToHigh();
// shut down the SDL video sub-system
SDL_QuitSubSystem(SDL_INIT_VIDEO);
s_inited = 0;
return 0;
}
// this variable contains information about the special scaling filters
static int s_sponge;
/**
* These functions determine an appropriate scale factor for fullscreen/
*/
inline double GetXScale(int xres)
{
return ((double)xres) / NWIDTH;
}
inline double GetYScale(int yres)
{
return ((double)yres) / s_tlines;
}
void FCEUD_VideoChanged()
{
int buf;
g_config->getOption("SDL.PAL", &buf);
if(buf == 1)
PAL = 1;
else
PAL = 0; // NTSC and Dendy
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
int InitVideo(FCEUGI *gi)
{
// This is a big TODO. Stubbing this off into its own function,
// as the SDL surface routines have changed drastically in SDL2
// TODO - SDL2
}
#else
/**
* Attempts to initialize the graphical video display. Returns 0 on
* success, -1 on failure.
*/
int
InitVideo(FCEUGI *gi)
{
// XXX soules - const? is this necessary?
const SDL_VideoInfo *vinf;
int error, flags = 0;
int doublebuf, xstretch, ystretch, xres, yres, show_fps;
FCEUI_printf("Initializing video...");
// load the relevant configuration variables
g_config->getOption("SDL.Fullscreen", &s_fullscreen);
g_config->getOption("SDL.DoubleBuffering", &doublebuf);
#ifdef OPENGL
g_config->getOption("SDL.OpenGL", &s_useOpenGL);
#endif
g_config->getOption("SDL.SpecialFilter", &s_sponge);
g_config->getOption("SDL.XStretch", &xstretch);
g_config->getOption("SDL.YStretch", &ystretch);
g_config->getOption("SDL.LastXRes", &xres);
g_config->getOption("SDL.LastYRes", &yres);
g_config->getOption("SDL.ClipSides", &s_clipSides);
g_config->getOption("SDL.NoFrame", &noframe);
g_config->getOption("SDL.ShowFPS", &show_fps);
// check the starting, ending, and total scan lines
FCEUI_GetCurrentVidSystem(&s_srendline, &s_erendline);
s_tlines = s_erendline - s_srendline + 1;
// check if we should auto-set x/y resolution
// check for OpenGL and set the global flags
#if OPENGL
if(s_useOpenGL && !s_sponge) {
flags = SDL_OPENGL;
}
#endif
// initialize the SDL video subsystem if it is not already active
if(!SDL_WasInit(SDL_INIT_VIDEO)) {
error = SDL_InitSubSystem(SDL_INIT_VIDEO);
if(error) {
FCEUD_PrintError(SDL_GetError());
return -1;
}
}
s_inited = 1;
// shows the cursor within the display window
SDL_ShowCursor(1);
// determine if we can allocate the display on the video card
vinf = SDL_GetVideoInfo();
if(vinf->hw_available) {
flags |= SDL_HWSURFACE;
}
// get the monitor's current resolution if we do not already have it
if(s_nativeWidth < 0) {
s_nativeWidth = vinf->current_w;
}
if(s_nativeHeight < 0) {
s_nativeHeight = vinf->current_h;
}
// check to see if we are showing FPS
FCEUI_SetShowFPS(show_fps);
// check if we are rendering fullscreen
if(s_fullscreen) {
int no_cursor;
g_config->getOption("SDL.NoFullscreenCursor", &no_cursor);
flags |= SDL_FULLSCREEN;
SDL_ShowCursor(!no_cursor);
}
else {
SDL_ShowCursor(1);
}
if(noframe) {
flags |= SDL_NOFRAME;
}
// gives the SDL exclusive palette control... ensures the requested colors
flags |= SDL_HWPALETTE;
// enable double buffering if requested and we have hardware support
#ifdef OPENGL
if(s_useOpenGL) {
FCEU_printf("Initializing with OpenGL (Disable with '--opengl 0').\n");
if(doublebuf) {
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
}
} else
#endif
if(doublebuf && (flags & SDL_HWSURFACE)) {
flags |= SDL_DOUBLEBUF;
}
if(s_fullscreen) {
int desbpp, autoscale;
g_config->getOption("SDL.BitsPerPixel", &desbpp);
g_config->getOption("SDL.AutoScale", &autoscale);
if (autoscale)
{
double auto_xscale = GetXScale(xres);
double auto_yscale = GetYScale(yres);
double native_ratio = ((double)NWIDTH) / s_tlines;
double screen_ratio = ((double)xres) / yres;
int keep_ratio;
g_config->getOption("SDL.KeepRatio", &keep_ratio);
// Try to choose resolution
if (screen_ratio < native_ratio)
{
// The screen is narrower than the original. Maximizing width will not clip
auto_xscale = auto_yscale = GetXScale(xres);
if (keep_ratio)
auto_yscale = GetYScale(yres);
}
else
{
auto_yscale = auto_xscale = GetYScale(yres);
if (keep_ratio)
auto_xscale = GetXScale(xres);
}
s_exs = auto_xscale;
s_eys = auto_yscale;
}
else
{
g_config->getOption("SDL.XScale", &s_exs);
g_config->getOption("SDL.YScale", &s_eys);
}
g_config->getOption("SDL.SpecialFX", &s_eefx);
#ifdef OPENGL
if(!s_useOpenGL) {
s_exs = (int)s_exs;
s_eys = (int)s_eys;
} else {
desbpp = 0;
}
if((s_useOpenGL && !xstretch) || !s_useOpenGL)
#endif
if(xres < (NWIDTH * s_exs) || s_exs <= 0.01) {
FCEUD_PrintError("xscale out of bounds.");
KillVideo();
return -1;
}
#ifdef OPENGL
if((s_useOpenGL && !ystretch) || !s_useOpenGL)
#endif
if(yres < s_tlines * s_eys || s_eys <= 0.01) {
FCEUD_PrintError("yscale out of bounds.");
KillVideo();
return -1;
}
#ifdef OPENGL
s_screen = SDL_SetVideoMode(s_useOpenGL ? s_nativeWidth : xres,
s_useOpenGL ? s_nativeHeight : yres,
desbpp, flags);
#else
s_screen = SDL_SetVideoMode(xres, yres, desbpp, flags);
#endif
if(!s_screen) {
FCEUD_PrintError(SDL_GetError());
return -1;
}
} else {
int desbpp;
g_config->getOption("SDL.BitsPerPixel", &desbpp);
g_config->getOption("SDL.XScale", &s_exs);
g_config->getOption("SDL.YScale", &s_eys);
g_config->getOption("SDL.SpecialFX", &s_eefx);
// -Video Modes Tag-
if(s_sponge) {
if(s_sponge <= 3 && s_sponge >= 1)
{
s_exs = s_eys = 2;
} else if (s_sponge >=4 && s_sponge <= 5)
{
s_exs = s_eys = 3;
} else if (s_sponge >= 6 && s_sponge <= 8)
{
s_exs = s_eys = s_sponge - 4;
}
else if(s_sponge == 9)
{
s_exs = s_eys = 3;
}
else
{
s_exs = s_eys = 1;
}
if(s_sponge == 3) {
xres = 301 * s_exs;
}
s_eefx = 0;
if(s_sponge == 1 || s_sponge == 4) {
desbpp = 32;
}
}
int scrw = NWIDTH * s_exs;
if(s_sponge == 3) {
scrw = 301 * s_exs;
}
#ifdef OPENGL
if(!s_useOpenGL) {
s_exs = (int)s_exs;
s_eys = (int)s_eys;
}
if(s_exs <= 0.01) {
FCEUD_PrintError("xscale out of bounds.");
KillVideo();
return -1;
}
if(s_eys <= 0.01) {
FCEUD_PrintError("yscale out of bounds.");
KillVideo();
return -1;
}
if(s_sponge && s_useOpenGL) {
FCEUD_PrintError("scalers not compatible with openGL mode.");
KillVideo();
return -1;
}
#endif
#if defined(_GTK) && defined(SDL_VIDEO_DRIVER_X11) && defined(GDK_WINDOWING_X11)
if(noGui == 0)
{
while (gtk_events_pending())
gtk_main_iteration_do(FALSE);
char SDL_windowhack[128];
sprintf(SDL_windowhack, "SDL_WINDOWID=%u", (unsigned int)GDK_WINDOW_XID(gtk_widget_get_window(evbox)));
SDL_putenv(SDL_windowhack);
// init SDL video
if (SDL_WasInit(SDL_INIT_VIDEO))
SDL_QuitSubSystem(SDL_INIT_VIDEO);
if ( SDL_InitSubSystem(SDL_INIT_VIDEO) < 0 )
{
fprintf(stderr, "Couldn't init SDL video: %s\n", SDL_GetError());
gtk_main_quit();
}
}
#endif
s_screen = SDL_SetVideoMode(scrw, (int)(s_tlines * s_eys),
desbpp, flags);
if(!s_screen) {
FCEUD_PrintError(SDL_GetError());
return -1;
}
#ifdef _GTK
if(noGui == 0)
{
GtkRequisition req;
gtk_widget_size_request(GTK_WIDGET(MainWindow), &req);
gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height);
}
#endif
}
s_curbpp = s_screen->format->BitsPerPixel;
if(!s_screen) {
FCEUD_PrintError(SDL_GetError());
KillVideo();
return -1;
}
#if 0
// XXX soules - this would be creating a surface on the video
// card, but was commented out for some reason...
s_BlitBuf = SDL_CreateRGBSurface(SDL_HWSURFACE, 256, 240,
s_screen->format->BitsPerPixel,
s_screen->format->Rmask,
s_screen->format->Gmask,
s_screen->format->Bmask, 0);
#endif
FCEU_printf(" Video Mode: %d x %d x %d bpp %s\n",
s_screen->w, s_screen->h, s_screen->format->BitsPerPixel,
s_fullscreen ? "full screen" : "");
if(s_curbpp != 8 && s_curbpp != 16 && s_curbpp != 24 && s_curbpp != 32) {
FCEU_printf(" Sorry, %dbpp modes are not supported by FCE Ultra. Supported bit depths are 8bpp, 16bpp, and 32bpp.\n", s_curbpp);
KillVideo();
return -1;
}
// if the game being run has a name, set it as the window name
if(gi)
{
if(gi->name) {
SDL_WM_SetCaption((const char *)gi->name, (const char *)gi->name);
} else {
SDL_WM_SetCaption(FCEU_NAME_AND_VERSION,"FCE Ultra");
}
}
// create the surface for displaying graphical messages
#ifdef LSB_FIRST
s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,
32, 32, 24, 32 * 3,
0xFF, 0xFF00, 0xFF0000, 0x00);
#else
s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,
32, 32, 24, 32 * 3,
0xFF0000, 0xFF00, 0xFF, 0x00);
#endif
SDL_WM_SetIcon(s_IconSurface,0);
s_paletterefresh = 1;
// XXX soules - can't SDL do this for us?
// if using more than 8bpp, initialize the conversion routines
if(s_curbpp > 8) {
InitBlitToHigh(s_curbpp >> 3,
s_screen->format->Rmask,
s_screen->format->Gmask,
s_screen->format->Bmask,
s_eefx, s_sponge, 0);
#ifdef OPENGL
if(s_useOpenGL)
{
int openGLip;
g_config->getOption("SDL.OpenGLip", &openGLip);
if(!InitOpenGL(NOFFSET, 256 - (s_clipSides ? 8 : 0),
s_srendline, s_erendline + 1,
s_exs, s_eys, s_eefx,
openGLip, xstretch, ystretch, s_screen))
{
FCEUD_PrintError("Error initializing OpenGL.");
KillVideo();
return -1;
}
}
#endif
}
return 0;
}
#endif
/**
* Toggles the full-screen display.
*/
void ToggleFS()
{
// pause while we we are making the switch
bool paused = FCEUI_EmulationPaused();
if(!paused)
FCEUI_ToggleEmulationPause();
int error, fullscreen = s_fullscreen;
// shut down the current video system
KillVideo();
// flip the fullscreen flag
g_config->setOption("SDL.Fullscreen", !fullscreen);
#ifdef _GTK
if(noGui == 0)
{
if(!fullscreen)
showGui(0);
else
showGui(1);
}
#endif
// try to initialize the video
error = InitVideo(GameInfo);
if(error) {
// if we fail, just continue with what worked before
g_config->setOption("SDL.Fullscreen", fullscreen);
InitVideo(GameInfo);
}
// if we paused to make the switch; unpause
if(!paused)
FCEUI_ToggleEmulationPause();
}
static SDL_Color s_psdl[256];
/**
* Sets the color for a particular index in the palette.
*/
void
FCEUD_SetPalette(uint8 index,
uint8 r,
uint8 g,
uint8 b)
{
s_psdl[index].r = r;
s_psdl[index].g = g;
s_psdl[index].b = b;
s_paletterefresh = 1;
}
/**
* Gets the color for a particular index in the palette.
*/
void
FCEUD_GetPalette(uint8 index,
uint8 *r,
uint8 *g,
uint8 *b)
{
*r = s_psdl[index].r;
*g = s_psdl[index].g;
*b = s_psdl[index].b;
}
/**
* Pushes the palette structure into the underlying video subsystem.
*/
static void RedoPalette()
{
#ifdef OPENGL
if(s_useOpenGL)
SetOpenGLPalette((uint8*)s_psdl);
else
#endif
{
if(s_curbpp > 8) {
SetPaletteBlitToHigh((uint8*)s_psdl);
} else
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
//TODO - SDL2
#else
SDL_SetPalette(s_screen, SDL_PHYSPAL, s_psdl, 0, 256);
#endif
}
}
}
// XXX soules - console lock/unlock unimplemented?
///Currently unimplemented.
void LockConsole(){}
///Currently unimplemented.
void UnlockConsole(){}
/**
* Pushes the given buffer of bits to the screen.
*/
void
BlitScreen(uint8 *XBuf)
{
SDL_Surface *TmpScreen;
uint8 *dest;
int xo = 0, yo = 0;
if(!s_screen) {
return;
}
// refresh the palette if required
if(s_paletterefresh) {
RedoPalette();
s_paletterefresh = 0;
}
#ifdef OPENGL
// OpenGL is handled separately
if(s_useOpenGL) {
BlitOpenGL(XBuf);
return;
}
#endif
// XXX soules - not entirely sure why this is being done yet
XBuf += s_srendline * 256;
if(s_BlitBuf) {
TmpScreen = s_BlitBuf;
} else {
TmpScreen = s_screen;
}
// lock the display, if necessary
if(SDL_MUSTLOCK(TmpScreen)) {
if(SDL_LockSurface(TmpScreen) < 0) {
return;
}
}
dest = (uint8*)TmpScreen->pixels;
if(s_fullscreen) {
xo = (int)(((TmpScreen->w - NWIDTH * s_exs)) / 2);
dest += xo * (s_curbpp >> 3);
if(TmpScreen->h > (s_tlines * s_eys)) {
yo = (int)((TmpScreen->h - s_tlines * s_eys) / 2);
dest += yo * TmpScreen->pitch;
}
}
// XXX soules - again, I'm surprised SDL can't handle this
// perform the blit, converting bpp if necessary
if(s_curbpp > 8) {
if(s_BlitBuf) {
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
TmpScreen->pitch, 1, 1);
} else {
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
TmpScreen->pitch, (int)s_exs, (int)s_eys);
}
} else {
if(s_BlitBuf) {
Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
TmpScreen->pitch, 1, 1, 0, s_sponge);
} else {
Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
TmpScreen->pitch, (int)s_exs, (int)s_eys,
s_eefx, s_sponge);
}
}
// unlock the display, if necessary
if(SDL_MUSTLOCK(TmpScreen)) {
SDL_UnlockSurface(TmpScreen);
}
int scrw;
if(s_sponge == 3) { // NTSC 2x
scrw = 301;
} else {
scrw = NWIDTH;
}
// if we have a hardware video buffer, do a fast video->video copy
if(s_BlitBuf) {
SDL_Rect srect;
SDL_Rect drect;
srect.x = 0;
srect.y = 0;
srect.w = scrw;
srect.h = s_tlines;
drect.x = 0;
drect.y = 0;
drect.w = (Uint16)(s_exs * scrw);
drect.h = (Uint16)(s_eys * s_tlines);
SDL_BlitSurface(s_BlitBuf, &srect, s_screen, &drect);
}
// ensure that the display is updated
#if SDL_VERSION_ATLEAST(2, 0, 0)
//TODO - SDL2
#else
SDL_UpdateRect(s_screen, xo, yo,
(Uint32)(scrw * s_exs), (Uint32)(s_tlines * s_eys));
#endif
#ifdef CREATE_AVI
#if 0 /* PAL INTO NTSC HACK */
{ int fps = FCEUI_GetDesiredFPS();
if(FCEUI_GetDesiredFPS() == 838977920) fps = 1008307711;
NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp);
if(FCEUI_GetDesiredFPS() == 838977920)
{
static unsigned dup=0;
if(++dup==5) { dup=0;
NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); }
} }
#else
{ int fps = FCEUI_GetDesiredFPS();
static unsigned char* result = NULL;
static unsigned resultsize = 0;
int width = NWIDTH, height = s_tlines;
if(!result || resultsize != width*height*3*2)
{
if(result) free(result);
result = (unsigned char*) FCEU_dmalloc(resultsize = width*height*3*2);
}
switch(s_curbpp)
{
#if 0
case 24: case 32: case 15: case 16:
/* Convert to I420 if possible, because our I420 conversion is optimized
* and it'll produce less network traffic, hence faster throughput than
* anything else. And H.264 eats only I420, so it'd be converted sooner
* or later anyway if we didn't do it. Win-win situation.
*/
switch(s_curbpp)
{
case 32: Convert32To_I420Frame(s_screen->pixels, &result[0], width*height, width); break;
case 24: Convert24To_I420Frame(s_screen->pixels, &result[0], width*height, width); break;
case 15: Convert15To_I420Frame(s_screen->pixels, &result[0], width*height, width); break;
case 16: Convert16To_I420Frame(s_screen->pixels, &result[0], width*height, width); break;
}
NESVideoLoggingVideo(&result[0], width,height, fps, 12);
break;
#endif
default:
NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp);
}
}
#endif
#if REALTIME_LOGGING
{
static struct timeval last_time;
static int first_time=1;
extern long soundrate;
struct timeval cur_time;
gettimeofday(&cur_time, NULL);
double timediff =
(cur_time.tv_sec *1e6 + cur_time.tv_usec
- (last_time.tv_sec *1e6 + last_time.tv_usec)) / 1e6;
int nframes = timediff * 60 - 1;
if(first_time)
first_time = 0;
else while(nframes > 0)
{
static const unsigned char Buf[800*4] = {0};
NESVideoLoggingVideo(screen->pixels, 256,tlines, FCEUI_GetDesiredFPS(), s_curbpp);
NESVideoLoggingAudio(Buf, soundrate,16,1, soundrate/60.0);
--nframes;
}
memcpy(&last_time, &cur_time, sizeof(last_time));
}
#endif
#endif
#if SDL_VERSION_ATLEAST(2, 0, 0)
// TODO
#else
// have to flip the displayed buffer in the case of double buffering
if(s_screen->flags & SDL_DOUBLEBUF) {
SDL_Flip(s_screen);
}
#endif
}
/**
* Converts an x-y coordinate in the window manager into an x-y
* coordinate on FCEU's screen.
*/
uint32
PtoV(uint16 x,
uint16 y)
{
y = (uint16)((double)y / s_eys);
x = (uint16)((double)x / s_exs);
if(s_clipSides) {
x += 8;
}
y += s_srendline;
return (x | (y << 16));
}
bool enableHUDrecording = false;
bool FCEUI_AviEnableHUDrecording()
{
if (enableHUDrecording)
return true;
return false;
}
void FCEUI_SetAviEnableHUDrecording(bool enable)
{
enableHUDrecording = enable;
}
bool disableMovieMessages = false;
bool FCEUI_AviDisableMovieMessages()
{
if (disableMovieMessages)
return true;
return false;
}
void FCEUI_SetAviDisableMovieMessages(bool disable)
{
disableMovieMessages = disable;
}
-18
View File
@@ -1,18 +0,0 @@
#ifndef __FCEU_SDL_VIDEO_H
#define __FCEU_SDL_VIDEO_H
#ifdef _SDL2
#include <SDL2/SDL.h>
#else
#include <SDL.h>
#endif
uint32 PtoV(uint16 x, uint16 y);
bool FCEUD_ShouldDrawInputAids();
bool FCEUI_AviDisableMovieMessages();
static SDL_Surface *s_screen;
bool FCEUI_AviEnableHUDrecording();
void FCEUI_SetAviEnableHUDrecording(bool enable);
bool FCEUI_AviDisableMovieMessages();
void FCEUI_SetAviDisableMovieMessages(bool disable);
#endif
File diff suppressed because it is too large Load Diff
+7 -7
View File
@@ -1,15 +1,15 @@
#ifndef __FCEU_SDL_H
#define __FCEU_SDL_H
#if _SDL2
#include <SDL2/SDL.h>
#else
//#if _SDL2
//#include <SDL2/SDL.h>
//#else
//#include <SDL.h>
#endif
//#endif
#include "main.h"
#include "dface.h"
#include "input.h"
//#include "dface.h"
//#include "input.h"
// I'm using this as a #define so the compiler can optimize the
// modulo operation
@@ -24,7 +24,7 @@ extern int dendy;
extern int pal_emulation;
extern bool swapDuty;
int LoadGame(const char *path);
int LoadGame(const char *path, bool silent = false);
int CloseGame(void);
void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count);
uint64 FCEUD_GetTime();
-2
View File
@@ -1,2 +0,0 @@
void RefreshThrottleFPS();
int SpeedThrottle(void);
-360
View File
@@ -1,360 +0,0 @@
/* 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
*/
//todo - ensure that #ifdef WIN32 makes sense
//consider changing this to use sdl net stuff?
#include "main.h"
#include "input.h"
#include "dface.h"
#include "unix-netplay.h"
#include "../../fceu.h"
#include "../../utils/md5.h"
#include "../../utils/memory.h"
#include <string>
#include "../common/configSys.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cerrno>
#include <fcntl.h>
#ifdef WIN32
#include <winsock.h>
#else
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif
extern Config *g_config;
#ifndef socklen_t
#define socklen_t int
#endif
#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
#endif
int FCEUDnetplay=0;
static int s_Socket = -1;
static void
en32(uint8 *buf,
uint32 morp)
{
buf[0] = morp;
buf[1] = morp >> 8;
buf[2] = morp >> 16;
buf[3] = morp >> 24;
}
/*
static uint32 de32(uint8 *morp)
{
return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24));
}
*/
int
FCEUD_NetworkConnect(void)
{
struct sockaddr_in sockin;
struct hostent *phostentb;
unsigned long hadr;
int TSocket, tcpopt, error;
int netdivisor;
// get any required configuration variables
int port, localPlayers;
std::string server, username, password, key;
g_config->getOption("SDL.NetworkIP", &server);
g_config->getOption("SDL.NetworkUsername", &username);
g_config->getOption("SDL.NetworkPassword", &password);
g_config->getOption("SDL.NetworkGameKey", &key);
g_config->getOption("SDL.NetworkPort", &port);
g_config->getOption("SDL.NetworkPlayers", &localPlayers);
g_config->setOption("SDL.NetworkIP", "");
g_config->setOption("SDL.NetworkPassword", "");
g_config->setOption("SDL.NetworkGameKey", "");
// only initialize if remote server is specified
if(!server.size()) {
return 0;
}
TSocket = socket(AF_INET, SOCK_STREAM, 0);
if(TSocket < 0) {
char* s = "Error creating stream socket.";
puts(s);
FCEU_DispMessage(s,0);
FCEUD_NetworkClose();
return 0;
}
// try to setup TCP_NODELAY to avoid network jitters
tcpopt = 1;
#ifdef BEOS
error = setsockopt(TSocket, SOL_SOCKET, TCP_NODELAY, &tcpopt, sizeof(int));
#elif WIN32
error = setsockopt(TSocket, SOL_TCP, TCP_NODELAY,
(char*)&tcpopt, sizeof(int));
#else
error = setsockopt(TSocket, SOL_TCP, TCP_NODELAY, &tcpopt, sizeof(int));
#endif
if(error) {
puts("Nodelay fail");
}
memset(&sockin, 0, sizeof(sockin));
sockin.sin_family = AF_INET;
hadr = inet_addr(server.c_str());
if(hadr != INADDR_NONE) {
sockin.sin_addr.s_addr = hadr;
} else {
puts("*** Looking up host name...");
phostentb = gethostbyname(server.c_str());
if(!phostentb) {
puts("Error getting host network information.");
FCEU_DispMessage("Error getting host info",0);
close(TSocket);
FCEUD_NetworkClose();
return(0);
}
memcpy(&sockin.sin_addr, phostentb->h_addr, phostentb->h_length);
}
sockin.sin_port = htons(port);
puts("*** Connecting to remote host...");
error = connect(TSocket, (struct sockaddr *)&sockin, sizeof(sockin));
if(error < 0) {
puts("Error connecting to remote host.");
FCEU_DispMessage("Error connecting to server",0);
close(TSocket);
FCEUD_NetworkClose();
return 0;
}
s_Socket = TSocket;
puts("*** Sending initialization data to server...");
uint8 *sendbuf;
uint8 buf[5];
uint32 sblen;
sblen = 4 + 16 + 16 + 64 + 1 + username.size();
sendbuf = (uint8 *)FCEU_dmalloc(sblen);
memset(sendbuf, 0, sblen);
// XXX soules - should use htons instead of en32() from above!
//uint32 data = htons(sblen - 4);
//memcpy(sendbuf, &data, sizeof(data));
en32(sendbuf, sblen - 4);
if(key.size())
{
struct md5_context md5;
uint8 md5out[16];
md5_starts(&md5);
md5_update(&md5, (uint8*)&GameInfo->MD5.data, 16);
md5_update(&md5, (uint8 *)key.c_str(), key.size());
md5_finish(&md5, md5out);
memcpy(sendbuf + 4, md5out, 16);
} else
{
memcpy(sendbuf + 4, (uint8*)&GameInfo->MD5.data, 16);
}
if(password.size()) {
struct md5_context md5;
uint8 md5out[16];
md5_starts(&md5);
md5_update(&md5, (uint8 *)password.c_str(), password.size());
md5_finish(&md5, md5out);
memcpy(sendbuf + 4 + 16, md5out, 16);
}
memset(sendbuf + 4 + 16 + 16, 0, 64);
sendbuf[4 + 16 + 16 + 64] = (uint8)localPlayers;
if(username.size()) {
memcpy(sendbuf + 4 + 16 + 16 + 64 + 1,
username.c_str(), username.size());
}
#ifdef WIN32
send(s_Socket, (char*)sendbuf, sblen, 0);
#else
send(s_Socket, sendbuf, sblen, 0);
#endif
FCEU_dfree(sendbuf);
#ifdef WIN32
recv(s_Socket, (char*)buf, 1, 0);
#else
recv(s_Socket, buf, 1, MSG_WAITALL);
#endif
netdivisor = buf[0];
puts("*** Connection established.");
FCEU_DispMessage("Connection established.",0);
FCEUDnetplay = 1;
FCEUI_NetplayStart(localPlayers, netdivisor);
return 1;
}
int
FCEUD_SendData(void *data,
uint32 len)
{
int check = 0, error = 0;
#ifndef WIN32
error = ioctl(fileno(stdin), FIONREAD, &check);
#endif
if(!error && check) {
char buf[1024];
char *f;
fgets(buf, 1024, stdin);
if((f=strrchr(buf,'\n'))) {
*f = 0;
}
FCEUI_NetplayText((uint8 *)buf);
}
#ifdef WIN32
send(s_Socket, (char*)data, len ,0);
#else
send(s_Socket, data, len ,0);
#endif
return 1;
}
int
FCEUD_RecvData(void *data,
uint32 len)
{
int size;
NoWaiting &= ~2;
for(;;)
{
fd_set funfun;
struct timeval popeye;
popeye.tv_sec=0;
popeye.tv_usec=100000;
FD_ZERO(&funfun);
FD_SET(s_Socket, &funfun);
switch(select(s_Socket + 1,&funfun,0,0,&popeye)) {
case 0: continue;
case -1:return 0;
}
if(FD_ISSET(s_Socket,&funfun)) {
#ifdef WIN32
size = recv(s_Socket, (char*)data, len, 0);
#else
size = recv(s_Socket, data, len, MSG_WAITALL);
#endif
if(size == len) {
//unsigned long beefie;
FD_ZERO(&funfun);
FD_SET(s_Socket, &funfun);
popeye.tv_sec = popeye.tv_usec = 0;
if(select(s_Socket + 1, &funfun, 0, 0, &popeye) == 1)
//if(!ioctl(s_Socket,FIONREAD,&beefie))
// if(beefie)
{
NoWaiting|=2;
}
return 1;
} else {
return 0;
}
}
}
return 0;
}
void
FCEUD_NetworkClose(void)
{
if(s_Socket > 0) {
#ifdef BEOS
closesocket(s_Socket);
#else
close(s_Socket);
#endif
}
s_Socket = -1;
if(FCEUDnetplay) {
FCEUI_NetplayStop();
}
FCEUDnetplay = 0;
}
void
FCEUD_NetplayText(uint8 *text)
{
char *tot = (char *)FCEU_dmalloc(strlen((const char *)text) + 1);
char *tmp;
if (!tot)
return;
strcpy(tot, (const char *)text);
tmp = tot;
while(*tmp) {
if(*tmp < 0x20) {
*tmp = ' ';
}
tmp++;
}
puts(tot);
FCEU_dfree(tot);
}
-6
View File
@@ -1,6 +0,0 @@
extern char *netplaynick;
extern char *netplayhost;
extern char *netpassword;
extern char *netgamekey;
extern int tport;
extern int netlocalplayers;
-14
View File
@@ -1,14 +0,0 @@
my_list = Split("""
nesvideos-piece.cpp
rgbtorgb.cpp
""")
Import('env')
if env['LOGO']:
env.Append(CCFLAGS = "-DHAVE_GD")
for x in range(len(my_list)):
my_list[x] = 'drivers/videolog/' + my_list[x]
Return('my_list')
+2 -2
View File
@@ -828,7 +828,7 @@ extern "C"
|| new_height != LogoInfo::height)
{
if(new_height < LogoInfo::height || new_height > LogoInfo::height+20)
fprintf(stderr, "'%s': ERROR, expected %dx%d, got %dx%d\n", fn,
fprintf(stderr, "'%s': ERROR, expected %ux%u, got %ux%u\n", fn,
LogoInfo::width, LogoInfo::height,
new_width, new_height);
}
@@ -857,7 +857,7 @@ extern "C"
std::string avdir = "/home/you/yourlogo/";
char AvName[512];
sprintf(AvName, "logo_%d_%d_f%03u.png",
sprintf(AvName, "logo_%u_%u_f%03u.png",
LogoInfo::width,
LogoInfo::height,
frameno);
Binary file not shown.

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