diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..9b8cf68f3 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,90 @@ +name: build + +on: + push: + branches: [ "rainbow-stable", "master" ] + pull_request: + branches: [ "rainbow-stable", "master" ] + +env: + # Path to the solution file relative to the root of the project. + SOLUTION_FILE_PATH: vc\vc14_fceux.vcxproj + + # Configuration type to build. + # You can convert this to a build matrix if you need coverage of multiple configuration types. + # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + BUILD_CONFIGURATION: Release + +permissions: + contents: read + +jobs: + build-win64: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v3 + + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v1.1 + + - name: Build + working-directory: ${{env.GITHUB_WORKSPACE}} + run: cd pipelines ; .\win64_build.bat + + - uses: actions/upload-artifact@v3 + with: + name: fceux-win64 + path: vc\fceux-win64.zip + + build-win32: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v3 + + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v1.1 + + - name: Build + working-directory: ${{env.GITHUB_WORKSPACE}} + run: cd pipelines ; .\win32_build.bat + + - uses: actions/upload-artifact@v3 + with: + name: fceux-win32 + path: vc\fceux-win32.zip + + build-ubuntu64: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: build + run: pipelines/linux_build.sh + + - name: prepare_artifacts + run: mv /tmp/fceux-*.deb /tmp/fceux-ubuntu-x64.deb + + - uses: actions/upload-artifact@v3 + with: + name: fceux-ubuntu64 + path: /tmp/fceux-ubuntu-x64.deb + + build-macos: + runs-on: macos-latest + + steps: + - uses: actions/checkout@v3 + + - name: build + run: pipelines/macOS_build.sh + + - name: prepare_artifacts + run: mv build/fceux-*.dmg build/fceux-macos.dmg + + - uses: actions/upload-artifact@v3 + with: + name: fceux-macos + path: build/fceux-macos.dmg diff --git a/README b/README index 1d6a12b66..15afb3097 100644 --- a/README +++ b/README @@ -27,6 +27,7 @@ Table of Contents * qt5 OR qt6 - (qt version >= 5.11 recommended) - Required Qt Modules: Widgets and OpenGL - Optional Qt Modules: Help +* libcurl - Required for Rainbow mapper * liblua5.1 (optional) - Will statically link internally if the system cannot provide this. * libx264 (optional) - H.264 video encoder for avi recording (recommended) * libx265 (optional) - H.265 video encoder for avi recording (recommended) diff --git a/pipelines/linux_build.sh b/pipelines/linux_build.sh index 517d115ed..2b7154df2 100755 --- a/pipelines/linux_build.sh +++ b/pipelines/linux_build.sh @@ -118,6 +118,12 @@ echo 'Install Check Dependency cppcheck' echo '****************************************' sudo apt-get --assume-yes install cppcheck +# Install libcurl-dev +echo '****************************************' +echo 'Install Dependency libcurl-dev (libcurl4-gnutls-dev)' +echo '****************************************' +sudo apt-get --assume-yes install libcurl4-gnutls-dev + echo '**************************' echo '*** Building Project ***' echo '**************************' diff --git a/pipelines/macOS_build_rainbow.sh b/pipelines/macOS_build_rainbow.sh new file mode 100755 index 000000000..35084479e --- /dev/null +++ b/pipelines/macOS_build_rainbow.sh @@ -0,0 +1,127 @@ +#!/bin/bash + +echo ' MacOS Build !!! ' +id +pwd +uname -a +sw_vers + +# Oldest version of macOS that will be able to run, in two numbers, example 12.2 (default: let cmake choose the version) +MACOS_MIN_VERSION= + +QT_MAJOR=5; +QT_PKGNAME=qt$QT_MAJOR; +FCEUX_VERSION_MAJOR=2 +FCEUX_VERSION_MINOR=5 +FCEUX_VERSION_PATCH=0 +SDL2_VERSION=2.0.14 + +SCRIPT_DIR=$( cd $(dirname $BASH_SOURCE[0]); pwd ); + +NPROC=`getconf _NPROCESSORS_ONLN`; +echo "Number of Processors: $NPROC"; + +INSTALL_PREFIX=/tmp/fceux + +# Clean build and packaging directories +sudo rm -rf build; +sudo rm -rf $INSTALL_PREFIX/fceux.app; + +# Remove windows specific DLLs so that they don't get installed +find output -name *.dll -exec rm -f {} \; + +gcc --version + +echo '****************************************' +echo 'Install Dependency sdl2' +echo '****************************************' +brew install sdl2 +BREW_SDL2=$? +echo "brew install sdl2 Return: $BREW_SDL2"; +#sleep 10 +if [ $BREW_SDL2 != 0 ]; then + echo "brew install sdl2 FAILED: Attempted to build from $SDL2_VERSION release source"; + curl -o SDL2-$SDL2_VERSION.tar.gz https://www.libsdl.org/release/SDL2-$SDL2_VERSION.tar.gz + tar -xvf SDL2-$SDL2_VERSION.tar.gz + cd SDL2-$SDL2_VERSION; + ./configure --without-x --enable-hidapi + make -j $NPROC + make install + cd .. +fi + +echo '****************************************' +echo "Install Dependency $QT_PKGNAME" +echo '****************************************' +brew install $QT_PKGNAME + +echo '****************************************' +echo 'Install Dependency minizip' +echo '****************************************' +brew install minizip + +echo '****************************************' +echo 'Install Optional Dependency x264' +echo '****************************************' +brew install x264 + +echo '****************************************' +echo 'Install Optional Dependency x265' +echo '****************************************' +brew install x265 + +echo '****************************************' +echo 'Install Optional Dependency ffmpeg' +echo '****************************************' +brew install ffmpeg + +#brew install zlib # macOS provides zlib, brew half-install another version to avoid conflicts, but it is useless in our case + +export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig: + +ls -ltr $HOME/Qt; + +if [ $QT_MAJOR == 6 ]; then +export Qt6_DIR=`brew --prefix qt6`; +echo "Qt6_DIR=$Qt6_DIR"; +Qt_DIR=$Qt6_DIR; +USE_QT6=1; +else +export Qt5_DIR=`brew --prefix qt5`; +echo "Qt5_DIR=$Qt5_DIR"; +Qt_DIR=$Qt5_DIR; +USE_QT6=0; +fi +#ls $Qt_DIR; + +PATH=$PATH:$Qt_DIR/bin +echo '**************************' +echo '*** Building Project ***' +echo '**************************' +./scripts/unix_make_docs.sh; +mkdir build; +cd build; + +deploy_option= +if [ ! -z "$MACOS_MIN_VERSION" ]; then + deploy_option="-DCMAKE_OSX_DEPLOYMENT_TARGET=$MACOS_MIN_VERSION" +fi + +cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX \ + -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ + $deploy_option \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=$MACOS_MIN_VERSION \ + -DCMAKE_PREFIX_PATH=$Qt_DIR \ + -DCMAKE_PROJECT_VERSION_MAJOR=$FCEUX_VERSION_MAJOR \ + -DCMAKE_PROJECT_VERSION_MINOR=$FCEUX_VERSION_MINOR \ + -DCMAKE_PROJECT_VERSION_PATCH=$FCEUX_VERSION_PATCH \ + -DCPACK_PACKAGE_VERSION_MAJOR=$FCEUX_VERSION_MAJOR \ + -DCPACK_PACKAGE_VERSION_MINOR=$FCEUX_VERSION_MINOR \ + -DCPACK_PACKAGE_VERSION_PATCH=$FCEUX_VERSION_PATCH \ + -DQT6=$USE_QT6 \ + .. || exit 1 +make -j $NPROC || exit 1 +#sudo make install || exit 1 # make install is already run by cpack +sudo cpack -G DragNDrop || exit 1 diff --git a/pipelines/qwin64_build.bat b/pipelines/qwin64_build.bat index 2bbf5c0ae..e25a9a64e 100644 --- a/pipelines/qwin64_build.bat +++ b/pipelines/qwin64_build.bat @@ -2,8 +2,8 @@ set PROJECT_ROOT=%~dp0.. set CWD=%CD% -call "C:\Qt\5.15\msvc2019_64\bin\qtenv2.bat" -REM call "C:\Qt\6.0\msvc2019_64\bin\qtenv2.bat" +call "C:\Qt\5.15.0\msvc2019_64\bin\qtenv2.bat" +::call "C:\Qt\6.0\msvc2019_64\bin\qtenv2.bat" call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" cd /d %CWD% @@ -48,9 +48,33 @@ set LIBARCHIVE_INSTALL_PREFIX=%CD% set PUBLIC_RELEASE=0 IF DEFINED FCEU_RELEASE_VERSION (set PUBLIC_RELEASE=1) +if exist curl\ ( + goto skipCURL +) + +curl -s -LO https://curl.se/download/curl-7.79.0.zip + +REM rmdir /q /s curl + +powershell -command "Expand-Archive" curl-7.79.0.zip . + +cd curl-7.79.0/winbuild +set RTLIBCFG=static +nmake /f Makefile.vc mode=static debug=no +cd ../.. + +mkdir curl +xcopy "curl-7.79.0/builds/libcurl-vc-x64-release-static-ipv6-sspi-schannel/include" "curl/include" /E /I +xcopy "curl-7.79.0/builds/libcurl-vc-x64-release-static-ipv6-sspi-schannel/lib" "curl/lib" /E /I +rmdir curl-7.79.0 /S /Q + +:skipCURL + +set CURL_INSTALL_PREFIX=%CD% + REM cmake -h REM cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DSDL_INSTALL_PREFIX=%SDL_INSTALL_PREFIX% .. -cmake -DQT6=0 -DPUBLIC_RELEASE=%PUBLIC_RELEASE% -DSDL_INSTALL_PREFIX=%SDL_INSTALL_PREFIX% -DLIBARCHIVE_INSTALL_PREFIX=%LIBARCHIVE_INSTALL_PREFIX% -DUSE_LIBAV=1 -DFFMPEG_INSTALL_PREFIX=%FFMPEG_INSTALL_PREFIX% -G"Visual Studio 16" -T"v142" .. +cmake -DQT6=0 -DPUBLIC_RELEASE=%PUBLIC_RELEASE% -DSDL_INSTALL_PREFIX=%SDL_INSTALL_PREFIX% -DUSE_LIBAV=1 -DFFMPEG_INSTALL_PREFIX=%FFMPEG_INSTALL_PREFIX% -DCURL_INSTALL_PREFIX=%CURL_INSTALL_PREFIX% -G"Visual Studio 16" -T"v142" .. REM nmake msbuild /m fceux.sln /p:Configuration=Release diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0437eaff8..ca032c3d0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -52,11 +52,14 @@ if(WIN32) #add_definitions( /wd4018 ) # Integer comparison sign mismatch warnings include_directories( ${SDL_INSTALL_PREFIX}/SDL2/include ) include_directories( ${LIBARCHIVE_INSTALL_PREFIX}/libarchive/include ) + include_directories( ${CURL_INSTALL_PREFIX}/curl/include ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/drivers/win/zlib ) set( OPENGL_LDFLAGS OpenGL::GL ) set( SDL2_LDFLAGS ${SDL_INSTALL_PREFIX}/SDL2/lib/x64/SDL2.lib ) set( LIBARCHIVE_LDFLAGS ${LIBARCHIVE_INSTALL_PREFIX}/libarchive/lib/archive.lib ) + set( CURL_LIBRARIES ${CURL_INSTALL_PREFIX}/curl/lib/libcurl_a.lib ) set( SYS_LIBS wsock32 ws2_32 vfw32 Htmlhelp ) + set( CURL_SYS_LIBS Normaliz Wldap32 Crypt32 advapi32 ) #ws2_32 set(APP_ICON_RESOURCES_WINDOWS ${CMAKE_SOURCE_DIR}/icons/fceux.rc ) if ( ${USE_LIBAV} ) @@ -86,6 +89,7 @@ else(WIN32) find_package(PkgConfig REQUIRED) find_package(OpenGL REQUIRED) find_package(ZLIB REQUIRED) + find_package(CURL REQUIRED) add_definitions( -Wall -Wno-write-strings -Wno-parentheses -Wno-unused-local-typedefs -fPIC ) #add_definitions( -Wno-sign-compare ) # Integer comparison sign mismatch warnings @@ -201,6 +205,7 @@ else(WIN32) set( SYS_LIBS -lrt -lpthread -ldl) endif() endif() + set( CURL_SYS_LIBS ) endif(WIN32) @@ -498,6 +503,9 @@ set(SRC_CORE ${CMAKE_CURRENT_SOURCE_DIR}/boards/vrc7p.cpp ${CMAKE_CURRENT_SOURCE_DIR}/boards/yoko.cpp ${CMAKE_CURRENT_SOURCE_DIR}/boards/inx007t.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/boards/RNBW/pping.c + ${CMAKE_CURRENT_SOURCE_DIR}/boards/rainbow_esp.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/boards/rainbow.cpp ${CMAKE_CURRENT_SOURCE_DIR}/input/arkanoid.cpp ${CMAKE_CURRENT_SOURCE_DIR}/input/bworld.cpp ${CMAKE_CURRENT_SOURCE_DIR}/input/cursor.cpp @@ -671,7 +679,9 @@ target_link_libraries( ${APP_NAME} ${OPENGL_LDFLAGS} ${SDL2_LDFLAGS} ${MINIZIP_LDFLAGS} ${ZLIB_LIBRARIES} ${LIBARCHIVE_LDFLAGS} + ${CURL_LIBRARIES} ${LUA_LDFLAGS} ${X264_LDFLAGS} ${X265_LDFLAGS} ${LIBAV_LDFLAGS} + ${CURL_SYS_LIBS} ${SYS_LIBS} ) diff --git a/src/boards/RNBW/bootrom_chr.h b/src/boards/RNBW/bootrom_chr.h new file mode 100644 index 000000000..63d42c313 --- /dev/null +++ b/src/boards/RNBW/bootrom_chr.h @@ -0,0 +1,258 @@ +const unsigned char bootrom_chr[4096] = { +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7E,0x81,0xA5,0x81,0xBD,0x99,0x81,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7E,0xFF,0xDB,0xFF,0xC3,0xE7,0xFF,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x6C,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x38,0x7C,0x38,0xFE,0xFE,0xD6,0x10,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x03,0x0F,0x1C,0x30,0x30,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0xC0,0xF0,0x3A,0x1E,0x0E,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x1C,0x1C,0x1C,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x44,0xC6,0xC6,0xFE,0x7C,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x0D,0x0D,0x00,0x0F,0xDF,0xD8,0x1B,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xB0,0xB0,0x00,0xF0,0xFB,0x1B,0xD8,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x0F,0x1F,0x38,0x75,0x65,0x65,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFE,0xFE,0x06,0x56,0x56,0x56,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7F,0x63,0x7F,0x63,0x63,0x67,0xE6,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x99,0x5A,0x3C,0xE7,0xE7,0x3C,0x5A,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x80,0xE0,0xF8,0xFE,0xF8,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x02,0x0E,0x3E,0xFE,0x3E,0x0E,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x3C,0x7E,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7F,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7E,0xC3,0x78,0xCC,0xCC,0x78,0x8C,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x60,0x60,0x30,0x30,0x1C,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x0C,0x0C,0x38,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x08,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x38,0x38,0x38,0x38,0x38,0x28,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xDB,0x1B,0xD8,0xDF,0x0F,0x00,0x0D,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xDB,0xD8,0x1B,0xFB,0xF0,0x00,0xB0,0xB0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x60,0x60,0x60,0x60,0x60,0x7F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x06,0x06,0x06,0x06,0x06,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0xFF,0xFF,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x7C,0xC0,0x78,0x0C,0xF8,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0xC6,0xCC,0x18,0x30,0x66,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x38,0x6C,0x38,0x76,0xDC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x60,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x30,0x60,0x60,0x60,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x60,0x30,0x18,0x18,0x18,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x70,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0xCC,0xDC,0xFC,0xEC,0xCC,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0xF0,0x30,0x30,0x30,0x30,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0xCC,0x0C,0x38,0x60,0xCC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0xCC,0x0C,0x38,0x0C,0xCC,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFC,0xC0,0xF8,0x0C,0x0C,0xCC,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x38,0x60,0xC0,0xF8,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFC,0xCC,0x0C,0x18,0x30,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0xCC,0xCC,0x78,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0xCC,0xCC,0x7C,0x0C,0x18,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x30,0x30,0x00,0x70,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x30,0x60,0xC0,0x60,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xFC,0x00,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0xCC,0x0C,0x18,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7C,0xC6,0xDE,0xDE,0xDE,0xC0,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x78,0xCC,0xCC,0xFC,0xCC,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFC,0x66,0x66,0x7C,0x66,0x66,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x3C,0x66,0xC0,0xC0,0xC0,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFC,0x6C,0x66,0x66,0x66,0x6C,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFE,0x62,0x68,0x78,0x68,0x62,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFE,0x62,0x68,0x78,0x68,0x60,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x3C,0x66,0xC0,0xC0,0xCE,0x66,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xCC,0xCC,0xCC,0xFC,0xCC,0xCC,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x1E,0x0C,0x0C,0x0C,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xE6,0x66,0x6C,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xF0,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xC6,0xEE,0xFE,0xD6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xC6,0xE6,0xF6,0xDE,0xCE,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFC,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0xCC,0xCC,0xCC,0xDC,0x78,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFC,0x66,0x66,0x7C,0x78,0x6C,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0xCC,0xE0,0x38,0x1C,0xCC,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFC,0xB4,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xCC,0xCC,0xCC,0x78,0x30,0x30,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFE,0xCC,0x98,0x30,0x62,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0x60,0x60,0x60,0x60,0x60,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xC0,0x60,0x30,0x18,0x0C,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0x18,0x18,0x18,0x18,0x18,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x78,0x0C,0x7C,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xE0,0x60,0x7C,0x66,0x66,0x66,0xBC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x78,0xCC,0xC0,0xCC,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x1C,0x0C,0x0C,0x7C,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x78,0xCC,0xFC,0xC0,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x38,0x6C,0x60,0xF0,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xE0,0x60,0x6C,0x76,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x00,0x70,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x00,0x78,0x18,0x18,0x18,0xD8,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xE0,0x60,0x66,0x6C,0x78,0x6C,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x70,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xEC,0xFE,0xD6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xF8,0xCC,0xCC,0xCC,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x78,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xDC,0x66,0x66,0x7C,0x60,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xD8,0x6C,0x6C,0x60,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x7C,0xC0,0x78,0x0C,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x10,0x30,0x7C,0x30,0x30,0x34,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xCC,0xCC,0xCC,0x78,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xC6,0xC6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xC6,0x6C,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xCC,0xCC,0xCC,0x7C,0x0C,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xFC,0x98,0x30,0x64,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x1C,0x30,0x30,0xE0,0x30,0x30,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xE0,0x30,0x30,0x1C,0x30,0x30,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x03,0x0F,0x1E,0x3E,0x3F,0x7E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0xC0,0xF0,0x78,0x7C,0xFC,0x7E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x07,0x1F,0x3F,0x78,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xE0,0xF8,0xFC,0x1E,0x06,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x20,0x70,0xF8,0x7C,0x3F,0x1F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x08,0x1C,0x3E,0x7C,0xF8,0xF0,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x03,0x05,0x0E,0x1C,0x38,0x70,0xE0,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x51,0x71,0x71,0x71,0x7F,0x71,0x7F,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFA,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x3F,0x07,0x0F,0x1D,0x39,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x23,0x27,0x2E,0x3C,0x38,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xC0,0x47,0x47,0xE7,0x00,0x00,0xE0,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x01,0x02,0x02,0x04,0x04,0x04,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x70,0x8C,0x02,0x32,0x81,0x01,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7E,0x7E,0x3E,0x3E,0x1F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7E,0x7E,0x7C,0x7C,0xF8,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x83,0x87,0x0C,0x08,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xC1,0xE1,0x30,0x10,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x0F,0x1F,0x3F,0x7C,0xF8,0x70,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xE0,0xF0,0xF8,0x7C,0x3E,0x1C,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x27,0x53,0xA9,0x54,0x2A,0x15,0x0A,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x80,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7F,0x71,0x7F,0x31,0x3F,0x31,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFE,0xFE,0xFE,0xFC,0xFC,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x44,0xEE,0x7C,0x38,0x7C,0xEE,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x08,0x14,0x22,0x14,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x47,0xE7,0x00,0x00,0xE0,0x47,0x27,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x02,0x05,0x0E,0x1C,0x38,0x70,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x02,0x8C,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x3C,0x7C,0xFF,0xFF,0x80,0x80,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xF8,0xF8,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x3C,0xFC,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,0x40,0x82,0x00,0x00,0xFF,0x00,0x00,0x00, +0x00,0x00,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00, +0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xC0,0x60,0x70,0x78,0x3C,0x04,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x3F,0x3F,0x3F,0x3F,0x3F,0x3E,0x3E,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xC0,0xE0,0xF0,0xF8,0xFC,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x01,0x01,0x03,0x02,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x80,0x80,0xC0,0x40,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x3F,0x7E,0x7E,0x7E,0x7E,0x7E,0x7E,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFC,0x7E,0x7E,0x7E,0x7E,0x7E,0x7E,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x3F,0x7C,0x79,0x7F,0x7F,0x7E,0x7E,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFC,0x3E,0x9E,0x9E,0x3E,0x7E,0x7E,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x04,0x3F,0x7F,0x00,0x35,0x35,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xF0,0x10,0xFE,0xFF,0x00,0x56,0x56,0x56,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x1F,0x1F,0x3F,0x3F,0x3F,0x3F,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFE,0xFE,0xFE,0xFC,0xFC,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x3F,0x30,0x3F,0x30,0x3F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x0C,0xFC,0x0C,0xFC,0x0C,0xFC,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x30,0x30,0x3E,0x3E,0x3E,0x3F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x0C,0x0C,0x7C,0x7C,0x7C,0xFC,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x0E,0x0E,0x1E,0x1F,0x3E,0x3E,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x70,0x70,0x78,0xF8,0x7C,0x7C,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7E,0x7E,0x7F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7E,0x7E,0xFE,0xFC,0xF8,0x38,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7E,0x7E,0x7F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7E,0x7E,0xFE,0xFC,0xF8,0x38,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x35,0x35,0x35,0x35,0x35,0x35,0x3F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x56,0x56,0x56,0x56,0x56,0x56,0xFE,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x0C,0x1E,0x3E,0x38,0x70,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x01,0x07,0x08,0x10,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0xE0,0xF8,0x3C,0x1E,0x0E,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xFF,0xFF,0xFE,0xFC,0xF8,0xF1,0xE3,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x08,0x1E,0x33,0x73,0xFE,0xFC,0xF8,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x1E,0x18,0x18,0x18,0x18,0x18,0x18,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x1A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x03,0x07,0x2E,0xFC,0xF8,0xFC,0x78,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x1C,0x0F,0x0F,0x1C,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x3F,0x3F,0x3F,0x3F,0x3E,0x3E,0x3F,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xC0,0xE0,0xF0,0xF8,0x7C,0x7C,0xFC,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x60,0x20,0x20,0x10,0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xE7,0xE1,0xC5,0xC8,0xC0,0xE3,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xE0,0xC0,0x80,0x10,0x30,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x1C,0x3E,0x1F,0x1F,0x3F,0x72,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x38,0xF0,0xF0,0x38,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x3E,0x3E,0x3E,0x3E,0x3E,0x3F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7C,0x7C,0x7C,0x7C,0x7C,0xFC,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x17,0x16,0x36,0x36,0x30,0x1F,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x79,0xB6,0x32,0xBA,0x32,0x78,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x02,0x82,0x84,0x84,0x88,0x88,0x80,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x11,0x9C,0x1E,0x0F,0x1F,0x5F,0x3F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xC0,0xE4,0xF0,0xFC,0xFE,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x40,0x40,0x20,0x20,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x01,0x03,0x03,0x07,0xFF,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x80,0x80,0xC0,0xFE,0xFE,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x0F,0x18,0x30,0x67,0xCC,0x98,0x91,0x93,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xE0,0x30,0x18,0xCC,0x66,0x32,0x12,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x07,0x1F,0x3E,0x77,0x6F,0xFE,0xDC,0xD0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xE0,0xF8,0x7C,0xBE,0xBE,0x17,0x07,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x20,0x70,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x04,0x0E,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x0E,0x67,0xF3,0x50,0x02,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xE7,0x06,0xF8,0x00,0x04,0x03,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x2C,0x2C,0x38,0x00,0x00,0xE0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x10,0x10,0x00,0x7F,0x9F,0x97,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x08,0x08,0x00,0xFE,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x02,0x02,0x04,0x04,0x04,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x3F,0x1F,0x1F,0x1F,0x3F,0x3F,0x78,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xF8,0xF0,0xF0,0xF0,0xF8,0xF8,0x3C,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x91,0x00,0x03,0x07,0x07,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x12,0x00,0x80,0xC0,0xC0,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xC8,0xC4,0xE6,0x67,0x73,0x3E,0x1F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x1F,0x1F,0x07,0x86,0x8E,0x3C,0xF8,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x1E,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x80,0xC0,0xE0,0xF0,0x70,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x01,0x03,0x07,0x0F,0x0E,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; \ No newline at end of file diff --git a/src/boards/RNBW/pping.c b/src/boards/RNBW/pping.c new file mode 100644 index 000000000..8f45eb739 --- /dev/null +++ b/src/boards/RNBW/pping.c @@ -0,0 +1,442 @@ +/* Portable Ping, pinging made easy + * + * PPing is a C library allowing to make ping requests. It aims at being + * and avoid requiring non-necessary privileges. As such, you can use the same + * simple interface on Linux, Windows and OSX without requiring root or + * administrator permissions. + * + * It also comes without dependencies outside of standard system libraries, + * no include path, nor library to install. + * + * If you want a header-only version, just include the .c + * + * Author: Sylvain Gadrat + * License: WTFPL v2 (except copy-pasted parts from random locations, they are the property of their authors) + */ + +/* How does it work? + * + * This lib knows three ways to emit ping requests: raw socket, icmp socket and IcmpSendEcho. + * + * - raw socket: universally supported, but requires root/administrator privileges. + * - icmp socket: supported by Linux and some other Unix, does not require root privileges. + * - IcmpSendEcho: supported by Windows (since Windows 2000 and Windows XP), does not require administrator privileges. + * + * The lib selects its implementation based on whatever works. + */ + +#ifdef PPING_DEBUG +# define PPING_DBG(...) fprintf(stderr, __VA_ARGS__) +#else +# define PPING_DBG(...) +#endif + +#include +#include +#include +#include +#include + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) + // include network API +# include // Most network things +# include // getnameinfo and socket_len_t +# pragma comment(lib, "Ws2_32.lib") // Something related to linking + + // IcmpSendEcho +# include +# include +# pragma comment(lib, "iphlpapi.lib") //FIXME better link dynimically with this one: the lib name is not the same on all windows + + // If the OS doesn't declare it, do it ourself (copy-pasted from GNU C Library, license: LGPL) +# include + struct icmphdr + { + uint8_t type; /* message type */ + uint8_t code; /* type sub-code */ + uint16_t checksum; + union + { + struct + { + uint16_t id; + uint16_t sequence; + } echo; /* echo datagram */ + uint32_t gateway; /* gateway address */ + struct + { + uint16_t __unused; + uint16_t mtu; + } frag; /* path mtu discovery */ + /*uint8_t reserved[4];*/ + } un; + }; + + // If the OS doesn't declare it, do it ourself +# define ICMP_ECHO 8 + + // Fix slightly changed names +# define SOL_IP IPPROTO_IP + + // Beloved bzero +# define bzero(b,len) (memset((b), '\0', (len)), (void) 0) + + // Init networking + static int net_init(void) { + WSADATA wsa_data; + if (WSAStartup(MAKEWORD(2, 2), &wsa_data)) { + PPING_DBG("WSA init failed\n"); + return 1; + } + return 0; + } + + // Same API but not the same type for byte pointers + static char* net_payload(void* p) { + return (char*)p; + } + + // errno underused on Windows + static void merror(char const* m) { + //TODO get a description of the error, in the meantime go check it here https://docs.microsoft.com/fr-fr/windows/win32/winsock/windows-sockets-error-codes-2 + PPING_DBG("%s: error %d\n", m, WSAGetLastError()); + } + +#else +#ifdef __APPLE__ + + // If the OS doesn't declare it, do it ourself (copy-pasted from GNU C Library, license: LGPL) +# include + struct icmphdr + { + uint8_t type; /* message type */ + uint8_t code; /* type sub-code */ + uint16_t checksum; + union + { + struct + { + uint16_t id; + uint16_t sequence; + } echo; /* echo datagram */ + uint32_t gateway; /* gateway address */ + struct + { + uint16_t unused; + uint16_t mtu; + } frag; /* path mtu discovery */ + /*uint8_t reserved[4];*/ + } un; + }; + + // Fix slightly changed names +# define SOL_IP IPPROTO_IP + +#endif + +# include +# include +# include +# include +# include +# include +# include + + static int net_init(void) { return 0; } + static void* net_payload(void* p) { return p; } + static void merror(char const* m) { +# ifdef PPING_DEBUG + perror(m); +# endif + } +#endif + +// Define the Packet Constants ping packet size +#define PING_PKT_S 64 + +// Automatic port number +#define PORT_NO 0 + +// Gives the timeout delay for receiving packets in seconds +#define RECV_TIMEOUT 1 + +// Length to reserve for IP header when manipulating RAW sockets +// Note: That's the minimal and typical length, actual length is stored in byte 0 if the IP header. +// Not sure if the case of a larger header can happen. +#define IP_HEADER_LEN 20 + +#ifdef __cplusplus +extern "C" { +#endif + +struct ping_pkt { + char fill[IP_HEADER_LEN]; // Let at least enough space for an IP header (there may be padding after this field, don't use it to parse IP header) + struct icmphdr hdr; + char msg[PING_PKT_S-sizeof(struct icmphdr)]; +}; + +struct pping_s { + struct sockaddr_in addr; + int socket; + int socket_is_raw; + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) + HANDLE icmp_file; +#endif +}; + +// Shamelessly copy-pasted from https://www.geeksforgeeks.org/ping-in-c/ +static unsigned short checksum(void *b, int len) { + unsigned short *buf = (unsigned short *)b; + unsigned int sum = 0; + unsigned short result; + + for (sum = 0; len > 1; len -= 2) { + sum += *buf++; + } + if (len == 1) { + sum += *(unsigned char*)buf; + } + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + result = ~sum; + return result; +} + +static int dns_lookup(char const*addr_host, struct sockaddr_in *addr_con) { + struct hostent *he; + + he = gethostbyname(addr_host); + if (he == NULL) { + merror("failed to resolve host"); + return 1; + } + + addr_con->sin_family = he->h_addrtype; + addr_con->sin_port = htons(PORT_NO); + addr_con->sin_addr.s_addr = *(long*)he->h_addr; + return 0; +} + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) +// Windows specific ping implementation +static int pping_ping_icmp_send_echo(HANDLE icmp_file, struct sockaddr_in *ping_addr) { + unsigned long ipaddr = ping_addr->sin_addr.s_addr; + DWORD r = 0; + char ping_msg[PING_PKT_S]; + LPVOID reply_buffer = NULL; + DWORD reply_size = 0; + size_t i; + + for (i = 0; i < sizeof(ping_msg)-1; i++) { + ping_msg[i] = i+'0'; + } + ping_msg[i] = 0; + + reply_size = sizeof(ICMP_ECHO_REPLY) + sizeof(ping_msg); + reply_buffer = (VOID*) malloc(reply_size); + if (reply_buffer == NULL) { + PPING_DBG("failed to allocate reply buffer\n"); + return 1; + } + + + r = IcmpSendEcho( + icmp_file, ipaddr, + ping_msg, sizeof(ping_msg), + NULL, + reply_buffer, reply_size, + RECV_TIMEOUT * 1000 + ); + if (r == 0) { + free(reply_buffer); + if (GetLastError() == WSA_QOS_ADMISSION_FAILURE) { + return 2; + }else { + PPING_DBG("IcmpSendEcho error: %ld\n", GetLastError()); + return 1; + } + } + + free(reply_buffer); + return 0; +} +#endif + +static int pping_ping_posix(int ping_sockfd, struct sockaddr_in *ping_addr, int sock_is_raw) { + int ttl_val=56, i; + unsigned int addr_len; + + struct ping_pkt pckt; + struct sockaddr_in r_addr; + struct timeval tv_out; + tv_out.tv_sec = RECV_TIMEOUT; + tv_out.tv_usec = 0; + + // Set socket TTL + if (setsockopt(ping_sockfd, SOL_IP, IP_TTL, net_payload(&ttl_val), sizeof(ttl_val)) != 0) { + PPING_DBG("failed to set TTL\n"); + return 1; + } + + // Craft ICMP echo request + bzero(&pckt, sizeof(pckt)); + + pckt.hdr.type = ICMP_ECHO; + if (sock_is_raw) { + pckt.hdr.un.echo.id = getpid(); + }else { + pckt.hdr.un.echo.id = 0; + } + + for (i = 0; i < sizeof(pckt.msg)-1; i++) { + pckt.msg[i] = i+'0'; + } + + pckt.msg[i] = 0; + pckt.hdr.un.echo.sequence = 0; // TODO may be configurable + pckt.hdr.checksum = checksum(&pckt.hdr, sizeof(pckt.hdr) + sizeof(pckt.msg)); + + // Send request + if (sendto(ping_sockfd, net_payload(&pckt.hdr), sizeof(pckt.hdr) + sizeof(pckt.msg), 0, (struct sockaddr*) ping_addr, sizeof(*ping_addr)) <= 0) { + perror("send failed"); + return 1; + } + + // Wait for packet + setsockopt(ping_sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv_out, sizeof tv_out); + + char* rcv_buf = (char*)&pckt.hdr; + size_t rcv_buf_len = sizeof(pckt.hdr) + sizeof(pckt.msg); +#ifndef __APPLE__ + if (sock_is_raw) { +#else + { +#endif + rcv_buf -= IP_HEADER_LEN; + rcv_buf_len += IP_HEADER_LEN; + } + + addr_len = sizeof(r_addr); + if (recvfrom(ping_sockfd, net_payload(rcv_buf), rcv_buf_len, 0, (struct sockaddr*)&r_addr, &addr_len) <= 0) { +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) + int timeout_error = (WSAGetLastError() == WSAETIMEDOUT); +#else + int timeout_error = (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS); +#endif + if (timeout_error) { + return 2; + }else { + merror("packet receive failed"); + return 1; + } + } + + // Check received packet + //TODO Check sequence number + if(!(pckt.hdr.type == 0 && pckt.hdr.code == 0)) { + PPING_DBG("Error..Packet received with ICMP type %d code %d\n", pckt.hdr.type, pckt.hdr.code); + return 1; + } + + return 0; +} + +struct pping_s* pping_init(char const* addr) { + struct pping_s* pping; + int skip_socket_creation; + + // Sanity check + if (addr == NULL) { + PPING_DBG("empty address\n"); + return NULL; + } + + // Winsock initialization + if (net_init() != 0) { + return NULL; + } + + // Allocate pping + pping = (struct pping_s*)malloc(sizeof(struct pping_s)); + pping->socket = -1; + pping->socket_is_raw = 0; +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) + pping->icmp_file = INVALID_HANDLE_VALUE; +#endif + + // DNS lookup + if (dns_lookup(addr, &pping->addr)) { + merror("DNS lookup failed"); + free(pping); + return NULL; + } + + // ICMP file creation + skip_socket_creation = 0; +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) + pping->icmp_file = IcmpCreateFile(); + if (pping->icmp_file == INVALID_HANDLE_VALUE) { + PPING_DBG("failed to open icmp file, fallback to posix implementation (you will need administrator privilege): %ld\n", GetLastError()); + }else { + skip_socket_creation = 1; + } +#endif + + // Socket creation + if (!skip_socket_creation) { + pping->socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); + if (pping->socket < 0) { + pping->socket_is_raw = 1; + pping->socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (pping->socket < 0) { + merror("failed to create socket"); + } + } + + if (pping->socket >= 0) { + PPING_DBG("socket created raw=%d\n", pping->socket_is_raw); + } + } + + return pping; +} + +int pping_ping(struct pping_s* pping) { +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) + // IcmpSendEcho implementation + if (pping->icmp_file != INVALID_HANDLE_VALUE) { + return pping_ping_icmp_send_echo(pping->icmp_file, &pping->addr); + } +#endif + + // Posix socket implementations + if (pping->socket >= 0) { + return pping_ping_posix(pping->socket, &pping->addr, pping->socket_is_raw); + } + + // Out of idea + PPING_DBG("no usable ping implementation found\n"); + return 1; +} + +void pping_free(struct pping_s* pping) { + free(pping); +} + +int pping_easy_ping(char const* addr) { + struct pping_s* pping; + int r; + + pping = pping_init(addr); + if (pping == NULL) { + return 1; + } + r = pping_ping(pping); + pping_free(pping); + return r; +} + +#ifdef __cplusplus +} +#endif diff --git a/src/boards/RNBW/pping.h b/src/boards/RNBW/pping.h new file mode 100644 index 000000000..f519edd6c --- /dev/null +++ b/src/boards/RNBW/pping.h @@ -0,0 +1,63 @@ +#ifndef PPING_H +#define PPING_H + +/* Portable Ping, pinging made easy + * + * PPing is a C library allowing to make ping requests. It aims at being + * and avoid requiring non-necessary privileges. As such, you can use the same + * simple interface on Linux, Windows and OSX without requiring root or + * administrator permissions. + * + * It also comes without dependencies outside of standard system libraries, + * no include path, nor library to install. + * + * If you want a header-only version, just include the .c + * + * Author: Sylvain Gadrat + * License: WTFPL v2 + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Ping an address, return after receiving the response + * @return 0: success ; 1 failure ; 2 timeout + * + * Can resolve domain name, beware that it will take significant time. Avoid + * using it (especially with a domain name) to measure round trip time. + */ +int pping_easy_ping(char const* addr); + +/* More complete API + * + * Usage example: + * void my_ping_func() { + * struct pping_s* pping; + * int result; + * + * pping = pping_init("example.com"); + * + * r = pping_ping(pping); + * if (r != 0) printf("lost first packet\n"); + * r = pping_ping(pping); + * if (r != 0) printf("lost second packet\n"); + * // ... + * + * pping_free(pping); + * } + * + * Notes: + * Time consuming tasks (like DNS resolution) are done in pping_init(). + * Time spent in pping_ping() is near the round trip time + */ +struct pping_s; +struct pping_s* pping_init(const char* addr); +int pping_ping(struct pping_s* pping); +void pping_free(struct pping_s* pping); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/boards/mmc5.cpp b/src/boards/mmc5.cpp index 82095f045..5bf9d2a4e 100644 --- a/src/boards/mmc5.cpp +++ b/src/boards/mmc5.cpp @@ -40,46 +40,50 @@ void MMC5RunSoundHQ(void); static INLINE void MMC5SPRVROM_BANK1(uint32 A, uint32 V) { if (CHRptr[0]) { V &= CHRmask1[0]; - MMC5SPRVPage[(A) >> 10] = &CHRptr[0][(V) << 10] - (A); + MMC5SPRVPage[(A) >> 9] = MMC5SPRVPage[((A) >> 9) + 1] = &CHRptr[0][(V) << 10] - (A); } } static INLINE void MMC5BGVROM_BANK1(uint32 A, uint32 V) { if (CHRptr[0]) { - V &= CHRmask1[0]; MMC5BGVPage[(A) >> 10] = &CHRptr[0][(V) << 10] - (A); + V &= CHRmask1[0]; MMC5BGVPage[(A) >> 9] = MMC5BGVPage[((A) >> 9) + 1] = &CHRptr[0][(V) << 10] - (A); } } static INLINE void MMC5SPRVROM_BANK2(uint32 A, uint32 V) { if (CHRptr[0]) { - V &= CHRmask2[0]; MMC5SPRVPage[(A) >> 10] = MMC5SPRVPage[((A) >> 10) + 1] = &CHRptr[0][(V) << 11] - (A); + V &= CHRmask2[0]; MMC5SPRVPage[(A) >> 9] = MMC5SPRVPage[((A) >> 9) + 1] = MMC5SPRVPage[((A) >> 9) + 2] = MMC5SPRVPage[((A) >> 9) + 3] = &CHRptr[0][(V) << 11] - (A); } } static INLINE void MMC5BGVROM_BANK2(uint32 A, uint32 V) { if (CHRptr[0]) { - V &= CHRmask2[0]; MMC5BGVPage[(A) >> 10] = MMC5BGVPage[((A) >> 10) + 1] = &CHRptr[0][(V) << 11] - (A); + V &= CHRmask2[0]; MMC5BGVPage[(A) >> 9] = MMC5BGVPage[((A) >> 9) + 1] = MMC5BGVPage[((A) >> 9) + 2] = MMC5BGVPage[((A) >> 9) + 3] = &CHRptr[0][(V) << 11] - (A); } } static INLINE void MMC5SPRVROM_BANK4(uint32 A, uint32 V) { if (CHRptr[0]) { - V &= CHRmask4[0]; MMC5SPRVPage[(A) >> 10] = MMC5SPRVPage[((A) >> 10) + 1] = MMC5SPRVPage[((A) >> 10) + 2] = MMC5SPRVPage[((A) >> 10) + 3] = &CHRptr[0][(V) << 12] - (A); + V &= CHRmask4[0]; MMC5SPRVPage[(A) >> 9] = MMC5SPRVPage[((A) >> 9) + 1] = MMC5SPRVPage[((A) >> 9) + 2] = MMC5SPRVPage[((A) >> 9) + 3] = + MMC5SPRVPage[((A) >> 9) + 4] = MMC5SPRVPage[((A) >> 9) + 5] = MMC5SPRVPage[((A) >> 9) + 6] = MMC5SPRVPage[((A) >> 9) + 7] = &CHRptr[0][(V) << 12] - (A); } } static INLINE void MMC5BGVROM_BANK4(uint32 A, uint32 V) { if (CHRptr[0]) { - V &= CHRmask4[0]; MMC5BGVPage[(A) >> 10] = MMC5BGVPage[((A) >> 10) + 1] = MMC5BGVPage[((A) >> 10) + 2] = MMC5BGVPage[((A) >> 10) + 3] = &CHRptr[0][(V) << 12] - (A); + V &= CHRmask4[0]; MMC5BGVPage[(A) >> 9] = MMC5BGVPage[((A) >> 9) + 1] = MMC5BGVPage[((A) >> 9) + 2] = MMC5BGVPage[((A) >> 9) + 3] = + MMC5BGVPage[((A) >> 9) + 4] = MMC5BGVPage[((A) >> 9) + 5] = MMC5BGVPage[((A) >> 9) + 6] = MMC5BGVPage[((A) >> 9) + 7] = &CHRptr[0][(V) << 12] - (A); } } static INLINE void MMC5SPRVROM_BANK8(uint32 V) { if (CHRptr[0]) { - V &= CHRmask8[0]; MMC5SPRVPage[0] = MMC5SPRVPage[1] = MMC5SPRVPage[2] = MMC5SPRVPage[3] = MMC5SPRVPage[4] = MMC5SPRVPage[5] = MMC5SPRVPage[6] = MMC5SPRVPage[7] = &CHRptr[0][(V) << 13]; + V &= CHRmask8[0]; MMC5SPRVPage[0] = MMC5SPRVPage[1] = MMC5SPRVPage[2] = MMC5SPRVPage[3] = MMC5SPRVPage[4] = MMC5SPRVPage[5] = MMC5SPRVPage[6] = MMC5SPRVPage[7] = + MMC5SPRVPage[8] = MMC5SPRVPage[9] = MMC5SPRVPage[10] = MMC5SPRVPage[11] = MMC5SPRVPage[12] = MMC5SPRVPage[13] = MMC5SPRVPage[14] = MMC5SPRVPage[15] = &CHRptr[0][(V) << 13]; } } static INLINE void MMC5BGVROM_BANK8(uint32 V) { if (CHRptr[0]) { - V &= CHRmask8[0]; MMC5BGVPage[0] = MMC5BGVPage[1] = MMC5BGVPage[2] = MMC5BGVPage[3] = MMC5BGVPage[4] = MMC5BGVPage[5] = MMC5BGVPage[6] = MMC5BGVPage[7] = &CHRptr[0][(V) << 13]; + V &= CHRmask8[0]; MMC5BGVPage[0] = MMC5BGVPage[1] = MMC5BGVPage[2] = MMC5BGVPage[3] = MMC5BGVPage[4] = MMC5BGVPage[5] = MMC5BGVPage[6] = MMC5BGVPage[7] = + MMC5BGVPage[8] = MMC5BGVPage[9] = MMC5BGVPage[10] = MMC5BGVPage[11] = MMC5BGVPage[12] = MMC5BGVPage[13] = MMC5BGVPage[14] = MMC5BGVPage[15] = &CHRptr[0][(V) << 13]; } } @@ -119,7 +123,7 @@ typedef struct __cartdata { uint8 size; } cartdata; -#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)] +#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 9][(V)] uint8* MMC5BGVRAMADR(uint32 A) { @@ -129,23 +133,23 @@ uint8* MMC5BGVRAMADR(uint32 A) { bool isPattern = PPUON != 0; if (ppuphase == PPUPHASE_OBJ && isPattern) - return &ABANKS[(A) >> 10][(A)]; + return &ABANKS[(A) >> 9][(A)]; if (ppuphase == PPUPHASE_BG && isPattern) - return &BBANKS[(A) >> 10][(A)]; + return &BBANKS[(A) >> 9][(A)]; else if(mmc5ABMode == 0) - return &ABANKS[(A) >> 10][(A)]; + return &ABANKS[(A) >> 9][(A)]; else - return &BBANKS[(A) >> 10][(A)]; + return &BBANKS[(A) >> 9][(A)]; } - else return &ABANKS[(A) >> 10][(A)];; + else return &ABANKS[(A) >> 9][(A)];; } if (!Sprite16) { if (mmc5ABMode == 0) - return &ABANKS[(A) >> 10][(A)]; + return &ABANKS[(A) >> 9][(A)]; else - return &BBANKS[(A) >> 10][(A)]; - } else return &BBANKS[(A) >> 10][(A)]; + return &BBANKS[(A) >> 9][(A)]; + } else return &BBANKS[(A) >> 9][(A)]; } static void mmc5_PPUWrite(uint32 A, uint8 V) { @@ -164,8 +168,8 @@ static void mmc5_PPUWrite(uint32 A, uint8 V) { } else PALRAM[tmp & 0x1F] = V & 0x3F; } else if (tmp < 0x2000) { - if (PPUCHRRAM & (1 << (tmp >> 10))) - VPage[tmp >> 10][tmp] = V; + if (PPUCHRRAM & (3 << (tmp >> 9))) + VPage[tmp >> 9][tmp] = V; } else { if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; @@ -201,7 +205,7 @@ uint8 FASTCALL mmc5_PPURead(uint32 A) { bool isPattern = !!PPUON; if (ppuphase == PPUPHASE_OBJ && isPattern) - return ABANKS[(A) >> 10][(A)]; + return ABANKS[(A) >> 9][(A)]; if (ppuphase == PPUPHASE_BG && isPattern) { if(split) @@ -212,12 +216,12 @@ uint8 FASTCALL mmc5_PPURead(uint32 A) if (MMC5HackCHRMode == 1) return *FCEUPPU_GetCHR(A,NTRefreshAddr); - return BBANKS[(A) >> 10][(A)]; + return BBANKS[(A) >> 9][(A)]; } else if(mmc5ABMode == 0) - return ABANKS[(A) >> 10][(A)]; + return ABANKS[(A) >> 9][(A)]; else - return BBANKS[(A) >> 10][(A)]; + return BBANKS[(A) >> 9][(A)]; } else { @@ -232,7 +236,7 @@ uint8 FASTCALL mmc5_PPURead(uint32 A) return *FCEUPPU_GetCHR(A,NTRefreshAddr); } - return ABANKS[(A) >> 10][(A)]; + return ABANKS[(A) >> 9][(A)]; } } else diff --git a/src/boards/rainbow.cpp b/src/boards/rainbow.cpp new file mode 100644 index 000000000..8aa879cdc --- /dev/null +++ b/src/boards/rainbow.cpp @@ -0,0 +1,2130 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2021-2022 Broke Studio + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + // mapper 682 - Rainbow board v1.0 revA and v1.1 by Broke Studio + // + // documentation available here: https://github.com/BrokeStudio/rainbow-lib + +#include "mapinc.h" +#include "../ines.h" +#include "rainbow_esp.h" + +#ifndef RAINBOW_DEBUG_MAPPER +#define RAINBOW_DEBUG_MAPPER 0 +#endif + +#if RAINBOW_DEBUG_MAPPER >= 1 +#define UDBG(...) FCEU_printf(__VA_ARGS__) +#else +#define UDBG(...) +#endif + +#define MAPPER_PLATFORM_PCB 0 +#define MAPPER_PLATFORM_EMU 1 +#define MAPPER_PLATFORM_WEB 2 +#define MAPPER_VERSION_PROTOTYPE 0 +#define MAPPER_VERSION (MAPPER_PLATFORM_EMU << 5) | MAPPER_VERSION_PROTOTYPE + +#define MIRR_VERTICAL 0b00 // VRAM +#define MIRR_HORIZONTAL 0b01 // VRAM +#define MIRR_ONE_SCREEN 0b10 // VRAM [+ CHR-RAM] +#define MIRR_FOUR_SCREEN 0b11 // CHR-RAM + +#define PRG_ROM_MODE_0 0b000 // 32K +#define PRG_ROM_MODE_1 0b001 // 16K + 16K +#define PRG_ROM_MODE_2 0b010 // 16K + 8K + 8K +#define PRG_ROM_MODE_3 0b011 // 8K + 8K + 8K + 8K +#define PRG_ROM_MODE_4 0b100 // 4K + 4K + 4K + 4K + 4K + 4K + 4K + 4K + +#define PRG_RAM_MODE_0 0b0 // 8K +#define PRG_RAM_MODE_1 0b1 // 4K + +#define CHR_CHIP_ROM 0b00 // CHR-ROM +#define CHR_CHIP_RAM 0b01 // CHR-RAM +#define CHR_CHIP_FPGA_RAM 0b10 // FPGA-RAM + +#define CHR_MODE_0 0b000 // 8K mode +#define CHR_MODE_1 0b001 // 4K mode +#define CHR_MODE_2 0b010 // 2K mode +#define CHR_MODE_3 0b011 // 1K mode +#define CHR_MODE_4 0b100 // 512B mode + +#define CHIP_TYPE_PRG 0 +#define CHIP_TYPE_CHR 1 + +#define NT_CIRAM 0b00 +#define NT_CHR_RAM 0b01 +#define NT_FPGA_RAM 0b10 +#define NT_CHR_ROM 0b11 + +#define SpriteON (PPU[1] & 0x10) //Show Sprite +#define ScreenON (PPU[1] & 0x08) //Show screen +#define PPUON (PPU[1] & 0x18) //PPU should operate +#define Sprite16 (PPU[0] & 0x20) //Sprites 8x16/8x8 + +static void RainbowReset(void); + +static uint8 prg_rom_mode, prg_ram_mode, bootrom; +static uint16 prg[11]; // 0: $5000, 1: $6000, 2: $7000, 3: $8000, 4: $9000, etc + +static uint8 chr_chip, chr_spr_ext_mode, chr_mode; +static uint16 chr[16]; + +static uint8 SPR_bank_offset; +static uint8 SPR_bank[64]; + +static uint8 audio_output; +static uint8 rx_address, tx_address, rx_index; + +static uint32 PRGSIZE = 0; +static uint32 CHRSIZE = 0; + +static uint8 *WRAM = NULL; +static int WRAMSIZE = 0; // max 512 KiB + +static uint8 *FPGA_RAM = NULL; +const uint32 FPGA_RAMSIZE = 8 * 1024; + +static uint8 *DUMMY_CHRRAM = NULL; +const uint32 DUMMY_CHRRAMSIZE = 4 * 1024; + +static uint8 *DUMMY_CHRROM = NULL; +const uint32 DUMMY_CHRROMSIZE = 8192 * 1024; // max 8192 MiB + +static uint8 *CHRRAM = NULL; +static int CHRRAMSIZE = 0; // max 512 KiB + +extern uint8 *ExtraNTARAM; + +uint8 fill_mode_tile; +uint8 fill_mode_attr; + +static uint8 RNBWbattery = 0; +static uint8 reset_step = 0; + +// Scanline IRQ +static bool S_IRQ_enable, S_IRQ_pending, S_IRQ_in_frame, S_IRQ_HBlank; +static uint8 S_IRQ_latch, S_IRQ_offset, S_IRQ_jitter_counter; + +// additional flags to emulate hardware correctly +static float S_IRQ_dot_count; +static uint8 S_IRQ_ready, S_IRQ_last_SL_triggered; + +// CPU Cycle IRQ +static bool C_IRQ_enable, C_IRQ_reset, C_IRQ_pending; +static int32 C_IRQLatch, C_IRQCount; + +// FPGA RAM auto R/W +uint16 fpga_ram_auto_rw_address; +uint8 fpga_ram_auto_rw_increment; + +// ESP message IRQ +static uint8 ESP_IRQ_pending; + +static uint8 flash_mode[2]; +static uint8 flash_sequence[2]; +static uint8 flash_id[2]; + +static uint8 *PRG_FLASHROM = NULL; +const uint32 PRG_FLASHROMSIZE = 8192 * 1024; // max 8MiB + +static uint8 *CHR_FLASHROM = NULL; +const uint32 CHR_FLASHROMSIZE = 8192 * 1024; // max 8MiB + +const bool S29AL008_TOP = false; +const bool S29AL016_TOP = true; +const bool S29JL032_TOP = false; +const bool S29GL064S_TOP = false; + +static SFORMAT FlashRegs[] = +{ + { &flash_mode, 2, "FMOD" }, + { &flash_sequence, 2, "FSEQ" }, + { &flash_id, 2, "FMID" }, + { 0 } +}; + +static SFORMAT RainbowStateRegs[] = +{ + { prg, 11, "PRG" }, + { chr, 16, "CHR" }, + + { &S_IRQ_enable, 1, "PPUE" }, + { &S_IRQ_pending, 1, "PPUP" }, + { &S_IRQ_in_frame, 1, "PPUF" }, + { &S_IRQ_HBlank, 1, "PPUH" }, + { &S_IRQ_latch, 1, "PPUL" }, + { &S_IRQ_offset, 1, "PPUO" }, + { &S_IRQ_dot_count, 4, "PPUD" }, + { &S_IRQ_ready, 1, "PPUR" }, + { &S_IRQ_last_SL_triggered, 1, "PPUT" }, + + { &C_IRQ_enable, 1, "CPUE" }, + { &C_IRQ_pending, 1, "CPUP" }, + { &C_IRQ_reset, 1, "CPUR" }, + { &C_IRQLatch, 4, "CPUL" }, + { &C_IRQCount, 4, "CPUC" }, + + { &ESP_IRQ_pending, 1, "ESPP" }, + + { 0 } +}; + +static void(*sfun[3]) (void); +static uint8 vpsg1[8]; +static uint8 vpsg2[4]; +static int32 cvbc[3]; +static int32 vcount[3]; +static int32 dcount[2]; + +static uint8 ZPCM[3]; + +static SFORMAT SStateRegs[] = +{ + { vpsg1, 8, "PSG1" }, // SQ 1+2 + { vpsg2, 4, "PSG2" }, // SAW + { 0 } +}; + +static BrokeStudioFirmware *esp = NULL; +static bool esp_enable; +static bool esp_irq_enable; +static bool has_esp_message_received; +static bool esp_message_sent; + +static void esp_check_new_message() { + // get new message if needed + if (esp_enable && esp->getDataReadyIO() && has_esp_message_received == false) + { + uint8 message_length = esp->tx(); + FPGA_RAM[0x1800 + (rx_address << 8)] = message_length; + for (uint8 i = 0; i < message_length; i++) + { + FPGA_RAM[0x1800 + (rx_address << 8) + 1 + i] = esp->tx(); + } + rx_index = 0; + has_esp_message_received = true; + } +} + +static bool esp_message_received() { + esp_check_new_message(); + return has_esp_message_received; +} + +static void clear_esp_message_received() { + has_esp_message_received = false; +} + +static void IRQEnd() { + if (!C_IRQ_pending & !S_IRQ_pending & !ESP_IRQ_pending) + { + X6502_IRQEnd(FCEU_IQEXT); + } +} + +static void RainbowIRQ(int a) { + + // Scanline IRQ + int sl = newppu_get_scanline()-1; + int dot = newppu_get_dot(); + + S_IRQ_jitter_counter += a; + + if (dot >= 256) + S_IRQ_HBlank = true; + else + S_IRQ_HBlank = false; + + if (!PPUON || sl >= 241) + { + // whenever rendering is off for any reason (vblank or forced disable) + // the irq counter resets, as well as the inframe flag (easily verifiable from software) + S_IRQ_in_frame = false; // in-frame flag cleared + S_IRQ_pending = false; // pending IRQ flag cleared + S_IRQ_ready = 0; + S_IRQ_last_SL_triggered = 255; + IRQEnd(); + } + else + { + if (!S_IRQ_in_frame) + { + S_IRQ_in_frame = true; + S_IRQ_pending = false; + IRQEnd(); + } + + // this is kind of hacky but result is pretty close to hardware + if ((sl == S_IRQ_latch) & (S_IRQ_ready == 0) & !S_IRQ_pending & (sl != S_IRQ_last_SL_triggered)) + { + S_IRQ_ready = 1; + S_IRQ_dot_count = (float)dot; + if (PAL) S_IRQ_dot_count -= a * 3.2; + else S_IRQ_dot_count -= (float)a * 3; + } + + if ((S_IRQ_ready == 1) & !S_IRQ_pending) + { + if (PAL) S_IRQ_dot_count += (float)a * 3.2; + else S_IRQ_dot_count += (float)a * 3; + + int dotTarget = (S_IRQ_offset * 2); + if (PAL) dotTarget += 20; + else dotTarget += 24; + + if (((int)S_IRQ_dot_count) >= dotTarget) + { + S_IRQ_ready = 2; + S_IRQ_last_SL_triggered = S_IRQ_latch; + } + } + + if (S_IRQ_enable & !S_IRQ_pending & (S_IRQ_ready == 2)) + { + X6502_IRQBegin(FCEU_IQEXT); + S_IRQ_pending = true; + S_IRQ_ready = 0; + S_IRQ_jitter_counter = 0; + } + } + + // Cycle Counter IRQ + if (C_IRQ_enable) { + C_IRQCount -= a; + if (C_IRQCount <= 0) { + C_IRQ_enable = C_IRQ_reset; + C_IRQ_pending = true; + C_IRQCount = C_IRQLatch; + X6502_IRQBegin(FCEU_IQEXT); + } + } + + // ESP / new message IRQ + if (esp_irq_enable) + { + if (esp_message_received()) + { + X6502_IRQBegin(FCEU_IQEXT); + ESP_IRQ_pending = 1; + } + else + { + ESP_IRQ_pending = 0; + } + } + + IRQEnd(); +} + +static void Sync(void) { + uint8 cart_chr_map; + + // $8000-$ffff + uint8 t_prg_rom_mode = bootrom ? PRG_ROM_MODE_3 : prg_rom_mode; + + // 32K + if (t_prg_rom_mode == PRG_ROM_MODE_0) + { + // PRG-ROM + if (!(prg[3] & 0x8000)) + setprg32r(0x11, 0x8000, prg[3] & 0x7fff); + // WRAM + if (prg[3] & 0x8000) + setprg32r(0x10, 0x8000, 0); + } + + // 16K + 16K + if (t_prg_rom_mode == PRG_ROM_MODE_1) + { + // PRG-ROM + if (!(prg[3] & 0x8000)) + setprg16r(0x11, 0x8000, prg[3] & 0x7fff); + // WRAM + if (prg[3] & 0x8000) + setprg16r(0x10, 0x8000, prg[3] & 0x01); + + // PRG-ROM + if (!(prg[7] & 0x8000)) + setprg16r(0x11, 0xC000, prg[7] & 0x7fff); + // WRAM + if (prg[7] & 0x8000) + setprg16r(0x10, 0xC000, prg[7] & 0x01); + } + + // 16K + 8K + 8K + if (t_prg_rom_mode == PRG_ROM_MODE_2) + { + // PRG-ROM + if (!(prg[3] & 0x8000)) + setprg16r(0x11, 0x8000, prg[3] & 0x7fff); + // WRAM + if (prg[3] & 0x8000) + setprg16r(0x10, 0x8000, prg[3] & 0x01); + + // PRG-ROM + if (!(prg[7] & 0x8000)) + setprg8r(0x11, 0xc000, prg[7] & 0x7fff); + // WRAM + if (prg[7] & 0x8000) + setprg8r(0x10, 0xc000, prg[7] & 0x03); + + // PRG-ROM + if (!(prg[9] & 0x8000)) + setprg8r(0x11, 0xe000, prg[9] & 0x7fff); + // WRAM + if (prg[9] & 0x8000) + setprg8r(0x10, 0xe000, prg[9] & 0x03); + } + + // 8K + 8K + 8K + 8K + if (t_prg_rom_mode == PRG_ROM_MODE_3) + { + for (uint8 i = 0; i < 4; i++) + { + // PRG-ROM + if (i == 3 && bootrom) + setprg8r(0x13, 0xe000, 1); + else + if (!(prg[3 + i * 2] & 0x8000)) + setprg8r(0x11, 0x8000 + 0x2000 * i, prg[3 + i * 2] & 0x7fff); + // WRAM + if (prg[3 + i * 2] & 0x8000) + setprg8r(0x10, 0x8000 + 0x2000 * i, prg[3 + i * 2] & 0x03); + } + } + + // 4K + 4K + 4K + 4K + 4K + 4K + 4K + 4K + if (t_prg_rom_mode == PRG_ROM_MODE_4) + { + for (uint8 i = 0; i < 8; i++) + { + // PRG-ROM + if (!(prg[3 + i] & 0x8000)) + setprg4r(0x11, 0x8000 + 0x1000 * i, prg[3 + i] & 0x7fff); + // WRAM + if (prg[3 + i] & 0x8000) + setprg4r(0x10, 0x8000 + 0x1000 * i, prg[3 + i] & 0x07); + } + } + + // $6000-$7fff + + // 8K + if (prg_ram_mode == PRG_RAM_MODE_0) + { + // WRAM + if (((prg[1] & 0xC000) >> 14) == 2) + setprg8r(0x10, 0x6000, prg[1] & 0x3f); + // FPGA-RAM + if (((prg[1] & 0xC000) >> 14) == 3) + setprg8r(0x12, 0x6000, 0); + // PRG-ROM + if (((prg[1] & 0x8000) >> 15) == 0) + setprg8r(0x11, 0x6000, prg[1] & 0x7fff); + } + + // 4K + if (prg_ram_mode == PRG_RAM_MODE_1) + { + // WRAM + if (((prg[1] & 0xC000) >> 14) == 2) + setprg4r(0x10, 0x6000, prg[1] & 0x7f); + // FPGA-RAM + if (((prg[1] & 0xC000) >> 14) == 3) + setprg4r(0x12, 0x6000, prg[1] & 0x01); + // PRG-ROM + if (((prg[1] & 0x8000) >> 15) == 0) + setprg4r(0x11, 0x6000, prg[1] & 0x7fff); + + // WRAM + if (((prg[2] & 0xC000) >> 14) == 2) + setprg4r(0x10, 0x7000, prg[2] & 0x7f); + // FPGA-RAM + if (((prg[2] & 0xC000) >> 14) == 3) + setprg4r(0x12, 0x7000, prg[2] & 0x01); + // PRG-ROM + if (((prg[2] & 0xC000) >> 15) == 0) + setprg4r(0x11, 0x7000, prg[2] & 0x7fff); + } + + // $5000-$5fff - 4K FPGA-RAM + if (bootrom) + setprg4r(0x13, 0x5000, 1); + else + setprg4r(0x12, 0x5000, prg[0] & 0x01); + + // $4800-$4fff + setprg2r(0x12, 0x4800, 3); + + // CHR + switch (chr_chip) + { + case CHR_CHIP_ROM: + RNBWHackVROMPtr = CHR_FLASHROM; + RNBWHackVROMMask = CHR_FLASHROMSIZE - 1; + break; + case CHR_CHIP_RAM: + RNBWHackVROMPtr = CHRRAM; + RNBWHackVROMMask = CHRRAMSIZE - 1; + break; + case CHR_CHIP_FPGA_RAM: + RNBWHackVROMPtr = FPGA_RAM; + RNBWHackVROMMask = FPGA_RAMSIZE - 1; + break; + } + + if (chr_chip == CHR_CHIP_FPGA_RAM) + { + setchr4r(0x12, 0x0000, 0); + setchr4r(0x12, 0x1000, 0); + } + else + { + cart_chr_map = chr_chip + 0x10; + switch (chr_mode) + { + case CHR_MODE_0: + setchr8r(cart_chr_map, chr[0] & 0x03ff); + break; + case CHR_MODE_1: + setchr4r(cart_chr_map, 0x0000, chr[0] & 0x07ff); + setchr4r(cart_chr_map, 0x1000, chr[1] & 0x07ff); + break; + case CHR_MODE_2: + setchr2r(cart_chr_map, 0x0000, chr[0] & 0x0fff); + setchr2r(cart_chr_map, 0x0800, chr[1] & 0x0fff); + setchr2r(cart_chr_map, 0x1000, chr[2] & 0x0fff); + setchr2r(cart_chr_map, 0x1800, chr[3] & 0x0fff); + break; + case CHR_MODE_3: + for (uint8 i = 0; i < 8; i++) { + setchr1r(cart_chr_map, i << 10, chr[i] & 0x1fff); + } + break; + case CHR_MODE_4: + for (uint8 i = 0; i < 16; i++) { + setchr512r(cart_chr_map, i << 9, chr[i] & 0x3fff); + } + break; + } + } + + for (int i = 0; i < 4; i++) + { + uint8 cur_RNBWHackNT = RNBWHackNTbank[i]; + uint8 cur_NT_chip = RNBWHackNTcontrol[i] >> 6; + //uint8 cur_NT_1K_dest = (RNBWHackNTcontrol[i] & 0x0C) >> 2; + //uint8 cur_NT_ext_mode = RNBWHackNTcontrol[i] & 0x03; + + switch (cur_NT_chip) + { + case NT_CIRAM: + vnapage[i] = NTARAM + 0x400 * (cur_RNBWHackNT & 0x01); + break; + case NT_CHR_RAM: + vnapage[i] = CHRRAM + 0x400 * (cur_RNBWHackNT & 0x1f); + break; + case NT_FPGA_RAM: + vnapage[i] = FPGA_RAM + 0x400 * (cur_RNBWHackNT & 0x03); + break; + case NT_CHR_ROM: + vnapage[i] = CHR_FLASHROM + 0x400 * cur_RNBWHackNT; + break; + } + } + + RNBWHackSplitNTARAMPtr = FPGA_RAM + 0x400 * (RNBWHackNTbank[4] & 0x03); + +} + +static DECLFW(RNBW_ExpAudioWr) { + uint8 i; + if (A >= 0x41A0 && A <= 0x41A2) + { + i = A & 3; // 0, 1, 2 + vpsg1[i] = V; + if (sfun[0]) + sfun[0](); + } + else if (A >= 0x41A3 && A <= 0x41A5) + { + i = 4 | ((A - 3) & 3); // 4, 5, 6 + vpsg1[i] = V; + if (sfun[1]) + sfun[1](); + } + else if (A >= 0x41A6 && A <= 0x41A8) + { + i = (A - 6) & 3; // 0, 1, 2 + vpsg2[i] = V; + if (sfun[2]) + sfun[2](); + } +} + +static DECLFR(RNBW_0x4011Rd) { + uint8 ZPCM_val = ((ZPCM[0] + ZPCM[1] + ZPCM[2]) & 0x3f) << 2; + return ZPCM_val; +} + +static DECLFR(RNBW_RstPowRd) { + if (fceuindbg == 0) + { + if (A == 0xFFFC) reset_step = 1; + else if ((A == 0xFFFD) & (reset_step == 1)) + { + RainbowReset(); + reset_step = 0; + } + else reset_step = 0; + } + return CartBR(A); +} + +static DECLFR(RNBW_0x4100Rd) { + switch (A) + { + case 0x4100: return (prg_ram_mode << 6) | prg_rom_mode; + case 0x4120: return (chr_chip << 6) | (chr_spr_ext_mode << 5) | (RNBWHackSplitEnable << 4) | chr_mode; + case 0x4151: { + uint8 rv = (S_IRQ_HBlank ? 0x80 : 0) | (S_IRQ_in_frame ? 0x40 : 0 | (S_IRQ_pending ? 0x01 : 0)); + S_IRQ_pending = false; + S_IRQ_ready = 0; + IRQEnd(); + return rv; + } + case 0x4154: return S_IRQ_jitter_counter; + + // FPGA RAM auto R/W + case 0x415F: + { + uint8_t retval = FPGA_RAM[fpga_ram_auto_rw_address]; + fpga_ram_auto_rw_address += fpga_ram_auto_rw_increment; + return retval; + } + case 0x4160: return MAPPER_VERSION; + case 0x4161: return (S_IRQ_pending ? 0x80 : 0) | (C_IRQ_pending ? 0x40 : 0) | (ESP_IRQ_pending ? 0x01 : 0); + + // ESP - WiFi + case 0x4190: + { + uint8 esp_enable_flag = esp_enable ? 0x01 : 0x00; + uint8 irq_enable_flag = esp_irq_enable ? 0x02 : 0x00; + UDBG("RAINBOW read flags %04x => %02xs\n", A, esp_enable_flag | irq_enable_flag); + return esp_enable_flag | irq_enable_flag; + } + case 0x4191: + { + uint8 esp_message_received_flag = esp_message_received() ? 0x80 : 0; + uint8 esp_rts_flag = esp->getDataReadyIO() ? 0x40 : 0x00; + return esp_message_received_flag | esp_rts_flag; + } + case 0x4192: return esp_message_sent ? 0x80 : 0; + default: + return CartBR(A); + } +} + +static DECLFW(RNBW_0x4100Wr) { + switch (A) + { + // Mapper configuration + case 0x4100: + prg_rom_mode = V & 0x07; + prg_ram_mode = (V & 0x80) >> 7; + Sync(); + break; + // PRG banking + case 0x4106: + case 0x4107: + case 0x4108: + case 0x4109: + case 0x410A: + case 0x410B: + case 0x410C: + case 0x410D: + case 0x410E: + case 0x410F: + { + int bank = (A & 0x0f) - 5; + prg[bank] = (prg[bank] & 0x00ff) | (V << 8); + Sync(); + break; + } + case 0x4115: prg[0] = V & 0x01; Sync(); break; + case 0x4116: + case 0x4117: + case 0x4118: + case 0x4119: + case 0x411A: + case 0x411B: + case 0x411C: + case 0x411D: + case 0x411E: + case 0x411F: + { + int bank = (A & 0x0f) - 5; + prg[bank] = (prg[bank] & 0xff00) | V; + Sync(); + break; + } + // CHR banking / chip selector / vertical split-screen / sprite extended mode + case 0x4120: + chr_chip = (V & 0xC0) >> 6; + chr_spr_ext_mode = (V & 0x20) >> 5; + RNBWHackSplitEnable = (V & 0x10) >> 4; + chr_mode = V & 0x07; + Sync(); + break; + case 0x4121: + RNBWHackBGBankOffset = V & 0x1f; + break; + // Fill-mode + case 0x4124: fill_mode_tile = V; break; + case 0x4125: fill_mode_attr = V & 0x03; break; + // Nametables bank + case 0x4126: RNBWHackNTbank[0] = V; Sync(); break; + case 0x4127: RNBWHackNTbank[1] = V; Sync(); break; + case 0x4128: RNBWHackNTbank[2] = V; Sync(); break; + case 0x4129: RNBWHackNTbank[3] = V; Sync(); break; + case 0x412E: RNBWHackNTbank[4] = V; Sync(); break; + // Nametables control + case 0x412A: RNBWHackNTcontrol[0] = V; Sync(); break; + case 0x412B: RNBWHackNTcontrol[1] = V; Sync(); break; + case 0x412C: RNBWHackNTcontrol[2] = V; Sync(); break; + case 0x412D: RNBWHackNTcontrol[3] = V; Sync(); break; + case 0x412F: RNBWHackNTcontrol[4] = V; Sync(); break; + // CHR banking + case 0x4130: + case 0x4131: + case 0x4132: + case 0x4133: + case 0x4134: + case 0x4135: + case 0x4136: + case 0x4137: + case 0x4138: + case 0x4139: + case 0x413A: + case 0x413B: + case 0x413C: + case 0x413D: + case 0x413E: + case 0x413F: + { + int bank = A & 0x0f; + chr[bank] = (chr[bank] & 0x00ff) | (V << 8); + Sync(); + break; + } + case 0x4140: + case 0x4141: + case 0x4142: + case 0x4143: + case 0x4144: + case 0x4145: + case 0x4146: + case 0x4147: + case 0x4148: + case 0x4149: + case 0x414A: + case 0x414B: + case 0x414C: + case 0x414D: + case 0x414E: + case 0x414F: + { + int bank = A & 0x0f; + chr[bank] = (chr[bank] & 0xff00) | V; + Sync(); + break; + } + // Scanline IRQ + case 0x4150: S_IRQ_latch = V; break; + case 0x4151: S_IRQ_enable = true; break; + case 0x4152: S_IRQ_pending = false; S_IRQ_enable = false; break; + case 0x4153: S_IRQ_offset = V > 169 ? 169 : V; break; + // CPU Cycle IRQ + case 0x4158: C_IRQLatch &= 0xFF00; C_IRQLatch |= V; C_IRQCount = C_IRQLatch; break; + case 0x4159: C_IRQLatch &= 0x00FF; C_IRQLatch |= V << 8; C_IRQCount = C_IRQLatch; break; + case 0x415A: + C_IRQ_enable = V & 0x01; + C_IRQ_reset = (V & 0x02) >> 1; + if (C_IRQ_enable) + C_IRQCount = C_IRQLatch; + break; + case 0x415B: + C_IRQ_pending = false; + IRQEnd(); + break; + // FPGA RAM auto R/W + case 0x415C: fpga_ram_auto_rw_address = (fpga_ram_auto_rw_address & 0x00ff) | ((V & 0x1f) << 8); break; + case 0x415D: fpga_ram_auto_rw_address = (fpga_ram_auto_rw_address & 0xff00) | (V); break; + case 0x415E: fpga_ram_auto_rw_increment = V; break; + case 0x415F: + { + FPGA_RAM[fpga_ram_auto_rw_address] = V; + fpga_ram_auto_rw_address += fpga_ram_auto_rw_increment; + break; + } + // Window Mode + case 0x4170: + RNBWHackWindowXStartTile = V & 0x1f; + break; + case 0x4171: + RNBWHackWindowXEndTile = V & 0x1f; + break; + case 0x4172: + //RNBWHackWindowYStart = V; // TODO + break; + case 0x4173: + //RNBWHackWindowYEnd = V; // TODO + break; + case 0x4174: + RNBWHackSplitXScroll = V & 0x1f; + break; + case 0x4175: + RNBWHackSplitYScroll = V; + break; + // ESP - WiFi + case 0x4190: + esp_enable = V & 0x01; + esp_irq_enable = V & 0x02; + break; + case 0x4191: + if (esp_enable) clear_esp_message_received(); + else FCEU_printf("RAINBOW warning: $4190.0 is not set\n"); + break; + case 0x4192: + if (esp_enable) + { + esp_message_sent = false; + uint8 message_length = FPGA_RAM[0x1800 + (tx_address << 8)]; + esp->rx(message_length); + for (uint8 i = 0; i < message_length; i++) + { + esp->rx(FPGA_RAM[0x1800 + (tx_address << 8) + 1 + i]); + } + esp_message_sent = true; + } + else FCEU_printf("RAINBOW warning: $4190.0 is not set\n"); + break; + case 0x4193: + rx_address = V & 0x07; + break; + case 0x4194: + tx_address = V & 0x07; + break; + case 0x41FF: + bootrom = V & 0x01; + if (bootrom == 0) RainbowReset(); // a bit hacky but does the job for testing + Sync(); + break; + case 0x4240: + SPR_bank_offset = V; + break; + case 0x41A9: + audio_output = V & 0x07; + break; + } + + // $4200-$423F Sprite 4K bank lower bits + if ((A >= 0x4200) & (A <= 0x423f)) + SPR_bank[A & 0x3f] = V; +} + +extern uint32 NTRefreshAddr; +uint8 FASTCALL RainbowPPURead(uint32 A) { + + int xt = NTRefreshAddr & 31; + int yt = (NTRefreshAddr >> 5) & 31; + int ntnum = (NTRefreshAddr >> 10) & 3; + + bool split = false; + int linetile; + if(newppu) + { + if (RNBWHackSplitEnable & ( + ((RNBWHackWindowXStartTile <= RNBWHackWindowXEndTile) & ((xt >= RNBWHackWindowXStartTile) & (xt <= RNBWHackWindowXEndTile))) | + ((RNBWHackWindowXStartTile > RNBWHackWindowXEndTile) & ((xt >= RNBWHackWindowXStartTile) | (xt <= RNBWHackWindowXEndTile))) + )) { + static const int kHack = -1; //dunno if theres science to this or if it just fixes SDF (cant be bothered to think about it) + linetile = (newppu_get_scanline() + kHack + RNBWHackSplitYScroll) / 8; + split = true; + } + } + + if (A < 0x2000) // pattern table / CHR data + { + if (ppuphase == PPUPHASE_OBJ && SpriteON) // sprite fetch + { + if (chr_spr_ext_mode) + if (Sprite16) + return RNBWHackVROMPtr[((SPR_bank[RNBWHackCurSprite] << 13) & RNBWHackVROMMask) + (A)]; // TODO: test + fix + else + return RNBWHackVROMPtr[((SPR_bank[RNBWHackCurSprite] << 12) & RNBWHackVROMMask) + (A)]; + else + { + return VPage[A >> 9][A]; // TODO: FIXME? + } + } + + if (ppuphase == PPUPHASE_BG && ScreenON) // tile fetch + { + + if(split) + { + return RNBWHackVROMPtr[A & 0xFFF]; + } + + uint8 *tmp = FCEUPPU_GetCHR(A, NTRefreshAddr); + if (tmp == NULL) return X.DB; + else return *tmp; + } + + // default + return FFCEUX_PPURead_Default(A); + } + else if (A < 0x3F00) // tiles / attributes + { + if ((A & 0x3FF) >= 0x3C0) { // attributes + if (split) { + //return 0x00; + //uint8 NT_1K_dest = (RNBWHackNTcontrol[4] & 0x0C) >> 2; + //uint8 NT_ext_mode = RNBWHackNTcontrol[4] & 0x03; + + //REF NT: return 0x2000 | (v << 0xB) | (h << 0xA) | (vt << 5) | ht; + //REF AT: return 0x2000 | (v << 0xB) | (h << 0xA) | 0x3C0 | ((vt & 0x1C) << 1) | ((ht & 0x1C) >> 2); + + // Attributes + //return FCEUPPU_GetAttr(ntnum, xt, yt); + + // Fill-mode? + if(RNBWHackNTcontrol[4] & 0x20) + return fill_mode_attr | fill_mode_attr << 2 | fill_mode_attr << 4 | fill_mode_attr << 6; + + A &= ~(0x1C << 1); //mask off VT + A |= (linetile & 0x1C) << 1; //mask on adjusted VT + return FPGA_RAM[RNBWHackNTbank[4] * 0x400 + (A & 0x3ff)]; + } else { + + // Fill-mode? + uint8 NT = (A >> 10) & 0x03; + if(RNBWHackNTcontrol[NT] & 0x20) + return fill_mode_attr | fill_mode_attr << 2 | fill_mode_attr << 4 | fill_mode_attr << 6; + + return FCEUPPU_GetAttr(ntnum, xt, yt); + } + } else { // tiles + if(split) { + // Tiles + + // Fill-mode? + if(RNBWHackNTcontrol[4] & 0x20) + return fill_mode_tile; + + A &= ~((0x1F << 5) | (1 << 0xB)); //mask off VT and V + A |= (linetile & 31) << 5; //mask on adjusted VT (V doesnt make any sense, I think) + + //uint8 *tmp = FCEUPPU_GetCHR(A, NTRefreshAddr); + //if (tmp == NULL) return X.DB; + //else return *tmp; + + return FPGA_RAM[RNBWHackNTbank[4] * 0x400 + (A & 0x3ff)]; + } else { + + // Fill-mode? + uint8 NT = (A >> 10) & 0x03; + if (RNBWHackNTcontrol[NT] & 0x20) + return fill_mode_tile; + + return vnapage[(A >> 10) & 0x3][A & 0x3FF]; + } + } +/* + if(split) + { + uint8 NT_1K_dest = (RNBWHackNTcontrol[4] & 0x0C) >> 2; + uint8 NT_ext_mode = RNBWHackNTcontrol[4] & 0x03; + + static const int kHack = -1; //dunno if theres science to this or if it just fixes SDF (cant be bothered to think about it) + int linetile = (newppu_get_scanline() + kHack) / 8 + RNBWHackSplitYScroll; + + //REF NT: return 0x2000 | (v << 0xB) | (h << 0xA) | (vt << 5) | ht; + //REF AT: return 0x2000 | (v << 0xB) | (h << 0xA) | 0x3C0 | ((vt & 0x1C) << 1) | ((ht & 0x1C) >> 2); + + // TODO: need to handle 8x8 attributes + if((A & 0x3FF) >= 0x3C0) + { + // Attributes + return FCEUPPU_GetAttr(ntnum, xt, yt); + + A &= ~(0x1C << 1); //mask off VT + A |= (linetile & 0x1C) << 1; //mask on adjusted VT + return FPGA_RAM[RNBWHackNTbank[4] * 0x400 + (A & 0x3ff)]; + } + else + { + // Tiles + //A &= ~((0x1F << 5) | (1 << 0xB)); //mask off VT and V + //A |= (linetile & 31) << 5; //mask on adjusted VT (V doesnt make any sense, I think) + + uint8 *tmp = FCEUPPU_GetCHR(A, NTRefreshAddr); + if (tmp == NULL) return X.DB; + else return *tmp; + + return FPGA_RAM[RNBWHackNTbank[4] * 0x400 + (A & 0x3ff)]; + + } + } +*/ +/* + if ((A & 0x3FF) >= 0x3C0) + { + uint8 NT = (A >> 10) & 0x03; + uint8 NT_1K_dest = (RNBWHackNTcontrol[NT] & 0x0C) >> 2; + uint8 NT_ext_mode = RNBWHackNTcontrol[NT] & 0x03; + + // 8x8 attributes + if (NT_ext_mode & 0x01) + { + uint8 byte = FPGA_RAM[NT_1K_dest * 0x400 + (NTRefreshAddr & 0x3ff)]; + //get attribute part and paste it 4x across the byte + byte >>= 6; + byte *= 0x55; + return byte; + } + } +*/ + + return vnapage[(A >> 10) & 0x3][A & 0x3FF]; + } else { // palette fetch + return FFCEUX_PPURead_Default(A); + } +} + +uint8 RainbowFlashID(uint8 chip, uint32 A) { + // Software ID mode is undefined by the datasheet for all but the lowest 2 addressable bytes, + // but some tests of the chip currently being used found it repeats in 512-byte patterns. + // http://forums.nesdev.com/viewtopic.php?p=178728#p178728 + + uint32 flash_size; + + if (chip == CHIP_TYPE_PRG) flash_size = ROM_size * 16; + else if (chip == CHIP_TYPE_CHR) flash_size = VROM_size * 8; + else flash_size = ROM_size * 16; // Invalid chip number. Behavior to be verified, but don't let flash_size uninitialized. + + uint32 aid = A & 0x1FF; + switch (aid) + { + case 0x00: return 0x01; // 0x01 = Cypress + case 0x02: + { + switch (flash_size) + { + case 1024: return S29AL008_TOP ? 0xDA : 0x5B; // S29AL008: 0xDA = top boot block | 0x5B = bottom boot block + case 2048: return S29AL016_TOP ? 0xC4 : 0x49; // S29AL016: 0xC4 = top boot block | 0x49 = bottom boot block + case 4096: return 0x7E; // S29JL032 + case 8192: return 0x7E; // S29GL064S + default: return 0xFF; + } + } + case 0x1C: + { + switch (flash_size) + { + case 4096: return 0x0A; // S29JL032 + case 8192: return 0x10; // S29GL064S + default: return 0xFF; + } + } + case 0x1E: + { + switch (flash_size) + { + case 4096: return S29JL032_TOP ? 0x01 : 0x00; // S29JL032: 0x00 = bottom boot block | 0x01 = top boot block + case 8192: return S29GL064S_TOP ? 0x01 : 0x00; // S29GL064S: 0x00 = bottom boot block | 0x01 = top boot block + default: return 0xFF; + } + } + default: return 0xFF; + } +} + +uint8 FASTCALL RainbowFlashChrID(uint32 A) { + return RainbowFlashID(CHIP_TYPE_CHR, A); +} + +static DECLFR(RainbowFlashPrgID) +{ + return RainbowFlashID(CHIP_TYPE_PRG, A); +} + +void RainbowFlashIDEnter(uint8 chip) +{ + switch (chip) + { + case CHIP_TYPE_PRG: + if (flash_id[chip]) + return; + flash_id[chip] = 1; + if (bootrom) + SetReadHandler(0x6000, 0xDFFF, RainbowFlashPrgID); + else + SetReadHandler(0x6000, 0xFFFF, RainbowFlashPrgID); + break; + case CHIP_TYPE_CHR: + if (CHR_FLASHROM == NULL) + return; + if (flash_id[chip]) + return; + flash_id[chip] = 1; + FFCEUX_PPURead = RainbowFlashChrID; + break; + default: + return; + } +} + +void RainbowFlashIDExit(uint8 chip) +{ + switch (chip) + { + case CHIP_TYPE_PRG: + if (!flash_id[chip]) + return; + flash_id[chip] = 0; + SetReadHandler(0x6000, 0xFFFF, CartBR); + break; + case CHIP_TYPE_CHR: + if (!flash_id[chip]) + return; + flash_id[chip] = 0; + FFCEUX_PPURead = RainbowPPURead; + break; + default: + return; + } +} + +void RainbowFlash(uint8 chip, uint32 flash_addr, uint8 V) { + + uint32 command_addr = flash_addr & 0x0FFF; + + enum + { + flash_mode_READY = 0, + flash_mode_COMMAND, + flash_mode_UNLOCK_BYPASS, + flash_mode_BYTE_WRITE, + flash_mode_ERASE, + }; + + switch (flash_mode[chip]) + { + default: + case flash_mode_READY: + if (command_addr == 0x0AAA && V == 0xAA) + { + flash_mode[chip] = flash_mode_COMMAND; + flash_sequence[chip] = 0; + } + else if (V == 0xF0) + { + RainbowFlashIDExit(chip); + } + break; + case flash_mode_COMMAND: + if (flash_sequence[chip] == 0) + { + if (command_addr == 0x0555 && V == 0x55) + { + flash_sequence[chip] = 1; + } + else + { + flash_mode[chip] = flash_mode_READY; + } + } + else if (flash_sequence[chip] == 1) + { + if (command_addr == 0x0AAA) + { + flash_sequence[chip] = 0; + switch (V) + { + default: flash_mode[chip] = flash_mode_READY; break; + case 0x20: flash_mode[chip] = flash_mode_UNLOCK_BYPASS; break; + case 0xA0: flash_mode[chip] = flash_mode_BYTE_WRITE; break; + case 0x80: flash_mode[chip] = flash_mode_ERASE; break; + case 0x90: RainbowFlashIDEnter(chip); flash_mode[chip] = flash_mode_READY; break; + case 0xF0: RainbowFlashIDExit(chip); flash_mode[chip] = flash_mode_READY; break; + } + } + else + flash_mode[chip] = flash_mode_READY; + } + else + flash_mode[chip] = flash_mode_READY; // should be unreachable + break; + case flash_mode_UNLOCK_BYPASS: + if (flash_sequence[chip] == 0) + { + switch (V) + { + case 0xA0: flash_sequence[chip] = 1; break; + case 0x90: flash_sequence[chip] = 2; break; + } + } + else if (flash_sequence[chip] == 1) + { + flash_sequence[chip] = 0; + if (chip == CHIP_TYPE_PRG) + { + if (PRG_FLASHROM[flash_addr] == 0xff) PRG_FLASHROM[flash_addr] &= V; + } + else if (chip == CHIP_TYPE_CHR) + { + if (CHR_FLASHROM[flash_addr] == 0xff) CHR_FLASHROM[flash_addr] &= V; + } + } + else if (flash_sequence[chip] == 2) + { + if (V == 0x00) + { + flash_sequence[chip] = 0; + flash_mode[chip] = flash_mode_READY; + } + } + break; + case flash_mode_BYTE_WRITE: + if (chip == CHIP_TYPE_PRG) + { + if (PRG_FLASHROM[flash_addr] == 0xff) PRG_FLASHROM[flash_addr] &= V; + } + else if (chip == CHIP_TYPE_CHR) + { + if (CHR_FLASHROM[flash_addr] == 0xff) CHR_FLASHROM[flash_addr] &= V; + } + flash_mode[chip] = flash_mode_READY; + break; + case flash_mode_ERASE: + if (flash_sequence[chip] == 0) + { + if (command_addr == 0x0AAA && V == 0xAA) + flash_sequence[chip] = 1; + else + flash_mode[chip] = flash_mode_READY; + } + else if (flash_sequence[chip] == 1) + { + if (command_addr == 0x0555 && V == 0x55) + flash_sequence[chip] = 2; + else + flash_mode[chip] = flash_mode_READY; + } + else if (flash_sequence[chip] == 2) + { + if (command_addr == 0x0AAA && V == 0x10) // erase chip + { + if (chip == CHIP_TYPE_PRG) + memset(PRG_FLASHROM, 0xFF, PRG_FLASHROMSIZE); + else if (chip == CHIP_TYPE_CHR) + memset(CHR_FLASHROM, 0xFF, CHR_FLASHROMSIZE); + + } + else if (V == 0x30) // erase sectors + { + uint32 sector_offset = (flash_addr & 0xFF0000); + uint8 sector_index = sector_offset >> 16; + uint8 sector_size = 64; + uint32 flash_size; + + if (chip == CHIP_TYPE_PRG) + flash_size = ROM_size * 16; + else if (chip == CHIP_TYPE_CHR) + flash_size = VROM_size * 8; + else + // Invalid chip number. Behavior to be verified, but don't let flash_size uninitialized. + flash_size = ROM_size * 16; + + switch (flash_size) + { + case 1024: // S29AL008 + if (S29AL008_TOP && sector_index == 15) + { + if (flash_addr >= 0xF0000 && flash_addr <= 0xF7FFF) { sector_offset = 0xF0000; sector_size = 32; } + else if (flash_addr >= 0xF8000 && flash_addr <= 0xF9FFF) { sector_offset = 0xF8000; sector_size = 8; } + else if (flash_addr >= 0xFA000 && flash_addr <= 0xFBFFF) { sector_offset = 0xFA000; sector_size = 8; } + else if (flash_addr >= 0xFC000 && flash_addr <= 0xFFFFF) { sector_offset = 0xFC000; sector_size = 16; } + } + else if (!S29AL008_TOP && sector_index == 0) + { + if (flash_addr >= 0x00000 && flash_addr <= 0x03FFF) { sector_offset = 0x00000; sector_size = 16; } + else if (flash_addr >= 0x04000 && flash_addr <= 0x05FFF) { sector_offset = 0x04000; sector_size = 8; } + else if (flash_addr >= 0x06000 && flash_addr <= 0x07FFF) { sector_offset = 0x06000; sector_size = 8; } + else if (flash_addr >= 0x08000 && flash_addr <= 0x0FFFF) { sector_offset = 0x08000; sector_size = 32; } + } + break; + case 2048: // S29AL016 + if (S29AL016_TOP && sector_index == 31) + { + if (flash_addr >= 0x1F0000 && flash_addr <= 0x1F7FFF) { sector_offset = 0xF0000; sector_size = 32; } + else if (flash_addr >= 0x1F8000 && flash_addr <= 0x1F9FFF) { sector_offset = 0xF8000; sector_size = 8; } + else if (flash_addr >= 0x1FA000 && flash_addr <= 0x1FBFFF) { sector_offset = 0xFA000; sector_size = 8; } + else if (flash_addr >= 0x1FC000 && flash_addr <= 0x1FFFFF) { sector_offset = 0xFC000; sector_size = 16; } + } + else if (!S29AL016_TOP && sector_index == 0) + { + if (flash_addr >= 0x00000 && flash_addr <= 0x03FFF) { sector_offset = 0x00000; sector_size = 16; } + else if (flash_addr >= 0x04000 && flash_addr <= 0x05FFF) { sector_offset = 0x04000; sector_size = 8; } + else if (flash_addr >= 0x06000 && flash_addr <= 0x07FFF) { sector_offset = 0x06000; sector_size = 8; } + else if (flash_addr >= 0x08000 && flash_addr <= 0x0FFFF) { sector_offset = 0x08000; sector_size = 32; } + } + break; + case 4096: // S29JL032 + if (S29JL032_TOP && sector_index == 63) + { + if (flash_addr >= 0x3F0000 && flash_addr <= 0x3F1FFF) { sector_offset = 0x3F0000; sector_size = 8; } + else if (flash_addr >= 0x3F2000 && flash_addr <= 0x3F3FFF) { sector_offset = 0x3F2000; sector_size = 8; } + else if (flash_addr >= 0x3F4000 && flash_addr <= 0x3F5FFF) { sector_offset = 0x3F4000; sector_size = 8; } + else if (flash_addr >= 0x3F6000 && flash_addr <= 0x3F7FFF) { sector_offset = 0x3F6000; sector_size = 8; } + else if (flash_addr >= 0x3F8000 && flash_addr <= 0x3F9FFF) { sector_offset = 0x3F8000; sector_size = 8; } + else if (flash_addr >= 0x3FA000 && flash_addr <= 0x3FBFFF) { sector_offset = 0x3FA000; sector_size = 8; } + else if (flash_addr >= 0x3FC000 && flash_addr <= 0x3FDFFF) { sector_offset = 0x3FC000; sector_size = 8; } + else if (flash_addr >= 0x3FE000 && flash_addr <= 0x3FFFFF) { sector_offset = 0x3FE000; sector_size = 8; } + + } + else if (!S29JL032_TOP && sector_index == 0) + { + if (flash_addr >= 0x000000 && flash_addr <= 0x001FFF) { sector_offset = 0x000000; sector_size = 8; } + else if (flash_addr >= 0x002000 && flash_addr <= 0x003FFF) { sector_offset = 0x002000; sector_size = 8; } + else if (flash_addr >= 0x004000 && flash_addr <= 0x005FFF) { sector_offset = 0x004000; sector_size = 8; } + else if (flash_addr >= 0x006000 && flash_addr <= 0x007FFF) { sector_offset = 0x006000; sector_size = 8; } + else if (flash_addr >= 0x008000 && flash_addr <= 0x009FFF) { sector_offset = 0x008000; sector_size = 8; } + else if (flash_addr >= 0x00A000 && flash_addr <= 0x00BFFF) { sector_offset = 0x00A000; sector_size = 8; } + else if (flash_addr >= 0x00C000 && flash_addr <= 0x00DFFF) { sector_offset = 0x00C000; sector_size = 8; } + else if (flash_addr >= 0x00E000 && flash_addr <= 0x00FFFF) { sector_offset = 0x00E000; sector_size = 8; } + } + break; + case 8192: // S29GL064S + if (!S29GL064S_TOP && sector_index == 0) + { + if (flash_addr >= 0x000000 && flash_addr <= 0x001FFF) { sector_offset = 0x000000; sector_size = 8; } + else if (flash_addr >= 0x002000 && flash_addr <= 0x003FFF) { sector_offset = 0x002000; sector_size = 8; } + else if (flash_addr >= 0x004000 && flash_addr <= 0x005FFF) { sector_offset = 0x004000; sector_size = 8; } + else if (flash_addr >= 0x006000 && flash_addr <= 0x007FFF) { sector_offset = 0x006000; sector_size = 8; } + else if (flash_addr >= 0x008000 && flash_addr <= 0x009FFF) { sector_offset = 0x008000; sector_size = 8; } + else if (flash_addr >= 0x00A000 && flash_addr <= 0x00BFFF) { sector_offset = 0x00A000; sector_size = 8; } + else if (flash_addr >= 0x00C000 && flash_addr <= 0x00DFFF) { sector_offset = 0x00C000; sector_size = 8; } + else if (flash_addr >= 0x00E000 && flash_addr <= 0x00FFFF) { sector_offset = 0x00E000; sector_size = 8; } + } + else if (S29GL064S_TOP && sector_index == 127) + { + if (flash_addr >= 0x7F0000 && flash_addr <= 0x7F1FFF) { sector_offset = 0x7F0000; sector_size = 8; } + else if (flash_addr >= 0x7F2000 && flash_addr <= 0x7F3FFF) { sector_offset = 0x7F2000; sector_size = 8; } + else if (flash_addr >= 0x7F4000 && flash_addr <= 0x7F5FFF) { sector_offset = 0x7F4000; sector_size = 8; } + else if (flash_addr >= 0x7F6000 && flash_addr <= 0x7F7FFF) { sector_offset = 0x7F6000; sector_size = 8; } + else if (flash_addr >= 0x7F8000 && flash_addr <= 0x7F9FFF) { sector_offset = 0x7F8000; sector_size = 8; } + else if (flash_addr >= 0x7FA000 && flash_addr <= 0x7FBFFF) { sector_offset = 0x7FA000; sector_size = 8; } + else if (flash_addr >= 0x7FC000 && flash_addr <= 0x7FDFFF) { sector_offset = 0x7FC000; sector_size = 8; } + else if (flash_addr >= 0x7FE000 && flash_addr <= 0x7FFFFF) { sector_offset = 0x7FE000; sector_size = 8; } + } + break; + } + + if (chip == CHIP_TYPE_PRG) + memset(PRG_FLASHROM + sector_offset, 0xFF, 1024 * sector_size); + else if (chip == CHIP_TYPE_CHR) + memset(CHR_FLASHROM + sector_offset, 0xFF, 1024 * sector_size); + + } + flash_mode[chip] = flash_mode_READY; + } + else + flash_mode[chip] = flash_mode_READY; // should be unreachable + break; + } +} + +static DECLFW(RNBW_0x6000Wr) { + if ((A < 0x6000) || A > (0xFFFF)) + return; + + uint32 flash_addr = A; + uint8 prg_idx; + + uint8 t_prg_rom_mode = bootrom ? PRG_ROM_MODE_3 : prg_rom_mode; + + if ((A >= 0x6000) & (A < 0x8000)) + { + switch (prg_ram_mode) + { + case PRG_RAM_MODE_0: + // 8K + if (((prg[1] & 0x8000) >> 14) != 0) + return CartBW(A, V); // FPGA_RAM or WRAM + + // PRG-ROM + flash_addr &= 0x1FFF; + flash_addr |= (prg[1] & 0x7FFF) << 13; + + break; + case PRG_RAM_MODE_1: + // 2 x 4K + prg_idx = ((A >> 12) & 0x07) - 5; + if (((prg[prg_idx] & 0x8000) >> 14) != 0) + return CartBW(A, V); // FPGA_RAM or WRAM + + // PRG-ROM + flash_addr &= 0x1FFF; + flash_addr |= (prg[prg_idx] & 0x7FFF) << 13; + + break; + } + } + else if ((A >= 0x8000) & (A <= 0xFFFF)) + { + switch (t_prg_rom_mode) + { + case PRG_ROM_MODE_0: + // 32K + if ((prg[3] >> 14) != 0) + return CartBW(A, V); // WRAM + + // PRG-ROM + flash_addr &= 0x7FFF; + flash_addr |= (prg[3] & 0x7FFF) << 15; + + break; + case PRG_ROM_MODE_1: + // 2 x 16K + prg_idx = ((A >> 12) & 0x04) + 3; + if ((prg[prg_idx] >> 14) != 0) + return CartBW(A, V); // WRAM + + // PRG-ROM + flash_addr &= 0x3FFF; + flash_addr |= (prg[prg_idx] & 0x7FFF) << 14; + + break; + case PRG_ROM_MODE_2: + if ((A >= 0x8000) & (A <= 0xBFFF)) + { + // 16K + if ((prg[3] >> 14) != 0) + return CartBW(A, V); // WRAM + + // PRG-ROM + flash_addr &= 0x3FFF; + flash_addr |= (prg[3] & 0x3F) << 14; + } + else if ((A >= 0xC000) & (A <= 0xFFFF)) + { + // 2 x 8K + prg_idx = ((A >> 12) & 0x06) + 3; + if ((prg[prg_idx] >> 14) != 0) + return CartBW(A, V); // WRAM + + // PRG-ROM + flash_addr &= 0x1FFF; + flash_addr |= (prg[prg_idx] & 0x7FFF) << 13; + + } + break; + case PRG_ROM_MODE_3: + // 4 x 8K + prg_idx = ((A >> 12) & 0x06) + 3; + if ((prg[prg_idx] >> 14) != 0) + return CartBW(A, V); // WRAM + + // PRG-ROM + flash_addr &= 0x1FFF; + flash_addr |= (prg[prg_idx] & 0x7FFF) << 13; + + break; + case PRG_ROM_MODE_4: + // 8 x 4K + prg_idx = ((A >> 12) & 0x07) + 3; + + if ((prg[prg_idx] >> 14) != 0) + return CartBW(A, V); // WRAM + + // PRG-ROM + flash_addr &= 0x0FFF; + flash_addr |= (prg[prg_idx] & 0x7FFF) << 13; + break; + + default: + return CartBW(A, V); + } + } + RainbowFlash(CHIP_TYPE_PRG, flash_addr, V); +} + +static void RainbowPPUWrite(uint32 A, uint8 V) { + /* + // if CHR-RAM but CHR-RAM does not exist then return + if (chr_chip == CHR_CHIP_RAM && CHRRAM == NULL) + return; + + // if CHR-ROM but CHR-ROM does not exist then return + if (chr_chip == CHR_CHIP_ROM && CHR_FLASHROM == NULL) + return; + else*/ + { + uint32 flash_addr = A; + if (A < 0x2000) + { + switch (chr_mode) + { + // NOTE: plus les bons modes ? + case CHR_MODE_0: + flash_addr &= 0x1FFF; + flash_addr |= (chr[A >> 13] & 0xffff) << 13; + break; + case CHR_MODE_1: + flash_addr &= 0xFFF; + flash_addr |= (chr[A >> 12] & 0xffff) << 12; + break; + case CHR_MODE_2: + flash_addr &= 0x7FF; + flash_addr |= (chr[A >> 11] & 0xffff) << 11; + break; + case CHR_MODE_3: + flash_addr &= 0x3FF; + flash_addr |= (chr[A >> 10] & 0xffff) << 10; + break; + case CHR_MODE_4: + flash_addr &= 0x1FF; + flash_addr |= (chr[A >> 9] & 0xffff) << 9; + break; + } + RainbowFlash(CHIP_TYPE_CHR, flash_addr, V); + } + } + FFCEUX_PPUWrite_Default(A, V); +} + +static void RainbowReset(void) { + // reset + reset_step = 0; + + // PRG - 32K banks mapped to first PRG-ROM bank + prg_rom_mode = PRG_ROM_MODE_0; + prg[3] = 0; + + // CHR - 8K banks mapped to first bank of CHR-ROM + // extended sprite mode disabled + chr_chip = CHR_CHIP_ROM; + chr_spr_ext_mode = 0; + RNBWHackSplitEnable = 0; + chr_mode = CHR_MODE_0; + chr[0] = 0; + + // Nametables - CIRAM horizontal mirroring + RNBWHackNTbank[0] = 0; + RNBWHackNTbank[1] = 0; + RNBWHackNTbank[2] = 1; + RNBWHackNTbank[3] = 1; + RNBWHackNTcontrol[0] = 0; + RNBWHackNTcontrol[1] = 0; + RNBWHackNTcontrol[2] = 0; + RNBWHackNTcontrol[3] = 0; + + // Scanline IRQ + S_IRQ_enable = false; + S_IRQ_pending = false; + S_IRQ_in_frame = false; + S_IRQ_HBlank = false; + S_IRQ_offset = 135; + + // CPU Cycle IRQ + C_IRQ_enable = false; + C_IRQ_pending = false; + C_IRQ_reset = false; + + // Audio Output + audio_output = 1; + + // ESP / WiFi + esp_enable = false; + //clear_esp_message_received(); + esp_message_sent = true; + //rx_address = 0; + //tx_address = 0; + //rx_index = 0; + ESP_IRQ_pending = 0; + Sync(); +} + +static void RainbowPower(void) { + + // mapper init + if (MiscROMS) bootrom = 1; + else bootrom = 0; + RainbowReset(); + + // reset-power vectors + SetReadHandler(0xFFFC, 0xFFFF, RNBW_RstPowRd); + + // + SetReadHandler(0x4800, 0xFFFB, CartBR); + SetWriteHandler(0x4800, 0x5FFF, CartBW); + + /* + if (WRAM) + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + FCEU_CheatAddRAM(FPGA_RAMSIZE >> 10, 0x5000, FPGA_RAM); + FCEU_CheatAddRAM(0x1800 >> 10, 0x4800, FPGA_RAM); + */ + // mapper registers (writes) + SetWriteHandler(0x4100, 0x47ff, RNBW_0x4100Wr); + + // mapper registers (reads) + SetReadHandler(0x4100, 0x47ff, RNBW_0x4100Rd); + + // audio expansion (reads) + SetReadHandler(0x4011, 0x4011, RNBW_0x4011Rd); + + // audio expansion registers (writes) + SetWriteHandler(0x41A0, 0x41A8, RNBW_ExpAudioWr); + + // self-flashing + flash_mode[CHIP_TYPE_PRG] = 0; + flash_mode[CHIP_TYPE_CHR] = 0; + flash_sequence[CHIP_TYPE_PRG] = 0; + flash_sequence[CHIP_TYPE_CHR] = 0; + flash_id[CHIP_TYPE_PRG] = false; + flash_id[CHIP_TYPE_CHR] = false; + SetWriteHandler(0x6000, 0xFFFF, RNBW_0x6000Wr); + + // fill WRAM/FPGA_RAM/CHRRAM/DUMMY_CHRRAM/DUMMY_CHRROM with random values + if (WRAM && !RNBWbattery) + FCEU_MemoryRand(WRAM, WRAMSIZE, false); + + if (FPGA_RAM && !RNBWbattery) + FCEU_MemoryRand(FPGA_RAM, FPGA_RAMSIZE, false); + + if (CHRRAM && !RNBWbattery) + FCEU_MemoryRand(CHRRAM, CHRRAMSIZE, false); + + if (DUMMY_CHRRAM) + FCEU_MemoryRand(DUMMY_CHRRAM, DUMMY_CHRRAMSIZE, false); + + if (DUMMY_CHRROM) + FCEU_MemoryRand(DUMMY_CHRROM, DUMMY_CHRROMSIZE, false); + + // init FPGA RAM with bootrom CHR data + for (size_t i = 0; i < 0x1000; i++) + { + FPGA_RAM[i] = bootrom_chr[i]; + } + + // init FPGA RAM with bootrom PRG data + if (MiscROMS) + { + // init FPGA_RAM with MISC ROM data + for (size_t i = 0; i < 0xE00; i++) + { + FPGA_RAM[0x1000 + i] = MiscROMS[i]; + } + } + + // ESP firmware + esp = new BrokeStudioFirmware; + //esp_enable = false; + //esp_irq_enable = false; + clear_esp_message_received(); + //esp_message_sent = true; + //rx_address = 0; + //tx_address = 0; + //rx_index = 0; +} + +static void RainbowClose(void) +{ + if (WRAM) + { + FCEU_gfree(WRAM); + WRAM = NULL; + } + + if (FPGA_RAM) + { + FCEU_gfree(FPGA_RAM); + FPGA_RAM = NULL; + } + + if (CHRRAM) + ExtraNTARAM = NULL; + + if (DUMMY_CHRRAM) + { + FCEU_gfree(DUMMY_CHRRAM); + DUMMY_CHRRAM = NULL; + ExtraNTARAM = NULL; + } + + if (PRG_FLASHROM) + { + FCEU_gfree(PRG_FLASHROM); + PRG_FLASHROM = NULL; + } + + if (CHR_FLASHROM) + { + FCEU_gfree(CHR_FLASHROM); + CHR_FLASHROM = NULL; + } + + if (esp) + { + esp_enable = false; + delete esp; + esp = NULL; + } + + RNBWHack = 0; + RNBWHackNTcontrol[0] = 0; + RNBWHackNTcontrol[1] = 0; + RNBWHackNTcontrol[2] = 0; + RNBWHackNTcontrol[3] = 0; + RNBWHackNTcontrol[4] = 0; + RNBWHackVROMPtr = NULL; + RNBWHackExNTARAMPtr = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +// audio expansion + +static void DoSQV1(void); +static void DoSQV2(void); +static void DoSawV(void); + +static INLINE void DoSQV(int x) { + int32 V; + int32 amp = (((vpsg1[x << 2] & 15) << 8) * 6 / 8) >> 4; + int32 start, end; + + start = cvbc[x]; + end = (SOUNDTS << 16) / soundtsinc; + if (end <= start) + return; + cvbc[x] = end; + + if ((vpsg1[(x << 2) | 0x2] & 0x80) && (audio_output & 0x03)) + { + if (vpsg1[x << 2] & 0x80) + { + for (V = start; V < end; V++) + { + Wave[V >> 4] += amp; + } + } + else + { + int32 thresh = (vpsg1[x << 2] >> 4) & 7; + int32 freq = ((vpsg1[(x << 2) | 0x1] | ((vpsg1[(x << 2) | 0x2] & 15) << 8)) + 1) << 17; + for (V = start; V < end; V++) { + if (dcount[x] > thresh) + { + Wave[V >> 4] += amp; + } + vcount[x] -= nesincsize; + while (vcount[x] <= 0) { + vcount[x] += freq; + dcount[x] = (dcount[x] + 1) & 15; + } + } + } + } +} + +static void DoSQV1(void) { + DoSQV(0); +} + +static void DoSQV2(void) { + DoSQV(1); +} + +static void DoSawV(void) { + int V; + int32 start, end; + + start = cvbc[2]; + end = (SOUNDTS << 16) / soundtsinc; + if (end <= start) + return; + cvbc[2] = end; + + if ((vpsg2[2] & 0x80) && (audio_output & 0x03)) + { + static int32 saw1phaseacc = 0; + uint32 freq3; + static uint8 b3 = 0; + static int32 phaseacc = 0; + static uint32 duff = 0; + + freq3 = (vpsg2[1] + ((vpsg2[2] & 15) << 8) + 1); + + for (V = start; V < end; V++) { + saw1phaseacc -= nesincsize; + if (saw1phaseacc <= 0) + { + int32 t; + rea: + t = freq3; + t <<= 18; + saw1phaseacc += t; + phaseacc += vpsg2[0] & 0x3f; + b3++; + if (b3 == 7) + { + b3 = 0; + phaseacc = 0; + } + if (saw1phaseacc <= 0) + goto rea; + duff = (((phaseacc >> 3) & 0x1f) << 4) * 6 / 8; + } + Wave[V >> 4] += duff; + } + } +} + +static INLINE void DoSQVHQ(int x) { + int volume = vpsg1[x << 2] & 15; + int duty = (vpsg1[x << 2] >> 4) & 7; + bool ignore_duty = vpsg1[x << 2] & 0x80; + int freq_lo = vpsg1[(x << 2) | 0x1]; + int freq_hi = vpsg1[(x << 2) | 0x2] & 15; + bool enable = vpsg1[(x << 2) | 0x2] & 0x80; + + int32 V; + int32 amp = (volume << 8) * 6 / 8; + + if (enable) + { + if (ignore_duty) + { + for (V = cvbc[x]; V < (int)SOUNDTS; V++) + { + if (audio_output & 0x03) WaveHi[V] += amp; + ZPCM[x] = volume; + } + } + else + { + int32 thresh = duty; + for (V = cvbc[x]; V < (int)SOUNDTS; V++) { + if (dcount[x] > thresh) + { + if (audio_output & 0x03) WaveHi[V] += amp; + ZPCM[x] = volume; + } + vcount[x]--; + if (vcount[x] <= 0) + { + vcount[x] = (freq_lo | (freq_hi << 8)) + 1; + dcount[x] = (dcount[x] + 1) & 15; + } + } + } + } + else + { + ZPCM[x] = 0; + } + cvbc[x] = SOUNDTS; + + return; +} + +static void DoSQV1HQ(void) { + DoSQVHQ(0); +} + +static void DoSQV2HQ(void) { + DoSQVHQ(1); +} + +static void DoSawVHQ(void) { + static uint8 b3 = 0; + static int32 phaseacc = 0; + int32 V; + + if (vpsg2[2] & 0x80) + { + for (V = cvbc[2]; V < (int)SOUNDTS; V++) { + ZPCM[2] = (phaseacc >> 3) & 0x1f; + if (audio_output & 0x03) WaveHi[V] += (((phaseacc >> 3) & 0x1f) << 8) * 6 / 8; + vcount[2]--; + if (vcount[2] <= 0) + { + vcount[2] = (vpsg2[1] + ((vpsg2[2] & 15) << 8) + 1) << 1; + phaseacc += vpsg2[0] & 0x3f; + b3++; + if (b3 == 7) { + b3 = 0; + phaseacc = 0; + } + } + } + } + else + { + ZPCM[2] = 0; + } + cvbc[2] = SOUNDTS; +} + +void RainbowSound(int Count) { + int x; + + DoSQV1(); + DoSQV2(); + DoSawV(); + for (x = 0; x < 3; x++) + cvbc[x] = Count; +} + +void RainbowSoundHQ(void) { + DoSQV1HQ(); + DoSQV2HQ(); + DoSawVHQ(); +} + +void RainbowSyncHQ(int32 ts) { + int x; + for (x = 0; x < 3; x++) cvbc[x] = ts; +} + +static void RainbowESI(void) { + GameExpSound.RChange = RainbowESI; + GameExpSound.Fill = RainbowSound; + GameExpSound.HiFill = RainbowSoundHQ; + GameExpSound.HiSync = RainbowSyncHQ; + + memset(cvbc, 0, sizeof(cvbc)); + memset(vcount, 0, sizeof(vcount)); + memset(dcount, 0, sizeof(dcount)); + if (FSettings.SndRate) + { + if (FSettings.soundq >= 1) + { + sfun[0] = DoSQV1HQ; + sfun[1] = DoSQV2HQ; + sfun[2] = DoSawVHQ; + } + else + { + sfun[0] = DoSQV1; + sfun[1] = DoSQV2; + sfun[2] = DoSawV; + } + } + else + memset(sfun, 0, sizeof(sfun)); + AddExState(&SStateRegs, ~0, 0, 0); +} + +#if 0 +// Let's disable NSF support for now since I don't have an NSF ROM file to test it yet. + +// NSF Init + +void NSFRainbow_Init(void) { + RainbowESI(); + SetWriteHandler(0x8000, 0xbfff, RNBW_ExpAudioWr); +} +#endif + +// mapper init + +void RAINBOW_Init(CartInfo *info) { + info->Power = RainbowPower; + info->Reset = RainbowReset; + info->Close = RainbowClose; + + RNBWbattery = info->battery; + + // WRAM + if (info->wram_size != 0) + { + if (info->wram_size > 0x80000) + { + WRAMSIZE = 0x80000; // maximum is 512KiB + } + else if (info->wram_size < 0x8000) + { + WRAMSIZE = 0x8000; // minimum is 32Kib + } + else + { + WRAMSIZE = info->wram_size & 0xF8000; // we need this to match the hardware as close as possible + } + + if (WRAMSIZE != 0) + { + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + info->wram_size = WRAMSIZE; + + if (RNBWbattery) + { + info->addSaveGameBuf(WRAM, WRAMSIZE); + } + } + else + { + info->wram_size = 0; + } + } + + // FPGA_RAM + FPGA_RAM = (uint8*)FCEU_gmalloc(FPGA_RAMSIZE); + SetupCartPRGMapping(0x12, FPGA_RAM, FPGA_RAMSIZE, 1); + SetupCartCHRMapping(0x12, FPGA_RAM, FPGA_RAMSIZE, 1); + AddExState(FPGA_RAM, FPGA_RAMSIZE, 0, "FPGA_RAM"); + if (info->battery) + { + info->addSaveGameBuf(FPGA_RAM, FPGA_RAMSIZE); + } + + // PRG FLASH ROM + PRG_FLASHROM = (uint8*)FCEU_gmalloc(PRG_FLASHROMSIZE); + AddExState(PRG_FLASHROM, PRG_FLASHROMSIZE, 0, "PFROM"); + if (info->battery) + { + info->addSaveGameBuf(PRG_FLASHROM, PRG_FLASHROMSIZE); + } + + // copy PRG ROM into PRG_FLASHROM, use it instead of PRG ROM + PRGSIZE = ROM_size * 16 * 1024; + for (uint32 w = 0, r = 0; w < PRG_FLASHROMSIZE; ++w) + { + PRG_FLASHROM[w] = ROM[r]; + ++r; + if (r >= PRGSIZE) + r = 0; + } + SetupCartPRGMapping(0x11, PRG_FLASHROM, PRG_FLASHROMSIZE, 0); + + // CHR-RAM + if (info->vram_size != 0) + { + if (info->vram_size > 0x80000) + { + CHRRAMSIZE = 0x80000; // maximum is 512KiB + } + else if (info->vram_size < 0x8000) + { + CHRRAMSIZE = 0x8000; // minimum is 32Kib + } + else + { + CHRRAMSIZE = info->vram_size & 0xF8000; // we need this to match the hardware as close as possible + } + + if (CHRRAMSIZE != 0) + { + CHRRAMSIZE = info->vram_size; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x11, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); + ExtraNTARAM = CHRRAM + 30 * 1024; + AddExState(ExtraNTARAM, 2048, 0, "EXNR"); + info->vram_size = CHRRAMSIZE; + } + else + { + info->vram_size = 0; + } + } + else + { + // create dummy CHR-RAM to avoid crash when trying to use CHR-RAM for nametables + // when no CHR-RAM is specified in the ROM header + DUMMY_CHRRAM = (uint8*)FCEU_gmalloc(DUMMY_CHRRAMSIZE); + ExtraNTARAM = DUMMY_CHRRAM; + AddExState(ExtraNTARAM, DUMMY_CHRRAMSIZE, 0, "EXNR"); + } + + // CHR FLASHROM + if (VROM_size != 0) + { + CHR_FLASHROM = (uint8*)FCEU_gmalloc(CHR_FLASHROMSIZE); + AddExState(CHR_FLASHROM, CHR_FLASHROMSIZE, 0, "CFROM"); + if (info->battery) + { + info->addSaveGameBuf(CHR_FLASHROM, CHR_FLASHROMSIZE); + } + + // copy CHR ROM into CHR_FLASHROM, use it instead of CHR ROM + CHRSIZE = VROM_size * 8 * 1024; + for (uint32 w = 0, r = 0; w < CHR_FLASHROMSIZE; ++w) + { + CHR_FLASHROM[w] = VROM[r]; + ++r; + if (r >= CHRSIZE) + r = 0; + } + SetupCartCHRMapping(0x10, CHR_FLASHROM, CHR_FLASHROMSIZE, 0); + } + else + { + // create dummy CHR-ROM to avoid crash when trying to use CHR-ROM for pattern tables + // when no CHR-ROM is specified in the ROM header + DUMMY_CHRROM = (uint8*)FCEU_gmalloc(DUMMY_CHRROMSIZE); + SetupCartCHRMapping(0x10, DUMMY_CHRROM, DUMMY_CHRROMSIZE, 0); + } + + // BOOTROM + if (info->misc_roms != 0 && MiscROMS) + { + SetupCartPRGMapping(0x13, MiscROMS, MiscROMS_size, 0); + } + + FFCEUX_PPURead = RainbowPPURead; + FFCEUX_PPUWrite = RainbowPPUWrite; + + //GameHBIRQHook = Rainbowhb; + MapIRQHook = RainbowIRQ; + RNBWHack = 1; + RNBWHackNTcontrol[0] = 0; + RNBWHackNTcontrol[1] = 0; + RNBWHackNTcontrol[2] = 0; + RNBWHackNTcontrol[3] = 0; + RNBWHackVROMPtr = FPGA_RAM; + RNBWHackVROMMask = FPGA_RAMSIZE - 1; + RNBWHackExNTARAMPtr = FPGA_RAM; + RainbowESI(); + GameStateRestore = StateRestore; + + AddExState(&FlashRegs, ~0, 0, 0); + AddExState(&RainbowStateRegs, ~0, 0, 0); +} diff --git a/src/boards/rainbow_esp.cpp b/src/boards/rainbow_esp.cpp new file mode 100644 index 000000000..867440b09 --- /dev/null +++ b/src/boards/rainbow_esp.cpp @@ -0,0 +1,2395 @@ +#include "rainbow_esp.h" + +#include "../fceu.h" +#include "../utils/crc32.h" + +#include "RNBW/pping.h" + +#include +#include + +#ifdef _WIN32 + +#define ERR_MSG_SIZE 513 + +// UDP networking +#pragma comment(lib, "ws2_32.lib") // Winsock Library +#define WIN32_LEAN_AND_MEAN +#include +#include + +// Compatibility hacks +typedef SSIZE_T ssize_t; +#define bzero(b, len) (memset((b), '\0', (len)), (void)0) +#define cast_network_payload(x) reinterpret_cast(x) +#define close_sock(x) closesocket(x) + +#else + +// UDP networking +#include +#include +#include +#include +#include + +// Compatibility hacks +#define cast_network_payload(x) reinterpret_cast(x) +#define close_sock(x) ::close(x) + +#endif + +#ifndef RAINBOW_DEBUG_ESP +#define RAINBOW_DEBUG_ESP 0 +#endif + +#if RAINBOW_DEBUG_ESP >= 1 +#define UDBG(...) FCEU_printf(__VA_ARGS__) +#else +#define UDBG(...) +#endif + +#if RAINBOW_DEBUG_ESP >= 2 +#define UDBG_FLOOD(...) FCEU_printf(__VA_ARGS__) +#else +#define UDBG_FLOOD(...) +#endif + +#if RAINBOW_DEBUG_ESP >= 1 +#include "../debug.h" +namespace +{ + uint64_t wall_clock_milli() + { + return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + }; +} +#endif + +namespace +{ + std::array dir_names = {"save", "roms", "user"}; +} + +BrokeStudioFirmware::BrokeStudioFirmware() +{ + UDBG("[Rainbow] BrokeStudioFirmware constructor\n"); + + // Get default host/port +#ifdef _WIN32 + char *value = nullptr; + size_t len; + + if (_dupenv_s(&value, &len, "RAINBOW_SERVER_ADDR") == 0 && value != nullptr) + { + this->server_settings_address = string(value); + this->default_server_settings_address = string(value); + } + + free(value); + + if (_dupenv_s(&value, &len, "RAINBOW_SERVER_PORT") == 0 && value != nullptr) + { + std::istringstream port_iss(value); + port_iss >> this->server_settings_port; + this->default_server_settings_port = this->server_settings_port; + } + + free(value); +#else + char const *hostname = ::getenv("RAINBOW_SERVER_ADDR"); + if (hostname == nullptr) + hostname = ""; + this->server_settings_address = hostname; + this->default_server_settings_address = hostname; + + char const *port_cstr = ::getenv("RAINBOW_SERVER_PORT"); + if (port_cstr == nullptr) + port_cstr = "0"; + std::istringstream port_iss(port_cstr); + port_iss >> this->server_settings_port; + this->default_server_settings_port = this->server_settings_port; +#endif + + // Clear UDP address pool + for (size_t i = 0; i < 16; i++) { + this->ipAddressPool[i].ipAddress = ""; + this->ipAddressPool[i].port = 0; + } + + // Init fake registered networks + this->networks = {{ + {"EMULATOR_SSID", "EMULATOR_PASS", true}, + {"", "", false}, + {"", "", false}, + }}; + + // Load file list from save file (if any) + this->loadFiles(); + + // Mark ping result as useless + this->ping_ready = false; + + // Initialize download system + this->initDownload(); +} + +BrokeStudioFirmware::~BrokeStudioFirmware() +{ + UDBG("[Rainbow] BrokeStudioFirmware destructor\n"); + this->closeConnection(); + this->cleanupDownload(); +} + +void BrokeStudioFirmware::rx(uint8_t v) +{ + UDBG_FLOOD("RAINBOW BrokeStudioFirmware rx %02x\n", v); + if (this->msg_first_byte) + { + this->msg_first_byte = false; + this->msg_length = v + 1; + } + this->rx_buffer.push_back(v); + + if (this->rx_buffer.size() == this->msg_length) + { + this->processBufferedMessage(); + this->msg_first_byte = true; + } +} + +uint8_t BrokeStudioFirmware::tx() +{ + // Refresh buffer from network + this->receiveDataFromServer(); + this->receivePingResult(); + + // Fill buffer with the next message (if needed) + if (this->tx_buffer.empty() && !this->tx_messages.empty()) + { + deque message = this->tx_messages.front(); + this->tx_buffer.insert(this->tx_buffer.end(), message.begin(), message.end()); + this->tx_messages.pop_front(); + } + + // Get byte from buffer + if (!this->tx_buffer.empty()) + { + last_byte_read = this->tx_buffer.front(); + this->tx_buffer.pop_front(); + } + + UDBG_FLOOD("RAINBOW BrokeStudioFirmware tx %02x\n", last_byte_read); + return last_byte_read; +} + +bool BrokeStudioFirmware::getDataReadyIO() +{ + this->receiveDataFromServer(); + this->receivePingResult(); + return !(this->tx_buffer.empty() && this->tx_messages.empty()); +} + +void BrokeStudioFirmware::processBufferedMessage() +{ + assert(this->rx_buffer.size() >= 2); // Buffer must contain exactly one message, minimal message is two bytes (length + type) + uint8_t const message_size = this->rx_buffer.front(); + assert(message_size >= 1); // minimal payload is one byte (type) + assert(this->rx_buffer.size() == static_cast::size_type>(message_size) + 1); // Buffer size must match declared payload size + + // Process the message in RX buffer + switch (static_cast(this->rx_buffer.at(1))) + { + + // ESP CMDS + + case toesp_cmds_t::ESP_GET_STATUS: + UDBG("[Rainbow] ESP received command ESP_GET_STATUS\n"); + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::READY), + static_cast(isSdCardFilePresent ? 1 : 0) + }); + break; + case toesp_cmds_t::DEBUG_GET_LEVEL: + UDBG("[Rainbow] ESP received command DEBUG_GET_LEVEL\n"); + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::DEBUG_LEVEL), + static_cast(this->debug_config) + }); + break; + case toesp_cmds_t::DEBUG_SET_LEVEL: + UDBG("[Rainbow] ESP received command DEBUG_SET_LEVEL\n"); + if (message_size == 2) + { + this->debug_config = this->rx_buffer.at(2); + } + FCEU_printf("DEBUG LEVEL SET TO: %u\n", this->debug_config); + break; + case toesp_cmds_t::DEBUG_LOG: + { + UDBG("[Rainbow] ESP received command DEBUG_LOG\n"); + static bool isRainbowDebugEnabled = RAINBOW_DEBUG_ESP > 0; + if (isRainbowDebugEnabled || (this->debug_config & 1)) + { + for (deque::const_iterator cur = this->rx_buffer.begin() + 2; cur < this->rx_buffer.end(); ++cur) + { + FCEU_printf("%02x ", *cur); + } + FCEU_printf("\n"); + } + break; + } + case toesp_cmds_t::BUFFER_CLEAR_RX_TX: + UDBG("[Rainbow] ESP received command BUFFER_CLEAR_RX_TX\n"); + this->receiveDataFromServer(); + this->receivePingResult(); + this->tx_buffer.clear(); + this->tx_messages.clear(); + this->rx_buffer.clear(); + break; + case toesp_cmds_t::BUFFER_DROP_FROM_ESP: + UDBG("[Rainbow] ESP received command BUFFER_DROP_FROM_ESP\n"); + if (message_size == 3) + { + uint8_t const message_type = this->rx_buffer.at(2); + uint8_t const n_keep = this->rx_buffer.at(3); + + size_t i = 0; + for (deque>::iterator message = this->tx_messages.end(); + message != this->tx_messages.begin();) + { + --message; + if (message->at(1) == message_type) + { + ++i; + if (i > n_keep) + { + UDBG("[Rainbow] ESP erase message: index=%ld\n", message - this->tx_messages.begin()); + message = this->tx_messages.erase(message); + } + else + { + UDBG("[Rainbow] ESP keep message: index=%ld - too recent\n", message - this->tx_messages.begin()); + } + } + else + { + UDBG("[Rainbow] ESP keep message: index=%ld - bad type\n", message - this->tx_messages.begin()); + } + } + } + break; + case toesp_cmds_t::ESP_GET_FIRMWARE_VERSION: + UDBG("[Rainbow] ESP received command ESP_GET_FIRMWARE_VERSION\n"); + this->tx_messages.push_back({19, static_cast(fromesp_cmds_t::ESP_FIRMWARE_VERSION), 17, 'E', 'M', 'U', 'L', 'A', 'T', 'O', 'R', '_', 'F', 'I', 'R', 'M', 'W', 'A', 'R', 'E'}); + break; + + case toesp_cmds_t::ESP_FACTORY_RESET: + UDBG("[Rainbow] ESP received command ESP_FACTORY_RESET\n"); + UDBG("[Rainbow] ESP_FACTORY_RESET has no use here\n"); + this->tx_messages.push_back({2, static_cast(fromesp_cmds_t::ESP_FACTORY_RESET), static_cast(esp_factory_reset::ERROR_WHILE_SAVING_CONFIG)}); + break; + + case toesp_cmds_t::ESP_RESTART: + UDBG("[Rainbow] ESP received command ESP_RESTART\n"); + UDBG("[Rainbow] ESP_RESTART has no use here\n"); + break; + + // WIFI CMDS + + case toesp_cmds_t::WIFI_GET_STATUS: + UDBG("[Rainbow] ESP received command WIFI_GET_STATUS\n"); + this->tx_messages.push_back({3, static_cast(fromesp_cmds_t::WIFI_STATUS), 3, 0}); // Simple answer, wifi is ok + break; + // WIFI_GET_SSID/WIFI_GET_IP config commands are not relevant here, so we'll just use fake data + case toesp_cmds_t::WIFI_GET_SSID: + UDBG("[Rainbow] ESP received command WIFI_GET_SSID\n"); + if ((this->wifi_config & static_cast(wifi_config_t::WIFI_ENABLE)) == static_cast(wifi_config_t::WIFI_ENABLE)) + { + this->tx_messages.push_back({15, static_cast(fromesp_cmds_t::SSID), 13, 'E', 'M', 'U', 'L', 'A', 'T', 'O', 'R', '_', 'S', 'S', 'I', 'D'}); + } + else + { + this->tx_messages.push_back({2, static_cast(fromesp_cmds_t::SSID), 0}); + } + break; + case toesp_cmds_t::WIFI_GET_IP: + UDBG("[Rainbow] ESP received command WIFI_GET_IP\n"); + if ((this->wifi_config & static_cast(wifi_config_t::WIFI_ENABLE)) == static_cast(wifi_config_t::WIFI_ENABLE)) + { + this->tx_messages.push_back({14, static_cast(fromesp_cmds_t::IP_ADDRESS), 12, '1', '9', '2', '.', '1', '6', '8', '.', '1', '.', '1', '0'}); + } + else + { + this->tx_messages.push_back({2, static_cast(fromesp_cmds_t::IP_ADDRESS), 0}); + } + break; + case toesp_cmds_t::WIFI_GET_CONFIG: + UDBG("[Rainbow] ESP received command WIFI_GET_CONFIG\n"); + this->tx_messages.push_back({2, static_cast(fromesp_cmds_t::WIFI_CONFIG), this->wifi_config}); + break; + case toesp_cmds_t::WIFI_SET_CONFIG: + UDBG("[Rainbow] ESP received command WIFI_SET_CONFIG\n"); + this->wifi_config = this->rx_buffer.at(2); + break; + + // AP CMDS + // AP_GET_SSID/AP_GET_IP config commands are not relevant here, so we'll just use fake data + case toesp_cmds_t::AP_GET_SSID: + UDBG("[Rainbow] ESP received command AP_GET_SSID\n"); + if ((this->wifi_config & static_cast(wifi_config_t::AP_ENABLE)) == static_cast(wifi_config_t::AP_ENABLE)) + { + this->tx_messages.push_back({18, static_cast(fromesp_cmds_t::SSID), 16, 'E', 'M', 'U', 'L', 'A', 'T', 'O', 'R', '_', 'A', 'P', '_', 'S', 'S', 'I', 'D'}); + } + else + { + this->tx_messages.push_back({2, static_cast(fromesp_cmds_t::SSID), 0}); + } + break; + case toesp_cmds_t::AP_GET_IP: + UDBG("[Rainbow] ESP received command AP_GET_ID\n"); + if ((this->wifi_config & static_cast(wifi_config_t::AP_ENABLE)) == static_cast(wifi_config_t::AP_ENABLE)) + { + this->tx_messages.push_back({16, static_cast(fromesp_cmds_t::IP_ADDRESS), 14, '1', '2', '7', '.', '0', '.', '0', '.', '1', ':', '8', '0', '8', '0'}); + } + else + { + this->tx_messages.push_back({2, static_cast(fromesp_cmds_t::IP_ADDRESS), 0}); + } + break; + + // RND CMDS + + case toesp_cmds_t::RND_GET_BYTE: + UDBG("[Rainbow] ESP received command RND_GET_BYTE\n"); + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::RND_BYTE), + static_cast(rand() % 256) + }); + break; + case toesp_cmds_t::RND_GET_BYTE_RANGE: + { + UDBG("[Rainbow] ESP received command RND_GET_BYTE_RANGE\n"); + if (message_size < 3) + { + break; + } + int const min_value = this->rx_buffer.at(2); + int const max_value = this->rx_buffer.at(3); + int const range = max_value - min_value; + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::RND_BYTE), + static_cast(min_value + (rand() % range)) + }); + break; + } + case toesp_cmds_t::RND_GET_WORD: + UDBG("[Rainbow] ESP received command RND_GET_WORD\n"); + this->tx_messages.push_back({ + 3, + static_cast(fromesp_cmds_t::RND_WORD), + static_cast(rand() % 256), + static_cast(rand() % 256) + }); + break; + case toesp_cmds_t::RND_GET_WORD_RANGE: + { + UDBG("[Rainbow] ESP received command RND_GET_WORD_RANGE\n"); + if (message_size < 5) + { + break; + } + int const min_value = (static_cast(this->rx_buffer.at(2)) << 8) + this->rx_buffer.at(3); + int const max_value = (static_cast(this->rx_buffer.at(4)) << 8) + this->rx_buffer.at(5); + int const range = max_value - min_value; + int const rand_value = min_value + (rand() % range); + this->tx_messages.push_back({ + 3, + static_cast(fromesp_cmds_t::RND_WORD), + static_cast(rand_value >> 8), + static_cast(rand_value & 0xff) + }); + break; + } + + // SERVER CMDS + + case toesp_cmds_t::SERVER_GET_STATUS: + { + UDBG("[Rainbow] ESP received command SERVER_GET_STATUS\n"); + uint8_t status; + switch (this->active_protocol) + { + case server_protocol_t::TCP: + // TODO actually check connection state + status = (this->tcp_socket != -1); // Considere server connection ok if we created a socket + break; + case server_protocol_t::TCP_SECURED: + // TODO + status = 0; + break; + case server_protocol_t::UDP: + status = (this->udp_socket != -1); // Considere server connection ok if we created a socket + break; + default: + status = 0; // Unknown active protocol, connection certainly broken + } + + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::SERVER_STATUS), + status + }); + break; + } + case toesp_cmds_t::SERVER_PING: + UDBG("[Rainbow] ESP received command SERVER_PING\n"); + if (!this->ping_thread.joinable()) + { + if (this->server_settings_address.empty()) + { + this->tx_messages.push_back({ + 1, + static_cast(fromesp_cmds_t::SERVER_PING) + }); + } + else if (message_size >= 1) + { + assert(!this->ping_thread.joinable()); + this->ping_ready = false; + uint8_t n = (message_size == 1 ? 0 : this->rx_buffer.at(2)); + if (n == 0) + { + n = 4; + } + this->ping_thread = thread(&BrokeStudioFirmware::pingRequest, this, n); + } + } + break; + case toesp_cmds_t::SERVER_SET_PROTOCOL: + { + UDBG("[Rainbow] ESP received command SERVER_SET_PROTOCOL\n"); + if (message_size == 2) + { + server_protocol_t requested_protocol = static_cast(this->rx_buffer.at(2)); + if (requested_protocol > server_protocol_t::UDP_POOL) + { + UDBG("[Rainbow] SERVER_SET_PROTOCOL: unknown protocol (%u)\n", static_cast(requested_protocol)); + } + else + { + if (requested_protocol == server_protocol_t::TCP_SECURED) + { + UDBG("[Rainbow] SERVER_SET_PROTOCOL: protocol TCP_SECURED not supported, falling back to TCP\n"); + requested_protocol = server_protocol_t::TCP; + } + this->active_protocol = requested_protocol; + } + } + break; + } + case toesp_cmds_t::SERVER_GET_SETTINGS: + { + UDBG("[Rainbow] ESP received command SERVER_GET_SETTINGS\n"); + if (this->server_settings_address.empty() && this->server_settings_port == 0) + { + this->tx_messages.push_back({ + 1, + static_cast(fromesp_cmds_t::SERVER_SETTINGS) + }); + } + else + { + deque message({ + static_cast(1 + 2 + 1 + this->server_settings_address.size()), + static_cast(fromesp_cmds_t::SERVER_SETTINGS), + static_cast(this->server_settings_port >> 8), + static_cast(this->server_settings_port & 0xff), + static_cast(this->server_settings_address.size()) + }); + message.insert(message.end(), this->server_settings_address.begin(), this->server_settings_address.end()); + this->tx_messages.push_back(message); + } + break; + } + case toesp_cmds_t::SERVER_SET_SETTINGS: + UDBG("[Rainbow] ESP received command SERVER_SET_SETTINGS\n"); + if (message_size >= 5) + { + this->server_settings_port = + (static_cast(this->rx_buffer.at(2)) << 8) + + (static_cast(this->rx_buffer.at(3))); + uint8_t len = this->rx_buffer.at(4); + this->server_settings_address = string(this->rx_buffer.begin() + 5, this->rx_buffer.begin() + 5 + len); + } + break; + case toesp_cmds_t::SERVER_GET_SAVED_SETTINGS: + { + UDBG("[Rainbow] ESP received command SERVER_GET_SAVED_SETTINGS\n"); + if (this->default_server_settings_address.empty() && this->default_server_settings_port == 0) + { + this->tx_messages.push_back({ + 1, + static_cast(fromesp_cmds_t::SERVER_SETTINGS) + }); + } + else + { + deque message({ + static_cast(1 + 2 + 1 + this->default_server_settings_address.size()), + static_cast(fromesp_cmds_t::SERVER_SETTINGS), + static_cast(this->default_server_settings_port >> 8), + static_cast(this->default_server_settings_port & 0xff), + static_cast(this->server_settings_address.size()) + }); + message.insert(message.end(), this->default_server_settings_address.begin(), this->default_server_settings_address.end()); + this->tx_messages.push_back(message); + } + break; + } + case toesp_cmds_t::SERVER_SET_SAVED_SETTINGS: + { + UDBG("[Rainbow] ESP received command SERVER_SET_SAVED_SETTINGS\n"); + if (message_size == 1) + { + this->default_server_settings_port = 0; + this->default_server_settings_address = ""; + } else if (message_size >= 5) + { + this->default_server_settings_port = + (static_cast(this->rx_buffer.at(2)) << 8) + + (static_cast(this->rx_buffer.at(3))); + uint8_t len = this->rx_buffer.at(4); + this->default_server_settings_address = string(this->rx_buffer.begin() + 5, this->rx_buffer.begin() + 5 + len); + this->server_settings_port = this->default_server_settings_port; + this->server_settings_address = default_server_settings_address; + } + break; + } + case toesp_cmds_t::SERVER_RESTORE_SAVED_SETTINGS: + UDBG("[Rainbow] ESP received command SERVER_RESTORE_SAVED_SETTINGS\n"); + this->server_settings_address = this->default_server_settings_address; + this->server_settings_port = this->default_server_settings_port; + break; + case toesp_cmds_t::SERVER_CONNECT: + UDBG("[Rainbow] ESP received command SERVER_CONNECT\n"); + this->openConnection(); + break; + case toesp_cmds_t::SERVER_DISCONNECT: + UDBG("[Rainbow] ESP received command SERVER_DISCONNECT\n"); + this->closeConnection(); + break; + case toesp_cmds_t::SERVER_SEND_MSG: + { + UDBG("[Rainbow] ESP received command SERVER_SEND_MSG"); + uint8_t const payload_size = static_cast(this->rx_buffer.size() - 2); + deque::const_iterator payload_begin = this->rx_buffer.begin() + 2; + deque::const_iterator payload_end = payload_begin + payload_size; + + switch (this->active_protocol) + { + case server_protocol_t::TCP: + this->sendTcpDataToServer(payload_begin, payload_end); + break; + case server_protocol_t::TCP_SECURED: + UDBG("[Rainbow] ESP protocol TCP_SECURED not implemented\n"); + break; + case server_protocol_t::UDP: + this->sendUdpDatagramToServer(payload_begin, payload_end); + break; + default: + UDBG("[Rainbow] ESP protocol (%u) not implemented\n", static_cast(this->active_protocol)); + }; + break; + } + + // UDP ADDRESS POOL CMDS + + case toesp_cmds_t::UDP_ADDR_POOL_CLEAR: + UDBG("[Rainbow] ESP received command UDP_ADDR_POOL_CLEAR"); + for(size_t i = 0; i < 16; i++) { + this->ipAddressPool[i].ipAddress = ""; + this->ipAddressPool[i].port = 0; + } + break; + + case toesp_cmds_t::UDP_ADDR_POOL_ADD: + { + UDBG("[Rainbow] ESP received command UDP_ADDR_POOL_ADD"); + int port = + (static_cast(this->rx_buffer.at(2)) << 8) + + (static_cast(this->rx_buffer.at(3))); + uint8_t len = this->rx_buffer.at(4); + if(len >= 16) break; + string ipAddress = string(this->rx_buffer.begin() + 5, this->rx_buffer.begin() + 5 + len); + + for(size_t i = 0; i < 16; i++) { + if(this->ipAddressPool[i].ipAddress == ipAddress && this->ipAddressPool[i].port == port) + break; + } + + for(size_t i = 0; i < 16; i++) { + if(this->ipAddressPool[i].ipAddress == "") { + this->ipAddressPool[i].ipAddress = ipAddress; + this->ipAddressPool[i].port = port; + break; + } + } + + break; + } + + case toesp_cmds_t::UDP_ADDR_POOL_REMOVE: + { + UDBG("[Rainbow] ESP received command UDP_ADDR_POOL_REMOVE"); + int port = + (static_cast(this->rx_buffer.at(2)) << 8) + + (static_cast(this->rx_buffer.at(3))); + uint8_t len = this->rx_buffer.at(4); + if(len >= 16) break; + string ipAddress = string(this->rx_buffer.begin() + 5, this->rx_buffer.begin() + 5 + len); + + for(size_t i = 0; i < 16; i++) { + if(this->ipAddressPool[i].ipAddress == ipAddress && this->ipAddressPool[i].port == port) { + this->ipAddressPool[i].ipAddress = ""; + this->ipAddressPool[i].port = 0; + break; + } + } + break; + } + + case toesp_cmds_t::UDP_ADDR_POOL_SEND_MSG: + { + UDBG("[Rainbow] ESP received command UDP_ADDR_POOL_SEND_MSG"); + if (this->active_protocol == server_protocol_t::UDP_POOL) { + uint8_t const payload_size = static_cast(this->rx_buffer.size() - 2); + deque::const_iterator payload_begin = this->rx_buffer.begin() + 2; + deque::const_iterator payload_end = payload_begin + payload_size; + this->sendUdpDatagramToPool(payload_begin, payload_end); + } + break; + } + + // NETWORK CMDS + // network commands are not relevant here, so we'll just use test/fake data + case toesp_cmds_t::NETWORK_SCAN: + UDBG("[Rainbow] ESP received command NETWORK_SCAN\n"); + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::NETWORK_SCAN_RESULT), + NUM_FAKE_NETWORKS + }); + break; + case toesp_cmds_t::NETWORK_GET_SCAN_RESULT: + UDBG("[Rainbow] ESP received command NETWORK_GET_SCAN_RESULT\n"); + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::NETWORK_SCAN_RESULT), + NUM_FAKE_NETWORKS + }); + break; + case toesp_cmds_t::NETWORK_GET_SCANNED_DETAILS: + UDBG("[Rainbow] ESP received command NETWORK_GET_SCANNED_DETAILS\n"); + if (message_size == 2) + { + uint8_t networkItem = this->rx_buffer.at(2); + if (networkItem > NUM_FAKE_NETWORKS - 1) + networkItem = NUM_FAKE_NETWORKS - 1; + this->tx_messages.push_back({ + 24, + static_cast(fromesp_cmds_t::NETWORK_SCANNED_DETAILS), + 4, // encryption type + 0x47, // RSSI + 0x00, 0x00, 0x00, 0x01, // channel + 0, // hidden? + 15, // SSID length + 'E', 'M', 'U', 'L', 'A', 'T', 'O', 'R', '_', 'S', 'S', 'I', 'D', '_', static_cast(networkItem + '0') // SSID + }); + } + break; + case toesp_cmds_t::NETWORK_GET_REGISTERED: + UDBG("[Rainbow] ESP received command NETWORK_GET_REGISTERED\n"); + if (message_size == 1) + { + this->tx_messages.push_back({ + NUM_NETWORKS + 1, + static_cast(fromesp_cmds_t::NETWORK_REGISTERED), + static_cast((this->networks[0].ssid != "") ? 1 : 0), + static_cast((this->networks[1].ssid != "") ? 1 : 0), + static_cast((this->networks[2].ssid != "") ? 1 : 0) + }); + } + break; + case toesp_cmds_t::NETWORK_GET_REGISTERED_DETAILS: + UDBG("[Rainbow] ESP received command NETWORK_GET_REGISTERED_DETAILS\n"); + if (message_size == 2) + { + uint8_t networkItem = this->rx_buffer.at(2); + if (networkItem > NUM_NETWORKS - 1) + networkItem = NUM_NETWORKS - 1; + deque message({ + static_cast(2 + 1 + this->networks[networkItem].ssid.length() + 1 + this->networks[networkItem].pass.length()), + static_cast(fromesp_cmds_t::NETWORK_REGISTERED_DETAILS), + static_cast(this->networks[networkItem].active ? 1 : 0), + static_cast(this->networks[networkItem].ssid.length()) + }); + message.insert(message.end(), this->networks[networkItem].ssid.begin(), this->networks[networkItem].ssid.end()); + message.insert(message.end(), static_cast(this->networks[networkItem].pass.length())); + message.insert(message.end(), this->networks[networkItem].pass.begin(), this->networks[networkItem].pass.end()); + this->tx_messages.push_back(message); + } + break; + case toesp_cmds_t::NETWORK_REGISTER: + UDBG("[Rainbow] ESP received command NETWORK_REGISTER\n"); + if (message_size >= 8) + { + uint8_t const networkItem = this->rx_buffer.at(2); + if (networkItem > NUM_NETWORKS - 1) + break; + bool const networkActive = this->rx_buffer.at(3) == 0 ? false : true; + if (networkActive) + { + for (size_t i = 0; i < NUM_NETWORKS; ++i) + { + this->networks[i].active = false; + } + } + this->networks[networkItem].active = networkActive; + uint8_t SSIDlength = min(SSID_MAX_LENGTH, this->rx_buffer.at(4)); + uint8_t PASSlength = min(PASS_MAX_LENGTH, this->rx_buffer.at(5 + SSIDlength)); + this->networks[networkItem].ssid = string(this->rx_buffer.begin() + 5, this->rx_buffer.begin() + 5 + SSIDlength); + this->networks[networkItem].pass = string(this->rx_buffer.begin() + 5 + SSIDlength + 1, this->rx_buffer.begin() + 5 + SSIDlength + 1 + PASSlength); + } + break; + case toesp_cmds_t::NETWORK_UNREGISTER: + UDBG("[Rainbow] ESP received command NETWORK_UNREGISTER\n"); + if (message_size == 2) + { + uint8_t const networkItem = this->rx_buffer.at(2); + if (networkItem > NUM_NETWORKS - 1) + break; + this->networks[networkItem].ssid = ""; + this->networks[networkItem].pass = ""; + this->networks[networkItem].active = false; + } + break; + case toesp_cmds_t::NETWORK_SET_ACTIVE: + UDBG("[Rainbow] ESP received command NETWORK_SET_ACTIVE: "); + if (message_size == 3) + { + uint8_t const networkItem = this->rx_buffer.at(2); + if (networkItem > NUM_NETWORKS - 1) + break; + bool const networkActive = this->rx_buffer.at(3) == 0 ? false : true; + UDBG("[Rainbow] ESP network %d (%s)\n", networkItem, networkActive ? "active" : "inactive"); + if (this->networks[networkItem].ssid == "") + break; + if (networkActive) + { + for (size_t i = 0; i < NUM_NETWORKS; ++i) + { + this->networks[i].active = false; + } + } + this->networks[networkItem].active = networkActive; + } + break; + + // FILE CMDS + + case toesp_cmds_t::FILE_OPEN: + { + UDBG("[Rainbow] ESP received command FILE_OPEN\n"); + if (message_size >= 4) + { + uint8_t config = this->rx_buffer.at(2); + FileConfig file_config = parseFileConfig(config); + string filename; + + if (file_config.access_mode == static_cast(file_config_flags_t::ACCESS_MODE_AUTO)) + { + uint8_t const path = this->rx_buffer.at(3); + uint8_t const file = this->rx_buffer.at(4); + if (path < NUM_FILE_PATHS && file < NUM_FILES) + { + filename = getAutoFilename(path, file); + int i = findFile(file_config.drive, filename); + if (i == -1) + { + FileStruct temp_file = {file_config.drive, filename, vector()}; + this->files.push_back(temp_file); + } + } + } + else if (file_config.access_mode == static_cast(file_config_flags_t::ACCESS_MODE_MANUAL)) + { + uint8_t const path_length = this->rx_buffer.at(3); + filename = string(this->rx_buffer.begin() + 4, this->rx_buffer.begin() + 4 + path_length); + int i = findFile(file_config.drive, filename); + if (i == -1) + { + FileStruct temp_file = {file_config.drive, filename, vector()}; + this->files.push_back(temp_file); + } + } + int i = findFile(file_config.drive, filename); + this->working_file.active = true; + this->working_file.offset = 0; + this->working_file.file = &this->files.at(i); + this->saveFiles(); + } + break; + } + case toesp_cmds_t::FILE_CLOSE: + UDBG("[Rainbow] ESP received command FILE_CLOSE\n"); + this->working_file.active = false; + this->saveFiles(); + break; + case toesp_cmds_t::FILE_STATUS: + { + UDBG("[Rainbow] ESP received command FILE_STATUS\n"); + + if (this->working_file.active == false) + { + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::FILE_STATUS), + 0 + }); + } + else + { + FileConfig file_config = parseFileConfig(this->working_file.config); + if (file_config.access_mode == static_cast(file_config_flags_t::ACCESS_MODE_AUTO)) + { + this->tx_messages.push_back({ + 5, + static_cast(fromesp_cmds_t::FILE_STATUS), + 1, + static_cast(this->working_file.config), + static_cast(this->working_file.auto_path), + static_cast(this->working_file.auto_file), + }); + } + else if (file_config.access_mode == static_cast(file_config_flags_t::ACCESS_MODE_MANUAL)) + { + string filename = this->working_file.file->filename; + filename = filename.substr(filename.find_first_of("/") + 1); + deque message({ + static_cast(3 + filename.size()), + static_cast(fromesp_cmds_t::FILE_STATUS), + 1, + static_cast(filename.size()), + }); + message.insert(message.end(), filename.begin(), filename.end()); + this->tx_messages.push_back(message); + } + } + break; + } + case toesp_cmds_t::FILE_EXISTS: + { + UDBG("[Rainbow] ESP received command FILE_EXISTS\n"); + + if (message_size < 2) + { + break; + } + uint8_t config = this->rx_buffer.at(2); + FileConfig file_config = parseFileConfig(config); + string filename; + int i = -1; + + if (file_config.access_mode == static_cast(file_config_flags_t::ACCESS_MODE_AUTO)) + { + if (message_size == 4) + { + uint8_t const path = this->rx_buffer.at(3); + uint8_t const file = this->rx_buffer.at(4); + filename = getAutoFilename(path, file); + } + } + else if (file_config.access_mode == static_cast(file_config_flags_t::ACCESS_MODE_MANUAL)) + { + uint8_t const path_length = this->rx_buffer.at(3); + filename = string(this->rx_buffer.begin() + 4, this->rx_buffer.begin() + 4 + path_length); + } + + // special case just for emulation + if (filename != "/web/") + { + if (filename.find_last_of("/") == filename.length() - 1) + { + i = findPath(file_config.drive, filename); + } + else + { + i = findFile(file_config.drive, filename); + } + } + + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::FILE_EXISTS), + static_cast(i == -1 ? 0 : 1) + }); + break; + } + case toesp_cmds_t::FILE_DELETE: + { + UDBG("[Rainbow] ESP received command FILE_DELETE\n"); + + if (message_size < 2) + { + break; + } + uint8_t config = this->rx_buffer.at(2); + FileConfig file_config = parseFileConfig(config); + string filename; + int i = -1; + + if (file_config.access_mode == static_cast(file_config_flags_t::ACCESS_MODE_AUTO)) + { + if (message_size == 4) + { + uint8_t const path = this->rx_buffer.at(3); + uint8_t const file = this->rx_buffer.at(4); + if (path < NUM_FILE_PATHS && file < NUM_FILES) + { + filename = getAutoFilename(path, file); + } + else + { + // Invalid path or file + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::FILE_DELETE), + static_cast(file_delete_results_t::INVALID_PATH_OR_FILE) + }); + break; + } + } + } + else if (file_config.access_mode == static_cast(file_config_flags_t::ACCESS_MODE_MANUAL)) + { + uint8_t const path_length = this->rx_buffer.at(4); + filename = string(this->rx_buffer.begin() + 5, this->rx_buffer.begin() + 5 + path_length); + } + + i = findFile(file_config.drive, filename); + if (i == -1) + { + // File does not exist + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::FILE_DELETE), + static_cast(file_delete_results_t::FILE_NOT_FOUND) + }); + break; + } + else + { + this->files.erase(this->files.begin() + i); + this->saveFiles(); + } + + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::FILE_DELETE), + static_cast(file_delete_results_t::SUCCESS) + }); + + break; + } + case toesp_cmds_t::FILE_SET_CUR: + UDBG("[Rainbow] ESP received command FILE_SET_CUR\n"); + if (message_size >= 2 && message_size <= 5) + { + if (this->working_file.active) + { + this->working_file.offset = this->rx_buffer.at(2); + if(message_size == 3) this->working_file.offset += this->rx_buffer.at(3) << 8; + if(message_size == 4) this->working_file.offset += this->rx_buffer.at(4) << 16; + if(message_size == 5) this->working_file.offset += this->rx_buffer.at(5) << 24; + } + } + break; + case toesp_cmds_t::FILE_READ: + UDBG("[Rainbow] ESP received command FILE_READ\n"); + if (message_size == 2) + { + if (this->working_file.active) + { + uint8_t const n = this->rx_buffer.at(2); + this->readFile(n); + this->working_file.offset += n; + UDBG("[Rainbow] ESP working file offset: %u (%x)\n", this->working_file.offset, this->working_file.offset); + /*UDBG("file size: %lu bytes\n", this->esp_files[this->working_path_auto][this->working_file_auto].size()); + if (this->working_file.offset > this->esp_files[this->working_path_auto][this->working_file_auto].size()) { + this->working_file.offset = this->esp_files[this->working_path_auto][this->working_file_auto].size(); + }*/ + } + else + { + this->tx_messages.push_back({2, static_cast(fromesp_cmds_t::FILE_DATA), 0}); + } + } + break; + case toesp_cmds_t::FILE_WRITE: + UDBG("[Rainbow] ESP received command FILE_WRITE\n"); + if (message_size >= 2 && this->working_file.active) + { + this->writeFile(this->rx_buffer.begin() + 2, this->rx_buffer.begin() + message_size + 1); + this->working_file.offset += message_size - 1; + } + break; + case toesp_cmds_t::FILE_APPEND: + UDBG("[Rainbow] ESP received command FILE_APPEND\n"); + if (message_size >= 2 && this->working_file.active) + { + this->appendFile(this->rx_buffer.begin() + 2, this->rx_buffer.begin() + message_size + 1); + } + break; + case toesp_cmds_t::FILE_COUNT: + { + UDBG("[Rainbow] ESP received command FILE_COUNT\n"); + + if (message_size < 2) + { + break; + } + uint8_t config = this->rx_buffer.at(2); + FileConfig file_config = parseFileConfig(config); + + if (file_config.access_mode == static_cast(file_config_flags_t::ACCESS_MODE_AUTO)) + { + if (message_size == 3) + { + uint8_t const path = this->rx_buffer.at(3); + if (path >= NUM_FILE_PATHS) + { + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::FILE_COUNT), + 0 + }); + } + else + { + uint8_t nb_files = 0; + + for (uint8_t file = 0; file < NUM_FILES; ++file) + { + string filename = getAutoFilename(path, file); + int i = findFile(file_config.drive, filename); + if (i != -1) + nb_files++; + } + + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::FILE_COUNT), + nb_files + }); + UDBG("[Rainbow] ESP %u files found in path %u\n", nb_files, path); + } + } + } + else + { + // TODO manual mode + UDBG("[Rainbow] ESP command FILE_COUNT manual mode not implemented\n"); + } + + break; + } + case toesp_cmds_t::FILE_GET_LIST: + { + UDBG("[Rainbow] ESP received command FILE_GET_LIST\n"); + + if (message_size < 2) + { + break; + } + uint8_t config = this->rx_buffer.at(2); + FileConfig file_config = parseFileConfig(config); + + if (file_config.access_mode == static_cast(file_config_flags_t::ACCESS_MODE_AUTO)) + { + if (message_size >= 3) + { + vector existing_files; + uint8_t const path = this->rx_buffer.at(3); + uint8_t page_size = NUM_FILES; + uint8_t current_page = 0; + if (message_size == 5) + { + page_size = this->rx_buffer.at(4); + current_page = this->rx_buffer.at(5); + } + uint8_t page_start = current_page * page_size; + uint8_t page_end = current_page * page_size + page_size; + uint8_t nb_files = 0; + + for (uint8_t file = 0; file < NUM_FILES; ++file) + { + string filename = getAutoFilename(path, file); + int i = findFile(file_config.drive, filename); + if (i != -1) + nb_files++; + } + + if (page_end > nb_files) + { + page_end = nb_files; + } + + nb_files = 0; + for (uint8_t file = 0; file < NUM_FILES; ++file) + { + string filename = getAutoFilename(path, file); + int i = findFile(file_config.drive, filename); + if (i != -1) + { + if (nb_files >= page_start && nb_files < page_end) + { + existing_files.push_back(file); + } + nb_files++; + } + if (nb_files >= page_end) + break; + } + + deque message({ + static_cast(existing_files.size() + 2), + static_cast(fromesp_cmds_t::FILE_LIST), + static_cast(existing_files.size())} + ); + message.insert(message.end(), existing_files.begin(), existing_files.end()); + this->tx_messages.push_back(message); + } + } + else + { + // TODO manual mode + UDBG("[Rainbow] ESP command FILE_GET_LIST manual mode not implemented\n"); + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::FILE_LIST), + 0 + }); + } + break; + } + case toesp_cmds_t::FILE_GET_FREE_ID: + UDBG("[Rainbow] ESP received command FILE_GET_FREE_ID\n"); + if (message_size == 3) + { + uint8_t const drive = this->rx_buffer.at(2); + uint8_t const path = this->rx_buffer.at(3); + uint8_t i; + + for (i = 0; i < NUM_FILES; ++i) + { + string filename = getAutoFilename(path, i); + int f = findFile(drive, filename); + if (f == -1) + break; + } + + if (i != NUM_FILES) + { + // Free file ID found + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::FILE_ID), + i, + }); + } + else + { + // Free file ID not found + this->tx_messages.push_back({ + 1, + static_cast(fromesp_cmds_t::FILE_ID) + }); + } + } + break; + case toesp_cmds_t::FILE_GET_FS_INFO: + { + UDBG("[Rainbow] ESP received command FILE_GET_FS_INFO\n"); + if (message_size < 2) + { + break; + } + uint8_t config = this->rx_buffer.at(2); + FileConfig file_config = parseFileConfig(config); + uint64_t free = 0; + uint64_t used = 0; + uint8_t free_pct = 0; + uint8_t used_pct = 0; + if (file_config.drive == static_cast(file_config_flags_t::DESTINATION_ESP)) + { + + for (size_t i = 0; i < this->files.size(); ++i) + { + if (this->files.at(i).drive == static_cast(file_config_flags_t::DESTINATION_ESP)) + { + used += this->files.at(i).data.size(); + } + } + + free = ESP_FLASH_SIZE - used; + free_pct = ((ESP_FLASH_SIZE - used) * 100) / ESP_FLASH_SIZE; + used_pct = 100 - free_pct; // (used * 100) / ESP_FLASH_SIZE; + + this->tx_messages.push_back({ + 27, + static_cast(fromesp_cmds_t::FILE_FS_INFO), + (ESP_FLASH_SIZE >> 54) & 0xff, + (ESP_FLASH_SIZE >> 48) & 0xff, + (ESP_FLASH_SIZE >> 40) & 0xff, + (ESP_FLASH_SIZE >> 32) & 0xff, + (ESP_FLASH_SIZE >> 24) & 0xff, + (ESP_FLASH_SIZE >> 16) & 0xff, + (ESP_FLASH_SIZE >> 8) & 0xff, + (ESP_FLASH_SIZE)&0xff, + static_cast((free >> 54) & 0xff), + static_cast((free >> 48) & 0xff), + static_cast((free >> 40) & 0xff), + static_cast((free >> 32) & 0xff), + static_cast((free >> 24) & 0xff), + static_cast((free >> 16) & 0xff), + static_cast((free >> 8) & 0xff), + static_cast((free)&0xff), + free_pct, + static_cast((used >> 54) & 0xff), + static_cast((used >> 48) & 0xff), + static_cast((used >> 40) & 0xff), + static_cast((used >> 32) & 0xff), + static_cast((used >> 24) & 0xff), + static_cast((used >> 16) & 0xff), + static_cast((used >> 8) & 0xff), + static_cast((used)&0xff), + used_pct + }); + break; + } + else if (file_config.drive == static_cast(file_config_flags_t::DESTINATION_SD)) + { + if (isSdCardFilePresent) + { + + for (size_t i = 0; i < this->files.size(); ++i) + { + if (this->files.at(i).drive == static_cast(file_config_flags_t::DESTINATION_SD)) + { + used += this->files.at(i).data.size(); + } + } + + free = SD_CARD_SIZE - used; + free_pct = ((SD_CARD_SIZE - used) * 100) / SD_CARD_SIZE; + used_pct = 100 - free_pct; // (used * 100) / SD_CARD_SIZE; + + this->tx_messages.push_back({ + 27, + static_cast(fromesp_cmds_t::FILE_FS_INFO), + (SD_CARD_SIZE >> 54) & 0xff, + (SD_CARD_SIZE >> 48) & 0xff, + (SD_CARD_SIZE >> 40) & 0xff, + (SD_CARD_SIZE >> 32) & 0xff, + (SD_CARD_SIZE >> 24) & 0xff, + (SD_CARD_SIZE >> 16) & 0xff, + (SD_CARD_SIZE >> 8) & 0xff, + (SD_CARD_SIZE)&0xff, + static_cast((free >> 54) & 0xff), + static_cast((free >> 48) & 0xff), + static_cast((free >> 40) & 0xff), + static_cast((free >> 32) & 0xff), + static_cast((free >> 24) & 0xff), + static_cast((free >> 16) & 0xff), + static_cast((free >> 8) & 0xff), + static_cast((free)&0xff), + free_pct, + static_cast((used >> 54) & 0xff), + static_cast((used >> 48) & 0xff), + static_cast((used >> 40) & 0xff), + static_cast((used >> 32) & 0xff), + static_cast((used >> 24) & 0xff), + static_cast((used >> 16) & 0xff), + static_cast((used >> 8) & 0xff), + static_cast((used)&0xff), + used_pct + }); + break; + } + } + this->tx_messages.push_back({ + 1, + static_cast(fromesp_cmds_t::FILE_FS_INFO) + }); + break; + } + case toesp_cmds_t::FILE_GET_INFO: + { + UDBG("[Rainbow] ESP received command FILE_GET_INFO\n"); + + if (message_size < 2) + { + break; + } + uint8_t config = this->rx_buffer.at(2); + FileConfig file_config = parseFileConfig(config); + + if (file_config.access_mode == static_cast(file_config_flags_t::ACCESS_MODE_AUTO)) + { + if (message_size == 4) + { + uint8_t const path = this->rx_buffer.at(3); + uint8_t const file = this->rx_buffer.at(4); + string filename = getAutoFilename(path, file); + int i = findFile(file_config.drive, filename); + if (path < NUM_FILE_PATHS && file < NUM_FILES && i != -1) + { + // Compute info + uint32_t file_crc32; + file_crc32 = CalcCRC32(0L, this->files.at(i).data.data(), this->files.at(i).data.size()); + size_t file_size = this->files.at(i).data.size(); + + // Send info + this->tx_messages.push_back({ + 9, + static_cast(fromesp_cmds_t::FILE_INFO), + + static_cast((file_crc32 >> 24) & 0xff), + static_cast((file_crc32 >> 16) & 0xff), + static_cast((file_crc32 >> 8) & 0xff), + static_cast(file_crc32 & 0xff), + + static_cast((file_size >> 24) & 0xff), + static_cast((file_size >> 16) & 0xff), + static_cast((file_size >> 8) & 0xff), + static_cast(file_size & 0xff) + }); + } + else + { + // File not found or path/file out of bounds + this->tx_messages.push_back({ + 1, + static_cast(fromesp_cmds_t::FILE_INFO) + }); + } + } + } + else + { + // TODO manual mode + UDBG("[Rainbow] ESP command FILE_GET_INFO manual mode not implemented\n"); + } + + break; + } + case toesp_cmds_t::FILE_DOWNLOAD: + { + UDBG("[Rainbow] ESP received command FILE_DOWNLOAD\n"); + + if (message_size < 2) + { + break; + } + uint8_t config = this->rx_buffer.at(2); + FileConfig file_config = parseFileConfig(config); + + if (file_config.access_mode == static_cast(file_config_flags_t::ACCESS_MODE_AUTO)) + { + if (message_size > 6) + { + // Parse + uint8_t const urlLength = this->rx_buffer.at(3); + if (message_size != urlLength + 5) + { + break; + } + string const url(this->rx_buffer.begin() + 4, this->rx_buffer.begin() + 4 + urlLength); + + uint8_t const path = this->rx_buffer.at(4 + urlLength); + uint8_t const file = this->rx_buffer.at(4 + 1 + urlLength); + + // Delete existing file + if (path < NUM_FILE_PATHS && file < NUM_FILES) + { + string filename = getAutoFilename(path, file); + int i = findFile(file_config.drive, filename); + if (i != -1) + { + this->files.erase(this->files.begin() + i); + this->saveFiles(); + } + } + else + { + // Invalid path / file + this->tx_messages.push_back({ + 4, + static_cast(fromesp_cmds_t::FILE_DOWNLOAD), + static_cast(file_download_results_t::INVALID_DESTINATION), + 0, + 0 + }); + break; + } + + // Download new file + this->downloadFile(url, path, file); + } + } + else + { + // TODO manual mode + UDBG("[Rainbow] ESP command FILE_DOWNLOAD manual mode not implemented\n"); + } + break; + } + case toesp_cmds_t::FILE_FORMAT: + UDBG("[Rainbow] ESP received command FILE_FORMAT\n"); + if (message_size == 2) + { + uint8_t drive = rx_buffer.at(2); + clearFiles(drive); + } + break; + default: + UDBG("[Rainbow] ESP received unknown message %02x\n", this->rx_buffer.at(1)); + break; + }; + + // Remove processed message + this->rx_buffer.clear(); +} + +FileConfig BrokeStudioFirmware::parseFileConfig(uint8_t config) +{ + return FileConfig({ + static_cast(config & static_cast(file_config_flags_t::ACCESS_MODE_MASK)), + static_cast((config & static_cast(file_config_flags_t::DESTINATION_MASK))) + }); +} + +int BrokeStudioFirmware::findFile(uint8_t drive, string filename) +{ + for (size_t i = 0; i < this->files.size(); ++i) + { + if ((this->files.at(i).drive == drive) && (this->files.at(i).filename == filename)) + { + return static_cast(i); + } + } + return -1; +} + +int BrokeStudioFirmware::findPath(uint8_t drive, string path) +{ + for (size_t i = 0; i < this->files.size(); ++i) + { + if ((this->files.at(i).drive == drive) && (this->files.at(i).filename.substr(0, path.length()) == path)) + { + return static_cast(i); + } + } + return -1; +} + +string BrokeStudioFirmware::getAutoFilename(uint8_t path, uint8_t file) +{ + return "/" + dir_names[path] + "/file" + std::to_string(file) + ".bin"; +} + +void BrokeStudioFirmware::readFile(uint8_t n) +{ + // Get data range + vector::const_iterator data_begin; + vector::const_iterator data_end; + if (this->working_file.offset >= this->working_file.file->data.size()) + { + data_begin = this->working_file.file->data.end(); + data_end = data_begin; + } + else + { + data_begin = this->working_file.file->data.begin() + this->working_file.offset; + data_end = this->working_file.file->data.begin() + min(static_cast::size_type>(this->working_file.offset) + n, this->working_file.file->data.size()); + } + vector::size_type const data_size = data_end - data_begin; + + // Write response + deque message({ + static_cast(data_size + 2), + static_cast(fromesp_cmds_t::FILE_DATA), + static_cast(data_size) + }); + message.insert(message.end(), data_begin, data_end); + this->tx_messages.push_back(message); +} + +template +void BrokeStudioFirmware::writeFile(I data_begin, I data_end) +{ + if (this->working_file.active == false) + { + return; + } + + auto const data_size = data_end - data_begin; + uint32_t const offset_end = this->working_file.offset + data_size; + if (offset_end > this->working_file.file->data.size()) + { + this->working_file.file->data.resize(offset_end, 0); + } + + for (vector::size_type i = this->working_file.offset; i < offset_end; ++i) + { + this->working_file.file->data[i] = *data_begin; + ++data_begin; + } +} + +template +void BrokeStudioFirmware::appendFile(I data_begin, I data_end) +{ + if (this->working_file.active == false) { + return; + } + + auto const data_size = data_end - data_begin; + size_t file_size = this->working_file.file->data.size(); + uint32_t const offset_end = file_size + data_size; + this->working_file.file->data.resize(offset_end, 0); + + for (vector::size_type i = file_size; i < offset_end; ++i) { + this->working_file.file->data[i] = *data_begin; + ++data_begin; + } +} + +void BrokeStudioFirmware::saveFiles() +{ +#ifdef _WIN32 + char *value = nullptr; + size_t len; + + if (_dupenv_s(&value, &len, "RAINBOW_ESP_FILESYSTEM_FILE") == 0 && value != nullptr) + { + saveFile(0, value); + } + else + { + FCEU_printf("[Rainbow] RAINBOW_ESP_FILESYSTEM_FILE environment variable is not set\n"); + } + + free(value); + + if (_dupenv_s(&value, &len, "RAINBOW_SD_FILESYSTEM_FILE") == 0 && value != nullptr) + { + saveFile(2, value); + } + else + { + FCEU_printf("[Rainbow] RAINBOW_SD_FILESYSTEM_FILE environment variable is not set\n"); + } + + free(value); +#else + char const *esp_filesystem_file_path = ::getenv("RAINBOW_ESP_FILESYSTEM_FILE"); + if (esp_filesystem_file_path == NULL) + { + FCEU_printf("[Rainbow] RAINBOW_ESP_FILESYSTEM_FILE environment variable is not set\n"); + } + else + { + saveFile(0, esp_filesystem_file_path); + } + + char const *sd_filesystem_file_path = ::getenv("RAINBOW_SD_FILESYSTEM_FILE"); + if (sd_filesystem_file_path == NULL) + { + FCEU_printf("[Rainbow] RAINBOW_SD_FILESYSTEM_FILE environment variable is not set\n"); + } + else + { + saveFile(2, sd_filesystem_file_path); + } +#endif +} + +void BrokeStudioFirmware::saveFile(uint8_t drive, char const *filename) +{ + ofstream ofs(filename, std::fstream::binary); + if (ofs.fail()) + { + FCEU_printf("[Rainbow] Couldn't open RAINBOW_FILESYSTEM_FILE (%s)\n", filename); + return; + } + + // header + ofs << 'R'; + ofs << 'N'; + ofs << 'B'; + ofs << 'W'; + ofs << 'F'; + ofs << 'S'; + ofs << (char)0x1A; + + // file format version + ofs << (char)(0x00); + + for (auto file = this->files.begin(); file != this->files.end(); ++file) + { + if (file->drive != drive) + continue; + + // file separator + ofs << 'F'; + ofs << '>'; + + // filename length + ofs << (char)file->filename.length(); + + // filename + for (char &c : string(file->filename)) + { + ofs << (c); + } + // data size + size_t size = file->data.size(); + ofs << (char)((size & 0xff000000) >> 24); + ofs << (char)((size & 0x00ff0000) >> 16); + ofs << (char)((size & 0x0000ff00) >> 8); + ofs << (char)((size & 0x000000ff)); + + // actual data + for (uint8_t byte : file->data) + { + ofs << (char)byte; + } + } +} + +void BrokeStudioFirmware::loadFiles() +{ +#ifdef _WIN32 + char *value = nullptr; + size_t len; + + if (_dupenv_s(&value, &len, "RAINBOW_ESP_FILESYSTEM_FILE") == 0 && value != nullptr) + { + isEspFlashFilePresent = true; + loadFile(0, value); + } + else + { + isEspFlashFilePresent = false; + FCEU_printf("RAINBOW_ESP_FILESYSTEM_FILE environment variable is not set\n"); + } + + free(value); + + if (_dupenv_s(&value, &len, "RAINBOW_SD_FILESYSTEM_FILE") == 0 && value != nullptr) + { + isSdCardFilePresent = true; + loadFile(2, value); + } + else + { + isSdCardFilePresent = false; + FCEU_printf("RAINBOW_SD_FILESYSTEM_FILE environment variable is not set\n"); + } + + free(value); +#else + char const *esp_filesystem_file_path = ::getenv("RAINBOW_ESP_FILESYSTEM_FILE"); + if (esp_filesystem_file_path == NULL) + { + isEspFlashFilePresent = false; + FCEU_printf("RAINBOW_ESP_FILESYSTEM_FILE environment variable is not set\n"); + } + else + { + isEspFlashFilePresent = true; + loadFile(0, esp_filesystem_file_path); + } + + char const *sd_filesystem_file_path = ::getenv("RAINBOW_SD_FILESYSTEM_FILE"); + if (sd_filesystem_file_path == NULL) + { + isSdCardFilePresent = false; + FCEU_printf("RAINBOW_SD_FILESYSTEM_FILE environment variable is not set\n"); + } + else + { + isSdCardFilePresent = true; + loadFile(2, sd_filesystem_file_path); + } +#endif +} + +void BrokeStudioFirmware::loadFile(uint8_t drive, char const *filename) +{ + ifstream ifs(filename, std::fstream::binary); + if (ifs.fail()) + { + FCEU_printf("Couldn't open RAINBOW_FILESYSTEM_FILE (%s)\n", filename); + return; + } + + clearFiles(drive); + + uint8_t l; + uint8_t t; + uint32_t size; + uint8_t v; + + // check file header + string header; + header.push_back(ifs.get()); // R + header.push_back(ifs.get()); // N + header.push_back(ifs.get()); // B + header.push_back(ifs.get()); // W + header.push_back(ifs.get()); // F + header.push_back(ifs.get()); // S + header.push_back(ifs.get()); // 0x1A + if (header != "RNBWFS\x1a") + { + FCEU_printf("RAINBOW_FILESYSTEM_FILE (%s) file invalid\n", filename); + return; + } + + // file format version + v = ifs.get(); + + if (v == 0) + { + while (ifs.peek() != EOF) + { + + // check file separator + header = ""; + header.push_back(ifs.get()); // F + header.push_back(ifs.get()); //> + if (header != "F>") + { + FCEU_printf("RAINBOW_FILESYSTEM_FILE (%s) file malformed\n", filename); + return; + } + + FileStruct temp_file; + + // drive + temp_file.drive = drive; + + // filename length + l = ifs.get(); + temp_file.filename.reserve(l); + + // filename + for (size_t i = 0; i < l; ++i) + { + temp_file.filename.push_back(ifs.get()); + } + + // data size + size = 0; + t = ifs.get(); + size |= (t << 24); + t = ifs.get(); + size |= (t << 16); + t = ifs.get(); + size |= (t << 8); + t = ifs.get(); + size |= t; + temp_file.data.clear(); + temp_file.data.reserve(size); + + // actual data + for (uint32_t i = 0; i < size; ++i) + { + t = ifs.get(); + temp_file.data.push_back(t); + } + this->files.push_back(temp_file); + } + } + else + { + FCEU_printf("RAINBOW_FILESYSTEM_FILE (%s) format version unknown\n", filename); + } +} + +void BrokeStudioFirmware::clearFiles(uint8_t drive) +{ + unsigned int i = 0; + while (i < this->files.size()) + { + if (this->files.at(i).drive == drive) + { + this->files.erase(this->files.begin() + i); + } + else + { + ++i; + } + } +} + +template +void BrokeStudioFirmware::sendUdpDatagramToServer(I begin, I end) +{ +#if RAINBOW_DEBUG_ESP >= 1 + FCEU_printf("RAINBOW %lu udp datagram to send", wall_clock_milli()); +#if RAINBOW_DEBUG_ESP >= 2 + FCEU_printf(": "); + for (I cur = begin; cur < end; ++cur) + { + FCEU_printf("%02x ", *cur); + } +#endif + FCEU_printf("\n"); +#endif + + if (this->udp_socket != -1) + { + size_t message_size = end - begin; + vector aggregated; + aggregated.reserve(message_size); + aggregated.insert(aggregated.end(), begin, end); + + ssize_t n = sendto( + this->udp_socket, cast_network_payload(aggregated.data()), static_cast(aggregated.size()), 0, + reinterpret_cast(&this->server_addr), sizeof(sockaddr)); + + if (n == -1) + { +#ifdef _WIN32 + char errmsg[ERR_MSG_SIZE]; + errno_t r = strerror_s(errmsg, ERR_MSG_SIZE, errno); + UDBG("[Rainbow] UDP send failed: %s\n", string(errmsg)); +#else + UDBG("[Rainbow] UDP send failed: %s\n", strerror(errno)); +#endif + } + else if (static_cast(n) != message_size) + { + UDBG("[Rainbow] UDP sent partial message\n"); + } + } +} + +template +void BrokeStudioFirmware::sendUdpDatagramToPool(I begin, I end) +{ +#if RAINBOW_DEBUG_ESP >= 1 + FCEU_printf("RAINBOW %lu udp datagram to send", wall_clock_milli()); +#if RAINBOW_DEBUG_ESP >= 2 + FCEU_printf(": "); + for (I cur = begin; cur < end; ++cur) + { + FCEU_printf("%02x ", *cur); + } +#endif + FCEU_printf("\n"); +#endif + + if(this->udp_socket == -1) return; + + size_t message_size = end - begin; + vector aggregated; + aggregated.reserve(message_size); + aggregated.insert(aggregated.end(), begin, end); + + for(size_t i = 0; i < 16; i++) { + if(this->ipAddressPool[i].ipAddress != "") { + + // Init UDP socket and store parsed address + std::pair res_dest_addr = this->resolve_address(this->ipAddressPool[i].ipAddress, this->ipAddressPool[i].port); + if(!res_dest_addr.first) { + continue; + } + + sockaddr dest_addr = res_dest_addr.second; + + ssize_t n = sendto( + this->udp_socket, cast_network_payload(aggregated.data()), static_cast(aggregated.size()), 0, + &dest_addr, sizeof(sockaddr) + ); + + if(n == -1) { +#ifdef _WIN32 + char errmsg[ERR_MSG_SIZE]; + errno_t r = strerror_s(errmsg, ERR_MSG_SIZE, errno); + UDBG("[Rainbow] UDP send failed: %s\n", string(errmsg)); +#else + UDBG("[Rainbow] UDP send failed: %s\n", strerror(errno)); +#endif + } else if(static_cast(n) != message_size) { + UDBG("[Rainbow] UDP sent partial message"); + } + } + } +} + +template +void BrokeStudioFirmware::sendTcpDataToServer(I begin, I end) +{ +#if RAINBOW_DEBUG_ESP >= 1 + FCEU_printf("RAINBOW %lu tcp data to send", wall_clock_milli()); +#if RAINBOW_DEBUG_ESP >= 2 + FCEU_printf(": "); + for (I cur = begin; cur < end; ++cur) + { + FCEU_printf("%02x ", *cur); + } +#endif + FCEU_printf("\n"); +#endif + + if (this->tcp_socket != -1) + { + size_t message_size = end - begin; + vector aggregated; + aggregated.reserve(message_size); + aggregated.insert(aggregated.end(), begin, end); + + ssize_t n = ::send( + this->tcp_socket, + cast_network_payload(aggregated.data()), static_cast(aggregated.size()), + 0); + if (n == -1) + { +#ifdef _WIN32 + char errmsg[ERR_MSG_SIZE]; + errno_t r = strerror_s(errmsg, ERR_MSG_SIZE, errno); + UDBG("[Rainbow] TCP send failed: %s\n", string(errmsg)); +#else + UDBG("[Rainbow] TCP send failed: %s\n", strerror(errno)); +#endif + } + else if (static_cast(n) != message_size) + { + UDBG("[Rainbow] TCP sent partial message\n"); + } + } +} + +deque BrokeStudioFirmware::read_socket(int socket) +{ + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(socket, &rfds); + + timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + + int n_readable = ::select(socket + 1, &rfds, NULL, NULL, &tv); + if (n_readable == -1) + { +#ifdef _WIN32 + char errmsg[ERR_MSG_SIZE]; + errno_t r = strerror_s(errmsg, ERR_MSG_SIZE, errno); + UDBG("[Rainbow] failed to check sockets for data: %s\n", string(errmsg)); +#else + UDBG("[Rainbow] failed to check sockets for data: %s\n", strerror(errno)); +#endif + } + else if (n_readable > 0) + { + if (FD_ISSET(socket, &rfds)) + { + size_t const MAX_MSG_SIZE = 254; + vector data; + data.resize(MAX_MSG_SIZE); + + sockaddr_in addr_from; + socklen_t addr_from_len = sizeof(addr_from); + ssize_t msg_len = ::recvfrom( + socket, cast_network_payload(data.data()), MAX_MSG_SIZE, 0, + reinterpret_cast(&addr_from), &addr_from_len); + + if (msg_len == -1) + { +#ifdef _WIN32 + char errmsg[ERR_MSG_SIZE]; + errno_t r = strerror_s(errmsg, ERR_MSG_SIZE, errno); + UDBG("[Rainbow] failed to read socket: %s\n", string(errmsg)); +#else + UDBG("[Rainbow] failed to read socket: %s\n", strerror(errno)); +#endif + } + else if (msg_len <= static_cast(MAX_MSG_SIZE)) + { + UDBG("[Rainbow] %lu received message of size %zd", wall_clock_milli(), msg_len); +#if RAINBOW_DEBUG_ESP >= 2 + UDBG_FLOOD(": "); + for (auto it = data.begin(); it != data.begin() + msg_len; ++it) + { + UDBG_FLOOD("%02x", *it); + } +#endif + UDBG("\n"); + deque message({static_cast(msg_len + 1), + static_cast(fromesp_cmds_t::MESSAGE_FROM_SERVER)}); + message.insert(message.end(), data.begin(), data.begin() + msg_len); + return message; + } + else + { + UDBG("[Rainbow] received a bigger message than expected\n"); + // TODO handle it like Rainbow's ESP handle it + } + } + } + return deque(); +} + +void BrokeStudioFirmware::receiveDataFromServer() +{ + // TCP + if (this->tcp_socket != -1) + { + deque message = read_socket(this->tcp_socket); + if (!message.empty()) + { + this->tx_messages.push_back(message); + } + } + + // UDP + if (this->udp_socket != -1) + { + deque message = read_socket(this->udp_socket); + if (!message.empty()) + { + this->tx_messages.push_back(message); + } + } +} + +void BrokeStudioFirmware::closeConnection() +{ + // TODO close UDP socket + + // Close TCP socket + if (this->tcp_socket != -1) + { + close_sock(this->tcp_socket); + } +} + +void BrokeStudioFirmware::openConnection() +{ + this->closeConnection(); + +#ifdef _WIN32 + char errmsg[ERR_MSG_SIZE]; + errno_t r; +#endif + + if (this->active_protocol == server_protocol_t::TCP) + { + // Resolve server's hostname + std::pair res_server_addr = this->resolve_address(this->server_settings_address, this->server_settings_port); + if (!res_server_addr.first) + { + return; + } + this->server_addr = res_server_addr.second; + + // Create socket + this->tcp_socket = ::socket(AF_INET, SOCK_STREAM, 0); + if (this->tcp_socket == -1) + { +#ifdef _WIN32 + r = strerror_s(errmsg, ERR_MSG_SIZE, errno); + UDBG("[Rainbow] unable to create TCP socket: %s\n", string(errmsg)); +#else + UDBG("[Rainbow] unable to create TCP socket: %s\n", strerror(errno)); +#endif + } + + // Connect to server + int connect_res = ::connect(this->tcp_socket, &this->server_addr, sizeof(sockaddr)); + if (connect_res == -1) + { +#ifdef _WIN32 + r = strerror_s(errmsg, ERR_MSG_SIZE, errno); + UDBG("[Rainbow] unable to connect to TCP server: %s\n", string(errmsg)); +#else + UDBG("[Rainbow] unable to connect to TCP server: %s\n", strerror(errno)); + this->tcp_socket = -1; +#endif + } + } + else if (this->active_protocol == server_protocol_t::TCP_SECURED) + { + // TODO + UDBG("[Rainbow] TCP_SECURED not yet implemented"); + } + else if(this->active_protocol == server_protocol_t::UDP || this->active_protocol == server_protocol_t::UDP_POOL) + { + if(this->active_protocol == server_protocol_t::UDP) { + // Init UDP socket and store parsed address + std::pair res_server_addr = this->resolve_address(this->server_settings_address, this->server_settings_port); + if (!res_server_addr.first) + { + return; + } + this->server_addr = res_server_addr.second; + } + + this->udp_socket = ::socket(AF_INET, SOCK_DGRAM, 0); + if (this->udp_socket == -1) + { +#ifdef _WIN32 + r = strerror_s(errmsg, ERR_MSG_SIZE, errno); + UDBG("[Rainbow] unable to connect to UDP server: %s\n", string(errmsg)); +#else + UDBG("[Rainbow] unable to connect to UDP server: %s\n", strerror(errno)); +#endif + } + + sockaddr_in bind_addr; + bzero(reinterpret_cast(&bind_addr), sizeof(bind_addr)); + bind_addr.sin_family = AF_INET; + bind_addr.sin_port = htons(0); + bind_addr.sin_addr.s_addr = htonl(INADDR_ANY); + bind(this->udp_socket, reinterpret_cast(&bind_addr), sizeof(sockaddr)); + } +} + +void BrokeStudioFirmware::pingRequest(uint8_t n) +{ + using std::chrono::duration_cast; + using std::chrono::milliseconds; + using std::chrono::steady_clock; + using std::chrono::time_point; + + uint8_t ping_min = 255; + uint8_t ping_max = 0; + uint32_t total_ms = 0; + uint8_t lost = 0; + + pping_s *pping = pping_init(this->server_settings_address.c_str()); + if (pping == NULL) + { + lost = n; + } + else + { + for (uint8_t i = 0; i < n; ++i) + { + time_point begin = steady_clock::now(); + int r = pping_ping(pping); + time_point end = steady_clock::now(); + + if (r != 0) + { + UDBG("[Rainbow] ESP ping lost packet\n"); + ++lost; + } + else + { + uint32_t const round_trip_time_ms = duration_cast(end - begin).count(); + uint8_t const rtt = (round_trip_time_ms + 2) / 4; + UDBG("[Rainbow] ESP ping %d ms\n", round_trip_time_ms); + ping_min = min(ping_min, rtt); + ping_max = max(ping_max, rtt); + total_ms += round_trip_time_ms; + } + + if (i < n - 1) + { + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } + pping_free(pping); + } + + this->ping_min = ping_min; + if (lost < n) + { + this->ping_avg = ((total_ms / (n - lost)) + 2) / 4; + } + this->ping_max = ping_max; + this->ping_lost = lost; + this->ping_ready = true; + UDBG("[Rainbow] ESP ping stored: %d/%d/%d/%d (min/max/avg/lost)\n", this->ping_min, this->ping_max, this->ping_avg, this->ping_lost); +} + +void BrokeStudioFirmware::receivePingResult() +{ + if (!this->ping_ready) + { + return; + } + assert(this->ping_thread.joinable()); + + this->ping_thread.join(); + this->ping_ready = false; + + this->tx_messages.push_back({ + 5, + static_cast(fromesp_cmds_t::SERVER_PING), + this->ping_min, + this->ping_max, + this->ping_avg, + this->ping_lost + }); +} + +std::pair BrokeStudioFirmware::resolve_address(string address, uint16_t port) +{ + // Resolve IP address for hostname + bool result = false; + addrinfo hint; + memset((void *)&hint, 0, sizeof(hint)); + hint.ai_family = AF_INET; + addrinfo *addrInfo; + sockaddr sa; + memset(&sa, 0, sizeof(sa)); + + if (getaddrinfo(address.c_str(), std::to_string(port).c_str(), &hint, &addrInfo) != 0) + { + UDBG("[Rainbow] Unable to resolve server's hostname (%s:%s)\n", address.c_str(), std::to_string(port).c_str()); + } + else + { + result = true; + sa = *addrInfo->ai_addr; + } + + freeaddrinfo(addrInfo); + return std::make_pair(result, sa); +} + +namespace +{ + size_t download_write_callback(char *ptr, size_t size, size_t nmemb, void *userdata) + { + vector *data = reinterpret_cast *>(userdata); + data->insert(data->end(), reinterpret_cast(ptr), reinterpret_cast(ptr + size * nmemb)); + return size * nmemb; + } +} + +void BrokeStudioFirmware::initDownload() +{ + this->curl_handle = curl_easy_init(); + curl_easy_setopt(this->curl_handle, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(this->curl_handle, CURLOPT_WRITEFUNCTION, &download_write_callback); + curl_easy_setopt(this->curl_handle, CURLOPT_FAILONERROR, 1L); +} + +std::pair BrokeStudioFirmware::curle_to_net_error(CURLcode curle) +{ + static std::map> const resolution = { + { + CURLE_UNSUPPORTED_PROTOCOL, + std::pair( + static_cast(BrokeStudioFirmware::file_download_results_t::UNKNOWN_OR_UNSUPPORTED_PROTOCOL), + static_cast(BrokeStudioFirmware::file_download_network_error_t::CONNECTION_LOST) + ) + }, + { CURLE_WRITE_ERROR, + std::pair( + static_cast(BrokeStudioFirmware::file_download_results_t::NETWORK_ERROR), + static_cast(BrokeStudioFirmware::file_download_network_error_t::STREAM_WRITE) + ) + }, + { + CURLE_OUT_OF_MEMORY, + std::pair( + static_cast(BrokeStudioFirmware::file_download_results_t::NETWORK_ERROR), + static_cast(BrokeStudioFirmware::file_download_network_error_t::OUT_OF_RAM) + ) + }, + }; + + auto entry = resolution.find(curle); + if (entry != resolution.end()) + { + return entry->second; + } + return std::pair( + static_cast(BrokeStudioFirmware::file_download_results_t::NETWORK_ERROR), + static_cast(BrokeStudioFirmware::file_download_network_error_t::CONNECTION_FAILED) + ); +} + +void BrokeStudioFirmware::downloadFile(string const &url, uint8_t path, uint8_t file) +{ + UDBG("[Rainbow] ESP download %s -> (%u,%u)\n", url.c_str(), (unsigned int)path, (unsigned int)file); + // TODO asynchronous download using curl_multi_* (and maybe a thread, or regular ticks on rx/tx/getDataReadyIO) + /* + // Directly fail if the curl handle was not properly initialized or if WiFi is not enabled (wifiConfig bit 0) + if ((this->curl_handle == nullptr) || (wifiConfig & wifi_config_t::WIFI_ENABLED == 0)) { + UDBG("[Rainbow] ESP download failed: no handle\n"); + this->tx_messages.push_back({ + 2, + static_cast(fromesp_cmds_t::FILE_DOWNLOAD), + static_cast(file_download_results_t::NETWORK_ERROR), + 0, + static_cast(file_download_network_error_t::NOT_CONNECTED) + }); + return; + } + */ + + // Download file + vector data; + curl_easy_setopt(this->curl_handle, CURLOPT_URL, url.c_str()); + curl_easy_setopt(this->curl_handle, CURLOPT_WRITEDATA, (void *)&data); + CURLcode res = curl_easy_perform(this->curl_handle); + + // Store data and write result message + if (res != CURLE_OK) + { + UDBG("[Rainbow] ESP download failed\n"); + std::pair rainbow_error = curle_to_net_error(res); + this->tx_messages.push_back({ + 4, + static_cast(fromesp_cmds_t::FILE_DOWNLOAD), + rainbow_error.first, + 0, + rainbow_error.second + }); + } + else + { + UDBG("[Rainbow] ESP download success\n"); + // Store data + string filename = this->getAutoFilename(path, file); + this->files.push_back(FileStruct({0, filename, data})); + this->saveFiles(); + + // Write result message + this->tx_messages.push_back({ + 4, + static_cast(fromesp_cmds_t::FILE_DOWNLOAD), + static_cast(file_download_results_t::SUCCESS) + }); + } +} + +void BrokeStudioFirmware::cleanupDownload() +{ + curl_easy_cleanup(this->curl_handle); + this->curl_handle = nullptr; +} diff --git a/src/boards/rainbow_esp.h b/src/boards/rainbow_esp.h new file mode 100644 index 000000000..70f0736fd --- /dev/null +++ b/src/boards/rainbow_esp.h @@ -0,0 +1,371 @@ +#pragma once +#include "../types.h" +#include "RNBW/bootrom_chr.h" + +#define CURL_STATICLIB +#include "curl/curl.h" + +#include +#include +#include +#include +#include +#include + +using std::array; +using std::atomic; +using std::deque; +using std::ifstream; +using std::max; +using std::min; +using std::ofstream; +using std::pair; +using std::string; +using std::thread; +using std::vector; + +#ifdef _WIN32 +#include +#else +#include +#endif + +////////////////////////////////////// +// BrokeStudio's ESP firmware implementation + +static const uint8_t NO_WORKING_FILE = 0xff; +static const uint8_t NUM_FILE_PATHS = 3; +static const uint8_t NUM_FILES = 64; + +static const uint64_t ESP_FLASH_SIZE = 0x200000; // 2MiB +static const uint64_t SD_CARD_SIZE = 0x80000000; // 2GiB + +static const uint8_t NUM_NETWORKS = 3; +static const uint8_t NUM_FAKE_NETWORKS = 5; +static const uint8_t SSID_MAX_LENGTH = 32; +static const uint8_t PASS_MAX_LENGTH = 64; + +static const uint8_t DBG_CFG_OFF = 0x00; +static const uint8_t DBG_CFG_DEV_LOG = 0x01; +static const uint8_t DBG_CFG_SERIAL = 0x02; +static const uint8_t DBG_CFG_NETWORK = 0x04; + +struct NetworkInfo +{ + string ssid; + string pass; + bool active; +}; + +struct FileConfig +{ + uint8_t access_mode; + uint8_t drive; +}; + +struct FileStruct +{ + uint8_t drive; + string filename; + vector data; +}; + +struct WorkingFile +{ + bool active; + uint8_t config; + uint8_t auto_path; + uint8_t auto_file; + uint32_t offset; + FileStruct *file; +}; + +struct UPDpoolAddress +{ + string ipAddress; + uint16_t port; +}; + +class BrokeStudioFirmware +{ +public: + BrokeStudioFirmware(); + ~BrokeStudioFirmware(); + + void rx(uint8_t v); + uint8_t tx(); + + bool getDataReadyIO(); + +private: + // Defined message types from CPU to ESP + enum class toesp_cmds_t : uint8_t + { + // ESP CMDS + ESP_GET_STATUS = 0, // 0x00 + DEBUG_GET_LEVEL = 1, // 0x01 + DEBUG_SET_LEVEL = 2, // 0x02 + DEBUG_LOG = 3, // 0x03 + BUFFER_CLEAR_RX_TX = 4, // 0x04 + BUFFER_DROP_FROM_ESP = 5, // 0x05 + ESP_GET_FIRMWARE_VERSION = 6, // 0x06 + ESP_FACTORY_RESET = 7, // 0x07 + ESP_RESTART = 8, // 0x08 + + // WIFI CMDS + WIFI_GET_STATUS = 9, // 0x09 + WIFI_GET_SSID = 10, // 0x0A + WIFI_GET_IP = 11, // 0x0B + WIFI_GET_CONFIG = 12, // 0x0C + WIFI_SET_CONFIG = 13, // 0x0D + + // ACCESS POINT CMDS + AP_GET_SSID = 14, // 0x0E + AP_GET_IP = 15, // 0x0F + + // RND CMDS + RND_GET_BYTE = 16, // 0x10 + RND_GET_BYTE_RANGE = 17, // 0x11 + RND_GET_WORD = 18, // 0x12 + RND_GET_WORD_RANGE = 19, // 0x13 + + // SERVER CMDS + SERVER_GET_STATUS = 20, // 0x14 + SERVER_PING = 21, // 0x15 + SERVER_SET_PROTOCOL = 22, // 0x16 + SERVER_GET_SETTINGS = 23, // 0x17 + SERVER_SET_SETTINGS = 24, // 0x18 + SERVER_GET_SAVED_SETTINGS = 25, // 0x19 + SERVER_SET_SAVED_SETTINGS = 26, // 0x1A + SERVER_RESTORE_SAVED_SETTINGS = 27, // 0x1B + SERVER_CONNECT = 28, // 0x1C + SERVER_DISCONNECT = 29, // 0x1D + SERVER_SEND_MSG = 30, // 0x1E + + // UDP ADDRESS POOL CMDS + UDP_ADDR_POOL_CLEAR = 55, // 0x37 + UDP_ADDR_POOL_ADD = 56, // 0x38 + UDP_ADDR_POOL_REMOVE = 57, // 0x39 + UDP_ADDR_POOL_SEND_MSG = 58, // 0x3A + + // NETWORK CMDS + NETWORK_SCAN = 31, // 0x1F + NETWORK_GET_SCAN_RESULT = 32, // 0x20 + NETWORK_GET_SCANNED_DETAILS = 33, // 0x21 + NETWORK_GET_REGISTERED = 34, // 0x22 + NETWORK_GET_REGISTERED_DETAILS = 35, // 0x23 + NETWORK_REGISTER = 36, // 0x24 + NETWORK_UNREGISTER = 37, // 0x25 + NETWORK_SET_ACTIVE = 38, // 0x26 + + // FILE CMDS + FILE_OPEN = 39, // 0x27 + FILE_CLOSE = 40, // 0x28 + FILE_STATUS = 41, // 0x29 + FILE_EXISTS = 42, // 0x2A + FILE_DELETE = 43, // 0x2B + FILE_SET_CUR = 44, // 0x2C + FILE_READ = 45, // 0x2D + FILE_WRITE = 46, // 0x2E + FILE_APPEND = 47, // 0x2F + FILE_COUNT = 48, // 0x30 + FILE_GET_LIST = 49, // 0x31 + FILE_GET_FREE_ID = 50, // 0x32 + FILE_GET_FS_INFO = 51, // 0x33 + FILE_GET_INFO = 52, // 0x34 + FILE_DOWNLOAD = 53, // 0x35 + FILE_FORMAT = 54, // 0x36 + }; + + // Defined message types from ESP to CPU + enum class fromesp_cmds_t : uint8_t + { + // ESP CMDS + READY, + DEBUG_LEVEL, + ESP_FIRMWARE_VERSION, + ESP_FACTORY_RESET, + + // WIFI / AP CMDS + WIFI_STATUS, + SSID, + IP_ADDRESS, + WIFI_CONFIG, + + // RND CMDS + RND_BYTE, + RND_WORD, + + // SERVER CMDS + SERVER_STATUS, + SERVER_PING, + SERVER_SETTINGS, + MESSAGE_FROM_SERVER, + + // NETWORK CMDS + NETWORK_SCAN_RESULT, + NETWORK_SCANNED_DETAILS, + NETWORK_REGISTERED_DETAILS, + NETWORK_REGISTERED, + + // FILE CMDS + FILE_STATUS, + FILE_EXISTS, + FILE_DELETE, + FILE_LIST, + FILE_DATA, + FILE_COUNT, + FILE_ID, + FILE_FS_INFO, + FILE_INFO, + FILE_DOWNLOAD, + }; + + // ESP factory reset result codes + enum class esp_factory_reset : uint8_t + { + SUCCESS = 0, + ERROR_WHILE_SAVING_CONFIG = 1, + ERROR_WHILE_DELETING_TWEB = 2, + ERROR_WHILE_DELETING_WEB = 3 + }; + + enum class server_protocol_t : uint8_t + { + TCP = 0, + TCP_SECURED = 1, + UDP = 2, + UDP_POOL = 3, + }; + + // WIFI_CONFIG + enum class wifi_config_t : uint8_t + { + WIFI_ENABLE = 1, + AP_ENABLE = 2, + WEB_SERVER_ENABLE = 4 + }; + + // FILE_CONFIG + enum class file_config_flags_t : uint8_t + { + ACCESS_MODE_MASK = 1, + ACCESS_MODE_AUTO = 0, + ACCESS_MODE_MANUAL = 1, + DESTINATION_MASK = 2, + DESTINATION_ESP = 0, + DESTINATION_SD = 2, + }; + + enum class file_delete_results_t : uint8_t + { + SUCCESS, + ERROR_WHILE_DELETING_FILE, + FILE_NOT_FOUND, + INVALID_PATH_OR_FILE, + }; + + enum class file_download_results_t : uint8_t + { + SUCCESS, + INVALID_DESTINATION, + ERROR_WHILE_DELETING_FILE, + UNKNOWN_OR_UNSUPPORTED_PROTOCOL, + NETWORK_ERROR, + HTTP_STATUS_NOT_IN_2XX, + }; + + enum class file_download_network_error_t : uint8_t + { + CONNECTION_FAILED = 255, + SEND_HEADER_FAILED = 254, + SEND_PAYLOAD_FILED = 253, + NOT_CONNECTED = 252, + CONNECTION_LOST = 251, + NO_STREAM = 250, + NO_HTTP_SERVER = 249, + OUT_OF_RAM = 248, + ENCODING = 247, + STREAM_WRITE = 246, + READ_TIMEOUT = 245, + }; + + void processBufferedMessage(); + FileConfig parseFileConfig(uint8_t config); + int findFile(uint8_t drive, string filename); + int findPath(uint8_t drive, string path); + string getAutoFilename(uint8_t path, uint8_t file); + void readFile(uint8_t n); + template + void writeFile(I data_begin, I data_end); + template + void appendFile(I data_begin, I data_end); + void saveFiles(); + void saveFile(uint8_t drive, char const* filename); + void loadFiles(); + void loadFile(uint8_t drive, char const* filename); + void clearFiles(uint8_t drive); + + template + void sendUdpDatagramToServer(I begin, I end); + template + void sendUdpDatagramToPool(I begin, I end); + template + void sendTcpDataToServer(I begin, I end); + void receiveDataFromServer(); + + void closeConnection(); + void openConnection(); + + void pingRequest(uint8_t n); + void receivePingResult(); + + pair resolve_address(string address, uint16_t port); + static deque read_socket(int socket); + + void initDownload(); + static pair curle_to_net_error(CURLcode curle); + void downloadFile(string const &url, uint8_t path, uint8_t file); + void cleanupDownload(); + +private: + deque rx_buffer; + deque tx_buffer; + deque> tx_messages; + + bool isEspFlashFilePresent = false; + bool isSdCardFilePresent = false; + WorkingFile working_file; + vector files; + + array networks; + + server_protocol_t active_protocol = server_protocol_t::TCP; + string default_server_settings_address; + uint16_t default_server_settings_port = 0; + string server_settings_address; + uint16_t server_settings_port = 0; + + UPDpoolAddress ipAddressPool[16]; + + uint8_t debug_config = 0; + uint8_t wifi_config = 1; + + uint8_t ping_min = 0; + uint8_t ping_avg = 0; + uint8_t ping_max = 0; + uint8_t ping_lost = 0; + atomic ping_ready; + thread ping_thread; + + int udp_socket = -1; + sockaddr server_addr; + + int tcp_socket = -1; + + bool msg_first_byte = true; + uint8_t msg_length = 0; + uint8_t last_byte_read = 0; + + CURL* curl_handle = nullptr; +}; diff --git a/src/cart.cpp b/src/cart.cpp index 73b5d57ed..db35555b9 100644 --- a/src/cart.cpp +++ b/src/cart.cpp @@ -38,11 +38,11 @@ #include #include -uint8 *Page[32], *VPage[8]; +uint8 *Page[32], *VPage[16]; uint8 **VPageR = VPage; -uint8 *VPageG[8]; -uint8 *MMC5SPRVPage[8]; -uint8 *MMC5BGVPage[8]; +uint8 *VPageG[16]; +uint8 *MMC5SPRVPage[16]; +uint8 *MMC5BGVPage[16]; static uint8 PRGIsRAM[32]; /* This page is/is not PRG RAM. */ @@ -62,6 +62,7 @@ uint32 PRGmask8[32]; uint32 PRGmask16[32]; uint32 PRGmask32[32]; +uint32 CHRmask512[32]; uint32 CHRmask1[32]; uint32 CHRmask2[32]; uint32 CHRmask4[32]; @@ -105,8 +106,8 @@ void ResetCartMapping(void) { PRGptr[x] = CHRptr[x] = 0; PRGsize[x] = CHRsize[x] = 0; } - for (x = 0; x < 8; x++) { - MMC5SPRVPage[x] = MMC5BGVPage[x] = VPageR[x] = nothing - 0x400 * x; + for (x = 0; x < 16; x++) { + MMC5SPRVPage[x] = MMC5BGVPage[x] = VPageR[x] = nothing - 0x200 * x; } } @@ -127,11 +128,13 @@ void SetupCartCHRMapping(int chip, uint8 *p, uint32 size, int ram) { CHRptr[chip] = p; CHRsize[chip] = size; + CHRmask512[chip] = (size >> 9) - 1; CHRmask1[chip] = (size >> 10) - 1; CHRmask2[chip] = (size >> 11) - 1; CHRmask4[chip] = (size >> 12) - 1; CHRmask8[chip] = (size >> 13) - 1; + if (CHRmask512[chip] >= (unsigned int)(-1)) CHRmask512[chip] = 0; if (CHRmask1[chip] >= (unsigned int)(-1)) CHRmask1[chip] = 0; if (CHRmask2[chip] >= (unsigned int)(-1)) CHRmask2[chip] = 0; if (CHRmask4[chip] >= (unsigned int)(-1)) CHRmask4[chip] = 0; @@ -225,38 +228,51 @@ void setprg32(uint32 A, uint32 V) { setprg32r(0, A, V); } +void setchr512r(int r, uint32 A, uint32 V) { + if (!CHRptr[r]) return; + FCEUPPU_LineUpdate(); + V &= CHRmask512[r]; + if (CHRram[r]) + PPUCHRRAM |= (1 << (A >> 9)); + else + PPUCHRRAM &= ~(1 << (A >> 9)); + VPageR[(A) >> 9] = &CHRptr[r][(V) << 9] - (A); +} + void setchr1r(int r, uint32 A, uint32 V) { if (!CHRptr[r]) return; FCEUPPU_LineUpdate(); V &= CHRmask1[r]; if (CHRram[r]) - PPUCHRRAM |= (1 << (A >> 10)); + PPUCHRRAM |= (3 << (A >> 9)); else - PPUCHRRAM &= ~(1 << (A >> 10)); - VPageR[(A) >> 10] = &CHRptr[r][(V) << 10] - (A); + PPUCHRRAM &= ~(3 << (A >> 9)); + VPageR[(A) >> 9] = VPageR[((A) >> 9) + 1] = &CHRptr[r][(V) << 10] - (A); } void setchr2r(int r, uint32 A, uint32 V) { if (!CHRptr[r]) return; FCEUPPU_LineUpdate(); V &= CHRmask2[r]; - VPageR[(A) >> 10] = VPageR[((A) >> 10) + 1] = &CHRptr[r][(V) << 11] - (A); + VPageR[(A) >> 9] = VPageR[((A) >> 9) + 1] = VPageR[((A) >> 9) + 2] = VPageR[((A) >> 9) + 3] = &CHRptr[r][(V) << 11] - (A); if (CHRram[r]) - PPUCHRRAM |= (3 << (A >> 10)); + PPUCHRRAM |= (15 << (A >> 9)); else - PPUCHRRAM &= ~(3 << (A >> 10)); + PPUCHRRAM &= ~(15 << (A >> 9)); } void setchr4r(int r, unsigned int A, unsigned int V) { if (!CHRptr[r]) return; FCEUPPU_LineUpdate(); V &= CHRmask4[r]; - VPageR[(A) >> 10] = VPageR[((A) >> 10) + 1] = - VPageR[((A) >> 10) + 2] = VPageR[((A) >> 10) + 3] = &CHRptr[r][(V) << 12] - (A); + VPageR[(A) >> 9] = VPageR[((A) >> 9) + 1] = + VPageR[((A) >> 9) + 2] = VPageR[((A) >> 9) + 3] = + VPageR[((A) >> 9) + 4] = VPageR[((A) >> 9) + 5] = + VPageR[((A) >> 9) + 6] = VPageR[((A) >> 9) + 7] = &CHRptr[r][(V) << 12] - (A); if (CHRram[r]) - PPUCHRRAM |= (15 << (A >> 10)); + PPUCHRRAM |= (255 << (A >> 9)); else - PPUCHRRAM &= ~(15 << (A >> 10)); + PPUCHRRAM &= ~(255 << (A >> 9)); } void setchr8r(int r, uint32 V) { @@ -265,10 +281,10 @@ void setchr8r(int r, uint32 V) { if (!CHRptr[r]) return; FCEUPPU_LineUpdate(); V &= CHRmask8[r]; - for (x = 7; x >= 0; x--) + for (x = 15; x >= 0; x--) VPageR[x] = &CHRptr[r][V << 13]; if (CHRram[r]) - PPUCHRRAM |= (255); + PPUCHRRAM |= (65535); else PPUCHRRAM = 0; } @@ -495,7 +511,7 @@ void FixGenieMap(void) { geniestage = 2; - for (x = 0; x < 8; x++) + for (x = 0; x < 16; x++) VPage[x] = VPageG[x]; VPageR = VPage; @@ -526,8 +542,8 @@ void FCEU_GeniePower(void) { SetWriteHandler(0x8000, 0xFFFF, GenieWrite); SetReadHandler(0x8000, 0xFFFF, GenieRead); - for (x = 0; x < 8; x++) - VPage[x] = GENIEROM + 4096 - 0x400 * x; + for (x = 0; x < 16; x++) + VPage[x] = GENIEROM + 4096 - 0x200 * x; if (AllocGenieRW()) VPageR = VPageG; diff --git a/src/cart.h b/src/cart.h index 0b5813353..e08728389 100644 --- a/src/cart.h +++ b/src/cart.h @@ -52,6 +52,7 @@ struct CartInfo uint32 CRC32; // Should be set by the iNES/UNIF loading // code, used by mapper/board code, maybe // other code in the future. + int misc_roms; CartInfo(void) { @@ -77,6 +78,7 @@ struct CartInfo battery_vram_size = 0; memset( MD5, 0, sizeof(MD5)); CRC32 = 0; + misc_roms = 0; }; }; @@ -86,7 +88,7 @@ void FCEU_SaveGameSave(CartInfo *LocalHWInfo); void FCEU_LoadGameSave(CartInfo *LocalHWInfo); void FCEU_ClearGameSave(CartInfo *LocalHWInfo); -extern uint8 *Page[32], *VPage[8], *MMC5SPRVPage[8], *MMC5BGVPage[8]; +extern uint8 *Page[32], *VPage[16], *MMC5SPRVPage[16], *MMC5BGVPage[16]; void ResetCartMapping(void); void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram); @@ -129,6 +131,7 @@ void setprg8r(int r, unsigned int A, unsigned int V); void setprg16r(int r, unsigned int A, unsigned int V); void setprg32r(int r, unsigned int A, unsigned int V); +void setchr512r(int r, unsigned int A, unsigned int V); void setchr1r(int r, unsigned int A, unsigned int V); void setchr2r(int r, unsigned int A, unsigned int V); void setchr4r(int r, unsigned int A, unsigned int V); diff --git a/src/debug.cpp b/src/debug.cpp index fad9c6f6e..9a11e50b9 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -352,7 +352,7 @@ uint8 GetMem(uint16 A) { case 6: return RawReg4016; case 7: return IRQFrameMode; } - else if ((A >= 0x4018) && (A < 0x5000)) // AnS: changed the range, so MMC5 ExRAM can be watched in the Hexeditor + else if ((A >= 0x4018) && (A < 0x4800)) // AnS: changed the range, so MMC5 ExRAM can be watched in the Hexeditor | BrokeStudio: changed the range, so Rainbow FPGA-RAM can be watched in the Hexeditor return 0xFF; if (GameInfo) { //adelikat: 11/17/09: Prevent crash if this is called with no game loaded. uint32 ret; @@ -366,7 +366,7 @@ uint8 GetMem(uint16 A) { uint8 GetPPUMem(uint8 A) { uint16 tmp = FCEUPPU_PeekAddress() & 0x3FFF; - if (tmp<0x2000) return VPage[tmp>>10][tmp]; + if (tmp<0x2000) return VPage[tmp>>9][tmp]; if (tmp>=0x3F00) return PALRAM[tmp&0x1F]; return vnapage[(tmp>>10)&0x3][tmp&0x3FF]; } diff --git a/src/debug.h b/src/debug.h index 708c12efc..1e27e138a 100644 --- a/src/debug.h +++ b/src/debug.h @@ -119,7 +119,7 @@ extern void IncrementInstructionsCounters(); //------------- //internal variables that debuggers will want access to -extern uint8 *vnapage[4],*VPage[8]; +extern uint8 *vnapage[4],*VPage[16]; extern uint8 PPU[4],PALRAM[0x20],UPALRAM[3],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset; extern uint32 FCEUPPU_PeekAddress(); extern uint8 READPAL_MOTHEROFALL(uint32 A); diff --git a/src/drivers/Qt/HexEditor.cpp b/src/drivers/Qt/HexEditor.cpp index b1c5d8aaa..3d1875137 100644 --- a/src/drivers/Qt/HexEditor.cpp +++ b/src/drivers/Qt/HexEditor.cpp @@ -259,7 +259,7 @@ static int getPPU( unsigned int i ) return 0; } i &= 0x3FFF; - if (i < 0x2000)return VPage[(i) >> 10][(i)]; + if (i < 0x2000)return VPage[(i) >> 9][(i)]; //NSF PPU Viewer crash here (UGETAB) (Also disabled by 'MaxSize = 0x2000') if (GameInfo->type == GIT_NSF) return 0; @@ -356,7 +356,7 @@ static int writeMem( int mode, unsigned int addr, int value ) addr &= 0x3FFF; if (addr < 0x2000) { - VPage[addr >> 10][addr] = value; //todo: detect if this is vrom and turn it red if so + VPage[addr >> 9][addr] = value; //todo: detect if this is vrom and turn it red if so } if ((addr >= 0x2000) && (addr < 0x3F00)) { diff --git a/src/drivers/Qt/ppuViewer.cpp b/src/drivers/Qt/ppuViewer.cpp index 390716982..aefecbca4 100644 --- a/src/drivers/Qt/ppuViewer.cpp +++ b/src/drivers/Qt/ppuViewer.cpp @@ -1323,7 +1323,7 @@ void ppuPatternView_t::paintEvent(QPaintEvent *event) static int getPPU( unsigned int i ) { i &= 0x3FFF; - if (i < 0x2000)return VPage[(i) >> 10][(i)]; + if (i < 0x2000)return VPage[(i) >> 9][(i)]; //NSF PPU Viewer crash here (UGETAB) (Also disabled by 'MaxSize = 0x2000') if (GameInfo->type == GIT_NSF) return 0; @@ -1363,7 +1363,7 @@ static int writeMemPPU( unsigned int addr, int value ) addr &= 0x3FFF; if (addr < 0x2000) { - VPage[addr >> 10][addr] = value; //todo: detect if this is vrom and turn it red if so + VPage[addr >> 9][addr] = value; //todo: detect if this is vrom and turn it red if so } if ((addr >= 0x2000) && (addr < 0x3F00)) { @@ -1626,8 +1626,8 @@ void FCEUD_UpdatePPUView(int scanline, int refreshchr) int i10, x10; for (i = 0, x=0x1000; i < 0x1000; i++, x++) { - i10 = i>>10; - x10 = x>>10; + i10 = i>>9; + x10 = x>>9; if ( VPage[i10] == NULL ) { diff --git a/src/drivers/sdl/memview.cpp b/src/drivers/sdl/memview.cpp index bc17ee3da..5f78d03c0 100644 --- a/src/drivers/sdl/memview.cpp +++ b/src/drivers/sdl/memview.cpp @@ -64,7 +64,7 @@ static int getRAM( unsigned int i ) static int getPPU( unsigned int i ) { i &= 0x3FFF; - if (i < 0x2000)return VPage[(i) >> 10][(i)]; + if (i < 0x2000)return VPage[(i) >> 9][(i)]; //NSF PPU Viewer crash here (UGETAB) (Also disabled by 'MaxSize = 0x2000') if (GameInfo->type == GIT_NSF) return 0; @@ -255,7 +255,7 @@ struct memViewWin_t addr &= 0x3FFF; if (addr < 0x2000) { - VPage[addr >> 10][addr] = value; //todo: detect if this is vrom and turn it red if so + VPage[addr >> 9][addr] = value; //todo: detect if this is vrom and turn it red if so } if ((addr >= 0x2000) && (addr < 0x3F00)) { diff --git a/src/drivers/win/curl/7.79.0.txt b/src/drivers/win/curl/7.79.0.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/drivers/win/curl/x64/include/curl/curl.h b/src/drivers/win/curl/x64/include/curl/curl.h new file mode 100644 index 000000000..835c3d871 --- /dev/null +++ b/src/drivers/win/curl/x64/include/curl/curl.h @@ -0,0 +1,3067 @@ +#ifndef CURLINC_CURL_H +#define CURLINC_CURL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * If you have libcurl problems, all docs and details are found here: + * https://curl.se/libcurl/ + */ + +#ifdef CURL_NO_OLDIES +#define CURL_STRICTER +#endif + +#include "curlver.h" /* libcurl version defines */ +#include "system.h" /* determine things run-time */ + +/* + * Define CURL_WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && \ + !defined(__SYMBIAN32__) +#define CURL_WIN32 +#endif + +#include +#include + +#if defined(__FreeBSD__) && (__FreeBSD__ >= 2) +/* Needed for __FreeBSD_version symbol definition */ +#include +#endif + +/* The include stuff here below is mainly for time_t! */ +#include +#include + +#if defined(CURL_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) +#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \ + defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)) +/* The check above prevents the winsock2 inclusion if winsock.h already was + included, since they can't co-exist without problems */ +#include +#include +#endif +#endif + +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish + libc5-based Linux systems. Only include it on systems that are known to + require it! */ +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ + defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ + defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ + defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \ + defined(__VXWORKS__) +#include +#endif + +#if !defined(CURL_WIN32) && !defined(_WIN32_WCE) +#include +#endif + +#if !defined(CURL_WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__) +#include +#endif + +#ifdef __BEOS__ +#include +#endif + +/* Compatibility for non-Clang compilers */ +#ifndef __has_declspec_attribute +# define __has_declspec_attribute(x) 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_easy CURL; +typedef struct Curl_share CURLSH; +#else +typedef void CURL; +typedef void CURLSH; +#endif + +/* + * libcurl external API function linkage decorations. + */ + +#ifdef CURL_STATICLIB +# define CURL_EXTERN +#elif defined(CURL_WIN32) || defined(__SYMBIAN32__) || \ + (__has_declspec_attribute(dllexport) && \ + __has_declspec_attribute(dllimport)) +# if defined(BUILDING_LIBCURL) +# define CURL_EXTERN __declspec(dllexport) +# else +# define CURL_EXTERN __declspec(dllimport) +# endif +#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS) +# define CURL_EXTERN CURL_EXTERN_SYMBOL +#else +# define CURL_EXTERN +#endif + +#ifndef curl_socket_typedef +/* socket typedef */ +#if defined(CURL_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) +typedef SOCKET curl_socket_t; +#define CURL_SOCKET_BAD INVALID_SOCKET +#else +typedef int curl_socket_t; +#define CURL_SOCKET_BAD -1 +#endif +#define curl_socket_typedef +#endif /* curl_socket_typedef */ + +/* enum for the different supported SSL backends */ +typedef enum { + CURLSSLBACKEND_NONE = 0, + CURLSSLBACKEND_OPENSSL = 1, + CURLSSLBACKEND_GNUTLS = 2, + CURLSSLBACKEND_NSS = 3, + CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */ + CURLSSLBACKEND_GSKIT = 5, + CURLSSLBACKEND_POLARSSL = 6, + CURLSSLBACKEND_WOLFSSL = 7, + CURLSSLBACKEND_SCHANNEL = 8, + CURLSSLBACKEND_SECURETRANSPORT = 9, + CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */ + CURLSSLBACKEND_MBEDTLS = 11, + CURLSSLBACKEND_MESALINK = 12, + CURLSSLBACKEND_BEARSSL = 13, + CURLSSLBACKEND_RUSTLS = 14 +} curl_sslbackend; + +/* aliases for library clones and renames */ +#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL +#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL + +/* deprecated names: */ +#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL +#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT + +struct curl_httppost { + struct curl_httppost *next; /* next entry in the list */ + char *name; /* pointer to allocated name */ + long namelength; /* length of name length */ + char *contents; /* pointer to allocated data contents */ + long contentslength; /* length of contents field, see also + CURL_HTTPPOST_LARGE */ + char *buffer; /* pointer to allocated buffer contents */ + long bufferlength; /* length of buffer field */ + char *contenttype; /* Content-Type */ + struct curl_slist *contentheader; /* list of extra headers for this form */ + struct curl_httppost *more; /* if one field name has more than one + file, this link should link to following + files */ + long flags; /* as defined below */ + +/* specified content is a file name */ +#define CURL_HTTPPOST_FILENAME (1<<0) +/* specified content is a file name */ +#define CURL_HTTPPOST_READFILE (1<<1) +/* name is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRNAME (1<<2) +/* contents is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRCONTENTS (1<<3) +/* upload file from buffer */ +#define CURL_HTTPPOST_BUFFER (1<<4) +/* upload file from pointer contents */ +#define CURL_HTTPPOST_PTRBUFFER (1<<5) +/* upload file contents by using the regular read callback to get the data and + pass the given pointer as custom pointer */ +#define CURL_HTTPPOST_CALLBACK (1<<6) +/* use size in 'contentlen', added in 7.46.0 */ +#define CURL_HTTPPOST_LARGE (1<<7) + + char *showfilename; /* The file name to show. If not set, the + actual file name will be used (if this + is a file part) */ + void *userp; /* custom pointer used for + HTTPPOST_CALLBACK posts */ + curl_off_t contentlen; /* alternative length of contents + field. Used if CURL_HTTPPOST_LARGE is + set. Added in 7.46.0 */ +}; + + +/* This is a return code for the progress callback that, when returned, will + signal libcurl to continue executing the default progress function */ +#define CURL_PROGRESSFUNC_CONTINUE 0x10000001 + +/* This is the CURLOPT_PROGRESSFUNCTION callback prototype. It is now + considered deprecated but was the only choice up until 7.31.0 */ +typedef int (*curl_progress_callback)(void *clientp, + double dltotal, + double dlnow, + double ultotal, + double ulnow); + +/* This is the CURLOPT_XFERINFOFUNCTION callback prototype. It was introduced + in 7.32.0, avoids the use of floating point numbers and provides more + detailed information. */ +typedef int (*curl_xferinfo_callback)(void *clientp, + curl_off_t dltotal, + curl_off_t dlnow, + curl_off_t ultotal, + curl_off_t ulnow); + +#ifndef CURL_MAX_READ_SIZE + /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */ +#define CURL_MAX_READ_SIZE 524288 +#endif + +#ifndef CURL_MAX_WRITE_SIZE + /* Tests have proven that 20K is a very bad buffer size for uploads on + Windows, while 16K for some odd reason performed a lot better. + We do the ifndef check to allow this value to easier be changed at build + time for those who feel adventurous. The practical minimum is about + 400 bytes since libcurl uses a buffer of this size as a scratch area + (unrelated to network send operations). */ +#define CURL_MAX_WRITE_SIZE 16384 +#endif + +#ifndef CURL_MAX_HTTP_HEADER +/* The only reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause reallocs + infinitely */ +#define CURL_MAX_HTTP_HEADER (100*1024) +#endif + +/* This is a magic return code for the write callback that, when returned, + will signal libcurl to pause receiving on the current transfer. */ +#define CURL_WRITEFUNC_PAUSE 0x10000001 + +typedef size_t (*curl_write_callback)(char *buffer, + size_t size, + size_t nitems, + void *outstream); + +/* This callback will be called when a new resolver request is made */ +typedef int (*curl_resolver_start_callback)(void *resolver_state, + void *reserved, void *userdata); + +/* enumeration of file types */ +typedef enum { + CURLFILETYPE_FILE = 0, + CURLFILETYPE_DIRECTORY, + CURLFILETYPE_SYMLINK, + CURLFILETYPE_DEVICE_BLOCK, + CURLFILETYPE_DEVICE_CHAR, + CURLFILETYPE_NAMEDPIPE, + CURLFILETYPE_SOCKET, + CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */ + + CURLFILETYPE_UNKNOWN /* should never occur */ +} curlfiletype; + +#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0) +#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1) +#define CURLFINFOFLAG_KNOWN_TIME (1<<2) +#define CURLFINFOFLAG_KNOWN_PERM (1<<3) +#define CURLFINFOFLAG_KNOWN_UID (1<<4) +#define CURLFINFOFLAG_KNOWN_GID (1<<5) +#define CURLFINFOFLAG_KNOWN_SIZE (1<<6) +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7) + +/* Information about a single file, used when doing FTP wildcard matching */ +struct curl_fileinfo { + char *filename; + curlfiletype filetype; + time_t time; /* always zero! */ + unsigned int perm; + int uid; + int gid; + curl_off_t size; + long int hardlinks; + + struct { + /* If some of these fields is not NULL, it is a pointer to b_data. */ + char *time; + char *perm; + char *user; + char *group; + char *target; /* pointer to the target filename of a symlink */ + } strings; + + unsigned int flags; + + /* used internally */ + char *b_data; + size_t b_size; + size_t b_used; +}; + +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */ +#define CURL_CHUNK_BGN_FUNC_OK 0 +#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */ +#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */ + +/* if splitting of data transfer is enabled, this callback is called before + download of an individual chunk started. Note that parameter "remains" works + only for FTP wildcard downloading (for now), otherwise is not used */ +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info, + void *ptr, + int remains); + +/* return codes for CURLOPT_CHUNK_END_FUNCTION */ +#define CURL_CHUNK_END_FUNC_OK 0 +#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */ + +/* If splitting of data transfer is enabled this callback is called after + download of an individual chunk finished. + Note! After this callback was set then it have to be called FOR ALL chunks. + Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC. + This is the reason why we don't need "transfer_info" parameter in this + callback and we are not interested in "remains" parameter too. */ +typedef long (*curl_chunk_end_callback)(void *ptr); + +/* return codes for FNMATCHFUNCTION */ +#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */ +#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */ +#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */ + +/* callback type for wildcard downloading pattern matching. If the + string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */ +typedef int (*curl_fnmatch_callback)(void *ptr, + const char *pattern, + const char *string); + +/* These are the return codes for the seek callbacks */ +#define CURL_SEEKFUNC_OK 0 +#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */ +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so + libcurl might try other means instead */ +typedef int (*curl_seek_callback)(void *instream, + curl_off_t offset, + int origin); /* 'whence' */ + +/* This is a return code for the read callback that, when returned, will + signal libcurl to immediately abort the current transfer. */ +#define CURL_READFUNC_ABORT 0x10000000 +/* This is a return code for the read callback that, when returned, will + signal libcurl to pause sending data on the current transfer. */ +#define CURL_READFUNC_PAUSE 0x10000001 + +/* Return code for when the trailing headers' callback has terminated + without any errors*/ +#define CURL_TRAILERFUNC_OK 0 +/* Return code for when was an error in the trailing header's list and we + want to abort the request */ +#define CURL_TRAILERFUNC_ABORT 1 + +typedef size_t (*curl_read_callback)(char *buffer, + size_t size, + size_t nitems, + void *instream); + +typedef int (*curl_trailer_callback)(struct curl_slist **list, + void *userdata); + +typedef enum { + CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ + CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */ + CURLSOCKTYPE_LAST /* never use */ +} curlsocktype; + +/* The return code from the sockopt_callback can signal information back + to libcurl: */ +#define CURL_SOCKOPT_OK 0 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return + CURLE_ABORTED_BY_CALLBACK */ +#define CURL_SOCKOPT_ALREADY_CONNECTED 2 + +typedef int (*curl_sockopt_callback)(void *clientp, + curl_socket_t curlfd, + curlsocktype purpose); + +struct curl_sockaddr { + int family; + int socktype; + int protocol; + unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it + turned really ugly and painful on the systems that + lack this type */ + struct sockaddr addr; +}; + +typedef curl_socket_t +(*curl_opensocket_callback)(void *clientp, + curlsocktype purpose, + struct curl_sockaddr *address); + +typedef int +(*curl_closesocket_callback)(void *clientp, curl_socket_t item); + +typedef enum { + CURLIOE_OK, /* I/O operation successful */ + CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ + CURLIOE_FAILRESTART, /* failed to restart the read */ + CURLIOE_LAST /* never use */ +} curlioerr; + +typedef enum { + CURLIOCMD_NOP, /* no operation */ + CURLIOCMD_RESTARTREAD, /* restart the read stream from start */ + CURLIOCMD_LAST /* never use */ +} curliocmd; + +typedef curlioerr (*curl_ioctl_callback)(CURL *handle, + int cmd, + void *clientp); + +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS +/* + * The following typedef's are signatures of malloc, free, realloc, strdup and + * calloc respectively. Function pointers of these types can be passed to the + * curl_global_init_mem() function to set user defined memory management + * callback routines. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); + +#define CURL_DID_MEMORY_FUNC_TYPEDEFS +#endif + +/* the kind of data that is passed to information_callback*/ +typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ + CURLINFO_HEADER_OUT, /* 2 */ + CURLINFO_DATA_IN, /* 3 */ + CURLINFO_DATA_OUT, /* 4 */ + CURLINFO_SSL_DATA_IN, /* 5 */ + CURLINFO_SSL_DATA_OUT, /* 6 */ + CURLINFO_END +} curl_infotype; + +typedef int (*curl_debug_callback) + (CURL *handle, /* the handle/transfer this concerns */ + curl_infotype type, /* what kind of data */ + char *data, /* points to the data */ + size_t size, /* size of the data pointed to */ + void *userptr); /* whatever the user please */ + +/* All possible error codes from all sorts of curl functions. Future versions + may return other values, stay prepared. + + Always add new return codes last. Never *EVER* remove any. The return + codes must remain the same! + */ + +typedef enum { + CURLE_OK = 0, + CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ + CURLE_FAILED_INIT, /* 2 */ + CURLE_URL_MALFORMAT, /* 3 */ + CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ + CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ + CURLE_COULDNT_RESOLVE_HOST, /* 6 */ + CURLE_COULDNT_CONNECT, /* 7 */ + CURLE_WEIRD_SERVER_REPLY, /* 8 */ + CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server + due to lack of access - when login fails + this is not returned. */ + CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for + 7.15.4, reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ + CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server + [was obsoleted in August 2007 for 7.17.0, + reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ + CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ + CURLE_FTP_CANT_GET_HOST, /* 15 */ + CURLE_HTTP2, /* 16 - A problem in the http2 framing layer. + [was obsoleted in August 2007 for 7.17.0, + reused in July 2014 for 7.38.0] */ + CURLE_FTP_COULDNT_SET_TYPE, /* 17 */ + CURLE_PARTIAL_FILE, /* 18 */ + CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ + CURLE_OBSOLETE20, /* 20 - NOT USED */ + CURLE_QUOTE_ERROR, /* 21 - quote command failure */ + CURLE_HTTP_RETURNED_ERROR, /* 22 */ + CURLE_WRITE_ERROR, /* 23 */ + CURLE_OBSOLETE24, /* 24 - NOT USED */ + CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ + CURLE_READ_ERROR, /* 26 - couldn't open/read from file */ + CURLE_OUT_OF_MEMORY, /* 27 */ + /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error + instead of a memory allocation error if CURL_DOES_CONVERSIONS + is defined + */ + CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ + CURLE_OBSOLETE29, /* 29 - NOT USED */ + CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + CURLE_OBSOLETE32, /* 32 - NOT USED */ + CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ + CURLE_HTTP_POST_ERROR, /* 34 */ + CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ + CURLE_FILE_COULDNT_READ_FILE, /* 37 */ + CURLE_LDAP_CANNOT_BIND, /* 38 */ + CURLE_LDAP_SEARCH_FAILED, /* 39 */ + CURLE_OBSOLETE40, /* 40 - NOT USED */ + CURLE_FUNCTION_NOT_FOUND, /* 41 - NOT USED starting with 7.53.0 */ + CURLE_ABORTED_BY_CALLBACK, /* 42 */ + CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ + CURLE_OBSOLETE44, /* 44 - NOT USED */ + CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ + CURLE_OBSOLETE46, /* 46 - NOT USED */ + CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */ + CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ + CURLE_SETOPT_OPTION_SYNTAX, /* 49 - Malformed setopt option */ + CURLE_OBSOLETE50, /* 50 - NOT USED */ + CURLE_OBSOLETE51, /* 51 - NOT USED */ + CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ + CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_OBSOLETE57, /* 57 - NOT IN USE */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ + CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint + wasn't verified fine */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ + CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */ + CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ + CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ + CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind + that failed */ + CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ + CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not + accepted and we failed to login */ + CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ + CURLE_TFTP_PERM, /* 69 - permission problem on server */ + CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ + CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ + CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ + CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ + CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ + CURLE_CONV_FAILED, /* 75 - conversion failed */ + CURLE_CONV_REQD, /* 76 - caller must register conversion + callbacks using curl_easy_setopt options + CURLOPT_CONV_FROM_NETWORK_FUNCTION, + CURLOPT_CONV_TO_NETWORK_FUNCTION, and + CURLOPT_CONV_FROM_UTF8_FUNCTION */ + CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing + or wrong format */ + CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ + CURLE_SSH, /* 79 - error from the SSH layer, somewhat + generic so the error message will be of + interest when this has happened */ + + CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL + connection */ + CURLE_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it's ready and try again (Added + in 7.18.2) */ + CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or + wrong format (Added in 7.19.0) */ + CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in + 7.19.0) */ + CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */ + CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ + CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */ + CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ + CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */ + CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the + session will be queued */ + CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not + match */ + CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */ + CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer + */ + CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from + inside a callback */ + CURLE_AUTH_ERROR, /* 94 - an authentication function returned an + error */ + CURLE_HTTP3, /* 95 - An HTTP/3 layer problem */ + CURLE_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */ + CURLE_PROXY, /* 97 - proxy handshake error */ + CURLE_SSL_CLIENTCERT, /* 98 - client-side certificate required */ + CURL_LAST /* never use! */ +} CURLcode; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Previously obsolete error code re-used in 7.38.0 */ +#define CURLE_OBSOLETE16 CURLE_HTTP2 + +/* Previously obsolete error codes re-used in 7.24.0 */ +#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED +#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT + +/* compatibility with older names */ +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING +#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY + +/* The following were added in 7.62.0 */ +#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.21.5, April 2011 */ +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION + +/* Added for 7.78.0 */ +#define CURLE_TELNET_OPTION_SYNTAX CURLE_SETOPT_OPTION_SYNTAX + +/* The following were added in 7.17.1 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.17.0 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */ +#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46 +#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44 +#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10 +#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16 +#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32 +#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29 +#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12 +#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20 +#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40 +#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24 +#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57 +#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN + +#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED +#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE +#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR +#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL +#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS +#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR +#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED + +/* The following were added earlier */ + +#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT + +#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR +#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED +#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED + +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME + +/* This was the error code 50 in 7.7.3 and a few earlier versions, this + is no longer used by libcurl but is instead #defined here only to not + make programs break */ +#define CURLE_ALREADY_COMPLETE 99999 + +/* Provide defines for really old option names */ +#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */ +#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */ +#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA + +/* Since long deprecated options with no code in the lib that does anything + with them. */ +#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40 +#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72 + +#endif /*!CURL_NO_OLDIES*/ + +/* + * Proxy error codes. Returned in CURLINFO_PROXY_ERROR if CURLE_PROXY was + * return for the transfers. + */ +typedef enum { + CURLPX_OK, + CURLPX_BAD_ADDRESS_TYPE, + CURLPX_BAD_VERSION, + CURLPX_CLOSED, + CURLPX_GSSAPI, + CURLPX_GSSAPI_PERMSG, + CURLPX_GSSAPI_PROTECTION, + CURLPX_IDENTD, + CURLPX_IDENTD_DIFFER, + CURLPX_LONG_HOSTNAME, + CURLPX_LONG_PASSWD, + CURLPX_LONG_USER, + CURLPX_NO_AUTH, + CURLPX_RECV_ADDRESS, + CURLPX_RECV_AUTH, + CURLPX_RECV_CONNECT, + CURLPX_RECV_REQACK, + CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED, + CURLPX_REPLY_COMMAND_NOT_SUPPORTED, + CURLPX_REPLY_CONNECTION_REFUSED, + CURLPX_REPLY_GENERAL_SERVER_FAILURE, + CURLPX_REPLY_HOST_UNREACHABLE, + CURLPX_REPLY_NETWORK_UNREACHABLE, + CURLPX_REPLY_NOT_ALLOWED, + CURLPX_REPLY_TTL_EXPIRED, + CURLPX_REPLY_UNASSIGNED, + CURLPX_REQUEST_FAILED, + CURLPX_RESOLVE_HOST, + CURLPX_SEND_AUTH, + CURLPX_SEND_CONNECT, + CURLPX_SEND_REQUEST, + CURLPX_UNKNOWN_FAIL, + CURLPX_UNKNOWN_MODE, + CURLPX_USER_REJECTED, + CURLPX_LAST /* never use */ +} CURLproxycode; + +/* This prototype applies to all conversion callbacks */ +typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length); + +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ + void *ssl_ctx, /* actually an OpenSSL + or WolfSSL SSL_CTX, + or an mbedTLS + mbedtls_ssl_config */ + void *userptr); + +typedef enum { + CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use + CONNECT HTTP/1.1 */ + CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT + HTTP/1.0 */ + CURLPROXY_HTTPS = 2, /* added in 7.52.0 */ + CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already + in 7.10 */ + CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ + CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ + CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the + host name rather than the IP address. added + in 7.18.0 */ +} curl_proxytype; /* this enum was added in 7.10 */ + +/* + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options: + * + * CURLAUTH_NONE - No HTTP authentication + * CURLAUTH_BASIC - HTTP Basic authentication (default) + * CURLAUTH_DIGEST - HTTP Digest authentication + * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated) + * CURLAUTH_NTLM - HTTP NTLM authentication + * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour + * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper + * CURLAUTH_BEARER - HTTP Bearer token authentication + * CURLAUTH_ONLY - Use together with a single other type to force no + * authentication or just that single type + * CURLAUTH_ANY - All fine types set + * CURLAUTH_ANYSAFE - All fine types except Basic + */ + +#define CURLAUTH_NONE ((unsigned long)0) +#define CURLAUTH_BASIC (((unsigned long)1)<<0) +#define CURLAUTH_DIGEST (((unsigned long)1)<<1) +#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2) +/* Deprecated since the advent of CURLAUTH_NEGOTIATE */ +#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE +/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */ +#define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE +#define CURLAUTH_NTLM (((unsigned long)1)<<3) +#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4) +#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5) +#define CURLAUTH_BEARER (((unsigned long)1)<<6) +#define CURLAUTH_AWS_SIGV4 (((unsigned long)1)<<7) +#define CURLAUTH_ONLY (((unsigned long)1)<<31) +#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) +#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) + +#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */ +#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */ +#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */ +#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */ +#define CURLSSH_AUTH_HOST (1<<2) /* host key files */ +#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */ +#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */ +#define CURLSSH_AUTH_GSSAPI (1<<5) /* gssapi (kerberos, ...) */ +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY + +#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */ +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */ +#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */ + +#define CURL_ERROR_SIZE 256 + +enum curl_khtype { + CURLKHTYPE_UNKNOWN, + CURLKHTYPE_RSA1, + CURLKHTYPE_RSA, + CURLKHTYPE_DSS, + CURLKHTYPE_ECDSA, + CURLKHTYPE_ED25519 +}; + +struct curl_khkey { + const char *key; /* points to a null-terminated string encoded with base64 + if len is zero, otherwise to the "raw" data */ + size_t len; + enum curl_khtype keytype; +}; + +/* this is the set of return values expected from the curl_sshkeycallback + callback */ +enum curl_khstat { + CURLKHSTAT_FINE_ADD_TO_FILE, + CURLKHSTAT_FINE, + CURLKHSTAT_REJECT, /* reject the connection, return an error */ + CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so + this causes a CURLE_DEFER error but otherwise the + connection will be left intact etc */ + CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key*/ + CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ +}; + +/* this is the set of status codes pass in to the callback */ +enum curl_khmatch { + CURLKHMATCH_OK, /* match */ + CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ + CURLKHMATCH_MISSING, /* no matching host/key found */ + CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ +}; + +typedef int + (*curl_sshkeycallback) (CURL *easy, /* easy handle */ + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch, /* libcurl's view on the keys */ + void *clientp); /* custom pointer passed from app */ + +/* parameter for the CURLOPT_USE_SSL option */ +typedef enum { + CURLUSESSL_NONE, /* do not attempt to use SSL */ + CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */ + CURLUSESSL_CONTROL, /* SSL for the control connection or fail */ + CURLUSESSL_ALL, /* SSL for all communication or fail */ + CURLUSESSL_LAST /* not an option, never use */ +} curl_usessl; + +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */ + +/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the + name of improving interoperability with older servers. Some SSL libraries + have introduced work-arounds for this flaw but those work-arounds sometimes + make the SSL communication fail. To regain functionality with those broken + servers, a user can this way allow the vulnerability back. */ +#define CURLSSLOPT_ALLOW_BEAST (1<<0) + +/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those + SSL backends where such behavior is present. */ +#define CURLSSLOPT_NO_REVOKE (1<<1) + +/* - NO_PARTIALCHAIN tells libcurl to *NOT* accept a partial certificate chain + if possible. The OpenSSL backend has this ability. */ +#define CURLSSLOPT_NO_PARTIALCHAIN (1<<2) + +/* - REVOKE_BEST_EFFORT tells libcurl to ignore certificate revocation offline + checks and ignore missing revocation list for those SSL backends where such + behavior is present. */ +#define CURLSSLOPT_REVOKE_BEST_EFFORT (1<<3) + +/* - CURLSSLOPT_NATIVE_CA tells libcurl to use standard certificate store of + operating system. Currently implemented under MS-Windows. */ +#define CURLSSLOPT_NATIVE_CA (1<<4) + +/* - CURLSSLOPT_AUTO_CLIENT_CERT tells libcurl to automatically locate and use + a client certificate for authentication. (Schannel) */ +#define CURLSSLOPT_AUTO_CLIENT_CERT (1<<5) + +/* The default connection attempt delay in milliseconds for happy eyeballs. + CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document + this value, keep them in sync. */ +#define CURL_HET_DEFAULT 200L + +/* The default connection upkeep interval in milliseconds. */ +#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2009 */ + +#define CURLFTPSSL_NONE CURLUSESSL_NONE +#define CURLFTPSSL_TRY CURLUSESSL_TRY +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL +#define CURLFTPSSL_ALL CURLUSESSL_ALL +#define CURLFTPSSL_LAST CURLUSESSL_LAST +#define curl_ftpssl curl_usessl +#endif /*!CURL_NO_OLDIES*/ + +/* parameter for the CURLOPT_FTP_SSL_CCC option */ +typedef enum { + CURLFTPSSL_CCC_NONE, /* do not send CCC */ + CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */ + CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */ + CURLFTPSSL_CCC_LAST /* not an option, never use */ +} curl_ftpccc; + +/* parameter for the CURLOPT_FTPSSLAUTH option */ +typedef enum { + CURLFTPAUTH_DEFAULT, /* let libcurl decide */ + CURLFTPAUTH_SSL, /* use "AUTH SSL" */ + CURLFTPAUTH_TLS, /* use "AUTH TLS" */ + CURLFTPAUTH_LAST /* not an option, never use */ +} curl_ftpauth; + +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +typedef enum { + CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */ + CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD + again if MKD succeeded, for SFTP this does + similar magic */ + CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD + again even if MKD failed! */ + CURLFTP_CREATE_DIR_LAST /* not an option, never use */ +} curl_ftpcreatedir; + +/* parameter for the CURLOPT_FTP_FILEMETHOD option */ +typedef enum { + CURLFTPMETHOD_DEFAULT, /* let libcurl pick */ + CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */ + CURLFTPMETHOD_NOCWD, /* no CWD at all */ + CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */ + CURLFTPMETHOD_LAST /* not an option, never use */ +} curl_ftpmethod; + +/* bitmask defines for CURLOPT_HEADEROPT */ +#define CURLHEADER_UNIFIED 0 +#define CURLHEADER_SEPARATE (1<<0) + +/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */ +#define CURLALTSVC_READONLYFILE (1<<2) +#define CURLALTSVC_H1 (1<<3) +#define CURLALTSVC_H2 (1<<4) +#define CURLALTSVC_H3 (1<<5) + + +struct curl_hstsentry { + char *name; + size_t namelen; + unsigned int includeSubDomains:1; + char expire[18]; /* YYYYMMDD HH:MM:SS [null-terminated] */ +}; + +struct curl_index { + size_t index; /* the provided entry's "index" or count */ + size_t total; /* total number of entries to save */ +}; + +typedef enum { + CURLSTS_OK, + CURLSTS_DONE, + CURLSTS_FAIL +} CURLSTScode; + +typedef CURLSTScode (*curl_hstsread_callback)(CURL *easy, + struct curl_hstsentry *e, + void *userp); +typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy, + struct curl_hstsentry *e, + struct curl_index *i, + void *userp); + +/* CURLHSTS_* are bits for the CURLOPT_HSTS option */ +#define CURLHSTS_ENABLE (long)(1<<0) +#define CURLHSTS_READONLYFILE (long)(1<<1) + +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ +#define CURLPROTO_HTTP (1<<0) +#define CURLPROTO_HTTPS (1<<1) +#define CURLPROTO_FTP (1<<2) +#define CURLPROTO_FTPS (1<<3) +#define CURLPROTO_SCP (1<<4) +#define CURLPROTO_SFTP (1<<5) +#define CURLPROTO_TELNET (1<<6) +#define CURLPROTO_LDAP (1<<7) +#define CURLPROTO_LDAPS (1<<8) +#define CURLPROTO_DICT (1<<9) +#define CURLPROTO_FILE (1<<10) +#define CURLPROTO_TFTP (1<<11) +#define CURLPROTO_IMAP (1<<12) +#define CURLPROTO_IMAPS (1<<13) +#define CURLPROTO_POP3 (1<<14) +#define CURLPROTO_POP3S (1<<15) +#define CURLPROTO_SMTP (1<<16) +#define CURLPROTO_SMTPS (1<<17) +#define CURLPROTO_RTSP (1<<18) +#define CURLPROTO_RTMP (1<<19) +#define CURLPROTO_RTMPT (1<<20) +#define CURLPROTO_RTMPE (1<<21) +#define CURLPROTO_RTMPTE (1<<22) +#define CURLPROTO_RTMPS (1<<23) +#define CURLPROTO_RTMPTS (1<<24) +#define CURLPROTO_GOPHER (1<<25) +#define CURLPROTO_SMB (1<<26) +#define CURLPROTO_SMBS (1<<27) +#define CURLPROTO_MQTT (1<<28) +#define CURLPROTO_GOPHERS (1<<29) +#define CURLPROTO_ALL (~0) /* enable everything */ + +/* long may be 32 or 64 bits, but we should never depend on anything else + but 32 */ +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 +#define CURLOPTTYPE_OFF_T 30000 +#define CURLOPTTYPE_BLOB 40000 + +/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the + string options from the header file */ + + +#define CURLOPT(na,t,nu) na = t + nu + +/* CURLOPT aliases that make no run-time difference */ + +/* 'char *' argument to a string with a trailing zero */ +#define CURLOPTTYPE_STRINGPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'struct curl_slist *' argument */ +#define CURLOPTTYPE_SLISTPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'void *' argument passed untouched to callback */ +#define CURLOPTTYPE_CBPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'long' argument with a set of values/bitmask */ +#define CURLOPTTYPE_VALUES CURLOPTTYPE_LONG + +/* + * All CURLOPT_* values. + */ + +typedef enum { + /* This is the FILE * or void * the regular output should be written to. */ + CURLOPT(CURLOPT_WRITEDATA, CURLOPTTYPE_CBPOINT, 1), + + /* The full URL to get/put */ + CURLOPT(CURLOPT_URL, CURLOPTTYPE_STRINGPOINT, 2), + + /* Port number to connect to, if other than default. */ + CURLOPT(CURLOPT_PORT, CURLOPTTYPE_LONG, 3), + + /* Name of proxy to use. */ + CURLOPT(CURLOPT_PROXY, CURLOPTTYPE_STRINGPOINT, 4), + + /* "user:password;options" to use when fetching. */ + CURLOPT(CURLOPT_USERPWD, CURLOPTTYPE_STRINGPOINT, 5), + + /* "user:password" to use with proxy. */ + CURLOPT(CURLOPT_PROXYUSERPWD, CURLOPTTYPE_STRINGPOINT, 6), + + /* Range to get, specified as an ASCII string. */ + CURLOPT(CURLOPT_RANGE, CURLOPTTYPE_STRINGPOINT, 7), + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + CURLOPT(CURLOPT_READDATA, CURLOPTTYPE_CBPOINT, 9), + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. */ + CURLOPT(CURLOPT_ERRORBUFFER, CURLOPTTYPE_OBJECTPOINT, 10), + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_WRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 11), + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_READFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 12), + + /* Time-out the read operation after this amount of seconds */ + CURLOPT(CURLOPT_TIMEOUT, CURLOPTTYPE_LONG, 13), + + /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was successful. -1 means + * unknown size. + * + * For large file support, there is also a _LARGE version of the key + * which takes an off_t type, allowing platforms with larger off_t + * sizes to handle larger files. See below for INFILESIZE_LARGE. + */ + CURLOPT(CURLOPT_INFILESIZE, CURLOPTTYPE_LONG, 14), + + /* POST static input fields. */ + CURLOPT(CURLOPT_POSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 15), + + /* Set the referrer page (needed by some CGIs) */ + CURLOPT(CURLOPT_REFERER, CURLOPTTYPE_STRINGPOINT, 16), + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + CURLOPT(CURLOPT_FTPPORT, CURLOPTTYPE_STRINGPOINT, 17), + + /* Set the User-Agent string (examined by some CGIs) */ + CURLOPT(CURLOPT_USERAGENT, CURLOPTTYPE_STRINGPOINT, 18), + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + CURLOPT(CURLOPT_LOW_SPEED_LIMIT, CURLOPTTYPE_LONG, 19), + + /* Set the "low speed time" */ + CURLOPT(CURLOPT_LOW_SPEED_TIME, CURLOPTTYPE_LONG, 20), + + /* Set the continuation offset. + * + * Note there is also a _LARGE version of this key which uses + * off_t types, allowing for large file offsets on platforms which + * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. + */ + CURLOPT(CURLOPT_RESUME_FROM, CURLOPTTYPE_LONG, 21), + + /* Set cookie in request: */ + CURLOPT(CURLOPT_COOKIE, CURLOPTTYPE_STRINGPOINT, 22), + + /* This points to a linked list of headers, struct curl_slist kind. This + list is also used for RTSP (in spite of its name) */ + CURLOPT(CURLOPT_HTTPHEADER, CURLOPTTYPE_SLISTPOINT, 23), + + /* This points to a linked list of post entries, struct curl_httppost */ + CURLOPT(CURLOPT_HTTPPOST, CURLOPTTYPE_OBJECTPOINT, 24), + + /* name of the file keeping your private SSL-certificate */ + CURLOPT(CURLOPT_SSLCERT, CURLOPTTYPE_STRINGPOINT, 25), + + /* password for the SSL or SSH private key */ + CURLOPT(CURLOPT_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 26), + + /* send TYPE parameter? */ + CURLOPT(CURLOPT_CRLF, CURLOPTTYPE_LONG, 27), + + /* send linked-list of QUOTE commands */ + CURLOPT(CURLOPT_QUOTE, CURLOPTTYPE_SLISTPOINT, 28), + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + CURLOPT(CURLOPT_HEADERDATA, CURLOPTTYPE_CBPOINT, 29), + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + CURLOPT(CURLOPT_COOKIEFILE, CURLOPTTYPE_STRINGPOINT, 31), + + /* What version to specifically try to use. + See CURL_SSLVERSION defines below. */ + CURLOPT(CURLOPT_SSLVERSION, CURLOPTTYPE_VALUES, 32), + + /* What kind of HTTP time condition to use, see defines */ + CURLOPT(CURLOPT_TIMECONDITION, CURLOPTTYPE_VALUES, 33), + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + CURLOPT(CURLOPT_TIMEVALUE, CURLOPTTYPE_LONG, 34), + + /* 35 = OBSOLETE */ + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CURLOPT(CURLOPT_CUSTOMREQUEST, CURLOPTTYPE_STRINGPOINT, 36), + + /* FILE handle to use instead of stderr */ + CURLOPT(CURLOPT_STDERR, CURLOPTTYPE_OBJECTPOINT, 37), + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + CURLOPT(CURLOPT_POSTQUOTE, CURLOPTTYPE_SLISTPOINT, 39), + + /* OBSOLETE, do not use! */ + CURLOPT(CURLOPT_OBSOLETE40, CURLOPTTYPE_OBJECTPOINT, 40), + + /* talk a lot */ + CURLOPT(CURLOPT_VERBOSE, CURLOPTTYPE_LONG, 41), + + /* throw the header out too */ + CURLOPT(CURLOPT_HEADER, CURLOPTTYPE_LONG, 42), + + /* shut off the progress meter */ + CURLOPT(CURLOPT_NOPROGRESS, CURLOPTTYPE_LONG, 43), + + /* use HEAD to get http document */ + CURLOPT(CURLOPT_NOBODY, CURLOPTTYPE_LONG, 44), + + /* no output on http error codes >= 400 */ + CURLOPT(CURLOPT_FAILONERROR, CURLOPTTYPE_LONG, 45), + + /* this is an upload */ + CURLOPT(CURLOPT_UPLOAD, CURLOPTTYPE_LONG, 46), + + /* HTTP POST method */ + CURLOPT(CURLOPT_POST, CURLOPTTYPE_LONG, 47), + + /* bare names when listing directories */ + CURLOPT(CURLOPT_DIRLISTONLY, CURLOPTTYPE_LONG, 48), + + /* Append instead of overwrite on upload! */ + CURLOPT(CURLOPT_APPEND, CURLOPTTYPE_LONG, 50), + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CURLOPT(CURLOPT_NETRC, CURLOPTTYPE_VALUES, 51), + + /* use Location: Luke! */ + CURLOPT(CURLOPT_FOLLOWLOCATION, CURLOPTTYPE_LONG, 52), + + /* transfer data in text/ASCII format */ + CURLOPT(CURLOPT_TRANSFERTEXT, CURLOPTTYPE_LONG, 53), + + /* HTTP PUT */ + CURLOPT(CURLOPT_PUT, CURLOPTTYPE_LONG, 54), + + /* 55 = OBSOLETE */ + + /* DEPRECATED + * Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_progress_callback + * prototype defines. */ + CURLOPT(CURLOPT_PROGRESSFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 56), + + /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION + callbacks */ + CURLOPT(CURLOPT_XFERINFODATA, CURLOPTTYPE_CBPOINT, 57), +#define CURLOPT_PROGRESSDATA CURLOPT_XFERINFODATA + + /* We want the referrer field set automatically when following locations */ + CURLOPT(CURLOPT_AUTOREFERER, CURLOPTTYPE_LONG, 58), + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + CURLOPT(CURLOPT_PROXYPORT, CURLOPTTYPE_LONG, 59), + + /* size of the POST input data, if strlen() is not good to use */ + CURLOPT(CURLOPT_POSTFIELDSIZE, CURLOPTTYPE_LONG, 60), + + /* tunnel non-http operations through a HTTP proxy */ + CURLOPT(CURLOPT_HTTPPROXYTUNNEL, CURLOPTTYPE_LONG, 61), + + /* Set the interface string to use as outgoing network interface */ + CURLOPT(CURLOPT_INTERFACE, CURLOPTTYPE_STRINGPOINT, 62), + + /* Set the krb4/5 security level, this also enables krb4/5 awareness. This + * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string + * is set but doesn't match one of these, 'private' will be used. */ + CURLOPT(CURLOPT_KRBLEVEL, CURLOPTTYPE_STRINGPOINT, 63), + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + CURLOPT(CURLOPT_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 64), + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAINFO, CURLOPTTYPE_STRINGPOINT, 65), + + /* 66 = OBSOLETE */ + /* 67 = OBSOLETE */ + + /* Maximum number of http redirects to follow */ + CURLOPT(CURLOPT_MAXREDIRS, CURLOPTTYPE_LONG, 68), + + /* Pass a long set to 1 to get the date of the requested document (if + possible)! Pass a zero to shut it off. */ + CURLOPT(CURLOPT_FILETIME, CURLOPTTYPE_LONG, 69), + + /* This points to a linked list of telnet options */ + CURLOPT(CURLOPT_TELNETOPTIONS, CURLOPTTYPE_SLISTPOINT, 70), + + /* Max amount of cached alive connections */ + CURLOPT(CURLOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 71), + + /* OBSOLETE, do not use! */ + CURLOPT(CURLOPT_OBSOLETE72, CURLOPTTYPE_LONG, 72), + + /* 73 = OBSOLETE */ + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you're absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + CURLOPT(CURLOPT_FRESH_CONNECT, CURLOPTTYPE_LONG, 74), + + /* Set to explicitly forbid the upcoming transfer's connection to be re-used + when done. Do not use this unless you're absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + CURLOPT(CURLOPT_FORBID_REUSE, CURLOPTTYPE_LONG, 75), + + /* Set to a file name that contains random data for libcurl to use to + seed the random engine when doing SSL connects. */ + CURLOPT(CURLOPT_RANDOM_FILE, CURLOPTTYPE_STRINGPOINT, 76), + + /* Set to the Entropy Gathering Daemon socket pathname */ + CURLOPT(CURLOPT_EGDSOCKET, CURLOPTTYPE_STRINGPOINT, 77), + + /* Time-out connect operations after this amount of seconds, if connects are + OK within this time, then fine... This only aborts the connect phase. */ + CURLOPT(CURLOPT_CONNECTTIMEOUT, CURLOPTTYPE_LONG, 78), + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_HEADERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 79), + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + CURLOPT(CURLOPT_HTTPGET, CURLOPTTYPE_LONG, 80), + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + CURLOPT(CURLOPT_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 81), + + /* Specify which file name to write all known cookies in after completed + operation. Set file name to "-" (dash) to make it go to stdout. */ + CURLOPT(CURLOPT_COOKIEJAR, CURLOPTTYPE_STRINGPOINT, 82), + + /* Specify which SSL ciphers to use */ + CURLOPT(CURLOPT_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 83), + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + CURLOPT(CURLOPT_HTTP_VERSION, CURLOPTTYPE_VALUES, 84), + + /* Specifically switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + CURLOPT(CURLOPT_FTP_USE_EPSV, CURLOPTTYPE_LONG, 85), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + CURLOPT(CURLOPT_SSLCERTTYPE, CURLOPTTYPE_STRINGPOINT, 86), + + /* name of the file keeping your private SSL-key */ + CURLOPT(CURLOPT_SSLKEY, CURLOPTTYPE_STRINGPOINT, 87), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + CURLOPT(CURLOPT_SSLKEYTYPE, CURLOPTTYPE_STRINGPOINT, 88), + + /* crypto engine for the SSL-sub system */ + CURLOPT(CURLOPT_SSLENGINE, CURLOPTTYPE_STRINGPOINT, 89), + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + CURLOPT(CURLOPT_SSLENGINE_DEFAULT, CURLOPTTYPE_LONG, 90), + + /* Non-zero value means to use the global dns cache */ + /* DEPRECATED, do not use! */ + CURLOPT(CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOPTTYPE_LONG, 91), + + /* DNS cache timeout */ + CURLOPT(CURLOPT_DNS_CACHE_TIMEOUT, CURLOPTTYPE_LONG, 92), + + /* send linked-list of pre-transfer QUOTE commands */ + CURLOPT(CURLOPT_PREQUOTE, CURLOPTTYPE_SLISTPOINT, 93), + + /* set the debug function */ + CURLOPT(CURLOPT_DEBUGFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CURLOPT(CURLOPT_DEBUGDATA, CURLOPTTYPE_CBPOINT, 95), + + /* mark this as start of a cookie session */ + CURLOPT(CURLOPT_COOKIESESSION, CURLOPTTYPE_LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAPATH, CURLOPTTYPE_STRINGPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CURLOPT(CURLOPT_BUFFERSIZE, CURLOPTTYPE_LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CURLOPT(CURLOPT_NOSIGNAL, CURLOPTTYPE_LONG, 99), + + /* Provide a CURLShare for mutexing non-ts data */ + CURLOPT(CURLOPT_SHARE, CURLOPTTYPE_OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and + CURLPROXY_SOCKS5. */ + CURLOPT(CURLOPT_PROXYTYPE, CURLOPTTYPE_VALUES, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. Before 7.21.6, this was known as + CURLOPT_ENCODING */ + CURLOPT(CURLOPT_ACCEPT_ENCODING, CURLOPTTYPE_STRINGPOINT, 102), + + /* Set pointer to private data */ + CURLOPT(CURLOPT_PRIVATE, CURLOPTTYPE_OBJECTPOINT, 103), + + /* Set aliases for HTTP 200 in the HTTP Response header */ + CURLOPT(CURLOPT_HTTP200ALIASES, CURLOPTTYPE_SLISTPOINT, 104), + + /* Continue to send authentication (user+password) when following locations, + even when hostname changed. This can potentially send off the name + and password to whatever host the server decides. */ + CURLOPT(CURLOPT_UNRESTRICTED_AUTH, CURLOPTTYPE_LONG, 105), + + /* Specifically switch on or off the FTP engine's use of the EPRT command ( + it also disables the LPRT attempt). By default, those ones will always be + attempted before the good old traditional PORT command. */ + CURLOPT(CURLOPT_FTP_USE_EPRT, CURLOPTTYPE_LONG, 106), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_USERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CURLOPT(CURLOPT_HTTPAUTH, CURLOPTTYPE_VALUES, 107), + + /* Set the ssl context callback function, currently only for OpenSSL or + WolfSSL ssl_ctx, or mbedTLS mbedtls_ssl_config in the second argument. + The function must match the curl_ssl_ctx_callback prototype. */ + CURLOPT(CURLOPT_SSL_CTX_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 108), + + /* Set the userdata for the ssl context callback function's third + argument */ + CURLOPT(CURLOPT_SSL_CTX_DATA, CURLOPTTYPE_CBPOINT, 109), + + /* FTP Option that causes missing dirs to be created on the remote server. + In 7.19.4 we introduced the convenience enums for this option using the + CURLFTP_CREATE_DIR prefix. + */ + CURLOPT(CURLOPT_FTP_CREATE_MISSING_DIRS, CURLOPTTYPE_LONG, 110), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CURLOPT(CURLOPT_PROXYAUTH, CURLOPTTYPE_VALUES, 111), + + /* FTP option that changes the timeout, in seconds, associated with + getting a response. This is different from transfer timeout time and + essentially places a demand on the FTP server to acknowledge commands + in a timely manner. */ + CURLOPT(CURLOPT_FTP_RESPONSE_TIMEOUT, CURLOPTTYPE_LONG, 112), +#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT + + /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to + tell libcurl to use those IP versions only. This only has effect on + systems with support for more than one, i.e IPv4 _and_ IPv6. */ + CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_VALUES, 113), + + /* Set this option to limit the size of a file that will be downloaded from + an HTTP or FTP server. + + Note there is also _LARGE version which adds large file support for + platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ + CURLOPT(CURLOPT_MAXFILESIZE, CURLOPTTYPE_LONG, 114), + + /* See the comment for INFILESIZE above, but in short, specifies + * the size of the file being uploaded. -1 means unknown. + */ + CURLOPT(CURLOPT_INFILESIZE_LARGE, CURLOPTTYPE_OFF_T, 115), + + /* Sets the continuation offset. There is also a CURLOPTTYPE_LONG version + * of this; look above for RESUME_FROM. + */ + CURLOPT(CURLOPT_RESUME_FROM_LARGE, CURLOPTTYPE_OFF_T, 116), + + /* Sets the maximum size of data that will be downloaded from + * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. + */ + CURLOPT(CURLOPT_MAXFILESIZE_LARGE, CURLOPTTYPE_OFF_T, 117), + + /* Set this option to the file name of your .netrc file you want libcurl + to parse (using the CURLOPT_NETRC option). If not set, libcurl will do + a poor attempt to find the user's home directory and check for a .netrc + file in there. */ + CURLOPT(CURLOPT_NETRC_FILE, CURLOPTTYPE_STRINGPOINT, 118), + + /* Enable SSL/TLS for FTP, pick one of: + CURLUSESSL_TRY - try using SSL, proceed anyway otherwise + CURLUSESSL_CONTROL - SSL for the control connection or fail + CURLUSESSL_ALL - SSL for all communication or fail + */ + CURLOPT(CURLOPT_USE_SSL, CURLOPTTYPE_VALUES, 119), + + /* The _LARGE version of the standard POSTFIELDSIZE option */ + CURLOPT(CURLOPT_POSTFIELDSIZE_LARGE, CURLOPTTYPE_OFF_T, 120), + + /* Enable/disable the TCP Nagle algorithm */ + CURLOPT(CURLOPT_TCP_NODELAY, CURLOPTTYPE_LONG, 121), + + /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 123 OBSOLETE. Gone in 7.16.0 */ + /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 127 OBSOLETE. Gone in 7.16.0 */ + /* 128 OBSOLETE. Gone in 7.16.0 */ + + /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option + can be used to change libcurl's default action which is to first try + "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK + response has been received. + + Available parameters are: + CURLFTPAUTH_DEFAULT - let libcurl decide + CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS + CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL + */ + CURLOPT(CURLOPT_FTPSSLAUTH, CURLOPTTYPE_VALUES, 129), + + CURLOPT(CURLOPT_IOCTLFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 130), + CURLOPT(CURLOPT_IOCTLDATA, CURLOPTTYPE_CBPOINT, 131), + + /* 132 OBSOLETE. Gone in 7.16.0 */ + /* 133 OBSOLETE. Gone in 7.16.0 */ + + /* null-terminated string for pass on to the FTP server when asked for + "account" info */ + CURLOPT(CURLOPT_FTP_ACCOUNT, CURLOPTTYPE_STRINGPOINT, 134), + + /* feed cookie into cookie engine */ + CURLOPT(CURLOPT_COOKIELIST, CURLOPTTYPE_STRINGPOINT, 135), + + /* ignore Content-Length */ + CURLOPT(CURLOPT_IGNORE_CONTENT_LENGTH, CURLOPTTYPE_LONG, 136), + + /* Set to non-zero to skip the IP address received in a 227 PASV FTP server + response. Typically used for FTP-SSL purposes but is not restricted to + that. libcurl will then instead use the same IP address it used for the + control connection. */ + CURLOPT(CURLOPT_FTP_SKIP_PASV_IP, CURLOPTTYPE_LONG, 137), + + /* Select "file method" to use when doing FTP, see the curl_ftpmethod + above. */ + CURLOPT(CURLOPT_FTP_FILEMETHOD, CURLOPTTYPE_VALUES, 138), + + /* Local port number to bind the socket to */ + CURLOPT(CURLOPT_LOCALPORT, CURLOPTTYPE_LONG, 139), + + /* Number of ports to try, including the first one set with LOCALPORT. + Thus, setting it to 1 will make no additional attempts but the first. + */ + CURLOPT(CURLOPT_LOCALPORTRANGE, CURLOPTTYPE_LONG, 140), + + /* no transfer, set up connection and let application use the socket by + extracting it with CURLINFO_LASTSOCKET */ + CURLOPT(CURLOPT_CONNECT_ONLY, CURLOPTTYPE_LONG, 141), + + /* Function that will be called to convert from the + network encoding (instead of using the iconv calls in libcurl) */ + CURLOPT(CURLOPT_CONV_FROM_NETWORK_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 142), + + /* Function that will be called to convert to the + network encoding (instead of using the iconv calls in libcurl) */ + CURLOPT(CURLOPT_CONV_TO_NETWORK_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 143), + + /* Function that will be called to convert from UTF8 + (instead of using the iconv calls in libcurl) + Note that this is used only for SSL certificate processing */ + CURLOPT(CURLOPT_CONV_FROM_UTF8_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 144), + + /* if the connection proceeds too quickly then need to slow it down */ + /* limit-rate: maximum number of bytes per second to send or receive */ + CURLOPT(CURLOPT_MAX_SEND_SPEED_LARGE, CURLOPTTYPE_OFF_T, 145), + CURLOPT(CURLOPT_MAX_RECV_SPEED_LARGE, CURLOPTTYPE_OFF_T, 146), + + /* Pointer to command string to send if USER/PASS fails. */ + CURLOPT(CURLOPT_FTP_ALTERNATIVE_TO_USER, CURLOPTTYPE_STRINGPOINT, 147), + + /* callback function for setting socket options */ + CURLOPT(CURLOPT_SOCKOPTFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 148), + CURLOPT(CURLOPT_SOCKOPTDATA, CURLOPTTYPE_CBPOINT, 149), + + /* set to 0 to disable session ID re-use for this transfer, default is + enabled (== 1) */ + CURLOPT(CURLOPT_SSL_SESSIONID_CACHE, CURLOPTTYPE_LONG, 150), + + /* allowed SSH authentication methods */ + CURLOPT(CURLOPT_SSH_AUTH_TYPES, CURLOPTTYPE_VALUES, 151), + + /* Used by scp/sftp to do public/private key authentication */ + CURLOPT(CURLOPT_SSH_PUBLIC_KEYFILE, CURLOPTTYPE_STRINGPOINT, 152), + CURLOPT(CURLOPT_SSH_PRIVATE_KEYFILE, CURLOPTTYPE_STRINGPOINT, 153), + + /* Send CCC (Clear Command Channel) after authentication */ + CURLOPT(CURLOPT_FTP_SSL_CCC, CURLOPTTYPE_LONG, 154), + + /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ + CURLOPT(CURLOPT_TIMEOUT_MS, CURLOPTTYPE_LONG, 155), + CURLOPT(CURLOPT_CONNECTTIMEOUT_MS, CURLOPTTYPE_LONG, 156), + + /* set to zero to disable the libcurl's decoding and thus pass the raw body + data to the application even when it is encoded/compressed */ + CURLOPT(CURLOPT_HTTP_TRANSFER_DECODING, CURLOPTTYPE_LONG, 157), + CURLOPT(CURLOPT_HTTP_CONTENT_DECODING, CURLOPTTYPE_LONG, 158), + + /* Permission used when creating new files and directories on the remote + server for protocols that support it, SFTP/SCP/FILE */ + CURLOPT(CURLOPT_NEW_FILE_PERMS, CURLOPTTYPE_LONG, 159), + CURLOPT(CURLOPT_NEW_DIRECTORY_PERMS, CURLOPTTYPE_LONG, 160), + + /* Set the behavior of POST when redirecting. Values must be set to one + of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ + CURLOPT(CURLOPT_POSTREDIR, CURLOPTTYPE_VALUES, 161), + + /* used by scp/sftp to verify the host's public key */ + CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, CURLOPTTYPE_STRINGPOINT, 162), + + /* Callback function for opening socket (instead of socket(2)). Optionally, + callback is able change the address or refuse to connect returning + CURL_SOCKET_BAD. The callback should have type + curl_opensocket_callback */ + CURLOPT(CURLOPT_OPENSOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 163), + CURLOPT(CURLOPT_OPENSOCKETDATA, CURLOPTTYPE_CBPOINT, 164), + + /* POST volatile input fields. */ + CURLOPT(CURLOPT_COPYPOSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 165), + + /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ + CURLOPT(CURLOPT_PROXY_TRANSFER_MODE, CURLOPTTYPE_LONG, 166), + + /* Callback function for seeking in the input stream */ + CURLOPT(CURLOPT_SEEKFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 167), + CURLOPT(CURLOPT_SEEKDATA, CURLOPTTYPE_CBPOINT, 168), + + /* CRL file */ + CURLOPT(CURLOPT_CRLFILE, CURLOPTTYPE_STRINGPOINT, 169), + + /* Issuer certificate */ + CURLOPT(CURLOPT_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 170), + + /* (IPv6) Address scope */ + CURLOPT(CURLOPT_ADDRESS_SCOPE, CURLOPTTYPE_LONG, 171), + + /* Collect certificate chain info and allow it to get retrievable with + CURLINFO_CERTINFO after the transfer is complete. */ + CURLOPT(CURLOPT_CERTINFO, CURLOPTTYPE_LONG, 172), + + /* "name" and "pwd" to use when fetching. */ + CURLOPT(CURLOPT_USERNAME, CURLOPTTYPE_STRINGPOINT, 173), + CURLOPT(CURLOPT_PASSWORD, CURLOPTTYPE_STRINGPOINT, 174), + + /* "name" and "pwd" to use with Proxy when fetching. */ + CURLOPT(CURLOPT_PROXYUSERNAME, CURLOPTTYPE_STRINGPOINT, 175), + CURLOPT(CURLOPT_PROXYPASSWORD, CURLOPTTYPE_STRINGPOINT, 176), + + /* Comma separated list of hostnames defining no-proxy zones. These should + match both hostnames directly, and hostnames within a domain. For + example, local.com will match local.com and www.local.com, but NOT + notlocal.com or www.notlocal.com. For compatibility with other + implementations of this, .local.com will be considered to be the same as + local.com. A single * is the only valid wildcard, and effectively + disables the use of proxy. */ + CURLOPT(CURLOPT_NOPROXY, CURLOPTTYPE_STRINGPOINT, 177), + + /* block size for TFTP transfers */ + CURLOPT(CURLOPT_TFTP_BLKSIZE, CURLOPTTYPE_LONG, 178), + + /* Socks Service */ + /* DEPRECATED, do not use! */ + CURLOPT(CURLOPT_SOCKS5_GSSAPI_SERVICE, CURLOPTTYPE_STRINGPOINT, 179), + + /* Socks Service */ + CURLOPT(CURLOPT_SOCKS5_GSSAPI_NEC, CURLOPTTYPE_LONG, 180), + + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + CURLOPT(CURLOPT_PROTOCOLS, CURLOPTTYPE_LONG, 181), + + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. */ + CURLOPT(CURLOPT_REDIR_PROTOCOLS, CURLOPTTYPE_LONG, 182), + + /* set the SSH knownhost file name to use */ + CURLOPT(CURLOPT_SSH_KNOWNHOSTS, CURLOPTTYPE_STRINGPOINT, 183), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CURLOPT(CURLOPT_SSH_KEYFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 184), + + /* set the SSH host key callback custom pointer */ + CURLOPT(CURLOPT_SSH_KEYDATA, CURLOPTTYPE_CBPOINT, 185), + + /* set the SMTP mail originator */ + CURLOPT(CURLOPT_MAIL_FROM, CURLOPTTYPE_STRINGPOINT, 186), + + /* set the list of SMTP mail receiver(s) */ + CURLOPT(CURLOPT_MAIL_RCPT, CURLOPTTYPE_SLISTPOINT, 187), + + /* FTP: send PRET before PASV */ + CURLOPT(CURLOPT_FTP_USE_PRET, CURLOPTTYPE_LONG, 188), + + /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ + CURLOPT(CURLOPT_RTSP_REQUEST, CURLOPTTYPE_VALUES, 189), + + /* The RTSP session identifier */ + CURLOPT(CURLOPT_RTSP_SESSION_ID, CURLOPTTYPE_STRINGPOINT, 190), + + /* The RTSP stream URI */ + CURLOPT(CURLOPT_RTSP_STREAM_URI, CURLOPTTYPE_STRINGPOINT, 191), + + /* The Transport: header to use in RTSP requests */ + CURLOPT(CURLOPT_RTSP_TRANSPORT, CURLOPTTYPE_STRINGPOINT, 192), + + /* Manually initialize the client RTSP CSeq for this handle */ + CURLOPT(CURLOPT_RTSP_CLIENT_CSEQ, CURLOPTTYPE_LONG, 193), + + /* Manually initialize the server RTSP CSeq for this handle */ + CURLOPT(CURLOPT_RTSP_SERVER_CSEQ, CURLOPTTYPE_LONG, 194), + + /* The stream to pass to INTERLEAVEFUNCTION. */ + CURLOPT(CURLOPT_INTERLEAVEDATA, CURLOPTTYPE_CBPOINT, 195), + + /* Let the application define a custom write method for RTP data */ + CURLOPT(CURLOPT_INTERLEAVEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 196), + + /* Turn on wildcard matching */ + CURLOPT(CURLOPT_WILDCARDMATCH, CURLOPTTYPE_LONG, 197), + + /* Directory matching callback called before downloading of an + individual file (chunk) started */ + CURLOPT(CURLOPT_CHUNK_BGN_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 198), + + /* Directory matching callback called after the file (chunk) + was downloaded, or skipped */ + CURLOPT(CURLOPT_CHUNK_END_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 199), + + /* Change match (fnmatch-like) callback for wildcard matching */ + CURLOPT(CURLOPT_FNMATCH_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 200), + + /* Let the application define custom chunk data pointer */ + CURLOPT(CURLOPT_CHUNK_DATA, CURLOPTTYPE_CBPOINT, 201), + + /* FNMATCH_FUNCTION user pointer */ + CURLOPT(CURLOPT_FNMATCH_DATA, CURLOPTTYPE_CBPOINT, 202), + + /* send linked-list of name:port:address sets */ + CURLOPT(CURLOPT_RESOLVE, CURLOPTTYPE_SLISTPOINT, 203), + + /* Set a username for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 204), + + /* Set a password for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_PASSWORD, CURLOPTTYPE_STRINGPOINT, 205), + + /* Set authentication type for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_TYPE, CURLOPTTYPE_STRINGPOINT, 206), + + /* Set to 1 to enable the "TE:" header in HTTP requests to ask for + compressed transfer-encoded responses. Set to 0 to disable the use of TE: + in outgoing requests. The current default is 0, but it might change in a + future libcurl release. + + libcurl will ask for the compressed methods it knows of, and if that + isn't any, it will not ask for transfer-encoding at all even if this + option is set to 1. + + */ + CURLOPT(CURLOPT_TRANSFER_ENCODING, CURLOPTTYPE_LONG, 207), + + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CURLOPT(CURLOPT_CLOSESOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 208), + CURLOPT(CURLOPT_CLOSESOCKETDATA, CURLOPTTYPE_CBPOINT, 209), + + /* allow GSSAPI credential delegation */ + CURLOPT(CURLOPT_GSSAPI_DELEGATION, CURLOPTTYPE_VALUES, 210), + + /* Set the name servers to use for DNS resolution */ + CURLOPT(CURLOPT_DNS_SERVERS, CURLOPTTYPE_STRINGPOINT, 211), + + /* Time-out accept operations (currently for FTP only) after this amount + of milliseconds. */ + CURLOPT(CURLOPT_ACCEPTTIMEOUT_MS, CURLOPTTYPE_LONG, 212), + + /* Set TCP keepalive */ + CURLOPT(CURLOPT_TCP_KEEPALIVE, CURLOPTTYPE_LONG, 213), + + /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */ + CURLOPT(CURLOPT_TCP_KEEPIDLE, CURLOPTTYPE_LONG, 214), + CURLOPT(CURLOPT_TCP_KEEPINTVL, CURLOPTTYPE_LONG, 215), + + /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */ + CURLOPT(CURLOPT_SSL_OPTIONS, CURLOPTTYPE_VALUES, 216), + + /* Set the SMTP auth originator */ + CURLOPT(CURLOPT_MAIL_AUTH, CURLOPTTYPE_STRINGPOINT, 217), + + /* Enable/disable SASL initial response */ + CURLOPT(CURLOPT_SASL_IR, CURLOPTTYPE_LONG, 218), + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_xferinfo_callback + * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ + CURLOPT(CURLOPT_XFERINFOFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 219), + + /* The XOAUTH2 bearer token */ + CURLOPT(CURLOPT_XOAUTH2_BEARER, CURLOPTTYPE_STRINGPOINT, 220), + + /* Set the interface string to use as outgoing network + * interface for DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_INTERFACE, CURLOPTTYPE_STRINGPOINT, 221), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_LOCAL_IP4, CURLOPTTYPE_STRINGPOINT, 222), + + /* Set the local IPv6 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_LOCAL_IP6, CURLOPTTYPE_STRINGPOINT, 223), + + /* Set authentication options directly */ + CURLOPT(CURLOPT_LOGIN_OPTIONS, CURLOPTTYPE_STRINGPOINT, 224), + + /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */ + CURLOPT(CURLOPT_SSL_ENABLE_NPN, CURLOPTTYPE_LONG, 225), + + /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */ + CURLOPT(CURLOPT_SSL_ENABLE_ALPN, CURLOPTTYPE_LONG, 226), + + /* Time to wait for a response to a HTTP request containing an + * Expect: 100-continue header before sending the data anyway. */ + CURLOPT(CURLOPT_EXPECT_100_TIMEOUT_MS, CURLOPTTYPE_LONG, 227), + + /* This points to a linked list of headers used for proxy requests only, + struct curl_slist kind */ + CURLOPT(CURLOPT_PROXYHEADER, CURLOPTTYPE_SLISTPOINT, 228), + + /* Pass in a bitmask of "header options" */ + CURLOPT(CURLOPT_HEADEROPT, CURLOPTTYPE_VALUES, 229), + + /* The public key in DER form used to validate the peer public key + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 230), + + /* Path to Unix domain socket */ + CURLOPT(CURLOPT_UNIX_SOCKET_PATH, CURLOPTTYPE_STRINGPOINT, 231), + + /* Set if we should verify the certificate status. */ + CURLOPT(CURLOPT_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 232), + + /* Set if we should enable TLS false start. */ + CURLOPT(CURLOPT_SSL_FALSESTART, CURLOPTTYPE_LONG, 233), + + /* Do not squash dot-dot sequences */ + CURLOPT(CURLOPT_PATH_AS_IS, CURLOPTTYPE_LONG, 234), + + /* Proxy Service Name */ + CURLOPT(CURLOPT_PROXY_SERVICE_NAME, CURLOPTTYPE_STRINGPOINT, 235), + + /* Service Name */ + CURLOPT(CURLOPT_SERVICE_NAME, CURLOPTTYPE_STRINGPOINT, 236), + + /* Wait/don't wait for pipe/mutex to clarify */ + CURLOPT(CURLOPT_PIPEWAIT, CURLOPTTYPE_LONG, 237), + + /* Set the protocol used when curl is given a URL without a protocol */ + CURLOPT(CURLOPT_DEFAULT_PROTOCOL, CURLOPTTYPE_STRINGPOINT, 238), + + /* Set stream weight, 1 - 256 (default is 16) */ + CURLOPT(CURLOPT_STREAM_WEIGHT, CURLOPTTYPE_LONG, 239), + + /* Set stream dependency on another CURL handle */ + CURLOPT(CURLOPT_STREAM_DEPENDS, CURLOPTTYPE_OBJECTPOINT, 240), + + /* Set E-xclusive stream dependency on another CURL handle */ + CURLOPT(CURLOPT_STREAM_DEPENDS_E, CURLOPTTYPE_OBJECTPOINT, 241), + + /* Do not send any tftp option requests to the server */ + CURLOPT(CURLOPT_TFTP_NO_OPTIONS, CURLOPTTYPE_LONG, 242), + + /* Linked-list of host:port:connect-to-host:connect-to-port, + overrides the URL's host:port (only for the network layer) */ + CURLOPT(CURLOPT_CONNECT_TO, CURLOPTTYPE_SLISTPOINT, 243), + + /* Set TCP Fast Open */ + CURLOPT(CURLOPT_TCP_FASTOPEN, CURLOPTTYPE_LONG, 244), + + /* Continue to send data if the server responds early with an + * HTTP status code >= 300 */ + CURLOPT(CURLOPT_KEEP_SENDING_ON_ERROR, CURLOPTTYPE_LONG, 245), + + /* The CApath or CAfile used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAINFO, CURLOPTTYPE_STRINGPOINT, 246), + + /* The CApath directory used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAPATH, CURLOPTTYPE_STRINGPOINT, 247), + + /* Set if we should verify the proxy in ssl handshake, + set 1 to verify. */ + CURLOPT(CURLOPT_PROXY_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 248), + + /* Set if we should verify the Common name from the proxy certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches + * the provided hostname. */ + CURLOPT(CURLOPT_PROXY_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 249), + + /* What version to specifically try to use for proxy. + See CURL_SSLVERSION defines below. */ + CURLOPT(CURLOPT_PROXY_SSLVERSION, CURLOPTTYPE_VALUES, 250), + + /* Set a username for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 251), + + /* Set a password for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_PASSWORD, CURLOPTTYPE_STRINGPOINT, 252), + + /* Set authentication type for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_TYPE, CURLOPTTYPE_STRINGPOINT, 253), + + /* name of the file keeping your private SSL-certificate for proxy */ + CURLOPT(CURLOPT_PROXY_SSLCERT, CURLOPTTYPE_STRINGPOINT, 254), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for + proxy */ + CURLOPT(CURLOPT_PROXY_SSLCERTTYPE, CURLOPTTYPE_STRINGPOINT, 255), + + /* name of the file keeping your private SSL-key for proxy */ + CURLOPT(CURLOPT_PROXY_SSLKEY, CURLOPTTYPE_STRINGPOINT, 256), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for + proxy */ + CURLOPT(CURLOPT_PROXY_SSLKEYTYPE, CURLOPTTYPE_STRINGPOINT, 257), + + /* password for the SSL private key for proxy */ + CURLOPT(CURLOPT_PROXY_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 258), + + /* Specify which SSL ciphers to use for proxy */ + CURLOPT(CURLOPT_PROXY_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 259), + + /* CRL file for proxy */ + CURLOPT(CURLOPT_PROXY_CRLFILE, CURLOPTTYPE_STRINGPOINT, 260), + + /* Enable/disable specific SSL features with a bitmask for proxy, see + CURLSSLOPT_* */ + CURLOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLOPTTYPE_LONG, 261), + + /* Name of pre proxy to use. */ + CURLOPT(CURLOPT_PRE_PROXY, CURLOPTTYPE_STRINGPOINT, 262), + + /* The public key in DER form used to validate the proxy public key + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 263), + + /* Path to an abstract Unix domain socket */ + CURLOPT(CURLOPT_ABSTRACT_UNIX_SOCKET, CURLOPTTYPE_STRINGPOINT, 264), + + /* Suppress proxy CONNECT response headers from user callbacks */ + CURLOPT(CURLOPT_SUPPRESS_CONNECT_HEADERS, CURLOPTTYPE_LONG, 265), + + /* The request target, instead of extracted from the URL */ + CURLOPT(CURLOPT_REQUEST_TARGET, CURLOPTTYPE_STRINGPOINT, 266), + + /* bitmask of allowed auth methods for connections to SOCKS5 proxies */ + CURLOPT(CURLOPT_SOCKS5_AUTH, CURLOPTTYPE_LONG, 267), + + /* Enable/disable SSH compression */ + CURLOPT(CURLOPT_SSH_COMPRESSION, CURLOPTTYPE_LONG, 268), + + /* Post MIME data. */ + CURLOPT(CURLOPT_MIMEPOST, CURLOPTTYPE_OBJECTPOINT, 269), + + /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of + seconds since 1 Jan 1970. */ + CURLOPT(CURLOPT_TIMEVALUE_LARGE, CURLOPTTYPE_OFF_T, 270), + + /* Head start in milliseconds to give happy eyeballs. */ + CURLOPT(CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, CURLOPTTYPE_LONG, 271), + + /* Function that will be called before a resolver request is made */ + CURLOPT(CURLOPT_RESOLVER_START_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 272), + + /* User data to pass to the resolver start callback. */ + CURLOPT(CURLOPT_RESOLVER_START_DATA, CURLOPTTYPE_CBPOINT, 273), + + /* send HAProxy PROXY protocol header? */ + CURLOPT(CURLOPT_HAPROXYPROTOCOL, CURLOPTTYPE_LONG, 274), + + /* shuffle addresses before use when DNS returns multiple */ + CURLOPT(CURLOPT_DNS_SHUFFLE_ADDRESSES, CURLOPTTYPE_LONG, 275), + + /* Specify which TLS 1.3 ciphers suites to use */ + CURLOPT(CURLOPT_TLS13_CIPHERS, CURLOPTTYPE_STRINGPOINT, 276), + CURLOPT(CURLOPT_PROXY_TLS13_CIPHERS, CURLOPTTYPE_STRINGPOINT, 277), + + /* Disallow specifying username/login in URL. */ + CURLOPT(CURLOPT_DISALLOW_USERNAME_IN_URL, CURLOPTTYPE_LONG, 278), + + /* DNS-over-HTTPS URL */ + CURLOPT(CURLOPT_DOH_URL, CURLOPTTYPE_STRINGPOINT, 279), + + /* Preferred buffer size to use for uploads */ + CURLOPT(CURLOPT_UPLOAD_BUFFERSIZE, CURLOPTTYPE_LONG, 280), + + /* Time in ms between connection upkeep calls for long-lived connections. */ + CURLOPT(CURLOPT_UPKEEP_INTERVAL_MS, CURLOPTTYPE_LONG, 281), + + /* Specify URL using CURL URL API. */ + CURLOPT(CURLOPT_CURLU, CURLOPTTYPE_OBJECTPOINT, 282), + + /* add trailing data just after no more data is available */ + CURLOPT(CURLOPT_TRAILERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 283), + + /* pointer to be passed to HTTP_TRAILER_FUNCTION */ + CURLOPT(CURLOPT_TRAILERDATA, CURLOPTTYPE_CBPOINT, 284), + + /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */ + CURLOPT(CURLOPT_HTTP09_ALLOWED, CURLOPTTYPE_LONG, 285), + + /* alt-svc control bitmask */ + CURLOPT(CURLOPT_ALTSVC_CTRL, CURLOPTTYPE_LONG, 286), + + /* alt-svc cache file name to possibly read from/write to */ + CURLOPT(CURLOPT_ALTSVC, CURLOPTTYPE_STRINGPOINT, 287), + + /* maximum age of a connection to consider it for reuse (in seconds) */ + CURLOPT(CURLOPT_MAXAGE_CONN, CURLOPTTYPE_LONG, 288), + + /* SASL authorisation identity */ + CURLOPT(CURLOPT_SASL_AUTHZID, CURLOPTTYPE_STRINGPOINT, 289), + + /* allow RCPT TO command to fail for some recipients */ + CURLOPT(CURLOPT_MAIL_RCPT_ALLLOWFAILS, CURLOPTTYPE_LONG, 290), + + /* the private SSL-certificate as a "blob" */ + CURLOPT(CURLOPT_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 291), + CURLOPT(CURLOPT_SSLKEY_BLOB, CURLOPTTYPE_BLOB, 292), + CURLOPT(CURLOPT_PROXY_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 293), + CURLOPT(CURLOPT_PROXY_SSLKEY_BLOB, CURLOPTTYPE_BLOB, 294), + CURLOPT(CURLOPT_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 295), + + /* Issuer certificate for proxy */ + CURLOPT(CURLOPT_PROXY_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 296), + CURLOPT(CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 297), + + /* the EC curves requested by the TLS client (RFC 8422, 5.1); + * OpenSSL support via 'set_groups'/'set_curves': + * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html + */ + CURLOPT(CURLOPT_SSL_EC_CURVES, CURLOPTTYPE_STRINGPOINT, 298), + + /* HSTS bitmask */ + CURLOPT(CURLOPT_HSTS_CTRL, CURLOPTTYPE_LONG, 299), + /* HSTS file name */ + CURLOPT(CURLOPT_HSTS, CURLOPTTYPE_STRINGPOINT, 300), + + /* HSTS read callback */ + CURLOPT(CURLOPT_HSTSREADFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 301), + CURLOPT(CURLOPT_HSTSREADDATA, CURLOPTTYPE_CBPOINT, 302), + + /* HSTS write callback */ + CURLOPT(CURLOPT_HSTSWRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 303), + CURLOPT(CURLOPT_HSTSWRITEDATA, CURLOPTTYPE_CBPOINT, 304), + + /* Parameters for V4 signature */ + CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305), + + /* Same as CURLOPT_SSL_VERIFYPEER but for DoH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 306), + + /* Same as CURLOPT_SSL_VERIFYHOST but for DoH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 307), + + /* Same as CURLOPT_SSL_VERIFYSTATUS but for DoH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 308), + + /* The CA certificates as "blob" used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAINFO_BLOB, CURLOPTTYPE_BLOB, 309), + + /* The CA certificates as "blob" used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAINFO_BLOB, CURLOPTTYPE_BLOB, 310), + + CURLOPT_LASTENTRY /* the last unused */ +} CURLoption; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2011 */ + +/* This was added in version 7.19.1 */ +#define CURLOPT_POST301 CURLOPT_POSTREDIR + +/* These are scheduled to disappear by 2009 */ + +/* The following were added in 7.17.0 */ +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_FTPAPPEND CURLOPT_APPEND +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL + +/* The following were added earlier */ + +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL + +#else +/* This is set if CURL_NO_OLDIES is defined at compile-time */ +#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */ +#endif + + + /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. */ +#define CURL_IPRESOLVE_WHATEVER 0 /* default, uses addresses to all IP + versions that your system allows */ +#define CURL_IPRESOLVE_V4 1 /* uses only IPv4 addresses/connections */ +#define CURL_IPRESOLVE_V6 2 /* uses only IPv6 addresses/connections */ + + /* three convenient "aliases" that follow the name scheme better */ +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER + + /* These enums are for use with the CURLOPT_HTTP_VERSION option. */ +enum { + CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd + like the library to choose the best possible + for us! */ + CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ + CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ + CURL_HTTP_VERSION_2_0, /* please use HTTP 2 in the request */ + CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */ + CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, /* please use HTTP 2 without HTTP/1.1 + Upgrade */ + CURL_HTTP_VERSION_3 = 30, /* Makes use of explicit HTTP/3 without fallback. + Use CURLOPT_ALTSVC to enable HTTP/3 upgrade */ + CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ +}; + +/* Convenience definition simple because the name of the version is HTTP/2 and + not 2.0. The 2_0 version of the enum name was set while the version was + still planned to be 2.0 and we stick to it for compatibility. */ +#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0 + +/* + * Public API enums for RTSP requests + */ +enum { + CURL_RTSPREQ_NONE, /* first in list */ + CURL_RTSPREQ_OPTIONS, + CURL_RTSPREQ_DESCRIBE, + CURL_RTSPREQ_ANNOUNCE, + CURL_RTSPREQ_SETUP, + CURL_RTSPREQ_PLAY, + CURL_RTSPREQ_PAUSE, + CURL_RTSPREQ_TEARDOWN, + CURL_RTSPREQ_GET_PARAMETER, + CURL_RTSPREQ_SET_PARAMETER, + CURL_RTSPREQ_RECORD, + CURL_RTSPREQ_RECEIVE, + CURL_RTSPREQ_LAST /* last in list */ +}; + + /* These enums are for use with the CURLOPT_NETRC option. */ +enum CURL_NETRC_OPTION { + CURL_NETRC_IGNORED, /* The .netrc will never be read. + * This is the default. */ + CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred + * to one in the .netrc. */ + CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. + * Unless one is set programmatically, the .netrc + * will be queried. */ + CURL_NETRC_LAST +}; + +enum { + CURL_SSLVERSION_DEFAULT, + CURL_SSLVERSION_TLSv1, /* TLS 1.x */ + CURL_SSLVERSION_SSLv2, + CURL_SSLVERSION_SSLv3, + CURL_SSLVERSION_TLSv1_0, + CURL_SSLVERSION_TLSv1_1, + CURL_SSLVERSION_TLSv1_2, + CURL_SSLVERSION_TLSv1_3, + + CURL_SSLVERSION_LAST /* never use, keep last */ +}; + +enum { + CURL_SSLVERSION_MAX_NONE = 0, + CURL_SSLVERSION_MAX_DEFAULT = (CURL_SSLVERSION_TLSv1 << 16), + CURL_SSLVERSION_MAX_TLSv1_0 = (CURL_SSLVERSION_TLSv1_0 << 16), + CURL_SSLVERSION_MAX_TLSv1_1 = (CURL_SSLVERSION_TLSv1_1 << 16), + CURL_SSLVERSION_MAX_TLSv1_2 = (CURL_SSLVERSION_TLSv1_2 << 16), + CURL_SSLVERSION_MAX_TLSv1_3 = (CURL_SSLVERSION_TLSv1_3 << 16), + + /* never use, keep last */ + CURL_SSLVERSION_MAX_LAST = (CURL_SSLVERSION_LAST << 16) +}; + +enum CURL_TLSAUTH { + CURL_TLSAUTH_NONE, + CURL_TLSAUTH_SRP, + CURL_TLSAUTH_LAST /* never use, keep last */ +}; + +/* symbols to use with CURLOPT_POSTREDIR. + CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303 + can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302 + | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */ + +#define CURL_REDIR_GET_ALL 0 +#define CURL_REDIR_POST_301 1 +#define CURL_REDIR_POST_302 2 +#define CURL_REDIR_POST_303 4 +#define CURL_REDIR_POST_ALL \ + (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303) + +typedef enum { + CURL_TIMECOND_NONE, + + CURL_TIMECOND_IFMODSINCE, + CURL_TIMECOND_IFUNMODSINCE, + CURL_TIMECOND_LASTMOD, + + CURL_TIMECOND_LAST +} curl_TimeCond; + +/* Special size_t value signaling a null-terminated string. */ +#define CURL_ZERO_TERMINATED ((size_t) -1) + +/* curl_strequal() and curl_strnequal() are subject for removal in a future + release */ +CURL_EXTERN int curl_strequal(const char *s1, const char *s2); +CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n); + +/* Mime/form handling support. */ +typedef struct curl_mime curl_mime; /* Mime context. */ +typedef struct curl_mimepart curl_mimepart; /* Mime part context. */ + +/* + * NAME curl_mime_init() + * + * DESCRIPTION + * + * Create a mime context and return its handle. The easy parameter is the + * target handle. + */ +CURL_EXTERN curl_mime *curl_mime_init(CURL *easy); + +/* + * NAME curl_mime_free() + * + * DESCRIPTION + * + * release a mime handle and its substructures. + */ +CURL_EXTERN void curl_mime_free(curl_mime *mime); + +/* + * NAME curl_mime_addpart() + * + * DESCRIPTION + * + * Append a new empty part to the given mime context and return a handle to + * the created part. + */ +CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime); + +/* + * NAME curl_mime_name() + * + * DESCRIPTION + * + * Set mime/form part name. + */ +CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name); + +/* + * NAME curl_mime_filename() + * + * DESCRIPTION + * + * Set mime part remote file name. + */ +CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_type() + * + * DESCRIPTION + * + * Set mime part type. + */ +CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype); + +/* + * NAME curl_mime_encoder() + * + * DESCRIPTION + * + * Set mime data transfer encoder. + */ +CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part, + const char *encoding); + +/* + * NAME curl_mime_data() + * + * DESCRIPTION + * + * Set mime part data source from memory data, + */ +CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part, + const char *data, size_t datasize); + +/* + * NAME curl_mime_filedata() + * + * DESCRIPTION + * + * Set mime part data source from named file. + */ +CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_data_cb() + * + * DESCRIPTION + * + * Set mime part data source from callback function. + */ +CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part, + curl_off_t datasize, + curl_read_callback readfunc, + curl_seek_callback seekfunc, + curl_free_callback freefunc, + void *arg); + +/* + * NAME curl_mime_subparts() + * + * DESCRIPTION + * + * Set mime part data source from subparts. + */ +CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part, + curl_mime *subparts); +/* + * NAME curl_mime_headers() + * + * DESCRIPTION + * + * Set mime part headers. + */ +CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part, + struct curl_slist *headers, + int take_ownership); + +typedef enum { + CURLFORM_NOTHING, /********* the first one is unused ************/ + CURLFORM_COPYNAME, + CURLFORM_PTRNAME, + CURLFORM_NAMELENGTH, + CURLFORM_COPYCONTENTS, + CURLFORM_PTRCONTENTS, + CURLFORM_CONTENTSLENGTH, + CURLFORM_FILECONTENT, + CURLFORM_ARRAY, + CURLFORM_OBSOLETE, + CURLFORM_FILE, + + CURLFORM_BUFFER, + CURLFORM_BUFFERPTR, + CURLFORM_BUFFERLENGTH, + + CURLFORM_CONTENTTYPE, + CURLFORM_CONTENTHEADER, + CURLFORM_FILENAME, + CURLFORM_END, + CURLFORM_OBSOLETE2, + + CURLFORM_STREAM, + CURLFORM_CONTENTLEN, /* added in 7.46.0, provide a curl_off_t length */ + + CURLFORM_LASTENTRY /* the last unused */ +} CURLformoption; + +/* structure to be used as parameter for CURLFORM_ARRAY */ +struct curl_forms { + CURLformoption option; + const char *value; +}; + +/* use this for multipart formpost building */ +/* Returns code for curl_formadd() + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ +typedef enum { + CURL_FORMADD_OK, /* first, no error */ + + CURL_FORMADD_MEMORY, + CURL_FORMADD_OPTION_TWICE, + CURL_FORMADD_NULL, + CURL_FORMADD_UNKNOWN_OPTION, + CURL_FORMADD_INCOMPLETE, + CURL_FORMADD_ILLEGAL_ARRAY, + CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */ + + CURL_FORMADD_LAST /* last */ +} CURLFORMcode; + +/* + * NAME curl_formadd() + * + * DESCRIPTION + * + * Pretty advanced function for building multi-part formposts. Each invoke + * adds one part that together construct a full post. Then use + * CURLOPT_HTTPPOST to send it off to libcurl. + */ +CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...); + +/* + * callback function for curl_formget() + * The void *arg pointer will be the one passed as second argument to + * curl_formget(). + * The character buffer passed to it must not be freed. + * Should return the buffer length passed to it as the argument "len" on + * success. + */ +typedef size_t (*curl_formget_callback)(void *arg, const char *buf, + size_t len); + +/* + * NAME curl_formget() + * + * DESCRIPTION + * + * Serialize a curl_httppost struct built with curl_formadd(). + * Accepts a void pointer as second argument which will be passed to + * the curl_formget_callback function. + * Returns 0 on success. + */ +CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append); +/* + * NAME curl_formfree() + * + * DESCRIPTION + * + * Free a multipart formpost previously built with curl_formadd(). + */ +CURL_EXTERN void curl_formfree(struct curl_httppost *form); + +/* + * NAME curl_getenv() + * + * DESCRIPTION + * + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is + * complete. DEPRECATED - see lib/README.curlx + */ +CURL_EXTERN char *curl_getenv(const char *variable); + +/* + * NAME curl_version() + * + * DESCRIPTION + * + * Returns a static ascii string of the libcurl version. + */ +CURL_EXTERN char *curl_version(void); + +/* + * NAME curl_easy_escape() + * + * DESCRIPTION + * + * Escapes URL strings (converts all letters consider illegal in URLs to their + * %XX versions). This function returns a new allocated string or NULL if an + * error occurred. + */ +CURL_EXTERN char *curl_easy_escape(CURL *handle, + const char *string, + int length); + +/* the previous version: */ +CURL_EXTERN char *curl_escape(const char *string, + int length); + + +/* + * NAME curl_easy_unescape() + * + * DESCRIPTION + * + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit + * versions). This function returns a new allocated string or NULL if an error + * occurred. + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are + * converted into the host encoding. + */ +CURL_EXTERN char *curl_easy_unescape(CURL *handle, + const char *string, + int length, + int *outlength); + +/* the previous version */ +CURL_EXTERN char *curl_unescape(const char *string, + int length); + +/* + * NAME curl_free() + * + * DESCRIPTION + * + * Provided for de-allocation in the same translation unit that did the + * allocation. Added in libcurl 7.10 + */ +CURL_EXTERN void curl_free(void *p); + +/* + * NAME curl_global_init() + * + * DESCRIPTION + * + * curl_global_init() should be invoked exactly once for each application that + * uses libcurl and before any call of other libcurl functions. + * + * This function is not thread-safe! + */ +CURL_EXTERN CURLcode curl_global_init(long flags); + +/* + * NAME curl_global_init_mem() + * + * DESCRIPTION + * + * curl_global_init() or curl_global_init_mem() should be invoked exactly once + * for each application that uses libcurl. This function can be used to + * initialize libcurl and set user defined memory management callback + * functions. Users can implement memory management routines to check for + * memory leaks, check for mis-use of the curl library etc. User registered + * callback routines will be invoked by this library instead of the system + * memory management routines like malloc, free etc. + */ +CURL_EXTERN CURLcode curl_global_init_mem(long flags, + curl_malloc_callback m, + curl_free_callback f, + curl_realloc_callback r, + curl_strdup_callback s, + curl_calloc_callback c); + +/* + * NAME curl_global_cleanup() + * + * DESCRIPTION + * + * curl_global_cleanup() should be invoked exactly once for each application + * that uses libcurl + */ +CURL_EXTERN void curl_global_cleanup(void); + +/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +struct curl_slist { + char *data; + struct curl_slist *next; +}; + +/* + * NAME curl_global_sslset() + * + * DESCRIPTION + * + * When built with multiple SSL backends, curl_global_sslset() allows to + * choose one. This function can only be called once, and it must be called + * *before* curl_global_init(). + * + * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The + * backend can also be specified via the name parameter (passing -1 as id). + * If both id and name are specified, the name will be ignored. If neither id + * nor name are specified, the function will fail with + * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the + * NULL-terminated list of available backends. + * + * Upon success, the function returns CURLSSLSET_OK. + * + * If the specified SSL backend is not available, the function returns + * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated + * list of available SSL backends. + * + * The SSL backend can be set only once. If it has already been set, a + * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE. + */ + +struct curl_ssl_backend { + curl_sslbackend id; + const char *name; +}; +typedef struct curl_ssl_backend curl_ssl_backend; + +typedef enum { + CURLSSLSET_OK = 0, + CURLSSLSET_UNKNOWN_BACKEND, + CURLSSLSET_TOO_LATE, + CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */ +} CURLsslset; + +CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, + const curl_ssl_backend ***avail); + +/* + * NAME curl_slist_append() + * + * DESCRIPTION + * + * Appends a string to a linked list. If no list exists, it will be created + * first. Returns the new list, after appending. + */ +CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *, + const char *); + +/* + * NAME curl_slist_free_all() + * + * DESCRIPTION + * + * free a previously built curl_slist. + */ +CURL_EXTERN void curl_slist_free_all(struct curl_slist *); + +/* + * NAME curl_getdate() + * + * DESCRIPTION + * + * Returns the time, in seconds since 1 Jan 1970 of the time string given in + * the first argument. The time argument in the second parameter is unused + * and should be set to NULL. + */ +CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); + +/* info about the certificate chain, only for OpenSSL, GnuTLS, Schannel, NSS + and GSKit builds. Asked for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ +struct curl_certinfo { + int num_of_certs; /* number of certificates with information */ + struct curl_slist **certinfo; /* for each index in this array, there's a + linked list with textual information in the + format "name: value" */ +}; + +/* Information about the SSL library used and the respective internal SSL + handle, which can be used to obtain further information regarding the + connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */ +struct curl_tlssessioninfo { + curl_sslbackend backend; + void *internals; +}; + +#define CURLINFO_STRING 0x100000 +#define CURLINFO_LONG 0x200000 +#define CURLINFO_DOUBLE 0x300000 +#define CURLINFO_SLIST 0x400000 +#define CURLINFO_PTR 0x400000 /* same as SLIST */ +#define CURLINFO_SOCKET 0x500000 +#define CURLINFO_OFF_T 0x600000 +#define CURLINFO_MASK 0x0fffff +#define CURLINFO_TYPEMASK 0xf00000 + +typedef enum { + CURLINFO_NONE, /* first, never use this */ + CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, + CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, + CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, + CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, + CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, + CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, + CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7, + CURLINFO_SIZE_UPLOAD_T = CURLINFO_OFF_T + 7, + CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8, + CURLINFO_SIZE_DOWNLOAD_T = CURLINFO_OFF_T + 8, + CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9, + CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T + 9, + CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10, + CURLINFO_SPEED_UPLOAD_T = CURLINFO_OFF_T + 10, + CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, + CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, + CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, + CURLINFO_FILETIME = CURLINFO_LONG + 14, + CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14, + CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15, + CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15, + CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16, + CURLINFO_CONTENT_LENGTH_UPLOAD_T = CURLINFO_OFF_T + 16, + CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, + CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + CURLINFO_PRIVATE = CURLINFO_STRING + 21, + CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, + CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, + CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, + CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, + CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, + CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, + CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, + CURLINFO_LASTSOCKET = CURLINFO_LONG + 29, + CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, + CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, + CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, + CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, + CURLINFO_CERTINFO = CURLINFO_PTR + 34, + CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, + CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, + CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, + CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, + CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, + CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, + CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, + CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, + CURLINFO_TLS_SESSION = CURLINFO_PTR + 43, + CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44, + CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45, + CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46, + CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47, + CURLINFO_PROTOCOL = CURLINFO_LONG + 48, + CURLINFO_SCHEME = CURLINFO_STRING + 49, + CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50, + CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51, + CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52, + CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53, + CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54, + CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55, + CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56, + CURLINFO_RETRY_AFTER = CURLINFO_OFF_T + 57, + CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58, + CURLINFO_PROXY_ERROR = CURLINFO_LONG + 59, + CURLINFO_REFERER = CURLINFO_STRING + 60, + + CURLINFO_LASTONE = 60 +} CURLINFO; + +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as + CURLINFO_HTTP_CODE */ +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE + +typedef enum { + CURLCLOSEPOLICY_NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY_USED, + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, + + CURLCLOSEPOLICY_LAST /* last, never use this */ +} curl_closepolicy; + +#define CURL_GLOBAL_SSL (1<<0) /* no purpose since since 7.57.0 */ +#define CURL_GLOBAL_WIN32 (1<<1) +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +#define CURL_GLOBAL_NOTHING 0 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL +#define CURL_GLOBAL_ACK_EINTR (1<<2) + + +/***************************************************************************** + * Setup defines, protos etc for the sharing stuff. + */ + +/* Different data locks for a single share */ +typedef enum { + CURL_LOCK_DATA_NONE = 0, + /* CURL_LOCK_DATA_SHARE is used internally to say that + * the locking is just made to change the internal state of the share + * itself. + */ + CURL_LOCK_DATA_SHARE, + CURL_LOCK_DATA_COOKIE, + CURL_LOCK_DATA_DNS, + CURL_LOCK_DATA_SSL_SESSION, + CURL_LOCK_DATA_CONNECT, + CURL_LOCK_DATA_PSL, + CURL_LOCK_DATA_LAST +} curl_lock_data; + +/* Different lock access types */ +typedef enum { + CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */ + CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */ + CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */ + CURL_LOCK_ACCESS_LAST /* never use */ +} curl_lock_access; + +typedef void (*curl_lock_function)(CURL *handle, + curl_lock_data data, + curl_lock_access locktype, + void *userptr); +typedef void (*curl_unlock_function)(CURL *handle, + curl_lock_data data, + void *userptr); + + +typedef enum { + CURLSHE_OK, /* all is fine */ + CURLSHE_BAD_OPTION, /* 1 */ + CURLSHE_IN_USE, /* 2 */ + CURLSHE_INVALID, /* 3 */ + CURLSHE_NOMEM, /* 4 out of memory */ + CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */ + CURLSHE_LAST /* never use */ +} CURLSHcode; + +typedef enum { + CURLSHOPT_NONE, /* don't use */ + CURLSHOPT_SHARE, /* specify a data type to share */ + CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ + CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ + CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ + CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock + callback functions */ + CURLSHOPT_LAST /* never use */ +} CURLSHoption; + +CURL_EXTERN CURLSH *curl_share_init(void); +CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...); +CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *); + +/**************************************************************************** + * Structures for querying information about the curl library at runtime. + */ + +typedef enum { + CURLVERSION_FIRST, + CURLVERSION_SECOND, + CURLVERSION_THIRD, + CURLVERSION_FOURTH, + CURLVERSION_FIFTH, + CURLVERSION_SIXTH, + CURLVERSION_SEVENTH, + CURLVERSION_EIGHTH, + CURLVERSION_NINTH, + CURLVERSION_TENTH, + CURLVERSION_LAST /* never actually use this */ +} CURLversion; + +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basically all programs ever that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redefine the NOW to another enum + from above. */ +#define CURLVERSION_NOW CURLVERSION_TENTH + +struct curl_version_info_data { + CURLversion age; /* age of the returned struct */ + const char *version; /* LIBCURL_VERSION */ + unsigned int version_num; /* LIBCURL_VERSION_NUM */ + const char *host; /* OS/host/cpu/machine when configured */ + int features; /* bitmask, see defines below */ + const char *ssl_version; /* human readable string */ + long ssl_version_num; /* not used anymore, always 0 */ + const char *libz_version; /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + const char * const *protocols; + + /* The fields below this were added in CURLVERSION_SECOND */ + const char *ares; + int ares_num; + + /* This field was added in CURLVERSION_THIRD */ + const char *libidn; + + /* These field were added in CURLVERSION_FOURTH */ + + /* Same as '_libiconv_version' if built with HAVE_ICONV */ + int iconv_ver_num; + + const char *libssh_version; /* human readable string */ + + /* These fields were added in CURLVERSION_FIFTH */ + unsigned int brotli_ver_num; /* Numeric Brotli version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *brotli_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_SIXTH */ + unsigned int nghttp2_ver_num; /* Numeric nghttp2 version + (MAJOR << 16) | (MINOR << 8) | PATCH */ + const char *nghttp2_version; /* human readable string. */ + const char *quic_version; /* human readable quic (+ HTTP/3) library + + version or NULL */ + + /* These fields were added in CURLVERSION_SEVENTH */ + const char *cainfo; /* the built-in default CURLOPT_CAINFO, might + be NULL */ + const char *capath; /* the built-in default CURLOPT_CAPATH, might + be NULL */ + + /* These fields were added in CURLVERSION_EIGHTH */ + unsigned int zstd_ver_num; /* Numeric Zstd version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *zstd_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_NINTH */ + const char *hyper_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_TENTH */ + const char *gsasl_version; /* human readable string. */ +}; +typedef struct curl_version_info_data curl_version_info_data; + +#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ +#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported + (deprecated) */ +#define CURL_VERSION_SSL (1<<2) /* SSL options are present */ +#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */ +#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */ +#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported + (deprecated) */ +#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */ +#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */ +#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */ +#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */ +#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are + supported */ +#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */ +#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */ +#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */ +#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ +#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper + is supported */ +#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */ +#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */ +#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */ +#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */ +#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used + for cookie domain verification */ +#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */ +#define CURL_VERSION_MULTI_SSL (1<<22) /* Multiple SSL backends available */ +#define CURL_VERSION_BROTLI (1<<23) /* Brotli features are present. */ +#define CURL_VERSION_ALTSVC (1<<24) /* Alt-Svc handling built-in */ +#define CURL_VERSION_HTTP3 (1<<25) /* HTTP3 support built-in */ +#define CURL_VERSION_ZSTD (1<<26) /* zstd features are present */ +#define CURL_VERSION_UNICODE (1<<27) /* Unicode support on Windows */ +#define CURL_VERSION_HSTS (1<<28) /* HSTS is supported */ +#define CURL_VERSION_GSASL (1<<29) /* libgsasl is supported */ + + /* + * NAME curl_version_info() + * + * DESCRIPTION + * + * This function returns a pointer to a static copy of the version info + * struct. See above. + */ +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion); + +/* + * NAME curl_easy_strerror() + * + * DESCRIPTION + * + * The curl_easy_strerror function may be used to turn a CURLcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_easy_strerror(CURLcode); + +/* + * NAME curl_share_strerror() + * + * DESCRIPTION + * + * The curl_share_strerror function may be used to turn a CURLSHcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_share_strerror(CURLSHcode); + +/* + * NAME curl_easy_pause() + * + * DESCRIPTION + * + * The curl_easy_pause function pauses or unpauses transfers. Select the new + * state by setting the bitmask, use the convenience defines below. + * + */ +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); + +#define CURLPAUSE_RECV (1<<0) +#define CURLPAUSE_RECV_CONT (0) + +#define CURLPAUSE_SEND (1<<2) +#define CURLPAUSE_SEND_CONT (0) + +#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) +#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) + +#ifdef __cplusplus +} +#endif + +/* unfortunately, the easy.h and multi.h include files need options and info + stuff before they can be included! */ +#include "easy.h" /* nothing in curl is fun without the easy stuff */ +#include "multi.h" +#include "urlapi.h" +#include "options.h" + +/* the typechecker doesn't work in C++ (yet) */ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ + ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \ + !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK) +#include "typecheck-gcc.h" +#else +#if defined(__STDC__) && (__STDC__ >= 1) +/* This preprocessor magic that replaces a call with the exact same call is + only done to make sure application authors pass exactly three arguments + to these functions. */ +#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) +#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) +#endif /* __STDC__ >= 1 */ +#endif /* gcc >= 4.3 && !__cplusplus */ + +#endif /* CURLINC_CURL_H */ diff --git a/src/drivers/win/curl/x64/include/curl/curlver.h b/src/drivers/win/curl/x64/include/curl/curlver.h new file mode 100644 index 000000000..43ab83248 --- /dev/null +++ b/src/drivers/win/curl/x64/include/curl/curlver.h @@ -0,0 +1,77 @@ +#ifndef CURLINC_CURLVER_H +#define CURLINC_CURLVER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This header file contains nothing but libcurl version info, generated by + a script at release-time. This was made its own header file in 7.11.2 */ + +/* This is the global package copyright */ +#define LIBCURL_COPYRIGHT "1996 - 2021 Daniel Stenberg, ." + +/* This is the version number of the libcurl package from which this header + file origins: */ +#define LIBCURL_VERSION "7.79.0" + +/* The numeric version number is also available "in parts" by using these + defines: */ +#define LIBCURL_VERSION_MAJOR 7 +#define LIBCURL_VERSION_MINOR 79 +#define LIBCURL_VERSION_PATCH 0 + +/* This is the numeric version of the libcurl version number, meant for easier + parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will + always follow this syntax: + + 0xXXYYZZ + + Where XX, YY and ZZ are the main version, release and patch numbers in + hexadecimal (using 8 bits each). All three numbers are always represented + using two digits. 1.2 would appear as "0x010200" while version 9.11.7 + appears as "0x090b07". + + This 6-digit (24 bits) hexadecimal number does not show pre-release number, + and it is always a greater number in a more recent release. It makes + comparisons with greater than and less than work. + + Note: This define is the full hex number and _does not_ use the + CURL_VERSION_BITS() macro since curl's own configure script greps for it + and needs it to contain the full number. +*/ +#define LIBCURL_VERSION_NUM 0x074f00 + +/* + * This is the date and time when the full source package was created. The + * timestamp is not stored in git, as the timestamp is properly set in the + * tarballs by the maketgz script. + * + * The format of the date follows this template: + * + * "2007-11-23" + */ +#define LIBCURL_TIMESTAMP "2021-09-15" + +#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z)) +#define CURL_AT_LEAST_VERSION(x,y,z) \ + (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) + +#endif /* CURLINC_CURLVER_H */ diff --git a/src/drivers/win/curl/x64/include/curl/easy.h b/src/drivers/win/curl/x64/include/curl/easy.h new file mode 100644 index 000000000..2dbfb26b5 --- /dev/null +++ b/src/drivers/win/curl/x64/include/curl/easy.h @@ -0,0 +1,123 @@ +#ifndef CURLINC_EASY_H +#define CURLINC_EASY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +/* Flag bits in the curl_blob struct: */ +#define CURL_BLOB_COPY 1 /* tell libcurl to copy the data */ +#define CURL_BLOB_NOCOPY 0 /* tell libcurl to NOT copy the data */ + +struct curl_blob { + void *data; + size_t len; + unsigned int flags; /* bit 0 is defined, the rest are reserved and should be + left zeroes */ +}; + +CURL_EXTERN CURL *curl_easy_init(void); +CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); +CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); +CURL_EXTERN void curl_easy_cleanup(CURL *curl); + +/* + * NAME curl_easy_getinfo() + * + * DESCRIPTION + * + * Request internal information from the curl session with this function. The + * third argument MUST be a pointer to a long, a pointer to a char * or a + * pointer to a double (as the documentation describes elsewhere). The data + * pointed to will be filled in accordingly and can be relied upon only if the + * function returns CURLE_OK. This function is intended to get used *AFTER* a + * performed transfer, all results from this function are undefined until the + * transfer is completed. + */ +CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); + + +/* + * NAME curl_easy_duphandle() + * + * DESCRIPTION + * + * Creates a new curl session handle with the same options set for the handle + * passed in. Duplicating a handle could only be a matter of cloning data and + * options, internal state info and things like persistent connections cannot + * be transferred. It is useful in multithreaded applications when you can run + * curl_easy_duphandle() for each new thread to avoid a series of identical + * curl_easy_setopt() invokes in every thread. + */ +CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl); + +/* + * NAME curl_easy_reset() + * + * DESCRIPTION + * + * Re-initializes a CURL handle to the default values. This puts back the + * handle to the same state as it was in when it was just created. + * + * It does keep: live connections, the Session ID cache, the DNS cache and the + * cookies. + */ +CURL_EXTERN void curl_easy_reset(CURL *curl); + +/* + * NAME curl_easy_recv() + * + * DESCRIPTION + * + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, + size_t *n); + +/* + * NAME curl_easy_send() + * + * DESCRIPTION + * + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, + size_t buflen, size_t *n); + + +/* + * NAME curl_easy_upkeep() + * + * DESCRIPTION + * + * Performs connection upkeep for the given session handle. + */ +CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/drivers/win/curl/x64/include/curl/mprintf.h b/src/drivers/win/curl/x64/include/curl/mprintf.h new file mode 100644 index 000000000..3549552db --- /dev/null +++ b/src/drivers/win/curl/x64/include/curl/mprintf.h @@ -0,0 +1,50 @@ +#ifndef CURLINC_MPRINTF_H +#define CURLINC_MPRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include +#include /* needed for FILE */ +#include "curl.h" /* for CURL_EXTERN */ + +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN int curl_mprintf(const char *format, ...); +CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...); +CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...); +CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, + const char *format, ...); +CURL_EXTERN int curl_mvprintf(const char *format, va_list args); +CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args); +CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args); +CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, + const char *format, va_list args); +CURL_EXTERN char *curl_maprintf(const char *format, ...); +CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args); + +#ifdef __cplusplus +} +#endif + +#endif /* CURLINC_MPRINTF_H */ diff --git a/src/drivers/win/curl/x64/include/curl/multi.h b/src/drivers/win/curl/x64/include/curl/multi.h new file mode 100644 index 000000000..37f9829b3 --- /dev/null +++ b/src/drivers/win/curl/x64/include/curl/multi.h @@ -0,0 +1,456 @@ +#ifndef CURLINC_MULTI_H +#define CURLINC_MULTI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + This is an "external" header file. Don't give away any internals here! + + GOALS + + o Enable a "pull" interface. The application that uses libcurl decides where + and when to ask libcurl to get/send data. + + o Enable multiple simultaneous transfers in the same thread without making it + complicated for the application. + + o Enable the application to select() on its own file descriptors and curl's + file descriptors simultaneous easily. + +*/ + +/* + * This header file should not really need to include "curl.h" since curl.h + * itself includes this file and we expect user applications to do #include + * without the need for especially including multi.h. + * + * For some reason we added this include here at one point, and rather than to + * break existing (wrongly written) libcurl applications, we leave it as-is + * but with this warning attached. + */ +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_multi CURLM; +#else +typedef void CURLM; +#endif + +typedef enum { + CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or + curl_multi_socket*() soon */ + CURLM_OK, + CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ + CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ + CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */ + CURLM_INTERNAL_ERROR, /* this is a libcurl bug */ + CURLM_BAD_SOCKET, /* the passed in socket argument did not match */ + CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */ + CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was + attempted to get added - again */ + CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a + callback */ + CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */ + CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */ + CURLM_LAST +} CURLMcode; + +/* just to make code nicer when using curl_multi_socket() you can now check + for CURLM_CALL_MULTI_SOCKET too in the same style it works for + curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */ +#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM + +/* bitmask bits for CURLMOPT_PIPELINING */ +#define CURLPIPE_NOTHING 0L +#define CURLPIPE_HTTP1 1L +#define CURLPIPE_MULTIPLEX 2L + +typedef enum { + CURLMSG_NONE, /* first, not used */ + CURLMSG_DONE, /* This easy handle has completed. 'result' contains + the CURLcode of the transfer */ + CURLMSG_LAST /* last, not used */ +} CURLMSG; + +struct CURLMsg { + CURLMSG msg; /* what this message means */ + CURL *easy_handle; /* the handle it concerns */ + union { + void *whatever; /* message-specific data */ + CURLcode result; /* return code for transfer */ + } data; +}; +typedef struct CURLMsg CURLMsg; + +/* Based on poll(2) structure and values. + * We don't use pollfd and POLL* constants explicitly + * to cover platforms without poll(). */ +#define CURL_WAIT_POLLIN 0x0001 +#define CURL_WAIT_POLLPRI 0x0002 +#define CURL_WAIT_POLLOUT 0x0004 + +struct curl_waitfd { + curl_socket_t fd; + short events; + short revents; /* not supported yet */ +}; + +/* + * Name: curl_multi_init() + * + * Desc: inititalize multi-style curl usage + * + * Returns: a new CURLM handle to use in all 'curl_multi' functions. + */ +CURL_EXTERN CURLM *curl_multi_init(void); + +/* + * Name: curl_multi_add_handle() + * + * Desc: add a standard curl handle to the multi stack + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_remove_handle() + * + * Desc: removes a curl handle from the multi stack again + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_fdset() + * + * Desc: Ask curl for its fd_set sets. The app can use these to select() or + * poll() on. We want curl_multi_perform() called as soon as one of + * them are ready. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, + fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *exc_fd_set, + int *max_fd); + +/* + * Name: curl_multi_wait() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + +/* + * Name: curl_multi_poll() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_poll(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + +/* + * Name: curl_multi_wakeup() + * + * Desc: wakes up a sleeping curl_multi_poll call. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle); + + /* + * Name: curl_multi_perform() + * + * Desc: When the app thinks there's data available for curl it calls this + * function to read/write whatever there is right now. This returns + * as soon as the reads and writes are done. This function does not + * require that there actually is data available for reading or that + * data can be written, it can be called just in case. It returns + * the number of handles that still transfer data in the second + * argument's integer-pointer. + * + * Returns: CURLMcode type, general multi error code. *NOTE* that this only + * returns errors etc regarding the whole multi stack. There might + * still have occurred problems on individual transfers even when + * this returns OK. + */ +CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, + int *running_handles); + + /* + * Name: curl_multi_cleanup() + * + * Desc: Cleans up and removes a whole multi stack. It does not free or + * touch any individual easy handles in any way. We need to define + * in what state those handles will be if this function is called + * in the middle of a transfer. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle); + +/* + * Name: curl_multi_info_read() + * + * Desc: Ask the multi handle if there's any messages/informationals from + * the individual transfers. Messages include informationals such as + * error code from the transfer or just the fact that a transfer is + * completed. More details on these should be written down as well. + * + * Repeated calls to this function will return a new struct each + * time, until a special "end of msgs" struct is returned as a signal + * that there is no more to get at this point. + * + * The data the returned pointer points to will not survive calling + * curl_multi_cleanup(). + * + * The 'CURLMsg' struct is meant to be very simple and only contain + * very basic information. If more involved information is wanted, + * we will provide the particular "transfer handle" in that struct + * and that should/could/would be used in subsequent + * curl_easy_getinfo() calls (or similar). The point being that we + * must never expose complex structs to applications, as then we'll + * undoubtably get backwards compatibility problems in the future. + * + * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out + * of structs. It also writes the number of messages left in the + * queue (after this read) in the integer the second argument points + * to. + */ +CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle, + int *msgs_in_queue); + +/* + * Name: curl_multi_strerror() + * + * Desc: The curl_multi_strerror function may be used to turn a CURLMcode + * value into the equivalent human readable error string. This is + * useful for printing meaningful error messages. + * + * Returns: A pointer to a null-terminated error message. + */ +CURL_EXTERN const char *curl_multi_strerror(CURLMcode); + +/* + * Name: curl_multi_socket() and + * curl_multi_socket_all() + * + * Desc: An alternative version of curl_multi_perform() that allows the + * application to pass in one of the file descriptors that have been + * detected to have "action" on them and let libcurl perform. + * See man page for details. + */ +#define CURL_POLL_NONE 0 +#define CURL_POLL_IN 1 +#define CURL_POLL_OUT 2 +#define CURL_POLL_INOUT 3 +#define CURL_POLL_REMOVE 4 + +#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD + +#define CURL_CSELECT_IN 0x01 +#define CURL_CSELECT_OUT 0x02 +#define CURL_CSELECT_ERR 0x04 + +typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */ + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp); /* private socket + pointer */ +/* + * Name: curl_multi_timer_callback + * + * Desc: Called by libcurl whenever the library detects a change in the + * maximum number of milliseconds the app is allowed to wait before + * curl_multi_socket() or curl_multi_perform() must be called + * (to allow libcurl's timed events to take place). + * + * Returns: The callback should return zero. + */ +typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */ + long timeout_ms, /* see above */ + void *userp); /* private callback + pointer */ + +CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle, + curl_socket_t s, + int ev_bitmask, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle, + int *running_handles); + +#ifndef CURL_ALLOW_OLD_MULTI_SOCKET +/* This macro below was added in 7.16.3 to push users who recompile to use + the new curl_multi_socket_action() instead of the old curl_multi_socket() +*/ +#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z) +#endif + +/* + * Name: curl_multi_timeout() + * + * Desc: Returns the maximum number of milliseconds the app is allowed to + * wait before curl_multi_socket() or curl_multi_perform() must be + * called (to allow libcurl's timed events to take place). + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle, + long *milliseconds); + +typedef enum { + /* This is the socket callback function pointer */ + CURLOPT(CURLMOPT_SOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 1), + + /* This is the argument passed to the socket callback */ + CURLOPT(CURLMOPT_SOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 2), + + /* set to 1 to enable pipelining for this multi handle */ + CURLOPT(CURLMOPT_PIPELINING, CURLOPTTYPE_LONG, 3), + + /* This is the timer callback function pointer */ + CURLOPT(CURLMOPT_TIMERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 4), + + /* This is the argument passed to the timer callback */ + CURLOPT(CURLMOPT_TIMERDATA, CURLOPTTYPE_OBJECTPOINT, 5), + + /* maximum number of entries in the connection cache */ + CURLOPT(CURLMOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 6), + + /* maximum number of (pipelining) connections to one host */ + CURLOPT(CURLMOPT_MAX_HOST_CONNECTIONS, CURLOPTTYPE_LONG, 7), + + /* maximum number of requests in a pipeline */ + CURLOPT(CURLMOPT_MAX_PIPELINE_LENGTH, CURLOPTTYPE_LONG, 8), + + /* a connection with a content-length longer than this + will not be considered for pipelining */ + CURLOPT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 9), + + /* a connection with a chunk length longer than this + will not be considered for pipelining */ + CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10), + + /* a list of site names(+port) that are blocked from pipelining */ + CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11), + + /* a list of server types that are blocked from pipelining */ + CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12), + + /* maximum number of open connections in total */ + CURLOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, CURLOPTTYPE_LONG, 13), + + /* This is the server push callback function pointer */ + CURLOPT(CURLMOPT_PUSHFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 14), + + /* This is the argument passed to the server push callback */ + CURLOPT(CURLMOPT_PUSHDATA, CURLOPTTYPE_OBJECTPOINT, 15), + + /* maximum number of concurrent streams to support on a connection */ + CURLOPT(CURLMOPT_MAX_CONCURRENT_STREAMS, CURLOPTTYPE_LONG, 16), + + CURLMOPT_LASTENTRY /* the last unused */ +} CURLMoption; + + +/* + * Name: curl_multi_setopt() + * + * Desc: Sets options for the multi handle. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, + CURLMoption option, ...); + + +/* + * Name: curl_multi_assign() + * + * Desc: This function sets an association in the multi handle between the + * given socket and a private pointer of the application. This is + * (only) useful for curl_multi_socket uses. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, + curl_socket_t sockfd, void *sockp); + + +/* + * Name: curl_push_callback + * + * Desc: This callback gets called when a new stream is being pushed by the + * server. It approves or denies the new stream. It can also decide + * to completely fail the connection. + * + * Returns: CURL_PUSH_OK, CURL_PUSH_DENY or CURL_PUSH_ERROROUT + */ +#define CURL_PUSH_OK 0 +#define CURL_PUSH_DENY 1 +#define CURL_PUSH_ERROROUT 2 /* added in 7.72.0 */ + +struct curl_pushheaders; /* forward declaration only */ + +CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h, + size_t num); +CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h, + const char *name); + +typedef int (*curl_push_callback)(CURL *parent, + CURL *easy, + size_t num_headers, + struct curl_pushheaders *headers, + void *userp); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/src/drivers/win/curl/x64/include/curl/options.h b/src/drivers/win/curl/x64/include/curl/options.h new file mode 100644 index 000000000..14373b551 --- /dev/null +++ b/src/drivers/win/curl/x64/include/curl/options.h @@ -0,0 +1,68 @@ +#ifndef CURLINC_OPTIONS_H +#define CURLINC_OPTIONS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + CURLOT_LONG, /* long (a range of values) */ + CURLOT_VALUES, /* (a defined set or bitmask) */ + CURLOT_OFF_T, /* curl_off_t (a range of values) */ + CURLOT_OBJECT, /* pointer (void *) */ + CURLOT_STRING, /* (char * to zero terminated buffer) */ + CURLOT_SLIST, /* (struct curl_slist *) */ + CURLOT_CBPTR, /* (void * passed as-is to a callback) */ + CURLOT_BLOB, /* blob (struct curl_blob *) */ + CURLOT_FUNCTION /* function pointer */ +} curl_easytype; + +/* Flag bits */ + +/* "alias" means it is provided for old programs to remain functional, + we prefer another name */ +#define CURLOT_FLAG_ALIAS (1<<0) + +/* The CURLOPTTYPE_* id ranges can still be used to figure out what type/size + to use for curl_easy_setopt() for the given id */ +struct curl_easyoption { + const char *name; + CURLoption id; + curl_easytype type; + unsigned int flags; +}; + +CURL_EXTERN const struct curl_easyoption * +curl_easy_option_by_name(const char *name); + +CURL_EXTERN const struct curl_easyoption * +curl_easy_option_by_id (CURLoption id); + +CURL_EXTERN const struct curl_easyoption * +curl_easy_option_next(const struct curl_easyoption *prev); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif +#endif /* CURLINC_OPTIONS_H */ diff --git a/src/drivers/win/curl/x64/include/curl/stdcheaders.h b/src/drivers/win/curl/x64/include/curl/stdcheaders.h new file mode 100644 index 000000000..60596c756 --- /dev/null +++ b/src/drivers/win/curl/x64/include/curl/stdcheaders.h @@ -0,0 +1,33 @@ +#ifndef CURLINC_STDCHEADERS_H +#define CURLINC_STDCHEADERS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +size_t fread(void *, size_t, size_t, FILE *); +size_t fwrite(const void *, size_t, size_t, FILE *); + +int strcasecmp(const char *, const char *); +int strncasecmp(const char *, const char *, size_t); + +#endif /* CURLINC_STDCHEADERS_H */ diff --git a/src/drivers/win/curl/x64/include/curl/system.h b/src/drivers/win/curl/x64/include/curl/system.h new file mode 100644 index 000000000..faf8fcf84 --- /dev/null +++ b/src/drivers/win/curl/x64/include/curl/system.h @@ -0,0 +1,504 @@ +#ifndef CURLINC_SYSTEM_H +#define CURLINC_SYSTEM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Try to keep one section per platform, compiler and architecture, otherwise, + * if an existing section is reused for a different one and later on the + * original is adjusted, probably the piggybacking one can be adversely + * changed. + * + * In order to differentiate between platforms/compilers/architectures use + * only compiler built in predefined preprocessor symbols. + * + * curl_off_t + * ---------- + * + * For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit + * wide signed integral data type. The width of this data type must remain + * constant and independent of any possible large file support settings. + * + * As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit + * wide signed integral data type if there is no 64-bit type. + * + * As a general rule, curl_off_t shall not be mapped to off_t. This rule shall + * only be violated if off_t is the only 64-bit data type available and the + * size of off_t is independent of large file support settings. Keep your + * build on the safe side avoiding an off_t gating. If you have a 64-bit + * off_t then take for sure that another 64-bit data type exists, dig deeper + * and you will find it. + * + */ + +#if defined(__DJGPP__) || defined(__GO32__) +# if defined(__DJGPP__) && (__DJGPP__ > 1) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__SALFORDC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__BORLANDC__) +# if (__BORLANDC__ < 0x520) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TURBOC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__WATCOMC__) +# if defined(__386__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__POCC__) +# if (__POCC__ < 280) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# elif defined(_MSC_VER) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__LCC__) +# if defined(__e2k__) /* MCST eLbrus C Compiler */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# else /* Local (or Little) C Compiler */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# endif + +#elif defined(__SYMBIAN32__) +# if defined(__EABI__) /* Treat all ARM compilers equally */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__CW32__) +# pragma longlong on +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__VC32__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__MWERKS__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(_WIN32_WCE) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__MINGW32__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_WS2TCPIP_H 1 + +#elif defined(__VMS) +# if defined(__VAX) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__OS400__) +# if defined(__ILEC400__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__MVS__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# elif defined(_LP64) +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__370__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# elif defined(_LP64) +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(TPF) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TINYC__) /* also known as tcc */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */ +# if !defined(__LP64) && (defined(__ILP32) || \ + defined(__i386) || \ + defined(__sparcv8) || \ + defined(__sparcv8plus)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64) || \ + defined(__amd64) || defined(__sparcv9) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__xlc__) /* IBM xlc compiler */ +# if !defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +/* ===================================== */ +/* KEEP MSVC THE PENULTIMATE ENTRY */ +/* ===================================== */ + +#elif defined(_MSC_VER) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +/* ===================================== */ +/* KEEP GENERIC GCC THE LAST ENTRY */ +/* ===================================== */ + +#elif defined(__GNUC__) && !defined(_SCO_DS) +# if !defined(__LP64__) && \ + (defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \ + defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \ + defined(__sparc__) || defined(__mips__) || defined(__sh__) || \ + defined(__XTENSA__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64__) || \ + defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \ + defined(__e2k__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#else +/* generic "safe guess" on old 32 bit style */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +#endif + +#ifdef _AIX +/* AIX needs */ +#define CURL_PULL_SYS_POLL_H +#endif + + +/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file */ +/* ws2tcpip.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_WS2TCPIP_H +# include +# include +# include +#endif + +/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */ +/* sys/types.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_TYPES_H +# include +#endif + +/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */ +/* sys/socket.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_SOCKET_H +# include +#endif + +/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */ +/* sys/poll.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_POLL_H +# include +#endif + +/* Data type definition of curl_socklen_t. */ +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T + typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; +#endif + +/* Data type definition of curl_off_t. */ + +#ifdef CURL_TYPEOF_CURL_OFF_T + typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; +#endif + +/* + * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow + * these to be visible and exported by the external libcurl interface API, + * while also making them visible to the library internals, simply including + * curl_setup.h, without actually needing to include curl.h internally. + * If some day this section would grow big enough, all this should be moved + * to its own header file. + */ + +/* + * Figure out if we can use the ## preprocessor operator, which is supported + * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__ + * or __cplusplus so we need to carefully check for them too. + */ + +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ + defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \ + defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \ + defined(__ILEC400__) + /* This compiler is believed to have an ISO compatible preprocessor */ +#define CURL_ISOCPP +#else + /* This compiler is believed NOT to have an ISO compatible preprocessor */ +#undef CURL_ISOCPP +#endif + +/* + * Macros for minimum-width signed and unsigned curl_off_t integer constants. + */ + +#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551) +# define CURLINC_OFF_T_C_HLPR2(x) x +# define CURLINC_OFF_T_C_HLPR1(x) CURLINC_OFF_T_C_HLPR2(x) +# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \ + CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \ + CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU) +#else +# ifdef CURL_ISOCPP +# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix +# else +# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix +# endif +# define CURLINC_OFF_T_C_HLPR1(Val,Suffix) CURLINC_OFF_T_C_HLPR2(Val,Suffix) +# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU) +#endif + +#endif /* CURLINC_SYSTEM_H */ diff --git a/src/drivers/win/curl/x64/include/curl/typecheck-gcc.h b/src/drivers/win/curl/x64/include/curl/typecheck-gcc.h new file mode 100644 index 000000000..34d0267ed --- /dev/null +++ b/src/drivers/win/curl/x64/include/curl/typecheck-gcc.h @@ -0,0 +1,705 @@ +#ifndef CURLINC_TYPECHECK_GCC_H +#define CURLINC_TYPECHECK_GCC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* wraps curl_easy_setopt() with typechecking */ + +/* To add a new kind of warning, add an + * if(curlcheck_sometype_option(_curl_opt)) + * if(!curlcheck_sometype(value)) + * _curl_easy_setopt_err_sometype(); + * block and define curlcheck_sometype_option, curlcheck_sometype and + * _curl_easy_setopt_err_sometype below + * + * NOTE: We use two nested 'if' statements here instead of the && operator, in + * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x + * when compiling with -Wlogical-op. + * + * To add an option that uses the same type as an existing option, you'll just + * need to extend the appropriate _curl_*_option macro + */ +#define curl_easy_setopt(handle, option, value) \ + __extension__({ \ + __typeof__(option) _curl_opt = option; \ + if(__builtin_constant_p(_curl_opt)) { \ + if(curlcheck_long_option(_curl_opt)) \ + if(!curlcheck_long(value)) \ + _curl_easy_setopt_err_long(); \ + if(curlcheck_off_t_option(_curl_opt)) \ + if(!curlcheck_off_t(value)) \ + _curl_easy_setopt_err_curl_off_t(); \ + if(curlcheck_string_option(_curl_opt)) \ + if(!curlcheck_string(value)) \ + _curl_easy_setopt_err_string(); \ + if(curlcheck_write_cb_option(_curl_opt)) \ + if(!curlcheck_write_cb(value)) \ + _curl_easy_setopt_err_write_callback(); \ + if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \ + if(!curlcheck_resolver_start_callback(value)) \ + _curl_easy_setopt_err_resolver_start_callback(); \ + if((_curl_opt) == CURLOPT_READFUNCTION) \ + if(!curlcheck_read_cb(value)) \ + _curl_easy_setopt_err_read_cb(); \ + if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \ + if(!curlcheck_ioctl_cb(value)) \ + _curl_easy_setopt_err_ioctl_cb(); \ + if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \ + if(!curlcheck_sockopt_cb(value)) \ + _curl_easy_setopt_err_sockopt_cb(); \ + if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \ + if(!curlcheck_opensocket_cb(value)) \ + _curl_easy_setopt_err_opensocket_cb(); \ + if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \ + if(!curlcheck_progress_cb(value)) \ + _curl_easy_setopt_err_progress_cb(); \ + if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \ + if(!curlcheck_debug_cb(value)) \ + _curl_easy_setopt_err_debug_cb(); \ + if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \ + if(!curlcheck_ssl_ctx_cb(value)) \ + _curl_easy_setopt_err_ssl_ctx_cb(); \ + if(curlcheck_conv_cb_option(_curl_opt)) \ + if(!curlcheck_conv_cb(value)) \ + _curl_easy_setopt_err_conv_cb(); \ + if((_curl_opt) == CURLOPT_SEEKFUNCTION) \ + if(!curlcheck_seek_cb(value)) \ + _curl_easy_setopt_err_seek_cb(); \ + if(curlcheck_cb_data_option(_curl_opt)) \ + if(!curlcheck_cb_data(value)) \ + _curl_easy_setopt_err_cb_data(); \ + if((_curl_opt) == CURLOPT_ERRORBUFFER) \ + if(!curlcheck_error_buffer(value)) \ + _curl_easy_setopt_err_error_buffer(); \ + if((_curl_opt) == CURLOPT_STDERR) \ + if(!curlcheck_FILE(value)) \ + _curl_easy_setopt_err_FILE(); \ + if(curlcheck_postfields_option(_curl_opt)) \ + if(!curlcheck_postfields(value)) \ + _curl_easy_setopt_err_postfields(); \ + if((_curl_opt) == CURLOPT_HTTPPOST) \ + if(!curlcheck_arr((value), struct curl_httppost)) \ + _curl_easy_setopt_err_curl_httpost(); \ + if((_curl_opt) == CURLOPT_MIMEPOST) \ + if(!curlcheck_ptr((value), curl_mime)) \ + _curl_easy_setopt_err_curl_mimepost(); \ + if(curlcheck_slist_option(_curl_opt)) \ + if(!curlcheck_arr((value), struct curl_slist)) \ + _curl_easy_setopt_err_curl_slist(); \ + if((_curl_opt) == CURLOPT_SHARE) \ + if(!curlcheck_ptr((value), CURLSH)) \ + _curl_easy_setopt_err_CURLSH(); \ + } \ + curl_easy_setopt(handle, _curl_opt, value); \ + }) + +/* wraps curl_easy_getinfo() with typechecking */ +#define curl_easy_getinfo(handle, info, arg) \ + __extension__({ \ + __typeof__(info) _curl_info = info; \ + if(__builtin_constant_p(_curl_info)) { \ + if(curlcheck_string_info(_curl_info)) \ + if(!curlcheck_arr((arg), char *)) \ + _curl_easy_getinfo_err_string(); \ + if(curlcheck_long_info(_curl_info)) \ + if(!curlcheck_arr((arg), long)) \ + _curl_easy_getinfo_err_long(); \ + if(curlcheck_double_info(_curl_info)) \ + if(!curlcheck_arr((arg), double)) \ + _curl_easy_getinfo_err_double(); \ + if(curlcheck_slist_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_slist *)) \ + _curl_easy_getinfo_err_curl_slist(); \ + if(curlcheck_tlssessioninfo_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \ + _curl_easy_getinfo_err_curl_tlssesssioninfo(); \ + if(curlcheck_certinfo_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_certinfo *)) \ + _curl_easy_getinfo_err_curl_certinfo(); \ + if(curlcheck_socket_info(_curl_info)) \ + if(!curlcheck_arr((arg), curl_socket_t)) \ + _curl_easy_getinfo_err_curl_socket(); \ + if(curlcheck_off_t_info(_curl_info)) \ + if(!curlcheck_arr((arg), curl_off_t)) \ + _curl_easy_getinfo_err_curl_off_t(); \ + } \ + curl_easy_getinfo(handle, _curl_info, arg); \ + }) + +/* + * For now, just make sure that the functions are called with three arguments + */ +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) + + +/* the actual warnings, triggered by calling the _curl_easy_setopt_err* + * functions */ + +/* To define a new warning, use _CURL_WARNING(identifier, "message") */ +#define CURLWARNING(id, message) \ + static void __attribute__((__warning__(message))) \ + __attribute__((__unused__)) __attribute__((__noinline__)) \ + id(void) { __asm__(""); } + +CURLWARNING(_curl_easy_setopt_err_long, + "curl_easy_setopt expects a long argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_off_t, + "curl_easy_setopt expects a curl_off_t argument for this option") +CURLWARNING(_curl_easy_setopt_err_string, + "curl_easy_setopt expects a " + "string ('char *' or char[]) argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_write_callback, + "curl_easy_setopt expects a curl_write_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_resolver_start_callback, + "curl_easy_setopt expects a " + "curl_resolver_start_callback argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_read_cb, + "curl_easy_setopt expects a curl_read_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_ioctl_cb, + "curl_easy_setopt expects a curl_ioctl_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_sockopt_cb, + "curl_easy_setopt expects a curl_sockopt_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_opensocket_cb, + "curl_easy_setopt expects a " + "curl_opensocket_callback argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_progress_cb, + "curl_easy_setopt expects a curl_progress_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_debug_cb, + "curl_easy_setopt expects a curl_debug_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_ssl_ctx_cb, + "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_conv_cb, + "curl_easy_setopt expects a curl_conv_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_seek_cb, + "curl_easy_setopt expects a curl_seek_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_cb_data, + "curl_easy_setopt expects a " + "private data pointer as argument for this option") +CURLWARNING(_curl_easy_setopt_err_error_buffer, + "curl_easy_setopt expects a " + "char buffer of CURL_ERROR_SIZE as argument for this option") +CURLWARNING(_curl_easy_setopt_err_FILE, + "curl_easy_setopt expects a 'FILE *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_postfields, + "curl_easy_setopt expects a 'void *' or 'char *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_httpost, + "curl_easy_setopt expects a 'struct curl_httppost *' " + "argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_mimepost, + "curl_easy_setopt expects a 'curl_mime *' " + "argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_slist, + "curl_easy_setopt expects a 'struct curl_slist *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_CURLSH, + "curl_easy_setopt expects a CURLSH* argument for this option") + +CURLWARNING(_curl_easy_getinfo_err_string, + "curl_easy_getinfo expects a pointer to 'char *' for this info") +CURLWARNING(_curl_easy_getinfo_err_long, + "curl_easy_getinfo expects a pointer to long for this info") +CURLWARNING(_curl_easy_getinfo_err_double, + "curl_easy_getinfo expects a pointer to double for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_slist, + "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_tlssessioninfo *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_certinfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_certinfo *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_socket, + "curl_easy_getinfo expects a pointer to curl_socket_t for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_off_t, + "curl_easy_getinfo expects a pointer to curl_off_t for this info") + +/* groups of curl_easy_setops options that take the same type of argument */ + +/* To add a new option to one of the groups, just add + * (option) == CURLOPT_SOMETHING + * to the or-expression. If the option takes a long or curl_off_t, you don't + * have to do anything + */ + +/* evaluates to true if option takes a long argument */ +#define curlcheck_long_option(option) \ + (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT) + +#define curlcheck_off_t_option(option) \ + (((option) > CURLOPTTYPE_OFF_T) && ((option) < CURLOPTTYPE_BLOB)) + +/* evaluates to true if option takes a char* argument */ +#define curlcheck_string_option(option) \ + ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \ + (option) == CURLOPT_ACCEPT_ENCODING || \ + (option) == CURLOPT_ALTSVC || \ + (option) == CURLOPT_CAINFO || \ + (option) == CURLOPT_CAPATH || \ + (option) == CURLOPT_COOKIE || \ + (option) == CURLOPT_COOKIEFILE || \ + (option) == CURLOPT_COOKIEJAR || \ + (option) == CURLOPT_COOKIELIST || \ + (option) == CURLOPT_CRLFILE || \ + (option) == CURLOPT_CUSTOMREQUEST || \ + (option) == CURLOPT_DEFAULT_PROTOCOL || \ + (option) == CURLOPT_DNS_INTERFACE || \ + (option) == CURLOPT_DNS_LOCAL_IP4 || \ + (option) == CURLOPT_DNS_LOCAL_IP6 || \ + (option) == CURLOPT_DNS_SERVERS || \ + (option) == CURLOPT_DOH_URL || \ + (option) == CURLOPT_EGDSOCKET || \ + (option) == CURLOPT_FTPPORT || \ + (option) == CURLOPT_FTP_ACCOUNT || \ + (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \ + (option) == CURLOPT_HSTS || \ + (option) == CURLOPT_INTERFACE || \ + (option) == CURLOPT_ISSUERCERT || \ + (option) == CURLOPT_KEYPASSWD || \ + (option) == CURLOPT_KRBLEVEL || \ + (option) == CURLOPT_LOGIN_OPTIONS || \ + (option) == CURLOPT_MAIL_AUTH || \ + (option) == CURLOPT_MAIL_FROM || \ + (option) == CURLOPT_NETRC_FILE || \ + (option) == CURLOPT_NOPROXY || \ + (option) == CURLOPT_PASSWORD || \ + (option) == CURLOPT_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PRE_PROXY || \ + (option) == CURLOPT_PROXY || \ + (option) == CURLOPT_PROXYPASSWORD || \ + (option) == CURLOPT_PROXYUSERNAME || \ + (option) == CURLOPT_PROXYUSERPWD || \ + (option) == CURLOPT_PROXY_CAINFO || \ + (option) == CURLOPT_PROXY_CAPATH || \ + (option) == CURLOPT_PROXY_CRLFILE || \ + (option) == CURLOPT_PROXY_ISSUERCERT || \ + (option) == CURLOPT_PROXY_KEYPASSWD || \ + (option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PROXY_SERVICE_NAME || \ + (option) == CURLOPT_PROXY_SSLCERT || \ + (option) == CURLOPT_PROXY_SSLCERTTYPE || \ + (option) == CURLOPT_PROXY_SSLKEY || \ + (option) == CURLOPT_PROXY_SSLKEYTYPE || \ + (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \ + (option) == CURLOPT_PROXY_TLS13_CIPHERS || \ + (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_PROXY_TLSAUTH_TYPE || \ + (option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \ + (option) == CURLOPT_RANDOM_FILE || \ + (option) == CURLOPT_RANGE || \ + (option) == CURLOPT_REFERER || \ + (option) == CURLOPT_REQUEST_TARGET || \ + (option) == CURLOPT_RTSP_SESSION_ID || \ + (option) == CURLOPT_RTSP_STREAM_URI || \ + (option) == CURLOPT_RTSP_TRANSPORT || \ + (option) == CURLOPT_SASL_AUTHZID || \ + (option) == CURLOPT_SERVICE_NAME || \ + (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ + (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \ + (option) == CURLOPT_SSH_KNOWNHOSTS || \ + (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ + (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \ + (option) == CURLOPT_SSLCERT || \ + (option) == CURLOPT_SSLCERTTYPE || \ + (option) == CURLOPT_SSLENGINE || \ + (option) == CURLOPT_SSLKEY || \ + (option) == CURLOPT_SSLKEYTYPE || \ + (option) == CURLOPT_SSL_CIPHER_LIST || \ + (option) == CURLOPT_TLS13_CIPHERS || \ + (option) == CURLOPT_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_TLSAUTH_TYPE || \ + (option) == CURLOPT_TLSAUTH_USERNAME || \ + (option) == CURLOPT_UNIX_SOCKET_PATH || \ + (option) == CURLOPT_URL || \ + (option) == CURLOPT_USERAGENT || \ + (option) == CURLOPT_USERNAME || \ + (option) == CURLOPT_AWS_SIGV4 || \ + (option) == CURLOPT_USERPWD || \ + (option) == CURLOPT_XOAUTH2_BEARER || \ + (option) == CURLOPT_SSL_EC_CURVES || \ + 0) + +/* evaluates to true if option takes a curl_write_callback argument */ +#define curlcheck_write_cb_option(option) \ + ((option) == CURLOPT_HEADERFUNCTION || \ + (option) == CURLOPT_WRITEFUNCTION) + +/* evaluates to true if option takes a curl_conv_callback argument */ +#define curlcheck_conv_cb_option(option) \ + ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION) + +/* evaluates to true if option takes a data argument to pass to a callback */ +#define curlcheck_cb_data_option(option) \ + ((option) == CURLOPT_CHUNK_DATA || \ + (option) == CURLOPT_CLOSESOCKETDATA || \ + (option) == CURLOPT_DEBUGDATA || \ + (option) == CURLOPT_FNMATCH_DATA || \ + (option) == CURLOPT_HEADERDATA || \ + (option) == CURLOPT_HSTSREADDATA || \ + (option) == CURLOPT_HSTSWRITEDATA || \ + (option) == CURLOPT_INTERLEAVEDATA || \ + (option) == CURLOPT_IOCTLDATA || \ + (option) == CURLOPT_OPENSOCKETDATA || \ + (option) == CURLOPT_PROGRESSDATA || \ + (option) == CURLOPT_READDATA || \ + (option) == CURLOPT_SEEKDATA || \ + (option) == CURLOPT_SOCKOPTDATA || \ + (option) == CURLOPT_SSH_KEYDATA || \ + (option) == CURLOPT_SSL_CTX_DATA || \ + (option) == CURLOPT_WRITEDATA || \ + (option) == CURLOPT_RESOLVER_START_DATA || \ + (option) == CURLOPT_TRAILERDATA || \ + 0) + +/* evaluates to true if option takes a POST data argument (void* or char*) */ +#define curlcheck_postfields_option(option) \ + ((option) == CURLOPT_POSTFIELDS || \ + (option) == CURLOPT_COPYPOSTFIELDS || \ + 0) + +/* evaluates to true if option takes a struct curl_slist * argument */ +#define curlcheck_slist_option(option) \ + ((option) == CURLOPT_HTTP200ALIASES || \ + (option) == CURLOPT_HTTPHEADER || \ + (option) == CURLOPT_MAIL_RCPT || \ + (option) == CURLOPT_POSTQUOTE || \ + (option) == CURLOPT_PREQUOTE || \ + (option) == CURLOPT_PROXYHEADER || \ + (option) == CURLOPT_QUOTE || \ + (option) == CURLOPT_RESOLVE || \ + (option) == CURLOPT_TELNETOPTIONS || \ + (option) == CURLOPT_CONNECT_TO || \ + 0) + +/* groups of curl_easy_getinfo infos that take the same type of argument */ + +/* evaluates to true if info expects a pointer to char * argument */ +#define curlcheck_string_info(info) \ + (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG && \ + (info) != CURLINFO_PRIVATE) + +/* evaluates to true if info expects a pointer to long argument */ +#define curlcheck_long_info(info) \ + (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE) + +/* evaluates to true if info expects a pointer to double argument */ +#define curlcheck_double_info(info) \ + (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST) + +/* true if info expects a pointer to struct curl_slist * argument */ +#define curlcheck_slist_info(info) \ + (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST)) + +/* true if info expects a pointer to struct curl_tlssessioninfo * argument */ +#define curlcheck_tlssessioninfo_info(info) \ + (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION)) + +/* true if info expects a pointer to struct curl_certinfo * argument */ +#define curlcheck_certinfo_info(info) ((info) == CURLINFO_CERTINFO) + +/* true if info expects a pointer to struct curl_socket_t argument */ +#define curlcheck_socket_info(info) \ + (CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T) + +/* true if info expects a pointer to curl_off_t argument */ +#define curlcheck_off_t_info(info) \ + (CURLINFO_OFF_T < (info)) + + +/* typecheck helpers -- check whether given expression has requested type*/ + +/* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros, + * otherwise define a new macro. Search for __builtin_types_compatible_p + * in the GCC manual. + * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is + * the actual expression passed to the curl_easy_setopt macro. This + * means that you can only apply the sizeof and __typeof__ operators, no + * == or whatsoever. + */ + +/* XXX: should evaluate to true if expr is a pointer */ +#define curlcheck_any_ptr(expr) \ + (sizeof(expr) == sizeof(void *)) + +/* evaluates to true if expr is NULL */ +/* XXX: must not evaluate expr, so this check is not accurate */ +#define curlcheck_NULL(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL))) + +/* evaluates to true if expr is type*, const type* or NULL */ +#define curlcheck_ptr(expr, type) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), type *) || \ + __builtin_types_compatible_p(__typeof__(expr), const type *)) + +/* evaluates to true if expr is one of type[], type*, NULL or const type* */ +#define curlcheck_arr(expr, type) \ + (curlcheck_ptr((expr), type) || \ + __builtin_types_compatible_p(__typeof__(expr), type [])) + +/* evaluates to true if expr is a string */ +#define curlcheck_string(expr) \ + (curlcheck_arr((expr), char) || \ + curlcheck_arr((expr), signed char) || \ + curlcheck_arr((expr), unsigned char)) + +/* evaluates to true if expr is a long (no matter the signedness) + * XXX: for now, int is also accepted (and therefore short and char, which + * are promoted to int when passed to a variadic function) */ +#define curlcheck_long(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), long) || \ + __builtin_types_compatible_p(__typeof__(expr), signed long) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \ + __builtin_types_compatible_p(__typeof__(expr), int) || \ + __builtin_types_compatible_p(__typeof__(expr), signed int) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \ + __builtin_types_compatible_p(__typeof__(expr), short) || \ + __builtin_types_compatible_p(__typeof__(expr), signed short) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \ + __builtin_types_compatible_p(__typeof__(expr), char) || \ + __builtin_types_compatible_p(__typeof__(expr), signed char) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned char)) + +/* evaluates to true if expr is of type curl_off_t */ +#define curlcheck_off_t(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), curl_off_t)) + +/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */ +/* XXX: also check size of an char[] array? */ +#define curlcheck_error_buffer(expr) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), char *) || \ + __builtin_types_compatible_p(__typeof__(expr), char[])) + +/* evaluates to true if expr is of type (const) void* or (const) FILE* */ +#if 0 +#define curlcheck_cb_data(expr) \ + (curlcheck_ptr((expr), void) || \ + curlcheck_ptr((expr), FILE)) +#else /* be less strict */ +#define curlcheck_cb_data(expr) \ + curlcheck_any_ptr(expr) +#endif + +/* evaluates to true if expr is of type FILE* */ +#define curlcheck_FILE(expr) \ + (curlcheck_NULL(expr) || \ + (__builtin_types_compatible_p(__typeof__(expr), FILE *))) + +/* evaluates to true if expr can be passed as POST data (void* or char*) */ +#define curlcheck_postfields(expr) \ + (curlcheck_ptr((expr), void) || \ + curlcheck_arr((expr), char) || \ + curlcheck_arr((expr), unsigned char)) + +/* helper: __builtin_types_compatible_p distinguishes between functions and + * function pointers, hide it */ +#define curlcheck_cb_compatible(func, type) \ + (__builtin_types_compatible_p(__typeof__(func), type) || \ + __builtin_types_compatible_p(__typeof__(func) *, type)) + +/* evaluates to true if expr is of type curl_resolver_start_callback */ +#define curlcheck_resolver_start_callback(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_resolver_start_callback)) + +/* evaluates to true if expr is of type curl_read_callback or "similar" */ +#define curlcheck_read_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), __typeof__(fread) *) || \ + curlcheck_cb_compatible((expr), curl_read_callback) || \ + curlcheck_cb_compatible((expr), _curl_read_callback1) || \ + curlcheck_cb_compatible((expr), _curl_read_callback2) || \ + curlcheck_cb_compatible((expr), _curl_read_callback3) || \ + curlcheck_cb_compatible((expr), _curl_read_callback4) || \ + curlcheck_cb_compatible((expr), _curl_read_callback5) || \ + curlcheck_cb_compatible((expr), _curl_read_callback6)) +typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *); +typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_write_callback or "similar" */ +#define curlcheck_write_cb(expr) \ + (curlcheck_read_cb(expr) || \ + curlcheck_cb_compatible((expr), __typeof__(fwrite) *) || \ + curlcheck_cb_compatible((expr), curl_write_callback) || \ + curlcheck_cb_compatible((expr), _curl_write_callback1) || \ + curlcheck_cb_compatible((expr), _curl_write_callback2) || \ + curlcheck_cb_compatible((expr), _curl_write_callback3) || \ + curlcheck_cb_compatible((expr), _curl_write_callback4) || \ + curlcheck_cb_compatible((expr), _curl_write_callback5) || \ + curlcheck_cb_compatible((expr), _curl_write_callback6)) +typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *); +typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */ +#define curlcheck_ioctl_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_ioctl_callback) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback1) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback2) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback3) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback4)) +typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *); +typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *); +typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *); +typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *); + +/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ +#define curlcheck_sockopt_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_sockopt_callback) || \ + curlcheck_cb_compatible((expr), _curl_sockopt_callback1) || \ + curlcheck_cb_compatible((expr), _curl_sockopt_callback2)) +typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); +typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t, + curlsocktype); + +/* evaluates to true if expr is of type curl_opensocket_callback or + "similar" */ +#define curlcheck_opensocket_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_opensocket_callback) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback1) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback2) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback3) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback4)) +typedef curl_socket_t (*_curl_opensocket_callback1) + (void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback2) + (void *, curlsocktype, const struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback3) + (const void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback4) + (const void *, curlsocktype, const struct curl_sockaddr *); + +/* evaluates to true if expr is of type curl_progress_callback or "similar" */ +#define curlcheck_progress_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_progress_callback) || \ + curlcheck_cb_compatible((expr), _curl_progress_callback1) || \ + curlcheck_cb_compatible((expr), _curl_progress_callback2)) +typedef int (*_curl_progress_callback1)(void *, + double, double, double, double); +typedef int (*_curl_progress_callback2)(const void *, + double, double, double, double); + +/* evaluates to true if expr is of type curl_debug_callback or "similar" */ +#define curlcheck_debug_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_debug_callback) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback1) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback2) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback3) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback4) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback5) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback6) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback7) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback8)) +typedef int (*_curl_debug_callback1) (CURL *, + curl_infotype, char *, size_t, void *); +typedef int (*_curl_debug_callback2) (CURL *, + curl_infotype, char *, size_t, const void *); +typedef int (*_curl_debug_callback3) (CURL *, + curl_infotype, const char *, size_t, void *); +typedef int (*_curl_debug_callback4) (CURL *, + curl_infotype, const char *, size_t, const void *); +typedef int (*_curl_debug_callback5) (CURL *, + curl_infotype, unsigned char *, size_t, void *); +typedef int (*_curl_debug_callback6) (CURL *, + curl_infotype, unsigned char *, size_t, const void *); +typedef int (*_curl_debug_callback7) (CURL *, + curl_infotype, const unsigned char *, size_t, void *); +typedef int (*_curl_debug_callback8) (CURL *, + curl_infotype, const unsigned char *, size_t, const void *); + +/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */ +/* this is getting even messier... */ +#define curlcheck_ssl_ctx_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_ssl_ctx_callback) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback1) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback2) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback3) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback4) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback5) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback6) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback7) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback8)) +typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *, + const void *); +#ifdef HEADER_SSL_H +/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX + * this will of course break if we're included before OpenSSL headers... + */ +typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX *, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX *, + const void *); +#else +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8; +#endif + +/* evaluates to true if expr is of type curl_conv_callback or "similar" */ +#define curlcheck_conv_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_conv_callback) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback1) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback2) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback3) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback4)) +typedef CURLcode (*_curl_conv_callback1)(char *, size_t length); +typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length); +typedef CURLcode (*_curl_conv_callback3)(void *, size_t length); +typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length); + +/* evaluates to true if expr is of type curl_seek_callback or "similar" */ +#define curlcheck_seek_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_seek_callback) || \ + curlcheck_cb_compatible((expr), _curl_seek_callback1) || \ + curlcheck_cb_compatible((expr), _curl_seek_callback2)) +typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int); +typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int); + + +#endif /* CURLINC_TYPECHECK_GCC_H */ diff --git a/src/drivers/win/curl/x64/include/curl/urlapi.h b/src/drivers/win/curl/x64/include/curl/urlapi.h new file mode 100644 index 000000000..1d7088011 --- /dev/null +++ b/src/drivers/win/curl/x64/include/curl/urlapi.h @@ -0,0 +1,126 @@ +#ifndef CURLINC_URLAPI_H +#define CURLINC_URLAPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* the error codes for the URL API */ +typedef enum { + CURLUE_OK, + CURLUE_BAD_HANDLE, /* 1 */ + CURLUE_BAD_PARTPOINTER, /* 2 */ + CURLUE_MALFORMED_INPUT, /* 3 */ + CURLUE_BAD_PORT_NUMBER, /* 4 */ + CURLUE_UNSUPPORTED_SCHEME, /* 5 */ + CURLUE_URLDECODE, /* 6 */ + CURLUE_OUT_OF_MEMORY, /* 7 */ + CURLUE_USER_NOT_ALLOWED, /* 8 */ + CURLUE_UNKNOWN_PART, /* 9 */ + CURLUE_NO_SCHEME, /* 10 */ + CURLUE_NO_USER, /* 11 */ + CURLUE_NO_PASSWORD, /* 12 */ + CURLUE_NO_OPTIONS, /* 13 */ + CURLUE_NO_HOST, /* 14 */ + CURLUE_NO_PORT, /* 15 */ + CURLUE_NO_QUERY, /* 16 */ + CURLUE_NO_FRAGMENT /* 17 */ +} CURLUcode; + +typedef enum { + CURLUPART_URL, + CURLUPART_SCHEME, + CURLUPART_USER, + CURLUPART_PASSWORD, + CURLUPART_OPTIONS, + CURLUPART_HOST, + CURLUPART_PORT, + CURLUPART_PATH, + CURLUPART_QUERY, + CURLUPART_FRAGMENT, + CURLUPART_ZONEID /* added in 7.65.0 */ +} CURLUPart; + +#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */ +#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set, + if the port number matches the + default for the scheme */ +#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if + missing */ +#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */ +#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */ +#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */ +#define CURLU_URLDECODE (1<<6) /* URL decode on get */ +#define CURLU_URLENCODE (1<<7) /* URL encode on set */ +#define CURLU_APPENDQUERY (1<<8) /* append a form style part */ +#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */ +#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the + scheme is unknown. */ +#define CURLU_ALLOW_SPACE (1<<11) /* Allow spaces in the URL */ + +typedef struct Curl_URL CURLU; + +/* + * curl_url() creates a new CURLU handle and returns a pointer to it. + * Must be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url(void); + +/* + * curl_url_cleanup() frees the CURLU handle and related resources used for + * the URL parsing. It will not free strings previously returned with the URL + * API. + */ +CURL_EXTERN void curl_url_cleanup(CURLU *handle); + +/* + * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new + * handle must also be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url_dup(CURLU *in); + +/* + * curl_url_get() extracts a specific part of the URL from a CURLU + * handle. Returns error code. The returned pointer MUST be freed with + * curl_free() afterwards. + */ +CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what, + char **part, unsigned int flags); + +/* + * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns + * error code. The passed in string will be copied. Passing a NULL instead of + * a part string, clears that part. + */ +CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what, + const char *part, unsigned int flags); + + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* CURLINC_URLAPI_H */ diff --git a/src/drivers/win/curl/x64/lib/libcurl_a.lib b/src/drivers/win/curl/x64/lib/libcurl_a.lib new file mode 100644 index 000000000..d74ad2334 Binary files /dev/null and b/src/drivers/win/curl/x64/lib/libcurl_a.lib differ diff --git a/src/drivers/win/curl/x86/include/curl/curl.h b/src/drivers/win/curl/x86/include/curl/curl.h new file mode 100644 index 000000000..835c3d871 --- /dev/null +++ b/src/drivers/win/curl/x86/include/curl/curl.h @@ -0,0 +1,3067 @@ +#ifndef CURLINC_CURL_H +#define CURLINC_CURL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * If you have libcurl problems, all docs and details are found here: + * https://curl.se/libcurl/ + */ + +#ifdef CURL_NO_OLDIES +#define CURL_STRICTER +#endif + +#include "curlver.h" /* libcurl version defines */ +#include "system.h" /* determine things run-time */ + +/* + * Define CURL_WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && \ + !defined(__SYMBIAN32__) +#define CURL_WIN32 +#endif + +#include +#include + +#if defined(__FreeBSD__) && (__FreeBSD__ >= 2) +/* Needed for __FreeBSD_version symbol definition */ +#include +#endif + +/* The include stuff here below is mainly for time_t! */ +#include +#include + +#if defined(CURL_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) +#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \ + defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)) +/* The check above prevents the winsock2 inclusion if winsock.h already was + included, since they can't co-exist without problems */ +#include +#include +#endif +#endif + +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish + libc5-based Linux systems. Only include it on systems that are known to + require it! */ +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ + defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ + defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ + defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \ + defined(__VXWORKS__) +#include +#endif + +#if !defined(CURL_WIN32) && !defined(_WIN32_WCE) +#include +#endif + +#if !defined(CURL_WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__) +#include +#endif + +#ifdef __BEOS__ +#include +#endif + +/* Compatibility for non-Clang compilers */ +#ifndef __has_declspec_attribute +# define __has_declspec_attribute(x) 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_easy CURL; +typedef struct Curl_share CURLSH; +#else +typedef void CURL; +typedef void CURLSH; +#endif + +/* + * libcurl external API function linkage decorations. + */ + +#ifdef CURL_STATICLIB +# define CURL_EXTERN +#elif defined(CURL_WIN32) || defined(__SYMBIAN32__) || \ + (__has_declspec_attribute(dllexport) && \ + __has_declspec_attribute(dllimport)) +# if defined(BUILDING_LIBCURL) +# define CURL_EXTERN __declspec(dllexport) +# else +# define CURL_EXTERN __declspec(dllimport) +# endif +#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS) +# define CURL_EXTERN CURL_EXTERN_SYMBOL +#else +# define CURL_EXTERN +#endif + +#ifndef curl_socket_typedef +/* socket typedef */ +#if defined(CURL_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) +typedef SOCKET curl_socket_t; +#define CURL_SOCKET_BAD INVALID_SOCKET +#else +typedef int curl_socket_t; +#define CURL_SOCKET_BAD -1 +#endif +#define curl_socket_typedef +#endif /* curl_socket_typedef */ + +/* enum for the different supported SSL backends */ +typedef enum { + CURLSSLBACKEND_NONE = 0, + CURLSSLBACKEND_OPENSSL = 1, + CURLSSLBACKEND_GNUTLS = 2, + CURLSSLBACKEND_NSS = 3, + CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */ + CURLSSLBACKEND_GSKIT = 5, + CURLSSLBACKEND_POLARSSL = 6, + CURLSSLBACKEND_WOLFSSL = 7, + CURLSSLBACKEND_SCHANNEL = 8, + CURLSSLBACKEND_SECURETRANSPORT = 9, + CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */ + CURLSSLBACKEND_MBEDTLS = 11, + CURLSSLBACKEND_MESALINK = 12, + CURLSSLBACKEND_BEARSSL = 13, + CURLSSLBACKEND_RUSTLS = 14 +} curl_sslbackend; + +/* aliases for library clones and renames */ +#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL +#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL + +/* deprecated names: */ +#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL +#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT + +struct curl_httppost { + struct curl_httppost *next; /* next entry in the list */ + char *name; /* pointer to allocated name */ + long namelength; /* length of name length */ + char *contents; /* pointer to allocated data contents */ + long contentslength; /* length of contents field, see also + CURL_HTTPPOST_LARGE */ + char *buffer; /* pointer to allocated buffer contents */ + long bufferlength; /* length of buffer field */ + char *contenttype; /* Content-Type */ + struct curl_slist *contentheader; /* list of extra headers for this form */ + struct curl_httppost *more; /* if one field name has more than one + file, this link should link to following + files */ + long flags; /* as defined below */ + +/* specified content is a file name */ +#define CURL_HTTPPOST_FILENAME (1<<0) +/* specified content is a file name */ +#define CURL_HTTPPOST_READFILE (1<<1) +/* name is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRNAME (1<<2) +/* contents is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRCONTENTS (1<<3) +/* upload file from buffer */ +#define CURL_HTTPPOST_BUFFER (1<<4) +/* upload file from pointer contents */ +#define CURL_HTTPPOST_PTRBUFFER (1<<5) +/* upload file contents by using the regular read callback to get the data and + pass the given pointer as custom pointer */ +#define CURL_HTTPPOST_CALLBACK (1<<6) +/* use size in 'contentlen', added in 7.46.0 */ +#define CURL_HTTPPOST_LARGE (1<<7) + + char *showfilename; /* The file name to show. If not set, the + actual file name will be used (if this + is a file part) */ + void *userp; /* custom pointer used for + HTTPPOST_CALLBACK posts */ + curl_off_t contentlen; /* alternative length of contents + field. Used if CURL_HTTPPOST_LARGE is + set. Added in 7.46.0 */ +}; + + +/* This is a return code for the progress callback that, when returned, will + signal libcurl to continue executing the default progress function */ +#define CURL_PROGRESSFUNC_CONTINUE 0x10000001 + +/* This is the CURLOPT_PROGRESSFUNCTION callback prototype. It is now + considered deprecated but was the only choice up until 7.31.0 */ +typedef int (*curl_progress_callback)(void *clientp, + double dltotal, + double dlnow, + double ultotal, + double ulnow); + +/* This is the CURLOPT_XFERINFOFUNCTION callback prototype. It was introduced + in 7.32.0, avoids the use of floating point numbers and provides more + detailed information. */ +typedef int (*curl_xferinfo_callback)(void *clientp, + curl_off_t dltotal, + curl_off_t dlnow, + curl_off_t ultotal, + curl_off_t ulnow); + +#ifndef CURL_MAX_READ_SIZE + /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */ +#define CURL_MAX_READ_SIZE 524288 +#endif + +#ifndef CURL_MAX_WRITE_SIZE + /* Tests have proven that 20K is a very bad buffer size for uploads on + Windows, while 16K for some odd reason performed a lot better. + We do the ifndef check to allow this value to easier be changed at build + time for those who feel adventurous. The practical minimum is about + 400 bytes since libcurl uses a buffer of this size as a scratch area + (unrelated to network send operations). */ +#define CURL_MAX_WRITE_SIZE 16384 +#endif + +#ifndef CURL_MAX_HTTP_HEADER +/* The only reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause reallocs + infinitely */ +#define CURL_MAX_HTTP_HEADER (100*1024) +#endif + +/* This is a magic return code for the write callback that, when returned, + will signal libcurl to pause receiving on the current transfer. */ +#define CURL_WRITEFUNC_PAUSE 0x10000001 + +typedef size_t (*curl_write_callback)(char *buffer, + size_t size, + size_t nitems, + void *outstream); + +/* This callback will be called when a new resolver request is made */ +typedef int (*curl_resolver_start_callback)(void *resolver_state, + void *reserved, void *userdata); + +/* enumeration of file types */ +typedef enum { + CURLFILETYPE_FILE = 0, + CURLFILETYPE_DIRECTORY, + CURLFILETYPE_SYMLINK, + CURLFILETYPE_DEVICE_BLOCK, + CURLFILETYPE_DEVICE_CHAR, + CURLFILETYPE_NAMEDPIPE, + CURLFILETYPE_SOCKET, + CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */ + + CURLFILETYPE_UNKNOWN /* should never occur */ +} curlfiletype; + +#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0) +#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1) +#define CURLFINFOFLAG_KNOWN_TIME (1<<2) +#define CURLFINFOFLAG_KNOWN_PERM (1<<3) +#define CURLFINFOFLAG_KNOWN_UID (1<<4) +#define CURLFINFOFLAG_KNOWN_GID (1<<5) +#define CURLFINFOFLAG_KNOWN_SIZE (1<<6) +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7) + +/* Information about a single file, used when doing FTP wildcard matching */ +struct curl_fileinfo { + char *filename; + curlfiletype filetype; + time_t time; /* always zero! */ + unsigned int perm; + int uid; + int gid; + curl_off_t size; + long int hardlinks; + + struct { + /* If some of these fields is not NULL, it is a pointer to b_data. */ + char *time; + char *perm; + char *user; + char *group; + char *target; /* pointer to the target filename of a symlink */ + } strings; + + unsigned int flags; + + /* used internally */ + char *b_data; + size_t b_size; + size_t b_used; +}; + +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */ +#define CURL_CHUNK_BGN_FUNC_OK 0 +#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */ +#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */ + +/* if splitting of data transfer is enabled, this callback is called before + download of an individual chunk started. Note that parameter "remains" works + only for FTP wildcard downloading (for now), otherwise is not used */ +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info, + void *ptr, + int remains); + +/* return codes for CURLOPT_CHUNK_END_FUNCTION */ +#define CURL_CHUNK_END_FUNC_OK 0 +#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */ + +/* If splitting of data transfer is enabled this callback is called after + download of an individual chunk finished. + Note! After this callback was set then it have to be called FOR ALL chunks. + Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC. + This is the reason why we don't need "transfer_info" parameter in this + callback and we are not interested in "remains" parameter too. */ +typedef long (*curl_chunk_end_callback)(void *ptr); + +/* return codes for FNMATCHFUNCTION */ +#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */ +#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */ +#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */ + +/* callback type for wildcard downloading pattern matching. If the + string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */ +typedef int (*curl_fnmatch_callback)(void *ptr, + const char *pattern, + const char *string); + +/* These are the return codes for the seek callbacks */ +#define CURL_SEEKFUNC_OK 0 +#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */ +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so + libcurl might try other means instead */ +typedef int (*curl_seek_callback)(void *instream, + curl_off_t offset, + int origin); /* 'whence' */ + +/* This is a return code for the read callback that, when returned, will + signal libcurl to immediately abort the current transfer. */ +#define CURL_READFUNC_ABORT 0x10000000 +/* This is a return code for the read callback that, when returned, will + signal libcurl to pause sending data on the current transfer. */ +#define CURL_READFUNC_PAUSE 0x10000001 + +/* Return code for when the trailing headers' callback has terminated + without any errors*/ +#define CURL_TRAILERFUNC_OK 0 +/* Return code for when was an error in the trailing header's list and we + want to abort the request */ +#define CURL_TRAILERFUNC_ABORT 1 + +typedef size_t (*curl_read_callback)(char *buffer, + size_t size, + size_t nitems, + void *instream); + +typedef int (*curl_trailer_callback)(struct curl_slist **list, + void *userdata); + +typedef enum { + CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ + CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */ + CURLSOCKTYPE_LAST /* never use */ +} curlsocktype; + +/* The return code from the sockopt_callback can signal information back + to libcurl: */ +#define CURL_SOCKOPT_OK 0 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return + CURLE_ABORTED_BY_CALLBACK */ +#define CURL_SOCKOPT_ALREADY_CONNECTED 2 + +typedef int (*curl_sockopt_callback)(void *clientp, + curl_socket_t curlfd, + curlsocktype purpose); + +struct curl_sockaddr { + int family; + int socktype; + int protocol; + unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it + turned really ugly and painful on the systems that + lack this type */ + struct sockaddr addr; +}; + +typedef curl_socket_t +(*curl_opensocket_callback)(void *clientp, + curlsocktype purpose, + struct curl_sockaddr *address); + +typedef int +(*curl_closesocket_callback)(void *clientp, curl_socket_t item); + +typedef enum { + CURLIOE_OK, /* I/O operation successful */ + CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ + CURLIOE_FAILRESTART, /* failed to restart the read */ + CURLIOE_LAST /* never use */ +} curlioerr; + +typedef enum { + CURLIOCMD_NOP, /* no operation */ + CURLIOCMD_RESTARTREAD, /* restart the read stream from start */ + CURLIOCMD_LAST /* never use */ +} curliocmd; + +typedef curlioerr (*curl_ioctl_callback)(CURL *handle, + int cmd, + void *clientp); + +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS +/* + * The following typedef's are signatures of malloc, free, realloc, strdup and + * calloc respectively. Function pointers of these types can be passed to the + * curl_global_init_mem() function to set user defined memory management + * callback routines. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); + +#define CURL_DID_MEMORY_FUNC_TYPEDEFS +#endif + +/* the kind of data that is passed to information_callback*/ +typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ + CURLINFO_HEADER_OUT, /* 2 */ + CURLINFO_DATA_IN, /* 3 */ + CURLINFO_DATA_OUT, /* 4 */ + CURLINFO_SSL_DATA_IN, /* 5 */ + CURLINFO_SSL_DATA_OUT, /* 6 */ + CURLINFO_END +} curl_infotype; + +typedef int (*curl_debug_callback) + (CURL *handle, /* the handle/transfer this concerns */ + curl_infotype type, /* what kind of data */ + char *data, /* points to the data */ + size_t size, /* size of the data pointed to */ + void *userptr); /* whatever the user please */ + +/* All possible error codes from all sorts of curl functions. Future versions + may return other values, stay prepared. + + Always add new return codes last. Never *EVER* remove any. The return + codes must remain the same! + */ + +typedef enum { + CURLE_OK = 0, + CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ + CURLE_FAILED_INIT, /* 2 */ + CURLE_URL_MALFORMAT, /* 3 */ + CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ + CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ + CURLE_COULDNT_RESOLVE_HOST, /* 6 */ + CURLE_COULDNT_CONNECT, /* 7 */ + CURLE_WEIRD_SERVER_REPLY, /* 8 */ + CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server + due to lack of access - when login fails + this is not returned. */ + CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for + 7.15.4, reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ + CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server + [was obsoleted in August 2007 for 7.17.0, + reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ + CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ + CURLE_FTP_CANT_GET_HOST, /* 15 */ + CURLE_HTTP2, /* 16 - A problem in the http2 framing layer. + [was obsoleted in August 2007 for 7.17.0, + reused in July 2014 for 7.38.0] */ + CURLE_FTP_COULDNT_SET_TYPE, /* 17 */ + CURLE_PARTIAL_FILE, /* 18 */ + CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ + CURLE_OBSOLETE20, /* 20 - NOT USED */ + CURLE_QUOTE_ERROR, /* 21 - quote command failure */ + CURLE_HTTP_RETURNED_ERROR, /* 22 */ + CURLE_WRITE_ERROR, /* 23 */ + CURLE_OBSOLETE24, /* 24 - NOT USED */ + CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ + CURLE_READ_ERROR, /* 26 - couldn't open/read from file */ + CURLE_OUT_OF_MEMORY, /* 27 */ + /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error + instead of a memory allocation error if CURL_DOES_CONVERSIONS + is defined + */ + CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ + CURLE_OBSOLETE29, /* 29 - NOT USED */ + CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + CURLE_OBSOLETE32, /* 32 - NOT USED */ + CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ + CURLE_HTTP_POST_ERROR, /* 34 */ + CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ + CURLE_FILE_COULDNT_READ_FILE, /* 37 */ + CURLE_LDAP_CANNOT_BIND, /* 38 */ + CURLE_LDAP_SEARCH_FAILED, /* 39 */ + CURLE_OBSOLETE40, /* 40 - NOT USED */ + CURLE_FUNCTION_NOT_FOUND, /* 41 - NOT USED starting with 7.53.0 */ + CURLE_ABORTED_BY_CALLBACK, /* 42 */ + CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ + CURLE_OBSOLETE44, /* 44 - NOT USED */ + CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ + CURLE_OBSOLETE46, /* 46 - NOT USED */ + CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */ + CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ + CURLE_SETOPT_OPTION_SYNTAX, /* 49 - Malformed setopt option */ + CURLE_OBSOLETE50, /* 50 - NOT USED */ + CURLE_OBSOLETE51, /* 51 - NOT USED */ + CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ + CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_OBSOLETE57, /* 57 - NOT IN USE */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ + CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint + wasn't verified fine */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ + CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */ + CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ + CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ + CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind + that failed */ + CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ + CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not + accepted and we failed to login */ + CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ + CURLE_TFTP_PERM, /* 69 - permission problem on server */ + CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ + CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ + CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ + CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ + CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ + CURLE_CONV_FAILED, /* 75 - conversion failed */ + CURLE_CONV_REQD, /* 76 - caller must register conversion + callbacks using curl_easy_setopt options + CURLOPT_CONV_FROM_NETWORK_FUNCTION, + CURLOPT_CONV_TO_NETWORK_FUNCTION, and + CURLOPT_CONV_FROM_UTF8_FUNCTION */ + CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing + or wrong format */ + CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ + CURLE_SSH, /* 79 - error from the SSH layer, somewhat + generic so the error message will be of + interest when this has happened */ + + CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL + connection */ + CURLE_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it's ready and try again (Added + in 7.18.2) */ + CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or + wrong format (Added in 7.19.0) */ + CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in + 7.19.0) */ + CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */ + CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ + CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */ + CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ + CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */ + CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the + session will be queued */ + CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not + match */ + CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */ + CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer + */ + CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from + inside a callback */ + CURLE_AUTH_ERROR, /* 94 - an authentication function returned an + error */ + CURLE_HTTP3, /* 95 - An HTTP/3 layer problem */ + CURLE_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */ + CURLE_PROXY, /* 97 - proxy handshake error */ + CURLE_SSL_CLIENTCERT, /* 98 - client-side certificate required */ + CURL_LAST /* never use! */ +} CURLcode; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Previously obsolete error code re-used in 7.38.0 */ +#define CURLE_OBSOLETE16 CURLE_HTTP2 + +/* Previously obsolete error codes re-used in 7.24.0 */ +#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED +#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT + +/* compatibility with older names */ +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING +#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY + +/* The following were added in 7.62.0 */ +#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.21.5, April 2011 */ +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION + +/* Added for 7.78.0 */ +#define CURLE_TELNET_OPTION_SYNTAX CURLE_SETOPT_OPTION_SYNTAX + +/* The following were added in 7.17.1 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.17.0 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */ +#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46 +#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44 +#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10 +#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16 +#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32 +#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29 +#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12 +#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20 +#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40 +#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24 +#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57 +#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN + +#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED +#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE +#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR +#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL +#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS +#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR +#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED + +/* The following were added earlier */ + +#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT + +#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR +#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED +#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED + +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME + +/* This was the error code 50 in 7.7.3 and a few earlier versions, this + is no longer used by libcurl but is instead #defined here only to not + make programs break */ +#define CURLE_ALREADY_COMPLETE 99999 + +/* Provide defines for really old option names */ +#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */ +#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */ +#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA + +/* Since long deprecated options with no code in the lib that does anything + with them. */ +#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40 +#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72 + +#endif /*!CURL_NO_OLDIES*/ + +/* + * Proxy error codes. Returned in CURLINFO_PROXY_ERROR if CURLE_PROXY was + * return for the transfers. + */ +typedef enum { + CURLPX_OK, + CURLPX_BAD_ADDRESS_TYPE, + CURLPX_BAD_VERSION, + CURLPX_CLOSED, + CURLPX_GSSAPI, + CURLPX_GSSAPI_PERMSG, + CURLPX_GSSAPI_PROTECTION, + CURLPX_IDENTD, + CURLPX_IDENTD_DIFFER, + CURLPX_LONG_HOSTNAME, + CURLPX_LONG_PASSWD, + CURLPX_LONG_USER, + CURLPX_NO_AUTH, + CURLPX_RECV_ADDRESS, + CURLPX_RECV_AUTH, + CURLPX_RECV_CONNECT, + CURLPX_RECV_REQACK, + CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED, + CURLPX_REPLY_COMMAND_NOT_SUPPORTED, + CURLPX_REPLY_CONNECTION_REFUSED, + CURLPX_REPLY_GENERAL_SERVER_FAILURE, + CURLPX_REPLY_HOST_UNREACHABLE, + CURLPX_REPLY_NETWORK_UNREACHABLE, + CURLPX_REPLY_NOT_ALLOWED, + CURLPX_REPLY_TTL_EXPIRED, + CURLPX_REPLY_UNASSIGNED, + CURLPX_REQUEST_FAILED, + CURLPX_RESOLVE_HOST, + CURLPX_SEND_AUTH, + CURLPX_SEND_CONNECT, + CURLPX_SEND_REQUEST, + CURLPX_UNKNOWN_FAIL, + CURLPX_UNKNOWN_MODE, + CURLPX_USER_REJECTED, + CURLPX_LAST /* never use */ +} CURLproxycode; + +/* This prototype applies to all conversion callbacks */ +typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length); + +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ + void *ssl_ctx, /* actually an OpenSSL + or WolfSSL SSL_CTX, + or an mbedTLS + mbedtls_ssl_config */ + void *userptr); + +typedef enum { + CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use + CONNECT HTTP/1.1 */ + CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT + HTTP/1.0 */ + CURLPROXY_HTTPS = 2, /* added in 7.52.0 */ + CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already + in 7.10 */ + CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ + CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ + CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the + host name rather than the IP address. added + in 7.18.0 */ +} curl_proxytype; /* this enum was added in 7.10 */ + +/* + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options: + * + * CURLAUTH_NONE - No HTTP authentication + * CURLAUTH_BASIC - HTTP Basic authentication (default) + * CURLAUTH_DIGEST - HTTP Digest authentication + * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated) + * CURLAUTH_NTLM - HTTP NTLM authentication + * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour + * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper + * CURLAUTH_BEARER - HTTP Bearer token authentication + * CURLAUTH_ONLY - Use together with a single other type to force no + * authentication or just that single type + * CURLAUTH_ANY - All fine types set + * CURLAUTH_ANYSAFE - All fine types except Basic + */ + +#define CURLAUTH_NONE ((unsigned long)0) +#define CURLAUTH_BASIC (((unsigned long)1)<<0) +#define CURLAUTH_DIGEST (((unsigned long)1)<<1) +#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2) +/* Deprecated since the advent of CURLAUTH_NEGOTIATE */ +#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE +/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */ +#define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE +#define CURLAUTH_NTLM (((unsigned long)1)<<3) +#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4) +#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5) +#define CURLAUTH_BEARER (((unsigned long)1)<<6) +#define CURLAUTH_AWS_SIGV4 (((unsigned long)1)<<7) +#define CURLAUTH_ONLY (((unsigned long)1)<<31) +#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) +#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) + +#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */ +#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */ +#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */ +#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */ +#define CURLSSH_AUTH_HOST (1<<2) /* host key files */ +#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */ +#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */ +#define CURLSSH_AUTH_GSSAPI (1<<5) /* gssapi (kerberos, ...) */ +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY + +#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */ +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */ +#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */ + +#define CURL_ERROR_SIZE 256 + +enum curl_khtype { + CURLKHTYPE_UNKNOWN, + CURLKHTYPE_RSA1, + CURLKHTYPE_RSA, + CURLKHTYPE_DSS, + CURLKHTYPE_ECDSA, + CURLKHTYPE_ED25519 +}; + +struct curl_khkey { + const char *key; /* points to a null-terminated string encoded with base64 + if len is zero, otherwise to the "raw" data */ + size_t len; + enum curl_khtype keytype; +}; + +/* this is the set of return values expected from the curl_sshkeycallback + callback */ +enum curl_khstat { + CURLKHSTAT_FINE_ADD_TO_FILE, + CURLKHSTAT_FINE, + CURLKHSTAT_REJECT, /* reject the connection, return an error */ + CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so + this causes a CURLE_DEFER error but otherwise the + connection will be left intact etc */ + CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key*/ + CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ +}; + +/* this is the set of status codes pass in to the callback */ +enum curl_khmatch { + CURLKHMATCH_OK, /* match */ + CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ + CURLKHMATCH_MISSING, /* no matching host/key found */ + CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ +}; + +typedef int + (*curl_sshkeycallback) (CURL *easy, /* easy handle */ + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch, /* libcurl's view on the keys */ + void *clientp); /* custom pointer passed from app */ + +/* parameter for the CURLOPT_USE_SSL option */ +typedef enum { + CURLUSESSL_NONE, /* do not attempt to use SSL */ + CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */ + CURLUSESSL_CONTROL, /* SSL for the control connection or fail */ + CURLUSESSL_ALL, /* SSL for all communication or fail */ + CURLUSESSL_LAST /* not an option, never use */ +} curl_usessl; + +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */ + +/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the + name of improving interoperability with older servers. Some SSL libraries + have introduced work-arounds for this flaw but those work-arounds sometimes + make the SSL communication fail. To regain functionality with those broken + servers, a user can this way allow the vulnerability back. */ +#define CURLSSLOPT_ALLOW_BEAST (1<<0) + +/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those + SSL backends where such behavior is present. */ +#define CURLSSLOPT_NO_REVOKE (1<<1) + +/* - NO_PARTIALCHAIN tells libcurl to *NOT* accept a partial certificate chain + if possible. The OpenSSL backend has this ability. */ +#define CURLSSLOPT_NO_PARTIALCHAIN (1<<2) + +/* - REVOKE_BEST_EFFORT tells libcurl to ignore certificate revocation offline + checks and ignore missing revocation list for those SSL backends where such + behavior is present. */ +#define CURLSSLOPT_REVOKE_BEST_EFFORT (1<<3) + +/* - CURLSSLOPT_NATIVE_CA tells libcurl to use standard certificate store of + operating system. Currently implemented under MS-Windows. */ +#define CURLSSLOPT_NATIVE_CA (1<<4) + +/* - CURLSSLOPT_AUTO_CLIENT_CERT tells libcurl to automatically locate and use + a client certificate for authentication. (Schannel) */ +#define CURLSSLOPT_AUTO_CLIENT_CERT (1<<5) + +/* The default connection attempt delay in milliseconds for happy eyeballs. + CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document + this value, keep them in sync. */ +#define CURL_HET_DEFAULT 200L + +/* The default connection upkeep interval in milliseconds. */ +#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2009 */ + +#define CURLFTPSSL_NONE CURLUSESSL_NONE +#define CURLFTPSSL_TRY CURLUSESSL_TRY +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL +#define CURLFTPSSL_ALL CURLUSESSL_ALL +#define CURLFTPSSL_LAST CURLUSESSL_LAST +#define curl_ftpssl curl_usessl +#endif /*!CURL_NO_OLDIES*/ + +/* parameter for the CURLOPT_FTP_SSL_CCC option */ +typedef enum { + CURLFTPSSL_CCC_NONE, /* do not send CCC */ + CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */ + CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */ + CURLFTPSSL_CCC_LAST /* not an option, never use */ +} curl_ftpccc; + +/* parameter for the CURLOPT_FTPSSLAUTH option */ +typedef enum { + CURLFTPAUTH_DEFAULT, /* let libcurl decide */ + CURLFTPAUTH_SSL, /* use "AUTH SSL" */ + CURLFTPAUTH_TLS, /* use "AUTH TLS" */ + CURLFTPAUTH_LAST /* not an option, never use */ +} curl_ftpauth; + +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +typedef enum { + CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */ + CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD + again if MKD succeeded, for SFTP this does + similar magic */ + CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD + again even if MKD failed! */ + CURLFTP_CREATE_DIR_LAST /* not an option, never use */ +} curl_ftpcreatedir; + +/* parameter for the CURLOPT_FTP_FILEMETHOD option */ +typedef enum { + CURLFTPMETHOD_DEFAULT, /* let libcurl pick */ + CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */ + CURLFTPMETHOD_NOCWD, /* no CWD at all */ + CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */ + CURLFTPMETHOD_LAST /* not an option, never use */ +} curl_ftpmethod; + +/* bitmask defines for CURLOPT_HEADEROPT */ +#define CURLHEADER_UNIFIED 0 +#define CURLHEADER_SEPARATE (1<<0) + +/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */ +#define CURLALTSVC_READONLYFILE (1<<2) +#define CURLALTSVC_H1 (1<<3) +#define CURLALTSVC_H2 (1<<4) +#define CURLALTSVC_H3 (1<<5) + + +struct curl_hstsentry { + char *name; + size_t namelen; + unsigned int includeSubDomains:1; + char expire[18]; /* YYYYMMDD HH:MM:SS [null-terminated] */ +}; + +struct curl_index { + size_t index; /* the provided entry's "index" or count */ + size_t total; /* total number of entries to save */ +}; + +typedef enum { + CURLSTS_OK, + CURLSTS_DONE, + CURLSTS_FAIL +} CURLSTScode; + +typedef CURLSTScode (*curl_hstsread_callback)(CURL *easy, + struct curl_hstsentry *e, + void *userp); +typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy, + struct curl_hstsentry *e, + struct curl_index *i, + void *userp); + +/* CURLHSTS_* are bits for the CURLOPT_HSTS option */ +#define CURLHSTS_ENABLE (long)(1<<0) +#define CURLHSTS_READONLYFILE (long)(1<<1) + +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ +#define CURLPROTO_HTTP (1<<0) +#define CURLPROTO_HTTPS (1<<1) +#define CURLPROTO_FTP (1<<2) +#define CURLPROTO_FTPS (1<<3) +#define CURLPROTO_SCP (1<<4) +#define CURLPROTO_SFTP (1<<5) +#define CURLPROTO_TELNET (1<<6) +#define CURLPROTO_LDAP (1<<7) +#define CURLPROTO_LDAPS (1<<8) +#define CURLPROTO_DICT (1<<9) +#define CURLPROTO_FILE (1<<10) +#define CURLPROTO_TFTP (1<<11) +#define CURLPROTO_IMAP (1<<12) +#define CURLPROTO_IMAPS (1<<13) +#define CURLPROTO_POP3 (1<<14) +#define CURLPROTO_POP3S (1<<15) +#define CURLPROTO_SMTP (1<<16) +#define CURLPROTO_SMTPS (1<<17) +#define CURLPROTO_RTSP (1<<18) +#define CURLPROTO_RTMP (1<<19) +#define CURLPROTO_RTMPT (1<<20) +#define CURLPROTO_RTMPE (1<<21) +#define CURLPROTO_RTMPTE (1<<22) +#define CURLPROTO_RTMPS (1<<23) +#define CURLPROTO_RTMPTS (1<<24) +#define CURLPROTO_GOPHER (1<<25) +#define CURLPROTO_SMB (1<<26) +#define CURLPROTO_SMBS (1<<27) +#define CURLPROTO_MQTT (1<<28) +#define CURLPROTO_GOPHERS (1<<29) +#define CURLPROTO_ALL (~0) /* enable everything */ + +/* long may be 32 or 64 bits, but we should never depend on anything else + but 32 */ +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 +#define CURLOPTTYPE_OFF_T 30000 +#define CURLOPTTYPE_BLOB 40000 + +/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the + string options from the header file */ + + +#define CURLOPT(na,t,nu) na = t + nu + +/* CURLOPT aliases that make no run-time difference */ + +/* 'char *' argument to a string with a trailing zero */ +#define CURLOPTTYPE_STRINGPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'struct curl_slist *' argument */ +#define CURLOPTTYPE_SLISTPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'void *' argument passed untouched to callback */ +#define CURLOPTTYPE_CBPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'long' argument with a set of values/bitmask */ +#define CURLOPTTYPE_VALUES CURLOPTTYPE_LONG + +/* + * All CURLOPT_* values. + */ + +typedef enum { + /* This is the FILE * or void * the regular output should be written to. */ + CURLOPT(CURLOPT_WRITEDATA, CURLOPTTYPE_CBPOINT, 1), + + /* The full URL to get/put */ + CURLOPT(CURLOPT_URL, CURLOPTTYPE_STRINGPOINT, 2), + + /* Port number to connect to, if other than default. */ + CURLOPT(CURLOPT_PORT, CURLOPTTYPE_LONG, 3), + + /* Name of proxy to use. */ + CURLOPT(CURLOPT_PROXY, CURLOPTTYPE_STRINGPOINT, 4), + + /* "user:password;options" to use when fetching. */ + CURLOPT(CURLOPT_USERPWD, CURLOPTTYPE_STRINGPOINT, 5), + + /* "user:password" to use with proxy. */ + CURLOPT(CURLOPT_PROXYUSERPWD, CURLOPTTYPE_STRINGPOINT, 6), + + /* Range to get, specified as an ASCII string. */ + CURLOPT(CURLOPT_RANGE, CURLOPTTYPE_STRINGPOINT, 7), + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + CURLOPT(CURLOPT_READDATA, CURLOPTTYPE_CBPOINT, 9), + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. */ + CURLOPT(CURLOPT_ERRORBUFFER, CURLOPTTYPE_OBJECTPOINT, 10), + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_WRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 11), + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_READFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 12), + + /* Time-out the read operation after this amount of seconds */ + CURLOPT(CURLOPT_TIMEOUT, CURLOPTTYPE_LONG, 13), + + /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was successful. -1 means + * unknown size. + * + * For large file support, there is also a _LARGE version of the key + * which takes an off_t type, allowing platforms with larger off_t + * sizes to handle larger files. See below for INFILESIZE_LARGE. + */ + CURLOPT(CURLOPT_INFILESIZE, CURLOPTTYPE_LONG, 14), + + /* POST static input fields. */ + CURLOPT(CURLOPT_POSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 15), + + /* Set the referrer page (needed by some CGIs) */ + CURLOPT(CURLOPT_REFERER, CURLOPTTYPE_STRINGPOINT, 16), + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + CURLOPT(CURLOPT_FTPPORT, CURLOPTTYPE_STRINGPOINT, 17), + + /* Set the User-Agent string (examined by some CGIs) */ + CURLOPT(CURLOPT_USERAGENT, CURLOPTTYPE_STRINGPOINT, 18), + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + CURLOPT(CURLOPT_LOW_SPEED_LIMIT, CURLOPTTYPE_LONG, 19), + + /* Set the "low speed time" */ + CURLOPT(CURLOPT_LOW_SPEED_TIME, CURLOPTTYPE_LONG, 20), + + /* Set the continuation offset. + * + * Note there is also a _LARGE version of this key which uses + * off_t types, allowing for large file offsets on platforms which + * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. + */ + CURLOPT(CURLOPT_RESUME_FROM, CURLOPTTYPE_LONG, 21), + + /* Set cookie in request: */ + CURLOPT(CURLOPT_COOKIE, CURLOPTTYPE_STRINGPOINT, 22), + + /* This points to a linked list of headers, struct curl_slist kind. This + list is also used for RTSP (in spite of its name) */ + CURLOPT(CURLOPT_HTTPHEADER, CURLOPTTYPE_SLISTPOINT, 23), + + /* This points to a linked list of post entries, struct curl_httppost */ + CURLOPT(CURLOPT_HTTPPOST, CURLOPTTYPE_OBJECTPOINT, 24), + + /* name of the file keeping your private SSL-certificate */ + CURLOPT(CURLOPT_SSLCERT, CURLOPTTYPE_STRINGPOINT, 25), + + /* password for the SSL or SSH private key */ + CURLOPT(CURLOPT_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 26), + + /* send TYPE parameter? */ + CURLOPT(CURLOPT_CRLF, CURLOPTTYPE_LONG, 27), + + /* send linked-list of QUOTE commands */ + CURLOPT(CURLOPT_QUOTE, CURLOPTTYPE_SLISTPOINT, 28), + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + CURLOPT(CURLOPT_HEADERDATA, CURLOPTTYPE_CBPOINT, 29), + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + CURLOPT(CURLOPT_COOKIEFILE, CURLOPTTYPE_STRINGPOINT, 31), + + /* What version to specifically try to use. + See CURL_SSLVERSION defines below. */ + CURLOPT(CURLOPT_SSLVERSION, CURLOPTTYPE_VALUES, 32), + + /* What kind of HTTP time condition to use, see defines */ + CURLOPT(CURLOPT_TIMECONDITION, CURLOPTTYPE_VALUES, 33), + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + CURLOPT(CURLOPT_TIMEVALUE, CURLOPTTYPE_LONG, 34), + + /* 35 = OBSOLETE */ + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CURLOPT(CURLOPT_CUSTOMREQUEST, CURLOPTTYPE_STRINGPOINT, 36), + + /* FILE handle to use instead of stderr */ + CURLOPT(CURLOPT_STDERR, CURLOPTTYPE_OBJECTPOINT, 37), + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + CURLOPT(CURLOPT_POSTQUOTE, CURLOPTTYPE_SLISTPOINT, 39), + + /* OBSOLETE, do not use! */ + CURLOPT(CURLOPT_OBSOLETE40, CURLOPTTYPE_OBJECTPOINT, 40), + + /* talk a lot */ + CURLOPT(CURLOPT_VERBOSE, CURLOPTTYPE_LONG, 41), + + /* throw the header out too */ + CURLOPT(CURLOPT_HEADER, CURLOPTTYPE_LONG, 42), + + /* shut off the progress meter */ + CURLOPT(CURLOPT_NOPROGRESS, CURLOPTTYPE_LONG, 43), + + /* use HEAD to get http document */ + CURLOPT(CURLOPT_NOBODY, CURLOPTTYPE_LONG, 44), + + /* no output on http error codes >= 400 */ + CURLOPT(CURLOPT_FAILONERROR, CURLOPTTYPE_LONG, 45), + + /* this is an upload */ + CURLOPT(CURLOPT_UPLOAD, CURLOPTTYPE_LONG, 46), + + /* HTTP POST method */ + CURLOPT(CURLOPT_POST, CURLOPTTYPE_LONG, 47), + + /* bare names when listing directories */ + CURLOPT(CURLOPT_DIRLISTONLY, CURLOPTTYPE_LONG, 48), + + /* Append instead of overwrite on upload! */ + CURLOPT(CURLOPT_APPEND, CURLOPTTYPE_LONG, 50), + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CURLOPT(CURLOPT_NETRC, CURLOPTTYPE_VALUES, 51), + + /* use Location: Luke! */ + CURLOPT(CURLOPT_FOLLOWLOCATION, CURLOPTTYPE_LONG, 52), + + /* transfer data in text/ASCII format */ + CURLOPT(CURLOPT_TRANSFERTEXT, CURLOPTTYPE_LONG, 53), + + /* HTTP PUT */ + CURLOPT(CURLOPT_PUT, CURLOPTTYPE_LONG, 54), + + /* 55 = OBSOLETE */ + + /* DEPRECATED + * Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_progress_callback + * prototype defines. */ + CURLOPT(CURLOPT_PROGRESSFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 56), + + /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION + callbacks */ + CURLOPT(CURLOPT_XFERINFODATA, CURLOPTTYPE_CBPOINT, 57), +#define CURLOPT_PROGRESSDATA CURLOPT_XFERINFODATA + + /* We want the referrer field set automatically when following locations */ + CURLOPT(CURLOPT_AUTOREFERER, CURLOPTTYPE_LONG, 58), + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + CURLOPT(CURLOPT_PROXYPORT, CURLOPTTYPE_LONG, 59), + + /* size of the POST input data, if strlen() is not good to use */ + CURLOPT(CURLOPT_POSTFIELDSIZE, CURLOPTTYPE_LONG, 60), + + /* tunnel non-http operations through a HTTP proxy */ + CURLOPT(CURLOPT_HTTPPROXYTUNNEL, CURLOPTTYPE_LONG, 61), + + /* Set the interface string to use as outgoing network interface */ + CURLOPT(CURLOPT_INTERFACE, CURLOPTTYPE_STRINGPOINT, 62), + + /* Set the krb4/5 security level, this also enables krb4/5 awareness. This + * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string + * is set but doesn't match one of these, 'private' will be used. */ + CURLOPT(CURLOPT_KRBLEVEL, CURLOPTTYPE_STRINGPOINT, 63), + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + CURLOPT(CURLOPT_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 64), + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAINFO, CURLOPTTYPE_STRINGPOINT, 65), + + /* 66 = OBSOLETE */ + /* 67 = OBSOLETE */ + + /* Maximum number of http redirects to follow */ + CURLOPT(CURLOPT_MAXREDIRS, CURLOPTTYPE_LONG, 68), + + /* Pass a long set to 1 to get the date of the requested document (if + possible)! Pass a zero to shut it off. */ + CURLOPT(CURLOPT_FILETIME, CURLOPTTYPE_LONG, 69), + + /* This points to a linked list of telnet options */ + CURLOPT(CURLOPT_TELNETOPTIONS, CURLOPTTYPE_SLISTPOINT, 70), + + /* Max amount of cached alive connections */ + CURLOPT(CURLOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 71), + + /* OBSOLETE, do not use! */ + CURLOPT(CURLOPT_OBSOLETE72, CURLOPTTYPE_LONG, 72), + + /* 73 = OBSOLETE */ + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you're absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + CURLOPT(CURLOPT_FRESH_CONNECT, CURLOPTTYPE_LONG, 74), + + /* Set to explicitly forbid the upcoming transfer's connection to be re-used + when done. Do not use this unless you're absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + CURLOPT(CURLOPT_FORBID_REUSE, CURLOPTTYPE_LONG, 75), + + /* Set to a file name that contains random data for libcurl to use to + seed the random engine when doing SSL connects. */ + CURLOPT(CURLOPT_RANDOM_FILE, CURLOPTTYPE_STRINGPOINT, 76), + + /* Set to the Entropy Gathering Daemon socket pathname */ + CURLOPT(CURLOPT_EGDSOCKET, CURLOPTTYPE_STRINGPOINT, 77), + + /* Time-out connect operations after this amount of seconds, if connects are + OK within this time, then fine... This only aborts the connect phase. */ + CURLOPT(CURLOPT_CONNECTTIMEOUT, CURLOPTTYPE_LONG, 78), + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_HEADERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 79), + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + CURLOPT(CURLOPT_HTTPGET, CURLOPTTYPE_LONG, 80), + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + CURLOPT(CURLOPT_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 81), + + /* Specify which file name to write all known cookies in after completed + operation. Set file name to "-" (dash) to make it go to stdout. */ + CURLOPT(CURLOPT_COOKIEJAR, CURLOPTTYPE_STRINGPOINT, 82), + + /* Specify which SSL ciphers to use */ + CURLOPT(CURLOPT_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 83), + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + CURLOPT(CURLOPT_HTTP_VERSION, CURLOPTTYPE_VALUES, 84), + + /* Specifically switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + CURLOPT(CURLOPT_FTP_USE_EPSV, CURLOPTTYPE_LONG, 85), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + CURLOPT(CURLOPT_SSLCERTTYPE, CURLOPTTYPE_STRINGPOINT, 86), + + /* name of the file keeping your private SSL-key */ + CURLOPT(CURLOPT_SSLKEY, CURLOPTTYPE_STRINGPOINT, 87), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + CURLOPT(CURLOPT_SSLKEYTYPE, CURLOPTTYPE_STRINGPOINT, 88), + + /* crypto engine for the SSL-sub system */ + CURLOPT(CURLOPT_SSLENGINE, CURLOPTTYPE_STRINGPOINT, 89), + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + CURLOPT(CURLOPT_SSLENGINE_DEFAULT, CURLOPTTYPE_LONG, 90), + + /* Non-zero value means to use the global dns cache */ + /* DEPRECATED, do not use! */ + CURLOPT(CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOPTTYPE_LONG, 91), + + /* DNS cache timeout */ + CURLOPT(CURLOPT_DNS_CACHE_TIMEOUT, CURLOPTTYPE_LONG, 92), + + /* send linked-list of pre-transfer QUOTE commands */ + CURLOPT(CURLOPT_PREQUOTE, CURLOPTTYPE_SLISTPOINT, 93), + + /* set the debug function */ + CURLOPT(CURLOPT_DEBUGFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CURLOPT(CURLOPT_DEBUGDATA, CURLOPTTYPE_CBPOINT, 95), + + /* mark this as start of a cookie session */ + CURLOPT(CURLOPT_COOKIESESSION, CURLOPTTYPE_LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAPATH, CURLOPTTYPE_STRINGPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CURLOPT(CURLOPT_BUFFERSIZE, CURLOPTTYPE_LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CURLOPT(CURLOPT_NOSIGNAL, CURLOPTTYPE_LONG, 99), + + /* Provide a CURLShare for mutexing non-ts data */ + CURLOPT(CURLOPT_SHARE, CURLOPTTYPE_OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and + CURLPROXY_SOCKS5. */ + CURLOPT(CURLOPT_PROXYTYPE, CURLOPTTYPE_VALUES, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. Before 7.21.6, this was known as + CURLOPT_ENCODING */ + CURLOPT(CURLOPT_ACCEPT_ENCODING, CURLOPTTYPE_STRINGPOINT, 102), + + /* Set pointer to private data */ + CURLOPT(CURLOPT_PRIVATE, CURLOPTTYPE_OBJECTPOINT, 103), + + /* Set aliases for HTTP 200 in the HTTP Response header */ + CURLOPT(CURLOPT_HTTP200ALIASES, CURLOPTTYPE_SLISTPOINT, 104), + + /* Continue to send authentication (user+password) when following locations, + even when hostname changed. This can potentially send off the name + and password to whatever host the server decides. */ + CURLOPT(CURLOPT_UNRESTRICTED_AUTH, CURLOPTTYPE_LONG, 105), + + /* Specifically switch on or off the FTP engine's use of the EPRT command ( + it also disables the LPRT attempt). By default, those ones will always be + attempted before the good old traditional PORT command. */ + CURLOPT(CURLOPT_FTP_USE_EPRT, CURLOPTTYPE_LONG, 106), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_USERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CURLOPT(CURLOPT_HTTPAUTH, CURLOPTTYPE_VALUES, 107), + + /* Set the ssl context callback function, currently only for OpenSSL or + WolfSSL ssl_ctx, or mbedTLS mbedtls_ssl_config in the second argument. + The function must match the curl_ssl_ctx_callback prototype. */ + CURLOPT(CURLOPT_SSL_CTX_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 108), + + /* Set the userdata for the ssl context callback function's third + argument */ + CURLOPT(CURLOPT_SSL_CTX_DATA, CURLOPTTYPE_CBPOINT, 109), + + /* FTP Option that causes missing dirs to be created on the remote server. + In 7.19.4 we introduced the convenience enums for this option using the + CURLFTP_CREATE_DIR prefix. + */ + CURLOPT(CURLOPT_FTP_CREATE_MISSING_DIRS, CURLOPTTYPE_LONG, 110), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CURLOPT(CURLOPT_PROXYAUTH, CURLOPTTYPE_VALUES, 111), + + /* FTP option that changes the timeout, in seconds, associated with + getting a response. This is different from transfer timeout time and + essentially places a demand on the FTP server to acknowledge commands + in a timely manner. */ + CURLOPT(CURLOPT_FTP_RESPONSE_TIMEOUT, CURLOPTTYPE_LONG, 112), +#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT + + /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to + tell libcurl to use those IP versions only. This only has effect on + systems with support for more than one, i.e IPv4 _and_ IPv6. */ + CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_VALUES, 113), + + /* Set this option to limit the size of a file that will be downloaded from + an HTTP or FTP server. + + Note there is also _LARGE version which adds large file support for + platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ + CURLOPT(CURLOPT_MAXFILESIZE, CURLOPTTYPE_LONG, 114), + + /* See the comment for INFILESIZE above, but in short, specifies + * the size of the file being uploaded. -1 means unknown. + */ + CURLOPT(CURLOPT_INFILESIZE_LARGE, CURLOPTTYPE_OFF_T, 115), + + /* Sets the continuation offset. There is also a CURLOPTTYPE_LONG version + * of this; look above for RESUME_FROM. + */ + CURLOPT(CURLOPT_RESUME_FROM_LARGE, CURLOPTTYPE_OFF_T, 116), + + /* Sets the maximum size of data that will be downloaded from + * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. + */ + CURLOPT(CURLOPT_MAXFILESIZE_LARGE, CURLOPTTYPE_OFF_T, 117), + + /* Set this option to the file name of your .netrc file you want libcurl + to parse (using the CURLOPT_NETRC option). If not set, libcurl will do + a poor attempt to find the user's home directory and check for a .netrc + file in there. */ + CURLOPT(CURLOPT_NETRC_FILE, CURLOPTTYPE_STRINGPOINT, 118), + + /* Enable SSL/TLS for FTP, pick one of: + CURLUSESSL_TRY - try using SSL, proceed anyway otherwise + CURLUSESSL_CONTROL - SSL for the control connection or fail + CURLUSESSL_ALL - SSL for all communication or fail + */ + CURLOPT(CURLOPT_USE_SSL, CURLOPTTYPE_VALUES, 119), + + /* The _LARGE version of the standard POSTFIELDSIZE option */ + CURLOPT(CURLOPT_POSTFIELDSIZE_LARGE, CURLOPTTYPE_OFF_T, 120), + + /* Enable/disable the TCP Nagle algorithm */ + CURLOPT(CURLOPT_TCP_NODELAY, CURLOPTTYPE_LONG, 121), + + /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 123 OBSOLETE. Gone in 7.16.0 */ + /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 127 OBSOLETE. Gone in 7.16.0 */ + /* 128 OBSOLETE. Gone in 7.16.0 */ + + /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option + can be used to change libcurl's default action which is to first try + "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK + response has been received. + + Available parameters are: + CURLFTPAUTH_DEFAULT - let libcurl decide + CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS + CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL + */ + CURLOPT(CURLOPT_FTPSSLAUTH, CURLOPTTYPE_VALUES, 129), + + CURLOPT(CURLOPT_IOCTLFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 130), + CURLOPT(CURLOPT_IOCTLDATA, CURLOPTTYPE_CBPOINT, 131), + + /* 132 OBSOLETE. Gone in 7.16.0 */ + /* 133 OBSOLETE. Gone in 7.16.0 */ + + /* null-terminated string for pass on to the FTP server when asked for + "account" info */ + CURLOPT(CURLOPT_FTP_ACCOUNT, CURLOPTTYPE_STRINGPOINT, 134), + + /* feed cookie into cookie engine */ + CURLOPT(CURLOPT_COOKIELIST, CURLOPTTYPE_STRINGPOINT, 135), + + /* ignore Content-Length */ + CURLOPT(CURLOPT_IGNORE_CONTENT_LENGTH, CURLOPTTYPE_LONG, 136), + + /* Set to non-zero to skip the IP address received in a 227 PASV FTP server + response. Typically used for FTP-SSL purposes but is not restricted to + that. libcurl will then instead use the same IP address it used for the + control connection. */ + CURLOPT(CURLOPT_FTP_SKIP_PASV_IP, CURLOPTTYPE_LONG, 137), + + /* Select "file method" to use when doing FTP, see the curl_ftpmethod + above. */ + CURLOPT(CURLOPT_FTP_FILEMETHOD, CURLOPTTYPE_VALUES, 138), + + /* Local port number to bind the socket to */ + CURLOPT(CURLOPT_LOCALPORT, CURLOPTTYPE_LONG, 139), + + /* Number of ports to try, including the first one set with LOCALPORT. + Thus, setting it to 1 will make no additional attempts but the first. + */ + CURLOPT(CURLOPT_LOCALPORTRANGE, CURLOPTTYPE_LONG, 140), + + /* no transfer, set up connection and let application use the socket by + extracting it with CURLINFO_LASTSOCKET */ + CURLOPT(CURLOPT_CONNECT_ONLY, CURLOPTTYPE_LONG, 141), + + /* Function that will be called to convert from the + network encoding (instead of using the iconv calls in libcurl) */ + CURLOPT(CURLOPT_CONV_FROM_NETWORK_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 142), + + /* Function that will be called to convert to the + network encoding (instead of using the iconv calls in libcurl) */ + CURLOPT(CURLOPT_CONV_TO_NETWORK_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 143), + + /* Function that will be called to convert from UTF8 + (instead of using the iconv calls in libcurl) + Note that this is used only for SSL certificate processing */ + CURLOPT(CURLOPT_CONV_FROM_UTF8_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 144), + + /* if the connection proceeds too quickly then need to slow it down */ + /* limit-rate: maximum number of bytes per second to send or receive */ + CURLOPT(CURLOPT_MAX_SEND_SPEED_LARGE, CURLOPTTYPE_OFF_T, 145), + CURLOPT(CURLOPT_MAX_RECV_SPEED_LARGE, CURLOPTTYPE_OFF_T, 146), + + /* Pointer to command string to send if USER/PASS fails. */ + CURLOPT(CURLOPT_FTP_ALTERNATIVE_TO_USER, CURLOPTTYPE_STRINGPOINT, 147), + + /* callback function for setting socket options */ + CURLOPT(CURLOPT_SOCKOPTFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 148), + CURLOPT(CURLOPT_SOCKOPTDATA, CURLOPTTYPE_CBPOINT, 149), + + /* set to 0 to disable session ID re-use for this transfer, default is + enabled (== 1) */ + CURLOPT(CURLOPT_SSL_SESSIONID_CACHE, CURLOPTTYPE_LONG, 150), + + /* allowed SSH authentication methods */ + CURLOPT(CURLOPT_SSH_AUTH_TYPES, CURLOPTTYPE_VALUES, 151), + + /* Used by scp/sftp to do public/private key authentication */ + CURLOPT(CURLOPT_SSH_PUBLIC_KEYFILE, CURLOPTTYPE_STRINGPOINT, 152), + CURLOPT(CURLOPT_SSH_PRIVATE_KEYFILE, CURLOPTTYPE_STRINGPOINT, 153), + + /* Send CCC (Clear Command Channel) after authentication */ + CURLOPT(CURLOPT_FTP_SSL_CCC, CURLOPTTYPE_LONG, 154), + + /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ + CURLOPT(CURLOPT_TIMEOUT_MS, CURLOPTTYPE_LONG, 155), + CURLOPT(CURLOPT_CONNECTTIMEOUT_MS, CURLOPTTYPE_LONG, 156), + + /* set to zero to disable the libcurl's decoding and thus pass the raw body + data to the application even when it is encoded/compressed */ + CURLOPT(CURLOPT_HTTP_TRANSFER_DECODING, CURLOPTTYPE_LONG, 157), + CURLOPT(CURLOPT_HTTP_CONTENT_DECODING, CURLOPTTYPE_LONG, 158), + + /* Permission used when creating new files and directories on the remote + server for protocols that support it, SFTP/SCP/FILE */ + CURLOPT(CURLOPT_NEW_FILE_PERMS, CURLOPTTYPE_LONG, 159), + CURLOPT(CURLOPT_NEW_DIRECTORY_PERMS, CURLOPTTYPE_LONG, 160), + + /* Set the behavior of POST when redirecting. Values must be set to one + of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ + CURLOPT(CURLOPT_POSTREDIR, CURLOPTTYPE_VALUES, 161), + + /* used by scp/sftp to verify the host's public key */ + CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, CURLOPTTYPE_STRINGPOINT, 162), + + /* Callback function for opening socket (instead of socket(2)). Optionally, + callback is able change the address or refuse to connect returning + CURL_SOCKET_BAD. The callback should have type + curl_opensocket_callback */ + CURLOPT(CURLOPT_OPENSOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 163), + CURLOPT(CURLOPT_OPENSOCKETDATA, CURLOPTTYPE_CBPOINT, 164), + + /* POST volatile input fields. */ + CURLOPT(CURLOPT_COPYPOSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 165), + + /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ + CURLOPT(CURLOPT_PROXY_TRANSFER_MODE, CURLOPTTYPE_LONG, 166), + + /* Callback function for seeking in the input stream */ + CURLOPT(CURLOPT_SEEKFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 167), + CURLOPT(CURLOPT_SEEKDATA, CURLOPTTYPE_CBPOINT, 168), + + /* CRL file */ + CURLOPT(CURLOPT_CRLFILE, CURLOPTTYPE_STRINGPOINT, 169), + + /* Issuer certificate */ + CURLOPT(CURLOPT_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 170), + + /* (IPv6) Address scope */ + CURLOPT(CURLOPT_ADDRESS_SCOPE, CURLOPTTYPE_LONG, 171), + + /* Collect certificate chain info and allow it to get retrievable with + CURLINFO_CERTINFO after the transfer is complete. */ + CURLOPT(CURLOPT_CERTINFO, CURLOPTTYPE_LONG, 172), + + /* "name" and "pwd" to use when fetching. */ + CURLOPT(CURLOPT_USERNAME, CURLOPTTYPE_STRINGPOINT, 173), + CURLOPT(CURLOPT_PASSWORD, CURLOPTTYPE_STRINGPOINT, 174), + + /* "name" and "pwd" to use with Proxy when fetching. */ + CURLOPT(CURLOPT_PROXYUSERNAME, CURLOPTTYPE_STRINGPOINT, 175), + CURLOPT(CURLOPT_PROXYPASSWORD, CURLOPTTYPE_STRINGPOINT, 176), + + /* Comma separated list of hostnames defining no-proxy zones. These should + match both hostnames directly, and hostnames within a domain. For + example, local.com will match local.com and www.local.com, but NOT + notlocal.com or www.notlocal.com. For compatibility with other + implementations of this, .local.com will be considered to be the same as + local.com. A single * is the only valid wildcard, and effectively + disables the use of proxy. */ + CURLOPT(CURLOPT_NOPROXY, CURLOPTTYPE_STRINGPOINT, 177), + + /* block size for TFTP transfers */ + CURLOPT(CURLOPT_TFTP_BLKSIZE, CURLOPTTYPE_LONG, 178), + + /* Socks Service */ + /* DEPRECATED, do not use! */ + CURLOPT(CURLOPT_SOCKS5_GSSAPI_SERVICE, CURLOPTTYPE_STRINGPOINT, 179), + + /* Socks Service */ + CURLOPT(CURLOPT_SOCKS5_GSSAPI_NEC, CURLOPTTYPE_LONG, 180), + + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + CURLOPT(CURLOPT_PROTOCOLS, CURLOPTTYPE_LONG, 181), + + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. */ + CURLOPT(CURLOPT_REDIR_PROTOCOLS, CURLOPTTYPE_LONG, 182), + + /* set the SSH knownhost file name to use */ + CURLOPT(CURLOPT_SSH_KNOWNHOSTS, CURLOPTTYPE_STRINGPOINT, 183), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CURLOPT(CURLOPT_SSH_KEYFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 184), + + /* set the SSH host key callback custom pointer */ + CURLOPT(CURLOPT_SSH_KEYDATA, CURLOPTTYPE_CBPOINT, 185), + + /* set the SMTP mail originator */ + CURLOPT(CURLOPT_MAIL_FROM, CURLOPTTYPE_STRINGPOINT, 186), + + /* set the list of SMTP mail receiver(s) */ + CURLOPT(CURLOPT_MAIL_RCPT, CURLOPTTYPE_SLISTPOINT, 187), + + /* FTP: send PRET before PASV */ + CURLOPT(CURLOPT_FTP_USE_PRET, CURLOPTTYPE_LONG, 188), + + /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ + CURLOPT(CURLOPT_RTSP_REQUEST, CURLOPTTYPE_VALUES, 189), + + /* The RTSP session identifier */ + CURLOPT(CURLOPT_RTSP_SESSION_ID, CURLOPTTYPE_STRINGPOINT, 190), + + /* The RTSP stream URI */ + CURLOPT(CURLOPT_RTSP_STREAM_URI, CURLOPTTYPE_STRINGPOINT, 191), + + /* The Transport: header to use in RTSP requests */ + CURLOPT(CURLOPT_RTSP_TRANSPORT, CURLOPTTYPE_STRINGPOINT, 192), + + /* Manually initialize the client RTSP CSeq for this handle */ + CURLOPT(CURLOPT_RTSP_CLIENT_CSEQ, CURLOPTTYPE_LONG, 193), + + /* Manually initialize the server RTSP CSeq for this handle */ + CURLOPT(CURLOPT_RTSP_SERVER_CSEQ, CURLOPTTYPE_LONG, 194), + + /* The stream to pass to INTERLEAVEFUNCTION. */ + CURLOPT(CURLOPT_INTERLEAVEDATA, CURLOPTTYPE_CBPOINT, 195), + + /* Let the application define a custom write method for RTP data */ + CURLOPT(CURLOPT_INTERLEAVEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 196), + + /* Turn on wildcard matching */ + CURLOPT(CURLOPT_WILDCARDMATCH, CURLOPTTYPE_LONG, 197), + + /* Directory matching callback called before downloading of an + individual file (chunk) started */ + CURLOPT(CURLOPT_CHUNK_BGN_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 198), + + /* Directory matching callback called after the file (chunk) + was downloaded, or skipped */ + CURLOPT(CURLOPT_CHUNK_END_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 199), + + /* Change match (fnmatch-like) callback for wildcard matching */ + CURLOPT(CURLOPT_FNMATCH_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 200), + + /* Let the application define custom chunk data pointer */ + CURLOPT(CURLOPT_CHUNK_DATA, CURLOPTTYPE_CBPOINT, 201), + + /* FNMATCH_FUNCTION user pointer */ + CURLOPT(CURLOPT_FNMATCH_DATA, CURLOPTTYPE_CBPOINT, 202), + + /* send linked-list of name:port:address sets */ + CURLOPT(CURLOPT_RESOLVE, CURLOPTTYPE_SLISTPOINT, 203), + + /* Set a username for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 204), + + /* Set a password for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_PASSWORD, CURLOPTTYPE_STRINGPOINT, 205), + + /* Set authentication type for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_TYPE, CURLOPTTYPE_STRINGPOINT, 206), + + /* Set to 1 to enable the "TE:" header in HTTP requests to ask for + compressed transfer-encoded responses. Set to 0 to disable the use of TE: + in outgoing requests. The current default is 0, but it might change in a + future libcurl release. + + libcurl will ask for the compressed methods it knows of, and if that + isn't any, it will not ask for transfer-encoding at all even if this + option is set to 1. + + */ + CURLOPT(CURLOPT_TRANSFER_ENCODING, CURLOPTTYPE_LONG, 207), + + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CURLOPT(CURLOPT_CLOSESOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 208), + CURLOPT(CURLOPT_CLOSESOCKETDATA, CURLOPTTYPE_CBPOINT, 209), + + /* allow GSSAPI credential delegation */ + CURLOPT(CURLOPT_GSSAPI_DELEGATION, CURLOPTTYPE_VALUES, 210), + + /* Set the name servers to use for DNS resolution */ + CURLOPT(CURLOPT_DNS_SERVERS, CURLOPTTYPE_STRINGPOINT, 211), + + /* Time-out accept operations (currently for FTP only) after this amount + of milliseconds. */ + CURLOPT(CURLOPT_ACCEPTTIMEOUT_MS, CURLOPTTYPE_LONG, 212), + + /* Set TCP keepalive */ + CURLOPT(CURLOPT_TCP_KEEPALIVE, CURLOPTTYPE_LONG, 213), + + /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */ + CURLOPT(CURLOPT_TCP_KEEPIDLE, CURLOPTTYPE_LONG, 214), + CURLOPT(CURLOPT_TCP_KEEPINTVL, CURLOPTTYPE_LONG, 215), + + /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */ + CURLOPT(CURLOPT_SSL_OPTIONS, CURLOPTTYPE_VALUES, 216), + + /* Set the SMTP auth originator */ + CURLOPT(CURLOPT_MAIL_AUTH, CURLOPTTYPE_STRINGPOINT, 217), + + /* Enable/disable SASL initial response */ + CURLOPT(CURLOPT_SASL_IR, CURLOPTTYPE_LONG, 218), + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_xferinfo_callback + * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ + CURLOPT(CURLOPT_XFERINFOFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 219), + + /* The XOAUTH2 bearer token */ + CURLOPT(CURLOPT_XOAUTH2_BEARER, CURLOPTTYPE_STRINGPOINT, 220), + + /* Set the interface string to use as outgoing network + * interface for DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_INTERFACE, CURLOPTTYPE_STRINGPOINT, 221), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_LOCAL_IP4, CURLOPTTYPE_STRINGPOINT, 222), + + /* Set the local IPv6 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_LOCAL_IP6, CURLOPTTYPE_STRINGPOINT, 223), + + /* Set authentication options directly */ + CURLOPT(CURLOPT_LOGIN_OPTIONS, CURLOPTTYPE_STRINGPOINT, 224), + + /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */ + CURLOPT(CURLOPT_SSL_ENABLE_NPN, CURLOPTTYPE_LONG, 225), + + /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */ + CURLOPT(CURLOPT_SSL_ENABLE_ALPN, CURLOPTTYPE_LONG, 226), + + /* Time to wait for a response to a HTTP request containing an + * Expect: 100-continue header before sending the data anyway. */ + CURLOPT(CURLOPT_EXPECT_100_TIMEOUT_MS, CURLOPTTYPE_LONG, 227), + + /* This points to a linked list of headers used for proxy requests only, + struct curl_slist kind */ + CURLOPT(CURLOPT_PROXYHEADER, CURLOPTTYPE_SLISTPOINT, 228), + + /* Pass in a bitmask of "header options" */ + CURLOPT(CURLOPT_HEADEROPT, CURLOPTTYPE_VALUES, 229), + + /* The public key in DER form used to validate the peer public key + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 230), + + /* Path to Unix domain socket */ + CURLOPT(CURLOPT_UNIX_SOCKET_PATH, CURLOPTTYPE_STRINGPOINT, 231), + + /* Set if we should verify the certificate status. */ + CURLOPT(CURLOPT_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 232), + + /* Set if we should enable TLS false start. */ + CURLOPT(CURLOPT_SSL_FALSESTART, CURLOPTTYPE_LONG, 233), + + /* Do not squash dot-dot sequences */ + CURLOPT(CURLOPT_PATH_AS_IS, CURLOPTTYPE_LONG, 234), + + /* Proxy Service Name */ + CURLOPT(CURLOPT_PROXY_SERVICE_NAME, CURLOPTTYPE_STRINGPOINT, 235), + + /* Service Name */ + CURLOPT(CURLOPT_SERVICE_NAME, CURLOPTTYPE_STRINGPOINT, 236), + + /* Wait/don't wait for pipe/mutex to clarify */ + CURLOPT(CURLOPT_PIPEWAIT, CURLOPTTYPE_LONG, 237), + + /* Set the protocol used when curl is given a URL without a protocol */ + CURLOPT(CURLOPT_DEFAULT_PROTOCOL, CURLOPTTYPE_STRINGPOINT, 238), + + /* Set stream weight, 1 - 256 (default is 16) */ + CURLOPT(CURLOPT_STREAM_WEIGHT, CURLOPTTYPE_LONG, 239), + + /* Set stream dependency on another CURL handle */ + CURLOPT(CURLOPT_STREAM_DEPENDS, CURLOPTTYPE_OBJECTPOINT, 240), + + /* Set E-xclusive stream dependency on another CURL handle */ + CURLOPT(CURLOPT_STREAM_DEPENDS_E, CURLOPTTYPE_OBJECTPOINT, 241), + + /* Do not send any tftp option requests to the server */ + CURLOPT(CURLOPT_TFTP_NO_OPTIONS, CURLOPTTYPE_LONG, 242), + + /* Linked-list of host:port:connect-to-host:connect-to-port, + overrides the URL's host:port (only for the network layer) */ + CURLOPT(CURLOPT_CONNECT_TO, CURLOPTTYPE_SLISTPOINT, 243), + + /* Set TCP Fast Open */ + CURLOPT(CURLOPT_TCP_FASTOPEN, CURLOPTTYPE_LONG, 244), + + /* Continue to send data if the server responds early with an + * HTTP status code >= 300 */ + CURLOPT(CURLOPT_KEEP_SENDING_ON_ERROR, CURLOPTTYPE_LONG, 245), + + /* The CApath or CAfile used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAINFO, CURLOPTTYPE_STRINGPOINT, 246), + + /* The CApath directory used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAPATH, CURLOPTTYPE_STRINGPOINT, 247), + + /* Set if we should verify the proxy in ssl handshake, + set 1 to verify. */ + CURLOPT(CURLOPT_PROXY_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 248), + + /* Set if we should verify the Common name from the proxy certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches + * the provided hostname. */ + CURLOPT(CURLOPT_PROXY_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 249), + + /* What version to specifically try to use for proxy. + See CURL_SSLVERSION defines below. */ + CURLOPT(CURLOPT_PROXY_SSLVERSION, CURLOPTTYPE_VALUES, 250), + + /* Set a username for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 251), + + /* Set a password for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_PASSWORD, CURLOPTTYPE_STRINGPOINT, 252), + + /* Set authentication type for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_TYPE, CURLOPTTYPE_STRINGPOINT, 253), + + /* name of the file keeping your private SSL-certificate for proxy */ + CURLOPT(CURLOPT_PROXY_SSLCERT, CURLOPTTYPE_STRINGPOINT, 254), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for + proxy */ + CURLOPT(CURLOPT_PROXY_SSLCERTTYPE, CURLOPTTYPE_STRINGPOINT, 255), + + /* name of the file keeping your private SSL-key for proxy */ + CURLOPT(CURLOPT_PROXY_SSLKEY, CURLOPTTYPE_STRINGPOINT, 256), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for + proxy */ + CURLOPT(CURLOPT_PROXY_SSLKEYTYPE, CURLOPTTYPE_STRINGPOINT, 257), + + /* password for the SSL private key for proxy */ + CURLOPT(CURLOPT_PROXY_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 258), + + /* Specify which SSL ciphers to use for proxy */ + CURLOPT(CURLOPT_PROXY_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 259), + + /* CRL file for proxy */ + CURLOPT(CURLOPT_PROXY_CRLFILE, CURLOPTTYPE_STRINGPOINT, 260), + + /* Enable/disable specific SSL features with a bitmask for proxy, see + CURLSSLOPT_* */ + CURLOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLOPTTYPE_LONG, 261), + + /* Name of pre proxy to use. */ + CURLOPT(CURLOPT_PRE_PROXY, CURLOPTTYPE_STRINGPOINT, 262), + + /* The public key in DER form used to validate the proxy public key + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 263), + + /* Path to an abstract Unix domain socket */ + CURLOPT(CURLOPT_ABSTRACT_UNIX_SOCKET, CURLOPTTYPE_STRINGPOINT, 264), + + /* Suppress proxy CONNECT response headers from user callbacks */ + CURLOPT(CURLOPT_SUPPRESS_CONNECT_HEADERS, CURLOPTTYPE_LONG, 265), + + /* The request target, instead of extracted from the URL */ + CURLOPT(CURLOPT_REQUEST_TARGET, CURLOPTTYPE_STRINGPOINT, 266), + + /* bitmask of allowed auth methods for connections to SOCKS5 proxies */ + CURLOPT(CURLOPT_SOCKS5_AUTH, CURLOPTTYPE_LONG, 267), + + /* Enable/disable SSH compression */ + CURLOPT(CURLOPT_SSH_COMPRESSION, CURLOPTTYPE_LONG, 268), + + /* Post MIME data. */ + CURLOPT(CURLOPT_MIMEPOST, CURLOPTTYPE_OBJECTPOINT, 269), + + /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of + seconds since 1 Jan 1970. */ + CURLOPT(CURLOPT_TIMEVALUE_LARGE, CURLOPTTYPE_OFF_T, 270), + + /* Head start in milliseconds to give happy eyeballs. */ + CURLOPT(CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, CURLOPTTYPE_LONG, 271), + + /* Function that will be called before a resolver request is made */ + CURLOPT(CURLOPT_RESOLVER_START_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 272), + + /* User data to pass to the resolver start callback. */ + CURLOPT(CURLOPT_RESOLVER_START_DATA, CURLOPTTYPE_CBPOINT, 273), + + /* send HAProxy PROXY protocol header? */ + CURLOPT(CURLOPT_HAPROXYPROTOCOL, CURLOPTTYPE_LONG, 274), + + /* shuffle addresses before use when DNS returns multiple */ + CURLOPT(CURLOPT_DNS_SHUFFLE_ADDRESSES, CURLOPTTYPE_LONG, 275), + + /* Specify which TLS 1.3 ciphers suites to use */ + CURLOPT(CURLOPT_TLS13_CIPHERS, CURLOPTTYPE_STRINGPOINT, 276), + CURLOPT(CURLOPT_PROXY_TLS13_CIPHERS, CURLOPTTYPE_STRINGPOINT, 277), + + /* Disallow specifying username/login in URL. */ + CURLOPT(CURLOPT_DISALLOW_USERNAME_IN_URL, CURLOPTTYPE_LONG, 278), + + /* DNS-over-HTTPS URL */ + CURLOPT(CURLOPT_DOH_URL, CURLOPTTYPE_STRINGPOINT, 279), + + /* Preferred buffer size to use for uploads */ + CURLOPT(CURLOPT_UPLOAD_BUFFERSIZE, CURLOPTTYPE_LONG, 280), + + /* Time in ms between connection upkeep calls for long-lived connections. */ + CURLOPT(CURLOPT_UPKEEP_INTERVAL_MS, CURLOPTTYPE_LONG, 281), + + /* Specify URL using CURL URL API. */ + CURLOPT(CURLOPT_CURLU, CURLOPTTYPE_OBJECTPOINT, 282), + + /* add trailing data just after no more data is available */ + CURLOPT(CURLOPT_TRAILERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 283), + + /* pointer to be passed to HTTP_TRAILER_FUNCTION */ + CURLOPT(CURLOPT_TRAILERDATA, CURLOPTTYPE_CBPOINT, 284), + + /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */ + CURLOPT(CURLOPT_HTTP09_ALLOWED, CURLOPTTYPE_LONG, 285), + + /* alt-svc control bitmask */ + CURLOPT(CURLOPT_ALTSVC_CTRL, CURLOPTTYPE_LONG, 286), + + /* alt-svc cache file name to possibly read from/write to */ + CURLOPT(CURLOPT_ALTSVC, CURLOPTTYPE_STRINGPOINT, 287), + + /* maximum age of a connection to consider it for reuse (in seconds) */ + CURLOPT(CURLOPT_MAXAGE_CONN, CURLOPTTYPE_LONG, 288), + + /* SASL authorisation identity */ + CURLOPT(CURLOPT_SASL_AUTHZID, CURLOPTTYPE_STRINGPOINT, 289), + + /* allow RCPT TO command to fail for some recipients */ + CURLOPT(CURLOPT_MAIL_RCPT_ALLLOWFAILS, CURLOPTTYPE_LONG, 290), + + /* the private SSL-certificate as a "blob" */ + CURLOPT(CURLOPT_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 291), + CURLOPT(CURLOPT_SSLKEY_BLOB, CURLOPTTYPE_BLOB, 292), + CURLOPT(CURLOPT_PROXY_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 293), + CURLOPT(CURLOPT_PROXY_SSLKEY_BLOB, CURLOPTTYPE_BLOB, 294), + CURLOPT(CURLOPT_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 295), + + /* Issuer certificate for proxy */ + CURLOPT(CURLOPT_PROXY_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 296), + CURLOPT(CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 297), + + /* the EC curves requested by the TLS client (RFC 8422, 5.1); + * OpenSSL support via 'set_groups'/'set_curves': + * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html + */ + CURLOPT(CURLOPT_SSL_EC_CURVES, CURLOPTTYPE_STRINGPOINT, 298), + + /* HSTS bitmask */ + CURLOPT(CURLOPT_HSTS_CTRL, CURLOPTTYPE_LONG, 299), + /* HSTS file name */ + CURLOPT(CURLOPT_HSTS, CURLOPTTYPE_STRINGPOINT, 300), + + /* HSTS read callback */ + CURLOPT(CURLOPT_HSTSREADFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 301), + CURLOPT(CURLOPT_HSTSREADDATA, CURLOPTTYPE_CBPOINT, 302), + + /* HSTS write callback */ + CURLOPT(CURLOPT_HSTSWRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 303), + CURLOPT(CURLOPT_HSTSWRITEDATA, CURLOPTTYPE_CBPOINT, 304), + + /* Parameters for V4 signature */ + CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305), + + /* Same as CURLOPT_SSL_VERIFYPEER but for DoH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 306), + + /* Same as CURLOPT_SSL_VERIFYHOST but for DoH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 307), + + /* Same as CURLOPT_SSL_VERIFYSTATUS but for DoH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 308), + + /* The CA certificates as "blob" used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAINFO_BLOB, CURLOPTTYPE_BLOB, 309), + + /* The CA certificates as "blob" used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAINFO_BLOB, CURLOPTTYPE_BLOB, 310), + + CURLOPT_LASTENTRY /* the last unused */ +} CURLoption; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2011 */ + +/* This was added in version 7.19.1 */ +#define CURLOPT_POST301 CURLOPT_POSTREDIR + +/* These are scheduled to disappear by 2009 */ + +/* The following were added in 7.17.0 */ +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_FTPAPPEND CURLOPT_APPEND +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL + +/* The following were added earlier */ + +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL + +#else +/* This is set if CURL_NO_OLDIES is defined at compile-time */ +#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */ +#endif + + + /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. */ +#define CURL_IPRESOLVE_WHATEVER 0 /* default, uses addresses to all IP + versions that your system allows */ +#define CURL_IPRESOLVE_V4 1 /* uses only IPv4 addresses/connections */ +#define CURL_IPRESOLVE_V6 2 /* uses only IPv6 addresses/connections */ + + /* three convenient "aliases" that follow the name scheme better */ +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER + + /* These enums are for use with the CURLOPT_HTTP_VERSION option. */ +enum { + CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd + like the library to choose the best possible + for us! */ + CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ + CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ + CURL_HTTP_VERSION_2_0, /* please use HTTP 2 in the request */ + CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */ + CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, /* please use HTTP 2 without HTTP/1.1 + Upgrade */ + CURL_HTTP_VERSION_3 = 30, /* Makes use of explicit HTTP/3 without fallback. + Use CURLOPT_ALTSVC to enable HTTP/3 upgrade */ + CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ +}; + +/* Convenience definition simple because the name of the version is HTTP/2 and + not 2.0. The 2_0 version of the enum name was set while the version was + still planned to be 2.0 and we stick to it for compatibility. */ +#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0 + +/* + * Public API enums for RTSP requests + */ +enum { + CURL_RTSPREQ_NONE, /* first in list */ + CURL_RTSPREQ_OPTIONS, + CURL_RTSPREQ_DESCRIBE, + CURL_RTSPREQ_ANNOUNCE, + CURL_RTSPREQ_SETUP, + CURL_RTSPREQ_PLAY, + CURL_RTSPREQ_PAUSE, + CURL_RTSPREQ_TEARDOWN, + CURL_RTSPREQ_GET_PARAMETER, + CURL_RTSPREQ_SET_PARAMETER, + CURL_RTSPREQ_RECORD, + CURL_RTSPREQ_RECEIVE, + CURL_RTSPREQ_LAST /* last in list */ +}; + + /* These enums are for use with the CURLOPT_NETRC option. */ +enum CURL_NETRC_OPTION { + CURL_NETRC_IGNORED, /* The .netrc will never be read. + * This is the default. */ + CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred + * to one in the .netrc. */ + CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. + * Unless one is set programmatically, the .netrc + * will be queried. */ + CURL_NETRC_LAST +}; + +enum { + CURL_SSLVERSION_DEFAULT, + CURL_SSLVERSION_TLSv1, /* TLS 1.x */ + CURL_SSLVERSION_SSLv2, + CURL_SSLVERSION_SSLv3, + CURL_SSLVERSION_TLSv1_0, + CURL_SSLVERSION_TLSv1_1, + CURL_SSLVERSION_TLSv1_2, + CURL_SSLVERSION_TLSv1_3, + + CURL_SSLVERSION_LAST /* never use, keep last */ +}; + +enum { + CURL_SSLVERSION_MAX_NONE = 0, + CURL_SSLVERSION_MAX_DEFAULT = (CURL_SSLVERSION_TLSv1 << 16), + CURL_SSLVERSION_MAX_TLSv1_0 = (CURL_SSLVERSION_TLSv1_0 << 16), + CURL_SSLVERSION_MAX_TLSv1_1 = (CURL_SSLVERSION_TLSv1_1 << 16), + CURL_SSLVERSION_MAX_TLSv1_2 = (CURL_SSLVERSION_TLSv1_2 << 16), + CURL_SSLVERSION_MAX_TLSv1_3 = (CURL_SSLVERSION_TLSv1_3 << 16), + + /* never use, keep last */ + CURL_SSLVERSION_MAX_LAST = (CURL_SSLVERSION_LAST << 16) +}; + +enum CURL_TLSAUTH { + CURL_TLSAUTH_NONE, + CURL_TLSAUTH_SRP, + CURL_TLSAUTH_LAST /* never use, keep last */ +}; + +/* symbols to use with CURLOPT_POSTREDIR. + CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303 + can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302 + | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */ + +#define CURL_REDIR_GET_ALL 0 +#define CURL_REDIR_POST_301 1 +#define CURL_REDIR_POST_302 2 +#define CURL_REDIR_POST_303 4 +#define CURL_REDIR_POST_ALL \ + (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303) + +typedef enum { + CURL_TIMECOND_NONE, + + CURL_TIMECOND_IFMODSINCE, + CURL_TIMECOND_IFUNMODSINCE, + CURL_TIMECOND_LASTMOD, + + CURL_TIMECOND_LAST +} curl_TimeCond; + +/* Special size_t value signaling a null-terminated string. */ +#define CURL_ZERO_TERMINATED ((size_t) -1) + +/* curl_strequal() and curl_strnequal() are subject for removal in a future + release */ +CURL_EXTERN int curl_strequal(const char *s1, const char *s2); +CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n); + +/* Mime/form handling support. */ +typedef struct curl_mime curl_mime; /* Mime context. */ +typedef struct curl_mimepart curl_mimepart; /* Mime part context. */ + +/* + * NAME curl_mime_init() + * + * DESCRIPTION + * + * Create a mime context and return its handle. The easy parameter is the + * target handle. + */ +CURL_EXTERN curl_mime *curl_mime_init(CURL *easy); + +/* + * NAME curl_mime_free() + * + * DESCRIPTION + * + * release a mime handle and its substructures. + */ +CURL_EXTERN void curl_mime_free(curl_mime *mime); + +/* + * NAME curl_mime_addpart() + * + * DESCRIPTION + * + * Append a new empty part to the given mime context and return a handle to + * the created part. + */ +CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime); + +/* + * NAME curl_mime_name() + * + * DESCRIPTION + * + * Set mime/form part name. + */ +CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name); + +/* + * NAME curl_mime_filename() + * + * DESCRIPTION + * + * Set mime part remote file name. + */ +CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_type() + * + * DESCRIPTION + * + * Set mime part type. + */ +CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype); + +/* + * NAME curl_mime_encoder() + * + * DESCRIPTION + * + * Set mime data transfer encoder. + */ +CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part, + const char *encoding); + +/* + * NAME curl_mime_data() + * + * DESCRIPTION + * + * Set mime part data source from memory data, + */ +CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part, + const char *data, size_t datasize); + +/* + * NAME curl_mime_filedata() + * + * DESCRIPTION + * + * Set mime part data source from named file. + */ +CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_data_cb() + * + * DESCRIPTION + * + * Set mime part data source from callback function. + */ +CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part, + curl_off_t datasize, + curl_read_callback readfunc, + curl_seek_callback seekfunc, + curl_free_callback freefunc, + void *arg); + +/* + * NAME curl_mime_subparts() + * + * DESCRIPTION + * + * Set mime part data source from subparts. + */ +CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part, + curl_mime *subparts); +/* + * NAME curl_mime_headers() + * + * DESCRIPTION + * + * Set mime part headers. + */ +CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part, + struct curl_slist *headers, + int take_ownership); + +typedef enum { + CURLFORM_NOTHING, /********* the first one is unused ************/ + CURLFORM_COPYNAME, + CURLFORM_PTRNAME, + CURLFORM_NAMELENGTH, + CURLFORM_COPYCONTENTS, + CURLFORM_PTRCONTENTS, + CURLFORM_CONTENTSLENGTH, + CURLFORM_FILECONTENT, + CURLFORM_ARRAY, + CURLFORM_OBSOLETE, + CURLFORM_FILE, + + CURLFORM_BUFFER, + CURLFORM_BUFFERPTR, + CURLFORM_BUFFERLENGTH, + + CURLFORM_CONTENTTYPE, + CURLFORM_CONTENTHEADER, + CURLFORM_FILENAME, + CURLFORM_END, + CURLFORM_OBSOLETE2, + + CURLFORM_STREAM, + CURLFORM_CONTENTLEN, /* added in 7.46.0, provide a curl_off_t length */ + + CURLFORM_LASTENTRY /* the last unused */ +} CURLformoption; + +/* structure to be used as parameter for CURLFORM_ARRAY */ +struct curl_forms { + CURLformoption option; + const char *value; +}; + +/* use this for multipart formpost building */ +/* Returns code for curl_formadd() + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ +typedef enum { + CURL_FORMADD_OK, /* first, no error */ + + CURL_FORMADD_MEMORY, + CURL_FORMADD_OPTION_TWICE, + CURL_FORMADD_NULL, + CURL_FORMADD_UNKNOWN_OPTION, + CURL_FORMADD_INCOMPLETE, + CURL_FORMADD_ILLEGAL_ARRAY, + CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */ + + CURL_FORMADD_LAST /* last */ +} CURLFORMcode; + +/* + * NAME curl_formadd() + * + * DESCRIPTION + * + * Pretty advanced function for building multi-part formposts. Each invoke + * adds one part that together construct a full post. Then use + * CURLOPT_HTTPPOST to send it off to libcurl. + */ +CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...); + +/* + * callback function for curl_formget() + * The void *arg pointer will be the one passed as second argument to + * curl_formget(). + * The character buffer passed to it must not be freed. + * Should return the buffer length passed to it as the argument "len" on + * success. + */ +typedef size_t (*curl_formget_callback)(void *arg, const char *buf, + size_t len); + +/* + * NAME curl_formget() + * + * DESCRIPTION + * + * Serialize a curl_httppost struct built with curl_formadd(). + * Accepts a void pointer as second argument which will be passed to + * the curl_formget_callback function. + * Returns 0 on success. + */ +CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append); +/* + * NAME curl_formfree() + * + * DESCRIPTION + * + * Free a multipart formpost previously built with curl_formadd(). + */ +CURL_EXTERN void curl_formfree(struct curl_httppost *form); + +/* + * NAME curl_getenv() + * + * DESCRIPTION + * + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is + * complete. DEPRECATED - see lib/README.curlx + */ +CURL_EXTERN char *curl_getenv(const char *variable); + +/* + * NAME curl_version() + * + * DESCRIPTION + * + * Returns a static ascii string of the libcurl version. + */ +CURL_EXTERN char *curl_version(void); + +/* + * NAME curl_easy_escape() + * + * DESCRIPTION + * + * Escapes URL strings (converts all letters consider illegal in URLs to their + * %XX versions). This function returns a new allocated string or NULL if an + * error occurred. + */ +CURL_EXTERN char *curl_easy_escape(CURL *handle, + const char *string, + int length); + +/* the previous version: */ +CURL_EXTERN char *curl_escape(const char *string, + int length); + + +/* + * NAME curl_easy_unescape() + * + * DESCRIPTION + * + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit + * versions). This function returns a new allocated string or NULL if an error + * occurred. + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are + * converted into the host encoding. + */ +CURL_EXTERN char *curl_easy_unescape(CURL *handle, + const char *string, + int length, + int *outlength); + +/* the previous version */ +CURL_EXTERN char *curl_unescape(const char *string, + int length); + +/* + * NAME curl_free() + * + * DESCRIPTION + * + * Provided for de-allocation in the same translation unit that did the + * allocation. Added in libcurl 7.10 + */ +CURL_EXTERN void curl_free(void *p); + +/* + * NAME curl_global_init() + * + * DESCRIPTION + * + * curl_global_init() should be invoked exactly once for each application that + * uses libcurl and before any call of other libcurl functions. + * + * This function is not thread-safe! + */ +CURL_EXTERN CURLcode curl_global_init(long flags); + +/* + * NAME curl_global_init_mem() + * + * DESCRIPTION + * + * curl_global_init() or curl_global_init_mem() should be invoked exactly once + * for each application that uses libcurl. This function can be used to + * initialize libcurl and set user defined memory management callback + * functions. Users can implement memory management routines to check for + * memory leaks, check for mis-use of the curl library etc. User registered + * callback routines will be invoked by this library instead of the system + * memory management routines like malloc, free etc. + */ +CURL_EXTERN CURLcode curl_global_init_mem(long flags, + curl_malloc_callback m, + curl_free_callback f, + curl_realloc_callback r, + curl_strdup_callback s, + curl_calloc_callback c); + +/* + * NAME curl_global_cleanup() + * + * DESCRIPTION + * + * curl_global_cleanup() should be invoked exactly once for each application + * that uses libcurl + */ +CURL_EXTERN void curl_global_cleanup(void); + +/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +struct curl_slist { + char *data; + struct curl_slist *next; +}; + +/* + * NAME curl_global_sslset() + * + * DESCRIPTION + * + * When built with multiple SSL backends, curl_global_sslset() allows to + * choose one. This function can only be called once, and it must be called + * *before* curl_global_init(). + * + * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The + * backend can also be specified via the name parameter (passing -1 as id). + * If both id and name are specified, the name will be ignored. If neither id + * nor name are specified, the function will fail with + * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the + * NULL-terminated list of available backends. + * + * Upon success, the function returns CURLSSLSET_OK. + * + * If the specified SSL backend is not available, the function returns + * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated + * list of available SSL backends. + * + * The SSL backend can be set only once. If it has already been set, a + * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE. + */ + +struct curl_ssl_backend { + curl_sslbackend id; + const char *name; +}; +typedef struct curl_ssl_backend curl_ssl_backend; + +typedef enum { + CURLSSLSET_OK = 0, + CURLSSLSET_UNKNOWN_BACKEND, + CURLSSLSET_TOO_LATE, + CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */ +} CURLsslset; + +CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, + const curl_ssl_backend ***avail); + +/* + * NAME curl_slist_append() + * + * DESCRIPTION + * + * Appends a string to a linked list. If no list exists, it will be created + * first. Returns the new list, after appending. + */ +CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *, + const char *); + +/* + * NAME curl_slist_free_all() + * + * DESCRIPTION + * + * free a previously built curl_slist. + */ +CURL_EXTERN void curl_slist_free_all(struct curl_slist *); + +/* + * NAME curl_getdate() + * + * DESCRIPTION + * + * Returns the time, in seconds since 1 Jan 1970 of the time string given in + * the first argument. The time argument in the second parameter is unused + * and should be set to NULL. + */ +CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); + +/* info about the certificate chain, only for OpenSSL, GnuTLS, Schannel, NSS + and GSKit builds. Asked for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ +struct curl_certinfo { + int num_of_certs; /* number of certificates with information */ + struct curl_slist **certinfo; /* for each index in this array, there's a + linked list with textual information in the + format "name: value" */ +}; + +/* Information about the SSL library used and the respective internal SSL + handle, which can be used to obtain further information regarding the + connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */ +struct curl_tlssessioninfo { + curl_sslbackend backend; + void *internals; +}; + +#define CURLINFO_STRING 0x100000 +#define CURLINFO_LONG 0x200000 +#define CURLINFO_DOUBLE 0x300000 +#define CURLINFO_SLIST 0x400000 +#define CURLINFO_PTR 0x400000 /* same as SLIST */ +#define CURLINFO_SOCKET 0x500000 +#define CURLINFO_OFF_T 0x600000 +#define CURLINFO_MASK 0x0fffff +#define CURLINFO_TYPEMASK 0xf00000 + +typedef enum { + CURLINFO_NONE, /* first, never use this */ + CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, + CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, + CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, + CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, + CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, + CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, + CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7, + CURLINFO_SIZE_UPLOAD_T = CURLINFO_OFF_T + 7, + CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8, + CURLINFO_SIZE_DOWNLOAD_T = CURLINFO_OFF_T + 8, + CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9, + CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T + 9, + CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10, + CURLINFO_SPEED_UPLOAD_T = CURLINFO_OFF_T + 10, + CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, + CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, + CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, + CURLINFO_FILETIME = CURLINFO_LONG + 14, + CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14, + CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15, + CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15, + CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16, + CURLINFO_CONTENT_LENGTH_UPLOAD_T = CURLINFO_OFF_T + 16, + CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, + CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + CURLINFO_PRIVATE = CURLINFO_STRING + 21, + CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, + CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, + CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, + CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, + CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, + CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, + CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, + CURLINFO_LASTSOCKET = CURLINFO_LONG + 29, + CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, + CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, + CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, + CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, + CURLINFO_CERTINFO = CURLINFO_PTR + 34, + CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, + CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, + CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, + CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, + CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, + CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, + CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, + CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, + CURLINFO_TLS_SESSION = CURLINFO_PTR + 43, + CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44, + CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45, + CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46, + CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47, + CURLINFO_PROTOCOL = CURLINFO_LONG + 48, + CURLINFO_SCHEME = CURLINFO_STRING + 49, + CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50, + CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51, + CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52, + CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53, + CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54, + CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55, + CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56, + CURLINFO_RETRY_AFTER = CURLINFO_OFF_T + 57, + CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58, + CURLINFO_PROXY_ERROR = CURLINFO_LONG + 59, + CURLINFO_REFERER = CURLINFO_STRING + 60, + + CURLINFO_LASTONE = 60 +} CURLINFO; + +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as + CURLINFO_HTTP_CODE */ +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE + +typedef enum { + CURLCLOSEPOLICY_NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY_USED, + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, + + CURLCLOSEPOLICY_LAST /* last, never use this */ +} curl_closepolicy; + +#define CURL_GLOBAL_SSL (1<<0) /* no purpose since since 7.57.0 */ +#define CURL_GLOBAL_WIN32 (1<<1) +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +#define CURL_GLOBAL_NOTHING 0 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL +#define CURL_GLOBAL_ACK_EINTR (1<<2) + + +/***************************************************************************** + * Setup defines, protos etc for the sharing stuff. + */ + +/* Different data locks for a single share */ +typedef enum { + CURL_LOCK_DATA_NONE = 0, + /* CURL_LOCK_DATA_SHARE is used internally to say that + * the locking is just made to change the internal state of the share + * itself. + */ + CURL_LOCK_DATA_SHARE, + CURL_LOCK_DATA_COOKIE, + CURL_LOCK_DATA_DNS, + CURL_LOCK_DATA_SSL_SESSION, + CURL_LOCK_DATA_CONNECT, + CURL_LOCK_DATA_PSL, + CURL_LOCK_DATA_LAST +} curl_lock_data; + +/* Different lock access types */ +typedef enum { + CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */ + CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */ + CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */ + CURL_LOCK_ACCESS_LAST /* never use */ +} curl_lock_access; + +typedef void (*curl_lock_function)(CURL *handle, + curl_lock_data data, + curl_lock_access locktype, + void *userptr); +typedef void (*curl_unlock_function)(CURL *handle, + curl_lock_data data, + void *userptr); + + +typedef enum { + CURLSHE_OK, /* all is fine */ + CURLSHE_BAD_OPTION, /* 1 */ + CURLSHE_IN_USE, /* 2 */ + CURLSHE_INVALID, /* 3 */ + CURLSHE_NOMEM, /* 4 out of memory */ + CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */ + CURLSHE_LAST /* never use */ +} CURLSHcode; + +typedef enum { + CURLSHOPT_NONE, /* don't use */ + CURLSHOPT_SHARE, /* specify a data type to share */ + CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ + CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ + CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ + CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock + callback functions */ + CURLSHOPT_LAST /* never use */ +} CURLSHoption; + +CURL_EXTERN CURLSH *curl_share_init(void); +CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...); +CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *); + +/**************************************************************************** + * Structures for querying information about the curl library at runtime. + */ + +typedef enum { + CURLVERSION_FIRST, + CURLVERSION_SECOND, + CURLVERSION_THIRD, + CURLVERSION_FOURTH, + CURLVERSION_FIFTH, + CURLVERSION_SIXTH, + CURLVERSION_SEVENTH, + CURLVERSION_EIGHTH, + CURLVERSION_NINTH, + CURLVERSION_TENTH, + CURLVERSION_LAST /* never actually use this */ +} CURLversion; + +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basically all programs ever that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redefine the NOW to another enum + from above. */ +#define CURLVERSION_NOW CURLVERSION_TENTH + +struct curl_version_info_data { + CURLversion age; /* age of the returned struct */ + const char *version; /* LIBCURL_VERSION */ + unsigned int version_num; /* LIBCURL_VERSION_NUM */ + const char *host; /* OS/host/cpu/machine when configured */ + int features; /* bitmask, see defines below */ + const char *ssl_version; /* human readable string */ + long ssl_version_num; /* not used anymore, always 0 */ + const char *libz_version; /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + const char * const *protocols; + + /* The fields below this were added in CURLVERSION_SECOND */ + const char *ares; + int ares_num; + + /* This field was added in CURLVERSION_THIRD */ + const char *libidn; + + /* These field were added in CURLVERSION_FOURTH */ + + /* Same as '_libiconv_version' if built with HAVE_ICONV */ + int iconv_ver_num; + + const char *libssh_version; /* human readable string */ + + /* These fields were added in CURLVERSION_FIFTH */ + unsigned int brotli_ver_num; /* Numeric Brotli version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *brotli_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_SIXTH */ + unsigned int nghttp2_ver_num; /* Numeric nghttp2 version + (MAJOR << 16) | (MINOR << 8) | PATCH */ + const char *nghttp2_version; /* human readable string. */ + const char *quic_version; /* human readable quic (+ HTTP/3) library + + version or NULL */ + + /* These fields were added in CURLVERSION_SEVENTH */ + const char *cainfo; /* the built-in default CURLOPT_CAINFO, might + be NULL */ + const char *capath; /* the built-in default CURLOPT_CAPATH, might + be NULL */ + + /* These fields were added in CURLVERSION_EIGHTH */ + unsigned int zstd_ver_num; /* Numeric Zstd version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *zstd_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_NINTH */ + const char *hyper_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_TENTH */ + const char *gsasl_version; /* human readable string. */ +}; +typedef struct curl_version_info_data curl_version_info_data; + +#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ +#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported + (deprecated) */ +#define CURL_VERSION_SSL (1<<2) /* SSL options are present */ +#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */ +#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */ +#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported + (deprecated) */ +#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */ +#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */ +#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */ +#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */ +#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are + supported */ +#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */ +#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */ +#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */ +#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ +#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper + is supported */ +#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */ +#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */ +#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */ +#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */ +#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used + for cookie domain verification */ +#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */ +#define CURL_VERSION_MULTI_SSL (1<<22) /* Multiple SSL backends available */ +#define CURL_VERSION_BROTLI (1<<23) /* Brotli features are present. */ +#define CURL_VERSION_ALTSVC (1<<24) /* Alt-Svc handling built-in */ +#define CURL_VERSION_HTTP3 (1<<25) /* HTTP3 support built-in */ +#define CURL_VERSION_ZSTD (1<<26) /* zstd features are present */ +#define CURL_VERSION_UNICODE (1<<27) /* Unicode support on Windows */ +#define CURL_VERSION_HSTS (1<<28) /* HSTS is supported */ +#define CURL_VERSION_GSASL (1<<29) /* libgsasl is supported */ + + /* + * NAME curl_version_info() + * + * DESCRIPTION + * + * This function returns a pointer to a static copy of the version info + * struct. See above. + */ +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion); + +/* + * NAME curl_easy_strerror() + * + * DESCRIPTION + * + * The curl_easy_strerror function may be used to turn a CURLcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_easy_strerror(CURLcode); + +/* + * NAME curl_share_strerror() + * + * DESCRIPTION + * + * The curl_share_strerror function may be used to turn a CURLSHcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_share_strerror(CURLSHcode); + +/* + * NAME curl_easy_pause() + * + * DESCRIPTION + * + * The curl_easy_pause function pauses or unpauses transfers. Select the new + * state by setting the bitmask, use the convenience defines below. + * + */ +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); + +#define CURLPAUSE_RECV (1<<0) +#define CURLPAUSE_RECV_CONT (0) + +#define CURLPAUSE_SEND (1<<2) +#define CURLPAUSE_SEND_CONT (0) + +#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) +#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) + +#ifdef __cplusplus +} +#endif + +/* unfortunately, the easy.h and multi.h include files need options and info + stuff before they can be included! */ +#include "easy.h" /* nothing in curl is fun without the easy stuff */ +#include "multi.h" +#include "urlapi.h" +#include "options.h" + +/* the typechecker doesn't work in C++ (yet) */ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ + ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \ + !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK) +#include "typecheck-gcc.h" +#else +#if defined(__STDC__) && (__STDC__ >= 1) +/* This preprocessor magic that replaces a call with the exact same call is + only done to make sure application authors pass exactly three arguments + to these functions. */ +#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) +#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) +#endif /* __STDC__ >= 1 */ +#endif /* gcc >= 4.3 && !__cplusplus */ + +#endif /* CURLINC_CURL_H */ diff --git a/src/drivers/win/curl/x86/include/curl/curlver.h b/src/drivers/win/curl/x86/include/curl/curlver.h new file mode 100644 index 000000000..43ab83248 --- /dev/null +++ b/src/drivers/win/curl/x86/include/curl/curlver.h @@ -0,0 +1,77 @@ +#ifndef CURLINC_CURLVER_H +#define CURLINC_CURLVER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This header file contains nothing but libcurl version info, generated by + a script at release-time. This was made its own header file in 7.11.2 */ + +/* This is the global package copyright */ +#define LIBCURL_COPYRIGHT "1996 - 2021 Daniel Stenberg, ." + +/* This is the version number of the libcurl package from which this header + file origins: */ +#define LIBCURL_VERSION "7.79.0" + +/* The numeric version number is also available "in parts" by using these + defines: */ +#define LIBCURL_VERSION_MAJOR 7 +#define LIBCURL_VERSION_MINOR 79 +#define LIBCURL_VERSION_PATCH 0 + +/* This is the numeric version of the libcurl version number, meant for easier + parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will + always follow this syntax: + + 0xXXYYZZ + + Where XX, YY and ZZ are the main version, release and patch numbers in + hexadecimal (using 8 bits each). All three numbers are always represented + using two digits. 1.2 would appear as "0x010200" while version 9.11.7 + appears as "0x090b07". + + This 6-digit (24 bits) hexadecimal number does not show pre-release number, + and it is always a greater number in a more recent release. It makes + comparisons with greater than and less than work. + + Note: This define is the full hex number and _does not_ use the + CURL_VERSION_BITS() macro since curl's own configure script greps for it + and needs it to contain the full number. +*/ +#define LIBCURL_VERSION_NUM 0x074f00 + +/* + * This is the date and time when the full source package was created. The + * timestamp is not stored in git, as the timestamp is properly set in the + * tarballs by the maketgz script. + * + * The format of the date follows this template: + * + * "2007-11-23" + */ +#define LIBCURL_TIMESTAMP "2021-09-15" + +#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z)) +#define CURL_AT_LEAST_VERSION(x,y,z) \ + (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) + +#endif /* CURLINC_CURLVER_H */ diff --git a/src/drivers/win/curl/x86/include/curl/easy.h b/src/drivers/win/curl/x86/include/curl/easy.h new file mode 100644 index 000000000..2dbfb26b5 --- /dev/null +++ b/src/drivers/win/curl/x86/include/curl/easy.h @@ -0,0 +1,123 @@ +#ifndef CURLINC_EASY_H +#define CURLINC_EASY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +/* Flag bits in the curl_blob struct: */ +#define CURL_BLOB_COPY 1 /* tell libcurl to copy the data */ +#define CURL_BLOB_NOCOPY 0 /* tell libcurl to NOT copy the data */ + +struct curl_blob { + void *data; + size_t len; + unsigned int flags; /* bit 0 is defined, the rest are reserved and should be + left zeroes */ +}; + +CURL_EXTERN CURL *curl_easy_init(void); +CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); +CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); +CURL_EXTERN void curl_easy_cleanup(CURL *curl); + +/* + * NAME curl_easy_getinfo() + * + * DESCRIPTION + * + * Request internal information from the curl session with this function. The + * third argument MUST be a pointer to a long, a pointer to a char * or a + * pointer to a double (as the documentation describes elsewhere). The data + * pointed to will be filled in accordingly and can be relied upon only if the + * function returns CURLE_OK. This function is intended to get used *AFTER* a + * performed transfer, all results from this function are undefined until the + * transfer is completed. + */ +CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); + + +/* + * NAME curl_easy_duphandle() + * + * DESCRIPTION + * + * Creates a new curl session handle with the same options set for the handle + * passed in. Duplicating a handle could only be a matter of cloning data and + * options, internal state info and things like persistent connections cannot + * be transferred. It is useful in multithreaded applications when you can run + * curl_easy_duphandle() for each new thread to avoid a series of identical + * curl_easy_setopt() invokes in every thread. + */ +CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl); + +/* + * NAME curl_easy_reset() + * + * DESCRIPTION + * + * Re-initializes a CURL handle to the default values. This puts back the + * handle to the same state as it was in when it was just created. + * + * It does keep: live connections, the Session ID cache, the DNS cache and the + * cookies. + */ +CURL_EXTERN void curl_easy_reset(CURL *curl); + +/* + * NAME curl_easy_recv() + * + * DESCRIPTION + * + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, + size_t *n); + +/* + * NAME curl_easy_send() + * + * DESCRIPTION + * + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, + size_t buflen, size_t *n); + + +/* + * NAME curl_easy_upkeep() + * + * DESCRIPTION + * + * Performs connection upkeep for the given session handle. + */ +CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/drivers/win/curl/x86/include/curl/mprintf.h b/src/drivers/win/curl/x86/include/curl/mprintf.h new file mode 100644 index 000000000..3549552db --- /dev/null +++ b/src/drivers/win/curl/x86/include/curl/mprintf.h @@ -0,0 +1,50 @@ +#ifndef CURLINC_MPRINTF_H +#define CURLINC_MPRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include +#include /* needed for FILE */ +#include "curl.h" /* for CURL_EXTERN */ + +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN int curl_mprintf(const char *format, ...); +CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...); +CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...); +CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, + const char *format, ...); +CURL_EXTERN int curl_mvprintf(const char *format, va_list args); +CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args); +CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args); +CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, + const char *format, va_list args); +CURL_EXTERN char *curl_maprintf(const char *format, ...); +CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args); + +#ifdef __cplusplus +} +#endif + +#endif /* CURLINC_MPRINTF_H */ diff --git a/src/drivers/win/curl/x86/include/curl/multi.h b/src/drivers/win/curl/x86/include/curl/multi.h new file mode 100644 index 000000000..37f9829b3 --- /dev/null +++ b/src/drivers/win/curl/x86/include/curl/multi.h @@ -0,0 +1,456 @@ +#ifndef CURLINC_MULTI_H +#define CURLINC_MULTI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + This is an "external" header file. Don't give away any internals here! + + GOALS + + o Enable a "pull" interface. The application that uses libcurl decides where + and when to ask libcurl to get/send data. + + o Enable multiple simultaneous transfers in the same thread without making it + complicated for the application. + + o Enable the application to select() on its own file descriptors and curl's + file descriptors simultaneous easily. + +*/ + +/* + * This header file should not really need to include "curl.h" since curl.h + * itself includes this file and we expect user applications to do #include + * without the need for especially including multi.h. + * + * For some reason we added this include here at one point, and rather than to + * break existing (wrongly written) libcurl applications, we leave it as-is + * but with this warning attached. + */ +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_multi CURLM; +#else +typedef void CURLM; +#endif + +typedef enum { + CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or + curl_multi_socket*() soon */ + CURLM_OK, + CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ + CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ + CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */ + CURLM_INTERNAL_ERROR, /* this is a libcurl bug */ + CURLM_BAD_SOCKET, /* the passed in socket argument did not match */ + CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */ + CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was + attempted to get added - again */ + CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a + callback */ + CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */ + CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */ + CURLM_LAST +} CURLMcode; + +/* just to make code nicer when using curl_multi_socket() you can now check + for CURLM_CALL_MULTI_SOCKET too in the same style it works for + curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */ +#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM + +/* bitmask bits for CURLMOPT_PIPELINING */ +#define CURLPIPE_NOTHING 0L +#define CURLPIPE_HTTP1 1L +#define CURLPIPE_MULTIPLEX 2L + +typedef enum { + CURLMSG_NONE, /* first, not used */ + CURLMSG_DONE, /* This easy handle has completed. 'result' contains + the CURLcode of the transfer */ + CURLMSG_LAST /* last, not used */ +} CURLMSG; + +struct CURLMsg { + CURLMSG msg; /* what this message means */ + CURL *easy_handle; /* the handle it concerns */ + union { + void *whatever; /* message-specific data */ + CURLcode result; /* return code for transfer */ + } data; +}; +typedef struct CURLMsg CURLMsg; + +/* Based on poll(2) structure and values. + * We don't use pollfd and POLL* constants explicitly + * to cover platforms without poll(). */ +#define CURL_WAIT_POLLIN 0x0001 +#define CURL_WAIT_POLLPRI 0x0002 +#define CURL_WAIT_POLLOUT 0x0004 + +struct curl_waitfd { + curl_socket_t fd; + short events; + short revents; /* not supported yet */ +}; + +/* + * Name: curl_multi_init() + * + * Desc: inititalize multi-style curl usage + * + * Returns: a new CURLM handle to use in all 'curl_multi' functions. + */ +CURL_EXTERN CURLM *curl_multi_init(void); + +/* + * Name: curl_multi_add_handle() + * + * Desc: add a standard curl handle to the multi stack + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_remove_handle() + * + * Desc: removes a curl handle from the multi stack again + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_fdset() + * + * Desc: Ask curl for its fd_set sets. The app can use these to select() or + * poll() on. We want curl_multi_perform() called as soon as one of + * them are ready. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, + fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *exc_fd_set, + int *max_fd); + +/* + * Name: curl_multi_wait() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + +/* + * Name: curl_multi_poll() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_poll(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + +/* + * Name: curl_multi_wakeup() + * + * Desc: wakes up a sleeping curl_multi_poll call. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle); + + /* + * Name: curl_multi_perform() + * + * Desc: When the app thinks there's data available for curl it calls this + * function to read/write whatever there is right now. This returns + * as soon as the reads and writes are done. This function does not + * require that there actually is data available for reading or that + * data can be written, it can be called just in case. It returns + * the number of handles that still transfer data in the second + * argument's integer-pointer. + * + * Returns: CURLMcode type, general multi error code. *NOTE* that this only + * returns errors etc regarding the whole multi stack. There might + * still have occurred problems on individual transfers even when + * this returns OK. + */ +CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, + int *running_handles); + + /* + * Name: curl_multi_cleanup() + * + * Desc: Cleans up and removes a whole multi stack. It does not free or + * touch any individual easy handles in any way. We need to define + * in what state those handles will be if this function is called + * in the middle of a transfer. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle); + +/* + * Name: curl_multi_info_read() + * + * Desc: Ask the multi handle if there's any messages/informationals from + * the individual transfers. Messages include informationals such as + * error code from the transfer or just the fact that a transfer is + * completed. More details on these should be written down as well. + * + * Repeated calls to this function will return a new struct each + * time, until a special "end of msgs" struct is returned as a signal + * that there is no more to get at this point. + * + * The data the returned pointer points to will not survive calling + * curl_multi_cleanup(). + * + * The 'CURLMsg' struct is meant to be very simple and only contain + * very basic information. If more involved information is wanted, + * we will provide the particular "transfer handle" in that struct + * and that should/could/would be used in subsequent + * curl_easy_getinfo() calls (or similar). The point being that we + * must never expose complex structs to applications, as then we'll + * undoubtably get backwards compatibility problems in the future. + * + * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out + * of structs. It also writes the number of messages left in the + * queue (after this read) in the integer the second argument points + * to. + */ +CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle, + int *msgs_in_queue); + +/* + * Name: curl_multi_strerror() + * + * Desc: The curl_multi_strerror function may be used to turn a CURLMcode + * value into the equivalent human readable error string. This is + * useful for printing meaningful error messages. + * + * Returns: A pointer to a null-terminated error message. + */ +CURL_EXTERN const char *curl_multi_strerror(CURLMcode); + +/* + * Name: curl_multi_socket() and + * curl_multi_socket_all() + * + * Desc: An alternative version of curl_multi_perform() that allows the + * application to pass in one of the file descriptors that have been + * detected to have "action" on them and let libcurl perform. + * See man page for details. + */ +#define CURL_POLL_NONE 0 +#define CURL_POLL_IN 1 +#define CURL_POLL_OUT 2 +#define CURL_POLL_INOUT 3 +#define CURL_POLL_REMOVE 4 + +#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD + +#define CURL_CSELECT_IN 0x01 +#define CURL_CSELECT_OUT 0x02 +#define CURL_CSELECT_ERR 0x04 + +typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */ + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp); /* private socket + pointer */ +/* + * Name: curl_multi_timer_callback + * + * Desc: Called by libcurl whenever the library detects a change in the + * maximum number of milliseconds the app is allowed to wait before + * curl_multi_socket() or curl_multi_perform() must be called + * (to allow libcurl's timed events to take place). + * + * Returns: The callback should return zero. + */ +typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */ + long timeout_ms, /* see above */ + void *userp); /* private callback + pointer */ + +CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle, + curl_socket_t s, + int ev_bitmask, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle, + int *running_handles); + +#ifndef CURL_ALLOW_OLD_MULTI_SOCKET +/* This macro below was added in 7.16.3 to push users who recompile to use + the new curl_multi_socket_action() instead of the old curl_multi_socket() +*/ +#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z) +#endif + +/* + * Name: curl_multi_timeout() + * + * Desc: Returns the maximum number of milliseconds the app is allowed to + * wait before curl_multi_socket() or curl_multi_perform() must be + * called (to allow libcurl's timed events to take place). + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle, + long *milliseconds); + +typedef enum { + /* This is the socket callback function pointer */ + CURLOPT(CURLMOPT_SOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 1), + + /* This is the argument passed to the socket callback */ + CURLOPT(CURLMOPT_SOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 2), + + /* set to 1 to enable pipelining for this multi handle */ + CURLOPT(CURLMOPT_PIPELINING, CURLOPTTYPE_LONG, 3), + + /* This is the timer callback function pointer */ + CURLOPT(CURLMOPT_TIMERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 4), + + /* This is the argument passed to the timer callback */ + CURLOPT(CURLMOPT_TIMERDATA, CURLOPTTYPE_OBJECTPOINT, 5), + + /* maximum number of entries in the connection cache */ + CURLOPT(CURLMOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 6), + + /* maximum number of (pipelining) connections to one host */ + CURLOPT(CURLMOPT_MAX_HOST_CONNECTIONS, CURLOPTTYPE_LONG, 7), + + /* maximum number of requests in a pipeline */ + CURLOPT(CURLMOPT_MAX_PIPELINE_LENGTH, CURLOPTTYPE_LONG, 8), + + /* a connection with a content-length longer than this + will not be considered for pipelining */ + CURLOPT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 9), + + /* a connection with a chunk length longer than this + will not be considered for pipelining */ + CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10), + + /* a list of site names(+port) that are blocked from pipelining */ + CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11), + + /* a list of server types that are blocked from pipelining */ + CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12), + + /* maximum number of open connections in total */ + CURLOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, CURLOPTTYPE_LONG, 13), + + /* This is the server push callback function pointer */ + CURLOPT(CURLMOPT_PUSHFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 14), + + /* This is the argument passed to the server push callback */ + CURLOPT(CURLMOPT_PUSHDATA, CURLOPTTYPE_OBJECTPOINT, 15), + + /* maximum number of concurrent streams to support on a connection */ + CURLOPT(CURLMOPT_MAX_CONCURRENT_STREAMS, CURLOPTTYPE_LONG, 16), + + CURLMOPT_LASTENTRY /* the last unused */ +} CURLMoption; + + +/* + * Name: curl_multi_setopt() + * + * Desc: Sets options for the multi handle. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, + CURLMoption option, ...); + + +/* + * Name: curl_multi_assign() + * + * Desc: This function sets an association in the multi handle between the + * given socket and a private pointer of the application. This is + * (only) useful for curl_multi_socket uses. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, + curl_socket_t sockfd, void *sockp); + + +/* + * Name: curl_push_callback + * + * Desc: This callback gets called when a new stream is being pushed by the + * server. It approves or denies the new stream. It can also decide + * to completely fail the connection. + * + * Returns: CURL_PUSH_OK, CURL_PUSH_DENY or CURL_PUSH_ERROROUT + */ +#define CURL_PUSH_OK 0 +#define CURL_PUSH_DENY 1 +#define CURL_PUSH_ERROROUT 2 /* added in 7.72.0 */ + +struct curl_pushheaders; /* forward declaration only */ + +CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h, + size_t num); +CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h, + const char *name); + +typedef int (*curl_push_callback)(CURL *parent, + CURL *easy, + size_t num_headers, + struct curl_pushheaders *headers, + void *userp); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/src/drivers/win/curl/x86/include/curl/options.h b/src/drivers/win/curl/x86/include/curl/options.h new file mode 100644 index 000000000..14373b551 --- /dev/null +++ b/src/drivers/win/curl/x86/include/curl/options.h @@ -0,0 +1,68 @@ +#ifndef CURLINC_OPTIONS_H +#define CURLINC_OPTIONS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + CURLOT_LONG, /* long (a range of values) */ + CURLOT_VALUES, /* (a defined set or bitmask) */ + CURLOT_OFF_T, /* curl_off_t (a range of values) */ + CURLOT_OBJECT, /* pointer (void *) */ + CURLOT_STRING, /* (char * to zero terminated buffer) */ + CURLOT_SLIST, /* (struct curl_slist *) */ + CURLOT_CBPTR, /* (void * passed as-is to a callback) */ + CURLOT_BLOB, /* blob (struct curl_blob *) */ + CURLOT_FUNCTION /* function pointer */ +} curl_easytype; + +/* Flag bits */ + +/* "alias" means it is provided for old programs to remain functional, + we prefer another name */ +#define CURLOT_FLAG_ALIAS (1<<0) + +/* The CURLOPTTYPE_* id ranges can still be used to figure out what type/size + to use for curl_easy_setopt() for the given id */ +struct curl_easyoption { + const char *name; + CURLoption id; + curl_easytype type; + unsigned int flags; +}; + +CURL_EXTERN const struct curl_easyoption * +curl_easy_option_by_name(const char *name); + +CURL_EXTERN const struct curl_easyoption * +curl_easy_option_by_id (CURLoption id); + +CURL_EXTERN const struct curl_easyoption * +curl_easy_option_next(const struct curl_easyoption *prev); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif +#endif /* CURLINC_OPTIONS_H */ diff --git a/src/drivers/win/curl/x86/include/curl/stdcheaders.h b/src/drivers/win/curl/x86/include/curl/stdcheaders.h new file mode 100644 index 000000000..60596c756 --- /dev/null +++ b/src/drivers/win/curl/x86/include/curl/stdcheaders.h @@ -0,0 +1,33 @@ +#ifndef CURLINC_STDCHEADERS_H +#define CURLINC_STDCHEADERS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +size_t fread(void *, size_t, size_t, FILE *); +size_t fwrite(const void *, size_t, size_t, FILE *); + +int strcasecmp(const char *, const char *); +int strncasecmp(const char *, const char *, size_t); + +#endif /* CURLINC_STDCHEADERS_H */ diff --git a/src/drivers/win/curl/x86/include/curl/system.h b/src/drivers/win/curl/x86/include/curl/system.h new file mode 100644 index 000000000..faf8fcf84 --- /dev/null +++ b/src/drivers/win/curl/x86/include/curl/system.h @@ -0,0 +1,504 @@ +#ifndef CURLINC_SYSTEM_H +#define CURLINC_SYSTEM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Try to keep one section per platform, compiler and architecture, otherwise, + * if an existing section is reused for a different one and later on the + * original is adjusted, probably the piggybacking one can be adversely + * changed. + * + * In order to differentiate between platforms/compilers/architectures use + * only compiler built in predefined preprocessor symbols. + * + * curl_off_t + * ---------- + * + * For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit + * wide signed integral data type. The width of this data type must remain + * constant and independent of any possible large file support settings. + * + * As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit + * wide signed integral data type if there is no 64-bit type. + * + * As a general rule, curl_off_t shall not be mapped to off_t. This rule shall + * only be violated if off_t is the only 64-bit data type available and the + * size of off_t is independent of large file support settings. Keep your + * build on the safe side avoiding an off_t gating. If you have a 64-bit + * off_t then take for sure that another 64-bit data type exists, dig deeper + * and you will find it. + * + */ + +#if defined(__DJGPP__) || defined(__GO32__) +# if defined(__DJGPP__) && (__DJGPP__ > 1) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__SALFORDC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__BORLANDC__) +# if (__BORLANDC__ < 0x520) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TURBOC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__WATCOMC__) +# if defined(__386__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__POCC__) +# if (__POCC__ < 280) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# elif defined(_MSC_VER) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__LCC__) +# if defined(__e2k__) /* MCST eLbrus C Compiler */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# else /* Local (or Little) C Compiler */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# endif + +#elif defined(__SYMBIAN32__) +# if defined(__EABI__) /* Treat all ARM compilers equally */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__CW32__) +# pragma longlong on +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__VC32__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__MWERKS__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(_WIN32_WCE) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__MINGW32__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_WS2TCPIP_H 1 + +#elif defined(__VMS) +# if defined(__VAX) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__OS400__) +# if defined(__ILEC400__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__MVS__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# elif defined(_LP64) +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__370__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# elif defined(_LP64) +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(TPF) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TINYC__) /* also known as tcc */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */ +# if !defined(__LP64) && (defined(__ILP32) || \ + defined(__i386) || \ + defined(__sparcv8) || \ + defined(__sparcv8plus)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64) || \ + defined(__amd64) || defined(__sparcv9) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__xlc__) /* IBM xlc compiler */ +# if !defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +/* ===================================== */ +/* KEEP MSVC THE PENULTIMATE ENTRY */ +/* ===================================== */ + +#elif defined(_MSC_VER) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +/* ===================================== */ +/* KEEP GENERIC GCC THE LAST ENTRY */ +/* ===================================== */ + +#elif defined(__GNUC__) && !defined(_SCO_DS) +# if !defined(__LP64__) && \ + (defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \ + defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \ + defined(__sparc__) || defined(__mips__) || defined(__sh__) || \ + defined(__XTENSA__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64__) || \ + defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \ + defined(__e2k__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#else +/* generic "safe guess" on old 32 bit style */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +#endif + +#ifdef _AIX +/* AIX needs */ +#define CURL_PULL_SYS_POLL_H +#endif + + +/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file */ +/* ws2tcpip.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_WS2TCPIP_H +# include +# include +# include +#endif + +/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */ +/* sys/types.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_TYPES_H +# include +#endif + +/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */ +/* sys/socket.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_SOCKET_H +# include +#endif + +/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */ +/* sys/poll.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_POLL_H +# include +#endif + +/* Data type definition of curl_socklen_t. */ +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T + typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; +#endif + +/* Data type definition of curl_off_t. */ + +#ifdef CURL_TYPEOF_CURL_OFF_T + typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; +#endif + +/* + * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow + * these to be visible and exported by the external libcurl interface API, + * while also making them visible to the library internals, simply including + * curl_setup.h, without actually needing to include curl.h internally. + * If some day this section would grow big enough, all this should be moved + * to its own header file. + */ + +/* + * Figure out if we can use the ## preprocessor operator, which is supported + * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__ + * or __cplusplus so we need to carefully check for them too. + */ + +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ + defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \ + defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \ + defined(__ILEC400__) + /* This compiler is believed to have an ISO compatible preprocessor */ +#define CURL_ISOCPP +#else + /* This compiler is believed NOT to have an ISO compatible preprocessor */ +#undef CURL_ISOCPP +#endif + +/* + * Macros for minimum-width signed and unsigned curl_off_t integer constants. + */ + +#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551) +# define CURLINC_OFF_T_C_HLPR2(x) x +# define CURLINC_OFF_T_C_HLPR1(x) CURLINC_OFF_T_C_HLPR2(x) +# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \ + CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \ + CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU) +#else +# ifdef CURL_ISOCPP +# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix +# else +# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix +# endif +# define CURLINC_OFF_T_C_HLPR1(Val,Suffix) CURLINC_OFF_T_C_HLPR2(Val,Suffix) +# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU) +#endif + +#endif /* CURLINC_SYSTEM_H */ diff --git a/src/drivers/win/curl/x86/include/curl/typecheck-gcc.h b/src/drivers/win/curl/x86/include/curl/typecheck-gcc.h new file mode 100644 index 000000000..34d0267ed --- /dev/null +++ b/src/drivers/win/curl/x86/include/curl/typecheck-gcc.h @@ -0,0 +1,705 @@ +#ifndef CURLINC_TYPECHECK_GCC_H +#define CURLINC_TYPECHECK_GCC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* wraps curl_easy_setopt() with typechecking */ + +/* To add a new kind of warning, add an + * if(curlcheck_sometype_option(_curl_opt)) + * if(!curlcheck_sometype(value)) + * _curl_easy_setopt_err_sometype(); + * block and define curlcheck_sometype_option, curlcheck_sometype and + * _curl_easy_setopt_err_sometype below + * + * NOTE: We use two nested 'if' statements here instead of the && operator, in + * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x + * when compiling with -Wlogical-op. + * + * To add an option that uses the same type as an existing option, you'll just + * need to extend the appropriate _curl_*_option macro + */ +#define curl_easy_setopt(handle, option, value) \ + __extension__({ \ + __typeof__(option) _curl_opt = option; \ + if(__builtin_constant_p(_curl_opt)) { \ + if(curlcheck_long_option(_curl_opt)) \ + if(!curlcheck_long(value)) \ + _curl_easy_setopt_err_long(); \ + if(curlcheck_off_t_option(_curl_opt)) \ + if(!curlcheck_off_t(value)) \ + _curl_easy_setopt_err_curl_off_t(); \ + if(curlcheck_string_option(_curl_opt)) \ + if(!curlcheck_string(value)) \ + _curl_easy_setopt_err_string(); \ + if(curlcheck_write_cb_option(_curl_opt)) \ + if(!curlcheck_write_cb(value)) \ + _curl_easy_setopt_err_write_callback(); \ + if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \ + if(!curlcheck_resolver_start_callback(value)) \ + _curl_easy_setopt_err_resolver_start_callback(); \ + if((_curl_opt) == CURLOPT_READFUNCTION) \ + if(!curlcheck_read_cb(value)) \ + _curl_easy_setopt_err_read_cb(); \ + if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \ + if(!curlcheck_ioctl_cb(value)) \ + _curl_easy_setopt_err_ioctl_cb(); \ + if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \ + if(!curlcheck_sockopt_cb(value)) \ + _curl_easy_setopt_err_sockopt_cb(); \ + if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \ + if(!curlcheck_opensocket_cb(value)) \ + _curl_easy_setopt_err_opensocket_cb(); \ + if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \ + if(!curlcheck_progress_cb(value)) \ + _curl_easy_setopt_err_progress_cb(); \ + if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \ + if(!curlcheck_debug_cb(value)) \ + _curl_easy_setopt_err_debug_cb(); \ + if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \ + if(!curlcheck_ssl_ctx_cb(value)) \ + _curl_easy_setopt_err_ssl_ctx_cb(); \ + if(curlcheck_conv_cb_option(_curl_opt)) \ + if(!curlcheck_conv_cb(value)) \ + _curl_easy_setopt_err_conv_cb(); \ + if((_curl_opt) == CURLOPT_SEEKFUNCTION) \ + if(!curlcheck_seek_cb(value)) \ + _curl_easy_setopt_err_seek_cb(); \ + if(curlcheck_cb_data_option(_curl_opt)) \ + if(!curlcheck_cb_data(value)) \ + _curl_easy_setopt_err_cb_data(); \ + if((_curl_opt) == CURLOPT_ERRORBUFFER) \ + if(!curlcheck_error_buffer(value)) \ + _curl_easy_setopt_err_error_buffer(); \ + if((_curl_opt) == CURLOPT_STDERR) \ + if(!curlcheck_FILE(value)) \ + _curl_easy_setopt_err_FILE(); \ + if(curlcheck_postfields_option(_curl_opt)) \ + if(!curlcheck_postfields(value)) \ + _curl_easy_setopt_err_postfields(); \ + if((_curl_opt) == CURLOPT_HTTPPOST) \ + if(!curlcheck_arr((value), struct curl_httppost)) \ + _curl_easy_setopt_err_curl_httpost(); \ + if((_curl_opt) == CURLOPT_MIMEPOST) \ + if(!curlcheck_ptr((value), curl_mime)) \ + _curl_easy_setopt_err_curl_mimepost(); \ + if(curlcheck_slist_option(_curl_opt)) \ + if(!curlcheck_arr((value), struct curl_slist)) \ + _curl_easy_setopt_err_curl_slist(); \ + if((_curl_opt) == CURLOPT_SHARE) \ + if(!curlcheck_ptr((value), CURLSH)) \ + _curl_easy_setopt_err_CURLSH(); \ + } \ + curl_easy_setopt(handle, _curl_opt, value); \ + }) + +/* wraps curl_easy_getinfo() with typechecking */ +#define curl_easy_getinfo(handle, info, arg) \ + __extension__({ \ + __typeof__(info) _curl_info = info; \ + if(__builtin_constant_p(_curl_info)) { \ + if(curlcheck_string_info(_curl_info)) \ + if(!curlcheck_arr((arg), char *)) \ + _curl_easy_getinfo_err_string(); \ + if(curlcheck_long_info(_curl_info)) \ + if(!curlcheck_arr((arg), long)) \ + _curl_easy_getinfo_err_long(); \ + if(curlcheck_double_info(_curl_info)) \ + if(!curlcheck_arr((arg), double)) \ + _curl_easy_getinfo_err_double(); \ + if(curlcheck_slist_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_slist *)) \ + _curl_easy_getinfo_err_curl_slist(); \ + if(curlcheck_tlssessioninfo_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \ + _curl_easy_getinfo_err_curl_tlssesssioninfo(); \ + if(curlcheck_certinfo_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_certinfo *)) \ + _curl_easy_getinfo_err_curl_certinfo(); \ + if(curlcheck_socket_info(_curl_info)) \ + if(!curlcheck_arr((arg), curl_socket_t)) \ + _curl_easy_getinfo_err_curl_socket(); \ + if(curlcheck_off_t_info(_curl_info)) \ + if(!curlcheck_arr((arg), curl_off_t)) \ + _curl_easy_getinfo_err_curl_off_t(); \ + } \ + curl_easy_getinfo(handle, _curl_info, arg); \ + }) + +/* + * For now, just make sure that the functions are called with three arguments + */ +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) + + +/* the actual warnings, triggered by calling the _curl_easy_setopt_err* + * functions */ + +/* To define a new warning, use _CURL_WARNING(identifier, "message") */ +#define CURLWARNING(id, message) \ + static void __attribute__((__warning__(message))) \ + __attribute__((__unused__)) __attribute__((__noinline__)) \ + id(void) { __asm__(""); } + +CURLWARNING(_curl_easy_setopt_err_long, + "curl_easy_setopt expects a long argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_off_t, + "curl_easy_setopt expects a curl_off_t argument for this option") +CURLWARNING(_curl_easy_setopt_err_string, + "curl_easy_setopt expects a " + "string ('char *' or char[]) argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_write_callback, + "curl_easy_setopt expects a curl_write_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_resolver_start_callback, + "curl_easy_setopt expects a " + "curl_resolver_start_callback argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_read_cb, + "curl_easy_setopt expects a curl_read_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_ioctl_cb, + "curl_easy_setopt expects a curl_ioctl_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_sockopt_cb, + "curl_easy_setopt expects a curl_sockopt_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_opensocket_cb, + "curl_easy_setopt expects a " + "curl_opensocket_callback argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_progress_cb, + "curl_easy_setopt expects a curl_progress_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_debug_cb, + "curl_easy_setopt expects a curl_debug_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_ssl_ctx_cb, + "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_conv_cb, + "curl_easy_setopt expects a curl_conv_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_seek_cb, + "curl_easy_setopt expects a curl_seek_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_cb_data, + "curl_easy_setopt expects a " + "private data pointer as argument for this option") +CURLWARNING(_curl_easy_setopt_err_error_buffer, + "curl_easy_setopt expects a " + "char buffer of CURL_ERROR_SIZE as argument for this option") +CURLWARNING(_curl_easy_setopt_err_FILE, + "curl_easy_setopt expects a 'FILE *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_postfields, + "curl_easy_setopt expects a 'void *' or 'char *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_httpost, + "curl_easy_setopt expects a 'struct curl_httppost *' " + "argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_mimepost, + "curl_easy_setopt expects a 'curl_mime *' " + "argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_slist, + "curl_easy_setopt expects a 'struct curl_slist *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_CURLSH, + "curl_easy_setopt expects a CURLSH* argument for this option") + +CURLWARNING(_curl_easy_getinfo_err_string, + "curl_easy_getinfo expects a pointer to 'char *' for this info") +CURLWARNING(_curl_easy_getinfo_err_long, + "curl_easy_getinfo expects a pointer to long for this info") +CURLWARNING(_curl_easy_getinfo_err_double, + "curl_easy_getinfo expects a pointer to double for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_slist, + "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_tlssessioninfo *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_certinfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_certinfo *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_socket, + "curl_easy_getinfo expects a pointer to curl_socket_t for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_off_t, + "curl_easy_getinfo expects a pointer to curl_off_t for this info") + +/* groups of curl_easy_setops options that take the same type of argument */ + +/* To add a new option to one of the groups, just add + * (option) == CURLOPT_SOMETHING + * to the or-expression. If the option takes a long or curl_off_t, you don't + * have to do anything + */ + +/* evaluates to true if option takes a long argument */ +#define curlcheck_long_option(option) \ + (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT) + +#define curlcheck_off_t_option(option) \ + (((option) > CURLOPTTYPE_OFF_T) && ((option) < CURLOPTTYPE_BLOB)) + +/* evaluates to true if option takes a char* argument */ +#define curlcheck_string_option(option) \ + ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \ + (option) == CURLOPT_ACCEPT_ENCODING || \ + (option) == CURLOPT_ALTSVC || \ + (option) == CURLOPT_CAINFO || \ + (option) == CURLOPT_CAPATH || \ + (option) == CURLOPT_COOKIE || \ + (option) == CURLOPT_COOKIEFILE || \ + (option) == CURLOPT_COOKIEJAR || \ + (option) == CURLOPT_COOKIELIST || \ + (option) == CURLOPT_CRLFILE || \ + (option) == CURLOPT_CUSTOMREQUEST || \ + (option) == CURLOPT_DEFAULT_PROTOCOL || \ + (option) == CURLOPT_DNS_INTERFACE || \ + (option) == CURLOPT_DNS_LOCAL_IP4 || \ + (option) == CURLOPT_DNS_LOCAL_IP6 || \ + (option) == CURLOPT_DNS_SERVERS || \ + (option) == CURLOPT_DOH_URL || \ + (option) == CURLOPT_EGDSOCKET || \ + (option) == CURLOPT_FTPPORT || \ + (option) == CURLOPT_FTP_ACCOUNT || \ + (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \ + (option) == CURLOPT_HSTS || \ + (option) == CURLOPT_INTERFACE || \ + (option) == CURLOPT_ISSUERCERT || \ + (option) == CURLOPT_KEYPASSWD || \ + (option) == CURLOPT_KRBLEVEL || \ + (option) == CURLOPT_LOGIN_OPTIONS || \ + (option) == CURLOPT_MAIL_AUTH || \ + (option) == CURLOPT_MAIL_FROM || \ + (option) == CURLOPT_NETRC_FILE || \ + (option) == CURLOPT_NOPROXY || \ + (option) == CURLOPT_PASSWORD || \ + (option) == CURLOPT_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PRE_PROXY || \ + (option) == CURLOPT_PROXY || \ + (option) == CURLOPT_PROXYPASSWORD || \ + (option) == CURLOPT_PROXYUSERNAME || \ + (option) == CURLOPT_PROXYUSERPWD || \ + (option) == CURLOPT_PROXY_CAINFO || \ + (option) == CURLOPT_PROXY_CAPATH || \ + (option) == CURLOPT_PROXY_CRLFILE || \ + (option) == CURLOPT_PROXY_ISSUERCERT || \ + (option) == CURLOPT_PROXY_KEYPASSWD || \ + (option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PROXY_SERVICE_NAME || \ + (option) == CURLOPT_PROXY_SSLCERT || \ + (option) == CURLOPT_PROXY_SSLCERTTYPE || \ + (option) == CURLOPT_PROXY_SSLKEY || \ + (option) == CURLOPT_PROXY_SSLKEYTYPE || \ + (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \ + (option) == CURLOPT_PROXY_TLS13_CIPHERS || \ + (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_PROXY_TLSAUTH_TYPE || \ + (option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \ + (option) == CURLOPT_RANDOM_FILE || \ + (option) == CURLOPT_RANGE || \ + (option) == CURLOPT_REFERER || \ + (option) == CURLOPT_REQUEST_TARGET || \ + (option) == CURLOPT_RTSP_SESSION_ID || \ + (option) == CURLOPT_RTSP_STREAM_URI || \ + (option) == CURLOPT_RTSP_TRANSPORT || \ + (option) == CURLOPT_SASL_AUTHZID || \ + (option) == CURLOPT_SERVICE_NAME || \ + (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ + (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \ + (option) == CURLOPT_SSH_KNOWNHOSTS || \ + (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ + (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \ + (option) == CURLOPT_SSLCERT || \ + (option) == CURLOPT_SSLCERTTYPE || \ + (option) == CURLOPT_SSLENGINE || \ + (option) == CURLOPT_SSLKEY || \ + (option) == CURLOPT_SSLKEYTYPE || \ + (option) == CURLOPT_SSL_CIPHER_LIST || \ + (option) == CURLOPT_TLS13_CIPHERS || \ + (option) == CURLOPT_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_TLSAUTH_TYPE || \ + (option) == CURLOPT_TLSAUTH_USERNAME || \ + (option) == CURLOPT_UNIX_SOCKET_PATH || \ + (option) == CURLOPT_URL || \ + (option) == CURLOPT_USERAGENT || \ + (option) == CURLOPT_USERNAME || \ + (option) == CURLOPT_AWS_SIGV4 || \ + (option) == CURLOPT_USERPWD || \ + (option) == CURLOPT_XOAUTH2_BEARER || \ + (option) == CURLOPT_SSL_EC_CURVES || \ + 0) + +/* evaluates to true if option takes a curl_write_callback argument */ +#define curlcheck_write_cb_option(option) \ + ((option) == CURLOPT_HEADERFUNCTION || \ + (option) == CURLOPT_WRITEFUNCTION) + +/* evaluates to true if option takes a curl_conv_callback argument */ +#define curlcheck_conv_cb_option(option) \ + ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION) + +/* evaluates to true if option takes a data argument to pass to a callback */ +#define curlcheck_cb_data_option(option) \ + ((option) == CURLOPT_CHUNK_DATA || \ + (option) == CURLOPT_CLOSESOCKETDATA || \ + (option) == CURLOPT_DEBUGDATA || \ + (option) == CURLOPT_FNMATCH_DATA || \ + (option) == CURLOPT_HEADERDATA || \ + (option) == CURLOPT_HSTSREADDATA || \ + (option) == CURLOPT_HSTSWRITEDATA || \ + (option) == CURLOPT_INTERLEAVEDATA || \ + (option) == CURLOPT_IOCTLDATA || \ + (option) == CURLOPT_OPENSOCKETDATA || \ + (option) == CURLOPT_PROGRESSDATA || \ + (option) == CURLOPT_READDATA || \ + (option) == CURLOPT_SEEKDATA || \ + (option) == CURLOPT_SOCKOPTDATA || \ + (option) == CURLOPT_SSH_KEYDATA || \ + (option) == CURLOPT_SSL_CTX_DATA || \ + (option) == CURLOPT_WRITEDATA || \ + (option) == CURLOPT_RESOLVER_START_DATA || \ + (option) == CURLOPT_TRAILERDATA || \ + 0) + +/* evaluates to true if option takes a POST data argument (void* or char*) */ +#define curlcheck_postfields_option(option) \ + ((option) == CURLOPT_POSTFIELDS || \ + (option) == CURLOPT_COPYPOSTFIELDS || \ + 0) + +/* evaluates to true if option takes a struct curl_slist * argument */ +#define curlcheck_slist_option(option) \ + ((option) == CURLOPT_HTTP200ALIASES || \ + (option) == CURLOPT_HTTPHEADER || \ + (option) == CURLOPT_MAIL_RCPT || \ + (option) == CURLOPT_POSTQUOTE || \ + (option) == CURLOPT_PREQUOTE || \ + (option) == CURLOPT_PROXYHEADER || \ + (option) == CURLOPT_QUOTE || \ + (option) == CURLOPT_RESOLVE || \ + (option) == CURLOPT_TELNETOPTIONS || \ + (option) == CURLOPT_CONNECT_TO || \ + 0) + +/* groups of curl_easy_getinfo infos that take the same type of argument */ + +/* evaluates to true if info expects a pointer to char * argument */ +#define curlcheck_string_info(info) \ + (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG && \ + (info) != CURLINFO_PRIVATE) + +/* evaluates to true if info expects a pointer to long argument */ +#define curlcheck_long_info(info) \ + (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE) + +/* evaluates to true if info expects a pointer to double argument */ +#define curlcheck_double_info(info) \ + (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST) + +/* true if info expects a pointer to struct curl_slist * argument */ +#define curlcheck_slist_info(info) \ + (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST)) + +/* true if info expects a pointer to struct curl_tlssessioninfo * argument */ +#define curlcheck_tlssessioninfo_info(info) \ + (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION)) + +/* true if info expects a pointer to struct curl_certinfo * argument */ +#define curlcheck_certinfo_info(info) ((info) == CURLINFO_CERTINFO) + +/* true if info expects a pointer to struct curl_socket_t argument */ +#define curlcheck_socket_info(info) \ + (CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T) + +/* true if info expects a pointer to curl_off_t argument */ +#define curlcheck_off_t_info(info) \ + (CURLINFO_OFF_T < (info)) + + +/* typecheck helpers -- check whether given expression has requested type*/ + +/* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros, + * otherwise define a new macro. Search for __builtin_types_compatible_p + * in the GCC manual. + * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is + * the actual expression passed to the curl_easy_setopt macro. This + * means that you can only apply the sizeof and __typeof__ operators, no + * == or whatsoever. + */ + +/* XXX: should evaluate to true if expr is a pointer */ +#define curlcheck_any_ptr(expr) \ + (sizeof(expr) == sizeof(void *)) + +/* evaluates to true if expr is NULL */ +/* XXX: must not evaluate expr, so this check is not accurate */ +#define curlcheck_NULL(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL))) + +/* evaluates to true if expr is type*, const type* or NULL */ +#define curlcheck_ptr(expr, type) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), type *) || \ + __builtin_types_compatible_p(__typeof__(expr), const type *)) + +/* evaluates to true if expr is one of type[], type*, NULL or const type* */ +#define curlcheck_arr(expr, type) \ + (curlcheck_ptr((expr), type) || \ + __builtin_types_compatible_p(__typeof__(expr), type [])) + +/* evaluates to true if expr is a string */ +#define curlcheck_string(expr) \ + (curlcheck_arr((expr), char) || \ + curlcheck_arr((expr), signed char) || \ + curlcheck_arr((expr), unsigned char)) + +/* evaluates to true if expr is a long (no matter the signedness) + * XXX: for now, int is also accepted (and therefore short and char, which + * are promoted to int when passed to a variadic function) */ +#define curlcheck_long(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), long) || \ + __builtin_types_compatible_p(__typeof__(expr), signed long) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \ + __builtin_types_compatible_p(__typeof__(expr), int) || \ + __builtin_types_compatible_p(__typeof__(expr), signed int) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \ + __builtin_types_compatible_p(__typeof__(expr), short) || \ + __builtin_types_compatible_p(__typeof__(expr), signed short) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \ + __builtin_types_compatible_p(__typeof__(expr), char) || \ + __builtin_types_compatible_p(__typeof__(expr), signed char) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned char)) + +/* evaluates to true if expr is of type curl_off_t */ +#define curlcheck_off_t(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), curl_off_t)) + +/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */ +/* XXX: also check size of an char[] array? */ +#define curlcheck_error_buffer(expr) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), char *) || \ + __builtin_types_compatible_p(__typeof__(expr), char[])) + +/* evaluates to true if expr is of type (const) void* or (const) FILE* */ +#if 0 +#define curlcheck_cb_data(expr) \ + (curlcheck_ptr((expr), void) || \ + curlcheck_ptr((expr), FILE)) +#else /* be less strict */ +#define curlcheck_cb_data(expr) \ + curlcheck_any_ptr(expr) +#endif + +/* evaluates to true if expr is of type FILE* */ +#define curlcheck_FILE(expr) \ + (curlcheck_NULL(expr) || \ + (__builtin_types_compatible_p(__typeof__(expr), FILE *))) + +/* evaluates to true if expr can be passed as POST data (void* or char*) */ +#define curlcheck_postfields(expr) \ + (curlcheck_ptr((expr), void) || \ + curlcheck_arr((expr), char) || \ + curlcheck_arr((expr), unsigned char)) + +/* helper: __builtin_types_compatible_p distinguishes between functions and + * function pointers, hide it */ +#define curlcheck_cb_compatible(func, type) \ + (__builtin_types_compatible_p(__typeof__(func), type) || \ + __builtin_types_compatible_p(__typeof__(func) *, type)) + +/* evaluates to true if expr is of type curl_resolver_start_callback */ +#define curlcheck_resolver_start_callback(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_resolver_start_callback)) + +/* evaluates to true if expr is of type curl_read_callback or "similar" */ +#define curlcheck_read_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), __typeof__(fread) *) || \ + curlcheck_cb_compatible((expr), curl_read_callback) || \ + curlcheck_cb_compatible((expr), _curl_read_callback1) || \ + curlcheck_cb_compatible((expr), _curl_read_callback2) || \ + curlcheck_cb_compatible((expr), _curl_read_callback3) || \ + curlcheck_cb_compatible((expr), _curl_read_callback4) || \ + curlcheck_cb_compatible((expr), _curl_read_callback5) || \ + curlcheck_cb_compatible((expr), _curl_read_callback6)) +typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *); +typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_write_callback or "similar" */ +#define curlcheck_write_cb(expr) \ + (curlcheck_read_cb(expr) || \ + curlcheck_cb_compatible((expr), __typeof__(fwrite) *) || \ + curlcheck_cb_compatible((expr), curl_write_callback) || \ + curlcheck_cb_compatible((expr), _curl_write_callback1) || \ + curlcheck_cb_compatible((expr), _curl_write_callback2) || \ + curlcheck_cb_compatible((expr), _curl_write_callback3) || \ + curlcheck_cb_compatible((expr), _curl_write_callback4) || \ + curlcheck_cb_compatible((expr), _curl_write_callback5) || \ + curlcheck_cb_compatible((expr), _curl_write_callback6)) +typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *); +typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */ +#define curlcheck_ioctl_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_ioctl_callback) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback1) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback2) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback3) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback4)) +typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *); +typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *); +typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *); +typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *); + +/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ +#define curlcheck_sockopt_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_sockopt_callback) || \ + curlcheck_cb_compatible((expr), _curl_sockopt_callback1) || \ + curlcheck_cb_compatible((expr), _curl_sockopt_callback2)) +typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); +typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t, + curlsocktype); + +/* evaluates to true if expr is of type curl_opensocket_callback or + "similar" */ +#define curlcheck_opensocket_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_opensocket_callback) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback1) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback2) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback3) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback4)) +typedef curl_socket_t (*_curl_opensocket_callback1) + (void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback2) + (void *, curlsocktype, const struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback3) + (const void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback4) + (const void *, curlsocktype, const struct curl_sockaddr *); + +/* evaluates to true if expr is of type curl_progress_callback or "similar" */ +#define curlcheck_progress_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_progress_callback) || \ + curlcheck_cb_compatible((expr), _curl_progress_callback1) || \ + curlcheck_cb_compatible((expr), _curl_progress_callback2)) +typedef int (*_curl_progress_callback1)(void *, + double, double, double, double); +typedef int (*_curl_progress_callback2)(const void *, + double, double, double, double); + +/* evaluates to true if expr is of type curl_debug_callback or "similar" */ +#define curlcheck_debug_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_debug_callback) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback1) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback2) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback3) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback4) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback5) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback6) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback7) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback8)) +typedef int (*_curl_debug_callback1) (CURL *, + curl_infotype, char *, size_t, void *); +typedef int (*_curl_debug_callback2) (CURL *, + curl_infotype, char *, size_t, const void *); +typedef int (*_curl_debug_callback3) (CURL *, + curl_infotype, const char *, size_t, void *); +typedef int (*_curl_debug_callback4) (CURL *, + curl_infotype, const char *, size_t, const void *); +typedef int (*_curl_debug_callback5) (CURL *, + curl_infotype, unsigned char *, size_t, void *); +typedef int (*_curl_debug_callback6) (CURL *, + curl_infotype, unsigned char *, size_t, const void *); +typedef int (*_curl_debug_callback7) (CURL *, + curl_infotype, const unsigned char *, size_t, void *); +typedef int (*_curl_debug_callback8) (CURL *, + curl_infotype, const unsigned char *, size_t, const void *); + +/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */ +/* this is getting even messier... */ +#define curlcheck_ssl_ctx_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_ssl_ctx_callback) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback1) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback2) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback3) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback4) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback5) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback6) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback7) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback8)) +typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *, + const void *); +#ifdef HEADER_SSL_H +/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX + * this will of course break if we're included before OpenSSL headers... + */ +typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX *, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX *, + const void *); +#else +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8; +#endif + +/* evaluates to true if expr is of type curl_conv_callback or "similar" */ +#define curlcheck_conv_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_conv_callback) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback1) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback2) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback3) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback4)) +typedef CURLcode (*_curl_conv_callback1)(char *, size_t length); +typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length); +typedef CURLcode (*_curl_conv_callback3)(void *, size_t length); +typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length); + +/* evaluates to true if expr is of type curl_seek_callback or "similar" */ +#define curlcheck_seek_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_seek_callback) || \ + curlcheck_cb_compatible((expr), _curl_seek_callback1) || \ + curlcheck_cb_compatible((expr), _curl_seek_callback2)) +typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int); +typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int); + + +#endif /* CURLINC_TYPECHECK_GCC_H */ diff --git a/src/drivers/win/curl/x86/include/curl/urlapi.h b/src/drivers/win/curl/x86/include/curl/urlapi.h new file mode 100644 index 000000000..1d7088011 --- /dev/null +++ b/src/drivers/win/curl/x86/include/curl/urlapi.h @@ -0,0 +1,126 @@ +#ifndef CURLINC_URLAPI_H +#define CURLINC_URLAPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* the error codes for the URL API */ +typedef enum { + CURLUE_OK, + CURLUE_BAD_HANDLE, /* 1 */ + CURLUE_BAD_PARTPOINTER, /* 2 */ + CURLUE_MALFORMED_INPUT, /* 3 */ + CURLUE_BAD_PORT_NUMBER, /* 4 */ + CURLUE_UNSUPPORTED_SCHEME, /* 5 */ + CURLUE_URLDECODE, /* 6 */ + CURLUE_OUT_OF_MEMORY, /* 7 */ + CURLUE_USER_NOT_ALLOWED, /* 8 */ + CURLUE_UNKNOWN_PART, /* 9 */ + CURLUE_NO_SCHEME, /* 10 */ + CURLUE_NO_USER, /* 11 */ + CURLUE_NO_PASSWORD, /* 12 */ + CURLUE_NO_OPTIONS, /* 13 */ + CURLUE_NO_HOST, /* 14 */ + CURLUE_NO_PORT, /* 15 */ + CURLUE_NO_QUERY, /* 16 */ + CURLUE_NO_FRAGMENT /* 17 */ +} CURLUcode; + +typedef enum { + CURLUPART_URL, + CURLUPART_SCHEME, + CURLUPART_USER, + CURLUPART_PASSWORD, + CURLUPART_OPTIONS, + CURLUPART_HOST, + CURLUPART_PORT, + CURLUPART_PATH, + CURLUPART_QUERY, + CURLUPART_FRAGMENT, + CURLUPART_ZONEID /* added in 7.65.0 */ +} CURLUPart; + +#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */ +#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set, + if the port number matches the + default for the scheme */ +#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if + missing */ +#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */ +#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */ +#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */ +#define CURLU_URLDECODE (1<<6) /* URL decode on get */ +#define CURLU_URLENCODE (1<<7) /* URL encode on set */ +#define CURLU_APPENDQUERY (1<<8) /* append a form style part */ +#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */ +#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the + scheme is unknown. */ +#define CURLU_ALLOW_SPACE (1<<11) /* Allow spaces in the URL */ + +typedef struct Curl_URL CURLU; + +/* + * curl_url() creates a new CURLU handle and returns a pointer to it. + * Must be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url(void); + +/* + * curl_url_cleanup() frees the CURLU handle and related resources used for + * the URL parsing. It will not free strings previously returned with the URL + * API. + */ +CURL_EXTERN void curl_url_cleanup(CURLU *handle); + +/* + * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new + * handle must also be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url_dup(CURLU *in); + +/* + * curl_url_get() extracts a specific part of the URL from a CURLU + * handle. Returns error code. The returned pointer MUST be freed with + * curl_free() afterwards. + */ +CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what, + char **part, unsigned int flags); + +/* + * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns + * error code. The passed in string will be copied. Passing a NULL instead of + * a part string, clears that part. + */ +CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what, + const char *part, unsigned int flags); + + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* CURLINC_URLAPI_H */ diff --git a/src/drivers/win/curl/x86/lib/libcurl_a.lib b/src/drivers/win/curl/x86/lib/libcurl_a.lib new file mode 100644 index 000000000..274cf9b53 Binary files /dev/null and b/src/drivers/win/curl/x86/lib/libcurl_a.lib differ diff --git a/src/drivers/win/memview.cpp b/src/drivers/win/memview.cpp index 70b8b704b..f5d158d56 100644 --- a/src/drivers/win/memview.cpp +++ b/src/drivers/win/memview.cpp @@ -1,22 +1,22 @@ /* FCE Ultra - NES/Famicom Emulator -* -* Copyright notice for this file: -* Copyright (C) 2002 Ben Parnell -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ + * + * Copyright notice for this file: + * Copyright (C) 2002 Ben Parnell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ #include @@ -40,9 +40,9 @@ #include "Win32InputBox.h" #include "utils/xstring.h" -extern Name* lastBankNames; -extern Name* loadedBankNames; -extern Name* ramBankNames; +extern Name *lastBankNames; +extern Name *loadedBankNames; +extern Name *ramBankNames; extern int RegNameCount; extern MemoryMappedRegister RegNames[]; @@ -53,133 +53,123 @@ extern bool JustFrameAdvanced; using namespace std; -#define MODE_NES_MEMORY 0 -#define MODE_NES_PPU 1 -#define MODE_NES_OAM 2 -#define MODE_NES_FILE 3 - -#define ID_ADDRESS_FRZ_SUBMENU 1 -#define ID_ADDRESS_ADDBP_R 2 -#define ID_ADDRESS_ADDBP_W 3 -#define ID_ADDRESS_ADDBP_X 4 -#define ID_ADDRESS_SEEK_IN_ROM 5 -#define ID_ADDRESS_CREATE_GG_CODE 6 -#define ID_ADDRESS_ADD_BOOKMARK 20 -#define ID_ADDRESS_REMOVE_BOOKMARK 21 -#define ID_ADDRESS_EDIT_BOOKMARK 22 -#define ID_ADDRESS_SYMBOLIC_NAME 30 -#define BOOKMARKS_SUBMENU_POS 4 - -#define ID_ADDRESS_FRZ_TOGGLE_STATE 1 -#define ID_ADDRESS_FRZ_FREEZE 50 -#define ID_ADDRESS_FRZ_UNFREEZE 51 -#define ID_ADDRESS_FRZ_SEP 52 -#define ID_ADDRESS_FRZ_UNFREEZE_ALL 53 - -#define HIGHLIGHTING_SUBMENU_POS 3 -#define HEXEDITOR_COLOR_SUBMENU_POS 4 -#define CDLOGGER_COLOR_SUBMENU_POS 5 -#define ID_COLOR_HEXEDITOR 600 -#define ID_COLOR_CDLOGGER 650 +#define MODE_NES_MEMORY 0 +#define MODE_NES_PPU 1 +#define MODE_NES_OAM 2 +#define MODE_NES_FILE 3 + +#define ID_ADDRESS_FRZ_SUBMENU 1 +#define ID_ADDRESS_ADDBP_R 2 +#define ID_ADDRESS_ADDBP_W 3 +#define ID_ADDRESS_ADDBP_X 4 +#define ID_ADDRESS_SEEK_IN_ROM 5 +#define ID_ADDRESS_CREATE_GG_CODE 6 +#define ID_ADDRESS_ADD_BOOKMARK 20 +#define ID_ADDRESS_REMOVE_BOOKMARK 21 +#define ID_ADDRESS_EDIT_BOOKMARK 22 +#define ID_ADDRESS_SYMBOLIC_NAME 30 +#define BOOKMARKS_SUBMENU_POS 4 + +#define ID_ADDRESS_FRZ_TOGGLE_STATE 1 +#define ID_ADDRESS_FRZ_FREEZE 50 +#define ID_ADDRESS_FRZ_UNFREEZE 51 +#define ID_ADDRESS_FRZ_SEP 52 +#define ID_ADDRESS_FRZ_UNFREEZE_ALL 53 + +#define HIGHLIGHTING_SUBMENU_POS 3 +#define HEXEDITOR_COLOR_SUBMENU_POS 4 +#define CDLOGGER_COLOR_SUBMENU_POS 5 +#define ID_COLOR_HEXEDITOR 600 +#define ID_COLOR_CDLOGGER 650 #define HIGHLIGHT_ACTIVITY_MIN_VALUE 0 #define HIGHLIGHT_ACTIVITY_NUM_COLORS 16 #define PREVIOUS_VALUE_UNDEFINED -1 -COLORREF highlightActivityColors[HIGHLIGHT_ACTIVITY_NUM_COLORS] = { 0x0, 0x004035, 0x185218, 0x5e5c34, 0x804c00, 0xba0300, 0xd10038, 0xb21272, 0xba00ab, 0x6f00b0, 0x3700c2, 0x000cba, 0x002cc9, 0x0053bf, 0x0072cf, 0x3c8bc7 }; +COLORREF highlightActivityColors[HIGHLIGHT_ACTIVITY_NUM_COLORS] = {0x0, 0x004035, 0x185218, 0x5e5c34, 0x804c00, 0xba0300, 0xd10038, 0xb21272, 0xba00ab, 0x6f00b0, 0x3700c2, 0x000cba, 0x002cc9, 0x0053bf, 0x0072cf, 0x3c8bc7}; -COLORREF custom_color[16] = { 0 }; // User defined color for ChooseColor() +COLORREF custom_color[16] = {0}; // User defined color for ChooseColor() -string memviewhelp = "HexEditor"; //Hex Editor Help Page +string memviewhelp = "HexEditor"; // Hex Editor Help Page -int HexRowHeightBorder = 0; //adelikat: This will determine the number of pixels between rows in the hex editor, to alter this, the user can change it in the .cfg file, changing one will revert to the way FCEUX2.1.0 did it -int HexCharSpacing = 1; // pixels between chars +int HexRowHeightBorder = 0; // adelikat: This will determine the number of pixels between rows in the hex editor, to alter this, the user can change it in the .cfg file, changing one will revert to the way FCEUX2.1.0 did it +int HexCharSpacing = 1; // pixels between chars int DefHexRGB, DefCdlRGB; // This defines all of our right click popup menus struct { - int minaddress; //The minimum address where this popup will appear - int maxaddress; //The maximum address where this popup will appear - int editingmode; //The editing mode which this popup appears in - int id; //The menu ID for this popup - char *text; //the text for the menu item (some of these need to be dynamic) -} -popupmenu[] = -{ - {0x0000,0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_SYMBOLIC_NAME, "Add symbolic debug name"}, - {0x0000,0x2000, MODE_NES_MEMORY, ID_ADDRESS_FRZ_SUBMENU, "Freeze/Unfreeze This Address"}, - {0x6000,0x7FFF, MODE_NES_MEMORY, ID_ADDRESS_FRZ_SUBMENU, "Freeze/Unfreeze This Address"}, - {0x0000,0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_ADDBP_R, "Add Debugger Read Breakpoint"}, - {0x0000,0x3FFF, MODE_NES_PPU, ID_ADDRESS_ADDBP_R, "Add Debugger Read Breakpoint"}, - {0x0000,0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_ADDBP_W, "Add Debugger Write Breakpoint"}, - {0x0000,0x3FFF, MODE_NES_PPU, ID_ADDRESS_ADDBP_W, "Add Debugger Write Breakpoint"}, - {0x0000,0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_ADDBP_X, "Add Debugger Execute Breakpoint"}, - {0x8000,0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_SEEK_IN_ROM, "Go Here In ROM File"}, - {0x8000,0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_CREATE_GG_CODE, "Create Game Genie Code At This Address"} -}; + int minaddress; // The minimum address where this popup will appear + int maxaddress; // The maximum address where this popup will appear + int editingmode; // The editing mode which this popup appears in + int id; // The menu ID for this popup + char *text; // the text for the menu item (some of these need to be dynamic) +} popupmenu[] = + { + {0x0000, 0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_SYMBOLIC_NAME, "Add symbolic debug name"}, + {0x0000, 0x2000, MODE_NES_MEMORY, ID_ADDRESS_FRZ_SUBMENU, "Freeze/Unfreeze This Address"}, + {0x6000, 0x7FFF, MODE_NES_MEMORY, ID_ADDRESS_FRZ_SUBMENU, "Freeze/Unfreeze This Address"}, + {0x0000, 0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_ADDBP_R, "Add Debugger Read Breakpoint"}, + {0x0000, 0x3FFF, MODE_NES_PPU, ID_ADDRESS_ADDBP_R, "Add Debugger Read Breakpoint"}, + {0x0000, 0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_ADDBP_W, "Add Debugger Write Breakpoint"}, + {0x0000, 0x3FFF, MODE_NES_PPU, ID_ADDRESS_ADDBP_W, "Add Debugger Write Breakpoint"}, + {0x0000, 0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_ADDBP_X, "Add Debugger Execute Breakpoint"}, + {0x8000, 0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_SEEK_IN_ROM, "Go Here In ROM File"}, + {0x8000, 0xFFFF, MODE_NES_MEMORY, ID_ADDRESS_CREATE_GG_CODE, "Create Game Genie Code At This Address"}}; #define POPUPNUM (sizeof popupmenu / sizeof popupmenu[0]) // The color configure menu COLORMENU hexcolormenu[] = { - { "Normal text", PPRGB(HexFore) }, - { "Address header", PPRGB(HexAddr) }, -// { "Normal text background", PPRGB(HexBack) }, - { NULL }, - { "Selected text", PPRGB(HexHlFore) }, - { "Selected background", PPRGB(HexHlBack) }, - { "Selected text (unfocused)", PPRGB(HexHlShdFore) }, - { "Selected background (unfocused)", PPRGB(HexHlShdBack) }, - { NULL }, - { "Freezed address", PPRGB(HexFreeze), }, -// { "Freezed ROM address", PPRGB(RomFreeze), }, - { "Bookmark", PPRGB(HexBookmark) } -}, -cdlcolormenu[] = { - { "Code", PPRGB(CdlCode) }, - { "Data", PPRGB(CdlData) }, - { "PCM Data", PPRGB(CdlPcm) }, - { "Code && Data", PPRGB(CdlCodeData) }, - { NULL }, - { "Render", PPRGB(CdlRender) }, - { "Read", PPRGB(CdlRead) }, - { "Render && Read", PPRGB(CdlRenderRead) } -}; + {"Normal text", PPRGB(HexFore)}, + {"Address header", PPRGB(HexAddr)}, + // { "Normal text background", PPRGB(HexBack) }, + {NULL}, + {"Selected text", PPRGB(HexHlFore)}, + {"Selected background", PPRGB(HexHlBack)}, + {"Selected text (unfocused)", PPRGB(HexHlShdFore)}, + {"Selected background (unfocused)", PPRGB(HexHlShdBack)}, + {NULL}, + { + "Freezed address", + PPRGB(HexFreeze), + }, + // { "Freezed ROM address", PPRGB(RomFreeze), }, + {"Bookmark", PPRGB(HexBookmark)}}, + cdlcolormenu[] = {{"Code", PPRGB(CdlCode)}, {"Data", PPRGB(CdlData)}, {"PCM Data", PPRGB(CdlPcm)}, {"Code && Data", PPRGB(CdlCodeData)}, {NULL}, {"Render", PPRGB(CdlRender)}, {"Read", PPRGB(CdlRead)}, {"Render && Read", PPRGB(CdlRenderRead)}}; -struct { - COLORMENU* items; +struct +{ + COLORMENU *items; int base_id; int sub; int size; } colormenu[] = -{ - { hexcolormenu, ID_COLOR_HEXEDITOR, HEXEDITOR_COLOR_SUBMENU_POS, sizeof(hexcolormenu) / sizeof(hexcolormenu[0]) }, - { cdlcolormenu, ID_COLOR_CDLOGGER, CDLOGGER_COLOR_SUBMENU_POS, sizeof(cdlcolormenu) / sizeof(cdlcolormenu[0]) } -}; + { + {hexcolormenu, ID_COLOR_HEXEDITOR, HEXEDITOR_COLOR_SUBMENU_POS, sizeof(hexcolormenu) / sizeof(hexcolormenu[0])}, + {cdlcolormenu, ID_COLOR_CDLOGGER, CDLOGGER_COLOR_SUBMENU_POS, sizeof(cdlcolormenu) / sizeof(cdlcolormenu[0])}}; int LoadTableFile(); void UnloadTableFile(); void InputData(char *input); int GetMemViewData(uint32 i); -//int UpdateCheatColorCallB(char *name, uint32 a, uint8 v, int compare,int s,int type, void *data); //mbg merge 6/29/06 - added arg -//int DeleteCheatCallB(char *name, uint32 a, uint8 v, int compare,int s,int type); //mbg merge 6/29/06 - added arg +// int UpdateCheatColorCallB(char *name, uint32 a, uint8 v, int compare,int s,int type, void *data); //mbg merge 6/29/06 - added arg +// int DeleteCheatCallB(char *name, uint32 a, uint8 v, int compare,int s,int type); //mbg merge 6/29/06 - added arg void FreezeRam(int address, int mode, int final); int GetHexScreenCoordx(int offset); int GetHexScreenCoordy(int offset); -int GetAddyFromCoord(int x,int y); -void AutoScrollFromCoord(int x,int y); +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); -static int WriteFileData(uint32 offset,int data); +static int WriteFileData(uint32 offset, int data); static void PalettePoke(uint32 addr, uint8 data); void SwitchEditingText(int editingText); - HWND hMemView, hMemFind; int CurOffset; @@ -187,7 +177,7 @@ int ClientHeight; int NoColors; int EditingMode; int EditingText; -int AddyWasText; //used by the GetAddyFromCoord() function. +int AddyWasText; // used by the GetAddyFromCoord() function. int TableFileLoaded; int MemView_wndx, MemView_wndy; @@ -201,10 +191,10 @@ static RECT newMemViewRect; static char chartable[256]; HDC HDataDC; -int CursorX=2, CursorY=9; +int CursorX = 2, CursorY = 9; int CursorStartAddy, CursorEndAddy = PREVIOUS_VALUE_UNDEFINED; -int CursorDragPoint = -1;//, CursorShiftPoint = -1; -//int CursorStartNibble=1, CursorEndNibble; //1 means that only half of the byte is selected +int CursorDragPoint = -1; //, CursorShiftPoint = -1; +// int CursorStartNibble=1, CursorEndNibble; //1 means that only half of the byte is selected int TempData = PREVIOUS_VALUE_UNDEFINED; int DataAmount; int MaxSize; @@ -219,7 +209,7 @@ COLORREF *AnsiBGColorList; COLORREF *AnsiTextColorList; int PreviousCurOffset; -int *PreviousValues; // for HighlightActivity feature and for speedhack too +int *PreviousValues; // for HighlightActivity feature and for speedhack too unsigned int *HighlightedBytes; int lbuttondown; @@ -232,15 +222,16 @@ char FindTextBox[60]; extern iNES_HEADER head; -//undo structure -struct UNDOSTRUCT { +// undo structure +struct UNDOSTRUCT +{ int addr; int size; unsigned char *data; - UNDOSTRUCT *last; //mbg merge 7/18/06 removed struct qualifier + UNDOSTRUCT *last; // mbg merge 7/18/06 removed struct qualifier }; -struct UNDOSTRUCT *undo_list=0; +struct UNDOSTRUCT *undo_list = 0; void resetHighlightingActivityLog() { @@ -252,60 +243,66 @@ void resetHighlightingActivityLog() } } -void ApplyPatch(int addr,int size, uint8* data){ - UNDOSTRUCT *tmp = (UNDOSTRUCT*)malloc(sizeof(UNDOSTRUCT)); //mbg merge 7/18/06 removed struct qualifiers and added cast +void ApplyPatch(int addr, int size, uint8 *data) +{ + UNDOSTRUCT *tmp = (UNDOSTRUCT *)malloc(sizeof(UNDOSTRUCT)); // mbg merge 7/18/06 removed struct qualifiers and added cast int i; - //while(tmp != 0){tmp=tmp->next;x++;}; - //tmp = malloc(sizeof(struct UNDOSTRUCT)); - //sprintf(str,"%d",x); - //MessageBox(hMemView,str,"info", MB_OK); + // while(tmp != 0){tmp=tmp->next;x++;}; + // tmp = malloc(sizeof(struct UNDOSTRUCT)); + // sprintf(str,"%d",x); + // MessageBox(hMemView,str,"info", MB_OK); tmp->addr = addr; tmp->size = size; - tmp->data = (uint8*)malloc(sizeof(uint8)*size); - tmp->last=undo_list; + tmp->data = (uint8 *)malloc(sizeof(uint8) * size); + tmp->last = undo_list; - for(i = 0;i < size;i++){ - tmp->data[i] = GetFileData((uint32)addr+i); - WriteFileData((uint32)addr+i,data[i]); + for (i = 0; i < size; i++) + { + tmp->data[i] = GetFileData((uint32)addr + i); + WriteFileData((uint32)addr + i, data[i]); } - undo_list=tmp; + undo_list = tmp; - //UpdateColorTable(); + // UpdateColorTable(); return; } -void UndoLastPatch(){ - struct UNDOSTRUCT *tmp=undo_list; +void UndoLastPatch() +{ + struct UNDOSTRUCT *tmp = undo_list; int i; - if(undo_list == 0)return; - //while(tmp->next != 0){tmp=tmp->next;}; //traverse to the one before the last one + if (undo_list == 0) + return; + // while(tmp->next != 0){tmp=tmp->next;}; //traverse to the one before the last one - for(i = 0;i < tmp->size;i++){ - WriteFileData((uint32)tmp->addr+i,tmp->data[i]); + for (i = 0; i < tmp->size; i++) + { + WriteFileData((uint32)tmp->addr + i, tmp->data[i]); } - undo_list=undo_list->last; + undo_list = undo_list->last; - ChangeMemViewFocus(MODE_NES_FILE,tmp->addr, -1); //move to the focus to where we are undoing at. + ChangeMemViewFocus(MODE_NES_FILE, tmp->addr, -1); // move to the focus to where we are undoing at. free(tmp->data); free(tmp); return; } -void GotoAddress(HWND hwnd) { +void GotoAddress(HWND hwnd) +{ char gotoaddressstring[8]; int gotoaddress; char gototitle[18]; gotoaddressstring[0] = '\0'; - sprintf(gototitle, "%s%X%s", "Goto (0-", MaxSize-1, ")"); - if(CWin32InputBox::InputBox(gototitle, "Goto which address:", gotoaddressstring, 8, false, hwnd) == IDOK) + sprintf(gototitle, "%s%X%s", "Goto (0-", MaxSize - 1, ")"); + if (CWin32InputBox::InputBox(gototitle, "Goto which address:", gotoaddressstring, 8, false, hwnd) == IDOK) { - if(EOF != sscanf(gotoaddressstring, "%x", &gotoaddress)) + if (EOF != sscanf(gotoaddressstring, "%x", &gotoaddress)) { SetHexEditorAddress(gotoaddress); } @@ -317,19 +314,21 @@ void SetHexEditorAddress(int gotoaddress) if (gotoaddress < 0) gotoaddress = 0; - if (gotoaddress > (MaxSize-1)) - gotoaddress = (MaxSize-1); - + if (gotoaddress > (MaxSize - 1)) + gotoaddress = (MaxSize - 1); + CursorStartAddy = gotoaddress; CursorEndAddy = -1; ChangeMemViewFocus(EditingMode, CursorStartAddy, -1); } -static void FlushUndoBuffer(){ +static void FlushUndoBuffer() +{ struct UNDOSTRUCT *tmp; - while(undo_list!= 0){ - tmp=undo_list; - undo_list=undo_list->last; + while (undo_list != 0) + { + tmp = undo_list; + undo_list = undo_list->last; free(tmp->data); free(tmp); } @@ -337,95 +336,118 @@ static void FlushUndoBuffer(){ return; } - -static int GetFileData(uint32 offset){ - if(offset < 16) return *((unsigned char *)&head+offset); - if(offset < 16+PRGsize[0])return PRGptr[0][offset-16]; - if(offset < 16+PRGsize[0]+CHRsize[0])return CHRptr[0][offset-16-PRGsize[0]]; +static int GetFileData(uint32 offset) +{ + if (offset < 16) + return *((unsigned char *)&head + offset); + if (offset < 16 + PRGsize[0]) + return PRGptr[0][offset - 16]; + if (offset < 16 + PRGsize[0] + CHRsize[0]) + return CHRptr[0][offset - 16 - PRGsize[0]]; return -1; } -static int WriteFileData(uint32 addr,int data){ - if (addr < 16) MessageBox(hMemView, "You can't edit ROM header here, however you can use NES Header Editor to edit the header if it's an iNES format file.", "Sorry", MB_OK | MB_ICONERROR); - if((addr >= 16) && (addr < PRGsize[0]+16)) *(uint8 *)(GetNesPRGPointer(addr-16)) = data; - if((addr >= PRGsize[0]+16) && (addr < CHRsize[0]+PRGsize[0]+16)) *(uint8 *)(GetNesCHRPointer(addr-16-PRGsize[0])) = data; +static int WriteFileData(uint32 addr, int data) +{ + if (addr < 16) + MessageBox(hMemView, "You can't edit ROM header here, however you can use NES Header Editor to edit the header if it's an iNES format file.", "Sorry", MB_OK | MB_ICONERROR); + if ((addr >= 16) && (addr < PRGsize[0] + 16)) + *(uint8 *)(GetNesPRGPointer(addr - 16)) = data; + if ((addr >= PRGsize[0] + 16) && (addr < CHRsize[0] + PRGsize[0] + 16)) + *(uint8 *)(GetNesCHRPointer(addr - 16 - PRGsize[0])) = data; return 0; } -static int GetRomFileSize(){ //todo: fix or remove this? +static int GetRomFileSize() +{ // todo: fix or remove this? return 0; } void SaveRomAs() { - const char filter[]="NES ROM file (*.nes)\0*.nes\0All Files (*.*)\0*.*\0\0"; + const char filter[] = "NES ROM file (*.nes)\0*.nes\0All Files (*.*)\0*.*\0\0"; char nameo[2048]; OPENFILENAME ofn; - memset(&ofn,0,sizeof(ofn)); - ofn.lStructSize=sizeof(ofn); - ofn.hInstance=fceu_hInstance; - ofn.lpstrTitle="Save Nes ROM as..."; - ofn.lpstrFilter=filter; + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hInstance = fceu_hInstance; + ofn.lpstrTitle = "Save Nes ROM as..."; + ofn.lpstrFilter = filter; strcpy(nameo, mass_replace(GetRomName(), "|", ".").c_str()); - ofn.lpstrFile=nameo; - ofn.lpstrDefExt="nes"; - ofn.nMaxFile=256; - ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY; + ofn.lpstrFile = nameo; + ofn.lpstrDefExt = "nes"; + ofn.nMaxFile = 256; + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; ofn.hwndOwner = hMemView; if (GetSaveFileName(&ofn)) iNesSaveAs(nameo); } -int LoadTable(const char* nameo) +int LoadTable(const char *nameo) { char str[50]; FILE *FP; int i, line, charcode1, charcode2; - - for(i = 0;i < 256;i++){ + + for (i = 0; i < 256; i++) + { chartable[i] = 0; } - FP = fopen(nameo,"r"); + FP = fopen(nameo, "r"); line = 0; - while((fgets(str, 45, FP)) != NULL){/* get one line from the file */ + while ((fgets(str, 45, FP)) != NULL) + { /* get one line from the file */ line++; - if(strlen(str) < 3)continue; + if (strlen(str) < 3) + continue; charcode1 = charcode2 = -1; - if((str[0] >= 'a') && (str[0] <= 'f')) charcode1 = str[0]-('a'-0xA); - if((str[0] >= 'A') && (str[0] <= 'F')) charcode1 = str[0]-('A'-0xA); - if((str[0] >= '0') && (str[0] <= '9')) charcode1 = str[0]-'0'; - - if((str[1] >= 'a') && (str[1] <= 'f')) charcode2 = str[1]-('a'-0xA); - if((str[1] >= 'A') && (str[1] <= 'F')) charcode2 = str[1]-('A'-0xA); - if((str[1] >= '0') && (str[1] <= '9')) charcode2 = str[1]-'0'; - - if(charcode1 == -1){ + if ((str[0] >= 'a') && (str[0] <= 'f')) + charcode1 = str[0] - ('a' - 0xA); + if ((str[0] >= 'A') && (str[0] <= 'F')) + charcode1 = str[0] - ('A' - 0xA); + if ((str[0] >= '0') && (str[0] <= '9')) + charcode1 = str[0] - '0'; + + if ((str[1] >= 'a') && (str[1] <= 'f')) + charcode2 = str[1] - ('a' - 0xA); + if ((str[1] >= 'A') && (str[1] <= 'F')) + charcode2 = str[1] - ('A' - 0xA); + if ((str[1] >= '0') && (str[1] <= '9')) + charcode2 = str[1] - '0'; + + if (charcode1 == -1) + { UnloadTableFile(); fclose(FP); - return line; //we have an error getting the first input + return line; // we have an error getting the first input } - if(charcode2 != -1) charcode1 = (charcode1<<4)|charcode2; + if (charcode2 != -1) + charcode1 = (charcode1 << 4) | charcode2; - for(i = 0;i < (int)strlen(str);i++)if(str[i] == '=')break; + for (i = 0; i < (int)strlen(str); i++) + if (str[i] == '=') + break; - if(i == strlen(str)){ + if (i == strlen(str)) + { UnloadTableFile(); fclose(FP); - return line; //error no '=' found + return line; // error no '=' found } i++; - //ORing i with 32 just converts it to lowercase if it isn't - if(((str[i]|32) == 'r') && ((str[i+1]|32) == 'e') && ((str[i+2]|32) == 't')) + // ORing i with 32 just converts it to lowercase if it isn't + if (((str[i] | 32) == 'r') && ((str[i + 1] | 32) == 'e') && ((str[i + 2] | 32) == 't')) charcode2 = 0x0D; - else charcode2 = str[i]; + else + charcode2 = str[i]; chartable[charcode1] = charcode2; } @@ -434,33 +456,37 @@ int LoadTable(const char* nameo) return -1; } -//should return -1, otherwise returns the line number it had the error on +// should return -1, otherwise returns the line number it had the error on int LoadTableFile() { - const char filter[]="Table Files (*.TBL)\0*.tbl\0All Files (*.*)\0*.*\0\0"; + const char filter[] = "Table Files (*.TBL)\0*.tbl\0All Files (*.*)\0*.*\0\0"; char nameo[2048]; OPENFILENAME ofn; - memset(&ofn,0,sizeof(ofn)); - ofn.lStructSize=sizeof(ofn); - ofn.hInstance=fceu_hInstance; - ofn.lpstrTitle="Load Table File..."; - ofn.lpstrFilter=filter; - nameo[0]=0; - ofn.lpstrFile=nameo; - ofn.nMaxFile=256; - ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY; + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hInstance = fceu_hInstance; + ofn.lpstrTitle = "Load Table File..."; + ofn.lpstrFilter = filter; + nameo[0] = 0; + ofn.lpstrFile = nameo; + ofn.nMaxFile = 256; + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; ofn.hwndOwner = hMemView; - if(!GetOpenFileName(&ofn))return -1; + if (!GetOpenFileName(&ofn)) + return -1; int result = LoadTable(nameo); return result; } -void UnloadTableFile(){ - for(int i = 0;i < 256;i++){ +void UnloadTableFile() +{ + for (int i = 0; i < 256; i++) + { int j = i; - if(j < 0x20) j = 0x2E; -// if(j > 0x7e) j = 0x2E; + if (j < 0x20) + j = 0x2E; + // if(j > 0x7e) j = 0x2E; chartable[i] = j; } TableFileLoaded = 0; @@ -468,7 +494,8 @@ void UnloadTableFile(){ } void UpdateMemoryView(int draw_all) { - if (!hMemView) return; + if (!hMemView) + return; const int MemFontWidth = debugSystem->HexeditorFontWidth + HexCharSpacing; const int MemFontHeight = debugSystem->HexeditorFontHeight + HexRowHeightBorder; const char hex[] = "0123456789ABCDEF"; @@ -489,11 +516,11 @@ void UpdateMemoryView(int draw_all) int pos = i - CurOffset; if ((PreviousCurOffset != CurOffset) || draw_all) { - SetBkColor(HDataDC, CBackColor); //addresses back color + SetBkColor(HDataDC, CBackColor); // addresses back color if (i < MaxSize) - SetTextColor(HDataDC, MKRGB(HexAddr)); //addresses text color #000000 = black, #FFFFFF = white + SetTextColor(HDataDC, MKRGB(HexAddr)); // addresses text color #000000 = black, #FFFFFF = white else - SetTextColor(HDataDC, MKRGB(HexBound)); //addresses out of bounds + SetTextColor(HDataDC, MKRGB(HexBound)); // addresses out of bounds sprintf(str, "%06X: :", i); ExtTextOut(HDataDC, 0, MemLineRow, NULL, NULL, str, strlen(str), NULL); } @@ -507,7 +534,7 @@ void UpdateMemoryView(int draw_all) if ((CursorEndAddy == -1) && (CursorStartAddy == i + j)) { - //print up single highlighted text + // print up single highlighted text if (TempData != PREVIOUS_VALUE_UNDEFINED) { // User is typing New Data @@ -545,12 +572,13 @@ void UpdateMemoryView(int draw_all) SetBkColor(HDataDC, EditingText ? MKRGB(HexHlBack) : MKRGB(HexHlShdBack)); SetTextColor(HDataDC, EditingText ? MKRGB(HexHlFore) : MKRGB(HexHlShdFore)); str[0] = chartable[byteValue]; - if ((u8)str[0] < 0x20) str[0] = 0x2E; -// if ((u8)str[0] > 0x7e) str[0] = 0x2E; + if ((u8)str[0] < 0x20) + str[0] = 0x2E; + // if ((u8)str[0] > 0x7e) str[0] = 0x2E; str[1] = 0; ExtTextOut(HDataDC, (59 + j) * MemFontWidth, MemLineRow, NULL, NULL, str, 1, NULL); - PreviousValues[pos] = PREVIOUS_VALUE_UNDEFINED; //set it to redraw this one next time + PreviousValues[pos] = PREVIOUS_VALUE_UNDEFINED; // set it to redraw this one next time } else if (draw_all || (PreviousValues[pos] != byteValue) || byteHighlightingValue) { @@ -589,8 +617,9 @@ void UpdateMemoryView(int draw_all) SetBkColor(HDataDC, AnsiBGColorList[pos]); SetTextColor(HDataDC, ansiTmpColor); str[0] = chartable[byteValue]; - if ((u8)str[0] < 0x20) str[0] = 0x2E; -// if ((u8)str[0] > 0x7e) str[0] = 0x2E; + if ((u8)str[0] < 0x20) + str[0] = 0x2E; + // if ((u8)str[0] > 0x7e) str[0] = 0x2E; str[1] = 0; ExtTextOut(HDataDC, (59 + j) * MemFontWidth, MemLineRow, NULL, NULL, str, 1, NULL); @@ -608,7 +637,7 @@ void UpdateMemoryView(int draw_all) return; } -char* EditString[4] = {"RAM","PPU","OAM","ROM"}; +char *EditString[4] = {"RAM", "PPU", "OAM", "ROM"}; void UpdateCaption() { @@ -624,7 +653,8 @@ void UpdateCaption() sprintf(str, "Hex Editor - (PRG) ROM: 0x%X", CursorStartAddy); else if (CursorStartAddy - 16 - PRGsize[0] < (int)CHRsize[0]) sprintf(str, "Hex Editor - (CHR) ROM: 0x%X", CursorStartAddy); - } else + } + else { sprintf(str, "Hex Editor - %s: 0x%X", EditString[EditingMode], CursorStartAddy); } @@ -633,28 +663,32 @@ void UpdateCaption() { // when watching RAM we may as well see Symbolic Debug names loadNameFiles(); - Name* node = findNode(getNamesPointerForAddress(CursorStartAddy), CursorStartAddy); + Name *node = findNode(getNamesPointerForAddress(CursorStartAddy), CursorStartAddy); if (node && node->name) { strcat(str, " - "); strcat(str, node->name); } - for (int i = 0; i < RegNameCount; i++) { - if (!symbRegNames) break; + for (int i = 0; i < RegNameCount; i++) + { + if (!symbRegNames) + break; int test = 0; sscanf(RegNames[i].offset, "$%4x", &test); - if (test == CursorStartAddy) { + if (test == CursorStartAddy) + { strcat(str, " - "); strcat(str, RegNames[i].name); } } } - } else + } + else { sprintf(str, "Hex Editor - %s: 0x%X - 0x%X (0x%X)", - EditString[EditingMode], CursorStartAddy, CursorEndAddy, CursorEndAddy - CursorStartAddy + 1); + EditString[EditingMode], CursorStartAddy, CursorEndAddy, CursorEndAddy - CursorStartAddy + 1); } - SetWindowText(hMemView,str); + SetWindowText(hMemView, str); return; } @@ -662,58 +696,64 @@ int GetMemViewData(uint32 i) { switch (EditingMode) { - case MODE_NES_MEMORY: - return GetMem(i); - case MODE_NES_PPU: - i &= 0x3FFF; - if (i < 0x2000)return VPage[(i) >> 10][(i)]; - //NSF PPU Viewer crash here (UGETAB) (Also disabled by 'MaxSize = 0x2000') - if (GameInfo->type == GIT_NSF) - return (0); - else - { - if (i < 0x3F00) - return vnapage[(i >> 10) & 0x3][i & 0x3FF]; - return READPAL_MOTHEROFALL(i & 0x1F); - } - break; - case MODE_NES_OAM: - return SPRAM[i & 0xFF]; - case MODE_NES_FILE: - //todo: use getfiledata() here - if (i < 16) return *((unsigned char *)&head + i); - if (i < 16 + PRGsize[0])return PRGptr[0][i - 16]; - if (i < 16 + PRGsize[0] + CHRsize[0])return CHRptr[0][i - 16 - PRGsize[0]]; + case MODE_NES_MEMORY: + return GetMem(i); + case MODE_NES_PPU: + i &= 0x3FFF; + if (i < 0x2000) + return VPage[(i) >> 9][(i)]; + // NSF PPU Viewer crash here (UGETAB) (Also disabled by 'MaxSize = 0x2000') + if (GameInfo->type == GIT_NSF) + return (0); + else + { + if (i < 0x3F00) + return vnapage[(i >> 10) & 0x3][i & 0x3FF]; + return READPAL_MOTHEROFALL(i & 0x1F); + } + break; + case MODE_NES_OAM: + return SPRAM[i & 0xFF]; + case MODE_NES_FILE: + // todo: use getfiledata() here + if (i < 16) + return *((unsigned char *)&head + i); + if (i < 16 + PRGsize[0]) + return PRGptr[0][i - 16]; + if (i < 16 + PRGsize[0] + CHRsize[0]) + return CHRptr[0][i - 16 - PRGsize[0]]; } return 0; } void UpdateColorTable() { - UNDOSTRUCT *tmp; //mbg merge 7/18/06 removed struct qualifier - int i,j; - if(!hMemView)return; - for(i = 0;i < DataAmount;i++) + UNDOSTRUCT *tmp; // mbg merge 7/18/06 removed struct qualifier + int i, j; + if (!hMemView) + return; + for (i = 0; i < DataAmount; i++) { - if((i+CurOffset >= CursorStartAddy) && (i+CurOffset <= CursorEndAddy)) + if ((i + CurOffset >= CursorStartAddy) && (i + CurOffset <= CursorEndAddy)) { - CurBGColorList[i] = MKRGB(HexHlBack); //Highlighter color bg - 2 columns + CurBGColorList[i] = MKRGB(HexHlBack); // Highlighter color bg - 2 columns DimBGColorList[i] = MKRGB(HexHlShdBack); - CurTextColorList[i] = MKRGB(HexHlFore); //Highlighter color text - 2 columns + CurTextColorList[i] = MKRGB(HexHlFore); // Highlighter color text - 2 columns DimTextColorList[i] = MKRGB(HexHlShdFore); continue; } - CurBGColorList[i] = MKRGB(HexBack); //Regular color bb - 2columns - DimBGColorList[i] = MKRGB(HexBack); //Regular color bb - 2columns - CurTextColorList[i] = MKRGB(HexFore); //Regular color text - 2 columns - DimTextColorList[i] = MKRGB(HexFore); //Regular color text - 2 columns + CurBGColorList[i] = MKRGB(HexBack); // Regular color bb - 2columns + DimBGColorList[i] = MKRGB(HexBack); // Regular color bb - 2columns + CurTextColorList[i] = MKRGB(HexFore); // Regular color text - 2 columns + DimTextColorList[i] = MKRGB(HexFore); // Regular color text - 2 columns } - for (j=0;j= CurOffset) && ((int)hexBookmarks[j].address < CurOffset+DataAmount)) + if (hexBookmarks[j].editmode != EditingMode) + continue; + if (((int)hexBookmarks[j].address >= CurOffset) && ((int)hexBookmarks[j].address < CurOffset + DataAmount)) { CurTextColorList[hexBookmarks[j].address - CurOffset] = MKRGB(HexBookmark); // Green for Bookmarks DimTextColorList[hexBookmarks[j].address - CurOffset] = MKRGB(HexBookmark); // Green for Bookmarks @@ -722,136 +762,140 @@ void UpdateColorTable() switch (EditingMode) { - case MODE_NES_MEMORY: - for (int a = CurOffset; a < CurOffset + DataAmount; ++a) - if (FCEUI_FindCheatMapByte(a)) - { - CurTextColorList[a - CurOffset] = MKRGB(HexFreeze); - DimTextColorList[a - CurOffset] = MKRGB(HexFreeze); - } - break; - case MODE_NES_FILE: - if (cdloggerdataSize) + case MODE_NES_MEMORY: + for (int a = CurOffset; a < CurOffset + DataAmount; ++a) + if (FCEUI_FindCheatMapByte(a)) + { + CurTextColorList[a - CurOffset] = MKRGB(HexFreeze); + DimTextColorList[a - CurOffset] = MKRGB(HexFreeze); + } + break; + case MODE_NES_FILE: + if (cdloggerdataSize) + { + int temp_offset; + for (i = 0; i < DataAmount; i++) { - int temp_offset; - for (i = 0; i < DataAmount; i++) + temp_offset = CurOffset + i - 16; // (minus NES header) + if (temp_offset >= 0) { - temp_offset = CurOffset + i - 16; // (minus NES header) - if (temp_offset >= 0) + if ((unsigned int)temp_offset < cdloggerdataSize) { - if ((unsigned int)temp_offset < cdloggerdataSize) + // PRG + if ((cdloggerdata[temp_offset] & 3) == 3) { - // PRG - if ((cdloggerdata[temp_offset] & 3) == 3) - { - // the byte is both Code and Data - green - CurTextColorList[i] = MKRGB(CdlCodeData); - DimTextColorList[i] = MKRGB(CdlCodeData); - } - else if ((cdloggerdata[temp_offset] & 3) == 1) + // the byte is both Code and Data - green + CurTextColorList[i] = MKRGB(CdlCodeData); + DimTextColorList[i] = MKRGB(CdlCodeData); + } + else if ((cdloggerdata[temp_offset] & 3) == 1) + { + // the byte is Code - dark-yellow + CurTextColorList[i] = MKRGB(CdlCode); + DimTextColorList[i] = MKRGB(CdlCode); + } + else if ((cdloggerdata[temp_offset] & 3) == 2) + { + // the byte is Data - blue/cyan + if (cdloggerdata[temp_offset] & 0x40) { - // the byte is Code - dark-yellow - CurTextColorList[i] = MKRGB(CdlCode); - DimTextColorList[i] = MKRGB(CdlCode); + // PCM data - cyan + CurTextColorList[i] = MKRGB(CdlPcm); + DimTextColorList[i] = MKRGB(CdlPcm); } - else if ((cdloggerdata[temp_offset] & 3) == 2) + else { - // the byte is Data - blue/cyan - if (cdloggerdata[temp_offset] & 0x40) - { - // PCM data - cyan - CurTextColorList[i] = MKRGB(CdlPcm); - DimTextColorList[i] = MKRGB(CdlPcm); - } - else - { - // non-PCM data - blue - CurTextColorList[i] = MKRGB(CdlData); - DimTextColorList[i] = MKRGB(CdlData); - } + // non-PCM data - blue + CurTextColorList[i] = MKRGB(CdlData); + DimTextColorList[i] = MKRGB(CdlData); } } - else + } + else + { + temp_offset -= cdloggerdataSize; + if (((unsigned int)temp_offset < cdloggerVideoDataSize)) { - temp_offset -= cdloggerdataSize; - if (((unsigned int)temp_offset < cdloggerVideoDataSize)) + // CHR + if ((cdloggervdata[temp_offset] & 3) == 3) { - // CHR - if ((cdloggervdata[temp_offset] & 3) == 3) - { - // the byte was both rendered and read programmatically - light-green - CurTextColorList[i] = MKRGB(CdlRenderRead); - DimTextColorList[i] = MKRGB(CdlRenderRead); - } - else if ((cdloggervdata[temp_offset] & 3) == 1) - { - // the byte was rendered - yellow - CurTextColorList[i] = MKRGB(CdlRender); - DimTextColorList[i] = MKRGB(CdlRender); - } - else if ((cdloggervdata[temp_offset] & 3) == 2) - { - // the byte was read programmatically - light-blue - CurTextColorList[i] = MKRGB(CdlRead); - DimTextColorList[i] = MKRGB(CdlRead); - } + // the byte was both rendered and read programmatically - light-green + CurTextColorList[i] = MKRGB(CdlRenderRead); + DimTextColorList[i] = MKRGB(CdlRenderRead); + } + else if ((cdloggervdata[temp_offset] & 3) == 1) + { + // the byte was rendered - yellow + CurTextColorList[i] = MKRGB(CdlRender); + DimTextColorList[i] = MKRGB(CdlRender); + } + else if ((cdloggervdata[temp_offset] & 3) == 2) + { + // the byte was read programmatically - light-blue + CurTextColorList[i] = MKRGB(CdlRead); + DimTextColorList[i] = MKRGB(CdlRead); } } } } } + } - tmp = undo_list; - while (tmp != 0) + tmp = undo_list; + while (tmp != 0) + { + // if((tmp->addr < CurOffset+DataAmount) && (tmp->addr+tmp->size > CurOffset)) + for (i = tmp->addr; i < tmp->addr + tmp->size; i++) { - //if((tmp->addr < CurOffset+DataAmount) && (tmp->addr+tmp->size > CurOffset)) - for (i = tmp->addr; i < tmp->addr + tmp->size; i++) { - if ((i > CurOffset) && (i < CurOffset + DataAmount)) - { - CurTextColorList[i - CurOffset] = MKRGB(RomFreeze); - DimTextColorList[i - CurOffset] = MKRGB(RomFreeze); - } + if ((i > CurOffset) && (i < CurOffset + DataAmount)) + { + CurTextColorList[i - CurOffset] = MKRGB(RomFreeze); + DimTextColorList[i - CurOffset] = MKRGB(RomFreeze); } - tmp = tmp->last; } - break; + tmp = tmp->last; + } + break; } - UpdateMemoryView(1); //anytime the colors change, the memory viewer needs to be completely redrawn + UpdateMemoryView(1); // anytime the colors change, the memory viewer needs to be completely redrawn } -int addrtodelete; // This is a very ugly hackish method of doing this +int addrtodelete; // This is a very ugly hackish method of doing this int cheatwasdeleted; // but it works and that is all that matters here. -int DeleteCheatCallB(const char *name, uint32 a, uint8 v, int compare,int s,int type, void *data){ //mbg merge 6/29/06 - added arg - if(cheatwasdeleted == -1)return 1; +int DeleteCheatCallB(const char *name, uint32 a, uint8 v, int compare, int s, int type, void *data) +{ // mbg merge 6/29/06 - added arg + if (cheatwasdeleted == -1) + return 1; cheatwasdeleted++; - if(a == addrtodelete){ - FCEUI_DelCheat(cheatwasdeleted-1); + if (a == addrtodelete) + { + FCEUI_DelCheat(cheatwasdeleted - 1); cheatwasdeleted = -1; return 0; } return 1; } -void dumpToFile(const char* buffer, unsigned int size) +void dumpToFile(const char *buffer, unsigned int size) { char name[513] = {0}; OPENFILENAME ofn; memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize=sizeof(ofn); - ofn.hInstance=fceu_hInstance; - ofn.lpstrTitle="Save to file ..."; - ofn.lpstrFilter="Binary File (*.BIN)\0*.bin\0All Files (*.*)\0*.*\0\0"; + ofn.lStructSize = sizeof(ofn); + ofn.hInstance = fceu_hInstance; + ofn.lpstrTitle = "Save to file ..."; + ofn.lpstrFilter = "Binary File (*.BIN)\0*.bin\0All Files (*.*)\0*.*\0\0"; strcpy(name, mass_replace(GetRomName(), "|", ".").c_str()); - ofn.lpstrFile=name; - ofn.lpstrDefExt="bin"; - ofn.nMaxFile=256; - ofn.Flags=OFN_EXPLORER|OFN_HIDEREADONLY; + ofn.lpstrFile = name; + ofn.lpstrDefExt = "bin"; + ofn.nMaxFile = 256; + ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY; if (GetSaveFileName(&ofn)) { - FILE* memfile = fopen(name, "wb"); + FILE *memfile = fopen(name, "wb"); if (!memfile || fwrite(buffer, 1, size, memfile) != size) { @@ -863,25 +907,25 @@ void dumpToFile(const char* buffer, unsigned int size) } } -bool loadFromFile(char* buffer, unsigned int size) +bool loadFromFile(char *buffer, unsigned int size) { - char name[513] = { 0 }; + char name[513] = {0}; OPENFILENAME ofn; memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize=sizeof(ofn); - ofn.hInstance=fceu_hInstance; - ofn.lpstrTitle="Save to file ..."; - ofn.lpstrFilter="Binary File (*.BIN)\0*.bin\0All Files (*.*)\0*.*\0\0"; + ofn.lStructSize = sizeof(ofn); + ofn.hInstance = fceu_hInstance; + ofn.lpstrTitle = "Save to file ..."; + ofn.lpstrFilter = "Binary File (*.BIN)\0*.bin\0All Files (*.*)\0*.*\0\0"; strcpy(name, mass_replace(GetRomName(), "|", ".").c_str()); - ofn.lpstrFile=name; - ofn.lpstrDefExt="bin"; - ofn.nMaxFile=256; - ofn.Flags=OFN_EXPLORER | OFN_FILEMUSTEXIST; + ofn.lpstrFile = name; + ofn.lpstrDefExt = "bin"; + ofn.nMaxFile = 256; + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST; if (GetOpenFileName(&ofn)) { - FILE* memfile = fopen(name, "rb"); + FILE *memfile = fopen(name, "rb"); if (!memfile || fread(buffer, 1, size, memfile) != size) { @@ -897,32 +941,35 @@ bool loadFromFile(char* buffer, unsigned int size) return false; } -void UnfreezeAllRam() { +void UnfreezeAllRam() +{ - int i=0; + int i = 0; std::string Cname; uint32 Caddr; int Ctype; // Get last cheat number + 1 - while (FCEUI_GetCheat(i,NULL,NULL,NULL,NULL,NULL,NULL)) { + while (FCEUI_GetCheat(i, NULL, NULL, NULL, NULL, NULL, NULL)) + { i = i + 1; } // Subtract 1 to be on last cheat i = i - 1; - while (i >= 0) { + while (i >= 0) + { // Since this is automated, only remove unnamed variables, as they // would be added by the freeze command. Manual unfreeze should let them // make that mistake once or twice, in case they like it that way. - FCEUI_GetCheat(i,&Cname,&Caddr,NULL,NULL,NULL,&Ctype); - if ((Cname.empty()) && ((Caddr < 0x2000) || ((Caddr >= 0x6000) && (Caddr < 0x8000))) && (Ctype == 1)) { + FCEUI_GetCheat(i, &Cname, &Caddr, NULL, NULL, NULL, &Ctype); + if ((Cname.empty()) && ((Caddr < 0x2000) || ((Caddr >= 0x6000) && (Caddr < 0x8000))) && (Ctype == 1)) + { // Already Added, so consider it a success - FreezeRam(Caddr,-1,1); - + FreezeRam(Caddr, -1, 1); } i = i - 1; @@ -931,23 +978,25 @@ void UnfreezeAllRam() { return; } -void FreezeRam(int address, int mode, int final){ +void FreezeRam(int address, int mode, int final) +{ // mode: -1 == Unfreeze; 0 == Toggle; 1 == Freeze - if(FrozenAddressCount <= 256 && (address < 0x2000) || ((address >= 0x6000) && (address <= 0x7FFF))){ - //adelikat: added FrozenAddressCount check to if statement to prevent user from freezing more than 256 address (unfreezing when > 256 crashes) + if (FrozenAddressCount <= 256 && (address < 0x2000) || ((address >= 0x6000) && (address <= 0x7FFF))) + { + // adelikat: added FrozenAddressCount check to if statement to prevent user from freezing more than 256 address (unfreezing when > 256 crashes) addrtodelete = address; cheatwasdeleted = 0; if (mode == 0 || mode == -1) { - //mbg merge 6/29/06 - added argument + // mbg merge 6/29/06 - added argument FCEUI_ListCheats(DeleteCheatCallB, 0); - if(mode == 0 && cheatwasdeleted != -1) + if (mode == 0 && cheatwasdeleted != -1) FCEUI_AddCheat("", address, GetMem(address), -1, 1); } else { - //mbg merge 6/29/06 - added argument + // mbg merge 6/29/06 - added argument FCEUI_ListCheats(DeleteCheatCallB, 0); FCEUI_AddCheat("", address, GetMem(address), -1, 1); } @@ -957,29 +1006,37 @@ void FreezeRam(int address, int mode, int final){ } } -//input is expected to be an ASCII string -void InputData(char *input){ - //CursorEndAddy = -1; +// input is expected to be an ASCII string +void InputData(char *input) +{ + // CursorEndAddy = -1; int addr, datasize = 0; unsigned char *data; char inputc; - //char str[100]; - //mbg merge 7/18/06 added cast: - data = (uint8 *)malloc(strlen(input) + 1); //it can't be larger than the input string, so use that as the size + // char str[100]; + // mbg merge 7/18/06 added cast: + data = (uint8 *)malloc(strlen(input) + 1); // it can't be larger than the input string, so use that as the size - for(int i = 0;input[i] != 0;i++){ - if(!EditingText){ + for (int i = 0; input[i] != 0; i++) + { + if (!EditingText) + { inputc = -1; - if((input[i] >= 'a') && (input[i] <= 'f')) inputc = input[i]-('a'-0xA); - if((input[i] >= 'A') && (input[i] <= 'F')) inputc = input[i]-('A'-0xA); - if((input[i] >= '0') && (input[i] <= '9')) inputc = input[i]-'0'; - if(inputc == -1)continue; + if ((input[i] >= 'a') && (input[i] <= 'f')) + inputc = input[i] - ('a' - 0xA); + if ((input[i] >= 'A') && (input[i] <= 'F')) + inputc = input[i] - ('A' - 0xA); + if ((input[i] >= '0') && (input[i] <= '9')) + inputc = input[i] - '0'; + if (inputc == -1) + continue; - if(TempData != PREVIOUS_VALUE_UNDEFINED) + if (TempData != PREVIOUS_VALUE_UNDEFINED) { - data[datasize++] = inputc|(TempData<<4); + data[datasize++] = inputc | (TempData << 4); TempData = PREVIOUS_VALUE_UNDEFINED; - } else + } + else { TempData = inputc; } @@ -987,70 +1044,74 @@ void InputData(char *input){ else { int j; - for(j = 0; j < 256; j++) - if(chartable[j] == input[i]) + for (j = 0; j < 256; j++) + if (chartable[j] == input[i]) break; - if(j == 256) + if (j == 256) continue; data[datasize++] = j; } } - if(datasize+CursorStartAddy >= MaxSize){ //too big - datasize = MaxSize-CursorStartAddy; - //free(data); - //return; + if (datasize + CursorStartAddy >= MaxSize) + { // too big + datasize = MaxSize - CursorStartAddy; + // free(data); + // return; } - if (datasize < 1) return; // avoid adjusting cursor and accidentally writing at end + if (datasize < 1) + return; // avoid adjusting cursor and accidentally writing at end - //its possible for this loop not to get executed at all + // its possible for this loop not to get executed at all // for(addr = CursorStartAddy;addr < datasize+CursorStartAddy;addr++){ - //sprintf(str,"datasize = %d",datasize); - //MessageBox(hMemView,str, "debug", MB_OK); + // sprintf(str,"datasize = %d",datasize); + // MessageBox(hMemView,str, "debug", MB_OK); - if(EditingMode == MODE_NES_FILE) + if (EditingMode == MODE_NES_FILE) { ApplyPatch(CursorStartAddy, datasize, data); } else { - for(int i = 0;i < datasize;i++) + for (int i = 0; i < datasize; i++) { - addr = CursorStartAddy+i; + addr = CursorStartAddy + i; - if (addr >= MaxSize) continue; + if (addr >= MaxSize) + continue; - switch(EditingMode) + switch (EditingMode) { - case MODE_NES_MEMORY: - // RAM (system bus) - BWrite[addr](addr, data[i]); - break; - case MODE_NES_PPU: - // PPU - addr &= 0x3FFF; - if (addr < 0x2000) - VPage[addr >> 10][addr] = data[i]; //todo: detect if this is vrom and turn it red if so - if ((addr >= 0x2000) && (addr < 0x3F00)) - vnapage[(addr >> 10) & 0x3][addr & 0x3FF] = data[i]; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct? - if ((addr >= 0x3F00) && (addr < 0x3FFF)) - PalettePoke(addr, data[i]); - break; - case MODE_NES_OAM: - addr &= 0xFF; - SPRAM[addr] = data[i]; - break; - case MODE_NES_FILE: - // ROM - ApplyPatch(addr, 1, &data[i]); - break; + case MODE_NES_MEMORY: + // RAM (system bus) + BWrite[addr](addr, data[i]); + break; + case MODE_NES_PPU: + // PPU + addr &= 0x3FFF; + if (addr < 0x2000) + VPage[addr >> 9][addr] = data[i]; // todo: detect if this is vrom and turn it red if so + if ((addr >= 0x2000) && (addr < 0x3F00)) + vnapage[(addr >> 10) & 0x3][addr & 0x3FF] = data[i]; // todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct? + if ((addr >= 0x3F00) && (addr < 0x3FFF)) + PalettePoke(addr, data[i]); + break; + case MODE_NES_OAM: + addr &= 0xFF; + SPRAM[addr] = data[i]; + break; + case MODE_NES_FILE: + // ROM + ApplyPatch(addr, 1, &data[i]); + break; } } } - CursorStartAddy+=datasize; - CursorEndAddy=-1; - if(CursorStartAddy >= MaxSize)CursorStartAddy = MaxSize-1; + CursorStartAddy += datasize; + CursorEndAddy = -1; + if (CursorStartAddy >= MaxSize) + CursorStartAddy = MaxSize - 1; free(data); ChangeMemViewFocus(EditingMode, CursorStartAddy, -1); @@ -1058,32 +1119,39 @@ void InputData(char *input){ return; } +void ChangeMemViewFocus(int newEditingMode, int StartOffset, int EndOffset) +{ -void ChangeMemViewFocus(int newEditingMode, int StartOffset,int EndOffset){ - - if(!hMemView)DoMemView(); - if(EditingMode != newEditingMode) - MemViewCallB(hMemView,WM_COMMAND,MENU_MV_VIEW_RAM+newEditingMode,0); //let the window handler change this for us + if (!hMemView) + DoMemView(); + if (EditingMode != newEditingMode) + MemViewCallB(hMemView, WM_COMMAND, MENU_MV_VIEW_RAM + newEditingMode, 0); // let the window handler change this for us - if((EndOffset == StartOffset) || (EndOffset == -1)){ + if ((EndOffset == StartOffset) || (EndOffset == -1)) + { CursorEndAddy = -1; CursorStartAddy = StartOffset; - } else { - CursorStartAddy = std::min(StartOffset,EndOffset); - CursorEndAddy = std::max(StartOffset,EndOffset); + } + else + { + CursorStartAddy = std::min(StartOffset, EndOffset); + CursorEndAddy = std::max(StartOffset, EndOffset); } CursorDragPoint = -1; + if (std::min(StartOffset, EndOffset) >= MaxSize) + return; // this should never happen - if(std::min(StartOffset,EndOffset) >= MaxSize)return; //this should never happen - - if(StartOffset < CurOffset){ - CurOffset = (StartOffset/16)*16; + if (StartOffset < CurOffset) + { + CurOffset = (StartOffset / 16) * 16; } - if(StartOffset >= CurOffset+DataAmount){ - CurOffset = ((StartOffset/16)*16)-DataAmount+0x10; - if(CurOffset < 0)CurOffset = 0; + if (StartOffset >= CurOffset + DataAmount) + { + CurOffset = ((StartOffset / 16) * 16) - DataAmount + 0x10; + if (CurOffset < 0) + CurOffset = 0; } SetFocus(hMemView); @@ -1093,16 +1161,15 @@ void ChangeMemViewFocus(int newEditingMode, int StartOffset,int EndOffset){ si.fMask = SIF_POS; si.cbSize = sizeof(SCROLLINFO); si.nPos = CurOffset / 16; - SetScrollInfo(hMemView,SB_VERT,&si,TRUE); + SetScrollInfo(hMemView, SB_VERT, &si, TRUE); UpdateCaption(); UpdateColorTable(); return; } - int GetHexScreenCoordx(int offset) { - return (8 * (debugSystem->HexeditorFontWidth + HexCharSpacing)) + ((offset % 16) * 3 * (debugSystem->HexeditorFontWidth + HexCharSpacing)); //todo: add Curoffset to this and to below function + return (8 * (debugSystem->HexeditorFontWidth + HexCharSpacing)) + ((offset % 16) * 3 * (debugSystem->HexeditorFontWidth + HexCharSpacing)); // todo: add Curoffset to this and to below function } int GetHexScreenCoordy(int offset) @@ -1110,63 +1177,78 @@ int GetHexScreenCoordy(int offset) return (offset - CurOffset) / 16 * (debugSystem->HexeditorFontHeight + HexRowHeightBorder); } -//0000E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ +// 0000E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ -//if the mouse is in the text field, this function will set AddyWasText to 1 otherwise it is 0 -//if the mouse wasn't in any range, this function returns -1 -int GetAddyFromCoord(int x,int y) +// if the mouse is in the text field, this function will set AddyWasText to 1 otherwise it is 0 +// if the mouse wasn't in any range, this function returns -1 +int GetAddyFromCoord(int x, int y) { int MemFontWidth = debugSystem->HexeditorFontWidth + HexCharSpacing; int MemFontHeight = debugSystem->HexeditorFontHeight + HexRowHeightBorder; - if(y < 0)y = 0; - if(x < 8*MemFontWidth)x = 8*MemFontWidth+1; + if (y < 0) + y = 0; + if (x < 8 * MemFontWidth) + x = 8 * MemFontWidth + 1; - if(y > DataAmount*MemFontHeight) return -1; + if (y > DataAmount * MemFontHeight) + return -1; - if(x < 55*MemFontWidth){ + if (x < 55 * MemFontWidth) + { AddyWasText = 0; - return ((y/MemFontHeight)*16)+((x-(8*MemFontWidth))/(3*MemFontWidth))+CurOffset; + return ((y / MemFontHeight) * 16) + ((x - (8 * MemFontWidth)) / (3 * MemFontWidth)) + CurOffset; } - if((x > 59*MemFontWidth) && (x < 75*MemFontWidth)){ + if ((x > 59 * MemFontWidth) && (x < 75 * MemFontWidth)) + { AddyWasText = 1; - return ((y/MemFontHeight)*16)+((x-(59*MemFontWidth))/(MemFontWidth))+CurOffset; + return ((y / MemFontHeight) * 16) + ((x - (59 * MemFontWidth)) / (MemFontWidth)) + CurOffset; } return -1; } -void AutoScrollFromCoord(int x,int y) +void AutoScrollFromCoord(int x, int y) { SCROLLINFO si; - if(y < 0){ + if (y < 0) + { ZeroMemory(&si, sizeof(SCROLLINFO)); si.fMask = SIF_ALL; si.cbSize = sizeof(SCROLLINFO); - GetScrollInfo(hMemView,SB_VERT,&si); + GetScrollInfo(hMemView, SB_VERT, &si); si.nPos += y / 16; - if (si.nPos < si.nMin) si.nPos = si.nMin; - if ((si.nPos+(int)si.nPage) > si.nMax) si.nPos = si.nMax-si.nPage; - CurOffset = si.nPos*16; - if (CurOffset + DataAmount >= MaxSize) CurOffset = MaxSize - DataAmount; - if (CurOffset < 0) CurOffset = 0; - SetScrollInfo(hMemView,SB_VERT,&si,TRUE); + if (si.nPos < si.nMin) + si.nPos = si.nMin; + if ((si.nPos + (int)si.nPage) > si.nMax) + si.nPos = si.nMax - si.nPage; + CurOffset = si.nPos * 16; + if (CurOffset + DataAmount >= MaxSize) + CurOffset = MaxSize - DataAmount; + if (CurOffset < 0) + CurOffset = 0; + SetScrollInfo(hMemView, SB_VERT, &si, TRUE); return; } - if(y > ClientHeight){ + if (y > ClientHeight) + { ZeroMemory(&si, sizeof(SCROLLINFO)); si.fMask = SIF_ALL; si.cbSize = sizeof(SCROLLINFO); - GetScrollInfo(hMemView,SB_VERT,&si); - si.nPos -= (ClientHeight-y) / 16; - if (si.nPos < si.nMin) si.nPos = si.nMin; - if ((si.nPos+(int)si.nPage) > si.nMax) si.nPos = si.nMax-si.nPage; - CurOffset = si.nPos*16; - if (CurOffset + DataAmount >= MaxSize) CurOffset = MaxSize - DataAmount; - if (CurOffset < 0) CurOffset = 0; - SetScrollInfo(hMemView,SB_VERT,&si,TRUE); + GetScrollInfo(hMemView, SB_VERT, &si); + si.nPos -= (ClientHeight - y) / 16; + if (si.nPos < si.nMin) + si.nPos = si.nMin; + if ((si.nPos + (int)si.nPage) > si.nMax) + si.nPos = si.nMax - si.nPage; + CurOffset = si.nPos * 16; + if (CurOffset + DataAmount >= MaxSize) + CurOffset = MaxSize - DataAmount; + if (CurOffset < 0) + CurOffset = 0; + SetScrollInfo(hMemView, SB_VERT, &si, TRUE); return; } } @@ -1199,15 +1281,18 @@ 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 + 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) { static PAINTSTRUCT ps; @@ -1216,21 +1301,27 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa const int MemFontWidth = debugSystem->HexeditorFontWidth; const int MemFontHeight = debugSystem->HexeditorFontHeight + HexRowHeightBorder; -// char str[100]; + // char str[100]; extern int debuggerWasActive; static int tmpStartAddy = -1; static int tmpEndAddy = -1; - switch (message) { + switch (message) + { - case WM_ENTERMENULOOP:return 0; + case WM_ENTERMENULOOP: + return 0; case WM_INITMENUPOPUP: - if(undo_list != 0)EnableMenuItem(GetMenu(hMemView),MENU_MV_EDIT_UNDO,MF_BYCOMMAND | MF_ENABLED); - else EnableMenuItem(GetMenu(hMemView),MENU_MV_EDIT_UNDO,MF_BYCOMMAND | MF_GRAYED); + if (undo_list != 0) + EnableMenuItem(GetMenu(hMemView), MENU_MV_EDIT_UNDO, MF_BYCOMMAND | MF_ENABLED); + else + EnableMenuItem(GetMenu(hMemView), MENU_MV_EDIT_UNDO, MF_BYCOMMAND | MF_GRAYED); - if(TableFileLoaded)EnableMenuItem(GetMenu(hMemView),MENU_MV_FILE_UNLOAD_TBL,MF_BYCOMMAND | MF_ENABLED); - else EnableMenuItem(GetMenu(hMemView),MENU_MV_FILE_UNLOAD_TBL,MF_BYCOMMAND | MF_GRAYED); + if (TableFileLoaded) + EnableMenuItem(GetMenu(hMemView), MENU_MV_FILE_UNLOAD_TBL, MF_BYCOMMAND | MF_ENABLED); + else + EnableMenuItem(GetMenu(hMemView), MENU_MV_FILE_UNLOAD_TBL, MF_BYCOMMAND | MF_GRAYED); return 0; @@ -1247,33 +1338,34 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa // GetTextMetrics (HDataDC, &textMetric); MaxSize = 0x10000; - //Allocate Memory for color lists + // Allocate Memory for color lists DataAmount = 0x100; - //mbg merge 7/18/06 added casts: - CurTextColorList = (COLORREF*)malloc(DataAmount*sizeof(COLORREF)); - CurBGColorList = (COLORREF*)malloc(DataAmount*sizeof(COLORREF)); - DimTextColorList = (COLORREF*)malloc(DataAmount*sizeof(COLORREF)); - DimBGColorList = (COLORREF*)malloc(DataAmount*sizeof(COLORREF)); + // mbg merge 7/18/06 added casts: + CurTextColorList = (COLORREF *)malloc(DataAmount * sizeof(COLORREF)); + CurBGColorList = (COLORREF *)malloc(DataAmount * sizeof(COLORREF)); + DimTextColorList = (COLORREF *)malloc(DataAmount * sizeof(COLORREF)); + DimBGColorList = (COLORREF *)malloc(DataAmount * sizeof(COLORREF)); HexTextColorList = CurTextColorList; HexBGColorList = CurBGColorList; AnsiTextColorList = DimTextColorList; AnsiBGColorList = DimBGColorList; - PreviousValues = (int*)malloc(DataAmount*sizeof(int)); - HighlightedBytes = (unsigned int*)malloc(DataAmount*sizeof(unsigned int)); + PreviousValues = (int *)malloc(DataAmount * sizeof(int)); + HighlightedBytes = (unsigned int *)malloc(DataAmount * sizeof(unsigned int)); resetHighlightingActivityLog(); EditingText = CurOffset = 0; EditingMode = MODE_NES_MEMORY; CreateCheatMap(); - //set the default table + // set the default table UnloadTableFile(); - UpdateColorTable(); //draw it + UpdateColorTable(); // draw it // update menus HMENU menu = GetMenu(hwnd); for (int i = MODE_NES_MEMORY; i <= MODE_NES_FILE; i++) - if (EditingMode == i) { + if (EditingMode == i) + { CheckMenuRadioItem(menu, MENU_MV_VIEW_RAM, MENU_MV_VIEW_ROM, MENU_MV_VIEW_RAM, MF_BYCOMMAND); break; } @@ -1287,7 +1379,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa for (int j = 0; j < colormenu[i].size; ++j) InsertColorMenu(hwnd, GetSubMenu(hilightMenu, colormenu[i].sub), &colormenu[i].items[j], j, colormenu[i].base_id + j); } - return 0; + return 0; case WM_PAINT: BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); @@ -1299,16 +1391,16 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa UINT len; char *ftmp; - len=DragQueryFile((HDROP)wParam,0,0,0)+1; - if(ftmp = (char*)malloc(len)) + len = DragQueryFile((HDROP)wParam, 0, 0, 0) + 1; + if (ftmp = (char *)malloc(len)) { - DragQueryFile((HDROP)wParam,0,ftmp,len); + DragQueryFile((HDROP)wParam, 0, ftmp, len); string fileDropped = ftmp; - //adelikat: Drag and Drop only checks file extension, the internal functions are responsible for file error checking + // adelikat: Drag and Drop only checks file extension, the internal functions are responsible for file error checking //------------------------------------------------------- - //Check if .tbl + // Check if .tbl //------------------------------------------------------- - if (!(fileDropped.find(".tbl") == string::npos) && (fileDropped.find(".tbl") == fileDropped.length()-4)) + if (!(fileDropped.find(".tbl") == string::npos) && (fileDropped.find(".tbl") == fileDropped.length() - 4)) { LoadTable(fileDropped.c_str()); } @@ -1318,7 +1410,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa MessageBox(hwnd, str.c_str(), "File error", 0); } free(ftmp); - } + } } break; case WM_VSCROLL: @@ -1328,28 +1420,43 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa si.fMask = SIF_ALL; si.cbSize = sizeof(SCROLLINFO); GetScrollInfo(hwnd, SB_VERT, &si); - switch (LOWORD(wParam)) { - case SB_ENDSCROLL: - case SB_TOP: - case SB_BOTTOM: break; - case SB_LINEUP: si.nPos--; break; - case SB_LINEDOWN:si.nPos++; break; - case SB_PAGEUP: si.nPos -= si.nPage; break; - case SB_PAGEDOWN: si.nPos += si.nPage; break; - case SB_THUMBPOSITION: //break; - case SB_THUMBTRACK: si.nPos = si.nTrackPos; break; - } - if (si.nPos < si.nMin) si.nPos = si.nMin; - if ((si.nPos + (int)si.nPage) > si.nMax) si.nPos = si.nMax - si.nPage; //mbg merge 7/18/06 added cast + switch (LOWORD(wParam)) + { + case SB_ENDSCROLL: + case SB_TOP: + case SB_BOTTOM: + break; + case SB_LINEUP: + si.nPos--; + break; + case SB_LINEDOWN: + si.nPos++; + break; + case SB_PAGEUP: + si.nPos -= si.nPage; + break; + case SB_PAGEDOWN: + si.nPos += si.nPage; + break; + case SB_THUMBPOSITION: // break; + case SB_THUMBTRACK: + si.nPos = si.nTrackPos; + break; + } + if (si.nPos < si.nMin) + si.nPos = si.nMin; + if ((si.nPos + (int)si.nPage) > si.nMax) + si.nPos = si.nMax - si.nPage; // mbg merge 7/18/06 added cast CurOffset = si.nPos * 16; SetScrollInfo(hwnd, SB_VERT, &si, TRUE); UpdateColorTable(); return 0; } case WM_CHAR: - if(GetKeyState(VK_CONTROL) & 0x8000) return 0; //prevents input when pressing ctrl+c + if (GetKeyState(VK_CONTROL) & 0x8000) + return 0; // prevents input when pressing ctrl+c char c[2]; - c[0] = (char)(wParam&0xFF); + c[0] = (char)(wParam & 0xFF); c[1] = 0; InputData(c); UpdateColorTable(); @@ -1382,7 +1489,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa --tmpEndAddy; } else if (wParam == VK_DOWN) - { + { if (tmpEndAddy >= MaxSize - 1) return 0; tmpEndAddy += 16; @@ -1422,7 +1529,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa return 0; if (GetKeyState(VK_CONTROL) & 0x8000) tmpEndAddy = MaxSize - 1; - else + else tmpEndAddy = tmpEndAddy / 16 * 16 + 15; } @@ -1499,7 +1606,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa } else if (wParam == VK_END) { - if (CursorStartAddy == 0 && CursorEndAddy == -1 && CurOffset ==(MaxSize - DataAmount) / 16 * 16) + if (CursorStartAddy == 0 && CursorEndAddy == -1 && CurOffset == (MaxSize - DataAmount) / 16 * 16) return 0; CurOffset = (MaxSize - DataAmount) / 16 * 16; CursorStartAddy = MaxSize - 1; @@ -1535,7 +1642,8 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa if (CursorStartAddy <= 0) return 0; CursorStartAddy--; - } else if (wParam == VK_PRIOR) + } + else if (wParam == VK_PRIOR) { if (CurOffset <= 0) return 0; @@ -1556,7 +1664,8 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa CurOffset = 0; CursorStartAddy = 0; } - else if (wParam == VK_END) { + else if (wParam == VK_END) + { if (CurOffset >= (MaxSize - DataAmount) / 16 * 16) CurOffset = (MaxSize - DataAmount) / 16 * 16; CursorStartAddy = MaxSize - 1; @@ -1570,7 +1679,6 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa } TempData = PREVIOUS_VALUE_UNDEFINED; - // Cursor Out of bound check if (CursorStartAddy < 0) CursorStartAddy = 0; @@ -1585,7 +1693,8 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa if (CurOffset < 0) CurOffset = 0; } - else if (GetKeyState(VK_CONTROL) & 0x8000) { + else if (GetKeyState(VK_CONTROL) & 0x8000) + { if (wParam >= '0' && wParam <= '9') { @@ -1607,22 +1716,23 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa } } - switch (wParam) { - case 0x43: //Ctrl+C - MemViewCallB(hMemView, WM_COMMAND, MENU_MV_EDIT_COPY, 0); //recursion at work + switch (wParam) + { + case 0x43: // Ctrl+C + MemViewCallB(hMemView, WM_COMMAND, MENU_MV_EDIT_COPY, 0); // recursion at work return 0; - case 0x56: //Ctrl+V + case 0x56: // Ctrl+V MemViewCallB(hMemView, WM_COMMAND, MENU_MV_EDIT_PASTE, 0); return 0; - case 0x5a: //Ctrl+Z + case 0x5a: // Ctrl+Z UndoLastPatch(); break; - case 0x41: //Ctrl+A - // Fall through to Ctrl+G - case 0x47: //Ctrl+G + case 0x41: // Ctrl+A + // Fall through to Ctrl+G + case 0x47: // Ctrl+G GotoAddress(hwnd); break; - case 0x46: //Ctrl+F + case 0x46: // Ctrl+F OpenFindDialog(); break; default: @@ -1638,7 +1748,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa // Pressed a key without any function, stop return 0; - //This updates the scroll bar to curoffset + // This updates the scroll bar to curoffset SCROLLINFO si; ZeroMemory(&si, sizeof(SCROLLINFO)); si.fMask = SIF_POS; @@ -1653,12 +1763,12 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa SetCapture(hwnd); lbuttondown = 1; tmpStartAddy = GetAddyFromCoord(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); - if(tmpStartAddy < 0) + if (tmpStartAddy < 0) { CursorDragPoint = -1; return 0; } - if(tmpStartAddy > MaxSize) + if (tmpStartAddy > MaxSize) { CursorDragPoint = -1; return 0; @@ -1690,18 +1800,20 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa { if (CursorDragPoint < 0) return 0; - int x = GET_X_LPARAM(lParam); - int y = GET_Y_LPARAM(lParam); - if(lbuttondown){ - AutoScrollFromCoord(x,y); - tmpEndAddy = GetAddyFromCoord(x,y); + int x = GET_X_LPARAM(lParam); + int y = GET_Y_LPARAM(lParam); + if (lbuttondown) + { + AutoScrollFromCoord(x, y); + tmpEndAddy = GetAddyFromCoord(x, y); if (tmpEndAddy >= MaxSize) tmpEndAddy = MaxSize - 1; SwitchEditingText(AddyWasText); - if(tmpEndAddy >= 0){ + if (tmpEndAddy >= 0) + { CursorStartAddy = std::min(tmpStartAddy, tmpEndAddy); CursorEndAddy = std::max(tmpStartAddy, tmpEndAddy); - if(CursorEndAddy == CursorStartAddy) + if (CursorEndAddy == CursorStartAddy) CursorEndAddy = -1; } @@ -1714,7 +1826,8 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa lbuttondown = 0; if (CursorEndAddy == CursorStartAddy) CursorEndAddy = -1; - if((CursorEndAddy < CursorStartAddy) && (CursorEndAddy != -1)){ //this reverses them if they're not right + if ((CursorEndAddy < CursorStartAddy) && (CursorEndAddy != -1)) + { // this reverses them if they're not right int tmpAddy = CursorStartAddy; CursorStartAddy = CursorEndAddy; CursorEndAddy = tmpAddy; @@ -1725,7 +1838,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa return 0; case WM_CONTEXTMENU: { - POINT ptScreen = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + POINT ptScreen = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; POINT ptClient; int curAddy; if (ptScreen.x == -1 && ptScreen.y == -1) @@ -1747,106 +1860,112 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa HMENU hMenu = CreatePopupMenu(); char str[128]; - for(int i = 0;i < POPUPNUM;i++) + for (int i = 0; i < POPUPNUM; i++) { - if((curAddy >= popupmenu[i].minaddress) && (curAddy <= popupmenu[i].maxaddress) && (EditingMode == popupmenu[i].editingmode)) + if ((curAddy >= popupmenu[i].minaddress) && (curAddy <= popupmenu[i].maxaddress) && (EditingMode == popupmenu[i].editingmode)) { - switch(popupmenu[i].id) + switch (popupmenu[i].id) { - case ID_ADDRESS_SYMBOLIC_NAME: + case ID_ADDRESS_SYMBOLIC_NAME: + { + if (curAddy <= CursorEndAddy && curAddy >= CursorStartAddy) { - if (curAddy <= CursorEndAddy && curAddy >= CursorStartAddy) - { - if (curAddy >= 0x8000 && bank != -1) - sprintf(str, "Add Symbolic Debug Name For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); - else - sprintf(str, "Add Symbolic Debug Name For Address %04X-%04X", CursorStartAddy, CursorEndAddy); - } else - { - if (curAddy >= 0x8000 && bank != -1) - sprintf(str, "Add Symbolic Debug Name For Address %02X:%04X", bank, curAddy); - else - sprintf(str, "Add Symbolic Debug Name For Address %04X", curAddy); - } - popupmenu[i].text = str; - break; + if (curAddy >= 0x8000 && bank != -1) + sprintf(str, "Add Symbolic Debug Name For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); + else + sprintf(str, "Add Symbolic Debug Name For Address %04X-%04X", CursorStartAddy, CursorEndAddy); } - //this will set the text for the menu dynamically based on the id - case ID_ADDRESS_FRZ_SUBMENU: + else { - HMENU sub = CreatePopupMenu(); - AppendMenu(hMenu, MF_POPUP | MF_STRING, (UINT_PTR)sub, "Freeze / Unfreeze Address"); - AppendMenu(sub, MF_STRING, ID_ADDRESS_FRZ_TOGGLE_STATE, "Toggle state"); - AppendMenu(sub, MF_STRING, ID_ADDRESS_FRZ_FREEZE, "Freeze"); - AppendMenu(sub, MF_STRING, ID_ADDRESS_FRZ_UNFREEZE, "Unfreeze"); - AppendMenu(sub, MF_SEPARATOR, ID_ADDRESS_FRZ_SEP, "-"); - AppendMenu(sub, MF_STRING, ID_ADDRESS_FRZ_UNFREEZE_ALL, "Unfreeze all"); - - int tempAddy; - if (CursorEndAddy == -1) tempAddy = CursorStartAddy; - else tempAddy = CursorEndAddy; //This is necessary because CursorEnd = -1 if only 1 address is selected - if (tempAddy - CursorStartAddy + FrozenAddressCount > 255) //There is a limit of 256 possible frozen addresses, therefore if the user has selected more than this limit, disable freeze menu items - { - EnableMenuItem(sub,ID_ADDRESS_FRZ_TOGGLE_STATE,MF_GRAYED); - EnableMenuItem(sub,ID_ADDRESS_FRZ_FREEZE,MF_GRAYED); - } - continue; + if (curAddy >= 0x8000 && bank != -1) + sprintf(str, "Add Symbolic Debug Name For Address %02X:%04X", bank, curAddy); + else + sprintf(str, "Add Symbolic Debug Name For Address %04X", curAddy); } - case ID_ADDRESS_ADDBP_R: + popupmenu[i].text = str; + break; + } + // this will set the text for the menu dynamically based on the id + case ID_ADDRESS_FRZ_SUBMENU: + { + HMENU sub = CreatePopupMenu(); + AppendMenu(hMenu, MF_POPUP | MF_STRING, (UINT_PTR)sub, "Freeze / Unfreeze Address"); + AppendMenu(sub, MF_STRING, ID_ADDRESS_FRZ_TOGGLE_STATE, "Toggle state"); + AppendMenu(sub, MF_STRING, ID_ADDRESS_FRZ_FREEZE, "Freeze"); + AppendMenu(sub, MF_STRING, ID_ADDRESS_FRZ_UNFREEZE, "Unfreeze"); + AppendMenu(sub, MF_SEPARATOR, ID_ADDRESS_FRZ_SEP, "-"); + AppendMenu(sub, MF_STRING, ID_ADDRESS_FRZ_UNFREEZE_ALL, "Unfreeze all"); + + int tempAddy; + if (CursorEndAddy == -1) + tempAddy = CursorStartAddy; + else + tempAddy = CursorEndAddy; // This is necessary because CursorEnd = -1 if only 1 address is selected + if (tempAddy - CursorStartAddy + FrozenAddressCount > 255) // There is a limit of 256 possible frozen addresses, therefore if the user has selected more than this limit, disable freeze menu items { - // We want this to give the address to add the read breakpoint for - if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) - { - if (curAddy >= 0x8000 && bank != -1) - sprintf(str,"Add Read Breakpoint For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); - else - sprintf(str,"Add Read Breakpoint For Address %04X-%04X", CursorStartAddy, CursorEndAddy); - } else - { - if (curAddy >= 0x8000 && bank != -1) - sprintf(str,"Add Read Breakpoint For Address %02X:%04X", bank, curAddy); - else - sprintf(str,"Add Read Breakpoint For Address %04X", curAddy); - } - popupmenu[i].text = str; - break; + EnableMenuItem(sub, ID_ADDRESS_FRZ_TOGGLE_STATE, MF_GRAYED); + EnableMenuItem(sub, ID_ADDRESS_FRZ_FREEZE, MF_GRAYED); } - case ID_ADDRESS_ADDBP_W: + continue; + } + case ID_ADDRESS_ADDBP_R: + { + // We want this to give the address to add the read breakpoint for + if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) { - if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) - { - if (curAddy >= 0x8000 && bank != -1) - sprintf(str,"Add Write Breakpoint For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); - else - sprintf(str,"Add Write Breakpoint For Address %04X-%04X", CursorStartAddy, CursorEndAddy); - } else - { - if (curAddy >= 0x8000 && bank != -1) - sprintf(str,"Add Write Breakpoint For Address %02X:%04X", bank, curAddy); - else - sprintf(str,"Add Write Breakpoint For Address %04X", curAddy); - } - popupmenu[i].text = str; - break; + if (curAddy >= 0x8000 && bank != -1) + sprintf(str, "Add Read Breakpoint For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); + else + sprintf(str, "Add Read Breakpoint For Address %04X-%04X", CursorStartAddy, CursorEndAddy); } - case ID_ADDRESS_ADDBP_X: + else { - if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) - { - if (curAddy >= 0x8000 && bank != -1) - sprintf(str,"Add Execute Breakpoint For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); - else - sprintf(str,"Add Execute Breakpoint For Address %04X-%04X", CursorStartAddy, CursorEndAddy); - } else - { - if (curAddy >= 0x8000 && bank != -1) - sprintf(str,"Add Execute Breakpoint For Address %02X:%04X", bank, curAddy); - else - sprintf(str,"Add Execute Breakpoint For Address %04X", curAddy); - } - popupmenu[i].text = str; - break; + if (curAddy >= 0x8000 && bank != -1) + sprintf(str, "Add Read Breakpoint For Address %02X:%04X", bank, curAddy); + else + sprintf(str, "Add Read Breakpoint For Address %04X", curAddy); + } + popupmenu[i].text = str; + break; + } + case ID_ADDRESS_ADDBP_W: + { + if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) + { + if (curAddy >= 0x8000 && bank != -1) + sprintf(str, "Add Write Breakpoint For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); + else + sprintf(str, "Add Write Breakpoint For Address %04X-%04X", CursorStartAddy, CursorEndAddy); + } + else + { + if (curAddy >= 0x8000 && bank != -1) + sprintf(str, "Add Write Breakpoint For Address %02X:%04X", bank, curAddy); + else + sprintf(str, "Add Write Breakpoint For Address %04X", curAddy); } + popupmenu[i].text = str; + break; + } + case ID_ADDRESS_ADDBP_X: + { + if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) + { + if (curAddy >= 0x8000 && bank != -1) + sprintf(str, "Add Execute Breakpoint For Address %02X:%04X-%02X:%04X", bank, CursorStartAddy, bank, CursorEndAddy); + else + sprintf(str, "Add Execute Breakpoint For Address %04X-%04X", CursorStartAddy, CursorEndAddy); + } + else + { + if (curAddy >= 0x8000 && bank != -1) + sprintf(str, "Add Execute Breakpoint For Address %02X:%04X", bank, curAddy); + else + sprintf(str, "Add Execute Breakpoint For Address %04X", curAddy); + } + popupmenu[i].text = str; + break; + } } AppendMenu(hMenu, MF_STRING, popupmenu[i].id, popupmenu[i].text); } @@ -1863,292 +1982,309 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa AppendMenu(hMenu, MF_STRING, ID_ADDRESS_ADD_BOOKMARK, "Add Bookmark"); int id = TrackPopupMenuEx(hMenu, TPM_RETURNCMD | TPM_RIGHTBUTTON, ptScreen.x, ptScreen.y, hMemView, NULL); - switch(id) + switch (id) + { + case ID_ADDRESS_FRZ_TOGGLE_STATE: { - case ID_ADDRESS_FRZ_TOGGLE_STATE: + for (int frzAddr = CursorStartAddy; (CursorEndAddy == -1 && frzAddr == CursorStartAddy) || frzAddr <= CursorEndAddy; frzAddr++) { - for (int frzAddr = CursorStartAddy; (CursorEndAddy == -1 && frzAddr == CursorStartAddy) || frzAddr <= CursorEndAddy; frzAddr++) - { - FreezeRam(frzAddr, 0, frzAddr == CursorEndAddy); - } - break; + FreezeRam(frzAddr, 0, frzAddr == CursorEndAddy); } - case ID_ADDRESS_FRZ_FREEZE: + break; + } + case ID_ADDRESS_FRZ_FREEZE: + { + for (int frzAddr = CursorStartAddy; (CursorEndAddy == -1 && frzAddr == CursorStartAddy) || frzAddr <= CursorEndAddy; frzAddr++) { - for (int frzAddr = CursorStartAddy; (CursorEndAddy == -1 && frzAddr == CursorStartAddy) || frzAddr <= CursorEndAddy; frzAddr++) - { - FreezeRam(frzAddr, 1, frzAddr == CursorEndAddy); - } - break; + FreezeRam(frzAddr, 1, frzAddr == CursorEndAddy); } - case ID_ADDRESS_FRZ_UNFREEZE: + break; + } + case ID_ADDRESS_FRZ_UNFREEZE: + { + for (int frzAddr = CursorStartAddy; (CursorEndAddy == -1 && frzAddr == CursorStartAddy) || frzAddr <= CursorEndAddy; frzAddr++) { - for (int frzAddr = CursorStartAddy; (CursorEndAddy == -1 && frzAddr == CursorStartAddy) || frzAddr <= CursorEndAddy; frzAddr++) - { - FreezeRam(frzAddr, -1, frzAddr == CursorEndAddy); - } - break; - } - case ID_ADDRESS_FRZ_UNFREEZE_ALL: - { - UnfreezeAllRam(); - break; + FreezeRam(frzAddr, -1, frzAddr == CursorEndAddy); } break; + } + case ID_ADDRESS_FRZ_UNFREEZE_ALL: + { + UnfreezeAllRam(); + break; + } + break; - case ID_ADDRESS_ADDBP_R: + case ID_ADDRESS_ADDBP_R: + { + if (numWPs < MAXIMUM_NUMBER_OF_BREAKPOINTS) { - if (numWPs < MAXIMUM_NUMBER_OF_BREAKPOINTS) + watchpoint[numWPs].flags = WP_E | WP_R; + if (EditingMode == MODE_NES_PPU) + watchpoint[numWPs].flags |= BT_P; + if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) { - watchpoint[numWPs].flags = WP_E | WP_R; - if (EditingMode == MODE_NES_PPU) - watchpoint[numWPs].flags |= BT_P; - if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) - { - watchpoint[numWPs].address = CursorStartAddy; - watchpoint[numWPs].endaddress = CursorEndAddy; - } else - { - watchpoint[numWPs].address = curAddy; - watchpoint[numWPs].endaddress = 0; - } - char condition[10] = {0}; - if (EditingMode == MODE_NES_MEMORY) - { - // only break at this Bank - if (curAddy >= 0x8000 && bank != -1) - sprintf(condition, "T==#%02X", bank); - } - checkCondition(condition, numWPs); - - numWPs++; - { - extern int myNumWPs; - myNumWPs++; - } - if (hDebug) - AddBreakList(); - else - DoDebug(0); + watchpoint[numWPs].address = CursorStartAddy; + watchpoint[numWPs].endaddress = CursorEndAddy; } - break; - } - case ID_ADDRESS_ADDBP_W: - { - if (numWPs < MAXIMUM_NUMBER_OF_BREAKPOINTS) + else { - watchpoint[numWPs].flags = WP_E | WP_W; - if (EditingMode == MODE_NES_PPU) - watchpoint[numWPs].flags |= BT_P; - if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) - { - watchpoint[numWPs].address = CursorStartAddy; - watchpoint[numWPs].endaddress = CursorEndAddy; - } else - { - watchpoint[numWPs].address = curAddy; - watchpoint[numWPs].endaddress = 0; - } - char condition[10] = {0}; - if (EditingMode == MODE_NES_MEMORY) - { - // only break at this Bank - if (curAddy >= 0x8000 && bank != -1) - sprintf(condition, "T==#%02X", bank); - } - checkCondition(condition, numWPs); + watchpoint[numWPs].address = curAddy; + watchpoint[numWPs].endaddress = 0; + } + char condition[10] = {0}; + if (EditingMode == MODE_NES_MEMORY) + { + // only break at this Bank + if (curAddy >= 0x8000 && bank != -1) + sprintf(condition, "T==#%02X", bank); + } + checkCondition(condition, numWPs); - numWPs++; - { extern int myNumWPs; - myNumWPs++; } - if (hDebug) - AddBreakList(); - else - DoDebug(0); + numWPs++; + { + extern int myNumWPs; + myNumWPs++; } - break; + if (hDebug) + AddBreakList(); + else + DoDebug(0); } - case ID_ADDRESS_ADDBP_X: + break; + } + case ID_ADDRESS_ADDBP_W: + { + if (numWPs < MAXIMUM_NUMBER_OF_BREAKPOINTS) { - if (numWPs < MAXIMUM_NUMBER_OF_BREAKPOINTS) + watchpoint[numWPs].flags = WP_E | WP_W; + if (EditingMode == MODE_NES_PPU) + watchpoint[numWPs].flags |= BT_P; + if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) { - watchpoint[numWPs].flags = WP_E | WP_X; - if((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) - { - watchpoint[numWPs].address = CursorStartAddy; - watchpoint[numWPs].endaddress = CursorEndAddy; - } else - { - watchpoint[numWPs].address = curAddy; - watchpoint[numWPs].endaddress = 0; - } - char condition[10] = {0}; - if (EditingMode == MODE_NES_MEMORY) - { - // only break at this Bank - if (curAddy >= 0x8000 && bank != -1) - sprintf(condition, "T==#%02X", bank); - } - checkCondition(condition, numWPs); + watchpoint[numWPs].address = CursorStartAddy; + watchpoint[numWPs].endaddress = CursorEndAddy; + } + else + { + watchpoint[numWPs].address = curAddy; + watchpoint[numWPs].endaddress = 0; + } + char condition[10] = {0}; + if (EditingMode == MODE_NES_MEMORY) + { + // only break at this Bank + if (curAddy >= 0x8000 && bank != -1) + sprintf(condition, "T==#%02X", bank); + } + checkCondition(condition, numWPs); - numWPs++; - { extern int myNumWPs; - myNumWPs++; } - if (hDebug) - AddBreakList(); - else - DoDebug(0); + numWPs++; + { + extern int myNumWPs; + myNumWPs++; } - break; + if (hDebug) + AddBreakList(); + else + DoDebug(0); } - case ID_ADDRESS_SEEK_IN_ROM: - ChangeMemViewFocus(MODE_NES_FILE, GetNesFileAddress(curAddy), -1); - break; - case ID_ADDRESS_CREATE_GG_CODE: - SetGGConvFocus(curAddy, GetMem(curAddy)); - break; - case ID_ADDRESS_ADD_BOOKMARK: + break; + } + case ID_ADDRESS_ADDBP_X: + { + if (numWPs < MAXIMUM_NUMBER_OF_BREAKPOINTS) { - if (foundBookmark == -1) + watchpoint[numWPs].flags = WP_E | WP_X; + if ((curAddy <= CursorEndAddy) && (curAddy >= CursorStartAddy)) { - if (hexBookmarks.bookmarkCount >= 64) - MessageBox(hwnd, "Can't set more than 64 bookmarks.", "Error", MB_OK | MB_ICONERROR); - else - { - int ret = addBookmark(hwnd, CursorStartAddy, EditingMode); - if (ret == -1) - MessageBox(hwnd, "Error adding bookmark.", "Error", MB_OK | MB_ICONERROR); - else if (ret == 0) - { - updateBookmarkMenus(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS)); - UpdateColorTable(); - } - } + watchpoint[numWPs].address = CursorStartAddy; + watchpoint[numWPs].endaddress = CursorEndAddy; } - else // usually it cannot reach here. - MessageBox(hwnd, "This address already has a bookmark.", "Error", MB_OK | MB_ICONERROR); - break; + else + { + watchpoint[numWPs].address = curAddy; + watchpoint[numWPs].endaddress = 0; + } + char condition[10] = {0}; + if (EditingMode == MODE_NES_MEMORY) + { + // only break at this Bank + if (curAddy >= 0x8000 && bank != -1) + sprintf(condition, "T==#%02X", bank); + } + checkCondition(condition, numWPs); + + numWPs++; + { + extern int myNumWPs; + myNumWPs++; + } + if (hDebug) + AddBreakList(); + else + DoDebug(0); } - case ID_ADDRESS_EDIT_BOOKMARK: - if (foundBookmark != -1) + break; + } + case ID_ADDRESS_SEEK_IN_ROM: + ChangeMemViewFocus(MODE_NES_FILE, GetNesFileAddress(curAddy), -1); + break; + case ID_ADDRESS_CREATE_GG_CODE: + SetGGConvFocus(curAddy, GetMem(curAddy)); + break; + case ID_ADDRESS_ADD_BOOKMARK: + { + if (foundBookmark == -1) + { + if (hexBookmarks.bookmarkCount >= 64) + MessageBox(hwnd, "Can't set more than 64 bookmarks.", "Error", MB_OK | MB_ICONERROR); + else { - int ret = editBookmark(hwnd, foundBookmark); + int ret = addBookmark(hwnd, CursorStartAddy, EditingMode); if (ret == -1) - MessageBox(hwnd, "Error editing bookmark.", "Error", MB_OK | MB_ICONERROR); + MessageBox(hwnd, "Error adding bookmark.", "Error", MB_OK | MB_ICONERROR); else if (ret == 0) { updateBookmarkMenus(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS)); UpdateColorTable(); } } - else // usually it cannot reach here. - MessageBox(hwnd, "This address doesn't have a bookmark.", "Error", MB_OK | MB_ICONERROR); - break; - case ID_ADDRESS_REMOVE_BOOKMARK: - if (foundBookmark != -1) + } + else // usually it cannot reach here. + MessageBox(hwnd, "This address already has a bookmark.", "Error", MB_OK | MB_ICONERROR); + break; + } + case ID_ADDRESS_EDIT_BOOKMARK: + if (foundBookmark != -1) + { + int ret = editBookmark(hwnd, foundBookmark); + if (ret == -1) + MessageBox(hwnd, "Error editing bookmark.", "Error", MB_OK | MB_ICONERROR); + else if (ret == 0) { - int ret = removeBookmark(foundBookmark); - if (ret == -1) - MessageBox(hwnd, "Error removing bookmark.", "Error", MB_OK | MB_ICONERROR); - else if (ret == 0) - { - updateBookmarkMenus(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS)); - UpdateColorTable(); - } + updateBookmarkMenus(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS)); + UpdateColorTable(); } - else - // usually it cannot reach here. - MessageBox(hwnd, "This address doesn't have a bookmark.", "Error", MB_OK | MB_ICONERROR); - break; - case ID_ADDRESS_SYMBOLIC_NAME: + } + else // usually it cannot reach here. + MessageBox(hwnd, "This address doesn't have a bookmark.", "Error", MB_OK | MB_ICONERROR); + break; + case ID_ADDRESS_REMOVE_BOOKMARK: + if (foundBookmark != -1) { - if (curAddy <= CursorEndAddy && curAddy >= CursorStartAddy ? DoSymbolicDebugNaming(CursorStartAddy, CursorEndAddy - CursorStartAddy + 1, hMemView) : DoSymbolicDebugNaming(curAddy, hMemView)) + int ret = removeBookmark(foundBookmark); + if (ret == -1) + MessageBox(hwnd, "Error removing bookmark.", "Error", MB_OK | MB_ICONERROR); + else if (ret == 0) { - // enable "Symbolic Debug" if not yet enabled - if (!symbDebugEnabled) - { - symbDebugEnabled = true; - if (hDebug) - CheckDlgButton(hDebug, IDC_DEBUGGER_ENABLE_SYMBOLIC, BST_CHECKED); - } - UpdateCaption(); + updateBookmarkMenus(GetSubMenu(GetMenu(hwnd), BOOKMARKS_SUBMENU_POS)); + UpdateColorTable(); } - break; + } + else + // usually it cannot reach here. + MessageBox(hwnd, "This address doesn't have a bookmark.", "Error", MB_OK | MB_ICONERROR); + break; + case ID_ADDRESS_SYMBOLIC_NAME: + { + if (curAddy <= CursorEndAddy && curAddy >= CursorStartAddy ? DoSymbolicDebugNaming(CursorStartAddy, CursorEndAddy - CursorStartAddy + 1, hMemView) : DoSymbolicDebugNaming(curAddy, hMemView)) + { + // enable "Symbolic Debug" if not yet enabled + if (!symbDebugEnabled) + { + symbDebugEnabled = true; + if (hDebug) + CheckDlgButton(hDebug, IDC_DEBUGGER_ENABLE_SYMBOLIC, BST_CHECKED); + } + UpdateCaption(); } break; } - //6 = Create GG Code + break; + } + // 6 = Create GG Code return 0; } case WM_MBUTTONDOWN: { - if (EditingMode != MODE_NES_MEMORY) return 0; + if (EditingMode != MODE_NES_MEMORY) + return 0; int addr = GetAddyFromCoord(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); - if(addr < 0) return 0; + if (addr < 0) + return 0; FreezeRam(addr, 0, 1); return 0; } case WM_MOUSEWHEEL: { SCROLLINFO si; - int delta = (short)HIWORD(wParam);///WHEEL_DELTA; + int delta = (short)HIWORD(wParam); /// WHEEL_DELTA; ZeroMemory(&si, sizeof(SCROLLINFO)); si.fMask = SIF_ALL; si.cbSize = sizeof(SCROLLINFO); - GetScrollInfo(hwnd,SB_VERT,&si); - if(delta < 0)si.nPos+=si.nPage; - if(delta > 0)si.nPos-=si.nPage; - if (si.nPos < si.nMin) si.nPos = si.nMin; - if ((si.nPos+(int)si.nPage) > si.nMax) si.nPos = si.nMax-si.nPage; //added cast - CurOffset = si.nPos*16; - if (CurOffset >= MaxSize - DataAmount) CurOffset = MaxSize - DataAmount; - if (CurOffset < 0) CurOffset = 0; - SetScrollInfo(hwnd,SB_VERT,&si,TRUE); + GetScrollInfo(hwnd, SB_VERT, &si); + if (delta < 0) + si.nPos += si.nPage; + if (delta > 0) + si.nPos -= si.nPage; + if (si.nPos < si.nMin) + si.nPos = si.nMin; + if ((si.nPos + (int)si.nPage) > si.nMax) + si.nPos = si.nMax - si.nPage; // added cast + CurOffset = si.nPos * 16; + if (CurOffset >= MaxSize - DataAmount) + CurOffset = MaxSize - DataAmount; + if (CurOffset < 0) + CurOffset = 0; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); UpdateColorTable(); return 0; } case WM_SIZE: - if(wParam == SIZE_RESTORED) //If dialog was resized - { - GetWindowRect(hwnd,&newMemViewRect); //Get new size - MemViewSizeX = newMemViewRect.right-newMemViewRect.left; //Store new size (this will be used to store in the .cfg file) - MemViewSizeY = newMemViewRect.bottom-newMemViewRect.top; - } - ClientHeight = HIWORD (lParam); - if (DataAmount != ((ClientHeight/MemFontHeight)*16)) - { - DataAmount = ((ClientHeight/MemFontHeight)*16); - if (CurOffset >= MaxSize - DataAmount) CurOffset = MaxSize - DataAmount; - if (CurOffset < 0) CurOffset = 0; - //mbg merge 7/18/06 added casts: - CurTextColorList = (COLORREF*)realloc(CurTextColorList, DataAmount*sizeof(COLORREF)); - CurBGColorList = (COLORREF*)realloc(CurBGColorList, DataAmount*sizeof(COLORREF)); - DimTextColorList = (COLORREF*)realloc(DimTextColorList, DataAmount*sizeof(COLORREF)); - DimBGColorList = (COLORREF*)realloc(DimBGColorList, DataAmount*sizeof(COLORREF)); + if (wParam == SIZE_RESTORED) // If dialog was resized + { + GetWindowRect(hwnd, &newMemViewRect); // Get new size + MemViewSizeX = newMemViewRect.right - newMemViewRect.left; // Store new size (this will be used to store in the .cfg file) + MemViewSizeY = newMemViewRect.bottom - newMemViewRect.top; + } + ClientHeight = HIWORD(lParam); + if (DataAmount != ((ClientHeight / MemFontHeight) * 16)) + { + DataAmount = ((ClientHeight / MemFontHeight) * 16); + if (CurOffset >= MaxSize - DataAmount) + CurOffset = MaxSize - DataAmount; + if (CurOffset < 0) + CurOffset = 0; + // mbg merge 7/18/06 added casts: + CurTextColorList = (COLORREF *)realloc(CurTextColorList, DataAmount * sizeof(COLORREF)); + CurBGColorList = (COLORREF *)realloc(CurBGColorList, DataAmount * sizeof(COLORREF)); + DimTextColorList = (COLORREF *)realloc(DimTextColorList, DataAmount * sizeof(COLORREF)); + DimBGColorList = (COLORREF *)realloc(DimBGColorList, DataAmount * sizeof(COLORREF)); HexTextColorList = EditingText ? DimTextColorList : CurTextColorList; HexBGColorList = EditingText ? DimBGColorList : CurBGColorList; AnsiTextColorList = EditingText ? CurTextColorList : DimTextColorList; AnsiBGColorList = EditingText ? CurBGColorList : DimBGColorList; - PreviousValues = (int*)realloc(PreviousValues,(DataAmount)*sizeof(int)); - HighlightedBytes = (unsigned int*)realloc(HighlightedBytes,(DataAmount)*sizeof(unsigned int)); + PreviousValues = (int *)realloc(PreviousValues, (DataAmount) * sizeof(int)); + HighlightedBytes = (unsigned int *)realloc(HighlightedBytes, (DataAmount) * sizeof(unsigned int)); resetHighlightingActivityLog(); } - //Set vertical scroll bar range and page size + // Set vertical scroll bar range and page size SCROLLINFO si; ZeroMemory(&si, sizeof(SCROLLINFO)); - si.cbSize = sizeof (si) ; - si.fMask = (SIF_RANGE|SIF_PAGE) ; - si.nMin = 0 ; - si.nMax = MaxSize/16 ; - si.nPage = ClientHeight/MemFontHeight; - SetScrollInfo (hwnd, SB_VERT, &si, TRUE); + si.cbSize = sizeof(si); + si.fMask = (SIF_RANGE | SIF_PAGE); + si.nMin = 0; + si.nMax = MaxSize / 16; + si.nPage = ClientHeight / MemFontHeight; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); UpdateColorTable(); - return 0 ; + return 0; case WM_COMMAND: - switch(wParam) + switch (wParam) { case MENU_MV_FILE_SAVE: FlushUndoBuffer(); @@ -2163,14 +2299,15 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa case MENU_MV_FILE_LOAD_TBL: { int errLine = LoadTableFile(); - if (errLine != -1) { + if (errLine != -1) + { char str[128]; sprintf(str, "Error loading table file at Line %d", errLine); MessageBox(hMemView, str, "Error", MB_OK | MB_ICONERROR); } UpdateColorTable(); } - return 0; + return 0; case MENU_MV_FILE_UNLOAD_TBL: UnloadTableFile(); UpdateColorTable(); @@ -2180,7 +2317,8 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa { char bar[0x800]; unsigned int i; - for (i=0;i>10][(i)]; - else if(i < 0x3F00) bar[i] = vnapage[(i>>10)&0x3][i&0x3FF]; - else bar[i] = READPAL_MOTHEROFALL(i & 0x1F); + if (i < 0x2000) + bar[i] = VPage[(i) >> 9][(i)]; + else if (i < 0x3F00) + bar[i] = vnapage[(i >> 10) & 0x3][i & 0x3FF]; + else + bar[i] = READPAL_MOTHEROFALL(i & 0x1F); } dumpToFile(bar, sizeof(bar)); return 0; } case MENU_MV_FILE_DUMP_OAM: - { - char bar[0x100]; - unsigned int i; - for (i=0;i<0x100;i++) bar[i] = SPRAM[i]; - dumpToFile(bar,0x100); - return 0; - } + { + char bar[0x100]; + unsigned int i; + for (i = 0; i < 0x100; i++) + bar[i] = SPRAM[i]; + dumpToFile(bar, 0x100); + return 0; + } case MENU_MV_FILE_LOAD_RAM: { char bar[0x800]; if (loadFromFile(bar, sizeof(bar))) { - for (uint16 addr=0; addr>10][addr] = v; //todo: detect if this is vrom and turn it red if so - if((addr >= 0x2000) && (addr < 0x3F00)) - vnapage[(addr>>10)&0x3][addr&0x3FF] = v; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct? - if((addr >= 0x3F00) && (addr < 0x3FFF)) - PalettePoke(addr,v); + if (addr < 0x2000) + VPage[addr >> 9][addr] = v; // todo: detect if this is vrom and turn it red if so + if ((addr >= 0x2000) && (addr < 0x3F00)) + vnapage[(addr >> 10) & 0x3][addr & 0x3FF] = v; // todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct? + if ((addr >= 0x3F00) && (addr < 0x3FFF)) + PalettePoke(addr, v); } } return 0; @@ -2251,7 +2394,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa char bar[0x100]; if (loadFromFile(bar, sizeof(bar))) { - for (uint16 addr=0; addr= MaxSize - DataAmount) CurOffset = MaxSize - DataAmount; - if (CurOffset < 0) CurOffset = 0; - if(CursorEndAddy >= MaxSize) CursorEndAddy = -1; - if(CursorStartAddy >= MaxSize) CursorStartAddy= MaxSize-1; + if (CurOffset >= MaxSize - DataAmount) + CurOffset = MaxSize - DataAmount; + if (CurOffset < 0) + CurOffset = 0; + if (CursorEndAddy >= MaxSize) + CursorEndAddy = -1; + if (CursorStartAddy >= MaxSize) + CursorStartAddy = MaxSize - 1; - //Set vertical scroll bar range and page size + // Set vertical scroll bar range and page size ZeroMemory(&si, sizeof(SCROLLINFO)); - si.cbSize = sizeof (si) ; - si.fMask = (SIF_RANGE|SIF_PAGE) ; - si.nMin = 0 ; - si.nMax = MaxSize/16 ; - si.nPage = ClientHeight/MemFontHeight; - SetScrollInfo (hwnd, SB_VERT, &si, TRUE); + si.cbSize = sizeof(si); + si.fMask = (SIF_RANGE | SIF_PAGE); + si.nMin = 0; + si.nMax = MaxSize / 16; + si.nPage = ClientHeight / MemFontHeight; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); resetHighlightingActivityLog(); UpdateColorTable(); @@ -2367,7 +2519,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa case ID_HIGHLIGHTING_HIGHLIGHT_ACTIVITY: { MemView_HighlightActivity ^= 1; - CheckMenuItem(GetMenu(hMemView), ID_HIGHLIGHTING_HIGHLIGHT_ACTIVITY, (MemView_HighlightActivity) ? MF_CHECKED: MF_UNCHECKED); + CheckMenuItem(GetMenu(hMemView), ID_HIGHLIGHTING_HIGHLIGHT_ACTIVITY, (MemView_HighlightActivity) ? MF_CHECKED : MF_UNCHECKED); resetHighlightingActivityLog(); if (!MemView_HighlightActivity) UpdateMemoryView(1); @@ -2394,7 +2546,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa case ID_HIGHLIGHTING_FADEWHENPAUSED: { MemView_HighlightActivity_FadeWhenPaused ^= 1; - CheckMenuItem(GetMenu(hMemView), ID_HIGHLIGHTING_FADEWHENPAUSED, (MemView_HighlightActivity_FadeWhenPaused) ? MF_CHECKED: MF_UNCHECKED); + CheckMenuItem(GetMenu(hMemView), ID_HIGHLIGHTING_FADEWHENPAUSED, (MemView_HighlightActivity_FadeWhenPaused) ? MF_CHECKED : MF_UNCHECKED); resetHighlightingActivityLog(); return 0; } @@ -2448,14 +2600,14 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa } break; case ID_CDLOGGER_DEFCOLOR: - if (!IsCdlColorDefault() && MessageBox(hwnd, "Do you want to restore all the colors to default?", "Restore default colors", MB_YESNO | MB_ICONINFORMATION) == IDYES) - { - RestoreDefaultCdlColor(); - UpdateColorTable(); - for (int i = 0; i < sizeof(hexcolormenu) / sizeof(COLORMENU); ++i) - ModifyColorMenu(hwnd, GetCdlColorMenu(hwnd), &cdlcolormenu[i], i, ID_COLOR_CDLOGGER + i); - } - break; + if (!IsCdlColorDefault() && MessageBox(hwnd, "Do you want to restore all the colors to default?", "Restore default colors", MB_YESNO | MB_ICONINFORMATION) == IDYES) + { + RestoreDefaultCdlColor(); + UpdateColorTable(); + for (int i = 0; i < sizeof(hexcolormenu) / sizeof(COLORMENU); ++i) + ModifyColorMenu(hwnd, GetCdlColorMenu(hwnd), &cdlcolormenu[i], i, ID_COLOR_CDLOGGER + i); + } + break; case MENU_MV_BOOKMARKS_RM_ALL: if (hexBookmarks.bookmarkCount) { @@ -2468,7 +2620,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa return 0; case ID_BOOKMARKS_EXPORT: { - char name[2048] = { 0 }; + char name[2048] = {0}; OPENFILENAME ofn; memset(&ofn, 0, sizeof(ofn)); @@ -2486,13 +2638,13 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa int success = false; if (GetSaveFileName(&ofn)) { - FILE* bld = fopen(name, "wb"); + 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); + extern int storeHexPreferences(FILE *, HexBookmarkList & = hexBookmarks); if (!storeHexPreferences(bld)) success = true; fclose(bld); @@ -2504,7 +2656,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa } case ID_BOOKMARKS_IMPORT: { - char nameo[2048] = { 0 }; + char nameo[2048] = {0}; OPENFILENAME ofn; memset(&ofn, 0, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); @@ -2520,8 +2672,8 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa bool success = false; if (GetOpenFileName(&ofn)) { - char buffer[256] = { 0 }; - FILE* bld = fopen(nameo, "r"); + char buffer[256] = {0}; + FILE *bld = fopen(nameo, "r"); if (bld) { // Read the header to know it's hex bookmark list @@ -2530,12 +2682,12 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa { HexBookmarkList import; // it shares the same logic of creating the hexpreference part of .deb file - extern int loadHexPreferences(FILE*, HexBookmarkList& = hexBookmarks); + extern int loadHexPreferences(FILE *, HexBookmarkList & = hexBookmarks); if (!loadHexPreferences(bld, import) && import.bookmarkCount > 0) { if (importBookmarkProps & IMPORT_DISCARD_ORIGINAL) { - 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)); @@ -2666,7 +2818,8 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa if (conflictShortcutCount) { - if (conflictBookmarkCount) strcat(buffer, " and "); + if (conflictBookmarkCount) + strcat(buffer, " and "); sprintf(units, "%d conflict shortcut", conflictShortcutCount); if (conflictShortcutCount != 1) strcat(units, "s"); @@ -2675,14 +2828,13 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa 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_) @@ -2693,7 +2845,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa // 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 + // update the bookmark shortcut mapping if (tmpImportBookmarkProps & IMPORT_OVERWRITE_SHORTCUT) { memcpy(hexBookmarks.shortcuts, shortcutListOverwrite, sizeof(hexBookmarks.shortcuts)); @@ -2740,19 +2892,19 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa 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; + return 0; case ID_BOOKMARKS_OPTION: { int tmpImportBookmarkProps = importBookmarkProps; if (DialogBoxParam(fceu_hInstance, "IMPORTBOOKMARKOPTIONDIALOG", hwnd, ImportBookmarkCallB, (LPARAM)&tmpImportBookmarkProps)) importBookmarkProps = tmpImportBookmarkProps; } - return 0; + return 0; case MENU_MV_HELP: OpenHelpWindow(memviewhelp); return 0; @@ -2765,82 +2917,84 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa if (newValue != -1) { - ChangeMemViewFocus(hexBookmarks[bookmark].editmode,newValue,-1); + ChangeMemViewFocus(hexBookmarks[bookmark].editmode, newValue, -1); UpdateColorTable(); } return 0; } } - case WM_MOVE: { - if (!IsIconic(hwnd)) { - RECT wrect; - GetWindowRect(hwnd,&wrect); - MemView_wndx = wrect.left; - MemView_wndy = wrect.top; + case WM_MOVE: + { + if (!IsIconic(hwnd)) + { + RECT wrect; + GetWindowRect(hwnd, &wrect); + MemView_wndx = wrect.left; + MemView_wndy = wrect.top; - #ifdef WIN32 - WindowBoundsCheckResize(MemView_wndx,MemView_wndy,MemViewSizeX,wrect.right); - #endif +#ifdef WIN32 + WindowBoundsCheckResize(MemView_wndx, MemView_wndy, MemViewSizeX, wrect.right); +#endif } return 0; - } + } case WM_CLOSE: KillMemView(); return 0; } - return DefWindowProc (hwnd, message, wParam, lParam) ; + return DefWindowProc(hwnd, message, wParam, lParam); } - - void DoMemView() { - WNDCLASSEX wndclass ; - //static RECT al; + WNDCLASSEX wndclass; + // static RECT al; - if (!GameInfo) { + if (!GameInfo) + { FCEUD_PrintError("You must have a game loaded before you can use the Hex Editor."); return; } - //if (GameInfo->type==GIT_NSF) { + // if (GameInfo->type==GIT_NSF) { // FCEUD_PrintError("Sorry, you can't yet use the Memory Viewer with NSFs."); // return; - //} + // } if (!hMemView) { - memset(&wndclass,0,sizeof(wndclass)); - wndclass.cbSize=sizeof(WNDCLASSEX); - wndclass.style = CS_HREDRAW | CS_VREDRAW ; - wndclass.lpfnWndProc = MemViewCallB ; - wndclass.cbClsExtra = 0 ; - wndclass.cbWndExtra = 0 ; - wndclass.hInstance = fceu_hInstance; - wndclass.hIcon = LoadIcon(fceu_hInstance, "ICON_1"); - wndclass.hIconSm = LoadIcon(fceu_hInstance, "ICON_1"); - wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); - wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); - wndclass.lpszMenuName = "MEMVIEWMENU"; + memset(&wndclass, 0, sizeof(wndclass)); + wndclass.cbSize = sizeof(WNDCLASSEX); + wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = MemViewCallB; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = fceu_hInstance; + wndclass.hIcon = LoadIcon(fceu_hInstance, "ICON_1"); + wndclass.hIconSm = LoadIcon(fceu_hInstance, "ICON_1"); + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + wndclass.lpszMenuName = "MEMVIEWMENU"; wndclass.lpszClassName = "MEMVIEW"; - if(!RegisterClassEx(&wndclass)) + if (!RegisterClassEx(&wndclass)) { FCEUD_PrintError("Error Registering MEMVIEW Window Class."); return; } - hMemView = CreateWindowEx(0,"MEMVIEW","Memory Editor", - //WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS, /* Style */ - WS_SYSMENU|WS_MAXIMIZEBOX|WS_MINIMIZEBOX|WS_THICKFRAME|WS_VSCROLL, - CW_USEDEFAULT,CW_USEDEFAULT,580,248, /* X,Y ; Width, Height */ - NULL,NULL,fceu_hInstance,NULL ); - ShowWindow (hMemView, SW_SHOW) ; + hMemView = CreateWindowEx(0, "MEMVIEW", "Memory Editor", + // WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS, /* Style */ + WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME | WS_VSCROLL, + CW_USEDEFAULT, CW_USEDEFAULT, 580, 248, /* X,Y ; Width, Height */ + NULL, NULL, fceu_hInstance, NULL); + ShowWindow(hMemView, SW_SHOW); UpdateCaption(); - } else + } + else { - //SetWindowPos(hMemView, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER); + // SetWindowPos(hMemView, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER); ShowWindow(hMemView, SW_SHOWNORMAL); SetForegroundWindow(hMemView); UpdateCaption(); @@ -2850,178 +3004,225 @@ void DoMemView() if (hMemView) { - //UpdateMemView(0); - //MemViewDoBlit(); + // UpdateMemView(0); + // MemViewDoBlit(); } } -INT_PTR CALLBACK MemFindCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { +INT_PTR CALLBACK MemFindCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ - switch(uMsg) + switch (uMsg) { - case WM_INITDIALOG: - SetWindowPos(hwndDlg,0,MemFind_wndx,MemFind_wndy,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER); + case WM_INITDIALOG: + SetWindowPos(hwndDlg, 0, MemFind_wndx, MemFind_wndy, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER); - if(FindDirectionUp) CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_DIR_UP, BST_CHECKED); - else CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_DIR_DOWN, BST_CHECKED); + if (FindDirectionUp) + CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_DIR_UP, BST_CHECKED); + else + CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_DIR_DOWN, BST_CHECKED); - if(FindAsText) CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_TYPE_TEXT, BST_CHECKED); - else CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_TYPE_HEX, BST_CHECKED); + if (FindAsText) + CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_TYPE_TEXT, BST_CHECKED); + else + CheckDlgButton(hwndDlg, IDC_MEMVIEWFIND_TYPE_HEX, BST_CHECKED); - if(FindTextBox[0])SetDlgItemText(hwndDlg,IDC_MEMVIEWFIND_WHAT,FindTextBox); + if (FindTextBox[0]) + SetDlgItemText(hwndDlg, IDC_MEMVIEWFIND_WHAT, FindTextBox); - SendDlgItemMessage(hwndDlg,IDC_MEMVIEWFIND_WHAT,EM_SETLIMITTEXT,59,0); - break; - case WM_CREATE: + SendDlgItemMessage(hwndDlg, IDC_MEMVIEWFIND_WHAT, EM_SETLIMITTEXT, 59, 0); + break; + case WM_CREATE: - break; - case WM_PAINT: - break; - case WM_CLOSE: - case WM_QUIT: - GetDlgItemText(hwndDlg,IDC_MEMVIEWFIND_WHAT,FindTextBox,60); - DestroyWindow(hwndDlg); - hMemFind = 0; - hwndDlg = 0; - break; - case WM_MOVING: - break; - case WM_MOVE: { - if (!IsIconic(hwndDlg)) { - RECT wrect; - GetWindowRect(hwndDlg,&wrect); - MemFind_wndx = wrect.left; - MemFind_wndy = wrect.top; - - #ifdef WIN32 - WindowBoundsCheckNoResize(MemFind_wndx,MemFind_wndy,wrect.right); - #endif - } - break; + break; + case WM_PAINT: + break; + case WM_CLOSE: + case WM_QUIT: + GetDlgItemText(hwndDlg, IDC_MEMVIEWFIND_WHAT, FindTextBox, 60); + DestroyWindow(hwndDlg); + hMemFind = 0; + hwndDlg = 0; + break; + case WM_MOVING: + break; + case WM_MOVE: + { + if (!IsIconic(hwndDlg)) + { + RECT wrect; + GetWindowRect(hwndDlg, &wrect); + MemFind_wndx = wrect.left; + MemFind_wndy = wrect.top; + +#ifdef WIN32 + WindowBoundsCheckNoResize(MemFind_wndx, MemFind_wndy, wrect.right); +#endif } - case WM_RBUTTONDBLCLK: - case WM_RBUTTONDOWN: - break; - case WM_MOUSEMOVE: - break; + break; + } + case WM_RBUTTONDBLCLK: + case WM_RBUTTONDOWN: + break; + case WM_MOUSEMOVE: + break; - case WM_COMMAND: - switch(HIWORD(wParam)) { - case BN_CLICKED: - switch(LOWORD(wParam)) - { - case IDC_MEMVIEWFIND_TYPE_HEX : - FindAsText=0; - break; - case IDC_MEMVIEWFIND_TYPE_TEXT : - FindAsText=1; - break; - - case IDC_MEMVIEWFIND_DIR_UP : - FindDirectionUp = 1; - break; - case IDC_MEMVIEWFIND_DIR_DOWN : - FindDirectionUp = 0; - break; - case IDC_MEMVIEWFIND_NEXT : - FindNext(); - break; - } + case WM_COMMAND: + switch (HIWORD(wParam)) + { + case BN_CLICKED: + switch (LOWORD(wParam)) + { + case IDC_MEMVIEWFIND_TYPE_HEX: + FindAsText = 0; + break; + case IDC_MEMVIEWFIND_TYPE_TEXT: + FindAsText = 1; + break; + + case IDC_MEMVIEWFIND_DIR_UP: + FindDirectionUp = 1; break; + case IDC_MEMVIEWFIND_DIR_DOWN: + FindDirectionUp = 0; + break; + case IDC_MEMVIEWFIND_NEXT: + FindNext(); + break; + } + break; } break; - case WM_HSCROLL: - break; + case WM_HSCROLL: + break; } return FALSE; } -void FindNext(){ +void FindNext() +{ char str[60]; unsigned char data[60]; int datasize = 0, i, j, inputc = -1, found; - if(hMemFind) GetDlgItemText(hMemFind,IDC_MEMVIEWFIND_WHAT,str,60); - else strcpy(str,FindTextBox); - - for(i = 0;str[i] != 0;i++){ - if(!FindAsText){ - if(inputc == -1){ - if((str[i] >= 'a') && (str[i] <= 'f')) inputc = str[i]-('a'-0xA); - if((str[i] >= 'A') && (str[i] <= 'F')) inputc = str[i]-('A'-0xA); - if((str[i] >= '0') && (str[i] <= '9')) inputc = str[i]-'0'; - } else { - if((str[i] >= 'a') && (str[i] <= 'f')) inputc = (inputc<<4)|(str[i]-('a'-0xA)); - if((str[i] >= 'A') && (str[i] <= 'F')) inputc = (inputc<<4)|(str[i]-('A'-0xA)); - if((str[i] >= '0') && (str[i] <= '9')) inputc = (inputc<<4)|(str[i]-'0'); - - if(((str[i] >= 'a') && (str[i] <= 'f')) || - ((str[i] >= 'A') && (str[i] <= 'F')) || - ((str[i] >= '0') && (str[i] <= '9'))){ - data[datasize++] = inputc; - inputc = -1; + if (hMemFind) + GetDlgItemText(hMemFind, IDC_MEMVIEWFIND_WHAT, str, 60); + else + strcpy(str, FindTextBox); + + for (i = 0; str[i] != 0; i++) + { + if (!FindAsText) + { + if (inputc == -1) + { + if ((str[i] >= 'a') && (str[i] <= 'f')) + inputc = str[i] - ('a' - 0xA); + if ((str[i] >= 'A') && (str[i] <= 'F')) + inputc = str[i] - ('A' - 0xA); + if ((str[i] >= '0') && (str[i] <= '9')) + inputc = str[i] - '0'; + } + else + { + if ((str[i] >= 'a') && (str[i] <= 'f')) + inputc = (inputc << 4) | (str[i] - ('a' - 0xA)); + if ((str[i] >= 'A') && (str[i] <= 'F')) + inputc = (inputc << 4) | (str[i] - ('A' - 0xA)); + if ((str[i] >= '0') && (str[i] <= '9')) + inputc = (inputc << 4) | (str[i] - '0'); + + if (((str[i] >= 'a') && (str[i] <= 'f')) || + ((str[i] >= 'A') && (str[i] <= 'F')) || + ((str[i] >= '0') && (str[i] <= '9'))) + { + data[datasize++] = inputc; + inputc = -1; } } - } else { - for(j = 0;j < 256;j++)if(chartable[j] == str[i])break; - if(j == 256)continue; + } + else + { + for (j = 0; j < 256; j++) + if (chartable[j] == str[i]) + break; + if (j == 256) + continue; data[datasize++] = j; } } - if(datasize < 1){ - MessageBox(hMemView,"Invalid String","Error", MB_OK); + if (datasize < 1) + { + MessageBox(hMemView, "Invalid String", "Error", MB_OK); return; } - if(!FindDirectionUp){ - for(i = CursorStartAddy+1;i+datasize <= MaxSize;i++){ + if (!FindDirectionUp) + { + for (i = CursorStartAddy + 1; i + datasize <= MaxSize; i++) + { found = 1; - for(j = 0;j < datasize;j++){ - if(GetMemViewData(i+j) != data[j])found = 0; + for (j = 0; j < datasize; j++) + { + if (GetMemViewData(i + j) != data[j]) + found = 0; } - if(found == 1){ - ChangeMemViewFocus(EditingMode,i, i+datasize-1); + if (found == 1) + { + ChangeMemViewFocus(EditingMode, i, i + datasize - 1); return; } } - for(i = 0;i < CursorStartAddy;i++){ + for (i = 0; i < CursorStartAddy; i++) + { found = 1; - for(j = 0;j < datasize;j++){ - if(GetMemViewData(i+j) != data[j])found = 0; + for (j = 0; j < datasize; j++) + { + if (GetMemViewData(i + j) != data[j]) + found = 0; } - if(found == 1){ - ChangeMemViewFocus(EditingMode,i, i+datasize-1); + if (found == 1) + { + ChangeMemViewFocus(EditingMode, i, i + datasize - 1); return; } } - } else { //FindDirection is up - for(i = CursorStartAddy-1;i >= 0;i--){ + } + else + { // FindDirection is up + for (i = CursorStartAddy - 1; i >= 0; i--) + { found = 1; - for(j = 0;j < datasize;j++){ - if(GetMemViewData(i+j) != data[j])found = 0; + for (j = 0; j < datasize; j++) + { + if (GetMemViewData(i + j) != data[j]) + found = 0; } - if(found == 1){ - ChangeMemViewFocus(EditingMode,i, i+datasize-1); + if (found == 1) + { + ChangeMemViewFocus(EditingMode, i, i + datasize - 1); return; } } - for(i = MaxSize-datasize;i > CursorStartAddy;i--){ + for (i = MaxSize - datasize; i > CursorStartAddy; i--) + { found = 1; - for(j = 0;j < datasize;j++){ - if(GetMemViewData(i+j) != data[j])found = 0; + for (j = 0; j < datasize; j++) + { + if (GetMemViewData(i + j) != data[j]) + found = 0; } - if(found == 1){ - ChangeMemViewFocus(EditingMode,i, i+datasize-1); + if (found == 1) + { + ChangeMemViewFocus(EditingMode, i, i + datasize - 1); return; } } } - - MessageBox(hMemView,"String Not Found","Error", MB_OK); + MessageBox(hMemView, "String Not Found", "Error", MB_OK); return; } - void OpenFindDialog() { if (!hMemView) @@ -3030,7 +3231,7 @@ void OpenFindDialog() // set focus to the text field SendMessage(hMemFind, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hMemFind, IDC_MEMVIEWFIND_WHAT), true); else - hMemFind = CreateDialog(fceu_hInstance,"MEMVIEWFIND",hMemView,MemFindCallB); + hMemFind = CreateDialog(fceu_hInstance, "MEMVIEWFIND", hMemView, MemFindCallB); return; } @@ -3047,7 +3248,7 @@ void PalettePoke(uint32 addr, uint8 data) } else { - UPALRAM[addr-1] = data; + UPALRAM[addr - 1] = data; } } else @@ -3058,7 +3259,7 @@ void PalettePoke(uint32 addr, uint8 data) INT_PTR CALLBACK ImportBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - static int* tmpImportBookmarkProps; + static int *tmpImportBookmarkProps; static HWND hTipMerge; static HWND hTipIgnore; @@ -3070,16 +3271,122 @@ INT_PTR CALLBACK ImportBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPA switch (uMsg) { - case WM_INITDIALOG: - CenterWindow(hwndDlg); - tmpImportBookmarkProps = (int*)lParam; - if (!(*tmpImportBookmarkProps & IMPORT_OVERWRITE_NO_PROMPT)) - CheckDlgButton(hwndDlg, IDC_CHECK_BOOKMARKIMPORTOPTION_CONFIRMEVERYTIMEONCONFLICT, BST_CHECKED); + 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); + 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); @@ -3087,11 +3394,8 @@ INT_PTR CALLBACK ImportBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPA 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); - + 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); @@ -3099,146 +3403,45 @@ INT_PTR CALLBACK ImportBookmarkCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPA 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; } - - 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; } -void SwitchEditingText(int editingText) { +void SwitchEditingText(int editingText) +{ if (EditingText != editingText) { - if (editingText) { + if (editingText) + { HexTextColorList = DimTextColorList; HexBGColorList = DimBGColorList; AnsiTextColorList = CurTextColorList; @@ -3255,7 +3458,7 @@ void SwitchEditingText(int editingText) { } } -bool ChangeColor(HWND hwnd, COLORMENU* item) +bool ChangeColor(HWND hwnd, COLORMENU *item) { int backup = RGB(*item->r, *item->g, *item->b); CHOOSECOLOR choose; @@ -3273,11 +3476,9 @@ bool ChangeColor(HWND hwnd, COLORMENU* item) return true; } return false; - } - -BOOL OpColorMenu(HWND hwnd, HMENU menu, COLORMENU* item, int pos, int id, BOOL (WINAPI *opMenu)(HMENU hmenu, UINT item, BOOL byPos, LPCMENUITEMINFO info)) +BOOL OpColorMenu(HWND hwnd, HMENU menu, COLORMENU *item, int pos, int id, BOOL(WINAPI *opMenu)(HMENU hmenu, UINT item, BOOL byPos, LPCMENUITEMINFO info)) { MENUITEMINFO info; @@ -3288,7 +3489,7 @@ BOOL OpColorMenu(HWND hwnd, HMENU menu, COLORMENU* item, int pos, int id, BOOL ( { HDC hdc = GetDC(hwnd); HDC memdc = CreateCompatibleDC(hdc); - + int width = GetSystemMetrics(SM_CXMENUCHECK); int height = GetSystemMetrics(SM_CYMENUCHECK); @@ -3296,7 +3497,7 @@ BOOL OpColorMenu(HWND hwnd, HMENU menu, COLORMENU* item, int pos, int id, BOOL ( item->bitmap = CreateCompatibleBitmap(hdc, width, height); SelectObject(memdc, item->bitmap); HBRUSH brush = CreateSolidBrush(RGB(*item->r, *item->g, *item->b)); - RECT rect = { 1, 1, width - 1, height - 1}; + RECT rect = {1, 1, width - 1, height - 1}; FillRect(memdc, &rect, brush); DeleteObject(brush); DeleteDC(memdc); diff --git a/src/drivers/win/ppuview.cpp b/src/drivers/win/ppuview.cpp index 95dbb55a3..b0adc40b6 100644 --- a/src/drivers/win/ppuview.cpp +++ b/src/drivers/win/ppuview.cpp @@ -27,7 +27,7 @@ HWND hPPUView; -extern uint8 *VPage[8]; +extern uint8 *VPage[16]; extern uint8 PALRAM[0x20]; extern uint8 UPALRAM[3]; @@ -158,16 +158,16 @@ void FCEUD_UpdatePPUView(int scanline, int refreshchr) { for (i = 0, x=0x1000; i < 0x1000; i++, x++) { - chrcache0[i] = VPage[i>>10][i]; - chrcache1[i] = VPage[x>>10][x]; + chrcache0[i] = VPage[i>>9][i]; + chrcache1[i] = VPage[x>>9][x]; if (debug_loggingCD) { if (cdloggerVideoDataSize) { int addr; - addr = &VPage[i >> 10][i] - CHRptr[0]; + addr = &VPage[i >> 9][i] - CHRptr[0]; if ((addr >= 0) && (addr < (int)cdloggerVideoDataSize)) logcache0[i] = cdloggervdata[addr]; - addr = &VPage[x >> 10][x] - CHRptr[0]; + addr = &VPage[x >> 9][x] - CHRptr[0]; if ((addr >= 0) && (addr < (int)cdloggerVideoDataSize)) logcache1[i] = cdloggervdata[addr]; } else { diff --git a/src/drivers/win/texthook.cpp b/src/drivers/win/texthook.cpp index f1879d5de..5d192ec7c 100644 --- a/src/drivers/win/texthook.cpp +++ b/src/drivers/win/texthook.cpp @@ -52,7 +52,7 @@ extern void FCEUD_BlitScreen(uint8 *XBuf); //needed for pause, not sure where th extern uint8 PALRAM[0x20]; extern uint8 PPU[4]; extern uint8 *vnapage[4]; -extern uint8 *VPage[8]; +extern uint8 *VPage[16]; //------------------------------ HWND hTextHooker; @@ -303,14 +303,14 @@ void UpdateTextHooker() { if ( EmulationPaused == 1 ) { //if the selection has changed since we paused if ( tileToggles[x][y] != pausedTileToggles[x][y] ) { - DrawTextHookerChr(pbitmap,&VPage[(ptable+chr)>>10][ptable+chr],tileattr,1); + DrawTextHookerChr(pbitmap,&VPage[(ptable+chr)>>9][ptable+chr],tileattr,1); } else { //nothing has changed since we paused - DrawTextHookerChr(pbitmap,&VPage[(ptable+chr)>>10][ptable+chr],tileattr,0); + DrawTextHookerChr(pbitmap,&VPage[(ptable+chr)>>9][ptable+chr],tileattr,0); } //after updates have been made to tileToggles, reset pausedTileToggles pausedTileToggles[x][y] = tileToggles[x][y]; } else { //we aren't paused, do a normal call - DrawTextHookerChr(pbitmap,&VPage[(ptable+chr)>>10][ptable+chr],tileattr,tileToggles[x][y]); + DrawTextHookerChr(pbitmap,&VPage[(ptable+chr)>>9][ptable+chr],tileattr,tileToggles[x][y]); } pbitmap += (8*3); } diff --git a/src/fceu.cpp b/src/fceu.cpp index 37d61a531..6a74063f1 100644 --- a/src/fceu.cpp +++ b/src/fceu.cpp @@ -407,6 +407,7 @@ void ResetGameLoaded(void) { memset(&GameExpSound, 0, sizeof(GameExpSound)); MapIRQHook = NULL; MMC5Hack = 0; + RNBWHack = 0; PEC586Hack = 0; QTAIHack = 0; PAL &= 1; diff --git a/src/fceu.h b/src/fceu.h index b35bf4abc..5ce025ddf 100644 --- a/src/fceu.h +++ b/src/fceu.h @@ -7,7 +7,7 @@ extern int fceuindbg; extern int newppu; void ResetGameLoaded(void); -//overclocking-related +// overclocking-related extern bool overclock_enabled; extern bool overclocking; extern bool skip_7bit_overclocking; @@ -20,10 +20,10 @@ extern bool AutoResumePlay; extern bool frameAdvanceLagSkip; extern char romNameWhenClosingEmulator[]; -#define DECLFR(x) uint8 x (uint32 A) -#define DECLFW(x) void x (uint32 A, uint8 V) +#define DECLFR(x) uint8 x(uint32 A) +#define DECLFW(x) void x(uint32 A, uint8 V) -void FCEU_MemoryRand(uint8 *ptr, uint32 size, bool default_zero=false); +void FCEU_MemoryRand(uint8 *ptr, uint32 size, bool default_zero = false); void SetReadHandler(int32 start, int32 end, readfunc func); void SetWriteHandler(int32 start, int32 end, writefunc func); writefunc GetWriteHandler(int32 a); @@ -40,12 +40,12 @@ void PowerNES(void); void SetAutoFireOffset(int offset); void SetAutoFirePattern(int onframes, int offframes); -void GetAutoFirePattern( int *onframes, int *offframes); +void GetAutoFirePattern(int *onframes, int *offframes); bool GetAutoFireState(int btnIdx); void AutoFire(void); void FCEUI_RewindToLastAutosave(void); -//mbg 7/23/06 +// mbg 7/23/06 const char *FCEUI_GetAboutString(void); extern uint64 timestampbase; @@ -61,16 +61,32 @@ extern uint8 MMC50x5130; extern uint8 MMC5HackSPScroll; extern uint8 MMC5HackSPPage; +// Rainbow external shared buffers/vars +extern int RNBWHack; +extern uint8 *RNBWHackExNTARAMPtr; +extern uint8 *RNBWHackVROMPtr; +extern uint32 RNBWHackVROMMask; +extern uint8 RNBWHackNTbank[5]; +extern uint8 RNBWHackNTcontrol[5]; +extern uint8 RNBWHackBGBankOffset; +extern uint8 RNBWHackCurSprite; +extern uint8 RNBWHackSplitEnable; +extern uint8 RNBWHackWindowXStartTile; +extern uint8 RNBWHackWindowXEndTile; +extern uint8 RNBWHackSplitXScroll; +extern uint8 RNBWHackSplitYScroll; +extern uint8 *RNBWHackSplitNTARAMPtr; + extern int PEC586Hack; -// VRCV extarnal shared buffers/vars +// VRCV external shared buffers/vars extern int QTAIHack; extern uint8 QTAINTRAM[2048]; extern uint8 qtaintramreg; #define GAME_MEM_BLOCK_SIZE 131072 -extern uint8 *RAM; //shared memory modifications +extern uint8 *RAM; // shared memory modifications extern int EmulationPaused; extern int frameAdvance_Delay; extern int RAMInitOption; @@ -81,17 +97,17 @@ void FCEU_WriteRomByte(uint32 i, uint8 value); extern readfunc ARead[0x10000]; extern writefunc BWrite[0x10000]; -enum GI { - GI_RESETM2 =1, - GI_POWER =2, - GI_CLOSE =3, +enum GI +{ + GI_RESETM2 = 1, + GI_POWER = 2, + GI_CLOSE = 3, GI_RESETSAVE = 4 }; extern void (*GameInterface)(GI h); extern void (*GameStateRestore)(int version); - #include "git.h" extern FCEUGI *GameInfo; extern int GameAttributes; @@ -100,12 +116,13 @@ extern uint8 PAL; extern int dendy; extern bool movieSubtitles; -//#include "driver.h" +// #include "driver.h" -typedef struct fceu_settings_struct { +typedef struct fceu_settings_struct +{ int PAL; int NetworkPlay; - int SoundVolume; //Master volume + int SoundVolume; // Master volume int TriangleVolume; int Square1Volume; int Square2Volume; @@ -113,20 +130,20 @@ typedef struct fceu_settings_struct { int PCMVolume; bool GameGenie; - //the currently selected first and last rendered scanlines. + // the currently selected first and last rendered scanlines. int FirstSLine; int LastSLine; - //the number of scanlines in the currently selected configuration + // the number of scanlines in the currently selected configuration int TotalScanlines() { return LastSLine - FirstSLine + 1; } - //Driver-supplied user-selected first and last rendered scanlines. - //Usr*SLine[0] is for NTSC, Usr*SLine[1] is for PAL. + // Driver-supplied user-selected first and last rendered scanlines. + // Usr*SLine[0] is for NTSC, Usr*SLine[1] is for PAL. int UsrFirstSLine[2]; int UsrLastSLine[2]; - //this variable isn't used at all, snap is always name-based - //bool SnapName; + // this variable isn't used at all, snap is always name-based + // bool SnapName; uint32 SndRate; int soundq; int lowpass; @@ -137,12 +154,12 @@ int FCEU_TextScanlineOffsetFromBottom(int y); extern FCEUS FSettings; -bool CheckFileExists(const char* filename); //Receives a filename (fullpath) and checks to see if that file exists +bool CheckFileExists(const char *filename); // Receives a filename (fullpath) and checks to see if that file exists -void FCEU_PrintError( __FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 2 ); -void FCEU_printf( __FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 2 ); -void FCEU_DispMessage( __FCEU_PRINTF_FORMAT const char *format, int disppos, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 3 ); -void FCEU_DispMessageOnMovie( __FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 2 ); +void FCEU_PrintError(__FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE(1, 2); +void FCEU_printf(__FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE(1, 2); +void FCEU_DispMessage(__FCEU_PRINTF_FORMAT const char *format, int disppos, ...) __FCEU_PRINTF_ATTRIBUTE(1, 3); +void FCEU_DispMessageOnMovie(__FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE(1, 2); void FCEU_TogglePPU(); void SetNESDeemph_OldHacky(uint8 d, int force); @@ -161,30 +178,29 @@ extern uint8 Exit; extern int default_palette_selection; extern uint8 vsdip; -//#define FCEUDEF_DEBUGGER //mbg merge 7/17/06 - cleaning out conditional compiles +// #define FCEUDEF_DEBUGGER //mbg merge 7/17/06 - cleaning out conditional compiles -#define JOY_A 0x01 -#define JOY_B 0x02 -#define JOY_SELECT 0x04 -#define JOY_START 0x08 -#define JOY_UP 0x10 -#define JOY_DOWN 0x20 -#define JOY_LEFT 0x40 -#define JOY_RIGHT 0x80 +#define JOY_A 0x01 +#define JOY_B 0x02 +#define JOY_SELECT 0x04 +#define JOY_START 0x08 +#define JOY_UP 0x10 +#define JOY_DOWN 0x20 +#define JOY_LEFT 0x40 +#define JOY_RIGHT 0x80 -#define LOADER_INVALID_FORMAT 0 -#define LOADER_OK 1 -#define LOADER_HANDLED_ERROR 2 -#define LOADER_UNHANDLED_ERROR 3 +#define LOADER_INVALID_FORMAT 0 +#define LOADER_OK 1 +#define LOADER_HANDLED_ERROR 2 +#define LOADER_UNHANDLED_ERROR 3 #endif -#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #define EMULATIONPAUSED_PAUSED 0x01 #define EMULATIONPAUSED_TIMER 0x02 #define EMULATIONPAUSED_FA 0x04 #define FRAMEADVANCE_DELAY_DEFAULT 10 -#define NES_HEADER_SIZE 16 - +#define NES_HEADER_SIZE 16 diff --git a/src/ines.cpp b/src/ines.cpp index 9bf183f50..b41093398 100644 --- a/src/ines.cpp +++ b/src/ines.cpp @@ -50,6 +50,7 @@ uint8 *trainerpoo = NULL; uint8 *ROM = NULL; uint8 *VROM = NULL; uint8 *ExtraNTARAM = NULL; +uint8 *MiscROMS = NULL; iNES_HEADER head; static CartInfo iNESCart; @@ -58,6 +59,7 @@ uint8 Mirroring = 0; uint8 MirroringAs2bits = 0; uint32 ROM_size = 0; uint32 VROM_size = 0; +uint32 MiscROMS_size = 0; char LoadedRomFName[4096]; //mbg merge 7/17/06 added char LoadedRomFNamePatchToUse[4096]; @@ -117,6 +119,10 @@ void iNESGI(GI h) { //bbit edited: removed static keyword FCEU_free(VROM); VROM = NULL; } + if (MiscROMS) { + FCEU_free(MiscROMS); + MiscROMS = NULL; + } if (trainerpoo) { free(trainerpoo); trainerpoo = NULL; @@ -798,6 +804,8 @@ BMAPPINGLocal bmap[] = { {"KONAMI QTAi Board", 547, QTAi_Init }, + {"RAINBOW", 682, RAINBOW_Init }, + {"", 0, NULL} }; @@ -823,6 +831,7 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) { iNESCart.vram_size = (head.VRAM_size & 0x0F)?(64 << (head.VRAM_size & 0x0F)):0; iNESCart.battery_vram_size = (head.VRAM_size & 0xF0)?(64 << ((head.VRAM_size & 0xF0)>>4)):0; iNESCart.submapper = head.ROM_type3 >> 4; + iNESCart.misc_roms = head.misc_roms & 0x03; } MapperNo = (head.ROM_type >> 4); @@ -867,6 +876,10 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) { VROM_size = ((1 << (head.VROM_size >> 2)) * ((head.VROM_size & 0b11) * 2 + 1)) >> 13; } + if (iNES2 && iNESCart.misc_roms != 0) { + MiscROMS_size = fp->size - (ROM_size * 0x4000 + VROM_size * 0x2000 + 0x10); + } + int round = true; for (int i = 0; i != sizeof(not_power2) / sizeof(not_power2[0]); ++i) { //for games not to the power of 2, so we just read enough @@ -953,6 +966,13 @@ int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode) { if (VROM_size) FCEU_fread(VROM, 0x2000, VROM_size, fp); + if (iNES2 && iNESCart.misc_roms != 0 && MiscROMS_size) + { + MiscROMS = (uint8*)FCEU_malloc(MiscROMS_size); + memset(MiscROMS, 0xFF, MiscROMS_size); + FCEU_fread(MiscROMS, MiscROMS_size, 1, fp); + } + md5_starts(&md5); md5_update(&md5, ROM, ROM_size << 14); @@ -1180,7 +1200,7 @@ static int iNES_Init(int num) { } if (CHRRAMSize > 0) { - int mCHRRAMSize = (CHRRAMSize < 1024) ? 1024 : CHRRAMSize; // VPage has a resolution of 1k banks, ensure minimum allocation to prevent malicious access from NES software + int mCHRRAMSize = (CHRRAMSize < 512) ? 512 : CHRRAMSize; // VPage has a resolution of 512B banks, ensure minimum allocation to prevent malicious access from NES software if ((UNIFchrrama = VROM = (uint8*)FCEU_dmalloc(mCHRRAMSize)) == NULL) return 2; FCEU_MemoryRand(VROM, CHRRAMSize); SetupCartCHRMapping(0, VROM, CHRRAMSize, 1); diff --git a/src/ines.h b/src/ines.h index 6c95863a4..a521b23b5 100644 --- a/src/ines.h +++ b/src/ines.h @@ -42,8 +42,10 @@ class TMasterRomInfoParams : public std::map //mbg merge 6/29/06 extern uint8 *ROM; extern uint8 *VROM; +extern uint8 *MiscROMS; extern uint32 VROM_size; extern uint32 ROM_size; +extern uint32 MiscROMS_size; extern uint8 *ExtraNTARAM; extern uint8 **VPageR; extern int iNesSave(void); //bbit Edited: line added diff --git a/src/ppu.cpp b/src/ppu.cpp index ce84a9df2..13f9f238c 100644 --- a/src/ppu.cpp +++ b/src/ppu.cpp @@ -28,7 +28,7 @@ #include "file.h" #include "utils/endian.h" #include "utils/memory.h" - + #include "cart.h" #include "palette.h" #include "state.h" @@ -36,30 +36,30 @@ #include "input.h" #include "driver.h" #include "debug.h" - + #include #include #include -#define VBlankON (PPU[0] & 0x80) //Generate VBlank NMI -#define Sprite16 (PPU[0] & 0x20) //Sprites 8x16/8x8 -#define BGAdrHI (PPU[0] & 0x10) //BG pattern adr $0000/$1000 -#define SpAdrHI (PPU[0] & 0x08) //Sprite pattern adr $0000/$1000 -#define INC32 (PPU[0] & 0x04) //auto increment 1/32 +#define VBlankON (PPU[0] & 0x80) // Generate VBlank NMI +#define Sprite16 (PPU[0] & 0x20) // Sprites 8x16/8x8 +#define BGAdrHI (PPU[0] & 0x10) // BG pattern adr $0000/$1000 +#define SpAdrHI (PPU[0] & 0x08) // Sprite pattern adr $0000/$1000 +#define INC32 (PPU[0] & 0x04) // auto increment 1/32 -#define SpriteON (PPU[1] & 0x10) //Show Sprite -#define ScreenON (PPU[1] & 0x08) //Show screen -#define PPUON (PPU[1] & 0x18) //PPU should operate -#define GRAYSCALE (PPU[1] & 0x01) //Grayscale (AND palette entries with 0x30) +#define SpriteON (PPU[1] & 0x10) // Show Sprite +#define ScreenON (PPU[1] & 0x08) // Show screen +#define PPUON (PPU[1] & 0x18) // PPU should operate +#define GRAYSCALE (PPU[1] & 0x01) // Grayscale (AND palette entries with 0x30) #define SpriteLeft8 (PPU[1] & 0x04) -#define BGLeft8 (PPU[1] & 0x02) +#define BGLeft8 (PPU[1] & 0x02) -#define PPU_status (PPU[2]) +#define PPU_status (PPU[2]) -#define READPALNOGS(ofs) (PALRAM[(ofs)]) -#define READPAL(ofs) (PALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF)) -#define READUPAL(ofs) (UPALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF)) +#define READPALNOGS(ofs) (PALRAM[(ofs)]) +#define READPAL(ofs) (PALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF)) +#define READUPAL(ofs) (UPALRAM[(ofs)] & (GRAYSCALE ? 0x30 : 0xFF)) static void FetchSpriteData(void); static void RefreshLine(int lastpixel); @@ -75,10 +75,12 @@ static bool new_ppu_reset = false; int test = 0; -template -struct BITREVLUT { - T* lut; - BITREVLUT() { +template +struct BITREVLUT +{ + T *lut; + BITREVLUT() + { int bits = BITS; int n = 1 << BITS; lut = new T[n]; @@ -90,7 +92,8 @@ struct BITREVLUT { lut[0] = 0; lut[1] = a; - while (--bits) { + while (--bits) + { m <<= 1; a >>= 1; for (int i = 0; i < m; i++) @@ -98,18 +101,21 @@ struct BITREVLUT { } } - T operator[](int index) { + T operator[](int index) + { return lut[index]; } }; BITREVLUT bitrevlut; -struct PPUSTATUS { +struct PPUSTATUS +{ int32 sl; int32 cycle, end_cycle; }; -struct SPRITE_READ { +struct SPRITE_READ +{ int32 num; int32 count; int32 fetch; @@ -119,13 +125,15 @@ struct SPRITE_READ { int32 last; int32 mode; - void reset() { + void reset() + { num = count = fetch = found = ret = last = mode = 0; found_pos[0] = found_pos[1] = found_pos[2] = found_pos[3] = 0; found_pos[4] = found_pos[5] = found_pos[6] = found_pos[7] = 0; } - void start_scanline() { + void start_scanline() + { num = 1; found = 0; fetch = 1; @@ -137,39 +145,41 @@ struct SPRITE_READ { } }; -//doesn't need to be savestated as it is just a reflection of the current position in the ppu loop +// doesn't need to be savestated as it is just a reflection of the current position in the ppu loop PPUPHASE ppuphase; -//this needs to be savestated since a game may be trying to read from this across vblanks +// this needs to be savestated since a game may be trying to read from this across vblanks SPRITE_READ spr_read; -//definitely needs to be savestated +// definitely needs to be savestated uint8 idleSynch = 1; -//uses the internal counters concept at http://nesdev.icequake.net/PPU%20addressing.txt -struct PPUREGS { - //normal clocked regs. as the game can interfere with these at any time, they need to be savestated - uint32 fv; //3 - uint32 v; //1 - uint32 h; //1 - uint32 vt; //5 - uint32 ht; //5 - - //temp unlatched regs (need savestating, can be written to at any time) +// uses the internal counters concept at http://nesdev.icequake.net/PPU%20addressing.txt +struct PPUREGS +{ + // normal clocked regs. as the game can interfere with these at any time, they need to be savestated + uint32 fv; // 3 + uint32 v; // 1 + uint32 h; // 1 + uint32 vt; // 5 + uint32 ht; // 5 + + // temp unlatched regs (need savestating, can be written to at any time) uint32 _fv, _v, _h, _vt, _ht; - //other regs that need savestating - uint32 fh; //3 (horz scroll) - uint32 s; //1 ($2000 bit 4: "Background pattern table address (0: $0000; 1: $1000)") + // other regs that need savestating + uint32 fh; // 3 (horz scroll) + uint32 s; // 1 ($2000 bit 4: "Background pattern table address (0: $0000; 1: $1000)") - //other regs that don't need saving - uint32 par; //8 (sort of a hack, just stored in here, but not managed by this system) + // other regs that don't need saving + uint32 par; // 8 (sort of a hack, just stored in here, but not managed by this system) - //cached state data. these are always reset at the beginning of a frame and don't need saving - //but just to be safe, we're gonna save it + // cached state data. these are always reset at the beginning of a frame and don't need saving + // but just to be safe, we're gonna save it PPUSTATUS status; - void reset() { + void reset() + { fv = v = h = vt = ht = 0; fh = par = s = 0; _fv = _v = _h = _vt = _ht = 0; @@ -178,7 +188,8 @@ struct PPUREGS { status.sl = 241; } - void install_latches() { + void install_latches() + { fv = _fv; v = _v; h = _h; @@ -186,32 +197,37 @@ struct PPUREGS { ht = _ht; } - void install_h_latches() { + void install_h_latches() + { ht = _ht; h = _h; } - void clear_latches() { + void clear_latches() + { _fv = _v = _h = _vt = _ht = 0; fh = 0; } - void increment_hsc() { - //The first one, the horizontal scroll counter, consists of 6 bits, and is - //made up by daisy-chaining the HT counter to the H counter. The HT counter is - //then clocked every 8 pixel dot clocks (or every 8/3 CPU clock cycles). + void increment_hsc() + { + // The first one, the horizontal scroll counter, consists of 6 bits, and is + // made up by daisy-chaining the HT counter to the H counter. The HT counter is + // then clocked every 8 pixel dot clocks (or every 8/3 CPU clock cycles). ht++; h += (ht >> 5); ht &= 31; h &= 1; } - void increment_vs() { + void increment_vs() + { fv++; int fv_overflow = (fv >> 3); vt += fv_overflow; - vt &= 31; //fixed tecmo super bowl - if (vt == 30 && fv_overflow == 1) { //caution here (only do it at the exact instant of overflow) fixes p'radikus conflict + vt &= 31; // fixed tecmo super bowl + if (vt == 30 && fv_overflow == 1) + { // caution here (only do it at the exact instant of overflow) fixes p'radikus conflict v++; vt = 0; } @@ -219,53 +235,61 @@ struct PPUREGS { v &= 1; } - uint32 get_ntread() { + uint32 get_ntread() + { return 0x2000 | (v << 0xB) | (h << 0xA) | (vt << 5) | ht; } - uint32 get_2007access() { + uint32 get_2007access() + { return ((fv & 3) << 0xC) | (v << 0xB) | (h << 0xA) | (vt << 5) | ht; } - //The PPU has an internal 4-position, 2-bit shifter, which it uses for - //obtaining the 2-bit palette select data during an attribute table byte - //fetch. To represent how this data is shifted in the diagram, letters a..c - //are used in the diagram to represent the right-shift position amount to - //apply to the data read from the attribute data (a is always 0). This is why - //you only see bits 0 and 1 used off the read attribute data in the diagram. - uint32 get_atread() { + // The PPU has an internal 4-position, 2-bit shifter, which it uses for + // obtaining the 2-bit palette select data during an attribute table byte + // fetch. To represent how this data is shifted in the diagram, letters a..c + // are used in the diagram to represent the right-shift position amount to + // apply to the data read from the attribute data (a is always 0). This is why + // you only see bits 0 and 1 used off the read attribute data in the diagram. + uint32 get_atread() + { return 0x2000 | (v << 0xB) | (h << 0xA) | 0x3C0 | ((vt & 0x1C) << 1) | ((ht & 0x1C) >> 2); } - //address line 3 relates to the pattern table fetch occuring (the PPU always makes them in pairs). - uint32 get_ptread() { + // address line 3 relates to the pattern table fetch occuring (the PPU always makes them in pairs). + uint32 get_ptread() + { return (s << 0xC) | (par << 0x4) | fv; } - void increment2007(bool rendering, bool by32) { + void increment2007(bool rendering, bool by32) + { if (rendering) { - //don't do this: - //if (by32) increment_vs(); - //else increment_hsc(); - //do this instead: - increment_vs(); //yes, even if we're moving by 32 + // don't do this: + // if (by32) increment_vs(); + // else increment_hsc(); + // do this instead: + increment_vs(); // yes, even if we're moving by 32 return; } - //If the VRAM address increment bit (2000.2) is clear (inc. amt. = 1), all the - //scroll counters are daisy-chained (in the order of HT, VT, H, V, FV) so that - //the carry out of each counter controls the next counter's clock rate. The - //result is that all 5 counters function as a single 15-bit one. Any access to - //2007 clocks the HT counter here. + // If the VRAM address increment bit (2000.2) is clear (inc. amt. = 1), all the + // scroll counters are daisy-chained (in the order of HT, VT, H, V, FV) so that + // the carry out of each counter controls the next counter's clock rate. The + // result is that all 5 counters function as a single 15-bit one. Any access to + // 2007 clocks the HT counter here. // - //If the VRAM address increment bit is set (inc. amt. = 32), the only - //difference is that the HT counter is no longer being clocked, and the VT - //counter is now being clocked by access to 2007. - if (by32) { + // If the VRAM address increment bit is set (inc. amt. = 32), the only + // difference is that the HT counter is no longer being clocked, and the VT + // counter is now being clocked by access to 2007. + if (by32) + { vt++; - } else { + } + else + { ht++; vt += (ht >> 5) & 1; } @@ -281,10 +305,10 @@ struct PPUREGS { void debug_log() { - FCEU_printf("ppur: fv(%d), v(%d), h(%d), vt(%d), ht(%d)\n",fv,v,h,vt,ht); - FCEU_printf(" _fv(%d), _v(%d), _h(%d), _vt(%d), _ht(%d)\n",_fv,_v,_h,_vt,_ht); - FCEU_printf(" fh(%d), s(%d), par(%d)\n",fh,s,par); - FCEU_printf(" .status cycle(%d), end_cycle(%d), sl(%d)\n",status.cycle,status.end_cycle,status.sl); + FCEU_printf("ppur: fv(%d), v(%d), h(%d), vt(%d), ht(%d)\n", fv, v, h, vt, ht); + FCEU_printf(" _fv(%d), _v(%d), _h(%d), _vt(%d), _ht(%d)\n", _fv, _v, _h, _vt, _ht); + FCEU_printf(" fh(%d), s(%d), par(%d)\n", fh, s, par); + FCEU_printf(" .status cycle(%d), end_cycle(%d), sl(%d)\n", status.cycle, status.end_cycle, status.sl); } } ppur; @@ -292,27 +316,31 @@ int newppu_get_scanline() { return ppur.status.sl; } int newppu_get_dot() { return ppur.status.cycle; } void newppu_hacky_emergency_reset() { - if(ppur.status.end_cycle == 0) + if (ppur.status.end_cycle == 0) ppur.reset(); } -static void makeppulut(void) { +static void makeppulut(void) +{ int x; int y; int cc, xo, pixel; - - for (x = 0; x < 256; x++) { + for (x = 0; x < 256; x++) + { ppulut1[x] = 0; for (y = 0; y < 8; y++) ppulut1[x] |= ((x >> (7 - y)) & 1) << (y * 4); ppulut2[x] = ppulut1[x] << 1; } - for (cc = 0; cc < 16; cc++) { - for (xo = 0; xo < 8; xo++) { + for (cc = 0; cc < 16; cc++) + { + for (xo = 0; xo < 8; xo++) + { ppulut3[xo | (cc << 3)] = 0; - for (pixel = 0; pixel < 8; pixel++) { + for (pixel = 0; pixel < 8; pixel++) + { int shiftr; shiftr = (pixel + xo) / 8; shiftr *= 2; @@ -326,9 +354,9 @@ static int ppudead = 1; static int kook = 0; int fceuindbg = 0; -//mbg 6/23/08 -//make the no-bg fill color configurable -//0xFF shall indicate to use palette[0] +// mbg 6/23/08 +// make the no-bg fill color configurable +// 0xFF shall indicate to use palette[0] uint8 gNoBGFillColor = 0xFF; int MMC5Hack = 0; @@ -341,6 +369,21 @@ uint8 MMC50x5130 = 0; uint8 MMC5HackSPScroll = 0; uint8 MMC5HackSPPage = 0; +int RNBWHack = 0; +uint8 *RNBWHackExNTARAMPtr = 0; +uint8 *RNBWHackVROMPtr = 0; +uint32 RNBWHackVROMMask = 0xff; +uint8 RNBWHackNTbank[5]; +uint8 RNBWHackNTcontrol[5]; +uint8 RNBWHackBGBankOffset; +uint8 RNBWHackCurSprite; +uint8 RNBWHackSplitEnable; +uint8 RNBWHackWindowXStartTile; +uint8 RNBWHackWindowXEndTile; +uint8 RNBWHackSplitXScroll; +uint8 RNBWHackSplitYScroll; +uint8 *RNBWHackSplitNTARAMPtr; + int PEC586Hack = 0; int QTAIHack = 0; @@ -350,9 +393,9 @@ uint8 qtaintramreg; uint8 VRAMBuffer = 0, PPUGenLatch = 0; uint8 *vnapage[4]; uint8 PPUNTARAM = 0; -uint8 PPUCHRRAM = 0; +uint16 PPUCHRRAM = 0; -//Color deemphasis emulation. Joy... +// Color deemphasis emulation. Joy... static uint8 deemp = 0; static int deempcnt[8]; @@ -367,7 +410,7 @@ uint32 TempAddr = 0, RefreshAddr = 0, DummyRead = 0, NTRefreshAddr = 0; static int maxsprites = 8; -//scanline is equal to the current visible scanline we're on. +// scanline is equal to the current visible scanline we're on. int scanline; int g_rasterpos; static uint32 scanlines_per_frame; @@ -375,18 +418,19 @@ static uint32 scanlines_per_frame; uint8 PPU[4]; uint8 PPUSPL; uint8 NTARAM[0x800], PALRAM[0x20], SPRAM[0x100], SPRBUF[0x100]; -uint8 UPALRAM[0x03];//for 0x4/0x8/0xC addresses in palette, the ones in - //0x20 are 0 to not break fceu rendering. +uint8 UPALRAM[0x03]; // for 0x4/0x8/0xC addresses in palette, the ones in + // 0x20 are 0 to not break fceu rendering. -#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)] -#define VRAMADR(V) &VPage[(V) >> 10][(V)] +#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 9][(V)] +#define VRAMADR(V) &VPage[(V) >> 9][(V)] -uint8* MMC5BGVRAMADR(uint32 A); +uint8 *MMC5BGVRAMADR(uint32 A); uint8 READPAL_MOTHEROFALL(uint32 A) { - if(!(A & 3)) { - if(!(A & 0xC)) + if (!(A & 3)) + { + if (!(A & 0xC)) return READPAL(0x00); else return READUPAL(((A & 0xC) >> 2) - 1); @@ -395,59 +439,218 @@ uint8 READPAL_MOTHEROFALL(uint32 A) return READPAL(A & 0x1F); } -//this duplicates logic which is embedded in the ppu rendering code -//which figures out where to get CHR data from depending on various hack modes -//mostly involving mmc5. -//this might be incomplete. -uint8* FCEUPPU_GetCHR(uint32 vadr, uint32 refreshaddr) { - if (MMC5Hack) { - if (MMC5HackCHRMode == 1) { +// this duplicates logic which is embedded in the ppu rendering code +// which figures out where to get CHR data from depending on various hack modes +// mostly involving mmc5 and rainbow. +// this might be incomplete. +uint8 *FCEUPPU_GetCHR(uint32 vadr, uint32 refreshaddr) +{ + if (MMC5Hack) + { + if (MMC5HackCHRMode == 1) + { uint8 *C = MMC5HackVROMPTR; C += (((MMC5HackExNTARAMPtr[refreshaddr & 0x3ff]) & 0x3f & MMC5HackVROMMask) << 12) + (vadr & 0xfff); - C += (MMC50x5130 & 0x3) << 18; //11-jun-2009 for kuja_killer + C += (MMC50x5130 & 0x3) << 18; // 11-jun-2009 for kuja_killer return C; - } else { + } + else + { return MMC5BGVRAMADR(vadr); } - } else return VRAMADR(vadr); + } + else if (RNBWHack) + { + // uint8 xt = refreshaddr & 31; + uint8 NT; + /* + static const int kHack = -1; //dunno if theres science to this or if it just fixes SDF (cant be bothered to think about it) + int linetile = (newppu_get_scanline() + kHack + RNBWHackSplitYScroll) / 8; + int coltile = newppu_get_dot(); + coltile = coltile / 8; // +RNBWHackSplitXScroll; + bool split = false; + if (RNBWHackSplitEnable & ( + ( (RNBWHackWindowXStartTile <= RNBWHackWindowXEndTile) & ( (coltile >= RNBWHackWindowXStartTile) & (coltile <= RNBWHackWindowXEndTile) ) ) | + ( (RNBWHackWindowXStartTile > RNBWHackWindowXEndTile) & ( (coltile >= RNBWHackWindowXStartTile) | (coltile <= RNBWHackWindowXEndTile) ) ) + ) ) { + split = true; + NT = 4; + } else { + NT = (NTRefreshAddr >> 10) & 0x03; + } + */ + NT = (NTRefreshAddr >> 10) & 0x03; + uint8 NT_1K_dest = (RNBWHackNTcontrol[NT] & 0x0C) >> 2; + uint8 NT_ext_mode = RNBWHackNTcontrol[NT] & 0x03; + switch (NT_ext_mode) + { + case 0: // extended mode disabled + case 1: // extended attributes + { + /*if (split) { + int tmpA = vadr & 0x3ff; + tmpA &= ~(0x1F << 5); // | (1 << 0xB)); //mask off VT and V + tmpA |= (linetile & 31) << 5; //mask on adjusted VT (V doesnt make any sense, I think) + return RNBWHackSplitNTARAMPtr + tmpA; + + //vadr = (RNBWHackExNTARAMPtr[xs | (ys << 5)] << 4) + ((scanline + RNBWHackSplitYScroll) & 7); + + } + else*/ + return VRAMADR(vadr); + // return vnapage[(A >> 10) & 0x3][A & 0x3FF]; + //&VPage[(vadr) >> 9][(vadr)] + } + case 2: // extended tiles + case 3: // extended attributes + tiles + { + if (RNBWHackVROMPtr == NULL) + return NULL; + uint8 *C = RNBWHackVROMPtr; + C += ((RNBWHackBGBankOffset * 0x40000) + ((RNBWHackExNTARAMPtr[NT_1K_dest * 0x400 + (NTRefreshAddr & 0x3ff)] & 0x3f) << 12) + (vadr & 0xfff)) & RNBWHackVROMMask; + return C; + } + } + } + return VRAMADR(vadr); } -//likewise for ATTR -int FCEUPPU_GetAttr(int ntnum, int xt, int yt) { +// likewise for ATTR +int FCEUPPU_GetAttr(int ntnum, int xt, int yt) +{ int attraddr = 0x3C0 + ((yt >> 2) << 3) + (xt >> 2); int temp = (((yt & 2) << 1) + (xt & 2)); int refreshaddr = xt + yt * 32; if (MMC5Hack && MMC5HackCHRMode == 1) return (MMC5HackExNTARAMPtr[refreshaddr & 0x3ff] & 0xC0) >> 6; - else - return (vnapage[ntnum][attraddr] & (3 << temp)) >> temp; + else if (RNBWHack) + { + uint8 NT; + /* + int linetile; + bool split = false; + if (RNBWHackSplitEnable & ( + ((RNBWHackWindowXStartTile <= RNBWHackWindowXEndTile) & ((xt >= RNBWHackWindowXStartTile) & (xt <= RNBWHackWindowXEndTile))) | + ((RNBWHackWindowXStartTile > RNBWHackWindowXEndTile) & ((xt >= RNBWHackWindowXStartTile) | (xt <= RNBWHackWindowXEndTile))) + )) { + static const int kHack = -1; //dunno if theres science to this or if it just fixes SDF (cant be bothered to think about it) + linetile = (newppu_get_scanline() + kHack + RNBWHackSplitYScroll) / 8; + split = true; + NT = 4; + xt = NTRefreshAddr & 31; + yt = (NTRefreshAddr >> 5) & 31; + } + else { + NT = (NTRefreshAddr >> 10) & 0x03; + } + */ + NT = (NTRefreshAddr >> 10) & 0x03; + uint8 NT_1K_dest = (RNBWHackNTcontrol[NT] & 0x0C) >> 2; + uint8 NT_ext_mode = RNBWHackNTcontrol[NT] & 0x03; + switch (NT_ext_mode) + { + case 0: // extended mode disabled + case 2: // extended tiles + { + return (vnapage[ntnum][attraddr] & (3 << temp)) >> temp; + } + case 1: // extended attributes + { + /*if (split) { + int tmpA = refreshaddr & 0x3ff; + tmpA &= ~(0x1F << 5); // | (1 << 0xB)); //mask off VT and V + tmpA |= (linetile & 31) << 5; //mask on adjusted VT (V doesnt make any sense, I think) + //return RNBWHackSplitNTARAMPtr + (vadr & 0x3ff); + uint8 byte = (RNBWHackExNTARAMPtr[NT_1K_dest * 0x400 + tmpA] & 0xC0); + byte *= 0x55; + return byte; + } + else + {*/ + uint8 byte = (RNBWHackExNTARAMPtr[NT_1K_dest * 0x400 + (NTRefreshAddr & 0x3ff)] & 0xC0); + byte >>= 6; + byte *= 0x55; + return byte; + //} + } + case 3: // extended attributes + tiles + { + uint8 byte = (RNBWHackExNTARAMPtr[NT_1K_dest * 0x400 + (NTRefreshAddr & 0x3ff)] & 0xC0); + byte >>= 6; + byte *= 0x55; + return byte; + } + } + + ////////////////////////////////////////////////////////////////////// + /* + uint8 NT; + bool split = false; + if(RNBWHackSplitEnable) { + if(RNBWHackWindowXStartTile < RNBWHackWindowXEndTile) + { + if((xt >= RNBWHackWindowXStartTile) & (xt <= RNBWHackWindowXEndTile)) + split = true; + } + else + { + if((xt <= RNBWHackWindowXEndTile) | (xt >= RNBWHackWindowXStartTile)) + split = true; + } + } + if(split) { + NT = 4; + } else { + NT = (NTRefreshAddr >> 10) & 0x03; + } + uint8 NT_1K_dest = (RNBWHackNTcontrol[NT] & 0x0C) >> 2; + uint8 NT_ext_mode = RNBWHackNTcontrol[NT] & 0x03; + if (NT_ext_mode & 0x01) + return (RNBWHackExNTARAMPtr[NT_1K_dest * 0x400 + (NTRefreshAddr & 0x3ff)] & 0xC0) >> 6; + */ + ////////////////////////////////////////////////////////////////////// + } + return (vnapage[ntnum][attraddr] & (3 << temp)) >> temp; } -//new ppu----- -inline void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) { +// new ppu----- +void FFCEUX_PPUWrite_Default(uint32 A, uint8 V) +{ uint32 tmp = A; - if (PPU_hook) PPU_hook(A); + if (PPU_hook) + PPU_hook(A); - if (tmp < 0x2000) { - if (PPUCHRRAM & (1 << (tmp >> 10))) - VPage[tmp >> 10][tmp] = V; - } else if (tmp < 0x3F00) { - if (QTAIHack && (qtaintramreg & 1)) { + if (tmp < 0x2000) + { + if (PPUCHRRAM & (1 << (tmp >> 9))) + VPage[tmp >> 9][tmp] = V; + } + else if (tmp < 0x3F00) + { + if (QTAIHack && (qtaintramreg & 1)) + { QTAINTRAM[((((tmp & 0xF00) >> 10) >> ((qtaintramreg >> 1)) & 1) << 10) | (tmp & 0x3FF)] = V; - } else { + } + else + { if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; } - } else { - if (!(tmp & 3)) { - if (!(tmp & 0xC)) { + } + else + { + if (!(tmp & 3)) + { + if (!(tmp & 0xC)) + { PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = V & 0x3F; PALRAM[0x10] = PALRAM[0x14] = PALRAM[0x18] = PALRAM[0x1C] = V & 0x3F; } else UPALRAM[((tmp & 0xC) >> 2) - 1] = V & 0x3F; - } else + } + else PALRAM[tmp & 0x1F] = V & 0x3F; } } @@ -456,14 +659,14 @@ volatile int rendercount, vromreadcount, undefinedvromcount, LogAddress = -1; unsigned char *cdloggervdata = NULL; unsigned int cdloggerVideoDataSize = 0; -int GetCHRAddress(int A) +int GetCHRAddress(int A) { - if (cdloggerVideoDataSize) + if (cdloggerVideoDataSize) { int result = -1; - if ( (A >= 0) && (A < 0x2000) ) + if ((A >= 0) && (A < 0x2000)) { - result = &VPage[A >> 10][A] - CHRptr[0]; + result = &VPage[A >> 9][A] - CHRptr[0]; } if ((result >= 0) && (result < (int)cdloggerVideoDataSize)) { @@ -472,110 +675,136 @@ int GetCHRAddress(int A) } else { - if ( (A >= 0) && (A < 0x2000) ) return A; + if ((A >= 0) && (A < 0x2000)) + return A; } return -1; } -int GetCHROffset(uint8 *ptr) { +int GetCHROffset(uint8 *ptr) +{ int result = ptr - CHRptr[0]; - if (cdloggerVideoDataSize) { + if (cdloggerVideoDataSize) + { if ((result >= 0) && (result < (int)cdloggerVideoDataSize)) return result; - } else { + } + else + { if ((result >= 0) && (result < 0x2000)) return result; } return -1; } -#define RENDER_LOG(tmp) { \ - if (debug_loggingCD) \ - { \ - int addr = GetCHRAddress(tmp); \ - if (addr != -1) \ - { \ - if (!(cdloggervdata[addr] & 1)) \ - { \ - cdloggervdata[addr] |= 1; \ - if(cdloggerVideoDataSize) { \ - if (!(cdloggervdata[addr] & 2)) undefinedvromcount--; \ - rendercount++; \ - } \ - } \ - } \ - } \ -} - -#define RENDER_LOGP(tmp) { \ - if (debug_loggingCD) \ - { \ - int addr = GetCHROffset(tmp); \ - if (addr != -1) \ - { \ - if (!(cdloggervdata[addr] & 1)) \ - { \ - cdloggervdata[addr] |= 1; \ - if(cdloggerVideoDataSize) { \ - if (!(cdloggervdata[addr] & 2)) undefinedvromcount--; \ - rendercount++; \ - } \ - } \ - } \ - } \ -} - -uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A) { +#define RENDER_LOG(tmp) \ + { \ + if (debug_loggingCD) \ + { \ + int addr = GetCHRAddress(tmp); \ + if (addr != -1) \ + { \ + if (!(cdloggervdata[addr] & 1)) \ + { \ + cdloggervdata[addr] |= 1; \ + if (cdloggerVideoDataSize) \ + { \ + if (!(cdloggervdata[addr] & 2)) \ + undefinedvromcount--; \ + rendercount++; \ + } \ + } \ + } \ + } \ + } + +#define RENDER_LOGP(tmp) \ + { \ + if (debug_loggingCD) \ + { \ + int addr = GetCHROffset(tmp); \ + if (addr != -1) \ + { \ + if (!(cdloggervdata[addr] & 1)) \ + { \ + cdloggervdata[addr] |= 1; \ + if (cdloggerVideoDataSize) \ + { \ + if (!(cdloggervdata[addr] & 2)) \ + undefinedvromcount--; \ + rendercount++; \ + } \ + } \ + } \ + } \ + } + +uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A) +{ uint32 tmp = A; - if (PPU_hook) PPU_hook(A); + if (PPU_hook) + PPU_hook(A); - if (tmp < 0x2000) { - return VPage[tmp >> 10][tmp]; - } else if (tmp < 0x3F00) { + if (tmp < 0x2000) + { + return VPage[tmp >> 9][tmp]; + } + else if (tmp < 0x3F00) + { return vnapage[(tmp >> 10) & 0x3][tmp & 0x3FF]; - } else { + } + else + { uint8 ret; - if (!(tmp & 3)) { + if (!(tmp & 3)) + { if (!(tmp & 0xC)) ret = READPAL(0x00); else ret = READUPAL(((tmp & 0xC) >> 2) - 1); - } else + } + else ret = READPAL(tmp & 0x1F); return ret; } } - -uint8 (FASTCALL *FFCEUX_PPURead)(uint32 A) = 0; +uint8(FASTCALL *FFCEUX_PPURead)(uint32 A) = 0; void (*FFCEUX_PPUWrite)(uint32 A, uint8 V) = 0; #define CALL_PPUREAD(A) (FFCEUX_PPURead(A)) #define CALL_PPUWRITE(A, V) (FFCEUX_PPUWrite ? FFCEUX_PPUWrite(A, V) : FFCEUX_PPUWrite_Default(A, V)) -//whether to use the new ppu +// whether to use the new ppu int newppu = 0; -void ppu_getScroll(int &xpos, int &ypos) { - if (newppu) { +void ppu_getScroll(int &xpos, int &ypos) +{ + if (newppu) + { ypos = ppur._vt * 8 + ppur._fv + ppur._v * 256; xpos = ppur._ht * 8 + ppur.fh + ppur._h * 256; - } else { + } + else + { xpos = ((RefreshAddr & 0x400) >> 2) | ((RefreshAddr & 0x1F) << 3) | XOffset; ypos = ((RefreshAddr & 0x3E0) >> 2) | ((RefreshAddr & 0x7000) >> 12); - if (RefreshAddr & 0x800) ypos += 240; + if (RefreshAddr & 0x800) + ypos += 240; } } //--------------- -static DECLFR(A2002) { - if (newppu) { - //once we thought we clear latches here, but that caused midframe glitches. - //i think we should only reset the state machine for 2005/2006 - //ppur.clear_latches(); +static DECLFR(A2002) +{ + if (newppu) + { + // once we thought we clear latches here, but that caused midframe glitches. + // i think we should only reset the state machine for 2005/2006 + // ppur.clear_latches(); } uint8 ret; @@ -596,19 +825,26 @@ static DECLFR(A2002) { return ret; } -static DECLFR(A2004) { - if (newppu) { - if ((ppur.status.sl < 241) && PPUON) { +static DECLFR(A2004) +{ + if (newppu) + { + if ((ppur.status.sl < 241) && PPUON) + { // from cycles 0 to 63, the // 32 byte OAM buffer gets init // to 0xFF if (ppur.status.cycle < 64) return spr_read.ret = 0xFF; - else { + else + { for (int i = spr_read.last; - i != ppur.status.cycle; ++i) { - if (i < 256) { - switch (spr_read.mode) { + i != ppur.status.cycle; ++i) + { + if (i < 256) + { + switch (spr_read.mode) + { case 0: if (spr_read.count < 2) spr_read.ret = (PPU[3] & 0xF8) + (spr_read.count << 2); @@ -618,36 +854,49 @@ static DECLFR(A2004) { spr_read.found_pos[spr_read.found] = spr_read.ret; spr_read.ret = SPRAM[spr_read.ret]; - if (i & 1) { - //odd cycle - //see if in range - if (!((ppur.status.sl - 1 - spr_read.ret) & ~(Sprite16 ? 0xF : 0x7))) { + if (i & 1) + { + // odd cycle + // see if in range + if (!((ppur.status.sl - 1 - spr_read.ret) & ~(Sprite16 ? 0xF : 0x7))) + { ++spr_read.found; spr_read.fetch = 1; spr_read.mode = 1; - } else { - if (++spr_read.count == 64) { + } + else + { + if (++spr_read.count == 64) + { spr_read.mode = 4; spr_read.count = 0; - } else if (spr_read.found == 8) { + } + else if (spr_read.found == 8) + { spr_read.fetch = 0; spr_read.mode = 2; } } } break; - case 1: //sprite is in range fetch next 3 bytes - if (i & 1) { + case 1: // sprite is in range fetch next 3 bytes + if (i & 1) + { ++spr_read.fetch; - if (spr_read.fetch == 4) { + if (spr_read.fetch == 4) + { spr_read.fetch = 1; - if (++spr_read.count == 64) { + if (++spr_read.count == 64) + { spr_read.count = 0; spr_read.mode = 4; - } else if (spr_read.found == 8) { + } + else if (spr_read.found == 8) + { spr_read.fetch = 0; spr_read.mode = 2; - } else + } + else spr_read.mode = 0; } } @@ -659,55 +908,72 @@ static DECLFR(A2004) { spr_read.ret = SPRAM[spr_read.ret | spr_read.fetch]; break; - case 2: //8th sprite fetched + case 2: // 8th sprite fetched spr_read.ret = SPRAM[(spr_read.count << 2) | spr_read.fetch]; - if (i & 1) { - if (!((ppur.status.sl - 1 - SPRAM[((spr_read.count << 2) | spr_read.fetch)]) & ~((Sprite16) ? 0xF : 0x7))) { + if (i & 1) + { + if (!((ppur.status.sl - 1 - SPRAM[((spr_read.count << 2) | spr_read.fetch)]) & ~((Sprite16) ? 0xF : 0x7))) + { spr_read.fetch = 1; spr_read.mode = 3; - } else { - if (++spr_read.count == 64) { + } + else + { + if (++spr_read.count == 64) + { spr_read.count = 0; spr_read.mode = 4; } spr_read.fetch = - (spr_read.fetch + 1) & 3; + (spr_read.fetch + 1) & 3; } } spr_read.ret = spr_read.count; break; - case 3: //9th sprite overflow detected + case 3: // 9th sprite overflow detected spr_read.ret = SPRAM[spr_read.count | spr_read.fetch]; - if (i & 1) { - if (++spr_read.fetch == 4) { + if (i & 1) + { + if (++spr_read.fetch == 4) + { spr_read.count = (spr_read.count + 1) & 63; spr_read.mode = 4; } } break; - case 4: //read OAM[n][0] until hblank + case 4: // read OAM[n][0] until hblank if (i & 1) spr_read.count = (spr_read.count + 1) & 63; spr_read.fetch = 0; spr_read.ret = SPRAM[spr_read.count << 2]; break; } - } else if (i < 320) { + } + else if (i < 320) + { spr_read.ret = (i & 0x38) >> 3; - if (spr_read.found < (spr_read.ret + 1)) { - if (spr_read.num) { + if (spr_read.found < (spr_read.ret + 1)) + { + if (spr_read.num) + { spr_read.ret = SPRAM[252]; spr_read.num = 0; - } else + } + else spr_read.ret = 0xFF; - } else if ((i & 7) < 4) { + } + else if ((i & 7) < 4) + { spr_read.ret = - SPRAM[spr_read.found_pos[spr_read.ret] | spr_read.fetch++]; + SPRAM[spr_read.found_pos[spr_read.ret] | spr_read.fetch++]; if (spr_read.fetch == 4) spr_read.fetch = 0; - } else - spr_read.ret = SPRAM[spr_read.found_pos [spr_read.ret | 3]]; - } else { + } + else + spr_read.ret = SPRAM[spr_read.found_pos[spr_read.ret | 3]]; + } + else + { if (!spr_read.found) spr_read.ret = SPRAM[252]; else @@ -718,52 +984,68 @@ static DECLFR(A2004) { spr_read.last = ppur.status.cycle; return spr_read.ret; } - } else + } + else return SPRAM[PPU[3]]; - } else { + } + else + { FCEUPPU_LineUpdate(); return PPUGenLatch; } } -static DECLFR(A200x) { /* Not correct for $2004 reads. */ +static DECLFR(A200x) +{ /* Not correct for $2004 reads. */ FCEUPPU_LineUpdate(); return PPUGenLatch; } -static DECLFR(A2007) { +static DECLFR(A2007) +{ uint8 ret; uint32 tmp = RefreshAddr & 0x3FFF; - if (debug_loggingCD) { - if (!DummyRead && (LogAddress != -1)) { - if (!(cdloggervdata[LogAddress] & 2)) { + if (debug_loggingCD) + { + if (!DummyRead && (LogAddress != -1)) + { + if (!(cdloggervdata[LogAddress] & 2)) + { cdloggervdata[LogAddress] |= 2; - if ((!(cdloggervdata[LogAddress] & 1)) && cdloggerVideoDataSize) undefinedvromcount--; + if ((!(cdloggervdata[LogAddress] & 1)) && cdloggerVideoDataSize) + undefinedvromcount--; vromreadcount++; } - } else + } + else DummyRead = 0; } - if (newppu) { + if (newppu) + { ret = VRAMBuffer; RefreshAddr = ppur.get_2007access() & 0x3FFF; - if ((RefreshAddr & 0x3F00) == 0x3F00) { - //if it is in the palette range bypass the - //delayed read, and what gets filled in the temp - //buffer is the address - 0x1000, also - //if grayscale is set then the return is AND with 0x30 - //to get a gray color reading - if (!(tmp & 3)) { + if ((RefreshAddr & 0x3F00) == 0x3F00) + { + // if it is in the palette range bypass the + // delayed read, and what gets filled in the temp + // buffer is the address - 0x1000, also + // if grayscale is set then the return is AND with 0x30 + // to get a gray color reading + if (!(tmp & 3)) + { if (!(tmp & 0xC)) ret = READPAL(0x00); else ret = READUPAL(((tmp & 0xC) >> 2) - 1); - } else + } + else ret = READPAL(tmp & 0x1F); VRAMBuffer = CALL_PPUREAD(RefreshAddr - 0x1000); - } else { + } + else + { if (debug_loggingCD && (RefreshAddr < 0x2000)) LogAddress = GetCHRAddress(RefreshAddr); VRAMBuffer = CALL_PPUREAD(RefreshAddr); @@ -771,58 +1053,70 @@ static DECLFR(A2007) { ppur.increment2007(ppur.status.sl >= 0 && ppur.status.sl < 241 && PPUON, INC32 != 0); RefreshAddr = ppur.get_2007access(); return ret; - } else { + } + else + { - //OLDPPU + // OLDPPU FCEUPPU_LineUpdate(); - if (tmp >= 0x3F00) { // Palette RAM tied directly to the output data, without VRAM buffer - if (!(tmp & 3)) { + if (tmp >= 0x3F00) + { // Palette RAM tied directly to the output data, without VRAM buffer + if (!(tmp & 3)) + { if (!(tmp & 0xC)) ret = READPAL(0x00); else ret = READUPAL(((tmp & 0xC) >> 2) - 1); - } else + } + else ret = READPAL(tmp & 0x1F); - #ifdef FCEUDEF_DEBUGGER +#ifdef FCEUDEF_DEBUGGER if (!fceuindbg) - #endif +#endif { if ((tmp - 0x1000) < 0x2000) - VRAMBuffer = VPage[(tmp - 0x1000) >> 10][tmp - 0x1000]; + VRAMBuffer = VPage[(tmp - 0x1000) >> 9][tmp - 0x1000]; else VRAMBuffer = vnapage[((tmp - 0x1000) >> 10) & 0x3][(tmp - 0x1000) & 0x3FF]; - if (PPU_hook) PPU_hook(tmp); + if (PPU_hook) + PPU_hook(tmp); } - } else { + } + else + { ret = VRAMBuffer; - #ifdef FCEUDEF_DEBUGGER +#ifdef FCEUDEF_DEBUGGER if (!fceuindbg) - #endif +#endif { - if (PPU_hook) PPU_hook(tmp); + if (PPU_hook) + PPU_hook(tmp); PPUGenLatch = VRAMBuffer; - if (tmp < 0x2000) { + if (tmp < 0x2000) + { if (debug_loggingCD) LogAddress = GetCHRAddress(tmp); - if(MMC5Hack && newppu) + if (MMC5Hack && newppu) VRAMBuffer = *MMC5BGVRAMADR(tmp); else - VRAMBuffer = VPage[tmp >> 10][tmp]; - - } else if (tmp < 0x3F00) + VRAMBuffer = VPage[tmp >> 9][tmp]; + } + else if (tmp < 0x3F00) VRAMBuffer = vnapage[(tmp >> 10) & 0x3][tmp & 0x3FF]; } } - #ifdef FCEUDEF_DEBUGGER +#ifdef FCEUDEF_DEBUGGER if (!fceuindbg) - #endif +#endif { - if ((ScreenON || SpriteON) && (scanline < 240)) { + if ((ScreenON || SpriteON) && (scanline < 240)) + { uint32 rad = RefreshAddr; - if ((rad & 0x7000) == 0x7000) { + if ((rad & 0x7000) == 0x7000) + { rad ^= 0x7000; if ((rad & 0x3E0) == 0x3A0) rad ^= 0xBA0; @@ -830,22 +1124,27 @@ static DECLFR(A2007) { rad ^= 0x3e0; else rad += 0x20; - } else + } + else rad += 0x1000; RefreshAddr = rad; - } else { + } + else + { if (INC32) RefreshAddr += 32; else RefreshAddr++; } - if (PPU_hook) PPU_hook(RefreshAddr & 0x3fff); + if (PPU_hook) + PPU_hook(RefreshAddr & 0x3fff); } return ret; } } -static DECLFW(B2000) { +static DECLFW(B2000) +{ FCEUPPU_LineUpdate(); PPUGenLatch = V; @@ -861,41 +1160,51 @@ static DECLFW(B2000) { ppur.s = (V >> 4) & 1; } -static DECLFW(B2001) { +static DECLFW(B2001) +{ FCEUPPU_LineUpdate(); if (paldeemphswap) - V = (V&0x9F)|((V&0x40)>>1)|((V&0x20)<<1); + V = (V & 0x9F) | ((V & 0x40) >> 1) | ((V & 0x20) << 1); PPUGenLatch = V; PPU[1] = V; if (V & 0xE0) deemp = V >> 5; } -static DECLFW(B2002) { +static DECLFW(B2002) +{ PPUGenLatch = V; } -static DECLFW(B2003) { +static DECLFW(B2003) +{ PPUGenLatch = V; PPU[3] = V; PPUSPL = V & 0x7; } -static DECLFW(B2004) { +static DECLFW(B2004) +{ PPUGenLatch = V; - if (newppu) { - //the attribute upper bits are not connected - //so AND them out on write, since reading them - //should return 0 in those bits. + if (newppu) + { + // the attribute upper bits are not connected + // so AND them out on write, since reading them + // should return 0 in those bits. if ((PPU[3] & 3) == 2) V &= 0xE3; SPRAM[PPU[3]] = V; PPU[3] = (PPU[3] + 1) & 0xFF; - } else { - if (PPUSPL >= 8) { + } + else + { + if (PPUSPL >= 8) + { if (PPU[3] >= 8) SPRAM[PPU[3]] = V; - } else { + } + else + { SPRAM[PPUSPL] = V; } PPU[3]++; @@ -903,17 +1212,21 @@ static DECLFW(B2004) { } } -static DECLFW(B2005) { +static DECLFW(B2005) +{ uint32 tmp = TempAddr; FCEUPPU_LineUpdate(); PPUGenLatch = V; - if (!vtoggle) { + if (!vtoggle) + { tmp &= 0xFFE0; tmp |= V >> 3; XOffset = V & 7; ppur._ht = V >> 3; ppur.fh = V & 7; - } else { + } + else + { tmp &= 0x8C1F; tmp |= ((V & ~0x7) << 2); tmp |= (V & 7) << 12; @@ -924,12 +1237,13 @@ static DECLFW(B2005) { vtoggle ^= 1; } - -static DECLFW(B2006) { +static DECLFW(B2006) +{ FCEUPPU_LineUpdate(); PPUGenLatch = V; - if (!vtoggle) { + if (!vtoggle) + { TempAddr &= 0x00FF; TempAddr |= (V & 0x3f) << 8; @@ -938,7 +1252,9 @@ static DECLFW(B2006) { ppur._h = (V >> 2) & 1; ppur._v = (V >> 3) & 1; ppur._fv = (V >> 4) & 3; - } else { + } + else + { TempAddr &= 0xFF00; TempAddr |= V; @@ -957,39 +1273,54 @@ static DECLFW(B2006) { vtoggle ^= 1; } -static DECLFW(B2007) { +static DECLFW(B2007) +{ uint32 tmp = RefreshAddr & 0x3FFF; - if (debug_loggingCD) { - if(!cdloggerVideoDataSize && (tmp < 0x2000)) + if (debug_loggingCD) + { + if (!cdloggerVideoDataSize && (tmp < 0x2000)) cdloggervdata[tmp] = 0; } - if (newppu) { + if (newppu) + { PPUGenLatch = V; RefreshAddr = ppur.get_2007access() & 0x3FFF; CALL_PPUWRITE(RefreshAddr, V); ppur.increment2007(ppur.status.sl >= 0 && ppur.status.sl < 241 && PPUON, INC32 != 0); RefreshAddr = ppur.get_2007access(); - } else { + } + else + { PPUGenLatch = V; - if (tmp < 0x2000) { - if (PPUCHRRAM & (1 << (tmp >> 10))) - VPage[tmp >> 10][tmp] = V; - } else if (tmp < 0x3F00) { - if (QTAIHack && (qtaintramreg & 1)) { + if (tmp < 0x2000) + { + if (PPUCHRRAM & (1 << (tmp >> 9))) + VPage[tmp >> 9][tmp] = V; + } + else if (tmp < 0x3F00) + { + if (QTAIHack && (qtaintramreg & 1)) + { QTAINTRAM[((((tmp & 0xF00) >> 10) >> ((qtaintramreg >> 1)) & 1) << 10) | (tmp & 0x3FF)] = V; - } else { + } + else + { if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; } - } else { - if (!(tmp & 3)) { + } + else + { + if (!(tmp & 3)) + { if (!(tmp & 0xC)) PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = V & 0x3F; else UPALRAM[((tmp & 0xC) >> 2) - 1] = V & 0x3F; - } else + } + else PALRAM[tmp & 0x1F] = V & 0x3F; } if (INC32) @@ -1001,7 +1332,8 @@ static DECLFW(B2007) { } } -static DECLFW(B4014) { +static DECLFW(B4014) +{ uint32 t = V << 8; int x; @@ -1010,16 +1342,17 @@ static DECLFW(B4014) { SpriteDMA = V; } -#define PAL(c) ((c) + cc) +#define PAL(c) ((c) + cc) -#define GETLASTPIXEL (PAL ? ((timestamp * 48 - linestartts) / 15) : ((timestamp * 48 - linestartts) >> 4)) +#define GETLASTPIXEL (PAL ? ((timestamp * 48 - linestartts) / 15) : ((timestamp * 48 - linestartts) >> 4)) static uint8 *Pline, *Plinef; static int firsttile; -int linestartts; //no longer static so the debugger can see it +int linestartts; // no longer static so the debugger can see it static int tofix = 0; -static void ResetRL(uint8 *target) { +static void ResetRL(uint8 *target) +{ memset(target, 0xFF, 256); InputScanlineHook(0, 0, 0, 0); Plinef = target; @@ -1033,34 +1366,39 @@ static void ResetRL(uint8 *target) { static uint8 sprlinebuf[256 + 8]; -void FCEUPPU_LineUpdate(void) { +void FCEUPPU_LineUpdate(void) +{ if (newppu) return; #ifdef FCEUDEF_DEBUGGER if (!fceuindbg) #endif - if (Pline) { - int l = GETLASTPIXEL; - RefreshLine(l); - } + if (Pline) + { + int l = GETLASTPIXEL; + RefreshLine(l); + } } static bool rendersprites = true, renderbg = true; -void FCEUI_SetRenderPlanes(bool sprites, bool bg) { +void FCEUI_SetRenderPlanes(bool sprites, bool bg) +{ rendersprites = sprites; renderbg = bg; } -void FCEUI_GetRenderPlanes(bool& sprites, bool& bg) { +void FCEUI_GetRenderPlanes(bool &sprites, bool &bg) +{ sprites = rendersprites; bg = renderbg; } static void CheckSpriteHit(int p); -static void EndRL(void) { +static void EndRL(void) +{ RefreshLine(272); if (tofix) Fixit1(); @@ -1071,14 +1409,18 @@ static void EndRL(void) { static int32 sphitx; static uint8 sphitdata; -static void CheckSpriteHit(int p) { +static void CheckSpriteHit(int p) +{ int l = p - 16; int x; - if (sphitx == 0x100) return; + if (sphitx == 0x100) + return; - for (x = sphitx; x < (sphitx + 8) && x < l; x++) { - if ((sphitdata & (0x80 >> (x - sphitx))) && !(Plinef[x] & 64) && x < 255) { + for (x = sphitx; x < (sphitx + 8) && x < l; x++) + { + if ((sphitdata & (0x80 >> (x - sphitx))) && !(Plinef[x] & 64) && x < 255) + { PPU_status |= 0x40; sphitx = 0x100; break; @@ -1086,50 +1428,56 @@ static void CheckSpriteHit(int p) { } } -//spork the world. Any sprites on this line? Then this will be set to 1. -//Needed for zapper emulation and *gasp* sprite emulation. +// spork the world. Any sprites on this line? Then this will be set to 1. +// Needed for zapper emulation and *gasp* sprite emulation. static int spork = 0; // lasttile is really "second to last tile." -static void RefreshLine(int lastpixel) { +static void RefreshLine(int lastpixel) +{ static uint32 pshift[2]; static uint32 atlatch; uint32 smorkus = RefreshAddr; - #define RefreshAddr smorkus +#define RefreshAddr smorkus uint32 vofs; int X1; uint8 *P = Pline; int lasttile = lastpixel >> 3; int numtiles; - static int norecurse = 0; // Yeah, recursion would be bad. - // PPU_hook() functions can call - // mirroring/chr bank switching functions, - // which call FCEUPPU_LineUpdate, which call this - // function. - if (norecurse) return; - - if (sphitx != 0x100 && !(PPU_status & 0x40)) { + static int norecurse = 0; // Yeah, recursion would be bad. + // PPU_hook() functions can call + // mirroring/chr bank switching functions, + // which call FCEUPPU_LineUpdate, which call this + // function. + if (norecurse) + return; + + if (sphitx != 0x100 && !(PPU_status & 0x40)) + { if ((sphitx < (lastpixel - 16)) && !(sphitx < ((lasttile - 2) * 8))) lasttile++; } - if (lasttile > 34) lasttile = 34; + if (lasttile > 34) + lasttile = 34; numtiles = lasttile - firsttile; - if (numtiles <= 0) return; + if (numtiles <= 0) + return; P = Pline; vofs = 0; - if(PEC586Hack) + if (PEC586Hack) vofs = ((RefreshAddr & 0x200) << 3) | ((RefreshAddr >> 12) & 7); else vofs = ((PPU[0] & 0x10) << 8) | ((RefreshAddr >> 12) & 7); - if (!ScreenON && !SpriteON) { + if (!ScreenON && !SpriteON) + { uint32 tem; tem = READPAL(0) | (READPAL(0) << 8) | (READPAL(0) << 16) | (READPAL(0) << 24); tem |= 0x40404040; @@ -1139,98 +1487,220 @@ static void RefreshLine(int lastpixel) { firsttile = lasttile; - #define TOFIXNUM (272 - 0x4) - if (lastpixel >= TOFIXNUM && tofix) { +#define TOFIXNUM (272 - 0x4) + if (lastpixel >= TOFIXNUM && tofix) + { Fixit1(); tofix = 0; } - if ((lastpixel - 16) >= 0) { + if ((lastpixel - 16) >= 0) + { InputScanlineHook(Plinef, spork ? sprlinebuf : 0, linestartts, lasttile * 8 - 16); } return; } - //Priority bits, needed for sprite emulation. + // Priority bits, needed for sprite emulation. PALRAM[0] |= 64; PALRAM[4] |= 64; PALRAM[8] |= 64; PALRAM[0xC] |= 64; - //This high-level graphics MMC5 emulation code was written for MMC5 carts in "CL" mode. - //It's probably not totally correct for carts in "SL" mode. + // This high-level graphics MMC5 emulation code was written for MMC5 carts in "CL" mode. + // It's probably not totally correct for carts in "SL" mode. #define PPUT_MMC5 - if (MMC5Hack && geniestage != 1) { - if (MMC5HackCHRMode == 0 && (MMC5HackSPMode & 0x80)) { + if (MMC5Hack && geniestage != 1) + { + if (MMC5HackCHRMode == 0 && (MMC5HackSPMode & 0x80)) + { int tochange = MMC5HackSPMode & 0x1F; tochange -= firsttile; - for (X1 = firsttile; X1 < lasttile; X1++) { - if ((tochange <= 0 && MMC5HackSPMode & 0x40) || (tochange > 0 && !(MMC5HackSPMode & 0x40))) { - #define PPUT_MMC5SP - #include "pputile.inc" - #undef PPUT_MMC5SP - } else { - #include "pputile.inc" + for (X1 = firsttile; X1 < lasttile; X1++) + { + if ((tochange <= 0 && MMC5HackSPMode & 0x40) || (tochange > 0 && !(MMC5HackSPMode & 0x40))) + { +#define PPUT_MMC5SP +#include "pputile.inc" +#undef PPUT_MMC5SP + } + else + { +#include "pputile.inc" } tochange--; } - } else if (MMC5HackCHRMode == 1 && (MMC5HackSPMode & 0x80)) { + } + else if (MMC5HackCHRMode == 1 && (MMC5HackSPMode & 0x80)) + { int tochange = MMC5HackSPMode & 0x1F; tochange -= firsttile; - #define PPUT_MMC5SP - #define PPUT_MMC5CHR1 - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" +#define PPUT_MMC5SP +#define PPUT_MMC5CHR1 + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" + } +#undef PPUT_MMC5CHR1 +#undef PPUT_MMC5SP + } + else if (MMC5HackCHRMode == 1) + { +#define PPUT_MMC5CHR1 + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" + } +#undef PPUT_MMC5CHR1 + } + else + { + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" } - #undef PPUT_MMC5CHR1 - #undef PPUT_MMC5SP - } else if (MMC5HackCHRMode == 1) { - #define PPUT_MMC5CHR1 - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" + } + } +#undef PPUT_MMC5 + + // Rainbow mapper specific code for vertical split-screen + +#define PPUT_RNBW + else if (RNBWHack && geniestage != 1) + { + for (X1 = firsttile; X1 < lasttile; X1++) + { + if (RNBWHackSplitEnable & (((RNBWHackWindowXStartTile <= RNBWHackWindowXEndTile) & ((X1 >= RNBWHackWindowXStartTile) & (X1 <= RNBWHackWindowXEndTile))) | + ((RNBWHackWindowXStartTile > RNBWHackWindowXEndTile) & ((X1 >= RNBWHackWindowXStartTile) | (X1 <= RNBWHackWindowXEndTile))))) + { +// handle vertical split-screen +#define PPUT_RNBW_SPLIT + uint8 NT_1K_dest = (RNBWHackNTcontrol[4] & 0x0C) >> 2; + uint8 NT_ext_mode = RNBWHackNTcontrol[4] & 0x03; + switch (NT_ext_mode) + { + case 0: + { +#include "pputile.inc" + break; + } + case 1: // extended attributes + { +#define PPUT_RNBW_SPLIT_EXT_ATTR +#include "pputile.inc" +#undef PPUT_RNBW_SPLIT_EXT_ATTR + break; + } + case 2: // extended tiles + { +#define PPUT_RNBW_SPLIT_EXT_TILE +#include "pputile.inc" +#undef PPUT_RNBW_SPLIT_EXT_TILE + break; + } + case 3: // extended attributes + tiles + { +#define PPUT_RNBW_SPLIT_EXT_ATTR +#define PPUT_RNBW_SPLIT_EXT_TILE +#include "pputile.inc" +#undef PPUT_RNBW_SPLIT_EXT_TILE +#undef PPUT_RNBW_SPLIT_EXT_ATTR + break; + } +#undef PPUT_RNBW_SPLIT + } } - #undef PPUT_MMC5CHR1 - } else { - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" + else + { + // handle other screens + uint8 NT = (RefreshAddr >> 10) & 0x03; + uint8 NT_1K_dest = (RNBWHackNTcontrol[NT] & 0x0C) >> 2; + uint8 NT_ext_mode = RNBWHackNTcontrol[NT] & 0x03; + switch (NT_ext_mode) + { + case 0: + { +#include "pputile.inc" + break; + } + case 1: // extended attributes + { +#define PPUT_RNBW_EXT_ATTR +#include "pputile.inc" +#undef PPUT_RNBW_EXT_ATTR + break; + } + case 2: // extended tiles + { +#define PPUT_RNBW_EXT_TILE +#include "pputile.inc" +#undef PPUT_RNBW_EXT_TILE + break; + } + case 3: // extended attributes + tiles + { +#define PPUT_RNBW_EXT_ATTR +#define PPUT_RNBW_EXT_TILE +#include "pputile.inc" +#undef PPUT_RNBW_EXT_TILE +#undef PPUT_RNBW_EXT_ATTR + break; + } + } } } } - #undef PPUT_MMC5 - else if (PPU_hook) { +#undef PPUT_RNBW + else if (PPU_hook) + { norecurse = 1; - #define PPUT_HOOK - if (PEC586Hack) { - #define PPU_BGFETCH - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" +#define PPUT_HOOK + if (PEC586Hack) + { +#define PPU_BGFETCH + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" } - #undef PPU_BGFETCH - } else { - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" +#undef PPU_BGFETCH + } + else + { + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" } } - #undef PPUT_HOOK +#undef PPUT_HOOK norecurse = 0; - } else { - if (PEC586Hack) { - #define PPU_BGFETCH - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" + } + else + { + if (PEC586Hack) + { +#define PPU_BGFETCH + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" } - #undef PPU_BGFETCH - } if (QTAIHack) { - #define PPU_VRC5FETCH - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" +#undef PPU_BGFETCH + } + if (QTAIHack) + { +#define PPU_VRC5FETCH + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" } - #undef PPU_VRC5FETCH - } else { - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" +#undef PPU_VRC5FETCH + } + else + { + for (X1 = firsttile; X1 < lasttile; X1++) + { +#include "pputile.inc" } } } @@ -1238,21 +1708,23 @@ static void RefreshLine(int lastpixel) { #undef vofs #undef RefreshAddr - //Reverse changes made before. + // Reverse changes made before. PALRAM[0] &= 63; PALRAM[4] &= 63; PALRAM[8] &= 63; PALRAM[0xC] &= 63; RefreshAddr = smorkus; - if (firsttile <= 2 && 2 < lasttile && !(PPU[1] & 2)) { + if (firsttile <= 2 && 2 < lasttile && !(PPU[1] & 2)) + { uint32 tem; tem = READPAL(0) | (READPAL(0) << 8) | (READPAL(0) << 16) | (READPAL(0) << 24); tem |= 0x40404040; - *(uint32*)Plinef = *(uint32*)(Plinef + 4) = tem; + *(uint32 *)Plinef = *(uint32 *)(Plinef + 4) = tem; } - if (!ScreenON) { + if (!ScreenON) + { uint32 tem; int tstart, tcount; tem = READPAL(0) | (READPAL(0) << 8) | (READPAL(0) << 16) | (READPAL(0) << 24); @@ -1260,7 +1732,8 @@ static void RefreshLine(int lastpixel) { tcount = lasttile - firsttile; tstart = firsttile - 2; - if (tstart < 0) { + if (tstart < 0) + { tcount += tstart; tstart = 0; } @@ -1268,23 +1741,27 @@ static void RefreshLine(int lastpixel) { FCEU_dwmemset(Plinef + tstart * 8, tem, tcount * 8); } - if (lastpixel >= TOFIXNUM && tofix) { + if (lastpixel >= TOFIXNUM && tofix) + { Fixit1(); tofix = 0; } - //This only works right because of a hack earlier in this function. + // This only works right because of a hack earlier in this function. CheckSpriteHit(lastpixel); - if ((lastpixel - 16) >= 0) { + if ((lastpixel - 16) >= 0) + { InputScanlineHook(Plinef, spork ? sprlinebuf : 0, linestartts, lasttile * 8 - 16); } Pline = P; firsttile = lasttile; } -static INLINE void Fixit2(void) { - if (ScreenON || SpriteON) { +static INLINE void Fixit2(void) +{ + if (ScreenON || SpriteON) + { uint32 rad = RefreshAddr; rad &= 0xFBE0; rad |= TempAddr & 0x041f; @@ -1292,11 +1769,14 @@ static INLINE void Fixit2(void) { } } -static void Fixit1(void) { - if (ScreenON || SpriteON) { +static void Fixit1(void) +{ + if (ScreenON || SpriteON) + { uint32 rad = RefreshAddr; - if ((rad & 0x7000) == 0x7000) { + if ((rad & 0x7000) == 0x7000) + { rad ^= 0x7000; if ((rad & 0x3E0) == 0x3A0) rad ^= 0xBA0; @@ -1304,15 +1784,18 @@ static void Fixit1(void) { rad ^= 0x3e0; else rad += 0x20; - } else + } + else rad += 0x1000; RefreshAddr = rad; } } -void MMC5_hb(int); //Ugh ugh ugh. -static void DoLine(void) { - if (scanline >= 240 && scanline != totalscanlines) { +void MMC5_hb(int); // Ugh ugh ugh. +static void DoLine(void) +{ + if (scanline >= 240 && scanline != totalscanlines) + { X6502_Run(256 + 69); scanline++; X6502_Run(16); @@ -1321,64 +1804,73 @@ static void DoLine(void) { int x; uint8 *target = XBuf + ((scanline < 240 ? scanline : 240) << 8); - u8* dtarget = XDBuf + ((scanline < 240 ? scanline : 240) << 8); + u8 *dtarget = XDBuf + ((scanline < 240 ? scanline : 240) << 8); - if (MMC5Hack) MMC5_hb(scanline); + if (MMC5Hack) + MMC5_hb(scanline); X6502_Run(256); EndRL(); - if (!renderbg) {// User asked to not display background data. + if (!renderbg) + { // User asked to not display background data. uint32 tem; uint8 col; if (gNoBGFillColor == 0xFF) col = READPAL(0); - else col = gNoBGFillColor; + else + col = gNoBGFillColor; tem = col | (col << 8) | (col << 16) | (col << 24); - tem |= 0x40404040; + tem |= 0x40404040; FCEU_dwmemset(target, tem, 256); } if (SpriteON) CopySprites(target); - //greyscale handling (mask some bits off the color) ? ? ? + // greyscale handling (mask some bits off the color) ? ? ? if (ScreenON || SpriteON) { - if (PPU[1] & 0x01) { + if (PPU[1] & 0x01) + { for (x = 63; x >= 0; x--) - *(uint32*)&target[x << 2] = (*(uint32*)&target[x << 2]) & 0x30303030; + *(uint32 *)&target[x << 2] = (*(uint32 *)&target[x << 2]) & 0x30303030; } } - //some pathetic attempts at deemph - if ((PPU[1] >> 5) == 0x7) { + // some pathetic attempts at deemph + if ((PPU[1] >> 5) == 0x7) + { for (x = 63; x >= 0; x--) - *(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0xc0c0c0c0; - } else if (PPU[1] & 0xE0) + *(uint32 *)&target[x << 2] = ((*(uint32 *)&target[x << 2]) & 0x3f3f3f3f) | 0xc0c0c0c0; + } + else if (PPU[1] & 0xE0) for (x = 63; x >= 0; x--) - *(uint32*)&target[x << 2] = (*(uint32*)&target[x << 2]) | 0x40404040; + *(uint32 *)&target[x << 2] = (*(uint32 *)&target[x << 2]) | 0x40404040; else for (x = 63; x >= 0; x--) - *(uint32*)&target[x << 2] = ((*(uint32*)&target[x << 2]) & 0x3f3f3f3f) | 0x80808080; + *(uint32 *)&target[x << 2] = ((*(uint32 *)&target[x << 2]) & 0x3f3f3f3f) | 0x80808080; - //write the actual deemph + // write the actual deemph for (x = 63; x >= 0; x--) - *(uint32*)&dtarget[x << 2] = ((PPU[1]>>5)<<0)|((PPU[1]>>5)<<8)|((PPU[1]>>5)<<16)|((PPU[1]>>5)<<24); + *(uint32 *)&dtarget[x << 2] = ((PPU[1] >> 5) << 0) | ((PPU[1] >> 5) << 8) | ((PPU[1] >> 5) << 16) | ((PPU[1] >> 5) << 24); sphitx = 0x100; if (ScreenON || SpriteON) FetchSpriteData(); - if (GameHBIRQHook && (ScreenON || SpriteON) && ((PPU[0] & 0x38) != 0x18)) { + if (GameHBIRQHook && (ScreenON || SpriteON) && ((PPU[0] & 0x38) != 0x18)) + { X6502_Run(6); Fixit2(); X6502_Run(4); GameHBIRQHook(); X6502_Run(85 - 16 - 10); - } else { - X6502_Run(6); // Tried 65, caused problems with Slalom(maybe others) + } + else + { + X6502_Run(6); // Tried 65, caused problems with Slalom(maybe others) Fixit2(); X6502_Run(85 - 6 - 16); @@ -1394,30 +1886,35 @@ static void DoLine(void) { if (GameHBIRQHook2 && (ScreenON || SpriteON)) GameHBIRQHook2(); scanline++; - if (scanline < 240) { + if (scanline < 240) + { ResetRL(XBuf + (scanline << 8)); } X6502_Run(16); } -#define V_FLIP 0x80 -#define H_FLIP 0x40 +#define V_FLIP 0x80 +#define H_FLIP 0x40 #define SP_BACK 0x20 -typedef struct { +typedef struct +{ uint8 y, no, atr, x; } SPR; -typedef struct { +typedef struct +{ uint8 ca[2], atr, x; } SPRB; -void FCEUI_DisableSpriteLimitation(int a) { +void FCEUI_DisableSpriteLimitation(int a) +{ maxsprites = a ? 64 : 8; } static uint8 numsprites, SpriteBlurp; -static void FetchSpriteData(void) { +static void FetchSpriteData(void) +{ uint8 ns, sb; SPR *spr; uint8 H; @@ -1425,7 +1922,7 @@ static void FetchSpriteData(void) { int vofs; uint8 P0 = PPU[0]; - spr = (SPR*)SPRAM; + spr = (SPR *)SPRAM; H = 8; ns = sb = 0; @@ -1434,10 +1931,14 @@ static void FetchSpriteData(void) { H += (P0 & 0x20) >> 2; if (!PPU_hook) - for (n = 63; n >= 0; n--, spr++) { - if ((uint32)(scanline - spr->y) >= H) continue; - if (ns < maxsprites) { - if (n == 63) sb = 1; + for (n = 63; n >= 0; n--, spr++) + { + if ((uint32)(scanline - spr->y) >= H) + continue; + if (ns < maxsprites) + { + if (n == 63) + sb = 1; { SPRB dst; @@ -1452,12 +1953,15 @@ static void FetchSpriteData(void) { else vadr = (spr->no << 4) + vofs; - if (spr->atr & V_FLIP) { + if (spr->atr & V_FLIP) + { vadr += 7; vadr -= t; vadr += (P0 & 0x20) >> 1; vadr -= t & 8; - } else { + } + else + { vadr += t; vadr += t & 8; } @@ -1477,21 +1981,27 @@ static void FetchSpriteData(void) { dst.x = spr->x; dst.atr = spr->atr; - *(uint32*)&SPRBUF[ns << 2] = *(uint32*)&dst; + *(uint32 *)&SPRBUF[ns << 2] = *(uint32 *)&dst; } ns++; - } else { + } + else + { PPU_status |= 0x20; break; } } else - for (n = 63; n >= 0; n--, spr++) { - if ((uint32)(scanline - spr->y) >= H) continue; + for (n = 63; n >= 0; n--, spr++) + { + if ((uint32)(scanline - spr->y) >= H) + continue; - if (ns < maxsprites) { - if (n == 63) sb = 1; + if (ns < maxsprites) + { + if (n == 63) + sb = 1; { SPRB dst; @@ -1506,12 +2016,15 @@ static void FetchSpriteData(void) { else vadr = (spr->no << 4) + vofs; - if (spr->atr & V_FLIP) { + if (spr->atr & V_FLIP) + { vadr += 7; vadr -= t; vadr += (P0 & 0x20) >> 1; vadr -= t & 8; - } else { + } + else + { vadr += t; vadr += t & 8; } @@ -1523,7 +2036,8 @@ static void FetchSpriteData(void) { if (SpriteON) RENDER_LOGP(C); dst.ca[0] = C[0]; - if (ns < 8) { + if (ns < 8) + { PPU_hook(0x2000); PPU_hook(vadr); } @@ -1533,21 +2047,25 @@ static void FetchSpriteData(void) { dst.x = spr->x; dst.atr = spr->atr; - - *(uint32*)&SPRBUF[ns << 2] = *(uint32*)&dst; + *(uint32 *)&SPRBUF[ns << 2] = *(uint32 *)&dst; } ns++; - } else { + } + else + { PPU_status |= 0x20; break; } } - //Handle case when >8 sprites per scanline option is enabled. - if (ns > 8) PPU_status |= 0x20; - else if (PPU_hook) { - for (n = 0; n < (8 - ns); n++) { + // Handle case when >8 sprites per scanline option is enabled. + if (ns > 8) + PPU_status |= 0x20; + else if (PPU_hook) + { + for (n = 0; n < (8 - ns); n++) + { PPU_hook(0x2000); PPU_hook(vofs); } @@ -1556,18 +2074,21 @@ static void FetchSpriteData(void) { SpriteBlurp = sb; } -static void RefreshSprites(void) { +static void RefreshSprites(void) +{ int n; SPRB *spr; spork = 0; - if (!numsprites) return; + if (!numsprites) + return; FCEU_dwmemset(sprlinebuf, 0x80808080, 256); numsprites--; - spr = (SPRB*)SPRBUF + numsprites; + spr = (SPRB *)SPRBUF + numsprites; - for (n = numsprites; n >= 0; n--, spr--) { + for (n = numsprites; n >= 0; n--, spr--) + { uint32 pixdata; uint8 J, atr; @@ -1579,91 +2100,134 @@ static void RefreshSprites(void) { J = spr->ca[0] | spr->ca[1]; atr = spr->atr; - if (J) { - if (n == 0 && SpriteBlurp && !(PPU_status & 0x40)) { + if (J) + { + if (n == 0 && SpriteBlurp && !(PPU_status & 0x40)) + { sphitx = x; sphitdata = J; if (atr & H_FLIP) sphitdata = ((J << 7) & 0x80) | - ((J << 5) & 0x40) | - ((J << 3) & 0x20) | - ((J << 1) & 0x10) | - ((J >> 1) & 0x08) | - ((J >> 3) & 0x04) | - ((J >> 5) & 0x02) | - ((J >> 7) & 0x01); + ((J << 5) & 0x40) | + ((J << 3) & 0x20) | + ((J << 1) & 0x10) | + ((J >> 1) & 0x08) | + ((J >> 3) & 0x04) | + ((J >> 5) & 0x02) | + ((J >> 7) & 0x01); } C = sprlinebuf + x; VB = (0x10) + ((atr & 3) << 2); - if (atr & SP_BACK) { - if (atr & H_FLIP) { - if (J & 0x80) C[7] = READPAL(VB | (pixdata & 3)) | 0x40; + if (atr & SP_BACK) + { + if (atr & H_FLIP) + { + if (J & 0x80) + C[7] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x40) C[6] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x40) + C[6] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x20) C[5] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x20) + C[5] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x10) C[4] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x10) + C[4] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x08) C[3] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x08) + C[3] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x04) C[2] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x04) + C[2] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x02) C[1] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x02) + C[1] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x01) C[0] = READPAL(VB | pixdata) | 0x40; - } else { - if (J & 0x80) C[0] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x01) + C[0] = READPAL(VB | pixdata) | 0x40; + } + else + { + if (J & 0x80) + C[0] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x40) C[1] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x40) + C[1] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x20) C[2] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x20) + C[2] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x10) C[3] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x10) + C[3] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x08) C[4] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x08) + C[4] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x04) C[5] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x04) + C[5] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x02) C[6] = READPAL(VB | (pixdata & 3)) | 0x40; + if (J & 0x02) + C[6] = READPAL(VB | (pixdata & 3)) | 0x40; pixdata >>= 4; - if (J & 0x01) C[7] = READPAL(VB | pixdata) | 0x40; + if (J & 0x01) + C[7] = READPAL(VB | pixdata) | 0x40; } - } else { - if (atr & H_FLIP) { - if (J & 0x80) C[7] = READPAL(VB | (pixdata & 3)); + } + else + { + if (atr & H_FLIP) + { + if (J & 0x80) + C[7] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x40) C[6] = READPAL(VB | (pixdata & 3)); + if (J & 0x40) + C[6] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x20) C[5] = READPAL(VB | (pixdata & 3)); + if (J & 0x20) + C[5] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x10) C[4] = READPAL(VB | (pixdata & 3)); + if (J & 0x10) + C[4] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x08) C[3] = READPAL(VB | (pixdata & 3)); + if (J & 0x08) + C[3] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x04) C[2] = READPAL(VB | (pixdata & 3)); + if (J & 0x04) + C[2] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x02) C[1] = READPAL(VB | (pixdata & 3)); + if (J & 0x02) + C[1] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x01) C[0] = READPAL(VB | pixdata); - } else { - if (J & 0x80) C[0] = READPAL(VB | (pixdata & 3)); + if (J & 0x01) + C[0] = READPAL(VB | pixdata); + } + else + { + if (J & 0x80) + C[0] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x40) C[1] = READPAL(VB | (pixdata & 3)); + if (J & 0x40) + C[1] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x20) C[2] = READPAL(VB | (pixdata & 3)); + if (J & 0x20) + C[2] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x10) C[3] = READPAL(VB | (pixdata & 3)); + if (J & 0x10) + C[3] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x08) C[4] = READPAL(VB | (pixdata & 3)); + if (J & 0x08) + C[4] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x04) C[5] = READPAL(VB | (pixdata & 3)); + if (J & 0x04) + C[5] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x02) C[6] = READPAL(VB | (pixdata & 3)); + if (J & 0x02) + C[6] = READPAL(VB | (pixdata & 3)); pixdata >>= 4; - if (J & 0x01) C[7] = READPAL(VB | pixdata); + if (J & 0x01) + C[7] = READPAL(VB | pixdata); } } } @@ -1672,53 +2236,64 @@ static void RefreshSprites(void) { spork = 1; } -static void CopySprites(uint8 *target) { +static void CopySprites(uint8 *target) +{ uint8 *P = target; - if (!spork) return; + if (!spork) + return; spork = 0; - if (!rendersprites) return; //User asked to not display sprites. + if (!rendersprites) + return; // User asked to not display sprites. - if(!SpriteON) return; - - int start=8; - if(PPU[1] & 0x04) + if (!SpriteON) + return; + + int start = 8; + if (PPU[1] & 0x04) start = 0; - for(int i=start;i<256;i++) + for (int i = start; i < 256; i++) { uint8 t = sprlinebuf[i]; - if(!(t&0x80)) - if (!(t & 0x40) || (P[i] & 0x40)) // Normal sprite || behind bg sprite + if (!(t & 0x80)) + if (!(t & 0x40) || (P[i] & 0x40)) // Normal sprite || behind bg sprite P[i] = t; } } -void FCEUPPU_SetVideoSystem(int w) { - if (w) { - scanlines_per_frame = dendy ? 262: 312; +void FCEUPPU_SetVideoSystem(int w) +{ + if (w) + { + scanlines_per_frame = dendy ? 262 : 312; FSettings.FirstSLine = FSettings.UsrFirstSLine[1]; FSettings.LastSLine = FSettings.UsrLastSLine[1]; - //paldeemphswap = 1; // dendy has pal ppu, and pal ppu has these swapped - } else { + // paldeemphswap = 1; // dendy has pal ppu, and pal ppu has these swapped + } + else + { scanlines_per_frame = 262; FSettings.FirstSLine = FSettings.UsrFirstSLine[0]; FSettings.LastSLine = FSettings.UsrLastSLine[0]; - //paldeemphswap = 0; + // paldeemphswap = 0; } } -//Initializes the PPU -void FCEUPPU_Init(void) { +// Initializes the PPU +void FCEUPPU_Init(void) +{ makeppulut(); } -void PPU_ResetHooks() { +void PPU_ResetHooks() +{ FFCEUX_PPURead = FFCEUX_PPURead_Default; } -void FCEUPPU_Reset(void) { +void FCEUPPU_Reset(void) +{ VRAMBuffer = PPU[0] = PPU[1] = PPU_status = PPU[3] = 0; PPUSPL = 0; PPUGenLatch = 0; @@ -1731,7 +2306,8 @@ void FCEUPPU_Reset(void) { new_ppu_reset = true; // delay reset of ppur/spr_read until it's ready to start a new frame } -void FCEUPPU_Power(void) { +void FCEUPPU_Power(void) +{ int x; // initialize PPU memory regions according to settings @@ -1739,7 +2315,8 @@ void FCEUPPU_Power(void) { FCEU_MemoryRand(PALRAM, 0x20, true); FCEU_MemoryRand(SPRAM, 0x100, true); // palettes can only store values up to $3F, and PALRAM X4/X8/XC are mirrors of X0 for rendering purposes (UPALRAM is used for $2007 readback) - for (x = 0; x < 0x20; ++x) PALRAM[x] &= 0x3F; + for (x = 0; x < 0x20; ++x) + PALRAM[x] &= 0x3F; UPALRAM[0] = PALRAM[0x04]; UPALRAM[1] = PALRAM[0x08]; UPALRAM[2] = PALRAM[0x0C]; @@ -1747,7 +2324,8 @@ void FCEUPPU_Power(void) { PALRAM[0x1C] = PALRAM[0x18] = PALRAM[0x14] = PALRAM[0x10]; FCEUPPU_Reset(); - for (x = 0x2000; x < 0x4000; x += 8) { + for (x = 0x2000; x < 0x4000; x += 8) + { ARead[x] = A200x; BWrite[x] = B2000; ARead[x + 1] = A200x; @@ -1768,37 +2346,45 @@ void FCEUPPU_Power(void) { BWrite[0x4014] = B4014; } -int FCEUPPU_Loop(int skip) { - if ((newppu) && (GameInfo->type != GIT_NSF)) { +int FCEUPPU_Loop(int skip) +{ + if ((newppu) && (GameInfo->type != GIT_NSF)) + { int FCEUX_PPU_Loop(int skip); return FCEUX_PPU_Loop(skip); } - //Needed for Knight Rider, possibly others. - if (ppudead) { + // Needed for Knight Rider, possibly others. + if (ppudead) + { memset(XBuf, 0x80, 256 * 240); X6502_Run(scanlines_per_frame * (256 + 85)); ppudead--; - } else { + } + else + { X6502_Run(256 + 85); PPU_status |= 0x80; - //Not sure if this is correct. According to Matt Conte and my own tests, it is. - //Timing is probably off, though. - //NOTE: Not having this here breaks a Super Donkey Kong game. + // Not sure if this is correct. According to Matt Conte and my own tests, it is. + // Timing is probably off, though. + // NOTE: Not having this here breaks a Super Donkey Kong game. PPU[3] = PPUSPL = 0; - //I need to figure out the true nature and length of this delay. + // I need to figure out the true nature and length of this delay. X6502_Run(12); if (GameInfo->type == GIT_NSF) DoNSFFrame(); - else { + else + { if (VBlankON) TriggerNMI(); } X6502_Run((scanlines_per_frame - 242) * (256 + 85) - 12); - if (overclock_enabled && vblankscanlines) { - if (!DMC_7bit || !skip_7bit_overclocking) { + if (overclock_enabled && vblankscanlines) + { + if (!DMC_7bit || !skip_7bit_overclocking) + { overclocking = 1; X6502_Run(vblankscanlines * (256 + 85) - 12); overclocking = 0; @@ -1810,23 +2396,28 @@ int FCEUPPU_Loop(int skip) { { int x; - if (ScreenON || SpriteON) { + if (ScreenON || SpriteON) + { if (GameHBIRQHook && ((PPU[0] & 0x38) != 0x18)) GameHBIRQHook(); if (PPU_hook) - for (x = 0; x < 42; x++) { - PPU_hook(0x2000); PPU_hook(0); + for (x = 0; x < 42; x++) + { + PPU_hook(0x2000); + PPU_hook(0); } if (GameHBIRQHook2) GameHBIRQHook2(); } X6502_Run(85 - 16); - if (ScreenON || SpriteON) { + if (ScreenON || SpriteON) + { RefreshAddr = TempAddr; - if (PPU_hook) PPU_hook(RefreshAddr & 0x3fff); + if (PPU_hook) + PPU_hook(RefreshAddr & 0x3fff); } - //Clean this stuff up later. + // Clean this stuff up later. spork = numsprites = 0; ResetRL(XBuf); @@ -1835,31 +2426,40 @@ int FCEUPPU_Loop(int skip) { } if (GameInfo->type == GIT_NSF) X6502_Run((256 + 85) * normalscanlines); - #ifdef FRAMESKIP - else if (skip) { +#ifdef FRAMESKIP + else if (skip) + { int y; y = SPRAM[0]; y++; - PPU_status |= 0x20; // Fixes "Bee 52". Does it break anything? - if (GameHBIRQHook) { + PPU_status |= 0x20; // Fixes "Bee 52". Does it break anything? + if (GameHBIRQHook) + { X6502_Run(256); - for (scanline = 0; scanline < 240; scanline++) { + for (scanline = 0; scanline < 240; scanline++) + { if (ScreenON || SpriteON) GameHBIRQHook(); - if (scanline == y && SpriteON) PPU_status |= 0x40; + if (scanline == y && SpriteON) + PPU_status |= 0x40; X6502_Run((scanline == 239) ? 85 : (256 + 85)); } - } else if (y < 240) { + } + else if (y < 240) + { X6502_Run((256 + 85) * y); - if (SpriteON) PPU_status |= 0x40; // Quick and very dirty hack. + if (SpriteON) + PPU_status |= 0x40; // Quick and very dirty hack. X6502_Run((256 + 85) * (240 - y)); - } else + } + else X6502_Run((256 + 85) * 240); } - #endif - else { +#endif + else + { deemp = PPU[1] >> 5; // manual samples can't play correctly with overclocking @@ -1868,7 +2468,8 @@ int FCEUPPU_Loop(int skip) { else totalscanlines = normalscanlines + (overclock_enabled ? postrenderscanlines : 0); - for (scanline = 0; scanline < totalscanlines; ) { //scanline is incremented in DoLine. Evil. :/ + for (scanline = 0; scanline < totalscanlines;) + { // scanline is incremented in DoLine. Evil. :/ deempcnt[deemp]++; if (scanline < 240) @@ -1878,7 +2479,8 @@ int FCEUPPU_Loop(int skip) { if (scanline < normalscanlines || scanline == totalscanlines) overclocking = 0; - else { + else + { if (DMC_7bit && skip_7bit_overclocking) // 7bit sample started after 240th line break; overclocking = 1; @@ -1886,12 +2488,15 @@ int FCEUPPU_Loop(int skip) { } DMC_7bit = 0; - if (MMC5Hack) MMC5_hb(scanline); + if (MMC5Hack) + MMC5_hb(scanline); - //deemph nonsense, kept for complicated reasons (see SetNESDeemph_OldHacky implementation) + // deemph nonsense, kept for complicated reasons (see SetNESDeemph_OldHacky implementation) int maxref = 0; - for (int x = 1, max = 0; x < 7; x++) { - if (deempcnt[x] > max) { + for (int x = 1, max = 0; x < 7; x++) + { + if (deempcnt[x] > max) + { max = deempcnt[x]; maxref = x; } @@ -1899,16 +2504,18 @@ int FCEUPPU_Loop(int skip) { } SetNESDeemph_OldHacky(maxref, 0); } - } //else... to if(ppudead) + } // else... to if(ppudead) - #ifdef FRAMESKIP - if (skip) { +#ifdef FRAMESKIP + if (skip) + { FCEU_PutImageDummy(); - return(0); - } else - #endif + return (0); + } + else +#endif { - return(1); + return (1); } } @@ -1916,64 +2523,64 @@ int (*PPU_MASTER)(int skip) = FCEUPPU_Loop; static uint16 TempAddrT, RefreshAddrT; -void FCEUPPU_LoadState(int version) { +void FCEUPPU_LoadState(int version) +{ TempAddr = TempAddrT; RefreshAddr = RefreshAddrT; } SFORMAT FCEUPPU_STATEINFO[] = { - { NTARAM, 0x800, "NTAR" }, - { PALRAM, 0x20, "PRAM" }, - { SPRAM, 0x100, "SPRA" }, - { PPU, 0x4, "PPUR" }, - { &kook, 1, "KOOK" }, - { &ppudead, 1, "DEAD" }, - { &PPUSPL, 1, "PSPL" }, - { &XOffset, 1, "XOFF" }, - { &vtoggle, 1, "VTGL" }, - { &RefreshAddrT, 2 | FCEUSTATE_RLSB, "RADD" }, - { &TempAddrT, 2 | FCEUSTATE_RLSB, "TADD" }, - { &VRAMBuffer, 1, "VBUF" }, - { &PPUGenLatch, 1, "PGEN" }, - { 0 } -}; + {NTARAM, 0x800, "NTAR"}, + {PALRAM, 0x20, "PRAM"}, + {SPRAM, 0x100, "SPRA"}, + {PPU, 0x4, "PPUR"}, + {&kook, 1, "KOOK"}, + {&ppudead, 1, "DEAD"}, + {&PPUSPL, 1, "PSPL"}, + {&XOffset, 1, "XOFF"}, + {&vtoggle, 1, "VTGL"}, + {&RefreshAddrT, 2 | FCEUSTATE_RLSB, "RADD"}, + {&TempAddrT, 2 | FCEUSTATE_RLSB, "TADD"}, + {&VRAMBuffer, 1, "VBUF"}, + {&PPUGenLatch, 1, "PGEN"}, + {0}}; SFORMAT FCEU_NEWPPU_STATEINFO[] = { - { &idleSynch, 1, "IDLS" }, - { &spr_read.num, 4 | FCEUSTATE_RLSB, "SR_0" }, - { &spr_read.count, 4 | FCEUSTATE_RLSB, "SR_1" }, - { &spr_read.fetch, 4 | FCEUSTATE_RLSB, "SR_2" }, - { &spr_read.found, 4 | FCEUSTATE_RLSB, "SR_3" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx0" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx1" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx2" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx3" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx4" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx5" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx6" }, - { &spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx7" }, - { &spr_read.ret, 4 | FCEUSTATE_RLSB, "SR_4" }, - { &spr_read.last, 4 | FCEUSTATE_RLSB, "SR_5" }, - { &spr_read.mode, 4 | FCEUSTATE_RLSB, "SR_6" }, - { &ppur.fv, 4 | FCEUSTATE_RLSB, "PFVx" }, - { &ppur.v, 4 | FCEUSTATE_RLSB, "PVxx" }, - { &ppur.h, 4 | FCEUSTATE_RLSB, "PHxx" }, - { &ppur.vt, 4 | FCEUSTATE_RLSB, "PVTx" }, - { &ppur.ht, 4 | FCEUSTATE_RLSB, "PHTx" }, - { &ppur._fv, 4 | FCEUSTATE_RLSB, "P_FV" }, - { &ppur._v, 4 | FCEUSTATE_RLSB, "P_Vx" }, - { &ppur._h, 4 | FCEUSTATE_RLSB, "P_Hx" }, - { &ppur._vt, 4 | FCEUSTATE_RLSB, "P_VT" }, - { &ppur._ht, 4 | FCEUSTATE_RLSB, "P_HT" }, - { &ppur.fh, 4 | FCEUSTATE_RLSB, "PFHx" }, - { &ppur.s, 4 | FCEUSTATE_RLSB, "PSxx" }, - { &ppur.status.sl, 4 | FCEUSTATE_RLSB, "PST0" }, - { &ppur.status.cycle, 4 | FCEUSTATE_RLSB, "PST1" }, - { &ppur.status.end_cycle, 4 | FCEUSTATE_RLSB, "PST2" }, - { 0 } -}; - -void FCEUPPU_SaveState(void) { + {&idleSynch, 1, "IDLS"}, + {&spr_read.num, 4 | FCEUSTATE_RLSB, "SR_0"}, + {&spr_read.count, 4 | FCEUSTATE_RLSB, "SR_1"}, + {&spr_read.fetch, 4 | FCEUSTATE_RLSB, "SR_2"}, + {&spr_read.found, 4 | FCEUSTATE_RLSB, "SR_3"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx0"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx1"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx2"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx3"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx4"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx5"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx6"}, + {&spr_read.found_pos[0], 4 | FCEUSTATE_RLSB, "SRx7"}, + {&spr_read.ret, 4 | FCEUSTATE_RLSB, "SR_4"}, + {&spr_read.last, 4 | FCEUSTATE_RLSB, "SR_5"}, + {&spr_read.mode, 4 | FCEUSTATE_RLSB, "SR_6"}, + {&ppur.fv, 4 | FCEUSTATE_RLSB, "PFVx"}, + {&ppur.v, 4 | FCEUSTATE_RLSB, "PVxx"}, + {&ppur.h, 4 | FCEUSTATE_RLSB, "PHxx"}, + {&ppur.vt, 4 | FCEUSTATE_RLSB, "PVTx"}, + {&ppur.ht, 4 | FCEUSTATE_RLSB, "PHTx"}, + {&ppur._fv, 4 | FCEUSTATE_RLSB, "P_FV"}, + {&ppur._v, 4 | FCEUSTATE_RLSB, "P_Vx"}, + {&ppur._h, 4 | FCEUSTATE_RLSB, "P_Hx"}, + {&ppur._vt, 4 | FCEUSTATE_RLSB, "P_VT"}, + {&ppur._ht, 4 | FCEUSTATE_RLSB, "P_HT"}, + {&ppur.fh, 4 | FCEUSTATE_RLSB, "PFHx"}, + {&ppur.s, 4 | FCEUSTATE_RLSB, "PSxx"}, + {&ppur.status.sl, 4 | FCEUSTATE_RLSB, "PST0"}, + {&ppur.status.cycle, 4 | FCEUSTATE_RLSB, "PST1"}, + {&ppur.status.end_cycle, 4 | FCEUSTATE_RLSB, "PST2"}, + {0}}; + +void FCEUPPU_SaveState(void) +{ TempAddrT = TempAddr; RefreshAddrT = RefreshAddr; } @@ -1994,7 +2601,8 @@ int totpputime = 0; const int kLineTime = 341; const int kFetchTime = 2; -void runppu(int x) { +void runppu(int x) +{ ppur.status.cycle = (ppur.status.cycle + x) % ppur.status.end_cycle; if (!new_ppu_reset) // if resetting, suspend CPU until the first frame { @@ -2002,17 +2610,21 @@ void runppu(int x) { } } -//todo - consider making this a 3 or 4 slot fifo to keep from touching so much memory -struct BGData { - struct Record { +// todo - consider making this a 3 or 4 slot fifo to keep from touching so much memory +struct BGData +{ + struct Record + { uint8 nt, pecnt, at, pt[2], qtnt; uint8 ppu1[8]; - INLINE void Read() { + INLINE void Read() + { NTRefreshAddr = RefreshAddr = ppur.get_ntread(); if (PEC586Hack) ppur.s = (RefreshAddr & 0x200) >> 9; - else if (QTAIHack) { + else if (QTAIHack) + { qtnt = QTAINTRAM[((((RefreshAddr >> 10) & 3) >> ((qtaintramreg >> 1)) & 1) << 10) | (RefreshAddr & 0x3FF)]; ppur.s = qtnt & 0x3F; } @@ -2023,21 +2635,22 @@ struct BGData { ppu1[1] = PPU[1]; runppu(1); - - RefreshAddr = ppur.get_atread(); at = CALL_PPUREAD(RefreshAddr); - //modify at to get appropriate palette shift - if (ppur.vt & 2) at >>= 4; - if (ppur.ht & 2) at >>= 2; + // modify at to get appropriate palette shift + if (ppur.vt & 2) + at >>= 4; + if (ppur.ht & 2) + at >>= 2; at &= 0x03; at <<= 2; - //horizontal scroll clocked at cycle 3 and then - //vertical scroll at 251 + // horizontal scroll clocked at cycle 3 and then + // vertical scroll at 251 ppu1[2] = PPU[1]; runppu(1); - if (PPUON) { + if (PPUON) + { ppur.increment_hsc(); if (ppur.status.cycle == 251) ppur.increment_vs(); @@ -2047,7 +2660,8 @@ struct BGData { ppur.par = nt; RefreshAddr = ppur.get_ptread(); - if (PEC586Hack) { + if (PEC586Hack) + { pt[0] = CALL_PPUREAD(RefreshAddr | pecnt); ppu1[4] = PPU[1]; runppu(1); @@ -2058,7 +2672,9 @@ struct BGData { runppu(1); ppu1[7] = PPU[1]; runppu(1); - } else if (QTAIHack && (qtnt & 0x40)) { + } + else if (QTAIHack && (qtnt & 0x40)) + { pt[0] = *(CHRptr[0] + RefreshAddr); ppu1[4] = PPU[1]; runppu(1); @@ -2070,7 +2686,9 @@ struct BGData { runppu(1); ppu1[7] = PPU[1]; runppu(1); - } else { + } + else + { if (ScreenON) RENDER_LOG(RefreshAddr); pt[0] = CALL_PPUREAD(RefreshAddr); @@ -2090,10 +2708,11 @@ struct BGData { } }; - Record main[34]; //one at the end is junk, it can never be rendered + Record main[34]; // one at the end is junk, it can never be rendered } bgdata; -static inline int PaletteAdjustPixel(int pixel) { +static inline int PaletteAdjustPixel(int pixel) +{ if ((PPU[1] >> 5) == 0x7) return (pixel & 0x3f) | 0xc0; else if (PPU[1] & 0xE0) @@ -2103,7 +2722,8 @@ static inline int PaletteAdjustPixel(int pixel) { } int framectr = 0; -int FCEUX_PPU_Loop(int skip) { +int FCEUX_PPU_Loop(int skip) +{ if (new_ppu_reset) // first frame since reset, time to initialize { @@ -2112,8 +2732,9 @@ int FCEUX_PPU_Loop(int skip) { new_ppu_reset = false; } - //262 scanlines - if (ppudead) { + // 262 scanlines + if (ppudead) + { // not quite emulating all the NES power up behavior // since it is known that the NES ignores writes to some // register before around a full frame, but no games @@ -2134,53 +2755,54 @@ int FCEUX_PPU_Loop(int skip) { PPU_status |= 0x80; ppuphase = PPUPHASE_VBL; - //Not sure if this is correct. According to Matt Conte and my own tests, it is. - //Timing is probably off, though. - //NOTE: Not having this here breaks a Super Donkey Kong game. + // Not sure if this is correct. According to Matt Conte and my own tests, it is. + // Timing is probably off, though. + // NOTE: Not having this here breaks a Super Donkey Kong game. PPU[3] = PPUSPL = 0; - const int delay = 20; //fceu used 12 here but I couldnt get it to work in marble madness and pirates. + const int delay = 20; // fceu used 12 here but I couldnt get it to work in marble madness and pirates. - ppur.status.sl = 241; //for sprite reads + ppur.status.sl = 241; // for sprite reads - //formerly: runppu(delay); - for(int dot=0;dot 0 || SpriteLeft8); const bool renderbgnow = ScreenON && (xt > 0 || BGLeft8); - for (int xp = 0; xp < 8; xp++, rasterpos++, g_rasterpos++) { - //bg pos is different from raster pos due to its offsetability. - //so adjust for that here + for (int xp = 0; xp < 8; xp++, rasterpos++, g_rasterpos++) + { + // bg pos is different from raster pos due to its offsetability. + // so adjust for that here const int bgpos = rasterpos + ppur.fh; const int bgpx = bgpos & 7; const int bgtile = bgpos >> 3; @@ -2243,7 +2868,7 @@ int FCEUX_PPU_Loop(int skip) { uint8 pixel = 0; uint8 pixelcolor = blank; - //according to qeed's doc, use palette 0 or $2006's value if it is & 0x3Fxx + // according to qeed's doc, use palette 0 or $2006's value if it is & 0x3Fxx if (!ScreenON && !SpriteON) { // if there's anything wrong with how we're doing this, someone please chime in @@ -2255,54 +2880,63 @@ int FCEUX_PPU_Loop(int skip) { pixelcolor = READPAL_MOTHEROFALL(pixel); } - //generate the BG data - if (renderbgnow) { - uint8* pt = bgdata.main[bgtile].pt; + // generate the BG data + if (renderbgnow) + { + uint8 *pt = bgdata.main[bgtile].pt; pixel = ((pt[0] >> (7 - bgpx)) & 1) | (((pt[1] >> (7 - bgpx)) & 1) << 1) | bgdata.main[bgtile].at; } if (renderbg) pixelcolor = READPALNOGS(pixel); - //look for a sprite to be drawn + // look for a sprite to be drawn bool havepixel = false; - for (int s = 0; s < oamcount; s++) { - uint8* oam = oams[renderslot][s]; + for (int s = 0; s < oamcount; s++) + { + uint8 *oam = oams[renderslot][s]; int x = oam[3]; - if (rasterpos >= x && rasterpos < x + 8) { - //build the pixel. - //fetch the LSB of the patterns + if (rasterpos >= x && rasterpos < x + 8) + { + // build the pixel. + // fetch the LSB of the patterns uint8 spixel = oam[4] & 1; spixel |= (oam[5] & 1) << 1; - //shift down the patterns so the next pixel is in the LSB + // shift down the patterns so the next pixel is in the LSB oam[4] >>= 1; oam[5] >>= 1; - if (!renderspritenow) continue; + if (!renderspritenow) + continue; - //bail out if we already have a pixel from a higher priority sprite - if (havepixel) continue; + // bail out if we already have a pixel from a higher priority sprite + if (havepixel) + continue; - //transparent pixel bailout - if (spixel == 0) continue; + // transparent pixel bailout + if (spixel == 0) + continue; - //spritehit: - //1. is it sprite#0? - //2. is the bg pixel nonzero? - //then, it is spritehit. + // spritehit: + // 1. is it sprite#0? + // 2. is the bg pixel nonzero? + // then, it is spritehit. if (oam[6] == 0 && (pixel & 3) != 0 && - rasterpos < 255) { + rasterpos < 255) + { PPU_status |= 0x40; } havepixel = true; - //priority handling - if (oam[2] & 0x20) { - //behind background: - if ((pixel & 3) != 0) continue; + // priority handling + if (oam[2] & 0x20) + { + // behind background: + if ((pixel & 3) != 0) + continue; } - //bring in the palette bits and palettize + // bring in the palette bits and palettize spixel |= (oam[2] & 3) << 2; if (rendersprites) @@ -2310,173 +2944,191 @@ int FCEUX_PPU_Loop(int skip) { } } - //apply grayscale.. kind of clunky - //really we need to read the entire palette instead of just ppu1 - //this will be needed for special color effects probably (very fine rainbows and whatnot?) - //are you allowed to chang the palette mid-line anyway? well you can definitely change the grayscale flag as we know from the FF1 "polygon" effect - if(bgdata.main[xt+2].ppu1[xp]&1) + // apply grayscale.. kind of clunky + // really we need to read the entire palette instead of just ppu1 + // this will be needed for special color effects probably (very fine rainbows and whatnot?) + // are you allowed to chang the palette mid-line anyway? well you can definitely change the grayscale flag as we know from the FF1 "polygon" effect + if (bgdata.main[xt + 2].ppu1[xp] & 1) pixelcolor &= 0x30; - //this does deemph stuff inside it.. which is probably wrong... + // this does deemph stuff inside it.. which is probably wrong... *ptr = PaletteAdjustPixel(pixelcolor); ptr++; - //grab deemph.. - //I guess this works the same way as the grayscale, ideally? - *dptr++ = bgdata.main[xt+2].ppu1[xp]>>5; + // grab deemph.. + // I guess this works the same way as the grayscale, ideally? + *dptr++ = bgdata.main[xt + 2].ppu1[xp] >> 5; } } } - //look for sprites (was supposed to run concurrent with bg rendering) + // look for sprites (was supposed to run concurrent with bg rendering) oamcounts[scanslot] = 0; oamcount = 0; const int spriteHeight = Sprite16 ? 16 : 8; - for (int i = 0; i < 64; i++) { + for (int i = 0; i < 64; i++) + { oams[scanslot][oamcount][7] = 0; - uint8* spr = SPRAM + i * 4; - if (yp >= spr[0] && yp < spr[0] + spriteHeight) { - //if we already have maxsprites, then this new one causes an overflow, - //set the flag and bail out. - if (oamcount >= 8 && PPUON) { + uint8 *spr = SPRAM + i * 4; + if (yp >= spr[0] && yp < spr[0] + spriteHeight) + { + // if we already have maxsprites, then this new one causes an overflow, + // set the flag and bail out. + if (oamcount >= 8 && PPUON) + { PPU_status |= 0x20; if (maxsprites == 8) break; } - //just copy some bytes into the internal sprite buffer + // just copy some bytes into the internal sprite buffer for (int j = 0; j < 4; j++) oams[scanslot][oamcount][j] = spr[j]; oams[scanslot][oamcount][7] = 1; - //note that we stuff the oam index into [6]. - //i need to turn this into a struct so we can have fewer magic numbers + // note that we stuff the oam index into [6]. + // i need to turn this into a struct so we can have fewer magic numbers oams[scanslot][oamcount][6] = (uint8)i; oamcount++; } } oamcounts[scanslot] = oamcount; - //FV is clocked by the PPU's horizontal blanking impulse, and therefore will increment every scanline. - //well, according to (which?) tests, maybe at the end of hblank. - //but, according to what it took to get crystalis working, it is at the beginning of hblank. + // FV is clocked by the PPU's horizontal blanking impulse, and therefore will increment every scanline. + // well, according to (which?) tests, maybe at the end of hblank. + // but, according to what it took to get crystalis working, it is at the beginning of hblank. - //this is done at cycle 251 - //rendering scanline, it doesn't need to be scanline 0, - //because on the first scanline when the increment is 0, the vs_scroll is reloaded. - //if(PPUON && sl != 0) + // this is done at cycle 251 + // rendering scanline, it doesn't need to be scanline 0, + // because on the first scanline when the increment is 0, the vs_scroll is reloaded. + // if(PPUON && sl != 0) // ppur.increment_vs(); - //todo - think about clearing oams to a predefined value to force deterministic behavior + // todo - think about clearing oams to a predefined value to force deterministic behavior ppuphase = PPUPHASE_OBJ; - //fetch sprite patterns - for (int s = 0; s < maxsprites; s++) { - //if we have hit our eight sprite pattern and we dont have any more sprites, then bail + // fetch sprite patterns + for (int s = 0; s < maxsprites; s++) + { + // if we have hit our eight sprite pattern and we dont have any more sprites, then bail if (s == oamcount && s >= 8) break; - //if this is a real sprite sprite, then it is not above the 8 sprite limit. - //this is how we support the no 8 sprite limit feature. - //not that at some point we may need a virtual CALL_PPUREAD which just peeks and doesnt increment any counters - //this could be handy for the debugging tools also + // if this is a real sprite sprite, then it is not above the 8 sprite limit. + // this is how we support the no 8 sprite limit feature. + // not that at some point we may need a virtual CALL_PPUREAD which just peeks and doesnt increment any counters + // this could be handy for the debugging tools also const bool realSprite = (s < 8); - uint8* const oam = oams[scanslot][s]; + uint8 *const oam = oams[scanslot][s]; uint32 line = yp - oam[0]; - if (oam[2] & 0x80) //vflip + if (oam[2] & 0x80) // vflip line = spriteHeight - line - 1; uint32 patternNumber = oam[1]; uint32 patternAddress; - //create deterministic dummy fetch pattern - if (!oam[7]) { + // create deterministic dummy fetch pattern + if (!oam[7]) + { patternNumber = 0; line = 0; } - //8x16 sprite handling: - if (Sprite16) { + // 8x16 sprite handling: + if (Sprite16) + { uint32 bank = (patternNumber & 1) << 12; patternNumber = patternNumber & ~1; patternNumber |= (line >> 3); patternAddress = (patternNumber << 4) | bank; - } else { + } + else + { patternAddress = (patternNumber << 4) | (SpAdrHI << 9); } - //offset into the pattern for the current line. - //tricky: tall sprites have already had lines>8 taken care of by getting a new pattern number above. - //so we just need the line offset for the second pattern + // offset into the pattern for the current line. + // tricky: tall sprites have already had lines>8 taken care of by getting a new pattern number above. + // so we just need the line offset for the second pattern patternAddress += line & 7; - //garbage nametable fetches + // garbage nametable fetches int garbage_todo = 2; if (PPUON) { if (sl == 0 && ppur.status.cycle == 304) { runppu(1); - if (PPUON) ppur.install_latches(); + if (PPUON) + ppur.install_latches(); runppu(1); garbage_todo = 0; } if ((sl != 0 && sl < 241) && ppur.status.cycle == 256) { runppu(1); - //at 257: 3d world runner is ugly if we do this at 256 - if (PPUON) ppur.install_h_latches(); + // at 257: 3d world runner is ugly if we do this at 256 + if (PPUON) + ppur.install_h_latches(); runppu(1); garbage_todo = 0; } } - if (realSprite) runppu(garbage_todo); - - //Dragon's Lair (Europe version mapper 4) - //does not set SpriteON in the beginning but it does - //set the bg on so if using the conditional SpriteON the MMC3 counter - //the counter will never count and no IRQs will be fired so use PPUON - if (((PPU[0] & 0x38) != 0x18) && s == 2 && PPUON) { + if (realSprite) + runppu(garbage_todo); + + // Dragon's Lair (Europe version mapper 4) + // does not set SpriteON in the beginning but it does + // set the bg on so if using the conditional SpriteON the MMC3 counter + // the counter will never count and no IRQs will be fired so use PPUON + if (((PPU[0] & 0x38) != 0x18) && s == 2 && PPUON) + { //(The MMC3 scanline counter is based entirely on PPU A12, triggered on rising edges (after the line remains low for a sufficiently long period of time)) - //http://nesdevwiki.org/wiki/index.php/Nintendo_MMC3 - //test cases for timing: SMB3, Crystalis - //crystalis requires deferring this til somewhere in sprite [1,3] - //kirby requires deferring this til somewhere in sprite [2,5.. - //if (PPUON && GameHBIRQHook) { - if (GameHBIRQHook) { + // http://nesdevwiki.org/wiki/index.php/Nintendo_MMC3 + // test cases for timing: SMB3, Crystalis + // crystalis requires deferring this til somewhere in sprite [1,3] + // kirby requires deferring this til somewhere in sprite [2,5.. + // if (PPUON && GameHBIRQHook) { + if (GameHBIRQHook) + { GameHBIRQHook(); } } - //blind attempt to replicate old ppu functionality - if(s == 2 && PPUON) + // blind attempt to replicate old ppu functionality + if (s == 2 && PPUON) { - if (GameHBIRQHook2) { + if (GameHBIRQHook2) + { GameHBIRQHook2(); } } - if (realSprite) runppu(kFetchTime); - + if (realSprite) + runppu(kFetchTime); - //pattern table fetches + // pattern table fetches + RNBWHackCurSprite = oam[6]; RefreshAddr = patternAddress; if (SpriteON) RENDER_LOG(RefreshAddr); oam[4] = CALL_PPUREAD(RefreshAddr); - if (realSprite) runppu(kFetchTime); + if (realSprite) + runppu(kFetchTime); RefreshAddr += 8; if (SpriteON) RENDER_LOG(RefreshAddr); oam[5] = CALL_PPUREAD(RefreshAddr); - if (realSprite) runppu(kFetchTime); + if (realSprite) + runppu(kFetchTime); - //hflip - if (!(oam[2] & 0x40)) { + // hflip + if (!(oam[2] & 0x40)) + { oam[4] = bitrevlut[oam[4]]; oam[5] = bitrevlut[oam[5]]; } @@ -2484,40 +3136,43 @@ int FCEUX_PPU_Loop(int skip) { ppuphase = PPUPHASE_BG; - //fetch BG: two tiles for next line + // fetch BG: two tiles for next line for (int xt = 0; xt < 2; xt++) bgdata.main[xt].Read(); - //I'm unclear of the reason why this particular access to memory is made. - //The nametable address that is accessed 2 times in a row here, is also the - //same nametable address that points to the 3rd tile to be rendered on the - //screen (or basically, the first nametable address that will be accessed when - //the PPU is fetching background data on the next scanline). + // I'm unclear of the reason why this particular access to memory is made. + // The nametable address that is accessed 2 times in a row here, is also the + // same nametable address that points to the 3rd tile to be rendered on the + // screen (or basically, the first nametable address that will be accessed when + // the PPU is fetching background data on the next scanline). //(not implemented yet) runppu(kFetchTime); - if (sl == 0) { + if (sl == 0) + { if (idleSynch && PPUON && !PAL) ppur.status.end_cycle = 340; else ppur.status.end_cycle = 341; idleSynch ^= 1; - } else + } + else ppur.status.end_cycle = 341; runppu(kFetchTime); - //After memory access 170, the PPU simply rests for 4 cycles (or the - //equivelant of half a memory access cycle) before repeating the whole - //pixel/scanline rendering process. If the scanline being rendered is the very - //first one on every second frame, then this delay simply doesn't exist. + // After memory access 170, the PPU simply rests for 4 cycles (or the + // equivelant of half a memory access cycle) before repeating the whole + // pixel/scanline rendering process. If the scanline being rendered is the very + // first one on every second frame, then this delay simply doesn't exist. if (ppur.status.end_cycle == 341) runppu(1); - } //scanline loop + } // scanline loop DMC_7bit = 0; - if (MMC5Hack) MMC5_hb(240); + if (MMC5Hack) + MMC5_hb(240); - //idle for one line + // idle for one line runppu(kLineTime); framectr++; } diff --git a/src/ppu.h b/src/ppu.h index 4555264db..cadd920c8 100644 --- a/src/ppu.h +++ b/src/ppu.h @@ -16,7 +16,7 @@ void newppu_hacky_emergency_reset(); /* For cart.c and banksw.h, mostly */ extern uint8 NTARAM[0x800], *vnapage[4]; extern uint8 PPUNTARAM; -extern uint8 PPUCHRRAM; +extern uint16 PPUCHRRAM; void FCEUPPU_SaveState(void); void FCEUPPU_LoadState(int version); @@ -36,7 +36,7 @@ void PPU_ResetHooks(); extern uint8 (FASTCALL *FFCEUX_PPURead)(uint32 A); extern void (*FFCEUX_PPUWrite)(uint32 A, uint8 V); extern uint8 FASTCALL FFCEUX_PPURead_Default(uint32 A); -void FFCEUX_PPUWrite_Default(uint32 A, uint8 V); +extern void FFCEUX_PPUWrite_Default(uint32 A, uint8 V); extern int g_rasterpos; extern uint8 PPU[4]; diff --git a/src/pputile.inc b/src/pputile.inc index 02da9a220..9261152b5 100644 --- a/src/pputile.inc +++ b/src/pputile.inc @@ -5,13 +5,17 @@ uint32 vadr; uint8 tmpd; #endif -#ifndef PPUT_MMC5SP - FCEU_MAYBE_UNUSED uint8 zz; -#else +#ifdef PPUT_MMC5SP uint8 xs, ys; xs = X1; ys = ((scanline >> 3) + MMC5HackSPScroll) & 0x1F; if (ys >= 0x1E) ys -= 0x1E; +#elif defined(PPUT_RNBW_SPLIT) + uint8 xs, ys; + xs = (X1 + RNBWHackSplitXScroll) & 0x1f; + ys = ((scanline + RNBWHackSplitYScroll) >> 3 ) & 0x1F; +#else + FCEU_MAYBE_UNUSED uint8 zz; #endif if (X1 >= 2) { @@ -42,6 +46,17 @@ if (X1 >= 2) { #ifdef PPUT_MMC5SP vadr = (MMC5HackExNTARAMPtr[xs | (ys << 5)] << 4) + (vofs & 7); +#elif defined(PPUT_RNBW_SPLIT) + #if defined(PPUT_RNBW_SPLIT_EXT_TILE) + // TODO need to use split config in account here + vadr = (RNBWHackExNTARAMPtr[xs | (ys << 5)] << 4) + ((scanline + RNBWHackSplitYScroll) & 7); + #else + vadr = (RNBWHackExNTARAMPtr[xs | (ys << 5)] << 4) + ((scanline + RNBWHackSplitYScroll) & 7); + #endif +#elif defined(PPUT_RNBW_EXT_TILE) + zz = RefreshAddr & 0x1F; + C = vnapage[(RefreshAddr >> 10) & 3]; + vadr = (C[RefreshAddr & 0x3ff] << 4) + vofs; // Fetch name table byte. #else zz = RefreshAddr & 0x1F; C = vnapage[(RefreshAddr >> 10) & 3]; @@ -59,6 +74,15 @@ if (X1 >= 2) { #ifdef PPUT_MMC5SP cc = MMC5HackExNTARAMPtr[0x3c0 + (xs >> 2) + ((ys & 0x1C) << 1)]; cc = ((cc >> ((xs & 2) + ((ys & 0x2) << 1))) & 3); +#elif defined(PPUT_RNBW_SPLIT) + #if defined(PPUT_RNBW_SPLIT_EXT_ATTR) + cc = (RNBWHackExNTARAMPtr[NT_1K_dest * 0x400 + (xs | (ys << 5))] & 0xC0) >> 6; + #else + cc = RNBWHackExNTARAMPtr[0x3c0 + (xs >> 2) + ((ys & 0x1C) << 1)]; + cc = ((cc >> ((xs & 2) + ((ys & 0x2) << 1))) & 3); + #endif +#elif defined(PPUT_RNBW_EXT_ATTR) + cc = (RNBWHackExNTARAMPtr[NT_1K_dest * 0x400 + (RefreshAddr & 0x3ff)] & 0xC0) >> 6; #else #ifdef PPUT_MMC5CHR1 cc = (MMC5HackExNTARAMPtr[RefreshAddr & 0x3ff] & 0xC0) >> 6; @@ -77,6 +101,9 @@ pshift[1] <<= 8; #ifdef PPUT_MMC5SP C = MMC5HackVROMPTR + vadr; C += ((MMC5HackSPPage & 0x3f & MMC5HackVROMMask) << 12); +#elif defined(PPUT_RNBW_SPLIT) + C = RNBWHackVROMPtr + vadr; + //C += ((RNBWHackSPPage & 0x3f & RNBWHackVROMMask) << 12); #else #ifdef PPUT_MMC5CHR1 C = MMC5HackVROMPTR; @@ -86,6 +113,11 @@ pshift[1] <<= 8; C = MMC5BGVRAMADR(vadr); #else + #ifdef PPUT_RNBW_EXT_TILE + C = RNBWHackVROMPtr; + C += ( (RNBWHackBGBankOffset * 0x40000) + (( RNBWHackExNTARAMPtr[NT_1K_dest * 0x400 + (RefreshAddr & 0x3ff)] & 0x3f ) << 12) + (vadr & 0xfff) ) & RNBWHackVROMMask; + #endif + #ifdef PPU_VRC5FETCH if(tmpd & 0x40) C = CHRptr[0] + vadr; diff --git a/src/unif.h b/src/unif.h index 92fc5a36d..1bf0d95af 100644 --- a/src/unif.h +++ b/src/unif.h @@ -62,6 +62,7 @@ void MHROM_Init(CartInfo *info); void QTAi_Init(CartInfo *info); void NROM_Init(CartInfo *info); void Novel_Init(CartInfo *info); +void RAINBOW_Init(CartInfo *info); void S74LS374NA_Init(CartInfo *info); void S74LS374N_Init(CartInfo *info); void S8259A_Init(CartInfo *info); diff --git a/vc/vc14_fceux.vcxproj b/vc/vc14_fceux.vcxproj index 43e5dc9df..bab9a4e3e 100644 --- a/vc/vc14_fceux.vcxproj +++ b/vc/vc14_fceux.vcxproj @@ -1,4 +1,4 @@ - + @@ -150,7 +150,7 @@ Disabled - .;../src/drivers/win/zlib;../src/drivers/win/directx;../src;../src/drivers/win/lua/include;userconfig;defaultconfig;%(AdditionalIncludeDirectories) + .;../src/drivers/win/curl/x86/include;../src/drivers/win/zlib;../src/drivers/win/directx;../src;../src/drivers/win/lua/include;userconfig;defaultconfig;%(AdditionalIncludeDirectories) WIN32;_DEBUG;MSVC;_CRT_SECURE_NO_DEPRECATE;_WIN32_WINDOWS=0x0410;WINVER=0x0410;NETWORK;LSB_FIRST;_USE_32BIT_TIME_T;FCEUDEF_DEBUGGER;_USE_SHARED_MEMORY_;NOMINMAX;HAS_vsnprintf;_S9XLUA_H;%(PreprocessorDefinitions) false EnableFastChecks @@ -164,7 +164,7 @@ true - Rpcrt4.lib;comctl32.lib;vfw32.lib;winmm.lib;ws2_32.lib;htmlhelp.lib;../src/drivers/win/directx/dsound.lib;../src/drivers/win/directx/dxguid.lib;../src/drivers/win/directx/ddraw.lib;../src/drivers/win/directx/dinput.lib;../src/drivers/win/lua/win32/lua51.lib;../src/drivers/win/lua/win32/luaperks.lib;psapi.lib;mpr.lib;%(AdditionalDependencies) + Normaliz.lib;Wldap32.lib;Crypt32.lib;advapi32.lib;../src/drivers/win/curl/x86/lib/libcurl_a.lib;Rpcrt4.lib;comctl32.lib;vfw32.lib;winmm.lib;ws2_32.lib;htmlhelp.lib;../src/drivers/win/directx/dsound.lib;../src/drivers/win/directx/dxguid.lib;../src/drivers/win/directx/ddraw.lib;../src/drivers/win/directx/dinput.lib;../src/drivers/win/lua/win32/lua51.lib;../src/drivers/win/lua/win32/luaperks.lib;psapi.lib;mpr.lib;%(AdditionalDependencies) true Console mainCRTStartup @@ -195,7 +195,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" true Speed true - .;../src/drivers/win/zlib;../src/drivers/win/directx;../src;../src/drivers/win/lua/include;userconfig;defaultconfig;%(AdditionalIncludeDirectories) + .;../src/drivers/win/curl/x86/include;../src/drivers/win/zlib;../src/drivers/win/directx;../src;../src/drivers/win/lua/include;userconfig;defaultconfig;%(AdditionalIncludeDirectories) WIN32;NDEBUG;MSVC;_CRT_SECURE_NO_DEPRECATE;_WIN32_WINDOWS=0x0410;WINVER=0x0410;NETWORK;LSB_FIRST;_USE_32BIT_TIME_T;FCEUDEF_DEBUGGER;_USE_SHARED_MEMORY_;NOMINMAX;HAS_vsnprintf;_S9XLUA_H;%(PreprocessorDefinitions) MultiThreaded @@ -207,7 +207,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" true - Rpcrt4.lib;comctl32.lib;vfw32.lib;winmm.lib;ws2_32.lib;htmlhelp.lib;../src/drivers/win/directx/dsound.lib;../src/drivers/win/directx/dxguid.lib;../src/drivers/win/directx/ddraw.lib;../src/drivers/win/directx/dinput.lib;../src/drivers/win/lua/win32/lua51.lib;../src/drivers/win/lua/win32/luaperks.lib;psapi.lib;mpr.lib;%(AdditionalDependencies) + Normaliz.lib;Wldap32.lib;Crypt32.lib;advapi32.lib;../src/drivers/win/curl/x86/lib/libcurl_a.lib;Rpcrt4.lib;comctl32.lib;vfw32.lib;winmm.lib;ws2_32.lib;htmlhelp.lib;../src/drivers/win/directx/dsound.lib;../src/drivers/win/directx/dxguid.lib;../src/drivers/win/directx/ddraw.lib;../src/drivers/win/directx/dinput.lib;../src/drivers/win/lua/win32/lua51.lib;../src/drivers/win/lua/win32/luaperks.lib;psapi.lib;mpr.lib;%(AdditionalDependencies) lua51.dll;%(DelayLoadDLLs) true Windows @@ -238,7 +238,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" true Speed true - .;../src/drivers/win/zlib;../src/drivers/win/directx;../src;../src/drivers/win/lua/include;userconfig;defaultconfig;%(AdditionalIncludeDirectories) + .;../src/drivers/win/curl/x86/include;../src/drivers/win/zlib;../src/drivers/win/directx;../src;../src/drivers/win/lua/include;userconfig;defaultconfig;%(AdditionalIncludeDirectories) PUBLIC_RELEASE;WIN32;NDEBUG;MSVC;_CRT_SECURE_NO_DEPRECATE;_WIN32_WINDOWS=0x0410;WINVER=0x0410;NETWORK;LSB_FIRST;_USE_32BIT_TIME_T;FCEUDEF_DEBUGGER;_USE_SHARED_MEMORY_;NOMINMAX;HAS_vsnprintf;_S9XLUA_H;%(PreprocessorDefinitions) MultiThreaded @@ -250,7 +250,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" true - Rpcrt4.lib;comctl32.lib;vfw32.lib;winmm.lib;ws2_32.lib;htmlhelp.lib;../src/drivers/win/directx/dsound.lib;../src/drivers/win/directx/dxguid.lib;../src/drivers/win/directx/ddraw.lib;../src/drivers/win/directx/dinput.lib;../src/drivers/win/lua/win32/lua51.lib;../src/drivers/win/lua/win32/luaperks.lib;psapi.lib;mpr.lib;%(AdditionalDependencies) + Normaliz.lib;Wldap32.lib;Crypt32.lib;advapi32.lib;../src/drivers/win/curl/x86/lib/libcurl_a.lib;Rpcrt4.lib;comctl32.lib;vfw32.lib;winmm.lib;ws2_32.lib;htmlhelp.lib;../src/drivers/win/directx/dsound.lib;../src/drivers/win/directx/dxguid.lib;../src/drivers/win/directx/ddraw.lib;../src/drivers/win/directx/dinput.lib;../src/drivers/win/lua/win32/lua51.lib;../src/drivers/win/lua/win32/luaperks.lib;psapi.lib;mpr.lib;%(AdditionalDependencies) lua51.dll;%(DelayLoadDLLs) true Windows @@ -277,7 +277,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" Disabled - .;../src/drivers/win/zlib;../src/drivers/win/directx/x64;../src;../src/drivers/win/lua/include;userconfig;defaultconfig;%(AdditionalIncludeDirectories) + .;../src/drivers/win/curl/x64/include;../src/drivers/win/zlib;../src/drivers/win/directx/x64;../src;../src/drivers/win/lua/include;userconfig;defaultconfig;%(AdditionalIncludeDirectories) WIN32;WIN64;MSVC;_CRT_SECURE_NO_DEPRECATE;_WIN32_WINDOWS=0x0410;WINVER=0x0410;NETWORK;LSB_FIRST;FCEUDEF_DEBUGGER;_USE_SHARED_MEMORY_;NOMINMAX;HAS_vsnprintf;_S9XLUA_H;_DEBUG;MSVC;_CRT_SECURE_NO_DEPRECATE;__WIN_DRIVER__;_WIN32_WINDOWS=0x0410;WINVER=0x0410;NETWORK;LSB_FIRST;%(PreprocessorDefinitions) false EnableFastChecks @@ -291,7 +291,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" 4267;4244; - comctl32.lib;ws2_32.lib;vfw32.lib;winmm.lib;htmlhelp.lib;../src/drivers/win/directx/x64/dsound.lib;../src/drivers/win/directx/x64/dxguid.lib;../src/drivers/win/directx/x64/ddraw.lib;../src/drivers/win/directx/x64/dinput.lib;../src/drivers/win/lua/x64/lua51.lib;../src/drivers/win/lua/x64/luaperks.lib;psapi.lib;mpr.lib;%(AdditionalDependencies) + Normaliz.lib;Wldap32.lib;Crypt32.lib;advapi32.lib;../src/drivers/win/curl/x64/lib/libcurl_a.lib;comctl32.lib;ws2_32.lib;vfw32.lib;winmm.lib;htmlhelp.lib;../src/drivers/win/directx/x64/dsound.lib;../src/drivers/win/directx/x64/dxguid.lib;../src/drivers/win/directx/x64/ddraw.lib;../src/drivers/win/directx/x64/dinput.lib;../src/drivers/win/lua/x64/lua51.lib;../src/drivers/win/lua/x64/luaperks.lib;psapi.lib;mpr.lib;%(AdditionalDependencies) true Windows mainCRTStartup @@ -316,7 +316,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" true Speed true - .;../src/drivers/win/zlib;../src/drivers/win/directx/x64;../src;../src/drivers/win/lua/include;userconfig;defaultconfig;%(AdditionalIncludeDirectories) + .;../src/drivers/win/curl/x64/include;../src/drivers/win/zlib;../src/drivers/win/directx/x64;../src;../src/drivers/win/lua/include;userconfig;defaultconfig;%(AdditionalIncludeDirectories) WIN32;WIN64;MSVC;_CRT_SECURE_NO_DEPRECATE;_WIN32_WINDOWS=0x0410;WINVER=0x0410;NETWORK;LSB_FIRST;FCEUDEF_DEBUGGER;_USE_SHARED_MEMORY_;NOMINMAX;HAS_vsnprintf;_S9XLUA_H;NDEBUG;%(PreprocessorDefinitions) MultiThreaded @@ -327,7 +327,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" 4267;4244; - comctl32.lib;ws2_32.lib;vfw32.lib;winmm.lib;htmlhelp.lib;../src/drivers/win/directx/x64/dsound.lib;../src/drivers/win/directx/x64/dxguid.lib;../src/drivers/win/directx/x64/ddraw.lib;../src/drivers/win/directx/x64/dinput.lib;../src/drivers/win/lua/x64/lua51.lib;../src/drivers/win/lua/x64/luaperks.lib;psapi.lib;mpr.lib;%(AdditionalDependencies) + Normaliz.lib;Wldap32.lib;Crypt32.lib;advapi32.lib;../src/drivers/win/curl/x64/lib/libcurl_a.lib;comctl32.lib;ws2_32.lib;vfw32.lib;winmm.lib;htmlhelp.lib;../src/drivers/win/directx/x64/dsound.lib;../src/drivers/win/directx/x64/dxguid.lib;../src/drivers/win/directx/x64/ddraw.lib;../src/drivers/win/directx/x64/dinput.lib;../src/drivers/win/lua/x64/lua51.lib;../src/drivers/win/lua/x64/luaperks.lib;psapi.lib;mpr.lib;%(AdditionalDependencies) true Windows true @@ -354,7 +354,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" true Speed true - .;../src/drivers/win/zlib;../src/drivers/win/directx/x64;../src;../src/drivers/win/lua/include;userconfig;defaultconfig;%(AdditionalIncludeDirectories) + .;../src/drivers/win/curl/x64/include;../src/drivers/win/zlib;../src/drivers/win/directx/x64;../src;../src/drivers/win/lua/include;userconfig;defaultconfig;%(AdditionalIncludeDirectories) PUBLIC_RELEASE;WIN32;WIN64;MSVC;_CRT_SECURE_NO_DEPRECATE;_WIN32_WINDOWS=0x0410;WINVER=0x0410;NETWORK;LSB_FIRST;FCEUDEF_DEBUGGER;_USE_SHARED_MEMORY_;NOMINMAX;HAS_vsnprintf;_S9XLUA_H;NDEBUG;MSVC;_CRT_SECURE_NO_DEPRECATE;_WIN32_WINDOWS=0x0410;WINVER=0x0410;NETWORK;LSB_FIRST;%(PreprocessorDefinitions) MultiThreaded @@ -365,7 +365,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" 4267;4244; - comctl32.lib;ws2_32.lib;vfw32.lib;winmm.lib;htmlhelp.lib;../src/drivers/win/directx/x64/dsound.lib;../src/drivers/win/directx/x64/dxguid.lib;../src/drivers/win/directx/x64/ddraw.lib;../src/drivers/win/directx/x64/dinput.lib;../src/drivers/win/lua/x64/lua51.lib;../src/drivers/win/lua/x64/luaperks.lib;psapi.lib;mpr.lib;%(AdditionalDependencies) + Normaliz.lib;Wldap32.lib;Crypt32.lib;advapi32.lib;../src/drivers/win/curl/x64/lib/libcurl_a.lib;comctl32.lib;ws2_32.lib;vfw32.lib;winmm.lib;htmlhelp.lib;../src/drivers/win/directx/x64/dsound.lib;../src/drivers/win/directx/x64/dxguid.lib;../src/drivers/win/directx/x64/ddraw.lib;../src/drivers/win/directx/x64/dinput.lib;../src/drivers/win/lua/x64/lua51.lib;../src/drivers/win/lua/x64/luaperks.lib;psapi.lib;mpr.lib;%(AdditionalDependencies) true Windows true @@ -505,6 +505,9 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" + + + @@ -1019,6 +1022,8 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)" + + diff --git a/vc/vc14_fceux.vcxproj.filters b/vc/vc14_fceux.vcxproj.filters index 9392e42ef..183a3898d 100644 --- a/vc/vc14_fceux.vcxproj.filters +++ b/vc/vc14_fceux.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -838,6 +838,9 @@ boards + + boards + boards @@ -1121,6 +1124,17 @@ boards + + boards + + + boards + + + boards + + + @@ -1630,6 +1644,15 @@ drivers\win + + boards + + + + + + boards + @@ -1643,7 +1666,6 @@ drivers\win\res - pix @@ -1966,6 +1988,7 @@ drivers\win\res +