2 Commits

Author SHA1 Message Date
Alexander Batalov
3cca4a81e9 Check back button to RMB emulation 2022-10-02 13:56:49 +03:00
Alexander Batalov
3924b6bba3 Fix back button on Android 2022-09-28 09:19:02 +03:00
237 changed files with 18307 additions and 30224 deletions

View File

@@ -1,3 +1,2 @@
BasedOnStyle: WebKit
AllowShortIfStatementsOnASingleLine: WithoutElse
FixNamespaceComments: true

1
.gitattributes vendored
View File

@@ -7,7 +7,6 @@
*.java text eol=lf
*.json text eol=lf
*.md text eol=lf
*.mm text eol=lf
*.plist text eol=lf
*.pro text eol=lf
*.properties text eol=lf

View File

@@ -26,23 +26,11 @@ jobs:
sudo apt install cppcheck
- name: Clone
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: cppcheck
run: cppcheck --std=c++17 src/
code-format:
name: Code format check
runs-on: ubuntu-latest
steps:
- name: Clone
uses: actions/checkout@v4
- name: clang-format
run: find src -type f -name \*.cc -o -name \*.h | xargs clang-format --dry-run --Werror
android:
name: Android
@@ -50,20 +38,20 @@ jobs:
steps:
- name: Clone
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Setup Java
uses: actions/setup-java@v3
uses: actions/setup-java@v2
with:
distribution: temurin
java-version: 11
cache: gradle
- name: Cache cmake build
uses: actions/cache@v4
uses: actions/cache@v3
with:
path: os/android/app/.cxx
key: android-cmake-v2
key: android-cmake-v1
- name: Setup signing config
if: env.KEYSTORE_FILE_BASE64 != '' && env.KEYSTORE_PROPERTIES_FILE_BASE64 != ''
@@ -81,58 +69,12 @@ jobs:
./gradlew assembleDebug
- name: Upload
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: fallout2-ce-debug.apk
path: os/android/app/build/outputs/apk/debug/app-debug.apk
retention-days: 7
ios:
name: iOS
runs-on: macos-13
steps:
- name: Clone
uses: actions/checkout@v4
- name: Cache cmake build
uses: actions/cache@v4
with:
path: build
key: ios-cmake-v4
- name: Configure
run: |
cmake \
-B build \
-D CMAKE_TOOLCHAIN_FILE=cmake/toolchain/ios.toolchain.cmake \
-D ENABLE_BITCODE=0 \
-D PLATFORM=OS64 \
-G Xcode \
-D CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY='' \
# EOL
- name: Build
run: |
cmake \
--build build \
--config RelWithDebInfo \
-j $(sysctl -n hw.physicalcpu) \
# EOL
- name: Pack
run: |
cd build
cpack -C RelWithDebInfo
- name: Upload
uses: actions/upload-artifact@v4
with:
name: fallout2-ce.ipa
path: build/fallout2-ce.ipa
retention-days: 7
linux:
name: Linux (${{ matrix.arch }})
@@ -147,7 +89,7 @@ jobs:
steps:
- name: Clone
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Dependencies (x86)
if: matrix.arch == 'x86'
@@ -164,10 +106,10 @@ jobs:
sudo apt install libsdl2-dev zlib1g-dev
- name: Cache cmake build
uses: actions/cache@v4
uses: actions/cache@v3
with:
path: build
key: linux-${{ matrix.arch }}-cmake-v3
key: linux-${{ matrix.arch }}-cmake-v1
- name: Configure (x86)
if: matrix.arch == 'x86'
@@ -194,7 +136,7 @@ jobs:
# EOL
- name: Upload
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: fallout2-ce-linux-${{ matrix.arch }}
path: build/fallout2-ce
@@ -203,44 +145,38 @@ jobs:
macos:
name: macOS
runs-on: macos-13
runs-on: macos-11
steps:
- name: Clone
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Cache cmake build
uses: actions/cache@v4
uses: actions/cache@v3
with:
path: build
key: macos-cmake-v6
key: macos-cmake-v3
- name: Configure
run: |
cmake \
-B build \
-G Xcode \
-D CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY='' \
-D CMAKE_BUILD_TYPE=RelWithDebInfo \
# EOL
- name: Build
run: |
cmake \
--build build \
--config RelWithDebInfo \
-j $(sysctl -n hw.physicalcpu) \
--target package \
# EOL
- name: Pack
run: |
cd build
cpack -C RelWithDebInfo
- name: Upload
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: fallout2-ce-macos.dmg
path: build/Fallout II Community Edition.dmg
path: build/fallout2-ce.dmg
retention-days: 7
windows:
@@ -259,13 +195,13 @@ jobs:
steps:
- name: Clone
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Cache cmake build
uses: actions/cache@v4
uses: actions/cache@v3
with:
path: build
key: windows-${{ matrix.arch }}-cmake-v2
key: windows-${{ matrix.arch }}-cmake-v1
- name: Configure
run: |
@@ -283,7 +219,7 @@ jobs:
# EOL
- name: Upload
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: fallout2-ce-windows-${{ matrix.arch }}
path: build/RelWithDebInfo/fallout2-ce.exe

View File

@@ -17,17 +17,17 @@ jobs:
steps:
- name: Clone
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Setup Java
uses: actions/setup-java@v3
uses: actions/setup-java@v2
with:
distribution: temurin
java-version: 11
cache: gradle
- name: Cache cmake build
uses: actions/cache@v4
uses: actions/cache@v3
with:
path: os/android/app/.cxx
key: android-cmake-v1
@@ -51,59 +51,11 @@ jobs:
run: |
cd os/android/app/build/outputs/apk/release
cp app-release.apk fallout2-ce-android.apk
gh release upload ${{ github.event.release.tag_name }} fallout2-ce-android.apk
gh release upload ${{ github.ref_name }} fallout2-ce-android.apk
rm fallout2-ce-android.apk
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ios:
name: iOS
runs-on: macos-12
steps:
- name: Clone
uses: actions/checkout@v4
- name: Cache cmake build
uses: actions/cache@v4
with:
path: build
key: ios-cmake-v1
- name: Configure
run: |
cmake \
-B build \
-D CMAKE_TOOLCHAIN_FILE=cmake/toolchain/ios.toolchain.cmake \
-D ENABLE_BITCODE=0 \
-D PLATFORM=OS64 \
-G Xcode \
-D CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY='' \
# EOL
- name: Build
run: |
cmake \
--build build \
--config RelWithDebInfo \
-j $(sysctl -n hw.physicalcpu) \
# EOL
- name: Pack
run: |
cd build
cpack -C RelWithDebInfo
- name: Upload
run: |
cd build
cp fallout2-ce.ipa fallout2-ce-ios.ipa
gh release upload ${{ github.event.release.tag_name }} fallout2-ce-ios.ipa
rm fallout2-ce-ios.ipa
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
linux:
name: Linux (${{ matrix.arch }})
@@ -118,7 +70,7 @@ jobs:
steps:
- name: Clone
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Dependencies (x86)
if: matrix.arch == 'x86'
@@ -135,7 +87,7 @@ jobs:
sudo apt install libsdl2-dev zlib1g-dev
- name: Cache cmake build
uses: actions/cache@v4
uses: actions/cache@v3
with:
path: build
key: linux-${{ matrix.arch }}-cmake-v1
@@ -168,7 +120,7 @@ jobs:
run: |
cd build
tar -czvf fallout2-ce-linux-${{ matrix.arch }}.tar.gz fallout2-ce
gh release upload ${{ github.event.release.tag_name }} fallout2-ce-linux-${{ matrix.arch }}.tar.gz
gh release upload ${{ github.ref_name }} fallout2-ce-linux-${{ matrix.arch }}.tar.gz
rm fallout2-ce-linux-${{ matrix.arch }}.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -180,16 +132,16 @@ jobs:
steps:
- name: Clone
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Import code signing certificates
uses: apple-actions/import-codesign-certs@v2
uses: apple-actions/import-codesign-certs@v1
with:
p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_FILE_BASE64 }}
p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_PASSWORD }}
- name: Cache cmake build
uses: actions/cache@v4
uses: actions/cache@v3
with:
path: build
key: macos-cmake-v3
@@ -198,44 +150,41 @@ jobs:
run: |
cmake \
-B build \
-G Xcode \
-D CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY="${{ secrets.APPLE_DEVELOPER_CERTIFICATE_IDENTITY }}" \
-D CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_INJECT_BASE_ENTITLEMENTS="NO" \
-D CMAKE_XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS="--options=runtime --timestamp" \
-D CMAKE_BUILD_TYPE=RelWithDebInfo \
-D CPACK_BUNDLE_APPLE_CERT_APP="${{ secrets.APPLE_DEVELOPER_CERTIFICATE_IDENTITY }}" \
# EOL
- name: Build
run: |
cmake \
--build build \
--config RelWithDebInfo \
-j $(sysctl -n hw.physicalcpu) \
--target package \
# EOL
- name: Pack
run: |
cd build
cpack -C RelWithDebInfo
- name: Notarize
run: |
xcrun notarytool submit \
"build/Fallout II Community Edition.dmg" \
--apple-id "${{ secrets.APPLE_DEVELOPER_AC_USERNAME }}" \
--team-id "${{ secrets.APPLE_DEVELOPER_AC_TEAM }}" \
--password "${{ secrets.APPLE_DEVELOPER_AC_PASSWORD }}" \
--wait
- name: Staple
run: |
xcrun stapler staple \
"build/Fallout II Community Edition.dmg"
brew install mitchellh/gon/gon
cat << EOF > config.json
{
"notarize": {
"path": "build/fallout2-ce.dmg",
"bundle_id": "$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" build/fallout2-ce.app/Contents/Info.plist)",
"staple": true
}
}
EOF
gon config.json
rm config.json
env:
AC_USERNAME: ${{ secrets.APPLE_DEVELOPER_AC_USERNAME }}
AC_PASSWORD: ${{ secrets.APPLE_DEVELOPER_AC_PASSWORD }}
- name: Upload
run: |
cd build
cp "Fallout II Community Edition.dmg" fallout2-ce-macos.dmg
gh release upload ${{ github.event.release.tag_name }} fallout2-ce-macos.dmg
cp fallout2-ce.dmg fallout2-ce-macos.dmg
gh release upload ${{ github.ref_name }} fallout2-ce-macos.dmg
rm fallout2-ce-macos.dmg
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -256,10 +205,10 @@ jobs:
steps:
- name: Clone
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Cache cmake build
uses: actions/cache@v4
uses: actions/cache@v3
with:
path: build
key: windows-${{ matrix.arch }}-cmake-v1
@@ -283,7 +232,7 @@ jobs:
run: |
cd build/RelWithDebInfo
7z a fallout2-ce-windows-${{ matrix.arch }}.zip fallout2-ce.exe
gh release upload ${{ github.event.release.tag_name }} fallout2-ce-windows-${{ matrix.arch }}.zip
gh release upload ${{ github.ref_name }} fallout2-ce-windows-${{ matrix.arch }}.zip
rm fallout2-ce-windows-${{ matrix.arch }}.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -4,14 +4,9 @@ set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(EXECUTABLE_NAME fallout2-ce)
if(APPLE)
if(IOS)
set(CMAKE_OSX_DEPLOYMENT_TARGET "12" CACHE STRING "")
set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "")
else()
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "")
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE STRING "")
endif()
if (APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.11" CACHE STRING "")
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE STRING "")
endif()
project(${EXECUTABLE_NAME})
@@ -20,7 +15,7 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_CXX_EXTENSIONS NO)
if(ANDROID)
if (ANDROID)
add_library(${EXECUTABLE_NAME} SHARED)
else()
add_executable(${EXECUTABLE_NAME} WIN32 MACOSX_BUNDLE)
@@ -57,6 +52,8 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
"src/combat.h"
"src/config.cc"
"src/config.h"
"src/core.cc"
"src/core.h"
"src/credits.cc"
"src/credits.h"
"src/critter.cc"
@@ -83,6 +80,8 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
"src/display_monitor.h"
"src/draw.cc"
"src/draw.h"
"src/electronic_registration.cc"
"src/electronic_registration.h"
"src/elevator.cc"
"src/elevator.h"
"src/endgame.cc"
@@ -105,6 +104,8 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
"src/game_mouse.h"
"src/game_movie.cc"
"src/game_movie.h"
"src/game_palette.cc"
"src/game_palette.h"
"src/game_sound.cc"
"src/game_sound.h"
"src/game_vars.h"
@@ -114,10 +115,10 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
"src/geometry.h"
"src/graph_lib.cc"
"src/graph_lib.h"
"src/grayscale.cc"
"src/grayscale.h"
"src/heap.cc"
"src/heap.h"
"src/input.cc"
"src/input.h"
"src/interface.cc"
"src/interface.h"
"src/interpreter_extra.cc"
@@ -130,8 +131,6 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
"src/inventory.h"
"src/item.cc"
"src/item.h"
"src/kb.cc"
"src/kb.h"
"src/light.cc"
"src/light.h"
"src/lips.cc"
@@ -140,8 +139,6 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
"src/loadsave.h"
"src/main.cc"
"src/main.h"
"src/mainmenu.cc"
"src/mainmenu.h"
"src/map_defs.h"
"src/map.cc"
"src/map.h"
@@ -152,10 +149,10 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
"src/memory.h"
"src/message.cc"
"src/message.h"
"src/mmx.cc"
"src/mmx.h"
"src/mouse_manager.cc"
"src/mouse_manager.h"
"src/mouse.cc"
"src/mouse.h"
"src/movie_effect.cc"
"src/movie_effect.h"
"src/movie_lib.cc"
@@ -217,8 +214,6 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
"src/stat.h"
"src/string_parsers.cc"
"src/string_parsers.h"
"src/svga.cc"
"src/svga.h"
"src/text_font.cc"
"src/text_font.h"
"src/text_object.cc"
@@ -228,8 +223,8 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
"src/trait_defs.h"
"src/trait.cc"
"src/trait.h"
"src/vcr.cc"
"src/vcr.h"
"src/trap.cc"
"src/trap.h"
"src/version.cc"
"src/version.h"
"src/widget.cc"
@@ -253,53 +248,25 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
target_sources(${EXECUTABLE_NAME} PUBLIC
"src/audio_engine.cc"
"src/audio_engine.h"
"src/delay.cc"
"src/delay.h"
"src/fps_limiter.cc"
"src/fps_limiter.h"
"src/platform_compat.cc"
"src/platform_compat.h"
"src/pointer_registry.cc"
"src/pointer_registry.h"
"src/preferences.cc"
"src/preferences.h"
"src/settings.cc"
"src/settings.h"
"src/sfall_config.cc"
"src/sfall_config.h"
"src/sfall_global_vars.cc"
"src/sfall_global_vars.h"
"src/sfall_global_scripts.cc"
"src/sfall_global_scripts.h"
"src/sfall_ini.cc"
"src/sfall_ini.h"
"src/sfall_kb_helpers.cc"
"src/sfall_kb_helpers.h"
"src/sfall_lists.cc"
"src/sfall_lists.h"
"src/sfall_metarules.cc"
"src/sfall_metarules.h"
"src/sfall_opcodes.cc"
"src/sfall_opcodes.h"
"src/sfall_arrays.cc"
"src/sfall_arrays.h"
"src/touch.cc"
"src/touch.h"
)
if(IOS)
target_sources(${EXECUTABLE_NAME} PUBLIC
"src/platform/ios/paths.h"
"src/platform/ios/paths.mm"
)
endif()
if(WIN32)
target_compile_definitions(${EXECUTABLE_NAME} PUBLIC
_CRT_SECURE_NO_WARNINGS
_CRT_NONSTDC_NO_WARNINGS
NOMINMAX
WIN32_LEAN_AND_MEAN
)
else()
target_compile_definitions(${EXECUTABLE_NAME} PRIVATE
$<$<CONFIG:Debug>:_DEBUG>
$<$<CONFIG:RelWithDebInfo>:_DEBUG>
)
endif()
@@ -309,7 +276,7 @@ if(WIN32)
)
endif()
if(WIN32)
if (WIN32)
target_sources(${EXECUTABLE_NAME} PUBLIC
"os/windows/fallout2-ce.ico"
"os/windows/fallout2-ce.rc"
@@ -317,53 +284,23 @@ if(WIN32)
endif()
if(APPLE)
if(IOS)
set(RESOURCES
"os/ios/AppIcon.xcassets"
"os/ios/LaunchScreen.storyboard"
)
target_sources(${EXECUTABLE_NAME} PUBLIC ${RESOURCES})
set_source_files_properties(${RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
set_target_properties(${EXECUTABLE_NAME} PROPERTIES
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/os/ios/Info.plist"
XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon"
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.alexbatalov.fallout2-ce"
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2"
)
set(MACOSX_BUNDLE_BUNDLE_NAME "${EXECUTABLE_NAME}")
set(MACOSX_BUNDLE_DISPLAY_NAME "Fallout 2")
else()
set(RESOURCES
"os/macos/fallout2-ce.icns"
)
target_sources(${EXECUTABLE_NAME} PUBLIC ${RESOURCES})
set_source_files_properties(${RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
set_target_properties(${EXECUTABLE_NAME} PROPERTIES
OUTPUT_NAME "Fallout II Community Edition"
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/os/macos/Info.plist"
XCODE_ATTRIBUTE_EXECUTABLE_NAME "${EXECUTABLE_NAME}"
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.alexbatalov.fallout2-ce"
)
set(MACOSX_BUNDLE_ICON_FILE "fallout2-ce.icns")
set(MACOSX_BUNDLE_BUNDLE_NAME "Fallout II: Community Edition")
set(MACOSX_BUNDLE_DISPLAY_NAME "Fallout II")
endif()
target_sources(${EXECUTABLE_NAME} PUBLIC "os/macos/fallout2-ce.icns")
set_source_files_properties("os/macos/fallout2-ce.icns" PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
set_target_properties(${EXECUTABLE_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/os/macos/Info.plist")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.alexbatalov.fallout2-ce")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "1.3.0")
set(MACOSX_BUNDLE_BUNDLE_VERSION "1.3.0")
set(MACOSX_BUNDLE_BUNDLE_NAME "${EXECUTABLE_NAME}")
set(MACOSX_BUNDLE_ICON_FILE "fallout2-ce.icns")
set(MACOSX_BUNDLE_DISPLAY_NAME "Fallout 2")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "1.1.0")
set(MACOSX_BUNDLE_BUNDLE_VERSION "1.1.0")
endif()
add_subdirectory("third_party/fpattern")
target_link_libraries(${EXECUTABLE_NAME} fpattern::fpattern)
target_link_libraries(${EXECUTABLE_NAME} ${FPATTERN_LIBRARY})
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${FPATTERN_INCLUDE_DIR})
if((NOT ${CMAKE_SYSTEM_NAME} MATCHES "Linux") AND (NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") AND (NOT ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD"))
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
add_subdirectory("third_party/zlib")
add_subdirectory("third_party/sdl2")
else()
@@ -378,20 +315,23 @@ target_link_libraries(${EXECUTABLE_NAME} ${SDL2_LIBRARIES})
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${SDL2_INCLUDE_DIRS})
if(APPLE)
if(IOS)
install(TARGETS ${EXECUTABLE_NAME} DESTINATION "Payload")
install(TARGETS ${EXECUTABLE_NAME} DESTINATION .)
install(CODE "
include(BundleUtilities)
fixup_bundle(${CMAKE_BINARY_DIR}/${MACOSX_BUNDLE_BUNDLE_NAME}.app \"\" \"\")
"
COMPONENT Runtime)
set(CPACK_GENERATOR "ZIP")
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)
set(CPACK_PACKAGE_FILE_NAME "fallout2-ce")
set(CPACK_ARCHIVE_FILE_EXTENSION "ipa")
else()
install(TARGETS ${EXECUTABLE_NAME} DESTINATION .)
set(CPACK_GENERATOR "DragNDrop")
set(CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK ON)
set(CPACK_PACKAGE_FILE_NAME "Fallout II Community Edition")
if (CPACK_BUNDLE_APPLE_CERT_APP)
install(CODE "
execute_process(COMMAND codesign --deep --force --options runtime --sign \"${CPACK_BUNDLE_APPLE_CERT_APP}\" ${CMAKE_BINARY_DIR}/${MACOSX_BUNDLE_BUNDLE_NAME}.app)
"
COMPONENT Runtime)
endif()
set(CPACK_GENERATOR "DragNDrop")
set(CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK ON)
set(CPACK_PACKAGE_FILE_NAME "fallout2-ce")
include(CPack)
endif()

View File

@@ -1,14 +1,8 @@
# Fallout 2 Community Edition
Fallout 2 Community Edition is a fully working re-implementation of Fallout 2, with the same original gameplay, engine bugfixes, and some quality of life improvements, that works (mostly) hassle-free on multiple platforms.
Popular Fallout 2 total conversion mods are partially supported. Original versions of Nevada and Sonora (that do not rely on extended features provided by Sfall) likely work, although there is no complete walkthrough confirmation yet. [Fallout 2 Restoration Project](https://github.com/BGforgeNet/Fallout2_Restoration_Project), [Fallout Et Tu](https://github.com/rotators/Fo1in2) and [Olympus 2207](https://olympus2207.com) are not yet supported. Other mods (particularly Resurrection and Yesterday) are not tested.
There is also [Fallout Community Edition](https://github.com/alexbatalov/fallout1-ce).
## Installation
You must own the game to play. Purchase your copy on [GOG](https://www.gog.com/game/fallout_2), [Epic Games](https://store.epicgames.com/p/fallout-2) or [Steam](https://store.steampowered.com/app/38410). Download latest [release](https://github.com/alexbatalov/fallout2-ce/releases) or build from source. You can also check latest [debug](https://github.com/alexbatalov/fallout2-ce/actions) build intended for testers.
You must own the game to play. Purchase your copy on [GOG](https://www.gog.com/game/fallout_2) or [Steam](https://store.steampowered.com/app/38410). Download latest release or build from source.
### Windows
@@ -42,53 +36,13 @@ $ sudo apt install libsdl2-2.0-0
### Android
> **NOTE**: Fallout 2 was designed with mouse in mind. There are many controls that require precise cursor positioning, which is not possible with fingers. Current control scheme resembles trackpad usage:
- One finger moves mouse cursor around.
- Tap one finger for left mouse click.
- Tap two fingers for right mouse click (switches mouse cursor mode).
- Move two fingers to scroll current view (map view, worldmap view, inventory scrollers).
> **NOTE**: Fallout 2 was designed with mouse in mind. There are many controls that require precise cursor positioning, which is not possible with fingers. When playing on Android you'll use fingers to move mouse cursor, not a character, or a map. Double tap to "click" left mouse button in the current cursor position, triple tap to "click" right mouse button. It might feel awkward at first, but it's super handy - you can play with just a thumb. This is not set in stone and might change in the future.
> **NOTE**: From Android standpoint release and debug builds are different apps. Both apps require their own copy of game assets and have their own savegames. This is intentional. As a gamer just stick with release version and check for updates.
- Use Windows installation as a base - it contains data assets needed to play. Copy `Fallout2` folder to your device, for example to `Downloads`. You need `master.dat`, `critter.dat`, `patch000.dat`, and `data` folder. Watch for file names - keep (or make) them lowercased (see [Configuration](#configuration)).
- Use Windows installation as a base - it contains data assets needed to play. Copy `Fallout2` folder to your device, for example to `Downloads`. You need `master.dat`, `critter.dat`, `patch000.dat`, and `data` folder.
- Download `fallout2-ce.apk` and copy it to your device. Open it with file explorer, follow instructions (install from unknown source).
- When you run the game for the first time it will immediately present file picker. Select the folder from the first step. Wait until this data is copied. A loading dialog will appear, just wait for about 30 seconds. If you're installing total conversion mod or localized version with a large number of unpacked resources in `data` folder it can take up to 20 minutes. Once copied, the game will start automatically.
### iOS
> **NOTE**: See Android note on controls.
- Download `fallout2-ce.ipa`. Use sideloading applications ([AltStore](https://altstore.io/) or [Sideloadly](https://sideloadly.io/)) to install it to your device. Alternatively you can always build from source with your own signing certificate.
- Run the game once. You'll see error message saying "Couldn't find/load text fonts". This step is needed for iOS to expose the game via File Sharing feature.
- Use Finder (macOS Catalina and later) or iTunes (Windows and macOS Mojave or earlier) to copy `master.dat`, `critter.dat`, `patch000.dat`, and `data` folder to "Fallout 2" app ([how-to](https://support.apple.com/HT210598)). Watch for file names - keep (or make) them lowercased (see [Configuration](#configuration)).
## Configuration
The main configuration file is `fallout2.cfg`. There are several important settings you might need to adjust for your installation. Depending on your Fallout distribution main game assets `master.dat`, `critter.dat`, `patch000.dat`, and `data` folder might be either all lowercased, or all uppercased. You can either update `master_dat`, `critter_dat`, `master_patches` and `critter_patches` settings to match your file names, or rename files to match entries in your `fallout2.cfg`.
The `sound` folder (with `music` folder inside) might be located either in `data` folder, or be in the Fallout folder. Update `music_path1` setting to match your hierarchy, usually it's `data/sound/music/` or `sound/music/`. Make sure it matches your path exactly (so it might be `SOUND/MUSIC/` if you've installed Fallout from CD). Music files themselves (with `ACM` extension) should be all uppercased, regardless of `sound` and `music` folders.
The second configuration file is `f2_res.ini`. Use it to change game window size and enable/disable fullscreen mode.
```ini
[MAIN]
SCR_WIDTH=1280
SCR_HEIGHT=720
WINDOWED=1
```
Recommendations:
- **Desktops**: Use any size you see fit.
- **Tablets**: Set these values to logical resolution of your device, for example iPad Pro 11 is 1668x2388 (pixels), but it's logical resolution is 834x1194 (points).
- **Mobile phones**: Set height to 480, calculate width according to your device screen (aspect) ratio, for example Samsung S21 is 20:9 device, so the width should be 480 * 20 / 9 = 1067.
In time this stuff will receive in-game interface, right now you have to do it manually.
The third configuration file is `ddraw.ini` (part of Sfall). There are dozens of options that adjust or override engine behaviour and gameplay mechanics. This file is intended for modders and advanced users. Currently only a small subset of these settings are actually implemented.
- When you run the game for the first time it will immediately present file picker. Select the folder from the first step. Wait until this data is copied. A loading dialog will appear, just wait for about 30 seconds. The game will start automatically.
## Contributing

File diff suppressed because it is too large Load Diff

View File

@@ -9,8 +9,8 @@ android {
applicationId 'com.alexbatalov.fallout2ce'
minSdk 21
targetSdk 32
versionCode 4
versionName '1.3.0'
versionCode 2
versionName '1.1.0'
externalNativeBuild {
cmake {
arguments '-DANDROID_STL=c++_static'

View File

@@ -15,9 +15,13 @@ import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -33,8 +37,11 @@ import android.view.Display;
import android.view.Gravity;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
@@ -44,7 +51,6 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -59,9 +65,6 @@ import java.util.Locale;
*/
public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener {
private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 2;
private static final int SDL_MINOR_VERSION = 26;
private static final int SDL_MICRO_VERSION = 1;
/*
// Display InputType.SOURCE/CLASS of events and devices
//
@@ -210,7 +213,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
// Main components
protected static SDLActivity mSingleton;
protected static SDLSurface mSurface;
protected static DummyEdit mTextEdit;
protected static View mTextEdit;
protected static boolean mScreenKeyboardShown;
protected static ViewGroup mLayout;
protected static SDLClipboardHandler mClipboardHandler;
@@ -311,10 +314,6 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
mNextNativeState = NativeState.INIT;
mCurrentNativeState = NativeState.INIT;
}
protected SDLSurface createSDLSurface(Context context) {
return new SDLSurface(context);
}
// Setup
@Override
@@ -345,18 +344,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
errorMsgBrokenLib = e.getMessage();
}
if (!mBrokenLibraries) {
String expected_version = String.valueOf(SDL_MAJOR_VERSION) + "." +
String.valueOf(SDL_MINOR_VERSION) + "." +
String.valueOf(SDL_MICRO_VERSION);
String version = nativeGetVersion();
if (!version.equals(expected_version)) {
mBrokenLibraries = true;
errorMsgBrokenLib = "SDL C/Java version mismatch (expected " + expected_version + ", got " + version + ")";
}
}
if (mBrokenLibraries) {
if (mBrokenLibraries)
{
mSingleton = this;
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this);
dlgAlert.setMessage("An error occurred while trying to start the application. Please try again and/or reinstall."
@@ -393,7 +382,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
mHIDDeviceManager = HIDDeviceManager.acquire(this);
// Set up the surface
mSurface = createSDLSurface(getApplication());
mSurface = new SDLSurface(getApplication());
mLayout = new RelativeLayout(this);
mLayout.addView(mSurface);
@@ -897,7 +886,6 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
}
// C functions we call
public static native String nativeGetVersion();
public static native int nativeSetupJNI();
public static native int nativeRunMain(String library, String function, Object arguments);
public static native void nativeLowMemory();
@@ -1232,7 +1220,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
}
// This method is called by SDLControllerManager's API 26 Generic Motion Handler.
public static View getContentView() {
public static View getContentView()
{
return mLayout;
}
@@ -1303,77 +1292,6 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
return event.isPrintingKey() || event.getKeyCode() == KeyEvent.KEYCODE_SPACE;
}
public static boolean handleKeyEvent(View v, int keyCode, KeyEvent event, InputConnection ic) {
int deviceId = event.getDeviceId();
int source = event.getSource();
if (source == InputDevice.SOURCE_UNKNOWN) {
InputDevice device = InputDevice.getDevice(deviceId);
if (device != null) {
source = device.getSources();
}
}
// if (event.getAction() == KeyEvent.ACTION_DOWN) {
// Log.v("SDL", "key down: " + keyCode + ", deviceId = " + deviceId + ", source = " + source);
// } else if (event.getAction() == KeyEvent.ACTION_UP) {
// Log.v("SDL", "key up: " + keyCode + ", deviceId = " + deviceId + ", source = " + source);
// }
// Dispatch the different events depending on where they come from
// Some SOURCE_JOYSTICK, SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD
// So, we try to process them as JOYSTICK/DPAD/GAMEPAD events first, if that fails we try them as KEYBOARD
//
// Furthermore, it's possible a game controller has SOURCE_KEYBOARD and
// SOURCE_JOYSTICK, while its key events arrive from the keyboard source
// So, retrieve the device itself and check all of its sources
if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) {
// Note that we process events with specific key codes here
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLControllerManager.onNativePadDown(deviceId, keyCode) == 0) {
return true;
}
} else if (event.getAction() == KeyEvent.ACTION_UP) {
if (SDLControllerManager.onNativePadUp(deviceId, keyCode) == 0) {
return true;
}
}
}
if ((source & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (isTextInputEvent(event)) {
if (ic != null) {
ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
} else {
SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);
}
}
onNativeKeyDown(keyCode);
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
onNativeKeyUp(keyCode);
return true;
}
}
if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
// on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses
// they are ignored here because sending them as mouse input to SDL is messy
if ((keyCode == KeyEvent.KEYCODE_BACK) || (keyCode == KeyEvent.KEYCODE_FORWARD)) {
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
case KeyEvent.ACTION_UP:
// mark the event as handled or it will be handled by system
// handling KEYCODE_BACK by system will call onBackPressed()
return true;
}
}
}
return false;
}
/**
* This method is called by SDL using JNI.
*/
@@ -1891,6 +1809,463 @@ class SDLMain implements Runnable {
}
}
/**
SDLSurface. This is what we draw on, so we need to know when it's created
in order to do anything useful.
Because of this, that's where we set up the SDL thread
*/
class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
View.OnKeyListener, View.OnTouchListener, SensorEventListener {
// Sensors
protected SensorManager mSensorManager;
protected Display mDisplay;
// Keep track of the surface size to normalize touch events
protected float mWidth, mHeight;
// Is SurfaceView ready for rendering
public boolean mIsSurfaceReady;
// Startup
public SDLSurface(Context context) {
super(context);
getHolder().addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
setOnKeyListener(this);
setOnTouchListener(this);
mDisplay = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
setOnGenericMotionListener(SDLActivity.getMotionListener());
// Some arbitrary defaults to avoid a potential division by zero
mWidth = 1.0f;
mHeight = 1.0f;
mIsSurfaceReady = false;
}
public void handlePause() {
enableSensor(Sensor.TYPE_ACCELEROMETER, false);
}
public void handleResume() {
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
setOnKeyListener(this);
setOnTouchListener(this);
enableSensor(Sensor.TYPE_ACCELEROMETER, true);
}
public Surface getNativeSurface() {
return getHolder().getSurface();
}
// Called when we have a valid drawing surface
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.v("SDL", "surfaceCreated()");
SDLActivity.onNativeSurfaceCreated();
}
// Called when we lose the surface
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.v("SDL", "surfaceDestroyed()");
// Transition to pause, if needed
SDLActivity.mNextNativeState = SDLActivity.NativeState.PAUSED;
SDLActivity.handleNativeState();
mIsSurfaceReady = false;
SDLActivity.onNativeSurfaceDestroyed();
}
// Called when the surface is resized
@Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
Log.v("SDL", "surfaceChanged()");
if (SDLActivity.mSingleton == null) {
return;
}
mWidth = width;
mHeight = height;
int nDeviceWidth = width;
int nDeviceHeight = height;
try
{
if (Build.VERSION.SDK_INT >= 17) {
DisplayMetrics realMetrics = new DisplayMetrics();
mDisplay.getRealMetrics( realMetrics );
nDeviceWidth = realMetrics.widthPixels;
nDeviceHeight = realMetrics.heightPixels;
}
} catch(Exception ignored) {
}
synchronized(SDLActivity.getContext()) {
// In case we're waiting on a size change after going fullscreen, send a notification.
SDLActivity.getContext().notifyAll();
}
Log.v("SDL", "Window size: " + width + "x" + height);
Log.v("SDL", "Device size: " + nDeviceWidth + "x" + nDeviceHeight);
SDLActivity.nativeSetScreenResolution(width, height, nDeviceWidth, nDeviceHeight, mDisplay.getRefreshRate());
SDLActivity.onNativeResize();
// Prevent a screen distortion glitch,
// for instance when the device is in Landscape and a Portrait App is resumed.
boolean skip = false;
int requestedOrientation = SDLActivity.mSingleton.getRequestedOrientation();
if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
if (mWidth > mHeight) {
skip = true;
}
} else if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
if (mWidth < mHeight) {
skip = true;
}
}
// Special Patch for Square Resolution: Black Berry Passport
if (skip) {
double min = Math.min(mWidth, mHeight);
double max = Math.max(mWidth, mHeight);
if (max / min < 1.20) {
Log.v("SDL", "Don't skip on such aspect-ratio. Could be a square resolution.");
skip = false;
}
}
// Don't skip in MultiWindow.
if (skip) {
if (Build.VERSION.SDK_INT >= 24) {
if (SDLActivity.mSingleton.isInMultiWindowMode()) {
Log.v("SDL", "Don't skip in Multi-Window");
skip = false;
}
}
}
if (skip) {
Log.v("SDL", "Skip .. Surface is not ready.");
mIsSurfaceReady = false;
return;
}
/* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
SDLActivity.onNativeSurfaceChanged();
/* Surface is ready */
mIsSurfaceReady = true;
SDLActivity.mNextNativeState = SDLActivity.NativeState.RESUMED;
SDLActivity.handleNativeState();
}
// Key events
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
int deviceId = event.getDeviceId();
int source = event.getSource();
if (source == InputDevice.SOURCE_UNKNOWN) {
InputDevice device = InputDevice.getDevice(deviceId);
if (device != null) {
source = device.getSources();
}
}
// if (event.getAction() == KeyEvent.ACTION_DOWN) {
// Log.v("SDL", "key down: " + keyCode + ", deviceId = " + deviceId + ", source = " + source);
// } else if (event.getAction() == KeyEvent.ACTION_UP) {
// Log.v("SDL", "key up: " + keyCode + ", deviceId = " + deviceId + ", source = " + source);
// }
// Dispatch the different events depending on where they come from
// Some SOURCE_JOYSTICK, SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD
// So, we try to process them as JOYSTICK/DPAD/GAMEPAD events first, if that fails we try them as KEYBOARD
//
// Furthermore, it's possible a game controller has SOURCE_KEYBOARD and
// SOURCE_JOYSTICK, while its key events arrive from the keyboard source
// So, retrieve the device itself and check all of its sources
if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) {
// Note that we process events with specific key codes here
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLControllerManager.onNativePadDown(deviceId, keyCode) == 0) {
return true;
}
} else if (event.getAction() == KeyEvent.ACTION_UP) {
if (SDLControllerManager.onNativePadUp(deviceId, keyCode) == 0) {
return true;
}
}
}
if ((source & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLActivity.isTextInputEvent(event)) {
SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);
}
SDLActivity.onNativeKeyDown(keyCode);
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
SDLActivity.onNativeKeyUp(keyCode);
return true;
}
}
if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
// on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses
// they are ignored here because sending them as mouse input to SDL is messy
if ((keyCode == KeyEvent.KEYCODE_BACK) || (keyCode == KeyEvent.KEYCODE_FORWARD)) {
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
case KeyEvent.ACTION_UP:
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
SDLActivity.onNativeMouse(MotionEvent.BUTTON_SECONDARY, MotionEvent.ACTION_DOWN, 0, 0, true);
} else if (event.getAction() == KeyEvent.ACTION_UP) {
SDLActivity.onNativeMouse(MotionEvent.BUTTON_SECONDARY, MotionEvent.ACTION_UP, 0, 0, true);
}
}
// mark the event as handled or it will be handled by system
// handling KEYCODE_BACK by system will call onBackPressed()
return true;
}
}
}
return false;
}
// Touch events
@Override
public boolean onTouch(View v, MotionEvent event) {
/* Ref: http://developer.android.com/training/gestures/multi.html */
int touchDevId = event.getDeviceId();
final int pointerCount = event.getPointerCount();
int action = event.getActionMasked();
int pointerFingerId;
int i = -1;
float x,y,p;
/*
* Prevent id to be -1, since it's used in SDL internal for synthetic events
* Appears when using Android emulator, eg:
* adb shell input mouse tap 100 100
* adb shell input touchscreen tap 100 100
*/
if (touchDevId < 0) {
touchDevId -= 1;
}
// 12290 = Samsung DeX mode desktop mouse
// 12290 = 0x3002 = 0x2002 | 0x1002 = SOURCE_MOUSE | SOURCE_TOUCHSCREEN
// 0x2 = SOURCE_CLASS_POINTER
if (event.getSource() == InputDevice.SOURCE_MOUSE || event.getSource() == (InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_TOUCHSCREEN)) {
int mouseButton = 1;
try {
Object object = event.getClass().getMethod("getButtonState").invoke(event);
if (object != null) {
mouseButton = (Integer) object;
}
} catch(Exception ignored) {
}
// We need to check if we're in relative mouse mode and get the axis offset rather than the x/y values
// if we are. We'll leverage our existing mouse motion listener
SDLGenericMotionListener_API12 motionListener = SDLActivity.getMotionListener();
x = motionListener.getEventX(event);
y = motionListener.getEventY(event);
SDLActivity.onNativeMouse(mouseButton, action, x, y, motionListener.inRelativeMode());
} else {
switch(action) {
case MotionEvent.ACTION_MOVE:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
if (p > 1.0f) {
// may be larger than 1.0f on some devices
// see the documentation of getPressure(i)
p = 1.0f;
}
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_DOWN:
// Primary pointer up/down, the index is always zero
i = 0;
/* fallthrough */
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_DOWN:
// Non primary pointer up/down
if (i == -1) {
i = event.getActionIndex();
}
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
if (p > 1.0f) {
// may be larger than 1.0f on some devices
// see the documentation of getPressure(i)
p = 1.0f;
}
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
break;
case MotionEvent.ACTION_CANCEL:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
if (p > 1.0f) {
// may be larger than 1.0f on some devices
// see the documentation of getPressure(i)
p = 1.0f;
}
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p);
}
break;
default:
break;
}
}
return true;
}
// Sensor events
public void enableSensor(int sensortype, boolean enabled) {
// TODO: This uses getDefaultSensor - what if we have >1 accels?
if (enabled) {
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(sensortype),
SensorManager.SENSOR_DELAY_GAME, null);
} else {
mSensorManager.unregisterListener(this,
mSensorManager.getDefaultSensor(sensortype));
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
// Since we may have an orientation set, we won't receive onConfigurationChanged events.
// We thus should check here.
int newOrientation;
float x, y;
switch (mDisplay.getRotation()) {
case Surface.ROTATION_90:
x = -event.values[1];
y = event.values[0];
newOrientation = SDLActivity.SDL_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_270:
x = event.values[1];
y = -event.values[0];
newOrientation = SDLActivity.SDL_ORIENTATION_LANDSCAPE_FLIPPED;
break;
case Surface.ROTATION_180:
x = -event.values[0];
y = -event.values[1];
newOrientation = SDLActivity.SDL_ORIENTATION_PORTRAIT_FLIPPED;
break;
case Surface.ROTATION_0:
default:
x = event.values[0];
y = event.values[1];
newOrientation = SDLActivity.SDL_ORIENTATION_PORTRAIT;
break;
}
if (newOrientation != SDLActivity.mCurrentOrientation) {
SDLActivity.mCurrentOrientation = newOrientation;
SDLActivity.onNativeOrientationChanged(newOrientation);
}
SDLActivity.onNativeAccel(-x / SensorManager.GRAVITY_EARTH,
y / SensorManager.GRAVITY_EARTH,
event.values[2] / SensorManager.GRAVITY_EARTH);
}
}
// Captured pointer events for API 26.
public boolean onCapturedPointerEvent(MotionEvent event)
{
int action = event.getActionMasked();
float x, y;
switch (action) {
case MotionEvent.ACTION_SCROLL:
x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
SDLActivity.onNativeMouse(0, action, x, y, false);
return true;
case MotionEvent.ACTION_HOVER_MOVE:
case MotionEvent.ACTION_MOVE:
x = event.getX(0);
y = event.getY(0);
SDLActivity.onNativeMouse(0, action, x, y, true);
return true;
case MotionEvent.ACTION_BUTTON_PRESS:
case MotionEvent.ACTION_BUTTON_RELEASE:
// Change our action value to what SDL's code expects.
if (action == MotionEvent.ACTION_BUTTON_PRESS) {
action = MotionEvent.ACTION_DOWN;
} else { /* MotionEvent.ACTION_BUTTON_RELEASE */
action = MotionEvent.ACTION_UP;
}
x = event.getX(0);
y = event.getY(0);
int button = event.getButtonState();
SDLActivity.onNativeMouse(button, action, x, y, true);
return true;
}
return false;
}
}
/* This is a fake invisible editor view that receives the input and defines the
* pan&scan region
*/
@@ -1911,7 +2286,21 @@ class DummyEdit extends View implements View.OnKeyListener {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
return SDLActivity.handleKeyEvent(v, keyCode, event, ic);
/*
* This handles the hardware keyboard input
*/
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLActivity.isTextInputEvent(event)) {
ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
return true;
}
SDLActivity.onNativeKeyDown(keyCode);
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
SDLActivity.onNativeKeyUp(keyCode);
return true;
}
return false;
}
//
@@ -1935,10 +2324,9 @@ class DummyEdit extends View implements View.OnKeyListener {
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
ic = new SDLInputConnection(this, true);
outAttrs.inputType = InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_FLAG_MULTI_LINE;
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI |
EditorInfo.IME_FLAG_NO_FULLSCREEN /* API 11 */;
outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
| EditorInfo.IME_FLAG_NO_FULLSCREEN /* API 11 */;
return ic;
}
@@ -1946,17 +2334,9 @@ class DummyEdit extends View implements View.OnKeyListener {
class SDLInputConnection extends BaseInputConnection {
protected EditText mEditText;
protected String mCommittedText = "";
public SDLInputConnection(View targetView, boolean fullEditor) {
super(targetView, fullEditor);
mEditText = new EditText(SDL.getContext());
}
@Override
public Editable getEditable() {
return mEditText.getEditableText();
}
@Override
@@ -1979,84 +2359,79 @@ class SDLInputConnection extends BaseInputConnection {
}
}
return super.sendKeyEvent(event);
}
@Override
public boolean commitText(CharSequence text, int newCursorPosition) {
if (!super.commitText(text, newCursorPosition)) {
return false;
/* Generate backspaces for the text we're going to replace */
final Editable content = getEditable();
if (content != null) {
int a = getComposingSpanStart(content);
int b = getComposingSpanEnd(content);
if (a == -1 || b == -1) {
a = Selection.getSelectionStart(content);
b = Selection.getSelectionEnd(content);
}
if (a < 0) a = 0;
if (b < 0) b = 0;
if (b < a) {
int tmp = a;
a = b;
b = tmp;
}
int backspaces = (b - a);
for (int i = 0; i < backspaces; i++) {
nativeGenerateScancodeForUnichar('\b');
}
}
updateText();
return true;
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (c == '\n') {
if (SDLActivity.onNativeSoftReturnKey()) {
return true;
}
}
nativeGenerateScancodeForUnichar(c);
}
SDLInputConnection.nativeCommitText(text.toString(), newCursorPosition);
return super.commitText(text, newCursorPosition);
}
@Override
public boolean setComposingText(CharSequence text, int newCursorPosition) {
if (!super.setComposingText(text, newCursorPosition)) {
return false;
}
updateText();
return true;
}
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
if (!super.deleteSurroundingText(beforeLength, afterLength)) {
return false;
}
updateText();
return true;
}
nativeSetComposingText(text.toString(), newCursorPosition);
protected void updateText() {
final Editable content = getEditable();
if (content == null) {
return;
}
String text = content.toString();
int compareLength = Math.min(text.length(), mCommittedText.length());
int matchLength, offset;
/* Backspace over characters that are no longer in the string */
for (matchLength = 0; matchLength < compareLength; ) {
int codePoint = mCommittedText.codePointAt(matchLength);
if (codePoint != text.codePointAt(matchLength)) {
break;
}
matchLength += Character.charCount(codePoint);
}
/* FIXME: This doesn't handle graphemes, like '🌬️' */
for (offset = matchLength; offset < mCommittedText.length(); ) {
int codePoint = mCommittedText.codePointAt(offset);
nativeGenerateScancodeForUnichar('\b');
offset += Character.charCount(codePoint);
}
if (matchLength < text.length()) {
String pendingText = text.subSequence(matchLength, text.length()).toString();
for (offset = 0; offset < pendingText.length(); ) {
int codePoint = pendingText.codePointAt(offset);
if (codePoint == '\n') {
if (SDLActivity.onNativeSoftReturnKey()) {
return;
}
}
/* Higher code points don't generate simulated scancodes */
if (codePoint < 128) {
nativeGenerateScancodeForUnichar((char)codePoint);
}
offset += Character.charCount(codePoint);
}
SDLInputConnection.nativeCommitText(pendingText, 0);
}
mCommittedText = text;
return super.setComposingText(text, newCursorPosition);
}
public static native void nativeCommitText(String text, int newCursorPosition);
public static native void nativeGenerateScancodeForUnichar(char c);
public native void nativeGenerateScancodeForUnichar(char c);
public native void nativeSetComposingText(String text, int newCursorPosition);
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
// Workaround to capture backspace key. Ref: http://stackoverflow.com/questions/14560344/android-backspace-in-webview-baseinputconnection
// and https://bugzilla.libsdl.org/show_bug.cgi?id=2265
if (beforeLength > 0 && afterLength == 0) {
// backspace(s)
while (beforeLength-- > 0) {
nativeGenerateScancodeForUnichar('\b');
}
return true;
}
return super.deleteSurroundingText(beforeLength, afterLength);
}
}
class SDLClipboardHandler implements

View File

@@ -1,405 +0,0 @@
package org.libsdl.app;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
/**
SDLSurface. This is what we draw on, so we need to know when it's created
in order to do anything useful.
Because of this, that's where we set up the SDL thread
*/
public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
View.OnKeyListener, View.OnTouchListener, SensorEventListener {
// Sensors
protected SensorManager mSensorManager;
protected Display mDisplay;
// Keep track of the surface size to normalize touch events
protected float mWidth, mHeight;
// Is SurfaceView ready for rendering
public boolean mIsSurfaceReady;
// Startup
public SDLSurface(Context context) {
super(context);
getHolder().addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
setOnKeyListener(this);
setOnTouchListener(this);
mDisplay = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
setOnGenericMotionListener(SDLActivity.getMotionListener());
// Some arbitrary defaults to avoid a potential division by zero
mWidth = 1.0f;
mHeight = 1.0f;
mIsSurfaceReady = false;
}
public void handlePause() {
enableSensor(Sensor.TYPE_ACCELEROMETER, false);
}
public void handleResume() {
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
setOnKeyListener(this);
setOnTouchListener(this);
enableSensor(Sensor.TYPE_ACCELEROMETER, true);
}
public Surface getNativeSurface() {
return getHolder().getSurface();
}
// Called when we have a valid drawing surface
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.v("SDL", "surfaceCreated()");
SDLActivity.onNativeSurfaceCreated();
}
// Called when we lose the surface
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.v("SDL", "surfaceDestroyed()");
// Transition to pause, if needed
SDLActivity.mNextNativeState = SDLActivity.NativeState.PAUSED;
SDLActivity.handleNativeState();
mIsSurfaceReady = false;
SDLActivity.onNativeSurfaceDestroyed();
}
// Called when the surface is resized
@Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
Log.v("SDL", "surfaceChanged()");
if (SDLActivity.mSingleton == null) {
return;
}
mWidth = width;
mHeight = height;
int nDeviceWidth = width;
int nDeviceHeight = height;
try
{
if (Build.VERSION.SDK_INT >= 17) {
DisplayMetrics realMetrics = new DisplayMetrics();
mDisplay.getRealMetrics( realMetrics );
nDeviceWidth = realMetrics.widthPixels;
nDeviceHeight = realMetrics.heightPixels;
}
} catch(Exception ignored) {
}
synchronized(SDLActivity.getContext()) {
// In case we're waiting on a size change after going fullscreen, send a notification.
SDLActivity.getContext().notifyAll();
}
Log.v("SDL", "Window size: " + width + "x" + height);
Log.v("SDL", "Device size: " + nDeviceWidth + "x" + nDeviceHeight);
SDLActivity.nativeSetScreenResolution(width, height, nDeviceWidth, nDeviceHeight, mDisplay.getRefreshRate());
SDLActivity.onNativeResize();
// Prevent a screen distortion glitch,
// for instance when the device is in Landscape and a Portrait App is resumed.
boolean skip = false;
int requestedOrientation = SDLActivity.mSingleton.getRequestedOrientation();
if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
if (mWidth > mHeight) {
skip = true;
}
} else if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
if (mWidth < mHeight) {
skip = true;
}
}
// Special Patch for Square Resolution: Black Berry Passport
if (skip) {
double min = Math.min(mWidth, mHeight);
double max = Math.max(mWidth, mHeight);
if (max / min < 1.20) {
Log.v("SDL", "Don't skip on such aspect-ratio. Could be a square resolution.");
skip = false;
}
}
// Don't skip in MultiWindow.
if (skip) {
if (Build.VERSION.SDK_INT >= 24) {
if (SDLActivity.mSingleton.isInMultiWindowMode()) {
Log.v("SDL", "Don't skip in Multi-Window");
skip = false;
}
}
}
if (skip) {
Log.v("SDL", "Skip .. Surface is not ready.");
mIsSurfaceReady = false;
return;
}
/* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
SDLActivity.onNativeSurfaceChanged();
/* Surface is ready */
mIsSurfaceReady = true;
SDLActivity.mNextNativeState = SDLActivity.NativeState.RESUMED;
SDLActivity.handleNativeState();
}
// Key events
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
return SDLActivity.handleKeyEvent(v, keyCode, event, null);
}
// Touch events
@Override
public boolean onTouch(View v, MotionEvent event) {
/* Ref: http://developer.android.com/training/gestures/multi.html */
int touchDevId = event.getDeviceId();
final int pointerCount = event.getPointerCount();
int action = event.getActionMasked();
int pointerFingerId;
int i = -1;
float x,y,p;
/*
* Prevent id to be -1, since it's used in SDL internal for synthetic events
* Appears when using Android emulator, eg:
* adb shell input mouse tap 100 100
* adb shell input touchscreen tap 100 100
*/
if (touchDevId < 0) {
touchDevId -= 1;
}
// 12290 = Samsung DeX mode desktop mouse
// 12290 = 0x3002 = 0x2002 | 0x1002 = SOURCE_MOUSE | SOURCE_TOUCHSCREEN
// 0x2 = SOURCE_CLASS_POINTER
if (event.getSource() == InputDevice.SOURCE_MOUSE || event.getSource() == (InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_TOUCHSCREEN)) {
int mouseButton = 1;
try {
Object object = event.getClass().getMethod("getButtonState").invoke(event);
if (object != null) {
mouseButton = (Integer) object;
}
} catch(Exception ignored) {
}
// We need to check if we're in relative mouse mode and get the axis offset rather than the x/y values
// if we are. We'll leverage our existing mouse motion listener
SDLGenericMotionListener_API12 motionListener = SDLActivity.getMotionListener();
x = motionListener.getEventX(event);
y = motionListener.getEventY(event);
SDLActivity.onNativeMouse(mouseButton, action, x, y, motionListener.inRelativeMode());
} else {
switch(action) {
case MotionEvent.ACTION_MOVE:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
if (p > 1.0f) {
// may be larger than 1.0f on some devices
// see the documentation of getPressure(i)
p = 1.0f;
}
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_DOWN:
// Primary pointer up/down, the index is always zero
i = 0;
/* fallthrough */
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_DOWN:
// Non primary pointer up/down
if (i == -1) {
i = event.getActionIndex();
}
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
if (p > 1.0f) {
// may be larger than 1.0f on some devices
// see the documentation of getPressure(i)
p = 1.0f;
}
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
break;
case MotionEvent.ACTION_CANCEL:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
if (p > 1.0f) {
// may be larger than 1.0f on some devices
// see the documentation of getPressure(i)
p = 1.0f;
}
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p);
}
break;
default:
break;
}
}
return true;
}
// Sensor events
public void enableSensor(int sensortype, boolean enabled) {
// TODO: This uses getDefaultSensor - what if we have >1 accels?
if (enabled) {
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(sensortype),
SensorManager.SENSOR_DELAY_GAME, null);
} else {
mSensorManager.unregisterListener(this,
mSensorManager.getDefaultSensor(sensortype));
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
// Since we may have an orientation set, we won't receive onConfigurationChanged events.
// We thus should check here.
int newOrientation;
float x, y;
switch (mDisplay.getRotation()) {
case Surface.ROTATION_90:
x = -event.values[1];
y = event.values[0];
newOrientation = SDLActivity.SDL_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_270:
x = event.values[1];
y = -event.values[0];
newOrientation = SDLActivity.SDL_ORIENTATION_LANDSCAPE_FLIPPED;
break;
case Surface.ROTATION_180:
x = -event.values[0];
y = -event.values[1];
newOrientation = SDLActivity.SDL_ORIENTATION_PORTRAIT_FLIPPED;
break;
case Surface.ROTATION_0:
default:
x = event.values[0];
y = event.values[1];
newOrientation = SDLActivity.SDL_ORIENTATION_PORTRAIT;
break;
}
if (newOrientation != SDLActivity.mCurrentOrientation) {
SDLActivity.mCurrentOrientation = newOrientation;
SDLActivity.onNativeOrientationChanged(newOrientation);
}
SDLActivity.onNativeAccel(-x / SensorManager.GRAVITY_EARTH,
y / SensorManager.GRAVITY_EARTH,
event.values[2] / SensorManager.GRAVITY_EARTH);
}
}
// Captured pointer events for API 26.
public boolean onCapturedPointerEvent(MotionEvent event)
{
int action = event.getActionMasked();
float x, y;
switch (action) {
case MotionEvent.ACTION_SCROLL:
x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
SDLActivity.onNativeMouse(0, action, x, y, false);
return true;
case MotionEvent.ACTION_HOVER_MOVE:
case MotionEvent.ACTION_MOVE:
x = event.getX(0);
y = event.getY(0);
SDLActivity.onNativeMouse(0, action, x, y, true);
return true;
case MotionEvent.ACTION_BUTTON_PRESS:
case MotionEvent.ACTION_BUTTON_RELEASE:
// Change our action value to what SDL's code expects.
if (action == MotionEvent.ACTION_BUTTON_PRESS) {
action = MotionEvent.ACTION_DOWN;
} else { /* MotionEvent.ACTION_BUTTON_RELEASE */
action = MotionEvent.ACTION_UP;
}
x = event.getX(0);
y = event.getY(0);
int button = event.getButtonState();
SDLActivity.onNativeMouse(button, action, x, y, true);
return true;
}
return false;
}
}

178
os/android/gradlew.bat vendored
View File

@@ -1,89 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1009 KiB

View File

@@ -1,14 +0,0 @@
{
"images" : [
{
"filename" : "AppIcon.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -1,6 +0,0 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>${MACOSX_BUNDLE_DISPLAY_NAME}</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>LSMinimumSystemVersion</key>
<string>11.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>NSHighResolutionCapable</key>
<string>True</string>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiresFullScreen</key>
<true/>
<key>UIStatusBarHidden</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21225" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="834" height="1194"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>${MACOSX_BUNDLE_DISPLAY_NAME}</string>
<key>CFBundleExecutable</key>
@@ -28,8 +28,6 @@
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>NSHighResolutionCapable</key>
<string>True</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.role-playing-games</string>
<key>LSMinimumSystemVersion</key>
<string>10.11</string>
<key>SDL_FILESYSTEM_BASE_DIR_TYPE</key>

File diff suppressed because it is too large Load Diff

View File

@@ -6,8 +6,6 @@
namespace fallout {
extern int rotation;
int _action_attack(Attack* attack);
int _action_use_an_item_on_object(Object* a1, Object* a2, Object* a3);
int _action_use_an_object(Object* a1, Object* a2);
@@ -15,10 +13,10 @@ int actionPickUp(Object* critter, Object* item);
int _action_loot_container(Object* critter, Object* container);
int _action_skill_use(int a1);
int actionUseSkill(Object* a1, Object* a2, int skill);
bool _is_hit_from_front(Object* attacker, Object* defender);
bool _is_hit_from_front(Object* a1, Object* a2);
bool _can_see(Object* a1, Object* a2);
bool _action_explode_running();
int actionExplode(int tile, int elevation, int minDamage, int maxDamage, Object* sourceObj, bool animate);
int actionExplode(int tile, int elevation, int minDamage, int maxDamage, Object* a5, bool a6);
int actionTalk(Object* a1, Object* a2);
void actionDamage(int tile, int elevation, int minDamage, int maxDamage, int damageType, bool animated, bool bypassArmor);
bool actionCheckPush(Object* a1, Object* a2);

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@ typedef enum AnimationRequestOptions {
ANIMATION_REQUEST_UNRESERVED = 0x01,
ANIMATION_REQUEST_RESERVED = 0x02,
ANIMATION_REQUEST_NO_STAND = 0x04,
ANIMATION_REQUEST_PING = 0x100,
ANIMATION_REQUEST_0x100 = 0x100,
ANIMATION_REQUEST_INSIGNIFICANT = 0x200,
} AnimationRequestOptions;
@@ -100,12 +100,12 @@ typedef int(AnimationCallback)(void* a1, void* a2);
// Signature of animation callback accepting 3 parameters.
typedef int(AnimationCallback3)(void* a1, void* a2, void* a3);
typedef struct StraightPathNode {
typedef struct STRUCT_530014_28 {
int tile;
int elevation;
int x;
int y;
} StraightPathNode;
} STRUCT_530014_28;
typedef Object* PathBuilderCallback(Object* object, int tile, int elevation);
@@ -142,15 +142,15 @@ int animationRegisterSetLightDistance(Object* owner, int lightDistance, int dela
int animationRegisterToggleOutline(Object* object, bool outline, int delay);
int animationRegisterPlaySoundEffect(Object* owner, const char* soundEffectName, int delay);
int animationRegisterAnimateForever(Object* owner, int anim, int delay);
int animationRegisterPing(int flags, int delay);
int reg_anim_26(int a1, int a2);
int _make_path(Object* object, int from, int to, unsigned char* a4, int a5);
int pathfinderFindPath(Object* object, int from, int to, unsigned char* rotations, int a5, PathBuilderCallback* callback);
int _make_straight_path(Object* object, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6);
int _make_straight_path_func(Object* object, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6, PathBuilderCallback* callback);
int _make_straight_path(Object* a1, int from, int to, STRUCT_530014_28* pathNodes, Object** a5, int a6);
int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4, Object** a5, int a6, Object* (*a7)(Object*, int, int));
void _object_animate();
int _check_move(int* actionPointsPtr);
int _dude_move(int actionPoints);
int _dude_run(int actionPoints);
int _check_move(int* a1);
int _dude_move(int a1);
int _dude_run(int a1);
void _dude_fidget();
void _dude_stand(Object* obj, int rotation, int fid);
void _dude_standup(Object* a1);

View File

@@ -8,10 +8,10 @@
#include "debug.h"
#include "draw.h"
#include "game.h"
#include "game_config.h"
#include "memory.h"
#include "object.h"
#include "proto.h"
#include "settings.h"
#include "sfall_config.h"
namespace fallout {
@@ -34,10 +34,8 @@ static int artReadList(const char* path, char** out_arr, int* out_count);
static int artCacheGetFileSizeImpl(int a1, int* out_size);
static int artCacheReadDataImpl(int a1, int* a2, unsigned char* data);
static void artCacheFreeImpl(void* ptr);
static int artReadFrameData(unsigned char* data, File* stream, int count, int* paddingPtr);
static int artReadFrameData(unsigned char* data, File* stream, int count);
static int artReadHeader(Art* art, File* stream);
static int artGetDataSize(Art* art);
static int paddingForSize(int size);
// 0x5002D8
static char gDefaultJumpsuitMaleFileName[] = "hmjmps";
@@ -53,17 +51,17 @@ static char gDefaultTribalFemaleFileName[] = "hfprim";
// 0x510738
static ArtListDescription gArtListDescriptions[OBJ_TYPE_COUNT] = {
{ 0, "items", nullptr, nullptr, 0 },
{ 0, "critters", nullptr, nullptr, 0 },
{ 0, "scenery", nullptr, nullptr, 0 },
{ 0, "walls", nullptr, nullptr, 0 },
{ 0, "tiles", nullptr, nullptr, 0 },
{ 0, "misc", nullptr, nullptr, 0 },
{ 0, "intrface", nullptr, nullptr, 0 },
{ 0, "inven", nullptr, nullptr, 0 },
{ 0, "heads", nullptr, nullptr, 0 },
{ 0, "backgrnd", nullptr, nullptr, 0 },
{ 0, "skilldex", nullptr, nullptr, 0 },
{ 0, "items", 0, 0, 0 },
{ 0, "critters", 0, 0, 0 },
{ 0, "scenery", 0, 0, 0 },
{ 0, "walls", 0, 0, 0 },
{ 0, "tiles", 0, 0, 0 },
{ 0, "misc", 0, 0, 0 },
{ 0, "intrface", 0, 0, 0 },
{ 0, "inven", 0, 0, 0 },
{ 0, "heads", 0, 0, 0 },
{ 0, "backgrnd", 0, 0, 0 },
{ 0, "skilldex", 0, 0, 0 },
};
// This flag denotes that localized arts should be looked up first. Used
@@ -134,14 +132,18 @@ int artInit()
File* stream;
char string[200];
int cacheSize = settings.system.art_cache_size;
int cacheSize;
if (!configGetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_ART_CACHE_SIZE_KEY, &cacheSize)) {
cacheSize = 8;
}
if (!cacheInit(&gArtCache, artCacheGetFileSizeImpl, artCacheReadDataImpl, artCacheFreeImpl, cacheSize << 20)) {
debugPrint("cache_init failed in art_init\n");
return -1;
}
const char* language = settings.system.language.c_str();
if (compat_stricmp(language, ENGLISH) != 0) {
char* language;
if (configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_LANGUAGE_KEY, &language) && compat_stricmp(language, ENGLISH) != 0) {
strcpy(gArtLanguage, language);
gArtLanguageInitialized = true;
}
@@ -149,17 +151,32 @@ int artInit()
bool critterDbSelected = false;
for (int objectType = 0; objectType < OBJ_TYPE_COUNT; objectType++) {
gArtListDescriptions[objectType].flags = 0;
snprintf(path, sizeof(path), "%s%s%s\\%s.lst", _cd_path_base, "art\\", gArtListDescriptions[objectType].name, gArtListDescriptions[objectType].name);
sprintf(path, "%s%s%s\\%s.lst", _cd_path_base, "art\\", gArtListDescriptions[objectType].name, gArtListDescriptions[objectType].name);
int oldDb;
if (objectType == OBJ_TYPE_CRITTER) {
oldDb = _db_current();
critterDbSelected = true;
_db_select(_critter_db_handle);
}
if (artReadList(path, &(gArtListDescriptions[objectType].fileNames), &(gArtListDescriptions[objectType].fileNamesLength)) != 0) {
debugPrint("art_read_lst failed in art_init\n");
if (critterDbSelected) {
_db_select(oldDb);
}
cacheFree(&gArtCache);
return -1;
}
if (objectType == OBJ_TYPE_CRITTER) {
critterDbSelected = false;
_db_select(oldDb);
}
}
_anon_alias = (int*)internal_malloc(sizeof(*_anon_alias) * gArtListDescriptions[OBJ_TYPE_CRITTER].fileNamesLength);
if (_anon_alias == nullptr) {
if (_anon_alias == NULL) {
gArtListDescriptions[OBJ_TYPE_CRITTER].fileNamesLength = 0;
debugPrint("Out of memory for anon_alias in art_init\n");
cacheFree(&gArtCache);
@@ -167,7 +184,7 @@ int artInit()
}
gArtCritterFidShoudRunData = (int*)internal_malloc(sizeof(*gArtCritterFidShoudRunData) * gArtListDescriptions[1].fileNamesLength);
if (gArtCritterFidShoudRunData == nullptr) {
if (gArtCritterFidShoudRunData == NULL) {
gArtListDescriptions[OBJ_TYPE_CRITTER].fileNamesLength = 0;
debugPrint("Out of memory for artCritterFidShouldRunData in art_init\n");
cacheFree(&gArtCache);
@@ -178,52 +195,52 @@ int artInit()
gArtCritterFidShoudRunData[critterIndex] = 0;
}
snprintf(path, sizeof(path), "%s%s%s\\%s.lst", _cd_path_base, "art\\", gArtListDescriptions[OBJ_TYPE_CRITTER].name, gArtListDescriptions[OBJ_TYPE_CRITTER].name);
sprintf(path, "%s%s%s\\%s.lst", _cd_path_base, "art\\", gArtListDescriptions[OBJ_TYPE_CRITTER].name, gArtListDescriptions[OBJ_TYPE_CRITTER].name);
stream = fileOpen(path, "rt");
if (stream == nullptr) {
if (stream == NULL) {
debugPrint("Unable to open %s in art_init\n", path);
cacheFree(&gArtCache);
return -1;
}
// SFALL: Modify player model settings.
char* jumpsuitMaleFileName = nullptr;
char* jumpsuitMaleFileName = NULL;
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DUDE_NATIVE_LOOK_JUMPSUIT_MALE_KEY, &jumpsuitMaleFileName);
if (jumpsuitMaleFileName == nullptr || jumpsuitMaleFileName[0] == '\0') {
if (jumpsuitMaleFileName == NULL || jumpsuitMaleFileName[0] == '\0') {
jumpsuitMaleFileName = gDefaultJumpsuitMaleFileName;
}
char* jumpsuitFemaleFileName = nullptr;
char* jumpsuitFemaleFileName = NULL;
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DUDE_NATIVE_LOOK_JUMPSUIT_FEMALE_KEY, &jumpsuitFemaleFileName);
if (jumpsuitFemaleFileName == nullptr || jumpsuitFemaleFileName[0] == '\0') {
if (jumpsuitFemaleFileName == NULL || jumpsuitFemaleFileName[0] == '\0') {
jumpsuitFemaleFileName = gDefaultJumpsuitFemaleFileName;
}
char* tribalMaleFileName = nullptr;
char* tribalMaleFileName = NULL;
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DUDE_NATIVE_LOOK_TRIBAL_MALE_KEY, &tribalMaleFileName);
if (tribalMaleFileName == nullptr || tribalMaleFileName[0] == '\0') {
if (tribalMaleFileName == NULL || tribalMaleFileName[0] == '\0') {
tribalMaleFileName = gDefaultTribalMaleFileName;
}
char* tribalFemaleFileName = nullptr;
char* tribalFemaleFileName = NULL;
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DUDE_NATIVE_LOOK_TRIBAL_FEMALE_KEY, &tribalFemaleFileName);
if (tribalFemaleFileName == nullptr || tribalFemaleFileName[0] == '\0') {
if (tribalFemaleFileName == NULL || tribalFemaleFileName[0] == '\0') {
tribalFemaleFileName = gDefaultTribalFemaleFileName;
}
char* critterFileNames = gArtListDescriptions[OBJ_TYPE_CRITTER].fileNames;
for (int critterIndex = 0; critterIndex < gArtListDescriptions[OBJ_TYPE_CRITTER].fileNamesLength; critterIndex++) {
if (compat_stricmp(critterFileNames, jumpsuitMaleFileName) == 0) {
if (compat_stricmp(critterFileNames, "hmjmps") == 0) {
_art_vault_person_nums[DUDE_NATIVE_LOOK_JUMPSUIT][GENDER_MALE] = critterIndex;
} else if (compat_stricmp(critterFileNames, jumpsuitFemaleFileName) == 0) {
} else if (compat_stricmp(critterFileNames, "hfjmps") == 0) {
_art_vault_person_nums[DUDE_NATIVE_LOOK_JUMPSUIT][GENDER_FEMALE] = critterIndex;
}
if (compat_stricmp(critterFileNames, tribalMaleFileName) == 0) {
if (compat_stricmp(critterFileNames, "hmwarr") == 0) {
_art_vault_person_nums[DUDE_NATIVE_LOOK_TRIBAL][GENDER_MALE] = critterIndex;
_art_vault_guy_num = critterIndex;
} else if (compat_stricmp(critterFileNames, tribalFemaleFileName) == 0) {
} else if (compat_stricmp(critterFileNames, "hfprim") == 0) {
_art_vault_person_nums[DUDE_NATIVE_LOOK_TRIBAL][GENDER_FEMALE] = critterIndex;
}
@@ -236,11 +253,11 @@ int artInit()
}
char* sep1 = strchr(string, ',');
if (sep1 != nullptr) {
if (sep1 != NULL) {
_anon_alias[critterIndex] = atoi(sep1 + 1);
char* sep2 = strchr(sep1 + 1, ',');
if (sep2 != nullptr) {
if (sep2 != NULL) {
gArtCritterFidShoudRunData[critterIndex] = atoi(sep2 + 1);
} else {
gArtCritterFidShoudRunData[critterIndex] = 0;
@@ -262,17 +279,17 @@ int artInit()
}
gHeadDescriptions = (HeadDescription*)internal_malloc(sizeof(*gHeadDescriptions) * gArtListDescriptions[OBJ_TYPE_HEAD].fileNamesLength);
if (gHeadDescriptions == nullptr) {
if (gHeadDescriptions == NULL) {
gArtListDescriptions[OBJ_TYPE_HEAD].fileNamesLength = 0;
debugPrint("Out of memory for head_info in art_init\n");
cacheFree(&gArtCache);
return -1;
}
snprintf(path, sizeof(path), "%s%s%s\\%s.lst", _cd_path_base, "art\\", gArtListDescriptions[OBJ_TYPE_HEAD].name, gArtListDescriptions[OBJ_TYPE_HEAD].name);
sprintf(path, "%s%s%s\\%s.lst", _cd_path_base, "art\\", gArtListDescriptions[OBJ_TYPE_HEAD].name, gArtListDescriptions[OBJ_TYPE_HEAD].name);
stream = fileOpen(path, "rt");
if (stream == nullptr) {
if (stream == NULL) {
debugPrint("Unable to open %s in art_init\n", path);
cacheFree(&gArtCache);
return -1;
@@ -284,14 +301,14 @@ int artInit()
}
char* sep1 = strchr(string, ',');
if (sep1 != nullptr) {
if (sep1 != NULL) {
*sep1 = '\0';
} else {
sep1 = string;
}
char* sep2 = strchr(sep1, ',');
if (sep2 != nullptr) {
if (sep2 != NULL) {
*sep2 = '\0';
} else {
sep2 = sep1;
@@ -300,7 +317,7 @@ int artInit()
gHeadDescriptions[headIndex].goodFidgetCount = atoi(sep1 + 1);
char* sep3 = strchr(sep2, ',');
if (sep3 != nullptr) {
if (sep3 != NULL) {
*sep3 = '\0';
} else {
sep3 = sep2;
@@ -309,7 +326,7 @@ int artInit()
gHeadDescriptions[headIndex].neutralFidgetCount = atoi(sep2 + 1);
char* sep4 = strpbrk(sep3 + 1, " ,;\t\n");
if (sep4 != nullptr) {
if (sep4 != NULL) {
*sep4 = '\0';
}
@@ -336,10 +353,10 @@ void artExit()
for (int index = 0; index < OBJ_TYPE_COUNT; index++) {
internal_free(gArtListDescriptions[index].fileNames);
gArtListDescriptions[index].fileNames = nullptr;
gArtListDescriptions[index].fileNames = NULL;
internal_free(gArtListDescriptions[index].field_18);
gArtListDescriptions[index].field_18 = nullptr;
gArtListDescriptions[index].field_18 = NULL;
}
internal_free(gHeadDescriptions);
@@ -348,7 +365,7 @@ void artExit()
// 0x418F1C
char* artGetObjectTypeName(int objectType)
{
return objectType >= OBJ_TYPE_ITEM && objectType < OBJ_TYPE_COUNT ? gArtListDescriptions[objectType].name : nullptr;
return objectType >= OBJ_TYPE_ITEM && objectType < OBJ_TYPE_COUNT ? gArtListDescriptions[objectType].name : NULL;
}
// 0x418F34
@@ -396,7 +413,7 @@ void artRender(int fid, unsigned char* dest, int width, int height, int pitch)
CacheEntry* handle;
Art* frm = artLock(fid, &handle);
if (frm == nullptr) {
if (frm == NULL) {
return;
}
@@ -438,22 +455,14 @@ void artRender(int fid, unsigned char* dest, int width, int height, int pitch)
artUnlock(handle);
}
// mapper2.exe: 0x40A03C
int art_list_str(int fid, char* name)
{
// TODO: Incomplete.
return -1;
}
// 0x419160
Art* artLock(int fid, CacheEntry** handlePtr)
{
if (handlePtr == nullptr) {
return nullptr;
if (handlePtr == NULL) {
return NULL;
}
Art* art = nullptr;
Art* art = NULL;
cacheLock(&gArtCache, fid, (void**)&art, handlePtr);
return art;
}
@@ -464,44 +473,44 @@ unsigned char* artLockFrameData(int fid, int frame, int direction, CacheEntry**
Art* art;
ArtFrame* frm;
art = nullptr;
art = NULL;
if (handlePtr) {
cacheLock(&gArtCache, fid, (void**)&art, handlePtr);
}
if (art != nullptr) {
if (art != NULL) {
frm = artGetFrame(art, frame, direction);
if (frm != nullptr) {
if (frm != NULL) {
return (unsigned char*)frm + sizeof(*frm);
}
}
return nullptr;
return NULL;
}
// 0x4191CC
unsigned char* artLockFrameDataReturningSize(int fid, CacheEntry** handlePtr, int* widthPtr, int* heightPtr)
{
*handlePtr = nullptr;
*handlePtr = NULL;
Art* art = nullptr;
Art* art;
cacheLock(&gArtCache, fid, (void**)&art, handlePtr);
if (art == nullptr) {
return nullptr;
if (art == NULL) {
return NULL;
}
// NOTE: Uninline.
*widthPtr = artGetWidth(art, 0, 0);
if (*widthPtr == -1) {
return nullptr;
return NULL;
}
// NOTE: Uninline.
*heightPtr = artGetHeight(art, 0, 0);
if (*heightPtr == -1) {
return nullptr;
return NULL;
}
// NOTE: Uninline.
@@ -525,7 +534,7 @@ int artCopyFileName(int objectType, int id, char* dest)
{
ArtListDescription* ptr;
if (objectType < OBJ_TYPE_ITEM || objectType >= OBJ_TYPE_COUNT) {
if (objectType < OBJ_TYPE_ITEM && objectType >= OBJ_TYPE_COUNT) {
return -1;
}
@@ -633,34 +642,34 @@ char* artBuildFilePath(int fid)
v5 = (v2 & 0xF000) >> 12;
type = FID_TYPE(v2);
if (type < OBJ_TYPE_ITEM || type >= OBJ_TYPE_COUNT) {
return nullptr;
if (v3 >= gArtListDescriptions[type].fileNamesLength) {
return NULL;
}
if (v3 >= gArtListDescriptions[type].fileNamesLength) {
return nullptr;
if (type < OBJ_TYPE_ITEM || type >= OBJ_TYPE_COUNT) {
return NULL;
}
v8 = v3 * 13;
if (type == 1) {
if (_art_get_code(v4, v5, &v11, &v12) == -1) {
return nullptr;
return NULL;
}
if (v10) {
snprintf(_art_name, sizeof(_art_name), "%s%s%s\\%s%c%c.fr%c", _cd_path_base, "art\\", gArtListDescriptions[1].name, gArtListDescriptions[1].fileNames + v8, v11, v12, v10 + 47);
sprintf(_art_name, "%s%s%s\\%s%c%c.fr%c", _cd_path_base, "art\\", gArtListDescriptions[1].name, gArtListDescriptions[1].fileNames + v8, v11, v12, v10 + 47);
} else {
snprintf(_art_name, sizeof(_art_name), "%s%s%s\\%s%c%c.frm", _cd_path_base, "art\\", gArtListDescriptions[1].name, gArtListDescriptions[1].fileNames + v8, v11, v12);
sprintf(_art_name, "%s%s%s\\%s%c%c.frm", _cd_path_base, "art\\", gArtListDescriptions[1].name, gArtListDescriptions[1].fileNames + v8, v11, v12);
}
} else if (type == 8) {
v9 = _head2[v4];
if (v9 == 'f') {
snprintf(_art_name, sizeof(_art_name), "%s%s%s\\%s%c%c%d.frm", _cd_path_base, "art\\", gArtListDescriptions[8].name, gArtListDescriptions[8].fileNames + v8, _head1[v4], 102, v5);
sprintf(_art_name, "%s%s%s\\%s%c%c%d.frm", _cd_path_base, "art\\", gArtListDescriptions[8].name, gArtListDescriptions[8].fileNames + v8, _head1[v4], 102, v5);
} else {
snprintf(_art_name, sizeof(_art_name), "%s%s%s\\%s%c%c.frm", _cd_path_base, "art\\", gArtListDescriptions[8].name, gArtListDescriptions[8].fileNames + v8, _head1[v4], v9);
sprintf(_art_name, "%s%s%s\\%s%c%c.frm", _cd_path_base, "art\\", gArtListDescriptions[8].name, gArtListDescriptions[8].fileNames + v8, _head1[v4], v9);
}
} else {
snprintf(_art_name, sizeof(_art_name), "%s%s%s\\%s", _cd_path_base, "art\\", gArtListDescriptions[type].name, gArtListDescriptions[type].fileNames + v8);
sprintf(_art_name, "%s%s%s\\%s", _cd_path_base, "art\\", gArtListDescriptions[type].name, gArtListDescriptions[type].fileNames + v8);
}
return _art_name;
@@ -671,7 +680,7 @@ char* artBuildFilePath(int fid)
static int artReadList(const char* path, char** artListPtr, int* artListSizePtr)
{
File* stream = fileOpen(path, "rt");
if (stream == nullptr) {
if (stream == NULL) {
return -1;
}
@@ -687,14 +696,14 @@ static int artReadList(const char* path, char** artListPtr, int* artListSizePtr)
char* artList = (char*)internal_malloc(13 * count);
*artListPtr = artList;
if (artList == nullptr) {
if (artList == NULL) {
fileClose(stream);
return -1;
}
while (fileReadString(string, sizeof(string), stream)) {
char* brk = strpbrk(string, " ,;\r\t\n");
if (brk != nullptr) {
if (brk != NULL) {
*brk = '\0';
}
@@ -712,7 +721,7 @@ static int artReadList(const char* path, char** artListPtr, int* artListSizePtr)
// 0x419760
int artGetFramesPerSecond(Art* art)
{
if (art == nullptr) {
if (art == NULL) {
return 10;
}
@@ -722,13 +731,13 @@ int artGetFramesPerSecond(Art* art)
// 0x419778
int artGetActionFrame(Art* art)
{
return art == nullptr ? -1 : art->actionFrame;
return art == NULL ? -1 : art->actionFrame;
}
// 0x41978C
int artGetFrameCount(Art* art)
{
return art == nullptr ? -1 : art->frameCount;
return art == NULL ? -1 : art->frameCount;
}
// 0x4197A0
@@ -737,7 +746,7 @@ int artGetWidth(Art* art, int frame, int direction)
ArtFrame* frm;
frm = artGetFrame(art, frame, direction);
if (frm == nullptr) {
if (frm == NULL) {
return -1;
}
@@ -750,7 +759,7 @@ int artGetHeight(Art* art, int frame, int direction)
ArtFrame* frm;
frm = artGetFrame(art, frame, direction);
if (frm == nullptr) {
if (frm == NULL) {
return -1;
}
@@ -763,23 +772,23 @@ int artGetSize(Art* art, int frame, int direction, int* widthPtr, int* heightPtr
ArtFrame* frm;
frm = artGetFrame(art, frame, direction);
if (frm == nullptr) {
if (widthPtr != nullptr) {
if (frm == NULL) {
if (widthPtr != NULL) {
*widthPtr = 0;
}
if (heightPtr != nullptr) {
if (heightPtr != NULL) {
*heightPtr = 0;
}
return -1;
}
if (widthPtr != nullptr) {
if (widthPtr != NULL) {
*widthPtr = frm->width;
}
if (heightPtr != nullptr) {
if (heightPtr != NULL) {
*heightPtr = frm->height;
}
@@ -792,7 +801,7 @@ int artGetFrameOffsets(Art* art, int frame, int direction, int* xPtr, int* yPtr)
ArtFrame* frm;
frm = artGetFrame(art, frame, direction);
if (frm == nullptr) {
if (frm == NULL) {
return -1;
}
@@ -805,7 +814,7 @@ int artGetFrameOffsets(Art* art, int frame, int direction, int* xPtr, int* yPtr)
// 0x41984C
int artGetRotationOffsets(Art* art, int rotation, int* xPtr, int* yPtr)
{
if (art == nullptr) {
if (art == NULL) {
return -1;
}
@@ -821,8 +830,8 @@ unsigned char* artGetFrameData(Art* art, int frame, int direction)
ArtFrame* frm;
frm = artGetFrame(art, frame, direction);
if (frm == nullptr) {
return nullptr;
if (frm == NULL) {
return NULL;
}
return (unsigned char*)frm + sizeof(*frm);
@@ -832,20 +841,20 @@ unsigned char* artGetFrameData(Art* art, int frame, int direction)
ArtFrame* artGetFrame(Art* art, int frame, int rotation)
{
if (rotation < 0 || rotation >= 6) {
return nullptr;
return NULL;
}
if (art == nullptr) {
return nullptr;
if (art == NULL) {
return NULL;
}
if (frame < 0 || frame >= art->frameCount) {
return nullptr;
return NULL;
}
ArtFrame* frm = (ArtFrame*)((unsigned char*)art + sizeof(*art) + art->dataOffsets[rotation] + art->padding[rotation]);
ArtFrame* frm = (ArtFrame*)((unsigned char*)art + sizeof(*art) + art->dataOffsets[rotation]);
for (int index = 0; index < frame; index++) {
frm = (ArtFrame*)((unsigned char*)frm + sizeof(*frm) + frm->size + paddingForSize(frm->size));
frm = (ArtFrame*)((unsigned char*)frm + sizeof(*frm) + frm->size);
}
return frm;
}
@@ -854,15 +863,25 @@ ArtFrame* artGetFrame(Art* art, int frame, int rotation)
bool artExists(int fid)
{
bool result = false;
int oldDb = -1;
if (FID_TYPE(fid) == OBJ_TYPE_CRITTER) {
oldDb = _db_current();
_db_select(_critter_db_handle);
}
char* filePath = artBuildFilePath(fid);
if (filePath != nullptr) {
if (filePath != NULL) {
int fileSize;
if (dbGetFileSize(filePath, &fileSize) != -1) {
result = true;
}
}
if (oldDb != -1) {
_db_select(oldDb);
}
return result;
}
@@ -872,15 +891,25 @@ bool artExists(int fid)
bool _art_fid_valid(int fid)
{
bool result = false;
int oldDb = -1;
if (FID_TYPE(fid) == OBJ_TYPE_CRITTER) {
oldDb = _db_current();
_db_select(_critter_db_handle);
}
char* filePath = artBuildFilePath(fid);
if (filePath != nullptr) {
if (filePath != NULL) {
int fileSize;
if (dbGetFileSize(filePath, &fileSize) != -1) {
result = true;
}
}
if (oldDb != -1) {
_db_select(oldDb);
}
return result;
}
@@ -927,37 +956,47 @@ int artAliasFid(int fid)
// 0x419A78
static int artCacheGetFileSizeImpl(int fid, int* sizePtr)
{
int oldDb = -1;
int result = -1;
if (FID_TYPE(fid) == OBJ_TYPE_CRITTER) {
oldDb = _db_current();
_db_select(_critter_db_handle);
}
char* artFilePath = artBuildFilePath(fid);
if (artFilePath != nullptr) {
if (artFilePath != NULL) {
int fileSize;
bool loaded = false;
File* stream = nullptr;
if (gArtLanguageInitialized) {
char* pch = strchr(artFilePath, '\\');
if (pch == nullptr) {
if (pch == NULL) {
pch = artFilePath;
}
char localizedPath[COMPAT_MAX_PATH];
snprintf(localizedPath, sizeof(localizedPath), "art\\%s\\%s", gArtLanguage, pch);
sprintf(localizedPath, "art\\%s\\%s", gArtLanguage, pch);
stream = fileOpen(localizedPath, "rb");
}
if (stream == nullptr) {
stream = fileOpen(artFilePath, "rb");
}
if (stream != nullptr) {
Art art;
if (artReadHeader(&art, stream) == 0) {
*sizePtr = artGetDataSize(&art);
result = 0;
if (dbGetFileSize(localizedPath, &fileSize) == 0) {
loaded = true;
}
fileClose(stream);
}
if (!loaded) {
if (dbGetFileSize(artFilePath, &fileSize) == 0) {
loaded = true;
}
}
if (loaded) {
*sizePtr = fileSize;
result = 0;
}
}
if (oldDb != -1) {
_db_select(oldDb);
}
return result;
@@ -966,19 +1005,25 @@ static int artCacheGetFileSizeImpl(int fid, int* sizePtr)
// 0x419B78
static int artCacheReadDataImpl(int fid, int* sizePtr, unsigned char* data)
{
int oldDb = -1;
int result = -1;
if (FID_TYPE(fid) == OBJ_TYPE_CRITTER) {
oldDb = _db_current();
_db_select(_critter_db_handle);
}
char* artFileName = artBuildFilePath(fid);
if (artFileName != nullptr) {
if (artFileName != NULL) {
bool loaded = false;
if (gArtLanguageInitialized) {
char* pch = strchr(artFileName, '\\');
if (pch == nullptr) {
if (pch == NULL) {
pch = artFileName;
}
char localizedPath[COMPAT_MAX_PATH];
snprintf(localizedPath, sizeof(localizedPath), "art\\%s\\%s", gArtLanguage, pch);
sprintf(localizedPath, "art\\%s\\%s", gArtLanguage, pch);
if (artRead(localizedPath, data) == 0) {
loaded = true;
@@ -992,11 +1037,16 @@ static int artCacheReadDataImpl(int fid, int* sizePtr, unsigned char* data)
}
if (loaded) {
*sizePtr = artGetDataSize((Art*)data);
// TODO: Why it adds 74?
*sizePtr = ((Art*)data)->field_3A + 74;
result = 0;
}
}
if (oldDb != -1) {
_db_select(oldDb);
}
return result;
}
@@ -1048,10 +1098,9 @@ out:
}
// 0x419D60
static int artReadFrameData(unsigned char* data, File* stream, int count, int* paddingPtr)
static int artReadFrameData(unsigned char* data, File* stream, int count)
{
unsigned char* ptr = data;
int padding = 0;
for (int index = 0; index < count; index++) {
ArtFrame* frame = (ArtFrame*)ptr;
@@ -1063,12 +1112,8 @@ static int artReadFrameData(unsigned char* data, File* stream, int count, int* p
if (fileRead(ptr + sizeof(ArtFrame), frame->size, 1, stream) != 1) return -1;
ptr += sizeof(ArtFrame) + frame->size;
ptr += paddingForSize(frame->size);
padding += paddingForSize(frame->size);
}
*paddingPtr = padding;
return 0;
}
@@ -1082,55 +1127,16 @@ static int artReadHeader(Art* art, File* stream)
if (fileReadInt16List(stream, art->xOffsets, ROTATION_COUNT) == -1) return -1;
if (fileReadInt16List(stream, art->yOffsets, ROTATION_COUNT) == -1) return -1;
if (fileReadInt32List(stream, art->dataOffsets, ROTATION_COUNT) == -1) return -1;
if (fileReadInt32(stream, &(art->dataSize)) == -1) return -1;
// CE: Fix malformed `frm` files with `dataSize` set to 0 in Nevada.
if (art->dataSize == 0) {
art->dataSize = fileGetSize(stream);
}
if (fileReadInt32(stream, &(art->field_3A)) == -1) return -1;
return 0;
}
// NOTE: Original function was slightly different, but never used. Basically
// it's a memory allocating variant of `artRead` (which reads data into given
// buffer). This function is useful to load custom `frm` files since `Art` now
// needs more memory then it's on-disk size (due to memory padding).
//
// 0x419EC0
Art* artLoad(const char* path)
{
File* stream = fileOpen(path, "rb");
if (stream == nullptr) {
return nullptr;
}
Art header;
if (artReadHeader(&header, stream) != 0) {
fileClose(stream);
return nullptr;
}
fileClose(stream);
unsigned char* data = reinterpret_cast<unsigned char*>(internal_malloc(artGetDataSize(&header)));
if (data == nullptr) {
return nullptr;
}
if (artRead(path, data) != 0) {
internal_free(data);
return nullptr;
}
return reinterpret_cast<Art*>(data);
}
// 0x419FC0
int artRead(const char* path, unsigned char* data)
{
File* stream = fileOpen(path, "rb");
if (stream == nullptr) {
if (stream == NULL) {
return -2;
}
@@ -1140,16 +1146,9 @@ int artRead(const char* path, unsigned char* data)
return -3;
}
int currentPadding = paddingForSize(sizeof(Art));
int previousPadding = 0;
for (int index = 0; index < ROTATION_COUNT; index++) {
art->padding[index] = currentPadding;
if (index == 0 || art->dataOffsets[index - 1] != art->dataOffsets[index]) {
art->padding[index] += previousPadding;
currentPadding += previousPadding;
if (artReadFrameData(data + sizeof(Art) + art->dataOffsets[index] + art->padding[index], stream, art->frameCount, &previousPadding) != 0) {
if (artReadFrameData(data + sizeof(Art) + art->dataOffsets[index], stream, art->frameCount) != 0) {
fileClose(stream);
return -5;
}
@@ -1177,7 +1176,6 @@ int artWriteFrameData(unsigned char* data, File* stream, int count)
if (fileWrite(ptr + sizeof(ArtFrame), frame->size, 1, stream) != 1) return -1;
ptr += sizeof(ArtFrame) + frame->size;
ptr += paddingForSize(frame->size);
}
return 0;
@@ -1195,7 +1193,7 @@ int artWriteHeader(Art* art, File* stream)
if (fileWriteInt16List(stream, art->xOffsets, ROTATION_COUNT) == -1) return -1;
if (fileWriteInt16List(stream, art->yOffsets, ROTATION_COUNT) == -1) return -1;
if (fileWriteInt32List(stream, art->dataOffsets, ROTATION_COUNT) == -1) return -1;
if (fileWriteInt32(stream, art->dataSize) == -1) return -1;
if (fileWriteInt32(stream, art->field_3A) == -1) return -1;
return 0;
}
@@ -1205,12 +1203,12 @@ int artWriteHeader(Art* art, File* stream)
// 0x41A1E8
int artWrite(const char* path, unsigned char* data)
{
if (data == nullptr) {
if (data == NULL) {
return -1;
}
File* stream = fileOpen(path, "wb");
if (stream == nullptr) {
if (stream == NULL) {
return -1;
}
@@ -1222,7 +1220,7 @@ int artWrite(const char* path, unsigned char* data)
for (int index = 0; index < ROTATION_COUNT; index++) {
if (index == 0 || art->dataOffsets[index - 1] != art->dataOffsets[index]) {
if (artWriteFrameData(data + sizeof(Art) + art->dataOffsets[index] + art->padding[index], stream, art->frameCount) != 0) {
if (artWriteFrameData(data + sizeof(Art) + art->dataOffsets[index], stream, art->frameCount) != 0) {
fileClose(stream);
return -1;
}
@@ -1233,26 +1231,6 @@ int artWrite(const char* path, unsigned char* data)
return 0;
}
static int artGetDataSize(Art* art)
{
int dataSize = sizeof(*art) + art->dataSize;
for (int index = 0; index < ROTATION_COUNT; index++) {
if (index == 0 || art->dataOffsets[index - 1] != art->dataOffsets[index]) {
// Assume worst case - every frame is unaligned and need
// max padding.
dataSize += (sizeof(int) - 1) * art->frameCount;
}
}
return dataSize;
}
static int paddingForSize(int size)
{
return (sizeof(int) - size % sizeof(int)) % sizeof(int);
}
FrmImage::FrmImage()
{
_key = nullptr;

View File

@@ -67,6 +67,7 @@ typedef enum Background {
BACKGROUND_COUNT,
} Background;
#pragma pack(2)
typedef struct Art {
int field_0;
short framesPerSecond;
@@ -75,9 +76,9 @@ typedef struct Art {
short xOffsets[6];
short yOffsets[6];
int dataOffsets[6];
int padding[6];
int dataSize;
int field_3A;
} Art;
#pragma pack()
typedef struct ArtFrame {
short width;
@@ -123,7 +124,6 @@ char* artGetObjectTypeName(int objectType);
int artIsObjectTypeHidden(int objectType);
int artGetFidgetCount(int headFid);
void artRender(int fid, unsigned char* dest, int width, int height, int pitch);
int art_list_str(int fid, char* name);
Art* artLock(int fid, CacheEntry** cache_entry);
unsigned char* artLockFrameData(int fid, int frame, int direction, CacheEntry** out_cache_entry);
unsigned char* artLockFrameDataReturningSize(int fid, CacheEntry** out_cache_entry, int* widthPtr, int* heightPtr);
@@ -148,7 +148,6 @@ int _art_alias_num(int a1);
int artCritterFidShouldRun(int a1);
int artAliasFid(int fid);
int buildFid(int objectType, int frmId, int animType, int a4, int rotation);
Art* artLoad(const char* path);
int artRead(const char* path, unsigned char* data);
int artWrite(const char* path, unsigned char* data);

View File

@@ -7,101 +7,105 @@
#include "db.h"
#include "debug.h"
#include "memory_manager.h"
#include "pointer_registry.h"
#include "sound.h"
#include "sound_decoder.h"
namespace fallout {
typedef enum AudioFlags {
AUDIO_IN_USE = 0x01,
AUDIO_COMPRESSED = 0x02,
} AudioFileFlags;
typedef struct Audio {
int flags;
File* stream;
SoundDecoder* soundDecoder;
int fileSize;
int sampleRate;
int channels;
int position;
} Audio;
static bool defaultCompressionFunc(char* filePath);
static int audioSoundDecoderReadHandler(void* data, void* buf, unsigned int size);
static bool _defaultCompressionFunc(char* filePath);
static int audioSoundDecoderReadHandler(int fileHandle, void* buf, unsigned int size);
// 0x5108BC
static AudioQueryCompressedFunc* queryCompressedFunc = defaultCompressionFunc;
static AudioFileIsCompressedProc* _queryCompressedFunc = _defaultCompressionFunc;
// 0x56CB00
static int gAudioListLength;
// 0x56CB04
static Audio* gAudioList;
static AudioFile* gAudioList;
// 0x41A2B0
static bool defaultCompressionFunc(char* filePath)
static bool _defaultCompressionFunc(char* filePath)
{
char* pch = strrchr(filePath, '.');
if (pch != nullptr) {
strcpy(pch + 1, "raw");
if (pch != NULL) {
strcpy(pch + 1, "war");
}
return false;
}
// 0x41A2D0
static int audioSoundDecoderReadHandler(void* data, void* buffer, unsigned int size)
static int audioSoundDecoderReadHandler(int fileHandle, void* buffer, unsigned int size)
{
return fileRead(buffer, 1, size, reinterpret_cast<File*>(data));
return fileRead(buffer, 1, size, (File*)intToPtr(fileHandle));
}
// AudioOpen
// 0x41A2EC
int audioOpen(const char* fname, int* sampleRate)
int audioOpen(const char* fname, int flags, ...)
{
char path[80];
snprintf(path, sizeof(path), "%s", fname);
sprintf(path, "%s", fname);
int compression;
if (queryCompressedFunc(path)) {
if (_queryCompressedFunc(path)) {
compression = 2;
} else {
compression = 0;
}
File* stream = fileOpen(path, "rb");
if (stream == nullptr) {
char mode[4];
memset(mode, 0, 4);
// NOTE: Original implementation is slightly different, it uses separate
// variable to track index where to set 't' and 'b'.
char* pm = mode;
if (flags & 1) {
*pm++ = 'w';
} else if (flags & 2) {
*pm++ = 'w';
*pm++ = '+';
} else {
*pm++ = 'r';
}
if (flags & 0x100) {
*pm++ = 't';
} else if (flags & 0x200) {
*pm++ = 'b';
}
File* stream = fileOpen(path, mode);
if (stream == NULL) {
debugPrint("AudioOpen: Couldn't open %s for read\n", path);
return -1;
}
int index;
for (index = 0; index < gAudioListLength; index++) {
if ((gAudioList[index].flags & AUDIO_IN_USE) == 0) {
if ((gAudioList[index].flags & AUDIO_FILE_IN_USE) == 0) {
break;
}
}
if (index == gAudioListLength) {
if (gAudioList != nullptr) {
gAudioList = (Audio*)internal_realloc_safe(gAudioList, sizeof(*gAudioList) * (gAudioListLength + 1), __FILE__, __LINE__); // "..\int\audio.c", 216
if (gAudioList != NULL) {
gAudioList = (AudioFile*)internal_realloc_safe(gAudioList, sizeof(*gAudioList) * (gAudioListLength + 1), __FILE__, __LINE__); // "..\int\audio.c", 216
} else {
gAudioList = (Audio*)internal_malloc_safe(sizeof(*gAudioList), __FILE__, __LINE__); // "..\int\audio.c", 218
gAudioList = (AudioFile*)internal_malloc_safe(sizeof(*gAudioList), __FILE__, __LINE__); // "..\int\audio.c", 218
}
gAudioListLength++;
}
Audio* audioFile = &(gAudioList[index]);
audioFile->flags = AUDIO_IN_USE;
audioFile->stream = stream;
AudioFile* audioFile = &(gAudioList[index]);
audioFile->flags = AUDIO_FILE_IN_USE;
audioFile->fileHandle = ptrToInt(stream);
if (compression == 2) {
audioFile->flags |= AUDIO_COMPRESSED;
audioFile->soundDecoder = soundDecoderInit(audioSoundDecoderReadHandler, audioFile->stream, &(audioFile->channels), &(audioFile->sampleRate), &(audioFile->fileSize));
audioFile->flags |= AUDIO_FILE_COMPRESSED;
audioFile->soundDecoder = soundDecoderInit(audioSoundDecoderReadHandler, audioFile->fileHandle, &(audioFile->field_14), &(audioFile->field_10), &(audioFile->fileSize));
audioFile->fileSize *= 2;
*sampleRate = audioFile->sampleRate;
} else {
audioFile->fileSize = fileGetSize(stream);
}
@@ -112,30 +116,30 @@ int audioOpen(const char* fname, int* sampleRate)
}
// 0x41A50C
int audioClose(int handle)
int audioClose(int fileHandle)
{
Audio* audioFile = &(gAudioList[handle - 1]);
fileClose(audioFile->stream);
AudioFile* audioFile = &(gAudioList[fileHandle - 1]);
fileClose((File*)intToPtr(audioFile->fileHandle, true));
if ((audioFile->flags & AUDIO_COMPRESSED) != 0) {
if ((audioFile->flags & AUDIO_FILE_COMPRESSED) != 0) {
soundDecoderFree(audioFile->soundDecoder);
}
memset(audioFile, 0, sizeof(Audio));
memset(audioFile, 0, sizeof(AudioFile));
return 0;
}
// 0x41A574
int audioRead(int handle, void* buffer, unsigned int size)
int audioRead(int fileHandle, void* buffer, unsigned int size)
{
Audio* audioFile = &(gAudioList[handle - 1]);
AudioFile* audioFile = &(gAudioList[fileHandle - 1]);
int bytesRead;
if ((audioFile->flags & AUDIO_COMPRESSED) != 0) {
if ((audioFile->flags & AUDIO_FILE_COMPRESSED) != 0) {
bytesRead = soundDecoderDecode(audioFile->soundDecoder, buffer, size);
} else {
bytesRead = fileRead(buffer, 1, size, audioFile->stream);
bytesRead = fileRead(buffer, 1, size, (File*)intToPtr(audioFile->fileHandle));
}
audioFile->position += bytesRead;
@@ -144,13 +148,13 @@ int audioRead(int handle, void* buffer, unsigned int size)
}
// 0x41A5E0
long audioSeek(int handle, long offset, int origin)
long audioSeek(int fileHandle, long offset, int origin)
{
int pos;
unsigned char* buf;
int v10;
Audio* audioFile = &(gAudioList[handle - 1]);
AudioFile* audioFile = &(gAudioList[fileHandle - 1]);
switch (origin) {
case SEEK_SET:
@@ -166,11 +170,11 @@ long audioSeek(int handle, long offset, int origin)
assert(false && "Should be unreachable");
}
if ((audioFile->flags & AUDIO_COMPRESSED) != 0) {
if ((audioFile->flags & AUDIO_FILE_COMPRESSED) != 0) {
if (pos < audioFile->position) {
soundDecoderFree(audioFile->soundDecoder);
fileSeek(audioFile->stream, 0, SEEK_SET);
audioFile->soundDecoder = soundDecoderInit(audioSoundDecoderReadHandler, audioFile->stream, &(audioFile->channels), &(audioFile->sampleRate), &(audioFile->fileSize));
fileSeek((File*)intToPtr(audioFile->fileHandle), 0, SEEK_SET);
audioFile->soundDecoder = soundDecoderInit(audioSoundDecoderReadHandler, audioFile->fileHandle, &(audioFile->field_14), &(audioFile->field_10), &(audioFile->fileSize));
audioFile->position = 0;
audioFile->fileSize *= 2;
@@ -178,11 +182,11 @@ long audioSeek(int handle, long offset, int origin)
buf = (unsigned char*)internal_malloc_safe(4096, __FILE__, __LINE__); // "..\int\audio.c", 361
while (pos > 4096) {
pos -= 4096;
audioRead(handle, buf, 4096);
audioRead(fileHandle, buf, 4096);
}
if (pos != 0) {
audioRead(handle, buf, pos);
audioRead(fileHandle, buf, pos);
}
internal_free_safe(buf, __FILE__, __LINE__); // // "..\int\audio.c", 367
@@ -192,11 +196,11 @@ long audioSeek(int handle, long offset, int origin)
v10 = audioFile->position - pos;
while (v10 > 1024) {
v10 -= 1024;
audioRead(handle, buf, 1024);
audioRead(fileHandle, buf, 1024);
}
if (v10 != 0) {
audioRead(handle, buf, v10);
audioRead(fileHandle, buf, v10);
}
// TODO: Probably leaks memory.
@@ -204,21 +208,21 @@ long audioSeek(int handle, long offset, int origin)
return audioFile->position;
} else {
return fileSeek(audioFile->stream, offset, origin);
return fileSeek((File*)intToPtr(audioFile->fileHandle), offset, origin);
}
}
// 0x41A78C
long audioGetSize(int handle)
long audioGetSize(int fileHandle)
{
Audio* audioFile = &(gAudioList[handle - 1]);
AudioFile* audioFile = &(gAudioList[fileHandle - 1]);
return audioFile->fileSize;
}
// 0x41A7A8
long audioTell(int handle)
long audioTell(int fileHandle)
{
Audio* audioFile = &(gAudioList[handle - 1]);
AudioFile* audioFile = &(gAudioList[fileHandle - 1]);
return audioFile->position;
}
@@ -231,10 +235,10 @@ int audioWrite(int handle, const void* buf, unsigned int size)
}
// 0x41A7D4
int audioInit(AudioQueryCompressedFunc* func)
int audioInit(AudioFileIsCompressedProc* isCompressedProc)
{
queryCompressedFunc = func;
gAudioList = nullptr;
_queryCompressedFunc = isCompressedProc;
gAudioList = NULL;
gAudioListLength = 0;
return soundSetDefaultFileIO(audioOpen, audioClose, audioRead, audioWrite, audioSeek, audioTell, audioGetSize);
@@ -243,12 +247,12 @@ int audioInit(AudioQueryCompressedFunc* func)
// 0x41A818
void audioExit()
{
if (gAudioList != nullptr) {
if (gAudioList != NULL) {
internal_free_safe(gAudioList, __FILE__, __LINE__); // "..\int\audio.c", 406
}
gAudioListLength = 0;
gAudioList = nullptr;
gAudioList = NULL;
}
} // namespace fallout

View File

@@ -1,18 +1,18 @@
#ifndef AUDIO_H
#define AUDIO_H
#include "audio_file.h"
namespace fallout {
typedef bool(AudioQueryCompressedFunc)(char* filePath);
int audioOpen(const char* fname, int* sampleRate);
int audioClose(int handle);
int audioRead(int handle, void* buffer, unsigned int size);
long audioSeek(int handle, long offset, int origin);
long audioGetSize(int handle);
long audioTell(int handle);
int audioOpen(const char* fname, int mode, ...);
int audioClose(int fileHandle);
int audioRead(int fileHandle, void* buffer, unsigned int size);
long audioSeek(int fileHandle, long offset, int origin);
long audioGetSize(int fileHandle);
long audioTell(int fileHandle);
int audioWrite(int handle, const void* buf, unsigned int size);
int audioInit(AudioQueryCompressedFunc* func);
int audioInit(AudioFileIsCompressedProc* isCompressedProc);
void audioExit();
} // namespace fallout

View File

@@ -34,11 +34,6 @@ static SDL_AudioSpec gAudioEngineSpec;
static SDL_AudioDeviceID gAudioEngineDeviceId = -1;
static AudioEngineSoundBuffer gAudioEngineSoundBuffers[AUDIO_ENGINE_SOUND_BUFFERS];
static bool audioEngineIsInitialized()
{
return gAudioEngineDeviceId != -1;
}
static bool soundBufferIsValid(int soundBufferIndex)
{
return soundBufferIndex >= 0 && soundBufferIndex < AUDIO_ENGINE_SOUND_BUFFERS;
@@ -106,7 +101,7 @@ bool audioEngineInit()
desiredSpec.samples = 1024;
desiredSpec.callback = audioEngineMixin;
gAudioEngineDeviceId = SDL_OpenAudioDevice(nullptr, 0, &desiredSpec, &gAudioEngineSpec, SDL_AUDIO_ALLOW_ANY_CHANGE);
gAudioEngineDeviceId = SDL_OpenAudioDevice(NULL, 0, &desiredSpec, &gAudioEngineSpec, SDL_AUDIO_ALLOW_ANY_CHANGE);
if (gAudioEngineDeviceId == -1) {
return false;
}
@@ -118,36 +113,30 @@ bool audioEngineInit()
void audioEngineExit()
{
if (audioEngineIsInitialized()) {
if (gAudioEngineDeviceId != -1) {
SDL_CloseAudioDevice(gAudioEngineDeviceId);
gAudioEngineDeviceId = -1;
}
if (SDL_WasInit(SDL_INIT_AUDIO)) {
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
void audioEnginePause()
{
if (audioEngineIsInitialized()) {
if (gAudioEngineDeviceId != -1) {
SDL_PauseAudioDevice(gAudioEngineDeviceId, 1);
}
}
void audioEngineResume()
{
if (audioEngineIsInitialized()) {
if (gAudioEngineDeviceId != -1) {
SDL_PauseAudioDevice(gAudioEngineDeviceId, 0);
}
}
int audioEngineCreateSoundBuffer(unsigned int size, int bitsPerSample, int channels, int rate)
{
if (!audioEngineIsInitialized()) {
return -1;
}
for (int index = 0; index < AUDIO_ENGINE_SOUND_BUFFERS; index++) {
AudioEngineSoundBuffer* soundBuffer = &(gAudioEngineSoundBuffers[index]);
std::lock_guard<std::recursive_mutex> lock(soundBuffer->mutex);
@@ -173,10 +162,6 @@ int audioEngineCreateSoundBuffer(unsigned int size, int bitsPerSample, int chann
bool audioEngineSoundBufferRelease(int soundBufferIndex)
{
if (!audioEngineIsInitialized()) {
return false;
}
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
@@ -191,20 +176,16 @@ bool audioEngineSoundBufferRelease(int soundBufferIndex)
soundBuffer->active = false;
free(soundBuffer->data);
soundBuffer->data = nullptr;
soundBuffer->data = NULL;
SDL_FreeAudioStream(soundBuffer->stream);
soundBuffer->stream = nullptr;
soundBuffer->stream = NULL;
return true;
}
bool audioEngineSoundBufferSetVolume(int soundBufferIndex, int volume)
{
if (!audioEngineIsInitialized()) {
return false;
}
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
@@ -223,10 +204,6 @@ bool audioEngineSoundBufferSetVolume(int soundBufferIndex, int volume)
bool audioEngineSoundBufferGetVolume(int soundBufferIndex, int* volumePtr)
{
if (!audioEngineIsInitialized()) {
return false;
}
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
@@ -245,10 +222,6 @@ bool audioEngineSoundBufferGetVolume(int soundBufferIndex, int* volumePtr)
bool audioEngineSoundBufferSetPan(int soundBufferIndex, int pan)
{
if (!audioEngineIsInitialized()) {
return false;
}
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
@@ -268,10 +241,6 @@ bool audioEngineSoundBufferSetPan(int soundBufferIndex, int pan)
bool audioEngineSoundBufferPlay(int soundBufferIndex, unsigned int flags)
{
if (!audioEngineIsInitialized()) {
return false;
}
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
@@ -294,10 +263,6 @@ bool audioEngineSoundBufferPlay(int soundBufferIndex, unsigned int flags)
bool audioEngineSoundBufferStop(int soundBufferIndex)
{
if (!audioEngineIsInitialized()) {
return false;
}
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
@@ -316,10 +281,6 @@ bool audioEngineSoundBufferStop(int soundBufferIndex)
bool audioEngineSoundBufferGetCurrentPosition(int soundBufferIndex, unsigned int* readPosPtr, unsigned int* writePosPtr)
{
if (!audioEngineIsInitialized()) {
return false;
}
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
@@ -331,11 +292,11 @@ bool audioEngineSoundBufferGetCurrentPosition(int soundBufferIndex, unsigned int
return false;
}
if (readPosPtr != nullptr) {
if (readPosPtr != NULL) {
*readPosPtr = soundBuffer->pos;
}
if (writePosPtr != nullptr) {
if (writePosPtr != NULL) {
*writePosPtr = soundBuffer->pos;
if (soundBuffer->playing) {
@@ -351,10 +312,6 @@ bool audioEngineSoundBufferGetCurrentPosition(int soundBufferIndex, unsigned int
bool audioEngineSoundBufferSetCurrentPosition(int soundBufferIndex, unsigned int pos)
{
if (!audioEngineIsInitialized()) {
return false;
}
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
@@ -373,10 +330,6 @@ bool audioEngineSoundBufferSetCurrentPosition(int soundBufferIndex, unsigned int
bool audioEngineSoundBufferLock(int soundBufferIndex, unsigned int writePos, unsigned int writeBytes, void** audioPtr1, unsigned int* audioBytes1, void** audioPtr2, unsigned int* audioBytes2, unsigned int flags)
{
if (!audioEngineIsInitialized()) {
return false;
}
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
@@ -388,12 +341,12 @@ bool audioEngineSoundBufferLock(int soundBufferIndex, unsigned int writePos, uns
return false;
}
if (audioBytes1 == nullptr) {
if (audioBytes1 == NULL) {
return false;
}
if ((flags & AUDIO_ENGINE_SOUND_BUFFER_LOCK_FROM_WRITE_POS) != 0) {
if (!audioEngineSoundBufferGetCurrentPosition(soundBufferIndex, nullptr, &writePos)) {
if (!audioEngineSoundBufferGetCurrentPosition(soundBufferIndex, NULL, &writePos)) {
return false;
}
}
@@ -406,11 +359,11 @@ bool audioEngineSoundBufferLock(int soundBufferIndex, unsigned int writePos, uns
*(unsigned char**)audioPtr1 = (unsigned char*)soundBuffer->data + writePos;
*audioBytes1 = writeBytes;
if (audioPtr2 != nullptr) {
*audioPtr2 = nullptr;
if (audioPtr2 != NULL) {
*audioPtr2 = NULL;
}
if (audioBytes2 != nullptr) {
if (audioBytes2 != NULL) {
*audioBytes2 = 0;
}
} else {
@@ -418,11 +371,11 @@ bool audioEngineSoundBufferLock(int soundBufferIndex, unsigned int writePos, uns
*(unsigned char**)audioPtr1 = (unsigned char*)soundBuffer->data + writePos;
*audioBytes1 = soundBuffer->size - writePos;
if (audioPtr2 != nullptr) {
if (audioPtr2 != NULL) {
*(unsigned char**)audioPtr2 = (unsigned char*)soundBuffer->data;
}
if (audioBytes2 != nullptr) {
if (audioBytes2 != NULL) {
*audioBytes2 = writeBytes - (soundBuffer->size - writePos);
}
}
@@ -434,10 +387,6 @@ bool audioEngineSoundBufferLock(int soundBufferIndex, unsigned int writePos, uns
bool audioEngineSoundBufferUnlock(int soundBufferIndex, void* audioPtr1, unsigned int audioBytes1, void* audioPtr2, unsigned int audioBytes2)
{
if (!audioEngineIsInitialized()) {
return false;
}
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
@@ -456,10 +405,6 @@ bool audioEngineSoundBufferUnlock(int soundBufferIndex, void* audioPtr1, unsigne
bool audioEngineSoundBufferGetStatus(int soundBufferIndex, unsigned int* statusPtr)
{
if (!audioEngineIsInitialized()) {
return false;
}
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
@@ -471,7 +416,7 @@ bool audioEngineSoundBufferGetStatus(int soundBufferIndex, unsigned int* statusP
return false;
}
if (statusPtr == nullptr) {
if (statusPtr == NULL) {
return false;
}

View File

@@ -7,31 +7,16 @@
#include "debug.h"
#include "memory_manager.h"
#include "platform_compat.h"
#include "pointer_registry.h"
#include "sound.h"
#include "sound_decoder.h"
namespace fallout {
typedef enum AudioFileFlags {
AUDIO_FILE_IN_USE = 0x01,
AUDIO_FILE_COMPRESSED = 0x02,
} AudioFileFlags;
typedef struct AudioFile {
int flags;
FILE* stream;
SoundDecoder* soundDecoder;
int fileSize;
int sampleRate;
int channels;
int position;
} AudioFile;
static bool defaultCompressionFunc(char* filePath);
static int audioFileSoundDecoderReadHandler(void* data, void* buffer, unsigned int size);
static bool _defaultCompressionFunc__(char* filePath);
static int audioFileSoundDecoderReadHandler(int fileHandle, void* buffer, unsigned int size);
// 0x5108C0
static AudioFileQueryCompressedFunc* queryCompressedFunc = defaultCompressionFunc;
static AudioFileIsCompressedProc* _queryCompressedFunc_2 = _defaultCompressionFunc__;
// 0x56CB10
static AudioFile* gAudioFileList;
@@ -40,37 +25,58 @@ static AudioFile* gAudioFileList;
static int gAudioFileListLength;
// 0x41A850
static bool defaultCompressionFunc(char* filePath)
static bool _defaultCompressionFunc__(char* filePath)
{
char* pch = strrchr(filePath, '.');
if (pch != nullptr) {
strcpy(pch + 1, "raw");
if (pch != NULL) {
strcpy(pch + 1, "war");
}
return false;
}
// 0x41A870
static int audioFileSoundDecoderReadHandler(void* data, void* buffer, unsigned int size)
static int audioFileSoundDecoderReadHandler(int fileHandle, void* buffer, unsigned int size)
{
return fread(buffer, 1, size, reinterpret_cast<FILE*>(data));
return fread(buffer, 1, size, (FILE*)intToPtr(fileHandle));
}
// 0x41A88C
int audioFileOpen(const char* fname, int* sampleRate)
int audioFileOpen(const char* fname, int flags, ...)
{
char path[COMPAT_MAX_PATH];
strcpy(path, fname);
int compression;
if (queryCompressedFunc(path)) {
if (_queryCompressedFunc_2(path)) {
compression = 2;
} else {
compression = 0;
}
FILE* stream = compat_fopen(path, "rb");
if (stream == nullptr) {
char mode[4];
memset(mode, '\0', 4);
// NOTE: Original implementation is slightly different, it uses separate
// variable to track index where to set 't' and 'b'.
char* pm = mode;
if (flags & 0x01) {
*pm++ = 'w';
} else if (flags & 0x02) {
*pm++ = 'w';
*pm++ = '+';
} else {
*pm++ = 'r';
}
if (flags & 0x0100) {
*pm++ = 't';
} else if (flags & 0x0200) {
*pm++ = 'b';
}
FILE* stream = compat_fopen(path, mode);
if (stream == NULL) {
return -1;
}
@@ -82,7 +88,7 @@ int audioFileOpen(const char* fname, int* sampleRate)
}
if (index == gAudioFileListLength) {
if (gAudioFileList != nullptr) {
if (gAudioFileList != NULL) {
gAudioFileList = (AudioFile*)internal_realloc_safe(gAudioFileList, sizeof(*gAudioFileList) * (gAudioFileListLength + 1), __FILE__, __LINE__); // "..\int\audiof.c", 207
} else {
gAudioFileList = (AudioFile*)internal_malloc_safe(sizeof(*gAudioFileList), __FILE__, __LINE__); // "..\int\audiof.c", 209
@@ -92,14 +98,12 @@ int audioFileOpen(const char* fname, int* sampleRate)
AudioFile* audioFile = &(gAudioFileList[index]);
audioFile->flags = AUDIO_FILE_IN_USE;
audioFile->stream = stream;
audioFile->fileHandle = ptrToInt(stream);
if (compression == 2) {
audioFile->flags |= AUDIO_FILE_COMPRESSED;
audioFile->soundDecoder = soundDecoderInit(audioFileSoundDecoderReadHandler, audioFile->stream, &(audioFile->channels), &(audioFile->sampleRate), &(audioFile->fileSize));
audioFile->soundDecoder = soundDecoderInit(audioFileSoundDecoderReadHandler, audioFile->fileHandle, &(audioFile->field_14), &(audioFile->field_10), &(audioFile->fileSize));
audioFile->fileSize *= 2;
*sampleRate = audioFile->sampleRate;
} else {
audioFile->fileSize = getFileSize(stream);
}
@@ -110,10 +114,10 @@ int audioFileOpen(const char* fname, int* sampleRate)
}
// 0x41AAA0
int audioFileClose(int handle)
int audioFileClose(int fileHandle)
{
AudioFile* audioFile = &(gAudioFileList[handle - 1]);
fclose(audioFile->stream);
AudioFile* audioFile = &(gAudioFileList[fileHandle - 1]);
fclose((FILE*)intToPtr(audioFile->fileHandle, true));
if ((audioFile->flags & AUDIO_FILE_COMPRESSED) != 0) {
soundDecoderFree(audioFile->soundDecoder);
@@ -126,16 +130,16 @@ int audioFileClose(int handle)
}
// 0x41AB08
int audioFileRead(int handle, void* buffer, unsigned int size)
int audioFileRead(int fileHandle, void* buffer, unsigned int size)
{
AudioFile* ptr = &(gAudioFileList[handle - 1]);
AudioFile* ptr = &(gAudioFileList[fileHandle - 1]);
int bytesRead;
if ((ptr->flags & AUDIO_FILE_COMPRESSED) != 0) {
bytesRead = soundDecoderDecode(ptr->soundDecoder, buffer, size);
} else {
bytesRead = fread(buffer, 1, size, ptr->stream);
bytesRead = fread(buffer, 1, size, (FILE*)intToPtr(ptr->fileHandle));
}
ptr->position += bytesRead;
@@ -144,13 +148,13 @@ int audioFileRead(int handle, void* buffer, unsigned int size)
}
// 0x41AB74
long audioFileSeek(int handle, long offset, int origin)
long audioFileSeek(int fileHandle, long offset, int origin)
{
void* buf;
int remaining;
int a4;
AudioFile* audioFile = &(gAudioFileList[handle - 1]);
AudioFile* audioFile = &(gAudioFileList[fileHandle - 1]);
switch (origin) {
case SEEK_SET:
@@ -170,20 +174,20 @@ long audioFileSeek(int handle, long offset, int origin)
if (a4 <= audioFile->position) {
soundDecoderFree(audioFile->soundDecoder);
fseek(audioFile->stream, 0, 0);
fseek((FILE*)intToPtr(audioFile->fileHandle), 0, 0);
audioFile->soundDecoder = soundDecoderInit(audioFileSoundDecoderReadHandler, audioFile->stream, &(audioFile->channels), &(audioFile->sampleRate), &(audioFile->fileSize));
audioFile->soundDecoder = soundDecoderInit(audioFileSoundDecoderReadHandler, audioFile->fileHandle, &(audioFile->field_14), &(audioFile->field_10), &(audioFile->fileSize));
audioFile->fileSize *= 2;
audioFile->position = 0;
if (a4) {
buf = internal_malloc_safe(4096, __FILE__, __LINE__); // "..\int\audiof.c", 364
while (a4 > 4096) {
audioFileRead(handle, buf, 4096);
audioFileRead(fileHandle, buf, 4096);
a4 -= 4096;
}
if (a4 != 0) {
audioFileRead(handle, buf, a4);
audioFileRead(fileHandle, buf, a4);
}
internal_free_safe(buf, __FILE__, __LINE__); // "..\int\audiof.c", 370
}
@@ -191,47 +195,47 @@ long audioFileSeek(int handle, long offset, int origin)
buf = internal_malloc_safe(0x400, __FILE__, __LINE__); // "..\int\audiof.c", 316
remaining = audioFile->position - a4;
while (remaining > 1024) {
audioFileRead(handle, buf, 1024);
audioFileRead(fileHandle, buf, 1024);
remaining -= 1024;
}
if (remaining != 0) {
audioFileRead(handle, buf, remaining);
audioFileRead(fileHandle, buf, remaining);
}
// TODO: Obiously leaks memory.
}
return audioFile->position;
}
return fseek(audioFile->stream, offset, origin);
return fseek((FILE*)intToPtr(audioFile->fileHandle), offset, origin);
}
// 0x41AD20
long audioFileGetSize(int handle)
long audioFileGetSize(int fileHandle)
{
AudioFile* audioFile = &(gAudioFileList[handle - 1]);
AudioFile* audioFile = &(gAudioFileList[fileHandle - 1]);
return audioFile->fileSize;
}
// 0x41AD3C
long audioFileTell(int handle)
long audioFileTell(int fileHandle)
{
AudioFile* audioFile = &(gAudioFileList[handle - 1]);
AudioFile* audioFile = &(gAudioFileList[fileHandle - 1]);
return audioFile->position;
}
// AudiofWrite
// 0x41AD58
int audioFileWrite(int handle, const void* buffer, unsigned int size)
int audioFileWrite(int fileHandle, const void* buffer, unsigned int size)
{
debugPrint("AudiofWrite shouldn't be ever called\n");
return 0;
}
// 0x41AD68
int audioFileInit(AudioFileQueryCompressedFunc* func)
int audioFileInit(AudioFileIsCompressedProc* isCompressedProc)
{
queryCompressedFunc = func;
gAudioFileList = nullptr;
_queryCompressedFunc_2 = isCompressedProc;
gAudioFileList = NULL;
gAudioFileListLength = 0;
return soundSetDefaultFileIO(audioFileOpen, audioFileClose, audioFileRead, audioFileWrite, audioFileSeek, audioFileTell, audioFileGetSize);
@@ -240,12 +244,12 @@ int audioFileInit(AudioFileQueryCompressedFunc* func)
// 0x41ADAC
void audioFileExit()
{
if (gAudioFileList != nullptr) {
if (gAudioFileList != NULL) {
internal_free_safe(gAudioFileList, __FILE__, __LINE__); // "..\int\audiof.c", 405
}
gAudioFileListLength = 0;
gAudioFileList = nullptr;
gAudioFileList = NULL;
}
} // namespace fallout

View File

@@ -1,18 +1,35 @@
#ifndef AUDIO_FILE_H
#define AUDIO_FILE_H
#include "sound_decoder.h"
namespace fallout {
typedef bool(AudioFileQueryCompressedFunc)(char* filePath);
typedef enum AudioFileFlags {
AUDIO_FILE_IN_USE = 0x01,
AUDIO_FILE_COMPRESSED = 0x02,
} AudioFileFlags;
int audioFileOpen(const char* fname, int* sampleRate);
int audioFileClose(int handle);
int audioFileRead(int handle, void* buf, unsigned int size);
typedef struct AudioFile {
int flags;
int fileHandle;
SoundDecoder* soundDecoder;
int fileSize;
int field_10;
int field_14;
int position;
} AudioFile;
typedef bool(AudioFileIsCompressedProc)(char* filePath);
int audioFileOpen(const char* fname, int flags, ...);
int audioFileClose(int a1);
int audioFileRead(int a1, void* buf, unsigned int size);
long audioFileSeek(int handle, long offset, int origin);
long audioFileGetSize(int handle);
long audioFileTell(int handle);
long audioFileGetSize(int a1);
long audioFileTell(int a1);
int audioFileWrite(int handle, const void* buf, unsigned int size);
int audioFileInit(AudioFileQueryCompressedFunc* func);
int audioFileInit(AudioFileIsCompressedProc* isCompressedProc);
void audioFileExit();
} // namespace fallout

View File

@@ -8,22 +8,20 @@
#include "art.h"
#include "color.h"
#include "config.h"
#include "core.h"
#include "dbox.h"
#include "debug.h"
#include "draw.h"
#include "game.h"
#include "game_config.h"
#include "game_mouse.h"
#include "game_sound.h"
#include "graph_lib.h"
#include "input.h"
#include "item.h"
#include "kb.h"
#include "map.h"
#include "memory.h"
#include "object.h"
#include "platform_compat.h"
#include "settings.h"
#include "svga.h"
#include "text_font.h"
#include "window_manager.h"
@@ -271,9 +269,12 @@ int automapReset()
// 0x41B81C
void automapExit()
{
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s\\%s\\%s", settings.system.master_patches_path.c_str(), "MAPS", AUTOMAP_DB);
compat_remove(path);
char* masterPatchesPath;
if (configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_MASTER_PATCHES_KEY, &masterPatchesPath)) {
char path[COMPAT_MAX_PATH];
sprintf(path, "%s\\%s\\%s", masterPatchesPath, "MAPS", AUTOMAP_DB);
compat_remove(path);
}
}
// 0x41B87C
@@ -297,8 +298,6 @@ int _automapDisplayMap(int map)
// 0x41B8BC
void automapShow(bool isInGame, bool isUsingScanner)
{
ScopedGameMode gm(GameMode::kAutomap);
int frmIds[AUTOMAP_FRM_COUNT];
memcpy(frmIds, gAutomapFrmIds, sizeof(gAutomapFrmIds));
@@ -323,7 +322,7 @@ void automapShow(bool isInGame, bool isUsingScanner)
int automapWindowX = (screenGetWidth() - AUTOMAP_WINDOW_WIDTH) / 2;
int automapWindowY = (screenGetHeight() - AUTOMAP_WINDOW_HEIGHT) / 2;
int window = windowCreate(automapWindowX, automapWindowY, AUTOMAP_WINDOW_WIDTH, AUTOMAP_WINDOW_HEIGHT, color, WINDOW_MODAL | WINDOW_MOVE_ON_TOP);
int window = windowCreate(automapWindowX, automapWindowY, AUTOMAP_WINDOW_WIDTH, AUTOMAP_WINDOW_HEIGHT, color, WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
int scannerBtn = buttonCreate(window,
111,
@@ -336,7 +335,7 @@ void automapShow(bool isInGame, bool isUsingScanner)
KEY_LOWERCASE_S,
frmImages[AUTOMAP_FRM_BUTTON_UP].getData(),
frmImages[AUTOMAP_FRM_BUTTON_DOWN].getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (scannerBtn != -1) {
buttonSetCallbacks(scannerBtn, _gsound_red_butt_press, _gsound_red_butt_release);
@@ -353,7 +352,7 @@ void automapShow(bool isInGame, bool isUsingScanner)
KEY_ESCAPE,
frmImages[AUTOMAP_FRM_BUTTON_UP].getData(),
frmImages[AUTOMAP_FRM_BUTTON_DOWN].getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (cancelBtn != -1) {
buttonSetCallbacks(cancelBtn, _gsound_red_butt_press, _gsound_red_butt_release);
@@ -370,7 +369,7 @@ void automapShow(bool isInGame, bool isUsingScanner)
KEY_LOWERCASE_H,
frmImages[AUTOMAP_FRM_SWITCH_UP].getData(),
frmImages[AUTOMAP_FRM_SWITCH_DOWN].getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT | BUTTON_FLAG_0x01);
if (switchBtn != -1) {
buttonSetCallbacks(switchBtn, _gsound_toggle_butt_press_, _gsound_toggle_butt_press_);
@@ -399,13 +398,11 @@ void automapShow(bool isInGame, bool isUsingScanner)
bool done = false;
while (!done) {
sharedFpsLimiter.mark();
bool needsRefresh = false;
// FIXME: There is minor bug in the interface - pressing H/L to toggle
// high/low details does not update switch state.
int keyCode = inputGetInput();
int keyCode = _get_input();
switch (keyCode) {
case KEY_TAB:
case KEY_ESCAPE:
@@ -435,19 +432,19 @@ void automapShow(bool isInGame, bool isUsingScanner)
}
if ((gAutomapFlags & AUTOMAP_WITH_SCANNER) == 0) {
Object* scanner = nullptr;
Object* scanner = NULL;
Object* item1 = critterGetItem1(gDude);
if (item1 != nullptr && item1->pid == PROTO_ID_MOTION_SENSOR) {
if (item1 != NULL && item1->pid == PROTO_ID_MOTION_SENSOR) {
scanner = item1;
} else {
Object* item2 = critterGetItem2(gDude);
if (item2 != nullptr && item2->pid == PROTO_ID_MOTION_SENSOR) {
if (item2 != NULL && item2->pid == PROTO_ID_MOTION_SENSOR) {
scanner = item2;
}
}
if (scanner != nullptr && miscItemGetCharges(scanner) > 0) {
if (scanner != NULL && miscItemGetCharges(scanner) > 0) {
needsRefresh = true;
gAutomapFlags |= AUTOMAP_WITH_SCANNER;
miscItemConsumeCharge(scanner);
@@ -457,8 +454,8 @@ void automapShow(bool isInGame, bool isUsingScanner)
MessageListItem messageListItem;
// 17 - The motion sensor is not installed.
// 18 - The motion sensor has no charges remaining.
const char* title = getmsg(&gMiscMessageList, &messageListItem, scanner != nullptr ? 18 : 17);
showDialogBox(title, nullptr, 0, 165, 140, _colorTable[32328], nullptr, _colorTable[32328], 0);
const char* title = getmsg(&gMiscMessageList, &messageListItem, scanner != NULL ? 18 : 17);
showDialogBox(title, NULL, 0, 165, 140, _colorTable[32328], NULL, _colorTable[32328], 0);
}
}
@@ -481,9 +478,6 @@ void automapShow(bool isInGame, bool isUsingScanner)
automapRenderInMapWindow(window, elevation, frmImages[AUTOMAP_FRM_BACKGROUND].getData(), gAutomapFlags);
needsRefresh = false;
}
renderPresent();
sharedFpsLimiter.throttle();
}
if (isoWasEnabled) {
@@ -512,7 +506,7 @@ static void automapRenderInMapWindow(int window, int elevation, unsigned char* b
unsigned char* windowBuffer = windowGetBuffer(window);
blitBufferToBuffer(backgroundData, AUTOMAP_WINDOW_WIDTH, AUTOMAP_WINDOW_HEIGHT, AUTOMAP_WINDOW_WIDTH, windowBuffer, AUTOMAP_WINDOW_WIDTH);
for (Object* object = objectFindFirstAtElevation(elevation); object != nullptr; object = objectFindNextAtElevation()) {
for (Object* object = objectFindFirstAtElevation(elevation); object != NULL; object = objectFindNextAtElevation()) {
if (object->tile == -1) {
continue;
}
@@ -626,7 +620,7 @@ int automapRenderInPipboyWindow(int window, int map, int elevation)
unsigned char sceneryColor = _colorTable[480];
gAutomapEntry.data = (unsigned char*)internal_malloc(11024);
if (gAutomapEntry.data == nullptr) {
if (gAutomapEntry.data == NULL) {
debugPrint("\nAUTOMAP: Error allocating data buffer!\n");
return -1;
}
@@ -694,9 +688,9 @@ int automapSaveCurrent()
bool dataBuffersAllocated = false;
gAutomapEntry.data = (unsigned char*)internal_malloc(11024);
if (gAutomapEntry.data != nullptr) {
if (gAutomapEntry.data != NULL) {
gAutomapEntry.compressedData = (unsigned char*)internal_malloc(11024);
if (gAutomapEntry.compressedData != nullptr) {
if (gAutomapEntry.compressedData != NULL) {
dataBuffersAllocated = true;
}
}
@@ -709,10 +703,10 @@ int automapSaveCurrent()
// NOTE: Not sure about the size.
char path[256];
snprintf(path, sizeof(path), "%s\\%s", "MAPS", AUTOMAP_DB);
sprintf(path, "%s\\%s", "MAPS", AUTOMAP_DB);
File* stream1 = fileOpen(path, "r+b");
if (stream1 == nullptr) {
if (stream1 == NULL) {
debugPrint("\nAUTOMAP: Error opening automap database file!\n");
debugPrint("Error continued: automap_pip_save: path: %s", path);
internal_free(gAutomapEntry.data);
@@ -740,10 +734,10 @@ int automapSaveCurrent()
}
if (entryOffset != 0) {
snprintf(path, sizeof(path), "%s\\%s", "MAPS", AUTOMAP_TMP);
sprintf(path, "%s\\%s", "MAPS", AUTOMAP_TMP);
File* stream2 = fileOpen(path, "wb");
if (stream2 == nullptr) {
if (stream2 == NULL) {
debugPrint("\nAUTOMAP: Error creating temp file!\n");
internal_free(gAutomapEntry.data);
internal_free(gAutomapEntry.compressedData);
@@ -834,9 +828,15 @@ int automapSaveCurrent()
internal_free(gAutomapEntry.data);
internal_free(gAutomapEntry.compressedData);
char* masterPatchesPath;
if (!configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_MASTER_PATCHES_KEY, &masterPatchesPath)) {
debugPrint("\nAUTOMAP: Error reading config info!\n");
return -1;
}
// NOTE: Not sure about the size.
char automapDbPath[512];
snprintf(automapDbPath, sizeof(automapDbPath), "%s\\%s\\%s", settings.system.master_patches_path.c_str(), "MAPS", AUTOMAP_DB);
sprintf(automapDbPath, "%s\\%s\\%s", masterPatchesPath, "MAPS", AUTOMAP_DB);
if (compat_remove(automapDbPath) != 0) {
debugPrint("\nAUTOMAP: Error removing database!\n");
return -1;
@@ -844,7 +844,7 @@ int automapSaveCurrent()
// NOTE: Not sure about the size.
char automapTmpPath[512];
snprintf(automapTmpPath, sizeof(automapTmpPath), "%s\\%s\\%s", settings.system.master_patches_path.c_str(), "MAPS", AUTOMAP_TMP);
sprintf(automapTmpPath, "%s\\%s\\%s", masterPatchesPath, "MAPS", AUTOMAP_TMP);
if (compat_rename(automapTmpPath, automapDbPath) != 0) {
debugPrint("\nAUTOMAP: Error renaming database!\n");
return -1;
@@ -928,15 +928,15 @@ err:
// 0x41C8CC
static int automapLoadEntry(int map, int elevation)
{
gAutomapEntry.compressedData = nullptr;
gAutomapEntry.compressedData = NULL;
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s\\%s", "MAPS", AUTOMAP_DB);
sprintf(path, "%s\\%s", "MAPS", AUTOMAP_DB);
bool success = true;
File* stream = fileOpen(path, "r+b");
if (stream == nullptr) {
if (stream == NULL) {
debugPrint("\nAUTOMAP: Error opening automap database file!\n");
debugPrint("Error continued: AM_ReadEntry: path: %s", path);
return -1;
@@ -970,7 +970,7 @@ static int automapLoadEntry(int map, int elevation)
if (gAutomapEntry.isCompressed == 1) {
gAutomapEntry.compressedData = (unsigned char*)internal_malloc(11024);
if (gAutomapEntry.compressedData == nullptr) {
if (gAutomapEntry.compressedData == NULL) {
debugPrint("\nAUTOMAP: Error allocating decompression buffer!\n");
fileClose(stream);
return -1;
@@ -1003,7 +1003,7 @@ out:
return -1;
}
if (gAutomapEntry.compressedData != nullptr) {
if (gAutomapEntry.compressedData != NULL) {
internal_free(gAutomapEntry.compressedData);
}
@@ -1073,7 +1073,7 @@ static void _decode_map_data(int elevation)
_obj_process_seen();
Object* object = objectFindFirstAtElevation(elevation);
while (object != nullptr) {
while (object != NULL) {
if (object->tile != -1 && (object->flags & OBJECT_SEEN) != 0) {
int contentType;
@@ -1106,10 +1106,10 @@ static int automapCreate()
memcpy(gAutomapHeader.offsets, _defam, sizeof(_defam));
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s\\%s", "MAPS", AUTOMAP_DB);
sprintf(path, "%s\\%s", "MAPS", AUTOMAP_DB);
File* stream = fileOpen(path, "wb");
if (stream == nullptr) {
if (stream == NULL) {
debugPrint("\nAUTOMAP: Error creating automap database file!\n");
return -1;
}
@@ -1129,7 +1129,7 @@ static int automapCreate()
static int _copy_file_data(File* stream1, File* stream2, int length)
{
void* buffer = internal_malloc(0xFFFF);
if (buffer == nullptr) {
if (buffer == NULL) {
return -1;
}
@@ -1161,10 +1161,10 @@ static int _copy_file_data(File* stream1, File* stream2, int length)
int automapGetHeader(AutomapHeader** automapHeaderPtr)
{
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s\\%s", "MAPS", AUTOMAP_DB);
sprintf(path, "%s\\%s", "MAPS", AUTOMAP_DB);
File* stream = fileOpen(path, "rb");
if (stream == nullptr) {
if (stream == NULL) {
debugPrint("\nAUTOMAP: Error opening database file for reading!\n");
debugPrint("Error continued: ReadAMList: path: %s", path);
return -1;

View File

@@ -1,6 +1,8 @@
#include "autorun.h"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#endif
@@ -15,7 +17,7 @@ namespace fallout {
bool autorunMutexCreate()
{
#ifdef _WIN32
gInterplayGenericAutorunMutex = CreateMutexA(nullptr, FALSE, "InterplayGenericAutorunMutex");
gInterplayGenericAutorunMutex = CreateMutexA(NULL, FALSE, "InterplayGenericAutorunMutex");
if (GetLastError() == ERROR_ALREADY_EXISTS) {
CloseHandle(gInterplayGenericAutorunMutex);
return false;
@@ -29,7 +31,7 @@ bool autorunMutexCreate()
void autorunMutexClose()
{
#ifdef _WIN32
if (gInterplayGenericAutorunMutex != nullptr) {
if (gInterplayGenericAutorunMutex != NULL) {
CloseHandle(gInterplayGenericAutorunMutex);
}
#endif

View File

@@ -51,7 +51,7 @@ bool cacheInit(Cache* cache, CacheSizeProc* sizeProc, CacheReadProc* readProc, C
cache->readProc = readProc;
cache->freeProc = freeProc;
if (cache->entries == nullptr) {
if (cache->entries == NULL) {
return false;
}
@@ -64,7 +64,7 @@ bool cacheInit(Cache* cache, CacheSizeProc* sizeProc, CacheReadProc* readProc, C
// 0x41FD50
bool cacheFree(Cache* cache)
{
if (cache == nullptr) {
if (cache == NULL) {
return false;
}
@@ -78,14 +78,14 @@ bool cacheFree(Cache* cache)
cache->entriesCapacity = 0;
cache->hits = 0;
if (cache->entries != nullptr) {
if (cache->entries != NULL) {
internal_free(cache->entries);
cache->entries = nullptr;
cache->entries = NULL;
}
cache->sizeProc = nullptr;
cache->readProc = nullptr;
cache->freeProc = nullptr;
cache->sizeProc = NULL;
cache->readProc = NULL;
cache->freeProc = NULL;
return true;
}
@@ -93,11 +93,11 @@ bool cacheFree(Cache* cache)
// 0x41FDE8
bool cacheLock(Cache* cache, int key, void** data, CacheEntry** cacheEntryPtr)
{
if (cache == nullptr || data == nullptr || cacheEntryPtr == nullptr) {
if (cache == NULL || data == NULL || cacheEntryPtr == NULL) {
return false;
}
*cacheEntryPtr = nullptr;
*cacheEntryPtr = NULL;
int index;
int rc = cacheFindIndexForKey(cache, key, &index);
@@ -148,7 +148,7 @@ bool cacheLock(Cache* cache, int key, void** data, CacheEntry** cacheEntryPtr)
// 0x4200B8
bool cacheUnlock(Cache* cache, CacheEntry* cacheEntry)
{
if (cache == nullptr || cacheEntry == nullptr) {
if (cache == NULL || cacheEntry == NULL) {
return false;
}
@@ -169,7 +169,7 @@ bool cacheUnlock(Cache* cache, CacheEntry* cacheEntry)
// 0x42012C
bool cacheFlush(Cache* cache)
{
if (cache == nullptr) {
if (cache == NULL) {
return false;
}
@@ -194,13 +194,13 @@ bool cacheFlush(Cache* cache)
}
// 0x42019C
bool cachePrintStats(Cache* cache, char* dest, size_t size)
bool cachePrintStats(Cache* cache, char* dest)
{
if (cache == nullptr || dest == nullptr) {
if (cache == NULL || dest == NULL) {
return false;
}
snprintf(dest, size, "Cache stats are disabled.%s", "\n");
sprintf(dest, "Cache stats are disabled.%s", "\n");
return true;
}
@@ -211,7 +211,7 @@ bool cachePrintStats(Cache* cache, char* dest, size_t size)
static bool cacheFetchEntryForKey(Cache* cache, int key, int* indexPtr)
{
CacheEntry* cacheEntry = (CacheEntry*)internal_malloc(sizeof(*cacheEntry));
if (cacheEntry == nullptr) {
if (cacheEntry == NULL) {
return false;
}
@@ -376,7 +376,7 @@ static bool cacheEntryInit(CacheEntry* cacheEntry)
{
cacheEntry->key = 0;
cacheEntry->size = 0;
cacheEntry->data = nullptr;
cacheEntry->data = NULL;
cacheEntry->referenceCount = 0;
cacheEntry->hits = 0;
cacheEntry->flags = 0;
@@ -389,7 +389,7 @@ static bool cacheEntryInit(CacheEntry* cacheEntry)
// 0x420740
static bool cacheEntryFree(Cache* cache, CacheEntry* cacheEntry)
{
if (cacheEntry->data != nullptr) {
if (cacheEntry->data != NULL) {
heapBlockDeallocate(&(cache->heap), &(cacheEntry->heapHandleIndex));
}
@@ -420,12 +420,12 @@ static bool cacheClean(Cache* cache)
// 0x4207D4
static bool cacheResetStatistics(Cache* cache)
{
if (cache == nullptr) {
if (cache == NULL) {
return false;
}
CacheEntry** entries = (CacheEntry**)internal_malloc(sizeof(*entries) * cache->entriesLength);
if (entries == nullptr) {
if (entries == NULL) {
return false;
}
@@ -462,7 +462,7 @@ static bool cacheEnsureSize(Cache* cache, int size)
}
CacheEntry** entries = (CacheEntry**)internal_malloc(sizeof(*entries) * cache->entriesLength);
if (entries != nullptr) {
if (entries != NULL) {
memcpy(entries, cache->entries, sizeof(*entries) * cache->entriesLength);
qsort(entries, cache->entriesLength, sizeof(*entries), cacheEntriesCompareByUsage);
@@ -562,7 +562,7 @@ static bool cacheSetCapacity(Cache* cache, int newCapacity)
}
CacheEntry** entries = (CacheEntry**)internal_realloc(cache->entries, sizeof(*cache->entries) * newCapacity);
if (entries == nullptr) {
if (entries == NULL) {
return false;
}

View File

@@ -1,8 +1,6 @@
#ifndef CACHE_H
#define CACHE_H
#include <stddef.h>
#include "heap.h"
namespace fallout {
@@ -68,7 +66,7 @@ bool cacheFree(Cache* cache);
bool cacheLock(Cache* cache, int key, void** data, CacheEntry** cacheEntryPtr);
bool cacheUnlock(Cache* cache, CacheEntry* cacheEntry);
bool cacheFlush(Cache* cache);
bool cachePrintStats(Cache* cache, char* dest, size_t size);
bool cachePrintStats(Cache* cache, char* dest);
} // namespace fallout

File diff suppressed because it is too large Load Diff

View File

@@ -9,27 +9,24 @@
#include "art.h"
#include "character_editor.h"
#include "color.h"
#include "core.h"
#include "critter.h"
#include "db.h"
#include "debug.h"
#include "draw.h"
#include "game.h"
#include "game_config.h"
#include "game_sound.h"
#include "input.h"
#include "kb.h"
#include "memory.h"
#include "message.h"
#include "mouse.h"
#include "object.h"
#include "options.h"
#include "palette.h"
#include "platform_compat.h"
#include "preferences.h"
#include "proto.h"
#include "settings.h"
#include "sfall_config.h"
#include "skill.h"
#include "stat.h"
#include "svga.h"
#include "text_font.h"
#include "trait.h"
#include "window_manager.h"
@@ -107,10 +104,10 @@ static int gPremadeCharacterCount = PREMADE_CHARACTER_COUNT;
static int gCharacterSelectorWindow = -1;
// 0x51C7FC
static unsigned char* gCharacterSelectorWindowBuffer = nullptr;
static unsigned char* gCharacterSelectorWindowBuffer = NULL;
// 0x51C800
static unsigned char* gCharacterSelectorBackground = nullptr;
static unsigned char* gCharacterSelectorBackground = NULL;
// 0x51C804
static int gCharacterSelectorWindowPreviousButton = -1;
@@ -163,13 +160,11 @@ int characterSelectorOpen()
int rc = 0;
bool done = false;
while (!done) {
sharedFpsLimiter.mark();
if (_game_user_wants_to_quit != 0) {
break;
}
int keyCode = inputGetInput();
int keyCode = _get_input();
switch (keyCode) {
case KEY_MINUS:
@@ -239,9 +234,6 @@ int characterSelectorOpen()
characterSelectorWindowRefresh();
break;
}
renderPresent();
sharedFpsLimiter.throttle();
}
paletteFadeTo(gPaletteBlack);
@@ -269,7 +261,7 @@ static bool characterSelectorWindowInit()
}
gCharacterSelectorWindowBuffer = windowGetBuffer(gCharacterSelectorWindow);
if (gCharacterSelectorWindowBuffer == nullptr) {
if (gCharacterSelectorWindowBuffer == NULL) {
return characterSelectorWindowFatalError(false);
}
@@ -287,7 +279,7 @@ static bool characterSelectorWindowInit()
CS_WINDOW_WIDTH);
gCharacterSelectorBackground = (unsigned char*)internal_malloc(CS_WINDOW_BACKGROUND_WIDTH * CS_WINDOW_BACKGROUND_HEIGHT);
if (gCharacterSelectorBackground == nullptr)
if (gCharacterSelectorBackground == NULL)
return characterSelectorWindowFatalError(false);
blitBufferToBuffer(backgroundFrmImage.getData() + CS_WINDOW_WIDTH * CS_WINDOW_BACKGROUND_Y + CS_WINDOW_BACKGROUND_X,
@@ -323,7 +315,7 @@ static bool characterSelectorWindowInit()
500,
_previousButtonNormalFrmImage.getData(),
_previousButtonPressedFrmImage.getData(),
nullptr,
NULL,
0);
if (gCharacterSelectorWindowPreviousButton == -1) {
return characterSelectorWindowFatalError(false);
@@ -353,7 +345,7 @@ static bool characterSelectorWindowInit()
501,
_nextButtonNormalFrmImage.getData(),
_nextButtonPressedFrmImage.getData(),
nullptr,
NULL,
0);
if (gCharacterSelectorWindowNextButton == -1) {
return characterSelectorWindowFatalError(false);
@@ -383,7 +375,7 @@ static bool characterSelectorWindowInit()
KEY_LOWERCASE_T,
_takeButtonNormalFrmImage.getData(),
_takeButtonPressedFrmImage.getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (gCharacterSelectorWindowTakeButton == -1) {
return characterSelectorWindowFatalError(false);
@@ -412,7 +404,7 @@ static bool characterSelectorWindowInit()
KEY_LOWERCASE_M,
_modifyButtonNormalFrmImage.getData(),
_modifyButtonPressedFrmImage.getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (gCharacterSelectorWindowModifyButton == -1) {
return characterSelectorWindowFatalError(false);
@@ -442,7 +434,7 @@ static bool characterSelectorWindowInit()
KEY_LOWERCASE_C,
_createButtonNormalFrmImage.getData(),
_createButtonPressedFrmImage.getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (gCharacterSelectorWindowCreateButton == -1) {
return characterSelectorWindowFatalError(false);
@@ -472,7 +464,7 @@ static bool characterSelectorWindowInit()
KEY_ESCAPE,
_backButtonNormalFrmImage.getData(),
_backButtonPressedFrmImage.getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (gCharacterSelectorWindowBackButton == -1) {
return characterSelectorWindowFatalError(false);
@@ -546,9 +538,9 @@ static void characterSelectorWindowFree()
_backButtonNormalFrmImage.unlock();
_backButtonPressedFrmImage.unlock();
if (gCharacterSelectorBackground != nullptr) {
if (gCharacterSelectorBackground != NULL) {
internal_free(gCharacterSelectorBackground);
gCharacterSelectorBackground = nullptr;
gCharacterSelectorBackground = NULL;
}
windowDestroy(gCharacterSelectorWindow);
@@ -559,7 +551,7 @@ static void characterSelectorWindowFree()
static bool characterSelectorWindowRefresh()
{
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s.gcd", gCustomPremadeCharacterDescriptions[gCurrentPremadeCharacter].fileName);
sprintf(path, "%s.gcd", gCustomPremadeCharacterDescriptions[gCurrentPremadeCharacter].fileName);
premadeCharactersLocalizePath(path);
if (_proto_dude_init(path) == -1) {
@@ -595,7 +587,7 @@ static bool characterSelectorWindowRenderFace()
int faceFid = buildFid(OBJ_TYPE_INTERFACE, gCustomPremadeCharacterDescriptions[gCurrentPremadeCharacter].face, 0, 0, 0);
if (faceFrmImage.lock(faceFid)) {
unsigned char* data = faceFrmImage.getData();
if (data != nullptr) {
if (data != NULL) {
int width = faceFrmImage.getWidth();
int height = faceFrmImage.getHeight();
blitBufferToBufferTrans(data, width, height, width, (gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * 23 + 27), CS_WINDOW_WIDTH);
@@ -637,13 +629,13 @@ static bool characterSelectorWindowRenderStats()
value = critterGetStat(gDude, STAT_STRENGTH);
str = statGetName(STAT_STRENGTH);
snprintf(text, sizeof(text), "%s %02d", str, value);
sprintf(text, "%s %02d", str, value);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_PRIMARY_STAT_MID_X - length, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
str = statGetValueDescription(value);
snprintf(text, sizeof(text), " %s", str);
sprintf(text, " %s", str);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_PRIMARY_STAT_MID_X, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
@@ -654,13 +646,13 @@ static bool characterSelectorWindowRenderStats()
value = critterGetStat(gDude, STAT_PERCEPTION);
str = statGetName(STAT_PERCEPTION);
snprintf(text, sizeof(text), "%s %02d", str, value);
sprintf(text, "%s %02d", str, value);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_PRIMARY_STAT_MID_X - length, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
str = statGetValueDescription(value);
snprintf(text, sizeof(text), " %s", str);
sprintf(text, " %s", str);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_PRIMARY_STAT_MID_X, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
@@ -669,15 +661,15 @@ static bool characterSelectorWindowRenderStats()
y += vh;
value = critterGetStat(gDude, STAT_ENDURANCE);
str = statGetName(STAT_ENDURANCE);
str = statGetName(STAT_PERCEPTION);
snprintf(text, sizeof(text), "%s %02d", str, value);
sprintf(text, "%s %02d", str, value);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_PRIMARY_STAT_MID_X - length, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
str = statGetValueDescription(value);
snprintf(text, sizeof(text), " %s", str);
sprintf(text, " %s", str);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_PRIMARY_STAT_MID_X, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
@@ -688,13 +680,13 @@ static bool characterSelectorWindowRenderStats()
value = critterGetStat(gDude, STAT_CHARISMA);
str = statGetName(STAT_CHARISMA);
snprintf(text, sizeof(text), "%s %02d", str, value);
sprintf(text, "%s %02d", str, value);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_PRIMARY_STAT_MID_X - length, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
str = statGetValueDescription(value);
snprintf(text, sizeof(text), " %s", str);
sprintf(text, " %s", str);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_PRIMARY_STAT_MID_X, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
@@ -705,13 +697,13 @@ static bool characterSelectorWindowRenderStats()
value = critterGetStat(gDude, STAT_INTELLIGENCE);
str = statGetName(STAT_INTELLIGENCE);
snprintf(text, sizeof(text), "%s %02d", str, value);
sprintf(text, "%s %02d", str, value);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_PRIMARY_STAT_MID_X - length, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
str = statGetValueDescription(value);
snprintf(text, sizeof(text), " %s", str);
sprintf(text, " %s", str);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_PRIMARY_STAT_MID_X, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
@@ -722,13 +714,13 @@ static bool characterSelectorWindowRenderStats()
value = critterGetStat(gDude, STAT_AGILITY);
str = statGetName(STAT_AGILITY);
snprintf(text, sizeof(text), "%s %02d", str, value);
sprintf(text, "%s %02d", str, value);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_PRIMARY_STAT_MID_X - length, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
str = statGetValueDescription(value);
snprintf(text, sizeof(text), " %s", str);
sprintf(text, " %s", str);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_PRIMARY_STAT_MID_X, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
@@ -739,13 +731,13 @@ static bool characterSelectorWindowRenderStats()
value = critterGetStat(gDude, STAT_LUCK);
str = statGetName(STAT_LUCK);
snprintf(text, sizeof(text), "%s %02d", str, value);
sprintf(text, "%s %02d", str, value);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_PRIMARY_STAT_MID_X - length, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
str = statGetValueDescription(value);
snprintf(text, sizeof(text), " %s", str);
sprintf(text, " %s", str);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_PRIMARY_STAT_MID_X, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
@@ -765,7 +757,7 @@ static bool characterSelectorWindowRenderStats()
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_SECONDARY_STAT_MID_X - length, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
value = critterGetStat(gDude, STAT_MAXIMUM_HIT_POINTS);
snprintf(text, sizeof(text), " %d/%d", critterGetHitPoints(gDude), value);
sprintf(text, " %d/%d", critterGetHitPoints(gDude), value);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_SECONDARY_STAT_MID_X, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
@@ -780,7 +772,7 @@ static bool characterSelectorWindowRenderStats()
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_SECONDARY_STAT_MID_X - length, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
value = critterGetStat(gDude, STAT_ARMOR_CLASS);
snprintf(text, sizeof(text), " %d", value);
sprintf(text, " %d", value);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_SECONDARY_STAT_MID_X, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
@@ -798,7 +790,7 @@ static bool characterSelectorWindowRenderStats()
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_SECONDARY_STAT_MID_X - length, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
value = critterGetStat(gDude, STAT_MAXIMUM_ACTION_POINTS);
snprintf(text, sizeof(text), " %d", value);
sprintf(text, " %d", value);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_SECONDARY_STAT_MID_X, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
@@ -806,14 +798,14 @@ static bool characterSelectorWindowRenderStats()
// MELEE DAMAGE
y += vh;
str = statGetName(STAT_MELEE_DAMAGE);
str = statGetName(STAT_ARMOR_CLASS);
strcpy(text, str);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_SECONDARY_STAT_MID_X - length, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
value = critterGetStat(gDude, STAT_MELEE_DAMAGE);
snprintf(text, sizeof(text), " %d", value);
value = critterGetStat(gDude, STAT_ARMOR_CLASS);
sprintf(text, " %d", value);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_SECONDARY_STAT_MID_X, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
@@ -834,7 +826,7 @@ static bool characterSelectorWindowRenderStats()
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_SECONDARY_STAT_MID_X - length, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
value = skillGetValue(gDude, skills[index]);
snprintf(text, sizeof(text), " %d%%", value);
sprintf(text, " %d%%", value);
length = fontGetStringWidth(text);
fontDrawText(gCharacterSelectorWindowBuffer + CS_WINDOW_WIDTH * y + CS_WINDOW_SECONDARY_STAT_MID_X, text, length, CS_WINDOW_WIDTH, _colorTable[992]);
@@ -866,11 +858,11 @@ static bool characterSelectorWindowRenderBio()
fontSetCurrent(101);
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s.bio", gCustomPremadeCharacterDescriptions[gCurrentPremadeCharacter].fileName);
sprintf(path, "%s.bio", gCustomPremadeCharacterDescriptions[gCurrentPremadeCharacter].fileName);
premadeCharactersLocalizePath(path);
File* stream = fileOpen(path, "rt");
if (stream != nullptr) {
if (stream != NULL) {
int y = 40;
int lineHeight = fontGetLineHeight();
@@ -901,24 +893,24 @@ void premadeCharactersInit()
{
char* fileNamesString;
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_PREMADE_CHARACTERS_FILE_NAMES_KEY, &fileNamesString);
if (fileNamesString != nullptr && *fileNamesString == '\0') {
fileNamesString = nullptr;
if (fileNamesString != NULL && *fileNamesString == '\0') {
fileNamesString = NULL;
}
char* faceFidsString;
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_PREMADE_CHARACTERS_FACE_FIDS_KEY, &faceFidsString);
if (faceFidsString != nullptr && *faceFidsString == '\0') {
faceFidsString = nullptr;
if (faceFidsString != NULL && *faceFidsString == '\0') {
faceFidsString = NULL;
}
if (fileNamesString != nullptr && faceFidsString != nullptr) {
if (fileNamesString != NULL && faceFidsString != NULL) {
int fileNamesLength = 0;
for (char* pch = fileNamesString; pch != nullptr; pch = strchr(pch + 1, ',')) {
for (char* pch = fileNamesString; pch != NULL; pch = strchr(pch + 1, ',')) {
fileNamesLength++;
}
int faceFidsLength = 0;
for (char* pch = faceFidsString; pch != nullptr; pch = strchr(pch + 1, ',')) {
for (char* pch = faceFidsString; pch != NULL; pch = strchr(pch + 1, ',')) {
faceFidsLength++;
}
@@ -929,7 +921,7 @@ void premadeCharactersInit()
char* pch;
pch = strchr(fileNamesString, ',');
if (pch != nullptr) {
if (pch != NULL) {
*pch = '\0';
}
@@ -938,22 +930,22 @@ void premadeCharactersInit()
continue;
}
snprintf(gCustomPremadeCharacterDescriptions[index].fileName, sizeof(gCustomPremadeCharacterDescriptions[index].fileName), "premade\\%s", fileNamesString);
sprintf(gCustomPremadeCharacterDescriptions[index].fileName, "premade\\%s", fileNamesString);
if (pch != nullptr) {
if (pch != NULL) {
*pch = ',';
}
fileNamesString = pch + 1;
pch = strchr(faceFidsString, ',');
if (pch != nullptr) {
if (pch != NULL) {
*pch = '\0';
}
gCustomPremadeCharacterDescriptions[index].face = atoi(faceFidsString);
if (pch != nullptr) {
if (pch != NULL) {
*pch = ',';
}
@@ -987,7 +979,11 @@ static void premadeCharactersLocalizePath(char* path)
return;
}
const char* language = settings.system.language.c_str();
char* language;
if (!configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_LANGUAGE_KEY, &language)) {
return;
}
if (compat_stricmp(language, ENGLISH) == 0) {
return;
}

View File

@@ -5,7 +5,7 @@
#include <algorithm>
#include "svga.h"
#include "core.h"
namespace fallout {
@@ -51,7 +51,7 @@ static bool _colorsInited = false;
static double gBrightness = 1.0;
// 0x51DF20
static ColorTransitionCallback* gColorPaletteTransitionCallback = nullptr;
static ColorTransitionCallback* gColorPaletteTransitionCallback = NULL;
// 0x51DF24
static MallocProc* gColorPaletteMallocProc = colorPaletteMallocDefaultImpl;
@@ -63,7 +63,7 @@ static ReallocProc* gColorPaletteReallocProc = colorPaletteReallocDefaultImpl;
static FreeProc* gColorPaletteFreeProc = colorPaletteFreeDefaultImpl;
// 0x51DF30
static ColorFileNameManger* gColorFileNameMangler = nullptr;
static ColorFileNameManger* gColorFileNameMangler = NULL;
// 0x51DF34
unsigned char _cmap[768] = {
@@ -86,13 +86,13 @@ unsigned char* _blendTable[256];
unsigned char _mappedColor[256];
// 0x6738D0
Color colorMixAddTable[256][256];
unsigned char _colorMixAddTable[65536];
// 0x6838D0
Color intensityColorTable[256][256];
unsigned char _intensityColorTable[65536];
// 0x6938D0
Color colorMixMulTable[256][256];
unsigned char _colorMixMulTable[65536];
// 0x6A38D0
unsigned char _colorTable[32768];
@@ -114,7 +114,7 @@ static ColorPaletteFileOpenProc* gColorPaletteFileOpenProc;
// 0x4C7200
static int colorPaletteFileOpen(const char* filePath, int flags)
{
if (gColorPaletteFileOpenProc != nullptr) {
if (gColorPaletteFileOpenProc != NULL) {
return gColorPaletteFileOpenProc(filePath, flags);
}
@@ -126,7 +126,7 @@ static int colorPaletteFileOpen(const char* filePath, int flags)
// 0x4C7218
static int colorPaletteFileRead(int fd, void* buffer, size_t size)
{
if (gColorPaletteFileReadProc != nullptr) {
if (gColorPaletteFileReadProc != NULL) {
return gColorPaletteFileReadProc(fd, buffer, size);
}
@@ -138,7 +138,7 @@ static int colorPaletteFileRead(int fd, void* buffer, size_t size)
// 0x4C7230
static int colorPaletteFileClose(int fd)
{
if (gColorPaletteFileCloseProc != nullptr) {
if (gColorPaletteFileCloseProc != NULL) {
return gColorPaletteFileCloseProc(fd);
}
@@ -172,19 +172,22 @@ static void colorPaletteFreeDefaultImpl(void* ptr)
}
// 0x4C72B4
int _calculateColor(int intensity, Color color)
int _calculateColor(int a1, int a2)
{
return intensityColorTable[color][intensity / 512];
int v1 = (a1 >> 9) + ((a2 & 0xFF) << 8);
return _intensityColorTable[v1];
}
// 0x4C72E0
int Color2RGB(Color c)
int _Color2RGB_(int a1)
{
int r = _cmap[3 * c] >> 1;
int g = _cmap[3 * c + 1] >> 1;
int b = _cmap[3 * c + 2] >> 1;
int v1, v2, v3;
return (r << 10) | (g << 5) | b;
v1 = _cmap[3 * a1] >> 1;
v2 = _cmap[3 * a1 + 1] >> 1;
v3 = _cmap[3 * a1 + 2] >> 1;
return (((v1 << 5) | v2) << 5) | v3;
}
// Performs animated palette transition.
@@ -193,29 +196,22 @@ int Color2RGB(Color c)
void colorPaletteFadeBetween(unsigned char* oldPalette, unsigned char* newPalette, int steps)
{
for (int step = 0; step < steps; step++) {
sharedFpsLimiter.mark();
unsigned char palette[768];
for (int index = 0; index < 768; index++) {
palette[index] = oldPalette[index] - (oldPalette[index] - newPalette[index]) * step / steps;
}
if (gColorPaletteTransitionCallback != nullptr) {
if (gColorPaletteTransitionCallback != NULL) {
if (step % 128 == 0) {
gColorPaletteTransitionCallback();
}
}
_setSystemPalette(palette);
renderPresent();
sharedFpsLimiter.throttle();
}
sharedFpsLimiter.mark();
_setSystemPalette(newPalette);
renderPresent();
sharedFpsLimiter.throttle();
}
// 0x4C73D4
@@ -263,28 +259,29 @@ void _setSystemPaletteEntries(unsigned char* palette, int start, int end)
}
// 0x4C7550
static void _setIntensityTableColor(int cc)
static void _setIntensityTableColor(int a1)
{
int shift = 0;
int v1, v2, v3, v4, v5, v6, v7, v8, v9, v10;
v5 = 0;
v10 = a1 << 8;
for (int index = 0; index < 128; index++) {
int r = (Color2RGB(cc) & 0x7C00) >> 10;
int g = (Color2RGB(cc) & 0x3E0) >> 5;
int b = (Color2RGB(cc) & 0x1F);
v1 = (_Color2RGB_(a1) & 0x7C00) >> 10;
v2 = (_Color2RGB_(a1) & 0x3E0) >> 5;
v3 = (_Color2RGB_(a1) & 0x1F);
int darkerR = ((r * shift) >> 16);
int darkerG = ((g * shift) >> 16);
int darkerB = ((b * shift) >> 16);
int darkerColor = (darkerR << 10) | (darkerG << 5) | darkerB;
intensityColorTable[cc][index] = _colorTable[darkerColor];
v4 = (((v1 * v5) >> 16) << 10) | (((v2 * v5) >> 16) << 5) | ((v3 * v5) >> 16);
_intensityColorTable[index + v10] = _colorTable[v4];
int lighterR = r + (((0x1F - r) * shift) >> 16);
int lighterG = g + (((0x1F - g) * shift) >> 16);
int lighterB = b + (((0x1F - b) * shift) >> 16);
int lighterColor = (lighterR << 10) | (lighterG << 5) | lighterB;
intensityColorTable[cc][128 + index] = _colorTable[lighterColor];
v6 = v1 + (((0x1F - v1) * v5) >> 16);
v7 = v2 + (((0x1F - v2) * v5) >> 16);
v8 = v3 + (((0x1F - v3) * v5) >> 16);
shift += 512;
v9 = (v6 << 10) | (v7 << 5) | v8;
_intensityColorTable[0x7F + index + 1 + v10] = _colorTable[v9];
v5 += 0x200;
}
}
@@ -295,7 +292,7 @@ static void _setIntensityTables()
if (_mappedColor[index] != 0) {
_setIntensityTableColor(index);
} else {
memset(intensityColorTable[index], 0, 256);
memset(_intensityColorTable + index * 256, 0, 256);
}
}
}
@@ -304,18 +301,20 @@ static void _setIntensityTables()
static void _setMixTableColor(int a1)
{
int i;
int v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19;
int v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19;
int v20, v21, v22, v23, v24, v25, v26, v27, v28, v29;
v1 = a1 << 8;
for (i = 0; i < 256; i++) {
if (_mappedColor[a1] && _mappedColor[i]) {
v2 = (Color2RGB(a1) & 0x7C00) >> 10;
v3 = (Color2RGB(a1) & 0x3E0) >> 5;
v4 = (Color2RGB(a1) & 0x1F);
v2 = (_Color2RGB_(a1) & 0x7C00) >> 10;
v3 = (_Color2RGB_(a1) & 0x3E0) >> 5;
v4 = (_Color2RGB_(a1) & 0x1F);
v5 = (Color2RGB(i) & 0x7C00) >> 10;
v6 = (Color2RGB(i) & 0x3E0) >> 5;
v7 = (Color2RGB(i) & 0x1F);
v5 = (_Color2RGB_(i) & 0x7C00) >> 10;
v6 = (_Color2RGB_(i) & 0x3E0) >> 5;
v7 = (_Color2RGB_(i) & 0x1F);
v8 = v2 + v5;
v9 = v3 + v6;
@@ -360,29 +359,29 @@ static void _setMixTableColor(int a1)
v12 = _calculateColor(v19, v18);
}
colorMixAddTable[a1][i] = v12;
_colorMixAddTable[v1 + i] = v12;
v20 = (Color2RGB(a1) & 0x7C00) >> 10;
v21 = (Color2RGB(a1) & 0x3E0) >> 5;
v22 = (Color2RGB(a1) & 0x1F);
v20 = (_Color2RGB_(a1) & 0x7C00) >> 10;
v21 = (_Color2RGB_(a1) & 0x3E0) >> 5;
v22 = (_Color2RGB_(a1) & 0x1F);
v23 = (Color2RGB(i) & 0x7C00) >> 10;
v24 = (Color2RGB(i) & 0x3E0) >> 5;
v25 = (Color2RGB(i) & 0x1F);
v23 = (_Color2RGB_(i) & 0x7C00) >> 10;
v24 = (_Color2RGB_(i) & 0x3E0) >> 5;
v25 = (_Color2RGB_(i) & 0x1F);
v26 = (v20 * v23) >> 5;
v27 = (v21 * v24) >> 5;
v28 = (v22 * v25) >> 5;
v29 = (v26 << 10) | (v27 << 5) | v28;
colorMixMulTable[a1][i] = _colorTable[v29];
_colorMixMulTable[v1 + i] = _colorTable[v29];
} else {
if (_mappedColor[i]) {
colorMixAddTable[a1][i] = i;
colorMixMulTable[a1][i] = i;
_colorMixAddTable[v1 + i] = i;
_colorMixMulTable[v1 + i] = i;
} else {
colorMixAddTable[a1][i] = a1;
colorMixMulTable[a1][i] = a1;
_colorMixAddTable[v1 + i] = a1;
_colorMixMulTable[v1 + i] = a1;
}
}
}
@@ -391,7 +390,7 @@ static void _setMixTableColor(int a1)
// 0x4C78E4
bool colorPaletteLoad(const char* path)
{
if (gColorFileNameMangler != nullptr) {
if (gColorFileNameMangler != NULL) {
path = gColorFileNameMangler(path);
}
@@ -439,15 +438,15 @@ bool colorPaletteLoad(const char* path)
// NOTE: The value is "NEWC". Original code uses cmp opcode, not stricmp,
// or comparing characters one-by-one.
if (type == 'NEWC') {
if (type == 0x4E455743) {
// NOTE: Uninline.
colorPaletteFileRead(fd, intensityColorTable, sizeof(intensityColorTable));
colorPaletteFileRead(fd, _intensityColorTable, 0x10000);
// NOTE: Uninline.
colorPaletteFileRead(fd, colorMixAddTable, sizeof(colorMixAddTable));
colorPaletteFileRead(fd, _colorMixAddTable, 0x10000);
// NOTE: Uninline.
colorPaletteFileRead(fd, colorMixMulTable, sizeof(colorMixMulTable));
colorPaletteFileRead(fd, _colorMixMulTable, 0x10000);
} else {
_setIntensityTables();
@@ -480,9 +479,9 @@ static void _buildBlendTable(unsigned char* ptr, unsigned char ch)
beg = ptr;
r = (Color2RGB(ch) & 0x7C00) >> 10;
g = (Color2RGB(ch) & 0x3E0) >> 5;
b = (Color2RGB(ch) & 0x1F);
r = (_Color2RGB_(ch) & 0x7C00) >> 10;
g = (_Color2RGB_(ch) & 0x3E0) >> 5;
b = (_Color2RGB_(ch) & 0x1F);
for (i = 0; i < 256; i++) {
ptr[i] = i;
@@ -501,9 +500,9 @@ static void _buildBlendTable(unsigned char* ptr, unsigned char ch)
for (j = 0; j < 7; j++) {
for (i = 0; i < 256; i++) {
v12 = (Color2RGB(i) & 0x7C00) >> 10;
v14 = (Color2RGB(i) & 0x3E0) >> 5;
v16 = (Color2RGB(i) & 0x1F);
v12 = (_Color2RGB_(i) & 0x7C00) >> 10;
v14 = (_Color2RGB_(i) & 0x3E0) >> 5;
v16 = (_Color2RGB_(i) & 0x1F);
int index = 0;
index |= (r_2 + v12 * v31) / 7 << 10;
index |= (g_2 + v14 * v31) / 7 << 5;
@@ -547,7 +546,7 @@ unsigned char* _getColorBlendTable(int ch)
{
unsigned char* ptr;
if (_blendTable[ch] == nullptr) {
if (_blendTable[ch] == NULL) {
ptr = (unsigned char*)gColorPaletteMallocProc(4100);
*(int*)ptr = 1;
_blendTable[ch] = ptr + 4;
@@ -564,12 +563,12 @@ unsigned char* _getColorBlendTable(int ch)
void _freeColorBlendTable(int a1)
{
unsigned char* v2 = _blendTable[a1];
if (v2 != nullptr) {
if (v2 != NULL) {
int* count = (int*)(v2 - sizeof(int));
*count -= 1;
if (*count == 0) {
gColorPaletteFreeProc(count);
_blendTable[a1] = nullptr;
_blendTable[a1] = NULL;
}
}
}
@@ -636,7 +635,7 @@ bool colorPopColorPalette()
memcpy(_colorTable, entry->colorTable, sizeof(_colorTable));
free(entry);
gColorPaletteStack[gColorPaletteStackSize] = nullptr;
gColorPaletteStack[gColorPaletteStackSize] = NULL;
_setIntensityTables();

View File

@@ -5,7 +5,6 @@
namespace fallout {
typedef unsigned char Color;
typedef const char*(ColorFileNameManger)(const char*);
typedef void(ColorTransitionCallback)();
@@ -19,14 +18,14 @@ extern unsigned char _systemCmap[256 * 3];
extern unsigned char _currentGammaTable[64];
extern unsigned char* _blendTable[256];
extern unsigned char _mappedColor[256];
extern Color colorMixAddTable[256][256];
extern Color intensityColorTable[256][256];
extern Color colorMixMulTable[256][256];
extern unsigned char _colorMixAddTable[65536];
extern unsigned char _intensityColorTable[65536];
extern unsigned char _colorMixMulTable[65536];
extern unsigned char _colorTable[32768];
void colorPaletteSetFileIO(ColorPaletteFileOpenProc* openProc, ColorPaletteFileReadProc* readProc, ColorPaletteCloseProc* closeProc);
int _calculateColor(int intensity, Color color);
int Color2RGB(Color c);
int _calculateColor(int a1, int a2);
int _Color2RGB_(int a1);
void colorPaletteFadeBetween(unsigned char* oldPalette, unsigned char* newPalette, int steps);
void colorPaletteSetTransitionCallback(ColorTransitionCallback* callback);
void _setSystemPalette(unsigned char* palette);

File diff suppressed because it is too large Load Diff

View File

@@ -33,14 +33,14 @@ void _combat_update_critter_outline_for_los(Object* critter, bool a2);
void _combat_over_from_load();
void _combat_give_exps(int exp_points);
void _combat_turn_run();
void _combat(CombatStartData* csd);
void attackInit(Attack* attack, Object* attacker, Object* defender, int hitMode, int hitLocation);
int _combat_attack(Object* attacker, Object* defender, int hitMode, int hitLocation);
int _combat_bullet_start(const Object* attacker, const Object* target);
void _compute_explosion_on_extras(Attack* attack, bool isFromAttacker, bool isGrenade, bool noDamage);
void _combat(STRUCT_664980* attack);
void attackInit(Attack* attack, Object* a2, Object* a3, int a4, int a5);
int _combat_attack(Object* a1, Object* a2, int a3, int a4);
int _combat_bullet_start(const Object* a1, const Object* a2);
void _compute_explosion_on_extras(Attack* attack, int a2, bool isGrenade, int a4);
int _determine_to_hit(Object* a1, Object* a2, int hitLocation, int hitMode);
int _determine_to_hit_no_range(Object* attacker, Object* defender, int hitLocation, int hitMode, unsigned char* a5);
int _determine_to_hit_from_tile(Object* attacker, int tile, Object* defender, int hitLocation, int hitMode);
int _determine_to_hit_no_range(Object* a1, Object* a2, int a3, int a4, unsigned char* a5);
int _determine_to_hit_from_tile(Object* a1, int a2, Object* a3, int a4, int a5);
void attackComputeDeathFlags(Attack* attack);
void _apply_damage(Attack* attack, bool animated);
void _combat_display(Attack* attack);
@@ -48,17 +48,16 @@ void _combat_anim_begin();
void _combat_anim_finished();
int _combat_check_bad_shot(Object* attacker, Object* defender, int hitMode, bool aiming);
bool _combat_to_hit(Object* target, int* accuracy);
void _combat_attack_this(Object* target);
void _combat_attack_this(Object* a1);
void _combat_outline_on();
void _combat_outline_off();
void _combat_highlight_change();
bool _combat_is_shot_blocked(Object* sourceObj, int from, int to, Object* targetObj, int* numCrittersOnLof);
bool _combat_is_shot_blocked(Object* a1, int from, int to, Object* a4, int* a5);
int _combat_player_knocked_out_by();
int _combat_explode_scenery(Object* a1, Object* a2);
void _combat_delete_critter(Object* obj);
void _combatKillCritterOutsideCombat(Object* critter_obj, char* msg);
int combatGetTargetHighlight();
int criticalsGetValue(int killType, int hitLocation, int effect, int dataMember);
void criticalsSetValue(int killType, int hitLocation, int effect, int dataMember, int value);
void criticalsResetValue(int killType, int hitLocation, int effect, int dataMember);
@@ -71,10 +70,6 @@ int unarmedGetKickHitMode(bool isSecondary);
bool unarmedIsPenetrating(int hitMode);
bool damageModGetBonusHthDamageFix();
bool damageModGetDisplayBonusDamage();
int combat_get_hit_location_penalty(int hit_location);
void combat_set_hit_location_penalty(int hit_location, int penalty);
void combat_reset_hit_location_penalty();
Attack* combat_get_data();
static inline bool isInCombat()
{

File diff suppressed because it is too large Load Diff

View File

@@ -30,8 +30,6 @@ void aiReset();
int aiExit();
int aiLoad(File* stream);
int aiSave(File* stream);
int combat_ai_num();
char* combat_ai_name(int packet_num);
int aiGetAreaAttackMode(Object* obj);
int aiGetRunAwayMode(Object* obj);
int aiGetBestWeapon(Object* obj);
@@ -46,10 +44,10 @@ int aiSetAttackWho(Object* critter, int attackWho);
int aiSetChemUse(Object* critter, int chemUse);
int aiGetDisposition(Object* obj);
int aiSetDisposition(Object* obj, int a2);
int _caiSetupTeamCombat(Object* attackerTeam, Object* defenderTeam);
int _caiTeamCombatInit(Object** crittersList, int crittersListLength);
int _caiSetupTeamCombat(Object* a1, Object* a2);
int _caiTeamCombatInit(Object** a1, int a2);
void _caiTeamCombatExit();
Object* _ai_search_inven_weap(Object* critter, bool checkRequiredActionPoints, Object* defender);
Object* _ai_search_inven_weap(Object* critter, int a2, Object* a3);
Object* _ai_search_inven_armor(Object* critter);
int _cAIPrepWeaponItem(Object* critter, Object* item);
void aiAttemptWeaponReload(Object* critter, int animate);
@@ -61,10 +59,10 @@ bool _combatai_want_to_join(Object* a1);
bool _combatai_want_to_stop(Object* a1);
int critterSetTeam(Object* obj, int team);
int critterSetAiPacket(Object* object, int aiPacket);
int _combatai_msg(Object* critter, Attack* attack, int type, int delay);
int _combatai_msg(Object* a1, Attack* attack, int a3, int a4);
Object* _combat_ai_random_target(Attack* attack);
void _combatai_check_retaliation(Object* a1, Object* a2);
bool isWithinPerception(Object* a1, Object* a2);
int _combatai_check_retaliation(Object* a1, Object* a2);
bool objectCanHearObject(Object* a1, Object* a2);
void aiMessageListReloadIfNeeded();
void _combatai_notify_onlookers(Object* a1);
void _combatai_notify_friends(Object* a1);

View File

@@ -86,7 +86,7 @@ typedef enum HitLocation {
HIT_LOCATION_SPECIFIC_COUNT = HIT_LOCATION_COUNT - 1,
} HitLocation;
typedef struct CombatStartData {
typedef struct STRUCT_664980 {
Object* attacker;
Object* defender;
int actionPointsBonus;
@@ -94,10 +94,10 @@ typedef struct CombatStartData {
int damageBonus;
int minDamage;
int maxDamage;
int overrideAttackResults;
int attackerResults;
int targetResults;
} CombatStartData;
int field_1C; // probably bool, indicating field_20 and field_24 used
int field_20; // flags on attacker
int field_24; // flags on defender
} STRUCT_664980;
typedef struct Attack {
Object* attacker;

View File

@@ -31,11 +31,11 @@ static char gConfigLastSectionKey[CONFIG_FILE_MAX_LINE_LENGTH] = "unknown";
// 0x42BD90
bool configInit(Config* config)
{
if (config == nullptr) {
if (config == NULL) {
return false;
}
if (dictionaryInit(config, CONFIG_INITIAL_CAPACITY, sizeof(ConfigSection), nullptr) != 0) {
if (dictionaryInit(config, CONFIG_INITIAL_CAPACITY, sizeof(ConfigSection), NULL) != 0) {
return false;
}
@@ -45,7 +45,7 @@ bool configInit(Config* config)
// 0x42BDBC
void configFree(Config* config)
{
if (config == nullptr) {
if (config == NULL) {
return;
}
@@ -58,7 +58,7 @@ void configFree(Config* config)
char** value = (char**)keyValueEntry->value;
internal_free(*value);
*value = nullptr;
*value = NULL;
}
dictionaryFree(section);
@@ -78,7 +78,7 @@ void configFree(Config* config)
// 0x42BE38
bool configParseCommandLineArguments(Config* config, int argc, char** argv)
{
if (config == nullptr) {
if (config == NULL) {
return false;
}
@@ -88,7 +88,7 @@ bool configParseCommandLineArguments(Config* config, int argc, char** argv)
// Find opening bracket.
pch = strchr(string, '[');
if (pch == nullptr) {
if (pch == NULL) {
continue;
}
@@ -96,7 +96,7 @@ bool configParseCommandLineArguments(Config* config, int argc, char** argv)
// Find closing bracket.
pch = strchr(sectionKey, ']');
if (pch == nullptr) {
if (pch == NULL) {
continue;
}
@@ -120,7 +120,7 @@ bool configParseCommandLineArguments(Config* config, int argc, char** argv)
// 0x42BF48
bool configGetString(Config* config, const char* sectionKey, const char* key, char** valuePtr)
{
if (config == nullptr || sectionKey == nullptr || key == nullptr || valuePtr == nullptr) {
if (config == NULL || sectionKey == NULL || key == NULL || valuePtr == NULL) {
return false;
}
@@ -146,7 +146,7 @@ bool configGetString(Config* config, const char* sectionKey, const char* key, ch
// 0x42BF90
bool configSetString(Config* config, const char* sectionKey, const char* key, const char* value)
{
if (config == nullptr || sectionKey == nullptr || key == nullptr || value == nullptr) {
if (config == NULL || sectionKey == NULL || key == NULL || value == NULL) {
return false;
}
@@ -167,13 +167,13 @@ bool configSetString(Config* config, const char* sectionKey, const char* key, co
char** existingValue = (char**)keyValueEntry->value;
internal_free(*existingValue);
*existingValue = nullptr;
*existingValue = NULL;
dictionaryRemoveValue(section, key);
}
char* valueCopy = internal_strdup(value);
if (valueCopy == nullptr) {
if (valueCopy == NULL) {
return false;
}
@@ -188,7 +188,7 @@ bool configSetString(Config* config, const char* sectionKey, const char* key, co
// 0x42C05C
bool configGetInt(Config* config, const char* sectionKey, const char* key, int* valuePtr, unsigned char base /* = 0 */)
{
if (valuePtr == nullptr) {
if (valuePtr == NULL) {
return false;
}
@@ -220,7 +220,7 @@ bool configGetInt(Config* config, const char* sectionKey, const char* key, int*
// 0x42C090
bool configGetIntList(Config* config, const char* sectionKey, const char* key, int* arr, int count)
{
if (arr == nullptr || count < 2) {
if (arr == NULL || count < 2) {
return false;
}
@@ -234,7 +234,7 @@ bool configGetIntList(Config* config, const char* sectionKey, const char* key, i
while (1) {
char* pch = strchr(string, ',');
if (pch == nullptr) {
if (pch == NULL) {
break;
}
@@ -248,14 +248,12 @@ bool configGetIntList(Config* config, const char* sectionKey, const char* key, i
string = pch + 1;
}
// SFALL: Fix getting last item in a list if the list has less than the
// requested number of values (for `chem_primary_desire`).
if (count > 0) {
if (count <= 1) {
*arr = atoi(string);
count--;
return true;
}
return count == 0;
return false;
}
// 0x42C160
@@ -272,7 +270,7 @@ bool configSetInt(Config* config, const char* sectionKey, const char* key, int v
// 0x42C280
bool configRead(Config* config, const char* filePath, bool isDb)
{
if (config == nullptr || filePath == nullptr) {
if (config == NULL || filePath == NULL) {
return false;
}
@@ -280,28 +278,24 @@ bool configRead(Config* config, const char* filePath, bool isDb)
if (isDb) {
File* stream = fileOpen(filePath, "rb");
// CE: Return `false` if file does not exists in database.
if (stream == nullptr) {
return false;
if (stream != NULL) {
while (fileReadString(string, sizeof(string), stream) != NULL) {
configParseLine(config, string);
}
fileClose(stream);
}
while (fileReadString(string, sizeof(string), stream) != nullptr) {
configParseLine(config, string);
}
fileClose(stream);
} else {
FILE* stream = compat_fopen(filePath, "rt");
if (stream != NULL) {
while (fgets(string, sizeof(string), stream) != NULL) {
configParseLine(config, string);
}
// CE: Return `false` if file does not exists on the file system.
if (stream == nullptr) {
return false;
fclose(stream);
}
while (compat_fgets(string, sizeof(string), stream) != nullptr) {
configParseLine(config, string);
}
fclose(stream);
// FIXME: This function returns `true` even if the file was not actually
// read. I'm pretty sure it's bug.
}
return true;
@@ -312,13 +306,13 @@ bool configRead(Config* config, const char* filePath, bool isDb)
// 0x42C324
bool configWrite(Config* config, const char* filePath, bool isDb)
{
if (config == nullptr || filePath == nullptr) {
if (config == NULL || filePath == NULL) {
return false;
}
if (isDb) {
File* stream = fileOpen(filePath, "wt");
if (stream == nullptr) {
if (stream == NULL) {
return false;
}
@@ -338,7 +332,7 @@ bool configWrite(Config* config, const char* filePath, bool isDb)
fileClose(stream);
} else {
FILE* stream = compat_fopen(filePath, "wt");
if (stream == nullptr) {
if (stream == NULL) {
return false;
}
@@ -381,33 +375,18 @@ static bool configParseLine(Config* config, char* string)
// Find comment marker and truncate the string.
pch = strchr(string, ';');
if (pch != nullptr) {
if (pch != NULL) {
*pch = '\0';
}
// CE: Original implementation treats any line with brackets as section key.
// The problem can be seen when loading Olympus settings (ddraw.ini), which
// contains the following line:
//
// ```ini
// VersionString=Olympus 2207 [Complete].
// ```
//
// It thinks that [Complete] is a start of new section, and puts remaining
// keys there.
// Skip leading whitespace.
while (isspace(static_cast<unsigned char>(*string))) {
string++;
}
// Check if it's a section key.
if (*string == '[') {
char* sectionKey = string + 1;
// Find opening bracket.
pch = strchr(string, '[');
if (pch != NULL) {
char* sectionKey = pch + 1;
// Find closing bracket.
pch = strchr(sectionKey, ']');
if (pch != nullptr) {
if (pch != NULL) {
*pch = '\0';
strcpy(gConfigLastSectionKey, sectionKey);
return configTrimString(gConfigLastSectionKey);
@@ -431,13 +410,13 @@ static bool configParseLine(Config* config, char* string)
// 0x42C594
static bool configParseKeyValue(char* string, char* key, char* value)
{
if (string == nullptr || key == nullptr || value == nullptr) {
if (string == NULL || key == NULL || value == NULL) {
return false;
}
// Find equals character.
char* pch = strchr(string, '=');
if (pch == nullptr) {
if (pch == NULL) {
return false;
}
@@ -462,7 +441,7 @@ static bool configParseKeyValue(char* string, char* key, char* value)
// 0x42C638
static bool configEnsureSectionExists(Config* config, const char* sectionKey)
{
if (config == nullptr || sectionKey == nullptr) {
if (config == NULL || sectionKey == NULL) {
return false;
}
@@ -472,7 +451,7 @@ static bool configEnsureSectionExists(Config* config, const char* sectionKey)
}
ConfigSection section;
if (dictionaryInit(&section, CONFIG_INITIAL_CAPACITY, sizeof(char**), nullptr) == -1) {
if (dictionaryInit(&section, CONFIG_INITIAL_CAPACITY, sizeof(char**), NULL) == -1) {
return false;
}
@@ -488,11 +467,11 @@ static bool configEnsureSectionExists(Config* config, const char* sectionKey)
// 0x42C698
static bool configTrimString(char* string)
{
if (string == nullptr) {
if (string == NULL) {
return false;
}
size_t length = strlen(string);
int length = strlen(string);
if (length == 0) {
return true;
}
@@ -500,7 +479,7 @@ static bool configTrimString(char* string)
// Starting from the end of the string, loop while it's a whitespace and
// decrement string length.
char* pch = string + length - 1;
while (length != 0 && isspace(static_cast<unsigned char>(*pch))) {
while (length != 0 && isspace(*pch)) {
length--;
pch--;
}
@@ -511,7 +490,7 @@ static bool configTrimString(char* string)
// Starting from the beginning of the string loop while it's a whitespace
// and decrement string length.
pch = string;
while (isspace(static_cast<unsigned char>(*pch))) {
while (isspace(*pch)) {
pch++;
length--;
}
@@ -525,7 +504,7 @@ static bool configTrimString(char* string)
// 0x42C718
bool configGetDouble(Config* config, const char* sectionKey, const char* key, double* valuePtr)
{
if (valuePtr == nullptr) {
if (valuePtr == NULL) {
return false;
}
@@ -534,7 +513,7 @@ bool configGetDouble(Config* config, const char* sectionKey, const char* key, do
return false;
}
*valuePtr = strtod(stringValue, nullptr);
*valuePtr = strtod(stringValue, NULL);
return true;
}
@@ -543,7 +522,7 @@ bool configGetDouble(Config* config, const char* sectionKey, const char* key, do
bool configSetDouble(Config* config, const char* sectionKey, const char* key, double value)
{
char stringValue[32];
snprintf(stringValue, sizeof(stringValue), "%.6f", value);
sprintf(stringValue, "%.6f", value);
return configSetString(config, sectionKey, key, stringValue);
}
@@ -551,7 +530,7 @@ bool configSetDouble(Config* config, const char* sectionKey, const char* key, do
// NOTE: Boolean-typed variant of [configGetInt].
bool configGetBool(Config* config, const char* sectionKey, const char* key, bool* valuePtr)
{
if (valuePtr == nullptr) {
if (valuePtr == NULL) {
return false;
}

File diff suppressed because it is too large Load Diff

703
src/core.h Normal file
View File

@@ -0,0 +1,703 @@
#ifndef CORE_H
#define CORE_H
#include <SDL.h>
#include "db.h"
#include "dinput.h"
#include "geometry.h"
#include "window.h"
namespace fallout {
#define MOUSE_DEFAULT_CURSOR_WIDTH 8
#define MOUSE_DEFAULT_CURSOR_HEIGHT 8
#define MOUSE_DEFAULT_CURSOR_SIZE (MOUSE_DEFAULT_CURSOR_WIDTH * MOUSE_DEFAULT_CURSOR_HEIGHT)
#define MOUSE_STATE_LEFT_BUTTON_DOWN 0x01
#define MOUSE_STATE_RIGHT_BUTTON_DOWN 0x02
#define MOUSE_EVENT_LEFT_BUTTON_DOWN 0x01
#define MOUSE_EVENT_RIGHT_BUTTON_DOWN 0x02
#define MOUSE_EVENT_LEFT_BUTTON_REPEAT 0x04
#define MOUSE_EVENT_RIGHT_BUTTON_REPEAT 0x08
#define MOUSE_EVENT_LEFT_BUTTON_UP 0x10
#define MOUSE_EVENT_RIGHT_BUTTON_UP 0x20
#define MOUSE_EVENT_ANY_BUTTON_DOWN (MOUSE_EVENT_LEFT_BUTTON_DOWN | MOUSE_EVENT_RIGHT_BUTTON_DOWN)
#define MOUSE_EVENT_ANY_BUTTON_REPEAT (MOUSE_EVENT_LEFT_BUTTON_REPEAT | MOUSE_EVENT_RIGHT_BUTTON_REPEAT)
#define MOUSE_EVENT_ANY_BUTTON_UP (MOUSE_EVENT_LEFT_BUTTON_UP | MOUSE_EVENT_RIGHT_BUTTON_UP)
#define MOUSE_EVENT_LEFT_BUTTON_DOWN_REPEAT (MOUSE_EVENT_LEFT_BUTTON_DOWN | MOUSE_EVENT_LEFT_BUTTON_REPEAT)
#define MOUSE_EVENT_RIGHT_BUTTON_DOWN_REPEAT (MOUSE_EVENT_RIGHT_BUTTON_DOWN | MOUSE_EVENT_RIGHT_BUTTON_REPEAT)
#define MOUSE_EVENT_WHEEL 0x40
#define BUTTON_REPEAT_TIME 250
#define KEY_STATE_UP 0
#define KEY_STATE_DOWN 1
#define KEY_STATE_REPEAT 2
#define MODIFIER_KEY_STATE_NUM_LOCK 0x01
#define MODIFIER_KEY_STATE_CAPS_LOCK 0x02
#define MODIFIER_KEY_STATE_SCROLL_LOCK 0x04
#define KEYBOARD_EVENT_MODIFIER_CAPS_LOCK 0x0001
#define KEYBOARD_EVENT_MODIFIER_NUM_LOCK 0x0002
#define KEYBOARD_EVENT_MODIFIER_SCROLL_LOCK 0x0004
#define KEYBOARD_EVENT_MODIFIER_LEFT_SHIFT 0x0008
#define KEYBOARD_EVENT_MODIFIER_RIGHT_SHIFT 0x0010
#define KEYBOARD_EVENT_MODIFIER_LEFT_ALT 0x0020
#define KEYBOARD_EVENT_MODIFIER_RIGHT_ALT 0x0040
#define KEYBOARD_EVENT_MODIFIER_LEFT_CONTROL 0x0080
#define KEYBOARD_EVENT_MODIFIER_RIGHT_CONTROL 0x0100
#define KEYBOARD_EVENT_MODIFIER_ANY_SHIFT (KEYBOARD_EVENT_MODIFIER_LEFT_SHIFT | KEYBOARD_EVENT_MODIFIER_RIGHT_SHIFT)
#define KEYBOARD_EVENT_MODIFIER_ANY_ALT (KEYBOARD_EVENT_MODIFIER_LEFT_ALT | KEYBOARD_EVENT_MODIFIER_RIGHT_ALT)
#define KEYBOARD_EVENT_MODIFIER_ANY_CONTROL (KEYBOARD_EVENT_MODIFIER_LEFT_CONTROL | KEYBOARD_EVENT_MODIFIER_RIGHT_CONTROL)
#define KEY_QUEUE_SIZE 64
typedef enum Key {
KEY_ESCAPE = '\x1b',
KEY_TAB = '\x09',
KEY_BACKSPACE = '\x08',
KEY_RETURN = '\r',
KEY_SPACE = ' ',
KEY_EXCLAMATION = '!',
KEY_QUOTE = '"',
KEY_NUMBER_SIGN = '#',
KEY_DOLLAR = '$',
KEY_PERCENT = '%',
KEY_AMPERSAND = '&',
KEY_SINGLE_QUOTE = '\'',
KEY_PAREN_LEFT = '(',
KEY_PAREN_RIGHT = ')',
KEY_ASTERISK = '*',
KEY_PLUS = '+',
KEY_COMMA = ',',
KEY_MINUS = '-',
KEY_DOT = '.',
KEY_SLASH = '/',
KEY_0 = '0',
KEY_1 = '1',
KEY_2 = '2',
KEY_3 = '3',
KEY_4 = '4',
KEY_5 = '5',
KEY_6 = '6',
KEY_7 = '7',
KEY_8 = '8',
KEY_9 = '9',
KEY_COLON = ':',
KEY_SEMICOLON = ';',
KEY_LESS = '<',
KEY_EQUAL = '=',
KEY_GREATER = '>',
KEY_QUESTION = '?',
KEY_AT = '@',
KEY_UPPERCASE_A = 'A',
KEY_UPPERCASE_B = 'B',
KEY_UPPERCASE_C = 'C',
KEY_UPPERCASE_D = 'D',
KEY_UPPERCASE_E = 'E',
KEY_UPPERCASE_F = 'F',
KEY_UPPERCASE_G = 'G',
KEY_UPPERCASE_H = 'H',
KEY_UPPERCASE_I = 'I',
KEY_UPPERCASE_J = 'J',
KEY_UPPERCASE_K = 'K',
KEY_UPPERCASE_L = 'L',
KEY_UPPERCASE_M = 'M',
KEY_UPPERCASE_N = 'N',
KEY_UPPERCASE_O = 'O',
KEY_UPPERCASE_P = 'P',
KEY_UPPERCASE_Q = 'Q',
KEY_UPPERCASE_R = 'R',
KEY_UPPERCASE_S = 'S',
KEY_UPPERCASE_T = 'T',
KEY_UPPERCASE_U = 'U',
KEY_UPPERCASE_V = 'V',
KEY_UPPERCASE_W = 'W',
KEY_UPPERCASE_X = 'X',
KEY_UPPERCASE_Y = 'Y',
KEY_UPPERCASE_Z = 'Z',
KEY_BRACKET_LEFT = '[',
KEY_BACKSLASH = '\\',
KEY_BRACKET_RIGHT = ']',
KEY_CARET = '^',
KEY_UNDERSCORE = '_',
KEY_GRAVE = '`',
KEY_LOWERCASE_A = 'a',
KEY_LOWERCASE_B = 'b',
KEY_LOWERCASE_C = 'c',
KEY_LOWERCASE_D = 'd',
KEY_LOWERCASE_E = 'e',
KEY_LOWERCASE_F = 'f',
KEY_LOWERCASE_G = 'g',
KEY_LOWERCASE_H = 'h',
KEY_LOWERCASE_I = 'i',
KEY_LOWERCASE_J = 'j',
KEY_LOWERCASE_K = 'k',
KEY_LOWERCASE_L = 'l',
KEY_LOWERCASE_M = 'm',
KEY_LOWERCASE_N = 'n',
KEY_LOWERCASE_O = 'o',
KEY_LOWERCASE_P = 'p',
KEY_LOWERCASE_Q = 'q',
KEY_LOWERCASE_R = 'r',
KEY_LOWERCASE_S = 's',
KEY_LOWERCASE_T = 't',
KEY_LOWERCASE_U = 'u',
KEY_LOWERCASE_V = 'v',
KEY_LOWERCASE_W = 'w',
KEY_LOWERCASE_X = 'x',
KEY_LOWERCASE_Y = 'y',
KEY_LOWERCASE_Z = 'z',
KEY_BRACE_LEFT = '{',
KEY_BAR = '|',
KEY_BRACE_RIGHT = '}',
KEY_TILDE = '~',
KEY_DEL = 127,
KEY_136 = 136,
KEY_146 = 146,
KEY_149 = 149,
KEY_150 = 150,
KEY_151 = 151,
KEY_152 = 152,
KEY_161 = 161,
KEY_163 = 163,
KEY_164 = 164,
KEY_166 = 166,
KEY_168 = 168,
KEY_167 = 167,
KEY_170 = 170,
KEY_172 = 172,
KEY_176 = 176,
KEY_178 = 178,
KEY_179 = 179,
KEY_180 = 180,
KEY_181 = 181,
KEY_186 = 186,
KEY_191 = 191,
KEY_196 = 196,
KEY_199 = 199,
KEY_209 = 209,
KEY_214 = 214,
KEY_215 = 215,
KEY_220 = 220,
KEY_223 = 223,
KEY_224 = 224,
KEY_228 = 228,
KEY_231 = 231,
KEY_232 = 232,
KEY_233 = 233,
KEY_241 = 241,
KEY_246 = 246,
KEY_247 = 247,
KEY_249 = 249,
KEY_252 = 252,
KEY_ALT_Q = 272,
KEY_ALT_W = 273,
KEY_ALT_E = 274,
KEY_ALT_R = 275,
KEY_ALT_T = 276,
KEY_ALT_Y = 277,
KEY_ALT_U = 278,
KEY_ALT_I = 279,
KEY_ALT_O = 280,
KEY_ALT_P = 281,
KEY_ALT_A = 286,
KEY_ALT_S = 287,
KEY_ALT_D = 288,
KEY_ALT_F = 289,
KEY_ALT_G = 290,
KEY_ALT_H = 291,
KEY_ALT_J = 292,
KEY_ALT_K = 293,
KEY_ALT_L = 294,
KEY_ALT_Z = 300,
KEY_ALT_X = 301,
KEY_ALT_C = 302,
KEY_ALT_V = 303,
KEY_ALT_B = 304,
KEY_ALT_N = 305,
KEY_ALT_M = 306,
KEY_CTRL_Q = 17,
KEY_CTRL_W = 23,
KEY_CTRL_E = 5,
KEY_CTRL_R = 18,
KEY_CTRL_T = 20,
KEY_CTRL_Y = 25,
KEY_CTRL_U = 21,
KEY_CTRL_I = 9,
KEY_CTRL_O = 15,
KEY_CTRL_P = 16,
KEY_CTRL_A = 1,
KEY_CTRL_S = 19,
KEY_CTRL_D = 4,
KEY_CTRL_F = 6,
KEY_CTRL_G = 7,
KEY_CTRL_H = 8,
KEY_CTRL_J = 10,
KEY_CTRL_K = 11,
KEY_CTRL_L = 12,
KEY_CTRL_Z = 26,
KEY_CTRL_X = 24,
KEY_CTRL_C = 3,
KEY_CTRL_V = 22,
KEY_CTRL_B = 2,
KEY_CTRL_N = 14,
KEY_CTRL_M = 13,
KEY_F1 = 315,
KEY_F2 = 316,
KEY_F3 = 317,
KEY_F4 = 318,
KEY_F5 = 319,
KEY_F6 = 320,
KEY_F7 = 321,
KEY_F8 = 322,
KEY_F9 = 323,
KEY_F10 = 324,
KEY_F11 = 389,
KEY_F12 = 390,
KEY_SHIFT_F1 = 340,
KEY_SHIFT_F2 = 341,
KEY_SHIFT_F3 = 342,
KEY_SHIFT_F4 = 343,
KEY_SHIFT_F5 = 344,
KEY_SHIFT_F6 = 345,
KEY_SHIFT_F7 = 346,
KEY_SHIFT_F8 = 347,
KEY_SHIFT_F9 = 348,
KEY_SHIFT_F10 = 349,
KEY_SHIFT_F11 = 391,
KEY_SHIFT_F12 = 392,
KEY_CTRL_F1 = 350,
KEY_CTRL_F2 = 351,
KEY_CTRL_F3 = 352,
KEY_CTRL_F4 = 353,
KEY_CTRL_F5 = 354,
KEY_CTRL_F6 = 355,
KEY_CTRL_F7 = 356,
KEY_CTRL_F8 = 357,
KEY_CTRL_F9 = 358,
KEY_CTRL_F10 = 359,
KEY_CTRL_F11 = 393,
KEY_CTRL_F12 = 394,
KEY_ALT_F1 = 360,
KEY_ALT_F2 = 361,
KEY_ALT_F3 = 362,
KEY_ALT_F4 = 363,
KEY_ALT_F5 = 364,
KEY_ALT_F6 = 365,
KEY_ALT_F7 = 366,
KEY_ALT_F8 = 367,
KEY_ALT_F9 = 368,
KEY_ALT_F10 = 369,
KEY_ALT_F11 = 395,
KEY_ALT_F12 = 396,
KEY_HOME = 327,
KEY_CTRL_HOME = 375,
KEY_ALT_HOME = 407,
KEY_PAGE_UP = 329,
KEY_CTRL_PAGE_UP = 388,
KEY_ALT_PAGE_UP = 409,
KEY_INSERT = 338,
KEY_CTRL_INSERT = 402,
KEY_ALT_INSERT = 418,
KEY_DELETE = 339,
KEY_CTRL_DELETE = 403,
KEY_ALT_DELETE = 419,
KEY_END = 335,
KEY_CTRL_END = 373,
KEY_ALT_END = 415,
KEY_PAGE_DOWN = 337,
KEY_ALT_PAGE_DOWN = 417,
KEY_CTRL_PAGE_DOWN = 374,
KEY_ARROW_UP = 328,
KEY_CTRL_ARROW_UP = 397,
KEY_ALT_ARROW_UP = 408,
KEY_ARROW_DOWN = 336,
KEY_CTRL_ARROW_DOWN = 401,
KEY_ALT_ARROW_DOWN = 416,
KEY_ARROW_LEFT = 331,
KEY_CTRL_ARROW_LEFT = 371,
KEY_ALT_ARROW_LEFT = 411,
KEY_ARROW_RIGHT = 333,
KEY_CTRL_ARROW_RIGHT = 372,
KEY_ALT_ARROW_RIGHT = 413,
KEY_CTRL_BACKSLASH = 192,
KEY_NUMBERPAD_5 = 332,
KEY_CTRL_NUMBERPAD_5 = 399,
KEY_ALT_NUMBERPAD_5 = 9999,
KEY_FIRST_INPUT_CHARACTER = KEY_SPACE,
KEY_LAST_INPUT_CHARACTER = KEY_LOWERCASE_Z,
} Key;
typedef enum KeyboardLayout {
KEYBOARD_LAYOUT_QWERTY,
KEYBOARD_LAYOUT_FRENCH,
KEYBOARD_LAYOUT_GERMAN,
KEYBOARD_LAYOUT_ITALIAN,
KEYBOARD_LAYOUT_SPANISH,
} KeyboardLayout;
#define VCR_BUFFER_CAPACITY 4096
typedef enum VcrState {
VCR_STATE_RECORDING,
VCR_STATE_PLAYING,
VCR_STATE_TURNED_OFF,
} VcrState;
#define VCR_STATE_STOP_REQUESTED 0x80000000
typedef enum VcrTerminationFlags {
// Specifies that VCR playback should stop if any key is pressed.
VCR_TERMINATE_ON_KEY_PRESS = 0x01,
// Specifies that VCR playback should stop if mouse is mouved.
VCR_TERMINATE_ON_MOUSE_MOVE = 0x02,
// Specifies that VCR playback should stop if any mouse button is pressed.
VCR_TERMINATE_ON_MOUSE_PRESS = 0x04,
} VcrTerminationFlags;
typedef enum VcrPlaybackCompletionReason {
VCR_PLAYBACK_COMPLETION_REASON_NONE = 0,
// Indicates that VCR playback completed normally.
VCR_PLAYBACK_COMPLETION_REASON_COMPLETED = 1,
// Indicates that VCR playback terminated according to termination flags.
VCR_PLAYBACK_COMPLETION_REASON_TERMINATED = 2,
} VcrPlaybackCompletionReason;
typedef enum VcrEntryType {
VCR_ENTRY_TYPE_NONE = 0,
VCR_ENTRY_TYPE_INITIAL_STATE = 1,
VCR_ENTRY_TYPE_KEYBOARD_EVENT = 2,
VCR_ENTRY_TYPE_MOUSE_EVENT = 3,
} VcrEntryType;
typedef struct STRUCT_6ABF50 {
// Time when appropriate key was pressed down or -1 if it's up.
int tick;
int repeatCount;
} STRUCT_6ABF50;
typedef struct InputEvent {
// This is either logical key or input event id, which can be either
// character code pressed or some other numbers used throughout the
// game interface.
int logicalKey;
int mouseX;
int mouseY;
} InputEvent;
typedef void(IdleFunc)();
typedef void(FocusFunc)(bool focus);
typedef void(TickerProc)();
typedef struct TickerListNode {
int flags;
TickerProc* proc;
struct TickerListNode* next;
} TickerListNode;
typedef struct VcrEntry {
unsigned int type;
unsigned int time;
unsigned int counter;
union {
struct {
int mouseX;
int mouseY;
int keyboardLayout;
} initial;
struct {
short key;
} keyboardEvent;
struct {
int dx;
int dy;
int buttons;
} mouseEvent;
};
} VcrEntry;
typedef struct LogicalKeyEntry {
short field_0;
short unmodified;
short shift;
short lmenu;
short rmenu;
short ctrl;
} LogicalKeyEntry;
typedef struct KeyboardEvent {
int scanCode;
unsigned short modifiers;
} KeyboardEvent;
typedef int(PauseHandler)();
typedef int(ScreenshotHandler)(int width, int height, unsigned char* buffer, unsigned char* palette);
typedef void(VcrPlaybackCompletionCallback)(int reason);
extern IdleFunc* _idle_func;
extern FocusFunc* _focus_func;
extern int gKeyboardKeyRepeatRate;
extern int gKeyboardKeyRepeatDelay;
extern bool _keyboard_hooked;
extern unsigned char gMouseDefaultCursor[MOUSE_DEFAULT_CURSOR_SIZE];
extern int _mouse_idling;
extern unsigned char* gMouseCursorData;
extern unsigned char* _mouse_shape;
extern unsigned char* _mouse_fptr;
extern double gMouseSensitivity;
extern unsigned int _ticker_;
extern int gMouseButtonsState;
extern void (*_update_palette_func)();
extern bool gMmxEnabled;
extern bool gMmxProbed;
extern unsigned char _kb_installed;
extern bool gKeyboardDisabled;
extern bool gKeyboardNumpadDisabled;
extern bool gKeyboardNumlockDisabled;
extern int gKeyboardEventQueueWriteIndex;
extern int gKeyboardEventQueueReadIndex;
extern short word_51E2E8;
extern int gModifierKeysState;
extern int (*_kb_scan_to_ascii)();
extern VcrEntry* _vcr_buffer;
extern int _vcr_buffer_index;
extern unsigned int gVcrState;
extern unsigned int _vcr_time;
extern unsigned int _vcr_counter;
extern unsigned int gVcrTerminateFlags;
extern int gVcrPlaybackCompletionReason;
extern unsigned int _vcr_start_time;
extern int _vcr_registered_atexit;
extern File* gVcrFile;
extern int _vcr_buffer_end;
extern VcrPlaybackCompletionCallback* gVcrPlaybackCompletionCallback;
extern unsigned int gVcrRequestedTerminationFlags;
extern int gVcrOldKeyboardLayout;
extern int gNormalizedQwertyKeys[SDL_NUM_SCANCODES];
extern InputEvent gInputEventQueue[40];
extern STRUCT_6ABF50 _GNW95_key_time_stamps[SDL_NUM_SCANCODES];
extern int _input_mx;
extern int _input_my;
extern bool gPaused;
extern int gScreenshotKeyCode;
extern int _using_msec_timer;
extern int gPauseKeyCode;
extern ScreenshotHandler* gScreenshotHandler;
extern int gInputEventQueueReadIndex;
extern unsigned char* gScreenshotBuffer;
extern PauseHandler* gPauseHandler;
extern int gInputEventQueueWriteIndex;
extern bool gRunLoopDisabled;
extern TickerListNode* gTickerListHead;
extern unsigned int gTickerLastTimestamp;
extern bool gCursorIsHidden;
extern int _raw_x;
extern int gMouseCursorHeight;
extern int _raw_y;
extern int _raw_buttons;
extern int gMouseCursorY;
extern int gMouseCursorX;
extern int _mouse_disabled;
extern int gMouseEvent;
extern unsigned int _mouse_speed;
extern int _mouse_curr_frame;
extern bool gMouseInitialized;
extern int gMouseCursorPitch;
extern int gMouseCursorWidth;
extern int _mouse_num_frames;
extern int _mouse_hoty;
extern int _mouse_hotx;
extern unsigned int _mouse_idle_start_time;
extern WindowDrawingProc2* _mouse_blit_trans;
extern WINDOWDRAWINGPROC _mouse_blit;
extern unsigned char _mouse_trans;
extern int gMouseRightButtonDownTimestamp;
extern int gMouseLeftButtonDownTimestamp;
extern int gMousePreviousEvent;
extern unsigned short gSixteenBppPalette[256];
extern Rect _scr_size;
extern int gRedMask;
extern int gGreenMask;
extern int gBlueMask;
extern int gBlueShift;
extern int gRedShift;
extern int gGreenShift;
extern void (*_scr_blit)(unsigned char* src, int src_pitch, int a3, int src_x, int src_y, int src_width, int src_height, int dest_x, int dest_y);
extern void (*_zero_mem)();
extern bool gMmxSupported;
extern unsigned char gLastVideoModePalette[268];
extern KeyboardEvent gKeyboardEventsQueue[KEY_QUEUE_SIZE];
extern LogicalKeyEntry gLogicalKeyEntries[SDL_NUM_SCANCODES];
extern unsigned char gPressedPhysicalKeys[SDL_NUM_SCANCODES];
extern unsigned int _kb_idle_start_time;
extern KeyboardEvent gLastKeyboardEvent;
extern int gKeyboardLayout;
extern unsigned char gPressedPhysicalKeysCount;
extern VcrEntry stru_6AD940;
extern SDL_Window* gSdlWindow;
extern SDL_Surface* gSdlSurface;
extern SDL_Renderer* gSdlRenderer;
extern SDL_Texture* gSdlTexture;
extern SDL_Surface* gSdlTextureSurface;
int coreInit(int a1);
void coreExit();
int _get_input();
void _process_bk();
void enqueueInputEvent(int a1);
int dequeueInputEvent();
void inputEventQueueReset();
void tickersExecute();
void tickersAdd(TickerProc* fn);
void tickersRemove(TickerProc* fn);
void tickersEnable();
void tickersDisable();
void pauseGame();
int pauseHandlerDefaultImpl();
void pauseHandlerConfigure(int keyCode, PauseHandler* fn);
void takeScreenshot();
void screenshotBlitter(unsigned char* src, int src_pitch, int a3, int x, int y, int width, int height, int dest_x, int dest_y);
int screenshotHandlerDefaultImpl(int width, int height, unsigned char* data, unsigned char* palette);
void screenshotHandlerConfigure(int keyCode, ScreenshotHandler* handler);
unsigned int _get_time();
void coreDelayProcessingEvents(unsigned int ms);
void coreDelay(unsigned int ms);
unsigned int getTicksSince(unsigned int a1);
unsigned int getTicksBetween(unsigned int a1, unsigned int a2);
unsigned int _get_bk_time();
void inputSetKeyboardKeyRepeatRate(int value);
int inputGetKeyboardKeyRepeatRate();
void inputSetKeyboardKeyRepeatDelay(int value);
int inputGetKeyboardKeyRepeatDelay();
void inputSetFocusFunc(FocusFunc* func);
FocusFunc* inputGetFocusFunc();
void inputSetIdleFunc(IdleFunc* func);
IdleFunc* inputGetIdleFunc();
void buildNormalizedQwertyKeys();
int _GNW95_input_init();
void _GNW95_process_message();
void _GNW95_clear_time_stamps();
void _GNW95_process_key(KeyboardData* data);
void _GNW95_lost_focus();
int mouseInit();
void mouseFree();
void mousePrepareDefaultCursor();
int mouseSetFrame(unsigned char* a1, int width, int height, int pitch, int a5, int a6, int a7);
void _mouse_anim();
void mouseShowCursor();
void mouseHideCursor();
void _mouse_info();
void _mouse_simulate_input(int delta_x, int delta_y, int buttons);
bool _mouse_in(int left, int top, int right, int bottom);
bool _mouse_click_in(int left, int top, int right, int bottom);
void mouseGetRect(Rect* rect);
void mouseGetPosition(int* out_x, int* out_y);
void _mouse_set_position(int a1, int a2);
void _mouse_clip();
int mouseGetEvent();
bool cursorIsHidden();
void _mouse_get_raw_state(int* out_x, int* out_y, int* out_buttons);
void mouseSetSensitivity(double value);
void mmxSetEnabled(bool a1);
int _init_mode_320_200();
int _init_mode_320_400();
int _init_mode_640_480_16();
int _init_mode_640_480();
int _init_mode_640_400();
int _init_mode_800_600();
int _init_mode_1024_768();
int _init_mode_1280_1024();
void _get_start_mode_();
void _zero_vid_mem();
int _GNW95_init_mode_ex(int width, int height, int bpp);
int _init_vesa_mode(int width, int height);
int _GNW95_init_window(int width, int height, bool fullscreen);
int getShiftForBitMask(int mask);
int directDrawInit(int width, int height, int bpp);
void directDrawFree();
void directDrawSetPaletteInRange(unsigned char* a1, int a2, int a3);
void directDrawSetPalette(unsigned char* palette);
unsigned char* directDrawGetPalette();
void _GNW95_ShowRect(unsigned char* src, int src_pitch, int a3, int src_x, int src_y, int src_width, int src_height, int dest_x, int dest_y);
void _GNW95_MouseShowRect16(unsigned char* src, int srcPitch, int a3, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY);
void _GNW95_ShowRect16(unsigned char* src, int srcPitch, int a3, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY);
void _GNW95_MouseShowTransRect16(unsigned char* src, int srcPitch, int a3, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, unsigned char keyColor);
void _GNW95_zero_vid_mem();
int keyboardInit();
void keyboardFree();
void keyboardReset();
int _kb_getch();
void keyboardDisable();
void keyboardEnable();
int keyboardIsDisabled();
void keyboardSetLayout(int new_language);
int keyboardGetLayout();
void _kb_simulate_key(KeyboardData* data);
int _kb_next_ascii_English_US();
int keyboardDequeueLogicalKeyCode();
void keyboardBuildQwertyConfiguration();
void keyboardBuildFrenchConfiguration();
void keyboardBuildGermanConfiguration();
void keyboardBuildItalianConfiguration();
void keyboardBuildSpanishConfiguration();
void _kb_init_lock_status();
int keyboardPeekEvent(int index, KeyboardEvent** keyboardEventPtr);
bool vcrRecord(const char* fileName);
bool vcrPlay(const char* fileName, unsigned int terminationFlags, VcrPlaybackCompletionCallback* callback);
void vcrStop();
int vcrGetState();
int vcrUpdate();
bool vcrInitBuffer();
bool vcrFreeBuffer();
bool vcrClear();
bool vcrDump();
bool vcrLoad();
bool vcrWriteEntry(VcrEntry* ptr, File* stream);
bool vcrReadEntry(VcrEntry* ptr, File* stream);
int screenGetWidth();
int screenGetHeight();
int screenGetVisibleHeight();
void mouseGetPositionInWindow(int win, int* x, int* y);
bool mouseHitTestInWindow(int win, int left, int top, int right, int bottom);
void mouseGetWheel(int* x, int* y);
void convertMouseWheelToArrowKey(int* keyCodePtr);
} // namespace fallout
#endif /* CORE_H */

View File

@@ -2,29 +2,26 @@
#include <string.h>
#include <algorithm>
#include "art.h"
#include "color.h"
#include "core.h"
#include "cycle.h"
#include "db.h"
#include "debug.h"
#include "delay.h"
#include "draw.h"
#include "game_mouse.h"
#include "input.h"
#include "memory.h"
#include "message.h"
#include "mouse.h"
#include "palette.h"
#include "platform_compat.h"
#include "sound.h"
#include "svga.h"
#include "text_font.h"
#include "window_manager.h"
namespace fallout {
#define CREDITS_WINDOW_WIDTH (640)
#define CREDITS_WINDOW_HEIGHT (480)
#define CREDITS_WINDOW_SCROLLING_DELAY (38)
static bool creditsFileParseNextLine(char* dest, int* font, int* color);
@@ -66,9 +63,9 @@ void creditsOpen(const char* filePath, int backgroundFid, bool useReversedStyle)
soundContinueAll();
char localizedPath[COMPAT_MAX_PATH];
if (_message_make_path(localizedPath, sizeof(localizedPath), filePath)) {
if (_message_make_path(localizedPath, filePath)) {
gCreditsFile = fileOpen(localizedPath, "rt");
if (gCreditsFile != nullptr) {
if (gCreditsFile != NULL) {
soundContinueAll();
colorCycleDisable();
@@ -79,35 +76,39 @@ void creditsOpen(const char* filePath, int backgroundFid, bool useReversedStyle)
mouseShowCursor();
}
int windowWidth = screenGetWidth();
int windowHeight = screenGetHeight();
int window = windowCreate(0, 0, windowWidth, windowHeight, _colorTable[0], 20);
int creditsWindowX = (screenGetWidth() - CREDITS_WINDOW_WIDTH) / 2;
int creditsWindowY = (screenGetHeight() - CREDITS_WINDOW_HEIGHT) / 2;
int window = windowCreate(creditsWindowX, creditsWindowY, CREDITS_WINDOW_WIDTH, CREDITS_WINDOW_HEIGHT, _colorTable[0], 20);
soundContinueAll();
if (window != -1) {
unsigned char* windowBuffer = windowGetBuffer(window);
if (windowBuffer != nullptr) {
unsigned char* backgroundBuffer = (unsigned char*)internal_malloc(windowWidth * windowHeight);
if (windowBuffer != NULL) {
unsigned char* backgroundBuffer = (unsigned char*)internal_malloc(CREDITS_WINDOW_WIDTH * CREDITS_WINDOW_HEIGHT);
if (backgroundBuffer) {
soundContinueAll();
memset(backgroundBuffer, _colorTable[0], windowWidth * windowHeight);
memset(backgroundBuffer, _colorTable[0], CREDITS_WINDOW_WIDTH * CREDITS_WINDOW_HEIGHT);
if (backgroundFid != -1) {
FrmImage backgroundFrmImage;
if (backgroundFrmImage.lock(backgroundFid)) {
blitBufferToBuffer(backgroundFrmImage.getData(),
backgroundFrmImage.getWidth(),
backgroundFrmImage.getHeight(),
backgroundFrmImage.getWidth(),
backgroundBuffer + windowWidth * ((windowHeight - backgroundFrmImage.getHeight()) / 2) + (windowWidth - backgroundFrmImage.getWidth()) / 2,
windowWidth);
backgroundFrmImage.unlock();
CacheEntry* backgroundFrmHandle;
Art* frm = artLock(backgroundFid, &backgroundFrmHandle);
if (frm != NULL) {
int width = artGetWidth(frm, 0, 0);
int height = artGetHeight(frm, 0, 0);
unsigned char* backgroundFrmData = artGetFrameData(frm, 0, 0);
blitBufferToBuffer(backgroundFrmData,
width,
height,
width,
backgroundBuffer + CREDITS_WINDOW_WIDTH * ((CREDITS_WINDOW_HEIGHT - height) / 2) + (CREDITS_WINDOW_WIDTH - width) / 2,
CREDITS_WINDOW_WIDTH);
artUnlock(backgroundFrmHandle);
}
}
unsigned char* intermediateBuffer = (unsigned char*)internal_malloc(windowWidth * windowHeight);
if (intermediateBuffer != nullptr) {
memset(intermediateBuffer, 0, windowWidth * windowHeight);
unsigned char* intermediateBuffer = (unsigned char*)internal_malloc(CREDITS_WINDOW_WIDTH * CREDITS_WINDOW_HEIGHT);
if (intermediateBuffer != NULL) {
memset(intermediateBuffer, 0, CREDITS_WINDOW_WIDTH * CREDITS_WINDOW_HEIGHT);
fontSetCurrent(gCreditsWindowTitleFont);
int titleFontLineHeight = fontGetLineHeight();
@@ -115,21 +116,22 @@ void creditsOpen(const char* filePath, int backgroundFid, bool useReversedStyle)
fontSetCurrent(gCreditsWindowNameFont);
int nameFontLineHeight = fontGetLineHeight();
int lineHeight = std::max(titleFontLineHeight, nameFontLineHeight);
int stringBufferSize = windowWidth * lineHeight;
int lineHeight = nameFontLineHeight + (titleFontLineHeight >= nameFontLineHeight ? titleFontLineHeight - nameFontLineHeight : 0);
int stringBufferSize = CREDITS_WINDOW_WIDTH * lineHeight;
unsigned char* stringBuffer = (unsigned char*)internal_malloc(stringBufferSize);
if (stringBuffer != nullptr) {
if (stringBuffer != NULL) {
blitBufferToBuffer(backgroundBuffer,
windowWidth,
windowHeight,
windowWidth,
CREDITS_WINDOW_WIDTH,
CREDITS_WINDOW_HEIGHT,
CREDITS_WINDOW_WIDTH,
windowBuffer,
windowWidth);
CREDITS_WINDOW_WIDTH);
windowRefresh(window);
paletteFadeTo(_cmap);
unsigned char* v40 = intermediateBuffer + CREDITS_WINDOW_WIDTH * CREDITS_WINDOW_HEIGHT - CREDITS_WINDOW_WIDTH;
char str[260];
int font;
int color;
@@ -138,51 +140,47 @@ void creditsOpen(const char* filePath, int backgroundFid, bool useReversedStyle)
while (creditsFileParseNextLine(str, &font, &color)) {
fontSetCurrent(font);
int stringWidth = fontGetStringWidth(str);
if (stringWidth >= windowWidth) {
int v19 = fontGetStringWidth(str);
if (v19 >= CREDITS_WINDOW_WIDTH) {
continue;
}
memset(stringBuffer, 0, stringBufferSize);
fontDrawText(stringBuffer, str, windowWidth, windowWidth, color);
fontDrawText(stringBuffer, str, CREDITS_WINDOW_WIDTH, CREDITS_WINDOW_WIDTH, color);
unsigned char* dest = intermediateBuffer + windowWidth * windowHeight - windowWidth + (windowWidth - stringWidth) / 2;
unsigned char* dest = intermediateBuffer + CREDITS_WINDOW_WIDTH * CREDITS_WINDOW_HEIGHT - CREDITS_WINDOW_WIDTH + (CREDITS_WINDOW_WIDTH - v19) / 2;
unsigned char* src = stringBuffer;
for (int index = 0; index < lineHeight; index++) {
sharedFpsLimiter.mark();
if (inputGetInput() != -1) {
if (_get_input() != -1) {
stop = true;
break;
}
memmove(intermediateBuffer, intermediateBuffer + windowWidth, windowWidth * windowHeight - windowWidth);
memcpy(dest, src, stringWidth);
memmove(intermediateBuffer, intermediateBuffer + CREDITS_WINDOW_WIDTH, CREDITS_WINDOW_WIDTH * CREDITS_WINDOW_HEIGHT - CREDITS_WINDOW_WIDTH);
memcpy(dest, src, v19);
blitBufferToBuffer(backgroundBuffer,
windowWidth,
windowHeight,
windowWidth,
CREDITS_WINDOW_WIDTH,
CREDITS_WINDOW_HEIGHT,
CREDITS_WINDOW_WIDTH,
windowBuffer,
windowWidth);
CREDITS_WINDOW_WIDTH);
blitBufferToBufferTrans(intermediateBuffer,
windowWidth,
windowHeight,
windowWidth,
CREDITS_WINDOW_WIDTH,
CREDITS_WINDOW_HEIGHT,
CREDITS_WINDOW_WIDTH,
windowBuffer,
windowWidth);
CREDITS_WINDOW_WIDTH);
delay_ms(CREDITS_WINDOW_SCROLLING_DELAY - (getTicks() - tick));
while (getTicksSince(tick) < CREDITS_WINDOW_SCROLLING_DELAY) {
}
tick = getTicks();
tick = _get_time();
windowRefresh(window);
src += windowWidth;
sharedFpsLimiter.throttle();
renderPresent();
src += CREDITS_WINDOW_WIDTH;
}
if (stop) {
@@ -191,38 +189,34 @@ void creditsOpen(const char* filePath, int backgroundFid, bool useReversedStyle)
}
if (!stop) {
for (int index = 0; index < windowHeight; index++) {
sharedFpsLimiter.mark();
if (inputGetInput() != -1) {
for (int index = 0; index < CREDITS_WINDOW_HEIGHT; index++) {
if (_get_input() != -1) {
break;
}
memmove(intermediateBuffer, intermediateBuffer + windowWidth, windowWidth * windowHeight - windowWidth);
memset(intermediateBuffer + windowWidth * windowHeight - windowWidth, 0, windowWidth);
memmove(intermediateBuffer, intermediateBuffer + CREDITS_WINDOW_WIDTH, CREDITS_WINDOW_WIDTH * CREDITS_WINDOW_HEIGHT - CREDITS_WINDOW_WIDTH);
memset(intermediateBuffer + CREDITS_WINDOW_WIDTH * CREDITS_WINDOW_HEIGHT - CREDITS_WINDOW_WIDTH, 0, CREDITS_WINDOW_WIDTH);
blitBufferToBuffer(backgroundBuffer,
windowWidth,
windowHeight,
windowWidth,
CREDITS_WINDOW_WIDTH,
CREDITS_WINDOW_HEIGHT,
CREDITS_WINDOW_WIDTH,
windowBuffer,
windowWidth);
CREDITS_WINDOW_WIDTH);
blitBufferToBufferTrans(intermediateBuffer,
windowWidth,
windowHeight,
windowWidth,
CREDITS_WINDOW_WIDTH,
CREDITS_WINDOW_HEIGHT,
CREDITS_WINDOW_WIDTH,
windowBuffer,
windowWidth);
CREDITS_WINDOW_WIDTH);
delay_ms(CREDITS_WINDOW_SCROLLING_DELAY - (getTicks() - tick));
while (getTicksSince(tick) < CREDITS_WINDOW_SCROLLING_DELAY) {
}
tick = getTicks();
tick = _get_time();
windowRefresh(window);
sharedFpsLimiter.throttle();
renderPresent();
}
}

View File

@@ -135,7 +135,7 @@ static const int gRadiationEffectPenalties[RADIATION_LEVEL_COUNT][RADIATION_EFFE
};
// 0x518438
static Object* _critterClearObj = nullptr;
static Object* _critterClearObj = NULL;
// scrname.msg
//
@@ -171,15 +171,13 @@ int critterInit()
}
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%sscrname.msg", asc_5186C8);
sprintf(path, "%sscrname.msg", asc_5186C8);
if (!messageListLoad(&gCritterMessageList, path)) {
debugPrint("\nError: Loading critter name message file!");
return -1;
}
messageListRepositorySetStandardMessageList(STANDARD_MESSAGE_LIST_SCRNAME, &gCritterMessageList);
return 0;
}
@@ -195,7 +193,6 @@ void critterReset()
// 0x42D004
void critterExit()
{
messageListRepositorySetStandardMessageList(STANDARD_MESSAGE_LIST_SCRNAME, nullptr);
messageListFree(&gCritterMessageList);
}
@@ -247,7 +244,7 @@ char* critterGetName(Object* obj)
}
}
char* name = nullptr;
char* name = NULL;
if (obj->field_80 != -1) {
MessageListItem messageListItem;
messageListItem.num = 101 + obj->field_80;
@@ -256,7 +253,7 @@ char* critterGetName(Object* obj)
}
}
if (name == nullptr || *name == '\0') {
if (name == NULL || *name == '\0') {
name = protoGetName(obj->pid);
}
@@ -347,8 +344,8 @@ int critterAdjustPoison(Object* critter, int amount)
if (newPoison > 0) {
critter->data.critter.poison = newPoison;
_queue_clear_type(EVENT_TYPE_POISON, nullptr);
queueAddEvent(10 * (505 - 5 * newPoison), gDude, nullptr, EVENT_TYPE_POISON);
_queue_clear_type(EVENT_TYPE_POISON, NULL);
queueAddEvent(10 * (505 - 5 * newPoison), gDude, NULL, EVENT_TYPE_POISON);
// You have been poisoned!
messageListItem.num = 3000;
@@ -425,27 +422,27 @@ int critterAdjustRadiation(Object* obj, int amount)
}
if (amount > 0) {
proto->critter.data.flags |= CRITTER_RADIATED;
proto->critter.data.flags |= CRITTER_FLAG_0x2;
}
if (amount > 0) {
Object* geigerCounter = nullptr;
Object* geigerCounter = NULL;
Object* item1 = critterGetItem1(gDude);
if (item1 != nullptr) {
if (item1 != NULL) {
if (item1->pid == PROTO_ID_GEIGER_COUNTER_I || item1->pid == PROTO_ID_GEIGER_COUNTER_II) {
geigerCounter = item1;
}
}
Object* item2 = critterGetItem2(gDude);
if (item2 != nullptr) {
if (item2 != NULL) {
if (item2->pid == PROTO_ID_GEIGER_COUNTER_I || item2->pid == PROTO_ID_GEIGER_COUNTER_II) {
geigerCounter = item2;
}
}
if (geigerCounter != nullptr) {
if (geigerCounter != NULL) {
if (miscItemIsOn(geigerCounter)) {
if (amount > 5) {
// The geiger counter is clicking wildly.
@@ -492,7 +489,7 @@ int _critter_check_rads(Object* obj)
Proto* proto;
protoGetProto(obj->pid, &proto);
if ((proto->critter.data.flags & CRITTER_RADIATED) == 0) {
if ((proto->critter.data.flags & CRITTER_FLAG_0x2) == 0) {
return 0;
}
@@ -517,14 +514,14 @@ int _critter_check_rads(Object* obj)
else
radiationLevel = RADIATION_LEVEL_NONE;
if (statRoll(obj, STAT_ENDURANCE, gRadiationEnduranceModifiers[radiationLevel], nullptr) <= ROLL_FAILURE) {
if (statRoll(obj, STAT_ENDURANCE, gRadiationEnduranceModifiers[radiationLevel], NULL) <= ROLL_FAILURE) {
radiationLevel++;
}
if (radiationLevel > _old_rad_level) {
// Create timer event for applying radiation damage.
RadiationEvent* radiationEvent = (RadiationEvent*)internal_malloc(sizeof(*radiationEvent));
if (radiationEvent == nullptr) {
if (radiationEvent == NULL) {
return 0;
}
@@ -533,7 +530,7 @@ int _critter_check_rads(Object* obj)
queueAddEvent(GAME_TIME_TICKS_PER_HOUR * randomBetween(4, 18), obj, radiationEvent, EVENT_TYPE_RADIATION);
}
proto->critter.data.flags &= ~CRITTER_RADIATED;
proto->critter.data.flags &= ~(CRITTER_FLAG_0x2);
return 0;
}
@@ -630,7 +627,7 @@ int radiationEventProcess(Object* obj, void* data)
if (!radiationEvent->isHealing) {
// Schedule healing stats event in 7 days.
RadiationEvent* newRadiationEvent = (RadiationEvent*)internal_malloc(sizeof(*newRadiationEvent));
if (newRadiationEvent != nullptr) {
if (newRadiationEvent != NULL) {
_queue_clear_type(EVENT_TYPE_RADIATION, _clear_rad_damage);
newRadiationEvent->radiationLevel = radiationEvent->radiationLevel;
newRadiationEvent->isHealing = 1;
@@ -647,7 +644,7 @@ int radiationEventProcess(Object* obj, void* data)
int radiationEventRead(File* stream, void** dataPtr)
{
RadiationEvent* radiationEvent = (RadiationEvent*)internal_malloc(sizeof(*radiationEvent));
if (radiationEvent == nullptr) {
if (radiationEvent == NULL) {
return -1;
}
@@ -770,7 +767,7 @@ char* killTypeGetName(int killType)
MessageListItem messageListItem;
return getmsg(&gProtoMessageList, &messageListItem, 1450 + killType);
} else {
return nullptr;
return NULL;
}
} else {
return byte_501494;
@@ -785,7 +782,7 @@ char* killTypeGetDescription(int killType)
MessageListItem messageListItem;
return getmsg(&gProtoMessageList, &messageListItem, 1469 + killType);
} else {
return nullptr;
return NULL;
}
} else {
return byte_501494;
@@ -879,7 +876,7 @@ void critterKill(Object* critter, int anim, bool a3)
rectUnion(&updatedRect, &tempRect, &updatedRect);
}
if (!_critter_flag_check(critter->pid, CRITTER_FLAT)) {
if (!_critter_flag_check(critter->pid, CRITTER_FLAG_0x800)) {
critter->flags |= OBJECT_NO_BLOCK;
_obj_toggle_flat(critter, &tempRect);
}
@@ -927,7 +924,7 @@ int critterGetExp(Object* critter)
// 0x42DCDC
bool critterIsActive(Object* critter)
{
if (critter == nullptr) {
if (critter == NULL) {
return false;
}
@@ -949,7 +946,7 @@ bool critterIsActive(Object* critter)
// 0x42DD18
bool critterIsDead(Object* critter)
{
if (critter == nullptr) {
if (critter == NULL) {
return false;
}
@@ -971,7 +968,7 @@ bool critterIsDead(Object* critter)
// 0x42DD58
bool critterIsCrippled(Object* critter)
{
if (critter == nullptr) {
if (critter == NULL) {
return false;
}
@@ -985,7 +982,7 @@ bool critterIsCrippled(Object* critter)
// 0x42DD80
bool _critter_is_prone(Object* critter)
{
if (critter == nullptr) {
if (critter == NULL) {
return false;
}
@@ -996,15 +993,15 @@ bool _critter_is_prone(Object* critter)
int anim = FID_ANIM_TYPE(critter->fid);
return (critter->data.critter.combat.results & (DAM_KNOCKED_OUT | DAM_KNOCKED_DOWN)) != 0
|| (anim >= FIRST_KNOCKDOWN_AND_DEATH_ANIM && anim <= LAST_KNOCKDOWN_AND_DEATH_ANIM)
|| (anim >= FIRST_SF_DEATH_ANIM && anim <= LAST_SF_DEATH_ANIM);
|| (anim >= FIRST_KNOCKDOWN_AND_DEATH_ANIM && anim <= LAST_KNOCKDOWN_AND_DEATH_ANIM)
|| (anim >= FIRST_SF_DEATH_ANIM && anim <= LAST_SF_DEATH_ANIM);
}
// critter_body_type
// 0x42DDC4
int critterGetBodyType(Object* critter)
{
if (critter == nullptr) {
if (critter == NULL) {
debugPrint("\nError: critter_body_type: pobj was NULL!");
return 0;
}
@@ -1022,7 +1019,7 @@ int critterGetBodyType(Object* critter)
int gcdLoad(const char* path)
{
File* stream = fileOpen(path, "rb");
if (stream == nullptr) {
if (stream == NULL) {
return -1;
}
@@ -1094,7 +1091,7 @@ int protoCritterDataRead(File* stream, CritterProtoData* critterData)
int gcdSave(const char* path)
{
File* stream = fileOpen(path, "wb");
if (stream == nullptr) {
if (stream == NULL) {
return -1;
}
@@ -1166,7 +1163,7 @@ void dudeEnableState(int state)
proto->critter.data.flags |= (1 << state);
if (state == DUDE_STATE_SNEAKING) {
sneakEventProcess(nullptr, nullptr);
sneakEventProcess(NULL, NULL);
}
indicatorBarRefresh();
@@ -1197,7 +1194,7 @@ int sneakEventProcess(Object* obj, void* data)
int time;
int sneak = skillGetValue(gDude, SKILL_SNEAK);
if (skillRoll(gDude, SKILL_SNEAK, 0, nullptr) < ROLL_SUCCESS) {
if (skillRoll(gDude, SKILL_SNEAK, 0, NULL) < ROLL_SUCCESS) {
time = 600;
_sneak_working = false;
@@ -1218,7 +1215,7 @@ int sneakEventProcess(Object* obj, void* data)
_sneak_working = true;
}
queueAddEvent(time, gDude, nullptr, EVENT_TYPE_SNEAK);
queueAddEvent(time, gDude, NULL, EVENT_TYPE_SNEAK);
return 0;
}
@@ -1254,7 +1251,7 @@ int knockoutEventProcess(Object* obj, void* data)
obj->data.critter.combat.results |= DAM_KNOCKED_DOWN;
if (isInCombat()) {
obj->data.critter.combat.maneuver |= CRITTER_MANEUVER_ENGAGING;
obj->data.critter.combat.maneuver |= CRITTER_MANEUVER_0x01;
} else {
_dude_standup(obj);
}
@@ -1276,7 +1273,7 @@ int _critter_wake_clear(Object* obj, void* data)
obj->data.critter.combat.results &= ~(DAM_KNOCKED_OUT | DAM_KNOCKED_DOWN);
int fid = buildFid(FID_TYPE(obj->fid), obj->fid & 0xFFF, ANIM_STAND, (obj->fid & 0xF000) >> 12, obj->rotation + 1);
objectSetFid(obj, fid, nullptr);
objectSetFid(obj, fid, 0);
return 0;
}
@@ -1284,16 +1281,16 @@ int _critter_wake_clear(Object* obj, void* data)
// 0x42E4C0
int _critter_set_who_hit_me(Object* a1, Object* a2)
{
if (a1 == nullptr) {
if (a1 == NULL) {
return -1;
}
if (a2 != nullptr && FID_TYPE(a2->fid) != OBJ_TYPE_CRITTER) {
if (a2 != NULL && FID_TYPE(a2->fid) != OBJ_TYPE_CRITTER) {
return -1;
}
if (PID_TYPE(a1->pid) == OBJ_TYPE_CRITTER) {
if (a2 == nullptr || a1->data.critter.combat.team != a2->data.critter.combat.team || (statRoll(a1, STAT_INTELLIGENCE, -1, nullptr) < 2 && (!objectIsPartyMember(a1) || !objectIsPartyMember(a2)))) {
if (a2 == NULL || a1->data.critter.combat.team != a2->data.critter.combat.team || (statRoll(a1, STAT_INTELLIGENCE, -1, NULL) < 2 && (!objectIsPartyMember(a1) || !objectIsPartyMember(a2)))) {
a1->data.critter.combat.whoHitMe = a2;
if (a2 == gDude) {
reactionSetValue(a1, -3);
@@ -1373,7 +1370,7 @@ bool critterIsEncumbered(Object* critter)
// 0x42E690
bool critterIsFleeing(Object* critter)
{
return critter != nullptr
return critter != NULL
? (critter->data.critter.combat.maneuver & CRITTER_MANUEVER_FLEEING) != 0
: false;
}
@@ -1396,40 +1393,4 @@ bool _critter_flag_check(int pid, int flag)
return (proto->critter.data.flags & flag) != 0;
}
// 0x42E6F0
void critter_flag_set(int pid, int flag)
{
Proto* proto;
if (pid == -1) {
return;
}
if (PID_TYPE(pid) != OBJ_TYPE_CRITTER) {
return;
}
protoGetProto(pid, &proto);
proto->critter.data.flags |= flag;
}
// 0x42E71C
void critter_flag_unset(int pid, int flag)
{
Proto* proto;
if (pid == -1) {
return;
}
if (PID_TYPE(pid) != OBJ_TYPE_CRITTER) {
return;
}
protoGetProto(pid, &proto);
proto->critter.data.flags &= ~flag;
}
} // namespace fallout

View File

@@ -70,8 +70,6 @@ int critterGetMovementPointCostAdjustedForCrippledLegs(Object* critter, int a2);
bool critterIsEncumbered(Object* critter);
bool critterIsFleeing(Object* a1);
bool _critter_flag_check(int pid, int flag);
void critter_flag_set(int pid, int flag);
void critter_flag_unset(int pid, int flag);
} // namespace fallout

View File

@@ -1,17 +1,16 @@
#include "cycle.h"
#include "color.h"
#include "input.h"
#include "core.h"
#include "game_config.h"
#include "palette.h"
#include "settings.h"
#include "svga.h"
namespace fallout {
static constexpr unsigned int kSlowCyclePeriod = 1000 / 5;
static constexpr unsigned int kMediumCyclePeriod = 1000 / 7;
static constexpr unsigned int kFastCyclePeriod = 1000 / 10;
static constexpr unsigned int kVeryFastCyclePeriod = 1000 / 30;
#define COLOR_CYCLE_PERIOD_1 (200U)
#define COLOR_CYCLE_PERIOD_2 (142U)
#define COLOR_CYCLE_PERIOD_3 (100U)
#define COLOR_CYCLE_PERIOD_4 (33U)
// 0x51843C
static int gColorCycleSpeedFactor = 1;
@@ -22,7 +21,7 @@ static int gColorCycleSpeedFactor = 1;
// Green.
//
// 0x518440
static unsigned char slime[12] = {
static unsigned char _slime[12] = {
0, 108, 0,
11, 115, 7,
27, 123, 15,
@@ -32,7 +31,7 @@ static unsigned char slime[12] = {
// Light gray?
//
// 0x51844C
static unsigned char shoreline[18] = {
static unsigned char _shoreline[18] = {
83, 63, 43,
75, 59, 43,
67, 55, 39,
@@ -44,7 +43,7 @@ static unsigned char shoreline[18] = {
// Orange.
//
// 0x51845E
static unsigned char fire_slow[15] = {
static unsigned char _fire_slow[15] = {
255, 0, 0,
215, 0, 0,
147, 43, 11,
@@ -55,7 +54,7 @@ static unsigned char fire_slow[15] = {
// Red.
//
// 0x51846D
static unsigned char fire_fast[15] = {
static unsigned char _fire_fast[15] = {
71, 0, 0,
123, 0, 0,
179, 0, 0,
@@ -66,7 +65,7 @@ static unsigned char fire_fast[15] = {
// Light blue.
//
// 0x51847C
static unsigned char monitors[15] = {
static unsigned char _monitors[15] = {
107, 107, 111,
99, 103, 127,
87, 107, 143,
@@ -82,17 +81,38 @@ static bool gColorCycleInitialized = false;
// 0x518490
static bool gColorCycleEnabled = false;
// 0x518494
static int _slime_start = 0;
// 0x518498
static int _shoreline_start = 0;
// 0x51849C
static int _fire_slow_start = 0;
// 0x5184A0
static int _fire_fast_start = 0;
// 0x5184A4
static int _monitors_start = 0;
// 0x5184A8
static unsigned char _bobber_red = 0;
// 0x5184A9
static signed char _bobber_diff = -4;
// 0x56D7D0
static unsigned int last_cycle_fast;
static unsigned int gColorCycleTimestamp3;
// 0x56D7D4
static unsigned int last_cycle_slow;
static unsigned int gColorCycleTimestamp1;
// 0x56D7D8
static unsigned int last_cycle_medium;
static unsigned int gColorCycleTimestamp2;
// 0x56D7DC
static unsigned int last_cycle_very_fast;
static unsigned int gColorCycleTimestamp4;
// 0x42E780
void colorCycleInit()
@@ -101,28 +121,33 @@ void colorCycleInit()
return;
}
if (!settings.system.color_cycling) {
bool colorCycling;
if (!configGetBool(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_COLOR_CYCLING_KEY, &colorCycling)) {
colorCycling = true;
}
if (!colorCycling) {
return;
}
for (int index = 0; index < 12; index++) {
slime[index] >>= 2;
_slime[index] >>= 2;
}
for (int index = 0; index < 18; index++) {
shoreline[index] >>= 2;
_shoreline[index] >>= 2;
}
for (int index = 0; index < 15; index++) {
fire_slow[index] >>= 2;
_fire_slow[index] >>= 2;
}
for (int index = 0; index < 15; index++) {
fire_fast[index] >>= 2;
_fire_fast[index] >>= 2;
}
for (int index = 0; index < 15; index++) {
monitors[index] >>= 2;
_monitors[index] >>= 2;
}
tickersAdd(colorCycleTicker);
@@ -130,17 +155,22 @@ void colorCycleInit()
gColorCycleInitialized = true;
gColorCycleEnabled = true;
cycleSetSpeedFactor(settings.system.cycle_speed_factor);
int cycleSpeedFactor;
if (!configGetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CYCLE_SPEED_FACTOR_KEY, &cycleSpeedFactor)) {
cycleSpeedFactor = 1;
}
cycleSetSpeedFactor(cycleSpeedFactor);
}
// 0x42E8CC
void colorCycleReset()
{
if (gColorCycleInitialized) {
last_cycle_slow = 0;
last_cycle_medium = 0;
last_cycle_fast = 0;
last_cycle_very_fast = 0;
gColorCycleTimestamp1 = 0;
gColorCycleTimestamp2 = 0;
gColorCycleTimestamp3 = 0;
gColorCycleTimestamp4 = 0;
tickersAdd(colorCycleTicker);
gColorCycleEnabled = true;
}
@@ -178,33 +208,12 @@ bool colorCycleEnabled()
void cycleSetSpeedFactor(int value)
{
gColorCycleSpeedFactor = value;
settings.system.cycle_speed_factor = value;
configSetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CYCLE_SPEED_FACTOR_KEY, value);
}
// 0x42E97C
void colorCycleTicker()
{
// 0x518494
static int slime_start = 0;
// 0x518498
static int shoreline_start = 0;
// 0x51849C
static int fire_slow_start = 0;
// 0x5184A0
static int fire_fast_start = 0;
// 0x5184A4
static int monitors_start = 0;
// 0x5184A8
static unsigned char bobber_red = 0;
// 0x5184A9
static signed char bobber_diff = -4;
if (!gColorCycleEnabled) {
return;
}
@@ -212,111 +221,111 @@ void colorCycleTicker()
bool changed = false;
unsigned char* palette = _getSystemPalette();
unsigned int time = getTicks();
unsigned int time = _get_time();
if (getTicksBetween(time, last_cycle_slow) >= kSlowCyclePeriod * gColorCycleSpeedFactor) {
if (getTicksBetween(time, gColorCycleTimestamp1) >= COLOR_CYCLE_PERIOD_1 * gColorCycleSpeedFactor) {
changed = true;
last_cycle_slow = time;
gColorCycleTimestamp1 = time;
int paletteIndex = 229 * 3;
for (int index = slime_start; index < 12; index++) {
palette[paletteIndex++] = slime[index];
for (int index = _slime_start; index < 12; index++) {
palette[paletteIndex++] = _slime[index];
}
for (int index = 0; index < slime_start; index++) {
palette[paletteIndex++] = slime[index];
for (int index = 0; index < _slime_start; index++) {
palette[paletteIndex++] = _slime[index];
}
slime_start -= 3;
if (slime_start < 0) {
slime_start = 9;
_slime_start -= 3;
if (_slime_start < 0) {
_slime_start = 9;
}
paletteIndex = 248 * 3;
for (int index = shoreline_start; index < 18; index++) {
palette[paletteIndex++] = shoreline[index];
for (int index = _shoreline_start; index < 18; index++) {
palette[paletteIndex++] = _shoreline[index];
}
for (int index = 0; index < shoreline_start; index++) {
palette[paletteIndex++] = shoreline[index];
for (int index = 0; index < _shoreline_start; index++) {
palette[paletteIndex++] = _shoreline[index];
}
shoreline_start -= 3;
if (shoreline_start < 0) {
shoreline_start = 15;
_shoreline_start -= 3;
if (_shoreline_start < 0) {
_shoreline_start = 15;
}
paletteIndex = 238 * 3;
for (int index = fire_slow_start; index < 15; index++) {
palette[paletteIndex++] = fire_slow[index];
for (int index = _fire_slow_start; index < 15; index++) {
palette[paletteIndex++] = _fire_slow[index];
}
for (int index = 0; index < fire_slow_start; index++) {
palette[paletteIndex++] = fire_slow[index];
for (int index = 0; index < _fire_slow_start; index++) {
palette[paletteIndex++] = _fire_slow[index];
}
fire_slow_start -= 3;
if (fire_slow_start < 0) {
fire_slow_start = 12;
_fire_slow_start -= 3;
if (_fire_slow_start < 0) {
_fire_slow_start = 12;
}
}
if (getTicksBetween(time, last_cycle_medium) >= kMediumCyclePeriod * gColorCycleSpeedFactor) {
if (getTicksBetween(time, gColorCycleTimestamp2) >= COLOR_CYCLE_PERIOD_2 * gColorCycleSpeedFactor) {
changed = true;
last_cycle_medium = time;
gColorCycleTimestamp2 = time;
int paletteIndex = 243 * 3;
for (int index = fire_fast_start; index < 15; index++) {
palette[paletteIndex++] = fire_fast[index];
for (int index = _fire_fast_start; index < 15; index++) {
palette[paletteIndex++] = _fire_fast[index];
}
for (int index = 0; index < fire_fast_start; index++) {
palette[paletteIndex++] = fire_fast[index];
for (int index = 0; index < _fire_fast_start; index++) {
palette[paletteIndex++] = _fire_fast[index];
}
fire_fast_start -= 3;
if (fire_fast_start < 0) {
fire_fast_start = 12;
_fire_fast_start -= 3;
if (_fire_fast_start < 0) {
_fire_fast_start = 12;
}
}
if (getTicksBetween(time, last_cycle_fast) >= kFastCyclePeriod * gColorCycleSpeedFactor) {
if (getTicksBetween(time, gColorCycleTimestamp3) >= COLOR_CYCLE_PERIOD_3 * gColorCycleSpeedFactor) {
changed = true;
last_cycle_fast = time;
gColorCycleTimestamp3 = time;
int paletteIndex = 233 * 3;
for (int index = monitors_start; index < 15; index++) {
palette[paletteIndex++] = monitors[index];
for (int index = _monitors_start; index < 15; index++) {
palette[paletteIndex++] = _monitors[index];
}
for (int index = 0; index < monitors_start; index++) {
palette[paletteIndex++] = monitors[index];
for (int index = 0; index < _monitors_start; index++) {
palette[paletteIndex++] = _monitors[index];
}
monitors_start -= 3;
_monitors_start -= 3;
if (monitors_start < 0) {
monitors_start = 12;
if (_monitors_start < 0) {
_monitors_start = 12;
}
}
if (getTicksBetween(time, last_cycle_very_fast) >= kVeryFastCyclePeriod * gColorCycleSpeedFactor) {
if (getTicksBetween(time, gColorCycleTimestamp4) >= COLOR_CYCLE_PERIOD_4 * gColorCycleSpeedFactor) {
changed = true;
last_cycle_very_fast = time;
gColorCycleTimestamp4 = time;
if (bobber_red == 0 || bobber_red == 60) {
bobber_diff = -bobber_diff;
if (_bobber_red == 0 || _bobber_red == 60) {
_bobber_diff = -_bobber_diff;
}
bobber_red += bobber_diff;
_bobber_red += _bobber_diff;
int paletteIndex = 254 * 3;
palette[paletteIndex++] = bobber_red;
palette[paletteIndex++] = _bobber_red;
palette[paletteIndex++] = 0;
palette[paletteIndex++] = 0;
}

View File

@@ -11,7 +11,7 @@
namespace fallout {
// 0x5184AC
DatafileLoader* gDatafileLoader = nullptr;
DatafileLoader* gDatafileLoader = NULL;
// 0x5184B0
DatafileNameMangler* gDatafileNameMangler = datafileDefaultNameManglerImpl;
@@ -90,24 +90,24 @@ unsigned char* datafileReadRaw(char* path, int* widthPtr, int* heightPtr)
{
char* mangledPath = gDatafileNameMangler(path);
char* dot = strrchr(mangledPath, '.');
if (dot != nullptr) {
if (dot != NULL) {
if (compat_stricmp(dot + 1, "pcx") == 0) {
return pcxRead(mangledPath, widthPtr, heightPtr, gDatafilePalette);
}
}
if (gDatafileLoader != nullptr) {
if (gDatafileLoader != NULL) {
return gDatafileLoader(mangledPath, gDatafilePalette, widthPtr, heightPtr);
}
return nullptr;
return NULL;
}
// 0x42EFCC
unsigned char* datafileRead(char* path, int* widthPtr, int* heightPtr)
{
unsigned char* v1 = datafileReadRaw(path, widthPtr, heightPtr);
if (v1 != nullptr) {
if (v1 != NULL) {
sub_42EE84(v1, gDatafilePalette, *widthPtr, *heightPtr);
}
return v1;
@@ -121,12 +121,12 @@ unsigned char* sub_42EFF4(char* path)
int width;
int height;
unsigned char* v3 = datafileReadRaw(path, &width, &height);
if (v3 != nullptr) {
if (v3 != NULL) {
internal_free_safe(v3, __FILE__, __LINE__); // "..\\int\\DATAFILE.C", 148
return gDatafilePalette;
}
return nullptr;
return NULL;
}
// NOTE: Unused.
@@ -177,17 +177,17 @@ unsigned char* datafileLoad(char* path, int* sizePtr)
{
const char* mangledPath = gDatafileNameMangler(path);
File* stream = fileOpen(mangledPath, "rb");
if (stream == nullptr) {
return nullptr;
if (stream == NULL) {
return NULL;
}
int size = fileGetSize(stream);
unsigned char* data = (unsigned char*)internal_malloc_safe(size, __FILE__, __LINE__); // "..\\int\\DATAFILE.C", 185
if (data == nullptr) {
if (data == NULL) {
// NOTE: This code is unreachable, internal_malloc_safe never fails.
// Otherwise it leaks stream.
*sizePtr = 0;
return nullptr;
return NULL;
}
fileRead(data, 1, size, stream);

View File

@@ -19,7 +19,7 @@ static int _db_list_compare(const void* p1, const void* p2);
// Generic file progress report handler.
//
// 0x51DEEC
static FileReadProgressHandler* gFileReadProgressHandler = nullptr;
static FileReadProgressHandler* gFileReadProgressHandler = NULL;
// Bytes read so far while tracking progress.
//
@@ -50,29 +50,41 @@ static FileList* gFileListHead;
// 0x4C5D30
int dbOpen(const char* filePath1, int a2, const char* filePath2, int a4)
{
if (filePath1 != nullptr) {
if (filePath1 != NULL) {
if (!xbaseOpen(filePath1)) {
return -1;
}
}
if (filePath2 != nullptr) {
if (filePath2 != NULL) {
xbaseOpen(filePath2);
}
return 0;
}
// 0x4C5D58
int db_total()
// 0x4C5D54
int _db_select(int dbHandle)
{
return 1;
return 0;
}
// NOTE: Uncollapsed 0x4C5D54.
int _db_current()
{
return 0;
}
// 0x4C5D58
int _db_total()
{
return 0;
}
// 0x4C5D60
void dbExit()
{
xbaseReopenAll(nullptr);
xbaseReopenAll(NULL);
}
// TODO: sizePtr should be long*.
@@ -84,7 +96,7 @@ int dbGetFileSize(const char* filePath, int* sizePtr)
assert(sizePtr); // "de", "db.c", 109
File* stream = xfileOpen(filePath, "rb");
if (stream == nullptr) {
if (stream == NULL) {
return -1;
}
@@ -102,12 +114,12 @@ int dbGetFileContents(const char* filePath, void* ptr)
assert(ptr); // "buf", "db.c", 142
File* stream = xfileOpen(filePath, "rb");
if (stream == nullptr) {
if (stream == NULL) {
return -1;
}
long size = xfileGetSize(stream);
if (gFileReadProgressHandler != nullptr) {
if (gFileReadProgressHandler != NULL) {
unsigned char* byteBuffer = (unsigned char*)ptr;
long remainingSize = size;
@@ -166,7 +178,7 @@ int filePrintFormatted(File* stream, const char* format, ...)
// 0x4C5F24
int fileReadChar(File* stream)
{
if (gFileReadProgressHandler != nullptr) {
if (gFileReadProgressHandler != NULL) {
int ch = xfileReadChar(stream);
gFileReadProgressBytesRead++;
@@ -184,9 +196,9 @@ int fileReadChar(File* stream)
// 0x4C5F70
char* fileReadString(char* string, size_t size, File* stream)
{
if (gFileReadProgressHandler != nullptr) {
if (xfileReadString(string, size, stream) == nullptr) {
return nullptr;
if (gFileReadProgressHandler != NULL) {
if (xfileReadString(string, size, stream) == NULL) {
return NULL;
}
gFileReadProgressBytesRead += strlen(string);
@@ -210,7 +222,7 @@ int fileWriteString(const char* string, File* stream)
// 0x4C5FFC
size_t fileRead(void* ptr, size_t size, size_t count, File* stream)
{
if (gFileReadProgressHandler != nullptr) {
if (gFileReadProgressHandler != NULL) {
unsigned char* byteBuffer = (unsigned char*)ptr;
size_t totalBytesRead = 0;
@@ -326,7 +338,7 @@ int fileReadInt32(File* stream, int* valuePtr)
return -1;
}
*valuePtr = ((value & 0xFF000000) >> 24) | ((value & 0xFF0000) >> 8) | ((value & 0xFF00) << 8) | ((value & 0xFF) << 24);
*valuePtr = ((value >> 24) & 0xFF) | ((value >> 8) & 0xFF00) | ((value << 8) & 0xFF0000) | ((value << 24) & 0xFF000000);
return 0;
}
@@ -499,7 +511,7 @@ int fileReadInt32List(File* stream, int* arr, int count)
for (int index = 0; index < count; index++) {
int value = arr[index];
arr[index] = ((value & 0xFF000000) >> 24) | ((value & 0xFF0000) >> 8) | ((value & 0xFF00) << 8) | ((value & 0xFF) << 24);
arr[index] = ((value >> 24) & 0xFF) | ((value >> 8) & 0xFF00) | ((value << 8) & 0xFF0000) | ((value << 24) & 0xFF000000);
}
return 0;
@@ -602,7 +614,7 @@ int fileWriteUInt32List(File* stream, unsigned int* arr, int count)
int fileNameListInit(const char* pattern, char*** fileNameListPtr, int a3, int a4)
{
FileList* fileList = (FileList*)malloc(sizeof(*fileList));
if (fileList == nullptr) {
if (fileList == NULL) {
return 0;
}
@@ -633,18 +645,17 @@ int fileNameListInit(const char* pattern, char*** fileNameListPtr, int a3, int a
bool isWildcard = *pattern == '*';
for (int index = 0; index < fileNamesLength; index += 1) {
char* name = xlist->fileNames[index];
const char* name = xlist->fileNames[index];
char dir[COMPAT_MAX_DIR];
char fileName[COMPAT_MAX_FNAME];
char extension[COMPAT_MAX_EXT];
compat_windows_path_to_native(name);
compat_splitpath(name, nullptr, dir, fileName, extension);
compat_splitpath(name, NULL, dir, fileName, extension);
if (!isWildcard || *dir == '\0' || (strchr(dir, '\\') == nullptr && strchr(dir, '/') == nullptr)) {
if (!isWildcard || *dir == '\0' || strchr(dir, '\\') == NULL) {
// NOTE: Quick and dirty fix to buffer overflow. See RE to
// understand the problem.
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s%s", fileName, extension);
sprintf(path, "%s%s", fileName, extension);
free(xlist->fileNames[length]);
xlist->fileNames[length] = compat_strdup(path);
length++;
@@ -663,7 +674,7 @@ int fileNameListInit(const char* pattern, char*** fileNameListPtr, int a3, int a
// 0x4C6868
void fileNameListFree(char*** fileNameListPtr, int a2)
{
if (gFileListHead == nullptr) {
if (gFileListHead == NULL) {
return;
}
@@ -672,7 +683,7 @@ void fileNameListFree(char*** fileNameListPtr, int a2)
while (*fileNameListPtr != currentFileList->xlist.fileNames) {
previousFileList = currentFileList;
currentFileList = currentFileList->next;
if (currentFileList == nullptr) {
if (currentFileList == NULL) {
return;
}
}
@@ -688,6 +699,14 @@ void fileNameListFree(char*** fileNameListPtr, int a2)
free(currentFileList);
}
// NOTE: This function does nothing. It was probably used to set memory procs
// for building file name list.
//
// 0x4C68B8
void _db_register_mem(MallocProc* mallocProc, StrdupProc* strdupProc, FreeProc* freeProc)
{
}
// TODO: Return type should be long.
//
// 0x4C68BC
@@ -699,15 +718,23 @@ int fileGetSize(File* stream)
// 0x4C68C4
void fileSetReadProgressHandler(FileReadProgressHandler* handler, int size)
{
if (handler != nullptr && size != 0) {
if (handler != NULL && size != 0) {
gFileReadProgressHandler = handler;
gFileReadProgressChunkSize = size;
} else {
gFileReadProgressHandler = nullptr;
gFileReadProgressHandler = NULL;
gFileReadProgressChunkSize = 0;
}
}
// NOTE: This function is called when fallout2.cfg has "hashing" enabled, but
// it does nothing. It's impossible to guess it's name.
//
// 0x4C68E4
void _db_enable_hash_table_()
{
}
// 0x4C68E8
int _db_list_compare(const void* p1, const void* p2)
{

View File

@@ -3,6 +3,7 @@
#include <stddef.h>
#include "memory_defs.h"
#include "xfile.h"
namespace fallout {
@@ -12,7 +13,9 @@ typedef void FileReadProgressHandler();
typedef char* StrdupProc(const char* string);
int dbOpen(const char* filePath1, int a2, const char* filePath2, int a4);
int db_total();
int _db_select(int dbHandle);
int _db_current();
int _db_total();
void dbExit();
int dbGetFileSize(const char* filePath, int* sizePtr);
int dbGetFileContents(const char* filePath, void* ptr);
@@ -60,8 +63,10 @@ int _db_fwriteLongCount(File* stream, int* arr, int count);
int fileWriteUInt32List(File* stream, unsigned int* arr, int count);
int fileNameListInit(const char* pattern, char*** fileNames, int a3, int a4);
void fileNameListFree(char*** fileNames, int a2);
void _db_register_mem(MallocProc* mallocProc, StrdupProc* strdupProc, FreeProc* freeProc);
int fileGetSize(File* stream);
void fileSetReadProgressHandler(FileReadProgressHandler* handler, int size);
void _db_enable_hash_table_();
} // namespace fallout

View File

@@ -8,17 +8,13 @@
#include "art.h"
#include "character_editor.h"
#include "color.h"
#include "core.h"
#include "debug.h"
#include "delay.h"
#include "draw.h"
#include "game.h"
#include "game_sound.h"
#include "input.h"
#include "kb.h"
#include "message.h"
#include "mouse.h"
#include "platform_compat.h"
#include "svga.h"
#include "text_font.h"
#include "window_manager.h"
#include "word_wrap.h"
@@ -157,12 +153,12 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
bool v86 = false;
bool hasTwoButtons = false;
if (a8 != nullptr) {
if (a8 != NULL) {
hasTwoButtons = true;
}
bool hasTitle = false;
if (title != nullptr) {
if (title != NULL) {
hasTitle = true;
}
@@ -179,7 +175,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
int linesCount = 0;
for (int index = 0; index < bodyLength; index++) {
// NOTE: Originally there is no `max` macro.
// NOTE: Calls [fontGetStringWidth] twice because of [max] macro.
maximumLineWidth = std::max(fontGetStringWidth(body[index]), maximumLineWidth);
linesCount++;
}
@@ -207,14 +203,14 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
}
// Maintain original position in original resolution, otherwise center it.
x += (screenGetWidth() - 640) / 2;
y += (screenGetHeight() - 480) / 2;
if (screenGetWidth() != 640) x = (screenGetWidth() - backgroundFrmImage.getWidth()) / 2;
if (screenGetHeight() != 480) y = (screenGetHeight() - backgroundFrmImage.getHeight()) / 2;
int win = windowCreate(x,
y,
backgroundFrmImage.getWidth(),
backgroundFrmImage.getHeight(),
256,
WINDOW_MODAL | WINDOW_MOVE_ON_TOP);
WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
if (win == -1) {
fontSetCurrent(savedFont);
return -1;
@@ -266,7 +262,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
}
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s%s", asc_5186C8, "DBOX.MSG");
sprintf(path, "%s%s", asc_5186C8, "DBOX.MSG");
if (!messageListLoad(&messageList, path)) {
fontSetCurrent(savedFont);
@@ -298,7 +294,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
500,
buttonNormalFrmImage.getData(),
buttonPressedFrmImage.getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (btn != -1) {
buttonSetCallbacks(btn, _gsound_red_butt_press, _gsound_red_butt_release);
@@ -339,7 +335,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
501,
buttonNormalFrmImage.getData(),
buttonPressedFrmImage.getData(),
nullptr,
0,
BUTTON_FLAG_TRANSPARENT);
if (btn != -1) {
buttonSetCallbacks(btn, _gsound_red_butt_press, _gsound_red_butt_release);
@@ -373,7 +369,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
}
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s%s", asc_5186C8, "DBOX.MSG");
sprintf(path, "%s%s", asc_5186C8, "DBOX.MSG");
if (!messageListLoad(&messageList, path)) {
fontSetCurrent(savedFont);
@@ -404,7 +400,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
501,
buttonNormalFrmImage.getData(),
buttonPressedFrmImage.getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (btn != -1) {
buttonSetCallbacks(btn, _gsound_red_butt_press, _gsound_red_butt_release);
@@ -416,107 +412,81 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
fontSetCurrent(101);
int nextY = _ytable[dialogType];
int maxY = _ytable[dialogType] + _dblines[dialogType] * fontGetLineHeight();
int v23 = _ytable[dialogType];
if ((flags & DIALOG_BOX_NO_VERTICAL_CENTERING) == 0) {
int numberOfLines = 0;
if (hasTitle) {
numberOfLines++;
}
for (int index = 0; index < bodyLength; index++) {
short beginnings[WORD_WRAP_MAX_COUNT];
short subLineCount;
int maxWidth = backgroundFrmImage.getWidth() - _xtable[dialogType] * 2;
if (wordWrap(body[index], maxWidth, beginnings, &subLineCount) == 0) {
numberOfLines += subLineCount - 1;
}
}
if (numberOfLines > _dblines[dialogType]) {
numberOfLines = _dblines[dialogType];
}
nextY += (_dblines[dialogType] - numberOfLines) * fontGetLineHeight() / 2;
int v41 = _dblines[dialogType] * fontGetLineHeight() / 2 + v23;
v23 = v41 - ((bodyLength + 1) * fontGetLineHeight() / 2);
}
if (hasTitle) {
if ((flags & DIALOG_BOX_NO_HORIZONTAL_CENTERING) != 0) {
fontDrawText(windowBuf + backgroundFrmImage.getWidth() * nextY + _xtable[dialogType],
fontDrawText(windowBuf + backgroundFrmImage.getWidth() * v23 + _xtable[dialogType],
title,
backgroundFrmImage.getWidth(),
backgroundFrmImage.getWidth(),
titleColor);
} else {
int length = fontGetStringWidth(title);
fontDrawText(windowBuf + backgroundFrmImage.getWidth() * nextY + (backgroundFrmImage.getWidth() - length) / 2,
fontDrawText(windowBuf + backgroundFrmImage.getWidth() * v23 + (backgroundFrmImage.getWidth() - length) / 2,
title,
backgroundFrmImage.getWidth(),
backgroundFrmImage.getWidth(),
titleColor);
}
nextY += fontGetLineHeight();
v23 += fontGetLineHeight();
}
for (int index = 0; index < bodyLength && nextY < maxY; index++) {
int width = fontGetStringWidth(body[index]);
int maxWidth = backgroundFrmImage.getWidth() - _xtable[dialogType] * 2;
if (width <= maxWidth) {
for (int v94 = 0; v94 < bodyLength; v94++) {
int len = fontGetStringWidth(body[v94]);
if (len <= backgroundFrmImage.getWidth() - 26) {
if ((flags & DIALOG_BOX_NO_HORIZONTAL_CENTERING) != 0) {
fontDrawText(windowBuf + backgroundFrmImage.getWidth() * nextY + _xtable[dialogType],
body[index],
fontDrawText(windowBuf + backgroundFrmImage.getWidth() * v23 + _xtable[dialogType],
body[v94],
backgroundFrmImage.getWidth(),
backgroundFrmImage.getWidth(),
bodyColor);
} else {
int length = fontGetStringWidth(body[index]);
fontDrawText(windowBuf + backgroundFrmImage.getWidth() * nextY + (backgroundFrmImage.getWidth() - length) / 2,
body[index],
int length = fontGetStringWidth(body[v94]);
fontDrawText(windowBuf + backgroundFrmImage.getWidth() * v23 + (backgroundFrmImage.getWidth() - length) / 2,
body[v94],
backgroundFrmImage.getWidth(),
backgroundFrmImage.getWidth(),
bodyColor);
}
nextY += fontGetLineHeight();
v23 += fontGetLineHeight();
} else {
short beginnings[WORD_WRAP_MAX_COUNT];
short count;
if (wordWrap(body[index], maxWidth, beginnings, &count) != 0) {
if (wordWrap(body[v94], backgroundFrmImage.getWidth() - 26, beginnings, &count) != 0) {
debugPrint("\nError: dialog_out");
}
for (int beginningIndex = 1; beginningIndex < count && nextY < maxY; beginningIndex++) {
int subLineLength = beginnings[beginningIndex] - beginnings[beginningIndex - 1];
if (subLineLength >= 260) {
subLineLength = 259;
for (int v48 = 1; v48 < count; v48++) {
int v51 = beginnings[v48] - beginnings[v48 - 1];
if (v51 >= 260) {
v51 = 259;
}
char string[260];
strncpy(string, body[index] + beginnings[beginningIndex - 1], subLineLength);
string[subLineLength] = '\0';
// Remove trailing space as it affects width calculation.
if (subLineLength > 0 && string[subLineLength - 1] == ' ') {
string[subLineLength - 1] = '\0';
subLineLength -= 1;
}
strncpy(string, body[v94] + beginnings[v48 - 1], v51);
string[v51] = '\0';
if ((flags & DIALOG_BOX_NO_HORIZONTAL_CENTERING) != 0) {
fontDrawText(windowBuf + backgroundFrmImage.getWidth() * nextY + _xtable[dialogType],
fontDrawText(windowBuf + backgroundFrmImage.getWidth() * v23 + _xtable[dialogType],
string,
backgroundFrmImage.getWidth(),
backgroundFrmImage.getWidth(),
bodyColor);
} else {
int length = fontGetStringWidth(string);
fontDrawText(windowBuf + backgroundFrmImage.getWidth() * nextY + (backgroundFrmImage.getWidth() - length) / 2,
fontDrawText(windowBuf + backgroundFrmImage.getWidth() * v23 + (backgroundFrmImage.getWidth() - length) / 2,
string,
backgroundFrmImage.getWidth(),
backgroundFrmImage.getWidth(),
bodyColor);
}
nextY += fontGetLineHeight();
v23 += fontGetLineHeight();
}
}
}
@@ -525,9 +495,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
int rc = -1;
while (rc == -1) {
sharedFpsLimiter.mark();
int keyCode = inputGetInput();
int keyCode = _get_input();
if (keyCode == 500) {
rc = 1;
@@ -549,9 +517,6 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
if (_game_user_wants_to_quit != 0) {
rc = 1;
}
renderPresent();
sharedFpsLimiter.throttle();
}
windowDestroy(win);
@@ -597,9 +562,9 @@ int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLen
int backgroundHeight = frmImages[FILE_DIALOG_FRM_BACKGROUND].getHeight();
// Maintain original position in original resolution, otherwise center it.
x += (screenGetWidth() - 640) / 2;
y += (screenGetHeight() - 480) / 2;
int win = windowCreate(x, y, backgroundWidth, backgroundHeight, 256, WINDOW_MODAL | WINDOW_MOVE_ON_TOP);
if (screenGetWidth() != 640) x = (screenGetWidth() - backgroundWidth) / 2;
if (screenGetHeight() != 480) y = (screenGetHeight() - backgroundHeight) / 2;
int win = windowCreate(x, y, backgroundWidth, backgroundHeight, 256, WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
if (win == -1) {
return -1;
}
@@ -616,7 +581,7 @@ int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLen
}
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s%s", asc_5186C8, "DBOX.MSG");
sprintf(path, "%s%s", asc_5186C8, "DBOX.MSG");
if (!messageListLoad(&messageList, path)) {
windowDestroy(win);
@@ -644,7 +609,7 @@ int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLen
500,
frmImages[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL].getData(),
frmImages[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (doneBtn != -1) {
buttonSetCallbacks(doneBtn, _gsound_red_butt_press, _gsound_red_butt_release);
@@ -661,7 +626,7 @@ int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLen
501,
frmImages[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL].getData(),
frmImages[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (cancelBtn != -1) {
buttonSetCallbacks(cancelBtn, _gsound_red_butt_press, _gsound_red_butt_release);
@@ -678,7 +643,7 @@ int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLen
505,
frmImages[FILE_DIALOG_FRM_SCROLL_UP_ARROW_NORMAL].getData(),
frmImages[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (scrollUpBtn != -1) {
buttonSetCallbacks(cancelBtn, _gsound_red_butt_press, _gsound_red_butt_release);
@@ -695,7 +660,7 @@ int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLen
503,
frmImages[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_NORMAL].getData(),
frmImages[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED].getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (scrollUpBtn != -1) {
buttonSetCallbacks(cancelBtn, _gsound_red_butt_press, _gsound_red_butt_release);
@@ -711,12 +676,12 @@ int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLen
-1,
-1,
502,
nullptr,
nullptr,
nullptr,
NULL,
NULL,
NULL,
0);
if (title != nullptr) {
if (title != NULL) {
fontDrawText(windowBuffer + backgroundWidth * FILE_DIALOG_TITLE_Y + FILE_DIALOG_TITLE_X, title, backgroundWidth, backgroundWidth, _colorTable[18979]);
}
@@ -730,10 +695,8 @@ int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLen
int rc = -1;
while (rc == -1) {
sharedFpsLimiter.mark();
unsigned int tick = getTicks();
int keyCode = inputGetInput();
unsigned int tick = _get_time();
int keyCode = _get_input();
int scrollDirection = FILE_DIALOG_SCROLL_DIRECTION_NONE;
int scrollCounter = 0;
bool isScrolling = false;
@@ -842,7 +805,7 @@ int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLen
unsigned int scrollDelay = 4;
doubleClickSelectedFileIndex = -2;
while (1) {
unsigned int scrollTick = getTicks();
unsigned int scrollTick = _get_time();
scrollCounter += 1;
if ((!isScrolling && scrollCounter == 1) || (isScrolling && scrollCounter > 14.4)) {
isScrolling = true;
@@ -886,20 +849,18 @@ int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLen
}
unsigned int delay = (scrollCounter > 14.4) ? 1000 / scrollDelay : 1000 / 24;
delay_ms(delay - (getTicks() - scrollTick));
while (getTicksSince(scrollTick) < delay) {
}
if (_game_user_wants_to_quit != 0) {
rc = 1;
break;
}
int keyCode = inputGetInput();
int keyCode = _get_input();
if (keyCode == 505 || keyCode == 503) {
break;
}
renderPresent();
}
} else {
windowRefresh(win);
@@ -910,15 +871,13 @@ int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLen
doubleClickSelectedFileIndex = -2;
}
delay_ms(1000 / 24 - (getTicks() - tick));
while (getTicksSince(tick) < (1000 / 24)) {
}
}
if (_game_user_wants_to_quit) {
rc = 1;
}
renderPresent();
sharedFpsLimiter.throttle();
}
windowDestroy(win);
@@ -962,9 +921,9 @@ int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLen
int backgroundHeight = frmImages[FILE_DIALOG_FRM_BACKGROUND].getHeight();
// Maintain original position in original resolution, otherwise center it.
x += (screenGetWidth() - 640) / 2;
y += (screenGetHeight() - 480) / 2;
int win = windowCreate(x, y, backgroundWidth, backgroundHeight, 256, WINDOW_MODAL | WINDOW_MOVE_ON_TOP);
if (screenGetWidth() != 640) x = (screenGetWidth() - backgroundWidth) / 2;
if (screenGetHeight() != 480) y = (screenGetHeight() - backgroundHeight) / 2;
int win = windowCreate(x, y, backgroundWidth, backgroundHeight, 256, WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
if (win == -1) {
return -1;
}
@@ -981,7 +940,7 @@ int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLen
}
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s%s", asc_5186C8, "DBOX.MSG");
sprintf(path, "%s%s", asc_5186C8, "DBOX.MSG");
if (!messageListLoad(&messageList, path)) {
windowDestroy(win);
@@ -1009,7 +968,7 @@ int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLen
500,
frmImages[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL].getData(),
frmImages[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (doneBtn != -1) {
buttonSetCallbacks(doneBtn, _gsound_red_butt_press, _gsound_red_butt_release);
@@ -1026,7 +985,7 @@ int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLen
501,
frmImages[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL].getData(),
frmImages[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (cancelBtn != -1) {
buttonSetCallbacks(cancelBtn, _gsound_red_butt_press, _gsound_red_butt_release);
@@ -1043,7 +1002,7 @@ int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLen
505,
frmImages[FILE_DIALOG_FRM_SCROLL_UP_ARROW_NORMAL].getData(),
frmImages[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (scrollUpBtn != -1) {
buttonSetCallbacks(cancelBtn, _gsound_red_butt_press, _gsound_red_butt_release);
@@ -1060,7 +1019,7 @@ int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLen
503,
frmImages[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_NORMAL].getData(),
frmImages[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED].getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (scrollUpBtn != -1) {
buttonSetCallbacks(cancelBtn, _gsound_red_butt_press, _gsound_red_butt_release);
@@ -1076,12 +1035,12 @@ int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLen
-1,
-1,
502,
nullptr,
nullptr,
nullptr,
NULL,
NULL,
NULL,
0);
if (title != nullptr) {
if (title != NULL) {
fontDrawText(windowBuffer + backgroundWidth * FILE_DIALOG_TITLE_Y + FILE_DIALOG_TITLE_X, title, backgroundWidth, backgroundWidth, _colorTable[18979]);
}
@@ -1115,8 +1074,6 @@ int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLen
windowRefresh(win);
beginTextInput();
int blinkingCounter = 3;
bool blink = false;
@@ -1125,10 +1082,8 @@ int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLen
int rc = -1;
while (rc == -1) {
sharedFpsLimiter.mark();
unsigned int tick = getTicks();
int keyCode = inputGetInput();
unsigned int tick = _get_time();
int keyCode = _get_input();
int scrollDirection = FILE_DIALOG_SCROLL_DIRECTION_NONE;
int scrollCounter = 0;
bool isScrolling = false;
@@ -1274,7 +1229,7 @@ int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLen
unsigned int scrollDelay = 4;
doubleClickSelectedFileIndex = -2;
while (1) {
unsigned int scrollTick = getTicks();
unsigned int scrollTick = _get_time();
scrollCounter += 1;
if ((!isScrolling && scrollCounter == 1) || (isScrolling && scrollCounter > 14.4)) {
isScrolling = true;
@@ -1335,19 +1290,18 @@ int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLen
// FIXME: Missing windowRefresh makes blinking useless.
unsigned int delay = (scrollCounter > 14.4) ? 1000 / scrollDelay : 1000 / 24;
delay_ms(delay - (getTicks() - scrollTick));
while (getTicksSince(scrollTick) < delay) {
}
if (_game_user_wants_to_quit != 0) {
rc = 1;
break;
}
int key = inputGetInput();
int key = _get_input();
if (key == 505 || key == 503) {
break;
}
renderPresent();
}
} else {
blinkingCounter -= 1;
@@ -1368,19 +1322,15 @@ int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLen
doubleClickSelectedFileIndex = -2;
}
delay_ms(1000 / 24 - (getTicks() - tick));
while (getTicksSince(tick) < (1000 / 24)) {
}
}
if (_game_user_wants_to_quit != 0) {
rc = 1;
}
renderPresent();
sharedFpsLimiter.throttle();
}
endTextInput();
if (rc == 0) {
if (fileNameCopyLength != 0) {
fileNameCopy[fileNameCopyLength] = '\0';
@@ -1414,7 +1364,7 @@ static void fileDialogRenderFileList(unsigned char* buffer, char** fileList, int
for (int index = 0; index < fileListLength; index++) {
int color = index == selectedIndex ? _colorTable[32747] : _colorTable[992];
fontDrawText(buffer + pitch * y + FILE_DIALOG_FILE_LIST_X, fileList[pageOffset + index], FILE_DIALOG_FILE_LIST_WIDTH, pitch, color);
fontDrawText(buffer + pitch * y + FILE_DIALOG_FILE_LIST_X, fileList[pageOffset + index], pitch, pitch, color);
y += lineHeight;
}
}

View File

@@ -5,7 +5,10 @@
#include <stdlib.h>
#include <string.h>
#include <SDL.h>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include "memory.h"
#include "platform_compat.h"
@@ -22,7 +25,7 @@ static void _debug_putc(int ch);
static void _debug_scroll();
// 0x51DEF8
static FILE* _fd = nullptr;
static FILE* _fd = NULL;
// 0x51DEFC
static int _curx = 0;
@@ -31,7 +34,7 @@ static int _curx = 0;
static int _cury = 0;
// 0x51DF04
static DebugPrintProc* gDebugPrintProc = nullptr;
static DebugPrintProc* gDebugPrintProc = NULL;
// 0x4C6CD0
void _GNW_debug_init()
@@ -43,9 +46,9 @@ void _GNW_debug_init()
void _debug_register_mono()
{
if (gDebugPrintProc != _debug_mono) {
if (_fd != nullptr) {
if (_fd != NULL) {
fclose(_fd);
_fd = nullptr;
_fd = NULL;
}
gDebugPrintProc = _debug_mono;
@@ -56,8 +59,8 @@ void _debug_register_mono()
// 0x4C6D18
void _debug_register_log(const char* fileName, const char* mode)
{
if ((mode[0] == 'w' || mode[0] == 'a') && mode[1] == 't') {
if (_fd != nullptr) {
if ((mode[0] == 'w' && mode[1] == 'a') && mode[1] == 't') {
if (_fd != NULL) {
fclose(_fd);
}
@@ -70,9 +73,9 @@ void _debug_register_log(const char* fileName, const char* mode)
void _debug_register_screen()
{
if (gDebugPrintProc != _debug_screen) {
if (_fd != nullptr) {
if (_fd != NULL) {
fclose(_fd);
_fd = nullptr;
_fd = NULL;
}
gDebugPrintProc = _debug_screen;
@@ -83,12 +86,12 @@ void _debug_register_screen()
void _debug_register_env()
{
const char* type = getenv("DEBUGACTIVE");
if (type == nullptr) {
if (type == NULL) {
return;
}
char* copy = (char*)internal_malloc(strlen(type) + 1);
if (copy == nullptr) {
if (copy == NULL) {
return;
}
@@ -104,8 +107,14 @@ void _debug_register_env()
// NOTE: Uninline.
_debug_register_screen();
} else if (strcmp(copy, "gnw") == 0) {
// NOTE: Uninline.
_debug_register_func(_win_debug);
if (gDebugPrintProc != _win_debug) {
if (_fd != NULL) {
fclose(_fd);
_fd = NULL;
}
gDebugPrintProc = _win_debug;
}
}
internal_free(copy);
@@ -115,9 +124,9 @@ void _debug_register_env()
void _debug_register_func(DebugPrintProc* proc)
{
if (gDebugPrintProc != proc) {
if (_fd != nullptr) {
if (_fd != NULL) {
fclose(_fd);
_fd = nullptr;
_fd = NULL;
}
gDebugPrintProc = proc;
@@ -132,14 +141,20 @@ int debugPrint(const char* format, ...)
int rc;
if (gDebugPrintProc != nullptr) {
if (gDebugPrintProc != NULL) {
char string[260];
vsnprintf(string, sizeof(string), format, args);
vsprintf(string, format, args);
rc = gDebugPrintProc(string);
} else {
#ifndef NDEBUG
SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, format, args);
#ifdef _DEBUG
char string[260];
vsprintf(string, format, args);
#ifdef _WIN32
OutputDebugStringA(string);
#else
printf("%s", string);
#endif
#endif
rc = -1;
}
@@ -152,7 +167,7 @@ int debugPrint(const char* format, ...)
// 0x4C6F94
static int _debug_puts(char* string)
{
if (gDebugPrintProc != nullptr) {
if (gDebugPrintProc != NULL) {
return gDebugPrintProc(string);
}
@@ -166,7 +181,7 @@ static void _debug_clear()
int x;
int y;
buffer = nullptr;
buffer = NULL;
if (gDebugPrintProc == _debug_mono) {
buffer = (char*)0xB0000;
@@ -174,7 +189,7 @@ static void _debug_clear()
buffer = (char*)0xB8000;
}
if (buffer != nullptr) {
if (buffer != NULL) {
for (y = 0; y < 25; y++) {
for (x = 0; x < 80; x++) {
*buffer++ = ' ';
@@ -202,7 +217,7 @@ static int _debug_mono(char* string)
static int _debug_log(char* string)
{
if (gDebugPrintProc == _debug_log) {
if (_fd == nullptr) {
if (_fd == NULL) {
return -1;
}
@@ -300,7 +315,7 @@ static void _debug_scroll()
// 0x4C71E8
void _debug_exit(void)
{
if (_fd != nullptr) {
if (_fd != NULL) {
fclose(_fd);
}
}

View File

@@ -1,11 +0,0 @@
#include "delay.h"
#include <SDL.h>
void delay_ms(int ms)
{
if (ms <= 0) {
return;
}
SDL_Delay(ms);
}

View File

@@ -1,6 +0,0 @@
#ifndef DELAY_H
#define DELAY_H
void delay_ms(int ms);
#endif

View File

@@ -5,9 +5,7 @@
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <fpattern/fpattern.h>
#include <fpattern.h>
#include "platform_compat.h"
@@ -51,14 +49,14 @@ DBase* dbaseOpen(const char* filePath)
assert(filePath); // "filename", "dfile.c", 74
FILE* stream = compat_fopen(filePath, "rb");
if (stream == nullptr) {
return nullptr;
if (stream == NULL) {
return NULL;
}
DBase* dbase = (DBase*)malloc(sizeof(*dbase));
if (dbase == nullptr) {
if (dbase == NULL) {
fclose(stream);
return nullptr;
return NULL;
}
memset(dbase, 0, sizeof(*dbase));
@@ -95,7 +93,7 @@ DBase* dbaseOpen(const char* filePath)
}
dbase->entries = (DBaseEntry*)malloc(sizeof(*dbase->entries) * dbase->entriesLength);
if (dbase->entries == nullptr) {
if (dbase->entries == NULL) {
goto err;
}
@@ -112,7 +110,7 @@ DBase* dbaseOpen(const char* filePath)
}
entry->path = (char*)malloc(pathLength + 1);
if (entry->path == nullptr) {
if (entry->path == NULL) {
break;
}
@@ -158,7 +156,7 @@ err:
fclose(stream);
return nullptr;
return NULL;
}
// Closes [dbase], all open file handles, frees all associated resources,
@@ -170,24 +168,24 @@ bool dbaseClose(DBase* dbase)
assert(dbase); // "dbase", "dfile.c", 173
DFile* curr = dbase->dfileHead;
while (curr != nullptr) {
while (curr != NULL) {
DFile* next = curr->next;
dfileClose(curr);
curr = next;
}
if (dbase->entries != nullptr) {
if (dbase->entries != NULL) {
for (int index = 0; index < dbase->entriesLength; index++) {
DBaseEntry* entry = &(dbase->entries[index]);
char* entryName = entry->path;
if (entryName != nullptr) {
if (entryName != NULL) {
free(entryName);
}
}
free(dbase->entries);
}
if (dbase->path != nullptr) {
if (dbase->path != NULL) {
free(dbase->path);
}
@@ -258,15 +256,15 @@ int dfileClose(DFile* stream)
}
}
if (stream->decompressionStream != nullptr) {
if (stream->decompressionStream != NULL) {
free(stream->decompressionStream);
}
if (stream->decompressionBuffer != nullptr) {
if (stream->decompressionBuffer != NULL) {
free(stream->decompressionBuffer);
}
if (stream->stream != nullptr) {
if (stream->stream != NULL) {
fclose(stream->stream);
}
@@ -275,8 +273,8 @@ int dfileClose(DFile* stream)
//
// NOTE: Compiled code is slightly different.
DFile* curr = stream->dbase->dfileHead;
DFile* prev = nullptr;
while (curr != nullptr) {
DFile* prev = NULL;
while (curr != NULL) {
if (curr == stream) {
break;
}
@@ -285,8 +283,8 @@ int dfileClose(DFile* stream)
curr = curr->next;
}
if (curr != nullptr) {
if (prev == nullptr) {
if (curr != NULL) {
if (prev == NULL) {
stream->dbase->dfileHead = stream->next;
} else {
prev->next = stream->next;
@@ -309,7 +307,7 @@ DFile* dfileOpen(DBase* dbase, const char* filePath, const char* mode)
assert(filePath); // dfile.c, 296
assert(mode); // dfile.c, 297
return dfileOpenInternal(dbase, filePath, mode, nullptr);
return dfileOpenInternal(dbase, filePath, mode, 0);
}
// [vfprintf].
@@ -363,7 +361,7 @@ char* dfileReadString(char* string, int size, DFile* stream)
assert(stream); // "stream", "dfile.c", 409
if ((stream->flags & DFILE_EOF) != 0 || (stream->flags & DFILE_ERROR) != 0) {
return nullptr;
return NULL;
}
char* pch = string;
@@ -391,7 +389,7 @@ char* dfileReadString(char* string, int size, DFile* stream)
if (pch == string) {
// No character was set into the buffer.
return nullptr;
return NULL;
}
*pch = '\0';
@@ -633,7 +631,7 @@ static int dbaseFindEntryByFilePath(const void* a1, const void* a2)
static DFile* dfileOpenInternal(DBase* dbase, const char* filePath, const char* mode, DFile* dfile)
{
DBaseEntry* entry = (DBaseEntry*)bsearch(filePath, dbase->entries, dbase->entriesLength, sizeof(*dbase->entries), dbaseFindEntryByFilePath);
if (entry == nullptr) {
if (entry == NULL) {
goto err;
}
@@ -641,10 +639,10 @@ static DFile* dfileOpenInternal(DBase* dbase, const char* filePath, const char*
goto err;
}
if (dfile == nullptr) {
if (dfile == NULL) {
dfile = (DFile*)malloc(sizeof(*dfile));
if (dfile == nullptr) {
return nullptr;
if (dfile == NULL) {
return NULL;
}
memset(dfile, 0, sizeof(*dfile));
@@ -656,9 +654,9 @@ static DFile* dfileOpenInternal(DBase* dbase, const char* filePath, const char*
goto err;
}
if (dfile->stream != nullptr) {
if (dfile->stream != NULL) {
fclose(dfile->stream);
dfile->stream = nullptr;
dfile->stream = NULL;
}
dfile->compressedBytesRead = 0;
@@ -670,7 +668,7 @@ static DFile* dfileOpenInternal(DBase* dbase, const char* filePath, const char*
// Open stream to .DAT file.
dfile->stream = compat_fopen(dbase->path, "rb");
if (dfile->stream == nullptr) {
if (dfile->stream == NULL) {
goto err;
}
@@ -684,14 +682,14 @@ static DFile* dfileOpenInternal(DBase* dbase, const char* filePath, const char*
// buffer. This step is not needed when previous instance of dfile is
// passed via parameter, which might already have stream and
// buffer allocated.
if (dfile->decompressionStream == nullptr) {
if (dfile->decompressionStream == NULL) {
dfile->decompressionStream = (z_streamp)malloc(sizeof(*dfile->decompressionStream));
if (dfile->decompressionStream == nullptr) {
if (dfile->decompressionStream == NULL) {
goto err;
}
dfile->decompressionBuffer = (unsigned char*)malloc(DFILE_DECOMPRESSION_BUFFER_SIZE);
if (dfile->decompressionBuffer == nullptr) {
if (dfile->decompressionBuffer == NULL) {
goto err;
}
}
@@ -709,14 +707,14 @@ static DFile* dfileOpenInternal(DBase* dbase, const char* filePath, const char*
// Entry is not compressed, there is no need to keep decompression
// stream and decompression buffer (in case [dfile] was passed via
// parameter).
if (dfile->decompressionStream != nullptr) {
if (dfile->decompressionStream != NULL) {
free(dfile->decompressionStream);
dfile->decompressionStream = nullptr;
dfile->decompressionStream = NULL;
}
if (dfile->decompressionBuffer != nullptr) {
if (dfile->decompressionBuffer != NULL) {
free(dfile->decompressionBuffer);
dfile->decompressionBuffer = nullptr;
dfile->decompressionBuffer = NULL;
}
}
@@ -728,11 +726,11 @@ static DFile* dfileOpenInternal(DBase* dbase, const char* filePath, const char*
err:
if (dfile != nullptr) {
if (dfile != NULL) {
dfileClose(dfile);
}
return nullptr;
return NULL;
}
// 0x4E5F9C
@@ -820,7 +818,10 @@ static bool dfileReadCompressed(DFile* stream, void* ptr, size_t size)
if (stream->decompressionStream->avail_in == 0) {
// No more unprocessed data, request next chunk.
size_t bytesToRead = std::min(DFILE_DECOMPRESSION_BUFFER_SIZE, stream->entry->dataSize - stream->compressedBytesRead);
size_t bytesToRead = stream->entry->dataSize - stream->compressedBytesRead;
if (bytesToRead > DFILE_DECOMPRESSION_BUFFER_SIZE) {
bytesToRead = DFILE_DECOMPRESSION_BUFFER_SIZE;
}
if (fread(stream->decompressionBuffer, bytesToRead, 1, stream->stream) != 1) {
break;

View File

@@ -2,11 +2,10 @@
#include <string.h>
#include "core.h"
#include "memory_manager.h"
#include "mouse.h"
#include "movie.h"
#include "platform_compat.h"
#include "svga.h"
#include "text_font.h"
#include "window_manager.h"
@@ -28,10 +27,10 @@ int _topDialogLine = 0;
int _topDialogReply = 0;
// 0x5184E4
DialogFunc1* _replyWinDrawCallback = nullptr;
DialogFunc1* _replyWinDrawCallback = NULL;
// 0x5184E8
DialogFunc2* _optionsWinDrawCallback = nullptr;
DialogFunc2* _optionsWinDrawCallback = NULL;
// 0x5184EC
int gDialogBorderX = 7;
@@ -171,7 +170,7 @@ STRUCT_56DAE0_FIELD_4* _getReply()
STRUCT_56DAE0_FIELD_4_FIELD_C* v1;
v0 = &(_dialog[_tods].field_4[_dialog[_tods].field_C]);
if (v0->field_C == nullptr) {
if (v0->field_C == NULL) {
v0->field_14 = 1;
v1 = (STRUCT_56DAE0_FIELD_4_FIELD_C*)internal_malloc_safe(sizeof(STRUCT_56DAE0_FIELD_4_FIELD_C), __FILE__, __LINE__); // "..\\int\\DIALOG.C", 789
} else {
@@ -195,20 +194,20 @@ void _replyAddOption(const char* a1, const char* a2, int a3)
v17 = v18->field_14 - 1;
v18->field_C[v17].kind = 2;
if (a1 != nullptr) {
if (a1 != NULL) {
v14 = (char*)internal_malloc_safe(strlen(a1) + 1, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 805
strcpy(v14, a1);
v18->field_C[v17].field_0 = v14;
} else {
v18->field_C[v17].field_0 = nullptr;
v18->field_C[v17].field_0 = NULL;
}
if (a2 != nullptr) {
if (a2 != NULL) {
v15 = (char*)internal_malloc_safe(strlen(a2) + 1, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 810
strcpy(v15, a2);
v18->field_C[v17].string = v15;
} else {
v18->field_C[v17].string = nullptr;
v18->field_C[v17].string = NULL;
}
v18->field_C[v17].field_18 = windowGetFont();
@@ -228,12 +227,12 @@ void _replyAddOptionProc(const char* a1, int a2, int a3)
v5->field_C[v13].kind = 1;
if (a1 != nullptr) {
if (a1 != NULL) {
v11 = (char*)internal_malloc_safe(strlen(a1) + 1, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 830
strcpy(v11, a1);
v5->field_C[v13].field_0 = v11;
} else {
v5->field_C[v13].field_0 = nullptr;
v5->field_C[v13].field_0 = NULL;
}
v5->field_C[v13].proc = a2;
@@ -246,12 +245,12 @@ void _replyAddOptionProc(const char* a1, int a2, int a3)
// 0x42F714
void _optionFree(STRUCT_56DAE0_FIELD_4_FIELD_C* a1)
{
if (a1->field_0 != nullptr) {
if (a1->field_0 != NULL) {
internal_free_safe(a1->field_0, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 844
}
if (a1->kind == 2) {
if (a1->string != nullptr) {
if (a1->string != NULL) {
internal_free_safe(a1->string, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 846
}
}
@@ -269,7 +268,7 @@ void _replyFree()
for (i = 0; i < ptr->field_8; i++) {
v6 = &(_dialog[_tods].field_4[i]);
if (v6->field_C != nullptr) {
if (v6->field_C != NULL) {
for (j = 0; j < v6->field_14; j++) {
_optionFree(&(v6->field_C[j]));
}
@@ -277,20 +276,20 @@ void _replyFree()
internal_free_safe(v6->field_C, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 857
}
if (v6->field_8 != nullptr) {
if (v6->field_8 != NULL) {
internal_free_safe(v6->field_8, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 860
}
if (v6->field_4 != nullptr) {
if (v6->field_4 != NULL) {
internal_free_safe(v6->field_4, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 862
}
if (v6->field_0 != nullptr) {
if (v6->field_0 != NULL) {
internal_free_safe(v6->field_0, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 864
}
}
if (ptr->field_4 != nullptr) {
if (ptr->field_4 != NULL) {
internal_free_safe(ptr->field_4, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 867
}
}
@@ -305,9 +304,9 @@ int _endDialog()
_topDialogReply = _dialog[_tods].field_10;
_replyFree();
if (gDialogReplyTitle != nullptr) {
if (gDialogReplyTitle != NULL) {
internal_free_safe(gDialogReplyTitle, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 986
gDialogReplyTitle = nullptr;
gDialogReplyTitle = NULL;
}
--_tods;
@@ -414,7 +413,7 @@ int _dialogStart(Program* a1)
ptr = &(_dialog[_tods]);
ptr->field_0 = a1;
ptr->field_4 = nullptr;
ptr->field_4 = 0;
ptr->field_8 = 0;
ptr->field_C = -1;
ptr->field_10 = -1;
@@ -449,11 +448,11 @@ int _dialogGotoReply(const char* a1)
return 1;
}
if (a1 != nullptr) {
if (a1 != NULL) {
ptr = &(_dialog[_tods]);
for (i = 0; i < ptr->field_8; i++) {
v5 = &(ptr->field_4[i]);
if (v5->field_4 != nullptr && compat_stricmp(v5->field_4, a1) == 0) {
if (v5->field_4 != NULL && compat_stricmp(v5->field_4, a1) == 0) {
ptr->field_10 = i;
return 0;
}
@@ -470,15 +469,15 @@ int _dialogGotoReply(const char* a1)
// 0x430E84
int dialogSetReplyTitle(const char* a1)
{
if (gDialogReplyTitle != nullptr) {
if (gDialogReplyTitle != NULL) {
internal_free_safe(gDialogReplyTitle, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 2561
}
if (a1 != nullptr) {
if (a1 != NULL) {
gDialogReplyTitle = (char*)internal_malloc_safe(strlen(a1) + 1, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 2564
strcpy(gDialogReplyTitle, a1);
} else {
gDialogReplyTitle = nullptr;
gDialogReplyTitle = NULL;
}
return 0;
@@ -586,22 +585,22 @@ int _dialogSetScrollUp(int a1, int a2, char* a3, char* a4, char* a5, char* a6, i
_upButton = a1;
dword_56DBD8 = a2;
if (off_56DBE0 != nullptr) {
if (off_56DBE0 != NULL) {
internal_free_safe(off_56DBE0, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 2750
}
off_56DBE0 = a3;
if (off_56DBE4 != nullptr) {
if (off_56DBE4 != NULL) {
internal_free_safe(off_56DBE4, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 2752
}
off_56DBE4 = a4;
if (off_56DBE8 != nullptr) {
if (off_56DBE8 != NULL) {
internal_free_safe(off_56DBE8, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 2754
}
off_56DBE8 = a5;
if (off_56DBEC != nullptr) {
if (off_56DBEC != NULL) {
internal_free_safe(off_56DBEC, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 2756
}
off_56DBEC = a5;
@@ -617,22 +616,22 @@ int _dialogSetScrollDown(int a1, int a2, char* a3, char* a4, char* a5, char* a6,
_downButton = a1;
dword_56DBB8 = a2;
if (off_56DBC0 != nullptr) {
if (off_56DBC0 != NULL) {
internal_free_safe(off_56DBC0, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 2765
}
off_56DBC0 = a3;
if (off_56DBC4 != nullptr) {
if (off_56DBC4 != NULL) {
internal_free_safe(off_56DBC4, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 2767
}
off_56DBC4 = a4;
if (off_56DBC8 != nullptr) {
if (off_56DBC8 != NULL) {
internal_free_safe(off_56DBC8, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 2769
}
off_56DBC8 = a5;
if (off_56DBCC != nullptr) {
if (off_56DBCC != NULL) {
internal_free_safe(off_56DBCC, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 2771
}
off_56DBCC = a6;

View File

@@ -52,11 +52,11 @@ int dictionaryInit(Dictionary* dictionary, int initialCapacity, size_t valueSize
dictionary->valueSize = valueSize;
dictionary->entriesLength = 0;
if (io != nullptr) {
if (io != NULL) {
memcpy(&(dictionary->io), io, sizeof(*io));
} else {
dictionary->io.readProc = nullptr;
dictionary->io.writeProc = nullptr;
dictionary->io.readProc = NULL;
dictionary->io.writeProc = NULL;
dictionary->io.field_8 = 0;
dictionary->io.field_C = 0;
}
@@ -65,11 +65,11 @@ int dictionaryInit(Dictionary* dictionary, int initialCapacity, size_t valueSize
if (initialCapacity != 0) {
dictionary->entries = (DictionaryEntry*)gDictionaryMallocProc(sizeof(*dictionary->entries) * initialCapacity);
if (dictionary->entries == nullptr) {
if (dictionary->entries == NULL) {
rc = -1;
}
} else {
dictionary->entries = nullptr;
dictionary->entries = NULL;
}
if (rc != -1) {
@@ -91,7 +91,7 @@ int dictionarySetCapacity(Dictionary* dictionary, int newCapacity)
}
DictionaryEntry* entries = (DictionaryEntry*)gDictionaryReallocProc(dictionary->entries, sizeof(*dictionary->entries) * newCapacity);
if (entries == nullptr) {
if (entries == NULL) {
return -1;
}
@@ -110,16 +110,16 @@ int dictionaryFree(Dictionary* dictionary)
for (int index = 0; index < dictionary->entriesLength; index++) {
DictionaryEntry* entry = &(dictionary->entries[index]);
if (entry->key != nullptr) {
if (entry->key != NULL) {
gDictionaryFreeProc(entry->key);
}
if (entry->value != nullptr) {
if (entry->value != NULL) {
gDictionaryFreeProc(entry->value);
}
}
if (dictionary->entries != nullptr) {
if (dictionary->entries != NULL) {
gDictionaryFreeProc(dictionary->entries);
}
@@ -224,23 +224,23 @@ int dictionaryAddValue(Dictionary* dictionary, const char* key, const void* valu
// Make a copy of the key.
char* keyCopy = (char*)gDictionaryMallocProc(strlen(key) + 1);
if (keyCopy == nullptr) {
if (keyCopy == NULL) {
return -1;
}
strcpy(keyCopy, key);
// Make a copy of the value.
void* valueCopy = nullptr;
if (value != nullptr && dictionary->valueSize != 0) {
void* valueCopy = NULL;
if (value != NULL && dictionary->valueSize != 0) {
valueCopy = gDictionaryMallocProc(dictionary->valueSize);
if (valueCopy == nullptr) {
if (valueCopy == NULL) {
gDictionaryFreeProc(keyCopy);
return -1;
}
}
if (valueCopy != nullptr && dictionary->valueSize != 0) {
if (valueCopy != NULL && dictionary->valueSize != 0) {
memcpy(valueCopy, value, dictionary->valueSize);
}
@@ -282,7 +282,7 @@ int dictionaryRemoveValue(Dictionary* dictionary, const char* key)
// Free key and value (which are copies).
gDictionaryFreeProc(entry->key);
if (entry->value != nullptr) {
if (entry->value != NULL) {
gDictionaryFreeProc(entry->value);
}
@@ -397,16 +397,16 @@ int dictionaryLoad(FILE* stream, Dictionary* dictionary, int a3)
for (int index = 0; index < dictionary->entriesLength; index++) {
DictionaryEntry* entry = &(dictionary->entries[index]);
if (entry->key != nullptr) {
if (entry->key != NULL) {
gDictionaryFreeProc(entry->key);
}
if (entry->value != nullptr) {
if (entry->value != NULL) {
gDictionaryFreeProc(entry->value);
}
}
if (dictionary->entries != nullptr) {
if (dictionary->entries != NULL) {
gDictionaryFreeProc(dictionary->entries);
}
@@ -414,21 +414,21 @@ int dictionaryLoad(FILE* stream, Dictionary* dictionary, int a3)
return -1;
}
dictionary->entries = nullptr;
dictionary->entries = NULL;
if (dictionary->entriesCapacity <= 0) {
return 0;
}
dictionary->entries = (DictionaryEntry*)gDictionaryMallocProc(sizeof(*dictionary->entries) * dictionary->entriesCapacity);
if (dictionary->entries == nullptr) {
if (dictionary->entries == NULL) {
return -1;
}
for (int index = 0; index < dictionary->entriesLength; index++) {
DictionaryEntry* entry = &(dictionary->entries[index]);
entry->key = nullptr;
entry->value = nullptr;
entry->key = NULL;
entry->value = NULL;
}
if (dictionary->entriesLength <= 0) {
@@ -443,21 +443,21 @@ int dictionaryLoad(FILE* stream, Dictionary* dictionary, int a3)
}
entry->key = (char*)gDictionaryMallocProc(keyLength + 1);
if (entry->key == nullptr) {
if (entry->key == NULL) {
return -1;
}
if (compat_fgets(entry->key, keyLength + 1, stream) == nullptr) {
if (fgets(entry->key, keyLength, stream) == NULL) {
return -1;
}
if (dictionary->valueSize != 0) {
entry->value = gDictionaryMallocProc(dictionary->valueSize);
if (entry->value == nullptr) {
if (entry->value == NULL) {
return -1;
}
if (dictionary->io.readProc != nullptr) {
if (dictionary->io.readProc != NULL) {
if (dictionary->io.readProc(stream, entry->value, dictionary->valueSize, a3) != 0) {
return -1;
}
@@ -523,7 +523,7 @@ int dictionaryWrite(FILE* stream, Dictionary* dictionary, int a3)
return -1;
}
if (dictionary->io.writeProc != nullptr) {
if (dictionary->io.writeProc != NULL) {
if (dictionary->valueSize != 0) {
if (dictionary->io.writeProc(stream, entry->value, dictionary->valueSize, a3) != 0) {
return -1;
@@ -544,7 +544,7 @@ int dictionaryWrite(FILE* stream, Dictionary* dictionary, int a3)
// 0x4DA498
void dictionarySetMemoryProcs(MallocProc* mallocProc, ReallocProc* reallocProc, FreeProc* freeProc)
{
if (mallocProc != nullptr && reallocProc != nullptr && freeProc != nullptr) {
if (mallocProc != NULL && reallocProc != NULL && freeProc != NULL) {
gDictionaryMallocProc = mallocProc;
gDictionaryReallocProc = reallocProc;
gDictionaryFreeProc = freeProc;

View File

@@ -2,9 +2,30 @@
namespace fallout {
enum InputType {
INPUT_TYPE_MOUSE,
INPUT_TYPE_TOUCH,
} InputType;
static int gLastInputType = INPUT_TYPE_MOUSE;
static int gTouchMouseLastX = 0;
static int gTouchMouseLastY = 0;
static int gTouchMouseDeltaX = 0;
static int gTouchMouseDeltaY = 0;
static int gTouchFingers = 0;
static unsigned int gTouchGestureLastTouchDownTimestamp = 0;
static unsigned int gTouchGestureLastTouchUpTimestamp = 0;
static int gTouchGestureTaps = 0;
static bool gTouchGestureHandled = false;
static int gMouseWheelDeltaX = 0;
static int gMouseWheelDeltaY = 0;
extern int screenGetWidth();
extern int screenGetHeight();
// 0x4E0400
bool directInputInit()
{
@@ -50,22 +71,49 @@ bool mouseDeviceUnacquire()
// 0x4E053C
bool mouseDeviceGetData(MouseData* mouseState)
{
// CE: This function is sometimes called outside loops calling `get_input`
// and subsequently `GNW95_process_message`, so mouse events might not be
// handled by SDL yet.
//
// TODO: Move mouse events processing into `GNW95_process_message` and
// update mouse position manually.
SDL_PumpEvents();
if (gLastInputType == INPUT_TYPE_TOUCH) {
mouseState->x = gTouchMouseDeltaX;
mouseState->y = gTouchMouseDeltaY;
mouseState->buttons[0] = 0;
mouseState->buttons[1] = 0;
mouseState->wheelX = 0;
mouseState->wheelY = 0;
gTouchMouseDeltaX = 0;
gTouchMouseDeltaY = 0;
Uint32 buttons = SDL_GetRelativeMouseState(&(mouseState->x), &(mouseState->y));
mouseState->buttons[0] = (buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0;
mouseState->buttons[1] = (buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
mouseState->wheelX = gMouseWheelDeltaX;
mouseState->wheelY = gMouseWheelDeltaY;
if (gTouchFingers == 0) {
if (SDL_GetTicks() - gTouchGestureLastTouchUpTimestamp > 150) {
if (!gTouchGestureHandled) {
if (gTouchGestureTaps == 2) {
mouseState->buttons[0] = 1;
gTouchGestureHandled = true;
} else if (gTouchGestureTaps == 3) {
mouseState->buttons[1] = 1;
gTouchGestureHandled = true;
}
}
}
} else if (gTouchFingers == 1) {
if (SDL_GetTicks() - gTouchGestureLastTouchDownTimestamp > 150) {
if (gTouchGestureTaps == 1) {
mouseState->buttons[0] = 1;
gTouchGestureHandled = true;
} else if (gTouchGestureTaps == 2) {
mouseState->buttons[1] = 1;
gTouchGestureHandled = true;
}
}
}
} else {
Uint32 buttons = SDL_GetRelativeMouseState(&(mouseState->x), &(mouseState->y));
mouseState->buttons[0] = (buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0;
mouseState->buttons[1] = (buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
mouseState->wheelX = gMouseWheelDeltaX;
mouseState->wheelY = gMouseWheelDeltaY;
gMouseWheelDeltaX = 0;
gMouseWheelDeltaY = 0;
gMouseWheelDeltaX = 0;
gMouseWheelDeltaY = 0;
}
return true;
}
@@ -126,6 +174,70 @@ void handleMouseEvent(SDL_Event* event)
gMouseWheelDeltaX += event->wheel.x;
gMouseWheelDeltaY += event->wheel.y;
}
if (gLastInputType != INPUT_TYPE_MOUSE) {
// Reset touch data.
gTouchMouseLastX = 0;
gTouchMouseLastY = 0;
gTouchMouseDeltaX = 0;
gTouchMouseDeltaY = 0;
gTouchFingers = 0;
gTouchGestureLastTouchDownTimestamp = 0;
gTouchGestureLastTouchUpTimestamp = 0;
gTouchGestureTaps = 0;
gTouchGestureHandled = false;
gLastInputType = INPUT_TYPE_MOUSE;
}
}
void handleTouchEvent(SDL_Event* event)
{
int windowWidth = screenGetWidth();
int windowHeight = screenGetHeight();
if (event->tfinger.type == SDL_FINGERDOWN) {
gTouchFingers++;
gTouchMouseLastX = (int)(event->tfinger.x * windowWidth);
gTouchMouseLastY = (int)(event->tfinger.y * windowHeight);
gTouchMouseDeltaX = 0;
gTouchMouseDeltaY = 0;
if (event->tfinger.timestamp - gTouchGestureLastTouchDownTimestamp > 250) {
gTouchGestureTaps = 0;
gTouchGestureHandled = false;
}
gTouchGestureLastTouchDownTimestamp = event->tfinger.timestamp;
} else if (event->tfinger.type == SDL_FINGERMOTION) {
int prevX = gTouchMouseLastX;
int prevY = gTouchMouseLastY;
gTouchMouseLastX = (int)(event->tfinger.x * windowWidth);
gTouchMouseLastY = (int)(event->tfinger.y * windowHeight);
gTouchMouseDeltaX += gTouchMouseLastX - prevX;
gTouchMouseDeltaY += gTouchMouseLastY - prevY;
} else if (event->tfinger.type == SDL_FINGERUP) {
gTouchFingers--;
int prevX = gTouchMouseLastX;
int prevY = gTouchMouseLastY;
gTouchMouseLastX = (int)(event->tfinger.x * windowWidth);
gTouchMouseLastY = (int)(event->tfinger.y * windowHeight);
gTouchMouseDeltaX += gTouchMouseLastX - prevX;
gTouchMouseDeltaY += gTouchMouseLastY - prevY;
gTouchGestureTaps++;
gTouchGestureLastTouchUpTimestamp = event->tfinger.timestamp;
}
if (gLastInputType != INPUT_TYPE_TOUCH) {
// Reset mouse data.
SDL_GetRelativeMouseState(NULL, NULL);
gLastInputType = INPUT_TYPE_TOUCH;
}
}
} // namespace fallout

View File

@@ -7,15 +7,14 @@
#include "art.h"
#include "color.h"
#include "combat.h"
#include "core.h"
#include "draw.h"
#include "game_mouse.h"
#include "game_sound.h"
#include "geometry.h"
#include "input.h"
#include "interface.h"
#include "memory.h"
#include "sfall_config.h"
#include "svga.h"
#include "text_font.h"
#include "window_manager.h"
@@ -30,7 +29,7 @@ namespace fallout {
#define DISPLAY_MONITOR_X (23)
#define DISPLAY_MONITOR_Y (24)
#define DISPLAY_MONITOR_WIDTH (167 + gInterfaceBarContentOffset)
#define DISPLAY_MONITOR_WIDTH (167)
#define DISPLAY_MONITOR_HEIGHT (60)
#define DISPLAY_MONITOR_HALF_HEIGHT (DISPLAY_MONITOR_HEIGHT / 2)
@@ -59,7 +58,12 @@ static bool gDisplayMonitorInitialized = false;
// The rectangle that display monitor occupies in the main interface window.
//
// 0x518510
static Rect gDisplayMonitorRect;
static const Rect gDisplayMonitorRect = {
DISPLAY_MONITOR_X,
DISPLAY_MONITOR_Y,
DISPLAY_MONITOR_X + DISPLAY_MONITOR_WIDTH - 1,
DISPLAY_MONITOR_Y + DISPLAY_MONITOR_HEIGHT - 1,
};
// 0x518520
static int gDisplayMonitorScrollDownButton = -1;
@@ -101,13 +105,6 @@ static int gConsoleFilePrintCount = 0;
int displayMonitorInit()
{
if (!gDisplayMonitorInitialized) {
gDisplayMonitorRect = {
DISPLAY_MONITOR_X,
DISPLAY_MONITOR_Y,
DISPLAY_MONITOR_X + DISPLAY_MONITOR_WIDTH - 1,
DISPLAY_MONITOR_Y + DISPLAY_MONITOR_HEIGHT - 1,
};
int oldFont = fontGetCurrent();
fontSetCurrent(DISPLAY_MONITOR_FONT);
@@ -118,37 +115,29 @@ int displayMonitorInit()
fontSetCurrent(oldFont);
gDisplayMonitorBackgroundFrmData = (unsigned char*)internal_malloc(DISPLAY_MONITOR_WIDTH * DISPLAY_MONITOR_HEIGHT);
if (gDisplayMonitorBackgroundFrmData == nullptr) {
if (gDisplayMonitorBackgroundFrmData == NULL) {
return -1;
}
if (gInterfaceBarIsCustom) {
_intface_full_width = gInterfaceBarWidth;
blitBufferToBuffer(customInterfaceBarGetBackgroundImageData() + gInterfaceBarWidth * DISPLAY_MONITOR_Y + DISPLAY_MONITOR_X,
DISPLAY_MONITOR_WIDTH,
DISPLAY_MONITOR_HEIGHT,
gInterfaceBarWidth,
gDisplayMonitorBackgroundFrmData,
DISPLAY_MONITOR_WIDTH);
} else {
FrmImage backgroundFrmImage;
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 16, 0, 0, 0);
if (!backgroundFrmImage.lock(backgroundFid)) {
internal_free(gDisplayMonitorBackgroundFrmData);
return -1;
}
unsigned char* backgroundFrmData = backgroundFrmImage.getData();
_intface_full_width = backgroundFrmImage.getWidth();
blitBufferToBuffer(backgroundFrmData + _intface_full_width * DISPLAY_MONITOR_Y + DISPLAY_MONITOR_X,
DISPLAY_MONITOR_WIDTH,
DISPLAY_MONITOR_HEIGHT,
_intface_full_width,
gDisplayMonitorBackgroundFrmData,
DISPLAY_MONITOR_WIDTH);
CacheEntry* backgroundFrmHandle;
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 16, 0, 0, 0);
Art* backgroundFrm = artLock(backgroundFid, &backgroundFrmHandle);
if (backgroundFrm == NULL) {
internal_free(gDisplayMonitorBackgroundFrmData);
return -1;
}
unsigned char* backgroundFrmData = artGetFrameData(backgroundFrm, 0, 0);
_intface_full_width = artGetWidth(backgroundFrm, 0, 0);
blitBufferToBuffer(backgroundFrmData + _intface_full_width * DISPLAY_MONITOR_Y + DISPLAY_MONITOR_X,
DISPLAY_MONITOR_WIDTH,
DISPLAY_MONITOR_HEIGHT,
_intface_full_width,
gDisplayMonitorBackgroundFrmData,
DISPLAY_MONITOR_WIDTH);
artUnlock(backgroundFrmHandle);
gDisplayMonitorScrollUpButton = buttonCreate(gInterfaceBarWindow,
DISPLAY_MONITOR_X,
DISPLAY_MONITOR_Y,
@@ -158,16 +147,16 @@ int displayMonitorInit()
-1,
-1,
-1,
nullptr,
nullptr,
nullptr,
NULL,
NULL,
NULL,
0);
if (gDisplayMonitorScrollUpButton != -1) {
buttonSetMouseCallbacks(gDisplayMonitorScrollUpButton,
displayMonitorScrollUpOnMouseEnter,
displayMonitorOnMouseExit,
displayMonitorScrollUpOnMouseDown,
nullptr);
NULL);
}
gDisplayMonitorScrollDownButton = buttonCreate(gInterfaceBarWindow,
@@ -179,16 +168,16 @@ int displayMonitorInit()
-1,
-1,
-1,
nullptr,
nullptr,
nullptr,
NULL,
NULL,
NULL,
0);
if (gDisplayMonitorScrollDownButton != -1) {
buttonSetMouseCallbacks(gDisplayMonitorScrollDownButton,
displayMonitorScrollDownOnMouseEnter,
displayMonitorOnMouseExit,
displayMonitorScrollDownOnMouseDown,
nullptr);
NULL);
}
gDisplayMonitorEnabled = true;
@@ -257,7 +246,7 @@ void displayMonitorAddMessage(char* str)
}
// TODO: Refactor these two loops.
char* v1 = nullptr;
char* v1 = NULL;
while (true) {
while (fontGetStringWidth(str) < DISPLAY_MONITOR_WIDTH - _max_disp - knobWidth) {
char* temp = gDisplayMonitorLines[_disp_start];
@@ -274,7 +263,7 @@ void displayMonitorAddMessage(char* str)
gDisplayMonitorLines[_disp_start][DISPLAY_MONITOR_LINE_LENGTH - 1] = '\0';
_disp_start = (_disp_start + 1) % gDisplayMonitorLinesCapacity;
if (v1 == nullptr) {
if (v1 == NULL) {
fontSetCurrent(oldFont);
_disp_curr = _disp_start;
displayMonitorRefresh();
@@ -283,20 +272,20 @@ void displayMonitorAddMessage(char* str)
str = v1 + 1;
*v1 = ' ';
v1 = nullptr;
v1 = NULL;
}
char* space = strrchr(str, ' ');
if (space == nullptr) {
if (space == NULL) {
break;
}
if (v1 != nullptr) {
if (v1 != NULL) {
*v1 = ' ';
}
v1 = space;
if (space != nullptr) {
if (space != NULL) {
*space = '\0';
}
}
@@ -347,7 +336,7 @@ static void displayMonitorRefresh()
}
unsigned char* buf = windowGetBuffer(gInterfaceBarWindow);
if (buf == nullptr) {
if (buf == NULL) {
return;
}
@@ -438,11 +427,11 @@ static void consoleFileInit()
{
char* consoleFilePath;
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_CONSOLE_OUTPUT_FILE_KEY, &consoleFilePath);
if (consoleFilePath != nullptr && *consoleFilePath == '\0') {
consoleFilePath = nullptr;
if (consoleFilePath != NULL && *consoleFilePath == '\0') {
consoleFilePath = NULL;
}
if (consoleFilePath != nullptr) {
if (consoleFilePath != NULL) {
gConsoleFileStream.open(consoleFilePath);
}
}

View File

@@ -3,7 +3,8 @@
#include <string.h>
#include "color.h"
#include "svga.h"
#include "core.h"
#include "mmx.h"
namespace fallout {
@@ -27,7 +28,7 @@ void bufferDrawLine(unsigned char* buf, int pitch, int x1, int y1, int x2, int y
p1 = buf + pitch * y1 + x1;
p2 = buf + pitch * y2 + x2;
while (p1 <= p2) {
while (p1 < p2) {
*p1 = color;
*p2 = color;
p1 += pitch;
@@ -151,69 +152,87 @@ void bufferDrawRectShadowed(unsigned char* buf, int pitch, int left, int top, in
// 0x4D33F0
void blitBufferToBufferStretch(unsigned char* src, int srcWidth, int srcHeight, int srcPitch, unsigned char* dest, int destWidth, int destHeight, int destPitch)
{
int stepX = (destWidth << 16) / srcWidth;
int stepY = (destHeight << 16) / srcHeight;
int heightRatio = (destHeight << 16) / srcHeight;
int widthRatio = (destWidth << 16) / srcWidth;
int v1 = 0;
int v2 = heightRatio;
for (int srcY = 0; srcY < srcHeight; srcY += 1) {
int startDestY = (srcY * stepY) >> 16;
int endDestY = ((srcY + 1) * stepY) >> 16;
int v3 = widthRatio;
int v4 = (heightRatio * srcY) >> 16;
int v5 = v2 >> 16;
int v6 = 0;
unsigned char* currSrc = src + srcPitch * srcY;
unsigned char* c = src + v1;
for (int srcX = 0; srcX < srcWidth; srcX += 1) {
int startDestX = (srcX * stepX) >> 16;
int endDestX = ((srcX + 1) * stepX) >> 16;
int v7 = v3 >> 16;
int v8 = v6 >> 16;
for (int destY = startDestY; destY < endDestY; destY += 1) {
unsigned char* currDest = dest + destPitch * destY + startDestX;
for (int destX = startDestX; destX < endDestX; destX += 1) {
*currDest++ = *currSrc;
unsigned char* v9 = dest + destPitch * v4 + v8;
for (int destY = v4; destY < v5; destY += 1) {
for (int destX = v8; destX < v7; destX += 1) {
*v9++ = *c;
}
v9 += destPitch;
}
currSrc++;
v3 += widthRatio;
c++;
v6 += widthRatio;
}
v1 += srcPitch;
v2 += heightRatio;
}
}
// 0x4D3560
void blitBufferToBufferStretchTrans(unsigned char* src, int srcWidth, int srcHeight, int srcPitch, unsigned char* dest, int destWidth, int destHeight, int destPitch)
{
int stepX = (destWidth << 16) / srcWidth;
int stepY = (destHeight << 16) / srcHeight;
int heightRatio = (destHeight << 16) / srcHeight;
int widthRatio = (destWidth << 16) / srcWidth;
int v1 = 0;
int v2 = heightRatio;
for (int srcY = 0; srcY < srcHeight; srcY += 1) {
int startDestY = (srcY * stepY) >> 16;
int endDestY = ((srcY + 1) * stepY) >> 16;
int v3 = widthRatio;
int v4 = (heightRatio * srcY) >> 16;
int v5 = v2 >> 16;
int v6 = 0;
unsigned char* currSrc = src + srcPitch * srcY;
unsigned char* c = src + v1;
for (int srcX = 0; srcX < srcWidth; srcX += 1) {
int startDestX = (srcX * stepX) >> 16;
int endDestX = ((srcX + 1) * stepX) >> 16;
int v7 = v3 >> 16;
int v8 = v6 >> 16;
if (*currSrc != 0) {
for (int destY = startDestY; destY < endDestY; destY += 1) {
unsigned char* currDest = dest + destPitch * destY + startDestX;
for (int destX = startDestX; destX < endDestX; destX += 1) {
*currDest++ = *currSrc;
if (*c != 0) {
unsigned char* v9 = dest + destPitch * v4 + v8;
for (int destY = v4; destY < v5; destY += 1) {
for (int destX = v8; destX < v7; destX += 1) {
*v9++ = *c;
}
v9 += destPitch;
}
}
currSrc++;
v3 += widthRatio;
c++;
v6 += widthRatio;
}
v1 += srcPitch;
v2 += heightRatio;
}
}
// 0x4D36D4
void blitBufferToBuffer(unsigned char* src, int width, int height, int srcPitch, unsigned char* dest, int destPitch)
{
srcCopy(dest, destPitch, src, srcPitch, width, height);
mmxBlit(dest, destPitch, src, srcPitch, width, height);
}
// 0x4D3704
void blitBufferToBufferTrans(unsigned char* src, int width, int height, int srcPitch, unsigned char* dest, int destPitch)
{
transSrcCopy(dest, destPitch, src, srcPitch, width, height);
mmxBlitTrans(dest, destPitch, src, srcPitch, width, height);
}
// 0x4D387C
@@ -240,8 +259,8 @@ void _lighten_buf(unsigned char* buf, int width, int height, int pitch)
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
unsigned char color = *buf;
*buf++ = intensityColorTable[color][147];
unsigned char p = *buf;
*buf++ = _intensityColorTable[(p << 8) + 147];
}
buf += skip;
}
@@ -310,33 +329,4 @@ void bufferOutline(unsigned char* buf, int width, int height, int pitch, int col
}
}
// 0x4E0DB0
void srcCopy(unsigned char* dest, int destPitch, unsigned char* src, int srcPitch, int width, int height)
{
for (int y = 0; y < height; y++) {
memcpy(dest, src, width);
dest += destPitch;
src += srcPitch;
}
}
// 0x4E0ED5
void transSrcCopy(unsigned char* dest, int destPitch, unsigned char* src, int srcPitch, int width, int height)
{
int destSkip = destPitch - width;
int srcSkip = srcPitch - width;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
unsigned char c = *src++;
if (c != 0) {
*dest = c;
}
dest++;
}
src += srcSkip;
dest += destSkip;
}
}
} // namespace fallout

View File

@@ -15,8 +15,6 @@ void _buf_texture(unsigned char* buf, int width, int height, int pitch, void* a5
void _lighten_buf(unsigned char* buf, int width, int height, int pitch);
void _swap_color_buf(unsigned char* buf, int width, int height, int pitch, int color1, int color2);
void bufferOutline(unsigned char* buf, int width, int height, int pitch, int a5);
void srcCopy(unsigned char* dest, int destPitch, unsigned char* src, int srcPitch, int width, int height);
void transSrcCopy(unsigned char* dest, int destPitch, unsigned char* src, int srcPitch, int width, int height);
} // namespace fallout

View File

@@ -0,0 +1,51 @@
#include "electronic_registration.h"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include "game_config.h"
#include "platform_compat.h"
namespace fallout {
// 0x440DD0
void runElectronicRegistration()
{
int timesRun = 0;
configGetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_TIMES_RUN_KEY, &timesRun);
if (timesRun > 0 && timesRun < 5) {
#ifdef _WIN32
char path[COMPAT_MAX_PATH];
if (GetModuleFileNameA(NULL, path, sizeof(path)) != 0) {
char* pch = strrchr(path, '\\');
if (pch == NULL) {
pch = path;
}
strcpy(pch, "\\ereg");
STARTUPINFOA startupInfo;
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
PROCESS_INFORMATION processInfo;
// FIXME: Leaking processInfo.hProcess and processInfo.hThread:
// https://docs.microsoft.com/en-us/cpp/code-quality/c6335.
if (CreateProcessA("ereg\\reg32a.exe", NULL, NULL, NULL, FALSE, 0, NULL, path, &startupInfo, &processInfo)) {
WaitForSingleObject(processInfo.hProcess, INFINITE);
}
}
#endif
configSetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_TIMES_RUN_KEY, timesRun + 1);
} else {
if (timesRun == 0) {
configSetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_TIMES_RUN_KEY, 1);
}
}
}
} // namespace fallout

View File

@@ -0,0 +1,10 @@
#ifndef ELECTRONIC_REGISTRATION_H
#define ELECTRONIC_REGISTRATION_H
namespace fallout {
void runElectronicRegistration();
} // namespace fallout
#endif /* ELECTRONIC_REGISTRATION_H */

View File

@@ -6,21 +6,18 @@
#include <algorithm>
#include "art.h"
#include "core.h"
#include "cycle.h"
#include "debug.h"
#include "delay.h"
#include "draw.h"
#include "game_mouse.h"
#include "game_sound.h"
#include "geometry.h"
#include "input.h"
#include "interface.h"
#include "kb.h"
#include "map.h"
#include "pipboy.h"
#include "scripts.h"
#include "sfall_config.h"
#include "svga.h"
#include "window_manager.h"
namespace fallout {
@@ -395,9 +392,7 @@ int elevatorSelectLevel(int elevator, int* mapPtr, int* elevationPtr, int* tileP
bool done = false;
int keyCode;
while (!done) {
sharedFpsLimiter.mark();
keyCode = inputGetInput();
keyCode = _get_input();
if (keyCode == KEY_ESCAPE) {
done = true;
}
@@ -413,9 +408,6 @@ int elevatorSelectLevel(int elevator, int* mapPtr, int* elevationPtr, int* tileP
done = true;
}
}
renderPresent();
sharedFpsLimiter.throttle();
}
if (keyCode != KEY_ESCAPE) {
@@ -440,9 +432,7 @@ int elevatorSelectLevel(int elevator, int* mapPtr, int* elevationPtr, int* tileP
float v41 = (float)keyCode * v42;
float v44 = (float)(*elevationPtr) * v42;
do {
sharedFpsLimiter.mark();
unsigned int tick = getTicks();
unsigned int tick = _get_time();
v44 += v43;
blitBufferToBuffer(
_elevatorFrmImages[ELEVATOR_FRM_GAUGE].getData() + v18 * (int)v44,
@@ -454,13 +444,11 @@ int elevatorSelectLevel(int elevator, int* mapPtr, int* elevationPtr, int* tileP
windowRefresh(gElevatorWindow);
delay_ms(delay - (getTicks() - tick));
renderPresent();
sharedFpsLimiter.throttle();
while (getTicksSince(tick) < delay) {
}
} while ((v43 <= 0.0 || v44 < v41) && (v43 > 0.0 || v44 > v41));
inputPauseForTocks(200);
coreDelayProcessingEvents(200);
}
}
@@ -550,7 +538,7 @@ static int elevatorWindowInit(int elevator)
_elevatorBackgroundFrmImage.getWidth(),
_elevatorBackgroundFrmImage.getHeight(),
256,
WINDOW_MODAL | WINDOW_DONT_MOVE_TOP);
WINDOW_FLAG_0x10 | WINDOW_FLAG_0x02);
if (gElevatorWindow == -1) {
_elevatorBackgroundFrmImage.unlock();
_elevatorPanelFrmImage.unlock();
@@ -593,10 +581,10 @@ static int elevatorWindowInit(int elevator)
500 + level,
_elevatorFrmImages[ELEVATOR_FRM_BUTTON_UP].getData(),
_elevatorFrmImages[ELEVATOR_FRM_BUTTON_DOWN].getData(),
nullptr,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (btn != -1) {
buttonSetCallbacks(btn, _gsound_red_butt_press, nullptr);
buttonSetCallbacks(btn, _gsound_red_butt_press, NULL);
}
y += 60;
}
@@ -650,18 +638,18 @@ void elevatorsInit()
{
char* elevatorsFileName;
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_ELEVATORS_FILE_KEY, &elevatorsFileName);
if (elevatorsFileName != nullptr && *elevatorsFileName == '\0') {
elevatorsFileName = nullptr;
if (elevatorsFileName != NULL && *elevatorsFileName == '\0') {
elevatorsFileName = NULL;
}
if (elevatorsFileName != nullptr) {
if (elevatorsFileName != NULL) {
Config elevatorsConfig;
if (configInit(&elevatorsConfig)) {
if (configRead(&elevatorsConfig, elevatorsFileName, false)) {
char sectionKey[4];
char key[32];
for (int index = 0; index < ELEVATORS_MAX; index++) {
snprintf(sectionKey, sizeof(sectionKey), "%d", index);
sprintf(sectionKey, "%d", index);
if (index >= ELEVATOR_COUNT) {
int levels = 0;
@@ -673,13 +661,13 @@ void elevatorsInit()
configGetInt(&elevatorsConfig, sectionKey, "ButtonsFrm", &(gElevatorBackgrounds[index].panelFrmId));
for (int level = 0; level < ELEVATOR_LEVEL_MAX; level++) {
snprintf(key, sizeof(key), "ID%d", level + 1);
sprintf(key, "ID%d", level + 1);
configGetInt(&elevatorsConfig, sectionKey, key, &(gElevatorDescriptions[index][level].map));
snprintf(key, sizeof(key), "Elevation%d", level + 1);
sprintf(key, "Elevation%d", level + 1);
configGetInt(&elevatorsConfig, sectionKey, key, &(gElevatorDescriptions[index][level].elevation));
snprintf(key, sizeof(key), "Tile%d", level + 1);
sprintf(key, "Tile%d", level + 1);
configGetInt(&elevatorsConfig, sectionKey, key, &(gElevatorDescriptions[index][level].tile));
}
}
@@ -689,7 +677,7 @@ void elevatorsInit()
// value is then used in the certain places to remap from
// requested elevator to the new one.
for (int index = 0; index < ELEVATORS_MAX; index++) {
snprintf(sectionKey, sizeof(sectionKey), "%d", index);
sprintf(sectionKey, "%d", index);
int type;
if (configGetInt(&elevatorsConfig, sectionKey, "Image", &type)) {

View File

@@ -17,18 +17,7 @@ typedef enum Elevator {
ELEVATOR_SIERRA_1,
ELEVATOR_SIERRA_2,
ELEVATOR_SIERRA_SERVICE,
ELEVATOR_KLAMATH_TOXIC_CAVES,
ELEVATOR_14,
ELEVATOR_VAULT_CITY,
ELEVATOR_VAULT_15_MAIN,
ELEVATOR_VAULT_15_SURFACE,
ELEVATOR_NAVARRO_NORTHERN,
ELEVATOR_NAVARRO_CENTER,
ELEVATOR_NAVARRO_LAB,
ELEVATOR_NAVARRO_CANTEEN,
ELEVATOR_SAN_FRANCISCO_SHI_TEMPLE,
ELEVATOR_REDDING_WANAMINGO_MINE,
ELEVATOR_COUNT,
ELEVATOR_COUNT = 24,
} Elevator;
int elevatorSelectLevel(int elevator, int* mapPtr, int* elevationPtr, int* tilePtr);

View File

@@ -8,6 +8,7 @@
#include "art.h"
#include "color.h"
#include "core.h"
#include "credits.h"
#include "cycle.h"
#include "db.h"
@@ -15,21 +16,18 @@
#include "debug.h"
#include "draw.h"
#include "game.h"
#include "game_config.h"
#include "game_mouse.h"
#include "game_movie.h"
#include "game_sound.h"
#include "input.h"
#include "map.h"
#include "memory.h"
#include "mouse.h"
#include "object.h"
#include "palette.h"
#include "pipboy.h"
#include "platform_compat.h"
#include "random.h"
#include "settings.h"
#include "stat.h"
#include "svga.h"
#include "text_font.h"
#include "window_manager.h"
#include "word_wrap.h"
@@ -83,7 +81,9 @@ static void _endgame_movie_bk_process();
static int endgameEndingInit();
static void endgameEndingFree();
static int endgameDeathEndingValidate(int* percentage);
static void endgameEndingUpdateOverlay();
// 0x50B00C
char _aEnglish_2[] = ENGLISH;
// The number of lines in current subtitles file.
//
@@ -112,7 +112,7 @@ static int _endgame_maybe_done = 0;
// enddeath.txt
//
// 0x518678
static EndgameDeathEnding* gEndgameDeathEndings = nullptr;
static EndgameDeathEnding* gEndgameDeathEndings = NULL;
// The number of death endings in [gEndgameDeathEndings] array.
//
@@ -205,8 +205,6 @@ static unsigned char* gEndgameEndingSlideshowWindowBuffer;
// 0x570BF4
static int gEndgameEndingSlideshowWindow;
static int gEndgameEndingOverlay;
// 0x43F788
void endgamePlaySlideshow()
{
@@ -240,7 +238,7 @@ void endgamePlayMovie()
tickersAdd(_endgame_movie_bk_process);
backgroundSoundSetEndCallback(_endgame_movie_callback);
backgroundSoundLoad("akiss", 12, 14, 15);
inputPauseForTocks(3000);
coreDelayProcessingEvents(3000);
// NOTE: Result is ignored. I guess there was some kind of switch for male
// vs. female ending, but it was not implemented.
@@ -248,7 +246,7 @@ void endgamePlayMovie()
creditsOpen("credits.txt", -1, false);
backgroundSoundDelete();
backgroundSoundSetEndCallback(nullptr);
backgroundSoundSetEndCallback(NULL);
tickersRemove(_endgame_movie_bk_process);
backgroundSoundDelete();
colorPaletteLoad("color.pal");
@@ -286,7 +284,7 @@ static int endgameEndingHandleContinuePlaying()
MessageListItem messageListItem;
messageListItem.num = 30;
if (messageListGetItem(&gMiscMessageList, &messageListItem)) {
rc = showDialogBox(messageListItem.text, nullptr, 0, 169, 117, _colorTable[32328], nullptr, _colorTable[32328], DIALOG_BOX_YES_NO);
rc = showDialogBox(messageListItem.text, NULL, 0, 169, 117, _colorTable[32328], NULL, _colorTable[32328], DIALOG_BOX_YES_NO);
if (rc == 0) {
_game_user_wants_to_quit = 2;
}
@@ -317,16 +315,13 @@ static void endgameEndingRenderPanningScene(int direction, const char* narratorF
CacheEntry* backgroundHandle;
Art* background = artLock(fid, &backgroundHandle);
if (background != nullptr) {
if (background != NULL) {
int width = artGetWidth(background, 0, 0);
int height = artGetHeight(background, 0, 0);
unsigned char* backgroundData = artGetFrameData(background, 0, 0);
bufferFill(gEndgameEndingSlideshowWindowBuffer, ENDGAME_ENDING_WINDOW_WIDTH, ENDGAME_ENDING_WINDOW_HEIGHT, ENDGAME_ENDING_WINDOW_WIDTH, _colorTable[0]);
endgameEndingLoadPalette(6, 327);
// CE: Update overlay.
endgameEndingUpdateOverlay();
unsigned char palette[768];
memcpy(palette, _cmap, 768);
@@ -362,8 +357,6 @@ static void endgameEndingRenderPanningScene(int direction, const char* narratorF
unsigned int since = 0;
while (start != end) {
sharedFpsLimiter.mark();
int v12 = 640 - v32;
// TODO: Complex math, setup scene in debugger.
@@ -376,7 +369,7 @@ static void endgameEndingRenderPanningScene(int direction, const char* narratorF
windowRefresh(gEndgameEndingSlideshowWindow);
since = getTicks();
since = _get_time();
bool v14;
double v31;
@@ -416,14 +409,11 @@ static void endgameEndingRenderPanningScene(int direction, const char* narratorF
soundContinueAll();
if (inputGetInput() != -1) {
if (_get_input() != -1) {
// NOTE: Uninline.
endgameEndingVoiceOverFree();
break;
}
renderPresent();
sharedFpsLimiter.throttle();
}
tickersEnable();
@@ -435,12 +425,7 @@ static void endgameEndingRenderPanningScene(int direction, const char* narratorF
}
while (mouseGetEvent() != 0) {
sharedFpsLimiter.mark();
inputGetInput();
renderPresent();
sharedFpsLimiter.throttle();
_get_input();
}
}
@@ -449,20 +434,17 @@ static void endgameEndingRenderStaticScene(int fid, const char* narratorFileName
{
CacheEntry* backgroundHandle;
Art* background = artLock(fid, &backgroundHandle);
if (background == nullptr) {
if (background == NULL) {
return;
}
unsigned char* backgroundData = artGetFrameData(background, 0, 0);
if (backgroundData != nullptr) {
if (backgroundData != NULL) {
blitBufferToBuffer(backgroundData, ENDGAME_ENDING_WINDOW_WIDTH, ENDGAME_ENDING_WINDOW_HEIGHT, ENDGAME_ENDING_WINDOW_WIDTH, gEndgameEndingSlideshowWindowBuffer, ENDGAME_ENDING_WINDOW_WIDTH);
windowRefresh(gEndgameEndingSlideshowWindow);
endgameEndingLoadPalette(FID_TYPE(fid), fid & 0xFFF);
// CE: Update overlay.
endgameEndingUpdateOverlay();
endgameEndingVoiceOverInit(narratorFileName);
unsigned int delay;
@@ -474,19 +456,17 @@ static void endgameEndingRenderStaticScene(int fid, const char* narratorFileName
paletteFadeTo(_cmap);
inputPauseForTocks(500);
coreDelayProcessingEvents(500);
// NOTE: Uninline.
endgameEndingVoiceOverReset();
unsigned int referenceTime = getTicks();
unsigned int referenceTime = _get_time();
tickersDisable();
int keyCode;
while (true) {
sharedFpsLimiter.mark();
keyCode = inputGetInput();
keyCode = _get_input();
if (keyCode != -1) {
break;
}
@@ -507,9 +487,6 @@ static void endgameEndingRenderStaticScene(int fid, const char* narratorFileName
endgameEndingRefreshSubtitles();
windowRefresh(gEndgameEndingSlideshowWindow);
soundContinueAll();
renderPresent();
sharedFpsLimiter.throttle();
}
tickersEnable();
@@ -520,18 +497,13 @@ static void endgameEndingRenderStaticScene(int fid, const char* narratorFileName
gEndgameEndingVoiceOverSubtitlesLoaded = false;
if (keyCode == -1) {
inputPauseForTocks(500);
coreDelayProcessingEvents(500);
}
paletteFadeTo(gPaletteBlack);
while (mouseGetEvent() != 0) {
sharedFpsLimiter.mark();
inputGetInput();
renderPresent();
sharedFpsLimiter.throttle();
_get_input();
}
}
@@ -564,13 +536,6 @@ static int endgameEndingSlideshowWindowInit()
paletteFadeTo(gPaletteBlack);
// CE: Every slide has a separate color palette which is incompatible with
// main color palette. Setup overlay to hide everything.
gEndgameEndingOverlay = windowCreate(0, 0, screenGetWidth(), screenGetHeight(), _colorTable[0], WINDOW_MOVE_ON_TOP);
if (gEndgameEndingOverlay == -1) {
return -1;
}
int windowEndgameEndingX = (screenGetWidth() - ENDGAME_ENDING_WINDOW_WIDTH) / 2;
int windowEndgameEndingY = (screenGetHeight() - ENDGAME_ENDING_WINDOW_HEIGHT) / 2;
gEndgameEndingSlideshowWindow = windowCreate(windowEndgameEndingX,
@@ -578,13 +543,13 @@ static int endgameEndingSlideshowWindowInit()
ENDGAME_ENDING_WINDOW_WIDTH,
ENDGAME_ENDING_WINDOW_HEIGHT,
_colorTable[0],
WINDOW_MOVE_ON_TOP);
WINDOW_FLAG_0x04);
if (gEndgameEndingSlideshowWindow == -1) {
return -1;
}
gEndgameEndingSlideshowWindowBuffer = windowGetBuffer(gEndgameEndingSlideshowWindow);
if (gEndgameEndingSlideshowWindowBuffer == nullptr) {
if (gEndgameEndingSlideshowWindowBuffer == NULL) {
return -1;
}
@@ -592,25 +557,32 @@ static int endgameEndingSlideshowWindowInit()
speechSetEndCallback(_endgame_voiceover_callback);
gEndgameEndingSubtitlesEnabled = settings.preferences.subtitles;
gEndgameEndingSubtitlesEnabled = false;
configGetBool(&gGameConfig, GAME_CONFIG_PREFERENCES_KEY, GAME_CONFIG_SUBTITLES_KEY, &gEndgameEndingSubtitlesEnabled);
if (!gEndgameEndingSubtitlesEnabled) {
return 0;
}
snprintf(gEndgameEndingSubtitlesLocalizedPath, sizeof(gEndgameEndingSubtitlesLocalizedPath), "text\\%s\\cuts\\", settings.system.language.c_str());
char* language;
if (!configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_LANGUAGE_KEY, &language)) {
gEndgameEndingSubtitlesEnabled = false;
return 0;
}
sprintf(gEndgameEndingSubtitlesLocalizedPath, "text\\%s\\cuts\\", language);
gEndgameEndingSubtitles = (char**)internal_malloc(sizeof(*gEndgameEndingSubtitles) * ENDGAME_ENDING_MAX_SUBTITLES);
if (gEndgameEndingSubtitles == nullptr) {
if (gEndgameEndingSubtitles == NULL) {
gEndgameEndingSubtitlesEnabled = false;
return 0;
}
for (int index = 0; index < ENDGAME_ENDING_MAX_SUBTITLES; index++) {
gEndgameEndingSubtitles[index] = nullptr;
gEndgameEndingSubtitles[index] = NULL;
}
gEndgameEndingSubtitlesTimings = (unsigned int*)internal_malloc(sizeof(*gEndgameEndingSubtitlesTimings) * ENDGAME_ENDING_MAX_SUBTITLES);
if (gEndgameEndingSubtitlesTimings == nullptr) {
if (gEndgameEndingSubtitlesTimings == NULL) {
internal_free(gEndgameEndingSubtitles);
gEndgameEndingSubtitlesEnabled = false;
return 0;
@@ -628,7 +600,7 @@ static void endgameEndingSlideshowWindowFree()
internal_free(gEndgameEndingSubtitlesTimings);
internal_free(gEndgameEndingSubtitles);
gEndgameEndingSubtitles = nullptr;
gEndgameEndingSubtitles = NULL;
gEndgameEndingSubtitlesEnabled = false;
}
@@ -637,9 +609,8 @@ static void endgameEndingSlideshowWindowFree()
fontSetCurrent(gEndgameEndingSlideshowOldFont);
speechSetEndCallback(nullptr);
speechSetEndCallback(NULL);
windowDestroy(gEndgameEndingSlideshowWindow);
windowDestroy(gEndgameEndingOverlay);
if (!_endgame_mouse_state) {
mouseHideCursor();
@@ -669,7 +640,7 @@ static void endgameEndingVoiceOverInit(const char* fileBaseName)
gEndgameEndingVoiceOverSubtitlesLoaded = false;
// Build speech file path.
snprintf(path, sizeof(path), "%s%s", "narrator\\", fileBaseName);
sprintf(path, "%s%s", "narrator\\", fileBaseName);
if (speechLoad(path, 10, 14, 15) != -1) {
gEndgameEndingVoiceOverSpeechLoaded = true;
@@ -677,7 +648,7 @@ static void endgameEndingVoiceOverInit(const char* fileBaseName)
if (gEndgameEndingSubtitlesEnabled) {
// Build subtitles file path.
snprintf(path, sizeof(path), "%s%s.txt", gEndgameEndingSubtitlesLocalizedPath, fileBaseName);
sprintf(path, "%s%s.txt", gEndgameEndingSubtitlesLocalizedPath, fileBaseName);
if (endgameEndingSubtitlesLoad(path) != 0) {
return;
@@ -716,7 +687,7 @@ static void endgameEndingVoiceOverReset()
}
if (gEndgameEndingVoiceOverSubtitlesLoaded) {
gEndgameEndingSubtitlesReferenceTime = getTicks();
gEndgameEndingSubtitlesReferenceTime = _get_time();
}
}
@@ -741,13 +712,13 @@ static void endgameEndingLoadPalette(int type, int id)
// Remove extension from file name.
char* pch = strrchr(fileName, '.');
if (pch != nullptr) {
if (pch != NULL) {
*pch = '\0';
}
if (strlen(fileName) <= 8) {
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s\\%s.pal", "art\\intrface", fileName);
sprintf(path, "%s\\%s.pal", "art\\intrface", fileName);
colorPaletteLoad(path);
}
}
@@ -766,7 +737,7 @@ static int endgameEndingSubtitlesLoad(const char* filePath)
endgameEndingSubtitlesFree();
File* stream = fileOpen(filePath, "rt");
if (stream == nullptr) {
if (stream == NULL) {
return -1;
}
@@ -778,14 +749,14 @@ static int endgameEndingSubtitlesLoad(const char* filePath)
// Find and clamp string at EOL.
pch = strchr(string, '\n');
if (pch != nullptr) {
if (pch != NULL) {
*pch = '\0';
}
// Find separator. The value before separator is ignored (as opposed to
// movie subtitles, where the value before separator is a timing).
pch = strchr(string, ':');
if (pch != nullptr) {
if (pch != NULL) {
if (gEndgameEndingSubtitlesLength < ENDGAME_ENDING_MAX_SUBTITLES) {
gEndgameEndingSubtitles[gEndgameEndingSubtitlesLength] = internal_strdup(pch + 1);
gEndgameEndingSubtitlesLength++;
@@ -817,7 +788,7 @@ static void endgameEndingRefreshSubtitles()
}
char* text = gEndgameEndingSubtitles[gEndgameEndingSubtitlesCurrentLine];
if (text == nullptr) {
if (text == NULL) {
return;
}
@@ -856,9 +827,9 @@ static void endgameEndingRefreshSubtitles()
static void endgameEndingSubtitlesFree()
{
for (int index = 0; index < gEndgameEndingSubtitlesLength; index++) {
if (gEndgameEndingSubtitles[index] != nullptr) {
if (gEndgameEndingSubtitles[index] != NULL) {
internal_free(gEndgameEndingSubtitles[index]);
gEndgameEndingSubtitles[index] = nullptr;
gEndgameEndingSubtitles[index] = NULL;
}
}
@@ -878,7 +849,7 @@ static void _endgame_movie_bk_process()
{
if (_endgame_maybe_done) {
backgroundSoundLoad("10labone", 11, 14, 16);
backgroundSoundSetEndCallback(nullptr);
backgroundSoundSetEndCallback(NULL);
tickersRemove(_endgame_movie_bk_process);
}
}
@@ -894,15 +865,15 @@ static int endgameEndingInit()
EndgameEnding* entries;
size_t narratorFileNameLength;
if (gEndgameEndings != nullptr) {
if (gEndgameEndings != NULL) {
internal_free(gEndgameEndings);
gEndgameEndings = nullptr;
gEndgameEndings = NULL;
}
gEndgameEndingsLength = 0;
stream = fileOpen("data\\endgame.txt", "rt");
if (stream == nullptr) {
if (stream == NULL) {
return -1;
}
@@ -917,28 +888,28 @@ static int endgameEndingInit()
}
tok = strtok(ch, delim);
if (tok == nullptr) {
if (tok == NULL) {
continue;
}
entry.gvar = atoi(tok);
tok = strtok(nullptr, delim);
if (tok == nullptr) {
tok = strtok(NULL, delim);
if (tok == NULL) {
continue;
}
entry.value = atoi(tok);
tok = strtok(nullptr, delim);
if (tok == nullptr) {
tok = strtok(NULL, delim);
if (tok == NULL) {
continue;
}
entry.art_num = atoi(tok);
tok = strtok(nullptr, delim);
if (tok == nullptr) {
tok = strtok(NULL, delim);
if (tok == NULL) {
continue;
}
@@ -949,15 +920,15 @@ static int endgameEndingInit()
entry.voiceOverBaseName[narratorFileNameLength - 1] = '\0';
}
tok = strtok(nullptr, delim);
if (tok != nullptr) {
tok = strtok(NULL, delim);
if (tok != NULL) {
entry.direction = atoi(tok);
} else {
entry.direction = 1;
}
entries = (EndgameEnding*)internal_realloc(gEndgameEndings, sizeof(*entries) * (gEndgameEndingsLength + 1));
if (entries == nullptr) {
if (entries == NULL) {
goto err;
}
@@ -983,9 +954,9 @@ err:
// 0x44095C
static void endgameEndingFree()
{
if (gEndgameEndings != nullptr) {
if (gEndgameEndings != NULL) {
internal_free(gEndgameEndings);
gEndgameEndings = nullptr;
gEndgameEndings = NULL;
}
gEndgameEndingsLength = 0;
@@ -1007,7 +978,7 @@ int endgameDeathEndingInit()
strcpy(gEndgameDeathEndingFileName, "narrator\\nar_5");
stream = fileOpen("data\\enddeath.txt", "rt");
if (stream == nullptr) {
if (stream == NULL) {
return -1;
}
@@ -1022,49 +993,49 @@ int endgameDeathEndingInit()
}
tok = strtok(ch, delim);
if (tok == nullptr) {
if (tok == NULL) {
continue;
}
entry.gvar = atoi(tok);
tok = strtok(nullptr, delim);
if (tok == nullptr) {
tok = strtok(NULL, delim);
if (tok == NULL) {
continue;
}
entry.value = atoi(tok);
tok = strtok(nullptr, delim);
if (tok == nullptr) {
tok = strtok(NULL, delim);
if (tok == NULL) {
continue;
}
entry.worldAreaKnown = atoi(tok);
tok = strtok(nullptr, delim);
if (tok == nullptr) {
tok = strtok(NULL, delim);
if (tok == NULL) {
continue;
}
entry.worldAreaNotKnown = atoi(tok);
tok = strtok(nullptr, delim);
if (tok == nullptr) {
tok = strtok(NULL, delim);
if (tok == NULL) {
continue;
}
entry.min_level = atoi(tok);
tok = strtok(nullptr, delim);
if (tok == nullptr) {
tok = strtok(NULL, delim);
if (tok == NULL) {
continue;
}
entry.percentage = atoi(tok);
tok = strtok(nullptr, delim);
if (tok == nullptr) {
tok = strtok(NULL, delim);
if (tok == NULL) {
continue;
}
@@ -1079,7 +1050,7 @@ int endgameDeathEndingInit()
}
entries = (EndgameDeathEnding*)internal_realloc(gEndgameDeathEndings, sizeof(*entries) * (gEndgameDeathEndingsLength + 1));
if (entries == nullptr) {
if (entries == NULL) {
goto err;
}
@@ -1103,9 +1074,9 @@ err:
// 0x440BA8
int endgameDeathEndingExit()
{
if (gEndgameDeathEndings != nullptr) {
if (gEndgameDeathEndings != NULL) {
internal_free(gEndgameDeathEndings);
gEndgameDeathEndings = nullptr;
gEndgameDeathEndings = NULL;
gEndgameDeathEndingsLength = 0;
}
@@ -1229,14 +1200,4 @@ char* endgameDeathEndingGetFileName()
return gEndgameDeathEndingFileName;
}
void endgameEndingUpdateOverlay()
{
bufferFill(windowGetBuffer(gEndgameEndingOverlay),
windowGetWidth(gEndgameEndingOverlay),
windowGetHeight(gEndgameEndingOverlay),
windowGetWidth(gEndgameEndingOverlay),
intensityColorTable[_colorTable[0]][0]);
windowRefresh(gEndgameEndingOverlay);
}
} // namespace fallout

View File

@@ -61,7 +61,7 @@ ExternalProcedure* externalProcedureFind(const char* identifier)
unsigned int v2 = v1;
ExternalProcedure* externalProcedure = &(gExternalProcedures[v1]);
if (externalProcedure->program != nullptr) {
if (externalProcedure->program != NULL) {
if (compat_stricmp(externalProcedure->name, identifier) == 0) {
return externalProcedure;
}
@@ -74,14 +74,14 @@ ExternalProcedure* externalProcedureFind(const char* identifier)
}
externalProcedure = &(gExternalProcedures[v1]);
if (externalProcedure->program != nullptr) {
if (externalProcedure->program != NULL) {
if (compat_stricmp(externalProcedure->name, identifier) == 0) {
return externalProcedure;
}
}
} while (v1 != v2);
return nullptr;
return NULL;
}
// 0x441018
@@ -108,7 +108,7 @@ ExternalProcedure* externalProcedureAdd(const char* identifier)
}
} while (v1 != a2);
return nullptr;
return NULL;
}
// 0x4410AC
@@ -140,7 +140,7 @@ ExternalVariable* externalVariableFind(const char* identifier)
}
} while (v1 != v2);
return nullptr;
return NULL;
}
// 0x44118C
@@ -167,14 +167,14 @@ ExternalVariable* externalVariableAdd(const char* identifier)
}
} while (v1 != v2);
return nullptr;
return NULL;
}
// 0x44127C
int externalVariableSetValue(Program* program, const char* name, ProgramValue& programValue)
{
ExternalVariable* exportedVariable = externalVariableFind(name);
if (exportedVariable == nullptr) {
if (exportedVariable == NULL) {
return 1;
}
@@ -183,7 +183,7 @@ int externalVariableSetValue(Program* program, const char* name, ProgramValue& p
}
if ((programValue.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) {
if (program != nullptr) {
if (program != NULL) {
const char* stringValue = programGetString(program, programValue.opcode, programValue.integerValue);
exportedVariable->value.opcode = VALUE_TYPE_DYNAMIC_STRING;
@@ -201,7 +201,7 @@ int externalVariableSetValue(Program* program, const char* name, ProgramValue& p
int externalVariableGetValue(Program* program, const char* name, ProgramValue& value)
{
ExternalVariable* exportedVariable = externalVariableFind(name);
if (exportedVariable == nullptr) {
if (exportedVariable == NULL) {
return 1;
}
@@ -221,7 +221,7 @@ int externalVariableCreate(Program* program, const char* identifier)
const char* programName = program->name;
ExternalVariable* exportedVariable = externalVariableFind(identifier);
if (exportedVariable != nullptr) {
if (exportedVariable != NULL) {
if (compat_stricmp(exportedVariable->programName, programName) != 0) {
return 1;
}
@@ -231,7 +231,7 @@ int externalVariableCreate(Program* program, const char* identifier)
}
} else {
exportedVariable = externalVariableAdd(identifier);
if (exportedVariable == nullptr) {
if (exportedVariable == NULL) {
return 1;
}
@@ -254,7 +254,7 @@ void _removeProgramReferences(Program* program)
ExternalProcedure* externalProcedure = &(gExternalProcedures[index]);
if (externalProcedure->program == program) {
externalProcedure->name[0] = '\0';
externalProcedure->program = nullptr;
externalProcedure->program = NULL;
}
}
}
@@ -285,12 +285,12 @@ void externalVariablesClear()
Program* externalProcedureGetProgram(const char* identifier, int* addressPtr, int* argumentCountPtr)
{
ExternalProcedure* externalProcedure = externalProcedureFind(identifier);
if (externalProcedure == nullptr) {
return nullptr;
if (externalProcedure == NULL) {
return NULL;
}
if (externalProcedure->program == nullptr) {
return nullptr;
if (externalProcedure->program == NULL) {
return NULL;
}
*addressPtr = externalProcedure->address;
@@ -303,13 +303,13 @@ Program* externalProcedureGetProgram(const char* identifier, int* addressPtr, in
int externalProcedureCreate(Program* program, const char* identifier, int address, int argumentCount)
{
ExternalProcedure* externalProcedure = externalProcedureFind(identifier);
if (externalProcedure != nullptr) {
if (externalProcedure != NULL) {
if (program != externalProcedure->program) {
return 1;
}
} else {
externalProcedure = externalProcedureAdd(identifier);
if (externalProcedure == nullptr) {
if (externalProcedure == NULL) {
return 1;
}
@@ -330,14 +330,14 @@ void _exportClearAllVariables()
ExternalVariable* exportedVariable = &(gExternalVariables[index]);
if (exportedVariable->name[0] != '\0') {
if ((exportedVariable->value.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) {
if (exportedVariable->stringValue != nullptr) {
if (exportedVariable->stringValue != NULL) {
internal_free_safe(exportedVariable->stringValue, __FILE__, __LINE__); // "..\\int\\EXPORT.C", 387
}
}
if (exportedVariable->programName != nullptr) {
if (exportedVariable->programName != NULL) {
internal_free_safe(exportedVariable->programName, __FILE__, __LINE__); // "..\\int\\EXPORT.C", 393
exportedVariable->programName = nullptr;
exportedVariable->programName = NULL;
}
exportedVariable->name[0] = '\0';

View File

@@ -3,7 +3,7 @@
#include <stddef.h>
#include <string.h>
#include <fpattern/fpattern.h>
#include <fpattern.h>
namespace fallout {
@@ -16,41 +16,33 @@ bool fileFindFirst(const char* path, DirectoryFileFindData* findData)
return false;
}
#else
strcpy(findData->path, path);
char drive[COMPAT_MAX_DRIVE];
char dir[COMPAT_MAX_DIR];
char fname[COMPAT_MAX_FNAME];
char ext[COMPAT_MAX_EXT];
compat_splitpath(path, drive, dir, fname, ext);
// Reassemble file name and extension to serve as a pattern. It has to be
// lowercased because underlying `fpattern` implementation uses lowercased
// char-by-char matching.
compat_makepath(findData->pattern, nullptr, nullptr, fname, ext);
compat_strlwr(findData->pattern);
compat_splitpath(path, drive, dir, NULL, NULL);
char basePath[COMPAT_MAX_PATH];
compat_makepath(basePath, drive, dir, nullptr, nullptr);
compat_resolve_path(basePath);
compat_makepath(basePath, drive, dir, NULL, NULL);
findData->dir = opendir(basePath);
if (findData->dir == nullptr) {
if (findData->dir == NULL) {
return false;
}
findData->entry = readdir(findData->dir);
while (findData->entry != nullptr) {
char entryName[COMPAT_MAX_FNAME];
strcpy(entryName, fileFindGetName(findData));
compat_strlwr(entryName);
if (fpattern_match(findData->pattern, entryName)) {
while (findData->entry != NULL) {
char entryPath[COMPAT_MAX_PATH];
compat_makepath(entryPath, drive, dir, fileFindGetName(findData), NULL);
if (fpattern_match(findData->path, entryPath)) {
break;
}
findData->entry = readdir(findData->dir);
}
if (findData->entry == nullptr) {
if (findData->entry == NULL) {
closedir(findData->dir);
findData->dir = nullptr;
findData->dir = NULL;
return false;
}
#endif
@@ -66,20 +58,23 @@ bool fileFindNext(DirectoryFileFindData* findData)
return false;
}
#else
char drive[COMPAT_MAX_DRIVE];
char dir[COMPAT_MAX_DIR];
compat_splitpath(findData->path, drive, dir, NULL, NULL);
findData->entry = readdir(findData->dir);
while (findData->entry != nullptr) {
char entryName[COMPAT_MAX_FNAME];
strcpy(entryName, fileFindGetName(findData));
compat_strlwr(entryName);
if (fpattern_match(findData->pattern, entryName)) {
while (findData->entry != NULL) {
char entryPath[COMPAT_MAX_PATH];
compat_makepath(entryPath, drive, dir, fileFindGetName(findData), NULL);
if (fpattern_match(findData->path, entryPath)) {
break;
}
findData->entry = readdir(findData->dir);
}
if (findData->entry == nullptr) {
if (findData->entry == NULL) {
closedir(findData->dir);
findData->dir = nullptr;
findData->dir = NULL;
return false;
}
#endif
@@ -93,7 +88,7 @@ bool findFindClose(DirectoryFileFindData* findData)
#if defined(_MSC_VER)
FindClose(findData->hFind);
#else
if (findData->dir != nullptr) {
if (findData->dir != NULL) {
if (closedir(findData->dir) != 0) {
return false;
}

View File

@@ -2,6 +2,8 @@
#define FILE_FIND_H
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#else
#include <dirent.h>
@@ -37,7 +39,7 @@ typedef struct DirectoryFileFindData {
#else
DIR* dir;
struct dirent* entry;
char pattern[COMPAT_MAX_FNAME];
char path[COMPAT_MAX_PATH];
#endif
} DirectoryFileFindData;

View File

@@ -19,7 +19,7 @@ static void fileCopy(const char* existingFilePath, const char* newFilePath);
int fileCopyDecompressed(const char* existingFilePath, const char* newFilePath)
{
FILE* stream = compat_fopen(existingFilePath, "rb");
if (stream == nullptr) {
if (stream == NULL) {
return -1;
}
@@ -32,7 +32,7 @@ int fileCopyDecompressed(const char* existingFilePath, const char* newFilePath)
gzFile inStream = compat_gzopen(existingFilePath, "rb");
FILE* outStream = compat_fopen(newFilePath, "wb");
if (inStream != nullptr && outStream != nullptr) {
if (inStream != NULL && outStream != NULL) {
for (;;) {
int ch = gzgetc(inStream);
if (ch == -1) {
@@ -45,11 +45,11 @@ int fileCopyDecompressed(const char* existingFilePath, const char* newFilePath)
gzclose(inStream);
fclose(outStream);
} else {
if (inStream != nullptr) {
if (inStream != NULL) {
gzclose(inStream);
}
if (outStream != nullptr) {
if (outStream != NULL) {
fclose(outStream);
}
@@ -66,7 +66,7 @@ int fileCopyDecompressed(const char* existingFilePath, const char* newFilePath)
int fileCopyCompressed(const char* existingFilePath, const char* newFilePath)
{
FILE* inStream = compat_fopen(existingFilePath, "rb");
if (inStream == nullptr) {
if (inStream == NULL) {
return -1;
}
@@ -82,7 +82,7 @@ int fileCopyCompressed(const char* existingFilePath, const char* newFilePath)
fileCopy(existingFilePath, newFilePath);
} else {
gzFile outStream = compat_gzopen(newFilePath, "wb");
if (outStream == nullptr) {
if (outStream == NULL) {
fclose(inStream);
return -1;
}
@@ -108,7 +108,7 @@ int fileCopyCompressed(const char* existingFilePath, const char* newFilePath)
int _gzdecompress_file(const char* existingFilePath, const char* newFilePath)
{
FILE* stream = compat_fopen(existingFilePath, "rb");
if (stream == nullptr) {
if (stream == NULL) {
return -1;
}
@@ -120,12 +120,12 @@ int _gzdecompress_file(const char* existingFilePath, const char* newFilePath)
// TODO: Is it broken?
if (magic[0] != 0x1F || magic[1] != 0x8B) {
gzFile gzstream = compat_gzopen(existingFilePath, "rb");
if (gzstream == nullptr) {
if (gzstream == NULL) {
return -1;
}
stream = compat_fopen(newFilePath, "wb");
if (stream == nullptr) {
if (stream == NULL) {
gzclose(gzstream);
return -1;
}
@@ -150,9 +150,17 @@ int _gzdecompress_file(const char* existingFilePath, const char* newFilePath)
static void fileCopy(const char* existingFilePath, const char* newFilePath)
{
FILE* in = compat_fopen(existingFilePath, "rb");
FILE* out = compat_fopen(newFilePath, "wb");
if (in != nullptr && out != nullptr) {
char nativeExistingFilePath[COMPAT_MAX_PATH];
strcpy(nativeExistingFilePath, existingFilePath);
compat_windows_path_to_native(nativeExistingFilePath);
char nativeNewFilePath[COMPAT_MAX_PATH];
strcpy(nativeNewFilePath, newFilePath);
compat_windows_path_to_native(nativeNewFilePath);
FILE* in = fopen(nativeExistingFilePath, "rb");
FILE* out = fopen(nativeNewFilePath, "wb");
if (in != NULL && out != NULL) {
std::vector<unsigned char> buffer(0xFFFF);
size_t bytesRead;
@@ -171,11 +179,11 @@ static void fileCopy(const char* existingFilePath, const char* newFilePath)
}
}
if (in != nullptr) {
if (in != NULL) {
fclose(in);
}
if (out != nullptr) {
if (out != NULL) {
fclose(out);
}
}

View File

@@ -82,7 +82,7 @@ int interfaceFontsInit()
for (int font = 0; font < INTERFACE_FONT_MAX; font++) {
if (interfaceFontLoad(font) == -1) {
gInterfaceFontDescriptors[font].maxHeight = 0;
gInterfaceFontDescriptors[font].data = nullptr;
gInterfaceFontDescriptors[font].data = NULL;
} else {
++gInterfaceFontsLength;
@@ -107,7 +107,7 @@ int interfaceFontsInit()
void interfaceFontsExit()
{
for (int font = 0; font < INTERFACE_FONT_MAX; font++) {
if (gInterfaceFontDescriptors[font].data != nullptr) {
if (gInterfaceFontDescriptors[font].data != NULL) {
internal_free_safe(gInterfaceFontDescriptors[font].data, __FILE__, __LINE__); // FONTMGR.C, 124
}
}
@@ -119,89 +119,64 @@ static int interfaceFontLoad(int font_index)
InterfaceFontDescriptor* fontDescriptor = &(gInterfaceFontDescriptors[font_index]);
char path[56];
snprintf(path, sizeof(path), "font%d.aaf", font_index);
sprintf(path, "font%d.aaf", font_index);
File* stream = fileOpen(path, "rb");
if (stream == nullptr) {
return -1;
if (stream == NULL) {
return false;
}
int fileSize = fileGetSize(stream);
int sig;
if (fileRead(&sig, 4, 1, stream) != 1) {
fileClose(stream);
return -1;
}
if (fileRead(&sig, 4, 1, stream) != 1) goto err;
interfaceFontByteSwapInt32(&sig);
if (sig != 0x41414646) {
fileClose(stream);
return -1;
}
if (sig != 0x41414646) goto err;
if (fileRead(&(fontDescriptor->maxHeight), 2, 1, stream) != 1) {
fileClose(stream);
return -1;
}
if (fileRead(&(fontDescriptor->maxHeight), 2, 1, stream) != 1) goto err;
interfaceFontByteSwapInt16(&(fontDescriptor->maxHeight));
if (fileRead(&(fontDescriptor->letterSpacing), 2, 1, stream) != 1) {
fileClose(stream);
return -1;
}
if (fileRead(&(fontDescriptor->letterSpacing), 2, 1, stream) != 1) goto err;
interfaceFontByteSwapInt16(&(fontDescriptor->letterSpacing));
if (fileRead(&(fontDescriptor->wordSpacing), 2, 1, stream) != 1) {
fileClose(stream);
return -1;
}
if (fileRead(&(fontDescriptor->wordSpacing), 2, 1, stream) != 1) goto err;
interfaceFontByteSwapInt16(&(fontDescriptor->wordSpacing));
if (fileRead(&(fontDescriptor->lineSpacing), 2, 1, stream) != 1) {
fileClose(stream);
return -1;
}
if (fileRead(&(fontDescriptor->lineSpacing), 2, 1, stream) != 1) goto err;
interfaceFontByteSwapInt16(&(fontDescriptor->lineSpacing));
for (int index = 0; index < 256; index++) {
InterfaceFontGlyph* glyph = &(fontDescriptor->glyphs[index]);
if (fileRead(&(glyph->width), 2, 1, stream) != 1) {
fileClose(stream);
return -1;
}
if (fileRead(&(glyph->width), 2, 1, stream) != 1) goto err;
interfaceFontByteSwapInt16(&(glyph->width));
if (fileRead(&(glyph->height), 2, 1, stream) != 1) {
fileClose(stream);
return -1;
}
if (fileRead(&(glyph->height), 2, 1, stream) != 1) goto err;
interfaceFontByteSwapInt16(&(glyph->height));
if (fileRead(&(glyph->offset), 4, 1, stream) != 1) {
fileClose(stream);
return -1;
}
if (fileRead(&(glyph->offset), 4, 1, stream) != 1) goto err;
interfaceFontByteSwapInt32(&(glyph->offset));
}
int glyphDataSize = fileSize - 2060;
fileSize -= sizeof(InterfaceFontDescriptor);
fontDescriptor->data = (unsigned char*)internal_malloc_safe(glyphDataSize, __FILE__, __LINE__); // FONTMGR.C, 259
if (fontDescriptor->data == nullptr) {
fileClose(stream);
return -1;
}
fontDescriptor->data = (unsigned char*)internal_malloc_safe(fileSize, __FILE__, __LINE__); // FONTMGR.C, 259
if (fontDescriptor->data == NULL) goto err;
if (fileRead(fontDescriptor->data, glyphDataSize, 1, stream) != 1) {
if (fileRead(fontDescriptor->data, fileSize, 1, stream) != 1) {
internal_free_safe(fontDescriptor->data, __FILE__, __LINE__); // FONTMGR.C, 268
fileClose(stream);
return -1;
goto err;
}
fileClose(stream);
return 0;
err:
fileClose(stream);
return -1;
}
// 0x442120
@@ -213,7 +188,7 @@ static void interfaceFontSetCurrentImpl(int font)
font -= 100;
if (gInterfaceFontDescriptors[font].data != nullptr) {
if (gInterfaceFontDescriptors[font].data != NULL) {
gCurrentInterfaceFont = font;
gCurrentInterfaceFontDescriptor = &(gInterfaceFontDescriptors[font]);
}
@@ -236,22 +211,26 @@ static int interfaceFontGetStringWidthImpl(const char* string)
return 0;
}
int stringWidth = 0;
const char* pch = string;
int width = 0;
while (*string != '\0') {
unsigned char ch = static_cast<unsigned char>(*string++);
while (*pch != '\0') {
int v3;
int v4;
int characterWidth;
if (ch == ' ') {
characterWidth = gCurrentInterfaceFontDescriptor->wordSpacing;
if (*pch == ' ') {
v3 = gCurrentInterfaceFontDescriptor->letterSpacing;
v4 = gCurrentInterfaceFontDescriptor->wordSpacing;
} else {
characterWidth = gCurrentInterfaceFontDescriptor->glyphs[ch].width;
v3 = gCurrentInterfaceFontDescriptor->glyphs[*pch & 0xFF].width;
v4 = gCurrentInterfaceFontDescriptor->letterSpacing;
}
width += v3 + v4;
stringWidth += characterWidth + gCurrentInterfaceFontDescriptor->letterSpacing;
pch++;
}
return stringWidth;
return width;
}
// 0x4421DC
@@ -343,13 +322,13 @@ static void interfaceFontDrawImpl(unsigned char* buf, const char* string, int le
unsigned char* ptr = buf;
while (*string != '\0') {
unsigned char ch = static_cast<unsigned char>(*string++);
char ch = *string++;
int characterWidth;
if (ch == ' ') {
characterWidth = gCurrentInterfaceFontDescriptor->wordSpacing;
} else {
characterWidth = gCurrentInterfaceFontDescriptor->glyphs[ch].width;
characterWidth = gCurrentInterfaceFontDescriptor->glyphs[ch & 0xFF].width;
}
unsigned char* end;
@@ -364,7 +343,7 @@ static void interfaceFontDrawImpl(unsigned char* buf, const char* string, int le
break;
}
InterfaceFontGlyph* glyph = &(gCurrentInterfaceFontDescriptor->glyphs[ch]);
InterfaceFontGlyph* glyph = &(gCurrentInterfaceFontDescriptor->glyphs[ch & 0xFF]);
unsigned char* glyphDataPtr = gCurrentInterfaceFontDescriptor->data + glyph->offset;
// Skip blank pixels (difference between font's line height and glyph height).

View File

@@ -4,7 +4,7 @@
namespace fallout {
FpsLimiter::FpsLimiter(unsigned int fps)
FpsLimiter::FpsLimiter(std::size_t fps)
: _fps(fps)
, _ticks(0)
{

View File

@@ -1,17 +1,19 @@
#ifndef FPS_LIMITER_H
#define FPS_LIMITER_H
#include <cstddef>
namespace fallout {
class FpsLimiter {
public:
FpsLimiter(unsigned int fps = 60);
FpsLimiter(std::size_t fps = 60);
void mark();
void throttle() const;
private:
const unsigned int _fps;
unsigned int _ticks;
const std::size_t _fps;
std::size_t _ticks;
};
} // namespace fallout

View File

@@ -3,6 +3,12 @@
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h> // access
#endif
#include "actions.h"
#include "animation.h"
#include "art.h"
@@ -12,6 +18,7 @@
#include "color.h"
#include "combat.h"
#include "combat_ai.h"
#include "core.h"
#include "critter.h"
#include "cycle.h"
#include "db.h"
@@ -19,22 +26,21 @@
#include "debug.h"
#include "display_monitor.h"
#include "draw.h"
#include "electronic_registration.h"
#include "endgame.h"
#include "font_manager.h"
#include "game_config.h"
#include "game_dialog.h"
#include "game_memory.h"
#include "game_mouse.h"
#include "game_movie.h"
#include "game_sound.h"
#include "input.h"
#include "interface.h"
#include "inventory.h"
#include "item.h"
#include "kb.h"
#include "loadsave.h"
#include "map.h"
#include "memory.h"
#include "mouse.h"
#include "movie.h"
#include "movie_effect.h"
#include "object.h"
@@ -44,28 +50,20 @@
#include "perk.h"
#include "pipboy.h"
#include "platform_compat.h"
#include "preferences.h"
#include "proto.h"
#include "queue.h"
#include "random.h"
#include "scripts.h"
#include "settings.h"
#include "sfall_arrays.h"
#include "sfall_config.h"
#include "sfall_global_scripts.h"
#include "sfall_global_vars.h"
#include "sfall_ini.h"
#include "sfall_lists.h"
#include "skill.h"
#include "skilldex.h"
#include "stat.h"
#include "svga.h"
#include "text_font.h"
#include "tile.h"
#include "trait.h"
#include "trap.h"
#include "version.h"
#include "window_manager.h"
#include "window_manager_private.h"
#include "worldmap.h"
namespace fallout {
@@ -94,13 +92,13 @@ static char _aDec11199816543[] = VERSION_BUILD_TIME;
static bool gGameUiDisabled = false;
// 0x5186B8
static int gGameState = GAME_STATE_0;
static int _game_state_cur = GAME_STATE_0;
// 0x5186BC
static bool gIsMapper = false;
// 0x5186C0
int* gGameGlobalVars = nullptr;
int* gGameGlobalVars = NULL;
// 0x5186C4
int gGameGlobalVarsLength = 0;
@@ -116,8 +114,15 @@ int _game_user_wants_to_quit = 0;
// 0x58E940
MessageList gMiscMessageList;
// CE: Sonora folks like to store objects in global variables.
static void** gGameGlobalPointers = nullptr;
// master.dat loading result
//
// 0x58E948
int _master_db_handle;
// critter.dat loading result
//
// 0x58E94C
int _critter_db_handle;
// 0x442580
int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4, int argc, char** argv)
@@ -132,33 +137,32 @@ int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4
// override it's file name.
sfallConfigInit(argc, argv);
settingsInit(isMapper, argc, argv);
gameConfigInit(isMapper, argc, argv);
gIsMapper = isMapper;
if (gameDbInit() == -1) {
settingsExit(false);
gameConfigExit(false);
sfallConfigExit();
return -1;
}
// Message list repository is considered a specialized file manager, so
// it should be initialized early in the process.
messageListRepositoryInit();
runElectronicRegistration();
programWindowSetTitle(windowTitle);
_initWindow(1, a4);
paletteInit();
const char* language = settings.system.language.c_str();
if (compat_stricmp(language, FRENCH) == 0) {
keyboardSetLayout(KEYBOARD_LAYOUT_FRENCH);
} else if (compat_stricmp(language, GERMAN) == 0) {
keyboardSetLayout(KEYBOARD_LAYOUT_GERMAN);
} else if (compat_stricmp(language, ITALIAN) == 0) {
keyboardSetLayout(KEYBOARD_LAYOUT_ITALIAN);
} else if (compat_stricmp(language, SPANISH) == 0) {
keyboardSetLayout(KEYBOARD_LAYOUT_SPANISH);
char* language;
if (configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_LANGUAGE_KEY, &language)) {
if (compat_stricmp(language, FRENCH) == 0) {
keyboardSetLayout(KEYBOARD_LAYOUT_FRENCH);
} else if (compat_stricmp(language, GERMAN) == 0) {
keyboardSetLayout(KEYBOARD_LAYOUT_GERMAN);
} else if (compat_stricmp(language, ITALIAN) == 0) {
keyboardSetLayout(KEYBOARD_LAYOUT_ITALIAN);
} else if (compat_stricmp(language, SPANISH) == 0) {
keyboardSetLayout(KEYBOARD_LAYOUT_SPANISH);
}
}
// SFALL: Allow to skip splash screen
@@ -169,26 +173,14 @@ int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4
showSplash();
}
// CE: Handle debug mode (exactly as seen in `mapper2.exe`).
const char* debugMode = settings.debug.mode.c_str();
if (compat_stricmp(debugMode, "environment") == 0) {
_debug_register_env();
} else if (compat_stricmp(debugMode, "screen") == 0) {
_debug_register_screen();
} else if (compat_stricmp(debugMode, "log") == 0) {
_debug_register_log("debug.log", "wt");
} else if (compat_stricmp(debugMode, "mono") == 0) {
_debug_register_mono();
} else if (compat_stricmp(debugMode, "gnw") == 0) {
_debug_register_func(_win_debug);
}
_trap_init();
interfaceFontsInit();
fontManagerAdd(&gModernFontManager);
fontSetCurrent(font);
screenshotHandlerConfigure(KEY_F12, gameTakeScreenshot);
pauseHandlerConfigure(-1, nullptr);
pauseHandlerConfigure(-1, NULL);
tileDisable();
@@ -323,7 +315,7 @@ int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4
debugPrint(">message_init\t");
snprintf(path, sizeof(path), "%s%s", asc_5186C8, "misc.msg");
sprintf(path, "%s%s", asc_5186C8, "misc.msg");
if (!messageListLoad(&gMiscMessageList, path)) {
debugPrint("Failed on message_load\n");
@@ -356,32 +348,6 @@ int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4
// SFALL
premadeCharactersInit();
if (!sfall_gl_vars_init()) {
debugPrint("Failed on sfall_gl_vars_init");
return -1;
}
if (!sfallListsInit()) {
debugPrint("Failed on sfallListsInit");
return -1;
}
if (!sfallArraysInit()) {
debugPrint("Failed on sfallArraysInit");
return -1;
}
if (!sfall_gl_scr_init()) {
debugPrint("Failed on sfall_gl_scr_init");
return -1;
}
char* customConfigBasePath;
configGetString(&gSfallConfig, SFALL_CONFIG_SCRIPTS_KEY, SFALL_CONFIG_INI_CONFIG_FOLDER, &customConfigBasePath);
sfall_ini_set_base_path(customConfigBasePath);
messageListRepositorySetStandardMessageList(STANDARD_MESSAGE_LIST_MISC, &gMiscMessageList);
return 0;
}
@@ -422,13 +388,6 @@ void gameReset()
_game_user_wants_to_quit = 0;
automapReset();
_init_options_menu();
// SFALL
sfall_gl_vars_reset();
sfallListsReset();
messageListRepositoryReset();
sfallArraysReset();
sfall_gl_scr_reset();
}
// 0x442C34
@@ -437,14 +396,9 @@ void gameExit()
debugPrint("\nGame Exit\n");
// SFALL
sfall_gl_scr_exit();
sfallArraysExit();
sfallListsExit();
sfall_gl_vars_exit();
premadeCharactersExit();
tileDisable();
messageListRepositorySetStandardMessageList(STANDARD_MESSAGE_LIST_MISC, nullptr);
messageListFree(&gMiscMessageList);
combatExit();
gameDialogExit();
@@ -477,10 +431,10 @@ void gameExit()
partyMembersExit();
endgameDeathEndingExit();
interfaceFontsExit();
_trap_init();
_windowClose();
messageListRepositoryExit();
dbExit();
settingsExit(true);
gameConfigExit(true);
sfallConfigExit();
}
@@ -488,7 +442,7 @@ void gameExit()
int gameHandleKey(int eventCode, bool isInCombatMode)
{
// NOTE: Uninline.
if (gameGetState() == GAME_STATE_5) {
if (_game_state() == GAME_STATE_5) {
_gdialogSystemEnter();
}
@@ -599,7 +553,7 @@ int gameHandleKey(int eventCode, bool isInCombatMode)
case KEY_LOWERCASE_A:
if (interfaceBarEnabled()) {
if (!isInCombatMode) {
_combat(nullptr);
_combat(NULL);
}
}
break;
@@ -661,7 +615,7 @@ int gameHandleKey(int eventCode, bool isInCombatMode)
MessageListItem messageListItem;
char title[128];
strcpy(title, getmsg(&gMiscMessageList, &messageListItem, 7));
showDialogBox(title, nullptr, 0, 192, 116, _colorTable[32328], nullptr, _colorTable[32328], 0);
showDialogBox(title, NULL, 0, 192, 116, _colorTable[32328], NULL, _colorTable[32328], 0);
} else {
soundPlayFile("ib1p1xx1");
pipboyOpen(PIPBOY_OPEN_INTENT_UNSPECIFIED);
@@ -729,7 +683,7 @@ int gameHandleKey(int eventCode, bool isInCombatMode)
MessageListItem messageListItem;
char title[128];
strcpy(title, getmsg(&gMiscMessageList, &messageListItem, 7));
showDialogBox(title, nullptr, 0, 192, 116, _colorTable[32328], nullptr, _colorTable[32328], 0);
showDialogBox(title, NULL, 0, 192, 116, _colorTable[32328], NULL, _colorTable[32328], 0);
} else {
soundPlayFile("ib1p1xx1");
pipboyOpen(PIPBOY_OPEN_INTENT_REST);
@@ -742,7 +696,7 @@ int gameHandleKey(int eventCode, bool isInCombatMode)
}
if (gIsMapper) {
tileSetCenter(gDude->tile, TILE_SET_CENTER_REFRESH_WINDOW);
tileSetCenter(gDude->tile, TILE_SET_CENTER_FLAG_0x01);
} else {
_tile_scroll_to(gDude->tile, 2);
}
@@ -847,7 +801,7 @@ int gameHandleKey(int eventCode, bool isInCombatMode)
MessageList messageList;
if (messageListInit(&messageList)) {
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s%s", asc_5186C8, "editor.msg");
sprintf(path, "%s%s", asc_5186C8, "editor.msg");
if (messageListLoad(&messageList, path)) {
MessageListItem messageListItem;
@@ -856,7 +810,7 @@ int gameHandleKey(int eventCode, bool isInCombatMode)
char* time = gameTimeGetTimeString();
char date[128];
snprintf(date, sizeof(date), "%s: %d/%d %s", messageListItem.text, day, year, time);
sprintf(date, "%s: %d/%d %s", messageListItem.text, day, year, time);
displayMonitorAddMessage(date);
}
@@ -925,7 +879,7 @@ int gameHandleKey(int eventCode, bool isInCombatMode)
soundPlayFile("ib1p1xx1");
char version[VERSION_MAX];
versionGetVersion(version, sizeof(version));
versionGetVersion(version);
displayMonitorAddMessage(version);
displayMonitorAddMessage(_aDec11199816543);
}
@@ -1009,9 +963,9 @@ int gameSetGlobalVar(int var, int value)
if (diff != 0) {
char formattedMessage[80];
if (diff > 0) {
snprintf(formattedMessage, sizeof(formattedMessage), "You gained %d karma.", diff);
sprintf(formattedMessage, "You gained %d karma.", diff);
} else {
snprintf(formattedMessage, sizeof(formattedMessage), "You lost %d karma.", -diff);
sprintf(formattedMessage, "You lost %d karma.", -diff);
}
displayMonitorAddMessage(formattedMessage);
}
@@ -1027,18 +981,7 @@ int gameSetGlobalVar(int var, int value)
// 0x443CC8
static int gameLoadGlobalVars()
{
if (globalVarsRead("data\\vault13.gam", "GAME_GLOBAL_VARS:", &gGameGlobalVarsLength, &gGameGlobalVars) != 0) {
return -1;
}
gGameGlobalPointers = reinterpret_cast<void**>(internal_malloc(sizeof(*gGameGlobalPointers) * gGameGlobalVarsLength));
if (gGameGlobalPointers == nullptr) {
return -1;
}
memset(gGameGlobalPointers, 0, sizeof(*gGameGlobalPointers) * gGameGlobalVarsLength);
return 0;
return globalVarsRead("data\\vault13.gam", "GAME_GLOBAL_VARS:", &gGameGlobalVarsLength, &gGameGlobalVars);
}
// 0x443CE8
@@ -1047,18 +990,18 @@ int globalVarsRead(const char* path, const char* section, int* variablesListLeng
_inven_reset_dude();
File* stream = fileOpen(path, "rt");
if (stream == nullptr) {
if (stream == NULL) {
return -1;
}
if (*variablesListLengthPtr != 0) {
internal_free(*variablesListPtr);
*variablesListPtr = nullptr;
*variablesListPtr = NULL;
*variablesListLengthPtr = 0;
}
char string[260];
if (section != nullptr) {
if (section != NULL) {
while (fileReadString(string, 258, stream)) {
if (strncmp(string, section, 16) == 0) {
break;
@@ -1076,19 +1019,19 @@ int globalVarsRead(const char* path, const char* section, int* variablesListLeng
}
char* semicolon = strchr(string, ';');
if (semicolon != nullptr) {
if (semicolon != NULL) {
*semicolon = '\0';
}
*variablesListLengthPtr = *variablesListLengthPtr + 1;
*variablesListPtr = (int*)internal_realloc(*variablesListPtr, sizeof(int) * *variablesListLengthPtr);
if (*variablesListPtr == nullptr) {
if (*variablesListPtr == NULL) {
exit(1);
}
char* equals = strchr(string, '=');
if (equals != nullptr) {
if (equals != NULL) {
sscanf(equals + 1, "%d", *variablesListPtr + *variablesListLengthPtr - 1);
} else {
*variablesListPtr[*variablesListLengthPtr - 1] = 0;
@@ -1101,48 +1044,48 @@ int globalVarsRead(const char* path, const char* section, int* variablesListLeng
}
// 0x443E2C
int gameGetState()
int _game_state()
{
return gGameState;
return _game_state_cur;
}
// 0x443E34
int gameRequestState(int newGameState)
int _game_state_request(int a1)
{
switch (newGameState) {
case GAME_STATE_0:
newGameState = GAME_STATE_1;
break;
case GAME_STATE_2:
newGameState = GAME_STATE_3;
break;
case GAME_STATE_4:
newGameState = GAME_STATE_5;
break;
if (a1 == GAME_STATE_0) {
a1 = GAME_STATE_1;
} else if (a1 == GAME_STATE_2) {
a1 = GAME_STATE_3;
} else if (a1 == GAME_STATE_4) {
a1 = GAME_STATE_5;
}
if (gGameState == GAME_STATE_4 && newGameState == GAME_STATE_5) {
return -1;
if (_game_state_cur != GAME_STATE_4 || a1 != GAME_STATE_5) {
_game_state_cur = a1;
return 0;
}
gGameState = newGameState;
return 0;
return -1;
}
// 0x443E90
void gameUpdateState()
void _game_state_update()
{
switch (gGameState) {
int v0;
v0 = _game_state_cur;
switch (_game_state_cur) {
case GAME_STATE_1:
gGameState = GAME_STATE_0;
v0 = GAME_STATE_0;
break;
case GAME_STATE_3:
gGameState = GAME_STATE_2;
v0 = GAME_STATE_2;
break;
case GAME_STATE_5:
gGameState = GAME_STATE_4;
break;
v0 = GAME_STATE_4;
}
_game_state_cur = v0;
}
// 0x443EF0
@@ -1175,22 +1118,15 @@ static int gameTakeScreenshot(int width, int height, unsigned char* buffer, unsi
static void gameFreeGlobalVars()
{
gGameGlobalVarsLength = 0;
if (gGameGlobalVars != nullptr) {
if (gGameGlobalVars != NULL) {
internal_free(gGameGlobalVars);
gGameGlobalVars = nullptr;
}
if (gGameGlobalPointers != nullptr) {
internal_free(gGameGlobalPointers);
gGameGlobalPointers = nullptr;
gGameGlobalVars = NULL;
}
}
// 0x443F74
static void showHelp()
{
ScopedGameMode gm(GameMode::kHelp);
bool isoWasEnabled = isoDisable();
gameMouseObjectsHide();
@@ -1199,56 +1135,32 @@ static void showHelp()
bool colorCycleWasEnabled = colorCycleEnabled();
colorCycleDisable();
// CE: Help screen uses separate color palette which is incompatible with
// colors in other windows. Setup overlay to hide everything.
int overlay = windowCreate(0, 0, screenGetWidth(), screenGetHeight(), 0, WINDOW_HIDDEN | WINDOW_MOVE_ON_TOP);
int helpWindowX = (screenGetWidth() - HELP_SCREEN_WIDTH) / 2;
int helpWindowY = (screenGetHeight() - HELP_SCREEN_HEIGHT) / 2;
int win = windowCreate(helpWindowX, helpWindowY, HELP_SCREEN_WIDTH, HELP_SCREEN_HEIGHT, 0, WINDOW_HIDDEN | WINDOW_MOVE_ON_TOP);
int win = windowCreate(helpWindowX, helpWindowY, HELP_SCREEN_WIDTH, HELP_SCREEN_HEIGHT, 0, WINDOW_HIDDEN | WINDOW_FLAG_0x04);
if (win != -1) {
unsigned char* windowBuffer = windowGetBuffer(win);
if (windowBuffer != nullptr) {
if (windowBuffer != NULL) {
FrmImage backgroundFrmImage;
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 297, 0, 0, 0);
if (backgroundFrmImage.lock(backgroundFid)) {
paletteSetEntries(gPaletteBlack);
blitBufferToBuffer(backgroundFrmImage.getData(), HELP_SCREEN_WIDTH, HELP_SCREEN_HEIGHT, HELP_SCREEN_WIDTH, windowBuffer, HELP_SCREEN_WIDTH);
windowUnhide(win);
colorPaletteLoad("art\\intrface\\helpscrn.pal");
paletteSetEntries(_cmap);
// CE: Fill overlay with darkest color in the palette. It might
// not be completely black, but at least it's uniform.
bufferFill(windowGetBuffer(overlay),
screenGetWidth(),
screenGetHeight(),
screenGetWidth(),
intensityColorTable[_colorTable[0]][0]);
windowShow(overlay);
windowShow(win);
while (inputGetInput() == -1 && _game_user_wants_to_quit == 0) {
sharedFpsLimiter.mark();
renderPresent();
sharedFpsLimiter.throttle();
while (_get_input() == -1 && _game_user_wants_to_quit == 0) {
}
while (mouseGetEvent() != 0) {
sharedFpsLimiter.mark();
inputGetInput();
renderPresent();
sharedFpsLimiter.throttle();
_get_input();
}
paletteSetEntries(gPaletteBlack);
}
}
windowDestroy(overlay);
windowDestroy(win);
colorPaletteLoad("color.pal");
paletteSetEntries(_cmap);
@@ -1295,7 +1207,7 @@ int showQuitConfirmationDialog()
MessageListItem messageListItem;
messageListItem.num = 0;
if (messageListGetItem(&gMiscMessageList, &messageListItem)) {
rc = showDialogBox(messageListItem.text, nullptr, 0, 169, 117, _colorTable[32328], nullptr, _colorTable[32328], DIALOG_BOX_YES_NO);
rc = showDialogBox(messageListItem.text, 0, 0, 169, 117, _colorTable[32328], NULL, _colorTable[32328], DIALOG_BOX_YES_NO);
if (rc != 0) {
_game_user_wants_to_quit = 2;
}
@@ -1323,64 +1235,62 @@ int showQuitConfirmationDialog()
// 0x44418C
static int gameDbInit()
{
const char* main_file_name;
const char* patch_file_name;
int hashing;
char* main_file_name;
char* patch_file_name;
int patch_index;
char filename[COMPAT_MAX_PATH];
main_file_name = nullptr;
patch_file_name = nullptr;
hashing = 0;
main_file_name = NULL;
patch_file_name = NULL;
main_file_name = settings.system.master_dat_path.c_str();
if (configGetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_HASHING_KEY, &hashing)) {
_db_enable_hash_table_();
}
configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_MASTER_DAT_KEY, &main_file_name);
if (*main_file_name == '\0') {
main_file_name = nullptr;
main_file_name = NULL;
}
patch_file_name = settings.system.master_patches_path.c_str();
configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_MASTER_PATCHES_KEY, &patch_file_name);
if (*patch_file_name == '\0') {
patch_file_name = nullptr;
patch_file_name = NULL;
}
int master_db_handle = dbOpen(main_file_name, 0, patch_file_name, 1);
if (master_db_handle == -1) {
_master_db_handle = dbOpen(main_file_name, 0, patch_file_name, 1);
if (_master_db_handle == -1) {
showMesageBox("Could not find the master datafile. Please make sure the FALLOUT CD is in the drive and that you are running FALLOUT from the directory you installed it to.");
return -1;
}
main_file_name = settings.system.critter_dat_path.c_str();
configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CRITTER_DAT_KEY, &main_file_name);
if (*main_file_name == '\0') {
main_file_name = nullptr;
main_file_name = NULL;
}
patch_file_name = settings.system.critter_patches_path.c_str();
configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CRITTER_PATCHES_KEY, &patch_file_name);
if (*patch_file_name == '\0') {
patch_file_name = nullptr;
patch_file_name = NULL;
}
int critter_db_handle = dbOpen(main_file_name, 0, patch_file_name, 1);
if (critter_db_handle == -1) {
_critter_db_handle = dbOpen(main_file_name, 0, patch_file_name, 1);
if (_critter_db_handle == -1) {
_db_select(_master_db_handle);
showMesageBox("Could not find the critter datafile. Please make sure the FALLOUT CD is in the drive and that you are running FALLOUT from the directory you installed it to.");
return -1;
}
// SFALL: custom patch file name.
char* path_file_name_template = nullptr;
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_PATCH_FILE, &path_file_name_template);
if (path_file_name_template == nullptr || *path_file_name_template == '\0') {
path_file_name_template = "patch%03d.dat";
}
for (patch_index = 0; patch_index < 1000; patch_index++) {
snprintf(filename, sizeof(filename), path_file_name_template, patch_index);
sprintf(filename, "patch%03d.dat", patch_index);
if (compat_access(filename, 0) == 0) {
dbOpen(filename, 0, nullptr, 1);
if (access(filename, 0) == 0) {
dbOpen(filename, 0, NULL, 1);
}
}
if (compat_access("f2_res.dat", 0) == 0) {
dbOpen("f2_res.dat", 0, nullptr, 1);
}
_db_select(_master_db_handle);
return 0;
}
@@ -1388,22 +1298,23 @@ static int gameDbInit()
// 0x444384
static void showSplash()
{
int splash = settings.system.splash;
int splash;
configGetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_SPLASH_KEY, &splash);
char path[64];
const char* language = settings.system.language.c_str();
if (compat_stricmp(language, ENGLISH) != 0) {
snprintf(path, sizeof(path), "art\\%s\\splash\\", language);
char* language;
if (configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_LANGUAGE_KEY, &language) && compat_stricmp(language, ENGLISH) != 0) {
sprintf(path, "art\\%s\\splash\\", language);
} else {
snprintf(path, sizeof(path), "art\\splash\\");
sprintf(path, "art\\splash\\");
}
File* stream;
for (int index = 0; index < SPLASH_COUNT; index++) {
char filePath[64];
snprintf(filePath, sizeof(filePath), "%ssplash%d.rix", path, splash);
sprintf(filePath, "%ssplash%d.rix", path, splash);
stream = fileOpen(filePath, "rb");
if (stream != nullptr) {
if (stream != NULL) {
break;
}
@@ -1414,31 +1325,18 @@ static void showSplash()
}
}
if (stream == nullptr) {
if (stream == NULL) {
return;
}
unsigned char* palette = reinterpret_cast<unsigned char*>(internal_malloc(768));
if (palette == nullptr) {
unsigned char* palette = (unsigned char*)internal_malloc(768);
if (palette == NULL) {
fileClose(stream);
return;
}
int version;
fileReadInt32(stream, &version);
if (version != 'RIX3') {
fileClose(stream);
return;
}
short width;
fileRead(&width, sizeof(width), 1, stream);
short height;
fileRead(&height, sizeof(height), 1, stream);
unsigned char* data = reinterpret_cast<unsigned char*>(internal_malloc(width * height));
if (data == nullptr) {
unsigned char* data = (unsigned char*)internal_malloc(SPLASH_WIDTH * SPLASH_HEIGHT);
if (data == NULL) {
internal_free(palette);
fileClose(stream);
return;
@@ -1447,63 +1345,18 @@ static void showSplash()
paletteSetEntries(gPaletteBlack);
fileSeek(stream, 10, SEEK_SET);
fileRead(palette, 1, 768, stream);
fileRead(data, 1, width * height, stream);
fileRead(data, 1, SPLASH_WIDTH * SPLASH_HEIGHT, stream);
fileClose(stream);
int size = 0;
// TODO: Move to settings.
Config config;
if (configInit(&config)) {
if (configRead(&config, "f2_res.ini", false)) {
configGetInt(&config, "STATIC_SCREENS", "SPLASH_SCRN_SIZE", &size);
}
configFree(&config);
}
int screenWidth = screenGetWidth();
int screenHeight = screenGetHeight();
if (size != 0 || screenWidth < width || screenHeight < height) {
int scaledWidth;
int scaledHeight;
if (size == 2) {
scaledWidth = screenWidth;
scaledHeight = screenHeight;
} else {
if (screenHeight * width >= screenWidth * height) {
scaledWidth = screenWidth;
scaledHeight = screenWidth * height / width;
} else {
scaledWidth = screenHeight * width / height;
scaledHeight = screenHeight;
}
}
unsigned char* scaled = reinterpret_cast<unsigned char*>(internal_malloc(scaledWidth * scaledHeight));
if (scaled != nullptr) {
blitBufferToBufferStretch(data, width, height, width, scaled, scaledWidth, scaledHeight, scaledWidth);
int x = screenWidth > scaledWidth ? (screenWidth - scaledWidth) / 2 : 0;
int y = screenHeight > scaledHeight ? (screenHeight - scaledHeight) / 2 : 0;
_scr_blit(scaled, scaledWidth, scaledHeight, 0, 0, scaledWidth, scaledHeight, x, y);
paletteFadeTo(palette);
internal_free(scaled);
}
} else {
int x = (screenWidth - width) / 2;
int y = (screenHeight - height) / 2;
_scr_blit(data, width, height, 0, 0, width, height, x, y);
paletteFadeTo(palette);
}
int splashWindowX = (screenGetWidth() - SPLASH_WIDTH) / 2;
int splashWindowY = (screenGetHeight() - SPLASH_HEIGHT) / 2;
_scr_blit(data, SPLASH_WIDTH, SPLASH_HEIGHT, 0, 0, SPLASH_WIDTH, SPLASH_HEIGHT, splashWindowX, splashWindowY);
paletteFadeTo(palette);
internal_free(data);
internal_free(palette);
settings.system.splash = splash + 1;
configSetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_SPLASH_KEY, splash + 1);
}
int gameShowDeathDialog(const char* message)
@@ -1532,7 +1385,7 @@ int gameShowDeathDialog(const char* message)
int oldUserWantsToQuit = _game_user_wants_to_quit;
_game_user_wants_to_quit = 0;
int rc = showDialogBox(message, nullptr, 0, 169, 117, _colorTable[32328], nullptr, _colorTable[32328], DIALOG_BOX_LARGE);
int rc = showDialogBox(message, 0, 0, 169, 117, _colorTable[32328], NULL, _colorTable[32328], DIALOG_BOX_LARGE);
_game_user_wants_to_quit = oldUserWantsToQuit;
@@ -1553,54 +1406,4 @@ int gameShowDeathDialog(const char* message)
return rc;
}
void* gameGetGlobalPointer(int var)
{
if (var < 0 || var >= gGameGlobalVarsLength) {
debugPrint("ERROR: attempt to reference global pointer out of range: %d", var);
return nullptr;
}
return gGameGlobalPointers[var];
}
int gameSetGlobalPointer(int var, void* value)
{
if (var < 0 || var >= gGameGlobalVarsLength) {
debugPrint("ERROR: attempt to reference global var out of range: %d", var);
return -1;
}
gGameGlobalPointers[var] = value;
return 0;
}
int GameMode::currentGameMode = 0;
void GameMode::enterGameMode(int gameMode)
{
currentGameMode |= gameMode;
}
void GameMode::exitGameMode(int gameMode)
{
currentGameMode &= ~gameMode;
}
bool GameMode::isInGameMode(int gameMode)
{
return (currentGameMode & gameMode) != 0;
}
ScopedGameMode::ScopedGameMode(int gameMode)
{
this->gameMode = gameMode;
GameMode::enterGameMode(gameMode);
}
ScopedGameMode::~ScopedGameMode()
{
GameMode::exitGameMode(gameMode);
}
} // namespace fallout

View File

@@ -21,6 +21,8 @@ extern const char* asc_5186C8;
extern int _game_user_wants_to_quit;
extern MessageList gMiscMessageList;
extern int _master_db_handle;
extern int _critter_db_handle;
int gameInitWithOptions(const char* windowTitle, bool isMapper, int a3, int a4, int argc, char** argv);
void gameReset();
@@ -32,58 +34,12 @@ bool gameUiIsDisabled();
int gameGetGlobalVar(int var);
int gameSetGlobalVar(int var, int value);
int globalVarsRead(const char* path, const char* section, int* variablesListLengthPtr, int** variablesListPtr);
int gameGetState();
int gameRequestState(int newGameState);
void gameUpdateState();
int _game_state();
int _game_state_request(int a1);
void _game_state_update();
int showQuitConfirmationDialog();
int gameShowDeathDialog(const char* message);
void* gameGetGlobalPointer(int var);
int gameSetGlobalPointer(int var, void* value);
class GameMode {
public:
enum Flags {
kWorldmap = 0x1,
kDialog = 0x4,
kOptions = 0x8,
kSaveGame = 0x10,
kLoadGame = 0x20,
kCombat = 0x40,
kPreferences = 0x80,
kHelp = 0x100,
kEditor = 0x200,
kPipboy = 0x400,
kPlayerTurn = 0x800,
kInventory = 0x1000,
kAutomap = 0x2000,
kSkilldex = 0x4000,
kUseOn = 0x8000,
kLoot = 0x10000,
kBarter = 0x20000,
kHero = 0x40000,
kDialogReview = 0x80000,
kCounter = 0x100000,
kSpecial = 0x80000000,
};
static void enterGameMode(int gameMode);
static void exitGameMode(int gameMode);
static bool isInGameMode(int gameMode);
static int getCurrentGameMode() { return currentGameMode; }
private:
static int currentGameMode;
};
class ScopedGameMode {
public:
ScopedGameMode(int gameMode);
~ScopedGameMode();
private:
int gameMode;
};
} // namespace fallout

View File

@@ -1,17 +1,13 @@
#include "game_config.h"
#include "sfall_config.h"
#include <stdio.h>
#include <string.h>
#include "db.h"
#include "main.h"
#include "platform_compat.h"
namespace fallout {
static void gameConfigResolvePath(const char* section, const char* key);
// A flag indicating if [gGameConfig] was initialized.
//
// 0x5186D0
@@ -124,55 +120,15 @@ bool gameConfigInit(bool isMapper, int argc, char** argv)
configSetInt(&gGameConfig, GAME_CONFIG_MAPPER_KEY, GAME_CONFIG_SORT_SCRIPT_LIST_KEY, 0);
}
// CE: Detect alternative default music directory.
char alternativeMusicPath[COMPAT_MAX_PATH];
strcpy(alternativeMusicPath, "data\\sound\\music\\*.acm");
compat_windows_path_to_native(alternativeMusicPath);
compat_resolve_path(alternativeMusicPath);
char** acms;
int acmsLength = fileNameListInit(alternativeMusicPath, &acms, 0, 0);
if (acmsLength != -1) {
if (acmsLength > 0) {
configSetString(&gGameConfig, GAME_CONFIG_SOUND_KEY, GAME_CONFIG_MUSIC_PATH1_KEY, "data\\sound\\music\\");
configSetString(&gGameConfig, GAME_CONFIG_SOUND_KEY, GAME_CONFIG_MUSIC_PATH2_KEY, "data\\sound\\music\\");
}
fileNameListFree(&acms, 0);
}
// SFALL: Custom config file name.
char* customConfigFileName = nullptr;
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_CONFIG_FILE, &customConfigFileName);
const char* configFileName = customConfigFileName != nullptr && *customConfigFileName != '\0'
? customConfigFileName
: DEFAULT_GAME_CONFIG_FILE_NAME;
// Make `fallout2.cfg` file path.
char* executable = argv[0];
char* ch = strrchr(executable, '\\');
if (ch != nullptr) {
if (ch != NULL) {
*ch = '\0';
if (isMapper) {
snprintf(gGameConfigFilePath,
sizeof(gGameConfigFilePath),
"%s\\%s",
executable,
MAPPER_CONFIG_FILE_NAME);
} else {
snprintf(gGameConfigFilePath,
sizeof(gGameConfigFilePath),
"%s\\%s",
executable,
configFileName);
}
sprintf(gGameConfigFilePath, "%s\\%s", executable, GAME_CONFIG_FILE_NAME);
*ch = '\\';
} else {
if (isMapper) {
strcpy(gGameConfigFilePath, MAPPER_CONFIG_FILE_NAME);
} else {
strcpy(gGameConfigFilePath, configFileName);
}
strcpy(gGameConfigFilePath, GAME_CONFIG_FILE_NAME);
}
// Read contents of `fallout2.cfg` into config. The values from the file
@@ -183,15 +139,6 @@ bool gameConfigInit(bool isMapper, int argc, char** argv)
// whatever was loaded from `fallout2.cfg`.
configParseCommandLineArguments(&gGameConfig, argc, argv);
// CE: Normalize and resolve asset bundle paths.
gameConfigResolvePath(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_MASTER_DAT_KEY);
gameConfigResolvePath(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_MASTER_PATCHES_KEY);
gameConfigResolvePath(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CRITTER_DAT_KEY);
gameConfigResolvePath(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CRITTER_PATCHES_KEY);
gameConfigResolvePath(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CRITTER_PATCHES_KEY);
gameConfigResolvePath(GAME_CONFIG_SOUND_KEY, GAME_CONFIG_MUSIC_PATH1_KEY);
gameConfigResolvePath(GAME_CONFIG_SOUND_KEY, GAME_CONFIG_MUSIC_PATH2_KEY);
gGameConfigInitialized = true;
return true;
@@ -237,12 +184,4 @@ bool gameConfigExit(bool shouldSave)
return result;
}
static void gameConfigResolvePath(const char* section, const char* key)
{
char* path;
configGetString(&gGameConfig, section, key, &path);
compat_windows_path_to_native(path);
compat_resolve_path(path);
}
} // namespace fallout

View File

@@ -5,8 +5,8 @@
namespace fallout {
#define DEFAULT_GAME_CONFIG_FILE_NAME "fallout2.cfg"
#define MAPPER_CONFIG_FILE_NAME "mapper2.cfg"
// The file name of the main config file.
#define GAME_CONFIG_FILE_NAME "fallout2.cfg"
#define GAME_CONFIG_SYSTEM_KEY "system"
#define GAME_CONFIG_PREFERENCES_KEY "preferences"

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,7 @@ int gameDialogInit();
int gameDialogReset();
int gameDialogExit();
bool _gdialogActive();
void gameDialogEnter(Object* speaker, int a2);
void gameDialogEnter(Object* a1, int a2);
void _gdialogSystemEnter();
void gameDialogStartLips(const char* a1);
int gameDialogEnable();

View File

@@ -16,6 +16,7 @@ static void gameMemoryFree(void* ptr);
int gameMemoryInit()
{
dictionarySetMemoryProcs(internal_malloc, internal_realloc, internal_free);
_db_register_mem(internal_malloc, internal_strdup, internal_free);
memoryManagerSetProcs(gameMemoryMalloc, gameMemoryRealloc, gameMemoryFree);
return 0;

View File

@@ -4,30 +4,25 @@
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include "actions.h"
#include "animation.h"
#include "art.h"
#include "color.h"
#include "combat.h"
#include "core.h"
#include "critter.h"
#include "draw.h"
#include "game.h"
#include "game_config.h"
#include "game_sound.h"
#include "input.h"
#include "interface.h"
#include "item.h"
#include "kb.h"
#include "mouse.h"
#include "object.h"
#include "proto.h"
#include "proto_instance.h"
#include "settings.h"
#include "sfall_config.h"
#include "skill.h"
#include "skilldex.h"
#include "svga.h"
#include "text_font.h"
#include "tile.h"
#include "window_manager.h"
@@ -104,7 +99,7 @@ static unsigned int _gmouse_3d_last_move_time = 0;
// actmenu.frm
// 0x518C8C
static Art* gGameMouseActionMenuFrm = nullptr;
static Art* gGameMouseActionMenuFrm = NULL;
// 0x518C90
static CacheEntry* gGameMouseActionMenuFrmHandle = INVALID_CACHE_ENTRY;
@@ -125,11 +120,11 @@ static int _gmouse_3d_menu_frame_hot_x = 0;
static int _gmouse_3d_menu_frame_hot_y = 0;
// 0x518CA8
static unsigned char* gGameMouseActionMenuFrmData = nullptr;
static unsigned char* gGameMouseActionMenuFrmData = NULL;
// actpick.frm
// 0x518CAC
static Art* gGameMouseActionPickFrm = nullptr;
static Art* gGameMouseActionPickFrm = NULL;
// 0x518CB0
static CacheEntry* gGameMouseActionPickFrmHandle = INVALID_CACHE_ENTRY;
@@ -150,11 +145,11 @@ static int _gmouse_3d_pick_frame_hot_x = 0;
static int _gmouse_3d_pick_frame_hot_y = 0;
// 0x518CC8
static unsigned char* gGameMouseActionPickFrmData = nullptr;
static unsigned char* gGameMouseActionPickFrmData = NULL;
// acttohit.frm
// 0x518CCC
static Art* gGameMouseActionHitFrm = nullptr;
static Art* gGameMouseActionHitFrm = NULL;
// 0x518CD0
static CacheEntry* gGameMouseActionHitFrmHandle = INVALID_CACHE_ENTRY;
@@ -169,11 +164,11 @@ static int gGameMouseActionHitFrmHeight = 0;
static int gGameMouseActionHitFrmDataSize = 0;
// 0x518CE0
static unsigned char* gGameMouseActionHitFrmData = nullptr;
static unsigned char* gGameMouseActionHitFrmData = NULL;
// blank.frm
// 0x518CE4
static Art* gGameMouseBouncingCursorFrm = nullptr;
static Art* gGameMouseBouncingCursorFrm = NULL;
// 0x518CE8
static CacheEntry* gGameMouseBouncingCursorFrmHandle = INVALID_CACHE_ENTRY;
@@ -188,11 +183,11 @@ static int gGameMouseBouncingCursorFrmHeight = 0;
static int gGameMouseBouncingCursorFrmDataSize = 0;
// 0x518CF8
static unsigned char* gGameMouseBouncingCursorFrmData = nullptr;
static unsigned char* gGameMouseBouncingCursorFrmData = NULL;
// msef000.frm
// 0x518CFC
static Art* gGameMouseHexCursorFrm = nullptr;
static Art* gGameMouseHexCursorFrm = NULL;
// 0x518D00
static CacheEntry* gGameMouseHexCursorFrmHandle = INVALID_CACHE_ENTRY;
@@ -207,13 +202,13 @@ static int gGameMouseHexCursorHeight = 0;
static int gGameMouseHexCursorDataSize = 0;
// 0x518D10
static unsigned char* gGameMouseHexCursorFrmData = nullptr;
static unsigned char* gGameMouseHexCursorFrmData = NULL;
// 0x518D14
static unsigned char gGameMouseActionMenuItemsLength = 0;
// 0x518D18
static unsigned char* _gmouse_3d_menu_actions_start = nullptr;
static unsigned char* _gmouse_3d_menu_actions_start = NULL;
// 0x518D1C
static unsigned char gGameMouseActionMenuHighlightedItemIndex = 0;
@@ -277,7 +272,7 @@ static int _gmouse_bk_last_cursor = -1;
static bool gGameMouseItemHighlightEnabled = true;
// 0x518D94
static Object* gGameMouseHighlightedItem = nullptr;
static Object* gGameMouseHighlightedItem = NULL;
// 0x518D98
bool _gmouse_clicked_on_edge = false;
@@ -380,7 +375,7 @@ void gameMouseExit()
mouseHideCursor();
mouseSetFrame(nullptr, 0, 0, 0, 0, 0, 0);
mouseSetFrame(NULL, 0, 0, 0, 0, 0, 0);
// NOTE: Uninline.
gameMouseObjectsFree();
@@ -669,7 +664,7 @@ void gameMouseRefresh()
_gmouse_3d_hover_test = true;
Object* pointedObject = gameMouseGetObjectUnderCursor(-1, true, gElevation);
if (pointedObject != nullptr) {
if (pointedObject != NULL) {
int primaryAction = -1;
switch (FID_TYPE(pointedObject->fid)) {
@@ -694,7 +689,7 @@ void gameMouseRefresh()
primaryAction = GAME_MOUSE_ACTION_MENU_ITEM_TALK;
}
} else {
if (_critter_flag_check(pointedObject->pid, CRITTER_NO_STEAL)) {
if (_critter_flag_check(pointedObject->pid, CRITTER_FLAG_0x20)) {
primaryAction = GAME_MOUSE_ACTION_MENU_ITEM_LOOK;
} else {
primaryAction = GAME_MOUSE_ACTION_MENU_ITEM_USE;
@@ -732,17 +727,19 @@ void gameMouseRefresh()
}
} else if (gGameMouseMode == GAME_MOUSE_MODE_CROSSHAIR) {
Object* pointedObject = gameMouseGetObjectUnderCursor(OBJ_TYPE_CRITTER, false, gElevation);
if (pointedObject == nullptr) {
if (pointedObject == NULL) {
pointedObject = gameMouseGetObjectUnderCursor(-1, false, gElevation);
if (!objectIsDoor(pointedObject)) {
pointedObject = nullptr;
pointedObject = NULL;
}
}
if (pointedObject != nullptr) {
if (pointedObject != NULL) {
bool pointedObjectIsCritter = FID_TYPE(pointedObject->fid) == OBJ_TYPE_CRITTER;
if (settings.preferences.combat_looks) {
int combatLooks = 0;
configGetInt(&gGameConfig, GAME_CONFIG_PREFERENCES_KEY, GAME_CONFIG_COMBAT_LOOKS_KEY, &combatLooks);
if (combatLooks != 0) {
if (_obj_examine(gDude, pointedObject) == -1) {
_obj_look_at(gDude, pointedObject);
}
@@ -752,7 +749,7 @@ void gameMouseRefresh()
int accuracy;
char formattedAccuracy[8];
if (_combat_to_hit(pointedObject, &accuracy)) {
snprintf(formattedAccuracy, sizeof(formattedAccuracy), "%d%%", accuracy);
sprintf(formattedAccuracy, "%d%%", accuracy);
if (pointedObjectIsCritter) {
if (pointedObject->data.critter.combat.team != 0) {
@@ -764,7 +761,7 @@ void gameMouseRefresh()
color = _colorTable[17969];
}
} else {
snprintf(formattedAccuracy, sizeof(formattedAccuracy), " %c ", 'X');
sprintf(formattedAccuracy, " %c ", 'X');
if (pointedObjectIsCritter) {
if (pointedObject->data.critter.combat.team != 0) {
@@ -804,25 +801,30 @@ void gameMouseRefresh()
char formattedActionPoints[8];
int color;
int distance = _make_path(gDude, gDude->tile, gGameMouseHexCursor->tile, nullptr, 1);
if (distance != 0) {
int v6 = _make_path(gDude, gDude->tile, gGameMouseHexCursor->tile, NULL, 1);
if (v6) {
if (!isInCombat()) {
formattedActionPoints[0] = '\0';
color = _colorTable[31744];
} else {
int actionPointsMax = critterGetMovementPointCostAdjustedForCrippledLegs(gDude, distance);
int actionPointsRequired = std::max(0, actionPointsMax - _combat_free_move);
int v7 = critterGetMovementPointCostAdjustedForCrippledLegs(gDude, v6);
int v8;
if (v7 - _combat_free_move >= 0) {
v8 = v7 - _combat_free_move;
} else {
v8 = 0;
}
if (actionPointsRequired <= gDude->data.critter.combat.ap) {
snprintf(formattedActionPoints, sizeof(formattedActionPoints), "%d", actionPointsRequired);
if (v8 <= gDude->data.critter.combat.ap) {
sprintf(formattedActionPoints, "%d", v8);
color = _colorTable[32767];
} else {
snprintf(formattedActionPoints, sizeof(formattedActionPoints), "%c", 'X');
sprintf(formattedActionPoints, "%c", 'X');
color = _colorTable[31744];
}
}
} else {
snprintf(formattedActionPoints, sizeof(formattedActionPoints), "%c", 'X');
sprintf(formattedActionPoints, "%c", 'X');
color = _colorTable[31744];
}
@@ -856,11 +858,11 @@ void gameMouseRefresh()
v34 |= 1;
}
if (gGameMouseHighlightedItem != nullptr) {
if (gGameMouseHighlightedItem != NULL) {
if (objectClearOutline(gGameMouseHighlightedItem, &r26) == 0) {
v34 |= 2;
}
gGameMouseHighlightedItem = nullptr;
gGameMouseHighlightedItem = NULL;
}
switch (v34) {
@@ -933,13 +935,16 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState)
actionPoints = -1;
}
bool running;
configGetBool(&gGameConfig, GAME_CONFIG_PREFERENCES_KEY, GAME_CONFIG_RUNNING_KEY, &running);
if (gPressedPhysicalKeys[SDL_SCANCODE_LSHIFT] || gPressedPhysicalKeys[SDL_SCANCODE_RSHIFT]) {
if (settings.preferences.running) {
if (running) {
_dude_move(actionPoints);
return;
}
} else {
if (!settings.preferences.running) {
if (!running) {
_dude_move(actionPoints);
return;
}
@@ -951,7 +956,7 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState)
if (gGameMouseMode == GAME_MOUSE_MODE_ARROW) {
Object* v5 = gameMouseGetObjectUnderCursor(-1, true, gElevation);
if (v5 != nullptr) {
if (v5 != NULL) {
switch (FID_TYPE(v5->fid)) {
case OBJ_TYPE_ITEM:
actionPickUp(gDude, v5);
@@ -999,26 +1004,26 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState)
if (gGameMouseMode == GAME_MOUSE_MODE_CROSSHAIR) {
Object* v7 = gameMouseGetObjectUnderCursor(OBJ_TYPE_CRITTER, false, gElevation);
if (v7 == nullptr) {
if (v7 == NULL) {
v7 = gameMouseGetObjectUnderCursor(-1, false, gElevation);
if (!objectIsDoor(v7)) {
v7 = nullptr;
v7 = NULL;
}
}
if (v7 != nullptr) {
if (v7 != NULL) {
_combat_attack_this(v7);
_gmouse_3d_hover_test = true;
gGameMouseLastY = mouseY;
gGameMouseLastX = mouseX;
_gmouse_3d_last_move_time = getTicks() - 250;
_gmouse_3d_last_move_time = _get_time() - 250;
}
return;
}
if (gGameMouseMode == GAME_MOUSE_MODE_USE_CROSSHAIR) {
Object* object = gameMouseGetObjectUnderCursor(-1, true, gElevation);
if (object != nullptr) {
if (object != NULL) {
Object* weapon;
if (interfaceGetActiveItem(&weapon) != -1) {
if (isInCombat()) {
@@ -1056,7 +1061,7 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState)
|| gGameMouseMode == GAME_MOUSE_MODE_USE_SCIENCE
|| gGameMouseMode == GAME_MOUSE_MODE_USE_REPAIR) {
Object* object = gameMouseGetObjectUnderCursor(-1, 1, gElevation);
if (object == nullptr || actionUseSkill(gDude, object, gGameMouseModeSkills[gGameMouseMode - FIRST_GAME_MOUSE_MODE_SKILL]) != -1) {
if (object == NULL || actionUseSkill(gDude, object, gGameMouseModeSkills[gGameMouseMode - FIRST_GAME_MOUSE_MODE_SKILL]) != -1) {
gameMouseSetCursor(MOUSE_CURSOR_NONE);
gameMouseSetMode(GAME_MOUSE_MODE_MOVE);
}
@@ -1066,7 +1071,7 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState)
if ((mouseState & MOUSE_EVENT_LEFT_BUTTON_DOWN_REPEAT) == MOUSE_EVENT_LEFT_BUTTON_DOWN_REPEAT && gGameMouseMode == GAME_MOUSE_MODE_ARROW) {
Object* v16 = gameMouseGetObjectUnderCursor(-1, true, gElevation);
if (v16 != nullptr) {
if (v16 != NULL) {
int actionMenuItemsCount = 0;
int actionMenuItems[6];
switch (FID_TYPE(v16->fid)) {
@@ -1088,7 +1093,7 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState)
actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_TALK;
}
} else {
if (!_critter_flag_check(v16->pid, CRITTER_NO_STEAL)) {
if (!_critter_flag_check(v16->pid, CRITTER_FLAG_0x20)) {
actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_USE;
}
}
@@ -1133,9 +1138,7 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState)
int v33 = mouseY;
int actionIndex = 0;
while ((mouseGetEvent() & MOUSE_EVENT_LEFT_BUTTON_UP) == 0) {
sharedFpsLimiter.mark();
inputGetInput();
_get_input();
if (_game_user_wants_to_quit != 0) {
actionMenuItems[actionIndex] = 0;
@@ -1157,9 +1160,6 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState)
}
v33 = v47;
}
renderPresent();
sharedFpsLimiter.throttle();
}
isoEnable();
@@ -1167,7 +1167,7 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState)
_gmouse_3d_hover_test = false;
gGameMouseLastX = mouseX;
gGameMouseLastY = mouseY;
_gmouse_3d_last_move_time = getTicks();
_gmouse_3d_last_move_time = _get_time();
_mouse_set_position(mouseX, v33);
@@ -1266,14 +1266,14 @@ int gameMouseSetCursor(int cursor)
CacheEntry* mouseCursorFrmHandle;
int fid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseCursorFrmIds[cursor], 0, 0, 0);
Art* mouseCursorFrm = artLock(fid, &mouseCursorFrmHandle);
if (mouseCursorFrm == nullptr) {
if (mouseCursorFrm == NULL) {
return -1;
}
bool shouldUpdate = true;
int frame = 0;
if (cursor >= FIRST_GAME_MOUSE_ANIMATED_CURSOR) {
unsigned int tick = getTicks();
unsigned int tick = _get_time();
if ((gGameMouseHexCursor->flags & OBJECT_HIDDEN) == 0) {
gameMouseObjectsHide();
@@ -1328,12 +1328,6 @@ int gameMouseGetCursor()
return gGameMouseCursor;
}
// 0x44C9F0
void gmouse_set_mapper_mode(int mode)
{
_gmouse_mapper_mode = mode;
}
// 0x44C9F8
void _gmouse_3d_enable_modes()
{
@@ -1398,7 +1392,7 @@ void gameMouseSetMode(int mode)
gGameMouseMode = mode;
_gmouse_3d_hover_test = false;
_gmouse_3d_last_move_time = getTicks();
_gmouse_3d_last_move_time = _get_time();
tileWindowRefreshRect(&rect, gElevation);
@@ -1426,7 +1420,7 @@ void gameMouseCycleMode()
if (isInCombat()) {
Object* item;
if (interfaceGetActiveItem(&item) == 0) {
if (item != nullptr && itemGetType(item) != ITEM_TYPE_WEAPON && mode == GAME_MOUSE_MODE_CROSSHAIR) {
if (item != NULL && itemGetType(item) != ITEM_TYPE_WEAPON && mode == GAME_MOUSE_MODE_CROSSHAIR) {
mode = GAME_MOUSE_MODE_MOVE;
}
}
@@ -1465,7 +1459,7 @@ int gameMouseSetBouncingCursorFid(int fid)
}
if (!_gmouse_mapper_mode) {
return objectSetFid(gGameMouseBouncingCursor, fid, nullptr);
return objectSetFid(gGameMouseBouncingCursor, fid, NULL);
}
int v1 = 0;
@@ -1566,7 +1560,7 @@ void gameMouseObjectsShow()
}
_gmouse_3d_hover_test = false;
_gmouse_3d_last_move_time = getTicks() - 250;
_gmouse_3d_last_move_time = _get_time() - 250;
}
// 0x44CE34
@@ -1620,7 +1614,7 @@ Object* gameMouseGetObjectUnderCursor(int objectType, bool a2, int elevation)
}
}
Object* v4 = nullptr;
Object* v4 = NULL;
if (!v13) {
ObjectWithFlags* entries;
int count = _obj_create_intersect_list(mouseX, mouseY, elevation, objectType, &entries);
@@ -1651,14 +1645,14 @@ int gameMouseRenderPrimaryAction(int x, int y, int menuItem, int width, int heig
CacheEntry* menuItemFrmHandle;
int menuItemFid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseActionMenuItemFrmIds[menuItem], 0, 0, 0);
Art* menuItemFrm = artLock(menuItemFid, &menuItemFrmHandle);
if (menuItemFrm == nullptr) {
if (menuItemFrm == NULL) {
return -1;
}
CacheEntry* arrowFrmHandle;
int arrowFid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseModeFrmIds[GAME_MOUSE_MODE_ARROW], 0, 0, 0);
Art* arrowFrm = artLock(arrowFid, &arrowFrmHandle);
if (arrowFrm == nullptr) {
if (arrowFrm == NULL) {
artUnlock(menuItemFrmHandle);
// FIXME: Why this is success?
return 0;
@@ -1733,11 +1727,11 @@ int _gmouse_3d_pick_frame_hot(int* a1, int* a2)
// 0x44D214
int gameMouseRenderActionMenuItems(int x, int y, const int* menuItems, int menuItemsLength, int width, int height)
{
_gmouse_3d_menu_actions_start = nullptr;
_gmouse_3d_menu_actions_start = NULL;
gGameMouseActionMenuHighlightedItemIndex = 0;
gGameMouseActionMenuItemsLength = 0;
if (menuItems == nullptr) {
if (menuItems == NULL) {
return -1;
}
@@ -1757,7 +1751,7 @@ int gameMouseRenderActionMenuItems(int x, int y, const int* menuItems, int menuI
int fid = buildFid(OBJ_TYPE_INTERFACE, frmId, 0, 0, 0);
menuItemFrms[index] = artLock(fid, &(menuItemFrmHandles[index]));
if (menuItemFrms[index] == nullptr) {
if (menuItemFrms[index] == NULL) {
while (--index >= 0) {
artUnlock(menuItemFrmHandles[index]);
}
@@ -1768,7 +1762,7 @@ int gameMouseRenderActionMenuItems(int x, int y, const int* menuItems, int menuI
int fid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseModeFrmIds[GAME_MOUSE_MODE_ARROW], 0, 0, 0);
CacheEntry* arrowFrmHandle;
Art* arrowFrm = artLock(fid, &arrowFrmHandle);
if (arrowFrm == nullptr) {
if (arrowFrm == NULL) {
// FIXME: Unlock arts.
return -1;
}
@@ -1833,8 +1827,8 @@ int gameMouseRenderActionMenuItems(int x, int y, const int* menuItems, int menuI
gGameMouseActionMenuItemsLength = menuItemsLength;
_gmouse_3d_menu_actions_start = v58;
Sound* sound = soundEffectLoad("iaccuxx1", nullptr);
if (sound != nullptr) {
Sound* sound = soundEffectLoad("iaccuxx1", NULL);
if (sound != NULL) {
soundEffectPlay(sound);
}
@@ -1851,7 +1845,7 @@ int gameMouseHighlightActionMenuItemAtIndex(int menuItemIndex)
CacheEntry* handle;
int fid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseActionMenuItemFrmIds[gGameMouseActionMenuItems[gGameMouseActionMenuHighlightedItemIndex]], 0, 0, 0);
Art* art = artLock(fid, &handle);
if (art == nullptr) {
if (art == NULL) {
return -1;
}
@@ -1863,7 +1857,7 @@ int gameMouseHighlightActionMenuItemAtIndex(int menuItemIndex)
fid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseActionMenuItemFrmIds[gGameMouseActionMenuItems[menuItemIndex]] - 1, 0, 0, 0);
art = artLock(fid, &handle);
if (art == nullptr) {
if (art == NULL) {
return -1;
}
@@ -1882,7 +1876,7 @@ int gameMouseRenderAccuracy(const char* string, int color)
CacheEntry* crosshairFrmHandle;
int fid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseModeFrmIds[GAME_MOUSE_MODE_CROSSHAIR], 0, 0, 0);
Art* crosshairFrm = artLock(fid, &crosshairFrmHandle);
if (crosshairFrm == nullptr) {
if (crosshairFrm == NULL) {
return -1;
}
@@ -1948,7 +1942,10 @@ int gameMouseRenderActionPoints(const char* string, int color)
// 0x44D954
void gameMouseLoadItemHighlight()
{
gGameMouseItemHighlightEnabled = settings.preferences.item_highlight;
bool itemHighlight;
if (configGetBool(&gGameConfig, GAME_CONFIG_PREFERENCES_KEY, GAME_CONFIG_ITEM_HIGHLIGHT_KEY, &itemHighlight)) {
gGameMouseItemHighlightEnabled = itemHighlight;
}
}
// 0x44D984
@@ -1970,7 +1967,7 @@ int gameMouseObjectsInit()
return -1;
}
if (objectSetOutline(gGameMouseHexCursor, OUTLINE_PALETTED | OUTLINE_TYPE_2, nullptr) != 0) {
if (objectSetOutline(gGameMouseHexCursor, OUTLINE_PALETTED | OUTLINE_TYPE_2, NULL) != 0) {
return -1;
}
@@ -1979,18 +1976,18 @@ int gameMouseObjectsInit()
}
gGameMouseBouncingCursor->flags |= OBJECT_LIGHT_THRU;
gGameMouseBouncingCursor->flags |= OBJECT_NO_SAVE;
gGameMouseBouncingCursor->flags |= OBJECT_NO_REMOVE;
gGameMouseBouncingCursor->flags |= OBJECT_TEMPORARY;
gGameMouseBouncingCursor->flags |= OBJECT_FLAG_0x400;
gGameMouseBouncingCursor->flags |= OBJECT_SHOOT_THRU;
gGameMouseBouncingCursor->flags |= OBJECT_NO_BLOCK;
gGameMouseHexCursor->flags |= OBJECT_NO_REMOVE;
gGameMouseHexCursor->flags |= OBJECT_NO_SAVE;
gGameMouseHexCursor->flags |= OBJECT_FLAG_0x400;
gGameMouseHexCursor->flags |= OBJECT_TEMPORARY;
gGameMouseHexCursor->flags |= OBJECT_LIGHT_THRU;
gGameMouseHexCursor->flags |= OBJECT_SHOOT_THRU;
gGameMouseHexCursor->flags |= OBJECT_NO_BLOCK;
_obj_toggle_flat(gGameMouseHexCursor, nullptr);
_obj_toggle_flat(gGameMouseHexCursor, NULL);
int x;
int y;
@@ -2027,7 +2024,7 @@ int gameMouseObjectsReset()
gGameMouseLastX = -1;
gGameMouseLastY = -1;
_gmouse_3d_hover_test = false;
_gmouse_3d_last_move_time = getTicks();
_gmouse_3d_last_move_time = _get_time();
gameMouseLoadItemHighlight();
return 0;
@@ -2041,11 +2038,11 @@ void gameMouseObjectsFree()
if (gGameMouseObjectsInitialized) {
gameMouseActionMenuFree();
gGameMouseBouncingCursor->flags &= ~OBJECT_NO_SAVE;
gGameMouseHexCursor->flags &= ~OBJECT_NO_SAVE;
gGameMouseBouncingCursor->flags &= ~OBJECT_TEMPORARY;
gGameMouseHexCursor->flags &= ~OBJECT_TEMPORARY;
objectDestroy(gGameMouseBouncingCursor, nullptr);
objectDestroy(gGameMouseHexCursor, nullptr);
objectDestroy(gGameMouseBouncingCursor, NULL);
objectDestroy(gGameMouseHexCursor, NULL);
gGameMouseObjectsInitialized = false;
}
@@ -2059,35 +2056,35 @@ int gameMouseActionMenuInit()
// actmenu.frm - action menu
fid = buildFid(OBJ_TYPE_INTERFACE, 283, 0, 0, 0);
gGameMouseActionMenuFrm = artLock(fid, &gGameMouseActionMenuFrmHandle);
if (gGameMouseActionMenuFrm == nullptr) {
if (gGameMouseActionMenuFrm == NULL) {
goto err;
}
// actpick.frm - action pick
fid = buildFid(OBJ_TYPE_INTERFACE, 282, 0, 0, 0);
gGameMouseActionPickFrm = artLock(fid, &gGameMouseActionPickFrmHandle);
if (gGameMouseActionPickFrm == nullptr) {
if (gGameMouseActionPickFrm == NULL) {
goto err;
}
// acttohit.frm - action to hit
fid = buildFid(OBJ_TYPE_INTERFACE, 284, 0, 0, 0);
gGameMouseActionHitFrm = artLock(fid, &gGameMouseActionHitFrmHandle);
if (gGameMouseActionHitFrm == nullptr) {
if (gGameMouseActionHitFrm == NULL) {
goto err;
}
// blank.frm - used be mset000.frm for top of bouncing mouse cursor
fid = buildFid(OBJ_TYPE_INTERFACE, 0, 0, 0, 0);
gGameMouseBouncingCursorFrm = artLock(fid, &gGameMouseBouncingCursorFrmHandle);
if (gGameMouseBouncingCursorFrm == nullptr) {
if (gGameMouseBouncingCursorFrm == NULL) {
goto err;
}
// msef000.frm - hex mouse cursor
fid = buildFid(OBJ_TYPE_INTERFACE, 1, 0, 0, 0);
gGameMouseHexCursorFrm = artLock(fid, &gGameMouseHexCursorFrmHandle);
if (gGameMouseHexCursorFrm == nullptr) {
if (gGameMouseHexCursorFrm == NULL) {
goto err;
}
@@ -2134,35 +2131,35 @@ void gameMouseActionMenuFree()
if (gGameMouseBouncingCursorFrmHandle != INVALID_CACHE_ENTRY) {
artUnlock(gGameMouseBouncingCursorFrmHandle);
}
gGameMouseBouncingCursorFrm = nullptr;
gGameMouseBouncingCursorFrm = NULL;
gGameMouseBouncingCursorFrmHandle = INVALID_CACHE_ENTRY;
if (gGameMouseHexCursorFrmHandle != INVALID_CACHE_ENTRY) {
artUnlock(gGameMouseHexCursorFrmHandle);
}
gGameMouseHexCursorFrm = nullptr;
gGameMouseHexCursorFrm = NULL;
gGameMouseHexCursorFrmHandle = INVALID_CACHE_ENTRY;
if (gGameMouseActionHitFrmHandle != INVALID_CACHE_ENTRY) {
artUnlock(gGameMouseActionHitFrmHandle);
}
gGameMouseActionHitFrm = nullptr;
gGameMouseActionHitFrm = NULL;
gGameMouseActionHitFrmHandle = INVALID_CACHE_ENTRY;
if (gGameMouseActionMenuFrmHandle != INVALID_CACHE_ENTRY) {
artUnlock(gGameMouseActionMenuFrmHandle);
}
gGameMouseActionMenuFrm = nullptr;
gGameMouseActionMenuFrm = NULL;
gGameMouseActionMenuFrmHandle = INVALID_CACHE_ENTRY;
if (gGameMouseActionPickFrmHandle != INVALID_CACHE_ENTRY) {
artUnlock(gGameMouseActionPickFrmHandle);
}
gGameMouseActionPickFrm = nullptr;
gGameMouseActionPickFrm = NULL;
gGameMouseActionPickFrmHandle = INVALID_CACHE_ENTRY;
gGameMouseActionPickFrmData = nullptr;
gGameMouseActionPickFrmData = NULL;
gGameMouseActionPickFrmWidth = 0;
gGameMouseActionPickFrmHeight = 0;
gGameMouseActionPickFrmDataSize = 0;
@@ -2201,7 +2198,7 @@ int _gmouse_3d_move_to(int x, int y, int elevation, Rect* a4)
int offsetY = 0;
CacheEntry* hexCursorFrmHandle;
Art* hexCursorFrm = artLock(gGameMouseHexCursor->fid, &hexCursorFrmHandle);
if (hexCursorFrm != nullptr) {
if (hexCursorFrm != NULL) {
artGetRotationOffsets(hexCursorFrm, 0, &offsetX, &offsetY);
int frameOffsetX;
@@ -2256,7 +2253,9 @@ int _gmouse_3d_move_to(int x, int y, int elevation, Rect* a4)
x1 = -8;
y1 = 13;
if (compat_stricmp(settings.system.executable.c_str(), "mapper") == 0) {
char* executable;
configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_EXECUTABLE_KEY, &executable);
if (compat_stricmp(executable, "mapper") == 0) {
if (tileRoofIsVisible()) {
if ((gDude->flags & OBJECT_HIDDEN) == 0) {
y1 = -83;
@@ -2290,7 +2289,7 @@ int _gmouse_3d_move_to(int x, int y, int elevation, Rect* a4)
int offsetY = 0;
CacheEntry* hexCursorFrmHandle;
Art* hexCursorFrm = artLock(gGameMouseHexCursor->fid, &hexCursorFrmHandle);
if (hexCursorFrm != nullptr) {
if (hexCursorFrm != NULL) {
artGetRotationOffsets(hexCursorFrm, 0, &offsetX, &offsetY);
int frameOffsetX;
@@ -2419,19 +2418,19 @@ int gameMouseHandleScrolling(int x, int y, int cursor)
// 0x44E544
void _gmouse_remove_item_outline(Object* object)
{
if (gGameMouseHighlightedItem != nullptr && gGameMouseHighlightedItem == object) {
if (gGameMouseHighlightedItem != NULL && gGameMouseHighlightedItem == object) {
Rect rect;
if (objectClearOutline(object, &rect) == 0) {
tileWindowRefreshRect(&rect, gElevation);
}
gGameMouseHighlightedItem = nullptr;
gGameMouseHighlightedItem = NULL;
}
}
// 0x44E580
int objectIsDoor(Object* object)
{
if (object == nullptr) {
if (object == NULL) {
return false;
}
@@ -2458,15 +2457,4 @@ static void customMouseModeFrmsInit()
configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_USE_REPAIR_FRM_KEY, &(gGameMouseModeFrmIds[GAME_MOUSE_MODE_USE_REPAIR]));
}
void gameMouseRefreshImmediately()
{
gameMouseRefresh();
renderPresent();
}
Object* gmouse_get_outlined_object()
{
return gGameMouseHighlightedItem;
}
} // namespace fallout

View File

@@ -86,7 +86,6 @@ void gameMouseRefresh();
void _gmouse_handle_event(int mouseX, int mouseY, int mouseState);
int gameMouseSetCursor(int cursor);
int gameMouseGetCursor();
void gmouse_set_mapper_mode(int mode);
void gameMouseSetMode(int a1);
int gameMouseGetMode();
void gameMouseCycleMode();
@@ -102,9 +101,6 @@ int gameMouseHighlightActionMenuItemAtIndex(int menuItemIndex);
void gameMouseLoadItemHighlight();
void _gmouse_remove_item_outline(Object* object);
void gameMouseRefreshImmediately();
Object* gmouse_get_outlined_object();
} // namespace fallout
#endif /* GAME_MOUSE_H */

View File

@@ -4,21 +4,18 @@
#include <string.h>
#include "color.h"
#include "core.h"
#include "cycle.h"
#include "debug.h"
#include "game.h"
#include "game_config.h"
#include "game_mouse.h"
#include "game_sound.h"
#include "input.h"
#include "mouse.h"
#include "movie.h"
#include "movie_effect.h"
#include "palette.h"
#include "platform_compat.h"
#include "settings.h"
#include "svga.h"
#include "text_font.h"
#include "touch.h"
#include "window_manager.h"
namespace fallout {
@@ -54,18 +51,18 @@ static const char* gMovieFileNames[MOVIE_COUNT] = {
// 0x518DE4
static const char* gMoviePaletteFilePaths[MOVIE_COUNT] = {
nullptr,
NULL,
"art\\cuts\\introsub.pal",
"art\\cuts\\eldersub.pal",
nullptr,
NULL,
"art\\cuts\\artmrsub.pal",
nullptr,
nullptr,
nullptr,
NULL,
NULL,
NULL,
"art\\cuts\\artmrsub.pal",
nullptr,
nullptr,
nullptr,
NULL,
NULL,
NULL,
"art\\cuts\\artmrsub.pal",
"art\\cuts\\artmrsub.pal",
"art\\cuts\\artmrsub.pal",
@@ -144,18 +141,24 @@ int gameMoviePlay(int movie, int flags)
const char* movieFileName = gMovieFileNames[movie];
debugPrint("\nPlaying movie: %s\n", movieFileName);
const char* language = settings.system.language.c_str();
char* language;
if (!configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_LANGUAGE_KEY, &language)) {
debugPrint("\ngmovie_play() - Error: Unable to determine language!\n");
gGameMovieIsPlaying = false;
return -1;
}
char movieFilePath[COMPAT_MAX_PATH];
int movieFileSize;
bool movieFound = false;
if (compat_stricmp(language, ENGLISH) != 0) {
snprintf(movieFilePath, sizeof(movieFilePath), "art\\%s\\cuts\\%s", language, gMovieFileNames[movie]);
sprintf(movieFilePath, "art\\%s\\cuts\\%s", language, gMovieFileNames[movie]);
movieFound = dbGetFileSize(movieFilePath, &movieFileSize) == 0;
}
if (!movieFound) {
snprintf(movieFilePath, sizeof(movieFilePath), "art\\cuts\\%s", gMovieFileNames[movie]);
sprintf(movieFilePath, "art\\cuts\\%s", gMovieFileNames[movie]);
movieFound = dbGetFileSize(movieFilePath, &movieFileSize) == 0;
}
@@ -177,7 +180,7 @@ int gameMoviePlay(int movie, int flags)
GAME_MOVIE_WINDOW_WIDTH,
GAME_MOVIE_WINDOW_HEIGHT,
0,
WINDOW_MODAL);
WINDOW_FLAG_0x10);
if (win == -1) {
gGameMovieIsPlaying = false;
return -1;
@@ -191,8 +194,9 @@ int gameMoviePlay(int movie, int flags)
windowRefresh(win);
bool subtitlesEnabled = settings.preferences.subtitles;
bool subtitlesEnabled = false;
int v1 = 4;
configGetBool(&gGameConfig, GAME_CONFIG_PREFERENCES_KEY, GAME_CONFIG_SUBTITLES_KEY, &subtitlesEnabled);
if (subtitlesEnabled) {
char* subtitlesFilePath = gameMovieBuildSubtitlesFilePath(movieFilePath);
@@ -210,7 +214,7 @@ int gameMoviePlay(int movie, int flags)
int oldFont;
if (subtitlesEnabled) {
const char* subtitlesPaletteFilePath;
if (gMoviePaletteFilePaths[movie] != nullptr) {
if (gMoviePaletteFilePaths[movie] != NULL) {
subtitlesPaletteFilePath = gMoviePaletteFilePaths[movie];
} else {
subtitlesPaletteFilePath = "art\\cuts\\subtitle.pal";
@@ -246,12 +250,7 @@ int gameMoviePlay(int movie, int flags)
int v11 = 0;
int buttons;
do {
if (!_moviePlaying() || _game_user_wants_to_quit || inputGetInput() != -1) {
break;
}
Gesture gesture;
if (touch_get_gesture(&gesture) && gesture.state == kEnded) {
if (!_moviePlaying() || _game_user_wants_to_quit || _get_input() != -1) {
break;
}
@@ -282,18 +281,14 @@ int gameMoviePlay(int movie, int flags)
windowSetFont(oldFont);
float r = (float)((Color2RGB(oldTextColor) & 0x7C00) >> 10) * flt_50352A;
float g = (float)((Color2RGB(oldTextColor) & 0x3E0) >> 5) * flt_50352A;
float b = (float)(Color2RGB(oldTextColor) & 0x1F) * flt_50352A;
float r = (float)((_Color2RGB_(oldTextColor) & 0x7C00) >> 10) * flt_50352A;
float g = (float)((_Color2RGB_(oldTextColor) & 0x3E0) >> 5) * flt_50352A;
float b = (float)(_Color2RGB_(oldTextColor) & 0x1F) * flt_50352A;
windowSetTextColor(r, g, b);
}
windowDestroy(win);
// CE: Destroying a window redraws only content it was covering (centered
// 640x480). This leads to everything outside this rect to remain black.
windowRefreshAll(&_scr_size);
if ((flags & GAME_MOVIE_PAUSE_MUSIC) != 0) {
backgroundSoundResume();
}
@@ -335,14 +330,17 @@ bool gameMovieIsPlaying()
// 0x44EB1C
static char* gameMovieBuildSubtitlesFilePath(char* movieFilePath)
{
char* language;
configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_LANGUAGE_KEY, &language);
char* path = movieFilePath;
char* separator = strrchr(path, '\\');
if (separator != nullptr) {
if (separator != NULL) {
path = separator + 1;
}
snprintf(gGameMovieSubtitlesFilePath, sizeof(gGameMovieSubtitlesFilePath), "text\\%s\\cuts\\%s", settings.system.language.c_str(), path);
sprintf(gGameMovieSubtitlesFilePath, "text\\%s\\cuts\\%s", language, path);
char* pch = strrchr(gGameMovieSubtitlesFilePath, '.');
if (*pch != '\0') {

29
src/game_palette.cc Normal file
View File

@@ -0,0 +1,29 @@
#include "game_palette.h"
#include "color.h"
namespace fallout {
// 0x44EBC0
int _HighRGB_(int a1)
{
// TODO: Some strange bit arithmetic.
int v1 = _Color2RGB_(a1);
int r = (v1 & 0x7C00) >> 10;
int g = (v1 & 0x3E0) >> 5;
int b = (v1 & 0x1F);
int result = g;
if (r > result) {
result = r;
}
result = result & 0xFF;
if (result <= b) {
result = b;
}
return result;
}
} // namespace fallout

10
src/game_palette.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef GAME_PALETTE_H
#define GAME_PALETTE_H
namespace fallout {
int _HighRGB_(int a1);
} // namespace fallout
#endif /* GAME_PALETTE_H */

View File

@@ -6,11 +6,10 @@
#include "animation.h"
#include "art.h"
#include "audio.h"
#include "audio_file.h"
#include "combat.h"
#include "core.h"
#include "debug.h"
#include "game_config.h"
#include "input.h"
#include "item.h"
#include "map.h"
#include "memory.h"
@@ -20,10 +19,8 @@
#include "proto.h"
#include "queue.h"
#include "random.h"
#include "settings.h"
#include "sound_effects_cache.h"
#include "stat.h"
#include "svga.h"
#include "window_manager.h"
#include "worldmap.h"
@@ -68,16 +65,16 @@ static bool gSoundEffectsEnabled = false;
static int _gsound_active_effect_counter;
// 0x518E50
static Sound* gBackgroundSound = nullptr;
static Sound* gBackgroundSound = NULL;
// 0x518E54
static Sound* gSpeechSound = nullptr;
static Sound* gSpeechSound = NULL;
// 0x518E58
static SoundEndCallback* gBackgroundSoundEndCallback = nullptr;
static SoundEndCallback* gBackgroundSoundEndCallback = NULL;
// 0x518E5C
static SoundEndCallback* gSpeechEndCallback = nullptr;
static SoundEndCallback* gSpeechEndCallback = NULL;
// 0x518E60
static char _snd_lookup_weapon_type[WEAPON_SOUND_EFFECT_COUNT] = {
@@ -107,10 +104,10 @@ static int _background_loop_requested = -1;
static char* _sound_sfx_path = _aSoundSfx;
// 0x518E78
static char* _sound_music_path1 = nullptr;
static char* _sound_music_path1 = _aSoundMusic_0;
// 0x518E7C
static char* _sound_music_path2 = nullptr;
static char* _sound_music_path2 = _aSoundMusic_0;
// 0x518E80
static char* _sound_speech_path = _aSoundSpeech_0;
@@ -157,7 +154,7 @@ static int _gsound_speech_volume_get_set(int volume);
static void speechPause();
static void speechResume();
static void _gsound_bkg_proc();
static int gameSoundFileOpen(const char* fname, int* sampleRate);
static int gameSoundFileOpen(const char* fname, int access, ...);
static long _gsound_write_();
static long gameSoundFileTellNotImplemented(int handle);
static int gameSoundFileWrite(int handle, const void* buf, unsigned int size);
@@ -192,11 +189,13 @@ int gameSoundInit()
return -1;
}
if (!settings.sound.initialize) {
bool initialize;
configGetBool(&gGameConfig, GAME_CONFIG_SOUND_KEY, GAME_CONFIG_INITIALIZE_KEY, &initialize);
if (!initialize) {
return 0;
}
gGameSoundDebugEnabled = settings.sound.debug;
configGetBool(&gGameConfig, GAME_CONFIG_SOUND_KEY, GAME_CONFIG_DEBUG_KEY, &gGameSoundDebugEnabled);
if (gGameSoundDebugEnabled) {
debugPrint("Initializing sound system...");
@@ -240,7 +239,8 @@ int gameSoundInit()
audioFileInit(gameSoundIsCompressed);
audioInit(gameSoundIsCompressed);
int cacheSize = settings.sound.cache_size;
int cacheSize;
configGetInt(&gGameConfig, GAME_CONFIG_SOUND_KEY, GAME_CONFIG_CACHE_SIZE_KEY, &cacheSize);
if (cacheSize >= 0x40000) {
debugPrint("\n!!! Config file needs adustment. Please remove the ");
debugPrint("cache_size line and run fallout again. This will reset ");
@@ -265,11 +265,14 @@ int gameSoundInit()
gGameSoundInitialized = true;
// SOUNDS
bool sounds = 0;
configGetBool(&gGameConfig, GAME_CONFIG_SOUND_KEY, GAME_CONFIG_SOUNDS_KEY, &sounds);
if (gGameSoundDebugEnabled) {
debugPrint("Sounds are ");
}
if (settings.sound.sounds) {
if (sounds) {
// NOTE: Uninline.
soundEffectsEnable();
} else {
@@ -283,11 +286,14 @@ int gameSoundInit()
}
// MUSIC
bool music = 0;
configGetBool(&gGameConfig, GAME_CONFIG_SOUND_KEY, GAME_CONFIG_MUSIC_KEY, &music);
if (gGameSoundDebugEnabled) {
debugPrint("Music is ");
}
if (settings.sound.music) {
if (music) {
// NOTE: Uninline.
backgroundSoundEnable();
} else {
@@ -301,11 +307,14 @@ int gameSoundInit()
}
// SPEEECH
bool speech = 0;
configGetBool(&gGameConfig, GAME_CONFIG_SOUND_KEY, GAME_CONFIG_SPEECH_KEY, &speech);
if (gGameSoundDebugEnabled) {
debugPrint("Speech is ");
}
if (settings.sound.speech) {
if (speech) {
// NOTE: Uninline.
speechEnable();
} else {
@@ -318,16 +327,16 @@ int gameSoundInit()
debugPrint("on.\n");
}
gMasterVolume = settings.sound.master_volume;
configGetInt(&gGameConfig, GAME_CONFIG_SOUND_KEY, GAME_CONFIG_MASTER_VOLUME_KEY, &gMasterVolume);
gameSoundSetMasterVolume(gMasterVolume);
gMusicVolume = settings.sound.music_volume;
configGetInt(&gGameConfig, GAME_CONFIG_SOUND_KEY, GAME_CONFIG_MUSIC_VOLUME_KEY, &gMusicVolume);
backgroundSoundSetVolume(gMusicVolume);
gSoundEffectsVolume = settings.sound.sndfx_volume;
configGetInt(&gGameConfig, GAME_CONFIG_SOUND_KEY, GAME_CONFIG_SNDFX_VOLUME_KEY, &gSoundEffectsVolume);
soundEffectsSetVolume(gSoundEffectsVolume);
gSpeechVolume = settings.sound.speech_volume;
configGetInt(&gGameConfig, GAME_CONFIG_SOUND_KEY, GAME_CONFIG_SPEECH_VOLUME_KEY, &gSpeechVolume);
speechSetVolume(gSpeechVolume);
_gsound_background_fade = 0;
@@ -391,9 +400,6 @@ int gameSoundExit()
audioFileExit();
audioExit();
internal_free(_sound_music_path1);
internal_free(_sound_music_path2);
gGameSoundInitialized = false;
return 0;
@@ -550,7 +556,7 @@ void backgroundSoundSetVolume(int volume)
}
if (gMusicEnabled) {
if (gBackgroundSound != nullptr) {
if (gBackgroundSound != NULL) {
soundSetVolume(gBackgroundSound, (int)(gMusicVolume * 0.94));
}
}
@@ -624,18 +630,18 @@ int backgroundSoundLoad(const char* fileName, int a2, int a3, int a4)
debugPrint("failed because sound could not be allocated.\n");
}
gBackgroundSound = nullptr;
gBackgroundSound = NULL;
return -1;
}
rc = soundSetFileIO(gBackgroundSound, audioFileOpen, audioFileClose, audioFileRead, nullptr, audioFileSeek, gameSoundFileTellNotImplemented, audioFileGetSize);
rc = soundSetFileIO(gBackgroundSound, audioFileOpen, audioFileClose, audioFileRead, NULL, audioFileSeek, gameSoundFileTellNotImplemented, audioFileGetSize);
if (rc != 0) {
if (gGameSoundDebugEnabled) {
debugPrint("failed because file IO could not be set for compression.\n");
}
soundDelete(gBackgroundSound);
gBackgroundSound = nullptr;
gBackgroundSound = NULL;
return -1;
}
@@ -647,7 +653,7 @@ int backgroundSoundLoad(const char* fileName, int a2, int a3, int a4)
}
soundDelete(gBackgroundSound);
gBackgroundSound = nullptr;
gBackgroundSound = NULL;
return -1;
}
@@ -665,7 +671,7 @@ int backgroundSoundLoad(const char* fileName, int a2, int a3, int a4)
}
soundDelete(gBackgroundSound);
gBackgroundSound = nullptr;
gBackgroundSound = NULL;
return -1;
}
@@ -678,13 +684,13 @@ int backgroundSoundLoad(const char* fileName, int a2, int a3, int a4)
}
soundDelete(gBackgroundSound);
gBackgroundSound = nullptr;
gBackgroundSound = NULL;
return -1;
}
}
rc = soundSetCallback(gBackgroundSound, backgroundSoundCallback, nullptr);
rc = soundSetCallback(gBackgroundSound, backgroundSoundCallback, NULL);
if (rc != SOUND_NO_ERROR) {
if (gGameSoundDebugEnabled) {
debugPrint("soundSetCallback failed for background sound\n");
@@ -707,7 +713,7 @@ int backgroundSoundLoad(const char* fileName, int a2, int a3, int a4)
}
soundDelete(gBackgroundSound);
gBackgroundSound = nullptr;
gBackgroundSound = NULL;
return -1;
}
@@ -732,7 +738,7 @@ int backgroundSoundLoad(const char* fileName, int a2, int a3, int a4)
}
soundDelete(gBackgroundSound);
gBackgroundSound = nullptr;
gBackgroundSound = NULL;
return -1;
}
@@ -756,13 +762,13 @@ void backgroundSoundDelete()
if (gGameSoundInitialized && gMusicEnabled && gBackgroundSound) {
if (_gsound_background_fade) {
if (_soundFade(gBackgroundSound, 2000, 0) == 0) {
gBackgroundSound = nullptr;
gBackgroundSound = NULL;
return;
}
}
soundDelete(gBackgroundSound);
gBackgroundSound = nullptr;
gBackgroundSound = NULL;
}
}
@@ -780,7 +786,7 @@ void backgroundSoundRestart(int value)
// 0x450B50
void backgroundSoundPause()
{
if (gBackgroundSound != nullptr) {
if (gBackgroundSound != NULL) {
soundPause(gBackgroundSound);
}
}
@@ -788,7 +794,7 @@ void backgroundSoundPause()
// 0x450B64
void backgroundSoundResume()
{
if (gBackgroundSound != nullptr) {
if (gBackgroundSound != NULL) {
soundResume(gBackgroundSound);
}
}
@@ -841,7 +847,7 @@ void speechSetVolume(int volume)
gSpeechVolume = volume;
if (gSpeechEnabled) {
if (gSpeechSound != nullptr) {
if (gSpeechSound != NULL) {
soundSetVolume(gSpeechSound, (int)(volume * 0.69));
}
}
@@ -897,16 +903,16 @@ int speechLoad(const char* fname, int a2, int a3, int a4)
if (gGameSoundDebugEnabled) {
debugPrint("failed because sound could not be allocated.\n");
}
gSpeechSound = nullptr;
gSpeechSound = NULL;
return -1;
}
if (soundSetFileIO(gSpeechSound, audioOpen, audioClose, audioRead, nullptr, audioSeek, gameSoundFileTellNotImplemented, audioGetSize)) {
if (soundSetFileIO(gSpeechSound, &audioOpen, &audioClose, &audioRead, NULL, &audioSeek, &gameSoundFileTellNotImplemented, &audioGetSize)) {
if (gGameSoundDebugEnabled) {
debugPrint("failed because file IO could not be set for compression.\n");
}
soundDelete(gSpeechSound);
gSpeechSound = nullptr;
gSpeechSound = NULL;
return -1;
}
@@ -915,7 +921,7 @@ int speechLoad(const char* fname, int a2, int a3, int a4)
debugPrint("failed because the file could not be found.\n");
}
soundDelete(gSpeechSound);
gSpeechSound = nullptr;
gSpeechSound = NULL;
return -1;
}
@@ -925,12 +931,12 @@ int speechLoad(const char* fname, int a2, int a3, int a4)
debugPrint("failed because looping could not be set.\n");
}
soundDelete(gSpeechSound);
gSpeechSound = nullptr;
gSpeechSound = NULL;
return -1;
}
}
if (soundSetCallback(gSpeechSound, speechCallback, nullptr)) {
if (soundSetCallback(gSpeechSound, speechCallback, NULL)) {
if (gGameSoundDebugEnabled) {
debugPrint("soundSetCallback failed for speech sound\n");
}
@@ -949,7 +955,7 @@ int speechLoad(const char* fname, int a2, int a3, int a4)
debugPrint("failed on call to soundLoad.\n");
}
soundDelete(gSpeechSound);
gSpeechSound = nullptr;
gSpeechSound = NULL;
return -1;
}
@@ -970,7 +976,7 @@ int speechLoad(const char* fname, int a2, int a3, int a4)
debugPrint("failed starting to play.\n");
}
soundDelete(gSpeechSound);
gSpeechSound = nullptr;
gSpeechSound = NULL;
return -1;
}
@@ -992,7 +998,7 @@ int _gsound_speech_play_preloaded()
return -1;
}
if (gSpeechSound == nullptr) {
if (gSpeechSound == NULL) {
return -1;
}
@@ -1010,7 +1016,7 @@ int _gsound_speech_play_preloaded()
if (speechPlay() != 0) {
soundDelete(gSpeechSound);
gSpeechSound = nullptr;
gSpeechSound = NULL;
return -1;
}
@@ -1022,9 +1028,9 @@ int _gsound_speech_play_preloaded()
void speechDelete()
{
if (gGameSoundInitialized && gSpeechEnabled) {
if (gSpeechSound != nullptr) {
if (gSpeechSound != NULL) {
soundDelete(gSpeechSound);
gSpeechSound = nullptr;
gSpeechSound = NULL;
}
}
}
@@ -1032,7 +1038,7 @@ void speechDelete()
// 0x451054
void speechPause()
{
if (gSpeechSound != nullptr) {
if (gSpeechSound != NULL) {
soundPause(gSpeechSound);
}
}
@@ -1040,7 +1046,7 @@ void speechPause()
// 0x451068
void speechResume()
{
if (gSpeechSound != nullptr) {
if (gSpeechSound != NULL) {
soundResume(gSpeechSound);
}
}
@@ -1058,8 +1064,8 @@ int _gsound_play_sfx_file_volume(const char* a1, int a2)
return -1;
}
v1 = soundEffectLoadWithVolume(a1, nullptr, a2);
if (v1 == nullptr) {
v1 = soundEffectLoadWithVolume(a1, NULL, a2);
if (v1 == NULL) {
return -1;
}
@@ -1072,11 +1078,11 @@ int _gsound_play_sfx_file_volume(const char* a1, int a2)
Sound* soundEffectLoad(const char* name, Object* object)
{
if (!gGameSoundInitialized) {
return nullptr;
return NULL;
}
if (!gSoundEffectsEnabled) {
return nullptr;
return NULL;
}
if (gGameSoundDebugEnabled) {
@@ -1088,22 +1094,22 @@ Sound* soundEffectLoad(const char* name, Object* object)
debugPrint("failed because there are already %d active effects.\n", _gsound_active_effect_counter);
}
return nullptr;
return NULL;
}
Sound* sound = _gsound_get_sound_ready_for_effect();
if (sound == nullptr) {
if (sound == NULL) {
if (gGameSoundDebugEnabled) {
debugPrint("failed.\n");
}
return nullptr;
return NULL;
}
++_gsound_active_effect_counter;
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s%s%s", _sound_sfx_path, name, ".ACM");
sprintf(path, "%s%s%s", _sound_sfx_path, name, ".ACM");
if (soundLoad(sound, path) == 0) {
if (gGameSoundDebugEnabled) {
@@ -1113,7 +1119,7 @@ Sound* soundEffectLoad(const char* name, Object* object)
return sound;
}
if (object != nullptr) {
if (object != NULL) {
if (FID_TYPE(object->fid) == OBJ_TYPE_CRITTER && (name[0] == 'H' || name[0] == 'N')) {
char v9 = name[1];
if (v9 == 'A' || v9 == 'F' || v9 == 'M') {
@@ -1126,7 +1132,7 @@ Sound* soundEffectLoad(const char* name, Object* object)
}
}
snprintf(path, sizeof(path), "%sH%cXXXX%s%s", _sound_sfx_path, v9, name + 6, ".ACM");
sprintf(path, "%sH%cXXXX%s%s", _sound_sfx_path, v9, name + 6, ".ACM");
if (gGameSoundDebugEnabled) {
debugPrint("tyring %s ", path + strlen(_sound_sfx_path));
@@ -1141,7 +1147,7 @@ Sound* soundEffectLoad(const char* name, Object* object)
}
if (v9 == 'F') {
snprintf(path, sizeof(path), "%sHMXXXX%s%s", _sound_sfx_path, name + 6, ".ACM");
sprintf(path, "%sHMXXXX%s%s", _sound_sfx_path, name + 6, ".ACM");
if (gGameSoundDebugEnabled) {
debugPrint("tyring %s ", path + strlen(_sound_sfx_path));
@@ -1159,7 +1165,7 @@ Sound* soundEffectLoad(const char* name, Object* object)
}
if (strncmp(name, "MALIEU", 6) == 0 || strncmp(name, "MAMTN2", 6) == 0) {
snprintf(path, sizeof(path), "%sMAMTNT%s%s", _sound_sfx_path, name + 6, ".ACM");
sprintf(path, "%sMAMTNT%s%s", _sound_sfx_path, name + 6, ".ACM");
if (gGameSoundDebugEnabled) {
debugPrint("tyring %s ", path + strlen(_sound_sfx_path));
@@ -1182,7 +1188,7 @@ Sound* soundEffectLoad(const char* name, Object* object)
debugPrint("failed.\n");
}
return nullptr;
return NULL;
}
// 0x45145C
@@ -1190,7 +1196,7 @@ Sound* soundEffectLoadWithVolume(const char* name, Object* object, int volume)
{
Sound* sound = soundEffectLoad(name, object);
if (sound != nullptr) {
if (sound != NULL) {
soundSetVolume(sound, (volume * gSoundEffectsVolume) / VOLUME_MAX);
}
@@ -1236,7 +1242,7 @@ int _gsnd_anim_sound(Sound* sound, void* a2)
return 0;
}
if (sound == nullptr) {
if (sound == NULL) {
return 0;
}
@@ -1256,7 +1262,7 @@ int soundEffectPlay(Sound* sound)
return -1;
}
if (sound == nullptr) {
if (sound == NULL) {
return -1;
}
@@ -1322,16 +1328,16 @@ char* sfxBuildCharName(Object* a1, int anim, int extra)
char v9;
if (artCopyFileName(FID_TYPE(a1->fid), a1->fid & 0xFFF, v7) == -1) {
return nullptr;
return NULL;
}
if (anim == ANIM_TAKE_OUT) {
if (_art_get_code(anim, extra, &v8, &v9) == -1) {
return nullptr;
return NULL;
}
} else {
if (_art_get_code(anim, (a1->fid & 0xF000) >> 12, &v8, &v9) == -1) {
return nullptr;
return NULL;
}
}
@@ -1346,7 +1352,7 @@ char* sfxBuildCharName(Object* a1, int anim, int extra)
v8 = 'Z';
}
snprintf(_sfx_file_name, sizeof(_sfx_file_name), "%s%c%c", v7, v8, v9);
sprintf(_sfx_file_name, "%s%c%c", v7, v8, v9);
compat_strupr(_sfx_file_name);
return _sfx_file_name;
}
@@ -1355,7 +1361,7 @@ char* sfxBuildCharName(Object* a1, int anim, int extra)
// 0x4516F0
char* gameSoundBuildAmbientSoundEffectName(const char* a1)
{
snprintf(_sfx_file_name, sizeof(_sfx_file_name), "A%6s%1d", a1, 1);
sprintf(_sfx_file_name, "A%6s%1d", a1, 1);
compat_strupr(_sfx_file_name);
return _sfx_file_name;
}
@@ -1364,7 +1370,7 @@ char* gameSoundBuildAmbientSoundEffectName(const char* a1)
// 0x451718
char* gameSoundBuildInterfaceName(const char* a1)
{
snprintf(_sfx_file_name, sizeof(_sfx_file_name), "N%6s%1d", a1, 1);
sprintf(_sfx_file_name, "N%6s%1d", a1, 1);
compat_strupr(_sfx_file_name);
return _sfx_file_name;
}
@@ -1373,7 +1379,7 @@ char* gameSoundBuildInterfaceName(const char* a1)
// 0x451760
char* sfxBuildWeaponName(int effectType, Object* weapon, int hitMode, Object* target)
{
int soundVariant;
int v6;
char weaponSoundCode;
char effectTypeCode;
char materialCode;
@@ -1387,18 +1393,18 @@ char* sfxBuildWeaponName(int effectType, Object* weapon, int hitMode, Object* ta
if (hitMode != HIT_MODE_LEFT_WEAPON_PRIMARY
&& hitMode != HIT_MODE_RIGHT_WEAPON_PRIMARY
&& hitMode != HIT_MODE_PUNCH) {
soundVariant = 2;
v6 = 2;
} else {
soundVariant = 1;
v6 = 1;
}
} else {
soundVariant = 1;
v6 = 1;
}
int damageType = weaponGetDamageType(nullptr, weapon);
int damageType = weaponGetDamageType(NULL, weapon);
// SFALL
if (effectTypeCode != 'H' || target == nullptr || damageType == explosionGetDamageType() || damageType == DAMAGE_TYPE_PLASMA || damageType == DAMAGE_TYPE_EMP) {
if (effectTypeCode != 'H' || target == NULL || damageType == explosionGetDamageType() || damageType == DAMAGE_TYPE_PLASMA || damageType == DAMAGE_TYPE_EMP) {
materialCode = 'X';
} else {
const int type = FID_TYPE(target->fid);
@@ -1441,7 +1447,7 @@ char* sfxBuildWeaponName(int effectType, Object* weapon, int hitMode, Object* ta
}
}
snprintf(_sfx_file_name, sizeof(_sfx_file_name), "W%c%c%1d%cXX%1d", effectTypeCode, weaponSoundCode, soundVariant, materialCode, 1);
sprintf(_sfx_file_name, "W%c%c%1d%cXX%1d", effectTypeCode, weaponSoundCode, v6, materialCode, 1);
compat_strupr(_sfx_file_name);
return _sfx_file_name;
}
@@ -1453,7 +1459,7 @@ char* sfxBuildSceneryName(int actionType, int action, const char* name)
char actionTypeCode = actionType == SOUND_EFFECT_ACTION_TYPE_PASSIVE ? 'P' : 'A';
char actionCode = _snd_lookup_scenery_action[action];
snprintf(_sfx_file_name, sizeof(_sfx_file_name), "S%c%c%4s%1d", actionTypeCode, actionCode, name, 1);
sprintf(_sfx_file_name, "S%c%c%4s%1d", actionTypeCode, actionCode, name, 1);
compat_strupr(_sfx_file_name);
return _sfx_file_name;
@@ -1471,11 +1477,11 @@ char* sfxBuildOpenName(Object* object, int action)
} else {
scenerySoundId = 'A';
}
snprintf(_sfx_file_name, sizeof(_sfx_file_name), "S%cDOORS%c", _snd_lookup_scenery_action[action], scenerySoundId);
sprintf(_sfx_file_name, "S%cDOORS%c", _snd_lookup_scenery_action[action], scenerySoundId);
} else {
Proto* proto;
protoGetProto(object->pid, &proto);
snprintf(_sfx_file_name, sizeof(_sfx_file_name), "I%cCNTNR%c", _snd_lookup_scenery_action[action], proto->item.field_80);
sprintf(_sfx_file_name, "I%cCNTNR%c", _snd_lookup_scenery_action[action], proto->item.field_80);
}
compat_strupr(_sfx_file_name);
return _sfx_file_name;
@@ -1534,8 +1540,8 @@ int soundPlayFile(const char* name)
return -1;
}
Sound* sound = soundEffectLoad(name, nullptr);
if (sound == nullptr) {
Sound* sound = soundEffectLoad(name, NULL);
if (sound == NULL) {
return -1;
}
@@ -1551,10 +1557,14 @@ void _gsound_bkg_proc()
}
// 0x451A08
int gameSoundFileOpen(const char* fname, int* sampleRate)
int gameSoundFileOpen(const char* fname, int flags, ...)
{
if ((flags & 2) != 0) {
return -1;
}
File* stream = fileOpen(fname, "rb");
if (stream == nullptr) {
if (stream == NULL) {
return -1;
}
@@ -1650,7 +1660,7 @@ bool gameSoundIsCompressed(char* filePath)
void speechCallback(void* userData, int a2)
{
if (a2 == 1) {
gSpeechSound = nullptr;
gSpeechSound = NULL;
if (gSpeechEndCallback) {
gSpeechEndCallback();
@@ -1662,7 +1672,7 @@ void speechCallback(void* userData, int a2)
void backgroundSoundCallback(void* userData, int a2)
{
if (a2 == 1) {
gBackgroundSound = nullptr;
gBackgroundSound = NULL;
if (gBackgroundSoundEndCallback) {
gBackgroundSoundEndCallback();
@@ -1681,22 +1691,22 @@ void soundEffectCallback(void* userData, int a2)
// 0x451ADC
int _gsound_background_allocate(Sound** soundPtr, int a2, int a3)
{
int soundFlags = SOUND_FLAG_0x02 | SOUND_16BIT;
int type = 0;
int v5 = 10;
int v6 = 0;
if (a2 == 13) {
type |= SOUND_TYPE_MEMORY;
v6 |= 0x01;
} else if (a2 == 14) {
type |= SOUND_TYPE_STREAMING;
v6 |= 0x02;
}
if (a3 == 15) {
type |= SOUND_TYPE_FIRE_AND_FORGET;
v6 |= 0x04;
} else if (a3 == 16) {
soundFlags |= SOUND_LOOPING;
v5 = 42;
}
Sound* sound = soundAllocate(type, soundFlags);
if (sound == nullptr) {
Sound* sound = soundAllocate(v6, v5);
if (sound == NULL) {
return -1;
}
@@ -1723,7 +1733,7 @@ int gameSoundFindBackgroundSoundPathWithCopy(char* dest, const char* src)
}
char outPath[COMPAT_MAX_PATH];
snprintf(outPath, sizeof(outPath), "%s%s%s", _sound_music_path1, src, ".ACM");
sprintf(outPath, "%s%s%s", _sound_music_path1, src, ".ACM");
if (_gsound_file_exists_f(outPath)) {
strncpy(dest, outPath, COMPAT_MAX_PATH);
dest[COMPAT_MAX_PATH] = '\0';
@@ -1737,10 +1747,10 @@ int gameSoundFindBackgroundSoundPathWithCopy(char* dest, const char* src)
gameSoundDeleteOldMusicFile();
char inPath[COMPAT_MAX_PATH];
snprintf(inPath, sizeof(inPath), "%s%s%s", _sound_music_path2, src, ".ACM");
sprintf(inPath, "%s%s%s", _sound_music_path2, src, ".ACM");
FILE* inStream = compat_fopen(inPath, "rb");
if (inStream == nullptr) {
if (inStream == NULL) {
if (gGameSoundDebugEnabled) {
debugPrint("Unable to find music file %s to copy down.\n", src);
}
@@ -1749,7 +1759,7 @@ int gameSoundFindBackgroundSoundPathWithCopy(char* dest, const char* src)
}
FILE* outStream = compat_fopen(outPath, "wb");
if (outStream == nullptr) {
if (outStream == NULL) {
if (gGameSoundDebugEnabled) {
debugPrint("Unable to open music file %s for copying to.", src);
}
@@ -1760,7 +1770,7 @@ int gameSoundFindBackgroundSoundPathWithCopy(char* dest, const char* src)
}
void* buffer = internal_malloc(0x2000);
if (buffer == nullptr) {
if (buffer == NULL) {
if (gGameSoundDebugEnabled) {
debugPrint("Out of memory in gsound_background_find_with_copy.\n", src);
}
@@ -1824,7 +1834,7 @@ int gameSoundFindBackgroundSoundPath(char* dest, const char* src)
debugPrint(" finding background sound ");
}
snprintf(path, sizeof(path), "%s%s%s", _sound_music_path1, src, ".ACM");
sprintf(path, "%s%s%s", _sound_music_path1, src, ".ACM");
if (_gsound_file_exists_f(path)) {
strncpy(dest, path, COMPAT_MAX_PATH);
dest[COMPAT_MAX_PATH] = '\0';
@@ -1835,7 +1845,7 @@ int gameSoundFindBackgroundSoundPath(char* dest, const char* src)
debugPrint("in 2nd path ");
}
snprintf(path, sizeof(path), "%s%s%s", _sound_music_path2, src, ".ACM");
sprintf(path, "%s%s%s", _sound_music_path2, src, ".ACM");
if (_gsound_file_exists_f(path)) {
strncpy(dest, path, COMPAT_MAX_PATH);
dest[COMPAT_MAX_PATH] = '\0';
@@ -1868,7 +1878,7 @@ int gameSoundFindSpeechSoundPath(char* dest, const char* src)
debugPrint(" finding speech sound ");
}
snprintf(path, sizeof(path), "%s%s%s", _sound_speech_path, src, ".ACM");
sprintf(path, "%s%s%s", _sound_speech_path, src, ".ACM");
// Check for existence by getting file size.
int fileSize;
@@ -1892,7 +1902,7 @@ void gameSoundDeleteOldMusicFile()
{
if (_background_fname_copied[0] != '\0') {
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s%s%s", "sound\\music\\", _background_fname_copied, ".ACM");
sprintf(path, "%s%s%s", "sound\\music\\", _background_fname_copied, ".ACM");
if (compat_remove(path)) {
if (gGameSoundDebugEnabled) {
debugPrint("Deleting old music file failed.\n");
@@ -1951,42 +1961,35 @@ int speechPlay()
return 0;
}
// TODO: Refactor to use Settings.
//
// 0x452208
int _gsound_get_music_path(char** out_value, const char* key)
{
size_t len;
char* copy;
size_t v3;
char* v4;
char* value;
if (!configGetString(&gGameConfig, GAME_CONFIG_SOUND_KEY, key, &value)) {
*out_value = internal_strdup(_aSoundMusic_0);
configGetString(&gGameConfig, GAME_CONFIG_SOUND_KEY, key, out_value);
value = *out_value;
v3 = strlen(value) + 1;
if (*(value + v3 - 2) == '\\') {
return 0;
}
len = strlen(value);
if (value[len - 1] == '\\' || value[len - 1] == '/') {
*out_value = internal_strdup(value);
return 0;
}
copy = (char*)internal_malloc(len + 2);
if (copy == nullptr) {
v4 = (char*)internal_malloc(v3 - 1 + 2);
if (v4 == NULL) {
if (gGameSoundDebugEnabled) {
debugPrint("Out of memory in gsound_get_music_path.\n");
}
return -1;
}
strcpy(copy, value);
copy[len] = '\\';
copy[len + 1] = '\0';
if (!configSetString(&gGameConfig, GAME_CONFIG_SOUND_KEY, key, copy)) {
internal_free(copy);
strcpy(v4, value);
*(v4 + v3) = '\\';
*(v4 + v3 + 1) = '\0';
if (configSetString(&gGameConfig, GAME_CONFIG_SOUND_KEY, key, v4) != 1) {
if (gGameSoundDebugEnabled) {
debugPrint("config_set_string failed in gsound_music_path.\n");
}
@@ -1994,20 +1997,16 @@ int _gsound_get_music_path(char** out_value, const char* key)
return -1;
}
if (!configGetString(&gGameConfig, GAME_CONFIG_SOUND_KEY, key, &value)) {
internal_free(copy);
if (gGameSoundDebugEnabled) {
debugPrint("config_get_string failed in gsound_music_path.\n");
}
return -1;
if (configGetString(&gGameConfig, GAME_CONFIG_SOUND_KEY, key, out_value)) {
internal_free(v4);
return 0;
}
internal_free(copy);
if (gGameSoundDebugEnabled) {
debugPrint("config_get_string failed in gsound_music_path.\n");
}
*out_value = internal_strdup(value);
return 0;
return -1;
}
// 0x452378
@@ -2015,8 +2014,8 @@ Sound* _gsound_get_sound_ready_for_effect()
{
int rc;
Sound* sound = soundAllocate(SOUND_TYPE_MEMORY | SOUND_TYPE_FIRE_AND_FORGET, SOUND_FLAG_0x02 | SOUND_16BIT);
if (sound == nullptr) {
Sound* sound = soundAllocate(5, 10);
if (sound == NULL) {
if (gGameSoundDebugEnabled) {
debugPrint(" Can't allocate sound for effect. ");
}
@@ -2025,13 +2024,13 @@ Sound* _gsound_get_sound_ready_for_effect()
debugPrint("soundAllocate returned: %d, %s\n", 0, soundGetErrorDescription(0));
}
return nullptr;
return NULL;
}
if (soundEffectsCacheInitialized()) {
rc = soundSetFileIO(sound, soundEffectsCacheFileOpen, soundEffectsCacheFileClose, soundEffectsCacheFileRead, soundEffectsCacheFileWrite, soundEffectsCacheFileSeek, soundEffectsCacheFileTell, soundEffectsCacheFileLength);
} else {
rc = soundSetFileIO(sound, audioOpen, audioClose, audioRead, nullptr, audioSeek, gameSoundFileTellNotImplemented, audioGetSize);
rc = soundSetFileIO(sound, audioOpen, audioClose, audioRead, NULL, audioSeek, gameSoundFileTellNotImplemented, audioGetSize);
}
if (rc != 0) {
@@ -2045,10 +2044,10 @@ Sound* _gsound_get_sound_ready_for_effect()
soundDelete(sound);
return nullptr;
return NULL;
}
rc = soundSetCallback(sound, soundEffectCallback, nullptr);
rc = soundSetCallback(sound, soundEffectCallback, NULL);
if (rc != 0) {
if (gGameSoundDebugEnabled) {
debugPrint("failed because the callback could not be set.\n");
@@ -2060,7 +2059,7 @@ Sound* _gsound_get_sound_ready_for_effect()
soundDelete(sound);
return nullptr;
return NULL;
}
soundSetVolume(sound, gSoundEffectsVolume);
@@ -2074,7 +2073,7 @@ Sound* _gsound_get_sound_ready_for_effect()
bool _gsound_file_exists_f(const char* fname)
{
FILE* f = compat_fopen(fname, "rb");
if (f == nullptr) {
if (f == NULL) {
return false;
}
@@ -2095,17 +2094,17 @@ int _gsound_setup_paths()
// 0x452628
int _gsound_sfx_q_start()
{
return ambientSoundEffectEventProcess(nullptr, nullptr);
return ambientSoundEffectEventProcess(0, NULL);
}
// 0x452634
int ambientSoundEffectEventProcess(Object* a1, void* data)
{
_queue_clear_type(EVENT_TYPE_GSOUND_SFX_EVENT, nullptr);
_queue_clear_type(EVENT_TYPE_GSOUND_SFX_EVENT, NULL);
AmbientSoundEffectEvent* soundEffectEvent = (AmbientSoundEffectEvent*)data;
int ambientSoundEffectIndex = -1;
if (soundEffectEvent != nullptr) {
if (soundEffectEvent != NULL) {
ambientSoundEffectIndex = soundEffectEvent->ambientSoundEffectIndex;
} else {
if (wmSfxMaxCount() > 0) {
@@ -2114,7 +2113,7 @@ int ambientSoundEffectEventProcess(Object* a1, void* data)
}
AmbientSoundEffectEvent* nextSoundEffectEvent = (AmbientSoundEffectEvent*)internal_malloc(sizeof(*nextSoundEffectEvent));
if (nextSoundEffectEvent == nullptr) {
if (nextSoundEffectEvent == NULL) {
return -1;
}
@@ -2125,7 +2124,7 @@ int ambientSoundEffectEventProcess(Object* a1, void* data)
int delay = 10 * randomBetween(15, 20);
if (wmSfxMaxCount() > 0) {
nextSoundEffectEvent->ambientSoundEffectIndex = wmSfxRollNextIdx();
if (queueAddEvent(delay, nullptr, nextSoundEffectEvent, EVENT_TYPE_GSOUND_SFX_EVENT) == -1) {
if (queueAddEvent(delay, NULL, nextSoundEffectEvent, EVENT_TYPE_GSOUND_SFX_EVENT) == -1) {
return -1;
}
}

View File

@@ -9,12 +9,12 @@
namespace fallout {
// 0x51DEF4
static RectListNode* _rectList = nullptr;
static RectListNode* _rectList = NULL;
// 0x4C6900
void _GNW_rect_exit()
{
while (_rectList != nullptr) {
while (_rectList != NULL) {
RectListNode* next = _rectList->next;
internal_free(_rectList);
_rectList = next;
@@ -28,7 +28,7 @@ void _rect_clip_list(RectListNode** rectListNodePtr, Rect* rect)
rectCopy(&v1, rect);
// NOTE: Original code is slightly different.
while (*rectListNodePtr != nullptr) {
while (*rectListNodePtr != NULL) {
RectListNode* rectListNode = *rectListNodePtr;
if (v1.right >= rectListNode->rect.left
&& v1.bottom >= rectListNode->rect.top
@@ -44,7 +44,7 @@ void _rect_clip_list(RectListNode** rectListNodePtr, Rect* rect)
if (v2.top < v1.top) {
RectListNode* newRectListNode = _rect_malloc();
if (newRectListNode == nullptr) {
if (newRectListNode == NULL) {
return;
}
@@ -60,7 +60,7 @@ void _rect_clip_list(RectListNode** rectListNodePtr, Rect* rect)
if (v2.bottom > v1.bottom) {
RectListNode* newRectListNode = _rect_malloc();
if (newRectListNode == nullptr) {
if (newRectListNode == NULL) {
return;
}
@@ -76,7 +76,7 @@ void _rect_clip_list(RectListNode** rectListNodePtr, Rect* rect)
if (v2.left < v1.left) {
RectListNode* newRectListNode = _rect_malloc();
if (newRectListNode == nullptr) {
if (newRectListNode == NULL) {
return;
}
@@ -90,7 +90,7 @@ void _rect_clip_list(RectListNode** rectListNodePtr, Rect* rect)
if (v2.right > v1.right) {
RectListNode* newRectListNode = _rect_malloc();
if (newRectListNode == nullptr) {
if (newRectListNode == NULL) {
return;
}
@@ -107,69 +107,13 @@ void _rect_clip_list(RectListNode** rectListNodePtr, Rect* rect)
}
}
// 0x4C6AAC
RectListNode* rect_clip(Rect* b, Rect* t)
{
RectListNode* list = nullptr;
Rect clipped_t;
if (rectIntersection(t, b, &clipped_t) == 0) {
RectListNode** next = &list;
Rect clipped_b[4];
int k;
clipped_b[0].left = b->left;
clipped_b[0].top = b->top;
clipped_b[0].right = b->right;
clipped_b[0].bottom = clipped_t.top - 1;
clipped_b[1].left = b->left;
clipped_b[1].top = clipped_t.top;
clipped_b[1].right = clipped_t.left - 1;
clipped_b[1].bottom = clipped_t.bottom;
clipped_b[2].left = clipped_t.right + 1;
clipped_b[2].top = clipped_t.top;
clipped_b[2].right = b->right;
clipped_b[2].bottom = clipped_t.bottom;
clipped_b[3].left = b->left;
clipped_b[3].top = clipped_t.bottom + 1;
clipped_b[3].right = b->right;
clipped_b[3].bottom = b->bottom;
for (k = 0; k < 4; k++) {
if (clipped_b[k].left <= clipped_b[k].right && clipped_b[k].top <= clipped_b[k].bottom) {
*next = _rect_malloc();
if (*next == nullptr) {
return nullptr;
}
(*next)->rect = clipped_b[k];
(*next)->next = nullptr;
next = &((*next)->next);
}
}
} else {
list = _rect_malloc();
if (list == nullptr) {
return nullptr;
}
list->rect = *b;
list->next = nullptr;
}
return list;
}
// 0x4C6BB8
RectListNode* _rect_malloc()
{
if (_rectList == nullptr) {
if (_rectList == NULL) {
for (int index = 0; index < 10; index++) {
RectListNode* rectListNode = (RectListNode*)internal_malloc(sizeof(*rectListNode));
if (rectListNode == nullptr) {
if (rectListNode == NULL) {
break;
}
@@ -178,8 +122,8 @@ RectListNode* _rect_malloc()
}
}
if (_rectList == nullptr) {
return nullptr;
if (_rectList == NULL) {
return NULL;
}
RectListNode* rectListNode = _rectList;

View File

@@ -27,7 +27,6 @@ typedef struct RectListNode {
void _GNW_rect_exit();
void _rect_clip_list(RectListNode** rectListNodePtr, Rect* rect);
RectListNode* rect_clip(Rect* b, Rect* t);
RectListNode* _rect_malloc();
void _rect_free(RectListNode* entry);
void rectUnion(const Rect* s1, const Rect* s2, Rect* r);

View File

@@ -2,9 +2,6 @@
#include <string.h>
#include <algorithm>
#include "color.h"
#include "debug.h"
#include "memory.h"
@@ -14,9 +11,6 @@ static void _InitTree();
static void _InsertNode(int a1);
static void _DeleteNode(int a1);
// 0x596D90
static unsigned char _GreyTable[256];
// 0x596E90
static int* _dad_2;
@@ -41,32 +35,13 @@ static int _codesize;
// 0x596EAC
static int _match_position;
// 0x44EBC0
unsigned char HighRGB(unsigned char color)
{
int rgb = Color2RGB(color);
int r = (rgb & 0x7C00) >> 10;
int g = (rgb & 0x3E0) >> 5;
int b = (rgb & 0x1F);
return std::max(std::max(r, g), b);
}
// 0x44ED98
int load_lbm_to_buf(const char* path, unsigned char* buffer, int a3, int a4, int a5, int a6, int a7)
{
// TODO: Incomplete.
return -1;
}
// 0x44F250
int graphCompress(unsigned char* a1, unsigned char* a2, int a3)
{
_dad_2 = nullptr;
_rson = nullptr;
_lson = nullptr;
_text_buf = nullptr;
_dad_2 = NULL;
_rson = NULL;
_lson = NULL;
_text_buf = NULL;
// NOTE: Original code is slightly different, it uses deep nesting or a
// bunch of gotos.
@@ -75,20 +50,20 @@ int graphCompress(unsigned char* a1, unsigned char* a2, int a3)
_dad_2 = (int*)internal_malloc(sizeof(*_dad_2) * 4104);
_text_buf = (unsigned char*)internal_malloc(sizeof(*_text_buf) * 4122);
if (_lson == nullptr || _rson == nullptr || _dad_2 == nullptr || _text_buf == nullptr) {
if (_lson == NULL || _rson == NULL || _dad_2 == NULL || _text_buf == NULL) {
debugPrint("\nGRAPHLIB: Error allocating compression buffers!\n");
if (_dad_2 != nullptr) {
if (_dad_2 != NULL) {
internal_free(_dad_2);
}
if (_rson != nullptr) {
if (_rson != NULL) {
internal_free(_rson);
}
if (_lson != nullptr) {
if (_lson != NULL) {
internal_free(_lson);
}
if (_text_buf != nullptr) {
if (_text_buf != NULL) {
internal_free(_text_buf);
}
@@ -355,7 +330,7 @@ static void _DeleteNode(int a1)
int graphDecompress(unsigned char* src, unsigned char* dest, int length)
{
_text_buf = (unsigned char*)internal_malloc(sizeof(*_text_buf) * 4122);
if (_text_buf == nullptr) {
if (_text_buf == NULL) {
debugPrint("\nGRAPHLIB: Error allocating decompression buffer!\n");
return -1;
}
@@ -410,37 +385,4 @@ int graphDecompress(unsigned char* src, unsigned char* dest, int length)
return 0;
}
// 0x44FA78
void grayscalePaletteUpdate(int a1, int a2)
{
if (a1 >= 0 && a2 <= 255) {
for (int index = a1; index <= a2; index++) {
// NOTE: Calls `Color2RGB` many times due to `min` and `max` macro
// uses.
int v1 = std::max((Color2RGB(index) & 0x7C00) >> 10, std::max((Color2RGB(index) & 0x3E0) >> 5, Color2RGB(index) & 0x1F));
int v2 = std::min((Color2RGB(index) & 0x7C00) >> 10, std::min((Color2RGB(index) & 0x3E0) >> 5, Color2RGB(index) & 0x1F));
int v3 = v1 + v2;
int v4 = (int)((double)v3 * 240.0 / 510.0);
int paletteIndex = ((v4 & 0xFF) << 10) | ((v4 & 0xFF) << 5) | (v4 & 0xFF);
_GreyTable[index] = _colorTable[paletteIndex];
}
}
}
// 0x44FC40
void grayscalePaletteApply(unsigned char* buffer, int width, int height, int pitch)
{
unsigned char* ptr = buffer;
int skip = pitch - width;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
unsigned char c = *ptr;
*ptr++ = _GreyTable[c];
}
ptr += skip;
}
}
} // namespace fallout

View File

@@ -3,12 +3,8 @@
namespace fallout {
unsigned char HighRGB(unsigned char color);
int load_lbm_to_buf(const char* path, unsigned char* buffer, int a3, int a4, int a5, int a6, int a7);
int graphCompress(unsigned char* a1, unsigned char* a2, int a3);
int graphDecompress(unsigned char* a1, unsigned char* a2, int a3);
void grayscalePaletteUpdate(int a1, int a2);
void grayscalePaletteApply(unsigned char* surface, int width, int height, int pitch);
} // namespace fallout

46
src/grayscale.cc Normal file
View File

@@ -0,0 +1,46 @@
#include "grayscale.h"
#include <algorithm>
#include "color.h"
namespace fallout {
// 0x596D90
static unsigned char _GreyTable[256];
// 0x44FA78
void grayscalePaletteUpdate(int a1, int a2)
{
if (a1 >= 0 && a2 <= 255) {
for (int index = a1; index <= a2; index++) {
// NOTE: The only way to explain so much calls to [_Color2RGB_] with
// the same repeated pattern is by the use of min/max macros.
int v1 = std::max((_Color2RGB_(index) & 0x7C00) >> 10, std::max((_Color2RGB_(index) & 0x3E0) >> 5, _Color2RGB_(index) & 0x1F));
int v2 = std::min((_Color2RGB_(index) & 0x7C00) >> 10, std::min((_Color2RGB_(index) & 0x3E0) >> 5, _Color2RGB_(index) & 0x1F));
int v3 = v1 + v2;
int v4 = (int)((double)v3 * 240.0 / 510.0);
int paletteIndex = ((v4 & 0xFF) << 10) | ((v4 & 0xFF) << 5) | (v4 & 0xFF);
_GreyTable[index] = _colorTable[paletteIndex];
}
}
}
// 0x44FC40
void grayscalePaletteApply(unsigned char* buffer, int width, int height, int pitch)
{
unsigned char* ptr = buffer;
int skip = pitch - width;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
unsigned char c = *ptr;
*ptr++ = _GreyTable[c];
}
ptr += skip;
}
}
} // namespace fallout

11
src/grayscale.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef GRAYSCALE_H
#define GRAYSCALE_H
namespace fallout {
void grayscalePaletteUpdate(int a1, int a2);
void grayscalePaletteApply(unsigned char* surface, int width, int height, int pitch);
} // namespace fallout
#endif /* GRAYSCALE_H */

View File

@@ -73,7 +73,7 @@ typedef struct HeapMoveableExtent {
static bool heapInternalsInit();
static void heapInternalsFree();
static bool heapHandleListInit(Heap* heap);
static bool heapPrintStats(Heap* heap, char* dest, size_t size);
static bool heapPrintStats(Heap* heap, char* dest);
static bool heapFindFreeHandle(Heap* heap, int* handleIndexPtr);
static bool heapFindFreeBlock(Heap* heap, int size, void** blockPtr, int a4);
static int heapBlockCompareBySize(const void* a1, const void* a2);
@@ -85,23 +85,23 @@ static bool heapBuildMoveableBlocksList(int extentIndex);
// An array of pointers to free heap blocks.
//
// 0x518E9C
static unsigned char** gHeapFreeBlocks = nullptr;
static unsigned char** gHeapFreeBlocks = NULL;
// An array of moveable extents in heap.
//
// 0x518EA0
static HeapMoveableExtent* gHeapMoveableExtents = nullptr;
static HeapMoveableExtent* gHeapMoveableExtents = NULL;
// An array of pointers to moveable heap blocks.
//
// 0x518EA4
static unsigned char** gHeapMoveableBlocks = nullptr;
static unsigned char** gHeapMoveableBlocks = NULL;
// An array of indexes into [gHeapFreeBlocks] array to track which free blocks
// were already reserved for subsequent moving.
//
// 0x518EA8
static int* gHeapReservedFreeBlockIndexes = nullptr;
static int* gHeapReservedFreeBlockIndexes = NULL;
// The length of the [gHeapFreeBlocks] array.
//
@@ -139,26 +139,26 @@ static bool heapInternalsInit()
// it has failed.
do {
gHeapFreeBlocks = (unsigned char**)internal_malloc(sizeof(*gHeapFreeBlocks) * HEAP_FREE_BLOCKS_INITIAL_LENGTH);
if (gHeapFreeBlocks == nullptr) {
if (gHeapFreeBlocks == NULL) {
break;
}
gHeapFreeBlocksLength = HEAP_FREE_BLOCKS_INITIAL_LENGTH;
gHeapMoveableExtents = (HeapMoveableExtent*)internal_malloc(sizeof(*gHeapMoveableExtents) * HEAP_MOVEABLE_EXTENTS_INITIAL_LENGTH);
if (gHeapMoveableExtents == nullptr) {
if (gHeapMoveableExtents == NULL) {
break;
}
gHeapMoveableExtentsLength = HEAP_MOVEABLE_EXTENTS_INITIAL_LENGTH;
gHeapMoveableBlocks = (unsigned char**)internal_malloc(sizeof(*gHeapMoveableBlocks) * HEAP_MOVEABLE_BLOCKS_INITIAL_LENGTH);
if (gHeapMoveableBlocks == nullptr) {
if (gHeapMoveableBlocks == NULL) {
break;
}
gHeapMoveableBlocksLength = HEAP_MOVEABLE_BLOCKS_INITIAL_LENGTH;
gHeapReservedFreeBlockIndexes = (int*)internal_malloc(sizeof(*gHeapReservedFreeBlockIndexes) * HEAP_RESERVED_FREE_BLOCK_INDEXES_INITIAL_LENGTH);
if (gHeapReservedFreeBlockIndexes == nullptr) {
if (gHeapReservedFreeBlockIndexes == NULL) {
break;
}
gHeapReservedFreeBlockIndexesLength = HEAP_RESERVED_FREE_BLOCK_INDEXES_INITIAL_LENGTH;
@@ -175,27 +175,27 @@ static bool heapInternalsInit()
// 0x4533A0
static void heapInternalsFree()
{
if (gHeapReservedFreeBlockIndexes != nullptr) {
if (gHeapReservedFreeBlockIndexes != NULL) {
internal_free(gHeapReservedFreeBlockIndexes);
gHeapReservedFreeBlockIndexes = nullptr;
gHeapReservedFreeBlockIndexes = NULL;
}
gHeapReservedFreeBlockIndexesLength = 0;
if (gHeapMoveableBlocks != nullptr) {
if (gHeapMoveableBlocks != NULL) {
internal_free(gHeapMoveableBlocks);
gHeapMoveableBlocks = nullptr;
gHeapMoveableBlocks = NULL;
}
gHeapMoveableBlocksLength = 0;
if (gHeapMoveableExtents != nullptr) {
if (gHeapMoveableExtents != NULL) {
internal_free(gHeapMoveableExtents);
gHeapMoveableExtents = nullptr;
gHeapMoveableExtents = NULL;
}
gHeapMoveableExtentsLength = 0;
if (gHeapFreeBlocks != nullptr) {
if (gHeapFreeBlocks != NULL) {
internal_free(gHeapFreeBlocks);
gHeapFreeBlocks = nullptr;
gHeapFreeBlocks = NULL;
}
gHeapFreeBlocksLength = 0;
}
@@ -203,7 +203,7 @@ static void heapInternalsFree()
// 0x452974
bool heapInit(Heap* heap, int a2)
{
if (heap == nullptr) {
if (heap == NULL) {
return false;
}
@@ -218,7 +218,7 @@ bool heapInit(Heap* heap, int a2)
if (heapHandleListInit(heap)) {
int size = (a2 >> 10) + a2;
heap->data = (unsigned char*)internal_malloc(size);
if (heap->data != nullptr) {
if (heap->data != NULL) {
heap->size = size;
heap->freeBlocks = 1;
heap->freeSize = heap->size - HEAP_BLOCK_OVERHEAD_SIZE;
@@ -248,24 +248,24 @@ bool heapInit(Heap* heap, int a2)
// 0x452A3C
bool heapFree(Heap* heap)
{
if (heap == nullptr) {
if (heap == NULL) {
return false;
}
for (int index = 0; index < heap->handlesLength; index++) {
HeapHandle* handle = &(heap->handles[index]);
if (handle->state == 4 && handle->data != nullptr) {
if (handle->state == 4 && handle->data != NULL) {
internal_free(handle->data);
}
}
if (heap->handles != nullptr) {
if (heap->handles != NULL) {
internal_free(heap->handles);
heap->handles = nullptr;
heap->handles = NULL;
heap->handlesLength = 0;
}
if (heap->data != nullptr) {
if (heap->data != NULL) {
internal_free(heap->data);
}
@@ -283,7 +283,7 @@ bool heapFree(Heap* heap)
static bool heapHandleListInit(Heap* heap)
{
heap->handles = (HeapHandle*)internal_malloc(sizeof(*heap->handles) * HEAP_HANDLES_INITIAL_LENGTH);
if (heap->handles == nullptr) {
if (heap->handles == NULL) {
debugPrint("Heap Error : Could not initialize handles.\n");
return false;
}
@@ -291,7 +291,7 @@ static bool heapHandleListInit(Heap* heap)
for (int index = 0; index < HEAP_HANDLES_INITIAL_LENGTH; index++) {
HeapHandle* handle = &(heap->handles[index]);
handle->state = HEAP_HANDLE_STATE_INVALID;
handle->data = nullptr;
handle->data = NULL;
}
heap->handlesLength = HEAP_HANDLES_INITIAL_LENGTH;
@@ -307,9 +307,7 @@ bool heapBlockAllocate(Heap* heap, int* handleIndexPtr, int size, int a4)
int blockSize;
HeapHandle* handle;
size += 4 - size % 4;
if (heap == nullptr || handleIndexPtr == nullptr || size == 0) {
if (heap == NULL || handleIndexPtr == NULL || size == 0) {
goto err;
}
@@ -401,7 +399,7 @@ bool heapBlockAllocate(Heap* heap, int* handleIndexPtr, int size, int a4)
}
handle->state = HEAP_HANDLE_STATE_INVALID;
handle->data = nullptr;
handle->data = NULL;
debugPrint("Heap Error: Unknown block state during allocation.\n");
@@ -422,7 +420,7 @@ err:
// 0x452CB4
bool heapBlockDeallocate(Heap* heap, int* handleIndexPtr)
{
if (heap == nullptr || handleIndexPtr == nullptr) {
if (heap == NULL || handleIndexPtr == NULL) {
debugPrint("Heap Error: Could not deallocate block.\n");
return false;
}
@@ -466,7 +464,7 @@ bool heapBlockDeallocate(Heap* heap, int* handleIndexPtr)
// Reset handle
handle->state = HEAP_HANDLE_STATE_INVALID;
handle->data = nullptr;
handle->data = NULL;
return true;
}
@@ -481,7 +479,7 @@ bool heapBlockDeallocate(Heap* heap, int* handleIndexPtr)
// Reset handle
handle->state = HEAP_HANDLE_STATE_INVALID;
handle->data = nullptr;
handle->data = NULL;
return true;
}
@@ -493,7 +491,7 @@ bool heapBlockDeallocate(Heap* heap, int* handleIndexPtr)
// 0x452DE0
bool heapLock(Heap* heap, int handleIndex, unsigned char** bufferPtr)
{
if (heap == nullptr) {
if (heap == NULL) {
debugPrint("Heap Error: Could not lock block");
return false;
}
@@ -554,7 +552,7 @@ bool heapLock(Heap* heap, int handleIndex, unsigned char** bufferPtr)
// 0x452EE4
bool heapUnlock(Heap* heap, int handleIndex)
{
if (heap == nullptr) {
if (heap == NULL) {
debugPrint("Heap Error: Could not unlock block.\n");
return false;
}
@@ -601,9 +599,9 @@ bool heapUnlock(Heap* heap, int handleIndex)
}
// 0x4532AC
static bool heapPrintStats(Heap* heap, char* dest, size_t size)
static bool heapPrintStats(Heap* heap, char* dest)
{
if (heap == nullptr || dest == nullptr) {
if (heap == NULL || dest == NULL) {
return false;
}
@@ -619,7 +617,7 @@ static bool heapPrintStats(Heap* heap, char* dest, size_t size)
"Total handles: %d\n"
"Total heaps: %d";
snprintf(dest, size, format,
sprintf(dest, format,
heap->freeBlocks,
heap->freeSize,
heap->moveableBlocks,
@@ -649,7 +647,7 @@ static bool heapFindFreeHandle(Heap* heap, int* handleIndexPtr)
// If we're here the search above failed, we have to allocate more handles.
HeapHandle* handles = (HeapHandle*)internal_realloc(heap->handles, sizeof(*handles) * (heap->handlesLength + HEAP_HANDLES_INITIAL_LENGTH));
if (handles == nullptr) {
if (handles == NULL) {
return false;
}
@@ -659,7 +657,7 @@ static bool heapFindFreeHandle(Heap* heap, int* handleIndexPtr)
for (int index = heap->handlesLength; index < heap->handlesLength + HEAP_HANDLES_INITIAL_LENGTH; index++) {
HeapHandle* handle = &(heap->handles[index]);
handle->state = HEAP_HANDLE_STATE_INVALID;
handle->data = nullptr;
handle->data = NULL;
}
*handleIndexPtr = heap->handlesLength;
@@ -725,7 +723,7 @@ static bool heapFindFreeBlock(Heap* heap, int size, void** blockPtr, int a4)
// to index all blocks for longest moveable extent.
if (maxBlocksCount > gHeapReservedFreeBlockIndexesLength) {
int* indexes = (int*)internal_realloc(gHeapReservedFreeBlockIndexes, sizeof(*gHeapReservedFreeBlockIndexes) * maxBlocksCount);
if (indexes == nullptr) {
if (indexes == NULL) {
goto system;
}
@@ -914,14 +912,14 @@ system:
if (1) {
char stats[512];
if (heapPrintStats(heap, stats, sizeof(stats))) {
if (heapPrintStats(heap, stats)) {
debugPrint("\n%s\n", stats);
}
if (a4 == 0) {
debugPrint("Allocating block from system memory...\n");
unsigned char* block = (unsigned char*)internal_malloc(size + HEAP_BLOCK_OVERHEAD_SIZE);
if (block == nullptr) {
if (block == NULL) {
debugPrint("fatal error: internal_malloc() failed in heap_find_free_block()!\n");
return false;
}
@@ -952,7 +950,7 @@ static bool heapBuildMoveableBlocksList(int extentIndex)
HeapMoveableExtent* extent = &(gHeapMoveableExtents[extentIndex]);
if (extent->moveableBlocksLength > gHeapMoveableBlocksLength) {
unsigned char** moveableBlocks = (unsigned char**)internal_realloc(gHeapMoveableBlocks, sizeof(*gHeapMoveableBlocks) * extent->moveableBlocksLength);
if (moveableBlocks == nullptr) {
if (moveableBlocks == NULL) {
return false;
}
@@ -990,7 +988,7 @@ static bool heapBuildFreeBlocksList(Heap* heap)
if (heap->freeBlocks > gHeapFreeBlocksLength) {
unsigned char** freeBlocks = (unsigned char**)internal_realloc(gHeapFreeBlocks, sizeof(*freeBlocks) * heap->freeBlocks);
if (freeBlocks == nullptr) {
if (freeBlocks == NULL) {
return false;
}
@@ -1063,7 +1061,7 @@ static bool heapBuildMoveableExtentsList(Heap* heap, int* moveableExtentsLengthP
if (maxExtentsCount > gHeapMoveableExtentsLength) {
HeapMoveableExtent* moveableExtents = (HeapMoveableExtent*)internal_realloc(gHeapMoveableExtents, sizeof(*gHeapMoveableExtents) * maxExtentsCount);
if (moveableExtents == nullptr) {
if (moveableExtents == NULL) {
return false;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,53 +0,0 @@
#ifndef FALLOUT_INPUT_H_
#define FALLOUT_INPUT_H_
namespace fallout {
typedef void(IdleFunc)();
typedef void(FocusFunc)(bool focus);
typedef void(TickerProc)();
typedef int(PauseHandler)();
typedef int(ScreenshotHandler)(int width, int height, unsigned char* buffer, unsigned char* palette);
int inputInit(int a1);
void inputExit();
int inputGetInput();
void get_input_position(int* x, int* y);
void _process_bk();
void enqueueInputEvent(int a1);
void inputEventQueueReset();
void tickersExecute();
void tickersAdd(TickerProc* fn);
void tickersRemove(TickerProc* fn);
void tickersEnable();
void tickersDisable();
void pauseHandlerConfigure(int keyCode, PauseHandler* fn);
void takeScreenshot();
int screenshotHandlerDefaultImpl(int width, int height, unsigned char* data, unsigned char* palette);
void screenshotHandlerConfigure(int keyCode, ScreenshotHandler* handler);
unsigned int getTicks();
void inputPauseForTocks(unsigned int ms);
void inputBlockForTocks(unsigned int ms);
unsigned int getTicksSince(unsigned int a1);
unsigned int getTicksBetween(unsigned int a1, unsigned int a2);
unsigned int _get_bk_time();
void inputSetKeyboardKeyRepeatRate(int value);
int inputGetKeyboardKeyRepeatRate();
void inputSetKeyboardKeyRepeatDelay(int value);
int inputGetKeyboardKeyRepeatDelay();
void inputSetFocusFunc(FocusFunc* func);
FocusFunc* inputGetFocusFunc();
void inputSetIdleFunc(IdleFunc* func);
IdleFunc* inputGetIdleFunc();
int _GNW95_input_init();
void _GNW95_process_message();
void _GNW95_clear_time_stamps();
void _GNW95_lost_focus();
void beginTextInput();
void endTextInput();
} // namespace fallout
#endif /* FALLOUT_INPUT_H_ */

View File

@@ -8,6 +8,7 @@
#include "color.h"
#include "combat.h"
#include "config.h"
#include "core.h"
#include "critter.h"
#include "cycle.h"
#include "debug.h"
@@ -15,14 +16,12 @@
#include "draw.h"
#include "endgame.h"
#include "game.h"
#include "game_config.h"
#include "game_mouse.h"
#include "game_sound.h"
#include "geometry.h"
#include "input.h"
#include "item.h"
#include "kb.h"
#include "memory.h"
#include "mouse.h"
#include "object.h"
#include "platform_compat.h"
#include "proto.h"
@@ -30,7 +29,6 @@
#include "proto_types.h"
#include "skill.h"
#include "stat.h"
#include "svga.h"
#include "text_font.h"
#include "tile.h"
#include "window_manager.h"
@@ -124,15 +122,6 @@ static int indicatorBoxCompareByPosition(const void* a, const void* b);
static void indicatorBarRender(int count);
static bool indicatorBarAdd(int indicator);
static void customInterfaceBarInit();
static void customInterfaceBarExit();
static void sidePanelsInit();
static void sidePanelsExit();
static void sidePanelsHide();
static void sidePanelsShow();
static void sidePanelsDraw(const char* path, int win, bool isLeading);
// 0x518F08
static bool gInterfaceBarInitialized = false;
@@ -143,7 +132,7 @@ static bool gInterfaceBarSwapHandsInProgress = false;
static bool gInterfaceBarEnabled = false;
// 0x518F14
static bool gInterfaceBarHidden = false;
static bool _intfaceHidden = false;
// 0x518F18
static int gInventoryButton = -1;
@@ -170,7 +159,7 @@ static int gSingleAttackButton = -1;
static int gInterfaceCurrentHand = HAND_LEFT;
// 0x518F7C
static Rect gInterfaceBarMainActionRect;
static const Rect gInterfaceBarMainActionRect = { 267, 26, 455, 93 };
// 0x518F8C
static int gChangeHandsButton = -1;
@@ -181,7 +170,7 @@ static bool gInterfaceBarEndButtonsIsVisible = false;
// Combat mode curtains rect.
//
// 0x518FA0
static Rect gInterfaceBarEndButtonsRect;
static const Rect gInterfaceBarEndButtonsRect = { 580, 38, 637, 96 };
// 0x518FB0
static int gEndTurnButton = -1;
@@ -190,15 +179,15 @@ static int gEndTurnButton = -1;
static int gEndCombatButton = -1;
// 0x518FD4
static Rect gInterfaceBarActionPointsBarRect;
static const Rect gInterfaceBarActionPointsBarRect = { 316, 14, 406, 19 };
// 0x518FE8
static IndicatorDescription gIndicatorDescriptions[INDICATOR_COUNT] = {
{ 102, true, nullptr }, // ADDICT
{ 100, false, nullptr }, // SNEAK
{ 101, false, nullptr }, // LEVEL
{ 103, true, nullptr }, // POISONED
{ 104, true, nullptr }, // RADIATED
{ 102, true, NULL }, // ADDICT
{ 100, false, NULL }, // SNEAK
{ 101, false, NULL }, // LEVEL
{ 103, true, NULL }, // POISONED
{ 104, true, NULL }, // RADIATED
};
// 0x519024
@@ -289,16 +278,6 @@ static FrmImage _greenLightFrmImage;
static FrmImage _yellowLightFrmImage;
static FrmImage _redLightFrmImage;
int gInterfaceBarContentOffset = 0;
int gInterfaceBarWidth = -1;
bool gInterfaceBarIsCustom = false;
static Art* gCustomInterfaceBarBackground = nullptr;
int gInterfaceSidePanelsImageId = 2;
bool gInterfaceSidePanelsExtendFromScreenEdge = false;
static int gInterfaceSidePanelsLeadingWindow = -1;
static int gInterfaceSidePanelsTrailingWindow = -1;
// intface_init
// 0x45D880
int interfaceInit()
@@ -309,42 +288,33 @@ int interfaceInit()
return -1;
}
customInterfaceBarInit();
gInterfaceBarInitialized = 1;
gInterfaceBarActionPointsBarRect = { 316 + gInterfaceBarContentOffset, 14, 406 + gInterfaceBarContentOffset, 19 };
gInterfaceBarEndButtonsRect = { 580 + gInterfaceBarContentOffset, 38, 637 + gInterfaceBarContentOffset, 96 };
gInterfaceBarMainActionRect = { 267 + gInterfaceBarContentOffset, 26, 455 + gInterfaceBarContentOffset, 93 };
gInterfaceBarInitialized = true;
int interfaceBarWindowX = (screenGetWidth() - gInterfaceBarWidth) / 2;
int interfaceBarWindowX = (screenGetWidth() - INTERFACE_BAR_WIDTH) / 2;
int interfaceBarWindowY = screenGetHeight() - INTERFACE_BAR_HEIGHT;
gInterfaceBarWindow = windowCreate(interfaceBarWindowX, interfaceBarWindowY, gInterfaceBarWidth, INTERFACE_BAR_HEIGHT, _colorTable[0], WINDOW_HIDDEN);
gInterfaceBarWindow = windowCreate(interfaceBarWindowX, interfaceBarWindowY, INTERFACE_BAR_WIDTH, INTERFACE_BAR_HEIGHT, _colorTable[0], WINDOW_HIDDEN);
if (gInterfaceBarWindow == -1) {
// NOTE: Uninline.
return intface_fatal_error(-1);
}
gInterfaceWindowBuffer = windowGetBuffer(gInterfaceBarWindow);
if (gInterfaceWindowBuffer == nullptr) {
if (gInterfaceWindowBuffer == NULL) {
// NOTE: Uninline.
return intface_fatal_error(-1);
}
if (gInterfaceBarIsCustom) {
blitBufferToBuffer(customInterfaceBarGetBackgroundImageData(), gInterfaceBarWidth, INTERFACE_BAR_HEIGHT - 1, gInterfaceBarWidth, gInterfaceWindowBuffer, gInterfaceBarWidth);
} else {
FrmImage backgroundFrmImage;
fid = buildFid(OBJ_TYPE_INTERFACE, 16, 0, 0, 0);
if (!backgroundFrmImage.lock(fid)) {
return intface_fatal_error(-1);
}
blitBufferToBuffer(backgroundFrmImage.getData(), gInterfaceBarWidth, INTERFACE_BAR_HEIGHT - 1, gInterfaceBarWidth, gInterfaceWindowBuffer, gInterfaceBarWidth);
backgroundFrmImage.unlock();
FrmImage backgroundFrmImage;
fid = buildFid(OBJ_TYPE_INTERFACE, 16, 0, 0, 0);
if (!backgroundFrmImage.lock(fid)) {
// NOTE: Uninline.
return intface_fatal_error(-1);
}
blitBufferToBuffer(backgroundFrmImage.getData(), INTERFACE_BAR_WIDTH, INTERFACE_BAR_HEIGHT - 1, INTERFACE_BAR_WIDTH, gInterfaceWindowBuffer, 640);
backgroundFrmImage.unlock();
fid = buildFid(OBJ_TYPE_INTERFACE, 47, 0, 0, 0);
if (!_inventoryButtonNormalFrmImage.lock(fid)) {
// NOTE: Uninline.
@@ -357,7 +327,7 @@ int interfaceInit()
return intface_fatal_error(-1);
}
gInventoryButton = buttonCreate(gInterfaceBarWindow, 211 + gInterfaceBarContentOffset, 40, 32, 21, -1, -1, -1, KEY_LOWERCASE_I, _inventoryButtonNormalFrmImage.getData(), _inventoryButtonPressedFrmImage.getData(), nullptr, 0);
gInventoryButton = buttonCreate(gInterfaceBarWindow, 211, 40, 32, 21, -1, -1, -1, KEY_LOWERCASE_I, _inventoryButtonNormalFrmImage.getData(), _inventoryButtonPressedFrmImage.getData(), NULL, 0);
if (gInventoryButton == -1) {
// NOTE: Uninline.
return intface_fatal_error(-1);
@@ -377,7 +347,7 @@ int interfaceInit()
return intface_fatal_error(-1);
}
gOptionsButton = buttonCreate(gInterfaceBarWindow, 210 + gInterfaceBarContentOffset, 61, 34, 34, -1, -1, -1, KEY_LOWERCASE_O, _optionsButtonNormalFrmImage.getData(), _optionsButtonPressedFrmImage.getData(), nullptr, 0);
gOptionsButton = buttonCreate(gInterfaceBarWindow, 210, 61, 34, 34, -1, -1, -1, KEY_LOWERCASE_O, _optionsButtonNormalFrmImage.getData(), _optionsButtonPressedFrmImage.getData(), NULL, 0);
if (gOptionsButton == -1) {
// NOTE: Uninline.
return intface_fatal_error(-1);
@@ -403,7 +373,7 @@ int interfaceInit()
return intface_fatal_error(-1);
}
gSkilldexButton = buttonCreate(gInterfaceBarWindow, 523 + gInterfaceBarContentOffset, 6, 22, 21, -1, -1, -1, KEY_LOWERCASE_S, _skilldexButtonNormalFrmImage.getData(), _skilldexButtonPressedFrmImage.getData(), nullptr, BUTTON_FLAG_TRANSPARENT);
gSkilldexButton = buttonCreate(gInterfaceBarWindow, 523, 6, 22, 21, -1, -1, -1, KEY_LOWERCASE_S, _skilldexButtonNormalFrmImage.getData(), _skilldexButtonPressedFrmImage.getData(), NULL, BUTTON_FLAG_TRANSPARENT);
if (gSkilldexButton == -1) {
// NOTE: Uninline.
return intface_fatal_error(-1);
@@ -430,7 +400,7 @@ int interfaceInit()
return intface_fatal_error(-1);
}
gMapButton = buttonCreate(gInterfaceBarWindow, 526 + gInterfaceBarContentOffset, 39, 41, 19, -1, -1, -1, KEY_TAB, _mapButtonNormalFrmImage.getData(), _mapButtonPressedFrmImage.getData(), nullptr, BUTTON_FLAG_TRANSPARENT);
gMapButton = buttonCreate(gInterfaceBarWindow, 526, 39, 41, 19, -1, -1, -1, KEY_TAB, _mapButtonNormalFrmImage.getData(), _mapButtonPressedFrmImage.getData(), NULL, BUTTON_FLAG_TRANSPARENT);
if (gMapButton == -1) {
// NOTE: Uninline.
return intface_fatal_error(-1);
@@ -451,7 +421,7 @@ int interfaceInit()
return intface_fatal_error(-1);
}
gPipboyButton = buttonCreate(gInterfaceBarWindow, 526 + gInterfaceBarContentOffset, 77, 41, 19, -1, -1, -1, KEY_LOWERCASE_P, _pipboyButtonNormalFrmImage.getData(), _pipboyButtonPressedFrmImage.getData(), nullptr, 0);
gPipboyButton = buttonCreate(gInterfaceBarWindow, 526, 77, 41, 19, -1, -1, -1, KEY_LOWERCASE_P, _pipboyButtonNormalFrmImage.getData(), _pipboyButtonPressedFrmImage.getData(), NULL, 0);
if (gPipboyButton == -1) {
// NOTE: Uninline.
return intface_fatal_error(-1);
@@ -472,7 +442,7 @@ int interfaceInit()
return intface_fatal_error(-1);
}
gCharacterButton = buttonCreate(gInterfaceBarWindow, 526 + gInterfaceBarContentOffset, 58, 41, 19, -1, -1, -1, KEY_LOWERCASE_C, _characterButtonNormalFrmImage.getData(), _characterButtonPressedFrmImage.getData(), nullptr, 0);
gCharacterButton = buttonCreate(gInterfaceBarWindow, 526, 58, 41, 19, -1, -1, -1, KEY_LOWERCASE_C, _characterButtonNormalFrmImage.getData(), _characterButtonPressedFrmImage.getData(), NULL, 0);
if (gCharacterButton == -1) {
// NOTE: Uninline.
return intface_fatal_error(-1);
@@ -502,13 +472,13 @@ int interfaceInit()
memcpy(_itemButtonUp, _itemButtonNormalFrmImage.getData(), sizeof(_itemButtonUp));
memcpy(_itemButtonDown, _itemButtonPressedFrmImage.getData(), sizeof(_itemButtonDown));
gSingleAttackButton = buttonCreate(gInterfaceBarWindow, 267 + gInterfaceBarContentOffset, 26, 188, 67, -1, -1, -1, -20, _itemButtonUp, _itemButtonDown, nullptr, BUTTON_FLAG_TRANSPARENT);
gSingleAttackButton = buttonCreate(gInterfaceBarWindow, 267, 26, 188, 67, -1, -1, -1, -20, _itemButtonUp, _itemButtonDown, NULL, BUTTON_FLAG_TRANSPARENT);
if (gSingleAttackButton == -1) {
// NOTE: Uninline.
return intface_fatal_error(-1);
}
buttonSetRightMouseCallbacks(gSingleAttackButton, -1, KEY_LOWERCASE_N, nullptr, nullptr);
buttonSetRightMouseCallbacks(gSingleAttackButton, -1, KEY_LOWERCASE_N, NULL, NULL);
buttonSetCallbacks(gSingleAttackButton, _gsound_lrg_butt_press, _gsound_lrg_butt_release);
fid = buildFid(OBJ_TYPE_INTERFACE, 6, 0, 0, 0);
@@ -530,7 +500,7 @@ int interfaceInit()
}
// Swap hands button
gChangeHandsButton = buttonCreate(gInterfaceBarWindow, 218 + gInterfaceBarContentOffset, 6, 22, 21, -1, -1, -1, KEY_LOWERCASE_B, _changeHandsButtonNormalFrmImage.getData(), _changeHandsButtonPressedFrmImage.getData(), nullptr, BUTTON_FLAG_TRANSPARENT);
gChangeHandsButton = buttonCreate(gInterfaceBarWindow, 218, 6, 22, 21, -1, -1, -1, KEY_LOWERCASE_B, _changeHandsButtonNormalFrmImage.getData(), _changeHandsButtonPressedFrmImage.getData(), NULL, BUTTON_FLAG_TRANSPARENT);
if (gChangeHandsButton == -1) {
// NOTE: Uninline.
return intface_fatal_error(-1);
@@ -563,7 +533,7 @@ int interfaceInit()
return intface_fatal_error(-1);
}
blitBufferToBuffer(gInterfaceWindowBuffer + gInterfaceBarWidth * 14 + 316 + gInterfaceBarContentOffset, 90, 5, gInterfaceBarWidth, gInterfaceActionPointsBarBackground, 90);
blitBufferToBuffer(gInterfaceWindowBuffer + 640 * 14 + 316, 90, 5, 640, gInterfaceActionPointsBarBackground, 90);
if (indicatorBarInit() == -1) {
// NOTE: Uninline.
@@ -577,12 +547,9 @@ int interfaceInit()
displayMonitorInit();
// SFALL
sidePanelsInit();
gInterfaceBarEnabled = true;
gInterfaceBarInitialized = false;
gInterfaceBarHidden = true;
_intfaceHidden = 1;
return 0;
}
@@ -593,7 +560,7 @@ void interfaceReset()
interfaceBarEnable();
// NOTE: Uninline.
interfaceBarHide();
intface_hide();
indicatorBarRefresh();
displayMonitorReset();
@@ -608,9 +575,6 @@ void interfaceReset()
void interfaceFree()
{
if (gInterfaceBarWindow != -1) {
// SFALL
sidePanelsExit();
displayMonitorExit();
_redLightFrmImage.unlock();
@@ -693,8 +657,6 @@ void interfaceFree()
}
}
customInterfaceBarExit();
interfaceBarFree();
}
@@ -707,11 +669,11 @@ int interfaceLoad(File* stream)
}
}
bool interfaceBarEnabled;
if (fileReadBool(stream, &interfaceBarEnabled) == -1) return -1;
int interfaceBarEnabled;
if (fileReadInt32(stream, &interfaceBarEnabled) == -1) return -1;
bool interfaceBarHidden;
if (fileReadBool(stream, &interfaceBarHidden) == -1) return -1;
int v2;
if (fileReadInt32(stream, &v2) == -1) return -1;
int interfaceCurrentHand;
if (fileReadInt32(stream, &interfaceCurrentHand) == -1) return -1;
@@ -723,11 +685,11 @@ int interfaceLoad(File* stream)
interfaceBarEnable();
}
if (interfaceBarHidden) {
if (v2) {
// NOTE: Uninline.
interfaceBarHide();
intface_hide();
} else {
interfaceBarShow();
_intface_show();
}
interfaceRenderHitPoints(false);
@@ -763,10 +725,10 @@ int interfaceSave(File* stream)
return -1;
}
if (fileWriteBool(stream, gInterfaceBarEnabled) == -1) return -1;
if (fileWriteBool(stream, gInterfaceBarHidden) == -1) return -1;
if (fileWriteInt32(stream, gInterfaceBarEnabled) == -1) return -1;
if (fileWriteInt32(stream, _intfaceHidden) == -1) return -1;
if (fileWriteInt32(stream, gInterfaceCurrentHand) == -1) return -1;
if (fileWriteBool(stream, gInterfaceBarEndButtonsIsVisible) == -1) return -1;
if (fileWriteInt32(stream, gInterfaceBarEndButtonsIsVisible) == -1) return -1;
return 0;
}
@@ -774,38 +736,29 @@ int interfaceSave(File* stream)
// NOTE: Inlined.
//
// 0x45E9E0
void interfaceBarHide()
void intface_hide()
{
if (gInterfaceBarWindow != -1) {
if (!gInterfaceBarHidden) {
if (!_intfaceHidden) {
windowHide(gInterfaceBarWindow);
gInterfaceBarHidden = true;
_intfaceHidden = 1;
}
}
// SFALL
sidePanelsHide();
indicatorBarRefresh();
}
// 0x45EA10
void interfaceBarShow()
void _intface_show()
{
if (gInterfaceBarWindow != -1) {
if (gInterfaceBarHidden) {
if (_intfaceHidden) {
interfaceUpdateItems(false, INTERFACE_ITEM_ACTION_DEFAULT, INTERFACE_ITEM_ACTION_DEFAULT);
interfaceRenderHitPoints(false);
interfaceRenderArmorClass(false);
windowShow(gInterfaceBarWindow);
sidePanelsShow();
gInterfaceBarHidden = false;
windowUnhide(gInterfaceBarWindow);
_intfaceHidden = false;
}
}
// SFALL
sidePanelsShow();
indicatorBarRefresh();
}
@@ -935,10 +888,10 @@ void interfaceRenderHitPoints(bool animate)
if (animate) {
int delay = 250 / (abs(gInterfaceLastRenderedHitPoints - hp) + 1);
for (int index = 0; index < count; index++) {
interfaceRenderCounter(473 + gInterfaceBarContentOffset, 40, v1[index], v1[index + 1], v2[index], delay);
interfaceRenderCounter(473, 40, v1[index], v1[index + 1], v2[index], delay);
}
} else {
interfaceRenderCounter(473 + gInterfaceBarContentOffset, 40, gInterfaceLastRenderedHitPoints, hp, color, 0);
interfaceRenderCounter(473, 40, gInterfaceLastRenderedHitPoints, hp, color, 0);
}
gInterfaceLastRenderedHitPoints = hp;
@@ -957,7 +910,7 @@ void interfaceRenderArmorClass(bool animate)
delay = 250 / (abs(gInterfaceLastRenderedArmorClass - armorClass) + 1);
}
interfaceRenderCounter(473 + gInterfaceBarContentOffset, 75, gInterfaceLastRenderedArmorClass, armorClass, 0, delay);
interfaceRenderCounter(473, 75, gInterfaceLastRenderedArmorClass, armorClass, 0, delay);
gInterfaceLastRenderedArmorClass = armorClass;
}
@@ -971,7 +924,7 @@ void interfaceRenderActionPoints(int actionPointsLeft, int bonusActionPoints)
return;
}
blitBufferToBuffer(gInterfaceActionPointsBarBackground, 90, 5, 90, gInterfaceWindowBuffer + 14 * gInterfaceBarWidth + gInterfaceBarContentOffset + 316, gInterfaceBarWidth);
blitBufferToBuffer(gInterfaceActionPointsBarBackground, 90, 5, 90, gInterfaceWindowBuffer + 14 * 640 + 316, 640);
if (actionPointsLeft == -1) {
frmData = _redLightFrmImage.getData();
@@ -999,11 +952,11 @@ void interfaceRenderActionPoints(int actionPointsLeft, int bonusActionPoints)
int index;
for (index = 0; index < actionPointsLeft; index++) {
blitBufferToBuffer(frmData, 5, 5, 5, gInterfaceWindowBuffer + 14 * gInterfaceBarWidth + 316 + index * 9 + gInterfaceBarContentOffset, gInterfaceBarWidth);
blitBufferToBuffer(frmData, 5, 5, 5, gInterfaceWindowBuffer + 14 * 640 + 316 + index * 9, 640);
}
for (; index < (actionPointsLeft + bonusActionPoints); index++) {
blitBufferToBuffer(_yellowLightFrmImage.getData(), 5, 5, 5, gInterfaceWindowBuffer + 14 * gInterfaceBarWidth + 316 + gInterfaceBarContentOffset + index * 9, gInterfaceBarWidth);
blitBufferToBuffer(_yellowLightFrmImage.getData(), 5, 5, 5, gInterfaceWindowBuffer + 14 * 640 + 316 + index * 9, 640);
}
if (!gInterfaceBarInitialized) {
@@ -1053,8 +1006,8 @@ int interfaceUpdateItems(bool animated, int leftItemAction, int rightItemAction)
InterfaceItemState* leftItemState = &(gInterfaceItemStates[HAND_LEFT]);
Object* item1 = critterGetItem1(gDude);
if (item1 == leftItemState->item && leftItemState->item != nullptr) {
if (leftItemState->item != nullptr) {
if (item1 == leftItemState->item && leftItemState->item != NULL) {
if (leftItemState->item != NULL) {
leftItemState->isDisabled = dudeIsWeaponDisabled(item1);
leftItemState->itemFid = itemGetInventoryFid(item1);
}
@@ -1064,7 +1017,7 @@ int interfaceUpdateItems(bool animated, int leftItemAction, int rightItemAction)
leftItemState->item = item1;
if (item1 != nullptr) {
if (item1 != NULL) {
leftItemState->isDisabled = dudeIsWeaponDisabled(item1);
leftItemState->primaryHitMode = HIT_MODE_LEFT_WEAPON_PRIMARY;
leftItemState->secondaryHitMode = HIT_MODE_LEFT_WEAPON_SECONDARY;
@@ -1093,7 +1046,7 @@ int interfaceUpdateItems(bool animated, int leftItemAction, int rightItemAction)
// SFALL: Keep selected attack mode.
// CE: Implementation is different.
if (oldItem == nullptr) {
if (oldItem == NULL) {
leftItemState->action = oldAction;
}
}
@@ -1102,8 +1055,8 @@ int interfaceUpdateItems(bool animated, int leftItemAction, int rightItemAction)
InterfaceItemState* rightItemState = &(gInterfaceItemStates[HAND_RIGHT]);
Object* item2 = critterGetItem2(gDude);
if (item2 == rightItemState->item && rightItemState->item != nullptr) {
if (rightItemState->item != nullptr) {
if (item2 == rightItemState->item && rightItemState->item != NULL) {
if (rightItemState->item != NULL) {
rightItemState->isDisabled = dudeIsWeaponDisabled(rightItemState->item);
rightItemState->itemFid = itemGetInventoryFid(rightItemState->item);
}
@@ -1113,7 +1066,7 @@ int interfaceUpdateItems(bool animated, int leftItemAction, int rightItemAction)
rightItemState->item = item2;
if (item2 != nullptr) {
if (item2 != NULL) {
rightItemState->isDisabled = dudeIsWeaponDisabled(item2);
rightItemState->primaryHitMode = HIT_MODE_RIGHT_WEAPON_PRIMARY;
rightItemState->secondaryHitMode = HIT_MODE_RIGHT_WEAPON_SECONDARY;
@@ -1141,7 +1094,7 @@ int interfaceUpdateItems(bool animated, int leftItemAction, int rightItemAction)
// SFALL: Keep selected attack mode.
// CE: Implementation is different.
if (oldItem == nullptr) {
if (oldItem == NULL) {
rightItemState->action = oldAction;
}
}
@@ -1151,7 +1104,7 @@ int interfaceUpdateItems(bool animated, int leftItemAction, int rightItemAction)
Object* newCurrentItem = gInterfaceItemStates[gInterfaceCurrentHand].item;
if (newCurrentItem != oldCurrentItem) {
int animationCode = 0;
if (newCurrentItem != nullptr) {
if (newCurrentItem != NULL) {
if (itemGetType(newCurrentItem) == ITEM_TYPE_WEAPON) {
animationCode = weaponGetAnimationCode(newCurrentItem);
}
@@ -1180,7 +1133,7 @@ int interfaceBarSwapHands(bool animated)
if (animated) {
Object* item = gInterfaceItemStates[gInterfaceCurrentHand].item;
int animationCode = 0;
if (item != nullptr) {
if (item != NULL) {
if (itemGetType(item) == ITEM_TYPE_WEAPON) {
animationCode = weaponGetAnimationCode(item);
}
@@ -1298,7 +1251,7 @@ void _intface_use_item()
gameMouseSetCursor(MOUSE_CURSOR_CROSSHAIR);
gameMouseSetMode(GAME_MOUSE_MODE_CROSSHAIR);
if (!isInCombat()) {
_combat(nullptr);
_combat(NULL);
}
}
} else if (_proto_action_can_use_on(ptr->item->pid)) {
@@ -1355,6 +1308,7 @@ int _intface_update_ammo_lights()
int ratio = 0;
if (p->isWeapon != 0) {
// calls sub_478674 twice, probably because if min/max kind macro
int maximum = ammoGetCapacity(p->item);
if (maximum > 0) {
int current = ammoGetQuantity(p->item);
@@ -1362,6 +1316,7 @@ int _intface_update_ammo_lights()
}
} else {
if (itemGetType(p->item) == ITEM_TYPE_MISC) {
// calls sub_4793D0 twice, probably because if min/max kind macro
int maximum = miscItemGetMaxCharges(p->item);
if (maximum > 0) {
int current = miscItemGetCharges(p->item);
@@ -1370,7 +1325,7 @@ int _intface_update_ammo_lights()
}
}
interfaceUpdateAmmoBar(463 + gInterfaceBarContentOffset, ratio);
interfaceUpdateAmmoBar(463, ratio);
return 0;
}
@@ -1389,7 +1344,7 @@ void interfaceBarEndButtonsShow(bool animated)
int fid = buildFid(OBJ_TYPE_INTERFACE, 104, 0, 0, 0);
CacheEntry* handle;
Art* art = artLock(fid, &handle);
if (art == nullptr) {
if (art == NULL) {
return;
}
@@ -1401,26 +1356,21 @@ void interfaceBarEndButtonsShow(bool animated)
int time = 0;
int frame = 0;
while (frame < frameCount) {
sharedFpsLimiter.mark();
if (getTicksSince(time) >= delay) {
unsigned char* src = artGetFrameData(art, frame, 0);
if (src != nullptr) {
blitBufferToBuffer(src, 57, 58, 57, gInterfaceWindowBuffer + gInterfaceBarWidth * 38 + 580 + gInterfaceBarContentOffset, gInterfaceBarWidth);
if (src != NULL) {
blitBufferToBuffer(src, 57, 58, 57, gInterfaceWindowBuffer + 640 * 38 + 580, 640);
windowRefreshRect(gInterfaceBarWindow, &gInterfaceBarEndButtonsRect);
}
time = getTicks();
time = _get_time();
frame++;
}
gameMouseRefresh();
renderPresent();
sharedFpsLimiter.throttle();
}
} else {
unsigned char* src = artGetFrameData(art, frameCount - 1, 0);
blitBufferToBuffer(src, 57, 58, 57, gInterfaceWindowBuffer + gInterfaceBarWidth * 38 + 580 + gInterfaceBarContentOffset, gInterfaceBarWidth);
blitBufferToBuffer(src, 57, 58, 57, gInterfaceWindowBuffer + 640 * 38 + 580, 640);
windowRefreshRect(gInterfaceBarWindow, &gInterfaceBarEndButtonsRect);
}
@@ -1446,7 +1396,7 @@ void interfaceBarEndButtonsHide(bool animated)
int fid = buildFid(OBJ_TYPE_INTERFACE, 104, 0, 0, 0);
CacheEntry* handle;
Art* art = artLock(fid, &handle);
if (art == nullptr) {
if (art == NULL) {
return;
}
@@ -1460,28 +1410,23 @@ void interfaceBarEndButtonsHide(bool animated)
int frame = artGetFrameCount(art);
while (frame != 0) {
sharedFpsLimiter.mark();
if (getTicksSince(time) >= delay) {
unsigned char* src = artGetFrameData(art, frame - 1, 0);
unsigned char* dest = gInterfaceWindowBuffer + gInterfaceBarWidth * 38 + 580 + gInterfaceBarContentOffset;
if (src != nullptr) {
blitBufferToBuffer(src, 57, 58, 57, dest, gInterfaceBarWidth);
unsigned char* dest = gInterfaceWindowBuffer + 640 * 38 + 580;
if (src != NULL) {
blitBufferToBuffer(src, 57, 58, 57, dest, 640);
windowRefreshRect(gInterfaceBarWindow, &gInterfaceBarEndButtonsRect);
}
time = getTicks();
time = _get_time();
frame--;
}
gameMouseRefresh();
renderPresent();
sharedFpsLimiter.throttle();
}
} else {
unsigned char* dest = gInterfaceWindowBuffer + gInterfaceBarWidth * 38 + 580 + gInterfaceBarContentOffset;
unsigned char* dest = gInterfaceWindowBuffer + 640 * 38 + 580;
unsigned char* src = artGetFrameData(art, 0, 0);
blitBufferToBuffer(src, 57, 58, 57, dest, gInterfaceBarWidth);
blitBufferToBuffer(src, 57, 58, 57, dest, 640);
windowRefreshRect(gInterfaceBarWindow, &gInterfaceBarEndButtonsRect);
}
@@ -1504,7 +1449,7 @@ void interfaceBarEndButtonsRenderGreenLights()
}
soundPlayFile("icombat2");
blitBufferToBufferTrans(lightsFrmImage.getData(), 57, 58, 57, gInterfaceWindowBuffer + 38 * gInterfaceBarWidth + 580 + gInterfaceBarContentOffset, gInterfaceBarWidth);
blitBufferToBufferTrans(lightsFrmImage.getData(), 57, 58, 57, gInterfaceWindowBuffer + 38 * 640 + 580, 640);
windowRefreshRect(gInterfaceBarWindow, &gInterfaceBarEndButtonsRect);
}
}
@@ -1524,7 +1469,7 @@ void interfaceBarEndButtonsRenderRedLights()
}
soundPlayFile("icombat1");
blitBufferToBufferTrans(lightsFrmImage.getData(), 57, 58, 57, gInterfaceWindowBuffer + 38 * gInterfaceBarWidth + 580 + gInterfaceBarContentOffset, gInterfaceBarWidth);
blitBufferToBufferTrans(lightsFrmImage.getData(), 57, 58, 57, gInterfaceWindowBuffer + 38 * 640 + 580, 640);
windowRefreshRect(gInterfaceBarWindow, &gInterfaceBarEndButtonsRect);
}
}
@@ -1827,10 +1772,10 @@ static void interfaceBarSwapHandsAnimatePutAwayTakeOutSequence(int previousWeapo
}
// TODO: Get rid of cast.
animationRegisterCallbackForced(nullptr, nullptr, (AnimationCallback*)_intface_redraw_items_callback, -1);
animationRegisterCallbackForced(NULL, NULL, (AnimationCallback*)_intface_redraw_items_callback, -1);
Object* item = gInterfaceItemStates[gInterfaceCurrentHand].item;
if (item != nullptr && item->lightDistance > 4) {
if (item != NULL && item->lightDistance > 4) {
animationRegisterSetLightDistance(gDude, item->lightDistance, 0);
}
@@ -1842,7 +1787,7 @@ static void interfaceBarSwapHandsAnimatePutAwayTakeOutSequence(int previousWeapo
}
// TODO: Get rid of cast.
animationRegisterCallbackForced(nullptr, nullptr, (AnimationCallback*)_intface_change_fid_callback, -1);
animationRegisterCallbackForced(NULL, NULL, (AnimationCallback*)_intface_change_fid_callback, -1);
if (reg_anim_end() == -1) {
return;
@@ -1856,16 +1801,11 @@ static void interfaceBarSwapHandsAnimatePutAwayTakeOutSequence(int previousWeapo
gameMouseSetCursor(MOUSE_CURSOR_WAIT_WATCH);
while (gInterfaceBarSwapHandsInProgress) {
sharedFpsLimiter.mark();
if (_game_user_wants_to_quit) {
break;
}
inputGetInput();
renderPresent();
sharedFpsLimiter.throttle();
_get_input();
}
gameMouseSetCursor(MOUSE_CURSOR_NONE);
@@ -1900,7 +1840,7 @@ static int endTurnButtonInit()
return -1;
}
gEndTurnButton = buttonCreate(gInterfaceBarWindow, 590 + gInterfaceBarContentOffset, 43, 38, 22, -1, -1, -1, 32, _endTurnButtonNormalFrmImage.getData(), _endTurnButtonPressedFrmImage.getData(), nullptr, 0);
gEndTurnButton = buttonCreate(gInterfaceBarWindow, 590, 43, 38, 22, -1, -1, -1, 32, _endTurnButtonNormalFrmImage.getData(), _endTurnButtonPressedFrmImage.getData(), NULL, 0);
if (gEndTurnButton == -1) {
return -1;
}
@@ -1952,7 +1892,7 @@ static int endCombatButtonInit()
return -1;
}
gEndCombatButton = buttonCreate(gInterfaceBarWindow, 590 + gInterfaceBarContentOffset, 65, 38, 22, -1, -1, -1, 13, _endCombatButtonNormalFrmImage.getData(), _endCombatButtonPressedFrmImage.getData(), nullptr, 0);
gEndCombatButton = buttonCreate(gInterfaceBarWindow, 590, 65, 38, 22, -1, -1, -1, 13, _endCombatButtonNormalFrmImage.getData(), _endCombatButtonPressedFrmImage.getData(), NULL, 0);
if (gEndCombatButton == -1) {
return -1;
}
@@ -1988,19 +1928,19 @@ static void interfaceUpdateAmmoBar(int x, int ratio)
ratio -= 1;
}
unsigned char* dest = gInterfaceWindowBuffer + gInterfaceBarWidth * 26 + x;
unsigned char* dest = gInterfaceWindowBuffer + 640 * 26 + x;
for (int index = 70; index > ratio; index--) {
*dest = 14;
dest += gInterfaceBarWidth;
dest += 640;
}
while (ratio > 0) {
*dest = 196;
dest += gInterfaceBarWidth;
dest += 640;
*dest = 14;
dest += gInterfaceBarWidth;
dest += 640;
ratio -= 2;
}
@@ -2034,7 +1974,7 @@ static int _intface_item_reload()
return -1;
}
const char* sfx = sfxBuildWeaponName(WEAPON_SOUND_EFFECT_READY, gInterfaceItemStates[gInterfaceCurrentHand].item, HIT_MODE_RIGHT_WEAPON_PRIMARY, nullptr);
const char* sfx = sfxBuildWeaponName(WEAPON_SOUND_EFFECT_READY, gInterfaceItemStates[gInterfaceCurrentHand].item, HIT_MODE_RIGHT_WEAPON_PRIMARY, NULL);
soundPlayFile(sfx);
return 0;
@@ -2056,7 +1996,7 @@ static void interfaceRenderCounter(int x, int y, int previousValue, int value, i
}
unsigned char* numbers = _numbersFrmImage.getData() + offset;
unsigned char* dest = gInterfaceWindowBuffer + gInterfaceBarWidth * y;
unsigned char* dest = gInterfaceWindowBuffer + 640 * y;
unsigned char* downSrc = numbers + 90;
unsigned char* upSrc = numbers + 99;
@@ -2082,10 +2022,10 @@ static void interfaceRenderCounter(int x, int y, int previousValue, int value, i
int tens = (normalizedValue / 10) % 10;
int hundreds = normalizedValue / 100;
blitBufferToBuffer(numbers + 9 * hundreds, 9, 17, 360, hundredsDest, gInterfaceBarWidth);
blitBufferToBuffer(numbers + 9 * tens, 9, 17, 360, tensDest, gInterfaceBarWidth);
blitBufferToBuffer(numbers + 9 * ones, 9, 17, 360, onesDest, gInterfaceBarWidth);
blitBufferToBuffer(normalizedSign >= 0 ? plusSrc : minusSrc, 6, 17, 360, signDest, gInterfaceBarWidth);
blitBufferToBuffer(numbers + 9 * hundreds, 9, 17, 360, hundredsDest, 640);
blitBufferToBuffer(numbers + 9 * tens, 9, 17, 360, tensDest, 640);
blitBufferToBuffer(numbers + 9 * ones, 9, 17, 360, onesDest, 640);
blitBufferToBuffer(normalizedSign >= 0 ? plusSrc : minusSrc, 6, 17, 360, signDest, 640);
if (!gInterfaceBarInitialized) {
Rect numbersRect = { x, y, x + 33, y + 17 };
@@ -2099,31 +2039,28 @@ static void interfaceRenderCounter(int x, int y, int previousValue, int value, i
v49 = 1;
}
blitBufferToBuffer(upSrc, 9, 17, 360, onesDest, gInterfaceBarWidth);
blitBufferToBuffer(upSrc, 9, 17, 360, onesDest, 640);
_mouse_info();
gameMouseRefresh();
renderPresent();
inputBlockForTocks(delay);
coreDelay(delay);
windowRefreshRect(gInterfaceBarWindow, &numbersRect);
ones += v49;
if (ones > 9 || ones < 0) {
blitBufferToBuffer(upSrc, 9, 17, 360, tensDest, gInterfaceBarWidth);
blitBufferToBuffer(upSrc, 9, 17, 360, tensDest, 640);
_mouse_info();
gameMouseRefresh();
renderPresent();
inputBlockForTocks(delay);
coreDelay(delay);
windowRefreshRect(gInterfaceBarWindow, &numbersRect);
tens += v49;
ones -= 10 * v49;
if (tens == 10 || tens == -1) {
blitBufferToBuffer(upSrc, 9, 17, 360, hundredsDest, gInterfaceBarWidth);
blitBufferToBuffer(upSrc, 9, 17, 360, hundredsDest, 640);
_mouse_info();
gameMouseRefresh();
renderPresent();
inputBlockForTocks(delay);
coreDelay(delay);
windowRefreshRect(gInterfaceBarWindow, &numbersRect);
hundreds += v49;
@@ -2132,38 +2069,34 @@ static void interfaceRenderCounter(int x, int y, int previousValue, int value, i
hundreds -= 10 * v49;
}
blitBufferToBuffer(downSrc, 9, 17, 360, hundredsDest, gInterfaceBarWidth);
blitBufferToBuffer(downSrc, 9, 17, 360, hundredsDest, 640);
_mouse_info();
gameMouseRefresh();
renderPresent();
inputBlockForTocks(delay);
coreDelay(delay);
windowRefreshRect(gInterfaceBarWindow, &numbersRect);
}
blitBufferToBuffer(downSrc, 9, 17, 360, tensDest, gInterfaceBarWidth);
renderPresent();
inputBlockForTocks(delay);
blitBufferToBuffer(downSrc, 9, 17, 360, tensDest, 640);
coreDelay(delay);
windowRefreshRect(gInterfaceBarWindow, &numbersRect);
}
blitBufferToBuffer(downSrc, 9, 17, 360, onesDest, gInterfaceBarWidth);
blitBufferToBuffer(downSrc, 9, 17, 360, onesDest, 640);
_mouse_info();
gameMouseRefresh();
renderPresent();
inputBlockForTocks(delay);
coreDelay(delay);
windowRefreshRect(gInterfaceBarWindow, &numbersRect);
previousValue += change;
blitBufferToBuffer(numbers + 9 * hundreds, 9, 17, 360, hundredsDest, gInterfaceBarWidth);
blitBufferToBuffer(numbers + 9 * tens, 9, 17, 360, tensDest, gInterfaceBarWidth);
blitBufferToBuffer(numbers + 9 * ones, 9, 17, 360, onesDest, gInterfaceBarWidth);
blitBufferToBuffer(numbers + 9 * hundreds, 9, 17, 360, hundredsDest, 640);
blitBufferToBuffer(numbers + 9 * tens, 9, 17, 360, tensDest, 640);
blitBufferToBuffer(numbers + 9 * ones, 9, 17, 360, onesDest, 640);
blitBufferToBuffer(previousValue >= 0 ? plusSrc : minusSrc, 6, 17, 360, signDest, gInterfaceBarWidth);
blitBufferToBuffer(previousValue >= 0 ? plusSrc : minusSrc, 6, 17, 360, signDest, 640);
_mouse_info();
gameMouseRefresh();
renderPresent();
inputBlockForTocks(delay);
coreDelay(delay);
windowRefreshRect(gInterfaceBarWindow, &numbersRect);
}
}
@@ -2197,7 +2130,7 @@ static int indicatorBarInit()
}
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "%s%s", asc_5186C8, "intrface.msg");
sprintf(path, "%s%s", asc_5186C8, "intrface.msg");
if (rc != -1) {
if (!messageListLoad(&messageList, path)) {
@@ -2222,7 +2155,7 @@ static int indicatorBarInit()
IndicatorDescription* indicatorDescription = &(gIndicatorDescriptions[index]);
indicatorDescription->data = (unsigned char*)internal_malloc(INDICATOR_BOX_WIDTH * INDICATOR_BOX_HEIGHT);
if (indicatorDescription->data == nullptr) {
if (indicatorDescription->data == NULL) {
debugPrint("\nINTRFACE: Error initializing indicator box graphics! **");
while (--index >= 0) {
@@ -2276,9 +2209,9 @@ static void interfaceBarFree()
for (int index = 0; index < INDICATOR_COUNT; index++) {
IndicatorDescription* indicatorBoxDescription = &(gIndicatorDescriptions[index]);
if (indicatorBoxDescription->data != nullptr) {
if (indicatorBoxDescription->data != NULL) {
internal_free(indicatorBoxDescription->data);
indicatorBoxDescription->data = nullptr;
indicatorBoxDescription->data = NULL;
}
}
}
@@ -2301,7 +2234,7 @@ static void indicatorBarReset()
// 0x4614CC
int indicatorBarRefresh()
{
if (gInterfaceBarWindow != -1 && gIndicatorBarIsVisible && !gInterfaceBarHidden) {
if (gInterfaceBarWindow != -1 && gIndicatorBarIsVisible && !_intfaceHidden) {
for (int index = 0; index < INDICATOR_SLOTS_COUNT; index++) {
gIndicatorSlots[index] = -1;
}
@@ -2479,174 +2412,4 @@ bool indicatorBarHide()
return oldIsVisible;
}
static void customInterfaceBarInit()
{
gInterfaceBarContentOffset = gInterfaceBarWidth - 640;
if (gInterfaceBarContentOffset > 0 && screenGetWidth() > 640) {
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "art\\intrface\\HR_IFACE_%d.FRM", gInterfaceBarWidth);
gCustomInterfaceBarBackground = artLoad(path);
}
if (gCustomInterfaceBarBackground != nullptr) {
gInterfaceBarIsCustom = true;
} else {
gInterfaceBarContentOffset = 0;
gInterfaceBarWidth = 640;
gInterfaceBarIsCustom = false;
}
}
static void customInterfaceBarExit()
{
if (gCustomInterfaceBarBackground != nullptr) {
internal_free(gCustomInterfaceBarBackground);
gCustomInterfaceBarBackground = nullptr;
}
}
unsigned char* customInterfaceBarGetBackgroundImageData()
{
if (!gInterfaceBarIsCustom) {
return nullptr;
}
return artGetFrameData(gCustomInterfaceBarBackground, 0, 0);
}
static void sidePanelsInit()
{
if (gInterfaceBarMode) {
return;
}
if (gInterfaceSidePanelsImageId == 0) {
return;
}
if (gInterfaceBarWidth >= screenGetWidth()) {
return;
}
Rect windowRect;
windowGetRect(gInterfaceBarWindow, &windowRect);
gInterfaceSidePanelsLeadingWindow = windowCreate(0, windowRect.top, windowRect.left, windowRect.bottom - windowRect.top + 1, 0, WINDOW_HIDDEN | WINDOW_DONT_MOVE_TOP);
gInterfaceSidePanelsTrailingWindow = windowCreate(windowRect.right + 1, windowRect.top, screenGetWidth() - windowRect.right - 1, windowRect.bottom - windowRect.top + 1, 0, WINDOW_HIDDEN | WINDOW_DONT_MOVE_TOP);
char path[COMPAT_MAX_PATH];
snprintf(path, sizeof(path), "art\\intrface\\HR_IFACELFT%d.frm", gInterfaceSidePanelsImageId);
sidePanelsDraw(path, gInterfaceSidePanelsLeadingWindow, true);
snprintf(path, sizeof(path), "art\\intrface\\HR_IFACERHT%d.frm", gInterfaceSidePanelsImageId);
sidePanelsDraw(path, gInterfaceSidePanelsTrailingWindow, false);
}
static void sidePanelsExit()
{
if (gInterfaceSidePanelsTrailingWindow != -1) {
windowDestroy(gInterfaceSidePanelsTrailingWindow);
gInterfaceSidePanelsTrailingWindow = -1;
}
if (gInterfaceSidePanelsLeadingWindow != -1) {
windowDestroy(gInterfaceSidePanelsLeadingWindow);
gInterfaceSidePanelsLeadingWindow = -1;
}
}
static void sidePanelsHide()
{
if (gInterfaceSidePanelsLeadingWindow != -1) {
windowHide(gInterfaceSidePanelsLeadingWindow);
}
if (gInterfaceSidePanelsTrailingWindow != -1) {
windowHide(gInterfaceSidePanelsTrailingWindow);
}
}
static void sidePanelsShow()
{
if (gInterfaceSidePanelsLeadingWindow != -1) {
windowShow(gInterfaceSidePanelsLeadingWindow);
}
if (gInterfaceSidePanelsTrailingWindow != -1) {
windowShow(gInterfaceSidePanelsTrailingWindow);
}
}
static void sidePanelsDraw(const char* path, int win, bool isLeading)
{
Art* image = artLoad(path);
if (image == nullptr) {
return;
}
unsigned char* imageData = artGetFrameData(image, 0, 0);
int imageWidth = artGetWidth(image, 0, 0);
int imageHeight = artGetHeight(image, 0, 0);
int windowWidth = windowGetWidth(win);
int windowHeight = windowGetHeight(win);
int width = std::min(imageWidth, windowWidth);
if (!gInterfaceSidePanelsExtendFromScreenEdge && isLeading) {
imageData += imageWidth - width;
}
if (gInterfaceSidePanelsExtendFromScreenEdge && !isLeading) {
imageData += imageWidth - width;
}
blitBufferToBufferStretch(imageData,
width,
imageHeight,
imageWidth,
windowGetBuffer(win),
windowWidth,
windowHeight,
windowWidth);
internal_free(image);
}
// NOTE: Follows Sfall implementation of `GetCurrentAttackMode`. It slightly
// differs from `interfaceGetCurrentHitMode` (can return one of `reload` hit
// modes, the default is `punch`).
//
// 0x45EF6C
bool interface_get_current_attack_mode(int* hit_mode)
{
if (gInterfaceBarWindow == -1) {
return false;
}
switch (gInterfaceItemStates[gInterfaceCurrentHand].action) {
case INTERFACE_ITEM_ACTION_PRIMARY_AIMING:
case INTERFACE_ITEM_ACTION_PRIMARY:
*hit_mode = gInterfaceItemStates[gInterfaceCurrentHand].primaryHitMode;
break;
case INTERFACE_ITEM_ACTION_SECONDARY_AIMING:
case INTERFACE_ITEM_ACTION_SECONDARY:
*hit_mode = gInterfaceItemStates[gInterfaceCurrentHand].secondaryHitMode;
break;
case INTERFACE_ITEM_ACTION_RELOAD:
*hit_mode = gInterfaceCurrentHand == HAND_LEFT
? HIT_MODE_LEFT_WEAPON_RELOAD
: HIT_MODE_RIGHT_WEAPON_RELOAD;
break;
default:
*hit_mode = HIT_MODE_PUNCH;
break;
}
return true;
}
} // namespace fallout

View File

@@ -33,19 +33,14 @@ typedef enum InterfaceItemAction {
extern int gInterfaceBarWindow;
extern bool gInterfaceBarMode;
extern int gInterfaceBarWidth;
extern bool gInterfaceBarIsCustom;
extern int gInterfaceBarContentOffset;
extern int gInterfaceSidePanelsImageId;
extern bool gInterfaceSidePanelsExtendFromScreenEdge;
int interfaceInit();
void interfaceReset();
void interfaceFree();
int interfaceLoad(File* stream);
int interfaceSave(File* stream);
void interfaceBarHide();
void interfaceBarShow();
void intface_hide();
void _intface_show();
void interfaceBarEnable();
void interfaceBarDisable();
bool interfaceBarEnabled();
@@ -69,9 +64,6 @@ void interfaceBarEndButtonsRenderRedLights();
int indicatorBarRefresh();
bool indicatorBarShow();
bool indicatorBarHide();
bool interface_get_current_attack_mode(int* hit_mode);
unsigned char* customInterfaceBarGetBackgroundImageData();
} // namespace fallout

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,6 @@
#ifndef INTERPRETER_H
#define INTERPRETER_H
#include "object.h"
#include <setjmp.h>
#include <vector>
@@ -9,9 +8,7 @@
namespace fallout {
// The maximum number of opcodes.
//
// SFALL: Increase number of opcodes.
#define OPCODE_MAX_COUNT 768
#define OPCODE_MAX_COUNT (342)
typedef enum Opcode {
OPCODE_NOOP = 0x8000,
@@ -133,20 +130,15 @@ enum RawValueType {
typedef unsigned short opcode_t;
typedef struct Procedure {
int nameOffset;
int flags;
int time;
int conditionOffset;
int bodyOffset;
int argCount;
int field_0;
int field_4;
int field_8;
int field_C;
int field_10;
int field_14;
} Procedure;
class ProgramValue {
public:
ProgramValue();
ProgramValue(int value);
ProgramValue(Object* value);
typedef struct ProgramValue {
opcode_t opcode;
union {
int integerValue;
@@ -154,14 +146,8 @@ public:
void* pointerValue;
};
bool isEmpty() const;
bool isInt() const;
bool isFloat() const;
bool isString() const;
float asFloat() const;
bool isPointer() const;
int asInt() const;
};
bool isEmpty();
} ProgramValue;
typedef std::vector<ProgramValue> ProgramStack;
@@ -204,7 +190,6 @@ void _interpretOutputFunc(int (*func)(char*));
int _interpretOutput(const char* format, ...);
[[noreturn]] void programFatalError(const char* str, ...);
void _interpretDecStringRef(Program* program, opcode_t a2, int a3);
void programFree(Program* program);
Program* programCreateByPath(const char* path);
char* programGetString(Program* program, opcode_t opcode, int offset);
char* programGetIdentifier(Program* program, int offset);

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