Merge branch 'master' into Issue130

This commit is contained in:
Alexey 'Cluster' Avdyukhin 2020-10-08 19:56:48 +03:00 committed by GitHub
commit 9d837056c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
136 changed files with 23536 additions and 5500 deletions

1
CNAME Normal file
View File

@ -0,0 +1 @@
fceux.com

View File

@ -1,7 +1,9 @@
To compile and install FCEUX for SDL, follow the instructions in the README-SDL.md file.
Users of Microsoft Visual Studio can use the solution files within the vc directory.
Users of Microsoft Visual Studio can use the solution files within the vc directory. The Windows XP toolset is required to open and build this solution. If it
is not installed, go to "Tools" > "Get Tools and Features". Select "Individual Components" and then install "C++ Windows XP Support for VS 2017 (v141) tools".
These solution files will compile FCEUX and some included libraries for full functionality.
CMake has been depreciated in favor of scons. However, if you wish to use it you can find the old cmake build files in the attic.
The SDL port build tool of choice has come full circle back to Cmake. The cmake build tool will compile the new Qt version of the SDL GUI.
The scons build tool will build the older GTK based GUI which currently only builds on Linux.

19
README
View File

@ -24,7 +24,7 @@ Table of Contents
----------------
* sdl2 - Version >= 2.0
* cmake - Required to build fceux.
* qt5 - version >= 5.11 recommended
* qt5 OR gtk3 - (qt version >= 5.11 recommended) (gtk3 >= 3.22 recommended)
* liblua5.1 (optional) - Will statically link internally if the system cannot provide this.
* minizip
* zlib
@ -33,6 +33,7 @@ Table of Contents
2 - Installation
----------------
The old scons build system is no longer supported.
Fceux can be compiled and built using the cmake build system. To compile, run:
mkdir build; cd build;
@ -41,6 +42,11 @@ Fceux can be compiled and built using the cmake build system. To compile, run:
To build a binary with debug information included in it:
cmake -DCMAKE_BUILD_TYPE=Debug ..
The Qt version of the GUI builds by default and this is the preferred GUI for use.
For those who must have GTK/Gnome style,
the GTK version of the GUI can be selected to build with:
cmake -DCMAKE_BUILD_TYPE=Release -DGTK=1 .. # Release build using GTK GUI
To do the actual compiling:
make
@ -50,7 +56,7 @@ To compile faster with multiple processes in parallel:
After a sucessful compilation, the fceux binary will be generated to
./build/src/fceux . You can install fceux to your system with the following command:
make install
sudo make install
You can optionally define a install prefix when running cmake from the previous step:
@ -75,7 +81,12 @@ Look in the src/CMakeList.txt file to tweak options.
4 - GUI
-------
The Qt GUI is required and automatically builds as part of the build.
The Qt (or GTK) GUI is required and automatically builds as part of the build. The Qt GUI is the default.
When invoking cmake, the GTK GUI can be built (instead of Qt) by specifying a -DGTK=1 on the command line.
See above build instructions.
OpenGL options:
For Linux builds, the OpenGL library preference can be either GLVND or LEGACY (default).
To use GLVND OpenGL, add a -DGLVND=1 on the cmake command line.
5 - LUA Scripting
-----------------
@ -107,7 +118,7 @@ The latest version of iup (3.5 at the time of writing) is recommended.
-------
* Q. Im having issues with my sound!
* A. First of all, for the best sound quality be sure you are using SDL 1.2.14 or later. Versions 1.2.13 and earlier are known to have problems with fceux! Next, try different SDL audio drivers to see if this makes any difference. You can do this by using this command before running fceux:
* A. Try different SDL audio drivers to see if this makes any difference. You can do this by using this command before running fceux:
export SDL_AUDIODRIVER=driver

View File

@ -98,16 +98,16 @@ else:
conf.env.Append(CCFLAGS = "-DHAVE_ASPRINTF")
if env['SYSTEM_MINIZIP']:
assert env.ParseConfig('pkg-config minizip --cflags --libs'), "please install: libminizip"
assert conf.CheckLibWithHeader('z', 'zlib.h', 'c', 'inflate;', 1), "please install: zlib"
assert env.ParseConfig('pkg-config zlib --cflags --libs'), "please install: zlib"
#assert conf.CheckLibWithHeader('z', 'zlib.h', 'c', 'inflate;', 1), "please install: zlib"
env.Append(CPPDEFINES=["_SYSTEM_MINIZIP"])
else:
assert conf.CheckLibWithHeader('z', 'zlib.h', 'c', 'inflate;', 1), "please install: zlib"
assert env.ParseConfig('pkg-config zlib --cflags --libs'), "please install: zlib"
#assert conf.CheckLibWithHeader('z', 'zlib.h', 'c', 'inflate;', 1), "please install: zlib"
if env['SDL2']:
if not conf.CheckLib('SDL2'):
print('Did not find libSDL2 or SDL2.lib, exiting!')
Exit(1)
assert env.ParseConfig('pkg-config sdl2 --cflags --libs'), "please install: sdl2"
env.Append(CPPDEFINES=["_SDL2"])
env.ParseConfig('pkg-config sdl2 --cflags --libs')
#env.ParseConfig('pkg-config sdl2 --cflags --libs')
else:
if not conf.CheckLib('SDL'):
print('Did not find libSDL or SDL.lib, exiting!')

View File

@ -1,21 +1,66 @@
Priorities
==========
* Clean out old unused files - scons build system is dead, cmake is the way to go.
* GTK GUI was not cross-platform. Has been replaced in favor of Qt5. Need to clean out dead code.
* Cheat Editor will be a high priority.
* Code cleanup. Lots of compiler warning with newer GCC. Maybe I'm OCD... but these warnings bother me.
* GTK GUI was not cross-platform. A Qt5 version of the GUI has been created to meet this need.
I will keep the GTK GUI around for Linux users who prefer it, but when it comes to adding new features
the Qt GUI is where I plan to add them first (if at all).
* Code cleanup. Lots of compiler warnings with newer GCC. Maybe I'm OCD... but these warnings bother me.
Features
========
* Emulator no runs as a separate thread from the GUI. Much improved performance.
* Cross platform QT GUI is fully functional minus Debug Tools and Cheat Menu.
* Cross platform QT GUI is fully functional minus Debug Tools.
---------------------------------------------------------------------------------|
---------------------- GUI Capability Matrix -----------------------------------|
---------------------------------------------------------------------------------|
Feature | Qt5 | GTK3 |
-----------------------------------------------------|-------------|-------------|
Basic game ROM open/run and close via menu functions | YES | YES |
Load/save game states | YES | YES |
Select and execute Lua script via file browser | YES | YES |
Lua Console/Control Window | YES | NO |
Screenshot snap/save functionality | YES | YES |
Virtual game pad button mapping window | YES | YES |
Other input device type button mapping window | NO | NO |
Audio mixer / config window | YES | YES |
Video config window | YES | YES |
OpenGL graphics | YES | YES |
Hot key config window | YES | YES |
Palette config window | YES | YES |
Multi-thread (GUI and emulation on separate threads) | YES | NO |
Emulation speed control via menu | NO | NO |
Emulation speed control via hotkeys | YES | YES |
Fullscreen functionality | YES | YES |
AVI Record Functionality | NO | NO |
NES Emulation Power/Reset/Pause functionality | YES | YES |
Game genie load/enable capability | YES | YES |
Movie record/save/play functionality | YES | YES |
Cheat search window | YES | YES |
Active Cheat window | YES | YES |
RAM Search Window | NO | NO |
RAM Watch Window | NO | YES |
Memory Watch Window | NO | NO |
TAS Editor | NO | NO |
6502 Debugger Window | YES | YES |
PPU Viewer | YES | NO |
Name Table Viewer | YES | NO |
Memory Hex Editor | YES | YES |
Trace Logger | YES | NO |
Code/Data Logger | YES | NO |
Game Genie Encoder/Decoder | NO | NO |
iNES Header Editor | NO | NO |
Built in help pages | NO | NO |
Network play (who actually uses this???) | NO | NO |
-----------------------------------------------------|-------------|-------------|
---------------------------------------------------------------------------------|
---------------------------------------------------------------------------------|
QT
===
* Clean out rest of old GTK comments and #ifdefs
* GUI Cheat editor TODO
* GUI Debug Tools TODO
* GUI should compile in windows as well.... but testing is not a priority since the windows gui has a totally separate backend.
* GUI should compile in windows as well.... but testing is not a priority since the windows gui already has a totally separate backend.
BUGS
====

View File

@ -10,7 +10,9 @@ my $PKG_OUTPUT_FILE="fceux-$VERSION-$ARCH.deb";
# Start by auto figuring out dependencies of the executable.
# the rest of the package creation is trival.
my $SO_LIST=`objdump -x $INSTALL_PREFIX/usr/bin/fceux`;
my $SO_LIST="";
$SO_LIST=`objdump -x $INSTALL_PREFIX/usr/bin/fceux`;
$SO_LIST= $SO_LIST . `objdump -x $INSTALL_PREFIX/usr/bin/fceux-gtk`;
#print "$SO_LIST";

View File

@ -60,8 +60,8 @@ pkg-config --cflags --libs minizip
#echo '****************************************'
#echo 'Install Dependency libgtk-3-dev'
#echo '****************************************'
#sudo apt-get --assume-yes install libgtk-3-dev
#pkg-config --cflags --libs gtk+-3.0
sudo apt-get --assume-yes install libgtk-3-dev
pkg-config --cflags --libs gtk+-3.0
#
## Install GTK+-3 Sourceview
#sudo apt-get --assume-yes install libgtksourceview-3.0-dev
@ -92,14 +92,24 @@ mkdir -p $INSTALL_PREFIX/usr;
#scons --clean
#scons GTK3=1 SYSTEM_LUA=1 SYSTEM_MINIZIP=1 CREATE_AVI=1 install --prefix=$INSTALL_PREFIX/usr
echo "Num CPU: `nproc`";
mkdir build; cd build;
#qmake PREFIX=$INSTALL_PREFIX/usr ..
mkdir buildQT; cd buildQT;
cmake \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX/usr \
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \
..
make -j `nproc`
make -j `nproc`
make install
cd ..;
mkdir buildGTK; cd buildGTK;
cmake \
-DGTK=1 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX/usr \
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \
..
make -j `nproc`
make install
# Install Files
@ -134,6 +144,16 @@ else
exit 1;
fi
if [ -e $INSTALL_PREFIX/usr/bin/fceux-gtk ]; then
echo '**************************************************************'
echo 'Printing Shared Object Dependencies for fceux-gtk Executable'
echo '**************************************************************'
ldd $INSTALL_PREFIX/usr/bin/fceux-gtk
else
echo "Error: Executable Failed to build: $INSTALL_PREFIX/usr/bin/fceux-gtk";
exit 1;
fi
echo '**************************************************************'
echo 'Printing To Be Packaged Files '
echo '**************************************************************'

View File

@ -8,6 +8,7 @@ Interim builds:
* Win32: [fceux.zip](https://ci.appveyor.com/api/projects/zeromus/fceux/artifacts/fceux.zip?branch=master&job=Windows%2032)
* Win64: [fceux64.zip](https://ci.appveyor.com/api/projects/zeromus/fceux/artifacts/fceux64.zip?branch=master&job=Windows%2064)
* Ubuntu: [fceux-2.2.3-amd64.deb](https://ci.appveyor.com/api/projects/zeromus/fceux/artifacts/fceux-2.2.3-amd64.deb?branch=master&job=Ubuntu)
* MacOSX: [fceux-2.2.3-Darwin.dmg](https://ci.appveyor.com/api/projects/zeromus/fceux/artifacts/fceux-2.2.3-Darwin.dmg?branch=master&job=MacOS)
* Status: [Appveyor](https://ci.appveyor.com/project/zeromus/fceux/)
But you might like mesen more: https://github.com/SourMesen/Mesen

View File

@ -1,9 +1,14 @@
if ( ${GTK} )
message( STATUS "GUI backend: GTK")
set( APP_NAME fceux-gtk)
else()
message( STATUS "GUI backend: QT")
set( APP_NAME fceux)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set( APP_NAME fceux)
endif()
if(WIN32)
set(SOURCES ${SRC_CORE} ${SRC_DRIVERS_COMMON} ${SRC_DRIVERS_WIN})
@ -21,20 +26,34 @@ else(WIN32)
# Non Windows System
# UNIX (Linux or Mac OSX)
#set (OpenGL_GL_PREFERENCE GLVND)
set (OpenGL_GL_PREFERENCE LEGACY)
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(Qt5 COMPONENTS Widgets OpenGL REQUIRED)
find_package(OpenGL REQUIRED)
find_package(ZLIB REQUIRED)
add_definitions( ${Qt5Widgets_DEFINITIONS} )
include_directories( ${Qt5Widgets_INCLUDE_DIRS} )
add_definitions( -Wall -Wno-write-strings -Wno-sign-compare -Wno-parentheses -Wno-unused-local-typedefs -fPIC )
add_definitions( -DFCEUDEF_DEBUGGER )
add_definitions( -D__QT_DRIVER__ -Wall -Wno-write-strings -Wno-sign-compare -Wno-parentheses -Wno-unused-local-typedefs -fPIC -DQT_DEPRECATED_WARNINGS )
if ( ${GTK} )
pkg_check_modules( GTK3 REQUIRED gtk+-3.0)
pkg_check_modules( X11 REQUIRED x11)
add_definitions( ${GTK3_CFLAGS} ${X11_CFLAGS} )
add_definitions( -D_GTK -DOPENGL )
else(${GTK})
find_package(Qt5 COMPONENTS Widgets OpenGL REQUIRED)
add_definitions( ${Qt5Widgets_DEFINITIONS} )
include_directories( ${Qt5Widgets_INCLUDE_DIRS} )
add_definitions( -D__QT_DRIVER__ -DQT_DEPRECATED_WARNINGS )
endif()
# Check for libminizip
pkg_check_modules( MINIZIP REQUIRED minizip)
@ -377,11 +396,31 @@ set(SRC_DRIVERS_COMMON
${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
${CMAKE_CURRENT_SOURCE_DIR}/drivers/videolog/nesvideos-piece.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/videolog/rgbtorgb.cpp
)
if ( ${GTK} )
set(SRC_DRIVERS_SDL
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/cheat.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/config.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/debugger.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/glxwin.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/gui.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/GamePadConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/input.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/memview.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/ramwatch.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/sdl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/sdl-joystick.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/sdl-sound.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/sdl-throttle.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/sdl-video.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/unix-netplay.cpp
)
else()
set(SRC_DRIVERS_SDL
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleWindow.cpp
@ -390,10 +429,21 @@ set(SRC_DRIVERS_SDL
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GamePadConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HotKeyConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/PaletteConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GuiConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/LuaControl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/CheatsConf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HexEditor.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/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/config.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/input.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/nes_shm.cpp
@ -404,6 +454,7 @@ set(SRC_DRIVERS_SDL
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/sdl-throttle.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/unix-netplay.cpp
)
endif()
set(SOURCES ${SRC_CORE} ${SRC_DRIVERS_COMMON} ${SRC_DRIVERS_SDL})
@ -424,11 +475,27 @@ add_executable( ${APP_NAME} MACOSX_BUNDLE ${APP_ICON} ${SOURCES} ../resources.
${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp)
else()
add_executable( ${APP_NAME} ${SOURCES} ../resources.qrc
${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp)
if ( ${GTK} )
add_executable( ${APP_NAME} ${SOURCES}
${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp)
else()
add_executable( ${APP_NAME} ${SOURCES} ../resources.qrc
${CMAKE_CURRENT_BINARY_DIR}/fceux_git_info.cpp)
endif()
endif()
target_link_libraries( fceux
if ( ${GTK} )
target_link_libraries( ${APP_NAME}
${GTK3_LDFLAGS} ${X11_LDFLAGS}
${OPENGL_LDFLAGS}
${SDL2_LDFLAGS}
${MINIZIP_LDFLAGS} ${ZLIB_LIBRARIES}
${LUA_LDFLAGS}
${SYS_LIBS}
)
else()
target_link_libraries( ${APP_NAME}
${Qt5Widgets_LIBRARIES}
${Qt5OpenGL_LIBRARIES}
${OPENGL_LDFLAGS}
@ -437,6 +504,7 @@ target_link_libraries( fceux
${LUA_LDFLAGS}
${SYS_LIBS}
)
endif()
if (APPLE)

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,11 +296,14 @@ 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);
SetWriteHandler(0x6000, 0xFFFF, BandaiWrite);
SetWriteHandler(0x8000, 0xFFFF, BandaiWrite);
}
static void StateRestore(int version) {
@ -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);
}

View File

@ -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;
}

View File

@ -82,10 +82,10 @@ 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)
@ -161,7 +161,7 @@ static DECLFW(BMCFK23CWrite)
EXPREGS[A&3]=V;
// BUT WHY is there any rom that need it actually?
bool remap = false;
// bool remap = false;
// FCEU_printf("K3:(exp0=%02x)\n",EXPREGS[0]);
// FCEU_printf("WH0:%04X:%02X\n",A,V);
@ -199,7 +199,7 @@ static void BMCFK23CReset(void)
//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);
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;

View File

@ -52,7 +52,9 @@ static void MMC1CHR(void) {
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));
@ -96,13 +98,13 @@ static DECLFW(MMC1_write) {
Buffer |= (V & 1) << (BufferShift++);
if (BufferShift == 5) {
FCEU_printf("MMC1 REG%d:%02x (PC %04x)\n", n, Buffer, X.PC);
DRegs[n] = Buffer;
// FCEU_printf("MMC1 REG%d:%02x\n", n, Buffer);
BufferShift = Buffer = 0;
switch (n) {
case 0: MMC1MIRROR(); // break;
case 1: // break;
// case 2: MMC1CHR(); break;
case 0: MMC1MIRROR();
case 1:
case 2:
case 3: MMC1PRG(); break;
}
}
@ -151,13 +153,13 @@ static DECLFW(FNC_cmd_write) {
break;
}
case 0x40C0: {
// FCEU_printf("FNS W %04x:%02x\n", A, V);
FCEU_printf("FNS W %04x:%02x (PC %04x)\n", A, V, X.PC);
r40C0 = V;
MMC1CHR();
break;
}
// default:
// FCEU_printf("FNS W %04x:%02x\n", A, V);
default:
FCEU_printf("FNS W %04x:%02x (PC %04x)\n", A, V, X.PC);
}
}
@ -169,23 +171,32 @@ static DECLFR(FNC_stat_read) {
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\n", A);
FCEU_printf("FNS R %04x (PC %04x)\n", A, X.PC);
int ret = r40C0;
r40C0 &= 0;
return ret;
}
default: {
// FCEU_printf("FNS R %04x\n", A);
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++;
@ -217,8 +228,9 @@ static void FNS_Power(void) {
SetReadHandler(0x4080, 0x40FF, FNC_stat_read);
SetReadHandler(0x5000, 0x5FFF, FNC_kanji_read);
SetReadHandler(0x6000, 0x7FFF, MAWRAM);
SetWriteHandler(0x6000, 0x7FFF, MBWRAM);
SetReadHandler(0x6000, 0x6000, FNC_cart_i2c_read);
SetReadHandler(0x6001, 0x7FFF, CartBR);
SetWriteHandler(0x6000, 0x7FFF, CartBW);
FCEU_CheatAddRAM(8, 0x6000, WRAM);
MMC1CMReset();

View File

@ -63,6 +63,7 @@ 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;
@ -569,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);
@ -921,7 +922,7 @@ inline void FCEUI_CreateCheatMap()
inline void FCEUI_RefreshCheatMap()
{
memset(cheatMap, 0, CHEATMAP_SIZE);
for (int i = 0; i < numsubcheats; ++i)
for (uint32 i = 0; i < numsubcheats; ++i)
FCEUI_SetCheatMapByte(SubCheats[i].addr, true);
}
@ -932,4 +933,4 @@ inline void FCEUI_ReleaseCheatMap()
free(cheatMap);
cheatMap = NULL;
}
}
}

View File

@ -194,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);

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,"%4X",(unsigned int *)&offset) == EOF)
{
return -1;
}
@ -421,12 +421,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){
@ -865,10 +865,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
}

View File

@ -59,6 +59,7 @@ typedef struct {
//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);

View File

@ -142,7 +142,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
@ -250,7 +252,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();
@ -340,7 +342,7 @@ 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
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,99 @@
// GamePadConf.h
//
#pragma once
#include <QWidget>
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
#include <QCheckBox>
#include <QPushButton>
#include <QLabel>
#include <QFrame>
#include <QLineEdit>
#include <QGroupBox>
#include <QTreeView>
#include <QTreeWidget>
#include <QTextEdit>
#include "Qt/main.h"
class GuiCheatsDialog_t : public QDialog
{
Q_OBJECT
public:
GuiCheatsDialog_t(QWidget *parent = 0);
~GuiCheatsDialog_t(void);
int addSearchResult( uint32_t a, uint8_t last, uint8_t current );
int activeCheatListCB (char *name, uint32 a, uint8 v, int c, int s, int type, void *data);
protected:
void closeEvent(QCloseEvent *event);
QGroupBox *actCheatFrame;
QGroupBox *cheatSearchFrame;
QGroupBox *cheatResultFrame;
QPushButton *addCheatBtn;
QPushButton *delCheatBtn;
QPushButton *modCheatBtn;
QPushButton *importCheatFileBtn;
QPushButton *exportCheatFileBtn;
QPushButton *srchResetBtn;
QPushButton *knownValBtn;
QPushButton *eqValBtn;
QPushButton *neValBtn;
QPushButton *grValBtn;
QPushButton *ltValBtn;
QCheckBox *useNeVal;
QCheckBox *useGrVal;
QCheckBox *useLtVal;
QCheckBox *enaCheats;
QCheckBox *autoSave;
QCheckBox *pauseBox;
QTreeWidget *actvCheatList;
QTreeWidget *srchResults;
QLineEdit *cheatNameEntry;
QLineEdit *cheatAddrEntry;
QLineEdit *cheatValEntry;
QLineEdit *cheatCmpEntry;
QLineEdit *knownValEntry;
QLineEdit *neValEntry;
QLineEdit *grValEntry;
QLineEdit *ltValEntry;
QFont font;
int fontCharWidth;
int actvCheatIdx;
bool actvCheatRedraw;
bool pauseWhileActive;
bool wasPausedByCheats;
private:
void showCheatSearchResults(void);
void showActiveCheatList(bool redraw);
public slots:
void closeWindow(void);
private slots:
void resetSearchCallback(void);
void knownValueCallback(void);
void equalValueCallback(void);
void notEqualValueCallback(void);
void lessThanValueCallback(void);
void greaterThanValueCallback(void);
void openCheatFile(void);
void saveCheatFile(void);
void addActvCheat(void);
void deleteActvCheat(void);
void updateCheatParameters(void);
void autoLoadSaveCheats(int state);
void globalEnableCheats(int state);
void pauseWindowState(int state);
void actvCheatItemClicked( QTreeWidgetItem *item, int column);
};

View File

@ -0,0 +1,840 @@
// CodeDataLogger.cpp
//
#include <QDir>
#include <QFileDialog>
#include <QInputDialog>
#include <QMessageBox>
#include "../../types.h"
#include "../../fceu.h"
#include "../../cart.h"
#include "../../x6502.h"
#include "../../debug.h"
#include "../../ppu.h"
#include "../../ines.h"
#include "../../nsf.h"
#include "Qt/ConsoleUtilities.h"
#include "Qt/CodeDataLogger.h"
#include "Qt/main.h"
#include "Qt/dface.h"
#include "Qt/input.h"
#include "Qt/config.h"
#include "Qt/fceuWrapper.h"
static int autoSaveCDL = true;
static int autoLoadCDL = true;
static int autoResumeCDL = false;
static char loadedcdfile[512] = {0};
static int getDefaultCDLFile( char *filepath );
//----------------------------------------------------
CodeDataLoggerDialog_t::CodeDataLoggerDialog_t(QWidget *parent)
: QDialog( parent )
{
QVBoxLayout *mainLayout, *vbox1, *vbox;
QHBoxLayout *hbox;
QGridLayout *grid;
QGroupBox *frame, *subframe;
QPushButton *btn;
updateTimer = new QTimer( this );
connect( updateTimer, &QTimer::timeout, this, &CodeDataLoggerDialog_t::updatePeriodic );
setWindowTitle( tr("Code Data Logger") );
mainLayout = new QVBoxLayout();
vbox1 = new QVBoxLayout();
hbox = new QHBoxLayout();
grid = new QGridLayout();
statLabel = new QLabel( tr(" Logger is Paused: Press Start to Run ") );
cdlFileLabel = new QLabel( tr("CDL File:") );
vbox1->addLayout( grid );
vbox1->addLayout( hbox );
vbox1->addWidget( cdlFileLabel );
hbox->addWidget( statLabel, 0, Qt::AlignHCenter );
frame = new QGroupBox(tr("Code/Data Log Status"));
frame->setLayout( vbox1 );
prgLoggedCodeLabel = new QLabel( tr("0x000000 0.00%") );
prgLoggedDataLabel = new QLabel( tr("0x000000 0.00%") );
prgUnloggedLabel = new QLabel( tr("0x000000 0.00%") );
chrLoggedCodeLabel = new QLabel( tr("0x000000 0.00%") );
chrLoggedDataLabel = new QLabel( tr("0x000000 0.00%") );
chrUnloggedLabel = new QLabel( tr("0x000000 0.00%") );
autoSaveCdlCbox = new QCheckBox( tr("Auto-save .CDL when closing ROMs") );
autoLoadCdlCbox = new QCheckBox( tr("Auto-load .CDL when opening this window") );
autoResumeLogCbox = new QCheckBox( tr("Auto-resume logging when loading ROMs") );
g_config->getOption("SDL.AutoSaveCDL", &autoSaveCDL);
g_config->getOption("SDL.AutoLoadCDL", &autoLoadCDL);
g_config->getOption("SDL.AutoResumeCDL", &autoResumeCDL);
autoSaveCdlCbox->setChecked( autoSaveCDL );
autoLoadCdlCbox->setChecked( autoLoadCDL );
autoResumeLogCbox->setChecked( autoResumeCDL );
connect(autoSaveCdlCbox , SIGNAL(stateChanged(int)), this, SLOT(autoSaveCdlStateChange(int)) );
connect(autoLoadCdlCbox , SIGNAL(stateChanged(int)), this, SLOT(autoLoadCdlStateChange(int)) );
connect(autoResumeLogCbox, SIGNAL(stateChanged(int)), this, SLOT(autoResumeCdlStateChange(int)) );
subframe = new QGroupBox(tr("PRG Logged as Code"));
vbox = new QVBoxLayout();
vbox->addWidget( prgLoggedCodeLabel );
subframe->setLayout( vbox );
grid->addWidget( subframe, 0, 0, Qt::AlignCenter );
subframe = new QGroupBox(tr("PRG Logged as Data"));
vbox = new QVBoxLayout();
vbox->addWidget( prgLoggedDataLabel );
subframe->setLayout( vbox );
grid->addWidget( subframe, 0, 1, Qt::AlignCenter );
subframe = new QGroupBox(tr("PRG not Logged"));
vbox = new QVBoxLayout();
vbox->addWidget( prgUnloggedLabel );
subframe->setLayout( vbox );
grid->addWidget( subframe, 0, 2, Qt::AlignCenter );
subframe = new QGroupBox(tr("CHR Logged as Code"));
vbox = new QVBoxLayout();
vbox->addWidget( chrLoggedCodeLabel );
subframe->setLayout( vbox );
grid->addWidget( subframe, 1, 0, Qt::AlignCenter );
subframe = new QGroupBox(tr("CHR Logged as Data"));
vbox = new QVBoxLayout();
vbox->addWidget( chrLoggedDataLabel );
subframe->setLayout( vbox );
grid->addWidget( subframe, 1, 1, Qt::AlignCenter );
subframe = new QGroupBox(tr("CHR not Logged"));
vbox = new QVBoxLayout();
vbox->addWidget( chrUnloggedLabel );
subframe->setLayout( vbox );
grid->addWidget( subframe, 1, 2, Qt::AlignCenter );
grid = new QGridLayout();
vbox1->addLayout( grid );
btn = new QPushButton( tr("Reset Log") );
grid->addWidget( btn, 0, 0, Qt::AlignCenter );
connect( btn, SIGNAL(clicked(void)), this, SLOT(ResetCDLogClicked(void)));
startPauseButton = new QPushButton( tr("Start") );
grid->addWidget( startPauseButton, 0, 1, Qt::AlignCenter );
connect( startPauseButton, SIGNAL(clicked(void)), this, SLOT(StartPauseCDLogClicked(void)));
btn = new QPushButton( tr("Save") );
grid->addWidget( btn, 0, 2, Qt::AlignCenter );
connect( btn, SIGNAL(clicked(void)), this, SLOT(saveCdlFile(void)));
btn = new QPushButton( tr("Load") );
grid->addWidget( btn, 1, 0, Qt::AlignCenter );
connect( btn, SIGNAL(clicked(void)), this, SLOT(loadCdlFile(void)));
btn = new QPushButton( tr("Save As") );
grid->addWidget( btn, 1, 2, Qt::AlignCenter );
connect( btn, SIGNAL(clicked(void)), this, SLOT(saveCdlFileAs(void)));
hbox = new QHBoxLayout();
vbox1->addLayout( hbox );
subframe = new QGroupBox(tr("Logging Workflow Options"));
vbox = new QVBoxLayout();
vbox->addWidget( autoSaveCdlCbox );
vbox->addWidget( autoLoadCdlCbox );
vbox->addWidget( autoResumeLogCbox );
subframe->setLayout( vbox );
hbox->addWidget( subframe );
subframe = new QGroupBox(tr("Generate ROM"));
vbox = new QVBoxLayout();
btn = new QPushButton( tr("Save Stripped Data") );
vbox->addWidget( btn );
connect( btn, SIGNAL(clicked(void)), this, SLOT(SaveStrippedROMClicked(void)));
btn = new QPushButton( tr("Save Unused Data") );
vbox->addWidget( btn );
connect( btn, SIGNAL(clicked(void)), this, SLOT(SaveUnusedROMClicked(void)));
subframe->setLayout( vbox );
hbox->addWidget( subframe );
mainLayout->addWidget( frame );
setLayout( mainLayout );
updateTimer->start( 200 ); // 5hz
if (autoLoadCDL)
{
char nameo[2048];
getDefaultCDLFile( nameo );
LoadCDLog(nameo);
}
}
//----------------------------------------------------
CodeDataLoggerDialog_t::~CodeDataLoggerDialog_t(void)
{
updateTimer->stop();
printf("Code Data Logger Window Deleted\n");
}
//----------------------------------------------------
void CodeDataLoggerDialog_t::closeEvent(QCloseEvent *event)
{
printf("Code Data Logger Close Window Event\n");
done(0);
deleteLater();
event->accept();
}
//----------------------------------------------------
void CodeDataLoggerDialog_t::closeWindow(void)
{
printf("Code Data Logger Close Window\n");
done(0);
deleteLater();
}
//----------------------------------------------------
void CodeDataLoggerDialog_t::autoSaveCdlStateChange(int state)
{
autoSaveCDL = state != Qt::Unchecked;
g_config->setOption("SDL.AutoSaveCDL", autoSaveCDL);
}
//----------------------------------------------------
void CodeDataLoggerDialog_t::autoLoadCdlStateChange(int state)
{
autoLoadCDL = state != Qt::Unchecked;
g_config->setOption("SDL.AutoLoadCDL", autoLoadCDL);
}
//----------------------------------------------------
void CodeDataLoggerDialog_t::autoResumeCdlStateChange(int state)
{
autoResumeCDL = state != Qt::Unchecked;
g_config->setOption("SDL.AutoResumeCDL", autoResumeCDL);
}
//----------------------------------------------------
void CodeDataLoggerDialog_t::updatePeriodic(void)
{
char str[768];
float fcodecount = codecount;
float fdatacount = datacount;
float frendercount = rendercount;
float fvromreadcount = vromreadcount;
float fundefinedcount = undefinedcount;
float fundefinedvromcount = undefinedvromcount;
float fromsize = cdloggerdataSize;
float fvromsize = (cdloggerVideoDataSize != 0) ? cdloggerVideoDataSize : 1;
if ( FCEUI_GetLoggingCD() )
{
startPauseButton->setText( tr("Pause") );
statLabel->setText( tr(" Logger is Running: Press Pause to Stop ") );
statLabel->setStyleSheet("background-color: green; color: white;");
}
else
{
startPauseButton->setText( tr("Start") );
statLabel->setText( tr(" Logger is Paused: Press Start to Run ") );
statLabel->setStyleSheet("background-color: red; color: white;");
}
if ( cdloggerdataSize > 0 )
{
sprintf(str,"0x%06x %.2f%%", codecount, (fcodecount / fromsize) * 100);
prgLoggedCodeLabel->setText( tr(str) );
sprintf(str,"0x%06x %.2f%%", datacount,(fdatacount / fromsize) * 100);
prgLoggedDataLabel->setText( tr(str) );
sprintf(str,"0x%06x %.2f%%", undefinedcount, (fundefinedcount / fromsize) * 100);
prgUnloggedLabel->setText( tr(str) );
sprintf(str,"0x%06x %.2f%%", rendercount, (frendercount / fvromsize) * 100);
chrLoggedCodeLabel->setText( tr(str) );
sprintf(str,"0x%06x %.2f%%", vromreadcount, (fvromreadcount / fvromsize) * 100);
chrLoggedDataLabel->setText( tr(str) );
sprintf(str,"0x%06x %.2f%%", undefinedvromcount, (fundefinedvromcount / fvromsize) * 100);
chrUnloggedLabel->setText( tr(str) );
}
else
{
prgLoggedCodeLabel->setText( tr("------") );
prgLoggedDataLabel->setText( tr("------") );
prgUnloggedLabel->setText( tr("------") );
chrLoggedCodeLabel->setText( tr("------") );
chrLoggedDataLabel->setText( tr("------") );
chrUnloggedLabel->setText( tr("------") );
}
sprintf( str, "CDL File: %s", loadedcdfile );
cdlFileLabel->setText( tr(str) );
}
//----------------------------------------------------
void CodeDataLoggerDialog_t::ResetCDLogClicked(void)
{
::ResetCDLog();
}
//----------------------------------------------------
void CodeDataLoggerDialog_t::StartPauseCDLogClicked(void)
{
if ( FCEUI_GetLoggingCD() )
{
//printf("CD Logging Paused\n");
PauseCDLogging();
startPauseButton->setText( tr("Start") );
}
else
{
//printf("CD Logging Started\n");
StartCDLogging();
startPauseButton->setText( tr("Pause") );
}
}
//----------------------------------------------------
void CodeDataLoggerDialog_t::saveCdlFile(void)
{
SaveCDLogFile();
}
//----------------------------------------------------
void CodeDataLoggerDialog_t::saveCdlFileAs(void)
{
int ret, useNativeFileDialogVal;
QString filename;
const char *romFile;
QFileDialog dialog(this, tr("Save CDL To File") );
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilter(tr("CDL Files (*.cdl *.CDL) ;; All files (*)"));
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Save") );
dialog.setDefaultSuffix( tr(".cdl") );
romFile = getRomFile();
if ( romFile != NULL )
{
char dir[512], base[256];
parseFilepath( romFile, dir, base );
strcat( base, ".cdl");
dialog.setDirectory( tr(dir) );
dialog.selectFile( tr(base) );
}
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.show();
ret = dialog.exec();
if ( ret )
{
QStringList fileList;
fileList = dialog.selectedFiles();
if ( fileList.size() > 0 )
{
filename = fileList[0];
}
}
if ( filename.isNull() )
{
return;
}
//qDebug() << "selected file path : " << filename.toUtf8();
fceuWrapperLock();
strcpy( loadedcdfile, filename.toStdString().c_str() );
SaveCDLogFile();
fceuWrapperUnLock();
}
//----------------------------------------------------
void CodeDataLoggerDialog_t::loadCdlFile(void)
{
int ret, useNativeFileDialogVal;
QString filename;
char dir[512];
const char *romFile;
QFileDialog dialog(this, tr("Load CDL File") );
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilter(tr("CDL files (*.cdl *.CDL) ;; All files (*)"));
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Load") );
romFile = getRomFile();
if ( romFile )
{
getDirFromFile( romFile, dir );
dialog.setDirectory( tr(dir) );
}
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.show();
ret = dialog.exec();
if ( ret )
{
QStringList fileList;
fileList = dialog.selectedFiles();
if ( fileList.size() > 0 )
{
filename = fileList[0];
}
}
if ( filename.isNull() )
{
return;
}
//qDebug() << "selected file path : " << filename.toUtf8();
fceuWrapperLock();
LoadCDLog ( filename.toStdString().c_str() );
fceuWrapperUnLock();
return;
}
//----------------------------------------------------
void CodeDataLoggerDialog_t::SaveStrippedROM(int invert)
{
//this is based off of iNesSave()
//todo: make this support NSF
//
if (!GameInfo)
return;
if (GameInfo->type==GIT_NSF)
{
printf("Sorry, you're not allowed to save optimized NSFs yet. Please don't optimize individual banks, as there are still some issues with several NSFs to be fixed, and it is easier to fix those issues with as much of the bank data intact as possible.");
return;
}
if (codecount == 0)
{
printf("Unable to Generate Stripped ROM. Get Something Logged and try again.");
return;
}
int i, ret, useNativeFileDialogVal;
QString filename;
const char *romFile;
QFileDialog dialog(this, tr("Save Stripped File As...") );
dialog.setFileMode(QFileDialog::AnyFile);
if (GameInfo->type==GIT_NSF)
{
dialog.setNameFilter(tr("NSF Files (*.nsf *.NSF) ;; All files (*)"));
dialog.setDefaultSuffix( tr(".nsf") );
}
else
{
dialog.setNameFilter(tr("NES Files (*.nes *.NES) ;; All files (*)"));
dialog.setDefaultSuffix( tr(".nes") );
}
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Save") );
romFile = getRomFile();
if ( romFile != NULL )
{
char dir[512], base[256];
parseFilepath( romFile, dir, base );
dialog.setDirectory( tr(dir) );
}
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.show();
ret = dialog.exec();
if ( ret )
{
QStringList fileList;
fileList = dialog.selectedFiles();
if ( fileList.size() > 0 )
{
filename = fileList[0];
}
}
if ( filename.isNull() )
{
return;
}
//qDebug() << "selected file path : " << filename.toUtf8();
FILE *fp = fopen( filename.toStdString().c_str(),"wb");
if (!fp)
{
FCEUD_PrintError("Error opening target stripped rom file!");
return;
}
if (GameInfo->type==GIT_NSF)
{
uint8 NSFLoadLow;
uint8 NSFLoadHigh;
//Not used because if bankswitching, the addresses involved
//could still end up being used through writes
//static uint16 LoadAddr;
//LoadAddr=NSFHeader.LoadAddressLow;
//LoadAddr|=(NSFHeader.LoadAddressHigh&0x7F)<<8;
//Simple store/restore for writing a working NSF header
NSFLoadLow = NSFHeader.LoadAddressLow;
NSFLoadHigh = NSFHeader.LoadAddressHigh;
NSFHeader.LoadAddressLow=0;
NSFHeader.LoadAddressHigh&=0xF0;
fwrite(&NSFHeader,1,0x8,fp);
NSFHeader.LoadAddressLow = NSFLoadLow;
NSFHeader.LoadAddressHigh = NSFLoadHigh;
fseek(fp,0x8,SEEK_SET);
for (i = 0;i < ((NSFMaxBank+1)*4096);i++){
unsigned char pchar;
if (cdloggerdata[i] & 3)
{
pchar = invert?0:NSFDATA[i];
}
else
{
pchar = invert?NSFDATA[i]:0;
}
fputc(pchar, fp);
}
}
else
{
iNES_HEADER cdlhead;
cdlhead.ID[0] = 'N';
cdlhead.ID[1] = 'E';
cdlhead.ID[2] = 'S';
cdlhead.ID[3] = 0x1A;
cdlhead.ROM_size = cdloggerdataSize >> 14;
cdlhead.VROM_size = cdloggerVideoDataSize >> 13;
fwrite(&cdlhead,1,16,fp);
for (i = 0; i < (int)cdloggerdataSize; i++){
unsigned char pchar;
if (cdloggerdata[i] & 3)
{
pchar = invert?0:PRGptr[0][i];
}
else
{
pchar = invert?PRGptr[0][i]:0;
}
fputc(pchar, fp);
}
if (cdloggerVideoDataSize != 0)
{
// since the OldPPU at least logs the $2007 read accesses, we should save the data anyway
for (i = 0; i < (int)cdloggerVideoDataSize; i++) {
unsigned char vchar;
if (cdloggervdata[i] & 3)
{
vchar = invert?0:CHRptr[0][i];
}
else
{
vchar = invert?CHRptr[0][i]:0;
}
fputc(vchar, fp);
}
}
}
fclose(fp);
}
//----------------------------------------------------
void CodeDataLoggerDialog_t::SaveStrippedROMClicked(void)
{
SaveStrippedROM(0);
}
//----------------------------------------------------
void CodeDataLoggerDialog_t::SaveUnusedROMClicked(void)
{
SaveStrippedROM(1);
}
//----------------------------------------------------
static int getDefaultCDLFile( char *filepath )
{
const char *romFile;
char dir[512], baseFile[256];
filepath[0] = 0;
romFile = getRomFile();
if ( romFile == NULL )
{
return -1;
}
parseFilepath( romFile, dir, baseFile );
sprintf( filepath, "%s/%s.cdl", dir, baseFile );
//printf("%s\n", filepath );
return 0;
}
//----------------------------------------------------
void FreeCDLog(void)
{
fceuWrapperLock();
if (cdloggerdata)
{
free(cdloggerdata);
cdloggerdata = NULL;
cdloggerdataSize = 0;
}
if (cdloggervdata)
{
free(cdloggervdata);
cdloggervdata = NULL;
cdloggerVideoDataSize = 0;
}
fceuWrapperUnLock();
}
//----------------------------------------------------
void InitCDLog(void)
{
fceuWrapperLock();
cdloggerdataSize = PRGsize[0];
cdloggerdata = (unsigned char*)malloc(cdloggerdataSize);
if (!CHRram[0] || (CHRptr[0] == PRGptr[0])) { // Some kind of workaround for my OneBus VRAM hack, will remove it if I find another solution for that
cdloggerVideoDataSize = CHRsize[0];
cdloggervdata = (unsigned char*)malloc(cdloggerVideoDataSize);
} else {
if (GameInfo->type != GIT_NSF) {
cdloggerVideoDataSize = 0;
cdloggervdata = (unsigned char*)malloc(8192);
}
}
fceuWrapperUnLock();
}
//----------------------------------------------------
void ResetCDLog(void)
{
if ( GameInfo == NULL )
{
return;
}
fceuWrapperLock();
codecount = datacount = rendercount = vromreadcount = 0;
undefinedcount = cdloggerdataSize;
if ( cdloggerdata != NULL )
{
memset(cdloggerdata, 0, cdloggerdataSize);
}
if (cdloggerVideoDataSize != 0)
{
undefinedvromcount = cdloggerVideoDataSize;
if ( cdloggervdata != NULL )
{
memset(cdloggervdata, 0, cdloggerVideoDataSize);
}
}
else
{
if (GameInfo->type != GIT_NSF)
{
undefinedvromcount = 8192;
memset(cdloggervdata, 0, 8192);
}
}
fceuWrapperUnLock();
}
//----------------------------------------------------
bool LoadCDLog(const char* nameo)
{
FILE *FP;
int i,j;
FP = fopen(nameo, "rb");
if (FP == NULL)
{
return false;
}
for(i = 0;i < (int)cdloggerdataSize;i++)
{
j = fgetc(FP);
if (j == EOF)
break;
if ((j & 1) && !(cdloggerdata[i] & 1))
codecount++; //if the new byte has something logged and
if ((j & 2) && !(cdloggerdata[i] & 2))
datacount++; //and the old one doesn't. Then increment
if ((j & 3) && !(cdloggerdata[i] & 3))
undefinedcount--; //the appropriate counter.
cdloggerdata[i] |= j;
}
if(cdloggerVideoDataSize != 0)
{
for(i = 0;i < (int)cdloggerVideoDataSize;i++)
{
j = fgetc(FP);
if(j == EOF)break;
if((j & 1) && !(cdloggervdata[i] & 1))rendercount++; //if the new byte has something logged and
if((j & 2) && !(cdloggervdata[i] & 2))vromreadcount++; //if the new byte has something logged and
if((j & 3) && !(cdloggervdata[i] & 3))undefinedvromcount--; //the appropriate counter.
cdloggervdata[i] |= j;
}
}
fclose(FP);
RenameCDLog(nameo);
return true;
}
//----------------------------------------------------
void StartCDLogging(void)
{
fceuWrapperLock();
FCEUI_SetLoggingCD(1);
//EnableTracerMenuItems();
//SetDlgItemText(hCDLogger, BTN_CDLOGGER_START_PAUSE, "Pause");
fceuWrapperUnLock();
}
//----------------------------------------------------
bool PauseCDLogging(void)
{
// can't pause while Trace Logger is using
//if ((logging) && (logging_options & LOG_NEW_INSTRUCTIONS))
//{
// MessageBox(hCDLogger, "The Trace Logger is currently using this for some of its features.\nPlease turn the Trace Logger off and try again.","Unable to Pause Code/Data Logger", MB_OK);
// return false;
//}
fceuWrapperLock();
FCEUI_SetLoggingCD(0);
//EnableTracerMenuItems();
//SetDlgItemText(hCDLogger, BTN_CDLOGGER_START_PAUSE, "Start");
fceuWrapperUnLock();
return true;
}
//----------------------------------------------------
void CDLoggerROMClosed(void)
{
PauseCDLogging();
if (autoSaveCDL)
{
SaveCDLogFile();
}
}
//----------------------------------------------------
void CDLoggerROMChanged(void)
{
FreeCDLog();
InitCDLog();
ResetCDLog();
RenameCDLog("");
if (!autoResumeCDL)
return;
// try to load respective CDL file
char nameo[1024];
getDefaultCDLFile( nameo );
FILE *FP;
FP = fopen(nameo, "rb");
if (FP != NULL)
{
// .cdl file with this ROM name exists
fclose(FP);
//if (!hCDLogger)
//{
// DoCDLogger();
//}
if (LoadCDLog(nameo))
{
StartCDLogging();
}
}
}
//----------------------------------------------------
void RenameCDLog(const char* newName)
{
strcpy(loadedcdfile, newName);
}
//----------------------------------------------------
void SaveCDLogFile(void)
{
if (loadedcdfile[0] == 0)
{
char nameo[1024];
getDefaultCDLFile( nameo );
RenameCDLog(nameo);
}
FILE *FP;
FP = fopen(loadedcdfile, "wb");
if (FP == NULL)
{
FCEUD_PrintError("Error Saving File");
return;
}
fwrite(cdloggerdata, cdloggerdataSize, 1, FP);
if (cdloggerVideoDataSize != 0)
{
fwrite(cdloggervdata, cdloggerVideoDataSize, 1, FP);
}
fclose(FP);
}
//----------------------------------------------------

View File

@ -0,0 +1,73 @@
// CodeDataLogger.h
//
#pragma once
#include <QWidget>
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
#include <QCheckBox>
#include <QPushButton>
#include <QLabel>
#include <QFrame>
#include <QTimer>
#include <QGroupBox>
#include <QCloseEvent>
class CodeDataLoggerDialog_t : public QDialog
{
Q_OBJECT
public:
CodeDataLoggerDialog_t(QWidget *parent = 0);
~CodeDataLoggerDialog_t(void);
protected:
QTimer *updateTimer;
QLabel *prgLoggedCodeLabel;
QLabel *prgLoggedDataLabel;
QLabel *prgUnloggedLabel;
QLabel *chrLoggedCodeLabel;
QLabel *chrLoggedDataLabel;
QLabel *chrUnloggedLabel;
QLabel *cdlFileLabel;
QLabel *statLabel;
QCheckBox *autoSaveCdlCbox;
QCheckBox *autoLoadCdlCbox;
QCheckBox *autoResumeLogCbox;
QPushButton *startPauseButton;
void closeEvent(QCloseEvent *bar);
void SaveStrippedROM(int invert);
private:
public slots:
void closeWindow(void);
private slots:
void loadCdlFile(void);
void saveCdlFile(void);
void saveCdlFileAs(void);
void updatePeriodic(void);
void ResetCDLogClicked(void);
void StartPauseCDLogClicked(void);
void autoSaveCdlStateChange(int state);
void autoLoadCdlStateChange(int state);
void autoResumeCdlStateChange(int state);
void SaveStrippedROMClicked(void);
void SaveUnusedROMClicked(void);
};
void InitCDLog(void);
void ResetCDLog(void);
void FreeCDLog(void);
void StartCDLogging(void);
bool PauseCDLogging(void);
bool LoadCDLog(const char* nameo);
void RenameCDLog(const char* newName);
void CDLoggerROMClosed(void);
void CDLoggerROMChanged(void);
void SaveCDLogFile(void);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,285 @@
// ConsoleDebugger.h
//
#pragma once
#include <QWidget>
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
#include <QCheckBox>
#include <QGroupBox>
#include <QPushButton>
#include <QFont>
#include <QLabel>
#include <QTimer>
#include <QFrame>
#include <QGroupBox>
#include <QTreeView>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QLineEdit>
#include <QTextEdit>
#include <QPlainTextEdit>
#include <QScrollBar>
#include "Qt/main.h"
#include "Qt/SymbolicDebug.h"
#include "../../debug.h"
struct dbg_asm_entry_t
{
int addr;
int bank;
int rom;
int size;
int line;
uint8 opcode[3];
std::string text;
enum
{
ASM_TEXT = 0,
SYMBOL_NAME,
SYMBOL_COMMENT
} type;
dbg_asm_entry_t(void)
{
addr = 0; bank = -1; rom = -1;
size = 0; line = 0; type = ASM_TEXT;
for (int i=0; i<3; i++)
{
opcode[i] = 0;
}
}
};
class debuggerBookmark_t
{
public:
int addr;
std::string name;
debuggerBookmark_t(void)
{
addr = 0;
}
};
class debuggerBookmarkManager_t
{
public:
debuggerBookmarkManager_t(void);
~debuggerBookmarkManager_t(void);
int addBookmark( int addr, const char *name = NULL );
int editBookmark( int addr, const char *name );
int deleteBookmark( int addr );
int size(void);
void clear(void);
debuggerBookmark_t *begin(void);
debuggerBookmark_t *next(void);
debuggerBookmark_t *getAddr( int addr );
private:
std::map <int, debuggerBookmark_t*> bmMap;
std::map <int, debuggerBookmark_t*>::iterator internal_iter;
};
class ConsoleDebugger;
class QAsmView : public QWidget
{
Q_OBJECT
public:
QAsmView(QWidget *parent = 0);
~QAsmView(void);
void setScrollBars( QScrollBar *h, QScrollBar *v );
void updateAssemblyView(void);
void asmClear(void);
int getAsmLineFromAddr(int addr);
void setLine(int lineNum);
void setXScroll(int value);
void scrollToPC(void);
void setDisplayROMoffsets( bool value );
void setSymbolDebugEnable( bool value );
void setRegisterNameEnable( bool value );
int getCtxMenuAddr(void){ return ctxMenuAddr; };
protected:
void paintEvent(QPaintEvent *event);
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
void mousePressEvent(QMouseEvent * event);
void mouseMoveEvent(QMouseEvent * event);
void resizeEvent(QResizeEvent *event);
void contextMenuEvent(QContextMenuEvent *event);
void calcFontData(void);
QPoint convPixToCursor( QPoint p );
private:
ConsoleDebugger *parent;
QFont font;
QScrollBar *vbar;
QScrollBar *hbar;
int ctxMenuAddr;
int maxLineLen;
int pxCharWidth;
int pxCharHeight;
int pxCursorHeight;
int pxLineSpacing;
int pxLineLead;
int viewLines;
int viewWidth;
int viewHeight;
int lineOffset;
int maxLineOffset;
int pxLineWidth;
int pxLineXScroll;
int cursorPosX;
int cursorPosY;
dbg_asm_entry_t *asmPC;
std::vector <dbg_asm_entry_t*> asmEntry;
bool displayROMoffsets;
bool symbolicDebugEnable;
bool registerNameEnable;
};
class ConsoleDebugger : public QDialog
{
Q_OBJECT
public:
ConsoleDebugger(QWidget *parent = 0);
~ConsoleDebugger(void);
void updateWindowData(void);
void updateRegisterView(void);
void breakPointNotify(int bpNum);
void openBpEditWindow(int editIdx = -1, watchpointinfo *wp = NULL );
void openDebugSymbolEditWindow( int addr );
void setBookmarkSelectedAddress( int addr );
int getBookmarkSelectedAddress(void){ return selBmAddrVal; };
void edit_BM_name( int addr );
void queueUpdate(void);
QLabel *asmLineSelLbl;
protected:
void closeEvent(QCloseEvent *event);
//void keyPressEvent(QKeyEvent *event);
//void keyReleaseEvent(QKeyEvent *event);
//QTreeWidget *tree;
QScrollBar *vbar;
QScrollBar *hbar;
QAsmView *asmView;
QPlainTextEdit *stackText;
QLineEdit *seekEntry;
QLineEdit *pcEntry;
QLineEdit *regAEntry;
QLineEdit *regXEntry;
QLineEdit *regYEntry;
QLineEdit *cpuCycExdVal;
QLineEdit *instrExdVal;
QLineEdit *selBmAddr;
QGroupBox *stackFrame;
QGroupBox *bpFrame;
QGroupBox *sfFrame;
QGroupBox *bmFrame;
QTreeWidget *bpTree;
QTreeWidget *bmTree;
QCheckBox *brkBadOpsCbox;
QCheckBox *N_chkbox;
QCheckBox *V_chkbox;
QCheckBox *U_chkbox;
QCheckBox *B_chkbox;
QCheckBox *D_chkbox;
QCheckBox *I_chkbox;
QCheckBox *Z_chkbox;
QCheckBox *C_chkbox;
QCheckBox *brkCpuCycExd;
QCheckBox *brkInstrsExd;
QCheckBox *romOfsChkBox;
QCheckBox *symDbgChkBox;
QCheckBox *regNamChkBox;
QCheckBox *autoOpenChkBox;
QCheckBox *debFileChkBox;
QCheckBox *idaFontChkBox;
QLabel *emuStatLbl;
QLabel *ppuLbl;
QLabel *spriteLbl;
QLabel *scanLineLbl;
QLabel *pixLbl;
QLabel *cpuCyclesLbl1;
QLabel *cpuCyclesLbl2;
QLabel *cpuInstrsLbl1;
QLabel *cpuInstrsLbl2;
QTimer *periodicTimer;
QFont font;
int selBmAddrVal;
bool windowUpdateReq;
private:
void setRegsFromEntry(void);
void bpListUpdate( bool reset = false );
void bmListUpdate( bool reset = false );
public slots:
void closeWindow(void);
void asmViewCtxMenuAddBP(void);
void asmViewCtxMenuAddBM(void);
void asmViewCtxMenuAddSym(void);
void asmViewCtxMenuOpenHexEdit(void);
private slots:
void updatePeriodic(void);
void hbarChanged(int value);
void vbarChanged(int value);
void debugRunCB(void);
void debugStepIntoCB(void);
void debugStepOutCB(void);
void debugStepOverCB(void);
void debugRunLineCB(void);
void debugRunLine128CB(void);
void seekToCB(void);
void seekPCCB(void);
void add_BP_CB(void);
void edit_BP_CB(void);
void delete_BP_CB(void);
void add_BM_CB(void);
void edit_BM_CB(void);
void delete_BM_CB(void);
void resetCountersCB (void);
void reloadSymbolsCB(void);
void displayROMoffsetCB(int value);
void symbolDebugEnableCB(int value);
void registerNameEnableCB(int value);
void autoOpenDebugCB( int value );
void debFileAutoLoadCB( int value );
void breakOnBadOpcodeCB(int value);
void breakOnCyclesCB( int value );
void breakOnInstructionsCB( int value );
void bpItemClicked( QTreeWidgetItem *item, int column);
void bmItemClicked( QTreeWidgetItem *item, int column);
void bmItemDoubleClicked( QTreeWidgetItem *item, int column);
void cpuCycleThresChanged(const QString &txt);
void instructionsThresChanged(const QString &txt);
void selBmAddrChanged(const QString &txt);
};
bool debuggerWindowIsOpen(void);
void saveGameDebugBreakpoints(void);
void loadGameDebugBreakpoints(void);
void debuggerClearAllBreakpoints(void);
void updateAllDebuggerWindows(void);
extern debuggerBookmarkManager_t dbgBmMgr;

View File

@ -1,5 +1,7 @@
// ConsoleSoundConf.cpp
//
#include <QCloseEvent>
#include "../../fceu.h"
#include "../../driver.h"
#include "Qt/ConsoleSoundConf.h"
@ -217,7 +219,22 @@ ConsoleSndConfDialog_t::ConsoleSndConfDialog_t(QWidget *parent)
//----------------------------------------------------
ConsoleSndConfDialog_t::~ConsoleSndConfDialog_t(void)
{
printf("Destroy Sound Config Window\n");
}
//----------------------------------------------------------------------------
void ConsoleSndConfDialog_t::closeEvent(QCloseEvent *event)
{
printf("Sound Config Close Window Event\n");
done(0);
deleteLater();
event->accept();
}
//----------------------------------------------------------------------------
void ConsoleSndConfDialog_t::closeWindow(void)
{
//printf("Sound Close Window\n");
done(0);
deleteLater();
}
//----------------------------------------------------
void ConsoleSndConfDialog_t::setCheckBoxFromProperty( QCheckBox *cbx, const char *property )

View File

@ -25,6 +25,8 @@ class ConsoleSndConfDialog_t : public QDialog
~ConsoleSndConfDialog_t(void);
protected:
void closeEvent(QCloseEvent *event);
QCheckBox *enaChkbox;
QCheckBox *enaLowPass;
QCheckBox *swapDutyChkbox;
@ -44,6 +46,7 @@ class ConsoleSndConfDialog_t : public QDialog
void setSliderFromProperty( QSlider *slider, QLabel *lbl, const char *property );
private slots:
void closeWindow(void);
void bufSizeChanged(int value);
void volumeChanged(int value);
void triangleChanged(int value);

View File

@ -0,0 +1,147 @@
// ConsoleUtilities.cpp
#include <stdio.h>
#include <string.h>
#include "../../fceu.h"
#include "Qt/ConsoleUtilities.h"
//---------------------------------------------------------------------------
int getDirFromFile( const char *path, char *dir )
{
int i, lastSlash = -1, lastPeriod = -1;
i=0;
while ( path[i] != 0 )
{
if ( path[i] == '/' )
{
lastSlash = i;
}
else if ( path[i] == '.' )
{
lastPeriod = i;
}
dir[i] = path[i]; i++;
}
dir[i] = 0;
if ( lastPeriod >= 0 )
{
if ( lastPeriod > lastSlash )
{
dir[lastSlash] = 0;
}
}
return 0;
}
//---------------------------------------------------------------------------
const char *getRomFile( void )
{
if ( GameInfo )
{
return GameInfo->filename;
}
return NULL;
}
//---------------------------------------------------------------------------
// Return file base name stripping out preceding path and trailing suffix.
int getFileBaseName( const char *filepath, char *base )
{
int i=0,j=0,end=0;
if ( filepath == NULL )
{
base[0] = 0;
return 0;
}
i=0; j=0;
while ( filepath[i] != 0 )
{
if ( (filepath[i] == '/') || (filepath[i] == '\\') )
{
j = i+1;
}
i++;
}
i = j;
j=0;
while ( filepath[i] != 0 )
{
base[j] = filepath[i]; i++; j++;
}
base[j] = 0; end=j;
while ( j > 1 )
{
j--;
if ( base[j] == '.' )
{
end=j; base[j] = 0; break;
}
}
return end;
}
//---------------------------------------------------------------------------
int parseFilepath( const char *filepath, char *dir, char *base, char *suffix )
{
int i=0,j=0,end=0;
if ( filepath == NULL )
{
if ( dir ) dir[0] = 0;
if ( base ) base[0] = 0;
if ( suffix) suffix[0] = 0;
return 0;
}
i=0; j=0;
while ( filepath[i] != 0 )
{
if ( (filepath[i] == '/') || (filepath[i] == '\\') )
{
j = i+1;
}
if ( dir )
{
dir[i] = filepath[i];
}
i++;
}
if ( dir )
{
dir[j] = 0;
}
i = j;
if ( base == NULL )
{
return end;
}
j=0;
while ( filepath[i] != 0 )
{
base[j] = filepath[i]; i++; j++;
}
base[j] = 0; end=j;
if ( suffix )
{
suffix[0] = 0;
}
while ( j > 1 )
{
j--;
if ( base[j] == '.' )
{
if ( suffix )
{
strcpy( suffix, &base[j] );
}
end=j; base[j] = 0;
break;
}
}
return end;
}
//---------------------------------------------------------------------------

View File

@ -0,0 +1,9 @@
// ConsoleUtilities.h
int getDirFromFile( const char *path, char *dir );
const char *getRomFile( void );
int getFileBaseName( const char *filepath, char *base );
int parseFilepath( const char *filepath, char *dir, char *base, char *suffix = NULL );

View File

@ -1,5 +1,7 @@
// ConsoleVideoConf.cpp
//
#include <QCloseEvent>
#include "../../fceu.h"
#include "Qt/main.h"
#include "Qt/dface.h"
@ -26,7 +28,7 @@ ConsoleVideoConfDialog_t::ConsoleVideoConfDialog_t(QWidget *parent)
driverSelect = new QComboBox();
driverSelect->addItem( tr("OpenGL"), 0 );
//driverSelect->addItem( tr("SDL"), 1 );
driverSelect->addItem( tr("SDL"), 1 );
hbox1 = new QHBoxLayout();
@ -52,8 +54,10 @@ ConsoleVideoConfDialog_t::ConsoleVideoConfDialog_t(QWidget *parent)
regionSelect->addItem( tr("Dendy"), 2 );
setComboBoxFromProperty( regionSelect, "SDL.PAL");
setComboBoxFromProperty( driverSelect, "SDL.VideoDriver");
connect(regionSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(regionChanged(int)) );
connect(driverSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(driverChanged(int)) );
hbox1 = new QHBoxLayout();
@ -103,7 +107,7 @@ ConsoleVideoConfDialog_t::ConsoleVideoConfDialog_t(QWidget *parent)
button = new QPushButton( tr("Close") );
hbox1->addWidget( button );
connect(button, SIGNAL(clicked()), this, SLOT(closewindow(void)) );
connect(button, SIGNAL(clicked()), this, SLOT(closeWindow(void)) );
main_vbox->addLayout( hbox1 );
@ -113,8 +117,24 @@ ConsoleVideoConfDialog_t::ConsoleVideoConfDialog_t(QWidget *parent)
//----------------------------------------------------
ConsoleVideoConfDialog_t::~ConsoleVideoConfDialog_t(void)
{
printf("Destroy Video Config Window\n");
}
//----------------------------------------------------------------------------
void ConsoleVideoConfDialog_t::closeEvent(QCloseEvent *event)
{
printf("Video Config Close Window Event\n");
done(0);
deleteLater();
event->accept();
}
//----------------------------------------------------------------------------
void ConsoleVideoConfDialog_t::closeWindow(void)
{
//printf("Video Config Close Window\n");
done(0);
deleteLater();
}
//----------------------------------------------------
void ConsoleVideoConfDialog_t::resetVideo(void)
{
@ -199,6 +219,20 @@ void ConsoleVideoConfDialog_t::showFPSChanged( int value )
fceuWrapperUnLock();
}
//----------------------------------------------------
void ConsoleVideoConfDialog_t::driverChanged(int index)
{
int driver;
//printf("Driver: %i : %i \n", index, driverSelect->itemData(index).toInt() );
driver = driverSelect->itemData(index).toInt();
g_config->setOption ("SDL.VideoDriver", driver);
g_config->save ();
printf("Note: A restart of the application is needed for video driver change to take effect...\n");
}
//----------------------------------------------------
void ConsoleVideoConfDialog_t::regionChanged(int index)
{
int region;
@ -221,8 +255,3 @@ void ConsoleVideoConfDialog_t::applyChanges( void )
resetVideo();
}
//----------------------------------------------------
void ConsoleVideoConfDialog_t::closewindow( void )
{
done(0);
}
//----------------------------------------------------

View File

@ -25,6 +25,8 @@ class ConsoleVideoConfDialog_t : public QDialog
~ConsoleVideoConfDialog_t(void);
protected:
void closeEvent(QCloseEvent *bar);
QComboBox *driverSelect;
QComboBox *regionSelect;
QCheckBox *gl_LF_chkBox;
@ -40,6 +42,9 @@ class ConsoleVideoConfDialog_t : public QDialog
void resetVideo(void);
public slots:
void closeWindow(void);
private slots:
void use_new_PPU_changed( int value );
void frameskip_changed( int value );
@ -47,8 +52,8 @@ class ConsoleVideoConfDialog_t : public QDialog
void clipSidesChanged( int value );
void showFPSChanged( int value );
void regionChanged(int index);
void driverChanged(int index);
void applyChanges( void );
void closewindow( void );
};

View File

@ -15,6 +15,12 @@ extern unsigned int gui_draw_area_height;
ConsoleViewSDL_t::ConsoleViewSDL_t(QWidget *parent)
: QWidget( parent )
{
QPalette pal = palette();
pal.setColor(QPalette::Background, Qt::black);
setAutoFillBackground(true);
setPalette(pal);
view_width = GL_NES_WIDTH;
view_height = GL_NES_HEIGHT;
@ -30,11 +36,29 @@ ConsoleViewSDL_t::ConsoleViewSDL_t(QWidget *parent)
sdlTexture = NULL;
vsyncEnabled = false;
localBufSize = GL_NES_WIDTH * GL_NES_HEIGHT * sizeof(uint32_t);
localBuf = (uint32_t*)malloc( localBufSize );
if ( localBuf )
{
memset( localBuf, 0, localBufSize );
}
}
ConsoleViewSDL_t::~ConsoleViewSDL_t(void)
{
if ( localBuf )
{
free( localBuf ); localBuf = NULL;
}
}
void ConsoleViewSDL_t::transfer2LocalBuffer(void)
{
memcpy( localBuf, nes_shm->pixbuf, localBufSize );
}
int ConsoleViewSDL_t::init(void)
@ -46,10 +70,16 @@ int ConsoleViewSDL_t::init(void)
printf("[SDL] Failed to initialize video subsystem.\n");
return -1;
}
//else
//{
// printf("Initialized SDL Video Subsystem\n");
//}
else
{
printf("Initialized SDL Video Subsystem\n");
}
for (int i=0; i<SDL_GetNumVideoDrivers(); i++)
{
printf("SDL Video Driver %i: %s\n", i, SDL_GetVideoDriver(i) );
}
printf("Using Video Driver: %s \n", SDL_GetCurrentVideoDriver() );
windowHandle = this->winId();
@ -132,17 +162,18 @@ void ConsoleViewSDL_t::resizeEvent(QResizeEvent *event)
s = event->size();
view_width = s.width();
view_height = s.height();
//printf("SDL Resize: %i x %i \n", view_width, view_height);
printf("SDL Resize: %i x %i \n", view_width, view_height);
reset();
sdlViewport.x = sdlRendW - view_width;
sdlViewport.y = sdlRendH - view_height;
sdlViewport.w = view_width;
sdlViewport.h = view_height;
//sdlViewport.x = sdlRendW - view_width;
//sdlViewport.y = sdlRendH - view_height;
//sdlViewport.w = view_width;
//sdlViewport.h = view_height;
}
void ConsoleViewSDL_t::paintEvent( QPaintEvent *event )
//void ConsoleViewSDL_t::paintEvent( QPaintEvent *event )
void ConsoleViewSDL_t::render(void)
{
int nesWidth = GL_NES_WIDTH;
int nesHeight = GL_NES_HEIGHT;
@ -167,8 +198,10 @@ void ConsoleViewSDL_t::paintEvent( QPaintEvent *event )
rw=(int)(nesWidth*xscale);
rh=(int)(nesHeight*yscale);
sx=sdlViewport.x + (view_width-rw)/2;
sy=sdlViewport.y + (view_height-rh)/2;
//sx=sdlViewport.x + (view_width-rw)/2;
//sy=sdlViewport.y + (view_height-rh)/2;
sx=(view_width-rw)/2;
sy=(view_height-rh)/2;
if ( (sdlRenderer == NULL) || (sdlTexture == NULL) )
{
@ -183,13 +216,13 @@ void ConsoleViewSDL_t::paintEvent( QPaintEvent *event )
int rowPitch;
SDL_LockTexture( sdlTexture, nullptr, (void**)&textureBuffer, &rowPitch);
{
memcpy( textureBuffer, nes_shm->pixbuf, GL_NES_HEIGHT*GL_NES_WIDTH*sizeof(uint32_t) );
memcpy( textureBuffer, localBuf, GL_NES_HEIGHT*GL_NES_WIDTH*sizeof(uint32_t) );
}
SDL_UnlockTexture(sdlTexture);
SDL_RenderSetViewport( sdlRenderer, &sdlViewport );
//SDL_RenderSetViewport( sdlRenderer, &sdlViewport );
SDL_Rect source = {0, 0, GL_NES_WIDTH, GL_NES_HEIGHT };
SDL_Rect source = {0, 0, nesWidth, nesHeight };
SDL_Rect dest = { sx, sy, rw, rh };
SDL_RenderCopy(sdlRenderer, sdlTexture, &source, &dest);

View File

@ -19,10 +19,13 @@ class ConsoleViewSDL_t : public QWidget
int init(void);
void reset(void);
void cleanup(void);
void render(void);
void transfer2LocalBuffer(void);
protected:
void paintEvent(QPaintEvent *event);
//void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
int view_width;
int view_height;
@ -37,10 +40,13 @@ class ConsoleViewSDL_t : public QWidget
bool vsyncEnabled;
uint32_t *localBuf;
uint32_t localBufSize;
SDL_Window *sdlWindow;
SDL_Renderer *sdlRenderer;
SDL_Texture *sdlTexture;
SDL_Rect sdlViewport;
//SDL_Rect sdlViewport;
private slots:
};

View File

@ -4,6 +4,7 @@
#include <iostream>
#include <cstdlib>
#include <QFileDialog>
#include <QMessageBox>
#include "../../fceu.h"
#include "../../fds.h"
@ -20,23 +21,49 @@
#include "Qt/GamePadConf.h"
#include "Qt/HotKeyConf.h"
#include "Qt/PaletteConf.h"
#include "Qt/GuiConf.h"
#include "Qt/LuaControl.h"
#include "Qt/CheatsConf.h"
#include "Qt/HexEditor.h"
#include "Qt/TraceLogger.h"
#include "Qt/CodeDataLogger.h"
#include "Qt/ConsoleDebugger.h"
#include "Qt/ConsoleUtilities.h"
#include "Qt/ConsoleSoundConf.h"
#include "Qt/ConsoleVideoConf.h"
#include "Qt/AboutWindow.h"
#include "Qt/fceuWrapper.h"
#include "Qt/ppuViewer.h"
#include "Qt/NameTableViewer.h"
#include "Qt/keyscan.h"
#include "Qt/nes_shm.h"
consoleWin_t::consoleWin_t(QWidget *parent)
: QMainWindow( parent )
{
int use_SDL_video = false;
createMainMenu();
viewport = new ConsoleViewGL_t(this);
//viewport = new ConsoleViewSDL_t(this);
g_config->getOption( "SDL.VideoDriver", &use_SDL_video );
errorMsgValid = false;
viewport_GL = NULL;
viewport_SDL = NULL;
if ( use_SDL_video )
{
viewport_SDL = new ConsoleViewSDL_t(this);
setCentralWidget(viewport_SDL);
}
else
{
viewport_GL = new ConsoleViewGL_t(this);
setCentralWidget(viewport_GL);
}
setCentralWidget(viewport);
setWindowIcon(QIcon(":fceux1.png"));
gameTimer = new QTimer( this );
@ -53,26 +80,32 @@ consoleWin_t::consoleWin_t(QWidget *parent)
emulatorThread->start();
gamePadConfWin = NULL;
}
consoleWin_t::~consoleWin_t(void)
{
nes_shm->runEmulator = 0;
if ( gamePadConfWin != NULL )
{
gamePadConfWin->closeWindow();
}
gameTimer->stop();
closeGamePadConfWindow();
//printf("Thread Finished: %i \n", gameThread->isFinished() );
emulatorThread->quit();
emulatorThread->wait( 1000 );
fceuWrapperLock();
fceuWrapperClose();
fceuWrapperUnLock();
//printf("Thread Finished: %i \n", gameThread->isFinished() );
emulatorThread->quit();
emulatorThread->wait();
delete viewport;
if ( viewport_GL != NULL )
{
delete viewport_GL; viewport_GL = NULL;
}
if ( viewport_SDL != NULL )
{
delete viewport_SDL; viewport_SDL = NULL;
}
delete mutex;
// LoadGame() checks for an IP and if it finds one begins a network session
@ -89,14 +122,31 @@ void consoleWin_t::setCyclePeriodms( int ms )
//printf("Period Set to: %i ms \n", ms );
}
void consoleWin_t::showErrorMsgWindow()
{
QMessageBox msgBox(this);
fceuWrapperLock();
msgBox.setIcon( QMessageBox::Critical );
msgBox.setText( tr(errorMsg.c_str()) );
errorMsg.clear();
fceuWrapperUnLock();
msgBox.show();
msgBox.exec();
}
void consoleWin_t::QueueErrorMsgWindow( const char *msg )
{
errorMsg.append( msg );
errorMsg.append("\n");
errorMsgValid = true;
}
void consoleWin_t::closeEvent(QCloseEvent *event)
{
//printf("Main Window Close Event\n");
if ( gamePadConfWin != NULL )
{
//printf("Command Game Pad Close\n");
gamePadConfWin->closeWindow();
}
closeGamePadConfWindow();
event->accept();
closeApp();
@ -119,9 +169,12 @@ void consoleWin_t::createMainMenu(void)
{
QMenu *subMenu;
QActionGroup *group;
int useNativeMenuBar;
// This is needed for menu bar to show up on MacOS
menuBar()->setNativeMenuBar(false);
// This is needed for menu bar to show up on MacOS
g_config->getOption( "SDL.UseNativeMenuBar", &useNativeMenuBar );
menuBar()->setNativeMenuBar( useNativeMenuBar ? true : false );
//-----------------------------------------------------------------------
// File
@ -294,6 +347,14 @@ void consoleWin_t::createMainMenu(void)
optMenu->addAction(paletteConfig);
// Options -> GUI Config
guiConfig = new QAction(tr("GUI Config"), this);
//guiConfig->setShortcut( QKeySequence(tr("Ctrl+C")));
guiConfig->setStatusTip(tr("GUI Configure"));
connect(guiConfig, SIGNAL(triggered()), this, SLOT(openGuiConfWin(void)) );
optMenu->addAction(guiConfig);
// Options -> Auto-Resume
autoResume = new QAction(tr("Auto-Resume Play"), this);
//autoResume->setShortcut( QKeySequence(tr("Ctrl+C")));
@ -410,6 +471,70 @@ void consoleWin_t::createMainMenu(void)
subMenu->addAction(fdsLoadBiosAct);
//-----------------------------------------------------------------------
// Tools
toolsMenu = menuBar()->addMenu(tr("Tools"));
// Tools -> Cheats
cheatsAct = new QAction(tr("Cheats..."), this);
//cheatsAct->setShortcut( QKeySequence(tr("Shift+F7")));
cheatsAct->setStatusTip(tr("Open Cheat Window"));
connect(cheatsAct, SIGNAL(triggered()), this, SLOT(openCheats(void)) );
toolsMenu->addAction(cheatsAct);
//-----------------------------------------------------------------------
// Debug
debugMenu = menuBar()->addMenu(tr("Debug"));
// Debug -> Debugger
debuggerAct = new QAction(tr("Debugger..."), this);
//debuggerAct->setShortcut( QKeySequence(tr("Shift+F7")));
debuggerAct->setStatusTip(tr("Open 6502 Debugger"));
connect(debuggerAct, SIGNAL(triggered()), this, SLOT(openDebugWindow(void)) );
debugMenu->addAction(debuggerAct);
// Debug -> Hex Editor
hexEditAct = new QAction(tr("Hex Editor..."), this);
//hexEditAct->setShortcut( QKeySequence(tr("Shift+F7")));
hexEditAct->setStatusTip(tr("Open Memory Hex Editor"));
connect(hexEditAct, SIGNAL(triggered()), this, SLOT(openHexEditor(void)) );
debugMenu->addAction(hexEditAct);
// Debug -> PPU Viewer
ppuViewAct = new QAction(tr("PPU Viewer..."), this);
//ppuViewAct->setShortcut( QKeySequence(tr("Shift+F7")));
ppuViewAct->setStatusTip(tr("Open PPU Viewer"));
connect(ppuViewAct, SIGNAL(triggered()), this, SLOT(openPPUViewer(void)) );
debugMenu->addAction(ppuViewAct);
// Debug -> Name Table Viewer
ntViewAct = new QAction(tr("Name Table Viewer..."), this);
//ntViewAct->setShortcut( QKeySequence(tr("Shift+F7")));
ntViewAct->setStatusTip(tr("Open Name Table Viewer"));
connect(ntViewAct, SIGNAL(triggered()), this, SLOT(openNTViewer(void)) );
debugMenu->addAction(ntViewAct);
// Debug -> Trace Logger
traceLogAct = new QAction(tr("Trace Logger..."), this);
//traceLogAct->setShortcut( QKeySequence(tr("Shift+F7")));
traceLogAct->setStatusTip(tr("Open Trace Logger"));
connect(traceLogAct, SIGNAL(triggered()), this, SLOT(openTraceLogger(void)) );
debugMenu->addAction(traceLogAct);
// Debug -> Code/Data Logger
codeDataLogAct = new QAction(tr("Code/Data Logger..."), this);
//codeDataLogAct->setShortcut( QKeySequence(tr("Shift+F7")));
codeDataLogAct->setStatusTip(tr("Open Code Data Logger"));
connect(codeDataLogAct, SIGNAL(triggered()), this, SLOT(openCodeDataLogger(void)) );
debugMenu->addAction(codeDataLogAct);
//-----------------------------------------------------------------------
// Movie
movieMenu = menuBar()->addMenu(tr("Movie"));
@ -451,18 +576,29 @@ void consoleWin_t::createMainMenu(void)
//-----------------------------------------------------------------------
// Help
helpMenu = menuBar()->addMenu(tr("Help"));
aboutAct = new QAction(tr("About"), this);
// Help -> About FCEUX
aboutAct = new QAction(tr("About FCEUX"), this);
aboutAct->setStatusTip(tr("About FCEUX"));
connect(aboutAct, SIGNAL(triggered()), this, SLOT(aboutFCEUX(void)) );
helpMenu->addAction(aboutAct);
// Help -> About Qt
aboutActQt = new QAction(tr("About Qt"), this);
aboutActQt->setStatusTip(tr("About Qt"));
connect(aboutActQt, SIGNAL(triggered()), this, SLOT(aboutQt(void)) );
helpMenu->addAction(aboutActQt);
};
//---------------------------------------------------------------------------
void consoleWin_t::closeApp(void)
{
nes_shm->runEmulator = 0;
emulatorThread->quit();
emulatorThread->wait( 1000 );
fceuWrapperLock();
fceuWrapperClose();
fceuWrapperUnLock();
@ -471,46 +607,15 @@ void consoleWin_t::closeApp(void)
// clear the NetworkIP field so this doesn't happen unintentionally
g_config->setOption ("SDL.NetworkIP", "");
g_config->save ();
//SDL_Quit (); // Already called by fceuWrapperClose
//qApp::quit();
qApp->quit();
}
//---------------------------------------------------------------------------
int consoleWin_t::getDirFromFile( const char *path, char *dir )
{
int i, lastSlash = -1, lastPeriod = -1;
i=0;
while ( path[i] != 0 )
{
if ( path[i] == '/' )
{
lastSlash = i;
}
else if ( path[i] == '.' )
{
lastPeriod = i;
}
dir[i] = path[i]; i++;
}
dir[i] = 0;
if ( lastPeriod >= 0 )
{
if ( lastPeriod > lastSlash )
{
dir[lastSlash] = 0;
}
}
return 0;
}
//---------------------------------------------------------------------------
void consoleWin_t::openROMFile(void)
{
int ret;
int ret, useNativeFileDialogVal;
QString filename;
std::string last;
char dir[512];
@ -518,9 +623,11 @@ void consoleWin_t::openROMFile(void)
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilter(tr("NES files (*.nes)(*.NES) ;; All files (*)"));
dialog.setNameFilter(tr("NES files (*.nes *.NES) ;; All files (*)"));
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Open") );
g_config->getOption ("SDL.LastOpenFile", &last );
@ -528,9 +635,10 @@ void consoleWin_t::openROMFile(void)
dialog.setDirectory( tr(dir) );
// the gnome default file dialog is not playing nice with QT.
// TODO make this a config option to use native file dialog.
dialog.setOption(QFileDialog::DontUseNativeDialog, true);
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.show();
ret = dialog.exec();
@ -571,7 +679,7 @@ void consoleWin_t::closeROMCB(void)
void consoleWin_t::loadNSF(void)
{
int ret;
int ret, useNativeFileDialogVal;
QString filename;
std::string last;
char dir[512];
@ -579,9 +687,11 @@ void consoleWin_t::loadNSF(void)
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilter(tr("NSF Sound Files (*.nsf)(*.NSF) ;; Zip Files (*.zip)(*.ZIP) ;; All files (*)"));
dialog.setNameFilter(tr("NSF Sound Files (*.nsf *.NSF) ;; Zip Files (*.zip *.ZIP) ;; All files (*)"));
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Load") );
g_config->getOption ("SDL.LastOpenNSF", &last );
@ -589,9 +699,10 @@ void consoleWin_t::loadNSF(void)
dialog.setDirectory( tr(dir) );
// the gnome default file dialog is not playing nice with QT.
// TODO make this a config option to use native file dialog.
dialog.setOption(QFileDialog::DontUseNativeDialog, true);
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.show();
ret = dialog.exec();
@ -622,7 +733,7 @@ void consoleWin_t::loadNSF(void)
void consoleWin_t::loadStateFrom(void)
{
int ret;
int ret, useNativeFileDialogVal;
QString filename;
std::string last;
char dir[512];
@ -630,9 +741,11 @@ void consoleWin_t::loadStateFrom(void)
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilter(tr("FCS Files (*.fc?)(*.FC?) ;; SAV Files (*.sav)(*.SAV) ;; All files (*)"));
dialog.setNameFilter(tr("FCS & SAV Files (*.sav *.SAV *.fc? *.FC?) ;; All files (*)"));
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Load") );
g_config->getOption ("SDL.LastLoadStateFrom", &last );
@ -640,9 +753,10 @@ void consoleWin_t::loadStateFrom(void)
dialog.setDirectory( tr(dir) );
// the gnome default file dialog is not playing nice with QT.
// TODO make this a config option to use native file dialog.
dialog.setOption(QFileDialog::DontUseNativeDialog, true);
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.show();
ret = dialog.exec();
@ -673,7 +787,7 @@ void consoleWin_t::loadStateFrom(void)
void consoleWin_t::saveStateAs(void)
{
int ret;
int ret, useNativeFileDialogVal;
QString filename;
std::string last;
char dir[512];
@ -681,9 +795,12 @@ void consoleWin_t::saveStateAs(void)
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilter(tr("FCS Files (*.fc?)(*.FC?) ;; SAV Files (*.sav)(*.SAV) ;; All files (*)"));
dialog.setNameFilter(tr("SAV Files (*.sav *.SAV) ;; All files (*)"));
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Save") );
dialog.setDefaultSuffix( tr(".sav") );
g_config->getOption ("SDL.LastSaveStateAs", &last );
@ -691,9 +808,10 @@ void consoleWin_t::saveStateAs(void)
dialog.setDirectory( tr(dir) );
// the gnome default file dialog is not playing nice with QT.
// TODO make this a config option to use native file dialog.
dialog.setOption(QFileDialog::DontUseNativeDialog, true);
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.show();
ret = dialog.exec();
@ -816,80 +934,21 @@ void consoleWin_t::takeScreenShot(void)
void consoleWin_t::loadLua(void)
{
#ifdef _S9XLUA_H
int ret;
QString filename;
std::string last;
char dir[512];
QFileDialog dialog(this, tr("Open LUA Script") );
LuaControlDialog_t *luaCtrlWin;
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilter(tr("LUA Scripts (*.lua)(*.LUA) ;; All files (*)"));
dialog.setViewMode(QFileDialog::List);
g_config->getOption ("SDL.LastLoadLua", &last );
if ( last.size() == 0 )
{
last.assign( "/usr/share/fceux/luaScripts" );
}
getDirFromFile( last.c_str(), dir );
dialog.setDirectory( tr(dir) );
// the gnome default file dialog is not playing nice with QT.
// TODO make this a config option to use native file dialog.
dialog.setOption(QFileDialog::DontUseNativeDialog, true);
dialog.show();
ret = dialog.exec();
if ( ret )
{
QStringList fileList;
fileList = dialog.selectedFiles();
if ( fileList.size() > 0 )
{
filename = fileList[0];
}
}
if ( filename.isNull() )
{
return;
}
qDebug() << "selected file path : " << filename.toUtf8();
g_config->setOption ("SDL.LastLoadLua", filename.toStdString().c_str() );
fceuWrapperLock();
if ( 0 == FCEU_LoadLuaCode( filename.toStdString().c_str() ) )
{
printf("Error: Could not open the selected lua script: '%s'\n", filename.toStdString().c_str() );
}
fceuWrapperUnLock();
//printf("Open Lua Control Window\n");
luaCtrlWin = new LuaControlDialog_t(this);
luaCtrlWin->show();
#endif
}
void consoleWin_t::openGamePadConfWin(void)
{
if ( gamePadConfWin != NULL )
{
printf("GamePad Config Window Already Open\n");
return;
}
//printf("Open GamePad Config Window\n");
gamePadConfWin = new GamePadConfDialog_t(this);
gamePadConfWin->show();
gamePadConfWin->exec();
delete gamePadConfWin;
gamePadConfWin = NULL;
//printf("GamePad Config Window Destroyed\n");
openGamePadConfWindow(this);
}
void consoleWin_t::openGameSndConfWin(void)
@ -901,11 +960,6 @@ void consoleWin_t::openGameSndConfWin(void)
sndConfWin = new ConsoleSndConfDialog_t(this);
sndConfWin->show();
sndConfWin->exec();
delete sndConfWin;
//printf("Sound Config Window Destroyed\n");
}
void consoleWin_t::openGameVideoConfWin(void)
@ -917,11 +971,6 @@ void consoleWin_t::openGameVideoConfWin(void)
vidConfWin = new ConsoleVideoConfDialog_t(this);
vidConfWin->show();
vidConfWin->exec();
delete vidConfWin;
//printf("Video Config Window Destroyed\n");
}
void consoleWin_t::openHotkeyConfWin(void)
@ -933,11 +982,6 @@ void consoleWin_t::openHotkeyConfWin(void)
hkConfWin = new HotKeyConfDialog_t(this);
hkConfWin->show();
hkConfWin->exec();
delete hkConfWin;
//printf("Hotkey Config Window Destroyed\n");
}
void consoleWin_t::openPaletteConfWin(void)
@ -949,11 +993,80 @@ void consoleWin_t::openPaletteConfWin(void)
paletteConfWin = new PaletteConfDialog_t(this);
paletteConfWin->show();
paletteConfWin->exec();
}
delete paletteConfWin;
void consoleWin_t::openGuiConfWin(void)
{
GuiConfDialog_t *guiConfWin;
//printf("Palette Config Window Destroyed\n");
//printf("Open GUI Config Window\n");
guiConfWin = new GuiConfDialog_t(this);
guiConfWin->show();
}
void consoleWin_t::openCheats(void)
{
GuiCheatsDialog_t *cheatWin;
//printf("Open GUI Cheat Window\n");
cheatWin = new GuiCheatsDialog_t(this);
cheatWin->show();
}
void consoleWin_t::openDebugWindow(void)
{
ConsoleDebugger *debugWin;
//printf("Open GUI 6502 Debugger Window\n");
debugWin = new ConsoleDebugger(this);
debugWin->show();
}
void consoleWin_t::openHexEditor(void)
{
HexEditorDialog_t *hexEditWin;
//printf("Open GUI Hex Editor Window\n");
hexEditWin = new HexEditorDialog_t(this);
hexEditWin->show();
}
void consoleWin_t::openPPUViewer(void)
{
//printf("Open GUI PPU Viewer Window\n");
openPPUViewWindow(this);
}
void consoleWin_t::openNTViewer(void)
{
//printf("Open GUI Name Table Viewer Window\n");
openNameTableViewWindow(this);
}
void consoleWin_t::openCodeDataLogger(void)
{
CodeDataLoggerDialog_t *cdlWin;
//printf("Open Code Data Logger Window\n");
cdlWin = new CodeDataLoggerDialog_t(this);
cdlWin->show();
}
void consoleWin_t::openTraceLogger(void)
{
openTraceLoggerWindow(this);
}
void consoleWin_t::toggleAutoResume(void)
@ -1024,7 +1137,7 @@ void consoleWin_t::toggleGameGenie(bool checked)
void consoleWin_t::loadGameGenieROM(void)
{
int ret;
int ret, useNativeFileDialogVal;
QString filename;
std::string last;
char dir[512];
@ -1032,9 +1145,11 @@ void consoleWin_t::loadGameGenieROM(void)
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilter(tr("GG ROM File (gg.rom)(*Genie*.nes) ;; All files (*)"));
dialog.setNameFilter(tr("GG ROM File (gg.rom *Genie*.nes) ;; All files (*)"));
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Load") );
g_config->getOption ("SDL.LastOpenFile", &last );
@ -1042,9 +1157,10 @@ void consoleWin_t::loadGameGenieROM(void)
dialog.setDirectory( tr(dir) );
// the gnome default file dialog is not playing nice with QT.
// TODO make this a config option to use native file dialog.
dialog.setOption(QFileDialog::DontUseNativeDialog, true);
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.show();
ret = dialog.exec();
@ -1104,7 +1220,7 @@ void consoleWin_t::fdsEjectDisk(void)
void consoleWin_t::fdsLoadBiosFile(void)
{
int ret;
int ret, useNativeFileDialogVal;
QString filename;
std::string last;
char dir[512];
@ -1112,9 +1228,11 @@ void consoleWin_t::fdsLoadBiosFile(void)
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilter(tr("ROM files (*.rom)(*.ROM) ;; All files (*)"));
dialog.setNameFilter(tr("ROM files (*.rom *.ROM) ;; All files (*)"));
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Load") );
g_config->getOption ("SDL.LastOpenFile", &last );
@ -1122,9 +1240,10 @@ void consoleWin_t::fdsLoadBiosFile(void)
dialog.setDirectory( tr(dir) );
// the gnome default file dialog is not playing nice with QT.
// TODO make this a config option to use native file dialog.
dialog.setOption(QFileDialog::DontUseNativeDialog, true);
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.show();
ret = dialog.exec();
@ -1168,7 +1287,7 @@ void consoleWin_t::fdsLoadBiosFile(void)
void consoleWin_t::openMovie(void)
{
int ret;
int ret, useNativeFileDialogVal;
QString filename;
std::string last;
char dir[512];
@ -1179,6 +1298,8 @@ void consoleWin_t::openMovie(void)
dialog.setNameFilter(tr("FM2 Movies (*.fm2) ;; All files (*)"));
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Open") );
g_config->getOption ("SDL.LastOpenFile", &last );
@ -1186,9 +1307,10 @@ void consoleWin_t::openMovie(void)
dialog.setDirectory( tr(dir) );
// the gnome default file dialog is not playing nice with QT.
// TODO make this a config option to use native file dialog.
dialog.setOption(QFileDialog::DontUseNativeDialog, true);
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.show();
ret = dialog.exec();
@ -1250,7 +1372,7 @@ void consoleWin_t::recordMovie(void)
void consoleWin_t::recordMovieAs(void)
{
int ret;
int ret, useNativeFileDialogVal;
QString filename;
std::string last;
char dir[512];
@ -1261,6 +1383,8 @@ void consoleWin_t::recordMovieAs(void)
dialog.setNameFilter(tr("FM2 Movies (*.fm2) ;; All files (*)"));
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Save") );
g_config->getOption ("SDL.LastOpenFile", &last );
@ -1268,9 +1392,10 @@ void consoleWin_t::recordMovieAs(void)
dialog.setDirectory( tr(dir) );
// the gnome default file dialog is not playing nice with QT.
// TODO make this a config option to use native file dialog.
dialog.setOption(QFileDialog::DontUseNativeDialog, true);
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.show();
ret = dialog.exec();
@ -1317,11 +1442,16 @@ void consoleWin_t::aboutFCEUX(void)
aboutWin = new AboutWindow(this);
aboutWin->show();
aboutWin->exec();
return;
}
delete aboutWin;
void consoleWin_t::aboutQt(void)
{
//printf("About Qt Window\n");
QMessageBox::aboutQt(this);
//printf("About Window Destroyed\n");
//printf("About Qt Destroyed\n");
return;
}
@ -1354,10 +1484,23 @@ void consoleWin_t::updatePeriodic(void)
{
nes_shm->blitUpdated = 0;
viewport->transfer2LocalBuffer();
if ( viewport_SDL )
{
viewport_SDL->transfer2LocalBuffer();
viewport_SDL->render();
}
else
{
viewport_GL->transfer2LocalBuffer();
//viewport_GL->repaint();
viewport_GL->update();
}
}
//viewport->repaint();
viewport->update();
if ( errorMsgValid )
{
showErrorMsgWindow();
errorMsgValid = false;
}
return;

View File

@ -39,17 +39,21 @@ class consoleWin_t : public QMainWindow
consoleWin_t(QWidget *parent = 0);
~consoleWin_t(void);
ConsoleViewGL_t *viewport;
//ConsoleViewSDL_t *viewport;
ConsoleViewGL_t *viewport_GL;
ConsoleViewSDL_t *viewport_SDL;
void setCyclePeriodms( int ms );
QMutex *mutex;
void QueueErrorMsgWindow( const char *msg );
protected:
QMenu *fileMenu;
QMenu *optMenu;
QMenu *emuMenu;
QMenu *toolsMenu;
QMenu *debugMenu;
QMenu *movieMenu;
QMenu *helpMenu;
@ -68,9 +72,11 @@ class consoleWin_t : public QMainWindow
QAction *gameVideoConfig;
QAction *hotkeyConfig;
QAction *paletteConfig;
QAction *guiConfig;
QAction *autoResume;
QAction *fullscreen;
QAction *aboutAct;
QAction *aboutActQt;
QAction *state[10];
QAction *powerAct;
QAction *resetAct;
@ -82,27 +88,38 @@ class consoleWin_t : public QMainWindow
QAction *fdsSwitchAct;
QAction *fdsEjectAct;
QAction *fdsLoadBiosAct;
QAction *cheatsAct;
QAction *debuggerAct;
QAction *codeDataLogAct;
QAction *traceLogAct;
QAction *hexEditAct;
QAction *ppuViewAct;
QAction *ntViewAct;
QAction *openMovAct;
QAction *stopMovAct;
QAction *recMovAct;
QAction *recAsMovAct;
QTimer *gameTimer;
emulatorThread_t *emulatorThread;
GamePadConfDialog_t *gamePadConfWin;
std::string errorMsg;
bool errorMsgValid;
protected:
void closeEvent(QCloseEvent *event);
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
void syncActionConfig( QAction *act, const char *property );
int getDirFromFile( const char *path, char *dir );
void showErrorMsgWindow(void);
private:
void createMainMenu(void);
public slots:
void openDebugWindow(void);
void openHexEditor(void);
private slots:
void closeApp(void);
void openROMFile(void);
@ -113,11 +130,15 @@ class consoleWin_t : public QMainWindow
void quickSave(void);
void closeROMCB(void);
void aboutFCEUX(void);
void aboutQt(void);
void openGamePadConfWin(void);
void openGameSndConfWin(void);
void openGameVideoConfWin(void);
void openHotkeyConfWin(void);
void openPaletteConfWin(void);
void openGuiConfWin(void);
void openCodeDataLogger(void);
void openTraceLogger(void);
void toggleAutoResume(void);
void toggleFullscreen(void);
void updatePeriodic(void);
@ -143,6 +164,9 @@ class consoleWin_t : public QMainWindow
void fdsSwitchDisk(void);
void fdsEjectDisk(void);
void fdsLoadBiosFile(void);
void openPPUViewer(void);
void openNTViewer(void);
void openCheats(void);
void openMovie(void);
void stopMovie(void);
void recordMovie(void);

View File

@ -1,35 +1,105 @@
// GamePadConf.cpp
//
#include <QDir>
#include <QInputDialog>
#include <QMessageBox>
#include "Qt/GamePadConf.h"
#include "Qt/main.h"
#include "Qt/dface.h"
#include "Qt/input.h"
#include "Qt/config.h"
#include "Qt/keyscan.h"
#include "Qt/sdl-joystick.h"
#include "Qt/fceuWrapper.h"
struct GamePadConfigLocalData_t
{
std::string guid;
std::string profile;
struct {
char needsSave;
} btn[GAMEPAD_NUM_BUTTONS];
GamePadConfigLocalData_t(void)
{
for (int i=0; i<GAMEPAD_NUM_BUTTONS; i++)
{
btn[i].needsSave = 0;
}
}
};
static GamePadConfigLocalData_t lcl[GAMEPAD_NUM_DEVICES];
static GamePadConfDialog_t *gamePadConfWin = NULL;
//----------------------------------------------------
int openGamePadConfWindow( QWidget *parent )
{
if ( gamePadConfWin != NULL )
{
return -1;
}
gamePadConfWin = new GamePadConfDialog_t(parent);
gamePadConfWin->show();
return 0;
}
//----------------------------------------------------
int closeGamePadConfWindow(void)
{
if ( gamePadConfWin != NULL )
{
gamePadConfWin->closeWindow();
}
return 0;
}
//----------------------------------------------------
GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent)
: QDialog( parent )
{
QHBoxLayout *hbox1, *hbox2;
QHBoxLayout *hbox, *hbox1, *hbox2, *hbox3, *hbox4;
QVBoxLayout *vbox;
QGridLayout *grid;
QCheckBox *efs_chkbox, *udlr_chkbox;
QGroupBox *frame;
QPushButton *loadDefaultButton;
QGroupBox *frame1, *frame2;
QLabel *label;
QPushButton *newProfileButton;
QPushButton *saveProfileButton;
QPushButton *applyProfileButton;
QPushButton *removeProfileButton;
QPushButton *clearAllButton;
QPushButton *closebutton;
QPushButton *clearButton[GAMEPAD_NUM_BUTTONS];
std::string prefix;
char stmp[256];
gamePadConfWin = this;
// Ensure that joysticks are enabled, no harm calling init again.
InitJoysticks();
portNum = 0;
configNo = 0;
buttonConfigStatus = 1;
inputTimer = new QTimer( this );
connect( inputTimer, &QTimer::timeout, this, &GamePadConfDialog_t::updatePeriodic );
setWindowTitle( tr("GamePad Config") );
hbox1 = new QHBoxLayout();
hbox2 = new QHBoxLayout();
hbox3 = new QHBoxLayout();
hbox4 = new QHBoxLayout();
QLabel *label = new QLabel(tr("Port:"));
label = new QLabel(tr("Console Port:"));
portSel = new QComboBox();
hbox1->addWidget( label );
hbox1->addWidget( portSel );
@ -39,6 +109,83 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent)
portSel->addItem( tr("3"), 2 );
portSel->addItem( tr("4"), 3 );
label = new QLabel(tr("Device:"));
devSel = new QComboBox();
hbox2->addWidget( label );
hbox2->addWidget( devSel );
devSel->addItem( tr("Keyboard"), -1 );
for (int i=0; i<MAX_JOYSTICKS; i++)
{
jsDev_t *js = getJoystickDevice( i );
if ( js != NULL )
{
if ( js->isConnected() )
{
sprintf( stmp, "%i: %s", i, js->getName() );
devSel->addItem( tr(stmp), i );
}
}
}
for (int i=0; i<devSel->count(); i++)
{
if ( devSel->itemData(i).toInt() == GamePad[portNum].getDeviceIndex() )
{
devSel->setCurrentIndex( i );
}
}
label = new QLabel(tr("GUID:"));
guidLbl = new QLabel();
hbox3->addWidget( label );
hbox3->addWidget( guidLbl );
guidLbl->setText( GamePad[portNum].getGUID() );
frame1 = new QGroupBox(tr("Mapping Profile:"));
//grid = new QGridLayout();
vbox = new QVBoxLayout();
//frame1->setLayout( grid );
frame1->setLayout( vbox );
hbox = new QHBoxLayout();
vbox->addLayout( hbox );
mapSel = new QComboBox();
hbox->addWidget( mapSel );
mapSel->setWhatsThis( tr("Combo box for selection of a saved button mapping profile for the selected device"));
mapSel->addItem( tr("default"), 0 );
hbox = new QHBoxLayout();
vbox->addLayout( hbox );
applyProfileButton = new QPushButton( tr("Load") );
applyProfileButton->setWhatsThis(tr("Sets Current Active Map to the Selected Profile"));
hbox->addWidget( applyProfileButton );
saveProfileButton = new QPushButton( tr("Save") );
saveProfileButton->setWhatsThis(tr("Stores Current Active Map to the Selected Profile"));
hbox->addWidget( saveProfileButton );
hbox = new QHBoxLayout();
vbox->addLayout( hbox );
newProfileButton = new QPushButton( tr("New") );
newProfileButton->setWhatsThis(tr("Create a New Map Profile"));
hbox->addWidget( newProfileButton );
removeProfileButton = new QPushButton( tr("Delete") );
removeProfileButton->setWhatsThis(tr("Deletes the Selected Map Profile"));
hbox->addWidget( removeProfileButton );
mapMsg = new QLabel();
vbox->addWidget(mapMsg);
efs_chkbox = new QCheckBox( tr("Enable Four Score") );
udlr_chkbox = new QCheckBox( tr("Allow Up+Down/Left+Right") );
@ -50,13 +197,12 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent)
g_config->getOption("SDL.Input.EnableOppositeDirectionals", &opposite_dirs);
udlr_chkbox->setChecked( opposite_dirs );
frame = new QGroupBox(tr("Buttons:"));
grid = new QGridLayout();
frame2 = new QGroupBox(tr("Current Active Button Mappings:"));
grid = new QGridLayout();
grid-> setHorizontalSpacing(50);
//frame->setFrameStyle( QFrame::Box );
frame->setLayout( grid );
frame2->setLayout( grid );
for (int i=0; i<GAMEPAD_NUM_BUTTONS; i++)
{
@ -71,23 +217,25 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent)
buttonName = new QLabel(tr(text));
keyName[i] = new QLabel();
keyState[i] = new QLabel( tr("F") );
label = new QLabel( tr("State:") );
button[i] = new GamePadConfigButton_t(i);
clearButton[i] = new QPushButton( tr("Clear") );
grid->addWidget( buttonName , i, 0, Qt::AlignCenter );
grid->addWidget( keyName[i] , i, 1, Qt::AlignCenter );
grid->addWidget( button[i] , i, 2, Qt::AlignCenter );
grid->addWidget( clearButton[i], i, 3, Qt::AlignCenter );
grid->addWidget( label , i, 2, Qt::AlignCenter );
grid->addWidget( keyState[i] , i, 3, Qt::AlignCenter );
grid->addWidget( button[i] , i, 4, Qt::AlignCenter );
grid->addWidget( clearButton[i], i, 5, Qt::AlignCenter );
}
updateCntrlrDpy();
loadDefaultButton = new QPushButton(tr("Load Defaults"));
clearAllButton = new QPushButton(tr("Clear All"));
closebutton = new QPushButton(tr("Close"));
hbox2->addWidget( loadDefaultButton );
hbox2->addWidget( clearAllButton );
hbox2->addWidget( closebutton );
hbox4->addWidget( clearAllButton );
hbox4->addWidget( closebutton );
connect(button[0], SIGNAL(clicked()), this, SLOT(changeButton0(void)) );
connect(button[1], SIGNAL(clicked()), this, SLOT(changeButton1(void)) );
@ -111,30 +259,55 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent)
connect(clearButton[8], SIGNAL(clicked()), this, SLOT(clearButton8(void)) );
connect(clearButton[9], SIGNAL(clicked()), this, SLOT(clearButton9(void)) );
connect(loadDefaultButton, SIGNAL(clicked()), this, SLOT(loadDefaults(void)) );
connect(newProfileButton , SIGNAL(clicked()), this, SLOT(newProfileCallback(void)) );
connect(applyProfileButton , SIGNAL(clicked()), this, SLOT(loadProfileCallback(void)) );
connect(saveProfileButton , SIGNAL(clicked()), this, SLOT(saveProfileCallback(void)) );
connect(removeProfileButton, SIGNAL(clicked()), this, SLOT(deleteProfileCallback(void)) );
connect(clearAllButton , SIGNAL(clicked()), this, SLOT(clearAllCallback(void)) );
connect(closebutton , SIGNAL(clicked()), this, SLOT(closeWindow(void)) );
connect(portSel , SIGNAL(activated(int)), this, SLOT(controllerSelect(int)) );
connect(portSel , SIGNAL(activated(int)), this, SLOT(portSelect(int)) );
connect(devSel , SIGNAL(activated(int)), this, SLOT(deviceSelect(int)) );
connect(efs_chkbox , SIGNAL(stateChanged(int)), this, SLOT(ena4score(int)) );
connect(udlr_chkbox, SIGNAL(stateChanged(int)), this, SLOT(oppDirEna(int)) );
QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->addLayout( hbox1 );
mainLayout->addLayout( hbox2 );
mainLayout->addLayout( hbox3 );
mainLayout->addWidget( frame1 );
mainLayout->addWidget( efs_chkbox );
mainLayout->addWidget( udlr_chkbox );
mainLayout->addWidget( frame );
mainLayout->addLayout( hbox2 );
mainLayout->addWidget( frame2 );
mainLayout->addLayout( hbox4 );
setLayout( mainLayout );
inputTimer->start( 33 ); // 30hz
for (int i=0; i<GAMEPAD_NUM_DEVICES; i++)
{
sprintf( stmp, "SDL.Input.GamePad.%i.", i );
prefix = stmp;
g_config->getOption(prefix + "Profile", &lcl[i].profile );
lcl[i].guid.assign( GamePad[i].getGUID() );
}
loadMapList();
}
//----------------------------------------------------
GamePadConfDialog_t::~GamePadConfDialog_t(void)
{
inputTimer->stop();
buttonConfigStatus = 0;
gamePadConfWin = NULL;
printf("GamePad Window Deleted\n");
}
void GamePadConfDialog_t::keyPressEvent(QKeyEvent *event)
{
@ -148,30 +321,152 @@ void GamePadConfDialog_t::keyReleaseEvent(QKeyEvent *event)
pushKeyEvent( event, 0 );
}
//----------------------------------------------------
void GamePadConfDialog_t::loadMapList(void)
{
QDir dir;
QStringList filters, fileList;
const char *baseDir = FCEUI_GetBaseDirectory();
const char *guid;
std::string path;
std::string prefix, mapName;
int index, devIdx;
jsDev_t *js;
size_t n=0;
char stmp[256];
index = devSel->currentIndex();
devIdx = devSel->itemData(index).toInt();
if ( devIdx < 0 )
{
guid = "keyboard";
}
else
{
js = getJoystickDevice( devIdx );
guid = js->getGUID();
}
if ( guid == NULL )
{
return;
}
path = std::string(baseDir) + "/input/" + std::string(guid);
dir.setPath( QString::fromStdString(path) );
filters << "*.txt";
dir.setNameFilters(filters);
fileList = dir.entryList( filters, QDir::Files, QDir::NoSort );
sprintf( stmp, "SDL.Input.GamePad.%u.", portNum );
prefix = stmp;
g_config->getOption(prefix + "Profile", &mapName );
mapSel->clear();
mapSel->addItem( tr("default"), 0 ); n=1;
for (size_t i=0; i < fileList.size(); i++)
{
size_t suffixIdx;
std::string fileName = fileList[i].toStdString();
suffixIdx = fileName.find_last_of('.');
fileName.erase( suffixIdx );
//printf("File: %s \n", fileName.c_str() );
//
if ( fileName.compare("default") == 0 ) continue;
mapSel->addItem( tr(fileName.c_str()), (int)i+1 );
if ( mapName.compare( fileName ) == 0 )
{
mapSel->setCurrentIndex(n);
}
n++;
}
}
//----------------------------------------------------
void GamePadConfDialog_t::updateCntrlrDpy(void)
{
char keyNameStr[128];
for (int i=0; i<GAMEPAD_NUM_BUTTONS; i++)
{
if (GamePadConfig[portNum][i].ButtType[configNo] == BUTTC_KEYBOARD)
if (GamePad[portNum].bmap[i].ButtType == BUTTC_KEYBOARD)
{
snprintf( keyNameStr, sizeof (keyNameStr), "%s",
SDL_GetKeyName (GamePadConfig[portNum][i].ButtonNum[configNo]));
SDL_GetKeyName (GamePad[portNum].bmap[i].ButtonNum));
}
else
{
strcpy( keyNameStr, ButtonName( &GamePadConfig[portNum][i], configNo ) );
strcpy( keyNameStr, ButtonName( &GamePad[portNum].bmap[i] ) );
}
keyName[i]->setText( tr(keyNameStr) );
//if ( lcl[portNum].btn[i].needsSave )
//{
// keyName[i]->setStyleSheet("color: red;");
//}
//else
//{
// keyName[i]->setStyleSheet("color: black;");
//}
}
}
//----------------------------------------------------
void GamePadConfDialog_t::controllerSelect(int index)
void GamePadConfDialog_t::portSelect(int index)
{
//printf("Port Number:%i \n", index);
portNum = index;
updateCntrlrDpy();
for (int i=0; i<devSel->count(); i++)
{
if ( devSel->itemData(i).toInt() == GamePad[portNum].getDeviceIndex() )
{
devSel->setCurrentIndex( i );
}
}
guidLbl->setText( GamePad[portNum].getGUID() );
loadMapList();
}
//----------------------------------------------------
void GamePadConfDialog_t::deviceSelect(int index)
{
jsDev_t *js;
int devIdx = devSel->itemData(index).toInt();
js = getJoystickDevice( devIdx );
if ( js != NULL )
{
if ( js->isConnected() )
{
guidLbl->setText( js->getGUID() );
}
}
else
{
guidLbl->setText("");
}
GamePad[portNum].setDeviceIndex( devIdx );
lcl[portNum].guid.assign( GamePad[portNum].getGUID() );
lcl[portNum].profile.assign("default");
loadMapList();
updateCntrlrDpy();
}
//----------------------------------------------------
void GamePadConfDialog_t::ena4score(int state)
@ -190,8 +485,8 @@ void GamePadConfDialog_t::oppDirEna(int state)
//----------------------------------------------------
void GamePadConfDialog_t::changeButton(int padNo, int x)
{
char buf[256];
std::string prefix;
//char buf[256];
//std::string prefix;
const char *keyNameStr;
if ( buttonConfigStatus == 2 )
@ -205,32 +500,13 @@ void GamePadConfDialog_t::changeButton(int padNo, int x)
button[x]->setText("Waiting" );
snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo);
prefix = buf;
DWaitButton (NULL, &GamePadConfig[padNo][x], configNo, &buttonConfigStatus );
DWaitButton (NULL, &GamePad[padNo].bmap[x], &buttonConfigStatus );
g_config->setOption (prefix + GamePadNames[x],
GamePadConfig[padNo][x].ButtonNum[configNo]);
if (GamePadConfig[padNo][x].ButtType[configNo] == BUTTC_KEYBOARD)
{
g_config->setOption (prefix + "DeviceType", "Keyboard");
}
else if (GamePadConfig[padNo][x].ButtType[configNo] == BUTTC_JOYSTICK)
{
g_config->setOption (prefix + "DeviceType", "Joystick");
}
else
{
g_config->setOption (prefix + "DeviceType", "Unknown");
}
g_config->setOption (prefix + "DeviceNum",
GamePadConfig[padNo][x].DeviceNum[configNo]);
keyNameStr = ButtonName( &GamePadConfig[padNo][x], configNo );
keyNameStr = ButtonName( &GamePad[padNo].bmap[x] );
keyName[x]->setText( keyNameStr );
button[x]->setText("Change");
lcl[padNo].btn[x].needsSave = 1;
ButtonConfigEnd ();
@ -239,34 +515,32 @@ void GamePadConfDialog_t::changeButton(int padNo, int x)
//----------------------------------------------------
void GamePadConfDialog_t::clearButton( int padNo, int x )
{
char buf[256];
std::string prefix;
GamePadConfig[padNo][x].ButtonNum[configNo] = -1;
GamePad[padNo].bmap[x].ButtonNum = -1;
keyName[x]->setText("");
snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo);
prefix = buf;
g_config->setOption (prefix + GamePadNames[x],
GamePadConfig[padNo][x].ButtonNum[configNo]);
lcl[padNo].btn[x].needsSave = 1;
}
//----------------------------------------------------
void GamePadConfDialog_t::closeEvent(QCloseEvent *event)
{
//printf("GamePad Close Window Event\n");
promptToSave();
printf("GamePad Close Window Event\n");
buttonConfigStatus = 0;
done(0);
deleteLater();
event->accept();
}
//----------------------------------------------------
void GamePadConfDialog_t::closeWindow(void)
{
//printf("Close Window\n");
promptToSave();
printf("Close Window\n");
buttonConfigStatus = 0;
done(0);
deleteLater();
}
//----------------------------------------------------
void GamePadConfDialog_t::changeButton0(void)
@ -377,46 +651,236 @@ void GamePadConfDialog_t::clearAllCallback(void)
}
}
//----------------------------------------------------
void GamePadConfDialog_t::loadDefaults(void)
void GamePadConfDialog_t::saveConfig(void)
{
char buf[256];
std::string prefix;
int i;
char stmp[256];
std::string prefix, mapName;
if ( portNum > 0 )
sprintf( stmp, "SDL.Input.GamePad.%u.", portNum );
prefix = stmp;
mapName = mapSel->currentText().toStdString();
g_config->setOption(prefix + "DeviceGUID", GamePad[portNum].getGUID() );
g_config->setOption(prefix + "Profile" , mapName.c_str() );
for (i=0; i<GAMEPAD_NUM_BUTTONS; i++)
{
clearAllCallback();
return;
lcl[portNum].btn[i].needsSave = 0;
}
g_config->save();
}
//----------------------------------------------------
void GamePadConfDialog_t::createNewProfile( const char *name )
{
char stmp[256];
//printf("Creating: %s \n", name );
GamePad[portNum].createProfile(name);
mapSel->addItem( tr(name) );
mapSel->setCurrentIndex( mapSel->count() - 1 );
saveConfig();
sprintf( stmp, "Mapping Created: %s/%s \n", GamePad[portNum].getGUID(), name );
mapMsg->setText( tr(stmp) );
}
//----------------------------------------------------
void GamePadConfDialog_t::newProfileCallback(void)
{
int ret;
QInputDialog dialog(this);
dialog.setWindowTitle( tr("New Profile") );
dialog.setLabelText( tr("Specify New Profile Name") );
dialog.setOkButtonText( tr("Create") );
dialog.show();
ret = dialog.exec();
if ( QDialog::Accepted == ret )
{
createNewProfile( dialog.textValue().toStdString().c_str() );
}
}
//----------------------------------------------------
void GamePadConfDialog_t::loadProfileCallback(void)
{
char stmp[256];
int index, devIdx, ret;
std::string mapName;
index = devSel->currentIndex();
devIdx = devSel->itemData(index).toInt();
mapName = mapSel->currentText().toStdString();
GamePad[portNum].setDeviceIndex( devIdx );
if ( mapName.compare("default") == 0 )
{
ret =GamePad[portNum].loadDefaults();
}
else
{
ret = GamePad[portNum].loadProfile( mapName.c_str() );
}
if ( ret == 0 )
{
saveConfig();
sprintf( stmp, "Mapping Loaded: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() );
}
else
{
sprintf( stmp, "Error: Failed to Load Mapping: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() );
}
mapMsg->setText( tr(stmp) );
updateCntrlrDpy();
}
//----------------------------------------------------
void GamePadConfDialog_t::saveProfileCallback(void)
{
int ret;
std::string mapName;
char stmp[256];
mapName = mapSel->currentText().toStdString();
ret = GamePad[portNum].saveCurrentMapToFile( mapName.c_str() );
if ( ret == 0 )
{
saveConfig();
sprintf( stmp, "Mapping Saved: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() );
}
else
{
sprintf( stmp, "Error: Failed to Save Mapping: %s \n", mapName.c_str() );
}
mapMsg->setText( tr(stmp) );
}
//----------------------------------------------------
void GamePadConfDialog_t::deleteProfileCallback(void)
{
int ret;
std::string mapName;
char stmp[256];
mapName = mapSel->currentText().toStdString();
ret = GamePad[portNum].deleteMapping( mapName.c_str() );
if ( ret == 0 )
{
sprintf( stmp, "Mapping Deleted: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() );
}
else
{
sprintf( stmp, "Error: Failed to Delete Mapping: %s \n", mapName.c_str() );
}
mapMsg->setText( tr(stmp) );
loadMapList();
}
//----------------------------------------------------
void GamePadConfDialog_t::promptToSave(void)
{
int i,j,n;
std::string msg;
QMessageBox msgBox(this);
char saveRequired = 0;
char padNeedsSave[GAMEPAD_NUM_DEVICES];
char stmp[256];
n=0;
for (i=0; i<GAMEPAD_NUM_DEVICES; i++)
{
padNeedsSave[i] = 0;
for (j=0; j<GAMEPAD_NUM_BUTTONS; j++)
{
if ( lcl[i].btn[j].needsSave )
{
padNeedsSave[i] = 1;
saveRequired = 1;
n++;
break;
}
}
}
snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", portNum);
prefix = buf;
for (int x=0; x<GAMEPAD_NUM_BUTTONS; x++)
if ( !saveRequired )
{
GamePadConfig[portNum][x].ButtType[configNo] = BUTTC_KEYBOARD;
GamePadConfig[portNum][x].DeviceNum[configNo] = 0;
GamePadConfig[portNum][x].ButtonNum[configNo] = DefaultGamePad[portNum][x];
GamePadConfig[portNum][x].NumC = 1;
return;
}
sprintf( stmp, "Warning: Gamepad mappings have not been saved for port%c ", (n > 1) ? 's':' ');
g_config->setOption (prefix + GamePadNames[x],
GamePadConfig[portNum][x].ButtonNum[configNo]);
msg.assign( stmp );
if (GamePadConfig[portNum][x].ButtType[configNo] == BUTTC_KEYBOARD)
j=n;
for (i=0; i<GAMEPAD_NUM_DEVICES; i++)
{
if ( padNeedsSave[i] )
{
g_config->setOption (prefix + "DeviceType", "Keyboard");
sprintf( stmp, "%i", i+1 );
msg.append(stmp);
j--;
if ( j > 1 )
{
msg.append(", ");
}
else if ( j == 1 )
{
msg.append(" and ");
}
}
else if (GamePadConfig[portNum][x].ButtType[configNo] == BUTTC_JOYSTICK)
}
msg.append(".");
msgBox.setIcon( QMessageBox::Warning );
msgBox.setText( tr(msg.c_str()) );
msgBox.show();
//msgBox.resize( 512, 128 );
msgBox.exec();
}
//----------------------------------------------------
void GamePadConfDialog_t::updatePeriodic(void)
{
for (int i=0; i<GAMEPAD_NUM_BUTTONS; i++)
{
const char *txt, *style;
if ( GamePad[portNum].bmap[i].state )
{
txt = " T ";
style = "background-color: green; color: white;";
}
else
{
txt = " F ";
style = "background-color: red; color: white;";
}
keyState[i]->setText( tr(txt) );
keyState[i]->setStyleSheet( style );
if ( lcl[portNum].btn[i].needsSave )
{
g_config->setOption (prefix + "DeviceType", "Joystick");
keyName[i]->setStyleSheet("color: red;");
}
else
{
g_config->setOption (prefix + "DeviceType", "Unknown");
keyName[i]->setStyleSheet("color: black;");
}
g_config->setOption (prefix + "DeviceNum",
GamePadConfig[portNum][x].DeviceNum[configNo]);
}
updateCntrlrDpy();
}
}
//----------------------------------------------------
GamePadConfigButton_t::GamePadConfigButton_t(int i)

View File

@ -12,6 +12,7 @@
#include <QPushButton>
#include <QLabel>
#include <QFrame>
#include <QTimer>
#include <QGroupBox>
#include "Qt/main.h"
@ -37,12 +38,18 @@ class GamePadConfDialog_t : public QDialog
~GamePadConfDialog_t(void);
protected:
QTimer *inputTimer;
QComboBox *portSel;
QComboBox *devSel;
QComboBox *mapSel;
QComboBox *profSel;
QLabel *guidLbl;
QLabel *mapMsg;
QLabel *keyName[GAMEPAD_NUM_BUTTONS];
QLabel *keyState[GAMEPAD_NUM_BUTTONS];
GamePadConfigButton_t *button[GAMEPAD_NUM_BUTTONS];
int portNum;
int configNo;
int buttonConfigStatus;
void changeButton( int port, int button );
@ -52,6 +59,10 @@ class GamePadConfDialog_t : public QDialog
void closeEvent(QCloseEvent *bar);
private:
void updateCntrlrDpy(void);
void createNewProfile( const char *name );
void loadMapList(void);
void saveConfig(void);
void promptToSave(void);
public slots:
void closeWindow(void);
@ -77,9 +88,18 @@ class GamePadConfDialog_t : public QDialog
void clearButton8(void);
void clearButton9(void);
void clearAllCallback(void);
void loadDefaults(void);
void ena4score(int state);
void oppDirEna(int state);
void controllerSelect(int index);
void portSelect(int index);
void deviceSelect(int index);
void newProfileCallback(void);
void loadProfileCallback(void);
void saveProfileCallback(void);
void deleteProfileCallback(void);
void updatePeriodic(void);
};
int openGamePadConfWindow( QWidget *parent );
int closeGamePadConfWindow(void);

View File

@ -0,0 +1,82 @@
// PaletteConf.cpp
//
#include <QTextEdit>
#include "Qt/GuiConf.h"
#include "Qt/main.h"
#include "Qt/input.h"
#include "Qt/config.h"
#include "Qt/keyscan.h"
#include "Qt/fceuWrapper.h"
#include "Qt/ConsoleWindow.h"
//----------------------------------------------------
GuiConfDialog_t::GuiConfDialog_t(QWidget *parent)
: QDialog( parent )
{
int useNativeFileDialogVal;
int useNativeMenuBarVal;
QVBoxLayout *mainLayout;
//resize( 512, 600 );
// sync with config
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
g_config->getOption ("SDL.UseNativeMenuBar", &useNativeMenuBarVal);
setWindowTitle( tr("GUI Config") );
mainLayout = new QVBoxLayout();
useNativeFileDialog = new QCheckBox( tr("Use Native OS File Dialog") );
useNativeMenuBar = new QCheckBox( tr("Use Native OS Menu Bar") );
useNativeFileDialog->setChecked( useNativeFileDialogVal );
useNativeMenuBar->setChecked( useNativeMenuBarVal );
connect(useNativeFileDialog , SIGNAL(stateChanged(int)), this, SLOT(useNativeFileDialogChanged(int)) );
connect(useNativeMenuBar , SIGNAL(stateChanged(int)), this, SLOT(useNativeMenuBarChanged(int)) );
mainLayout->addWidget( useNativeFileDialog );
mainLayout->addWidget( useNativeMenuBar );
setLayout( mainLayout );
}
//----------------------------------------------------
GuiConfDialog_t::~GuiConfDialog_t(void)
{
printf("Destroy GUI Config Close Window\n");
}
//----------------------------------------------------------------------------
void GuiConfDialog_t::closeEvent(QCloseEvent *event)
{
printf("GUI Config Close Window Event\n");
done(0);
deleteLater();
event->accept();
}
//----------------------------------------------------
void GuiConfDialog_t::closeWindow(void)
{
//printf("Close Window\n");
done(0);
deleteLater();
}
//----------------------------------------------------
void GuiConfDialog_t::useNativeFileDialogChanged(int state)
{
int value = (state == Qt::Unchecked) ? 0 : 1;
g_config->setOption ("SDL.UseNativeFileDialog", value);
}
//----------------------------------------------------
void GuiConfDialog_t::useNativeMenuBarChanged(int state)
{
int value = (state == Qt::Unchecked) ? 0 : 1;
g_config->setOption ("SDL.UseNativeMenuBar", value);
consoleWindow->menuBar()->setNativeMenuBar( value );
}
//----------------------------------------------------

41
src/drivers/Qt/GuiConf.h Normal file
View File

@ -0,0 +1,41 @@
// GuiConf.h
//
#pragma once
#include <QWidget>
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
#include <QCheckBox>
#include <QPushButton>
#include <QLabel>
#include <QFrame>
#include <QGroupBox>
#include <QLineEdit>
#include "Qt/main.h"
class GuiConfDialog_t : public QDialog
{
Q_OBJECT
public:
GuiConfDialog_t(QWidget *parent = 0);
~GuiConfDialog_t(void);
protected:
void closeEvent(QCloseEvent *event);
QCheckBox *useNativeFileDialog;
QCheckBox *useNativeMenuBar;
private:
public slots:
void closeWindow(void);
private slots:
void useNativeFileDialogChanged(int v);
void useNativeMenuBarChanged(int v);
};

2397
src/drivers/Qt/HexEditor.cpp Normal file

File diff suppressed because it is too large Load Diff

250
src/drivers/Qt/HexEditor.h Normal file
View File

@ -0,0 +1,250 @@
// GamePadConf.h
//
#pragma once
#include <list>
#include <vector>
#include <QWidget>
#include <QDialog>
#include <QTimer>
#include <QAction>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
#include <QCheckBox>
#include <QPushButton>
#include <QLabel>
#include <QMenu>
#include <QFrame>
#include <QGroupBox>
#include <QPlainTextEdit>
#include <QKeyEvent>
struct memByte_t
{
unsigned char data;
unsigned char color;
unsigned char actv;
};
struct memBlock_t
{
memBlock_t(void);
~memBlock_t(void);
void init(void);
int size(void){ return _size; }
int numLines(void){ return _maxLines; }
int reAlloc( int newSize );
void setAccessFunc( int (*newMemAccessFunc)( unsigned int offset) );
struct memByte_t *buf;
int _size;
int _maxLines;
int (*memAccessFunc)( unsigned int offset);
};
class HexBookMark
{
public:
HexBookMark(void);
~HexBookMark(void);
int addr;
int mode;
char desc[64];
};
class HexBookMarkManager_t
{
public:
HexBookMarkManager_t(void);
~HexBookMarkManager_t(void);
void removeAll(void);
int addBookMark( int addr, int mode, const char *desc );
int size(void);
HexBookMark *getBookMark( int index );
int saveToFile(void);
int loadFromFile(void);
private:
void updateVector(void);
std::list <HexBookMark*> ls;
std::vector <HexBookMark*> v;
};
class QHexEdit;
class HexBookMarkMenuAction : public QAction
{
Q_OBJECT
public:
HexBookMarkMenuAction( QString desc, QWidget *parent = 0);
~HexBookMarkMenuAction(void);
QHexEdit *qedit;
HexBookMark *bm;
public slots:
void activateCB(void);
};
class HexEditorDialog_t;
class QHexEdit : public QWidget
{
Q_OBJECT
public:
QHexEdit(QWidget *parent = 0);
~QHexEdit(void);
int getMode(void){ return viewMode; };
void setMode( int mode );
void setLine( int newLineOffset );
void setAddr( int newAddrOffset );
void setScrollBars( QScrollBar *h, QScrollBar *v );
void setHorzScroll( int value );
void setHighlightActivity( int enable );
void setHighlightReverseVideo( int enable );
void setForeGroundColor( QColor fg );
void setBackGroundColor( QColor bg );
void memModeUpdate(void);
int checkMemActivity(void);
int getAddr(void){ return cursorAddr; };
enum {
MODE_NES_RAM = 0,
MODE_NES_PPU,
MODE_NES_OAM,
MODE_NES_ROM
};
static const int HIGHLIGHT_ACTIVITY_NUM_COLORS = 16;
protected:
void paintEvent(QPaintEvent *event);
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
void mousePressEvent(QMouseEvent * event);
void resizeEvent(QResizeEvent *event);
void contextMenuEvent(QContextMenuEvent *event);
void calcFontData(void);
void resetCursor(void);
QPoint convPixToCursor( QPoint p );
int convPixToAddr( QPoint p );
QFont font;
int getRomAddrColor( int addr, QColor &fg, QColor &bg );
memBlock_t mb;
int (*memAccessFunc)( unsigned int offset);
QScrollBar *vbar;
QScrollBar *hbar;
QColor highLightColor[ HIGHLIGHT_ACTIVITY_NUM_COLORS ];
QColor rvActvTextColor[ HIGHLIGHT_ACTIVITY_NUM_COLORS ];
HexEditorDialog_t *parent;
uint64_t total_instructions_lp;
int viewMode;
int lineOffset;
int pxCharWidth;
int pxCharHeight;
int pxCursorHeight;
int pxLineSpacing;
int pxLineLead;
int pxLineWidth;
int pxLineXScroll;
int pxXoffset;
int pxYoffset;
int pxHexOffset;
int pxHexAscii;
int cursorPosX;
int cursorPosY;
int cursorAddr;
int cursorBlinkCount;
int viewLines;
int viewWidth;
int viewHeight;
int maxLineOffset;
int editAddr;
int editValue;
int editMask;
int jumpToRomValue;
int ctxAddr;
bool cursorBlink;
bool reverseVideo;
bool actvHighlightEnable;
private slots:
void jumpToROM(void);
void addBookMarkCB(void);
void addDebugSym(void);
void addRamReadBP(void);
void addRamWriteBP(void);
void addRamExecuteBP(void);
void addPpuReadBP(void);
void addPpuWriteBP(void);
};
class HexEditorDialog_t : public QDialog
{
Q_OBJECT
public:
HexEditorDialog_t(QWidget *parent = 0);
~HexEditorDialog_t(void);
void gotoAddress(int newAddr);
void populateBookmarkMenu(void);
void setWindowTitle(void);
void openDebugSymbolEditWindow( int addr );
QHexEdit *editor;
protected:
void closeEvent(QCloseEvent *bar);
QScrollBar *vbar;
QScrollBar *hbar;
QTimer *periodicTimer;
QMenu *bookmarkMenu;
QAction *viewRAM;
QAction *viewPPU;
QAction *viewOAM;
QAction *viewROM;
private:
public slots:
void closeWindow(void);
private slots:
void updatePeriodic(void);
void vbarMoved(int value);
void vbarChanged(int value);
void hbarChanged(int value);
void saveRomFile(void);
void saveRomFileAs(void);
void setViewRAM(void);
void setViewPPU(void);
void setViewOAM(void);
void setViewROM(void);
void actvHighlightCB(bool value);
void actvHighlightRVCB(bool value);
void pickForeGroundColor(void);
void pickBackGroundColor(void);
void removeAllBookmarks(void);
};
int hexEditorNumWindows(void);
void hexEditorLoadBookmarks(void);
void hexEditorSaveBookmarks(void);
int hexEditorOpenFromDebugger( int mode, int addr );

View File

@ -7,6 +7,7 @@
#include <SDL.h>
#include <QHeaderView>
#include <QCloseEvent>
#include "Qt/main.h"
#include "Qt/dface.h"
@ -68,13 +69,22 @@ HotKeyConfDialog_t::HotKeyConfDialog_t(QWidget *parent)
//----------------------------------------------------------------------------
HotKeyConfDialog_t::~HotKeyConfDialog_t(void)
{
printf("Destroy Hot Key Config Window\n");
}
//----------------------------------------------------------------------------
void HotKeyConfDialog_t::closeEvent(QCloseEvent *event)
{
printf("Hot Key Close Window Event\n");
done(0);
deleteLater();
event->accept();
}
//----------------------------------------------------------------------------
void HotKeyConfDialog_t::closeWindow(void)
{
//printf("Close Window\n");
done(0);
deleteLater();
}
//----------------------------------------------------------------------------
void HotKeyConfDialog_t::assignHotkey(QKeyEvent *event)

View File

@ -1,4 +1,4 @@
// GamePadConf.h
// HotKeyConf.h
//
#pragma once
@ -27,6 +27,7 @@ class HotKeyConfDialog_t : public QDialog
~HotKeyConfDialog_t(void);
protected:
void closeEvent(QCloseEvent *event);
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
void assignHotkey(QKeyEvent *event);

View File

@ -0,0 +1,266 @@
// LuaControl.cpp
//
#include <list>
#include <QTextEdit>
#include <QFileDialog>
#include "../../fceu.h"
#ifdef _S9XLUA_H
#include "../../fceulua.h"
#endif
#include "Qt/LuaControl.h"
#include "Qt/main.h"
#include "Qt/input.h"
#include "Qt/config.h"
#include "Qt/keyscan.h"
#include "Qt/fceuWrapper.h"
#include "Qt/ConsoleUtilities.h"
static bool luaScriptRunning = false;
static std::string luaOutputText;
static std::list <LuaControlDialog_t*> winList;
//----------------------------------------------------
LuaControlDialog_t::LuaControlDialog_t(QWidget *parent)
: QDialog( parent )
{
QVBoxLayout *mainLayout;
QHBoxLayout *hbox;
QLabel *lbl;
std::string filename;
resize( 512, 512 );
setWindowTitle( tr("Lua Script Control") );
mainLayout = new QVBoxLayout();
lbl = new QLabel( tr("Script File:") );
scriptPath = new QLineEdit();
scriptArgs = new QLineEdit();
g_config->getOption ("SDL.LastLoadLua", &filename );
scriptPath->setText( filename.c_str() );
luaOutput = new QTextEdit();
luaOutput->setReadOnly(true);
hbox = new QHBoxLayout();
browseButton = new QPushButton( tr("Browse") );
stopButton = new QPushButton( tr("Stop") );
if ( luaScriptRunning )
{
startButton = new QPushButton( tr("Restart") );
}
else
{
startButton = new QPushButton( tr("Start") );
}
stopButton->setEnabled( luaScriptRunning );
connect(browseButton , SIGNAL(clicked()), this, SLOT(openLuaScriptFile(void)) );
connect(stopButton , SIGNAL(clicked()), this, SLOT(stopLuaScript(void)) );
connect(startButton , SIGNAL(clicked()), this, SLOT(startLuaScript(void)) );
hbox->addWidget( browseButton );
hbox->addWidget( stopButton );
hbox->addWidget( startButton );
mainLayout->addWidget( lbl );
mainLayout->addWidget( scriptPath );
mainLayout->addLayout( hbox );
hbox = new QHBoxLayout();
lbl = new QLabel( tr("Arguments:") );
hbox->addWidget( lbl );
hbox->addWidget( scriptArgs );
mainLayout->addLayout( hbox );
lbl = new QLabel( tr("Output Console:") );
mainLayout->addWidget( lbl );
mainLayout->addWidget( luaOutput );
//connect(useNativeFileDialog , SIGNAL(stateChanged(int)), this, SLOT(useNativeFileDialogChanged(int)) );
setLayout( mainLayout );
winList.push_back( this );
}
//----------------------------------------------------
LuaControlDialog_t::~LuaControlDialog_t(void)
{
std::list <LuaControlDialog_t*>::iterator it;
printf("Destroy Lua Control Window\n");
for (it = winList.begin(); it != winList.end(); it++)
{
if ( (*it) == this )
{
winList.erase(it);
//printf("Removing Lua Window\n");
break;
}
}
}
//----------------------------------------------------
void LuaControlDialog_t::closeEvent(QCloseEvent *event)
{
printf("Lua Control Close Window Event\n");
done(0);
deleteLater();
event->accept();
}
//----------------------------------------------------
void LuaControlDialog_t::closeWindow(void)
{
//printf("Lua Control Close Window\n");
done(0);
deleteLater();
}
//----------------------------------------------------
void LuaControlDialog_t::openLuaScriptFile(void)
{
#ifdef _S9XLUA_H
int ret, useNativeFileDialogVal;
QString filename;
std::string last;
char dir[512];
QFileDialog dialog(this, tr("Open LUA Script") );
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilter(tr("LUA Scripts (*.lua *.LUA) ;; All files (*)"));
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Load") );
g_config->getOption ("SDL.LastLoadLua", &last );
if ( last.size() == 0 )
{
last.assign( "/usr/share/fceux/luaScripts" );
}
getDirFromFile( last.c_str(), dir );
dialog.setDirectory( tr(dir) );
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.show();
ret = dialog.exec();
if ( ret )
{
QStringList fileList;
fileList = dialog.selectedFiles();
if ( fileList.size() > 0 )
{
filename = fileList[0];
}
}
if ( filename.isNull() )
{
return;
}
qDebug() << "selected file path : " << filename.toUtf8();
g_config->setOption ("SDL.LastLoadLua", filename.toStdString().c_str() );
scriptPath->setText( filename.toStdString().c_str() );
#endif
}
//----------------------------------------------------
void LuaControlDialog_t::startLuaScript(void)
{
#ifdef _S9XLUA_H
luaOutputText.clear();
fceuWrapperLock();
if ( 0 == FCEU_LoadLuaCode( scriptPath->text().toStdString().c_str(), scriptArgs->text().toStdString().c_str() ) )
{
printf("Error: Could not open the selected lua script: '%s'\n", scriptPath->text().toStdString().c_str() );
}
fceuWrapperUnLock();
#endif
}
//----------------------------------------------------
void LuaControlDialog_t::stopLuaScript(void)
{
#ifdef _S9XLUA_H
fceuWrapperLock();
FCEU_LuaStop();
fceuWrapperUnLock();
#endif
}
//----------------------------------------------------
void LuaControlDialog_t::refreshState(void)
{
if ( luaScriptRunning )
{
stopButton->setEnabled( true );
startButton->setText( tr("Restart") );
}
else
{
stopButton->setEnabled( false );
startButton->setText( tr("Start") );
}
luaOutput->setText( luaOutputText.c_str() );
}
//----------------------------------------------------
void updateLuaWindows( void )
{
std::list <LuaControlDialog_t*>::iterator it;
for (it = winList.begin(); it != winList.end(); it++)
{
(*it)->refreshState();
}
}
//----------------------------------------------------
void WinLuaOnStart(intptr_t hDlgAsInt)
{
luaScriptRunning = true;
//printf("Lua Script Running: %i \n", luaScriptRunning );
updateLuaWindows();
}
//----------------------------------------------------
void WinLuaOnStop(intptr_t hDlgAsInt)
{
luaScriptRunning = false;
//printf("Lua Script Running: %i \n", luaScriptRunning );
updateLuaWindows();
}
//----------------------------------------------------
void PrintToWindowConsole(intptr_t hDlgAsInt, const char* str)
{
//printf("%s\n", str );
luaOutputText.append( str );
updateLuaWindows();
}
//----------------------------------------------------

View File

@ -0,0 +1,49 @@
// LuaControl.h
//
#pragma once
#include <QWidget>
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
#include <QCheckBox>
#include <QPushButton>
#include <QLabel>
#include <QFrame>
#include <QGroupBox>
#include <QLineEdit>
#include <QTextEdit>
#include "Qt/main.h"
class LuaControlDialog_t : public QDialog
{
Q_OBJECT
public:
LuaControlDialog_t(QWidget *parent = 0);
~LuaControlDialog_t(void);
void refreshState(void);
protected:
void closeEvent(QCloseEvent *bar);
QLineEdit *scriptPath;
QLineEdit *scriptArgs;
QPushButton *browseButton;
QPushButton *stopButton;
QPushButton *startButton;
QTextEdit *luaOutput;
private:
public slots:
void closeWindow(void);
private slots:
void openLuaScriptFile(void);
void startLuaScript(void);
void stopLuaScript(void);
};

View File

@ -0,0 +1,776 @@
// NameTableViewer.cpp
#include <stdio.h>
#include <stdint.h>
#include <QDir>
#include <QPainter>
#include <QInputDialog>
#include <QMessageBox>
#include "../../types.h"
#include "../../fceu.h"
#include "../../cart.h"
#include "../../ppu.h"
#include "../../ines.h"
#include "../../debug.h"
#include "../../palette.h"
#include "Qt/NameTableViewer.h"
#include "Qt/main.h"
#include "Qt/dface.h"
#include "Qt/input.h"
#include "Qt/config.h"
#include "Qt/fceuWrapper.h"
static ppuNameTableViewerDialog_t *nameTableViewWindow = NULL;
static uint8_t palcache[36]; //palette cache
static int NTViewScanline = 0;
static int NTViewSkip = 100;
static int NTViewRefresh = 1;
static int chrchanged = 0;
static int xpos = 0, ypos = 0;
static int attview = 0;
static int hidepal = 0;
static bool drawScrollLines = true;
static bool redrawtables = true;
// checkerboard tile for attribute view
static const uint8_t ATTRIBUTE_VIEW_TILE[16] = { 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
static class NTCache
{
public:
NTCache(void)
: curr_vnapage(0)
{}
uint8_t* curr_vnapage;
uint8_t cache[0x400];
} cache[4];
static ppuNameTable_t nameTable[4];
enum NT_MirrorType
{
NT_NONE = -1,
NT_HORIZONTAL, NT_VERTICAL, NT_FOUR_SCREEN,
NT_SINGLE_SCREEN_TABLE_0, NT_SINGLE_SCREEN_TABLE_1,
NT_SINGLE_SCREEN_TABLE_2, NT_SINGLE_SCREEN_TABLE_3,
NT_NUM_MIRROR_TYPES
};
static NT_MirrorType ntmirroring = NT_NONE, oldntmirroring = NT_NONE;
static void initNameTableViewer(void);
static void ChangeMirroring(void);
//----------------------------------------------------
int openNameTableViewWindow( QWidget *parent )
{
if ( nameTableViewWindow != NULL )
{
return -1;
}
initNameTableViewer();
nameTableViewWindow = new ppuNameTableViewerDialog_t(parent);
nameTableViewWindow->show();
return 0;
}
//----------------------------------------------------
ppuNameTableViewerDialog_t::ppuNameTableViewerDialog_t(QWidget *parent)
: QDialog( parent )
{
QVBoxLayout *mainLayout, *vbox;
QHBoxLayout *hbox;
QGridLayout *grid;
QGroupBox *frame;
char stmp[64];
nameTableViewWindow = this;
setWindowTitle( tr("Name Table Viewer") );
mainLayout = new QVBoxLayout();
setLayout( mainLayout );
vbox = new QVBoxLayout();
frame = new QGroupBox( tr("Name Tables") );
ntView = new ppuNameTableView_t(this);
grid = new QGridLayout();
vbox->addWidget( ntView );
frame->setLayout( vbox );
mainLayout->addWidget( frame, 100 );
mainLayout->addLayout( grid , 1 );
showScrollLineCbox = new QCheckBox( tr("Show Scroll Lines") );
showAttrbCbox = new QCheckBox( tr("Show Attributes") );
ignorePaletteCbox = new QCheckBox( tr("Ignore Palette") );
showScrollLineCbox->setChecked( drawScrollLines );
showAttrbCbox->setChecked( attview );
ignorePaletteCbox->setChecked( hidepal );
grid->addWidget( showScrollLineCbox, 0, 0, Qt::AlignLeft );
grid->addWidget( showAttrbCbox , 1, 0, Qt::AlignLeft );
grid->addWidget( ignorePaletteCbox , 2, 0, Qt::AlignLeft );
connect( showScrollLineCbox, SIGNAL(stateChanged(int)), this, SLOT(showScrollLinesChanged(int)));
connect( showAttrbCbox , SIGNAL(stateChanged(int)), this, SLOT(showAttrbChanged(int)));
connect( ignorePaletteCbox , SIGNAL(stateChanged(int)), this, SLOT(ignorePaletteChanged(int)));
hbox = new QHBoxLayout();
refreshSlider = new QSlider( Qt::Horizontal );
hbox->addWidget( new QLabel( tr("Refresh: More") ) );
hbox->addWidget( refreshSlider );
hbox->addWidget( new QLabel( tr("Less") ) );
grid->addLayout( hbox, 0, 1, Qt::AlignRight );
refreshSlider->setMinimum( 0);
refreshSlider->setMaximum(25);
refreshSlider->setValue(NTViewRefresh);
connect( refreshSlider, SIGNAL(valueChanged(int)), this, SLOT(refreshSliderChanged(int)));
hbox = new QHBoxLayout();
scanLineEdit = new QLineEdit();
hbox->addWidget( new QLabel( tr("Display on Scanline:") ) );
hbox->addWidget( scanLineEdit );
grid->addLayout( hbox, 1, 1, Qt::AlignRight );
scanLineEdit->setMaxLength( 3 );
scanLineEdit->setInputMask( ">900;" );
sprintf( stmp, "%i", NTViewScanline );
scanLineEdit->setText( tr(stmp) );
connect( scanLineEdit, SIGNAL(textEdited(const QString &)), this, SLOT(scanLineChanged(const QString &)));
hbox = new QHBoxLayout();
frame = new QGroupBox( tr("Current Mirroring") );
grid = new QGridLayout();
mainLayout->addLayout( hbox, 1 );
hbox->addWidget( frame );
frame->setLayout( grid );
horzMirrorBtn = new QRadioButton( tr("Horizontal") );
vertMirrorBtn = new QRadioButton( tr("Vertical") );
fourScreenBtn = new QRadioButton( tr("Four Screen") );
singleScreenBtn[0] = new QRadioButton( tr("Single Screen 0") );
singleScreenBtn[1] = new QRadioButton( tr("Single Screen 1") );
singleScreenBtn[2] = new QRadioButton( tr("Single Screen 2") );
singleScreenBtn[3] = new QRadioButton( tr("Single Screen 3") );
grid->addWidget( horzMirrorBtn, 0, 0, Qt::AlignLeft );
grid->addWidget( vertMirrorBtn, 1, 0, Qt::AlignLeft );
grid->addWidget( fourScreenBtn, 2, 0, Qt::AlignLeft );
grid->addWidget( singleScreenBtn[0], 0, 1, Qt::AlignLeft );
grid->addWidget( singleScreenBtn[1], 1, 1, Qt::AlignLeft );
grid->addWidget( singleScreenBtn[2], 2, 1, Qt::AlignLeft );
grid->addWidget( singleScreenBtn[3], 3, 1, Qt::AlignLeft );
connect( horzMirrorBtn , SIGNAL(clicked(void)), this, SLOT(horzMirrorClicked(void)));
connect( vertMirrorBtn , SIGNAL(clicked(void)), this, SLOT(vertMirrorClicked(void)));
connect( fourScreenBtn , SIGNAL(clicked(void)), this, SLOT(fourScreenClicked(void)));
connect( singleScreenBtn[0], SIGNAL(clicked(void)), this, SLOT(singleScreen0Clicked(void)));
connect( singleScreenBtn[1], SIGNAL(clicked(void)), this, SLOT(singleScreen1Clicked(void)));
connect( singleScreenBtn[2], SIGNAL(clicked(void)), this, SLOT(singleScreen2Clicked(void)));
connect( singleScreenBtn[3], SIGNAL(clicked(void)), this, SLOT(singleScreen3Clicked(void)));
updateMirrorButtons();
vbox = new QVBoxLayout();
frame = new QGroupBox( tr("Properties") );
hbox->addWidget( frame );
frame->setLayout( vbox );
tileID = new QLabel( tr("Tile ID:") );
tileXY = new QLabel( tr("X/Y :") );
ppuAddrLbl = new QLabel( tr("PPU Address:") );
attrbLbl = new QLabel( tr("Attribute:") );
vbox->addWidget( tileID );
vbox->addWidget( tileXY );
vbox->addWidget( ppuAddrLbl );
vbox->addWidget( attrbLbl );
FCEUD_UpdateNTView( -1, true);
updateTimer = new QTimer( this );
connect( updateTimer, &QTimer::timeout, this, &ppuNameTableViewerDialog_t::periodicUpdate );
updateTimer->start( 33 ); // 30hz
}
//----------------------------------------------------
ppuNameTableViewerDialog_t::~ppuNameTableViewerDialog_t(void)
{
updateTimer->stop();
nameTableViewWindow = NULL;
printf("Name Table Viewer Window Deleted\n");
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::closeEvent(QCloseEvent *event)
{
printf("Name Table Viewer Close Window Event\n");
done(0);
deleteLater();
event->accept();
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::closeWindow(void)
{
printf("Close Window\n");
done(0);
deleteLater();
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::periodicUpdate(void)
{
updateMirrorButtons();
if ( redrawtables )
{
this->update();
redrawtables = false;
}
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::setPropertyLabels( int TileID, int TileX, int TileY, int NameTable, int PPUAddress, int AttAddress, int Attrib )
{
char stmp[64];
sprintf( stmp, "Tile ID: %02X", TileID);
tileID->setText( tr(stmp) );
sprintf( stmp, "X/Y : %0d/%0d", TileX, TileY);
tileXY->setText( tr(stmp) );
sprintf(stmp,"PPU Address: %04X",PPUAddress);
ppuAddrLbl->setText( tr(stmp) );
sprintf(stmp,"Attribute: %1X (%04X)",Attrib,AttAddress);
attrbLbl->setText( tr(stmp) );
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::updateMirrorButtons(void)
{
switch ( ntmirroring )
{
default:
case NT_NONE:
break;
case NT_HORIZONTAL:
horzMirrorBtn->setChecked(true);
break;
case NT_VERTICAL:
vertMirrorBtn->setChecked(true);
break;
case NT_FOUR_SCREEN:
fourScreenBtn->setChecked(true);
break;
case NT_SINGLE_SCREEN_TABLE_0:
case NT_SINGLE_SCREEN_TABLE_1:
case NT_SINGLE_SCREEN_TABLE_2:
case NT_SINGLE_SCREEN_TABLE_3:
{
int i = ntmirroring - NT_SINGLE_SCREEN_TABLE_0;
singleScreenBtn[i]->setChecked(true);
}
break;
}
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::horzMirrorClicked(void)
{
ntmirroring = NT_HORIZONTAL;
ChangeMirroring();
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::vertMirrorClicked(void)
{
ntmirroring = NT_VERTICAL;
ChangeMirroring();
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::fourScreenClicked(void)
{
ntmirroring = NT_FOUR_SCREEN;
ChangeMirroring();
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::singleScreen0Clicked(void)
{
ntmirroring = NT_SINGLE_SCREEN_TABLE_0;
ChangeMirroring();
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::singleScreen1Clicked(void)
{
ntmirroring = NT_SINGLE_SCREEN_TABLE_1;
ChangeMirroring();
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::singleScreen2Clicked(void)
{
ntmirroring = NT_SINGLE_SCREEN_TABLE_2;
ChangeMirroring();
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::singleScreen3Clicked(void)
{
ntmirroring = NT_SINGLE_SCREEN_TABLE_3;
ChangeMirroring();
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::scanLineChanged( const QString &txt )
{
std::string s;
s = txt.toStdString();
if ( s.size() > 0 )
{
NTViewScanline = strtoul( s.c_str(), NULL, 10 );
}
//printf("ScanLine: '%s' %i\n", s.c_str(), PPUViewScanline );
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::showScrollLinesChanged(int state)
{
drawScrollLines = (state != Qt::Unchecked);
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::showAttrbChanged(int state)
{
attview = (state != Qt::Unchecked);
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::ignorePaletteChanged(int state)
{
hidepal = (state != Qt::Unchecked);
}
//----------------------------------------------------
void ppuNameTableViewerDialog_t::refreshSliderChanged(int value)
{
NTViewRefresh = value;
}
//----------------------------------------------------
ppuNameTableView_t::ppuNameTableView_t(QWidget *parent)
: QWidget(parent)
{
this->parent = (ppuNameTableViewerDialog_t*)parent;
this->setFocusPolicy(Qt::StrongFocus);
this->setMouseTracking(true);
viewWidth = 256 * 2;
viewHeight = 240 * 2;
setMinimumWidth( viewWidth );
setMinimumHeight( viewHeight );
}
//----------------------------------------------------
ppuNameTableView_t::~ppuNameTableView_t(void)
{
}
//----------------------------------------------------
void ppuNameTableView_t::resizeEvent(QResizeEvent *event)
{
viewWidth = event->size().width();
viewHeight = event->size().height();
//printf("%ix%i\n", viewWidth, viewHeight );
}
//----------------------------------------------------
void ppuNameTableView_t::computeNameTableProperties( int x, int y )
{
int i, xx, yy, w, h, TileID, TileX, TileY, NameTable, PPUAddress, AttAddress, Attrib;
ppuNameTable_t *tbl = NULL;
NameTable = 0;
if ( vnapage[0] == NULL )
{
return;
}
for (i=0; i<4; i++)
{
xx = nameTable[i].x;
yy = nameTable[i].y;
w = (nameTable[i].w * 256);
h = (nameTable[i].h * 240);
if ( (x >= xx) && (x < (xx+w) ) &&
(y >= yy) && (y < (yy+h) ) )
{
tbl = &nameTable[i];
NameTable = i;
break;
}
}
if ( tbl == NULL )
{
//printf("Mouse not over a tile\n");
return;
}
xx = tbl->x; yy = tbl->y;
w = tbl->w; h = tbl->h;
if ( (NameTable%2) == 1 )
{
TileX = ((x - xx) / (w*8)) + 32;
}
else
{
TileX = (x - xx) / (w*8);
}
if ( (NameTable/2) == 1 )
{
TileY = ((y - yy) / (h*8)) + 30;
}
else
{
TileY = (y - yy) / (h*8);
}
PPUAddress = 0x2000+(NameTable*0x400)+((TileY%30)*32)+(TileX%32);
TileID = vnapage[(PPUAddress>>10)&0x3][PPUAddress&0x3FF];
AttAddress = 0x23C0 | (PPUAddress & 0x0C00) | ((PPUAddress >> 4) & 0x38) | ((PPUAddress >> 2) & 0x07);
Attrib = vnapage[(AttAddress>>10)&0x3][AttAddress&0x3FF];
Attrib = (Attrib >> ((PPUAddress&2) | ((PPUAddress&64)>>4))) & 0x3;
//printf("NT:%i Tile X/Y : %i/%i \n", NameTable, TileX, TileY );
if ( parent )
{
parent->setPropertyLabels( TileID, TileX, TileY, NameTable, PPUAddress, AttAddress, Attrib );
}
}
//----------------------------------------------------
void ppuNameTableView_t::mouseMoveEvent(QMouseEvent *event)
{
computeNameTableProperties( event->pos().x(), event->pos().y() );
}
//----------------------------------------------------------------------------
void ppuNameTableView_t::mousePressEvent(QMouseEvent * event)
{
//QPoint tile = convPixToTile( event->pos() );
if ( event->button() == Qt::LeftButton )
{
}
else if ( event->button() == Qt::RightButton )
{
}
}
//----------------------------------------------------
void ppuNameTableView_t::paintEvent(QPaintEvent *event)
{
ppuNameTable_t *nt;
int n,i,j,ii,jj,w,h,x,y,xx,yy,ww,hh;
QPainter painter(this);
QColor scanLineColor(255,255,255);
viewWidth = event->rect().width();
viewHeight = event->rect().height();
w = viewWidth / (256*2);
h = viewHeight / (240*2);
//printf("%ix%i\n", viewWidth, viewHeight );
xx = 0; yy = 0;
for (n=0; n<4; n++)
{
nt = &nameTable[n];
nt->w = w; nt->h = h;
nt->x = xx = (n%2) * (viewWidth / 2);
nt->y = yy = (n/2) * (viewHeight / 2);
for (j=0; j<30; j++)
{
jj = (j*8);
for (i=0; i<32; i++)
{
ii = (i*8);
nt->tile[j][i].x = xx+(ii*w);
nt->tile[j][i].y = yy+(jj*h);
for (y=0; y<8; y++)
{
for (x=0; x<8; x++)
{
painter.fillRect( xx+(ii+x)*w, yy+(jj+y)*h, w, h, nt->tile[j][i].pixel[y][x].color );
}
}
}
}
if ( drawScrollLines )
{
ww = nt->w * 256;
hh = nt->h * 240;
painter.setPen( scanLineColor );
if ( (xpos >= xx) && (xpos < (xx+ww)) )
{
painter.drawLine( xpos, yy, xpos, yy + hh );
}
if ( (ypos >= yy) && (ypos < (yy+hh)) )
{
painter.drawLine( xx, ypos, xx + ww, ypos );
}
}
}
}
//----------------------------------------------------
static void initNameTableViewer(void)
{
//clear cache
memset(palcache,0,32);
// forced palette (e.g. for debugging nametables when palettes are all-black)
palcache[(8*4)+0] = 0x0F;
palcache[(8*4)+1] = 0x00;
palcache[(8*4)+2] = 0x10;
palcache[(8*4)+3] = 0x20;
}
//----------------------------------------------------
static void ChangeMirroring(void)
{
switch (ntmirroring)
{
case NT_HORIZONTAL:
vnapage[0] = vnapage[1] = &NTARAM[0x000];
vnapage[2] = vnapage[3] = &NTARAM[0x400];
break;
case NT_VERTICAL:
vnapage[0] = vnapage[2] = &NTARAM[0x000];
vnapage[1] = vnapage[3] = &NTARAM[0x400];
break;
case NT_FOUR_SCREEN:
vnapage[0] = &NTARAM[0x000];
vnapage[1] = &NTARAM[0x400];
if(ExtraNTARAM)
{
vnapage[2] = ExtraNTARAM;
vnapage[3] = ExtraNTARAM + 0x400;
}
break;
case NT_SINGLE_SCREEN_TABLE_0:
vnapage[0] = vnapage[1] = vnapage[2] = vnapage[3] = &NTARAM[0x000];
break;
case NT_SINGLE_SCREEN_TABLE_1:
vnapage[0] = vnapage[1] = vnapage[2] = vnapage[3] = &NTARAM[0x400];
break;
case NT_SINGLE_SCREEN_TABLE_2:
if(ExtraNTARAM)
vnapage[0] = vnapage[1] = vnapage[2] = vnapage[3] = ExtraNTARAM;
break;
case NT_SINGLE_SCREEN_TABLE_3:
if(ExtraNTARAM)
vnapage[0] = vnapage[1] = vnapage[2] = vnapage[3] = ExtraNTARAM + 0x400;
break;
default:
case NT_NONE:
break;
}
return;
}
//----------------------------------------------------
inline void DrawChr( ppuNameTableTile_t *tile, const uint8_t *chr, int pal)
{
int y, x, tmp, index=0, p=0;
uint8 chr0, chr1;
//uint8 *table = &VPage[0][0]; //use the background table
//pbitmap += 3*
for (y = 0; y < 8; y++) { //todo: use index for y?
chr0 = chr[index];
chr1 = chr[index+8];
tmp=7;
for (x = 0; x < 8; x++) { //todo: use tmp for x?
p = (chr0>>tmp)&1;
p |= ((chr1>>tmp)&1)<<1;
p = palcache[p+(pal*4)];
tmp--;
tile->pixel[y][x].color.setBlue( palo[p].b );
tile->pixel[y][x].color.setGreen( palo[p].g );
tile->pixel[y][x].color.setRed( palo[p].r );
}
index++;
//pbitmap += (NTWIDTH*3)-24;
}
//index+=8;
//pbitmap -= (((PALETTEBITWIDTH>>2)<<3)-24);
}
//----------------------------------------------------
static void DrawNameTable(int scanline, int ntnum, bool invalidateCache)
{
NTCache &c = cache[ntnum];
uint8_t *tablecache = c.cache;
uint8_t *table = vnapage[ntnum];
if (table == NULL)
{
table = vnapage[ntnum&1];
}
int a, ptable=0;
if (PPU[0]&0x10){ //use the correct pattern table based on this bit
ptable=0x1000;
}
bool invalid = invalidateCache;
//if we werent asked to invalidate the cache, maybe we need to invalidate it anyway due to vnapage changing
if (!invalid)
{
invalid = (c.curr_vnapage != vnapage[ntnum]);
}
c.curr_vnapage = vnapage[ntnum];
//HACK: never cache anything
invalid = true;
for (int y=0;y<30;y++)
{
for (int x=0;x<32;x++)
{
int ntaddr = (y*32)+x;
int attraddr = 0x3C0+((y>>2)<<3)+(x>>2);
if (invalid
|| (table[ntaddr] != tablecache[ntaddr])
|| (table[attraddr] != tablecache[attraddr]))
{
int temp = (((y&2)<<1)+(x&2));
a = (table[attraddr] & (3<<temp)) >> temp;
//the commented out code below is all allegedly equivalent to the single line above:
//tmpx = x>>2;
//tmpy = y>>2;
//a = 0x3C0+(tmpy*8)+tmpx;
//if((((x>>1)&1) == 0) && (((y>>1)&1) == 0)) a = table[a]&0x3;
//if((((x>>1)&1) == 1) && (((y>>1)&1) == 0)) a = (table[a]&0xC)>>2;
//if((((x>>1)&1) == 0) && (((y>>1)&1) == 1)) a = (table[a]&0x30)>>4;
//if((((x>>1)&1) == 1) && (((y>>1)&1) == 1)) a = (table[a]&0xC0)>>6;
int chr = table[ntaddr]*16;
extern int FCEUPPU_GetAttr(int ntnum, int xt, int yt);
//test.. instead of pretending that the nametable is a screen at 0,0 we pretend that it is at the current xscroll and yscroll
//int xpos = ((RefreshAddr & 0x400) >> 2) | ((RefreshAddr & 0x1F) << 3) | XOffset;
//int ypos = ((RefreshAddr & 0x3E0) >> 2) | ((RefreshAddr & 0x7000) >> 12);
//if(RefreshAddr & 0x800) ypos += 240;
//int refreshaddr = (xpos/8+x)+(ypos/8+y)*32;
int refreshaddr = (x)+(y)*32;
a = FCEUPPU_GetAttr(ntnum,x,y);
if (hidepal) a = 8;
const uint8* chrp = FCEUPPU_GetCHR(ptable+chr,refreshaddr);
if (attview) chrp = ATTRIBUTE_VIEW_TILE;
//a good way to do it:
DrawChr( &nameTable[ntnum].tile[y][x], chrp, a);
tablecache[ntaddr] = table[ntaddr];
tablecache[attraddr] = table[attraddr];
//one could comment out the line above...
//since there are so many fewer attribute values than NT values, it might be best just to refresh the whole attr table below with the memcpy
//obviously this whole scheme of nt cache doesnt work if an mmc5 game is playing tricks with the attribute table
}
}
}
}
//----------------------------------------------------
void FCEUD_UpdateNTView(int scanline, bool drawall)
{
if (nameTableViewWindow == 0)
{
return;
}
if ( (scanline != -1) && (scanline != NTViewScanline) )
{
return;
}
ppu_getScroll(xpos,ypos);
if (NTViewSkip < NTViewRefresh)
{
NTViewSkip++;
return;
}
NTViewSkip = 0;
if (chrchanged)
{
drawall = 1;
}
//update palette only if required
if (memcmp(palcache,PALRAM,32) != 0)
{
memcpy(palcache,PALRAM,32);
drawall = 1; //palette has changed, so redraw all
}
if ( vnapage[0] == NULL )
{
return;
}
ntmirroring = NT_NONE;
if (vnapage[0] == vnapage[1])ntmirroring = NT_HORIZONTAL;
if (vnapage[0] == vnapage[2])ntmirroring = NT_VERTICAL;
if ((vnapage[0] != vnapage[1]) && (vnapage[0] != vnapage[2]))ntmirroring = NT_FOUR_SCREEN;
if ((vnapage[0] == vnapage[1]) && (vnapage[1] == vnapage[2]) && (vnapage[2] == vnapage[3]))
{
if(vnapage[0] == &NTARAM[0x000])ntmirroring = NT_SINGLE_SCREEN_TABLE_0;
if(vnapage[0] == &NTARAM[0x400])ntmirroring = NT_SINGLE_SCREEN_TABLE_1;
if(vnapage[0] == ExtraNTARAM)ntmirroring = NT_SINGLE_SCREEN_TABLE_2;
if(vnapage[0] == ExtraNTARAM+0x400)ntmirroring = NT_SINGLE_SCREEN_TABLE_3;
}
if (oldntmirroring != ntmirroring)
{
//UpdateMirroringButtons();
oldntmirroring = ntmirroring;
}
for (int i=0;i<4;i++)
{
DrawNameTable(scanline,i,drawall);
}
chrchanged = 0;
redrawtables = true;
return;
}
//----------------------------------------------------

View File

@ -0,0 +1,114 @@
// NameTableViewer.h
#pragma once
#include <QWidget>
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
#include <QCheckBox>
#include <QPushButton>
#include <QRadioButton>
#include <QLabel>
#include <QFrame>
#include <QTimer>
#include <QSlider>
#include <QLineEdit>
#include <QGroupBox>
#include <QCloseEvent>
struct ppuNameTablePixel_t
{
QColor color;
};
struct ppuNameTableTile_t
{
struct ppuNameTablePixel_t pixel[8][8];
int x;
int y;
};
struct ppuNameTable_t
{
struct ppuNameTableTile_t tile[30][32];
int x;
int y;
int w;
int h;
};
class ppuNameTableViewerDialog_t;
class ppuNameTableView_t : public QWidget
{
Q_OBJECT
public:
ppuNameTableView_t( QWidget *parent = 0);
~ppuNameTableView_t(void);
protected:
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent * event);
void computeNameTableProperties( int x, int y );
ppuNameTableViewerDialog_t *parent;
int viewWidth;
int viewHeight;
};
class ppuNameTableViewerDialog_t : public QDialog
{
Q_OBJECT
public:
ppuNameTableViewerDialog_t(QWidget *parent = 0);
~ppuNameTableViewerDialog_t(void);
void setPropertyLabels( int TileID, int TileX, int TileY, int NameTable, int PPUAddress, int AttAddress, int Attrib );
protected:
void closeEvent(QCloseEvent *bar);
ppuNameTableView_t *ntView;
QCheckBox *showScrollLineCbox;
QCheckBox *showAttrbCbox;
QCheckBox *ignorePaletteCbox;
QSlider *refreshSlider;
QLineEdit *scanLineEdit;
QTimer *updateTimer;
QRadioButton *horzMirrorBtn;
QRadioButton *vertMirrorBtn;
QRadioButton *fourScreenBtn;
QRadioButton *singleScreenBtn[4];
QLabel *tileID;
QLabel *tileXY;
QLabel *ppuAddrLbl;
QLabel *attrbLbl;
public slots:
void closeWindow(void);
private slots:
void periodicUpdate(void);
void updateMirrorButtons(void);
void horzMirrorClicked(void);
void vertMirrorClicked(void);
void fourScreenClicked(void);
void singleScreen0Clicked(void);
void singleScreen1Clicked(void);
void singleScreen2Clicked(void);
void singleScreen3Clicked(void);
void showAttrbChanged(int state);
void ignorePaletteChanged(int state);
void showScrollLinesChanged(int state);
void refreshSliderChanged(int value);
void scanLineChanged( const QString &txt );
};
int openNameTableViewWindow( QWidget *parent );

View File

@ -1,6 +1,7 @@
// PaletteConf.cpp
//
#include <QFileDialog>
#include <QTextEdit>
#include "Qt/PaletteConf.h"
#include "Qt/main.h"
@ -8,7 +9,19 @@
#include "Qt/config.h"
#include "Qt/keyscan.h"
#include "Qt/fceuWrapper.h"
#include "Qt/ConsoleUtilities.h"
#include "../../ppu.h"
extern bool force_grayscale;
static const char *commentText =
"Palette Selection uses the 1st Matching Condition:\n\
1. Game type is NSF (always uses fixed palette) \n\
2. Custom User Palette is Available and Enabled \n\
3. NTSC Color Emulation is Enabled \n\
4. Individual Game Palette is Available \n\
5. Default Built-in Palette ";
//----------------------------------------------------
PaletteConfDialog_t::PaletteConfDialog_t(QWidget *parent)
: QDialog( parent )
@ -18,10 +31,13 @@ PaletteConfDialog_t::PaletteConfDialog_t(QWidget *parent)
QGroupBox *frame;
//QPushButton *closebutton;
QPushButton *button;
QTextEdit *comments;
int hue, tint;
char stmp[64];
std::string paletteFile;
resize( 512, 600 );
// sync with config
g_config->getOption ("SDL.Hue", &hue);
g_config->getOption ("SDL.Tint", &tint);
@ -31,8 +47,21 @@ PaletteConfDialog_t::PaletteConfDialog_t(QWidget *parent)
mainLayout = new QVBoxLayout();
frame = new QGroupBox( tr("Custom Palette:") );
vbox = new QVBoxLayout();
hbox1 = new QHBoxLayout();
useCustom = new QCheckBox( tr("Use Custom Palette") );
GrayScale = new QCheckBox( tr("Force Grayscale") );
deemphSwap = new QCheckBox( tr("De-emphasis Bit Swap") );
useCustom->setChecked( FCEUI_GetUserPaletteAvail() );
GrayScale->setChecked( force_grayscale );
deemphSwap->setChecked( paldeemphswap );
connect(useCustom , SIGNAL(stateChanged(int)), this, SLOT(use_Custom_Changed(int)) );
connect(GrayScale , SIGNAL(stateChanged(int)), this, SLOT(force_GrayScale_Changed(int)) );
connect(deemphSwap, SIGNAL(stateChanged(int)), this, SLOT(deemphswap_Changed(int)) );
button = new QPushButton( tr("Open Palette") );
hbox1->addWidget( button );
@ -43,14 +72,20 @@ PaletteConfDialog_t::PaletteConfDialog_t(QWidget *parent)
custom_palette_path = new QLineEdit();
custom_palette_path->setReadOnly(true);
custom_palette_path->setText( paletteFile.c_str() );
hbox1->addWidget( custom_palette_path );
vbox->addWidget( useCustom );
vbox->addLayout( hbox1 );
vbox->addWidget( custom_palette_path );
vbox->addWidget( GrayScale );
vbox->addWidget( deemphSwap);
button = new QPushButton( tr("Clear") );
hbox1->addWidget( button );
connect( button, SIGNAL(clicked(void)), this, SLOT(clearPalette(void)) );
frame->setLayout( hbox1 );
frame->setLayout( vbox );
mainLayout->addWidget( frame );
@ -99,19 +134,36 @@ PaletteConfDialog_t::PaletteConfDialog_t(QWidget *parent)
mainLayout->addWidget( frame );
comments = new QTextEdit();
comments->setText( commentText );
comments->moveCursor(QTextCursor::Start);
comments->setReadOnly(true);
mainLayout->addWidget( comments );
setLayout( mainLayout );
}
//----------------------------------------------------
PaletteConfDialog_t::~PaletteConfDialog_t(void)
{
printf("Destroy Palette Config Window\n");
}
//----------------------------------------------------------------------------
void PaletteConfDialog_t::closeEvent(QCloseEvent *event)
{
printf("Palette Config Close Window Event\n");
done(0);
deleteLater();
event->accept();
}
//----------------------------------------------------
void PaletteConfDialog_t::closeWindow(void)
{
//printf("Close Window\n");
done(0);
deleteLater();
}
//----------------------------------------------------
void PaletteConfDialog_t::hueChanged(int v)
@ -156,6 +208,61 @@ void PaletteConfDialog_t::tintChanged(int v)
}
}
//----------------------------------------------------
void PaletteConfDialog_t::use_Custom_Changed(int state)
{
int value = (state == Qt::Unchecked) ? 0 : 1;
std::string filename;
//printf("Use Custom:%i \n", state );
g_config->getOption ("SDL.Palette", &filename);
if ( fceuWrapperTryLock() )
{
if ( value && (filename.size() > 0) )
{
LoadCPalette ( filename.c_str() );
}
else
{
FCEUI_SetUserPalette( NULL, 0);
}
fceuWrapperUnLock();
}
}
//----------------------------------------------------
void PaletteConfDialog_t::force_GrayScale_Changed(int state)
{
int value = (state == Qt::Unchecked) ? 0 : 1;
if ( fceuWrapperTryLock() )
{
int e, h, t;
g_config->getOption ("SDL.NTSCpalette", &e);
g_config->getOption ("SDL.Hue", &h);
g_config->getOption ("SDL.Tint", &t);
force_grayscale = value ? true : false;
FCEUI_SetNTSCTH( e, t, h);
fceuWrapperUnLock();
}
}
//----------------------------------------------------
void PaletteConfDialog_t::deemphswap_Changed(int state)
{
int value = (state == Qt::Unchecked) ? 0 : 1;
if ( fceuWrapperTryLock() )
{
int e, h, t;
g_config->getOption ("SDL.NTSCpalette", &e);
g_config->getOption ("SDL.Hue", &h);
g_config->getOption ("SDL.Tint", &t);
paldeemphswap = value ? true : false;
FCEUI_SetNTSCTH( e, t, h);
fceuWrapperUnLock();
}
}
//----------------------------------------------------
void PaletteConfDialog_t::use_NTSC_Changed(int state)
{
int h, t;
@ -184,26 +291,41 @@ void PaletteConfDialog_t::clearPalette(void)
{
FCEUI_SetUserPalette( NULL, 0);
fceuWrapperUnLock();
useCustom->setChecked(false);
}
}
//----------------------------------------------------
void PaletteConfDialog_t::openPaletteFile(void)
{
int ret;
int ret, useNativeFileDialogVal;
QString filename;
std::string last;
char dir[512];
QFileDialog dialog(this, tr("Open NES Palette") );
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilter(tr("NES Palettes (*.pal)(*.PAL) ;; All files (*)"));
dialog.setNameFilter(tr("NES Palettes (*.pal *.PAL) ;; All files (*)"));
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Load") );
dialog.setDirectory( tr("/usr/share/fceux/palettes") );
g_config->getOption ("SDL.Palette", &last );
// the gnome default file dialog is not playing nice with QT.
// TODO make this a config option to use native file dialog.
dialog.setOption(QFileDialog::DontUseNativeDialog, true);
if ( last.size() == 0 )
{
last.assign( "/usr/share/fceux/palettes" );
}
getDirFromFile( last.c_str(), dir );
dialog.setDirectory( tr(dir) );
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.show();
ret = dialog.exec();
@ -225,18 +347,22 @@ void PaletteConfDialog_t::openPaletteFile(void)
}
qDebug() << "selected file path : " << filename.toUtf8();
g_config->setOption ("SDL.Palette", filename.toStdString().c_str() );
g_config->setOption ("SDL.NTSCpalette", 0);
if ( fceuWrapperTryLock() )
{
LoadCPalette ( filename.toStdString().c_str() );
if ( LoadCPalette ( filename.toStdString().c_str() ) )
{
g_config->setOption ("SDL.Palette", filename.toStdString().c_str() );
custom_palette_path->setText( filename.toStdString().c_str() );
}
else
{
printf("Error: Failed to Load Palette File: %s \n", filename.toStdString().c_str() );
}
fceuWrapperUnLock();
useCustom->setChecked( FCEUI_GetUserPaletteAvail() );
}
custom_palette_path->setText( filename.toStdString().c_str() );
useNTSC->setChecked( 0 );
return;
}

View File

@ -26,7 +26,12 @@ class PaletteConfDialog_t : public QDialog
~PaletteConfDialog_t(void);
protected:
void closeEvent(QCloseEvent *event);
QLineEdit *custom_palette_path;
QCheckBox *useCustom;
QCheckBox *GrayScale;
QCheckBox *deemphSwap;
QCheckBox *useNTSC;
QSlider *tintSlider;
QSlider *hueSlider;
@ -42,5 +47,8 @@ class PaletteConfDialog_t : public QDialog
void openPaletteFile(void);
void clearPalette(void);
void use_NTSC_Changed(int v);
void use_Custom_Changed(int v);
void force_GrayScale_Changed(int v);
void deemphswap_Changed(int v);
};

View File

@ -0,0 +1,568 @@
// SymbolicDebug.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../../types.h"
#include "../../fceu.h"
#include "../../debug.h"
#include "../../driver.h"
#include "../../cart.h"
#include "../../ines.h"
#include "Qt/SymbolicDebug.h"
#include "Qt/ConsoleUtilities.h"
debugSymbolTable_t debugSymbolTable;
//--------------------------------------------------------------
// debugSymbolPage_t
//--------------------------------------------------------------
debugSymbolPage_t::debugSymbolPage_t(void)
{
pageNum = -1;
}
//--------------------------------------------------------------
debugSymbolPage_t::~debugSymbolPage_t(void)
{
std::map <int, debugSymbol_t*>::iterator it;
for (it=symMap.begin(); it!=symMap.end(); it++)
{
delete it->second;
}
symMap.clear();
}
//--------------------------------------------------------------
int debugSymbolPage_t::addSymbol( debugSymbol_t*sym )
{
std::map <int, debugSymbol_t*>::iterator it;
it = symMap.find( sym->ofs );
if ( it != symMap.end() )
{
return -1;
}
symMap[ sym->ofs ] = sym;
return 0;
}
//--------------------------------------------------------------
debugSymbol_t *debugSymbolPage_t::getSymbolAtOffset( int ofs )
{
debugSymbol_t*sym = NULL;
std::map <int, debugSymbol_t*>::iterator it;
it = symMap.find( ofs );
if ( it != symMap.end() )
{
sym = it->second;
}
return sym;
}
//--------------------------------------------------------------
int debugSymbolPage_t::save(void)
{
FILE *fp;
debugSymbol_t *sym;
std::map <int, debugSymbol_t*>::iterator it;
const char *romFile;
char stmp[512];
int i,j;
romFile = getRomFile();
if ( romFile == NULL )
{
return -1;
}
i=0;
while ( romFile[i] != 0 )
{
if ( romFile[i] == '|' )
{
stmp[i] = '.';
}
else
{
stmp[i] = romFile[i];
}
i++;
}
stmp[i] = 0;
if ( pageNum < 0 )
{
strcat( stmp, ".ram.nl" );
}
else
{
char suffix[32];
sprintf( suffix, ".%X.nl", pageNum );
strcat( stmp, suffix );
}
fp = fopen( stmp, "w" );
if ( fp == NULL )
{
printf("Error: Could not open file '%s' for writing\n", stmp );
return -1;
}
for (it=symMap.begin(); it!=symMap.end(); it++)
{
const char *c;
sym = it->second;
i=0; j=0; c = sym->comment.c_str();
while ( c[i] != 0 )
{
if ( c[i] == '\n' )
{
i++; break;
}
else
{
stmp[j] = c[i]; j++; i++;
}
}
stmp[j] = 0;
fprintf( fp, "$%04X#%s#%s\n", sym->ofs, sym->name.c_str(), stmp );
j=0;
while ( c[i] != 0 )
{
if ( c[i] == '\n' )
{
i++; stmp[j] = 0;
if ( j > 0 )
{
fprintf( fp, "\\%s\n", stmp );
}
j=0;
}
else
{
stmp[j] = c[i]; j++; i++;
}
}
}
fclose(fp);
return 0;
}
//--------------------------------------------------------------
void debugSymbolPage_t::print(void)
{
FILE *fp;
debugSymbol_t *sym;
std::map <int, debugSymbol_t*>::iterator it;
fp = stdout;
fprintf( fp, "Page: %X \n", pageNum );
for (it=symMap.begin(); it!=symMap.end(); it++)
{
sym = it->second;
fprintf( fp, " Sym: $%04X '%s' \n", sym->ofs, sym->name.c_str() );
}
}
//--------------------------------------------------------------
// debugSymbolTable_t
//--------------------------------------------------------------
debugSymbolTable_t::debugSymbolTable_t(void)
{
}
//--------------------------------------------------------------
debugSymbolTable_t::~debugSymbolTable_t(void)
{
this->clear();
}
//--------------------------------------------------------------
void debugSymbolTable_t::clear(void)
{
std::map <int, debugSymbolPage_t*>::iterator it;
for (it=pageMap.begin(); it!=pageMap.end(); it++)
{
delete it->second;
}
pageMap.clear();
}
//--------------------------------------------------------------
int generateNLFilenameForAddress(int address, char *NLfilename)
{
int bank;
if (address < 0x8000)
{
bank = -1;
}
else
{
bank = getBank(address);
#ifdef DW3_NL_0F_1F_HACK
if(bank == 0x0F)
bank = 0x1F;
#endif
}
return generateNLFilenameForBank( bank, NLfilename );
}
//--------------------------------------------------------------
int generateNLFilenameForBank(int bank, char *NLfilename)
{
int i;
const char *romFile;
romFile = getRomFile();
if ( romFile == NULL )
{
return -1;
}
i=0;
while ( romFile[i] != 0 )
{
if ( romFile[i] == '|' )
{
NLfilename[i] = '.';
}
else
{
NLfilename[i] = romFile[i];
}
i++;
}
NLfilename[i] = 0;
if (bank < 0)
{
// The NL file for the RAM addresses has the name nesrom.nes.ram.nl
strcat(NLfilename, ".ram.nl");
}
else
{
char stmp[64];
#ifdef DW3_NL_0F_1F_HACK
if(bank == 0x0F)
bank = 0x1F;
#endif
sprintf( stmp, ".%X.nl", bank);
strcat(NLfilename, stmp );
}
return 0;
}
//--------------------------------------------------------------
int debugSymbolTable_t::loadFileNL( int bank )
{
FILE *fp;
int i, j, ofs, lineNum = 0, literal = 0;
char fileName[512], line[512];
char stmp[512];
debugSymbolPage_t *page = NULL;
debugSymbol_t *sym = NULL;
//printf("Looking to Load Debug Bank: $%X \n", bank );
if ( generateNLFilenameForBank( bank, fileName ) )
{
return -1;
}
//printf("Loading NL File: %s\n", fileName );
fp = ::fopen( fileName, "r" );
if ( fp == NULL )
{
return -1;
}
page = new debugSymbolPage_t;
page->pageNum = bank;
pageMap[ page->pageNum ] = page;
while ( fgets( line, sizeof(line), fp ) != 0 )
{
i=0; lineNum++;
//printf("%4i:%s", lineNum, line );
if ( line[i] == '\\' )
{
// Line is a comment continuation line.
i++;
j=0;
stmp[j] = '\n'; j++;
while ( line[i] != 0 )
{
stmp[j] = line[i]; j++; i++;
}
stmp[j] = 0;
j--;
while ( j >= 0 )
{
if ( isspace( stmp[j] ) )
{
stmp[j] = 0;
}
else
{
break;
}
j--;
}
if ( sym != NULL )
{
sym->comment.append( stmp );
}
}
else if ( line[i] == '$' )
{
// Line is a new debug offset
j=0; i++;
if ( !isxdigit( line[i] ) )
{
printf("Error: Invalid Offset on Line %i of File %s\n", lineNum, fileName );
}
while ( isxdigit( line[i] ) )
{
stmp[j] = line[i]; i++; j++;
}
stmp[j] = 0;
ofs = strtol( stmp, NULL, 16 );
if ( line[i] != '#' )
{
printf("Error: Missing field delimiter following offset $%X on Line %i of File %s\n", ofs, lineNum, fileName );
continue;
}
i++;
while ( isspace(line[i]) ) i++;
j = 0;
while ( line[i] != 0 )
{
if ( line[i] == '\\' )
{
if ( literal )
{
switch ( line[i] )
{
case 'r':
stmp[j] = '\r';
break;
case 'n':
stmp[j] = '\n';
break;
case 't':
stmp[j] = '\t';
break;
default:
stmp[j] = line[i];
break;
}
j++; i++;
literal = 0;
}
else
{
i++;
literal = !literal;
}
}
else if ( line[i] == '#' )
{
break;
}
else
{
stmp[j] = line[i]; j++; i++;
}
}
stmp[j] = 0;
j--;
while ( j >= 0 )
{
if ( isspace( stmp[j] ) )
{
stmp[j] = 0;
}
else
{
break;
}
j--;
}
if ( line[i] != '#' )
{
printf("Error: Missing field delimiter following name '%s' on Line %i of File %s\n", stmp, lineNum, fileName );
continue;
}
i++;
sym = new debugSymbol_t();
if ( sym == NULL )
{
printf("Error: Failed to allocate memory for offset $%04X Name '%s' on Line %i of File %s\n", ofs, stmp, lineNum, fileName );
continue;
}
sym->ofs = ofs;
sym->name.assign( stmp );
while ( isspace( line[i] ) ) i++;
j=0;
while ( line[i] != 0 )
{
stmp[j] = line[i]; j++; i++;
}
stmp[j] = 0;
j--;
while ( j >= 0 )
{
if ( isspace( stmp[j] ) )
{
stmp[j] = 0;
}
else
{
break;
}
j--;
}
sym->comment.assign( stmp );
if ( page->addSymbol( sym ) )
{
printf("Error: Failed to add symbol for offset $%04X Name '%s' on Line %i of File %s\n", ofs, stmp, lineNum, fileName );
delete sym; sym = NULL; // Failed to add symbol
}
}
}
::fclose(fp);
return 0;
}
//--------------------------------------------------------------
int debugSymbolTable_t::loadGameSymbols(void)
{
int nPages, pageSize, romSize = 0x10000;
this->save();
this->clear();
if ( GameInfo != NULL )
{
romSize = 16 + CHRsize[0] + PRGsize[0];
}
loadFileNL( -1 );
pageSize = (1<<debuggerPageSize);
//nPages = 1<<(15-debuggerPageSize);
nPages = romSize / pageSize;
//printf("RomSize: %i NumPages: %i \n", romSize, nPages );
for(int i=0;i<nPages;i++)
{
//printf("Loading Page Offset: $%06X\n", pageSize*i );
loadFileNL( i );
}
//print();
return 0;
}
//--------------------------------------------------------------
int debugSymbolTable_t::addSymbolAtBankOffset( int bank, int ofs, debugSymbol_t *sym )
{
debugSymbolPage_t *page;
std::map <int, debugSymbolPage_t*>::iterator it;
it = pageMap.find( bank );
if ( it == pageMap.end() )
{
page = new debugSymbolPage_t();
page->pageNum = bank;
pageMap[ bank ] = page;
}
else
{
page = it->second;
}
page->addSymbol( sym );
return 0;
}
//--------------------------------------------------------------
debugSymbol_t *debugSymbolTable_t::getSymbolAtBankOffset( int bank, int ofs )
{
debugSymbol_t*sym = NULL;
std::map <int, debugSymbolPage_t*>::iterator it;
it = pageMap.find( bank );
if ( it != pageMap.end() )
{
sym = (it->second)->getSymbolAtOffset( ofs );
}
return sym;
}
//--------------------------------------------------------------
void debugSymbolTable_t::save(void)
{
debugSymbolPage_t *page;
std::map <int, debugSymbolPage_t*>::iterator it;
for (it=pageMap.begin(); it!=pageMap.end(); it++)
{
page = it->second;
page->save();
}
}
//--------------------------------------------------------------
void debugSymbolTable_t::print(void)
{
debugSymbolPage_t *page;
std::map <int, debugSymbolPage_t*>::iterator it;
for (it=pageMap.begin(); it!=pageMap.end(); it++)
{
page = it->second;
page->print();
}
}
//--------------------------------------------------------------

View File

@ -0,0 +1,76 @@
// SymbolicDebug.h
//
#ifndef __SYMBOLIC_DEBUG_H__
#define __SYMBOLIC_DEBUG_H__
#include <string>
#include <list>
#include <map>
struct debugSymbol_t
{
int ofs;
std::string name;
std::string comment;
debugSymbol_t(void)
{
ofs = 0;
};
};
struct debugSymbolPage_t
{
int pageNum;
debugSymbolPage_t(void);
~debugSymbolPage_t(void);
int save(void);
void print(void);
int size(void){ return symMap.size(); }
int addSymbol( debugSymbol_t *sym );
debugSymbol_t *getSymbolAtOffset( int ofs );
std::map <int, debugSymbol_t*> symMap;
};
class debugSymbolTable_t
{
public:
debugSymbolTable_t(void);
~debugSymbolTable_t(void);
int loadFileNL( int addr );
int loadGameSymbols(void);
int numPages(void){ return pageMap.size(); }
void save(void);
void clear(void);
void print(void);
debugSymbol_t *getSymbolAtBankOffset( int bank, int ofs );
int addSymbolAtBankOffset( int bank, int ofs, debugSymbol_t *sym );
private:
std::map <int, debugSymbolPage_t*> pageMap;
};
extern debugSymbolTable_t debugSymbolTable;
//struct MemoryMappedRegister
//{
// char* offset;
// char* name;
//};
int generateNLFilenameForBank(int bank, char *NLfilename);
int generateNLFilenameForAddress(int address, char *NLfilename);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,153 @@
// TraceLogger.h
//
#pragma once
#include <QWidget>
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
#include <QCheckBox>
#include <QPushButton>
#include <QLabel>
#include <QFrame>
#include <QTimer>
#include <QGroupBox>
#include <QScrollBar>
#include <QCloseEvent>
struct traceRecord_t
{
struct {
uint16_t PC;
uint8_t A;
uint8_t X;
uint8_t Y;
uint8_t S;
uint8_t P;
} cpu;
uint8_t opCode[3];
uint8_t opSize;
uint8_t asmTxtSize;
char asmTxt[64];
uint64_t frameCount;
uint64_t cycleCount;
uint64_t instrCount;
uint64_t flags;
int32_t callAddr;
int32_t romAddr;
int32_t bank;
int32_t skippedLines;
traceRecord_t(void);
int appendAsmText( const char *txt );
int convToText( char *line );
};
class QTraceLogView : public QWidget
{
Q_OBJECT
public:
QTraceLogView(QWidget *parent = 0);
~QTraceLogView(void);
void setScrollBars( QScrollBar *h, QScrollBar *v );
protected:
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
void calcFontData(void);
protected:
QFont font;
QScrollBar *vbar;
QScrollBar *hbar;
int pxCharWidth;
int pxCharHeight;
int pxLineSpacing;
int pxLineLead;
int pxCursorHeight;
int pxLineXScroll;
int pxLineWidth;
int viewLines;
int viewWidth;
int viewHeight;
};
class TraceLoggerDialog_t : public QDialog
{
Q_OBJECT
public:
TraceLoggerDialog_t(QWidget *parent = 0);
~TraceLoggerDialog_t(void);
protected:
QTimer *updateTimer;
QCheckBox *logLastCbox;
QCheckBox *logFileCbox;
QComboBox *logMaxLinesComboBox;
QCheckBox *autoUpdateCbox;
QCheckBox *logRegCbox;
QCheckBox *logFrameCbox;
QCheckBox *logEmuMsgCbox;
QCheckBox *logProcStatFlagCbox;
QCheckBox *logCyclesCountCbox;
QCheckBox *logBreakpointCbox;
QCheckBox *useStackPointerCbox;
QCheckBox *toLeftDisassemblyCbox;
QCheckBox *logInstrCountCbox;
QCheckBox *logBankNumCbox;
QCheckBox *symTraceEnaCbox;
QCheckBox *logNewMapCodeCbox;
QCheckBox *logNewMapDataCbox;
QPushButton *selLogFileButton;
QPushButton *startStopButton;
QTraceLogView *traceView;
QScrollBar *hbar;
QScrollBar *vbar;
int traceViewCounter;
void closeEvent(QCloseEvent *bar);
private:
public slots:
void closeWindow(void);
private slots:
void updatePeriodic(void);
void toggleLoggingOnOff(void);
void logRegStateChanged(int state);
void logFrameStateChanged(int state);
void logEmuMsgStateChanged(int state);
void symTraceEnaStateChanged(int state);
void logProcStatFlagStateChanged(int state);
void logCyclesCountStateChanged(int state);
void logBreakpointStateChanged(int state);
void useStackPointerStateChanged(int state);
void toLeftDisassemblyStateChanged(int state);
void logInstrCountStateChanged(int state);
void logBankNumStateChanged(int state);
void logNewMapCodeChanged(int state);
void logNewMapDataChanged(int state);
void logMaxLinesChanged(int index);
void hbarChanged(int value);
void vbarChanged(int value);
void openLogFile(void);
};
int initTraceLogBuffer( int maxRecs );
void openTraceLoggerWindow( QWidget *parent );

View File

@ -102,20 +102,20 @@ LoadCPalette(const std::string &file)
static void
CreateDirs(const std::string &dir)
{
const char *subs[8]={"fcs","snaps","gameinfo","sav","cheats","movies","cfg.d"};
const char *subs[9]={"fcs","snaps","gameinfo","sav","cheats","movies","input"};
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++) {
for(x = 0; x < 7; x++) {
subdir = dir + PSS + subs[x];
mkdir(subdir.c_str());
}
#else
mkdir(dir.c_str(), S_IRWXU);
for(x = 0; x < 6; x++) {
for(x = 0; x < 7; x++) {
subdir = dir + PSS + subs[x];
mkdir(subdir.c_str(), S_IRWXU);
}
@ -199,6 +199,7 @@ InitConfig()
// video controls
config->addOption('f', "fullscreen", "SDL.Fullscreen", 0);
config->addOption("videoDriver", "SDL.VideoDriver", 0);
// set x/y res to 0 for automatic fullscreen resolution detection (no change)
config->addOption('x', "xres", "SDL.XResolution", 0);
@ -241,7 +242,7 @@ InitConfig()
config->addOption("input4", "SDL.Input.3", "Gamepad.3");
// allow for input configuration
config->addOption('i', "inputcfg", "SDL.InputCfg", InputCfg);
//config->addOption('i', "inputcfg", "SDL.InputCfg", InputCfg);
// display input
config->addOption("inputdisplay", "SDL.InputDisplay", 0);
@ -253,7 +254,20 @@ InitConfig()
config->addOption("pauseframe", "SDL.PauseFrame", 0);
config->addOption("recordhud", "SDL.RecordHUD", 1);
config->addOption("moviemsg", "SDL.MovieMsg", 1);
// Hex Editor Options
config->addOption("hexEditBgColor", "SDL.HexEditBgColor", "#000000");
config->addOption("hexEditFgColor", "SDL.HexEditFgColor", "#FFFFFF");
// Debugger Options
config->addOption("autoLoadDebugFiles", "SDL.AutoLoadDebugFiles", 1);
config->addOption("autoOpenDebugger" , "SDL.AutoOpenDebugger" , 0);
// Code Data Logger Options
config->addOption("autoSaveCDL" , "SDL.AutoSaveCDL", 1);
config->addOption("autoLoadCDL" , "SDL.AutoLoadCDL", 1);
config->addOption("autoResumeCDL", "SDL.AutoResumeCDL", 0);
// overwrite the config file?
config->addOption("no-config", "SDL.NoConfig", 0);
@ -292,6 +306,9 @@ InitConfig()
config->addOption("_lastopennsf", "SDL.LastOpenNSF", home_dir);
config->addOption("_lastsavestateas", "SDL.LastSaveStateAs", home_dir);
config->addOption("_lastloadlua", "SDL.LastLoadLua", "");
config->addOption("_useNativeFileDialog", "SDL.UseNativeFileDialog", false);
config->addOption("_useNativeMenuBar" , "SDL.UseNativeMenuBar", false);
// fcm -> fm2 conversion
config->addOption("fcmconvert", "SDL.FCMConvert", "");
@ -313,10 +330,8 @@ InitConfig()
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]);
}
config->addOption(prefix + "DeviceGUID", "");
config->addOption(prefix + "Profile" , "");
}
// PowerPad 0 - 1

View File

@ -18,6 +18,8 @@ void SilenceSound(int s); /* DOS and SDL */
int InitJoysticks(void);
int KillJoysticks(void);
int AddJoystick( int which );
int RemoveJoystick( int which );
uint32 *GetJSOr(void);
int InitVideo(FCEUGI *gi);

View File

@ -14,7 +14,12 @@
#include "Qt/sdl-video.h"
#include "Qt/nes_shm.h"
#include "Qt/unix-netplay.h"
#include "Qt/HexEditor.h"
#include "Qt/SymbolicDebug.h"
#include "Qt/CodeDataLogger.h"
#include "Qt/ConsoleDebugger.h"
#include "Qt/ConsoleWindow.h"
#include "Qt/fceux_git_info.h"
#include "common/cheat.h"
#include "../../fceu.h"
@ -80,20 +85,22 @@ int mutecapture = 0;
void FCEUD_Message(const char *text)
{
fputs(text, stdout);
fprintf(stdout, "\n");
//fprintf(stdout, "\n");
}
/**
* Shows an error message in a message box.
* (For now: prints to stderr.)
*
* If running in GTK mode, display a dialog message box of the error.
* If running in Qt mode, display a dialog message box of the error.
*
* @param errormsg Text of the error message.
**/
void FCEUD_PrintError(const char *errormsg)
{
fprintf(stderr, "%s\n", errormsg);
consoleWindow->QueueErrorMsgWindow( errormsg );
}
/**
@ -101,7 +108,8 @@ void FCEUD_PrintError(const char *errormsg)
*/
FILE *FCEUD_UTF8fopen(const char *fn, const char *mode)
{
return(fopen(fn,mode));
FILE *fp = ::fopen(fn,mode);
return(fp);
}
/**
@ -154,11 +162,6 @@ FCEUD_GetTimeFreq(void)
return 1000;
}
void FCEUD_DebugBreakpoint( int addr )
{
// TODO
}
/**
* Initialize all of the subsystem drivers: video, audio, and joystick.
*/
@ -193,8 +196,8 @@ DriverKill()
if (!noconfig)
g_config->save();
if(inited&2)
KillJoysticks();
KillJoysticks();
if(inited&4)
KillVideo();
if(inited&1)
@ -210,7 +213,7 @@ DriverKill()
*/
int LoadGame(const char *path)
{
int gg_enabled;
int gg_enabled, autoLoadDebug, autoOpenDebugger;
if (isloaded){
CloseGame();
@ -227,6 +230,26 @@ int LoadGame(const char *path)
return 0;
}
hexEditorLoadBookmarks();
g_config->getOption( "SDL.AutoLoadDebugFiles", &autoLoadDebug );
if ( autoLoadDebug )
{
loadGameDebugBreakpoints();
}
g_config->getOption( "SDL.AutoOpenDebugger", &autoOpenDebugger );
if ( autoOpenDebugger && !debuggerWindowIsOpen() )
{
consoleWindow->openDebugWindow();
}
debugSymbolTable.loadGameSymbols();
CDLoggerROMChanged();
int state_to_load;
g_config->getOption("SDL.AutoLoadState", &state_to_load);
if (state_to_load >= 0 && state_to_load < 10){
@ -273,6 +296,13 @@ CloseGame(void)
if(!isloaded) {
return(0);
}
hexEditorSaveBookmarks();
saveGameDebugBreakpoints();
debuggerClearAllBreakpoints();
debugSymbolTable.save();
debugSymbolTable.clear();
CDLoggerROMClosed();
int state_to_save;
g_config->getOption("SDL.AutoSaveState", &state_to_save);
@ -408,12 +438,15 @@ static void ShowUsage(const char *prog)
SDL_GetVersion(&v);
printf("Linked with SDL version %d.%d.%d\n", v.major, v.minor, v.patch);
printf("Compiled with QT version %d.%d.%d\n", QT_VERSION_MAJOR, QT_VERSION_MINOR, QT_VERSION_PATCH );
printf("git URL: %s\n", fceu_get_git_url() );
printf("git Rev: %s\n", fceu_get_git_rev() );
}
int fceuWrapperInit( int argc, char *argv[] )
{
int error;
std::string s;
for (int i=0; i<argc; i++)
{
@ -432,6 +465,10 @@ int fceuWrapperInit( int argc, char *argv[] )
printf("Could not initialize SDL: %s.\n", SDL_GetError());
exit(-1);
}
if ( SDL_SetHint( SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1" ) == SDL_FALSE )
{
printf("Error setting SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS\n");
}
// Initialize the configuration system
g_config = InitConfig();
@ -468,15 +505,14 @@ int fceuWrapperInit( int argc, char *argv[] )
g_config->save();
}
std::string s;
g_config->getOption("SDL.InputCfg", &s);
//g_config->getOption("SDL.InputCfg", &s);
if (s.size() != 0)
{
InitVideo(GameInfo);
InputCfg(s);
}
//if (s.size() != 0)
//{
// InitVideo(GameInfo);
// InputCfg(s);
//}
// update the input devices
UpdateInput(g_config);
@ -914,17 +950,23 @@ static void DoFun(int frameskip, int periodic_saves)
void fceuWrapperLock(void)
{
mutexPending++;
consoleWindow->mutex->lock();
if ( consoleWindow != NULL )
{
consoleWindow->mutex->lock();
}
mutexPending--;
mutexLocks++;
}
bool fceuWrapperTryLock(int timeout)
{
bool lockAcq;
bool lockAcq = false;
mutexPending++;
lockAcq = consoleWindow->mutex->tryLock( timeout );
if ( consoleWindow != NULL )
{
lockAcq = consoleWindow->mutex->tryLock( timeout );
}
mutexPending--;
if ( lockAcq )
@ -938,7 +980,10 @@ void fceuWrapperUnLock(void)
{
if ( mutexLocks > 0 )
{
consoleWindow->mutex->unlock();
if ( consoleWindow != NULL )
{
consoleWindow->mutex->unlock();
}
mutexLocks--;
}
else

View File

@ -24,8 +24,9 @@
#include "Qt/config.h"
#include "Qt/sdl-video.h"
#include "Qt/sdl.h"
#include "Qt/sdl-video.h"
#include "Qt/sdl-joystick.h"
#include "common/cheat.h"
#include "../../movie.h"
@ -49,8 +50,8 @@ extern bool bindSavestate, frameAdvanceLagSkip, lagCounterDisplay;
/* UsrInputType[] is user-specified. CurInputType[] is current
(game loading can override user settings)
*/
static int UsrInputType[NUM_INPUT_DEVICES];
static int CurInputType[NUM_INPUT_DEVICES];
static int UsrInputType[NUM_INPUT_DEVICES] = { SI_GAMEPAD, SI_GAMEPAD, SI_NONE };
static int CurInputType[NUM_INPUT_DEVICES] = { SI_GAMEPAD, SI_GAMEPAD, SI_NONE };
static int cspec = 0;
static int buttonConfigInProgress = 0;
@ -956,6 +957,12 @@ UpdatePhysicalInput ()
g_keyState[ event.key.keysym.scancode ] = (event.type == SDL_KEYDOWN) ? 1 : 0;
//checkKeyBoardState( event.key.keysym.scancode );
break;
case SDL_JOYDEVICEADDED:
AddJoystick( event.jdevice.which );
break;
case SDL_JOYDEVICEREMOVED:
RemoveJoystick( event.jdevice.which );
break;
default:
break;
}
@ -964,8 +971,6 @@ UpdatePhysicalInput ()
}
static int bcpv=0, bcpj=0;
/**
* Begin configuring the buttons by placing the video and joystick
* subsystems into a well-known state. Button configuration really
@ -973,13 +978,7 @@ static int bcpv=0, bcpj=0;
*/
int ButtonConfigBegin ()
{
// shut down the joystick subsystems
//SDL_Surface *screen;
bcpj = KillJoysticks ();
// XXX soules - why did we shut this down?
// initialize the joystick subsystem
// initialize the joystick subsystem (if not already inited)
InitJoysticks ();
buttonConfigInProgress = 1;
@ -995,18 +994,6 @@ int ButtonConfigBegin ()
void
ButtonConfigEnd ()
{
// shutdown the joystick and video subsystems
KillJoysticks ();
//SDL_QuitSubSystem(SDL_INIT_VIDEO);
// re-initialize joystick and video subsystems if they were active before
/*if(!bcpv) {
InitVideo(GameInfo);
} */
if (!bcpj)
{
InitJoysticks ();
}
buttonConfigInProgress = 0;
}
@ -1016,49 +1003,50 @@ ButtonConfigEnd ()
static int
DTestButton (ButtConfig * bc)
{
int x;
for (x = 0; x < bc->NumC; x++)
if (bc->ButtType == BUTTC_KEYBOARD)
{
if (bc->ButtType[x] == BUTTC_KEYBOARD)
if (g_keyState[SDL_GetScancodeFromKey (bc->ButtonNum)])
{
if (g_keyState[SDL_GetScancodeFromKey (bc->ButtonNum[x])])
{
return 1;
}
bc->state = 1;
return 1;
}
else if (bc->ButtType[x] == BUTTC_JOYSTICK)
else
{
bc->state = 0;
}
}
else if (bc->ButtType == BUTTC_JOYSTICK)
{
if (DTestButtonJoy (bc))
{
if (DTestButtonJoy (bc))
{
return 1;
}
return 1;
}
}
return 0;
}
#define MK(x) {{BUTTC_KEYBOARD},{0},{MKK(x)},1}
#define MK2(x1,x2) {{BUTTC_KEYBOARD},{0},{MKK(x1),MKK(x2)},2}
#define MKZ() {{0},{0},{-1},0}
#define MK(x) {BUTTC_KEYBOARD,0,MKK(x),0}
//#define MK2(x1,x2) {BUTTC_KEYBOARD,0,MKK(x1)}
#define MKZ() {0,0,-1,0}
#define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()}
ButtConfig GamePadConfig[ GAMEPAD_NUM_DEVICES ][ GAMEPAD_NUM_BUTTONS ] =
{
/* Gamepad 1 */
{MK (KP_3), MK (KP_2), MK (SLASH), MK (ENTER),
MK (w), MK (z), MK (a), MK (s), MKZ (), MKZ ()},
/* Gamepad 2 */
GPZ (),
/* Gamepad 3 */
GPZ (),
/* Gamepad 4 */
GPZ ()
};
//ButtConfig GamePadConfig[ GAMEPAD_NUM_DEVICES ][ GAMEPAD_NUM_BUTTONS ] =
//{
///* Gamepad 1 */
// {MK (KP_3), MK (KP_2), MK (SLASH), MK (ENTER),
// MK (w), MK (z), MK (a), MK (s), MKZ (), MKZ ()},
//
// /* Gamepad 2 */
// GPZ (),
//
// /* Gamepad 3 */
// GPZ (),
//
// /* Gamepad 4 */
// GPZ ()
//};
/**
* Update the status of the gamepad input devices.
@ -1090,7 +1078,7 @@ UpdateGamepad(void)
// a, b, select, start, up, down, left, right
for (x = 0; x < 8; x++)
{
if (DTestButton (&GamePadConfig[wg][x]))
if (DTestButton (&GamePad[wg].bmap[x]))
{
//printf("GamePad%i Button Hit: %i \n", wg, x );
if(opposite_dirs == 0)
@ -1128,7 +1116,7 @@ UpdateGamepad(void)
{
for (x = 0; x < 2; x++)
{
if (DTestButton (&GamePadConfig[wg][8 + x]))
if (DTestButton (&GamePad[wg].bmap[8 + x]))
{
JS |= (1 << x) << (wg << 3);
}
@ -1563,42 +1551,42 @@ UpdateFTrainer ()
* @param bc the NES gamepad's button config
* @param which the index of the button
*/
const char * ButtonName (const ButtConfig * bc, int which)
const char * ButtonName (const ButtConfig * bc)
{
static char name[256];
name[0] = 0;
if (bc->ButtonNum[which] == -1)
if (bc->ButtonNum == -1)
{
return name;
}
switch (bc->ButtType[which])
switch (bc->ButtType)
{
case BUTTC_KEYBOARD:
return SDL_GetKeyName (bc->ButtonNum[which]);
return SDL_GetKeyName (bc->ButtonNum);
break;
case BUTTC_JOYSTICK:
{
int joyNum, inputNum;
const char *inputType, *inputDirection;
char direction[128] = "";
joyNum = bc->DeviceNum[which];
joyNum = bc->DeviceNum;
if (bc->ButtonNum[which] & 0x8000)
if (bc->ButtonNum & 0x8000)
{
inputType = "Axis";
inputNum = bc->ButtonNum[which] & 0x3FFF;
inputDirection = bc->ButtonNum[which] & 0x4000 ? "-" : "+";
inputNum = bc->ButtonNum & 0x3FFF;
inputDirection = bc->ButtonNum & 0x4000 ? "-" : "+";
}
else if (bc->ButtonNum[which] & 0x2000)
else if (bc->ButtonNum & 0x2000)
{
int inputValue;
char direction[128] = "";
inputType = "Hat";
inputNum = (bc->ButtonNum[which] >> 8) & 0x1F;
inputValue = bc->ButtonNum[which] & 0xF;
inputNum = (bc->ButtonNum >> 8) & 0x1F;
inputValue = bc->ButtonNum & 0xF;
if (inputValue & SDL_HAT_UP)
strncat (direction, "Up ", sizeof (direction)-1);
@ -1617,7 +1605,7 @@ const char * ButtonName (const ButtConfig * bc, int which)
else
{
inputType = "Button";
inputNum = bc->ButtonNum[which];
inputNum = bc->ButtonNum;
inputDirection = "";
}
sprintf( name, "js%i:%s%i%s", joyNum, inputType, inputNum, inputDirection );
@ -1632,7 +1620,7 @@ const char * ButtonName (const ButtConfig * bc, int which)
* Waits for a button input and returns the information as to which
* button was pressed. Used in button configuration.
*/
int DWaitButton (const uint8_t * text, ButtConfig * bc, int wb, int *buttonConfigStatus )
int DWaitButton (const uint8_t * text, ButtConfig * bc, int *buttonConfigStatus )
{
SDL_Event event;
static int32 LastAx[64][64];
@ -1684,23 +1672,23 @@ int DWaitButton (const uint8_t * text, ButtConfig * bc, int wb, int *buttonConfi
{
case SDL_KEYDOWN:
//printf("SDL KeyDown:%i \n", event.key.keysym.sym );
bc->ButtType[wb] = BUTTC_KEYBOARD;
bc->DeviceNum[wb] = 0;
bc->ButtonNum[wb] = event.key.keysym.sym;
bc->ButtType = BUTTC_KEYBOARD;
bc->DeviceNum = 0;
bc->ButtonNum = event.key.keysym.sym;
return (1);
case SDL_JOYBUTTONDOWN:
bc->ButtType[wb] = BUTTC_JOYSTICK;
bc->DeviceNum[wb] = event.jbutton.which;
bc->ButtonNum[wb] = event.jbutton.button;
bc->ButtType = BUTTC_JOYSTICK;
bc->DeviceNum = event.jbutton.which;
bc->ButtonNum = event.jbutton.button;
return (1);
case SDL_JOYHATMOTION:
if (event.jhat.value == SDL_HAT_CENTERED)
done--;
else
{
bc->ButtType[wb] = BUTTC_JOYSTICK;
bc->DeviceNum[wb] = event.jhat.which;
bc->ButtonNum[wb] =
bc->ButtType = BUTTC_JOYSTICK;
bc->DeviceNum = event.jhat.which;
bc->ButtonNum =
(0x2000 | ((event.jhat.hat & 0x1F) << 8) | event.
jhat.value);
return (1);
@ -1722,9 +1710,9 @@ int DWaitButton (const uint8_t * text, ButtConfig * bc, int wb, int *buttonConfi
(LastAx[event.jaxis.which][event.jaxis.axis] -
event.jaxis.value) >= 8192)
{
bc->ButtType[wb] = BUTTC_JOYSTICK;
bc->DeviceNum[wb] = event.jaxis.which;
bc->ButtonNum[wb] = (0x8000 | event.jaxis.axis |
bc->ButtType = BUTTC_JOYSTICK;
bc->DeviceNum = event.jaxis.which;
bc->ButtonNum = (0x8000 | event.jaxis.axis |
((event.jaxis.value < 0)
? 0x4000 : 0));
return (1);
@ -1761,170 +1749,169 @@ int DWaitButton (const uint8_t * text, ButtConfig * bc, int wb, int *buttonConfi
* used as input for the specified button, thus allowing up to four
* possible settings for each input button.
*/
void
ConfigButton (char *text, ButtConfig * bc)
{
uint8 buf[256];
int wc;
for (wc = 0; wc < MAXBUTTCONFIG; wc++)
{
sprintf ((char *) buf, "%s (%d)", text, wc + 1);
DWaitButton (buf, bc, wc, NULL);
if (wc &&
bc->ButtType[wc] == bc->ButtType[wc - 1] &&
bc->DeviceNum[wc] == bc->DeviceNum[wc - 1] &&
bc->ButtonNum[wc] == bc->ButtonNum[wc - 1])
{
break;
}
}
bc->NumC = wc;
}
// void
//ConfigButton (char *text, ButtConfig * bc)
//{
// uint8 buf[256];
// int wc;
//
// for (wc = 0; wc < MAXBUTTCONFIG; wc++)
// {
// sprintf ((char *) buf, "%s (%d)", text, wc + 1);
// DWaitButton (buf, bc, wc, NULL);
//
// if (wc &&
// bc->ButtType[wc] == bc->ButtType[wc - 1] &&
// bc->DeviceNum[wc] == bc->DeviceNum[wc - 1] &&
// bc->ButtonNum[wc] == bc->ButtonNum[wc - 1])
// {
// break;
// }
// }
//}
/**
* Update the button configuration for a specified device.
*/
extern Config *g_config;
void ConfigDevice (int which, int arg)
{
char buf[256];
int x;
std::string prefix;
const char *str[10] =
{ "A", "B", "SELECT", "START", "UP", "DOWN", "LEFT", "RIGHT", "Rapid A",
"Rapid B"
};
// XXX soules - set the configuration options so that later calls
// don't override these. This is a temp hack until I
// can clean up this file.
ButtonConfigBegin ();
switch (which)
{
case FCFGD_QUIZKING:
prefix = "SDL.Input.QuizKing.";
for (x = 0; x < 6; x++)
{
sprintf (buf, "Quiz King Buzzer #%d", x + 1);
ConfigButton (buf, &QuizKingButtons[x]);
g_config->setOption (prefix + QuizKingNames[x],
QuizKingButtons[x].ButtonNum[0]);
}
if (QuizKingButtons[0].ButtType[0] == BUTTC_KEYBOARD)
{
g_config->setOption (prefix + "DeviceType", "Keyboard");
}
else if (QuizKingButtons[0].ButtType[0] == BUTTC_JOYSTICK)
{
g_config->setOption (prefix + "DeviceType", "Joystick");
}
else
{
g_config->setOption (prefix + "DeviceType", "Unknown");
}
g_config->setOption (prefix + "DeviceNum",
QuizKingButtons[0].DeviceNum[0]);
break;
case FCFGD_HYPERSHOT:
prefix = "SDL.Input.HyperShot.";
for (x = 0; x < 4; x++)
{
sprintf (buf, "Hyper Shot %d: %s",
((x & 2) >> 1) + 1, (x & 1) ? "JUMP" : "RUN");
ConfigButton (buf, &HyperShotButtons[x]);
g_config->setOption (prefix + HyperShotNames[x],
HyperShotButtons[x].ButtonNum[0]);
}
if (HyperShotButtons[0].ButtType[0] == BUTTC_KEYBOARD)
{
g_config->setOption (prefix + "DeviceType", "Keyboard");
}
else if (HyperShotButtons[0].ButtType[0] == BUTTC_JOYSTICK)
{
g_config->setOption (prefix + "DeviceType", "Joystick");
}
else
{
g_config->setOption (prefix + "DeviceType", "Unknown");
}
g_config->setOption (prefix + "DeviceNum",
HyperShotButtons[0].DeviceNum[0]);
break;
case FCFGD_POWERPAD:
snprintf (buf, 256, "SDL.Input.PowerPad.%d", (arg & 1));
prefix = buf;
for (x = 0; x < 12; x++)
{
sprintf (buf, "PowerPad %d: %d", (arg & 1) + 1, x + 11);
ConfigButton (buf, &powerpadsc[arg & 1][x]);
g_config->setOption (prefix + PowerPadNames[x],
powerpadsc[arg & 1][x].ButtonNum[0]);
}
if (powerpadsc[arg & 1][0].ButtType[0] == BUTTC_KEYBOARD)
{
g_config->setOption (prefix + "DeviceType", "Keyboard");
}
else if (powerpadsc[arg & 1][0].ButtType[0] == BUTTC_JOYSTICK)
{
g_config->setOption (prefix + "DeviceType", "Joystick");
}
else
{
g_config->setOption (prefix + "DeviceType", "Unknown");
}
g_config->setOption (prefix + "DeviceNum",
powerpadsc[arg & 1][0].DeviceNum[0]);
break;
case FCFGD_GAMEPAD:
snprintf (buf, 256, "SDL.Input.GamePad.%d", arg);
prefix = buf;
for (x = 0; x < 10; x++)
{
sprintf (buf, "GamePad #%d: %s", arg + 1, str[x]);
ConfigButton (buf, &GamePadConfig[arg][x]);
g_config->setOption (prefix + GamePadNames[x],
GamePadConfig[arg][x].ButtonNum[0]);
}
if (GamePadConfig[arg][0].ButtType[0] == BUTTC_KEYBOARD)
{
g_config->setOption (prefix + "DeviceType", "Keyboard");
}
else if (GamePadConfig[arg][0].ButtType[0] == BUTTC_JOYSTICK)
{
g_config->setOption (prefix + "DeviceType", "Joystick");
}
else
{
g_config->setOption (prefix + "DeviceType", "Unknown");
}
g_config->setOption (prefix + "DeviceNum",
GamePadConfig[arg][0].DeviceNum[0]);
break;
}
ButtonConfigEnd ();
}
//void ConfigDevice (int which, int arg)
//{
// char buf[256];
// int x;
// std::string prefix;
// const char *str[10] =
// { "A", "B", "SELECT", "START", "UP", "DOWN", "LEFT", "RIGHT", "Rapid A",
// "Rapid B"
// };
//
// // XXX soules - set the configuration options so that later calls
// // don't override these. This is a temp hack until I
// // can clean up this file.
//
// ButtonConfigBegin ();
// switch (which)
// {
// case FCFGD_QUIZKING:
// prefix = "SDL.Input.QuizKing.";
// for (x = 0; x < 6; x++)
// {
// sprintf (buf, "Quiz King Buzzer #%d", x + 1);
// ConfigButton (buf, &QuizKingButtons[x]);
//
// g_config->setOption (prefix + QuizKingNames[x],
// QuizKingButtons[x].ButtonNum);
// }
//
// if (QuizKingButtons[0].ButtType == BUTTC_KEYBOARD)
// {
// g_config->setOption (prefix + "DeviceType", "Keyboard");
// }
// else if (QuizKingButtons[0].ButtType == BUTTC_JOYSTICK)
// {
// g_config->setOption (prefix + "DeviceType", "Joystick");
// }
// else
// {
// g_config->setOption (prefix + "DeviceType", "Unknown");
// }
// g_config->setOption (prefix + "DeviceNum",
// QuizKingButtons[0].DeviceNum);
// break;
// case FCFGD_HYPERSHOT:
// prefix = "SDL.Input.HyperShot.";
// for (x = 0; x < 4; x++)
// {
// sprintf (buf, "Hyper Shot %d: %s",
// ((x & 2) >> 1) + 1, (x & 1) ? "JUMP" : "RUN");
// ConfigButton (buf, &HyperShotButtons[x]);
//
// g_config->setOption (prefix + HyperShotNames[x],
// HyperShotButtons[x].ButtonNum);
// }
//
// if (HyperShotButtons[0].ButtType == BUTTC_KEYBOARD)
// {
// g_config->setOption (prefix + "DeviceType", "Keyboard");
// }
// else if (HyperShotButtons[0].ButtType == BUTTC_JOYSTICK)
// {
// g_config->setOption (prefix + "DeviceType", "Joystick");
// }
// else
// {
// g_config->setOption (prefix + "DeviceType", "Unknown");
// }
// g_config->setOption (prefix + "DeviceNum",
// HyperShotButtons[0].DeviceNum);
// break;
// case FCFGD_POWERPAD:
// snprintf (buf, 256, "SDL.Input.PowerPad.%d", (arg & 1));
// prefix = buf;
// for (x = 0; x < 12; x++)
// {
// sprintf (buf, "PowerPad %d: %d", (arg & 1) + 1, x + 11);
// ConfigButton (buf, &powerpadsc[arg & 1][x]);
//
// g_config->setOption (prefix + PowerPadNames[x],
// powerpadsc[arg & 1][x].ButtonNum);
// }
//
// if (powerpadsc[arg & 1][0].ButtType == BUTTC_KEYBOARD)
// {
// g_config->setOption (prefix + "DeviceType", "Keyboard");
// }
// else if (powerpadsc[arg & 1][0].ButtType == BUTTC_JOYSTICK)
// {
// g_config->setOption (prefix + "DeviceType", "Joystick");
// }
// else
// {
// g_config->setOption (prefix + "DeviceType", "Unknown");
// }
// g_config->setOption (prefix + "DeviceNum",
// powerpadsc[arg & 1][0].DeviceNum);
// break;
//
// case FCFGD_GAMEPAD:
// snprintf (buf, 256, "SDL.Input.GamePad.%d", arg);
// prefix = buf;
// for (x = 0; x < 10; x++)
// {
// sprintf (buf, "GamePad #%d: %s", arg + 1, str[x]);
// ConfigButton (buf, &GamePadConfig[arg][x]);
//
// g_config->setOption (prefix + GamePadNames[x],
// GamePadConfig[arg][x].ButtonNum);
// }
//
// if (GamePadConfig[arg][0].ButtType == BUTTC_KEYBOARD)
// {
// g_config->setOption (prefix + "DeviceType", "Keyboard");
// }
// else if (GamePadConfig[arg][0].ButtType == BUTTC_JOYSTICK)
// {
// g_config->setOption (prefix + "DeviceType", "Joystick");
// }
// else
// {
// g_config->setOption (prefix + "DeviceType", "Unknown");
// }
// g_config->setOption (prefix + "DeviceNum",
// GamePadConfig[arg][0].DeviceNum);
// break;
// }
//
// ButtonConfigEnd ();
//}
/**
* Update the button configuration for a device, specified by a text string.
*/
void InputCfg (const std::string & text)
{
//void InputCfg (const std::string & text)
//{
//
// if (noGui)
// {
// if (text.find ("gamepad") != std::string::npos)
@ -1960,8 +1947,8 @@ void InputCfg (const std::string & text)
// }
// else
// printf ("Please run \"fceux --nogui\" before using --inputcfg\n");
}
//
//}
/**
@ -1973,7 +1960,9 @@ void InputCfg (const std::string & text)
UpdateInput (Config * config)
{
char buf[64];
std::string device, prefix;
std::string device, prefix, guid, mapping;
InitJoysticks();
for (unsigned int i = 0; i < 3; i++)
{
@ -2066,37 +2055,18 @@ UpdateInput (Config * config)
snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%u.", i);
prefix = buf;
config->getOption (prefix + "DeviceType", &device);
if (device.find ("Keyboard") != std::string::npos)
{
type = BUTTC_KEYBOARD;
}
else if (device.find ("Joystick") != std::string::npos)
{
type = BUTTC_JOYSTICK;
}
else
{
type = 0;
}
config->getOption (prefix + "DeviceType", &device );
config->getOption (prefix + "DeviceGUID", &guid );
config->getOption (prefix + "Profile" , &mapping);
config->getOption (prefix + "DeviceNum", &devnum);
for (unsigned int j = 0; j < GAMEPAD_NUM_BUTTONS; j++)
{
config->getOption (prefix + GamePadNames[j], &button);
GamePadConfig[i][j].ButtType[0] = type;
GamePadConfig[i][j].DeviceNum[0] = devnum;
GamePadConfig[i][j].ButtonNum[0] = button;
GamePadConfig[i][j].NumC = 1;
}
GamePad[i].init( i, guid.c_str(), mapping.c_str() );
}
// PowerPad 0 - 1
for (unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++)
{
char buf[64];
snprintf (buf, 32, "SDL.Input.PowerPad.%u.", i);
snprintf (buf, sizeof(buf)-1, "SDL.Input.PowerPad.%u.", i);
prefix = buf;
config->getOption (prefix + "DeviceType", &device);
@ -2118,10 +2088,9 @@ UpdateInput (Config * config)
{
config->getOption (prefix + PowerPadNames[j], &button);
powerpadsc[i][j].ButtType[0] = type;
powerpadsc[i][j].DeviceNum[0] = devnum;
powerpadsc[i][j].ButtonNum[0] = button;
powerpadsc[i][j].NumC = 1;
powerpadsc[i][j].ButtType = type;
powerpadsc[i][j].DeviceNum = devnum;
powerpadsc[i][j].ButtonNum = button;
}
}
@ -2145,10 +2114,9 @@ UpdateInput (Config * config)
{
config->getOption (prefix + QuizKingNames[j], &button);
QuizKingButtons[j].ButtType[0] = type;
QuizKingButtons[j].DeviceNum[0] = devnum;
QuizKingButtons[j].ButtonNum[0] = button;
QuizKingButtons[j].NumC = 1;
QuizKingButtons[j].ButtType = type;
QuizKingButtons[j].DeviceNum = devnum;
QuizKingButtons[j].ButtonNum = button;
}
// HyperShot
@ -2171,10 +2139,9 @@ UpdateInput (Config * config)
{
config->getOption (prefix + HyperShotNames[j], &button);
HyperShotButtons[j].ButtType[0] = type;
HyperShotButtons[j].DeviceNum[0] = devnum;
HyperShotButtons[j].ButtonNum[0] = button;
HyperShotButtons[j].NumC = 1;
HyperShotButtons[j].ButtType = type;
HyperShotButtons[j].DeviceNum = devnum;
HyperShotButtons[j].ButtonNum = button;
}
// Mahjong
@ -2197,10 +2164,9 @@ UpdateInput (Config * config)
{
config->getOption (prefix + MahjongNames[j], &button);
MahjongButtons[j].ButtType[0] = type;
MahjongButtons[j].DeviceNum[0] = devnum;
MahjongButtons[j].ButtonNum[0] = button;
MahjongButtons[j].NumC = 1;
MahjongButtons[j].ButtType = type;
MahjongButtons[j].DeviceNum = devnum;
MahjongButtons[j].ButtonNum = button;
}
// TopRider
@ -2223,10 +2189,9 @@ UpdateInput (Config * config)
{
config->getOption (prefix + TopRiderNames[j], &button);
TopRiderButtons[j].ButtType[0] = type;
TopRiderButtons[j].DeviceNum[0] = devnum;
TopRiderButtons[j].ButtonNum[0] = button;
TopRiderButtons[j].NumC = 1;
TopRiderButtons[j].ButtType = type;
TopRiderButtons[j].DeviceNum = devnum;
TopRiderButtons[j].ButtonNum = button;
}
// FTrainer
@ -2249,10 +2214,9 @@ UpdateInput (Config * config)
{
config->getOption (prefix + FTrainerNames[j], &button);
FTrainerButtons[j].ButtType[0] = type;
FTrainerButtons[j].DeviceNum[0] = devnum;
FTrainerButtons[j].ButtonNum[0] = button;
FTrainerButtons[j].NumC = 1;
FTrainerButtons[j].ButtType = type;
FTrainerButtons[j].DeviceNum = devnum;
FTrainerButtons[j].ButtonNum = button;
}
// FamilyKeyBoard
@ -2275,10 +2239,9 @@ UpdateInput (Config * config)
{
config->getOption (prefix + FamilyKeyBoardNames[j], &button);
fkbmap[j].ButtType[0] = type;
fkbmap[j].DeviceNum[0] = devnum;
fkbmap[j].ButtonNum[0] = button;
fkbmap[j].NumC = 1;
fkbmap[j].ButtType = type;
fkbmap[j].DeviceNum = devnum;
fkbmap[j].ButtonNum = button;
}
}

View File

@ -5,7 +5,7 @@
#include "common/configSys.h"
#define MAXBUTTCONFIG 4
//#define MAXBUTTCONFIG 4
enum {
BUTTC_KEYBOARD = 0,
@ -14,14 +14,14 @@ enum {
};
struct ButtConfig
{
int ButtType[MAXBUTTCONFIG];
int DeviceNum[MAXBUTTCONFIG];
int ButtonNum[MAXBUTTCONFIG];
uint32_t NumC;
int ButtType; //[MAXBUTTCONFIG];
int DeviceNum; //[MAXBUTTCONFIG];
int ButtonNum; //[MAXBUTTCONFIG];
int state;
//uint32_t NumC;
//uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */
};
extern int NoWaiting;
extern CFGSTRUCT InputConfig[];
extern ARGPSTRUCT InputArgs[];
@ -32,7 +32,7 @@ int getKeyState( int k );
int ButtonConfigBegin();
void ButtonConfigEnd();
void ConfigButton(char *text, ButtConfig *bc);
int DWaitButton(const uint8_t *text, ButtConfig *bc, int wb, int *buttonConfigStatus = NULL);
int DWaitButton(const uint8_t *text, ButtConfig *bc, int *buttonConfigStatus = NULL);
#define FCFGD_GAMEPAD 1
@ -46,7 +46,7 @@ void InitInputInterface(void);
void InputUserActiveFix(void);
extern bool replaceP2StartWithMicrophone;
extern ButtConfig GamePadConfig[4][10];
//extern ButtConfig GamePadConfig[4][10];
//extern ButtConfig powerpadsc[2][12];
//extern ButtConfig QuizKingButtons[6];
//extern ButtConfig FTrainerButtons[12];
@ -59,9 +59,9 @@ int DTestButtonJoy(ButtConfig *bc);
void FCEUD_UpdateInput(void);
void UpdateInput(Config *config);
void InputCfg(const std::string &);
//void InputCfg(const std::string &);
std::string GetUserText(const char* title);
const char* ButtonName(const ButtConfig* bc, int which);
const char* ButtonName(const ButtConfig* bc);
#endif

View File

@ -17,7 +17,14 @@ int main( int argc, char *argv[] )
consoleWindow->resize( 512, 512 );
consoleWindow->show();
consoleWindow->viewport->init();
if ( consoleWindow->viewport_SDL )
{
consoleWindow->viewport_SDL->init();
}
else
{
consoleWindow->viewport_GL->init();
}
retval = app.exec();

View File

@ -0,0 +1,701 @@
// ppuViewer.cpp
//
#include <stdio.h>
#include <stdint.h>
#include <QDir>
#include <QPainter>
#include <QInputDialog>
#include <QMessageBox>
#include "../../types.h"
#include "../../fceu.h"
#include "../../cart.h"
#include "../../ppu.h"
#include "../../debug.h"
#include "../../palette.h"
#include "Qt/ppuViewer.h"
#include "Qt/main.h"
#include "Qt/dface.h"
#include "Qt/input.h"
#include "Qt/config.h"
#include "Qt/fceuWrapper.h"
#define PATTERNWIDTH 128
#define PATTERNHEIGHT 128
#define PATTERNBITWIDTH PATTERNWIDTH*3
#define PALETTEWIDTH 16
#define PALETTEHEIGHT 2
#define PALETTEBITWIDTH PALETTEWIDTH*3
static ppuViewerDialog_t *ppuViewWindow = NULL;
static int PPUViewScanline = 0;
static int PPUViewSkip = 0;
static int PPUViewRefresh = 1;
static bool PPUView_maskUnusedGraphics = true;
static bool PPUView_invertTheMask = false;
static int PPUView_sprite16Mode[2] = { 0, 0 };
static int pindex[2] = { 0, 0 };
static QColor ppuv_palette[PALETTEHEIGHT][PALETTEWIDTH];
static uint8_t pallast[32+3] = { 0 }; // palette cache for change comparison
static uint8_t palcache[36] = { 0 }; //palette cache for drawing
static uint8_t chrcache0[0x1000] = {0}, chrcache1[0x1000] = {0}, logcache0[0x1000] = {0}, logcache1[0x1000] = {0}; //cache CHR, fixes a refresh problem when right-clicking
static bool redrawWindow = true;
static void initPPUViewer(void);
static ppuPatternTable_t pattern0;
static ppuPatternTable_t pattern1;
//----------------------------------------------------
int openPPUViewWindow( QWidget *parent )
{
if ( ppuViewWindow != NULL )
{
return -1;
}
initPPUViewer();
ppuViewWindow = new ppuViewerDialog_t(parent);
ppuViewWindow->show();
return 0;
}
//----------------------------------------------------
ppuViewerDialog_t::ppuViewerDialog_t(QWidget *parent)
: QDialog( parent )
{
QVBoxLayout *mainLayout, *vbox;
QVBoxLayout *patternVbox[2];
QHBoxLayout *hbox;
QGridLayout *grid;
char stmp[64];
ppuViewWindow = this;
setWindowTitle( tr("PPU Viewer") );
mainLayout = new QVBoxLayout();
setLayout( mainLayout );
vbox = new QVBoxLayout();
hbox = new QHBoxLayout();
grid = new QGridLayout;
patternVbox[0] = new QVBoxLayout();
patternVbox[1] = new QVBoxLayout();
patternFrame[0] = new QGroupBox( tr("Pattern Table 0") );
patternFrame[1] = new QGroupBox( tr("Pattern Table 1") );
patternView[0] = new ppuPatternView_t( 0, this);
patternView[1] = new ppuPatternView_t( 1, this);
sprite8x16Cbox[0] = new QCheckBox( tr("Sprites 8x16 Mode") );
sprite8x16Cbox[1] = new QCheckBox( tr("Sprites 8x16 Mode") );
tileLabel[0] = new QLabel( tr("Tile:") );
tileLabel[1] = new QLabel( tr("Tile:") );
sprite8x16Cbox[0]->setChecked( PPUView_sprite16Mode[0] );
sprite8x16Cbox[1]->setChecked( PPUView_sprite16Mode[1] );
patternVbox[0]->addWidget( patternView[0], 100 );
patternVbox[0]->addWidget( tileLabel[0], 1 );
patternVbox[0]->addWidget( sprite8x16Cbox[0], 1 );
patternVbox[1]->addWidget( patternView[1], 100 );
patternVbox[1]->addWidget( tileLabel[1], 1 );
patternVbox[1]->addWidget( sprite8x16Cbox[1], 1 );
patternFrame[0]->setLayout( patternVbox[0] );
patternFrame[1]->setLayout( patternVbox[1] );
hbox->addWidget( patternFrame[0] );
hbox->addWidget( patternFrame[1] );
mainLayout->addLayout( hbox, 10 );
mainLayout->addLayout( grid, 1 );
maskUnusedCbox = new QCheckBox( tr("Mask unused Graphics (Code/Data Logger)") );
invertMaskCbox = new QCheckBox( tr("Invert the Mask (Code/Data Logger)") );
maskUnusedCbox->setChecked( PPUView_maskUnusedGraphics );
invertMaskCbox->setChecked( PPUView_invertTheMask );
connect( sprite8x16Cbox[0], SIGNAL(stateChanged(int)), this, SLOT(sprite8x16Changed0(int)));
connect( sprite8x16Cbox[1], SIGNAL(stateChanged(int)), this, SLOT(sprite8x16Changed1(int)));
hbox = new QHBoxLayout();
refreshSlider = new QSlider( Qt::Horizontal );
hbox->addWidget( new QLabel( tr("Refresh: More") ) );
hbox->addWidget( refreshSlider );
hbox->addWidget( new QLabel( tr("Less") ) );
grid->addWidget( maskUnusedCbox, 0, 0, Qt::AlignLeft );
grid->addWidget( invertMaskCbox, 1, 0, Qt::AlignLeft );
grid->addLayout( hbox, 0, 1, Qt::AlignRight );
hbox = new QHBoxLayout();
scanLineEdit = new QLineEdit();
hbox->addWidget( new QLabel( tr("Display on Scanline:") ) );
hbox->addWidget( scanLineEdit );
grid->addLayout( hbox, 1, 1, Qt::AlignRight );
vbox = new QVBoxLayout();
paletteFrame = new QGroupBox( tr("Palettes:") );
paletteView = new ppuPalatteView_t(this);
vbox->addWidget( paletteView, 1 );
paletteFrame->setLayout( vbox );
mainLayout->addWidget( paletteFrame, 1 );
patternView[0]->setPattern( &pattern0 );
patternView[1]->setPattern( &pattern1 );
patternView[0]->setTileLabel( tileLabel[0] );
patternView[1]->setTileLabel( tileLabel[1] );
paletteView->setTileLabel( paletteFrame );
scanLineEdit->setMaxLength( 3 );
scanLineEdit->setInputMask( ">900;" );
sprintf( stmp, "%i", PPUViewScanline );
scanLineEdit->setText( tr(stmp) );
connect( scanLineEdit, SIGNAL(textEdited(const QString &)), this, SLOT(scanLineChanged(const QString &)));
refreshSlider->setMinimum( 0);
refreshSlider->setMaximum(25);
refreshSlider->setValue(PPUViewRefresh);
connect( refreshSlider, SIGNAL(valueChanged(int)), this, SLOT(refreshSliderChanged(int)));
FCEUD_UpdatePPUView( -1, 1 );
updateTimer = new QTimer( this );
connect( updateTimer, &QTimer::timeout, this, &ppuViewerDialog_t::periodicUpdate );
updateTimer->start( 33 ); // 30hz
}
//----------------------------------------------------
ppuViewerDialog_t::~ppuViewerDialog_t(void)
{
updateTimer->stop();
ppuViewWindow = NULL;
printf("PPU Viewer Window Deleted\n");
}
//----------------------------------------------------
void ppuViewerDialog_t::closeEvent(QCloseEvent *event)
{
printf("PPU Viewer Close Window Event\n");
done(0);
deleteLater();
event->accept();
}
//----------------------------------------------------
void ppuViewerDialog_t::closeWindow(void)
{
printf("Close Window\n");
done(0);
deleteLater();
}
//----------------------------------------------------
void ppuViewerDialog_t::periodicUpdate(void)
{
if ( redrawWindow )
{
this->update();
redrawWindow = false;
}
}
//----------------------------------------------------
void ppuViewerDialog_t::scanLineChanged( const QString &txt )
{
std::string s;
s = txt.toStdString();
if ( s.size() > 0 )
{
PPUViewScanline = strtoul( s.c_str(), NULL, 10 );
}
//printf("ScanLine: '%s' %i\n", s.c_str(), PPUViewScanline );
}
//----------------------------------------------------
void ppuViewerDialog_t::sprite8x16Changed0(int state)
{
PPUView_sprite16Mode[0] = (state == Qt::Unchecked) ? 0 : 1;
}
//----------------------------------------------------
void ppuViewerDialog_t::sprite8x16Changed1(int state)
{
PPUView_sprite16Mode[1] = (state == Qt::Unchecked) ? 0 : 1;
}
//----------------------------------------------------
void ppuViewerDialog_t::refreshSliderChanged(int value)
{
PPUViewRefresh = value;
}
//----------------------------------------------------
ppuPatternView_t::ppuPatternView_t( int patternIndexID, QWidget *parent)
: QWidget(parent)
{
this->setFocusPolicy(Qt::StrongFocus);
this->setMouseTracking(true);
patternIndex = patternIndexID;
setMinimumWidth( 256 );
setMinimumHeight( 256 );
viewWidth = 256;
viewHeight = 256;
tileLabel = NULL;
}
//----------------------------------------------------
void ppuPatternView_t::setPattern( ppuPatternTable_t *p )
{
pattern = p;
}
//----------------------------------------------------
void ppuPatternView_t::setTileLabel( QLabel *l )
{
tileLabel = l;
}
//----------------------------------------------------
ppuPatternView_t::~ppuPatternView_t(void)
{
}
//----------------------------------------------------
QPoint ppuPatternView_t::convPixToTile( QPoint p )
{
QPoint t(0,0);
int x,y,w,h,i,j,ii,jj,rr;
x = p.x(); y = p.y();
w = pattern->w;
h = pattern->h;
i = x / (w*8);
j = y / (h*8);
if ( PPUView_sprite16Mode[ patternIndex ] )
{
rr = (j%2);
jj = j;
if ( rr )
{
jj--;
}
ii = (i*2)+rr;
if ( ii >= 16 )
{
ii = ii % 16;
jj++;
}
}
else
{
ii = i; jj = j;
}
//printf("(x,y) = (%i,%i) w=%i h=%i $%X%X \n", x, y, w, h, jj, ii );
t.setX(ii);
t.setY(jj);
return t;
}
//----------------------------------------------------
void ppuPatternView_t::resizeEvent(QResizeEvent *event)
{
viewWidth = event->size().width();
viewHeight = event->size().height();
pattern->w = viewWidth / 128;
pattern->h = viewHeight / 128;
}
//----------------------------------------------------
void ppuPatternView_t::mouseMoveEvent(QMouseEvent *event)
{
QPoint tile = convPixToTile( event->pos() );
if ( (tile.x() < 16) && (tile.y() < 16) )
{
char stmp[64];
sprintf( stmp, "Tile: $%X%X", tile.y(), tile.x() );
tileLabel->setText( tr(stmp) );
}
}
//----------------------------------------------------------------------------
void ppuPatternView_t::mousePressEvent(QMouseEvent * event)
{
//QPoint tile = convPixToTile( event->pos() );
if ( event->button() == Qt::LeftButton )
{
// Load Tile Viewport
PPUViewSkip = 100;
FCEUD_UpdatePPUView( -1, 0 );
}
else if ( event->button() == Qt::RightButton )
{
pindex[ patternIndex ] = (pindex[ patternIndex ] + 1) % 9;
PPUViewSkip = 100;
FCEUD_UpdatePPUView( -1, 0 );
}
}
//----------------------------------------------------
void ppuPatternView_t::paintEvent(QPaintEvent *event)
{
int i,j,x,y,w,h,xx,yy,ii,jj,rr;
QPainter painter(this);
viewWidth = event->rect().width();
viewHeight = event->rect().height();
//printf("PPU PatternView %ix%i \n", viewWidth, viewHeight );
w = viewWidth / 128;
h = viewHeight / 128;
pattern->w = w;
pattern->h = h;
xx = 0; yy = 0;
if ( PPUView_sprite16Mode[ patternIndex ] )
{
for (i=0; i<16; i++) //Columns
{
for (j=0; j<16; j++) //Rows
{
rr = (j%2);
jj = j;
if ( rr )
{
jj--;
}
ii = (i*2)+rr;
if ( ii >= 16 )
{
ii = ii % 16;
jj++;
}
xx = (i*8)*w;
for (x=0; x < 8; x++)
{
yy = (j*8)*h;
for (y=0; y < 8; y++)
{
pattern->tile[jj][ii].x = xx;
pattern->tile[jj][ii].y = yy;
painter.fillRect( xx, yy, w, h, pattern->tile[jj][ii].pixel[y][x].color );
yy += h;
}
xx += w;
}
}
}
}
else
{
for (i=0; i<16; i++) //Columns
{
for (j=0; j<16; j++) //Rows
{
xx = (i*8)*w;
for (x=0; x < 8; x++)
{
yy = (j*8)*h;
for (y=0; y < 8; y++)
{
pattern->tile[j][i].x = xx;
pattern->tile[j][i].y = yy;
painter.fillRect( xx, yy, w, h, pattern->tile[j][i].pixel[y][x].color );
yy += h;
}
xx += w;
}
}
}
}
}
//----------------------------------------------------
static void initPPUViewer(void)
{
memset( pallast , 0, sizeof(pallast) );
memset( palcache , 0, sizeof(palcache) );
memset( chrcache0, 0, sizeof(chrcache0) );
memset( chrcache1, 0, sizeof(chrcache1) );
memset( logcache0, 0, sizeof(logcache0) );
memset( logcache1, 0, sizeof(logcache1) );
// forced palette (e.g. for debugging CHR when palettes are all-black)
palcache[(8*4)+0] = 0x0F;
palcache[(8*4)+1] = 0x00;
palcache[(8*4)+2] = 0x10;
palcache[(8*4)+3] = 0x20;
pindex[0] = 0;
pindex[1] = 0;
}
//----------------------------------------------------
static void DrawPatternTable( ppuPatternTable_t *pattern, uint8_t *table, uint8_t *log, uint8_t pal)
{
int i,j,x,y,index=0;
int p=0,tmp;
uint8_t chr0,chr1,logs,shift;
pal <<= 2;
for (i = 0; i < 16; i++) //Columns
{
for (j = 0; j < 16; j++) //Rows
{
//printf("Tile: %X%X index:%04X %04X\n", j,i,index, (i<<4)|(j<<8));
//-----------------------------------------------
for (y = 0; y < 8; y++)
{
chr0 = table[index];
chr1 = table[index + 8];
logs = log[index] & log[index + 8];
tmp = 7;
shift=(PPUView_maskUnusedGraphics && debug_loggingCD && (((logs & 3) != 0) == PPUView_invertTheMask))?3:0;
for (x = 0; x < 8; x++)
{
p = (chr0 >> tmp) & 1;
p |= ((chr1 >> tmp) & 1) << 1;
p = palcache[p | pal];
tmp--;
pattern->tile[i][j].pixel[y][x].color.setBlue( palo[p].b >> shift );
pattern->tile[i][j].pixel[y][x].color.setGreen( palo[p].g >> shift );
pattern->tile[i][j].pixel[y][x].color.setRed( palo[p].r >> shift );
//printf("Tile: %X%X Pixel: (%i,%i) P:%i RGB: (%i,%i,%i)\n", j, i, x, y, p,
// pattern->tile[j][i].pixel[y][x].color.red(),
// pattern->tile[j][i].pixel[y][x].color.green(),
// pattern->tile[j][i].pixel[y][x].color.blue() );
}
index++;
}
index+=8;
//------------------------------------------------
}
}
}
//----------------------------------------------------
void FCEUD_UpdatePPUView(int scanline, int refreshchr)
{
if ( ppuViewWindow == NULL )
{
return;
}
if ( (scanline != -1) && (scanline != PPUViewScanline) )
{
return;
}
int x,y,i;
if (refreshchr)
{
int i10, x10;
for (i = 0, x=0x1000; i < 0x1000; i++, x++)
{
i10 = i>>10;
x10 = x>>10;
if ( VPage[i10] == NULL )
{
continue;
}
chrcache0[i] = VPage[i10][i];
chrcache1[i] = VPage[x10][x];
if (debug_loggingCD)
{
if (cdloggerVideoDataSize)
{
int addr;
addr = &VPage[i10][i] - CHRptr[0];
if ((addr >= 0) && (addr < (int)cdloggerVideoDataSize))
logcache0[i] = cdloggervdata[addr];
addr = &VPage[x10][x] - CHRptr[0];
if ((addr >= 0) && (addr < (int)cdloggerVideoDataSize))
logcache1[i] = cdloggervdata[addr];
}
else
{
logcache0[i] = cdloggervdata[i];
logcache1[i] = cdloggervdata[x];
}
}
}
}
if (PPUViewSkip < PPUViewRefresh)
{
PPUViewSkip++;
return;
}
PPUViewSkip = 0;
// update palette only if required
if ((memcmp(pallast, PALRAM, 32) != 0) || (memcmp(pallast+32, UPALRAM, 3) != 0))
{
//printf("Updated PPU View Palette\n");
memcpy(pallast, PALRAM, 32);
memcpy(pallast+32, UPALRAM, 3);
// cache palette content
memcpy(palcache,PALRAM,32);
palcache[0x10] = palcache[0x00];
palcache[0x04] = palcache[0x14] = UPALRAM[0];
palcache[0x08] = palcache[0x18] = UPALRAM[1];
palcache[0x0C] = palcache[0x1C] = UPALRAM[2];
//draw palettes
for (y = 0; y < PALETTEHEIGHT; y++)
{
for (x = 0; x < PALETTEWIDTH; x++)
{
i = (y*PALETTEWIDTH) + x;
ppuv_palette[y][x].setBlue( palo[palcache[i]].b );
ppuv_palette[y][x].setGreen( palo[palcache[i]].g );
ppuv_palette[y][x].setRed( palo[palcache[i]].r );
}
}
}
DrawPatternTable( &pattern0,chrcache0,logcache0,pindex[0]);
DrawPatternTable( &pattern1,chrcache1,logcache1,pindex[1]);
redrawWindow = true;
}
//----------------------------------------------------
ppuPalatteView_t::ppuPalatteView_t(QWidget *parent)
: QWidget(parent)
{
this->setFocusPolicy(Qt::StrongFocus);
this->setMouseTracking(true);
setMinimumWidth( 32 * PALETTEWIDTH );
setMinimumHeight( 32 * PALETTEHEIGHT );
viewWidth = 32 * PALETTEWIDTH;
viewHeight = 32 * PALETTEHEIGHT;
boxWidth = viewWidth / PALETTEWIDTH;
boxHeight = viewHeight / PALETTEHEIGHT;
frame = NULL;
}
//----------------------------------------------------
ppuPalatteView_t::~ppuPalatteView_t(void)
{
}
//----------------------------------------------------
void ppuPalatteView_t::setTileLabel( QGroupBox *l )
{
frame = l;
}
//----------------------------------------------------
QPoint ppuPalatteView_t::convPixToTile( QPoint p )
{
QPoint t(0,0);
t.setX( p.x() / boxWidth );
t.setY( p.y() / boxHeight );
return t;
}
//----------------------------------------------------
void ppuPalatteView_t::resizeEvent(QResizeEvent *event)
{
viewWidth = event->size().width();
viewHeight = event->size().height();
boxWidth = viewWidth / PALETTEWIDTH;
boxHeight = viewHeight / PALETTEHEIGHT;
}
//----------------------------------------------------
void ppuPalatteView_t::mouseMoveEvent(QMouseEvent *event)
{
QPoint tile = convPixToTile( event->pos() );
if ( (tile.x() < PALETTEWIDTH) && (tile.y() < PALETTEHEIGHT) )
{
char stmp[64];
int ix = (tile.y()<<4)|tile.x();
sprintf( stmp, "Palette: $%02X", palcache[ix]);
frame->setTitle( tr(stmp) );
}
}
//----------------------------------------------------------------------------
void ppuPalatteView_t::mousePressEvent(QMouseEvent * event)
{
//QPoint tile = convPixToTile( event->pos() );
//if ( event->button() == Qt::LeftButton )
//{
//}
//else if ( event->button() == Qt::RightButton )
//{
//}
}
//----------------------------------------------------
void ppuPalatteView_t::paintEvent(QPaintEvent *event)
{
int x,y,w,h,xx,yy;
QPainter painter(this);
viewWidth = event->rect().width();
viewHeight = event->rect().height();
//printf("PPU PatternView %ix%i \n", viewWidth, viewHeight );
w = viewWidth / PALETTEWIDTH;
h = viewHeight / PALETTEHEIGHT;
yy = 0;
for (y=0; y < PALETTEHEIGHT; y++)
{
xx = 0;
for (x=0; x < PALETTEWIDTH; x++)
{
painter.fillRect( xx, yy, w, h, ppuv_palette[y][x] );
xx += w;
}
yy += h;
}
y = PALETTEHEIGHT*h;
for (int i=0; i<=PALETTEWIDTH; i++)
{
x = i*w;
painter.drawLine( x, 0 , x, y );
}
x = PALETTEWIDTH*w;
for (int i=0; i<=PALETTEHEIGHT; i++)
{
y = i*h;
painter.drawLine( 0, y, x, y );
}
}
//----------------------------------------------------

124
src/drivers/Qt/ppuViewer.h Normal file
View File

@ -0,0 +1,124 @@
// ppuViewer.h
//
#pragma once
#include <QWidget>
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
#include <QCheckBox>
#include <QPushButton>
#include <QLabel>
#include <QFrame>
#include <QTimer>
#include <QSlider>
#include <QLineEdit>
#include <QGroupBox>
#include <QCloseEvent>
#include "Qt/main.h"
struct ppuPatternTable_t
{
struct
{
struct
{
QColor color;
} pixel[8][8];
int x;
int y;
} tile[16][16];
int w;
int h;
};
class ppuPatternView_t : public QWidget
{
Q_OBJECT
public:
ppuPatternView_t( int patternIndex, QWidget *parent = 0);
~ppuPatternView_t(void);
void setPattern( ppuPatternTable_t *p );
void setTileLabel( QLabel *l );
QPoint convPixToTile( QPoint p );
protected:
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent * event);
int patternIndex;
int viewWidth;
int viewHeight;
QLabel *tileLabel;
ppuPatternTable_t *pattern;
};
class ppuPalatteView_t : public QWidget
{
Q_OBJECT
public:
ppuPalatteView_t(QWidget *parent = 0);
~ppuPalatteView_t(void);
void setTileLabel( QGroupBox *l );
QPoint convPixToTile( QPoint p );
protected:
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent * event);
int viewWidth;
int viewHeight;
int boxWidth;
int boxHeight;
QGroupBox *frame;
};
class ppuViewerDialog_t : public QDialog
{
Q_OBJECT
public:
ppuViewerDialog_t(QWidget *parent = 0);
~ppuViewerDialog_t(void);
protected:
ppuPatternView_t *patternView[2];
ppuPalatteView_t *paletteView;
void closeEvent(QCloseEvent *bar);
private:
QGroupBox *patternFrame[2];
QGroupBox *paletteFrame;
QLabel *tileLabel[2];
QCheckBox *sprite8x16Cbox[2];
QCheckBox *maskUnusedCbox;
QCheckBox *invertMaskCbox;
QSlider *refreshSlider;
QLineEdit *scanLineEdit;
QTimer *updateTimer;
public slots:
void closeWindow(void);
private slots:
void periodicUpdate(void);
void sprite8x16Changed0(int state);
void sprite8x16Changed1(int state);
void refreshSliderChanged(int value);
void scanLineChanged( const QString &s );
};
int openPPUViewWindow( QWidget *parent );

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
// sdl-joystick.h
#ifndef __SDL_JOYSTICK_H__
#define __SDL_JOYSTICK_H__
#include <string>
#include "Qt/main.h"
#include "Qt/input.h"
#include "Qt/sdl.h"
#define MAX_JOYSTICKS 32
struct nesGamePadMap_t
{
char guid[64];
char name[128];
char btn[GAMEPAD_NUM_BUTTONS][32];
char os[64];
nesGamePadMap_t(void);
~nesGamePadMap_t(void);
void clearMapping(void);
int parseMapping( const char *text );
};
struct jsDev_t
{
SDL_Joystick *js;
SDL_GameController *gc;
jsDev_t(void);
//~jsDev_t(void);
void init( int idx );
int close(void);
SDL_Joystick *getJS(void);
bool isGameController(void);
bool isConnected(void);
void print(void);
int bindPort( int idx );
int unbindPort( int idx );
int getBindPorts(void);
const char *getName(void);
const char *getGUID(void);
private:
int devIdx;
int portBindMask;
std::string guidStr;
std::string name;
};
class GamePad_t
{
public:
ButtConfig bmap[GAMEPAD_NUM_BUTTONS];
GamePad_t(void);
~GamePad_t(void);
int init( int port, const char *guid, const char *profile = NULL );
const char *getGUID(void);
int loadDefaults(void);
int loadProfile( const char *name, const char *guid = NULL );
int getDeviceIndex(void){ return devIdx; }
int setDeviceIndex( int devIdx );
int setMapping( const char *map );
int setMapping( nesGamePadMap_t *map );
int createProfile( const char *name );
int getMapFromFile( const char *filename, char *out );
int getDefaultMap( char *out, const char *guid = NULL );
int saveMappingToFile( const char *filename, const char *txtMap );
int saveCurrentMapToFile( const char *filename );
int deleteMapping( const char *name );
private:
int devIdx;
int portNum;
};
extern GamePad_t GamePad[4];
jsDev_t *getJoystickDevice( int devNum );
#endif

View File

@ -195,11 +195,19 @@ WriteSound(int32 *buf,
extern int EmulationPaused;
if (EmulationPaused == 0)
{
int waitCount = 0;
while(Count)
{
while(s_BufferIn == s_BufferSize)
{
SDL_Delay(1);
SDL_Delay(1); waitCount++;
if ( waitCount > 1000 )
{
printf("Error: Sound sink is not draining... Breaking out of audio loop to prevent lockup.\n");
return;
}
}
s_Buffer[s_BufferWrite] = *buf;

View File

@ -51,6 +51,7 @@
// GLOBALS
extern Config *g_config;
extern bool force_grayscale;
// STATIC GLOBALS
static int s_curbpp = 0;
@ -206,24 +207,6 @@ int InitVideo(FCEUGI *gi)
return -1;
}
#ifdef OPENGL
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 ( !initBlitToHighDone )
{
InitBlitToHigh(s_curbpp >> 3,
@ -269,9 +252,21 @@ FCEUD_SetPalette(uint8 index,
uint8 g,
uint8 b)
{
s_psdl[index].r = r;
s_psdl[index].g = g;
s_psdl[index].b = b;
if ( force_grayscale )
{
// convert the palette entry to grayscale
int gray = ((float)r * 0.299 + (float)g * 0.587 + (float)b * 0.114);
s_psdl[index].r = gray;
s_psdl[index].g = gray;
s_psdl[index].b = gray;
}
else
{
s_psdl[index].r = r;
s_psdl[index].g = g;
s_psdl[index].b = b;
}
s_paletterefresh = 1;
}

View File

@ -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));
}

View File

@ -0,0 +1,87 @@
// os_util.cpp
#include <stdio.h>
#include <stdlib.h>
#if defined(WIN32)
#include <windows.h>
#else
#include <errno.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( filename, "r" );
if ( fp != NULL )
{
::fclose(fp);
return true;
}
#else
struct stat sb;
if ( stat( filepath, &sb ) == 0 )
{
return true;
}
#endif
return false;
}
//************************************************************

View File

@ -0,0 +1,9 @@
// os_utils.h
//
int fceu_mkdir( const char *path );
int fceu_mkpath( const char *path );
bool fceu_file_exists( const char *filepath );

View File

@ -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++;

View File

@ -0,0 +1,873 @@
// GamePadConf.cpp
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <gtk/gtk.h>
#include "sdl/GamePadConf.h"
#include "sdl/main.h"
#include "sdl/dface.h"
#include "sdl/input.h"
#include "sdl/config.h"
#include "sdl/keyscan.h"
#include "sdl/sdl-joystick.h"
#include "sdl/gui.h"
extern Config *g_config;
static GtkWidget *gamePadConfwin = NULL;
static GtkWidget *padNoCombo = NULL;
static GtkWidget *devSelCombo = NULL;
static GtkWidget *mapProfCombo = NULL;
static GtkWidget *buttonMappings[GAMEPAD_NUM_BUTTONS] = { NULL };
static GtkWidget *buttonState[GAMEPAD_NUM_BUTTONS] = { NULL };
static GtkWidget *guidLbl = NULL;
static GtkWidget *msgLbl = NULL;
static int buttonConfigStatus = 0;
static int padNo = 0;
static int numProfiles = 0;
struct GamePadConfigLocalData_t
{
std::string guid;
std::string profile;
struct {
char needsSave;
} btn[GAMEPAD_NUM_BUTTONS];
GamePadConfigLocalData_t(void)
{
for (int i=0; i<GAMEPAD_NUM_BUTTONS; i++)
{
btn[i].needsSave = 0;
}
}
};
static GamePadConfigLocalData_t lcl[GAMEPAD_NUM_DEVICES];
static int getDeviceIndex( void )
{
int devIdx = -1;
const char *s;
s = gtk_combo_box_text_get_active_text ( GTK_COMBO_BOX_TEXT(devSelCombo) );
if ( s && isdigit( s[0] ) )
{
devIdx = atoi( s );
}
return devIdx;
}
static void updateCntrlrDpy(void)
{
int i;
char strBuf[128];
if ( (padNoCombo == NULL) )
{
return;
}
for (i = 0; i < GAMEPAD_NUM_BUTTONS; i++)
{
GtkWidget *mappedKey = buttonMappings[i];
if (GamePad[padNo].bmap[i].ButtType == BUTTC_KEYBOARD)
{
snprintf (strBuf, sizeof (strBuf), "<tt>%s</tt>",
SDL_GetKeyName (GamePad[padNo].bmap[i].
ButtonNum));
}
else
sprintf (strBuf, "<tt>%s</tt>", ButtonName( &GamePad[padNo].bmap[i] ) );
if ( mappedKey != NULL )
{
gtk_label_set_text (GTK_LABEL (mappedKey), strBuf);
gtk_label_set_use_markup (GTK_LABEL (mappedKey), TRUE);
}
}
}
static void loadMapList(void)
{
const char *baseDir = FCEUI_GetBaseDirectory();
const char *guid;
std::string path;
std::string prefix, mapName;
int devIdx = -1;
jsDev_t *js;
size_t i,n=0;
char stmp[256];
struct dirent *d;
DIR *dir;
devIdx = getDeviceIndex();
if ( devIdx < 0 )
{
guid = "keyboard";
}
else
{
js = getJoystickDevice( devIdx );
guid = js->getGUID();
}
if ( guid == NULL )
{
return;
}
path = std::string(baseDir) + "/input/" + std::string(guid);
sprintf( stmp, "SDL.Input.GamePad.%i.", padNo );
prefix = stmp;
g_config->getOption(prefix + "Profile", &mapName );
gtk_combo_box_text_remove_all( GTK_COMBO_BOX_TEXT(mapProfCombo) );
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (mapProfCombo), "default");
gtk_combo_box_set_active (GTK_COMBO_BOX (mapProfCombo), 0);
numProfiles = n = 1;
dir = ::opendir( path.c_str() );
if ( dir == NULL ) return;
d = ::readdir( dir );
while ( d != NULL )
{
i=0;
while ( d->d_name[i] != 0 )
{
if ( d->d_name[i] == '.' )
{
break;
}
stmp[i] = d->d_name[i]; i++;
}
stmp[i] = 0;
//printf("Directory: '%s'\n", stmp );
if ( i > 0 )
{
if ( strcmp( stmp, "default" ) != 0 )
{
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (mapProfCombo), stmp);
if ( mapName.compare(stmp) == 0 )
{
gtk_combo_box_set_active (GTK_COMBO_BOX (mapProfCombo), n);
}
n++;
}
}
d = ::readdir( dir );
}
numProfiles = n;
::closedir( dir );
}
static void selPortChanged( GtkWidget * w, gpointer p )
{
const char *txt;
txt = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT (padNoCombo));
if ( txt == NULL )
{
return;
}
padNo = atoi(txt) - 1;
GtkTreeModel *treeModel = gtk_combo_box_get_model( GTK_COMBO_BOX (devSelCombo) );
GtkTreeIter iter;
gboolean iterValid;
iterValid = gtk_tree_model_get_iter_first( treeModel, &iter );
while ( iterValid )
{
GValue value;
memset( &value, 0, sizeof(value));
gtk_tree_model_get_value (treeModel, &iter, 0, &value );
if ( G_IS_VALUE(&value) )
{
if ( G_VALUE_TYPE(&value) == G_TYPE_STRING )
{
int devIdx = -1;
const char *s = (const char *)g_value_peek_pointer( &value );
if ( isdigit( s[0] ) )
{
devIdx = atoi(s);
}
if ( (devIdx >= 0) && (devIdx == GamePad[padNo].getDeviceIndex() ) )
{
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (devSelCombo), &iter);
}
}
}
g_value_unset(&value);
iterValid = gtk_tree_model_iter_next( treeModel, &iter );
}
gtk_label_set_text( GTK_LABEL(guidLbl), GamePad[padNo].getGUID() );
loadMapList();
updateCntrlrDpy();
}
static void selInputDevice (GtkWidget * w, gpointer p)
{
//std::string s = "SDL.Input.";
int devIdx = -1;
jsDev_t *js;
if ( (padNoCombo == NULL) )
{
return;
}
devIdx = getDeviceIndex();
js = getJoystickDevice( devIdx );
if ( js != NULL )
{
if ( js->isConnected() )
{
gtk_label_set_text( GTK_LABEL(guidLbl), js->getGUID() );
}
}
else
{
gtk_label_set_text( GTK_LABEL(guidLbl), "keyboard" );
}
GamePad[padNo].setDeviceIndex( devIdx );
lcl[padNo].guid.assign( GamePad[padNo].getGUID() );
lcl[padNo].profile.assign("default");
loadMapList();
updateCntrlrDpy();
return;
}
static void saveConfig(void)
{
int i;
char stmp[256];
const char *txt;
std::string prefix, mapName;
sprintf( stmp, "SDL.Input.GamePad.%i.", padNo );
prefix = stmp;
txt = gtk_combo_box_text_get_active_text( GTK_COMBO_BOX_TEXT(mapProfCombo) );
if ( txt == NULL )
{
return;
}
mapName.assign( txt );
g_config->setOption(prefix + "DeviceGUID", GamePad[padNo].getGUID() );
g_config->setOption(prefix + "Profile" , mapName.c_str() );
for (i=0; i<GAMEPAD_NUM_BUTTONS; i++)
{
lcl[padNo].btn[i].needsSave = 0;
}
g_config->save();
}
static void createNewProfile( const char *name )
{
char stmp[256];
//printf("Creating: %s \n", name );
GamePad[padNo].createProfile(name);
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (mapProfCombo), name);
numProfiles++;
gtk_combo_box_set_active( GTK_COMBO_BOX (mapProfCombo), numProfiles - 1 );
saveConfig();
sprintf( stmp, "Mapping Created: %s/%s \n", GamePad[padNo].getGUID(), name );
gtk_label_set_text( GTK_LABEL(msgLbl), stmp );
loadMapList();
}
static void loadProfileCB (GtkButton * button, gpointer p)
{
char stmp[256];
int devIdx, ret;
std::string mapName;
const char *txt;
devIdx = getDeviceIndex();
txt = gtk_combo_box_text_get_active_text( GTK_COMBO_BOX_TEXT(mapProfCombo) );
if ( txt == NULL )
{
return;
}
mapName.assign( txt );
GamePad[padNo].setDeviceIndex( devIdx );
if ( mapName.compare("default") == 0 )
{
ret = GamePad[padNo].loadDefaults();
}
else
{
ret = GamePad[padNo].loadProfile( mapName.c_str() );
}
if ( ret == 0 )
{
saveConfig();
sprintf( stmp, "Mapping Loaded: %s/%s \n", GamePad[padNo].getGUID(), mapName.c_str() );
}
else
{
sprintf( stmp, "Error: Failed to Load Mapping: %s/%s \n", GamePad[padNo].getGUID(), mapName.c_str() );
}
gtk_label_set_text( GTK_LABEL(msgLbl), stmp );
updateCntrlrDpy();
}
static void saveProfileCB (GtkButton * button, gpointer p)
{
int ret;
std::string mapName;
char stmp[256];
const char *txt;
txt = gtk_combo_box_text_get_active_text( GTK_COMBO_BOX_TEXT(mapProfCombo) );
if ( txt == NULL )
{
return;
}
mapName.assign( txt );
ret = GamePad[padNo].saveCurrentMapToFile( mapName.c_str() );
if ( ret == 0 )
{
saveConfig();
sprintf( stmp, "Mapping Saved: %s/%s \n", GamePad[padNo].getGUID(), mapName.c_str() );
}
else
{
sprintf( stmp, "Error: Failed to Save Mapping: %s \n", mapName.c_str() );
}
gtk_label_set_text( GTK_LABEL(msgLbl), stmp );
}
static void newProfileCB (GtkButton * button, gpointer p)
{
int ret;
GtkWidget *vbox, *lbl, *entry;
GtkWidget *dialog
= gtk_dialog_new_with_buttons ("New Profile", GTK_WINDOW(gamePadConfwin),
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
"_Cancel", GTK_RESPONSE_CANCEL, "_Create", GTK_RESPONSE_ACCEPT, NULL );
vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
gtk_box_set_homogeneous (GTK_BOX (vbox), FALSE);
lbl = gtk_label_new("Specify New Profile Name");
entry = gtk_entry_new();
gtk_box_pack_start (GTK_BOX (vbox), lbl, TRUE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 5);
gtk_widget_show_all( dialog );
ret = gtk_dialog_run( GTK_DIALOG(dialog) );
if ( ret == GTK_RESPONSE_ACCEPT )
{
printf("Text: '%s'\n", gtk_entry_get_text( GTK_ENTRY(entry) ) );
createNewProfile( gtk_entry_get_text( GTK_ENTRY(entry) ) );
}
gtk_widget_destroy( dialog );
}
static void deleteProfileCB (GtkButton * button, gpointer p)
{
int ret;
std::string mapName;
char stmp[256];
const char *txt;
txt = gtk_combo_box_text_get_active_text( GTK_COMBO_BOX_TEXT(mapProfCombo) );
if ( txt == NULL )
{
return;
}
mapName.assign( txt );
ret = GamePad[padNo].deleteMapping( mapName.c_str() );
if ( ret == 0 )
{
sprintf( stmp, "Mapping Deleted: %s/%s \n", GamePad[padNo].getGUID(), mapName.c_str() );
}
else
{
sprintf( stmp, "Error: Failed to Delete Mapping: %s \n", mapName.c_str() );
}
gtk_label_set_text( GTK_LABEL(msgLbl), stmp );
loadMapList();
}
// This function configures a single button on a gamepad
static void clearGamepadButton (GtkButton * button, gpointer p)
{
long int x = (long int)p;
GamePad[padNo].bmap[x].ButtonNum = -1;
gtk_label_set_text (GTK_LABEL (buttonMappings[x]), "");
lcl[padNo].btn[x].needsSave = 1;
updateCntrlrDpy();
}
// This function configures a single button on a gamepad
static void configGamepadButton (GtkButton * button, gpointer p)
{
gint x = ((gint) (glong) (p));
//gint x = GPOINTER_TO_INT(p);
char buf[256];
std::string prefix;
// only configure when the "Change" button is pressed in, not when it is unpressed
if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
return;
gtk_button_set_label (GTK_BUTTON (button), "Waiting");
buttonConfigStatus = 2;
ButtonConfigBegin ();
snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo);
prefix = buf;
DWaitButton (NULL, &GamePad[padNo].bmap[x], &buttonConfigStatus );
// g_config->setOption (prefix + GamePadNames[x],
// GamePadConfig[padNo][x].ButtonNum[configNo]);
//
// if (GamePadConfig[padNo][x].ButtType[0] == BUTTC_KEYBOARD)
// {
// g_config->setOption (prefix + "DeviceType", "Keyboard");
// }
// else if (GamePadConfig[padNo][x].ButtType[0] == BUTTC_JOYSTICK)
// {
// g_config->setOption (prefix + "DeviceType", "Joystick");
// }
// else
// {
// g_config->setOption (prefix + "DeviceType", "Unknown");
// }
// g_config->setOption (prefix + "DeviceNum",
// GamePadConfig[padNo][x].DeviceNum[configNo]);
snprintf (buf, sizeof (buf), "<tt>%s</tt>",
ButtonName (&GamePad[padNo].bmap[x]));
if ( buttonMappings[x] != NULL )
{
gtk_label_set_markup (GTK_LABEL (buttonMappings[x]), buf);
}
lcl[padNo].btn[x].needsSave = 1;
ButtonConfigEnd ();
buttonConfigStatus = 1;
gtk_button_set_label (GTK_BUTTON (button), "Change");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
return;
}
//static void updateGamepadConfig (GtkWidget * w, gpointer p)
//{
// updateCntrlrDpy();
//}
static gint timeout_callback (gpointer data)
{
if ( gamePadConfwin == NULL )
{
return FALSE;
}
for (int i=0; i<GAMEPAD_NUM_BUTTONS; i++)
{
const char *txt;
if ( GamePad[padNo].bmap[i].state )
{
txt = "<b><span background='green' foreground='white'> T </span></b>";
}
else
{
txt = "<b><span background='red' foreground='white'> F </span></b>";
}
gtk_label_set_markup( GTK_LABEL( buttonState[i] ), txt );
//if ( lcl[portNum].btn[i].needsSave )
//{
// keyName[i]->setStyleSheet("color: red;");
//}
//else
//{
// keyName[i]->setStyleSheet("color: black;");
//}
}
return TRUE;
}
static void closeGamepadConfig (GtkWidget * w, GdkEvent * e, gpointer p)
{
gtk_widget_destroy (w);
gamePadConfwin = NULL;
padNoCombo = NULL;
for (int i = 0; i < GAMEPAD_NUM_BUTTONS; i++)
{
buttonMappings[i] = NULL;
buttonState[i] = NULL;
}
buttonConfigStatus = 0;
}
void openGamepadConfig (void)
{
GtkWidget *win;
GtkWidget *mainVbox;
GtkWidget *hbox, /* *vbox,*/ *lbl;
GtkWidget *hboxPadNo;
GtkWidget *padNoLabel;
GtkWidget* devSelLabel, *devSelHbox;
GtkWidget *fourScoreChk;
GtkWidget *oppositeDirChk;
GtkWidget *buttonFrame;
GtkWidget *buttonTable;
GtkWidget *button;
GtkWidget *grid;
GtkWidget *mappingFrame;
char stmp[256];
if ( gamePadConfwin != NULL )
{
return;
}
// Ensure that joysticks are enabled, no harm calling init again.
InitJoysticks();
padNo = 0;
win = gtk_dialog_new_with_buttons ("Controller Configuration",
GTK_WINDOW (MainWindow),
(GtkDialogFlags)
(GTK_DIALOG_DESTROY_WITH_PARENT),
"_Close", GTK_RESPONSE_OK, NULL);
gtk_window_set_title (GTK_WINDOW (win), "Controller Configuration");
gtk_window_set_icon_name (GTK_WINDOW (win), "input-gaming");
gtk_widget_set_size_request (win, 350, 500);
mainVbox = gtk_dialog_get_content_area (GTK_DIALOG (win));
gtk_box_set_homogeneous (GTK_BOX (mainVbox), FALSE);
hboxPadNo = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_set_homogeneous( GTK_BOX(hboxPadNo), TRUE );
padNoLabel = gtk_label_new ("Port:");
//configNoLabel = gtk_label_new("Config Number:");
fourScoreChk = gtk_check_button_new_with_label ("Enable Four Score");
oppositeDirChk =
gtk_check_button_new_with_label ("Allow Up+Down / Left+Right");
//typeCombo = gtk_combo_box_text_new ();
//gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (typeCombo),
// "gamepad");
//gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (typeCombo),
// "zapper");
//gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (typeCombo),
// "powerpad.0");
//gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (typeCombo),
// "powerpad.1");
//gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (typeCombo),
// "arkanoid");
//gtk_combo_box_set_active (GTK_COMBO_BOX (typeCombo), 0);
padNoCombo = gtk_combo_box_text_new ();
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (padNoCombo), "1");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (padNoCombo), "2");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (padNoCombo), "3");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (padNoCombo), "4");
gtk_combo_box_set_active (GTK_COMBO_BOX (padNoCombo), 0);
g_signal_connect (padNoCombo, "changed",
G_CALLBACK (selPortChanged), NULL);
devSelHbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_set_homogeneous( GTK_BOX(devSelHbox), TRUE );
devSelLabel = gtk_label_new ("Device:");
devSelCombo = gtk_combo_box_text_new ();
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (devSelCombo), "Keyboard");
gtk_combo_box_set_active (GTK_COMBO_BOX (devSelCombo), 0);
for (int i=0; i<MAX_JOYSTICKS; i++)
{
jsDev_t *js = getJoystickDevice( i );
if ( js != NULL )
{
if ( js->isConnected() )
{
sprintf( stmp, "%i: %s", i, js->getName() );
gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT (devSelCombo), stmp );
}
}
}
gtk_combo_box_set_active (GTK_COMBO_BOX (devSelCombo), 0);
{
GtkTreeModel *treeModel = gtk_combo_box_get_model( GTK_COMBO_BOX (devSelCombo) );
GtkTreeIter iter;
gboolean iterValid;
iterValid = gtk_tree_model_get_iter_first( treeModel, &iter );
while ( iterValid )
{
GValue value;
memset( &value, 0, sizeof(value));
gtk_tree_model_get_value (treeModel, &iter, 0, &value );
if ( G_IS_VALUE(&value) )
{
if ( G_VALUE_TYPE(&value) == G_TYPE_STRING )
{
int devIdx = -1;
const char *s = (const char *)g_value_peek_pointer( &value );
if ( isdigit( s[0] ) )
{
devIdx = atoi(s);
}
if ( (devIdx >= 0) && (devIdx == GamePad[padNo].getDeviceIndex() ) )
{
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (devSelCombo), &iter);
}
}
}
g_value_unset(&value);
iterValid = gtk_tree_model_iter_next( treeModel, &iter );
}
}
g_signal_connect (devSelCombo, "changed", G_CALLBACK (selInputDevice), NULL );
//g_signal_connect (typeCombo, "changed", G_CALLBACK (setInputDevice),
// gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT
// (typeCombo)));
setCheckbox (fourScoreChk, "SDL.FourScore");
g_signal_connect (fourScoreChk, "clicked", G_CALLBACK (toggleOption),
(gpointer) "SDL.FourScore");
setCheckbox (oppositeDirChk, "SDL.Input.EnableOppositeDirectionals");
g_signal_connect (oppositeDirChk, "clicked", G_CALLBACK (toggleOption),
(gpointer) "SDL.Input.EnableOppositeDirectionals");
gtk_box_pack_start (GTK_BOX (hboxPadNo), padNoLabel, TRUE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (hboxPadNo), padNoCombo, TRUE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (mainVbox), hboxPadNo, FALSE, TRUE, 5);
//gtk_box_pack_start_defaults(GTK_BOX(mainVbox), typeCombo);
gtk_box_pack_start (GTK_BOX (devSelHbox), devSelLabel, TRUE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (devSelHbox), devSelCombo, TRUE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (mainVbox), devSelHbox, TRUE, TRUE, 5);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_set_homogeneous( GTK_BOX(hbox), TRUE );
lbl = gtk_label_new ("GUID:");
guidLbl = gtk_label_new ("");
gtk_box_pack_start (GTK_BOX (hbox), lbl, TRUE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (hbox), guidLbl, TRUE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (mainVbox), hbox, TRUE, TRUE, 5);
gtk_label_set_text( GTK_LABEL(guidLbl), GamePad[padNo].getGUID() );
mappingFrame = gtk_frame_new ("<b><i>Mapping Profile:</i></b>");
gtk_label_set_use_markup (GTK_LABEL
(gtk_frame_get_label_widget
(GTK_FRAME (mappingFrame))), TRUE);
gtk_box_pack_start (GTK_BOX (mainVbox), mappingFrame, FALSE, TRUE, 5);
grid = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (grid), 5);
gtk_grid_set_column_spacing (GTK_GRID (grid), 5);
gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE);
//vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (mappingFrame), grid);
mapProfCombo = gtk_combo_box_text_new ();
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (mapProfCombo), "default");
gtk_combo_box_set_active (GTK_COMBO_BOX (mapProfCombo), 0);
gtk_grid_attach (GTK_GRID (grid), mapProfCombo, 0, 0, 2, 1 );
button = gtk_button_new_with_label ("Load");
gtk_grid_attach (GTK_GRID (grid), button, 0, 1, 1, 1 );
g_signal_connect (button, "clicked", G_CALLBACK (loadProfileCB), NULL );
button = gtk_button_new_with_label ("Save");
gtk_grid_attach (GTK_GRID (grid), button, 1, 1, 1, 1 );
g_signal_connect (button, "clicked", G_CALLBACK (saveProfileCB), NULL );
button = gtk_button_new_with_label ("New");
gtk_grid_attach (GTK_GRID (grid), button, 0, 2, 1, 1 );
g_signal_connect (button, "clicked", G_CALLBACK (newProfileCB), NULL );
button = gtk_button_new_with_label ("Delete");
gtk_grid_attach (GTK_GRID (grid), button, 1, 2, 1, 1 );
g_signal_connect (button, "clicked", G_CALLBACK (deleteProfileCB), NULL );
msgLbl = gtk_label_new("");
gtk_grid_attach (GTK_GRID (grid), msgLbl, 0, 3, 2, 1 );
gtk_box_pack_start (GTK_BOX (mainVbox), fourScoreChk, FALSE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (mainVbox), oppositeDirChk, FALSE, TRUE, 5);
// create gamepad buttons
buttonFrame = gtk_frame_new ("<b><i>Active Button Mappings:</i></b>");
gtk_label_set_use_markup (GTK_LABEL
(gtk_frame_get_label_widget
(GTK_FRAME (buttonFrame))), TRUE);
buttonTable = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (buttonFrame), buttonTable);
for (int i = 0; i < 3; i++)
{
gtk_grid_insert_column (GTK_GRID (buttonTable), i);
}
gtk_grid_set_column_spacing (GTK_GRID (buttonTable), 5);
gtk_grid_set_column_homogeneous (GTK_GRID (buttonTable), TRUE);
gtk_grid_set_row_spacing (GTK_GRID (buttonTable), 3);
for (int i = 0; i < GAMEPAD_NUM_BUTTONS; i++)
{
GtkWidget *buttonName = gtk_label_new (GamePadNames[i]);
GtkWidget *mappedKey = gtk_label_new (NULL);
GtkWidget *changeButton = gtk_toggle_button_new ();
GtkWidget *clearButton = gtk_button_new ();
char strBuf[128];
lbl = gtk_label_new ("State:");
buttonState[i] = gtk_label_new (" F ");
gtk_grid_insert_row (GTK_GRID (buttonTable), i);
sprintf (strBuf, "%s:", GamePadNames[i]);
gtk_label_set_text (GTK_LABEL (buttonName), strBuf);
gtk_button_set_label (GTK_BUTTON (changeButton), "Change");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (changeButton),
FALSE);
gtk_button_set_label (GTK_BUTTON (clearButton), "Clear");
gtk_grid_attach (GTK_GRID (buttonTable), buttonName, 0, i, 1, 1);
gtk_grid_attach (GTK_GRID (buttonTable), mappedKey, 1, i, 1, 1);
gtk_grid_attach (GTK_GRID (buttonTable), lbl, 2, i, 1, 1);
gtk_grid_attach (GTK_GRID (buttonTable), buttonState[i], 3, i, 1, 1);
gtk_grid_attach (GTK_GRID (buttonTable), changeButton, 4, i, 1, 1);
gtk_grid_attach (GTK_GRID (buttonTable), clearButton, 5, i, 1, 1);
g_signal_connect (changeButton, "clicked",
G_CALLBACK (configGamepadButton),
GINT_TO_POINTER (i));
g_signal_connect (clearButton, "clicked",
G_CALLBACK (clearGamepadButton),
GINT_TO_POINTER (i));
buttonMappings[i] = mappedKey;
}
gtk_box_pack_start (GTK_BOX (mainVbox), buttonFrame, TRUE, TRUE, 5);
g_signal_connect (win, "delete-event", G_CALLBACK (closeGamepadConfig), NULL);
g_signal_connect (win, "response", G_CALLBACK (closeGamepadConfig), NULL);
gtk_widget_show_all (win);
g_signal_connect (G_OBJECT (win), "key-press-event",
G_CALLBACK (convertKeypress), NULL);
g_signal_connect (G_OBJECT (win), "key-release-event",
G_CALLBACK (convertKeypress), NULL);
buttonConfigStatus = 1;
gamePadConfwin = win;
loadMapList();
// display the button mappings for the currently selected configuration
updateCntrlrDpy();
g_timeout_add ( 100, timeout_callback, NULL );
return;
}

View File

@ -0,0 +1,4 @@
// GamePadConf.h
// creates and opens the gamepad config window (GTK)
void openGamepadConfig (void);

View File

@ -102,20 +102,20 @@ LoadCPalette(const std::string &file)
static void
CreateDirs(const std::string &dir)
{
const char *subs[8]={"fcs","snaps","gameinfo","sav","cheats","movies","cfg.d"};
const char *subs[9]={"fcs","snaps","gameinfo","sav","cheats","movies","input"};
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++) {
for(x = 0; x < 7; x++) {
subdir = dir + PSS + subs[x];
mkdir(subdir.c_str());
}
#else
mkdir(dir.c_str(), S_IRWXU);
for(x = 0; x < 6; x++) {
for(x = 0; x < 7; x++) {
subdir = dir + PSS + subs[x];
mkdir(subdir.c_str(), S_IRWXU);
}
@ -199,6 +199,7 @@ InitConfig()
// video controls
config->addOption('f', "fullscreen", "SDL.Fullscreen", 0);
config->addOption("videoDriver", "SDL.VideoDriver", 0);
// set x/y res to 0 for automatic fullscreen resolution detection (no change)
config->addOption('x', "xres", "SDL.XResolution", 0);
@ -241,7 +242,7 @@ InitConfig()
config->addOption("input4", "SDL.Input.3", "Gamepad.3");
// allow for input configuration
config->addOption('i', "inputcfg", "SDL.InputCfg", InputCfg);
//config->addOption('i', "inputcfg", "SDL.InputCfg", InputCfg);
// display input
config->addOption("inputdisplay", "SDL.InputDisplay", 0);
@ -285,8 +286,6 @@ InitConfig()
//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);
@ -294,7 +293,9 @@ InitConfig()
config->addOption("_lastopennsf", "SDL.LastOpenNSF", home_dir);
config->addOption("_lastsavestateas", "SDL.LastSaveStateAs", home_dir);
config->addOption("_lastloadlua", "SDL.LastLoadLua", "");
#endif
config->addOption("_useNativeFileDialog", "SDL.UseNativeFileDialog", false);
config->addOption("_useNativeMenuBar" , "SDL.UseNativeMenuBar", false);
// fcm -> fm2 conversion
config->addOption("fcmconvert", "SDL.FCMConvert", "");
@ -316,10 +317,8 @@ InitConfig()
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]);
}
config->addOption(prefix + "DeviceGUID", "");
config->addOption(prefix + "Profile" , "");
}
// PowerPad 0 - 1

View File

@ -1709,6 +1709,21 @@ void FCEUD_DebugBreakpoint(int bp_num)
}
}
void FCEUD_TraceInstruction(uint8 *opcode, int size)
{
// Place holder to allow for compiling. GTK GUI doesn't support this. Qt Does.
}
void FCEUD_UpdatePPUView(int scanline, int refreshchr)
{
// Place holder to allow for compiling. GTK GUI doesn't support this. Qt Does.
}
void FCEUD_UpdateNTView(int scanline, bool drawall)
{
// Place holder to allow for compiling. GTK GUI doesn't support this. Qt Does.
}
static void closeDebuggerWindow (GtkWidget * w, GdkEvent * e, debuggerWin_t * dw)
{
std::list < debuggerWin_t * >::iterator it;

View File

@ -18,6 +18,8 @@ void SilenceSound(int s); /* DOS and SDL */
int InitJoysticks(void);
int KillJoysticks(void);
int AddJoystick( int which );
int RemoveJoystick( int which );
uint32 *GetJSOr(void);
int InitVideo(FCEUGI *gi);

View File

@ -0,0 +1,4 @@
// fceux_git_info.h
const char *fceu_get_git_url(void);
const char *fceu_get_git_rev(void);

View File

@ -33,6 +33,7 @@ static GLXContext glc = NULL;
static XWindowAttributes gwa;
static XEvent xev;
static GLint double_buffer_ena = 1;
static bool isDoubleBuffered = true;
static GLuint gltexture = 0;
static int spawn_new_window = 0;
@ -89,8 +90,14 @@ static void getAttrbList( GLint *buf )
int i=0;
buf[i] = GLX_RGBA; i++;
buf[i] = GLX_DEPTH_SIZE; i++;
buf[i] = 24; i++;
//buf[i] = GLX_DEPTH_SIZE; i++;
//buf[i] = 24; i++;
buf[i] = GLX_RED_SIZE; i++;
buf[i] = 8; i++;
buf[i] = GLX_GREEN_SIZE; i++;
buf[i] = 8; i++;
buf[i] = GLX_BLUE_SIZE; i++;
buf[i] = 8; i++;
if ( double_buffer_ena )
{
@ -258,7 +265,7 @@ static void render_image(void)
//print_pixbuf();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0,
GL_RGBA, GL_UNSIGNED_BYTE, glx_shm->pixbuf );
GL_BGRA, GL_UNSIGNED_BYTE, glx_shm->pixbuf );
glBegin(GL_QUADS);
glTexCoord2f(1.0f*l/256, 1.0f*b/256); // Bottom left of picture.
@ -283,7 +290,7 @@ static void render_image(void)
//glVertex2f( 1.0f, 1.0f); // Top right of target.
//glEnd();
if ( double_buffer_ena )
if ( isDoubleBuffered )
{
glXSwapBuffers( dpy, win );
}
@ -392,6 +399,7 @@ int spawn_glxwin( int flags )
//************************************************************************
int init_gtk3_GLXContext( int flags )
{
int screenNumber;
GLint att[32];
XWindowAttributes xattrb;
@ -410,12 +418,20 @@ int init_gtk3_GLXContext( int flags )
printf("Error: Failed to obtain gdkWindow Handle for evbox widget\n");
return -1;
}
if (!GDK_IS_X11_WINDOW (gdkWin))
{
printf("Error: GDK Window is not of X11 Type\n");
return -1;
}
GdkDisplay *gdk_display = gdk_window_get_display (gdkWin);
GdkScreen *gdk_screen = gdk_window_get_screen (gdkWin);
screenNumber = gdk_x11_screen_get_screen_number (gdk_screen);
dpy = GDK_DISPLAY_XDISPLAY( gdk_display );
win = GDK_WINDOW_XID( gdkWin );
root = GDK_ROOT_WINDOW();
dpy = gdk_x11_get_default_xdisplay();
if ( dpy == NULL )
{
printf("Error: Failed to obtain X Display Handle for evbox widget\n");
@ -431,16 +447,65 @@ int init_gtk3_GLXContext( int flags )
//printf("XWinSize: (%i x %i) \n", xattrb.width, xattrb.height );
//printf("XWinDepth: %i \n", xattrb.depth );
//printf("XWinVisual: %p \n", xattrb.visual );
printf("XScreenNumber: %i \n", screenNumber );
vi = glXChooseVisual(dpy, 0, att);
vi = glXChooseVisual(dpy, screenNumber, att);
if (vi == NULL)
{
printf("\n\tno appropriate visual found\n\n");
printf("\n\tERROR: GLX No appropriate visual found\n\n");
exit(0);
}
else {
printf("\n\tvisual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */
else
{
int val;
printf("\n\tGLX visual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */
if ( glXGetConfig( dpy, vi, GLX_RGBA, &val ) == 0 )
{
printf("GLX_RGBA: %i \n", val );
}
if ( glXGetConfig( dpy, vi, GLX_USE_GL, &val ) == 0 )
{
printf("GLX_USE_GL: %i \n", val );
}
if ( glXGetConfig( dpy, vi, GLX_LEVEL, &val ) == 0 )
{
printf("GLX_LEVEL: %i \n", val );
}
if ( glXGetConfig( dpy, vi, GLX_BUFFER_SIZE, &val ) == 0 )
{
printf("GLX_BUFFER_SIZE: %i \n", val );
}
if ( glXGetConfig( dpy, vi, GLX_DOUBLEBUFFER, &val ) == 0 )
{
isDoubleBuffered = val ? true : false;
printf("GLX_DOUBLEBUFFER: %i \n", val );
}
if ( glXGetConfig( dpy, vi, GLX_RED_SIZE, &val ) == 0 )
{
printf("GLX_RED_SIZE: %i \n", val );
}
if ( glXGetConfig( dpy, vi, GLX_GREEN_SIZE, &val ) == 0 )
{
printf("GLX_GREEN_SIZE: %i \n", val );
}
if ( glXGetConfig( dpy, vi, GLX_BLUE_SIZE, &val ) == 0 )
{
printf("GLX_BLUE_SIZE: %i \n", val );
}
if ( glXGetConfig( dpy, vi, GLX_ALPHA_SIZE, &val ) == 0 )
{
printf("GLX_ALPHA_SIZE: %i \n", val );
}
if ( glXGetConfig( dpy, vi, GLX_DEPTH_SIZE, &val ) == 0 )
{
printf("GLX_DEPTH_SIZE: %i \n", val );
}
if ( glXGetConfig( dpy, vi, GLX_STENCIL_SIZE, &val ) == 0 )
{
printf("GLX_STENCIL_SIZE: %i \n", val );
}
}
if ( glc == NULL )
@ -449,11 +514,20 @@ int init_gtk3_GLXContext( int flags )
if ( glc == NULL )
{
printf("Error: glXCreateContext Failed\n");
printf("ERROR: glXCreateContext Failed\n");
}
else
{
printf("glXIsDirect: %i \n", glXIsDirect( dpy, glc ) );
}
}
XFree(vi); vi = NULL;
if ( glc == NULL )
{
return -1;
}
glXMakeCurrent(dpy, win, glc);
genTextures( flags & GLXWIN_PIXEL_LINEAR_FILTER ? 1 : 0 );

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,10 @@ void pushOutputToGTK(const char* str);
void showGui(bool b);
void toggleMenuVis(void);
gint convertKeypress (GtkWidget * grab, GdkEventKey * event, gpointer user_data);
void toggleOption (GtkWidget * w, gpointer p);
void setCheckbox (GtkWidget * w, const char *configName);
bool checkGTKVersion(int major_required, int minor_required);
int configHotkey(char* hotkeyString);
@ -50,16 +54,10 @@ void openGamepadConfig();
void resizeGtkWindow();
#ifdef OPENGL
void setGl(GtkWidget* w, gpointer p);
void setDoubleBuffering(GtkWidget* w, gpointer p);
#endif
void setStateMenuItem( int i );
void openVideoConfig();
void openSoundConfig();
void quit ();
void openAbout ();
void emuReset ();
@ -90,7 +88,16 @@ int InitGTKSubsystem(int argc, char** argv);
uint32_t *getGuiPixelBuffer( int *w, int *h, int *s );
int guiPixelBufferReDraw(void);
int init_gui_video( int use_openGL );
enum videoDriver_t
{
VIDEO_NONE = -1,
VIDEO_OPENGL_GLX,
VIDEO_SDL,
VIDEO_CAIRO
};
extern enum videoDriver_t videoDriver;
int init_gui_video( videoDriver_t vd );
int destroy_gui_video( void );
void init_cairo_screen(void);
void destroy_cairo_screen(void);

View File

@ -24,8 +24,9 @@
#include "config.h"
#include "sdl-video.h"
#include "sdl.h"
#include "sdl-video.h"
#include "sdl-joystick.h"
#include "../common/cheat.h"
#include "../../movie.h"
@ -57,9 +58,10 @@ extern bool bindSavestate, frameAdvanceLagSkip, lagCounterDisplay;
/* UsrInputType[] is user-specified. CurInputType[] is current
(game loading can override user settings)
*/
static int UsrInputType[NUM_INPUT_DEVICES];
static int CurInputType[NUM_INPUT_DEVICES];
static int UsrInputType[NUM_INPUT_DEVICES] = { SI_GAMEPAD, SI_GAMEPAD, SI_NONE };
static int CurInputType[NUM_INPUT_DEVICES] = { SI_GAMEPAD, SI_GAMEPAD, SI_NONE };
static int cspec = 0;
static int buttonConfigInProgress = 0;
extern int gametype;
@ -618,10 +620,10 @@ static void KeyboardCommands (void)
if (_keyonly (Hotkeys[HK_DECREASE_SPEED]))
{
DecreaseEmulationSpeed ();
DecreaseEmulationSpeed();
}
if (_keyonly (Hotkeys[HK_INCREASE_SPEED]))
if (_keyonly(Hotkeys[HK_INCREASE_SPEED]))
{
IncreaseEmulationSpeed ();
}
@ -693,17 +695,10 @@ static void KeyboardCommands (void)
//}
if (_keyonly (Hotkeys[HK_QUIT]))
{
if (noGui == 1)
{
CloseGame ();
}
else
{
CloseGame();
FCEUI_Kill();
SDL_Quit();
exit(0);
}
CloseGame();
FCEUI_Kill();
SDL_Quit();
exit(0);
}
else
#ifdef _S9XLUA_H
@ -957,6 +952,8 @@ UpdatePhysicalInput ()
{
SDL_Event event;
//SDL_JoystickUpdate();
// loop, handling all pending events
while (SDL_PollEvent (&event))
{
@ -985,6 +982,12 @@ UpdatePhysicalInput ()
g_keyState[ event.key.keysym.scancode ] = (event.type == SDL_KEYDOWN) ? 1 : 0;
//checkKeyBoardState( event.key.keysym.scancode );
break;
case SDL_JOYDEVICEADDED:
AddJoystick( event.jdevice.which );
break;
case SDL_JOYDEVICEREMOVED:
RemoveJoystick( event.jdevice.which );
break;
default:
break;
}
@ -993,8 +996,6 @@ UpdatePhysicalInput ()
}
static int bcpv, bcpj;
/**
* Begin configuring the buttons by placing the video and joystick
* subsystems into a well-known state. Button configuration really
@ -1002,31 +1003,11 @@ static int bcpv, bcpj;
*/
int ButtonConfigBegin ()
{
//dont shut down video subsystem if we are using gtk to prevent the sdl window from becoming detached to GTK window
// prg318 - 10-2-2011
#ifdef _GTK
int noGui;
g_config->getOption ("SDL.NoGUI", &noGui);
if (noGui == 1)
{
//SDL_QuitSubSystem (SDL_INIT_VIDEO);
bcpv = KillVideo ();
}
#else
// XXX soules - why are we doing this right before KillVideo()?
//SDL_QuitSubSystem (SDL_INIT_VIDEO);
// shut down the video and joystick subsystems
bcpv = KillVideo ();
#endif
//SDL_Surface *screen;
bcpj = KillJoysticks ();
// XXX soules - why did we shut this down?
// initialize the joystick subsystem
// initialize the joystick subsystem (if not already inited)
InitJoysticks ();
buttonConfigInProgress = 1;
return 1;
}
@ -1038,18 +1019,7 @@ int ButtonConfigBegin ()
void
ButtonConfigEnd ()
{
// shutdown the joystick and video subsystems
KillJoysticks ();
//SDL_QuitSubSystem(SDL_INIT_VIDEO);
// re-initialize joystick and video subsystems if they were active before
/*if(!bcpv) {
InitVideo(GameInfo);
} */
if (!bcpj)
{
InitJoysticks ();
}
buttonConfigInProgress = 0;
}
/**
@ -1058,48 +1028,50 @@ ButtonConfigEnd ()
static int
DTestButton (ButtConfig * bc)
{
int x;
for (x = 0; x < bc->NumC; x++)
if (bc->ButtType == BUTTC_KEYBOARD)
{
if (bc->ButtType[x] == BUTTC_KEYBOARD)
if (g_keyState[SDL_GetScancodeFromKey (bc->ButtonNum)])
{
if (g_keyState[SDL_GetScancodeFromKey (bc->ButtonNum[x])])
{
return 1;
}
bc->state = 1;
return 1;
}
else if (bc->ButtType[x] == BUTTC_JOYSTICK)
else
{
bc->state = 0;
}
}
else if (bc->ButtType == BUTTC_JOYSTICK)
{
if (DTestButtonJoy (bc))
{
if (DTestButtonJoy (bc))
{
return 1;
}
return 1;
}
}
return 0;
}
#define MK(x) {{BUTTC_KEYBOARD},{0},{MKK(x)},1}
#define MK2(x1,x2) {{BUTTC_KEYBOARD},{0},{MKK(x1),MKK(x2)},2}
#define MKZ() {{0},{0},{0},0}
#define MK(x) {BUTTC_KEYBOARD,0,MKK(x),0}
//#define MK2(x1,x2) {BUTTC_KEYBOARD,0,MKK(x1)}
#define MKZ() {0,0,-1,0}
#define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()}
ButtConfig GamePadConfig[4][10] = {
/* Gamepad 1 */
{MK (KP_3), MK (KP_2), MK (SLASH), MK (ENTER),
MK (W), MK (Z), MK (A), MK (S), MKZ (), MKZ ()},
/* Gamepad 2 */
GPZ (),
/* Gamepad 3 */
GPZ (),
/* Gamepad 4 */
GPZ ()
};
//ButtConfig GamePadConfig[ GAMEPAD_NUM_DEVICES ][ GAMEPAD_NUM_BUTTONS ] =
//{
///* Gamepad 1 */
// {MK (KP_3), MK (KP_2), MK (SLASH), MK (ENTER),
// MK (w), MK (z), MK (a), MK (s), MKZ (), MKZ ()},
//
// /* Gamepad 2 */
// GPZ (),
//
// /* Gamepad 3 */
// GPZ (),
//
// /* Gamepad 4 */
// GPZ ()
//};
/**
* Update the status of the gamepad input devices.
@ -1131,7 +1103,7 @@ UpdateGamepad(void)
// a, b, select, start, up, down, left, right
for (x = 0; x < 8; x++)
{
if (DTestButton (&GamePadConfig[wg][x]))
if (DTestButton (&GamePad[wg].bmap[x]))
{
//printf("GamePad%i Button Hit: %i \n", wg, x );
if(opposite_dirs == 0)
@ -1169,7 +1141,7 @@ UpdateGamepad(void)
{
for (x = 0; x < 2; x++)
{
if (DTestButton (&GamePadConfig[wg][8 + x]))
if (DTestButton (&GamePad[wg].bmap[8 + x]))
{
JS |= (1 << x) << (wg << 3);
}
@ -1238,11 +1210,15 @@ static uint8 fkbkeys[0x48];
/**
* Update all of the input devices required for the active game.
*/
void FCEUD_UpdateInput ()
void FCEUD_UpdateInput(void)
{
int x;
int t = 0;
if ( buttonConfigInProgress )
{
return;
}
UpdatePhysicalInput ();
KeyboardCommands ();
@ -1356,8 +1332,8 @@ void InitInputInterface ()
{
void *InputDPtr;
int t;
int x;
int t = 0;
int x = 0;
int attrib;
memset( g_keyState, 0, sizeof(g_keyState) );
@ -1600,36 +1576,42 @@ UpdateFTrainer ()
* @param bc the NES gamepad's button config
* @param which the index of the button
*/
const char * ButtonName (const ButtConfig * bc, int which)
const char * ButtonName (const ButtConfig * bc)
{
static char name[256];
switch (bc->ButtType[which])
name[0] = 0;
if (bc->ButtonNum == -1)
{
return name;
}
switch (bc->ButtType)
{
case BUTTC_KEYBOARD:
return SDL_GetKeyName (bc->ButtonNum[which]);
return SDL_GetKeyName (bc->ButtonNum);
break;
case BUTTC_JOYSTICK:
{
int joyNum, inputNum;
const char *inputType, *inputDirection;
joyNum = bc->DeviceNum[which];
joyNum = bc->DeviceNum;
if (bc->ButtonNum[which] & 0x8000)
if (bc->ButtonNum & 0x8000)
{
inputType = "Axis";
inputNum = bc->ButtonNum[which] & 0x3FFF;
inputDirection = bc->ButtonNum[which] & 0x4000 ? "-" : "+";
inputNum = bc->ButtonNum & 0x3FFF;
inputDirection = bc->ButtonNum & 0x4000 ? "-" : "+";
}
else if (bc->ButtonNum[which] & 0x2000)
else if (bc->ButtonNum & 0x2000)
{
int inputValue;
char direction[128] = "";
inputType = "Hat";
inputNum = (bc->ButtonNum[which] >> 8) & 0x1F;
inputValue = bc->ButtonNum[which] & 0xF;
inputNum = (bc->ButtonNum >> 8) & 0x1F;
inputValue = bc->ButtonNum & 0xF;
if (inputValue & SDL_HAT_UP)
strncat (direction, "Up ", sizeof (direction)-1);
@ -1648,7 +1630,7 @@ const char * ButtonName (const ButtConfig * bc, int which)
else
{
inputType = "Button";
inputNum = bc->ButtonNum[which];
inputNum = bc->ButtonNum;
inputDirection = "";
}
sprintf( name, "js%i:%s%i%s", joyNum, inputType, inputNum, inputDirection );
@ -1663,11 +1645,12 @@ const char * ButtonName (const ButtConfig * bc, int which)
* Waits for a button input and returns the information as to which
* button was pressed. Used in button configuration.
*/
int DWaitButton (const uint8 * text, ButtConfig * bc, int wb, int *buttonConfigStatus )
int DWaitButton (const uint8_t * text, ButtConfig * bc, int *buttonConfigStatus )
{
SDL_Event event;
static int32 LastAx[64][64];
int x, y;
int timeout_ms = 10000;
if (text)
{
@ -1686,36 +1669,53 @@ int DWaitButton (const uint8 * text, ButtConfig * bc, int wb, int *buttonConfigS
}
}
// Purge all pending events, so that this next button press
// will be the one we want.
while (SDL_PollEvent (&event))
{
}
while (1)
{
int done = 0;
usleep(10000);
timeout_ms -= 10;
if ( timeout_ms <= 0 )
{
break;
}
#ifdef _GTK
while (gtk_events_pending ())
gtk_main_iteration_do (FALSE);
#endif
while (SDL_PollEvent (&event))
{
printf("Event Type: %i \n", event.type );
done++;
switch (event.type)
{
case SDL_KEYDOWN:
bc->ButtType[wb] = BUTTC_KEYBOARD;
bc->DeviceNum[wb] = 0;
bc->ButtonNum[wb] = event.key.keysym.sym;
//printf("SDL KeyDown:%i \n", event.key.keysym.sym );
bc->ButtType = BUTTC_KEYBOARD;
bc->DeviceNum = 0;
bc->ButtonNum = event.key.keysym.sym;
return (1);
case SDL_JOYBUTTONDOWN:
bc->ButtType[wb] = BUTTC_JOYSTICK;
bc->DeviceNum[wb] = event.jbutton.which;
bc->ButtonNum[wb] = event.jbutton.button;
bc->ButtType = BUTTC_JOYSTICK;
bc->DeviceNum = event.jbutton.which;
bc->ButtonNum = event.jbutton.button;
return (1);
case SDL_JOYHATMOTION:
if (event.jhat.value == SDL_HAT_CENTERED)
done--;
else
{
bc->ButtType[wb] = BUTTC_JOYSTICK;
bc->DeviceNum[wb] = event.jhat.which;
bc->ButtonNum[wb] =
bc->ButtType = BUTTC_JOYSTICK;
bc->DeviceNum = event.jhat.which;
bc->ButtonNum =
(0x2000 | ((event.jhat.hat & 0x1F) << 8) | event.
jhat.value);
return (1);
@ -1737,9 +1737,9 @@ int DWaitButton (const uint8 * text, ButtConfig * bc, int wb, int *buttonConfigS
(LastAx[event.jaxis.which][event.jaxis.axis] -
event.jaxis.value) >= 8192)
{
bc->ButtType[wb] = BUTTC_JOYSTICK;
bc->DeviceNum[wb] = event.jaxis.which;
bc->ButtonNum[wb] = (0x8000 | event.jaxis.axis |
bc->ButtType = BUTTC_JOYSTICK;
bc->DeviceNum = event.jaxis.which;
bc->ButtonNum = (0x8000 | event.jaxis.axis |
((event.jaxis.value < 0)
? 0x4000 : 0));
return (1);
@ -1776,213 +1776,206 @@ int DWaitButton (const uint8 * text, ButtConfig * bc, int wb, int *buttonConfigS
* used as input for the specified button, thus allowing up to four
* possible settings for each input button.
*/
void
ConfigButton (char *text, ButtConfig * bc)
{
uint8 buf[256];
int wc;
for (wc = 0; wc < MAXBUTTCONFIG; wc++)
{
sprintf ((char *) buf, "%s (%d)", text, wc + 1);
DWaitButton (buf, bc, wc, NULL);
if (wc &&
bc->ButtType[wc] == bc->ButtType[wc - 1] &&
bc->DeviceNum[wc] == bc->DeviceNum[wc - 1] &&
bc->ButtonNum[wc] == bc->ButtonNum[wc - 1])
{
break;
}
}
bc->NumC = wc;
}
// void
//ConfigButton (char *text, ButtConfig * bc)
//{
// uint8 buf[256];
// int wc;
//
// for (wc = 0; wc < MAXBUTTCONFIG; wc++)
// {
// sprintf ((char *) buf, "%s (%d)", text, wc + 1);
// DWaitButton (buf, bc, wc, NULL);
//
// if (wc &&
// bc->ButtType[wc] == bc->ButtType[wc - 1] &&
// bc->DeviceNum[wc] == bc->DeviceNum[wc - 1] &&
// bc->ButtonNum[wc] == bc->ButtonNum[wc - 1])
// {
// break;
// }
// }
//}
/**
* Update the button configuration for a specified device.
*/
extern Config *g_config;
void ConfigDevice (int which, int arg)
{
char buf[256];
int x;
std::string prefix;
const char *str[10] =
{ "A", "B", "SELECT", "START", "UP", "DOWN", "LEFT", "RIGHT", "Rapid A",
"Rapid B"
};
// XXX soules - set the configuration options so that later calls
// don't override these. This is a temp hack until I
// can clean up this file.
ButtonConfigBegin ();
switch (which)
{
case FCFGD_QUIZKING:
prefix = "SDL.Input.QuizKing.";
for (x = 0; x < 6; x++)
{
sprintf (buf, "Quiz King Buzzer #%d", x + 1);
ConfigButton (buf, &QuizKingButtons[x]);
g_config->setOption (prefix + QuizKingNames[x],
QuizKingButtons[x].ButtonNum[0]);
}
if (QuizKingButtons[0].ButtType[0] == BUTTC_KEYBOARD)
{
g_config->setOption (prefix + "DeviceType", "Keyboard");
}
else if (QuizKingButtons[0].ButtType[0] == BUTTC_JOYSTICK)
{
g_config->setOption (prefix + "DeviceType", "Joystick");
}
else
{
g_config->setOption (prefix + "DeviceType", "Unknown");
}
g_config->setOption (prefix + "DeviceNum",
QuizKingButtons[0].DeviceNum[0]);
break;
case FCFGD_HYPERSHOT:
prefix = "SDL.Input.HyperShot.";
for (x = 0; x < 4; x++)
{
sprintf (buf, "Hyper Shot %d: %s",
((x & 2) >> 1) + 1, (x & 1) ? "JUMP" : "RUN");
ConfigButton (buf, &HyperShotButtons[x]);
g_config->setOption (prefix + HyperShotNames[x],
HyperShotButtons[x].ButtonNum[0]);
}
if (HyperShotButtons[0].ButtType[0] == BUTTC_KEYBOARD)
{
g_config->setOption (prefix + "DeviceType", "Keyboard");
}
else if (HyperShotButtons[0].ButtType[0] == BUTTC_JOYSTICK)
{
g_config->setOption (prefix + "DeviceType", "Joystick");
}
else
{
g_config->setOption (prefix + "DeviceType", "Unknown");
}
g_config->setOption (prefix + "DeviceNum",
HyperShotButtons[0].DeviceNum[0]);
break;
case FCFGD_POWERPAD:
snprintf (buf, 256, "SDL.Input.PowerPad.%d", (arg & 1));
prefix = buf;
for (x = 0; x < 12; x++)
{
sprintf (buf, "PowerPad %d: %d", (arg & 1) + 1, x + 11);
ConfigButton (buf, &powerpadsc[arg & 1][x]);
g_config->setOption (prefix + PowerPadNames[x],
powerpadsc[arg & 1][x].ButtonNum[0]);
}
if (powerpadsc[arg & 1][0].ButtType[0] == BUTTC_KEYBOARD)
{
g_config->setOption (prefix + "DeviceType", "Keyboard");
}
else if (powerpadsc[arg & 1][0].ButtType[0] == BUTTC_JOYSTICK)
{
g_config->setOption (prefix + "DeviceType", "Joystick");
}
else
{
g_config->setOption (prefix + "DeviceType", "Unknown");
}
g_config->setOption (prefix + "DeviceNum",
powerpadsc[arg & 1][0].DeviceNum[0]);
break;
case FCFGD_GAMEPAD:
snprintf (buf, 256, "SDL.Input.GamePad.%d", arg);
prefix = buf;
for (x = 0; x < 10; x++)
{
sprintf (buf, "GamePad #%d: %s", arg + 1, str[x]);
ConfigButton (buf, &GamePadConfig[arg][x]);
g_config->setOption (prefix + GamePadNames[x],
GamePadConfig[arg][x].ButtonNum[0]);
}
if (GamePadConfig[arg][0].ButtType[0] == BUTTC_KEYBOARD)
{
g_config->setOption (prefix + "DeviceType", "Keyboard");
}
else if (GamePadConfig[arg][0].ButtType[0] == BUTTC_JOYSTICK)
{
g_config->setOption (prefix + "DeviceType", "Joystick");
}
else
{
g_config->setOption (prefix + "DeviceType", "Unknown");
}
g_config->setOption (prefix + "DeviceNum",
GamePadConfig[arg][0].DeviceNum[0]);
break;
}
ButtonConfigEnd ();
}
//void ConfigDevice (int which, int arg)
//{
// char buf[256];
// int x;
// std::string prefix;
// const char *str[10] =
// { "A", "B", "SELECT", "START", "UP", "DOWN", "LEFT", "RIGHT", "Rapid A",
// "Rapid B"
// };
//
// // XXX soules - set the configuration options so that later calls
// // don't override these. This is a temp hack until I
// // can clean up this file.
//
// ButtonConfigBegin ();
// switch (which)
// {
// case FCFGD_QUIZKING:
// prefix = "SDL.Input.QuizKing.";
// for (x = 0; x < 6; x++)
// {
// sprintf (buf, "Quiz King Buzzer #%d", x + 1);
// ConfigButton (buf, &QuizKingButtons[x]);
//
// g_config->setOption (prefix + QuizKingNames[x],
// QuizKingButtons[x].ButtonNum);
// }
//
// if (QuizKingButtons[0].ButtType == BUTTC_KEYBOARD)
// {
// g_config->setOption (prefix + "DeviceType", "Keyboard");
// }
// else if (QuizKingButtons[0].ButtType == BUTTC_JOYSTICK)
// {
// g_config->setOption (prefix + "DeviceType", "Joystick");
// }
// else
// {
// g_config->setOption (prefix + "DeviceType", "Unknown");
// }
// g_config->setOption (prefix + "DeviceNum",
// QuizKingButtons[0].DeviceNum);
// break;
// case FCFGD_HYPERSHOT:
// prefix = "SDL.Input.HyperShot.";
// for (x = 0; x < 4; x++)
// {
// sprintf (buf, "Hyper Shot %d: %s",
// ((x & 2) >> 1) + 1, (x & 1) ? "JUMP" : "RUN");
// ConfigButton (buf, &HyperShotButtons[x]);
//
// g_config->setOption (prefix + HyperShotNames[x],
// HyperShotButtons[x].ButtonNum);
// }
//
// if (HyperShotButtons[0].ButtType == BUTTC_KEYBOARD)
// {
// g_config->setOption (prefix + "DeviceType", "Keyboard");
// }
// else if (HyperShotButtons[0].ButtType == BUTTC_JOYSTICK)
// {
// g_config->setOption (prefix + "DeviceType", "Joystick");
// }
// else
// {
// g_config->setOption (prefix + "DeviceType", "Unknown");
// }
// g_config->setOption (prefix + "DeviceNum",
// HyperShotButtons[0].DeviceNum);
// break;
// case FCFGD_POWERPAD:
// snprintf (buf, 256, "SDL.Input.PowerPad.%d", (arg & 1));
// prefix = buf;
// for (x = 0; x < 12; x++)
// {
// sprintf (buf, "PowerPad %d: %d", (arg & 1) + 1, x + 11);
// ConfigButton (buf, &powerpadsc[arg & 1][x]);
//
// g_config->setOption (prefix + PowerPadNames[x],
// powerpadsc[arg & 1][x].ButtonNum);
// }
//
// if (powerpadsc[arg & 1][0].ButtType == BUTTC_KEYBOARD)
// {
// g_config->setOption (prefix + "DeviceType", "Keyboard");
// }
// else if (powerpadsc[arg & 1][0].ButtType == BUTTC_JOYSTICK)
// {
// g_config->setOption (prefix + "DeviceType", "Joystick");
// }
// else
// {
// g_config->setOption (prefix + "DeviceType", "Unknown");
// }
// g_config->setOption (prefix + "DeviceNum",
// powerpadsc[arg & 1][0].DeviceNum);
// break;
//
// case FCFGD_GAMEPAD:
// snprintf (buf, 256, "SDL.Input.GamePad.%d", arg);
// prefix = buf;
// for (x = 0; x < 10; x++)
// {
// sprintf (buf, "GamePad #%d: %s", arg + 1, str[x]);
// ConfigButton (buf, &GamePadConfig[arg][x]);
//
// g_config->setOption (prefix + GamePadNames[x],
// GamePadConfig[arg][x].ButtonNum);
// }
//
// if (GamePadConfig[arg][0].ButtType == BUTTC_KEYBOARD)
// {
// g_config->setOption (prefix + "DeviceType", "Keyboard");
// }
// else if (GamePadConfig[arg][0].ButtType == BUTTC_JOYSTICK)
// {
// g_config->setOption (prefix + "DeviceType", "Joystick");
// }
// else
// {
// g_config->setOption (prefix + "DeviceType", "Unknown");
// }
// g_config->setOption (prefix + "DeviceNum",
// GamePadConfig[arg][0].DeviceNum);
// break;
// }
//
// ButtonConfigEnd ();
//}
/**
* Update the button configuration for a device, specified by a text string.
*/
void InputCfg (const std::string & text)
{
#ifdef _GTK
// enable noGui to prevent the gtk x11 hack from executing
noGui = 1;
// this is only called at the begininng of execution; make sure the video subsystem is initialized
InitVideo (GameInfo);
#endif
if (noGui)
{
if (text.find ("gamepad") != std::string::npos)
{
int device = (text[strlen ("gamepad")] - '1');
if (device < 0 || device > 3)
{
FCEUD_PrintError
("Invalid gamepad device specified; must be one of gamepad1 through gamepad4");
exit (-1);
}
ConfigDevice (FCFGD_GAMEPAD, device);
}
else if (text.find ("powerpad") != std::string::npos)
{
int device = (text[strlen ("powerpad")] - '1');
if (device < 0 || device > 1)
{
FCEUD_PrintError
("Invalid powerpad device specified; must be powerpad1 or powerpad2");
exit (-1);
}
ConfigDevice (FCFGD_POWERPAD, device);
}
else if (text.find ("hypershot") != std::string::npos)
{
ConfigDevice (FCFGD_HYPERSHOT, 0);
}
else if (text.find ("quizking") != std::string::npos)
{
ConfigDevice (FCFGD_QUIZKING, 0);
}
}
else
printf ("Please run \"fceux --nogui\" before using --inputcfg\n");
}
//void InputCfg (const std::string & text)
//{
//
// if (noGui)
// {
// if (text.find ("gamepad") != std::string::npos)
// {
// int device = (text[strlen ("gamepad")] - '1');
// if (device < 0 || device > 3)
// {
// FCEUD_PrintError
// ("Invalid gamepad device specified; must be one of gamepad1 through gamepad4");
// exit (-1);
// }
// ConfigDevice (FCFGD_GAMEPAD, device);
// }
// else if (text.find ("powerpad") != std::string::npos)
// {
// int device = (text[strlen ("powerpad")] - '1');
// if (device < 0 || device > 1)
// {
// FCEUD_PrintError
// ("Invalid powerpad device specified; must be powerpad1 or powerpad2");
// exit (-1);
// }
// ConfigDevice (FCFGD_POWERPAD, device);
// }
// else if (text.find ("hypershot") != std::string::npos)
// {
// ConfigDevice (FCFGD_HYPERSHOT, 0);
// }
// else if (text.find ("quizking") != std::string::npos)
// {
// ConfigDevice (FCFGD_QUIZKING, 0);
// }
// }
// else
// printf ("Please run \"fceux --nogui\" before using --inputcfg\n");
//
//}
/**
@ -1994,7 +1987,9 @@ void InputCfg (const std::string & text)
UpdateInput (Config * config)
{
char buf[64];
std::string device, prefix;
std::string device, prefix, guid, mapping;
InitJoysticks();
for (unsigned int i = 0; i < 3; i++)
{
@ -2087,37 +2082,18 @@ UpdateInput (Config * config)
snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%u.", i);
prefix = buf;
config->getOption (prefix + "DeviceType", &device);
if (device.find ("Keyboard") != std::string::npos)
{
type = BUTTC_KEYBOARD;
}
else if (device.find ("Joystick") != std::string::npos)
{
type = BUTTC_JOYSTICK;
}
else
{
type = 0;
}
config->getOption (prefix + "DeviceType", &device );
config->getOption (prefix + "DeviceGUID", &guid );
config->getOption (prefix + "Profile" , &mapping);
config->getOption (prefix + "DeviceNum", &devnum);
for (unsigned int j = 0; j < GAMEPAD_NUM_BUTTONS; j++)
{
config->getOption (prefix + GamePadNames[j], &button);
GamePadConfig[i][j].ButtType[0] = type;
GamePadConfig[i][j].DeviceNum[0] = devnum;
GamePadConfig[i][j].ButtonNum[0] = button;
GamePadConfig[i][j].NumC = 1;
}
GamePad[i].init( i, guid.c_str(), mapping.c_str() );
}
// PowerPad 0 - 1
for (unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++)
{
char buf[64];
snprintf (buf, 32, "SDL.Input.PowerPad.%u.", i);
snprintf (buf, sizeof(buf)-1, "SDL.Input.PowerPad.%u.", i);
prefix = buf;
config->getOption (prefix + "DeviceType", &device);
@ -2139,10 +2115,9 @@ UpdateInput (Config * config)
{
config->getOption (prefix + PowerPadNames[j], &button);
powerpadsc[i][j].ButtType[0] = type;
powerpadsc[i][j].DeviceNum[0] = devnum;
powerpadsc[i][j].ButtonNum[0] = button;
powerpadsc[i][j].NumC = 1;
powerpadsc[i][j].ButtType = type;
powerpadsc[i][j].DeviceNum = devnum;
powerpadsc[i][j].ButtonNum = button;
}
}
@ -2166,10 +2141,9 @@ UpdateInput (Config * config)
{
config->getOption (prefix + QuizKingNames[j], &button);
QuizKingButtons[j].ButtType[0] = type;
QuizKingButtons[j].DeviceNum[0] = devnum;
QuizKingButtons[j].ButtonNum[0] = button;
QuizKingButtons[j].NumC = 1;
QuizKingButtons[j].ButtType = type;
QuizKingButtons[j].DeviceNum = devnum;
QuizKingButtons[j].ButtonNum = button;
}
// HyperShot
@ -2192,10 +2166,9 @@ UpdateInput (Config * config)
{
config->getOption (prefix + HyperShotNames[j], &button);
HyperShotButtons[j].ButtType[0] = type;
HyperShotButtons[j].DeviceNum[0] = devnum;
HyperShotButtons[j].ButtonNum[0] = button;
HyperShotButtons[j].NumC = 1;
HyperShotButtons[j].ButtType = type;
HyperShotButtons[j].DeviceNum = devnum;
HyperShotButtons[j].ButtonNum = button;
}
// Mahjong
@ -2218,10 +2191,9 @@ UpdateInput (Config * config)
{
config->getOption (prefix + MahjongNames[j], &button);
MahjongButtons[j].ButtType[0] = type;
MahjongButtons[j].DeviceNum[0] = devnum;
MahjongButtons[j].ButtonNum[0] = button;
MahjongButtons[j].NumC = 1;
MahjongButtons[j].ButtType = type;
MahjongButtons[j].DeviceNum = devnum;
MahjongButtons[j].ButtonNum = button;
}
// TopRider
@ -2244,10 +2216,9 @@ UpdateInput (Config * config)
{
config->getOption (prefix + TopRiderNames[j], &button);
TopRiderButtons[j].ButtType[0] = type;
TopRiderButtons[j].DeviceNum[0] = devnum;
TopRiderButtons[j].ButtonNum[0] = button;
TopRiderButtons[j].NumC = 1;
TopRiderButtons[j].ButtType = type;
TopRiderButtons[j].DeviceNum = devnum;
TopRiderButtons[j].ButtonNum = button;
}
// FTrainer
@ -2270,10 +2241,9 @@ UpdateInput (Config * config)
{
config->getOption (prefix + FTrainerNames[j], &button);
FTrainerButtons[j].ButtType[0] = type;
FTrainerButtons[j].DeviceNum[0] = devnum;
FTrainerButtons[j].ButtonNum[0] = button;
FTrainerButtons[j].NumC = 1;
FTrainerButtons[j].ButtType = type;
FTrainerButtons[j].DeviceNum = devnum;
FTrainerButtons[j].ButtonNum = button;
}
// FamilyKeyBoard
@ -2296,10 +2266,9 @@ UpdateInput (Config * config)
{
config->getOption (prefix + FamilyKeyBoardNames[j], &button);
fkbmap[j].ButtType[0] = type;
fkbmap[j].DeviceNum[0] = devnum;
fkbmap[j].ButtonNum[0] = button;
fkbmap[j].NumC = 1;
fkbmap[j].ButtType = type;
fkbmap[j].DeviceNum = devnum;
fkbmap[j].ButtonNum = button;
}
}
@ -2311,11 +2280,11 @@ const char *GamePadNames[GAMEPAD_NUM_BUTTONS] = { "A", "B", "Select", "Start",
const char *DefaultGamePadDevice[GAMEPAD_NUM_DEVICES] =
{ "Keyboard", "None", "None", "None" };
const int DefaultGamePad[GAMEPAD_NUM_DEVICES][GAMEPAD_NUM_BUTTONS] =
{ {SDLK_F, SDLK_D, SDLK_S, SDLK_RETURN,
SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
{ {SDLK_f, SDLK_d, SDLK_s, SDLK_RETURN,
SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}
};
// PowerPad defaults

View File

@ -1,34 +1,39 @@
#ifndef _aosdfjk02fmasf
#define _aosdfjk02fmasf
#include "../common/configSys.h"
#include <stdint.h>
#define MAXBUTTCONFIG 4
typedef struct {
uint8 ButtType[MAXBUTTCONFIG];
uint8 DeviceNum[MAXBUTTCONFIG];
//uint16 ButtonNum[MAXBUTTCONFIG];
int ButtonNum[MAXBUTTCONFIG];
uint32 NumC;
#include "common/configSys.h"
//#define MAXBUTTCONFIG 4
enum {
BUTTC_KEYBOARD = 0,
BUTTC_JOYSTICK = 1,
BUTTC_MOUSE = 2
};
struct ButtConfig
{
int ButtType; //[MAXBUTTCONFIG];
int DeviceNum; //[MAXBUTTCONFIG];
int ButtonNum; //[MAXBUTTCONFIG];
int state;
//uint32_t NumC;
//uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */
} ButtConfig;
};
extern int NoWaiting;
extern CFGSTRUCT InputConfig[];
extern ARGPSTRUCT InputArgs[];
extern int Hotkeys[];
void ParseGIInput(FCEUGI *GI);
void setHotKeys();
void setHotKeys(void);
int getKeyState( int k );
int ButtonConfigBegin();
void ButtonConfigEnd();
void ConfigButton(char *text, ButtConfig *bc);
int DWaitButton(const uint8 *text, ButtConfig *bc, int wb, int *buttonConfigStatus = NULL);
int DWaitButton(const uint8_t *text, ButtConfig *bc, int *buttonConfigStatus = NULL);
#define BUTTC_KEYBOARD 0x00
#define BUTTC_JOYSTICK 0x01
#define BUTTC_MOUSE 0x02
#define FCFGD_GAMEPAD 1
#define FCFGD_POWERPAD 2
@ -41,7 +46,7 @@ void InitInputInterface(void);
void InputUserActiveFix(void);
extern bool replaceP2StartWithMicrophone;
extern ButtConfig GamePadConfig[4][10];
//extern ButtConfig GamePadConfig[4][10];
//extern ButtConfig powerpadsc[2][12];
//extern ButtConfig QuizKingButtons[6];
//extern ButtConfig FTrainerButtons[12];
@ -54,9 +59,9 @@ int DTestButtonJoy(ButtConfig *bc);
void FCEUD_UpdateInput(void);
void UpdateInput(Config *config);
void InputCfg(const std::string &);
//void InputCfg(const std::string &);
std::string GetUserText(const char* title);
const char* ButtonName(const ButtConfig* bc, int which);
const char* ButtonName(const ButtConfig* bc);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
// sdl-joystick.h
#ifndef __SDL_JOYSTICK_H__
#define __SDL_JOYSTICK_H__
#include <string>
#include "sdl/main.h"
#include "sdl/input.h"
#include "sdl/sdl.h"
#define MAX_JOYSTICKS 32
struct nesGamePadMap_t
{
char guid[64];
char name[128];
char btn[GAMEPAD_NUM_BUTTONS][32];
char os[64];
nesGamePadMap_t(void);
~nesGamePadMap_t(void);
void clearMapping(void);
int parseMapping( const char *text );
};
struct jsDev_t
{
SDL_Joystick *js;
SDL_GameController *gc;
jsDev_t(void);
//~jsDev_t(void);
void init( int idx );
int close(void);
SDL_Joystick *getJS(void);
bool isGameController(void);
bool isConnected(void);
void print(void);
int bindPort( int idx );
int unbindPort( int idx );
int getBindPorts(void);
const char *getName(void);
const char *getGUID(void);
private:
int devIdx;
int portBindMask;
std::string guidStr;
std::string name;
};
class GamePad_t
{
public:
ButtConfig bmap[GAMEPAD_NUM_BUTTONS];
GamePad_t(void);
~GamePad_t(void);
int init( int port, const char *guid, const char *profile = NULL );
const char *getGUID(void);
int loadDefaults(void);
int loadProfile( const char *name, const char *guid = NULL );
int getDeviceIndex(void){ return devIdx; }
int setDeviceIndex( int devIdx );
int setMapping( const char *map );
int setMapping( nesGamePadMap_t *map );
int createProfile( const char *name );
int getMapFromFile( const char *filename, char *out );
int getDefaultMap( char *out, const char *guid = NULL );
int saveMappingToFile( const char *filename, const char *txtMap );
int saveCurrentMapToFile( const char *filename );
int deleteMapping( const char *name );
private:
int devIdx;
int portNum;
};
extern GamePad_t GamePad[4];
jsDev_t *getJoystickDevice( int devNum );
#endif

View File

@ -49,16 +49,21 @@ fillaudio(void *udata,
uint8 *stream,
int len)
{
static int16_t sample = 0;
int16 *tmps = (int16*)stream;
len >>= 1;
while(len) {
int16 sample = 0;
if(s_BufferIn) {
while (len)
{
if (s_BufferIn)
{
sample = s_Buffer[s_BufferRead];
s_BufferRead = (s_BufferRead + 1) % s_BufferSize;
s_BufferIn--;
} else {
sample = 0;
// Retain last known sample value, helps avoid clicking
// noise when sound system is starved of audio data.
//sample = 0;
//bufStarveDetected = 1;
}
*tmps = sample;
@ -179,11 +184,20 @@ WriteSound(int32 *buf,
{
extern int EmulationPaused;
if (EmulationPaused == 0)
{
int waitCount = 0;
while(Count)
{
while(s_BufferIn == s_BufferSize)
{
SDL_Delay(1);
SDL_Delay(1); waitCount++;
if ( waitCount > 1000 )
{
printf("Error: Sound sink is not draining... Breaking out of audio loop to prevent lockup.\n");
return;
}
}
s_Buffer[s_BufferWrite] = *buf;
@ -196,6 +210,7 @@ WriteSound(int32 *buf,
buf++;
}
}
}
/**

View File

@ -51,6 +51,10 @@
#include <cstring>
#include <cstdlib>
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LSB_FIRST
#endif
// GLOBALS
extern Config *g_config;
@ -79,6 +83,13 @@ extern bool MaxSpeed;
extern unsigned int gtk_draw_area_width;
extern unsigned int gtk_draw_area_height;
static int sdl_win_width = 0;
static int sdl_win_height = 0;
static SDL_Window *sdlWindow = NULL;
static SDL_Renderer *sdlRenderer = NULL;
static SDL_Texture *sdlTexture = NULL;
/**
* Attempts to destroy the graphical video display. Returns 0 on
* success, -1 on failure.
@ -148,6 +159,7 @@ void FCEUD_VideoChanged()
int InitVideo(FCEUGI *gi)
{
int vdSel;
int doublebuf, xstretch, ystretch, xres, yres, show_fps;
FCEUI_printf("Initializing video...");
@ -180,7 +192,9 @@ int InitVideo(FCEUGI *gi)
FCEUI_GetCurrentVidSystem(&s_srendline, &s_erendline);
s_tlines = s_erendline - s_srendline + 1;
init_gui_video( s_useOpenGL );
g_config->getOption("SDL.VideoDriver", &vdSel);
init_gui_video( (videoDriver_t)vdSel );
s_inited = 1;
@ -188,9 +202,9 @@ int InitVideo(FCEUGI *gi)
FCEUI_SetShowFPS(show_fps);
#ifdef LSB_FIRST
rmask = 0x000000FF;
rmask = 0x00FF0000;
gmask = 0x0000FF00;
bmask = 0x00FF0000;
bmask = 0x000000FF;
#else
rmask = 0x00FF0000;
gmask = 0x0000FF00;
@ -210,24 +224,6 @@ int InitVideo(FCEUGI *gi)
return -1;
}
#ifdef OPENGL
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 ( !initBlitToHighDone )
{
InitBlitToHigh(s_curbpp >> 3,
@ -467,3 +463,176 @@ void FCEUI_SetAviDisableMovieMessages(bool disable)
{
disableMovieMessages = disable;
}
//*****************************************************************************
int init_gtk3_sdl_video( void )
{
GdkWindow *gdkWin = gtk_widget_get_window(evbox);
Window win;
int sdlRendW, sdlRendH;
int vsyncEnabled=0;
if ( (gtk_draw_area_width < GLX_NES_WIDTH) || (gtk_draw_area_height < GLX_NES_HEIGHT) )
{
usleep(100000);
return -1;
}
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0)
{
printf("[SDL] Failed to initialize video subsystem.\n");
return -1;
}
else
{
printf("Initialized SDL Video Subsystem\n");
}
if ( gdkWin == NULL )
{
printf("Error: Failed to obtain gdkWindow Handle for evbox widget\n");
return -1;
}
win = GDK_WINDOW_XID( gdkWin );
for (int i=0; i<SDL_GetNumVideoDrivers(); i++)
{
printf("SDL Video Driver %i: %s\n", i, SDL_GetVideoDriver(i) );
}
printf("Using Video Driver: %s \n", SDL_GetCurrentVideoDriver() );
sdlWindow = SDL_CreateWindowFrom( (void*)win);
if (sdlWindow == NULL)
{
printf("[SDL] Failed to create window from handle.\n");
return -1;
}
uint32_t baseFlags = vsyncEnabled ? SDL_RENDERER_PRESENTVSYNC : 0;
sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, baseFlags | SDL_RENDERER_ACCELERATED);
if (sdlRenderer == NULL)
{
printf("[SDL] Failed to create accelerated renderer.\n");
printf("[SDL] Attempting to create software renderer...\n");
sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, baseFlags | SDL_RENDERER_SOFTWARE);
if (sdlRenderer == NULL)
{
printf("[SDL] Failed to create software renderer.\n");
return -1;
}
}
SDL_GetRendererOutputSize( sdlRenderer, &sdlRendW, &sdlRendH );
printf("[SDL] Renderer Output Size: %i x %i \n", sdlRendW, sdlRendH );
sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, GLX_NES_WIDTH, GLX_NES_HEIGHT);
if (sdlTexture == NULL)
{
printf("[SDL] Failed to create texture: %i x %i", GLX_NES_WIDTH, GLX_NES_HEIGHT );
return -1;
}
sdl_win_width = sdlRendW;
sdl_win_height = sdlRendH;
return 0;
}
//*****************************************************************************
int destroy_gtk3_sdl_video(void)
{
if (sdlTexture)
{
printf("Destroying SDL Texture...\n");
SDL_DestroyTexture(sdlTexture);
sdlTexture = NULL;
}
if (sdlRenderer)
{
printf("Destroying SDL Renderer...\n");
SDL_DestroyRenderer(sdlRenderer);
sdlRenderer = NULL;
}
//SDL_QuitSubSystem(SDL_INIT_VIDEO);
return 0;
}
//*****************************************************************************
int gtk3_sdl_resize(void)
{
destroy_gtk3_sdl_video();
init_gtk3_sdl_video();
return 0;
}
//*****************************************************************************
int gtk3_sdl_render(void)
{
int sx, sy, rw, rh;
int nesWidth = GLX_NES_WIDTH;
int nesHeight = GLX_NES_HEIGHT;
if ( (sdl_win_width != gtk_draw_area_width) || (sdl_win_height != gtk_draw_area_height) )
{
gtk3_sdl_resize();
}
if ( glx_shm != NULL )
{
nesWidth = glx_shm->ncol;
nesHeight = glx_shm->nrow;
}
//printf(" %i x %i \n", nesWidth, nesHeight );
float xscale = (float)gtk_draw_area_width / (float)nesWidth;
float yscale = (float)gtk_draw_area_height / (float)nesHeight;
if (xscale < yscale )
{
yscale = xscale;
}
else
{
xscale = yscale;
}
rw=(int)(nesWidth*xscale);
rh=(int)(nesHeight*yscale);
//sx=sdlViewport.x + (view_width-rw)/2;
//sy=sdlViewport.y + (view_height-rh)/2;
sx=(gtk_draw_area_width-rw)/2;
sy=(gtk_draw_area_height-rh)/2;
if ( (sdlRenderer == NULL) || (sdlTexture == NULL) )
{
return -1;
}
SDL_SetRenderDrawColor( sdlRenderer, 0, 0, 0, 0 );
SDL_RenderClear(sdlRenderer);
uint8_t *textureBuffer;
int rowPitch;
SDL_LockTexture( sdlTexture, nullptr, (void**)&textureBuffer, &rowPitch);
{
memcpy( textureBuffer, glx_shm->pixbuf, GLX_NES_HEIGHT*GLX_NES_WIDTH*sizeof(uint32_t) );
}
SDL_UnlockTexture(sdlTexture);
//SDL_RenderSetViewport( sdlRenderer, &sdlViewport );
SDL_Rect source = {0, 0, nesWidth, nesHeight };
SDL_Rect dest = { sx, sy, rw, rh };
SDL_RenderCopy(sdlRenderer, sdlTexture, &source, &dest);
SDL_RenderPresent(sdlRenderer);
return 0;
}
//*****************************************************************************

View File

@ -13,5 +13,11 @@ bool FCEUI_AviEnableHUDrecording();
void FCEUI_SetAviEnableHUDrecording(bool enable);
bool FCEUI_AviDisableMovieMessages();
void FCEUI_SetAviDisableMovieMessages(bool disable);
int init_gtk3_sdl_video(void);
int destroy_gtk3_sdl_video(void);
int gtk3_sdl_render(void);
int gtk3_sdl_resize(void);
#endif

View File

@ -35,6 +35,8 @@
#include "gui.h"
#endif
#include "fceux_git_info.h"
#include <unistd.h>
#include <csignal>
#include <cstring>
@ -57,6 +59,7 @@ extern bool MaxSpeed;
int isloaded;
bool turbo = false;
bool gtk_gui_run = true;
int closeFinishedMovie = 0;
@ -77,6 +80,8 @@ int pal_emulation;
int dendy;
bool swapDuty;
static bool luaScriptRunning = false;
// -Video Modes Tag- : See --special
static const char *DriverUsage=
"Option Value Description\n"
@ -179,6 +184,8 @@ static void ShowUsage(char *prog)
printf("Compiled with GTK version %d.%d.%d\n", GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION );
//printf("Linked with GTK version %d.%d.%d\n", GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION );
#endif
printf("git URL: %s\n", fceu_get_git_url() );
printf("git Rev: %s\n", fceu_get_git_rev() );
}
@ -330,8 +337,8 @@ DriverKill()
if (!noconfig)
g_config->save();
if(inited&2)
KillJoysticks();
KillJoysticks();
if(inited&4)
KillVideo();
if(inited&1)
@ -348,6 +355,7 @@ FCEUD_Update(uint8 *XBuf,
int32 *Buffer,
int Count)
{
int blitDone = 0;
extern int FCEUDnetplay;
#ifdef CREATE_AVI
@ -374,8 +382,8 @@ FCEUD_Update(uint8 *XBuf,
if (!mutecapture)
if(Count > 0 && Buffer) WriteSound(Buffer,Count);
}
if(inited & 2)
FCEUD_UpdateInput();
// if(inited & 2)
// FCEUD_UpdateInput();
if(XBuf && (inited & 4)) BlitScreen(XBuf);
//SpeedThrottle();
@ -407,7 +415,9 @@ FCEUD_Update(uint8 *XBuf,
// don't underflow when scaling fps
if(g_fpsScale>1.0 || ((tmpcan < Count*0.90) && !uflow)) {
if(XBuf && (inited&4) && !(NoWaiting & 2))
BlitScreen(XBuf);
{
BlitScreen(XBuf); blitDone = 1;
}
Buffer+=can;
Count-=can;
if(Count) {
@ -442,24 +452,23 @@ FCEUD_Update(uint8 *XBuf,
}
} else {
if(!NoWaiting && (!(eoptions&EO_NOTHROTTLE) || FCEUI_EmulationPaused()))
while (SpeedThrottle())
//if(!NoWaiting && (!(eoptions&EO_NOTHROTTLE) || FCEUI_EmulationPaused()))
//while (SpeedThrottle())
//{
// FCEUD_UpdateInput();
//}
if (XBuf && (inited&4))
{
FCEUD_UpdateInput();
}
if(XBuf && (inited&4)) {
BlitScreen(XBuf);
BlitScreen(XBuf); blitDone = 1;
}
}
if ( !blitDone )
{
if (XBuf && (inited&4))
{
BlitScreen(XBuf); blitDone = 1;
}
}
FCEUD_UpdateInput();
//if(!Count && !NoWaiting && !(eoptions&EO_NOTHROTTLE))
// SpeedThrottle();
//if(XBuf && (inited&4))
//{
// BlitScreen(XBuf);
//}
//if(Count)
// WriteSound(Buffer,Count,NoWaiting);
//FCEUD_UpdateInput();
}
@ -552,10 +561,15 @@ int main(int argc, char *argv[])
#endif
/* SDL_INIT_VIDEO Needed for (joystick config) event processing? */
if(SDL_Init(SDL_INIT_VIDEO)) {
if (SDL_Init(SDL_INIT_VIDEO))
{
printf("Could not initialize SDL: %s.\n", SDL_GetError());
return(-1);
}
if ( SDL_SetHint( SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1" ) == SDL_FALSE )
{
printf("Error setting SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS\n");
}
//#ifdef OPENGL
// SDL_GL_LoadLibrary(0);
@ -608,12 +622,14 @@ int main(int argc, char *argv[])
std::string s;
g_config->getOption("SDL.InputCfg", &s);
if(s.size() != 0)
{
InitVideo(GameInfo);
InputCfg(s);
}
//g_config->getOption("SDL.InputCfg", &s);
//
//if(s.size() != 0)
//{
// InitVideo(GameInfo);
// InputCfg(s);
//}
// set the FAMICOM PAD 2 Mic thing
{
int t;
@ -625,18 +641,6 @@ int main(int argc, char *argv[])
// update the input devices
UpdateInput(g_config);
// check if opengl is enabled with a scaler and display an error and bail
int opengl;
int scaler;
g_config->getOption("SDL.OpenGL", &opengl);
g_config->getOption("SDL.SpecialFilter", &scaler);
if(opengl && scaler)
{
printf("Scalers are not supported in OpenGL mode. Terminating.\n");
exit(2);
}
// check for a .fcm file to convert to .fm2
g_config->getOption ("SDL.FCMConvert", &s);
g_config->setOption ("SDL.FCMConvert", "");
@ -908,7 +912,7 @@ int main(int argc, char *argv[])
#ifdef _GTK
if(noGui == 0)
{
while(1)
while ( gtk_gui_run )
{
if(GameInfo)
{
@ -916,14 +920,16 @@ int main(int argc, char *argv[])
}
else
{
SDL_Delay(1);
SDL_Delay(10);
}
FCEUD_UpdateInput();
while(gtk_events_pending())
{
gtk_main_iteration_do(FALSE);
}
}
printf("Exiting GUI Main Loop...\n");
}
else
{
@ -936,11 +942,34 @@ int main(int argc, char *argv[])
DoFun(frameskip, periodic_saves);
}
#endif
printf("Closing Game...\n");
CloseGame();
printf("Exiting Infrastructure...\n");
// exit the infrastructure
FCEUI_Kill();
SDL_Quit();
#ifdef _GTK
usleep(50000);
if ( MainWindow != NULL )
{
printf("Destroying GUI Window...\n");
gtk_widget_destroy( MainWindow ); MainWindow = NULL;
}
usleep(50000);
while(gtk_events_pending())
{
//printf("Processing the last of the events...\n");
gtk_main_iteration_do(FALSE);
}
#endif
// LoadGame() checks for an IP and if it finds one begins a network session
// clear the NetworkIP field so this doesn't happen unintentionally
g_config->setOption ("SDL.NetworkIP", "");
g_config->save ();
printf("Done!\n");
return 0;
}
@ -1002,6 +1031,27 @@ void FCEUD_PrintError(const char *errormsg)
fprintf(stderr, "%s\n", errormsg);
}
//----------------------------------------------------
void WinLuaOnStart(intptr_t hDlgAsInt)
{
luaScriptRunning = true;
//printf("Lua Script Running: %i \n", luaScriptRunning );
}
//----------------------------------------------------
void WinLuaOnStop(intptr_t hDlgAsInt)
{
luaScriptRunning = false;
//printf("Lua Script Running: %i \n", luaScriptRunning );
}
//----------------------------------------------------
void PrintToWindowConsole(intptr_t hDlgAsInt, const char* str)
{
printf("Lua Output: %s\n", str );
}
//----------------------------------------------------
// dummy functions

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);

View File

@ -246,6 +246,29 @@ INT_PTR CWin32InputBox::GetInteger(
return ret;
}
INT_PTR CWin32InputBox::GetString(
LPCTSTR szTitle,
LPCTSTR szPrompt,
CHAR* result,
HWND hwndParent)
{
WIN32INPUTBOX_PARAM param;
char szResult[32+1];
sprintf(szResult, "");
param.szTitle = szTitle;
param.szPrompt = szPrompt;
param.szResult = szResult;
param.nResultSize = sizeof(szResult);
param.bMultiline = false;
param.hwndOwner = hwndParent;
INT_PTR ret = InputBoxEx(&param);
if (ret == IDOK)
sprintf(result, "%s", szResult);
return ret;
}
void CWin32InputBox::InitDialog()
{
// Set the button captions
@ -290,7 +313,7 @@ void CWin32InputBox::InitDialog()
0,
0,
rectDlg.right - rectDlg.left,
rectDlg.bottom - rectDlg.top - (rectEdit1.bottom - rectEdit1.top),
rectDlg.bottom - rectDlg.top - (rectEdit1.bottom - rectEdit1.top) + 16,
SWP_NOMOVE);
}
@ -302,7 +325,7 @@ void CWin32InputBox::InitDialog()
0,
0,
rectDlg.right - rectDlg.left,
rectEdit1.bottom - rectDlg.top + 5,
rectEdit1.bottom - rectDlg.top + 5 + 16,
SWP_NOMOVE);
::ShowWindow(hwndEdit2, SW_HIDE);

View File

@ -99,6 +99,12 @@ public:
LPCTSTR szPrompt,
int& result,
HWND hwndParent = 0);
static INT_PTR GetString(
LPCTSTR szTitle,
LPCTSTR szPrompt,
CHAR* result,
HWND hwndParent = 0);
};
#endif

View File

@ -37,6 +37,7 @@ HMENU hCheatcontext = 0; //Handle to cheat context menu
bool pauseWhileActive = false; //For checkbox "Pause while active"
extern int globalCheatDisabled;
extern int disableAutoLSCheats;
extern bool disableShowGG;
extern bool wasPausedByCheats;
int CheatWindow;
@ -281,7 +282,7 @@ HWND InitializeCheatList(HWND hwnd)
SendMessage(hwndChtList, LVM_INSERTCOLUMN, 0, (LPARAM)&lv);
lv.pszText = "Name";
lv.cx = 132;
lv.cx = 152;
SendMessage(hwndChtList, LVM_INSERTCOLUMN, 1, (LPARAM)&lv);
// Add a checkbox to indicate if the cheat is activated
@ -316,6 +317,7 @@ INT_PTR CALLBACK CheatConsoleCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
CheckDlgButton(hwndDlg, IDC_CHEAT_PAUSEWHENACTIVE, pauseWhileActive ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwndDlg, IDC_CHEAT_GLOBAL_SWITCH, globalCheatDisabled ? BST_UNCHECKED : BST_CHECKED);
CheckDlgButton(hwndDlg, IDC_CHEAT_AUTOLOADSAVE, disableAutoLSCheats == 2 ? BST_UNCHECKED : disableAutoLSCheats == 1 ? BST_INDETERMINATE : BST_CHECKED);
CheckDlgButton(hwndDlg, IDC_CHEAT_SHOWGG, disableShowGG ? BST_UNCHECKED : BST_CHECKED);
//setup font
SetupCheatFont(hwndDlg);
@ -761,6 +763,31 @@ INT_PTR CALLBACK CheatConsoleCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
}
SetCheatToolTip(hwndDlg, IDC_CHEAT_AUTOLOADSAVE);
}
break;
case IDC_CHEAT_SHOWGG:
{
disableShowGG ^= 1;
void(*CreateCheatStr)(char* buf, int a, int v, int c) = disableShowGG ? GetCheatCodeStr : EncodeGG;
int i = 0;
char buf[32];
LVITEM lvi;
lvi.iSubItem = 0;
struct CHEATF* cheat = cheats;
while (cheat != NULL)
{
if (cheat->addr > 0x7FFF)
{
CreateCheatStr(buf, cheat->addr, cheat->val, cheat->compare);
lvi.pszText = buf;
SendDlgItemMessage(hwndDlg, IDC_LIST_CHEATS, LVM_SETITEMTEXT, i, (LPARAM)&lvi);
}
cheat = cheat->next;
++i;
}
}
}
break;
case EN_SETFOCUS:
@ -1311,11 +1338,10 @@ void DoGGConv()
inline void GetCheatStr(char* buf, int a, int v, int c)
{
if (a > 0x7FFF)
EncodeGG(buf, a, v, c);
else {
if (a < 0x8000 || disableShowGG)
GetCheatCodeStr(buf, a, v, c);
}
else
EncodeGG(buf, a, v, c);
}
inline void GetCheatCodeStr(char* buf, int a, int v, int c)

View File

@ -58,6 +58,7 @@ extern int CurrentState;
extern bool pauseWhileActive; //adelikat: Cheats dialog
extern int globalCheatDisabled;
extern int disableAutoLSCheats;
extern bool disableShowGG;
extern bool enableHUDrecording;
extern bool disableMovieMessages;
extern bool replaceP2StartWithMicrophone;
@ -131,6 +132,7 @@ extern int RomFreezeColorB;
extern int HexBoundColorR;
extern int HexBoundColorG;
extern int HexBoundColorB;
extern int importBookmarkProps;
//adelikat: Hacky fix for Ram Watch recent menu
char* ramWatchRecent[] = {0, 0, 0, 0, 0};
@ -458,6 +460,7 @@ static CFGSTRUCT fceuconfig[] =
AC(HexBoundColorR),
AC(HexBoundColorG),
AC(HexBoundColorB),
AC(importBookmarkProps),
//ACS(memwLastfile[2048]),
AC(AutoRWLoad),
@ -469,6 +472,7 @@ static CFGSTRUCT fceuconfig[] =
AC(compressSavestates),
AC(pauseWhileActive),
AC(disableAutoLSCheats),
AC(disableShowGG),
AC(globalCheatDisabled),
AC(enableHUDrecording),
AC(disableMovieMessages),

View File

@ -2359,7 +2359,7 @@ INT_PTR CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
}
case IDC_DEBUGGER_BOOKMARK_ADD: AddDebuggerBookmark(hwndDlg); break;
case IDC_DEBUGGER_BOOKMARK_DEL: DeleteDebuggerBookmark(hwndDlg); break;
case IDC_DEBUGGER_BOOKMARK_NAME: NameDebuggerBookmark(hwndDlg); break;
case IDC_DEBUGGER_BOOKMARK_EDIT: EditDebuggerBookmark(hwndDlg); break;
case IDC_DEBUGGER_ENABLE_SYMBOLIC:
{
symbDebugEnabled ^= 1;

View File

@ -62,7 +62,9 @@ int debuggerWasActive = 0;
char temp_chr[40] = {0};
char delimiterChar[2] = "#";
extern INT_PTR CALLBACK nameBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK nameDebuggerBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
extern WNDPROC DefaultEditCtrlProc;
extern LRESULT APIENTRY FilterEditCtrlProc(HWND hDlg, UINT uMsg, WPARAM wP, LPARAM lP);
MemoryMappedRegister RegNames[] = {
{"$2000", "PPU_CTRL"},
@ -768,28 +770,6 @@ unsigned int getBookmarkAddress(unsigned int index)
return 0;
}
/**
* Adds a debugger bookmark to the list on the debugger window.
*
* @param hwnd HWMD of the debugger window
* @param buffer Text of the debugger bookmark
**/
void AddDebuggerBookmark2(HWND hwnd, unsigned int addr)
{
int index = bookmarks.size();
// try to find Symbolic name for this address
Name* node = findNode(getNamesPointerForAddress(addr), addr);
std::pair<unsigned int, std::string> bookmark(addr, node && node->name ? node->name : "");
bookmarks.push_back(bookmark);
// add new item to ListBox
char buffer[256];
sprintf(buffer, "%04X %s", bookmark.first, bookmark.second.c_str());
SendDlgItemMessage(hwnd, LIST_DEBUGGER_BOOKMARKS, LB_ADDSTRING, 0, (LPARAM)buffer);
// select this item
SendDlgItemMessage(hwnd, LIST_DEBUGGER_BOOKMARKS, LB_SETCURSEL, index, 0);
}
/**
* Takes the offset from the debugger bookmark edit field and adds a debugger
* bookmark with that offset to the bookmark list if the offset is valid.
@ -798,18 +778,44 @@ void AddDebuggerBookmark2(HWND hwnd, unsigned int addr)
**/
void AddDebuggerBookmark(HWND hwnd)
{
int n;
char buffer[5] = {0};
GetDlgItemText(hwnd, IDC_DEBUGGER_BOOKMARK, buffer, 5);
n = offsetStringToInt(BT_C, buffer);
int address = offsetStringToInt(BT_C, buffer);
// Make sure the offset is valid
if (n == -1 || n > 0xFFFF)
if (address == -1 || address > 0xFFFF)
{
MessageBox(hwnd, "Invalid offset", "Error", MB_OK | MB_ICONERROR);
return;
}
AddDebuggerBookmark2(hwnd, n);
/*
int index = 0;
for (std::vector<std::pair<unsigned int, std::string>>::iterator it = bookmarks.begin(); it != bookmarks.end(); ++it)
{
if (it->first == address)
{
// select this bookmark to notify it already have a bookmark
SendDlgItemMessage(hwnd, LIST_DEBUGGER_BOOKMARKS, LB_SETCURSEL, index, 0);
return;
}
++index;
}
*/
int index = bookmarks.size();
// try to find Symbolic name for this address
Name* node = findNode(getNamesPointerForAddress(address), address);
std::pair<unsigned int, std::string> bookmark(address, node && node->name ? node->name : "");
if (DialogBoxParam(fceu_hInstance, "NAMEBOOKMARKDLGDEBUGGER", hwnd, nameDebuggerBookmarkCallB, (LPARAM)&bookmark))
{
bookmarks.push_back(bookmark);
// add new item to ListBox
char buffer[256];
sprintf(buffer, "%04X %s", bookmark.first, bookmark.second.c_str());
SendDlgItemMessage(hwnd, LIST_DEBUGGER_BOOKMARKS, LB_ADDSTRING, 0, (LPARAM)buffer);
// select this item
SendDlgItemMessage(hwnd, LIST_DEBUGGER_BOOKMARKS, LB_SETCURSEL, index, 0);
}
}
/**
@ -841,7 +847,7 @@ void DeleteDebuggerBookmark(HWND hwnd)
}
}
void NameDebuggerBookmark(HWND hwnd)
void EditDebuggerBookmark(HWND hwnd)
{
// Get the selected bookmark
int selectedItem = SendDlgItemMessage(hwnd, LIST_DEBUGGER_BOOKMARKS, LB_GETCURSEL, 0, 0);
@ -865,7 +871,7 @@ void NameDebuggerBookmark(HWND hwnd)
}
}
// Show the bookmark name dialog
if (DialogBoxParam(fceu_hInstance, "NAMEBOOKMARKDLG", hwnd, nameBookmarkCallB, (LPARAM)&bookmark))
if (DialogBoxParam(fceu_hInstance, "NAMEBOOKMARKDLGDEBUGGER", hwnd, nameDebuggerBookmarkCallB, (LPARAM)&bookmark))
{
// Rename the selected bookmark
bookmarks[selectedItem] = bookmark;
@ -1159,4 +1165,88 @@ void WriteNameFileToDisk(const char* filename, Name* node)
}
}
INT_PTR CALLBACK nameDebuggerBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static std::pair<unsigned int, std::string>* debuggerBookmark;
switch (uMsg)
{
case WM_INITDIALOG:
{
// Limit bookmark descriptions to 50 characters
SendDlgItemMessage(hwndDlg, IDC_BOOKMARK_DESCRIPTION, EM_SETLIMITTEXT, 50, 0);
// Limit the address text
SendDlgItemMessage(hwndDlg, IDC_BOOKMARK_ADDRESS, EM_SETLIMITTEXT, 4, 0);
DefaultEditCtrlProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_BOOKMARK_ADDRESS), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc);
debuggerBookmark = (std::pair<unsigned int, std::string>*)lParam;
char addr[8];
sprintf(addr, "%04X", debuggerBookmark->first);
// Set address and description
sprintf(addr, "%04X", debuggerBookmark->first);
SetDlgItemText(hwndDlg, IDC_BOOKMARK_ADDRESS, addr);
SetDlgItemText(hwndDlg, IDC_BOOKMARK_DESCRIPTION, debuggerBookmark->second.c_str());
// Set focus to the edit field.
SetFocus(GetDlgItem(hwndDlg, IDC_BOOKMARK_DESCRIPTION));
SendDlgItemMessage(hwndDlg, IDC_BOOKMARK_DESCRIPTION, EM_SETSEL, 0, 52);
break;
}
case WM_QUIT:
case WM_CLOSE:
EndDialog(hwndDlg, 0);
break;
case WM_COMMAND:
switch (HIWORD(wParam))
{
case BN_CLICKED:
switch (LOWORD(wParam))
{
case IDOK:
{
char addr_str[8];
GetDlgItemText(hwndDlg, IDC_BOOKMARK_ADDRESS, addr_str, 8);
sscanf(addr_str, "%X", &debuggerBookmark->first);
if (debuggerBookmark->first > 0xFFFE)
{
// if the address is out of range
char errmsg[64];
sprintf(errmsg, "The address must be in range of 0-%X", 0xFFFE);
MessageBox(hwndDlg, errmsg, "Address out of range", MB_OK | MB_ICONERROR);
SetFocus(GetDlgItem(hwndDlg, IDC_BOOKMARK_ADDRESS));
return FALSE;
}
/*
extern std::vector<std::pair<unsigned int, std::string>> bookmarks;
for (std::vector<std::pair<unsigned int, std::string>>::iterator it = bookmarks.begin(); it != bookmarks.end(); ++it)
{
if (it->first == debuggerBookmark->first && it->second == debuggerBookmark->second)
{
// if the address already have a bookmark
MessageBox(hwndDlg, "This address already have a bookmark", "Bookmark duplicated", MB_OK | MB_ICONASTERISK);
return FALSE;
}
}
*/
// Update the description
char description[51];
GetDlgItemText(hwndDlg, IDC_BOOKMARK_DESCRIPTION, description, 50);
debuggerBookmark->second = description;
EndDialog(hwndDlg, 1);
break;
}
case IDCANCEL:
EndDialog(hwndDlg, 0);
}
}
}
return FALSE;
}

View File

@ -55,9 +55,8 @@ void setNamesPointerForAddress(uint16 address, Name* newNode);
void loadNameFiles();
void replaceNames(Name* list, char* str, std::vector<uint16>* addressesLog = 0);
void AddDebuggerBookmark(HWND hwnd);
void AddDebuggerBookmark2(HWND hwnd, unsigned int addr);
void DeleteDebuggerBookmark(HWND hwnd);
void NameDebuggerBookmark(HWND hwnd);
void EditDebuggerBookmark(HWND hwnd);
void DeleteAllDebuggerBookmarks();
void FillDebuggerBookmarkListbox(HWND hwnd);

View File

@ -114,8 +114,7 @@ static INT_PTR CALLBACK DirConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPAR
case WM_CLOSE:
case WM_QUIT:
CloseDirectoriesDialog(hwndDlg);
CloseDirectoriesDialog(hwndDlg); //adelikat: Hacky but this fixes the directory overides bug (or at least some instances of it). This of course really just puts a band-aid on the real problem.
EndDialog(hwndDlg, 0);
break;
case WM_COMMAND:
@ -126,9 +125,7 @@ static INT_PTR CALLBACK DirConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPAR
{
case CLOSE_BUTTON:
CloseDirectoriesDialog(hwndDlg);
break;
case BTN_CANCEL:
EndDialog(hwndDlg, 0);
CloseDirectoriesDialog(hwndDlg); //adelikat: Hacky but this fixes the directory overides bug (or at least some instances of it). This of course really just puts a band-aid on the real problem.
break;
default:
static char *helpert[14] = {

View File

@ -106,8 +106,6 @@ static uint32 FTrainerData=0;
static uint8 TopRiderData=0;
static uint32 FamiNetSysData = 0;
static uint8 BWorldData[1+13+1];
static void UpdateFKB(void);
static void UpdateSuborKB(void);
void UpdateGamepad(void);

View File

@ -1,5 +1,5 @@
#ifndef WIN_INPUT_H
#define WIN_INPU_H
#define WIN_INPUT_H
#include "dinput.h"
@ -30,6 +30,8 @@ extern LPDIRECTINPUT7 lpDI;
extern int InputType[3];
//extern int UsrInputType[3];
extern int cidisabled;
extern uint8 BWorldData[1 + 13 + 1];
#ifndef _aosdfjk02fmasf
#define _aosdfjk02fmasf

View File

@ -171,7 +171,7 @@ unsigned int skippy = 0; //Frame skip
int frameSkipCounter = 0; //Counter for managing frame skip
// Contains the names of the overridden standard directories
// in the order roms, nonvol, states, fdsrom, snaps, cheats, movies, memwatch, basic bot, macro, input presets, lua scripts, avi, base
char *directory_names[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
char *directory_names[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int edit_id[14] = { EDIT_ROM, EDIT_BATTERY, EDIT_STATE, EDIT_FDSBIOS, EDIT_SCREENSHOT, EDIT_CHEAT, EDIT_MOVIE, EDIT_MEMWATCH, EDIT_BOT, EDIT_MACRO, EDIT_PRESET, EDIT_LUA, EDIT_AVI, EDIT_ROOT };
int browse_btn_id[14] = {BUTTON_ROM, BUTTON_BATTERY, BUTTON_STATE, BUTTON_FDSBIOS, BUTTON_SCREENSHOT, BUTTON_CHEAT, BUTTON_MOVIE, BUTTON_MEMWATCH, BUTTON_BOT, BUTTON_MACRO, BUTTON_PRESET, BUTTON_LUA, BUTTON_AVI, BUTTON_ROOT };
std::string cfgFile = "fceux.cfg";
@ -286,7 +286,7 @@ void DefaultDirectoryWalker(void (*callback)(const char*))
sprintf(
TempArray,
"%s\\%s",
directory_names[NUMBER_OF_DEFAULT_DIRECTORIES] ? directory_names[NUMBER_OF_DEFAULT_DIRECTORIES] : BaseDirectory.c_str(),
directory_names[NUMBER_OF_DEFAULT_DIRECTORIES - 1] ? directory_names[NUMBER_OF_DEFAULT_DIRECTORIES - 1] : BaseDirectory.c_str(),
default_directory_names[curr_dir]
);

View File

@ -71,20 +71,21 @@ char *GetRomName(bool force = false); //Checks if rom is loaded, if so, outputs
char *GetRomPath(bool force = false); //Checks if rom is loaded, if so, outputs the Rom path only
///Contains the names of the default directories.
static const char *default_directory_names[13] = {
"", // roms
"sav", // nonvol
"fcs", // states
"", // fdsrom
"snaps", // snaps
"cheats", // cheats
"movies", // movies
"tools", // memwatch
"tools", // macro
"tools", // input presets
"tools", // lua scripts
"", // avi output
"" // adelikat - adding a dummy one here ( [13] but only 12 entries)
static const char *default_directory_names[14] = {
"", // roms
"sav", // novol
"fcs", // states
"", // fdsrom
"snaps", // snaps
"cheats", // cheats
"movies", // movies
"tools", // memwatch
"tools", // bot
"tools", // macro
"tools", // input presets
"luascripts", // lua scripts
"", // avi output
"" // adelikat - adding a dummy one here ( [14] but only 13 entries)
};
#define NUMBER_OF_DIRECTORIES sizeof(directory_names) / sizeof(*directory_names)

View File

@ -141,6 +141,7 @@ int GetAddyFromCoord(int x,int y);
void AutoScrollFromCoord(int x,int y);
LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK MemFindCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK importBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void FindNext();
void OpenFindDialog();
static int GetFileData(uint32 offset);
@ -615,7 +616,7 @@ void UpdateMemoryView(int draw_all)
return;
}
char EditString[4][20] = {"RAM","PPU","OAM","ROM"};
char* EditString[4] = {"RAM","PPU","OAM","ROM"};
void UpdateCaption()
{
@ -713,7 +714,7 @@ void UpdateColorTable()
TextColorList[i] = RGB(HexForeColorR,HexForeColorG,HexForeColorB); //Regular color text - 2 columns
}
for (j=0;j<nextBookmark;j++)
for (j=0;j<hexBookmarks.bookmarkCount;j++)
{
if(hexBookmarks[j].editmode != EditingMode) continue;
if(((int)hexBookmarks[j].address >= CurOffset) && ((int)hexBookmarks[j].address < CurOffset+DataAmount))
@ -912,73 +913,7 @@ void UnfreezeAllRam() {
return;
}
/*
int saveBookmarks(HWND hwnd)
{
char name[513] = { 0 };
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hInstance = fceu_hInstance;
ofn.lpstrTitle = "Save bookmarks as...";
ofn.lpstrFilter = "Bookmark list (*.bld)\0*.lst\0All Files (*.*)\0*.*\0\0";
strcpy(name, mass_replace(GetRomName(), "|", ".").c_str());
ofn.lpstrFile = name;
ofn.lpstrDefExt = "bld";
ofn.nMaxFile = 256;
ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY;
ofn.hwndOwner = hwnd;
bool success = false;
if (GetSaveFileName(&ofn))
{
FILE* bld = fopen(name, "wb");
if (bld)
{
fwrite("BOOKMARKLIST", strlen("BOOKMARKLIST"), 1, bld);
extern int storeHexPreferences(FILE*);
success = storeHexPreferences(bld);
fclose(bld);
}
}
return success;
}
int loadBookmarks(HWND hwnd)
{
char nameo[2048] = { 0 };
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hInstance = fceu_hInstance;
ofn.lpstrTitle = "Load bookmarks...";
ofn.lpstrFilter = "Bookmark list (*.bld)\0*.lst\0All Files (*.*)\0*.*\0\0";
ofn.lpstrFile = nameo;
ofn.nMaxFile = 256;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.hwndOwner = hwnd;
int success = 0;
if (GetOpenFileName(&ofn))
{
char buffer[13] = { 0 };
FILE* bld = fopen(nameo, "r");
if (bld)
{
fread(bld, strlen("BOOKMARKLIST"), 1, bld);
if (!strcpy(buffer, "BOOKMARKLIST"))
{
extern int loadHexPreferences(FILE*);
success = loadHexPreferences(bld);
}
fclose(bld);
}
}
return success;
}
*/
void FreezeRam(int address, int mode, int final){
// mode: -1 == Unfreeze; 0 == Toggle; 1 == Freeze
if(FrozenAddressCount <= 256 && (address < 0x2000) || ((address >= 0x6000) && (address <= 0x7FFF))){
@ -1078,7 +1013,7 @@ void InputData(char *input){
break;
case MODE_NES_FILE:
// ROM
ApplyPatch(addr, datasize, data);
ApplyPatch(addr, 1, &data[i]);
break;
}
}
@ -1245,16 +1180,31 @@ void AutoScrollFromCoord(int x,int y)
void KillMemView()
{
ReleaseDC(hMemView,mDC);
DestroyWindow(hMemView);
UnregisterClass("MEMVIEW",fceu_hInstance);
hMemView = 0;
hMemFind = 0;
if (EditingMode == MODE_NES_MEMORY)
ReleaseCheatMap();
return;
if (hMemView)
{
ReleaseDC(hMemView, mDC);
DestroyWindow(hMemView);
UnregisterClass("MEMVIEW", fceu_hInstance);
hMemView = NULL;
hMemFind = NULL;
if (EditingMode == MODE_NES_MEMORY)
ReleaseCheatMap();
}
}
int GetMaxSize(int EditingMode)
{
switch (EditingMode)
{
case MODE_NES_MEMORY: return 0x10000;
case MODE_NES_PPU: return (GameInfo->type == GIT_NSF ? 0x2000 : 0x4000);
case MODE_NES_OAM: return 0x100;
case MODE_NES_FILE: return 16 + CHRsize[0] + PRGsize[0]; //todo: add trainer size
}
return 0;
}
LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
@ -1414,12 +1364,12 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
int key_num;
sscanf(buf, "%d", &key_num);
key_num = (key_num + 9) % 10;
if (hexBookmarkShortcut[key_num] != -1)
if (hexBookmarks.shortcuts[key_num] != -1)
{
int address = hexBookmarks[hexBookmarkShortcut[key_num]].address;
int address = hexBookmarks[hexBookmarks.shortcuts[key_num]].address;
if (address != -1)
{
ChangeMemViewFocus(hexBookmarks[hexBookmarkShortcut[key_num]].editmode, address, -1);
ChangeMemViewFocus(hexBookmarks[hexBookmarks.shortcuts[key_num]].editmode, address, -1);
UpdateColorTable();
}
}
@ -1844,7 +1794,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
{
if (foundBookmark == -1)
{
if (nextBookmark >= 64)
if (hexBookmarks.bookmarkCount >= 64)
MessageBox(hwnd, "Can't set more than 64 bookmarks.", "Error", MB_OK | MB_ICONERROR);
else
{
@ -2162,17 +2112,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
break;
}
switch (EditingMode)
{
case MODE_NES_MEMORY:
MaxSize = 0x10000; break;
case MODE_NES_PPU:
MaxSize = (GameInfo->type == GIT_NSF ? 0x2000 : 0x4000); break;
case MODE_NES_OAM:
MaxSize = 0x100; break;
case MODE_NES_FILE: //todo: add trainer size
MaxSize = 16 + CHRsize[0] + PRGsize[0]; break;
}
MaxSize = GetMaxSize(EditingMode);
if (CurOffset >= MaxSize - DataAmount) CurOffset = MaxSize - DataAmount;
if (CurOffset < 0) CurOffset = 0;
@ -2229,7 +2169,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
}
case MENU_MV_BOOKMARKS_RM_ALL:
if (nextBookmark)
if (hexBookmarks.bookmarkCount)
{
if (MessageBox(hwnd, "Remove All Bookmarks?", "Bookmarks", MB_YESNO | MB_ICONINFORMATION) == IDYES)
{
@ -2238,15 +2178,294 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
}
}
return 0;
/*
case MENU_MV_BOOKMARKS_EXPORT:
if (!saveBookmarks(hwnd))
MessageBox(hwnd, "Error saving bookmarks.", "Error", MB_OK | MB_ICONERROR);
case ID_BOOKMARKS_EXPORT:
{
char name[2048] = { 0 };
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hInstance = fceu_hInstance;
ofn.lpstrTitle = "Save bookmarks as...";
ofn.lpstrFilter = "Hex Editor Bookmark list (*.hbm)\0*.hbm\0All Files (*.*)\0*.*\0\0";
strcpy(name, mass_replace(GetRomName(), "|", ".").c_str());
ofn.lpstrFile = name;
ofn.lpstrDefExt = "hbm";
ofn.nMaxFile = 2048;
ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
ofn.hwndOwner = hwnd;
int success = false;
if (GetSaveFileName(&ofn))
{
FILE* bld = fopen(name, "wb");
if (bld)
{
// write the header
fwrite("HexBookmarkList", strlen("HexBookmarkList"), 1, bld);
// it shares the same logic of creating the hexpreference part of .deb file
extern int storeHexPreferences(FILE*, HexBookmarkList& = hexBookmarks);
if (!storeHexPreferences(bld))
success = true;
fclose(bld);
}
if (!success)
MessageBox(hwnd, "Error saving bookmarks.", "Error saving bookmarks", MB_OK | MB_ICONERROR);
}
return 0;
case MENU_MV_BOOKMARKS_IMPORT:
loadBookmarks(hwnd);
return 0;
*/
}
case ID_BOOKMARKS_IMPORT:
{
char nameo[2048] = { 0 };
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hInstance = fceu_hInstance;
ofn.lpstrTitle = "Load bookmarks...";
ofn.lpstrFilter = "Hex Editor Bookmarks (*.hbm)\0*.hbm\0All Files (*.*)\0*.*\0\0";
ofn.lpstrFile = nameo;
ofn.lpstrDefExt = "hbm";
ofn.nMaxFile = 2048;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.hwndOwner = hwnd;
bool success = false;
if (GetOpenFileName(&ofn))
{
char buffer[256] = { 0 };
FILE* bld = fopen(nameo, "r");
if (bld)
{
// Read the header to know it's hex bookmark list
fread(buffer, strlen("HexBookmarkList"), 1, bld);
if (!strcmp(buffer, "HexBookmarkList"))
{
HexBookmarkList import;
// it shares the same logic of creating the hexpreference part of .deb file
extern int loadHexPreferences(FILE*, HexBookmarkList& = hexBookmarks);
if (!loadHexPreferences(bld, import) && import.bookmarkCount > 0)
{
if (importBookmarkProps & IMPORT_DISCARD_ORIGINAL)
{
discard_original:
if (importBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT || hexBookmarks.bookmarkCount == 0 || MessageBox(hwnd, "All your existing bookmarks will be discarded after importing the new bookmarks! Do you want to continue?", "Bookmark Import", MB_YESNO | MB_ICONWARNING) == IDYES)
{
removeAllBookmarks(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS));
for (i = 0; i < import.bookmarkCount; ++i)
{
hexBookmarks[i].address = import[i].address;
hexBookmarks[i].editmode = import[i].editmode;
strcpy(hexBookmarks[i].description, import[i].description);
memcpy(hexBookmarks.shortcuts, import.shortcuts, sizeof(hexBookmarks.shortcuts));
hexBookmarks.bookmarkCount = import.bookmarkCount;
hexBookmarks.shortcutCount = import.shortcutCount;
}
updateBookmarkMenus(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS));
UpdateColorTable();
}
}
else
{
// conflict bookmark count
int conflictBookmarkCount = 0;
// the conflict bookmark indexes of the main list
int conflictBookmarkIndex[64];
// conflict shortcut count
int conflictShortcutCount = 0;
// discarded bookmark count
int discardBookmarkCount = 0;
// bookmark that is out of scope
int outOfRangeBookmarkCount = 0;
// store the count of bookmarks after importing finished
int finalBookmarkCount = hexBookmarks.bookmarkCount;
// the reference index number in main bookmark list
// -1 means this bookmark is not be indexed
int indexRef[64];
memset(indexRef, -1, sizeof(indexRef));
for (i = 0; i < import.bookmarkCount; ++i)
{
bool conflict = false;
for (j = 0; j < hexBookmarks.bookmarkCount; ++j)
{
// to find if there are any conflict bookmarks
// currently, one address can have only one bookmark
// if the address and editmode are the same, then they are considered conflict
if (import[i].address == hexBookmarks[j].address && import[j].editmode == hexBookmarks[j].editmode)
{
conflictBookmarkIndex[conflictBookmarkCount] = i;
indexRef[i] = j;
++conflictBookmarkCount;
conflict = true;
break;
}
}
// after a loop, this bookmark doesn't have conflict with the original one
if (!conflict)
if (finalBookmarkCount >= 64)
// the total bookmark count has reached the limit of bookmarks (64),
// discard it
++discardBookmarkCount;
else if (import[j].address > GetMaxSize(import[j].editmode))
// the bookmark is out of valid range for current game,
// discard it.
++outOfRangeBookmarkCount;
else
{
// if the bookmark is still not discarded,
// then it's not a conflict one, append it to the last of the main list
indexRef[i] = finalBookmarkCount;
hexBookmarks[finalBookmarkCount].address = import[i].address;
hexBookmarks[finalBookmarkCount].editmode = import[i].editmode;
strcpy(hexBookmarks[finalBookmarkCount].description, import[i].description);
++finalBookmarkCount;
}
}
// the result of overwriting the shortcuts
int shortcutListOverwrite[10];
memcpy(shortcutListOverwrite, hexBookmarks.shortcuts, sizeof(hexBookmarks.shortcuts));
int shortcutListOverwriteCount = hexBookmarks.shortcutCount;
// the result of keep the shortcut as original
int shortcutListKeep[10];
memcpy(shortcutListKeep, hexBookmarks.shortcuts, sizeof(hexBookmarks.shortcuts));
int shortcutListKeepCount = hexBookmarks.shortcutCount;
for (i = 0; i < 10; ++i)
if (import.shortcuts[i] != -1)
{
bool repeat = false;
for (j = 0; j < 10; ++j)
if (indexRef[import.shortcuts[i]] == hexBookmarks.shortcuts[j] && i != j)
{
// the slot in the original list had this bookmark but different
// slot, remove the bookmark in the original slot
shortcutListOverwrite[j] = -1;
--shortcutListOverwriteCount;
++conflictShortcutCount;
repeat = true;
break;
}
if (shortcutListOverwrite[i] == -1)
++shortcutListOverwriteCount;
shortcutListOverwrite[i] = indexRef[import.shortcuts[i]];
// after a loop, the original list doesn't have a slot with same
// bookmark but different slot, and the slot in original list
// is empty, then the bookmark can occupy it.
if (!repeat && hexBookmarks.shortcuts[i] == -1)
{
shortcutListKeep[i] = indexRef[import.shortcuts[i]];
++shortcutListKeepCount;
}
}
int tmpImportBookmarkProps = importBookmarkProps;
bool continue_ = true;
// show the prompt message if there are conflicts
if (!(tmpImportBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT) && (conflictBookmarkCount || conflictShortcutCount))
{
char units[32];
strcpy(buffer, "The importing bookmark list has ");
sprintf(units, "%d duplicate bookmark", conflictBookmarkCount);
if (conflictBookmarkCount != 1)
strcat(units, "s");
strcat(buffer, units);
if (conflictShortcutCount)
{
if (conflictBookmarkCount) strcat(buffer, " and ");
sprintf(units, "%d conflict shortcut", conflictShortcutCount);
if (conflictShortcutCount != 1)
strcat(units, "s");
strcat(buffer, units);
}
strcat(buffer, " with yours.\r\nYou must choose which side would be reserved. Do you want to continue?");
continue_ = MessageBox(hwnd, buffer, "Bookmark conflict", MB_YESNO | MB_ICONEXCLAMATION) == IDYES && DialogBoxParam(fceu_hInstance, "IMPORTBOOKMARKOPTIONDIALOG", hwnd, importBookmarkCallB, (LPARAM)&tmpImportBookmarkProps);
if (tmpImportBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT)
importBookmarkProps = tmpImportBookmarkProps;
// in case user's mind changes on the fly
if (tmpImportBookmarkProps & IMPORT_DISCARD_ORIGINAL)
goto discard_original;
}
if (continue_)
{
if (tmpImportBookmarkProps & IMPORT_OVERWRITE_BOOKMARK)
// when it is set to overwrite conflicted bookmark, otherwise do nothing
for (i = 0; i < conflictBookmarkCount; ++i)
// the conflict bookmarks are all before the bookmark count in main list
strcpy(hexBookmarks[indexRef[conflictBookmarkIndex[i]]].description, import[conflictBookmarkIndex[i]].description);
// update the bookmark shortcut mapping
if (tmpImportBookmarkProps & IMPORT_OVERWRITE_SHORTCUT)
{
memcpy(hexBookmarks.shortcuts, shortcutListOverwrite, sizeof(hexBookmarks.shortcuts));
hexBookmarks.shortcutCount = shortcutListOverwriteCount;
}
else
{
memcpy(hexBookmarks.shortcuts, shortcutListKeep, sizeof(hexBookmarks.shortcuts));
hexBookmarks.shortcutCount = shortcutListKeepCount;
}
// set the count of the main list to the imported count
hexBookmarks.bookmarkCount = finalBookmarkCount;
updateBookmarkMenus(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS));
UpdateColorTable();
}
// tell user there are bookmarks that imported failed.
if (discardBookmarkCount || outOfRangeBookmarkCount)
{
char reason[64];
sprintf(buffer, "Import complete, but %d bookmark%s %s are not imported:\n", discardBookmarkCount + outOfRangeBookmarkCount, discardBookmarkCount + outOfRangeBookmarkCount == 1 ? "" : "s", discardBookmarkCount + outOfRangeBookmarkCount == 1 ? "is" : "are");
if (outOfRangeBookmarkCount)
{
sprintf(reason, "%d %s outside the valid address range of the game.", outOfRangeBookmarkCount, outOfRangeBookmarkCount == 1 ? "is" : "are");
strcat(buffer, reason);
}
if (discardBookmarkCount)
{
if (outOfRangeBookmarkCount)
strcat(buffer, "\n");
sprintf(reason, "%d %s discaded due to the list has reached its max limit (64).", discardBookmarkCount, discardBookmarkCount == 1 ? "is" : "are");
strcat(buffer, reason);
}
MessageBox(hwnd, buffer, "Loading Hex Editor bookmarks", MB_OK | MB_ICONEXCLAMATION);
}
}
}
else
MessageBox(hwnd, "An error occurred while loading bookmarks.", "Error loading bookmarks", MB_OK | MB_ICONERROR);
}
else
MessageBox(hwnd, "This file is not a Hex Editor bookmark list.", "Error loading bookmarks", MB_OK | MB_ICONERROR);
fclose(bld);
}
else
MessageBox(hwnd, "Error opening bookmark file", "Error loading bookmarks", MB_OK | MB_ICONERROR);
}
}
return 0;
case ID_BOOKMARKS_OPTION:
{
int tmpImportBookmarkProps = importBookmarkProps;
if (DialogBoxParam(fceu_hInstance, "IMPORTBOOKMARKOPTIONDIALOG", hwnd, importBookmarkCallB, (LPARAM)&tmpImportBookmarkProps))
importBookmarkProps = tmpImportBookmarkProps;
}
return 0;
case MENU_MV_HELP:
OpenHelpWindow(memviewhelp);
return 0;
@ -2282,10 +2501,6 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
case WM_CLOSE:
KillMemView();
//ReleaseDC (hwnd, mDC) ;
//DestroyWindow(hMemView);
//UnregisterClass("MEMVIEW",fceu_hInstance);
//hMemView = 0;
return 0;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
@ -2551,3 +2766,182 @@ void PalettePoke(uint32 addr, uint8 data)
PALRAM[addr] = data;
}
}
INT_PTR CALLBACK importBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static int* tmpImportBookmarkProps;
static HWND hTipMerge;
static HWND hTipIgnore;
static HWND hTipOverwrite;
static HWND hTipKeep;
static HWND hTipReassign;
static HWND hTipDiscard;
static HWND hTipConfirm;
switch (uMsg)
{
case WM_INITDIALOG:
CenterWindow(hwndDlg);
tmpImportBookmarkProps = (int*)lParam;
if (!(*tmpImportBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT))
CheckDlgButton(hwndDlg, IDC_CHECK_BOOKMARKIMPORTOPTION_CONFIRMEVERYTIMEONCONFLICT, BST_CHECKED);
if (*tmpImportBookmarkProps & IMPORT_DISCARD_ORIGINAL)
{
CheckDlgButton(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_DISCARD, BST_CHECKED);
EnableWindow(GetDlgItem(hwndDlg, IDC_GROUP_BOOKMARKIMPORTOPTION_SOLVECONFLICT), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_BOOKMARK), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_SHORTCUT), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN), FALSE);
}
else
{
CheckDlgButton(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_MERGE, BST_CHECKED);
EnableWindow(GetDlgItem(hwndDlg, IDC_GROUP_BOOKMARKIMPORTOPTION_SOLVECONFLICT), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_BOOKMARK), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_SHORTCUT), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN), TRUE);
}
if (*tmpImportBookmarkProps & IMPORT_OVERWRITE_BOOKMARK)
CheckDlgButton(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE, BST_CHECKED);
else
CheckDlgButton(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE, BST_CHECKED);
if (*tmpImportBookmarkProps & IMPORT_OVERWRITE_SHORTCUT)
CheckDlgButton(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN, BST_CHECKED);
else
CheckDlgButton(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP, BST_CHECKED);
TOOLINFO info;
memset(&info, 0, sizeof(TOOLINFO));
info.cbSize = sizeof(TOOLINFO);
info.uFlags = TTF_SUBCLASS | TTF_IDISHWND;
info.hwnd = hwndDlg;
hTipMerge = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, fceu_hInstance, NULL);
info.lpszText = "Merge the importing bookmarks into my list. \nThe non-conflict bookmarks will be append to the last. \nIf bookmarks or shortcuts have conflicts, \nsolve them according to the import settings.";
info.uId = (UINT_PTR)GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_MERGE);
SendMessage(hTipMerge, TTM_ADDTOOL, 0, (LPARAM)&info);
SendMessage(hTipMerge, TTM_SETMAXTIPWIDTH, 0, 8000);
SendMessage(hTipMerge, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
hTipIgnore = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, fceu_hInstance, NULL);
info.lpszText = "If the importing bookmark has the same address \nand edit mode with one of the original bookmarks,\nkeep the exsiting one unchanged.";
info.uId = (UINT_PTR)GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE);
SendMessage(hTipIgnore, TTM_ADDTOOL, 0, (LPARAM)&info);
SendMessage(hTipIgnore, TTM_SETMAXTIPWIDTH, 0, 8000);
SendMessage(hTipIgnore, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
hTipOverwrite = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, fceu_hInstance, NULL);
info.lpszText = "If the importing bookmark has the same address \nand edit mode with one of the existing bookmarks,\noverwrite the information of the existing one with the importing one.";
info.uId = (UINT_PTR)GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE);
SendMessage(hTipOverwrite, TTM_ADDTOOL, 0, (LPARAM)&info);
SendMessage(hTipOverwrite, TTM_SETMAXTIPWIDTH, 0, 8000);
SendMessage(hTipOverwrite, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
hTipKeep = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, fceu_hInstance, NULL);
info.lpszText = "If two different bookmarks from importing and existing \nuse the same shortcut,\nthe shortcut is remained using by the existing one.\nthe importing one will not use the shortcut.";
info.uId = (UINT_PTR)GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP);
SendMessage(hTipKeep, TTM_ADDTOOL, 0, (LPARAM)&info);
SendMessage(hTipKeep, TTM_SETMAXTIPWIDTH, 0, 8000);
SendMessage(hTipKeep, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
hTipReassign = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, fceu_hInstance, NULL);
info.lpszText = "If two different bookmarks from importing and existing \nuse the same shortcut,\nthe shortcut is assigned to the importing one.\nthe existing one will not use the shortcut.";
info.uId = (UINT_PTR)GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN);
SendMessage(hTipReassign, TTM_ADDTOOL, 0, (LPARAM)&info);
SendMessage(hTipReassign, TTM_SETMAXTIPWIDTH, 0, 8000);
SendMessage(hTipReassign, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
hTipDiscard = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, fceu_hInstance, NULL);
info.lpszText = "Discard all existing bookmarks and then import.\nThis is not recommended.";
info.uId = (UINT_PTR)GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_DISCARD);
SendMessage(hTipDiscard, TTM_ADDTOOL, 0, (LPARAM)&info);
SendMessage(hTipDiscard, TTM_SETMAXTIPWIDTH, 0, 8000);
SendMessage(hTipDiscard, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
hTipConfirm = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, fceu_hInstance, NULL);
info.lpszText = "Ask what to do every time when conflict occurs between existing and importing bookmarks.";
info.uId = (UINT_PTR)GetDlgItem(hwndDlg, IDC_CHECK_BOOKMARKIMPORTOPTION_CONFIRMEVERYTIMEONCONFLICT);
SendMessage(hTipConfirm, TTM_ADDTOOL, 0, (LPARAM)&info);
SendMessage(hTipConfirm, TTM_SETMAXTIPWIDTH, 0, 8000);
SendMessage(hTipConfirm, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
break;
case WM_CLOSE:
case WM_QUIT:
DestroyWindow(hTipMerge);
DestroyWindow(hTipIgnore);
DestroyWindow(hTipOverwrite);
DestroyWindow(hTipKeep);
DestroyWindow(hTipReassign);
DestroyWindow(hTipDiscard);
DestroyWindow(hTipConfirm);
EndDialog(hwndDlg, 0);
break;
case WM_COMMAND:
switch (HIWORD(wParam))
{
case BN_CLICKED:
switch (LOWORD(wParam))
{
case IDC_RADIO_BOOKMARKIMPORTOPTION_DISCARD:
EnableWindow(GetDlgItem(hwndDlg, IDC_GROUP_BOOKMARKIMPORTOPTION_SOLVECONFLICT), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_BOOKMARK), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_SHORTCUT), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN), FALSE);
break;
case IDC_RADIO_BOOKMARKIMPORTOPTION_MERGE:
EnableWindow(GetDlgItem(hwndDlg, IDC_GROUP_BOOKMARKIMPORTOPTION_SOLVECONFLICT), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_BOOKMARK), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_BOOKMARKIMPORTOPTION_SHORTCUT), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN), TRUE);
break;
case IDOK:
if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_BOOKMARKIMPORTOPTION_CONFIRMEVERYTIMEONCONFLICT) == BST_UNCHECKED)
*tmpImportBookmarkProps |= IMPORT_OVERWRITE_NO_PROMPT;
else
*tmpImportBookmarkProps &= ~IMPORT_OVERWRITE_NO_PROMPT;
if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_DISCARD))
*tmpImportBookmarkProps |= IMPORT_DISCARD_ORIGINAL;
if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_MERGE))
*tmpImportBookmarkProps &= ~IMPORT_DISCARD_ORIGINAL;
if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKOVERWRITE))
*tmpImportBookmarkProps |= IMPORT_OVERWRITE_BOOKMARK;
if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_BOOKMARKIGNORE))
*tmpImportBookmarkProps &= ~IMPORT_OVERWRITE_BOOKMARK;
if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTREASSIGN))
*tmpImportBookmarkProps |= IMPORT_OVERWRITE_SHORTCUT;
if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_BOOKMARKIMPORTOPTION_SHORTCUTKEEP))
*tmpImportBookmarkProps &= ~IMPORT_OVERWRITE_SHORTCUT;
EndDialog(hwndDlg, 1);
break;
case IDCANCEL:
case IDCLOSE:
EndDialog(hwndDlg, 0);
break;
}
}
}
return FALSE;
}

View File

@ -1,19 +1,23 @@
#ifndef MEMVIEW_H
#define MEMVIEW_H
void DoMemView();
void KillMemView();
void UpdateMemoryView(int draw_all);
void UpdateColorTable();
void ChangeMemViewFocus(int newEditingMode, int StartOffset,int EndOffset);
void UpdateCaption();
/*
int saveBookmarks(HWND hwnd);
int loadBookmarks(HWND hwnd);
*/
void ApplyPatch(int addr,int size, uint8* data);
void UndoLastPatch();
void SetHexEditorAddress(int gotoaddress);
int GetMaxSize(int editingMode);
extern HWND hMemView, hMemFind;
extern int EditingMode;
extern char EditString[4][20];
extern char* EditString[4];
#endif

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