# HG changeset patch
# User unc0rr
# Date 1513465764 -3600
# Node ID 1b2b84315d2790477246e4fe8966f934356f6f03
# Parent 01f88c3b7b66a6e38b9a75c886361449c94223ac# Parent 28cb18c5e7120d7afdc1530749a948aa114c1982
Merge default. This branch is up-to-date and code is working.
diff -r 01f88c3b7b66 -r 1b2b84315d27 .gitignore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.gitignore Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,83 @@
+CMakeCache.txt
+CMakeFiles
+moc_*.cxx
+qrc_*.cxx
+*.o
+*.a
+*.qm
+Makefile
+bin
+*.hi
+*.ppu
+*.*~
+*.core
+hedgewars.pro.user
+config.inc
+cmake_install.cmake
+QTfrontend/hwconsts.cpp
+QTfrontend/servermessages.h
+CPackConfig.cmake
+CPackSourceConfig.cmake
+tools/cmake_uninstall.cmake
+install_manifest.txt
+.DS_Store
+*.swp
+*.orig
+*.diff
+vittorio.*
+project_files/HedgewarsMobile/Data/
+project_files/HedgewarsMobile/Build/
+gameServer/dist/
+misc/liblua/Xcode/build/
+misc/libphysfs/Xcode/build/
+misc/libphyslayer/Xcode/build/
+moc_*.cxx_parameters
+relre:^release\/
+*.log
+*.cmd
+*.diff
+*.patch
+*.orig
+*.bak
+*.rej
+project_files/hwc/*.c
+project_files/hwc/*.h
+project_files/Android-build/SDL-android-project/jni/**
+project_files/Android-build/SDL-android-project/obj
+project_files/Android-build/SDL-android-project/libs/armeabi*
+project_files/Android-build/SDL-android-project/bin
+project_files/Android-build/SDL-android-project/gen
+project_files/Android-build/SDL-android-project/local.properties
+project_files/Android-build/SDL-android-project/project.properties
+project_files/Android-build/SDL-android-project/default.properties
+project_files/Android-build/SDL-android-project/proguard.cfg
+project_files/Android-build/SDL-android-project/.*
+project_files/Android-build/out
+project_files/Android-build/Makefile.android
+hedgewars-build-desktop-Qt*
+hedgewars-build-desktop-Qt*
+*.depends
+tools/build_windows_koda.bat
+share/hedgewars/Data/misc/hwengine.desktop
+*.exe
+_CPack_Packages/
+version_info.txt
+*.tar.*
+*.or
+*.res
+Hedgewars.app/*
+tools/CreateMacBundle.cmake
+share/Info.plist
+CTestTestfile.cmake
+arch.c
+*.swp
+*~.nib
+*.pbxuser
+*.perspective
+*.perspectivev3
+*.project.xcworkspace
+*.xcuserdata
+xcuserdata
+*.mode1v3
+*.mode2v3
+Testing/*
diff -r 01f88c3b7b66 -r 1b2b84315d27 .hgignore
--- a/.hgignore Thu Aug 11 23:05:14 2016 +0300
+++ b/.hgignore Sun Dec 17 00:09:24 2017 +0100
@@ -1,83 +1,89 @@
-glob:CMakeCache.txt
-glob:CMakeFiles
-glob:moc_*.cxx
-glob:qrc_*.cxx
-glob:*.o
-glob:*.a
-glob:*.qm
-glob:Makefile
-glob:bin
-glob:*.hi
-glob:*.ppu
-glob:*.*~
-glob:*.core
-glob:hedgewars.pro.user
-glob:config.inc
-glob:cmake_install.cmake
-glob:QTfrontend/hwconsts.cpp
-glob:QTfrontend/servermessages.h
-glob:CPackConfig.cmake
-glob:CPackSourceConfig.cmake
-glob:tools/cmake_uninstall.cmake
-glob:install_manifest.txt
-glob:.DS_Store
-glob:*.swp
-glob:*.orig
-glob:vittorio.*
-glob:project_files/HedgewarsMobile/Data/
-glob:project_files/HedgewarsMobile/Build/
-glob:gameServer/dist/
-glob:misc/liblua/Xcode/build/
-glob:misc/libphysfs/Xcode/build/
-glob:misc/libphyslayer/Xcode/build/
-glob:moc_*.cxx_parameters
-relre:^release\/
-glob:*.log
-glob:*.cmd
-glob:*.patch
-glob:*.orig
-glob:*.bak
-glob:*.rej
-glob:project_files/hwc/*.c
-glob:project_files/hwc/*.h
-glob:project_files/Android-build/SDL-android-project/jni/**
-glob:project_files/Android-build/SDL-android-project/obj
-glob:project_files/Android-build/SDL-android-project/libs/armeabi*
-glob:project_files/Android-build/SDL-android-project/bin
-glob:project_files/Android-build/SDL-android-project/gen
-glob:project_files/Android-build/SDL-android-project/local.properties
-glob:project_files/Android-build/SDL-android-project/project.properties
-glob:project_files/Android-build/SDL-android-project/default.properties
-glob:project_files/Android-build/SDL-android-project/proguard.cfg
-glob:project_files/Android-build/SDL-android-project/.*
-glob:project_files/Android-build/out
-glob:project_files/Android-build/Makefile.android
-glob:hedgewars-build-desktop-Qt*
-glob:*.depends
-glob:tools/build_windows_koda.bat
-glob:share/hedgewars/Data/misc/hwengine.desktop
-glob:*.exe
-glob:_CPack_Packages/
-glob:version_info.txt
-glob:*.tar.*
-glob:*.or
-glob:*.res
-glob:build-*
-glob:hedgewars-build-*
-glob:*.pro.user
-glob:Hedgewars.app/*
-glob:tools/CreateMacBundle.cmake
-glob:share/Info.plist
-glob:CTestTestfile.cmake
-glob:arch.c
-glob:*.swp
-glob:*~.nib
-glob:*.pbxuser
-glob:*.perspective
-glob:*.perspectivev3
-glob:*.project.xcworkspace
-glob:*.xcuserdata
-glob:xcuserdata
-glob:*.mode1v3
-glob:*.mode2v3
+syntax: regexp
+^release\/
+syntax: glob
+.git
+CMakeCache.txt
+CMakeFiles
+moc_*.cxx
+qrc_*.cxx
+*.o
+*.a
+*.qm
+Makefile
+bin
+*.hi
+*.ppu
+*.*~
+*.core
+hedgewars.pro.user
+config.inc
+cmake_install.cmake
+QTfrontend/hwconsts.cpp
+QTfrontend/servermessages.h
+CPackConfig.cmake
+CPackSourceConfig.cmake
+tools/cmake_uninstall.cmake
+install_manifest.txt
+.DS_Store
+*.swp
+*.orig
+vittorio.*
+project_files/HedgewarsMobile/Data/
+project_files/HedgewarsMobile/Build/
+gameServer/dist/
+misc/liblua/Xcode/build/
+misc/libphysfs/Xcode/build/
+misc/libphyslayer/Xcode/build/
+moc_*.cxx_parameters
+*.log
+*.cmd
+*.patch
+*.orig
+*.bak
+*.rej
+project_files/hwc/*.c
+project_files/hwc/*.h
+project_files/Android-build/SDL-android-project/jni/**
+project_files/Android-build/SDL-android-project/obj
+project_files/Android-build/SDL-android-project/libs/armeabi*
+project_files/Android-build/SDL-android-project/bin
+project_files/Android-build/SDL-android-project/gen
+project_files/Android-build/SDL-android-project/local.properties
+project_files/Android-build/SDL-android-project/project.properties
+project_files/Android-build/SDL-android-project/default.properties
+project_files/Android-build/SDL-android-project/proguard.cfg
+project_files/Android-build/SDL-android-project/.*
+project_files/Android-build/out
+project_files/Android-build/Makefile.android
+hedgewars-build-desktop-Qt*
+hedgewars-build-desktop-Qt*
+*.depends
+tools/build_windows_koda.bat
+share/hedgewars/Data/misc/hwengine.desktop
+*.exe
+_CPack_Packages/
+version_info.txt
+*.tar.*
+*.or
+*.res
+Hedgewars.app/*
+tools/CreateMacBundle.cmake
+share/Info.plist
+CTestTestfile.cmake
+arch.c
+*.swp
+*~.nib
+*.pbxuser
+*.perspective
+*.perspectivev3
+*.project.xcworkspace
+*.xcuserdata
+xcuserdata
+*.mode1v3
+*.mode2v3
+gameServer2/target
+gameServer2/Cargo.lock
+gameServer2/gameServer2.iml
+.idea
+Testing/
diff -r 01f88c3b7b66 -r 1b2b84315d27 .hgtags
--- a/.hgtags Thu Aug 11 23:05:14 2016 +0300
+++ b/.hgtags Sun Dec 17 00:09:24 2017 +0100
@@ -75,3 +75,5 @@
0000000000000000000000000000000000000000 fab746a3597e
d9622394ec9c2974a84b9b4d9e6c0ac26c4060ff 0.9.22-RC
0000000000000000000000000000000000000000 0.9.22-RC
+8cc070640fd1f4affb3c5dd5652b4d75a075c200 0.9.23-alpha
+8610462e3d336e112bffcd7c1530d271242216f1 0.9.23-release
diff -r 01f88c3b7b66 -r 1b2b84315d27 .travis.yml
--- a/.travis.yml Thu Aug 11 23:05:14 2016 +0300
+++ b/.travis.yml Sun Dec 17 00:09:24 2017 +0100
@@ -1,3 +1,5 @@
+sudo: required
+dist: trusty
language: c
sudo: true
os:
@@ -12,6 +14,11 @@
- gcc
- clang
+matrix:
+ exclude:
+ - os: osx
+ compiler: gcc
+
env:
- BUILD_ARGS="-DCMAKE_BUILD_TYPE=Release"
- BUILD_ARGS="-DCMAKE_BUILD_TYPE=Debug"
@@ -59,9 +66,12 @@
install: |
if [ "$TRAVIS_OS_NAME" == "linux" ]; then
- sudo apt-get install debhelper cmake dpkg-dev libqt4-dev qt4-qmake libphysfs-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev libsdl2-net-dev bzip2 ghc libghc-mtl-dev libghc-parsec3-dev libghc-vector-dev libghc-zlib-dev libghc-random-dev libghc-stm-dev libghc-network-dev libghc-dataenc-dev libghc-hslogger-dev libghc-utf8-string-dev libghc-sha-dev libghc-entropy-dev liblua5.1-0-dev imagemagick fpc fp-compiler fp-units-misc libpng-dev fp-units-gfx libavcodec-dev libavformat-dev libglew1.6-dev
+ sudo apt-get install -y debhelper cmake dpkg-dev libqt4-dev qt4-qmake libphysfs-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev libsdl2-net-dev bzip2 ghc libghc-mtl-dev libghc-parsec3-dev libghc-vector-dev libghc-zlib-dev libghc-random-dev libghc-stm-dev libghc-network-dev libghc-sandi-dev libghc-hslogger-dev libghc-utf8-string-dev libghc-sha-dev libghc-entropy-dev libghc-regex-tdfa-dev liblua5.1-0-dev imagemagick fpc fp-compiler fp-units-misc libpng-dev fp-units-gfx libavcodec-dev libavformat-dev libglew1.6-dev
elif [ "$TRAVIS_OS_NAME" == "osx" ]; then
- brew install fpc glew qt physfs lua51 sdl2 sdl2_image sdl2_net sdl2_ttf ffmpeg ghc cabal-install
+ brew tap cartr/qt4
+ brew tap-pin cartr/qt4
+ brew install qt@4
+ brew install fpc glew physfs lua51 sdl2 sdl2_image sdl2_net sdl2_ttf ffmpeg ghc cabal-install
brew install sdl2_mixer --with-libvorbis
# use cabal install haskell deps, pas2c ones are covered by server
if [[ "$BUILD_ARGS" != *"NOSERVER"* ]]; then
@@ -76,8 +86,8 @@
export BUILD_ARGS="$BUILD_ARGS -DNOAUTOUPDATE=1"
elif [ "$TRAVIS_OS_NAME" == "ios" ]; then
# FPC 3.0.0 required for using FPC 3.0.1 which contains rtl for ios
- sudo bash tools/dmg_pkg_install.sh ftp://freepascal.stack.nl/pub/fpc/dist/3.0.0/i386-macosx/fpc-3.0.0.intel-macosx.dmg
- sudo bash tools/dmg_pkg_install.sh ftp://freepascal.stack.nl/pub/fpc/dist/3.0.0/i386-macosx/fpc-3.0.1.intel-macosx.cross.ios.dmg
+ sudo bash tools/dmg_pkg_install.sh ftp://freepascal.stack.nl/pub/mirrors/fpc/dist/3.0.0/i386-macosx/fpc-3.0.0.intel-macosx.dmg
+ sudo bash tools/dmg_pkg_install.sh ftp://freepascal.stack.nl/pub/mirrors/fpc/dist/3.0.0/i386-macosx/fpc-3.0.1.intel-macosx.cross.ios.dmg
fi
before_script: |
diff -r 01f88c3b7b66 -r 1b2b84315d27 CMakeLists.txt
--- a/CMakeLists.txt Thu Aug 11 23:05:14 2016 +0300
+++ b/CMakeLists.txt Sun Dec 17 00:09:24 2017 +0100
@@ -1,5 +1,6 @@
project(hedgewars)
+
#initialise cmake environment
cmake_minimum_required(VERSION 2.6.4)
foreach(hwpolicy CMP0003 CMP0012 CMP0017 CMP0018)
@@ -79,8 +80,8 @@
#versioning
set(CPACK_PACKAGE_VERSION_MAJOR 0)
set(CPACK_PACKAGE_VERSION_MINOR 9)
-set(CPACK_PACKAGE_VERSION_PATCH 23)
-set(HEDGEWARS_PROTO_VER 52)
+set(CPACK_PACKAGE_VERSION_PATCH 24)
+set(HEDGEWARS_PROTO_VER 54)
set(HEDGEWARS_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
include(${CMAKE_MODULE_PATH}/revinfo.cmake)
diff -r 01f88c3b7b66 -r 1b2b84315d27 CREDITS
--- a/CREDITS Thu Aug 11 23:05:14 2016 +0300
+++ b/CREDITS Sun Dec 17 00:09:24 2017 +0100
@@ -1,36 +1,63 @@
-EXTENDED CREDITS LIST
+=============================
+=== EXTENDED CREDITS LIST ===
+=============================
+
+IF NOT OTHERWISE SPECIFIED, ALL OTHER CONTENT IS PROPERTY OF Andrey Korotaev .
+IF NO LICENSE IS SPECIFIED, THE LICENSE IS THE SAME AS MENTIONED IN README.md.
+
+Note: The asterisk is a placeholder which stands for any sequence of characters.
==========
= FONTS
==========
- see Fonts_LICENSE.txt
+=================
+= FRONTEND IMAGES
+=================
+(File name suffixes are omitted)
+
+- Tango Project and Wuzzy -> audio, home (CC0)
+- abustany and Wuzzy -> Videos (CC0)
+- Juliane Krug and Wuzzy -> Palette (CC0)
+- raseone and Wuzzy -> folder (CC0)
+
==========
= FORTS
==========
- Carlos Vives -> Tank (2010)
- Dragonfly -> EvilChicken (2010)
- Randy Broda -> SteelTower (2013)
+- Jon Dum and Wuzzy -> Snail (2017)
+- Maciej Mroziński (a.k.a. alzen) and Wuzzy -> Lonely_Island (2017)
+- Guillaume Englert and Wuzzy -> Olympic (2017)
==========
= HATS
==========
-- Robinator -> Terminator (2010)
-- shingo666 -> Samus (2010)
+- Robinator -> Terminator_Glasses (2010)
+- shingo666 -> ntd_Samus (2010)
- MeinCookie95 -> InfernalHorns (2010), Mummy (2010), war_* (2010-2011)
- thuban -> Elvis (2010)
- Miphica -> Disguise (2010)
-- Blayde -> Deer (2010), Moose (2010)
+- Blayde -> zoo_Deer (2010), zoo_Moose (2010)
- hillis -> AkuAku (2010)
-- Lortinak -> OldMan (2010), ShortHair (2010)
-- chujoii -> BrainSlug (2010), Dragon (2010), Ladle (2010), Laminaria (2010), Pantsu (2010), Pig (2010), Plunger (2010), SauceBoat (2010), ShaggyYeti (2010), SleepWalker (2010), SunWukong (2010), Teapot (2010), Teacup (2010), Zombi (2010)
-- Randy Broda -> Cyclops (2011), Soldier (2011)
-- Wohlstand -> PoliceGirl [based on policecap and sm_daisy] (2014)
+- Lortinak -> OldMan (2010), ShortHair_* (2010)
+- chujoii -> scif_BrainSlug (2010), scif_BrainSlug2 (2010), Dragon (2010), dish_Ladle (2010), Laminaria (2010), Pantsu (2010), zoo_Pig (2010), Plunger (2010), dish_SauceBoatSilver (2010), ShaggyYeti (2010), Sleepwalker (2010), SunWukong (2010), dish_Teapot (2010), dish_Teacup (2010), Zombi (2010)
+- Randy Broda -> cyclops (2011), TeamSoldier (2011)
+- Zav -> zoo_octopus (2009)
+- Star and Moon -> bishop (2011)
+- Gimo -> leprechaun [based on tophats] (2011)
+- Terrington_Snyde -> pirate_eyepatch (2013), jester (2013)
+- Wohlstand -> policegirl [based on policecap and sm_daisy] (2014)
+- TheMadCharles -> barrelhider (CC BY 3.0) (2015)
==========
= GRAVESTONES
==========
-- Randy Broda -> Dragonball (2012)
+- Randy Broda -> dragonball (2012)
+- CheezeMonkey -> pi (2011)
+- rosenholz -> Whisky (2013)
==========
= MAPS
@@ -49,6 +76,7 @@
- Jonatan Nilsson -> Pirate theme, EarthRise (former City) theme, Oriental theme, Snow theme)
- yd - http://opengameart.org/users/yd -> "oriented", used as Olympics SD theme
- Kevin MacLeod - http://incompetech.com/ -> "hitman", used as basis for preliminary default SD theme
+- Valentin Kraevskiy (alias alfadur) -> Jungle theme, Fruit theme
==========
= THEMES
@@ -66,6 +94,12 @@
- Stephen Alexander
==========
+= MISSIONS
+==========
+- Arkhnen -> Teamwork 2 (2012)
+- Wuzzy -> Big Armory (2016)
+
+==========
= SOUNDS
==========
- Mine impact sound from http://www.freesound.org/people/adcbicycle/sounds/13947/
@@ -77,9 +111,28 @@
http://www.freesound.org/people/Jovica/sounds/38317/
- Cleaver impact sound remixed from
http://www.freesound.org/people/sethlind/sounds/265021/
-- Extra Time sound originally by uair01 (CC-BY), remixed from
+- Extra Time sound originally by uair01 (CC-BY 3.0), remixed from
http://www.freesound.org/people/uair01/sounds/65291/
-- Air mine impact sound by Wuzzy (WTFPL), based on
+- Air mine impact sound by Wuzzy (CC-0), based on
http://www.freesound.org/people/batchku/sounds/10479/
+- Rubber duck sounds are in the Public Domain.
+- Countdown sounds by Wuzzy (CC-0)
+- Laser Sight sound originally from drzhn (CC-0), remixed from
+ https://www.freesound.org/people/drzhnn/sounds/199938/
+- Flying Saucer boost sound originally by Jagadamba (CC-BY 3.0), remixed from
+ https://www.freesound.org/people/Jagadamba/sounds/257057/
+- Blowtorch sound originally by rombard (CC-0), remixed from
+ https://www.freesound.org/people/rombart/sounds/197800/
+- Portable Portal Device color switching sound by Wuzzy (CC-0)
+- Portable Portal Device shot sound originally by bubaproducer (CC-BY 3.0), remixed from
+ https://www.freesound.org/people/bubaproducer/sounds/151026/
+- Portal opening sound by Wuzzy (CC-0)
+- Invulnerable sound: remix based on a sound by pepingrillin (CC-0)
+ https://www.freesound.org/people/pepingrillin/sounds/252079/
-ALL OTHER CONTENT IS PROPERTY OF Andrey Korotaev UNLESS OTHERWISE SPECIFIED
+======================
+= LICENSE REFERENCES =
+======================
+
+- CC-BY 3.0: https://creativecommons.org/licenses/by/3.0/
+- CC-0: https://creativecommons.org/publicdomain/zero/1.0/
diff -r 01f88c3b7b66 -r 1b2b84315d27 ChangeLog.txt
--- a/ChangeLog.txt Thu Aug 11 23:05:14 2016 +0300
+++ b/ChangeLog.txt Sun Dec 17 00:09:24 2017 +0100
@@ -1,61 +1,403 @@
+ features
* bugfixes
-0.9.22 -> 0.9.23
+====================== 0.9.23 ======================
+HIGHLIGHTS:
+ + Battalion style
+ + Fort mode is now a map type instead of a scheme setting
+ + Fort mode now works with more than 2 teams
+ + New weapon: rubber duck
+ + New theme, map, 3 forts, 3 missions, some hats and graves
+ + WxW style allows you to select one of many wall sets
+ + Complete HedgeEditor overhaul
+ + Greatly improved script parameter support for many styles
+ + Improves stats screen of most styles and missions
+ + Various improvements for almost all styles
+ + AI hedgehogs can now use Bee, Vamprism, and Time Box
+ + Campaign page now shows your progress
+ + Improved turn timer
+ + Improved randomization options in team and multiplayer pages
+ + Improved theme customization support
+ + Various Lua API additions
+ * Fix cursor often jumping around after clicking
+ * A huge amount of bugfixes for both campaigns, the missions and styles
+ * Video recording functionality is restored
+
Content:
- + New hat: "tf_scout" (this time for real)
+ + New game-style/mode: Battalion (see https://hedgewars.org/wiki/Battalion )
+ + New theme: Beach
+ + New theme music for Jungle and Fruit themes
+ + Change SD theme music for Halloween and Hoggywood (old tracks)
+ + Completely new Cheese map; replaces the old one
+ + New forts: Lonely_Island, Octopus, Olympic, Snail
+ + Many new random hedgehog and team names
+ + Add hats: barrelhider, bishop, jester, leprechaun, pirate_eyepatch, tf_scout, zoo_octopus
+ + Add hair-less variants of old hats: beefeaterhat, lambdahat, nursehat, pirate_bandana, pirate_hat, poke_ash_hat, RamboClean, sf_vega_hat, sf_guile_hat, simple_red, simple_yellow, simple_green, thugclean
+ * Remove hat: tf_scount (this was a duplicate of tf_demoman)
+ * Add graves: Clover, Old_Apple, pi, Simple_reversed, TV, Whisky, Ying_and_Yang
+ * Redo flags: cm_pentagram, cm_soviet, armenia, ireland, nepal, suisse, sweden, turkey
-Game engine:
+Game engine (weapons):
+ + New weapon: rubber duck
+ + Freezer can now freeze sticky mines (they get disabled and fall into the water)
+ + Keep rope / parachute / flying saucer selected when destroyed and secondary ammo selected
+ * Gameplay fix: Hammer damage is now rounded down. This means it will cause NO DAMAGE to a hedgehog with less than 3 hp.
+ * Fixed air strikes drops being off-center
+ * Fixed hedgehogs getting hurt while firing deagle / sniper rifle bullet in certain situations
+ * Fixed mine, sticky mine, seduction, resurrector not working correctly across wrap world edge
+ * Fixed teleportation being able to teleport in land if you clicked across the wrap or bounce world edge
+ * Fixed turn not ending when sticky mine was trapped on rubberband
+ * Rope is now destroyed when attempting to shoot it through wrap or bouncy world edge
+ * Fixed possible to move rope angle below 0° while having secondary weapon selected
+ * Fixed molotov cocktails bouncing vertically off rubber
+ * Fixed sniper rifle disabling laser sight utility after using
+ * Fixed RC planes being able to collect frozen crates
+ * Fixed cake taking over 200 seconds to explode when its stuck and can't move
+ * Fixed Birdy descending into water when hog took damage or died before it got picked up
+ * Fixed player being able to switch to dying hog
+ * Various other fixes
+
+Game engine (gameplay):
+ + Fort Mode will now work with more than 2 teams
+ + Divided Teams mode will now work with more than 2 teams (Hint: you probably want to set world edges to "wrap" in such games)
+ + Frozen hedgehogs can no longer be poisoned
+ + AI hedgehogs can now use Bee, Vampirism and Time Box
+ Improved hedgehog spawns on maps that lack land mass or free space
- + Highlander mode displays game scheme specifics (mines timer, etc.) in ESC info
- + AI hedgehogs can now use Bee and Vampirism
- + Divided Teams mode will now work with more than 2 teams (Hint: you probably want to set world edges to "wrap" in such games)
- + Fort Mode will now work with more than 2 teams
- + Added "Forts" to map type selection. This makes the mode easier selectable/discoverable. Also the slider can be used to adjust the distance between forts.
- + Render graves behind everything else, so that they can't hide mines etc.
+ + Hogs no longer spawn on icy terrain
+ + Temporarily suspend Heavy Wind mode while turn timer is not running
+ + Engine supports now really gigantic maps
+ * Fixed cursor often jumping back to screen center when putting target location while moving cursor
+ * Fixed team getting infinite ammo when stockpiling >= 100 ammo (max. finite ammo is now limited to 99)
+ * Fixed failure to collect crate across wrap world edge
+ * Remove buggy “/finish” chat command
+ * Fix key controls not working in ammo menu: ammo menu, placement, camera/cursor movement keys
+ * Various other fixes
+
+Game engine (graphics, sounds and texts):
+ + Show indicator symbols at bottom right while extra damage or low gravity are active
+ + Color coding for the turn timer: green = ready timer, yellow = turn in progress, red = retreat timer, gray = timer paused
+ + Play countdown sounds at 1-4 seconds turn time
+ Several new sound effects for weapons and utilities
- + Small visual effects enhancements
- + Briefly show theme and music authors in chat at start of game
- * Fixed air-strikes drops being off-center
- * Gameplay fix: Hammer damage is now rounded down. This means it will cause NO DAMAGE to a hedgehog with less than 3 hp.
- * Fixed screenshots being too bright if taken in quick succession
+ + More ticker messages: Hog gets sick, king died, hog was resurrected, hog time travels (and returns), timeout, kamikaze
+ + Small visual effects enhancements: Baseball bat, dynamite and more
+ + Render graves behind everything else, so that they can't hide mines etc.
* Video recording functionality is restored
- * Fixed bee not being affected by wrap world edge while still being thrown
- * Fixed turn not ending when sticky mine was trapped on rubberband
- * Fixed hedgehog-voices missing a response type (Justyouwait/"You're gonna pay for that") on some platforms (e.g. Linux)
- * Fixed SD-flakes of themes not working if regular flakes were disabled
- * Fixed RC planes being able to collect frozen crates
+ * Fixed screenshots being too bright if taken in quick succession
+ * Fixed hedgehog voices missing a response type (Justyouwait/"You're gonna pay for that") on some platforms (e.g. GNU/Linux)
+ * Fixed SD flakes of themes not working if regular flakes were disabled
* Fixed Seduction's "Yoohoo!" sound not playing
- * Fixed Hedgehogs getting hurt while firing deagle / sniper rifle bullet in certains situations
- * Various other fixes
+ * Fixed hedgehogs saying “Missed” when drowning enemy without dealing damage
+ * Fixed enemy saying "Missed” when giving poison without direct damage
+ * Fixed hedgehogs not saying “Stupid” and not displaying announcer message for inflicting self-harm
+ * Fixed incorrect time box tooltip when in Sudden Death
+ * Fixed short sound effect breakdown right after using a time box
+ * Fixed sticky mine sound sometimes playing when shooting portable portal device when a sticky mine is placed on terrain
+ * Fixed hedgehog holding nothing in hand when napalm or piano strike got selected
+ * Fixed excessive water splashes sometimes caused by mines
+
+Highlander:
+ + Show collected weapons after kill and play sound
+ + Mission panel now shows all game modifiers (e.g. mines time, vampirism, etc.)
+ + Loyal Highlander (optional): With “loyal=true” in script param, you only get weapons for enemy kills (clan kills don't count)
+ * Removed "Freezer"/IceGun from the default Highlander weaponset
Construction Mode:
+ Added script parameter support:
+ initialenergy: Amount of energy at start
+ energyperround: New energy per round
- + maxenergy: Maximum allowed
+ + maxenergy: Maximum allowed energy
+ + cratesperround: Maximum placable crates per round
+ + Completely reworked all in-game texts and descriptions
+ * Fix rubber being placable inside land
+ * Fix invalid girder placement costing energy
+ * Special tools like structure placer now have their own proper descriptions (instead of Air Attack description, etc.)
* Costs for weapon and utility crates were all equal
+ * Remove airplane cursor
+ * Fix Lua errors when hog goes to time travel while any filter is in map
* Many other fixes and tweaks
-Missions and Game Styles:
- + Added Basic Flying Saucer Training
+Racer and TechRacer:
+ + Allow to only place 2 waypoints in Racer
+ + Allow to remove Racer waypoints with precise key
+ + New script parameters for Racer:
+ + rounds: Number of rounds to play
+ + waypointradius: Size of waypoints
+ + maxwaypoints: Maximum allowed number of waypoints
+ + Show correct ranking and times in stats screen of Racer and TechRacer
+ * Fix description and icon of waypoint placement tool in Racer
+ * Remove airplane cursor in Racer
+ * Fixed waypoint message in TechRacer and Racer overwriting current weapon selection message
+ * Fixed TechRacer not recording finish if time was >= 100s
+
+WxW:
+ + Support for multiple sets of walls per map
+ + Add optional “Crate Before Attack” rule
+ + Add optional “All But Last” rule
+ + Add optional “Kill The Leader” rule
+ + Script parameter support (see Lua file comment for documentation)
+ + Possible to set max. number of weapons in game (script parameter only)
+ + Menu can be disabled (with script parameter “menu=false”) for insant game start
+ + Possible to set number of crates per turn
+ + Ropes, ShoppaKing, ShoppaHell and ShoppaNeon can now be played with the classic left and right walls
+ + Allows almost all game modifiers to be changed, the only exception is crate probabilities
+ + New wall sets for Ropes, ShoppaNeon, ShoppaDesert, ShoppaWild, ShoppaKing and ShoppaHell.
+ + Basic support for a bunch of Shoppa maps
+ + Fully functional even without a map border
+ + More sound effects
+ + More helpful mission display after configuration has been accepted
+ + Hide “Surf Before Crate” setting if surfing is disabled for this map, or the bottom is active and water never rises
+ + Hide walls setting if script does not provide walls for map yet
+ + Freeze crates at turn start if Walls Before Crate or Surf Before Crate is enabled (they unfreeze if you met requirements)
+ + Allow toggling the radar with Switch Hog key while roping or rope selected
+ * No smoke when hog is near near a WxW wall but walls need not to be touched
+ * Fix other player being able to change the menu config in the short period before the first turn
+
+Tumbler:
+ + Script parameter support:
+ + spawnbarrels: New barrels per turn
+ + spawnmines: New mines per turn
+ + ammoflamer: Initial Flamer fuel
+ + ammobarrel: Initial Barrel Launcher ammo
+ + ammomine: Initial Mine Deployer ammo
+ + minetimerplaced: Mine timer (ms) of mines dropped from Mine Deployer
+ + bonustime: Bonus time (s) in utility crates
+ + bonusflames: Bonus Flamer fuel in ammo crates
+ + chanceammo: Per-turn % chance of an ammo crate drop
+ + chancetime: Per-turn % chance of an utility crate (extra time) drop
+ + Alternative weapon selection with slot keys (F1, F2, F3)
+ + Add mine/barrel launch sounds
+ + Add countdown sounds
+ + Rewrote mission description and captions
+ + Sound and message when trying to fire empty weapon
+ * Permanently disable some game modifiers which won't work together with this
+
+Space Invasion:
+ + Show actual scores in stats screen, and a proper graph
+ + Show a couple of “awards” (snarky comments) in stats screen
+ + Remove bonuses “Boom!”, “BOOM!” and “BOOM!! BOOM!! BOOM!!” for balancing reasons
+ + Script parameter support:
+ + rounds: Number of rounds
+ + shield: Initial shield
+ + barrels: Initial barrel ammo
+ + pings: Available radar pings
+ + timebonus: Time bonus for red drones
+ + barrelbonus: Ammo bonus for green invaders
+ + shieldbonus: Shield bonus for purple invaders
+ + forcetheme: Set to “true” to use the selected theme instead of EarthRise
+ + Complete rewrite of almost all messages and the mission panel
+ + More event messages
+ + Show current score in HUD (white number)
+ + Stop overwriting most game scheme’s parameters
+ + Disable weapon scheme
+ + More sounds: Empty ammo, countdown, throw, kamikaze, radar ping, explosion
+ * Fix explosion being drawn twice when colliding with invader
+
+HedgeEditor:
+ + Dud mine placement mode
+ + Allow to select frames in sprite placement mode
+ + New placable sprite: sprTargetBee
+ + Complete rewrite of all help texts
+ + Allow to add and subtract health
+ + Add more convenient start values (e.g. for health)
+ + Allow to set timer of sticky mines
+ + Health crates can now have 0 health
+ + Hog and team names (from identity modes) are now translatable
+ + Show health/timer above health crates, barrels, mines, sticky mines and air mines
+ + Allow to toggle health/timer display with Precise+3
+ + Allow to toggle main help at any time with Precise+1
+ * Add proper description and name for the gear placement tool (no more fake air attack)
+ * Fix many issues with exported files
+ * Fix placement mode being changable when gear placement tool is not selected
+ * Make land gun spawn in utility crates instead of weapon crates
+ * Stop aggressively showing the mission panel after any button press
+ * Fix placement modes sometimes showing “nil” in caption
+ * Fix girder sprite being displayed at top left for no reason
+ * Ammo names are not hardcoded anymore (no more double work for translators)
+ * Fix many missing or poor-quality texts for translation
+ * Fix error when trying to set ShoppaBalance rank without anything selected
+ * Don't show misleading circle when placing girder/rubber
+ * Disable timer keys 2-4 in rubber placement mode
+ * Fix incorrect weapon crate preview of air attack, drill strike and napalm
+
+Other styles and schemes:
+ + The Specialists: Saints get low gravity
+ + Capture The Flag: Setting number of captures with script parameter “captures=”
+ + Mutant: Show appropriate ranking and graph in stats screen
+ + Shoppa: Don't place air mines
+ * Capture the Flag: Fix flag of first team spawning at second hog instead of first
+ * Gravity: Using the low gravity *utility* had no effect. Now it halves the base gravity of the style
+ * Disable Sudden Death for good in Shoppa game scheme, some game styles and mission maps
+
+A Classic Fairytale:
+ + Mission 4: Add infinite skip
+ + Mission 5: Spare traitor's life with Skip instead of Precise
+ + Mission 6: Add alternate dialogues when killing cyborgs before collecting the crates
+ + Mission 6: Give hero only a portal gun at the final portal seqment, remove the large amount of crate drops
+ + All missions: Clarify mine timers
+ * Mission 1: Leap of faith: Hog was able to walk to the right and get stuck
+ * Mission 1: Leap of faith: Teleport player back to mole when failing
+ * Mission 2: Fix crash when trying to open ammo menu in opening sequence
+ * Mission 2: Fix game sometimes getting stuck after walking back to Leaks A Lot
+ * Mission 2: Fix breakages when heroes died before a new sequence, or together with enemies
+ * Mission 2: Remove restart option when cooperating with cyborg; it messed up things too much
+ * Mission 3: Fix various Lua errors when playing with 2 hogs and one of them dies
+ * Mission 3: Fix broken end sequence after killing cyborg or princess
+ * Mission 3: Fix broken sequence of princess being caged
+ * Mission 3: All girder crates now have 3 girders each
+ * Mission 5: Fix crash when skipping animation while the cyborg talks before the 3rd wave of cannibals starts
+ * Mission 5: Make sure the player can only play with one hog after the cyborg imprisoned the other natives
+ * Mission 5: Fix final animation being stuck if cyborg's way to the left is blocked
+ * Mission 6: Block off left cave entrance to stop player to just rope all the way around
+ * Mission 6: Fix mines not being able to get triggered in first turn
+ * Mission 8: Fix Lua error message at the very beginning and error spam in intro sequence
+ * Mission 10: Fix mission becoming unplayable when all hogs except the traitor died
+ * All missions: Add missing texts for translation
+ * All missions: Fix incorrect crate types
+ * All missions: Rewrite mission texts to state missions more clearly
+ * Fix swapped mission preview images of missions 2 and 3
+
+A Space Adventure:
+ + Side missions save and show your personal best successes (e.g. fastest finish in Hard Flying)
+ + Spacetrip: Show 2 flowers over fully completed planets (with side missions)
+ + All missions: Add skip where it doesn't hurt
+ + All missions: Clarify mine timers
+ + All missions: Improve displaying behaviour of mission panel
+ + All missions: Change team colors
+ + Side missions: Remove or shorten intro sequences
+ + Side missions: Generous ready time to give more time to read the mission panel
+ + Getting to the device: Put device part in a real crate, improve some dialogues
+ + Final mission: Add outro sequence instead of instantly quitting
+ + Bad timing: Improve messaging and choice dialog
+ * Spacetrip: Fix various bugs and logic flaws in the initial mission
+ * A frozen adventure: Fix bazooka and excess freezers (>6) not retained over checkpoints
+ * A frozen adventure: Fix and improve poorly written messages
+ * Getting to the device: Add real crate and correct message for collecting device part
+ * Getting to the device: Remove checkpoints. There was a good chance for these missions to become unwinnable
+ * Searching in the dust: Remove checkpoints. See above.
+ * Searching in the dust: Fix Hog Solo dropping straight down when roping near smuggler
+ * Searching in the dust: Fix incorrect messages after collecting device part
+ * Precise flying: Fix victory not being recognized, also wait for flames to settle before losing
+ * Hard Flying: Fix ending in a Lua error
+ * The First Stop: Fix stats screen showing teams twice
+ * Fruit planet: Fix “Precise shooting” disappearing directly after completing “Bad timing”
+ * Fruit planet: Fix “Getting to the device” not visible when landing on fruit planet with first main mission completed only
+ * Killing The Specialists: Fix killing hog with Deagle gave you chance to use another weapon in same turn
+ * Fix weird behaviour when walking right before the first animation in most missions
+ * Fix a couple of texts being untranslatable
+ * Fix a variety of minor logic flaws in the story
+ * Fix typos
+ * All missions: Fix incorrect crate types
+
+Missions:
+ + New scenario: Teamwork 2
+ + New scenario: Big Armory
+ + New training: Basic Flying Saucer Training
+ Rope-Knocking Challenge was improved (now awards score based on kills and time; taunts for knocking out hedgehogs)
+ + Rewrote some help texts in basic rope training
+ + Graphical effect (black bars) while in cut scenes
+ + Change description and icon for baseball bat in Knockball mission map
+ + Sniper rifle target practice: Dynamite blows up quicker, can also skip with precise key
+ * Fixed mistakes and bad wording of strings in several missions, scripts and campaigns
+ * TrophyRace: Fix hedgehogs not being eliminated anymore after one hog skipped or ran out of time
* Portal Mind Challenge was cleaned up and reworked (especially less awful wording)
- * Fixed TechRacer not recording finish if time was >= 100s
* Fixed Target Practice missions getting stuck when a target dropped into water
- * Fixed mistakes and bad wording of strings in several missions, scripts and campaigns
+ * Climb Home: Fix game getting stuck when a player reached home in multiplayer
+ * Climb Home: Fix Lua error messages and broken stats screen
+ * Sniper rifle target practice: Fix targets spawning twice in dynamite scenes
+ * Sniper rifle target practice: Fix auto-camera generally behaving weird
Frontend:
- + Menu screens got few new icons and other tweaks, e.g. larger dropdown lists for easier access
- + Clicking on "New" in weapon scheme editor now creates empty weapon scheme instead of default
+ + Campaign screen shows which campaigns and missions you've completed so far
+ + Training screen now has 3 mission categories: Training (tutorials), Challenge (get a high score), Scenario (complete a task)
+ + Replaced the Fort Mode game modifier by adding "Forts" to the map type selection. This makes the mode easier selectable/discoverable. Also the slider can be used to adjust the distance between forts.
+ + Menu screens got few new icons and many other tweaks, e.g. larger dropdown lists for easier access
+ + Additional button for just randomizing theme that will not change your selected map
+ + Randomizing map/theme in online mode will not include DLC content
+ + New teams start with a random grave and fort
+ + Hedgewars creates 4 human teams and 2 computer teams on its first launch
+ + Allow to randomize hog names, hats, team name, flag, grave, voice and fort separately
+ + “Random team” button is now able to randomly select from all available hats
+ + Creating new game/weapon schemes guarantees unique names
+ + Custom maps and styles are now marked with an icon instead of an asterisk
+ + Mark custom forts in team editor
+ + Room host can delegate room control to other player by rightclick
+ + Switch from HTTP to HTTPS where possible
+ * Fix flag being selectable for computer players although it had no effect
+ * Campaign screen does no longer show AI-controlled teams
+ * Campaign names and campaign mission names can now be translated
+ * Creating randomized teams now randomizes (almost) every aspect
+ * Fixed mostly broken descriptions for multiplayer mission maps
+ * Clicking on "New" in weapon scheme editor now creates empty weapon scheme instead of default
+ * Fix language names in language list being always in English
+ * Prevent starting game with >48 hogs (because engine doesn't support it yet)
+ * Fix the key for toggling team bars being incorrectly described
+ * Fix caption of stats screen showing only one winner if multiple teams have won
+ * Remove broken “Play again” button appearing in stats page after an online game
+ * Weapons scheme editor: When leaving, it no longer flickers and the selection is not reset to Default
+ * Team editor: Fix old team being retained when renaming a team
+ * Team editor: Automatically rename team when leaving team editor page with an already used team name
+ * Fix broken cancel button in the login window
+
+Content Creation:
+ + Theme objects can now have more than 1 in-land rect specified. You can specify the amount in theme.cfg by adding another number (and a comma) before the first rect
+ + Theme objects can now be placed on water (by setting first in-land rectangle to 0,0,0,0)
+ + Themes can now use flakes with negative falling speed (rising flakes)
+ + Themes can now contain custom sound files: splash.ogg Droplet1.ogg Droplet2.ogg Droplet3.ogg skip.ogg
+ + Themes can now have mirrored clouds and flakes: CloudsL.png, SDCloudsL.png, FlakeL.png, SDFlakeL.png
+ + Water in themes supports custom animation and flow speed with water-animation and sd-water-animation in theme.cfg
+ + Simplified hat format for unanimated hats; a single 32×32 image is enough. For clan hats, use size 64×32, with the color overlay at the right
+ + Ammos.png and Ammos_bw.png in HWPs are now overlayed over the base images; use transparent icons to keep them unchanged from the original
+ + Custom Sudden Death background tint for themes with sd-tint
+ * Default water color was black instead of blue
-Lua-API:
+Translations:
+ + Complete translations: German, Polish
+ + Major translation updates: Scottish Gaelic, Italian
+ + Loading screen can now be translated
+ + A few window titles can be translated
+ + Campaign names and campaign mission names can be translated
+ + A Classic Fairytale, missions 8 and 10 can now be translated
+ * Built-in texts from Qt (e.g. “cut”, “paste”, “copy”) in frontend weren't translated
+ * Remove text from mission images to make them language-neutral
+ * Fix English-only language/country names in language selection
+ * Fix very, very broken mission map descriptions
+
+Lua API:
+ New call: SetCinematicMode(enable) -- e.g. for cutscenes etc.
+ + New call: GetAmmoName(ammoType [, ignoreOverwrite]) -- returns the localized name for the specified ammoType
+ + New call: GetVisualGearType(vgUid) -- returns the visual gear type
+ + New call: SetAmmoTexts(ammoType, name, caption, description) -- Overwrite displayed name and description of an ammo type
+ + New call: SetAmmoDescriptionAppendix(ammoType, descAppend) -- Append a custom text to the description of an ammo type without overwriting it
+ + New call: GetHogFort(gearUid) -- Returns the name of the fort of the hog's team
+ + New call: PlaceRubber(x, y, frameIdx) -- Places a rubber
+ + New call: SendGameResultOff() -- Disable the game automatically setting a game result in the stats screen
+ + New call: SendRankingStatsOff() -- Disable the game automatically filling the team rankings in the stats screen
+ + New call: SendAchievementsStatsOff() -- Disable the game automatically populating the bullet point list in the “Details” section on the stats screen
+ + New call: GetTeamStats(teamname) -- Returns a table of team stats
+ + New call: EndTurn([noTaunts]) -- Ends the current turn
+ + New hook: onVisualGearAdd(vgUid) -- called when a visual gear is added
+ + New hook: onVisualGearDelete(vgUid) -- called when a visual gear is deleted
+ + New hook: onUsedAmmo(ammoType) -- called when ammo has been finished using (e.g. after both shotgun shots)
+ + New variable: AirMinesNum -- Number of air mines being placed on a medium-sized map
+ + New variable: WorldEdge -- World edge type (weNone, weWrap, weBounce, weSea)
+ + New variable: AmmoTypeMax -- Maximum ammo type ID (useful to iterate through all ammo types, starting by 0)
+ + New variable: ReadyTimeLeft -- Remaining ready time, 0 if turn in progress. Can be set in onNewTurn
+ + Locale library: loc_noop -- Mark string for translation but don't translate it
+ + Animate library: AnimInit([startAnimating]) -- New parameter startAnimating: if true, will start game in cinematic mode with most controls disabled. Must play an animation after that
+ + Animate library: AnimSetInputMask(extraInputMask) -- Set input mask in a manner comptible with the Animate library
+ + Animate library: AnimMove(gear, dir, posx, posy, [maxMoveTime]) -- new optional parameter maxMoveTime. If hog did not reach its destination within maxMoveTime milliseconds, animation stops and hog is just teleported there
+ + Gear values: “Boom” -- used to modify explosion size and/or damage for most gears
+ + 8 overridable custom sprites/sounds: sprCustom1-sprCustom8, sndCustom1-sndCustom8
+ * Fixed call: HideHog(gear) -- Fix crash when gear is invalid. Returns true on success or false otherwise
+ * Fixed call: SwitchHog(gear) -- Fix new hog being unable to open ammo menu
+ * Removed call: SetAmmoStore -- Old undocumented function of questional use, has never been used
+ * Fixed variable: Goals -- Fix Goals text being cut off at ca. 255 characters
+ * Fix huge numbers having sign errors on 64-bit architectures
-0.9.21 -> 0.9.22
+====================== 0.9.22 ======================
+ New Weapon / Map object: AirMine (floating mine that will follow nearby hedgehogs)
+ Extensive changes to TechRacer: Variable terrain types, enhanced parameters, hwmap interpreter, fuel limiter, etc.
- + HedgeEditor - create missions/etc. in-game! see http://hedgewars.org/HedgeEditor
+ + HedgeEditor - create missions/etc. in-game! see https://hedgewars.org/HedgeEditor
+ Map previews can now take script parameters into account and preview waypoints in TechRacer
+ Added a couple new flags
+ Various tweaks to the interface and in-game chat
@@ -84,7 +426,7 @@
* Previously missing gear states are now available (gstSubmersible, gstFrozen and gstNoGravity)
* Fixed OnHogAttack giving the incorrect AmmoType (amNothing) under certain conditions
-0.9.20 -> 0.9.21:
+====================== 0.9.21 ======================
+ New type of randomly generated maps: Perlin Maps.
+ Old Random generated maps are more diverse now.
+ Slider for adjusting land generation detail.
@@ -148,7 +490,7 @@
* Fixes:
gfResetHealth is now a available like the other GameFlags
-0.9.19 -> 0.9.20:
+====================== 0.9.20 ======================
+ New campaign, A Space Adventure!
+ Password protected rooms
+ Shapes on drawn maps (ellipses, rectangles) - constrain dimensions with ctrl, as with straight line tool.
@@ -177,7 +519,7 @@
* Fixed context menu/cursor in text areas
* Many bugfixes. Keypad enter in chat, hog sliding freezing game, team name flaws in Windows, localisation of tips, crasher in slots with no weapons, frontend holiday css.
-0.9.18 -> 0.9.19:
+====================== 0.9.19 ======================
+ New Freezer weapon - freezes terrain, water, hedgehogs, mines, cases, explosives
+ Saucer can aim weapons and fire underwater
+ Main graphical user interface overhaul
@@ -212,7 +554,7 @@
* ParseCommand should be safe to use in Lua now, at any time
* Fixes to many weapons. Mudball, blowtorch, explosives, cluster bomb spread, portal.
-0.9.17 -> 0.9.18:
+====================== 0.9.18 ======================
+ 'A Classic Fairytale' Campaign
+ Video recorder (requires ffmpeg/libav)
@@ -241,7 +583,7 @@
* Fix drill strike bug when drill's timer gets ridiculously high value instead of explosion
* Fix some crashes, freezes and memory leaks in frontend and engine
-0.9.16 -> 0.9.17:
+====================== 0.9.17 ======================
+ New theme, Cave
+ New voicepack, Hillbilly
+ More attractive mission screen with previews
@@ -274,7 +616,7 @@
* Many frontend bugfixes, code cleanup. Crash in game abort, flake clipping, invalid state on room close
* Many other engine bugfixes. SDL event crasher, timebox crasher, birdy hang, desync on quits, crash in birdy eggshell, hammer + vamp + invuln, clouds on Deep Space theme, etc
-0.9.15 -> 0.9.16:
+====================== 0.9.16 ======================
+ In-game chat now supports backspace-repeat and Escape to close the text input area
+ Team status bars shrunk/made translucent if they take up a significant portion of the screen
+ Background music change on sudden death mode
@@ -338,7 +680,7 @@
* Fix invisible icons in popup menus
* Various fixes and adjustments
-0.9.14 -> 0.9.15:
+====================== 0.9.15 ======================
+ Ability to create, save and load hand drawn maps
+ New maps: Capture the Flag (Blizzard) Map
+ New themes: Christmas
@@ -365,7 +707,7 @@
+ Variable rope length in scheme
+ Allow hog speech when not your turn
-0.9.13 -> 0.9.14:
+====================== 0.9.14 ======================
+ New audio tracks
+ New forts: EvilChicken, Tank
+ New game modes: AI Survival Mode, Per Hedgehog Ammo, Reset Health, Reset Weapons, Unlimited Attacks
@@ -403,7 +745,7 @@
* Fixed bug that allowed charging a weapon while on rope, leading to frozen timer
* Various bug fixes
-0.9.12 -> 0.9.13:
+====================== 0.9.13 ======================
+ Speed optimizations
+ New weapon: Birdy (carries your hog and lets you throw poisonous eggs at your foes)
+ Hats are visible while using rope and blowtorch
@@ -464,7 +806,7 @@
+ PowerPC architecture supported
* Reduced memory footprint and leakage
-0.9.11 -> 0.9.12:
+====================== 0.9.12 ======================
+ Zoom
+ New weapons: flying saucer, molotov cocktail
+ More sounds
@@ -482,7 +824,7 @@
* Fix rope bugs
* Fix bugs in weapon selection code
-0.9.10 -> 0.9.11:
+====================== 0.9.11 ======================
+ Speech bubbles
+ Many new hats, new graves
+ New taunts
@@ -502,7 +844,7 @@
* Fix crash in parachute/rope if drowning with active girder/teleport
* Fix rope disappearing bug
-0.9.9 -> 0.9.10:
+====================== 0.9.10 ======================
+ Many new hats, maps, themes, updates on existing ones
+ Remove small pixels left by fire
+ Double possible land dimensions, allow up to 48 hedgehogs in game
@@ -527,7 +869,7 @@
* Fix bug with not working toggles 'rectrict joins' and 'restrict team adding'
+ Fix engine slowdown when trying to switch ammo while firing bazooka
-0.9.8 -> 0.9.9:
+====================== 0.9.9 ======================
+ Voicepacks
+ Teams health graphic on statistics page
+ Colorize join/quit messages in chat
@@ -542,7 +884,7 @@
* Fix autogenerated demos/saves filenames problems
* Fix engine freeze when switching hedgehog in certain conditions
-0.9.7 -> 0.9.8:
+====================== 0.9.8 ======================
+ Many net server fixes
+ Lobby on net server
+ Napalm weapon
@@ -558,7 +900,7 @@
* Fix a bug leading to engine silent crash when using whip, bat or firepunch (and probably flame)
* Limit chat history to 250 entries to avoid DoS attack with its use
-0.9.6 -> 0.9.7:
+====================== 0.9.7 ======================
+ Completely redesign the frontend, no longer looks like an ugly program launcher
+ New art
+ Add fullscreen mode to frontend
@@ -582,7 +924,7 @@
* Fixed grenade sound
* AI uses the mortar better
-0.9.5 -> 0.9.6:
+====================== 0.9.6 ======================
+ New Cake weapon
+ New maps: EarthRise, Bamboo, Bath, BambooPlinko
+ New theme EarthRise
@@ -593,7 +935,7 @@
* Fix clouds shaking up
* Repair screenshots capturing
-0.9.4 -> 0.9.5:
+====================== 0.9.5 ======================
+ Taunts
+ Exit confirmation dialog
+ Sudden death
@@ -603,7 +945,7 @@
+ More impressive exposions
* Fix bad sprite when you jump and get hit
-0.9.3 -> 0.9.4:
+====================== 0.9.4 ======================
+ In game chat is now implemented, chat (and taunt!) your buddies during network play
+ Mortar, whip and Kamikaze weapon additions
+ Two new themes, desert island and city
@@ -617,7 +959,7 @@
+ Lots of new graphics
* Many network/gameplay bug fixes
-0.9.2 -> 0.9.3:
+====================== 0.9.3 ======================
+ Switch to OpenGL rendering
+ Massive graphics update
+ New animations, weapon sprites
@@ -633,7 +975,7 @@
* Fix hedgehog moving direction after been shot by shotgun
* Fix bug with handling keys while it is enemy's turn
-0.9 -> 0.9.2:
+====================== 0.9.2 ======================
+ Add registration of net game in web
+ Introduce weapons sets support
diff -r 01f88c3b7b66 -r 1b2b84315d27 INSTALL
--- a/INSTALL Thu Aug 11 23:05:14 2016 +0300
+++ b/INSTALL Sun Dec 17 00:09:24 2017 +0100
@@ -1,47 +1,1 @@
-To compile and install you need:
- - CMake >= 2.6.0
- - FreePascal >= 2.2.4
- - Qt >= 4.7.0
- - SDL >= 2.0
- - SDL_net >= 2.0
- - SDL_mixer >= 2.0
- - SDL_image >= 2.0
- - SDL_ttf >= 2.0
- - Lua = 5.1.0
- - Physfs >= 2.0.0
-For server:
- - Glasgow Haskell Compiler >= 6.10
- - dataenc package
- - hslogger package
-For videorecording:
- - FFmpeg or LibAV
-For compressed screenshots:
- - libpng
-
-Lua will be automatically built if not found.
-
-PhysFS will internally built unless -DPHYSFS_SYSTEM=on is passed to cmake
-(also allows to set PHYSFS_LIBRARY and PHYSFS_INCLUDE_DIR if needed).
-
-1. Configure:
-$ cmake .
-or
-$ cmake -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX="install_prefix" \
--DDATA_INSTALL_DIR="data_dir" -DNOSERVER=1 .
-
-Add -DNOSERVER=0 to compile net server (remember to check out the additional
-dependencies with the hedgewars-server.cabal configuration file. If you have
-Qt installed but it is not found, you can set it up with
--DQT_QMAKE_EXECUTABLE="path_to_qmake".
-To get a glimpse of the main configuration options, you may use this command
-`cat CMakeLists.txt | grep option`
-
-2. Compile:
-$ make
-
-3. Install:
-# make install
-
-
-That's all! Enjoy!
-
+INSTALL.md
\ No newline at end of file
diff -r 01f88c3b7b66 -r 1b2b84315d27 INSTALL.md
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/INSTALL.md Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,203 @@
+Building and installing Hedgewars
+=================================
+
+This file explains to you how to build/compile Hedgewars and how to install it.
+
+See also:
+
+Dependencies
+------------
+
+### Core dependencies
+
+To compile and install Hedgewars, you need at least:
+
+- A C++ compiler (e.g. GCC)
+- CMake >= 2.6.0
+- A make program (e.g. GNU Make)
+- Free Pascal Compiler (FPC) >= 2.2.4
+- Qt = 4.7.0
+- SDL >= 2.0
+- SDL\_net >= 2.0
+- SDL\_mixer >= 2.0
+- SDL\_image >= 2.0
+- SDL\_ttf >= 2.0
+
+### Optional dependencies
+
+For some additional features, you can optionally install these dependencies:
+
+- For Hedgewars:
+ - PhysFS >= 2.0.0 (recommended)
+ - Lua = 5.1.0 (recommended)
+- For PNG screenshots:
+ - libpng >= 1.2 (recommended)
+- For video recording:
+ - FFmpeg or Libav
+- For the Hedgewars Server:
+ - GHC >= 6.10
+ - Various Haskell packages (see below)
+
+PhysFS will be internally built if `-DPHYSFS_SYSTEM=OFF` is passed to `cmake`
+(also allows to set `PHYSFS_LIBRARY` and `PHYSFS_INCLUDE_DIR` if needed).
+
+Lua will be automatically built if not found.
+
+### Hedgewars Server dependencies
+
+The Hedgewars Server is an **optional** separate application.
+It provides the online lobby and allows players to create rooms.
+You will also be able to launch the server from the frontend
+(network play → local network → start server).
+
+**Most players do not need this!**
+
+To compile it, you need:
+
+- Glasgow Haskell Compiler (GHC) >= 6.10
+- These Haskell packages:
+ - `containers`
+ - `vector`
+ - `bytestring`
+ - `network` >= 2.3
+ - `random`
+ - `time`
+ - `mtl` >= 2
+ - `sandi`
+ - `hslogger`
+ - `process`
+ - `deepseq`
+ - `utf8-string`
+ - `SHA`
+ - `entropy`
+ - `zlib` >= 0.5.3 and < 0.6
+ - `regex-tdfa`
+
+
+Building
+--------
+
+### Summary
+
+To build and install Hedgewars, obtain all dependencies, then run:
+
+ $ cmake .
+ $ make
+ # make install
+
+### Step 1: Configure
+
+For a default install with all dependencis, use this command:
+
+ $ cmake .
+
+To build with a custom install directory, instead run:
+
+ $ cmake -DCMAKE_INSTALL_PREFIX="" .
+
+(Replace `` with the directoy in which you
+want Hedgewars to be installed.)
+
+Add the `-DNOSERVER=ON` switch if you do not want to build
+the server.
+
+#### CMake options
+
+For more detailed build settings, change some CMake options.
+Run `ccmake` for an interactive way to edit them.
+
+Important CMake options:
+
+- `CMAKE_INSTALL_PREFIX`: Installation directory
+- `NOSERVER`: Set to `ON` to *not* build the server
+- `NOVIDEOREC`: Set to `ON` to *not* build the video recorder
+- `SYSTEM_PHYSFS`: Set to `OFF` to use Hedgewars-bundled PhysFS
+
+### Step 2: Make
+
+Run:
+
+ $ make
+
+This creates the following files:
+
+- `bin/hedgewars`: Hedgewars
+- `bin/hwengine`: Game engine, can be used to play demos and saved games
+- `bin/hedgewars-server`: Hedgewars Server (optional)
+
+### Step 3: Installation
+
+To install Hedgewars to the install directory run:
+
+ # make install
+
+That's all! Enjoy!
+
+Troubleshooting
+---------------
+
+### Qt is installed but it can't be found
+
+If this happens, set the following CMake option:
+
+ QT_QMAKE_EXECUTABLE=""
+
+(Replace `` with the path to the `qmake` application.)
+
+If this didn't work, make sure you have the correct Qt version
+(see above).
+
+### Hedgewars compiles successfully, but games instantly crash the map preview fails
+
+This is likely to be a problem with PhysFS. Try to build Hedgewars
+with the Hedgewars-bundled PhysFS by setting the CMake option
+`SYSTEM_PHYSFS=OFF`, then try to run `make` again.
+
+If the _bundled_ PhysFS fails, too, this is likely to be a bug in
+Hedgewars, please report at .
+
+### Broken/missing Haskell dependencies
+
+First, try to obtain the missing Haskell packages and make sure GHC
+is up-to date, then try again. Read the error messages carefully
+to figure out missing package names.
+
+If everything fails and you don't need the server, set the CMake
+option `NOSERVER=ON` so the server isn't built at all.
+
+### Error messages related to libavcodec / libavformat
+
+Update Libav or FFmpeg (whatever is present on your system) to
+the latest version or install one of them if you haven't already.
+Then try to build again.
+
+If this still doesn't work and you give up, set the CMake option
+`NOVIDEOREC=ON`, but then the video recording functionality will
+not be available.
+
+### Error messages related to Lua, “undefined reference to `lua_tonumber'”, and so on
+If you get error messages like these:
+
+* /home/username/hw/hedgewars//uScript.pas:226: undefined reference to `lua_tonumber'
+* /home/username/hw/hedgewars/CMakeFiles/hwengine.dir/uScript.o: In function `LUATOVISUALGEARTYPEORD':
+
+There might be something wrong with your Lua installation. Try to install Lua 5.1.
+If this doesn't work, or you don't want to install Lua 5.1, try to build Hedgewars
+with the bundled Lua version.
+
+To build with the bundled Lua version, adding the CMake option `SYSTEM_LUA=OFF`, then
+repeat the building process.
+
+### Cleaning up
+
+In case you want to start over and start with a clean build,
+run `make clean`, then go back to step 2.
+
+If things got seriously out of hand, you may want to reset
+*everything* (even your configuration). If you use the
+Mercural repository, you can run `hg purge --all`. Proceed with
+step 1.
+
+### Still can't build Hedgewars?
+
+Visit us in the forums or IRC (see `README.md`) and ask for help.
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/CMakeLists.txt
--- a/QTfrontend/CMakeLists.txt Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/CMakeLists.txt Sun Dec 17 00:09:24 2017 +0100
@@ -21,9 +21,9 @@
endif()
find_package(SDL2 REQUIRED)
-find_package(SDL2_mixer REQUIRED) #audio in SDLInteraction
+find_package(SDL2_mixer 2 REQUIRED) #audio in SDLInteraction
include_directories(${SDL2_INCLUDE_DIR})
-include_directories(${SDL2MIXER_INCLUDE_DIR})
+include_directories(${SDL2_MIXER_INCLUDE_DIRS})
if(LIBAV_FOUND)
add_definitions(-DVIDEOREC -D__STDC_CONSTANT_MACROS)
@@ -103,11 +103,6 @@
${CMAKE_CURRENT_BINARY_DIR}/hwconsts.cpp
)
-#xfire integration
-if(WIN32)
- list(APPEND hwfr_src util/platform/xfire.cpp util/platform/xfiregameclient.cpp)
-endif(WIN32)
-
if(MINGW)
# resource compilation for mingw
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/hedgewars_rc.o
@@ -208,7 +203,7 @@
list(APPEND HW_LINK_LIBS
${SDL2_LIBRARY}
- ${SDL2MIXER_LIBRARY}
+ ${SDL2_MIXER_LIBRARIES}
)
if(WIN32 AND NOT UNIX)
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/binds.cpp
--- a/QTfrontend/binds.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/binds.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -66,7 +66,8 @@
{"fullscr", "f12", QT_TRANSLATE_NOOP("binds", "change mode"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Toggle fullscreen mode:")},
{"capture", "c", QT_TRANSLATE_NOOP("binds", "capture"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Take a screenshot:")},
{"+speedup", "s", QT_TRANSLATE_NOOP("binds", "speed up replay"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Demo replay:")},
- {"rotmask", "delete", QT_TRANSLATE_NOOP("binds", "hedgehog info"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Toggle labels above hedgehogs:")},
+ //: This refers to the team info bars (name/flag/health) of all teams. These are shown at the bottom center of the screen
+ {"rotmask", "delete", QT_TRANSLATE_NOOP("binds", "toggle team bars"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Heads-up display:")},
#ifdef VIDEOREC
{"record", "r", QT_TRANSLATE_NOOP("binds", "record"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Record video:")}
#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/campaign.cpp
--- a/QTfrontend/campaign.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/campaign.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -23,68 +23,128 @@
#include
#include
-QList getCampMissionList(QString & campaignName, QString & teamName)
+QSettings* getCampTeamFile(QString & campaignName, QString & teamName)
{
- QList missionInfoList;
- QSettings teamfile(cfgdir->absolutePath() + "/Teams/" + teamName + ".hwt", QSettings::IniFormat, 0);
- teamfile.setIniCodec("UTF-8");
-
+ QSettings* teamfile = new QSettings(cfgdir->absolutePath() + "/Teams/" + teamName + ".hwt", QSettings::IniFormat, 0);
+ teamfile->setIniCodec("UTF-8");
// if entry not found check if there is written without _
// if then is found rename it to use _
QString spaceCampName = campaignName;
spaceCampName = spaceCampName.replace(QString("_"),QString(" "));
- if (!teamfile.childGroups().contains("Campaign " + campaignName) and
- teamfile.childGroups().contains("Campaign " + spaceCampName)){
- teamfile.beginGroup("Campaign " + spaceCampName);
- QStringList keys = teamfile.childKeys();
- teamfile.endGroup();
+ if (!teamfile->childGroups().contains("Campaign " + campaignName) and
+ teamfile->childGroups().contains("Campaign " + spaceCampName)){
+ teamfile->beginGroup("Campaign " + spaceCampName);
+ QStringList keys = teamfile->childKeys();
+ teamfile->endGroup();
for (int i=0;ivalue("Campaign " + spaceCampName + "/" + keys[i]);
+ teamfile->setValue("Campaign " + campaignName + "/" + keys[i], value);
}
- teamfile.remove("Campaign " + spaceCampName);
+ teamfile->remove("Campaign " + spaceCampName);
}
- int progress = teamfile.value("Campaign " + campaignName + "/Progress", 0).toInt();
- int unlockedMissions = teamfile.value("Campaign " + campaignName + "/UnlockedMissions", 0).toInt();
+ return teamfile;
+}
+
+/**
+ Returns true if the specified mission has been completed
+ campaignName: Name of the campaign in question
+ missionInList: QComboBox index of the mission as selected in the mission widget
+ teamName: Name of the playing team
+*/
+bool isMissionWon(QString & campaignName, int missionInList, QString & teamName)
+{
+ QSettings* teamfile = getCampTeamFile(campaignName, teamName);
+ int progress = teamfile->value("Campaign " + campaignName + "/Progress", 0).toInt();
+ int unlockedMissions = teamfile->value("Campaign " + campaignName + "/UnlockedMissions", 0).toInt();
+ if(progress>0 and unlockedMissions==0)
+ {
+ QSettings campfile("physfs://Missions/Campaign/" + campaignName + "/campaign.ini", QSettings::IniFormat, 0);
+ campfile.setIniCodec("UTF-8");
+ int totalMissions = campfile.value("MissionNum", 1).toInt();
+ return (progress > (progress - missionInList)) || (progress >= totalMissions);
+ }
+ else if(unlockedMissions>0)
+ {
+ int fileMissionId = missionInList + 1;
+ int actualMissionId = teamfile->value(QString("Campaign %1/Mission%2").arg(campaignName, QString::number(fileMissionId)), false).toInt();
+ return teamfile->value(QString("Campaign %1/Mission%2Won").arg(campaignName, QString::number(actualMissionId)), false).toBool();
+ }
+ else
+ return false;
+}
+
+/** Returns true if the campaign has been won by the team */
+bool isCampWon(QString & campaignName, QString & teamName)
+{
+ QSettings* teamfile = getCampTeamFile(campaignName, teamName);
+ bool won = teamfile->value("Campaign " + campaignName + "/Won", false).toBool();
+ return won;
+}
+
+QSettings* getCampMetaInfo()
+{
+ DataManager & dataMgr = DataManager::instance();
+ // get locale
+ QSettings settings(dataMgr.settingsFileName(),
+ QSettings::IniFormat);
+ QString loc = settings.value("misc/locale", "").toString();
+ if (loc.isEmpty())
+ loc = QLocale::system().name();
+ QString campaignDescFile = QString("physfs://Locale/campaigns_" + loc + ".txt");
+ // if file is non-existant try with language only
+ if (!QFile::exists(campaignDescFile))
+ campaignDescFile = QString("physfs://Locale/campaigns_" + loc.remove(QRegExp("_.*$")) + ".txt");
+
+ // fallback if file for current locale is non-existant
+ if (!QFile::exists(campaignDescFile))
+ campaignDescFile = QString("physfs://Locale/campaigns_en.txt");
+
+ QSettings* m_info = new QSettings(campaignDescFile, QSettings::IniFormat, 0);
+ m_info->setIniCodec("UTF-8");
+
+ return m_info;
+}
+
+/** Returns the localized campaign name */
+QString getRealCampName(const QString & campaignName)
+{
+ QString campaignNameSpaces = QString(campaignName).replace(QString("_"), QString(" "));
+ return getCampMetaInfo()->value(campaignName+".name", campaignNameSpaces).toString();
+}
+
+QList getCampMissionList(QString & campaignName, QString & teamName)
+{
+ QList missionInfoList;
+ QSettings* teamfile = getCampTeamFile(campaignName, teamName);
+
+ int progress = teamfile->value("Campaign " + campaignName + "/Progress", 0).toInt();
+ int unlockedMissions = teamfile->value("Campaign " + campaignName + "/UnlockedMissions", 0).toInt();
QSettings campfile("physfs://Missions/Campaign/" + campaignName + "/campaign.ini", QSettings::IniFormat, 0);
campfile.setIniCodec("UTF-8");
- DataManager & dataMgr = DataManager::instance();
- // get locale
- QSettings settings(dataMgr.settingsFileName(),
- QSettings::IniFormat);
- QString loc = settings.value("misc/locale", "").toString();
- if (loc.isEmpty())
- loc = QLocale::system().name();
- QString campaignDescFile = QString("physfs://Locale/campaigns_" + loc + ".txt");
- // if file is non-existant try with language only
- if (!QFile::exists(campaignDescFile))
- campaignDescFile = QString("physfs://Locale/campaigns_" + loc.remove(QRegExp("_.*$")) + ".txt");
-
- // fallback if file for current locale is non-existant
- if (!QFile::exists(campaignDescFile))
- campaignDescFile = QString("physfs://Locale/campaigns_en.txt");
-
- QSettings m_info(campaignDescFile, QSettings::IniFormat, 0);
- m_info.setIniCodec("UTF-8");
+ QSettings* m_info = getCampMetaInfo();
if(progress>=0 and unlockedMissions==0)
{
for(unsigned int i=progress+1;i>0;i--)
{
MissionInfo missionInfo;
- missionInfo.name = campfile.value(QString("Mission %1/Name").arg(i)).toString();
QString script = campfile.value(QString("Mission %1/Script").arg(i)).toString();
- missionInfo.script = script;
- missionInfo.description = m_info.value(campaignName+"-"+ script.replace(QString(".lua"),QString("")) + ".desc",
+ if(!script.isNull()) {
+ missionInfo.script = script;
+ missionInfo.name = campfile.value(QString("Mission %1/Name").arg(i)).toString();
+ QString scriptPrefix = campaignName+"-"+ script.replace(QString(".lua"),QString(""));
+ missionInfo.realName = m_info->value(scriptPrefix+".name", missionInfo.name).toString();
+ missionInfo.description = m_info->value(scriptPrefix + ".desc",
QObject::tr("No description available")).toString();
- QString image = campfile.value(QString("Mission %1/Script").arg(i)).toString().replace(QString(".lua"),QString(".png"));
- missionInfo.image = ":/res/campaign/"+campaignName+"/"+image;
- if (!QFile::exists(missionInfo.image))
- missionInfo.image = ":/res/CampaignDefault.png";
- missionInfoList.append(missionInfo);
+ QString image = campfile.value(QString("Mission %1/Script").arg(i)).toString().replace(QString(".lua"),QString(".png"));
+ missionInfo.image = ":/res/campaign/"+campaignName+"/"+image;
+ if (!QFile::exists(missionInfo.image))
+ missionInfo.image = ":/res/CampaignDefault.png";
+ missionInfoList.append(missionInfo);
+ }
}
}
else if(unlockedMissions>0)
@@ -92,12 +152,14 @@
for(int i=1;i<=unlockedMissions;i++)
{
QString missionNum = QString("%1").arg(i);
- int missionNumber = teamfile.value("Campaign " + campaignName + "/Mission"+missionNum, -1).toInt();
+ int missionNumber = teamfile->value("Campaign " + campaignName + "/Mission"+missionNum, -1).toInt();
MissionInfo missionInfo;
- missionInfo.name = campfile.value(QString("Mission %1/Name").arg(missionNumber)).toString();
QString script = campfile.value(QString("Mission %1/Script").arg(missionNumber)).toString();
missionInfo.script = script;
- missionInfo.description = m_info.value(campaignName+"-"+ script.replace(QString(".lua"),QString("")) + ".desc",
+ missionInfo.name = campfile.value(QString("Mission %1/Name").arg(missionNumber)).toString();
+ QString scriptPrefix = campaignName+"-"+ script.replace(QString(".lua"),QString(""));
+ missionInfo.realName = m_info->value(scriptPrefix+".name", missionInfo.name).toString();
+ missionInfo.description = m_info->value(scriptPrefix + ".desc",
QObject::tr("No description available")).toString();
QString image = campfile.value(QString("Mission %1/Script").arg(missionNumber)).toString().replace(QString(".lua"),QString(".png"));
missionInfo.image = ":/res/campaign/"+campaignName+"/"+image;
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/campaign.h
--- a/QTfrontend/campaign.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/campaign.h Sun Dec 17 00:09:24 2017 +0100
@@ -20,16 +20,24 @@
#define CAMPAIGN_H
#include
+#include
class MissionInfo
{
public:
QString name;
+ QString realName;
QString description;
QString script;
QString image;
};
+
+QSettings* getCampTeamFile(QString & campaignName, QString & teamName);
+QSettings* getCampMetaInfo();
+bool isCampWon(QString & campaignName, QString & teamName);
+bool isMissionWon(QString & campaignName, int missionInList, QString & teamName);
+QString getRealCampName(const QString & campaignName);
QList getCampMissionList(QString & campaignName, QString & teamName);
#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/game.cpp
--- a/QTfrontend/game.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/game.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -44,6 +44,7 @@
// last game info
QList lastGameStartArgs = QList();
GameType lastGameType = gtNone;
+QString lastTrainingSubFolder = NULL;
GameCFGWidget * lastGameCfg = NULL;
QString lastGameAmmo = NULL;
TeamSelWidget * lastGameTeamSel = NULL;
@@ -153,7 +154,8 @@
team1.setDifficulty(0);
team1.setColor(0);
team1.setNumHedgehogs(4);
- HWNamegen::teamRandomNames(team1,true);
+ HWNamegen::teamRandomEverything(team1);
+ team1.setVoicepack("Default");
HWProto::addStringListToBuffer(teamscfg,
team1.teamGameConfig(100));
@@ -162,8 +164,9 @@
team2.setColor(1);
team2.setNumHedgehogs(4);
do
- HWNamegen::teamRandomNames(team2,true);
+ HWNamegen::teamRandomEverything(team2);
while(!team2.name().compare(team1.name()) || !team2.hedgehog(0).Hat.compare(team1.hedgehog(0).Hat));
+ team2.setVoicepack("Default");
HWProto::addStringListToBuffer(teamscfg,
team2.teamGameConfig(100));
@@ -383,6 +386,8 @@
arguments << "--user-prefix";
arguments << cfgdir->absolutePath();
arguments << "--locale";
+ // TODO: Don't bother translators with this nonsense and detect this file automatically.
+ //: IMPORTANT: This text has a special meaning, do not translate it directly. This is the file name of translation files for the game engine, found in Data/Locale/. Usually, you replace “en” with the ISO-639-1 language code of your language.
arguments << tr("en.txt");
arguments << "--frame-interval";
arguments << QString::number(config->timerInterval());
@@ -430,6 +435,7 @@
void HWGame::PlayDemo(const QString & demofilename, bool isSave)
{
gameType = isSave ? gtSave : gtDemo;
+ lastGameType = gameType;
QFile demofile(demofilename);
if (!demofile.open(QIODevice::ReadOnly))
{
@@ -448,6 +454,9 @@
void HWGame::StartNet()
{
+ lastGameStartArgs.clear();
+ lastGameType = gtNet;
+
gameType = gtNet;
demo.clear();
Start(false);
@@ -476,14 +485,16 @@
SetGameState(gsStarted);
}
-void HWGame::StartTraining(const QString & file)
+void HWGame::StartTraining(const QString & file, const QString & subFolder)
{
lastGameStartArgs.clear();
lastGameStartArgs.append(file);
lastGameType = gtTraining;
+ lastTrainingSubFolder = subFolder;
gameType = gtTraining;
- training = "Missions/Training/" + file + ".lua";
+
+ training = "Missions/" + subFolder + "/" + file + ".lua";
demo.clear();
Start(false);
SetGameState(gsStarted);
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/game.h
--- a/QTfrontend/game.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/game.h Sun Dec 17 00:09:24 2017 +0100
@@ -64,6 +64,7 @@
// last game info
extern QList lastGameStartArgs;
extern GameType lastGameType;
+extern QString lastTrainingSubFolder;
extern GameCFGWidget * lastGameCfg;
extern QString lastGameAmmo;
extern TeamSelWidget * lastGameTeamSel;
@@ -79,7 +80,7 @@
void StartLocal();
void StartQuick();
void StartNet();
- void StartTraining(const QString & file);
+ void StartTraining(const QString & file, const QString & subFolder);
void StartCampaign(const QString & camp, const QString & campScript, const QString & campTeam);
void abort();
GameState gameState;
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/gameuiconfig.cpp
--- a/QTfrontend/gameuiconfig.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/gameuiconfig.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -183,10 +183,9 @@
Form->ui.pageOptions->setDefaultOptions();
// then load user configuration
- Form->ui.pageOptions->framerateBox->setCurrentIndex(
- Form->ui.pageOptions->framerateBox->findData(
- value("videorec/framerate", rec_Framerate()).toString() + " fps",
- Qt::MatchExactly) );
+ int framerateBoxIndex = Form->ui.pageOptions->framerateBox->findData(value("videorec/framerate", rec_Framerate()).toUInt());
+ if(framerateBoxIndex != -1)
+ Form->ui.pageOptions->framerateBox->setCurrentIndex(framerateBoxIndex);
Form->ui.pageOptions->bitrateBox->setValue(value("videorec/bitrate", rec_Bitrate()).toUInt());
bool useGameRes = value("videorec/usegameres",Form->ui.pageOptions->checkUseGameRes->isChecked()).toBool();
if (useGameRes)
@@ -625,10 +624,7 @@
int GameUIConfig::rec_Framerate()
{
- // remove the "fps" label
- QString fpsText = Form->ui.pageOptions->framerateBox->currentText();
- QStringList fpsList = fpsText.split(" ");
- return fpsList.first().toInt();
+ return Form->ui.pageOptions->framerateBox->itemData(Form->ui.pageOptions->framerateBox->currentIndex()).toInt();
}
int GameUIConfig::rec_Bitrate()
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/hedgewars.qrc
--- a/QTfrontend/hedgewars.qrc Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/hedgewars.qrc Sun Dec 17 00:09:24 2017 +0100
@@ -1,6 +1,6 @@
- ../share/hedgewars/Data/Graphics/AmmoMenu/Ammos.png
+ ../share/hedgewars/Data/Graphics/AmmoMenu/Ammos_base.png
res/css/qt.css
res/css/chat.css
res/css/christmas.css
@@ -85,12 +85,20 @@
res/delete.png
res/checked.png
res/unchecked.png
+ res/missionFinished.png
+ res/missionFinishedSelected.png
+ res/dlcMarker.png
+ res/dlcMarkerSelected.png
res/graphicsicon.png
+ res/frontendicon.png
+ res/folder.png
res/miscicon.png
res/Load.png
res/Save.png
res/Record.png
res/Videos.png
+ res/Palette.png
+ res/schemeicon.png
res/weaponsicon.png
res/teamicon.png
res/panelbg.png
@@ -101,7 +109,6 @@
res/PlaySound.png
res/hh_small.png
res/btnDisabled.png
- res/btnForts@2x.png
res/btnBorder@2x.png
res/btnInvulnerable@2x.png
res/btnLaserSight@2x.png
@@ -127,6 +134,7 @@
res/btnTagTeam@2x.png
res/btnBottomBorder@2x.png
res/iconBox.png
+ res/iconInitHealth.png
res/iconHealth.png
res/iconHealthPercent.png
res/iconSuddenDeath.png
@@ -148,6 +156,7 @@
res/iconScript.png
res/dice.png
res/Star.png
+ res/home.png
res/inverse-corner-bl.png
res/Flake.png
res/Egg.png
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/hwconsts.cpp.in
--- a/QTfrontend/hwconsts.cpp.in Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/hwconsts.cpp.in Sun Dec 17 00:09:24 2017 +0100
@@ -72,12 +72,15 @@
<< qMakePair(QString("Highlander"), QString(
AMMOLINE_HIGHLANDER_QT AMMOLINE_HIGHLANDER_PROB
AMMOLINE_HIGHLANDER_DELAY AMMOLINE_HIGHLANDER_CRATE ))
- << qMakePair(QString("Construction Mode"), QString(
+ << qMakePair(QString("Construction Mode"), QString(
AMMOLINE_CONSTRUCTION_QT AMMOLINE_CONSTRUCTION_PROB
AMMOLINE_CONSTRUCTION_DELAY AMMOLINE_CONSTRUCTION_CRATE ))
- << qMakePair(QString("Shoppa Pro"), QString(
+ << qMakePair(QString("Shoppa Pro"), QString(
AMMOLINE_SHOPPAPRO_QT AMMOLINE_SHOPPAPRO_PROB
AMMOLINE_SHOPPAPRO_DELAY AMMOLINE_SHOPPAPRO_CRATE ))
+ << qMakePair(QString("HedgeEditor"), QString(
+ AMMOLINE_HEDGEEDITOR_QT AMMOLINE_HEDGEEDITOR_PROB
+ AMMOLINE_HEDGEEDITOR_DELAY AMMOLINE_HEDGEEDITOR_CRATE ))
;
unsigned int colors[] = HW_TEAMCOLOR_ARRAY;
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/hwconsts.h
--- a/QTfrontend/hwconsts.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/hwconsts.h Sun Dec 17 00:09:24 2017 +0100
@@ -73,7 +73,7 @@
#define HEDGEHOGS_PER_TEAM 8
-// see http://en.wikipedia.org/wiki/List_of_colors
+// see https://en.wikipedia.org/wiki/List_of_colors
/*define HW_TEAMCOLOR_ARRAY {0xff007fff, /. azure ./ \
0xffdd0000, /. classic red ./ \
0xff3e9321, /. classic green ./ \
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/hwform.cpp
--- a/QTfrontend/hwform.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/hwform.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -46,6 +46,8 @@
#include
#include
#include
+#include
+#include
#if (QT_VERSION >= 0x040600)
#include
@@ -90,7 +92,6 @@
#include "input_password.h"
#include "ammoSchemeModel.h"
#include "bgwidget.h"
-#include "xfire.h"
#include "drawmapwidget.h"
#include "mouseoverfilter.h"
#include "roomslistmodel.h"
@@ -129,6 +130,8 @@
bool frontendEffects = true;
QString playerHash;
+QIcon finishedIcon;
+QIcon notFinishedIcon;
GameUIConfig* HWForm::config = NULL;
HWForm::HWForm(QWidget *parent, QString styleSheet)
@@ -142,10 +145,19 @@
// set music track
SDLInteraction::instance().setMusicTrack("/Music/main_theme.ogg");
-#ifdef USE_XFIRE
- xfire_init();
-#endif
this->setStyleSheet(styleSheet);
+
+
+ QIcon * hwIcon = new QIcon();
+ hwIcon->addFile(":/res/hh_small.png");
+ //hwIcon->addFile(":/res/hh25x25.png");
+ // crop-workaround for the fact that hh25x25.png is actually 25x35
+ QPixmap pm(":/res/hh25x25.png");
+ hwIcon->addPixmap(pm.copy(0,(pm.height()-25)/2,25,25));
+ hwIcon->addFile(":/res/teamicon.png");
+ hwIcon->addFile(":/res/teamicon2.png");
+
+ this->setWindowIcon(*hwIcon);
ui.setupUi(this);
setMinimumSize(760, 580);
//setFocusPolicy(Qt::StrongFocus);
@@ -157,6 +169,15 @@
frontendEffects = config->value("frontend/effects", true).toBool();
playerHash = QString(QCryptographicHash::hash(config->value("net/nick",tr("Guest")+QString("%1").arg(rand())).toString().toUtf8(), QCryptographicHash::Md5).toHex());
+ // Icons for finished missions
+ finishedIcon.addFile(":/res/missionFinished.png", QSize(), QIcon::Normal, QIcon::On);
+ finishedIcon.addFile(":/res/missionFinishedSelected.png", QSize(), QIcon::Selected, QIcon::On);
+
+ // A transparent icon, used to nicely align the unfinished missions with the finished ones
+ QPixmap emptySpace = QPixmap(15, 15);
+ emptySpace.fill(QColor(0, 0, 0, 0));
+ notFinishedIcon = QIcon(emptySpace);
+
ui.pageRoomsList->setSettings(config);
ui.pageNetGame->setSettings(config);
ui.pageNetGame->chatWidget->setSettings(config);
@@ -198,6 +219,7 @@
UpdateTeamsLists();
InitCampaignPage();
UpdateCampaignPage(0);
+ UpdateCampaignPageTeam(0);
UpdateCampaignPageMission(0);
UpdateWeapons();
@@ -243,7 +265,7 @@
ui.pageMultiplayer->BtnStartMPGame, SLOT(setEnabled(bool)));
connect(ui.pageMultiplayer, SIGNAL(SetupClicked()), this, SLOT(IntermediateSetup()));
connect(ui.pageMultiplayer->gameCFG, SIGNAL(goToSchemes(int)), this, SLOT(GoToScheme(int)));
- connect(ui.pageMultiplayer->gameCFG, SIGNAL(goToWeapons(int)), this, SLOT(GoToSelectWeaponSet(int)));
+ connect(ui.pageMultiplayer->gameCFG, SIGNAL(goToWeapons(int)), this, SLOT(GoToWeapons(int)));
connect(ui.pageMultiplayer->gameCFG, SIGNAL(goToDrawMap()), pageSwitchMapper, SLOT(map()));
pageSwitchMapper->setMapping(ui.pageMultiplayer->gameCFG, ID_PAGE_DRAWMAP);
@@ -257,14 +279,13 @@
connect(ui.pageOptions, SIGNAL(goBack()), config, SLOT(SaveOptions()));
connect(ui.pageOptions->BtnAssociateFiles, SIGNAL(clicked()), this, SLOT(AssociateFiles()));
- connect(ui.pageOptions->WeaponEdit, SIGNAL(clicked()), this, SLOT(GoToSelectWeapon()));
- connect(ui.pageOptions->WeaponNew, SIGNAL(clicked()), this, SLOT(GoToSelectNewWeapon()));
+ connect(ui.pageOptions->WeaponEdit, SIGNAL(clicked()), this, SLOT(GoToEditWeapons()));
+ connect(ui.pageOptions->WeaponNew, SIGNAL(clicked()), this, SLOT(GoToNewWeapons()));
connect(ui.pageOptions->WeaponDelete, SIGNAL(clicked()), this, SLOT(DeleteWeaponSet()));
connect(ui.pageOptions->SchemeEdit, SIGNAL(clicked()), this, SLOT(GoToEditScheme()));
connect(ui.pageOptions->SchemeNew, SIGNAL(clicked()), this, SLOT(GoToNewScheme()));
connect(ui.pageOptions->SchemeDelete, SIGNAL(clicked()), this, SLOT(DeleteScheme()));
connect(ui.pageOptions->CBFrontendEffects, SIGNAL(toggled(bool)), this, SLOT(onFrontendEffects(bool)) );
- connect(ui.pageSelectWeapon->pWeapons, SIGNAL(weaponsChanged()), this, SLOT(UpdateWeapons()));
connect(ui.pageNet->BtnSpecifyServer, SIGNAL(clicked()), this, SLOT(NetConnect()));
connect(ui.pageNet->BtnNetSvrStart, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
@@ -278,7 +299,7 @@
ui.pageNetGame->BtnStart, SLOT(setEnabled(bool)));
connect(ui.pageNetGame, SIGNAL(SetupClicked()), this, SLOT(IntermediateSetup()));
connect(ui.pageNetGame->pGameCFG, SIGNAL(goToSchemes(int)), this, SLOT(GoToScheme(int)));
- connect(ui.pageNetGame->pGameCFG, SIGNAL(goToWeapons(int)), this, SLOT(GoToSelectWeaponSet(int)));
+ connect(ui.pageNetGame->pGameCFG, SIGNAL(goToWeapons(int)), this, SLOT(GoToWeapons(int)));
connect(ui.pageNetGame->pGameCFG, SIGNAL(goToDrawMap()), pageSwitchMapper, SLOT(map()));
pageSwitchMapper->setMapping(ui.pageNetGame->pGameCFG, ID_PAGE_DRAWMAP);
@@ -303,21 +324,23 @@
connect(ui.pageSinglePlayer->BtnLoad, SIGNAL(clicked()), this, SLOT(GoToSaves()));
connect(ui.pageSinglePlayer->BtnDemos, SIGNAL(clicked()), this, SLOT(GoToDemos()));
- connect(ui.pageTraining, SIGNAL(startMission(const QString&)), this, SLOT(startTraining(const QString&)));
+ connect(ui.pageTraining, SIGNAL(startMission(const QString&, const QString&)), this, SLOT(startTraining(const QString&, const QString&)));
connect(ui.pageCampaign->BtnStartCampaign, SIGNAL(clicked()), this, SLOT(StartCampaign()));
connect(ui.pageCampaign->btnPreview, SIGNAL(clicked()), this, SLOT(StartCampaign()));
connect(ui.pageCampaign->CBTeam, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateCampaignPage(int)));
+ connect(ui.pageCampaign->CBTeam, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateCampaignPageTeam(int)));
connect(ui.pageCampaign->CBCampaign, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateCampaignPage(int)));
connect(ui.pageCampaign->CBMission, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateCampaignPageMission(int)));
- connect(ui.pageSelectWeapon->BtnDelete, SIGNAL(clicked()),
- ui.pageSelectWeapon->pWeapons, SLOT(deleteWeaponsName())); // executed first
- connect(ui.pageSelectWeapon->pWeapons, SIGNAL(weaponsDeleted()),
- this, SLOT(UpdateWeapons())); // executed second
- //connect(ui.pageSelectWeapon->pWeapons, SIGNAL(weaponsDeleted()),
- // this, SLOT(GoBack())); // executed third
-
+ connect(ui.pageSelectWeapon->pWeapons, SIGNAL(weaponsDeleted(QString)),
+ this, SLOT(DeleteWeapons(QString)));
+ connect(ui.pageSelectWeapon->pWeapons, SIGNAL(weaponsAdded(QString, QString)),
+ this, SLOT(AddWeapons(QString, QString)));
+ connect(ui.pageSelectWeapon->pWeapons, SIGNAL(weaponsEdited(QString, QString, QString)),
+ this, SLOT(EditWeapons(QString, QString, QString)));
+ connect(ui.pageSelectWeapon->pWeapons, SIGNAL(weaponsEdited(QString, QString, QString)),
+ ui.pageNetGame->pGameCFG, SLOT(resendAmmoData()));
connect(ui.pageMain->BtnNetLocal, SIGNAL(clicked()), this, SLOT(GoToNet()));
connect(ui.pageMain->BtnNetOfficial, SIGNAL(clicked()), this, SLOT(NetConnectOfficialServer()));
@@ -359,56 +382,13 @@
GoBack();
}
-#ifdef USE_XFIRE
-void HWForm::updateXfire(void)
-{
- if(hwnet && (hwnet->clientState() != HWNewNet::Disconnected))
- {
- xfire_setvalue(XFIRE_SERVER, !hwnet->getHost().compare(QString("%1:%2").arg(NETGAME_DEFAULT_SERVER).arg(NETGAME_DEFAULT_PORT)) ? "Official server" : hwnet->getHost().toAscii());
- switch(hwnet->clientState())
- {
- case HWNewNet::Connecting: // Connecting
- case HWNewNet::Connected:
- xfire_setvalue(XFIRE_STATUS, "Connecting");
- xfire_setvalue(XFIRE_NICKNAME, "-");
- xfire_setvalue(XFIRE_ROOM, "-");
- case HWNewNet::InLobby: // In lobby
- xfire_setvalue(XFIRE_STATUS, "Online");
- xfire_setvalue(XFIRE_NICKNAME, hwnet->getNick().toAscii());
- xfire_setvalue(XFIRE_ROOM, "In game lobby");
- break;
- case HWNewNet::InRoom: // In room
- xfire_setvalue(XFIRE_STATUS, "Online");
- xfire_setvalue(XFIRE_NICKNAME, hwnet->getNick().toAscii());
- xfire_setvalue(XFIRE_ROOM, (hwnet->getRoom() + " (waiting for players)").toAscii());
- break;
- case HWNewNet::InGame: // In game
- xfire_setvalue(XFIRE_STATUS, "Online");
- xfire_setvalue(XFIRE_NICKNAME, hwnet->getNick().toAscii());
- xfire_setvalue(XFIRE_ROOM, (hwnet->getRoom() + " (playing or spectating)").toAscii());
- break;
- default:
- break;
- }
- }
- else
- {
- xfire_setvalue(XFIRE_STATUS, "Offline");
- xfire_setvalue(XFIRE_NICKNAME, "-");
- xfire_setvalue(XFIRE_ROOM, "-");
- xfire_setvalue(XFIRE_SERVER, "-");
- }
- xfire_update();
-}
-#endif
-
void HWForm::onFrontendFullscreen(bool value)
{
if (value)
setWindowState(windowState() | Qt::WindowFullScreen);
else
{
- setWindowState(windowState() & static_cast(!Qt::WindowFullScreen));
+ setWindowState(windowState() & ~Qt::WindowFullScreen);
}
}
@@ -431,6 +411,7 @@
void HWForm::CustomizePalettes()
{
+ // Scroll bar widget palette
QList allSBars = findChildren();
QPalette pal = palette();
pal.setColor(QPalette::WindowText, QColor(0xff, 0xcc, 0x00));
@@ -440,6 +421,11 @@
for (int i = 0; i < allSBars.size(); ++i)
allSBars.at(i)->setPalette(pal);
+
+ // Set default hyperlink color
+ QPalette appPal = qApp->palette();
+ appPal.setColor(QPalette::Link, QColor(0xff, 0xff, 0x6e));
+ qApp->setPalette(appPal);
}
void HWForm::UpdateWeapons()
@@ -467,53 +453,155 @@
}
}
+void HWForm::AddWeapons(QString weaponsName, QString ammo)
+{
+ QVector combos;
+ combos.push_back(ui.pageOptions->WeaponsName);
+ combos.push_back(ui.pageMultiplayer->gameCFG->WeaponsName);
+ combos.push_back(ui.pageNetGame->pGameCFG->WeaponsName);
+ combos.push_back(ui.pageSelectWeapon->selectWeaponSet);
+
+ QStringList names = ui.pageSelectWeapon->pWeapons->getWeaponNames();
+
+ for(QVector::iterator it = combos.begin(); it != combos.end(); ++it)
+ {
+ (*it)->addItem(weaponsName, QVariant(ammo));
+ }
+ ui.pageSelectWeapon->selectWeaponSet->setCurrentIndex(ui.pageSelectWeapon->selectWeaponSet->count()-1);
+}
+
+void HWForm::DeleteWeapons(QString weaponsName)
+{
+ QVector combos;
+ combos.push_back(ui.pageOptions->WeaponsName);
+ combos.push_back(ui.pageMultiplayer->gameCFG->WeaponsName);
+ combos.push_back(ui.pageNetGame->pGameCFG->WeaponsName);
+ combos.push_back(ui.pageSelectWeapon->selectWeaponSet);
+
+ QStringList names = ui.pageSelectWeapon->pWeapons->getWeaponNames();
+
+ for(QVector::iterator it = combos.begin(); it != combos.end(); ++it)
+ {
+ int pos = (*it)->findText(weaponsName);
+ if (pos != -1)
+ {
+ (*it)->removeItem(pos);
+ }
+ }
+ ui.pageSelectWeapon->pWeapons->deletionDone();
+}
+
+void HWForm::EditWeapons(QString oldWeaponsName, QString newWeaponsName, QString ammo)
+{
+ QVector combos;
+ combos.push_back(ui.pageOptions->WeaponsName);
+ combos.push_back(ui.pageMultiplayer->gameCFG->WeaponsName);
+ combos.push_back(ui.pageNetGame->pGameCFG->WeaponsName);
+ combos.push_back(ui.pageSelectWeapon->selectWeaponSet);
+
+ QStringList names = ui.pageSelectWeapon->pWeapons->getWeaponNames();
+
+ for(QVector::iterator it = combos.begin(); it != combos.end(); ++it)
+ {
+ int pos = (*it)->findText(oldWeaponsName);
+ (*it)->setItemText(pos, newWeaponsName);
+ (*it)->setItemData(pos, ammo);
+ }
+}
+
void HWForm::UpdateTeamsLists()
{
QStringList teamslist = config->GetTeamsList();
if(teamslist.empty())
{
- QString currentNickName = config->value("net/nick",tr("Guest")+QString("%1").arg(rand())).toString().toUtf8();
+ QString currentNickName = config->value("net/nick",tr("Guest")+QString("%1").arg(rand())).toString();
QString teamName;
+ int firstHumanTeam = 1;
+ int lastHumanTeam = 2;
+ // Default team
if (currentNickName.isEmpty())
{
- teamName = tr("DefaultTeam");
+ teamName = tr("Team 1");
+ firstHumanTeam++;
}
else
{
teamName = tr("%1's Team").arg(currentNickName);
+ lastHumanTeam--;
}
HWTeam defaultTeam(teamName);
+ // Randomize fort and grave for greater variety by default.
+ // But we exclude DLC graves and forts to not have desyncing teams by default
+ // TODO: Remove DLC filtering when it isn't neccessary anymore
+ HWNamegen::teamRandomGrave(defaultTeam, false);
+ HWNamegen::teamRandomFort(defaultTeam, false);
defaultTeam.saveToFile();
teamslist.push_back(teamName);
+
+ // Add additional default teams
+
+ // More human teams to allow local multiplayer instantly
+ for(int i=firstHumanTeam; i<=lastHumanTeam; i++)
+ {
+ //: Default team name
+ teamName = tr("Team %1").arg(i);
+ HWTeam numberTeam(teamName);
+ HWNamegen::teamRandomGrave(numberTeam, false);
+ HWNamegen::teamRandomFort(numberTeam, false);
+ numberTeam.saveToFile();
+ teamslist.push_back(teamName);
+ }
+ // Add 2 default CPU teams
+ for(int i=1; i<=5; i=i+2)
+ {
+ //: Default computer team name
+ teamName = tr("Computer %1").arg(i);
+ HWTeam numberTeam(teamName);
+ HWNamegen::teamRandomGrave(numberTeam, false);
+ HWNamegen::teamRandomFort(numberTeam, false);
+ numberTeam.setDifficulty(6-i);
+ numberTeam.saveToFile();
+ teamslist.push_back(teamName);
+ }
}
ui.pageOptions->CBTeamName->clear();
ui.pageOptions->CBTeamName->addItems(teamslist);
ui.pageCampaign->CBTeam->clear();
- ui.pageCampaign->CBTeam->addItems(teamslist);
+ /* Only show human teams in campaign page */
+ for(int i=0; iCBTeam->addItem(teamslist[i]);
+ }
+ }
}
-void HWForm::GoToSelectNewWeapon()
+void HWForm::GoToNewWeapons()
{
ui.pageSelectWeapon->pWeapons->newWeaponsName();
GoToPage(ID_PAGE_SELECTWEAPON);
}
-void HWForm::GoToSelectWeapon()
+void HWForm::GoToEditWeapons()
{
ui.pageSelectWeapon->selectWeaponSet->setCurrentIndex(ui.pageOptions->WeaponsName->currentIndex());
GoToPage(ID_PAGE_SELECTWEAPON);
}
-void HWForm::GoToSelectWeaponSet(int index)
+void HWForm::GoToWeapons(int index)
{
ui.pageSelectWeapon->selectWeaponSet->setCurrentIndex(index);
GoToPage(ID_PAGE_SELECTWEAPON);
}
+
void HWForm::GoToSaves()
{
ui.pagePlayDemo->FillFromDir(PagePlayDemo::RT_Save);
@@ -594,10 +682,6 @@
void HWForm::OnPageShown(quint8 id, quint8 lastid)
{
-#ifdef USE_XFIRE
- updateXfire();
-#endif
-
#ifdef QT_DEBUG
qDebug("Leaving %s, entering %s", qPrintable(stringifyPageId(lastid)), qPrintable(stringifyPageId(id)));
#endif
@@ -954,7 +1038,16 @@
void HWForm::NewTeam()
{
- ui.pageEditTeam->createTeam(QLineEdit::tr("unnamed"), playerHash);
+ QString teamName = QLineEdit::tr("unnamed");
+ QStringList teamslist = config->GetTeamsList();
+ if(teamslist.contains(teamName))
+ {
+ //name already used -> look for an appropriate name:
+ int i=2;
+ while(teamslist.contains(teamName = QLineEdit::tr("unnamed (%1)").arg(i++)));
+ }
+
+ ui.pageEditTeam->createTeam(teamName, playerHash);
UpdateTeamsLists();
GoToPage(ID_PAGE_SETUP_TEAM);
}
@@ -1205,7 +1298,7 @@
{
case ID_PAGE_INGAME:
MessageDialog::ShowErrorMessage(errmsg, this);
- // no break
+ /* fallthrough */
case ID_PAGE_NETGAME:
ui.pageNetGame->displayError(errmsg);
break;
@@ -1300,6 +1393,8 @@
// chat widget actions
connect(ui.pageNetGame->chatWidget, SIGNAL(kick(const QString&)),
hwnet, SLOT(kickPlayer(const QString&)));
+ connect(ui.pageNetGame->chatWidget, SIGNAL(delegate(const QString&)),
+ hwnet, SLOT(delegateToPlayer(const QString&)));
connect(ui.pageNetGame->chatWidget, SIGNAL(ban(const QString&)),
hwnet, SLOT(banPlayer(const QString&)));
connect(ui.pageNetGame->chatWidget, SIGNAL(info(const QString&)),
@@ -1433,11 +1528,11 @@
pwDialog->lePassword->setFocus();
}
- //if dialog close, create an error message
+ //if dialog aborted, return failure
if (pwDialog->exec() != QDialog::Accepted) {
delete pwDialog;
GoBack();
- break;
+ return 1;
}
//set nick and pass from the dialog
@@ -1607,6 +1702,14 @@
void HWForm::StartMPGame()
{
+ int numHogs = ui.pageMultiplayer->teamsSelect->getNumHedgehogs();
+ /* Don't allow to start game with >48 hogs.
+ TODO: Remove this as soon the engine supports more hogs. */
+ if(numHogs > 48)
+ {
+ MessageDialog::ShowErrorMessage(QMessageBox::tr("Sorry, Hedgewars can't be played with more than 48 hedgehogs. Please try again with fewer hedgehogs.\n\nCurrent number of hedgehogs: %1").arg(numHogs), this);
+ return;
+ }
QString ammo;
ammo = ui.pageMultiplayer->gameCFG->WeaponsName->itemData(
ui.pageMultiplayer->gameCFG->WeaponsName->currentIndex()
@@ -1721,17 +1824,17 @@
ui.pageVideos->startEncoding(record);
}
-void HWForm::startTraining(const QString & scriptName)
+void HWForm::startTraining(const QString & scriptName, const QString & subFolder)
{
CreateGame(0, 0, 0);
- game->StartTraining(scriptName);
+ game->StartTraining(scriptName, subFolder);
}
void HWForm::StartCampaign()
{
CreateGame(0, 0, 0);
- QString camp = ui.pageCampaign->CBCampaign->currentText().replace(QString(" "),QString("_"));
+ QString camp = ui.pageCampaign->CBCampaign->itemData(ui.pageCampaign->CBCampaign->currentIndex()).toString();
QString miss = campaignMissionInfo[ui.pageCampaign->CBMission->currentIndex()].script;
QString campTeam = ui.pageCampaign->CBTeam->currentText();
game->StartCampaign(camp, miss, campTeam);
@@ -1762,11 +1865,8 @@
void HWForm::closeEvent(QCloseEvent *event)
{
-#ifdef USE_XFIRE
- xfire_free();
-#endif
config->SaveOptions();
-#if VIDEOREC
+#ifdef VIDEOREC
config->SaveVideosOptions();
#endif
event->accept();
@@ -1893,9 +1993,12 @@
);
unsigned int n = entries.count();
+
for(unsigned int i = 0; i < n; i++)
{
- ui.pageCampaign->CBCampaign->addItem(QString(entries[i]).replace(QString("_"),QString(" ")), QString(entries[i]).replace(QString("_"),QString(" ")));
+ const QString & campaignName = entries[i];
+ QString tName = team.name();
+ ui.pageCampaign->CBCampaign->addItem(getRealCampName(campaignName), campaignName);
}
}
@@ -1903,7 +2006,7 @@
{
Q_UNUSED(index);
HWTeam team(ui.pageCampaign->CBTeam->currentText());
- QString campaignName = ui.pageCampaign->CBCampaign->currentText().replace(QString(" "),QString("_"));
+ QString campaignName = ui.pageCampaign->CBCampaign->itemData(ui.pageCampaign->CBCampaign->currentIndex()).toString();
QString tName = team.name();
campaignMissionInfo = getCampMissionList(campaignName,tName);
@@ -1911,14 +2014,42 @@
for(int i=0;iCBMission->addItem(QString(campaignMissionInfo[i].name), QString(campaignMissionInfo[i].name));
+ ui.pageCampaign->CBMission->addItem(QString(campaignMissionInfo[i].realName), QString(campaignMissionInfo[i].name));
+ if(isMissionWon(campaignName, i, tName))
+ ui.pageCampaign->CBMission->setItemIcon(i, finishedIcon);
+ else
+ ui.pageCampaign->CBMission->setItemIcon(i, notFinishedIcon);
+ }
+}
+
+void HWForm::UpdateCampaignPageTeam(int index)
+{
+ Q_UNUSED(index);
+ HWTeam team(ui.pageCampaign->CBTeam->currentText());
+ QString tName = team.name();
+
+ QStringList entries = DataManager::instance().entryList(
+ "Missions/Campaign",
+ QDir::Dirs,
+ QStringList("[^\\.]*")
+ );
+
+ unsigned int n = entries.count();
+
+ for(unsigned int i = 0; i < n; i++)
+ {
+ QString campaignName = QString(entries[i]).replace(QString(" "),QString("_"));
+ if(isCampWon(campaignName, tName))
+ ui.pageCampaign->CBCampaign->setItemIcon(i, finishedIcon);
+ else
+ ui.pageCampaign->CBCampaign->setItemIcon(i, notFinishedIcon);
}
}
void HWForm::UpdateCampaignPageMission(int index)
{
// update thumbnail and description
- QString campaignName = ui.pageCampaign->CBCampaign->currentText().replace(QString(" "),QString("_"));
+ QString campaignName = ui.pageCampaign->CBCampaign->itemData(ui.pageCampaign->CBCampaign->currentIndex()).toString();
// when campaign changes the UpdateCampaignPageMission is triggered with wrong values
// this will cause segfault. This check prevents illegal memory reads
if(index > -1 && index < campaignMissionInfo.count()) {
@@ -1936,12 +2067,20 @@
UpdateCampaignPage(0);
for(int i=0;iCBMission->count();i++)
{
- if (ui.pageCampaign->CBMission->itemText(i)==missionTitle)
+ if (ui.pageCampaign->CBMission->itemData(i)==missionTitle)
{
ui.pageCampaign->CBMission->setCurrentIndex(i);
break;
}
}
+ int i = ui.pageCampaign->CBCampaign->currentIndex();
+ QString campaignName = ui.pageCampaign->CBCampaign->itemData(i).toString();
+ HWTeam team(ui.pageCampaign->CBTeam->currentText());
+ QString tName = team.name();
+ if(isCampWon(campaignName, tName))
+ ui.pageCampaign->CBCampaign->setItemIcon(i, finishedIcon);
+ else
+ ui.pageCampaign->CBCampaign->setItemIcon(i, notFinishedIcon);
}
// used for --set-everything [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality]
@@ -2079,7 +2218,7 @@
switch(lastGameType) {
case gtTraining:
- game->StartTraining(lastGameStartArgs.at(0).toString());
+ game->StartTraining(lastGameStartArgs.at(0).toString(), lastTrainingSubFolder);
break;
case gtQLocal:
game->StartQuick();
@@ -2113,11 +2252,27 @@
{
QNetworkReply *reply = qobject_cast(sender());
- if (reply && (reply->error() == QNetworkReply::NoError)) {
- FeedbackDialog dialog(this);
- dialog.exec();
- } else
- MessageDialog::ShowErrorMessage(tr("This page requires an internet connection."), this);
+ if (reply) {
+ switch (reply->error()) {
+ case QNetworkReply::NoError:
+ {
+ FeedbackDialog dialog(this);
+ dialog.exec();
+ }
+ break;
+ case QNetworkReply::UnknownNetworkError:
+ MessageDialog::ShowFatalMessage(
+ tr("Unknown network error (possibly missing SSL library)."), this);
+ break;
+ default:
+ MessageDialog::ShowFatalMessage(
+ QString(tr("This feature requires an Internet connection, but you don't appear to be online (error code: %1).")).arg(reply->error()), this);
+ break;
+ }
+ }
+ else {
+ MessageDialog::ShowFatalMessage(tr("Internal error: Reply object is invalid."), this);
+ }
}
void HWForm::startGame()
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/hwform.h
--- a/QTfrontend/hwform.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/hwform.h Sun Dec 17 00:09:24 2017 +0100
@@ -62,7 +62,6 @@
HWForm(QWidget *parent = 0, QString styleSheet = "");
Ui_HWForm ui;
static GameUIConfig * config;
- void updateXfire();
void exit();
void setButtonDescription(QString desc);
void backDescription();
@@ -75,9 +74,9 @@
void GoToSaves();
void GoToDemos();
void GoToNet();
- void GoToSelectWeapon();
- void GoToSelectWeaponSet(int index);
- void GoToSelectNewWeapon();
+ void GoToEditWeapons();
+ void GoToNewWeapons();
+ void GoToWeapons(int index);
void GoToScheme(int index);
void GoToEditScheme();
void GoToNewScheme();
@@ -96,7 +95,7 @@
void DeleteWeaponSet();
void SimpleGame();
void PlayDemo();
- void startTraining(const QString&);
+ void startTraining(const QString&, const QString&);
void StartCampaign();
void NetConnect();
void NetConnectServer(const QString & host, quint16 port);
@@ -124,10 +123,14 @@
void GetRecord(RecordType type, const QByteArray & record);
void CreateNetGame();
void UpdateWeapons();
+ void DeleteWeapons(QString weaponsName);
+ void AddWeapons(QString weaponsName, QString ammo);
+ void EditWeapons(QString oldWeaponsName, QString newWeaponsName, QString ammo);
void onFrontendFullscreen(bool value);
void onFrontendEffects(bool value);
void Music(bool checked);
void UpdateCampaignPage(int index);
+ void UpdateCampaignPageTeam(int index);
void UpdateCampaignPageProgress(int index);
void UpdateCampaignPageMission(int index);
void InitCampaignPage();
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/main.cpp
--- a/QTfrontend/main.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/main.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -44,6 +44,11 @@
#include
#elif defined __APPLE__
#include "CocoaInitializer.h"
+
+#endif
+
+#ifdef Q_OS_WIN
+#include
#endif
// Program resources
@@ -162,9 +167,8 @@
HWApplication app(argc, argv);
app.setAttribute(Qt::AA_DontShowIconsInMenus,false);
- // file engine and splash. to be initialized later
+ // file engine, to be initialized later
engine = NULL;
- QLabel *splash = NULL;
// parse arguments
@@ -241,17 +245,13 @@
// end of parameter parsing
-#if defined Q_OS_WIN
- QPixmap pixmap(":res/splash.png");
- splash = new QLabel(0, Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
- splash->setAttribute(Qt::WA_TranslucentBackground);
- const QRect deskSize = HWApplication::desktop()->screenGeometry(-1);
- QPoint splashCenter = QPoint( (deskSize.width() - pixmap.width())/2,
- (deskSize.height() - pixmap.height())/2 );
- splash->move(splashCenter);
- splash->setPixmap(pixmap);
- splash->show();
+
+#ifdef Q_OS_WIN
+ QPixmap pixmap(":/res/splash.png");
+ QSplashScreen splash(pixmap);
+ splash.show();
#endif
+
app.setStyle(new QPlastiqueStyle());
QDateTime now = QDateTime::currentDateTime();
@@ -346,7 +346,8 @@
}
#ifdef _WIN32
- // Win32 registry setup (used for xfire detection etc. - don't set it if we're running in "portable" mode with a custom config dir)
+ // Win32 registry setup (used for external software detection etc.
+ // don't set it if running in "portable" mode with a custom config dir)
if(!custom_config)
{
QSettings registry_hklm("HKEY_LOCAL_MACHINE", QSettings::NativeFormat);
@@ -392,9 +393,11 @@
qWarning("Starting Hedgewars %s-r%d (%s)", qPrintable(*cVersionString), cRevisionString->toInt(), qPrintable(*cHashString));
app.form = new HWForm(NULL, style);
+#ifdef Q_OS_WIN
+ splash.finish(app.form);
+#endif
app.form->show();
- if(splash)
- splash->close();
+
if (app.urlString)
app.fakeEvent();
return app.exec();
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/model/GameStyleModel.cpp
--- a/QTfrontend/model/GameStyleModel.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/model/GameStyleModel.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -32,11 +32,18 @@
{
beginResetModel();
+ QIcon dlcIcon;
+ dlcIcon.addFile(":/res/dlcMarker.png", QSize(), QIcon::Normal, QIcon::On);
+ dlcIcon.addFile(":/res/dlcMarkerSelected.png", QSize(), QIcon::Selected, QIcon::On);
+ QPixmap emptySpace = QPixmap(7, 15);
+ emptySpace.fill(QColor(0, 0, 0, 0));
+ QIcon notDlcIcon = QIcon(emptySpace);
+
// empty list, so that we can (re)fill it
QStandardItemModel::clear();
QList items;
- items.append(new QStandardItem("Normal"));
+ items.append(new QStandardItem(notDlcIcon, "Normal"));
// define a separator item
QStandardItem * separator = new QStandardItem("---");
@@ -82,7 +89,11 @@
QString scriptPath = PHYSFS_getRealDir(QString("Scripts/Multiplayer/%1.lua").arg(script).toLocal8Bit().data());
bool isDLC = !scriptPath.startsWith(datadir->absolutePath());
- QStandardItem * item = new QStandardItem((isDLC ? "*" : "") + name);
+ QStandardItem * item;
+ if (isDLC)
+ item = new QStandardItem(dlcIcon, name);
+ else
+ item = new QStandardItem(notDlcIcon, name);
item->setData(script, ScriptRole);
item->setData(scheme, SchemeRole);
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/model/MapModel.cpp
--- a/QTfrontend/model/MapModel.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/model/MapModel.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -80,6 +80,14 @@
//QList missionMaps;
QList mapList;
+
+ QIcon dlcIcon;
+ dlcIcon.addFile(":/res/dlcMarker.png", QSize(), QIcon::Normal, QIcon::On);
+ dlcIcon.addFile(":/res/dlcMarkerSelected.png", QSize(), QIcon::Selected, QIcon::On);
+ QPixmap emptySpace = QPixmap(7, 15);
+ emptySpace.fill(QColor(0, 0, 0, 0));
+ QIcon notDlcIcon = QIcon(emptySpace);
+
// add mission/static maps to lists
foreach (QString map, maps)
{
@@ -119,10 +127,22 @@
// load description (if applicable)
if (isMission)
{
- QString locale = HWApplication::keyboardInputLocale().name();
+ // get locale
+ QSettings settings(datamgr.settingsFileName(), QSettings::IniFormat);
+ QString locale = settings.value("misc/locale", "").toString();
+ if (locale.isEmpty())
+ locale = QLocale::system().name();
QSettings descSettings(QString("physfs://Maps/%1/desc.txt").arg(map), QSettings::IniFormat);
- desc = descSettings.value(locale, QString()).toString().replace("|", "\n").replace("\\,", ",");
+ descSettings.setIniCodec("UTF-8");
+ desc = descSettings.value(locale, QString()).toString();
+ // If not found, try with lanague-only code
+ if (desc.isEmpty())
+ {
+ QString localeSimple = locale.remove(QRegExp("_.*$"));
+ desc = descSettings.value(localeSimple, QString()).toString();
+ }
+ desc = desc.replace("_n", "\n").replace("_c", ",").replace("__", "_");
}
// detect if map is dlc
@@ -151,9 +171,15 @@
// caption
caption = map;
+ QIcon icon;
+ if (dlc)
+ icon = dlcIcon;
+ else
+ icon = notDlcIcon;
+
// we know everything there is about the map, let's get am item for it
QStandardItem * item = MapModel::infoToItem(
- QIcon(), caption, type, map, theme, limit, scheme, weapons, desc, dlc);
+ icon, caption, type, map, theme, limit, scheme, weapons, desc, dlc);
// append item to the list
mapList.append(item);
@@ -213,7 +239,7 @@
QString desc,
bool dlc)
{
- QStandardItem * item = new QStandardItem(icon, (dlc ? "*" : "") + caption);
+ QStandardItem * item = new QStandardItem(icon, caption);
MapInfo mapInfo;
QVariant qvar(QVariant::UserType);
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/model/ammoSchemeModel.cpp
--- a/QTfrontend/model/ammoSchemeModel.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/model/ammoSchemeModel.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -81,11 +81,11 @@
<< "Minefield"
<< "Barrel Mayhem"
<< "Tunnel Hogs"
- << "Fort Mode"
<< "Timeless"
<< "Thinking with Portals"
<< "King Mode"
- << "Construction Mode"
+ << "Construction Mode"
+ << "HedgeEditor"
;
numberOfDefaultSchemes = predefSchemesNames.size();
@@ -222,11 +222,11 @@
<< QVariant(0) // mines number 32
<< QVariant(0) // mine dud pct 33
<< QVariant(0) // explosives 34
- << QVariant(8) // air mines 35
+ << QVariant(0) // air mines 35
<< QVariant(0) // health case pct 36
<< QVariant(25) // health case amt 37
- << QVariant(47) // water rise amt 38
- << QVariant(5) // health dec amt 39
+ << QVariant(0) // water rise amt 38
+ << QVariant(0) // health dec amt 39
<< QVariant(100) // rope modfier 40
<< QVariant(100) // get away time 41
<< QVariant(0) // world edge 42
@@ -425,57 +425,9 @@
<< QVariant() // scriptparam 43
;
- QList forts;
- forts
- << predefSchemesNames[7] // name 0
- << QVariant(true) // fortsmode 1
- << QVariant(true) // team divide 2
- << QVariant(false) // solid land 3
- << QVariant(false) // border 4
- << QVariant(false) // low gravity 5
- << QVariant(false) // laser sight 6
- << QVariant(false) // invulnerable 7
- << QVariant(false) // reset health 8
- << QVariant(false) // vampiric 9
- << QVariant(false) // karma 10
- << QVariant(false) // artillery 11
- << QVariant(true) // random order 12
- << QVariant(false) // king 13
- << QVariant(false) // place hog 14
- << QVariant(false) // shared ammo 15
- << QVariant(false) // disable girders 16
- << QVariant(false) // disable land objects 17
- << QVariant(false) // AI survival 18
- << QVariant(false) // inf. attack 19
- << QVariant(false) // reset weps 20
- << QVariant(false) // per hog ammo 21
- << QVariant(false) // no wind 22
- << QVariant(false) // more wind 23
- << QVariant(false) // tag team 24
- << QVariant(false) // bottom border 25
- << QVariant(100) // damage modfier 26
- << QVariant(45) // turn time 27
- << QVariant(100) // init health 28
- << QVariant(15) // sudden death 29
- << QVariant(5) // case prob 30
- << QVariant(3) // mines time 31
- << QVariant(0) // mines number 32
- << QVariant(0) // mine dud pct 33
- << QVariant(0) // explosives 34
- << QVariant(0) // air mines 35
- << QVariant(35) // health case pct 36
- << QVariant(25) // health case amt 37
- << QVariant(47) // water rise amt 38
- << QVariant(5) // health dec amt 39
- << QVariant(100) // rope modfier 40
- << QVariant(100) // get away time 41
- << QVariant(0) // world edge 42
- << QVariant() // scriptparam 43
- ;
-
QList timeless;
timeless
- << predefSchemesNames[8] // name 0
+ << predefSchemesNames[7] // name 0
<< QVariant(false) // fortsmode 1
<< QVariant(false) // team divide 2
<< QVariant(false) // solid land 3
@@ -523,7 +475,7 @@
QList thinkingportals;
thinkingportals
- << predefSchemesNames[9] // name 0
+ << predefSchemesNames[8] // name 0
<< QVariant(false) // fortsmode 1
<< QVariant(false) // team divide 2
<< QVariant(false) // solid land 3
@@ -571,7 +523,7 @@
QList kingmode;
kingmode
- << predefSchemesNames[10] // name 0
+ << predefSchemesNames[9] // name 0
<< QVariant(false) // fortsmode 1
<< QVariant(false) // team divide 2
<< QVariant(false) // solid land 3
@@ -619,7 +571,7 @@
QList construction;
construction
- << predefSchemesNames[11] // name 0
+ << predefSchemesNames[10] // name 0
<< QVariant(false) // fortsmode 1
<< QVariant(false) // team divide 2
<< QVariant(false) // solid land 3
@@ -664,6 +616,56 @@
<< QVariant(0) // world edge 42
<< QVariant() // scriptparam 43
;
+
+ QList hedgeeditor;
+ hedgeeditor
+ << predefSchemesNames[11] // name 0
+ << QVariant(false) // fortsmode 1
+ << QVariant(false) // team divide 2
+ << QVariant(false) // solid land 3
+ << QVariant(false) // border 4
+ << QVariant(false) // low gravity 5
+ << QVariant(false) // laser sight 6
+ << QVariant(false) // invulnerable 7
+ << QVariant(false) // reset health 8
+ << QVariant(false) // vampiric 9
+ << QVariant(false) // karma 10
+ << QVariant(false) // artillery 11
+ << QVariant(false) // random order 12
+ << QVariant(false) // king 13
+ << QVariant(false) // place hog 14
+ << QVariant(false) // shared ammo 15
+ << QVariant(false) // disable girders 16
+ << QVariant(false) // disable land objects 17
+ << QVariant(false) // AI survival 18
+ << QVariant(false) // inf. attack 19
+ << QVariant(false) // reset weps 20
+ << QVariant(true) // per hog ammo 21
+ << QVariant(false) // no wind 22
+ << QVariant(false) // more wind 23
+ << QVariant(false) // tag team 24
+ << QVariant(false) // bottom border 25
+ << QVariant(100) // damage modfier 26
+ << QVariant(9999) // turn time 27
+ << QVariant(100) // init health 28
+ << QVariant(50) // sudden death 29
+ << QVariant(5) // case prob 30
+ << QVariant(3) // mines time 31
+ << QVariant(0) // mines number 32
+ << QVariant(0) // mine dud pct 33
+ << QVariant(0) // explosives 34
+ << QVariant(0) // air mines 35
+ << QVariant(35) // health case pct 36
+ << QVariant(25) // health case amt 37
+ << QVariant(0) // water rise amt 38
+ << QVariant(0) // health dec amt 39
+ << QVariant(100) // rope modfier 40
+ << QVariant(100) // get away time 41
+ << QVariant(0) // world edge 42
+ << QVariant() // scriptparam 43
+ ;
+
+
schemes.append(defaultScheme);
schemes.append(proMode);
@@ -672,11 +674,11 @@
schemes.append(minefield);
schemes.append(barrelmayhem);
schemes.append(tunnelhogs);
- schemes.append(forts);
schemes.append(timeless);
schemes.append(thinkingportals);
schemes.append(kingmode);
- schemes.append(construction);
+ schemes.append(construction);
+ schemes.append(hedgeeditor);
int size = fileConfig.beginReadArray("schemes");
@@ -722,6 +724,18 @@
return defaultScheme.size();
}
+bool AmmoSchemeModel::hasScheme(QString name)
+{
+ for(int i=0; i newScheme = defaultScheme;
- newScheme[0] = QVariant(tr("New"));
+
+ QString newName = tr("New");
+ if(hasScheme(newName))
+ {
+ //name already used -> look for an appropriate name:
+ int i=2;
+ while(hasScheme(newName = tr("New (%1)").arg(i++))) ;
+ }
+ newScheme[0] = QVariant(newName);
schemes.insert(schemes.size(), newScheme);
}
else
{
QList newScheme = schemes[row];
- newScheme[0] = QVariant(tr("Copy of %1").arg(newScheme[0].toString()));
+ QString oldName = newScheme[0].toString();
+ QString newName = tr("Copy of %1").arg(oldName);
+ if(hasScheme(newName))
+ {
+ //name already used -> look for an appropriate name:
+ int i=2;
+ while(hasScheme(newName = tr("Copy of %1 (%2)").arg(oldName).arg(i++)));
+ }
+ newScheme[0] = QVariant(newName);
schemes.insert(schemes.size(), newScheme);
}
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/model/ammoSchemeModel.h
--- a/QTfrontend/model/ammoSchemeModel.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/model/ammoSchemeModel.h Sun Dec 17 00:09:24 2017 +0100
@@ -34,6 +34,7 @@
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
int rowCount(const QModelIndex & parent) const;
int columnCount(const QModelIndex & parent) const;
+ bool hasScheme(QString name);
Qt::ItemFlags flags(const QModelIndex & index) const;
bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
bool insertRows(int row, int count, const QModelIndex & parent = QModelIndex());
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/model/roomslistmodel.cpp
--- a/QTfrontend/model/roomslistmodel.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/model/roomslistmodel.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -32,17 +32,18 @@
QAbstractTableModel(parent),
c_nColumns(9)
{
- m_headerData =
- QStringList()
- << tr("In progress")
- << tr("Room Name")
- << tr("C")
- << tr("T")
- << tr("Owner")
- << tr("Map")
- << tr("Script")
- << tr("Rules")
- << tr("Weapons");
+ m_headerData = QStringList();
+ m_headerData << tr("In progress");
+ m_headerData << tr("Room Name");
+ //: Caption of the column for the number of connected clients in the list of rooms
+ m_headerData << tr("C");
+ //: Caption of the column for the number of teams in the list of rooms
+ m_headerData << tr("T");
+ m_headerData << tr("Owner");
+ m_headerData << tr("Map");
+ m_headerData << tr("Script");
+ m_headerData << tr("Rules");
+ m_headerData << tr("Weapons");
m_staticMapModel = DataManager::instance().staticMapModel();
m_missionMapModel = DataManager::instance().missionMapModel();
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/net/newnetclient.cpp
--- a/QTfrontend/net/newnetclient.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/net/newnetclient.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -1012,6 +1012,11 @@
RawSendNet(QString("KICK%1%2").arg(delimiter).arg(nick));
}
+void HWNewNet::delegateToPlayer(const QString & nick)
+{
+ RawSendNet(QString("DELEGATE%1%2").arg(delimiter).arg(nick));
+}
+
void HWNewNet::infoPlayer(const QString & nick)
{
RawSendNet(QString("INFO%1%2").arg(delimiter).arg(nick));
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/net/newnetclient.h
--- a/QTfrontend/net/newnetclient.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/net/newnetclient.h Sun Dec 17 00:09:24 2017 +0100
@@ -167,6 +167,7 @@
void gameFinished(bool correcly);
void banPlayer(const QString &);
void kickPlayer(const QString &);
+ void delegateToPlayer(const QString &);
void infoPlayer(const QString &);
void followPlayer(const QString &);
void consoleCommand(const QString &);
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/net/tcpBase.cpp
--- a/QTfrontend/net/tcpBase.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/net/tcpBase.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -188,7 +188,6 @@
void TCPBase::ClientDisconnect()
{
- disconnect(IPCSocket, SIGNAL(readyRead()), this, SLOT(ClientRead()));
onClientDisconnect();
if(!simultaneousRun())
@@ -200,8 +199,11 @@
emit isReadyNow();
}
- IPCSocket->deleteLater();
- IPCSocket = NULL;
+ if(IPCSocket) {
+ disconnect(IPCSocket, SIGNAL(readyRead()), this, SLOT(ClientRead()));
+ IPCSocket->deleteLater();
+ IPCSocket = NULL;
+ }
deleteLater();
}
@@ -224,7 +226,8 @@
{
Q_UNUSED(exitStatus);
- ClientDisconnect();
+ if(!m_connected)
+ ClientDisconnect();
// show error message if there was an error that was not an engine's
// fatal error - because that one already sent a info via IPC
@@ -240,16 +243,6 @@
.arg("Feedback"));
}
-
- // cleanup up
- if (IPCSocket)
- {
- IPCSocket->close();
- IPCSocket->deleteLater();
- }
-
- // plot suicide
- deleteLater();
}
void TCPBase::tcpServerReady()
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/Multiplayer.png
Binary file QTfrontend/res/Multiplayer.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/NetworkPlay.png
Binary file QTfrontend/res/NetworkPlay.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/Palette.png
Binary file QTfrontend/res/Palette.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/Palette.svg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/res/Palette.svg Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+ Openclipart
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/PlaySound.png
Binary file QTfrontend/res/PlaySound.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/SimpleGame.png
Binary file QTfrontend/res/SimpleGame.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/StatsMedal1@2x.png
Binary file QTfrontend/res/StatsMedal1@2x.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/StatsMedal2@2x.png
Binary file QTfrontend/res/StatsMedal2@2x.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/StatsMedal3@2x.png
Binary file QTfrontend/res/StatsMedal3@2x.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/StatsMedal4@2x.png
Binary file QTfrontend/res/StatsMedal4@2x.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/Videos.png
Binary file QTfrontend/res/Videos.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/Videos.svg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/res/Videos.svg Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,429 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+ Openclipart
+
+
+
+ 2010-02-12T23:23:34
+ A movie reel, seen in perspective
+ https://openclipart.org/detail/29273/movie-reel-by-abustany
+
+
+ abustany
+
+
+
+
+ cinema
+ colour
+ film
+ movie
+ reel
+ video
+
+
+
+
+
+
+
+
+
+
+
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/audio.png
Binary file QTfrontend/res/audio.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/audio.svg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/res/audio.svg Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+ Openclipart
+
+
+
+ 2010-04-03T15:19:58
+ An icon from Tango Project. Since version 0.8.90 Tango Project icons are Public Domain.
+ https://openclipart.org/detail/36601/tango-audio-volume-high-by-warszawianka
+
+
+ warszawianka
+
+
+
+
+ externalsource
+ icon
+ tango
+
+
+
+
+
+
+
+
+
+
+
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/botlevels/net0.png
Binary file QTfrontend/res/botlevels/net0.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/botlevels/net0.xcf
Binary file QTfrontend/res/botlevels/net0.xcf has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/botlevels/net1.png
Binary file QTfrontend/res/botlevels/net1.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/botlevels/net2.png
Binary file QTfrontend/res/botlevels/net2.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/botlevels/net3.png
Binary file QTfrontend/res/botlevels/net3.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/botlevels/net4.png
Binary file QTfrontend/res/botlevels/net4.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/botlevels/net5.png
Binary file QTfrontend/res/botlevels/net5.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnAISurvival.png
Binary file QTfrontend/res/btnAISurvival.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnAISurvival.xcf
Binary file QTfrontend/res/btnAISurvival.xcf has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnAISurvival@2x.png
Binary file QTfrontend/res/btnAISurvival@2x.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnAISurvival@2x.xcf
Binary file QTfrontend/res/btnAISurvival@2x.xcf has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnBorder.png
Binary file QTfrontend/res/btnBorder.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnBorder@2x.png
Binary file QTfrontend/res/btnBorder@2x.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnBottomBorder.png
Binary file QTfrontend/res/btnBottomBorder.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnBottomBorder@2x.png
Binary file QTfrontend/res/btnBottomBorder@2x.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnForts.png
Binary file QTfrontend/res/btnForts.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnForts@2x.png
Binary file QTfrontend/res/btnForts@2x.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnLowGravity.png
Binary file QTfrontend/res/btnLowGravity.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnLowGravity@2x.png
Binary file QTfrontend/res/btnLowGravity@2x.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnMoreWind.png
Binary file QTfrontend/res/btnMoreWind.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnMoreWind@2x.png
Binary file QTfrontend/res/btnMoreWind@2x.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnNoWind.png
Binary file QTfrontend/res/btnNoWind.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnNoWind@2x.png
Binary file QTfrontend/res/btnNoWind@2x.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnPlaceHog.png
Binary file QTfrontend/res/btnPlaceHog.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnPlaceHog@2x.png
Binary file QTfrontend/res/btnPlaceHog@2x.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/btnRandomOrder@2x.png
Binary file QTfrontend/res/btnRandomOrder@2x.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/campaign/A_Classic_Fairytale/epil.png
Binary file QTfrontend/res/campaign/A_Classic_Fairytale/epil.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/campaign/A_Classic_Fairytale/family.png
Binary file QTfrontend/res/campaign/A_Classic_Fairytale/family.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/campaign/A_Classic_Fairytale/journey.png
Binary file QTfrontend/res/campaign/A_Classic_Fairytale/journey.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/campaign/A_Classic_Fairytale/shadow.png
Binary file QTfrontend/res/campaign/A_Classic_Fairytale/shadow.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/campaign/A_Classic_Fairytale/united.png
Binary file QTfrontend/res/campaign/A_Classic_Fairytale/united.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/campaign/A_Space_Adventure/cosmos.png
Binary file QTfrontend/res/campaign/A_Space_Adventure/cosmos.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/campaign/A_Space_Adventure/death01.png
Binary file QTfrontend/res/campaign/A_Space_Adventure/death01.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/campaign/A_Space_Adventure/death02.png
Binary file QTfrontend/res/campaign/A_Space_Adventure/death02.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/campaign/A_Space_Adventure/fruit03.png
Binary file QTfrontend/res/campaign/A_Space_Adventure/fruit03.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/campaign/A_Space_Adventure/ice01.png
Binary file QTfrontend/res/campaign/A_Space_Adventure/ice01.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/campaign/A_Space_Adventure/ice02.png
Binary file QTfrontend/res/campaign/A_Space_Adventure/ice02.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/campaign/A_Space_Adventure/moon02.png
Binary file QTfrontend/res/campaign/A_Space_Adventure/moon02.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/css/qt.css
--- a/QTfrontend/res/css/qt.css Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/res/css/qt.css Sun Dec 17 00:09:24 2017 +0100
@@ -94,6 +94,7 @@
border-radius: 16px;
background-color: rgba(13, 5, 68, 70%);
padding: 6px;
+margin-top: 4px;
}
/* Experimenting with PaintOnScreen and border-radius on IconedGroupBox children didn't work out well
IconedGroupBox QComboBox, IconedGroupBox QPushButton, IconedGroupBox QLineEdit,
@@ -207,7 +208,6 @@
subcontrol-position: top left;
text-align: left;
left: 15px;
-top: -4px;
}
QCheckBox::indicator:checked{
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/dlcMarker.png
Binary file QTfrontend/res/dlcMarker.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/dlcMarkerSelected.png
Binary file QTfrontend/res/dlcMarkerSelected.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/folder.png
Binary file QTfrontend/res/folder.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/folder.svg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/res/folder.svg Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,97 @@
+
+image/svg+xml Openclipart
\ No newline at end of file
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/frontendicon.png
Binary file QTfrontend/res/frontendicon.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/home.png
Binary file QTfrontend/res/home.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/home.svg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/res/home.svg Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,201 @@
+
+image/svg+xml Openclipart 2010-03-10T10:25:42 Home icon from <A href="http://tango.freedesktop.org/Tango_Desktop_Project"> Tango Project </A> \n<BR><BR>\nSince version 0.8.90 Tango Project icons are Public Domain: <A href="http://tango.freedesktop.org/Frequently_Asked_Questions#Terms_of_Use.3F"> Tango Project FAQ </A> https://openclipart.org/detail/30805/tango-go-home-by-warszawianka warszawianka architecture building externalsource home house icon tango
\ No newline at end of file
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/html/about.html
--- a/QTfrontend/res/html/about.html Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/res/html/about.html Sun Dec 17 00:09:24 2017 +0100
@@ -12,88 +12,94 @@
Developers:
- Engine, frontend, net server: Andrey Korotaev <unC0Rr@gmail.com >
- Many frontend improvements: Igor Ulyanov <disinbox@gmail.com >
- Many engine and frontend improvements: Derek Pomery <nemo@m8y.org >
- Drill rocket, Ballgun, RC Plane weapons: Martin Boze <afffect@gmail.com >
- Mine number and time game settings: David A. Cuadrado <krawek@gmail.com >
- Frontend improvements: Martin Minarik <ttsmj@pokec.sk >
- Frontend improvements: Kristian Lehmann <email@thexception.net >
- Mac OS X/iPhone port, OpenGL-ES conversion: Vittorio Giovara <vittorio.giovara@gmail.com >
- Many engine and frontend improvements (and bugs): Richard Karolyi <sheepluva@ercatec.net >
- Gamepad and Lua integration: Mario Liebisch <mario.liebisch@gmail.com >
- Many engine improvements and graphics: Carlos Vives <mail@carlosvives.es >
- Maze maps: Henning Kühn <prg@cooco.de >
- Engine and frontend improvements: Henrik Rostedt <henrik.rostedt@gmail.com >
- Lua game modes and missions: John Lambert <redgrinner@gmail.com >
- Frontend improvements: Mayur Pawashe <zorgiepoo@gmail.com >
- Android port: Richard Deurwaarder <xeli@xelification.com >
- Android netplay, portability abstraction: Simeon Maxein <smaxein@googlemail.com >
- WebGL port, some pas2c and GLES2 work: Meng Xiangyun <xymengxy@gmail.com >
- Video recording: Stepan Podoskin <stepik-777@mail.ru >
- Campaign support, first campaign: Szabolcs Orbàn <szabibibi@gmail.com >
- Keybinds, feedback, maps and hats interfaces: Drew Gottlieb <gottlieb.drew@gmail.com >
- Login dialogs, frontend improvements: Ondrej Skopek <skopekondrej@gmail.com >
- Icegun weapon: Julia Struchenko <urbertar@gmail.com >
- iPhone/iPad ports: Anton Malmygin <antonc27@mail.ru >
+ Engine, frontend, net server: Andrey Korotaev <unC0Rr@gmail.com >
+ Many frontend improvements: Igor Ulyanov <disinbox@gmail.com >
+ Many engine and frontend improvements: Derek Pomery <nemo@m8y.org >
+ Drill rocket, Ballgun, RC Plane weapons: Martin Boze <afffect@gmail.com >
+ Mine number and time game settings: David A. Cuadrado <krawek@gmail.com >
+ Frontend improvements: Martin Minarik <ttsmj@pokec.sk >
+ Frontend improvements: Kristian Lehmann <email@thexception.net >
+ Mac OS X/iPhone port, OpenGL-ES conversion: Vittorio Giovara <vittorio.giovara@gmail.com >
+ Many engine and frontend improvements (and bugs): Richard Karolyi <sheepluva@ercatec.net >
+ Gamepad and Lua integration: Mario Liebisch <mario.liebisch@gmail.com >
+ Many engine improvements and graphics: Carlos Vives <mail@carlosvives.es >
+ Maze maps: Henning Kühn <prg@cooco.de >
+ Engine and frontend improvements: Henrik Rostedt <henrik.rostedt@gmail.com >
+ Lua game modes and missions: John Lambert <redgrinner@gmail.com >
+ Frontend improvements: Mayur Pawashe <zorgiepoo@gmail.com >
+ Android port: Richard Deurwaarder <xeli@xelification.com >
+ Android netplay, portability abstraction: Simeon Maxein <smaxein@googlemail.com >
+ WebGL port, some pas2c and GLES2 work: Meng Xiangyun <xymengxy@gmail.com >
+ Video recording: Stepan Podoskin <stepik-777@mail.ru >
+ Campaign support, first campaign: Szabolcs Orbàn <szabibibi@gmail.com >
+ Keybinds, feedback, maps and hats interfaces: Drew Gottlieb <gottlieb.drew@gmail.com >
+ Login dialogs, frontend improvements: Ondrej Skopek <skopekondrej@gmail.com >
+ Icegun weapon: Julia Struchenko <urbertar@gmail.com >
+ iPhone/iPad ports: Anton Malmygin <antonc27@mail.ru >
+ Battalion style: Anachron <Anachron14@gmx.de >
+ Scripting, engine, frontend improvements, some missions: Wuzzy <Wuzzy2@mail.ru >
+ Theme customization improvements: KoBeWi
+ Theme music, engine and frontend improvements, graphics: Valentin Kraevskiy
Art:
John Dum <fizzy@gmail.com >
-
+
Joshua Frese <joshfrese@gmail.com >
-
+
Stanko Tadić <stanko@mfhinc.net >
-
+
Julien Koesten <julienkoesten@aol.com >
-
+
Joshua O'Sullivan <coheedftw@hotmail.co.uk >
-
+
Nils Lück <nils.luck.design@gmail.com >
-
+
Guillaume Englert <genglert@hybird.org >
-
+
+
CopherNeue <ppicondo.cvac@gmail.com >
+
Hats: Trey Perry <tx.perry.j@gmail.com >
Sounds:
Hedgehogs voice: Stephen Alexander <ArmagonNo1@gmail.com >
-
+
John Dum <fizzy@gmail.com >
-
+
Jonatan Nilsson <jonatanfan@gmail.com >
-
+
Daniel Martin <elhombresinremedio@gmail.com >
Translations:
- Brazilian Portuguese: Romulo Fernandes Machado <abra185@gmail.com >
- Bulgarian: Svetoslav Stefanov
- Czech: Petr Řezáček <rezacek@gmail.com >
- Chinese: Jie Luo <lililjlj@gmail.com >
- English: Andrey Korotaev <unC0Rr@gmail.com >
- Finnish: Nina Kuisma <ninnnu@gmail.com >, Janne Uusitupa
- French: Antoine Turmel <geekshadow@gmail.com >, Clement Woitrain <sphrixclement@gmail.com >, Matisumi
- German: Peter Hüwe <PeterHuewe@gmx.de >, Mario Liebisch <mario.liebisch@gmail.com >, Richard Karolyi <sheepluva@ercatec.net >, Wuzzy <almikes@aol.com >
- Greek: <talos_kriti@yahoo.gr >
- Italian: Luca Bonora <bonora.luca@gmail.com >, Marco Bresciani <m.bresciani@email.it >, Gianfranco Costamagna <costamagnagianfranco@yahoo.it >
- Japanese: ADAM Etienne <etienne.adam@gmail.com >, Marco Bresciani <m.bresciani@email.it >
- Korean: Anthony Bellew <anthonyreflected@gmail.com >
- Lithuanian: Lukas Urbonas <lukasu08@gmail.com >
- Polish: Maciej Mroziński <mynick2@o2.pl >, Wojciech Latkowski <magik17l@gmail.com >, Piotr Mitana, Maciej Górny
- Portuguese: Fábio Canário <inufabie@gmail.com >
- Russian: Andrey Korotaev <unC0Rr@gmail.com >, Vitaly Novichkov <admin@wohlnet.ru >, Anton Malmygin <antonc27@mail.ru >
- Slovak: Jose Riha
- Spanish: Carlos Vives <mail@carlosvives.es >
- Swedish: Niklas Grahn <raewolusjoon@yaoo.com >, Henrik Rostedt <henrik.rostedt@gmail.com >
+ Brazilian Portuguese: Romulo Fernandes Machado <abra185@gmail.com >
+ Bulgarian: Svetoslav Stefanov
+ Czech: Petr Řezáček <rezacek@gmail.com >
+ Chinese: Jie Luo <lililjlj@gmail.com >
+ English: Andrey Korotaev <unC0Rr@gmail.com >
+ Finnish: Nina Kuisma <ninnnu@gmail.com >, Janne Uusitupa
+ French: Antoine Turmel <geekshadow@gmail.com >, Clement Woitrain <sphrixclement@gmail.com >, Matisumi
+ German: Peter Hüwe <PeterHuewe@gmx.de >, Mario Liebisch <mario.liebisch@gmail.com >, Richard Karolyi <sheepluva@ercatec.net >, Wuzzy <Wuzzy2@mail.ru >
+ Greek: <talos_kriti@yahoo.gr >
+ Italian: Luca Bonora <bonora.luca@gmail.com >, Marco Bresciani <m.bresciani@email.it >, Gianfranco Costamagna <costamagnagianfranco@yahoo.it >, Enrico <enricobe@hotmail.com >
+ Japanese: ADAM Etienne <etienne.adam@gmail.com >, Marco Bresciani <m.bresciani@email.it >
+ Korean: Anthony Bellew <anthonyreflected@gmail.com >
+ Lithuanian: Lukas Urbonas <lukasu08@gmail.com >
+ Polish: Maciej Mroziński <mynick2@o2.pl >, Wojciech Latkowski <magik17l@gmail.com >, Piotr Mitana, Maciej Górny, KoBeWi
+ Portuguese: Fábio Canário <inufabie@gmail.com >
+ Russian: Andrey Korotaev <unC0Rr@gmail.com >, Vitaly Novichkov <admin@wohlnet.ru >, Anton Malmygin <antonc27@mail.ru >
+ Slovak: Jose Riha
+ Spanish: Carlos Vives <mail@carlosvives.es >
+ Swedish: Niklas Grahn <raewolusjoon@yaoo.com >, Henrik Rostedt <henrik.rostedt@gmail.com >
Ukrainian: Eugene V. Lyubimkin <jackyf.devel@gmail.com >, Igor Paliychuk <mansonigor@gmail.com >, Eugene Sakara <eresid@gmail.com >
Special thanks:
- Aleksey Andreev <blaknayabr@gmail.com >
- Aleksander Rudalev <alexv@pomorsu.ru >
- Natasha Korotaeva <layout@pisem.net >
+ Aleksey Andreev <blaknayabr@gmail.com >
+ Aleksander Rudalev <alexv@pomorsu.ru >
+ Natasha Korotaeva <layout@pisem.net >
Adam Higerd (aka ahigerd at FreeNode)
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/iconInitHealth.png
Binary file QTfrontend/res/iconInitHealth.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/missionFinished.png
Binary file QTfrontend/res/missionFinished.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/missionFinishedSelected.png
Binary file QTfrontend/res/missionFinishedSelected.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/net.png
Binary file QTfrontend/res/net.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/res/schemeicon.png
Binary file QTfrontend/res/schemeicon.png has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/team.cpp
--- a/QTfrontend/team.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/team.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -208,6 +208,14 @@
return f.exists();
}
+// Returns true if the team name has been changed but a file with the same team name already exists.
+// So if this team would be saved, another team file would be overwritten, which is generally not
+// desired.
+bool HWTeam::wouldOverwriteOtherFile()
+{
+ return (m_name != OldTeamName) && fileExists();
+}
+
bool HWTeam::deleteFile()
{
if(m_isNetTeam)
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/team.h
--- a/QTfrontend/team.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/team.h Sun Dec 17 00:09:24 2017 +0100
@@ -62,6 +62,7 @@
bool deleteFile();
bool saveToFile();
bool fileExists();
+ bool wouldOverwriteOtherFile();
// attribute getters
unsigned int campaignProgress() const;
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/dialog/bandialog.cpp
--- a/QTfrontend/ui/dialog/bandialog.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/dialog/bandialog.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -85,7 +85,13 @@
{
if(leId->text().isEmpty())
{
- QMessageBox::warning(this, tr("Warning"), tr("Please, specify %1").arg(byIP() ? tr("IP") : tr("nickname")));
+ QString warning_text;
+ if (byIP())
+ warning_text = QString(tr("Please specify an IP address."));
+ else
+ warning_text = QString(tr("Please specify a nickname."));
+
+ QMessageBox::warning(this, tr("Warning"), warning_text);
return;
}
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/dialog/upload_video.cpp
--- a/QTfrontend/ui/dialog/upload_video.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/dialog/upload_video.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -57,7 +57,7 @@
"By clicking 'upload,' you certify that you own all rights to the content or that "
"you are authorized by the owner to make the content publicly available on YouTube, "
"and that it otherwise complies with the YouTube Terms of Service located at "
- "http://www.youtube.com/t/terms .
";
+ "https://www.youtube.com/t/terms .
";
// youtube doesn't understand this characters, even when they are properly escaped
// (either with CDATA or with < or >)
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/AbstractPage.cpp
--- a/QTfrontend/ui/page/AbstractPage.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/AbstractPage.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -141,6 +141,13 @@
return btn;
}
+QPushButton* AbstractPage::addSoundlessButton(const QString & name, QGridLayout * grid, int row, int column, int rowSpan, int columnSpan, bool hasIcon, Qt::Alignment alignment)
+{
+ QPushButton * btn = formattedSoundlessButton(name, hasIcon);
+ grid->addWidget(btn, row, column, rowSpan, columnSpan, alignment);
+ return btn;
+}
+
QPushButton* AbstractPage::addSoundlessButton(const QString & name, QBoxLayout * box, int where, bool hasIcon, Qt::Alignment alignment)
{
QPushButton* btn = formattedSoundlessButton(name, hasIcon);
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/AbstractPage.h
--- a/QTfrontend/ui/page/AbstractPage.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/AbstractPage.h Sun Dec 17 00:09:24 2017 +0100
@@ -190,6 +190,7 @@
* @return the button.
*/
QPushButtonWithSound * addButton(const QString & name, QGridLayout * grid, int row, int column, int rowSpan = 1, int columnSpan = 1, bool hasIcon = false, Qt::Alignment alignment = 0);
+ QPushButton * addSoundlessButton(const QString & name, QGridLayout * grid, int row, int column, int rowSpan = 1, int columnSpan = 1, bool hasIcon = false, Qt::Alignment alignment = 0);
/**
* @brief Creates a default formatted button and adds it to a
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pagecampaign.cpp
--- a/QTfrontend/ui/page/pagecampaign.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pagecampaign.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -26,9 +26,10 @@
QLayout * PageCampaign::bodyLayoutDefinition()
{
QGridLayout * pageLayout = new QGridLayout();
- pageLayout->setColumnStretch(0, 1);
- pageLayout->setColumnStretch(1, 2);
- pageLayout->setColumnStretch(2, 1);
+ pageLayout->setColumnStretch(0, 5);
+ pageLayout->setColumnStretch(1, 1);
+ pageLayout->setColumnStretch(2, 9);
+ pageLayout->setColumnStretch(3, 5);
pageLayout->setRowStretch(0, 1);
pageLayout->setRowStretch(3, 1);
@@ -43,6 +44,7 @@
// set this as default image first time page is created, this will change in hwform.cpp
btnPreview = formattedButton(":/res/campaign/A_Classic_Fairytale/first_blood.png", true);
+ btnPreview->setWhatsThis(tr("Start fighting"));
infoLayout->setAlignment(btnPreview, Qt::AlignHCenter | Qt::AlignVCenter);
lbldescription = new QLabel(this);
@@ -52,6 +54,10 @@
lbltitle = new QLabel();
lbltitle->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
+ QLabel* lblteam = new QLabel(tr("Team"));
+ QLabel* lblcampaign = new QLabel(tr("Campaign"));
+ QLabel* lblmission = new QLabel(tr("Mission"));
+
CBTeam = new QComboBox(this);
CBMission = new QComboBox(this);
CBCampaign = new QComboBox(this);
@@ -63,19 +69,41 @@
infoLayout->addWidget(lbltitle,0,2,1,2);
infoLayout->addWidget(lbldescription,1,2,1,2);
- pageLayout->addLayout(infoLayout, 0, 0, 2, 3);
- pageLayout->addWidget(CBTeam, 2, 1);
- pageLayout->addWidget(CBCampaign, 3, 1);
- pageLayout->addWidget(CBMission, 4, 1);
+ pageLayout->addLayout(infoLayout, 0, 0, 2, 4);
+ pageLayout->addWidget(lblteam, 2, 1);
+ pageLayout->addWidget(lblcampaign, 3, 1);
+ pageLayout->addWidget(lblmission, 4, 1);
+ pageLayout->addWidget(CBTeam, 2, 2);
+ pageLayout->addWidget(CBCampaign, 3, 2);
+ pageLayout->addWidget(CBMission, 4, 2);
- BtnStartCampaign = new QPushButton(this);
- BtnStartCampaign->setFont(*font14);
- BtnStartCampaign->setText(QPushButton::tr("Go!"));
- pageLayout->addWidget(BtnStartCampaign, 3, 2);
return pageLayout;
}
+QLayout * PageCampaign::footerLayoutDefinition()
+{
+ QHBoxLayout * footerLayout = new QHBoxLayout();
+
+ const QIcon& lp = QIcon(":/res/Start.png");
+ QSize sz = lp.actualSize(QSize(65535, 65535));
+ BtnStartCampaign = new QPushButton();
+ BtnStartCampaign->setWhatsThis(tr("Start fighting"));
+ BtnStartCampaign->setStyleSheet("padding: 5px 10px");
+ BtnStartCampaign->setText(QPushButton::tr("Start"));
+ BtnStartCampaign->setMinimumWidth(sz.width() + 60);
+ BtnStartCampaign->setIcon(lp);
+ BtnStartCampaign->setFixedHeight(50);
+ BtnStartCampaign->setIconSize(sz);
+ BtnStartCampaign->setFlat(true);
+ BtnStartCampaign->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+ footerLayout->addStretch();
+ footerLayout->addWidget(BtnStartCampaign);
+
+ return footerLayout;
+}
+
PageCampaign::PageCampaign(QWidget* parent) : AbstractPage(parent)
{
initPage();
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pagecampaign.h
--- a/QTfrontend/ui/page/pagecampaign.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pagecampaign.h Sun Dec 17 00:09:24 2017 +0100
@@ -38,6 +38,9 @@
protected:
QLayout * bodyLayoutDefinition();
+
+ private:
+ QLayout * footerLayoutDefinition();
};
#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pagedata.cpp
--- a/QTfrontend/ui/page/pagedata.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pagedata.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -54,7 +54,14 @@
QHBoxLayout * bottomLayout = new QHBoxLayout();
bottomLayout->setStretch(0, 1);
- pbOpenDir = addButton(tr("Open packages directory"), bottomLayout, 1, false, Qt::AlignBottom);
+ pbHome = addButton(":/res/home.png", bottomLayout, 1, true, Qt::AlignBottom);
+ pbHome->setMinimumHeight(50);
+ pbHome->setMinimumWidth(50);
+ pbHome->setWhatsThis(tr("Load the start page"));
+
+ pbOpenDir = addButton(":/res/folder.png", bottomLayout, 2, true, Qt::AlignBottom);
+ pbOpenDir->setStyleSheet("padding: 5px 10px");
+ pbOpenDir->setWhatsThis(tr("Open packages directory"));
pbOpenDir->setMinimumHeight(50);
bottomLayout->setStretch(2, 1);
@@ -67,6 +74,7 @@
connect(web, SIGNAL(anchorClicked(QUrl)), this, SLOT(request(const QUrl&)));
connect(this, SIGNAL(goBack()), this, SLOT(onPageLeave()));
connect(pbOpenDir, SIGNAL(clicked()), this, SLOT(openPackagesDir()));
+ connect(pbHome, SIGNAL(clicked()), this, SLOT(fetchList()));
}
PageDataDownload::PageDataDownload(QWidget* parent) : AbstractPage(parent)
@@ -85,7 +93,12 @@
void PageDataDownload::request(const QUrl &url)
{
QUrl finalUrl;
- if(url.host().isEmpty())
+ if(url.isEmpty())
+ {
+ qWarning() << "Empty URL requested";
+ return;
+ }
+ else if(url.host().isEmpty())
finalUrl = QUrl("https://www.hedgewars.org" + url.path());
else
finalUrl = url;
@@ -123,22 +136,34 @@
void PageDataDownload::pageDownloaded()
{
QNetworkReply * reply = qobject_cast(sender());
+ const char *html =
+ "Hedgewars Downloadable Content "
+ "%1 ";
- if (reply && (reply->error() == QNetworkReply::NoError)) {
- QString html = QString::fromUtf8(reply->readAll());
- int begin = html.indexOf("");
- int end = html.indexOf("");
- if(begin != -1 && begin < end)
+ if (reply) {
+ if (reply->error() == QNetworkReply::NoError)
{
- html.truncate(end);
- html.remove(0, begin);
+ QString html = QString::fromUtf8(reply->readAll());
+ int begin = html.indexOf("");
+ int end = html.indexOf("");
+ if(begin != -1 && begin < end)
+ {
+ html.truncate(end);
+ html.remove(0, begin);
+ }
+ web->setHtml(html);
}
- web->setHtml(html);
- } else
- web->setHtml(QString(
- "Hedgewars Downloadable Content "
- "%1
")
- .arg(tr("This page requires an internet connection.")));
+ else
+ {
+ QString message = reply->error() == QNetworkReply::UnknownNetworkError ?
+ tr("Unknown network error (possibly missing SSL library).") :
+ QString(tr("This feature requires an Internet connection, but you don't appear to be online (error code: %1).")).arg(reply->error());
+ web->setHtml(QString(html).arg(message));
+ }
+ }
+ else {
+ web->setHtml(QString(html).arg(tr("Internal error: Reply object is invalid.")));
+ }
}
void PageDataDownload::fileDownloaded()
@@ -199,7 +224,6 @@
request(QUrl("https://hedgewars.org/content.html"));
}
-
void PageDataDownload::onPageLeave()
{
if (m_contentDownloaded)
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pagedata.h
--- a/QTfrontend/ui/page/pagedata.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pagedata.h Sun Dec 17 00:09:24 2017 +0100
@@ -48,6 +48,7 @@
QHash progressBars;
QVBoxLayout *progressBarsLayout;
QPushButtonWithSound * pbOpenDir;
+ QPushButtonWithSound * pbHome;
bool m_contentDownloaded; ///< true if something was downloaded since last page leave
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pageeditteam.cpp
--- a/QTfrontend/ui/page/pageeditteam.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pageeditteam.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -32,6 +32,7 @@
#include "HWApplication.h"
#include "keybinder.h"
+#include "physfs.h"
#include "DataManager.h"
#include "hatbutton.h"
@@ -77,20 +78,32 @@
HHNameEdit[i]->setFixedHeight(36);
HHNameEdit[i]->setWhatsThis(tr("This hedgehog's name"));
HHNameEdit[i]->setStyleSheet("padding: 6px;");
- GBHLayout->addWidget(HHNameEdit[i], i + 1, 1);
+ GBHLayout->addWidget(HHNameEdit[i], i + 1, 1, 1, 2);
- btnRandomHogName[i] = addButton(":/res/dice.png", GBHLayout, i + 1, 3, 1, 1, true);
+ btnRandomHogName[i] = addButton(":/res/dice.png", GBHLayout, i + 1, 5, 1, 1, true);
btnRandomHogName[i]->setFixedHeight(HHNameEdit[i]->height());
btnRandomHogName[i]->setWhatsThis(tr("Randomize this hedgehog's name"));
}
+ btnRandomHats = new QPushButton();
+ btnRandomHats->setText(tr("Random Hats"));
+ btnRandomHats->setStyleSheet("padding: 6px 10px;");
+ GBHLayout->addWidget(btnRandomHats, 9, 1, 1, 1, Qt::AlignCenter);
+ btnRandomHats->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+ btnRandomNames = new QPushButton();
+ btnRandomNames->setText(tr("Random Names"));
+ btnRandomNames->setStyleSheet("padding: 6px 10px;");
+ GBHLayout->addWidget(btnRandomNames, 9, 2, 1, 1, Qt::AlignCenter);
+ btnRandomNames->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+ vbox1->addWidget(GBoxHedgehogs);
+
btnRandomTeam = new QPushButton();
btnRandomTeam->setText(tr("Random Team"));
btnRandomTeam->setStyleSheet("padding: 6px 10px;");
- GBHLayout->addWidget(btnRandomTeam, 9, 0, 1, 4, Qt::AlignCenter);
btnRandomTeam->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
-
- vbox1->addWidget(GBoxHedgehogs);
+ vbox1->addWidget(btnRandomTeam, 0, Qt::AlignCenter);
GBoxTeam = new QGroupBox(this);
GBoxTeam->setTitle(QGroupBox::tr("Team Settings"));
@@ -114,10 +127,12 @@
TeamNameEdit = new QLineEdit(GBoxTeam);
TeamNameEdit->setMaxLength(64);
- GBTLayout->addWidget(TeamNameEdit, 0, 1);
+ TeamNameEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ GBTLayout->addWidget(TeamNameEdit, 0, 1, 1, 2);
vbox2->addWidget(GBoxTeam);
CBTeamLvl = new QComboBox(GBoxTeam);
+ CBTeamLvl->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
CBTeamLvl->setIconSize(QSize(32, 32));
CBTeamLvl->addItem(QIcon(":/res/botlevels/small0.png"), QComboBox::tr("Human"));
for(int i = 5; i > 0; i--)
@@ -126,46 +141,97 @@
QComboBox::tr("Computer (Level %1)").arg(i)
);
CBTeamLvl->setFixedHeight(38);
- GBTLayout->addWidget(CBTeamLvl, 1, 1);
+ GBTLayout->addWidget(CBTeamLvl, 1, 1, 1, 2);
CBGrave = new QComboBox(GBoxTeam);
+ CBGrave->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
CBGrave->setMaxCount(65535);
CBGrave->setMaxVisibleItems(20);
CBGrave->setIconSize(QSize(32, 32));
CBGrave->setFixedHeight(44);
- GBTLayout->addWidget(CBGrave, 2, 1);
+ GBTLayout->addWidget(CBGrave, 2, 1, 1, 2);
+ // Player flags, combobox to select flag
CBFlag = new QComboBox(GBoxTeam);
CBFlag->setMaxCount(65535);
CBFlag->setMaxVisibleItems(50);
CBFlag->setIconSize(QSize(22, 15));
- GBTLayout->addWidget(CBFlag, 3, 1);
+ CBFlag->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ GBTLayout->addWidget(CBFlag, 3, 1, 1, 2);
+
+ // CPU level flag. Static image, only displayed when computer player is selected
+ QImage imgBotlevels = QImage("physfs://Graphics/botlevels.png");
+
+ int botlevelOffsets[5]= { 19, 14, 10, 6, 0 };
+
+ for(int i=0; i<5; i++) {
+ QImage imgCPU = QImage("physfs://Graphics/Flags/cpu.png");
+ QPainter painter(&imgCPU);
+ painter.drawImage(botlevelOffsets[i], 0, imgBotlevels, botlevelOffsets[i]);
+
+ pixCPU[i] = QPixmap::fromImage(imgCPU);
+ }
+
+ QHBoxLayout* hboxCPU = new QHBoxLayout();
+ hboxCPU->setContentsMargins(0, 0, 0, 0);
+
+ hboxCPUWidget = new QWidget();
+ hboxCPUWidget->setLayout(hboxCPU);
- QHBoxLayout * hbox = new QHBoxLayout();
+ CPUFlag = new QLabel();
+ CPUFlag->setPixmap(pixCPU[0]);
+ CPUFlag->setFixedHeight(38);
+
+ hboxCPU->addWidget(CPUFlag);
+
+ CPUFlagLabel = new QLabel("CPU");
+ CPUFlagLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ hboxCPU->addWidget(CPUFlagLabel);
+
+ hboxCPUWidget->setHidden(true);
+ GBTLayout->addWidget(hboxCPUWidget, 3, 1, 1, 1);
+
+ btnRandomTeamName = addButton(":/res/dice.png", GBTLayout, 0, 3, 1, 1, true);
+ btnRandomTeamName->setWhatsThis(tr("Randomize the team name"));
+
+ btnRandomGrave = addButton(":/res/dice.png", GBTLayout, 2, 3, 1, 1, true);
+ btnRandomGrave->setWhatsThis(tr("Randomize the grave"));
+
+ btnRandomFlag = addButton(":/res/dice.png", GBTLayout, 3, 3, 1, 1, true);
+ btnRandomFlag->setWhatsThis(tr("Randomize the flag"));
+
CBVoicepack = new QComboBox(GBoxTeam);
CBVoicepack->setMaxVisibleItems(50);
+ CBVoicepack->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
- hbox->addWidget(CBVoicepack, 100);
- btnTestSound = addSoundlessButton(":/res/PlaySound.png", hbox, 1, true);
- btnTestSound->setWhatsThis("Play a random example of this voice");
- hbox->setStretchFactor(btnTestSound, 1);
+ GBTLayout->addWidget(CBVoicepack, 4, 1, 1, 1);
- GBTLayout->addLayout(hbox, 4, 1);
+ btnTestSound = addSoundlessButton(":/res/PlaySound.png", GBTLayout, 4, 2, 1, 1, true);
+ btnTestSound->setWhatsThis(tr("Play a random example of this voice"));
+
+ btnRandomVoice = addButton(":/res/dice.png", GBTLayout, 4, 3, 1, 1, true);
+ btnRandomVoice->setWhatsThis(tr("Randomize the voice"));
GBoxFort = new QGroupBox(this);
GBoxFort->setTitle(QGroupBox::tr("Fort"));
QGridLayout * GBFLayout = new QGridLayout(GBoxFort);
CBFort = new QComboBox(GBoxFort);
+ CBFort->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
CBFort->setMaxVisibleItems(25);
CBFort->setMaxCount(65535);
+
GBFLayout->addWidget(CBFort, 0, 0);
+
+ btnRandomFort = addButton(":/res/dice.png", GBFLayout, 0, 2, 1, 1, true);
+ btnRandomFort->setWhatsThis(tr("Randomize the fort"));
+
FortPreview = new SquareLabel(GBoxFort);
FortPreview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
FortPreview->setMinimumSize(128, 128);
FortPreview->setPixmap(QPixmap());
// perhaps due to handling its own paintevents, SquareLabel doesn't play nice with the stars
//FortPreview->setAttribute(Qt::WA_PaintOnScreen, true);
- GBFLayout->addWidget(FortPreview, 1, 0);
+ GBFLayout->addWidget(FortPreview, 1, 0, 1, 2);
vbox2->addWidget(GBoxFort);
vbox1->addStretch();
@@ -187,7 +253,7 @@
signalMapper2 = new QSignalMapper(this);
connect(signalMapper1, SIGNAL(mapped(int)), this, SLOT(fixHHname(int)));
- connect(signalMapper2, SIGNAL(mapped(int)), this, SLOT(setRandomName(int)));
+ connect(signalMapper2, SIGNAL(mapped(int)), this, SLOT(setRandomHogName(int)));
for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
{
@@ -198,11 +264,21 @@
signalMapper2->setMapping(btnRandomHogName[i], i);
}
- connect(btnRandomTeam, SIGNAL(clicked()), this, SLOT(setRandomNames()));
+ connect(btnRandomTeam, SIGNAL(clicked()), this, SLOT(setRandomTeam()));
+ connect(btnRandomNames, SIGNAL(clicked()), this, SLOT(setRandomHogNames()));
+ connect(btnRandomHats, SIGNAL(clicked()), this, SLOT(setRandomHats()));
+
+ connect(CBTeamLvl, SIGNAL(currentIndexChanged(const int)), this, SLOT(CBTeamLvl_activated(const int)));
+
+ connect(btnRandomTeamName, SIGNAL(clicked()), this, SLOT(setRandomTeamName()));
+ connect(btnRandomGrave, SIGNAL(clicked()), this, SLOT(setRandomGrave()));
+ connect(btnRandomFlag, SIGNAL(clicked()), this, SLOT(setRandomFlag()));
+ connect(btnRandomVoice, SIGNAL(clicked()), this, SLOT(setRandomVoice()));
+ connect(btnRandomFort, SIGNAL(clicked()), this, SLOT(setRandomFort()));
connect(btnTestSound, SIGNAL(clicked()), this, SLOT(testSound()));
- connect(CBFort, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(CBFort_activated(const QString &)));
+ connect(CBFort, SIGNAL(currentIndexChanged(const int)), this, SLOT(CBFort_activated(const int)));
}
PageEditTeam::PageEditTeam(QWidget* parent) :
@@ -236,11 +312,32 @@
CBVoicepack->addItems(list);
+ QIcon dlcIcon;
+ dlcIcon.addFile(":/res/dlcMarker.png", QSize(), QIcon::Normal, QIcon::On);
+ dlcIcon.addFile(":/res/dlcMarkerSelected.png", QSize(), QIcon::Selected, QIcon::On);
+ QPixmap emptySpace = QPixmap(7, 15);
+ emptySpace.fill(QColor(0, 0, 0, 0));
+ QIcon notDlcIcon = QIcon(emptySpace);
// forts
list = dataMgr.entryList("Forts", QDir::Files, QStringList("*L.png"));
- list.replaceInStrings(QRegExp("L\\.png$"), "");
- CBFort->addItems(list);
+ foreach (QString file, list)
+ {
+ QString fortPath = PHYSFS_getRealDir(QString("Forts/%1").arg(file).toLocal8Bit().data());
+
+ QString fort = file.replace(QRegExp("L\\.png$"), "");
+
+ bool isDLC = !fortPath.startsWith(datadir->absolutePath());
+ if (isDLC)
+ {
+ CBFort->addItem(dlcIcon, fort, fort);
+ }
+ else
+ {
+ CBFort->addItem(notDlcIcon, fort, fort);
+ }
+
+ }
// graves
@@ -314,10 +411,26 @@
HHNameEdit[idx]->setText(QLineEdit::tr("hedgehog %1").arg(idx+1));
}
-void PageEditTeam::CBFort_activated(const QString & fortname)
+void PageEditTeam::CBFort_activated(const int index)
+{
+ QString fortName = CBFort->itemData(index).toString();
+ QPixmap pix("physfs://Forts/" + fortName + "L.png");
+ FortPreview->setPixmap(pix);
+}
+
+void PageEditTeam::CBTeamLvl_activated(const int index)
{
- QPixmap pix("physfs://Forts/" + fortname + "L.png");
- FortPreview->setPixmap(pix);
+ CBFlag->setHidden(index != 0);
+ btnRandomFlag->setHidden(index != 0);
+
+ if(index > 0)
+ {
+ int cpuLevel = 6 - index;
+ CPUFlag->setPixmap(pixCPU[cpuLevel - 1]);
+ //: Name of a flag for computer-controlled enemies. %1 is replaced with the computer level
+ CPUFlagLabel->setText(tr("CPU %1").arg(cpuLevel));
+ }
+ hboxCPUWidget->setHidden(index == 0);
}
void PageEditTeam::testSound()
@@ -346,8 +459,16 @@
{
m_playerHash = playerHash;
lazyLoad();
+ OldTeamName = name;
+ // Mostly create a default team, with 2 important exceptions:
HWTeam newTeam(name);
+ // Randomize grave to make it less likely that default teams have equal graves (important for resurrector)
+ HWNamegen::teamRandomGrave(newTeam, false);
+ // Randomize fort for greater variety in fort mode with default teams
+ HWNamegen::teamRandomFort(newTeam, false);
+ // DLC forts and graves intentionally filtered out to prevent desyncs and missing grave error
+ // TODO: Remove DLC filter as soon it is not needed anymore
loadTeam(newTeam);
}
@@ -355,6 +476,7 @@
{
m_playerHash = playerHash;
lazyLoad();
+ OldTeamName = name;
HWTeam team(name);
team.loadFromFile();
@@ -374,17 +496,66 @@
HWTeam(name).deleteFile();
}
-void PageEditTeam::setRandomNames()
+void PageEditTeam::setRandomTeam()
+{
+ HWTeam team = data();
+ HWNamegen::teamRandomEverything(team);
+ loadTeam(team);
+}
+
+void PageEditTeam::setRandomHogNames()
{
HWTeam team = data();
- HWNamegen::teamRandomNames(team, true);
+ HWNamegen::teamRandomHogNames(team);
+ loadTeam(team);
+}
+
+void PageEditTeam::setRandomHats()
+{
+ HWTeam team = data();
+ HWNamegen::teamRandomHats(team);
+ loadTeam(team);
+}
+
+void PageEditTeam::setRandomHogName(int hh_index)
+{
+ HWTeam team = data();
+ HWNamegen::teamRandomHogName(team,hh_index);
loadTeam(team);
}
-void PageEditTeam::setRandomName(int hh_index)
+void PageEditTeam::setRandomTeamName()
+{
+ HWTeam team = data();
+ HWNamegen::teamRandomTeamName(team);
+ loadTeam(team);
+}
+
+void PageEditTeam::setRandomGrave()
{
HWTeam team = data();
- HWNamegen::teamRandomName(team,hh_index);
+ HWNamegen::teamRandomGrave(team);
+ loadTeam(team);
+}
+
+void PageEditTeam::setRandomFlag()
+{
+ HWTeam team = data();
+ HWNamegen::teamRandomFlag(team);
+ loadTeam(team);
+}
+
+void PageEditTeam::setRandomVoice()
+{
+ HWTeam team = data();
+ HWNamegen::teamRandomVoice(team);
+ loadTeam(team);
+}
+
+void PageEditTeam::setRandomFort()
+{
+ HWTeam team = data();
+ HWNamegen::teamRandomFort(team);
loadTeam(team);
}
@@ -411,7 +582,7 @@
CBGrave->setCurrentIndex(CBGrave->findText(team.grave()));
CBFlag->setCurrentIndex(CBFlag->findData(team.flag()));
- CBFort->setCurrentIndex(CBFort->findText(team.fort()));
+ CBFort->setCurrentIndex(CBFort->findData(team.fort()));
CBVoicepack->setCurrentIndex(CBVoicepack->findText(team.voicepack()));
QStandardItemModel * binds = DataManager::instance().bindsModel();
@@ -430,7 +601,8 @@
HWTeam PageEditTeam::data()
{
- HWTeam team(TeamNameEdit->text());
+ HWTeam team(OldTeamName);
+ team.setName(TeamNameEdit->text());
team.setDifficulty(CBTeamLvl->currentIndex());
for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
@@ -446,7 +618,7 @@
}
team.setGrave(CBGrave->currentText());
- team.setFort(CBFort->currentText());
+ team.setFort(CBFort->itemData(CBFort->currentIndex()).toString());
team.setVoicepack(CBVoicepack->currentText());
team.setFlag(CBFlag->itemData(CBFlag->currentIndex()).toString());
@@ -461,7 +633,35 @@
void PageEditTeam::saveTeam()
{
- data().saveToFile();
+ HWTeam team = data();
+ if(!team.wouldOverwriteOtherFile())
+ {
+ team.saveToFile();
+ }
+ else
+ {
+ // Name already used -> look for an appropriate name:
+ int i=2;
+ QString origName = team.name();
+ QString newName;
+ while(team.wouldOverwriteOtherFile())
+ {
+ newName = tr("%1 (%2)").arg(origName).arg(i++);
+ team.setName(newName);
+ if(i > 1000)
+ break;
+ }
+
+ QMessageBox teamNameFixedMsg(this);
+ teamNameFixedMsg.setIcon(QMessageBox::Warning);
+ teamNameFixedMsg.setWindowTitle(QMessageBox::tr("Teams - Name already taken"));
+ teamNameFixedMsg.setText(QMessageBox::tr("The team name '%1' is already taken, so your team has been renamed to '%2'.").arg(origName).arg(team.name()));
+ teamNameFixedMsg.setWindowModality(Qt::WindowModal);
+ teamNameFixedMsg.setStandardButtons(QMessageBox::Ok);
+ teamNameFixedMsg.exec();
+
+ team.saveToFile();
+ }
}
// When the "Use default for all binds" is pressed...
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pageeditteam.h
--- a/QTfrontend/ui/page/pageeditteam.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pageeditteam.h Sun Dec 17 00:09:24 2017 +0100
@@ -43,7 +43,8 @@
void deleteTeam(const QString & name);
public slots:
- void CBFort_activated(const QString & gravename);
+ void CBTeamLvl_activated(const int index);
+ void CBFort_activated(const int index);
private:
QTabWidget * tbw;
@@ -56,6 +57,10 @@
SquareLabel *FortPreview;
QComboBox *CBGrave;
QComboBox *CBFlag;
+ QLabel *CPUFlag;
+ QLabel *CPUFlagLabel;
+ QWidget *hboxCPUWidget;
+ QPixmap pixCPU[5];
QComboBox *CBTeamLvl;
QComboBox *CBVoicepack;
QGroupBox *GBoxBinds;
@@ -65,6 +70,7 @@
HatButton * HHHats[HEDGEHOGS_PER_TEAM];
HWTeam data();
QString m_playerHash;
+ QString OldTeamName;
KeyBinder * binder;
bool m_loaded;
@@ -75,17 +81,33 @@
void loadTeam(const HWTeam & team);
// page 1
+ QPushButton * btnRandomTeam;
+ QPushButton * btnRandomNames;
+ QPushButton * btnRandomHats;
+
QPushButton * btnRandomHogName[HEDGEHOGS_PER_TEAM];
- QPushButton * btnRandomTeam;
+ QPushButton * btnRandomTeamName;
+ QPushButton * btnRandomGrave;
+ QPushButton * btnRandomFlag;
+ QPushButton * btnRandomVoice;
+ QPushButton * btnRandomFort;
QPushButton * btnTestSound;
void lazyLoad();
private slots:
void saveTeam();
- void setRandomNames();
+ void setRandomTeam();
+ void setRandomHogNames();
+ void setRandomHats();
- void setRandomName(int hh_index);
+ void setRandomTeamName();
+ void setRandomGrave();
+ void setRandomFlag();
+ void setRandomVoice();
+ void setRandomFort();
+
+ void setRandomHogName(int hh_index);
/// Plays a random voice sound of the currently edited team.
void testSound();
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pagegamestats.cpp
--- a/QTfrontend/ui/page/pagegamestats.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pagegamestats.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -148,6 +148,7 @@
labelGameStats->setText("");
healthPoints.clear();
labelGameRank->setText("");
+ labelGameWin->setText("");
playerPosition = 0;
lastColor = 0;
}
@@ -301,8 +302,10 @@
QString message;
QString killstring;
if(kindOfPoints.compare("") == 0) {
+ //: Number of kills in stats screen, written after the team name
killstring = PageGameStats::tr("(%1 kill)", "", kills).arg(kills);
} else {
+ //: For custom number of points in the stats screen, written after the team name. %1 is the number, %2 is the word. Example: “4 points”
killstring = PageGameStats::tr("(%1 %2)", "", kills).arg(kills).arg(kindOfPoints);
kindOfPoints = QString("");
}
@@ -316,7 +319,7 @@
{
int i = info.indexOf(' ');
int num = info.left(i).toInt();
- QString message = " " + PageGameStats::tr("%1 thought it's good to shoot his own hedgehogs with %2 pts.", "", num).arg(info.mid(i + 1)).arg(num) + "
";
+ QString message = " " + PageGameStats::tr("%1 thought it's good to shoot their own hedgehogs for %2 pts.", "", num).arg(info.mid(i + 1)).arg(num) + "
";
AddStatText(message);
break;
}
@@ -324,7 +327,7 @@
{
int i = info.indexOf(' ');
int num = info.left(i).toInt();
- QString message = " " + PageGameStats::tr("%1 killed %2 of his own hedgehogs.", "", num).arg(info.mid(i + 1)).arg(num) + "
";
+ QString message = " " + PageGameStats::tr("%1 killed %2 of their own hedgehogs.", "", num).arg(info.mid(i + 1)).arg(num) + "
";
AddStatText(message);
break;
}
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pageinfo.cpp
--- a/QTfrontend/ui/page/pageinfo.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pageinfo.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -41,7 +41,7 @@
{
QHBoxLayout * bottomLayout = new QHBoxLayout();
bottomLayout->setContentsMargins(0,0,0,0);
- BtnSnapshots = addButton(":/res/Star.png", bottomLayout, 0, true, Qt::AlignBottom);
+ BtnSnapshots = addButton(":/res/folder.png", bottomLayout, 0, true, Qt::AlignBottom);
BtnSnapshots->setWhatsThis(tr("Open the snapshot folder"));
BtnSnapshots->setMinimumSize(50,50);
return bottomLayout;
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pagemultiplayer.cpp
--- a/QTfrontend/ui/page/pagemultiplayer.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pagemultiplayer.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -34,10 +34,12 @@
QHBoxLayout * pageLayout = new QHBoxLayout();
gameCFG = new GameCFGWidget(this);
- pageLayout->addWidget(gameCFG, 3, Qt::AlignTop);
+ pageLayout->addWidget(gameCFG);
+ pageLayout->setAlignment(gameCFG, Qt::AlignTop);
teamsSelect = new TeamSelWidget(this);
- pageLayout->addWidget(teamsSelect, 2, Qt::AlignTop);
+ pageLayout->addWidget(teamsSelect);
+ teamsSelect->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
return pageLayout;
}
@@ -59,14 +61,14 @@
const QIcon& lp = QIcon(":/res/Start.png");
QSize sz = lp.actualSize(QSize(65535, 65535));
BtnStartMPGame = new QPushButton();
+ BtnStartMPGame->setStyleSheet("padding: 5px 10px");
BtnStartMPGame->setText(tr("Start"));
BtnStartMPGame->setWhatsThis(tr("Start fighting (requires at least 2 teams)"));
- BtnStartMPGame->setMinimumWidth(sz.width() + 60);
BtnStartMPGame->setIcon(lp);
BtnStartMPGame->setFixedHeight(50);
BtnStartMPGame->setIconSize(sz);
BtnStartMPGame->setFlat(true);
- BtnStartMPGame->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ BtnStartMPGame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
footerLayout->addStretch();
footerLayout->addWidget(BtnStartMPGame, 0, Qt::AlignBottom);
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pagenetgame.cpp
--- a/QTfrontend/ui/page/pagenetgame.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pagenetgame.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -50,7 +50,7 @@
leRoomName = new HistoryLineEdit(this, 10);
leRoomName->setWhatsThis(tr("Room name"));
- leRoomName->setMaxLength(60);
+ leRoomName->setMaxLength(40);
leRoomName->setMinimumWidth(400);
leRoomName->setMaximumWidth(600);
leRoomName->setFixedHeight(30);
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pagenetserver.cpp
--- a/QTfrontend/ui/page/pagenetserver.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pagenetserver.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -83,7 +83,7 @@
labelURL->setText(
""
"");
labelURL->setOpenExternalLinks(true);
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pageoptions.cpp
--- a/QTfrontend/ui/page/pageoptions.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pageoptions.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -32,6 +32,7 @@
#include
#include
#include
+#include
#include
#include
@@ -167,7 +168,7 @@
}
{ // group: schemes
- OptionGroupBox * groupSchemes = new OptionGroupBox(":/res/weaponsicon.png", tr("Schemes"), this);
+ OptionGroupBox * groupSchemes = new OptionGroupBox(":/res/schemeicon.png", tr("Schemes"), this);
leftColumn->addWidget(groupSchemes);
groupSchemes->layout()->setColumnStretch(0, 1);
@@ -275,7 +276,8 @@
groupGame->layout()->addWidget(winResContainer, 2, 1);
QLabel *winLabelX = new QLabel(groupGame);
- winLabelX->setText("x"); // decorational x
+ //: Multiplication sign, to be used between two numbers. Note the “x” is only a dummy character, we recommend to use “×” if your language permits it
+ winLabelX->setText(tr("x"));
winLabelX->setFixedWidth(40);
winLabelX->setAlignment(Qt::AlignCenter);
@@ -310,10 +312,11 @@
// Stereo spacing
QLabel * lblStereo = new QLabel(groupGame);
- lblStereo->setText(QLabel::tr("Stereo rendering"));
+ lblStereo->setText(QLabel::tr("Stereoscopy"));
groupGame->layout()->addWidget(lblStereo, 4, 0);
CBStereoMode = new QComboBox(groupGame);
+ CBStereoMode->setWhatsThis(QComboBox::tr("Stereoscopy creates an illusion of depth when you wear 3D glasses."));
CBStereoMode->setMaxVisibleItems(50);
CBStereoMode->addItem(QComboBox::tr("Disabled"));
CBStereoMode->addItem(QComboBox::tr("Red/Cyan"));
@@ -406,7 +409,7 @@
}
{ // group: frontend
- OptionGroupBox * groupFrontend = new OptionGroupBox(":/res/graphicsicon.png", tr("Frontend"), this);
+ OptionGroupBox * groupFrontend = new OptionGroupBox(":/res/frontendicon.png", tr("Frontend"), this);
rightColumn->addWidget(groupFrontend);
// Fullscreen
@@ -419,11 +422,12 @@
CBFrontendEffects = new QCheckBox(groupFrontend);
CBFrontendEffects->setText(QCheckBox::tr("Visual effects"));
+ CBFrontendEffects->setWhatsThis(QCheckBox::tr("Enable visual effects such as animated menu transitions and falling stars"));
groupFrontend->layout()->addWidget(CBFrontendEffects, 1, 0);
}
{ // group: colors
- OptionGroupBox * groupColors = new OptionGroupBox(":/res/lightbulb_on.png", tr("Custom colors"), this);
+ OptionGroupBox * groupColors = new OptionGroupBox(":/res/Palette.png", tr("Custom colors"), this);
rightColumn->addWidget(groupColors);
groupColors->layout()->setColumnStretch(0, 1);
@@ -626,12 +630,41 @@
CBLanguage->setMaxVisibleItems(50);
groupMisc->layout()->addWidget(CBLanguage, 0, 1);
QStringList locs = DataManager::instance().entryList("Locale", QDir::Files, QStringList("hedgewars_*.qm"));
+ QStringList langnames;
CBLanguage->addItem(QComboBox::tr("(System default)"), QString());
for(int i = 0; i < locs.count(); i++)
{
QString lname = locs[i].replace(QRegExp("hedgewars_(.*)\\.qm"), "\\1");
- QLocale loc(lname);
- CBLanguage->addItem(QLocale::languageToString(loc.language()) + " (" + QLocale::countryToString(loc.country()) + ")", lname);
+ QLocale loc = QLocale(lname);
+ QString entryName;
+ // If local identifier has underscore, it means the country has been specified
+ if(lname.contains("_"))
+ {
+ // Append country name for disambiguation
+ // FIXME: These brackets are hardcoded and can't be translated. Luckily, these are rarely used and work with most languages anyway
+ entryName = loc.nativeLanguageName() + " (" + loc.nativeCountryName() + ")";
+ }
+ else
+ {
+ // Usually, we just print the language name
+ entryName = loc.nativeLanguageName();
+ }
+ // Fallback code, if language name is empty for some reason. This should normally not happen
+ if(entryName.isEmpty())
+ {
+ if(lname == "gd")
+ {
+ /* Workaround for Qt4: nativeLanguageName does not return correct name for Scottish Gaelic (QTBUG-59929),
+ so we have to add it ourselves :-/ */
+ entryName = QString::fromUtf8("Gàidhlig");
+ }
+ else
+ {
+ // If all else fails, show error and the locale identifier
+ entryName = tr("MISSING LANGUAGE NAME [%1]").arg(lname);
+ }
+ }
+ CBLanguage->addItem(entryName, lname);
}
QLabel *restartNoticeLabel = new QLabel(groupMisc);
@@ -647,6 +680,7 @@
CBNameWithDate = new QCheckBox(groupMisc);
CBNameWithDate->setText(QCheckBox::tr("Append date and time to record file name"));
+ CBNameWithDate->setWhatsThis(QCheckBox::tr("If enabled, Hedgewars adds the date and time in the form \"YYYY-MM-DD_hh-mm\" for automatically created demos."));
groupMisc->layout()->addWidget(CBNameWithDate, 3, 0, 1, 2);
// Associate file extensions
@@ -674,7 +708,7 @@
btnUpdateNow = new QPushButton(groupUpdates);
connect(btnUpdateNow, SIGNAL(clicked()), this, SLOT(checkForUpdates()));
btnUpdateNow->setWhatsThis(tr("Check for updates"));
- btnUpdateNow->setText("Check now");
+ btnUpdateNow->setText(tr("Check now"));
btnUpdateNow->setFixedSize(130, 30);
groupUpdates->layout()->addWidget(btnUpdateNow, 0, 1);
}
@@ -764,10 +798,10 @@
widthEdit->setValidator(new QIntValidator(this));
groupVideoRec->layout()->addWidget(widthEdit, 5, 1);
- // x
+ // multiplication sign
QLabel *labelX = new QLabel(groupVideoRec);
- labelX->setText("X");
+ labelX->setText(tr("x"));
groupVideoRec->layout()->addWidget(labelX, 5, 2);
// height
@@ -789,17 +823,18 @@
groupVideoRec->layout()->addWidget(labelFramerate, 6, 0);
framerateBox = new QComboBox(groupVideoRec);
- framerateBox->addItem("24 fps", 24);
- framerateBox->addItem("25 fps", 25);
- framerateBox->addItem("30 fps", 30);
- framerateBox->addItem("50 fps", 50);
- framerateBox->addItem("60 fps", 60);
+ framerateBox->addItem(QComboBox::tr("24 FPS"), 24);
+ framerateBox->addItem(QComboBox::tr("25 FPS"), 25);
+ framerateBox->addItem(QComboBox::tr("30 FPS"), 30);
+ framerateBox->addItem(QComboBox::tr("50 FPS"), 50);
+ framerateBox->addItem(QComboBox::tr("60 FPS"), 60);
groupVideoRec->layout()->addWidget(framerateBox, 6, 1);
// label for Bitrate
QLabel *labelBitrate = new QLabel(groupVideoRec);
- labelBitrate->setText(QLabel::tr("Bitrate (Kbps)"));
+ //: “Kibit/s” is the symbol for 1024 bits per second
+ labelBitrate->setText(QLabel::tr("Bitrate (Kibit/s)"));
groupVideoRec->layout()->addWidget(labelBitrate, 6, 2);
// bitrate
@@ -807,6 +842,7 @@
bitrateBox = new QSpinBox(groupVideoRec);
bitrateBox->setRange(100, 5000);
bitrateBox->setSingleStep(100);
+ bitrateBox->setWhatsThis(QSpinBox::tr("Specify the bitrate of recorded videos as a multiple of 1024 bits per second"));
groupVideoRec->layout()->addWidget(bitrateBox, 6, 3);
// button 'set default options'
@@ -951,7 +987,10 @@
void PageOptions::requestDeleteSelectedTeam()
{
- emit deleteTeamRequested(CBTeamName->currentText());
+ if(CBTeamName->count() > 1)
+ emit deleteTeamRequested(CBTeamName->currentText());
+ else
+ QMessageBox::warning(this, tr("Can't delete last team"), tr("You can't delete the last team!"));
}
void PageOptions::setTeamOptionsEnabled(bool enabled)
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pageplayrecord.cpp
--- a/QTfrontend/ui/page/pageplayrecord.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pageplayrecord.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -62,7 +62,7 @@
BtnPlayDemo = addButton(tr("Play demo"), bottomLayout, 0, false, Qt::AlignBottom);
const QIcon& lp = QIcon(":/res/Start.png");
QSize sz = lp.actualSize(QSize(65535, 65535));
- BtnPlayDemo->setMinimumWidth(sz.width());
+ BtnPlayDemo->setStyleSheet("padding: 5px 10px");
BtnPlayDemo->setIcon(lp);
BtnPlayDemo->setFixedHeight(50);
BtnPlayDemo->setIconSize(sz);
@@ -136,8 +136,8 @@
{
QMessageBox recordMsg(this);
recordMsg.setIcon(QMessageBox::Warning);
- recordMsg.setWindowTitle(QMessageBox::tr("Record Play - Error"));
- recordMsg.setText(QMessageBox::tr("Please select record from the list"));
+ recordMsg.setWindowTitle(QMessageBox::tr("Error"));
+ recordMsg.setText(QMessageBox::tr("Please select a file from the list."));
recordMsg.setWindowModality(Qt::WindowModal);
recordMsg.exec();
return ;
@@ -163,8 +163,8 @@
{
QMessageBox renameMsg(this);
renameMsg.setIcon(QMessageBox::Warning);
- renameMsg.setWindowTitle(QMessageBox::tr("Record Play - Error"));
- renameMsg.setText(QMessageBox::tr("Cannot rename to ") + newfullname);
+ renameMsg.setWindowTitle(QMessageBox::tr("Error"));
+ renameMsg.setText(QMessageBox::tr("Cannot rename file to %1.").arg(newfullname));
renameMsg.setWindowModality(Qt::WindowModal);
renameMsg.exec();
}
@@ -180,8 +180,8 @@
{
QMessageBox recordMsg(this);
recordMsg.setIcon(QMessageBox::Warning);
- recordMsg.setWindowTitle(QMessageBox::tr("Record Play - Error"));
- recordMsg.setText(QMessageBox::tr("Please select record from the list"));
+ recordMsg.setWindowTitle(QMessageBox::tr("Error"));
+ recordMsg.setText(QMessageBox::tr("Please select a file from the list."));
recordMsg.setWindowModality(Qt::WindowModal);
recordMsg.exec();
return ;
@@ -195,8 +195,8 @@
{
QMessageBox removeMsg(this);
removeMsg.setIcon(QMessageBox::Warning);
- removeMsg.setWindowTitle(QMessageBox::tr("Record Play - Error"));
- removeMsg.setText(QMessageBox::tr("Cannot delete file ") + rfile.fileName());
+ removeMsg.setWindowTitle(QMessageBox::tr("Error"));
+ removeMsg.setText(QMessageBox::tr("Cannot delete file %1.").arg(rfile.fileName()));
removeMsg.setWindowModality(Qt::WindowModal);
removeMsg.exec();
}
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pageroomslist.cpp
--- a/QTfrontend/ui/page/pageroomslist.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pageroomslist.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -176,6 +176,7 @@
BtnAdmin = addButton(tr("Admin features"), bottomLayout, 0, false, Qt::AlignBottom);
BtnAdmin->setMinimumSize(180, 50);
+ BtnAdmin->setStyleSheet("padding: 5px 10px");
BtnAdmin->setWhatsThis(tr("Open server administration page"));
return bottomLayout;
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pagescheme.cpp
--- a/QTfrontend/ui/page/pagescheme.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pagescheme.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -68,25 +68,21 @@
gbBasicSettings->setLayout(glBSLayout);
// Left
- TBW_mode_Forts = new ToggleButtonWidget(gbGameModes, ":/res/btnForts@2x.png");
- TBW_mode_Forts->setWhatsThis(tr("Defend your fort and destroy the opponents, two team colours max!"));
- glGMLayout->addWidget(TBW_mode_Forts,0,0,1,1);
-
TBW_disablegirders = new ToggleButtonWidget(gbGameModes, ":/res/btnDisableGirders@2x.png");
TBW_disablegirders->setWhatsThis(tr("Disable girders when generating random maps."));
- glGMLayout->addWidget(TBW_disablegirders,0,1,1,1);
+ glGMLayout->addWidget(TBW_disablegirders,0,0,1,1);
TBW_disablelandobjects = new ToggleButtonWidget(gbGameModes, ":/res/btnDisableLandObjects@2x.png");
TBW_disablelandobjects->setWhatsThis(tr("Disable land objects when generating random maps."));
- glGMLayout->addWidget(TBW_disablelandobjects,0,2,1,1);
+ glGMLayout->addWidget(TBW_disablelandobjects,0,1,1,1);
TBW_border = new ToggleButtonWidget(gbGameModes, ":/res/btnBorder@2x.png");
TBW_border->setWhatsThis(tr("Add an indestructible border around the terrain"));
- glGMLayout->addWidget(TBW_border,0,3,1,1);
+ glGMLayout->addWidget(TBW_border,0,2,1,1);
TBW_bottomborder = new ToggleButtonWidget(gbGameModes, ":/res/btnBottomBorder@2x.png");
TBW_bottomborder->setWhatsThis(tr("Add an indestructible border along the bottom"));
- glGMLayout->addWidget(TBW_bottomborder,0,4,1,1);
+ glGMLayout->addWidget(TBW_bottomborder,0,3,1,1);
TBW_solid = new ToggleButtonWidget(gbGameModes, ":/res/btnSolid@2x.png");
TBW_solid->setWhatsThis(tr("Land can not be destroyed!"));
@@ -232,11 +228,11 @@
l = new QLabel(gbBasicSettings);
l->setWhatsThis(wtInitHealth);
l->setFixedSize(32,32);
- l->setPixmap(QPixmap(":/res/iconHealth.png"));
+ l->setPixmap(QPixmap(":/res/iconInitHealth.png"));
glBSLayout->addWidget(l,2,1,1,1);
SB_InitHealth = new QSpinBox(gbBasicSettings);
SB_InitHealth->setWhatsThis(wtInitHealth);
- SB_InitHealth->setRange(50, 200);
+ SB_InitHealth->setRange(1, 1000);
SB_InitHealth->setValue(100);
SB_InitHealth->setSingleStep(25);
glBSLayout->addWidget(SB_InitHealth,2,2,1,1);
@@ -287,7 +283,7 @@
glBSLayout->addWidget(l,5,1,1,1);
SB_HealthDecrease = new QSpinBox(gbBasicSettings);
SB_HealthDecrease->setWhatsThis(wtHealthDecrease);
- SB_HealthDecrease->setRange(0, 100);
+ SB_HealthDecrease->setRange(0, 1000);
SB_HealthDecrease->setValue(5);
SB_HealthDecrease->setSingleStep(1);
glBSLayout->addWidget(SB_HealthDecrease,5,2,1,1);
@@ -354,7 +350,7 @@
glBSLayout->addWidget(l,9,1,1,1);
SB_CrateHealth = new QSpinBox(gbBasicSettings);
SB_CrateHealth->setWhatsThis(wtCrateHealth);
- SB_CrateHealth->setRange(0, 200);
+ SB_CrateHealth->setRange(0, 1000);
SB_CrateHealth->setValue(25);
SB_CrateHealth->setSingleStep(5);
glBSLayout->addWidget(SB_CrateHealth,9,2,1,1);
@@ -503,7 +499,7 @@
l->setText(QLabel::tr("Scheme Name:"));
LE_name = new QLineEdit(this);
- LE_name->setWhatsThis("Name of this scheme");
+ LE_name->setWhatsThis(tr("Name of this scheme"));
gl->addWidget(LE_name,15,1,1,5);
gl->addWidget(l,15,0,1,1);
@@ -550,7 +546,6 @@
selectScheme->setModel(model);
mapper->addMapping(LE_name, 0);
- mapper->addMapping(TBW_mode_Forts, 1);
mapper->addMapping(TBW_teamsDivide, 2);
mapper->addMapping(TBW_solid, 3);
mapper->addMapping(TBW_border, 4);
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pagescheme.h
--- a/QTfrontend/ui/page/pagescheme.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pagescheme.h Sun Dec 17 00:09:24 2017 +0100
@@ -51,7 +51,6 @@
private:
QDataWidgetMapper * mapper;
- ToggleButtonWidget * TBW_mode_Forts;
ToggleButtonWidget * TBW_teamsDivide;
ToggleButtonWidget * TBW_solid;
ToggleButtonWidget * TBW_border;
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pageselectweapon.cpp
--- a/QTfrontend/ui/page/pageselectweapon.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pageselectweapon.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -30,6 +30,7 @@
QGridLayout * pageLayout = new QGridLayout();
pWeapons = new SelWeaponWidget(cAmmoNumber, this);
+ pWeapons->init();
pageLayout->addWidget(pWeapons);
return pageLayout;
@@ -59,11 +60,12 @@
void PageSelectWeapon::connectSignals()
{
+ connect(selectWeaponSet, SIGNAL(currentIndexChanged(const QString&)), pWeapons, SLOT(switchWeapons(const QString&)));
connect(BtnDefault, SIGNAL(clicked()), pWeapons, SLOT(setDefault()));
connect(this, SIGNAL(goBack()), pWeapons, SLOT(save()));
connect(BtnNew, SIGNAL(clicked()), pWeapons, SLOT(newWeaponsName()));
connect(BtnCopy, SIGNAL(clicked()), pWeapons, SLOT(copy()));
- connect(selectWeaponSet, SIGNAL(currentIndexChanged(const QString&)), pWeapons, SLOT(setWeaponsName(const QString&)));
+ connect(BtnDelete, SIGNAL(clicked()), pWeapons, SLOT(deleteWeaponsName()));
}
PageSelectWeapon::PageSelectWeapon(QWidget* parent) : AbstractPage(parent)
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pagetraining.cpp
--- a/QTfrontend/ui/page/pagetraining.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pagetraining.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -73,14 +73,29 @@
pageLayout->setAlignment(infoLayout, Qt::AlignLeft);
- // mission list
- lstMissions = new QListWidget(this);
- lstMissions->setWhatsThis(tr("Pick the mission or training to play"));
- pageLayout->addWidget(lstMissions, 1, 0, 1, 2); // span 2 columns
+ // tab widget containing all lists
+ tbw = new QTabWidget(this);
+ pageLayout->addWidget(tbw, 1, 0, 1, 2); // span 2 columns
+ // let's not make the tab widget use more space than needed
+ tbw->setFixedWidth(400);
+ pageLayout->setAlignment(tbw, Qt::AlignHCenter);
+
+ tbw->setStyleSheet("QListWidget { border-style: none; padding-top: 6px; }");
- // let's not make the list use more space than needed
- lstMissions->setFixedWidth(400);
- pageLayout->setAlignment(lstMissions, Qt::AlignHCenter);
+ // training/challenge/scenario lists
+ lstTrainings = new QListWidget(this);
+ lstTrainings ->setWhatsThis(tr("Pick the training to play"));
+
+ lstChallenges = new QListWidget(this);
+ lstChallenges ->setWhatsThis(tr("Pick the challenge to play"));
+
+ lstScenarios= new QListWidget(this);
+ lstScenarios->setWhatsThis(tr("Pick the scenario to play"));
+
+ tbw->addTab(lstTrainings, tr("Trainings"));
+ tbw->addTab(lstChallenges, tr("Challenges"));
+ tbw->addTab(lstScenarios, tr("Scenarios"));
+ tbw->setCurrentWidget(lstTrainings);
return pageLayout;
}
@@ -89,9 +104,18 @@
{
QBoxLayout * bottomLayout = new QVBoxLayout();
- btnStart = formattedButton(QPushButton::tr("Go!"));
+ const QIcon& lp = QIcon(":/res/Start.png");
+ QSize sz = lp.actualSize(QSize(65535, 65535));
+ btnStart = new QPushButton();
+ btnStart->setStyleSheet("padding: 5px 10px");
+ btnStart->setText(QPushButton::tr("Start"));
btnStart->setWhatsThis(tr("Start fighting"));
- btnStart->setFixedWidth(140);
+ btnStart->setMinimumWidth(sz.width() + 60);
+ btnStart->setIcon(lp);
+ btnStart->setFixedHeight(50);
+ btnStart->setIconSize(sz);
+ btnStart->setFlat(true);
+ btnStart->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
bottomLayout->addWidget(btnStart);
@@ -103,9 +127,20 @@
void PageTraining::connectSignals()
{
- connect(lstMissions, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, SLOT(updateInfo()));
- connect(lstMissions, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(updateInfo()));
- connect(lstMissions, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(startSelected()));
+ connect(lstTrainings, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, SLOT(updateInfo()));
+ connect(lstTrainings, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(updateInfo()));
+ connect(lstTrainings, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(startSelected()));
+
+ connect(lstChallenges, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, SLOT(updateInfo()));
+ connect(lstChallenges, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(updateInfo()));
+ connect(lstChallenges, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(startSelected()));
+
+ connect(lstScenarios, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, SLOT(updateInfo()));
+ connect(lstScenarios, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(updateInfo()));
+ connect(lstScenarios, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(startSelected()));
+
+ connect(tbw, SIGNAL(currentChanged(int)), this, SLOT(updateInfo()));
+
connect(btnPreview, SIGNAL(clicked()), this, SLOT(startSelected()));
connect(btnStart, SIGNAL(clicked()), this, SLOT(startSelected()));
}
@@ -140,79 +175,130 @@
m_info = new QSettings(infoFile, QSettings::IniFormat, this);
m_info->setIniCodec("UTF-8");
-
- QStringList missionList = dataMgr.entryList(
- "Missions/Training",
- QDir::Files, QStringList("*.lua")).
- replaceInStrings(QRegExp("\\.lua$"), "");
-
- // scripts to lost - TODO: model?
- foreach (const QString & mission, missionList)
- {
- QListWidgetItem * item = new QListWidgetItem(mission);
+ QStringList m_list;
+ QListWidget * m_widget;
+ QString subFolder;
- // fallback name: replace underscores in mission name with spaces
- QString name = item->text().replace("_", " ");
-
- // see if we can get a prettier/translated name
- name = m_info->value(mission + ".name", name).toString();
+ for(int i=1; i<=3; i++) {
+ switch(i) {
+ case 1:
+ subFolder = "Training";
+ m_widget = lstTrainings;
+ break;
+ case 2:
+ subFolder = "Challenge";
+ m_widget = lstChallenges;
+ break;
+ case 3:
+ subFolder = "Scenario";
+ m_widget = lstScenarios;
+ break;
+ }
+ m_list = dataMgr.entryList(
+ "Missions/" + subFolder,
+ QDir::Files, QStringList("*.lua")).
+ replaceInStrings(QRegExp("\\.lua$"), "");
- item->setText(name);
+ // scripts to load - TODO: model?
+ foreach (const QString & m_id, m_list)
+ {
+ QListWidgetItem * item = new QListWidgetItem(m_id);
+
+ // fallback name: replace underscores in mission name with spaces
+ QString name = item->text().replace("_", " ");
- // store original name in data
- item->setData(Qt::UserRole, mission);
+ // see if we can get a prettier/translated name
+ name = m_info->value(m_id + ".name", name).toString();
+
+ item->setText(name);
- lstMissions->addItem(item);
+ // store original name in data
+ item->setData(Qt::UserRole, m_id);
+
+ m_widget->addItem(item);
+ }
}
updateInfo();
// pre-select first mission
- if (lstMissions->count() > 0)
- lstMissions->setCurrentRow(0);
+ if (lstTrainings->count() > 0)
+ lstTrainings->setCurrentRow(0);
+
+ if (lstChallenges->count() > 0)
+ lstChallenges->setCurrentRow(0);
+
+ if (lstScenarios->count() > 0)
+ lstScenarios->setCurrentRow(0);
}
+QString PageTraining::getSubFolderOfSelected()
+{
+ QString subFolder;
+ if (tbw->currentWidget() == lstTrainings) {
+ subFolder = "Training";
+ } else if (tbw->currentWidget() == lstChallenges) {
+ subFolder = "Challenge";
+ } else if (tbw->currentWidget() == lstScenarios) {
+ subFolder = "Scenario";
+ } else {
+ subFolder = "Training";
+ }
+ return subFolder;
+}
void PageTraining::startSelected()
{
- QListWidgetItem * curItem = lstMissions->currentItem();
+ QListWidget *list;
+ list = (QListWidget*) tbw->currentWidget();
+ QListWidgetItem * curItem = list->currentItem();
if (curItem != NULL)
- emit startMission(curItem->data(Qt::UserRole).toString());
+ emit startMission(curItem->data(Qt::UserRole).toString(), getSubFolderOfSelected());
}
void PageTraining::updateInfo()
{
- if (lstMissions->currentItem())
+ if (tbw->currentWidget())
{
- // TODO also use .pngs in userdata folder
- QString thumbFile = "physfs://Graphics/Missions/Training/" +
- lstMissions->currentItem()->data(Qt::UserRole).toString() +
- "@2x.png";
+ QString subFolder;
+ QListWidget *list;
+ subFolder = getSubFolderOfSelected();
+ list = (QListWidget*) tbw->currentWidget();
+ if (list->currentItem())
+ {
+ // TODO also use .pngs in userdata folder
+ QString thumbFile = "physfs://Graphics/Missions/" +
+ subFolder + "/" +
+ list->currentItem()->data(Qt::UserRole).toString() +
+ "@2x.png";
- if (QFile::exists(thumbFile))
- btnPreview->setIcon(QIcon(thumbFile));
- else
- btnPreview->setIcon(QIcon(":/res/Trainings.png"));
-
- QString realName = lstMissions->currentItem()->data(
- Qt::UserRole).toString();
+ if (QFile::exists(thumbFile))
+ btnPreview->setIcon(QIcon(thumbFile));
+ else
+ btnPreview->setIcon(QIcon(":/res/Trainings.png"));
- QString caption = m_info->value(realName + ".name",
- lstMissions->currentItem()->text()).toString();
+ btnPreview->setWhatsThis(tr("Start fighting"));
+
+ QString realName = list->currentItem()->data(
+ Qt::UserRole).toString();
- QString description = m_info->value(realName + ".desc",
- tr("No description available")).toString();
+ QString caption = m_info->value(realName + ".name",
+ list->currentItem()->text()).toString();
+
+ QString description = m_info->value(realName + ".desc",
+ tr("No description available")).toString();
- lblCaption->setText("" + caption +" ");
- lblDescription->setText(description);
- }
- else
- {
- btnPreview->setIcon(QIcon(":/res/Trainings.png"));
- lblCaption->setText(tr("Select a mission!"));
- // TODO better text and tr()
- lblDescription->setText("");
+ lblCaption->setText("" + caption +" ");
+ lblDescription->setText(description);
+ }
+ else
+ {
+ btnPreview->setIcon(QIcon(":/res/Trainings.png"));
+ lblCaption->setText(tr("Select a mission!"));
+ // TODO better text and tr()
+ lblDescription->setText("");
+ }
}
}
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pagetraining.h
--- a/QTfrontend/ui/page/pagetraining.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pagetraining.h Sun Dec 17 00:09:24 2017 +0100
@@ -30,7 +30,7 @@
signals:
- void startMission(const QString & scriptName);
+ void startMission(const QString & scriptName, const QString & subFolder);
protected:
@@ -44,8 +44,12 @@
QPushButton * btnStart;
QLabel * lblCaption;
QLabel * lblDescription;
- QListWidget * lstMissions;
+ QTabWidget * tbw;
+ QListWidget * lstTrainings;
+ QListWidget * lstChallenges;
+ QListWidget * lstScenarios;
QSettings * m_info;
+ QString getSubFolderOfSelected();
private slots:
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/page/pagevideos.cpp
--- a/QTfrontend/ui/page/pagevideos.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/page/pagevideos.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -77,7 +77,7 @@
QString name;
QString prefix; // original filename without extension
QString desc; // description (duration, resolution, etc...)
- QString uploadUrl; // http://youtu.be/???????
+ QString uploadUrl; // https://youtu.be/???????
HWRecorder * pRecorder; // non NULL if file is being encoded
QNetworkReply * pUploading; // non NULL if file is being uploaded
bool seen; // used when updating directory
@@ -114,7 +114,7 @@
// list of videos
{
IconedGroupBox* pTableGroup = new IconedGroupBox(this);
- pTableGroup->setIcon(QIcon(":/res/graphicsicon.png")); // FIXME
+ pTableGroup->setIcon(QIcon(":/res/Videos.png"));
pTableGroup->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
pTableGroup->setTitle(QGroupBox::tr("Videos"));
@@ -151,7 +151,7 @@
// description
{
IconedGroupBox* pDescGroup = new IconedGroupBox(this);
- pDescGroup->setIcon(QIcon(":/res/graphicsicon.png")); // FIXME
+ pDescGroup->setIcon(QIcon(":/res/miscicon.png"));
pDescGroup->setTitle(QGroupBox::tr("Description"));
QVBoxLayout* pDescLayout = new QVBoxLayout(pDescGroup);
@@ -194,7 +194,7 @@
pBottomDescLayout->addWidget(btnDelete);
btnToYouTube = new QPushButton(QPushButton::tr("Upload to YouTube"), pDescGroup);
btnToYouTube->setEnabled(false);
- btnToYouTube->setWhatsThis(QPushButton::tr("Upload this video to your Youtube account"));
+ btnToYouTube->setWhatsThis(QPushButton::tr("Upload this video to your YouTube account"));
pBottomDescLayout->addWidget(btnToYouTube);
pDescLayout->addWidget(labelThumbnail, 0);
@@ -823,7 +823,7 @@
if (!videoid.isEmpty())
{
- item->uploadUrl = "http://youtu.be/" + videoid;
+ item->uploadUrl = "https://youtu.be/" + videoid;
updateDescription();
// save url in file
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/MinesTimeSpinBox.h
--- a/QTfrontend/ui/widget/MinesTimeSpinBox.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/MinesTimeSpinBox.h Sun Dec 17 00:09:24 2017 +0100
@@ -44,7 +44,7 @@
protected:
/**
- * Returns it's value localized.
+ * Returns its value localized.
* @param value integer value to be representing as string.
* @return string representation
*/
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/about.cpp
--- a/QTfrontend/ui/widget/about.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/about.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -71,15 +71,18 @@
QLabel *lbl1 = new QLabel(this);
lbl1->setOpenExternalLinks(true);
lbl1->setText(
- ""
- "Hedgewars " + *cVersionString + " "
- "
" + QLabel::tr("Revision") + " " + *cRevisionString + " (" + *cHashString + ") "
- "
https://www.hedgewars.org/
" +
- QLabel::tr("This program is distributed under the %1").arg("
GNU GPL v2 ") +
+ //: %1 contains Hedgewars' version number
+ "
"+QString(tr("Hedgewars %1")).arg(*cVersionString) + " "
+ //: “Revision” stands for a revision in Mercurial, a distributed version control system. %1 is the revision, %2 is the hexadecimal hash.
+ "
" + QString(tr("Revision %1 (%2)")).arg(*cRevisionString, *cHashString) + " "
+ //: %1 is replaced by the URL of Hedgewars.
+ "
" + QString(tr("Visit our homepage: %1"))
+ .arg("https://www.hedgewars.org/ ") + "
" +
+ //: %1 is the name of a license
+ tr("This program is distributed under the %1.")
+ .arg("
"+
+ //: Short for “GNU General Public License version 2”
+ tr("GNU GPL v2")+" ") +
"
"
);
lbl1->setWordWrap(true);
@@ -93,10 +96,12 @@
/* Library information */
- QString libinfo = "";
+ //: For the version numbers of Hedgewars' software dependencies
+ QString libinfo = QString(tr("Dependency versions:") + QString("
"));
#ifdef __GNUC__
- libinfo.append(QString("
GCC %1
").arg(__VERSION__));
+ libinfo.append(QString(tr("
GCC : %1")).arg(__VERSION__));
+ libinfo.append(QString("
"));
#else
libinfo.append(QString(tr("Unknown Compiler")).arg(__VERSION__) + QString("
"));
#endif
@@ -105,83 +110,93 @@
SDL_version sdl_version;
SDL_GetVersion(&sdl_version);
sdl_ver = &sdl_version;
- libinfo.append(QString("
SDL2 version: %1.%2.%3
")
+ libinfo.append(QString(tr("
SDL2 : %1.%2.%3"))
.arg(sdl_ver->major)
.arg(sdl_ver->minor)
.arg(sdl_ver->patch));
+ libinfo.append(QString("
"));
const SDL_version *sdlmixer_ver = Mix_Linked_Version();
- libinfo.append(QString("
SDL2_mixer version: %1.%2.%3
")
+ libinfo.append(QString(tr("
SDL2_mixer : %1.%2.%3"))
.arg(sdlmixer_ver->major)
.arg(sdlmixer_ver->minor)
.arg(sdlmixer_ver->patch));
+ libinfo.append(QString("
"));
// the remaining sdl modules used only in engine, so instead of needlessly linking them here
// we dynamically call the function returning the linked version
- void *sdlnet_handle = SDL_LoadObject(sopath("SDL_net"));
+ void *sdlnet_handle = SDL_LoadObject(sopath("SDL2_net"));
if (sdlnet_handle != NULL) {
SDL_version *(*sdlnet_ver_get)(void) = NULL;
sdlnet_ver_get = (SDL_version *(*)(void)) SDL_LoadFunction(sdlnet_handle, "SDLNet_Linked_Version");
if (sdlnet_ver_get != NULL) {
SDL_version *sdlnet_ver = sdlnet_ver_get();
- libinfo.append(QString("
SDL_net version: %1.%2.%3
")
+ libinfo.append(QString(tr("
SDL2_net : %1.%2.%3"))
.arg(sdlnet_ver->major)
.arg(sdlnet_ver->minor)
.arg(sdlnet_ver->patch));
+ libinfo.append(QString("
"));
}
SDL_UnloadObject(sdlnet_handle);
}
- void *sdlimage_handle = SDL_LoadObject(sopath("SDL_image"));
+ void *sdlimage_handle = SDL_LoadObject(sopath("SDL2_image"));
if (sdlimage_handle != NULL) {
SDL_version *(*sdlimage_ver_get)(void) = NULL;
sdlimage_ver_get = (SDL_version *(*)(void)) SDL_LoadFunction(sdlimage_handle, "IMG_Linked_Version");
if (sdlimage_ver_get != NULL) {
SDL_version *sdlimage_ver = sdlimage_ver_get();
- libinfo.append(QString("
SDL_image version: %1.%2.%3
")
+ libinfo.append(QString(tr("
SDL2_image : %1.%2.%3"))
.arg(sdlimage_ver->major)
.arg(sdlimage_ver->minor)
.arg(sdlimage_ver->patch));
+ libinfo.append(QString("
"));
}
- SDL_UnloadObject(sdlnet_handle);
+ SDL_UnloadObject(sdlimage_handle);
}
- void *sdlttf_handle = SDL_LoadObject(sopath("SDL_ttf"));
+ void *sdlttf_handle = SDL_LoadObject(sopath("SDL2_ttf"));
if (sdlttf_handle != NULL) {
SDL_version *(*sdlttf_ver_get)(void) = NULL;
sdlttf_ver_get = (SDL_version *(*)(void)) SDL_LoadFunction(sdlttf_handle, "TTF_Linked_Version");
if (sdlttf_ver_get != NULL) {
SDL_version *sdlttf_ver = sdlttf_ver_get();
- libinfo.append(QString("
SDL_ttf version: %1.%2.%3
")
+ libinfo.append(QString(tr("
SDL2_ttf : %1.%2.%3"))
.arg(sdlttf_ver->major)
.arg(sdlttf_ver->minor)
.arg(sdlttf_ver->patch));
+ libinfo.append(QString("
"));
}
- SDL_UnloadObject(sdlnet_handle);
+ SDL_UnloadObject(sdlttf_handle);
}
- libinfo.append(QString("
Qt version: %1
").arg(QT_VERSION_STR));
+ libinfo.append(QString(tr("
Qt : %1")).arg(QT_VERSION_STR));
+ libinfo.append(QString("
"));
#ifdef VIDEOREC
- libinfo.append(QString("
libavcodec version: %1.%2.%3
")
+ libinfo.append(QString(tr("
libavcodec : %1.%2.%3"))
.arg(LIBAVCODEC_VERSION_MAJOR)
.arg(LIBAVCODEC_VERSION_MINOR)
.arg(LIBAVCODEC_VERSION_MICRO));
- libinfo.append(QString("
libavformat version: %1.%2.%3
")
+ libinfo.append(QString("
"));
+ libinfo.append(QString(tr("
libavformat : %1.%2.%3"))
.arg(LIBAVFORMAT_VERSION_MAJOR)
.arg(LIBAVFORMAT_VERSION_MINOR)
.arg(LIBAVFORMAT_VERSION_MICRO));
- libinfo.append(QString("
libavutil version: %1.%2.%3
")
+ libinfo.append(QString("
"));
+ libinfo.append(QString(tr("
libavutil : %1.%2.%3"))
.arg(LIBAVUTIL_VERSION_MAJOR)
.arg(LIBAVUTIL_VERSION_MINOR)
.arg(LIBAVUTIL_VERSION_MICRO));
+ libinfo.append(QString("
"));
#endif
- libinfo.append(QString("
PhysFS version: %1.%2.%3
")
+ libinfo.append(QString(tr("
PhysFS : %1.%2.%3"))
.arg(PHYSFS_VER_MAJOR)
.arg(PHYSFS_VER_MINOR)
.arg(PHYSFS_VER_PATCH));
+ libinfo.append(QString("
"));
// TODO: how to add Lua information?
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/chatwidget.cpp
--- a/QTfrontend/ui/widget/chatwidget.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/chatwidget.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -270,6 +270,10 @@
acBan->setIcon(QIcon(":/res/ban.png"));
acBan->setData(QVariant(true));
connect(acBan, SIGNAL(triggered(bool)), this, SLOT(onBan()));
+ acDelegate = new QAction(QAction::tr("Delegate room control"), chatNicks);
+ acDelegate->setIcon(QIcon(":/res/chat/roomadmin.png"));
+ acDelegate->setData(QVariant(true));
+ connect(acDelegate, SIGNAL(triggered(bool)), this, SLOT(onDelegate()));
acFollow = new QAction(QAction::tr("Follow"), chatNicks);
acFollow->setIcon(QIcon(":/res/follow.png"));
acFollow->setData(QVariant(false));
@@ -624,6 +628,14 @@
emit ban(mil[0].data().toString());
}
+void HWChatWidget::onDelegate()
+{
+ QModelIndexList mil = chatNicks->selectionModel()->selectedRows();
+
+ if(mil.size())
+ emit delegate(mil[0].data().toString());
+}
+
void HWChatWidget::onInfo()
{
QModelIndexList mil = chatNicks->selectionModel()->selectedRows();
@@ -732,6 +744,7 @@
{
chatNicks->removeAction(acKick);
//chatNicks->removeAction(acBan);
+ chatNicks->removeAction(acDelegate);
m_isAdmin = b;
@@ -739,6 +752,7 @@
{
chatNicks->insertAction(0, acKick);
//chatNicks->insertAction(0, acBan);
+ chatNicks->insertAction(acFriend, acDelegate);
}
}
@@ -931,6 +945,7 @@
{
acKick->setVisible(!isSelf && isOnline);
acBan->setVisible(!isSelf);
+ acDelegate->setVisible(!isSelf && players->isFlagSet(m_userNick, PlayersListModel::InRoom));
}
m_nicksMenu->clear();
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/chatwidget.h
--- a/QTfrontend/ui/widget/chatwidget.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/chatwidget.h Sun Dec 17 00:09:24 2017 +0100
@@ -128,6 +128,7 @@
void chatLine(const QString& str);
void kick(const QString & str);
void ban(const QString & str);
+ void delegate(const QString & str);
void info(const QString & str);
void follow(const QString &);
void nickCountUpdate(int cnt);
@@ -144,6 +145,7 @@
QAction * acInfo;
QAction * acKick;
QAction * acBan;
+ QAction * acDelegate;
QAction * acFollow;
QAction * acIgnore;
QAction * acFriend;
@@ -163,6 +165,7 @@
void returnPressed();
void onBan();
void onKick();
+ void onDelegate();
void onInfo();
void onFollow();
void onIgnore();
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/feedbackdialog.cpp
--- a/QTfrontend/ui/widget/feedbackdialog.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/feedbackdialog.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -156,8 +156,9 @@
captchaLayoutWidget->setLayout(captchaLayout);
feedbackLayout->addWidget(captchaLayoutWidget, 3, 1, 1, 2);
- // TODO: Set green arrow icon for send button (:/res/Start.png)
BtnSend = new QPushButton(tr("Send Feedback"));
+ BtnSend->setStyleSheet("qproperty-icon: url(:/res/Start.png);");
+
feedbackLayout->addWidget(BtnSend, 3, 3);
BtnSend->setFixedHeight(40);
connect(BtnSend, SIGNAL(clicked()), this, SLOT(SendFeedback()));
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/gamecfgwidget.cpp
--- a/QTfrontend/ui/widget/gamecfgwidget.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/gamecfgwidget.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -333,6 +333,8 @@
bcfg << QString("e$mapgen %1").arg(mapgen).toUtf8();
if(!schemeData(43).isNull())
bcfg << QString("e$scriptparam %1").arg(schemeData(43).toString()).toUtf8();
+ else
+ bcfg << QString("e$scriptparam ").toUtf8();
switch (mapgen)
@@ -695,6 +697,11 @@
schemeChanged(GameSchemes->currentIndex());
}
+void GameCFGWidget::resendAmmoData()
+{
+ ammoChanged(WeaponsName->currentIndex());
+}
+
void GameCFGWidget::onDrawnMapChanged(const QByteArray & data)
{
emit paramChanged("DRAWNMAP", QStringList(qCompress(data, 9).toBase64()));
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/gamecfgwidget.h
--- a/QTfrontend/ui/widget/gamecfgwidget.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/gamecfgwidget.h Sun Dec 17 00:09:24 2017 +0100
@@ -55,6 +55,7 @@
void setParam(const QString & param, const QStringList & value);
void fullNetConfig();
void resendSchemeData();
+ void resendAmmoData();
void setMaster(bool master);
void setTabbed(bool tabbed);
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/hedgehogerWidget.cpp
--- a/QTfrontend/ui/widget/hedgehogerWidget.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/hedgehogerWidget.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -83,7 +83,7 @@
{
Q_UNUSED(event);
- if (this->width() >= 11 * numItems + 26)
+ if ((this->width() >= 11 * numItems + 26) || (numItems == 1))
ItemNum::paintEvent(event);
else
{
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/keybinder.cpp
--- a/QTfrontend/ui/widget/keybinder.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/keybinder.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -60,6 +60,7 @@
{
QPushButton * btnResetAll = new QPushButton(resetButtonText);
catListContainer->addWidget(btnResetAll);
+ btnResetAll->setStyleSheet("padding: 5px 10px");
btnResetAll->setFixedHeight(40);
catListContainer->setStretch(1, 0);
catListContainer->setSpacing(10);
@@ -241,13 +242,12 @@
{
QComboBox * box = bindCellComboBoxMappings->value(item);
QTableWidget * table = item->tableWidget();
- QFrame * frame = box->findChild
();
+ box->move(
+ table->horizontalHeader()->sectionSize(0),
+ (table->verticalHeader()->defaultSectionSize() * (item->row() + 1)) - (box->height()) + 1
+ );
box->showPopup();
- frame->move(
- frame->x() + table->horizontalHeader()->sectionSize(0),
- frame->y() + (table->verticalHeader()->defaultSectionSize() * item->row())
- );
}
// When a new row in a bind table is *selected*, this clears selection in any other table
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/mapContainer.cpp
--- a/QTfrontend/ui/widget/mapContainer.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/mapContainer.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -253,7 +253,7 @@
bottomLeftLayout->addStretch(1);
/* Theme chooser */
- QHBoxLayout * themeHBox = new QHBoxLayout(this);
+ QHBoxLayout * themeHBox = new QHBoxLayout();
btnRandTheme = new QPushButton();
btnRandTheme->setWhatsThis(tr("Randomize the theme"));
@@ -262,7 +262,7 @@
btnRandTheme->setFixedHeight(30);
btnRandTheme->setFixedWidth(30);
connect(btnRandTheme, SIGNAL(clicked()), this, SLOT(setRandomTheme()));
- m_childWidgets << btnTheme;
+ m_childWidgets << btnRandTheme;
themeHBox->addWidget(btnRandTheme, 0);
btnTheme = new QPushButton(this);
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/roomnameprompt.cpp
--- a/QTfrontend/ui/widget/roomnameprompt.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/roomnameprompt.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -48,7 +48,8 @@
// Input box
leRoomName = new QLineEdit(this);
leRoomName->setText(roomName);
- leRoomName->setMaxLength(59); // It didn't like 60 :(
+ //leRoomName->setMaxLength(59); // It didn't like 60 :(
+ leRoomName->setMaxLength(40);
leRoomName->setStyleSheet("QLineEdit { padding: 3px; }");
leRoomName->selectAll();
dialogLayout->addWidget(leRoomName);
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/selectWeapon.cpp
--- a/QTfrontend/ui/widget/selectWeapon.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/selectWeapon.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -189,11 +189,19 @@
setWeapons(*cDefaultAmmoStore);
}
+//Save current weapons set.
void SelWeaponWidget::save()
{
+ //The save() function is called by ANY change of the combo box.
+ //If an entry is deleted, this code would just re-add the deleted
+ //item. We use isDeleted to check if we are currently deleting to
+ //prevent this.
+ if (isDeleting)
+ return;
// TODO make this return if success or not, so that the page can react
// properly and not goBack if saving failed
- if (m_name->text() == "") return;
+ if (m_name->text() == "")
+ return;
QString state1;
QString state2;
@@ -218,12 +226,15 @@
for(int i = 0; i < cDefaultAmmos.size(); i++)
{
- if (cDefaultAmmos[i].first.compare(m_name->text()) == 0)
+ // Don't allow same name as default weapon set, even case-insensitively.
+ // This prevents some problems with saving/loading.
+ if (cDefaultAmmos[i].first.toLower().compare(m_name->text().toLower()) == 0)
{
// don't show warning if no change
if (cDefaultAmmos[i].second.compare(stateFull) == 0)
return;
+ m_name->setText(curWeaponsName);
QMessageBox deniedMsg(this);
deniedMsg.setIcon(QMessageBox::Warning);
deniedMsg.setWindowTitle(QMessageBox::tr("Weapons - Warning"));
@@ -240,7 +251,7 @@
wconf->remove(curWeaponsName);
}
wconf->setValue(m_name->text(), stateFull);
- emit weaponsChanged();
+ emit weaponsEdited(curWeaponsName, m_name->text(), stateFull);
}
int SelWeaponWidget::operator [] (unsigned int weaponIndex) const
@@ -256,10 +267,11 @@
void SelWeaponWidget::deleteWeaponsName()
{
- if (curWeaponsName == "") return;
+ QString delWeaponsName = curWeaponsName;
+ if (delWeaponsName == "") return;
for(int i = 0; i < cDefaultAmmos.size(); i++)
- if (!cDefaultAmmos[i].first.compare(m_name->text()))
+ if (!cDefaultAmmos[i].first.compare(delWeaponsName))
{
QMessageBox deniedMsg(this);
deniedMsg.setIcon(QMessageBox::Warning);
@@ -273,19 +285,21 @@
QMessageBox reallyDeleteMsg(this);
reallyDeleteMsg.setIcon(QMessageBox::Question);
reallyDeleteMsg.setWindowTitle(QMessageBox::tr("Weapons - Are you sure?"));
- reallyDeleteMsg.setText(QMessageBox::tr("Do you really want to delete the weapon set '%1'?").arg(curWeaponsName));
+ reallyDeleteMsg.setText(QMessageBox::tr("Do you really want to delete the weapon set '%1'?").arg(delWeaponsName));
reallyDeleteMsg.setWindowModality(Qt::WindowModal);
reallyDeleteMsg.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
if (reallyDeleteMsg.exec() == QMessageBox::Ok)
{
- wconf->remove(curWeaponsName);
- emit weaponsDeleted();
+ isDeleting = true;
+ wconf->remove(delWeaponsName);
+ emit weaponsDeleted(delWeaponsName);
}
}
void SelWeaponWidget::newWeaponsName()
{
+ save();
QString newName = tr("New");
if(wconf->contains(newName))
{
@@ -294,6 +308,8 @@
while(wconf->contains(newName = tr("New (%1)").arg(i++))) ;
}
setWeaponsName(newName);
+ wconf->setValue(newName, *cEmptyAmmoStore);
+ emit weaponsAdded(newName, *cEmptyAmmoStore);
}
void SelWeaponWidget::setWeaponsName(const QString& name)
@@ -312,6 +328,13 @@
}
}
+void SelWeaponWidget::switchWeapons(const QString& name)
+{
+ // Rescue old weapons set, then select new one
+ save();
+ setWeaponsName(name);
+}
+
QStringList SelWeaponWidget::getWeaponNames() const
{
return wconf->allKeys();
@@ -319,6 +342,7 @@
void SelWeaponWidget::copy()
{
+ save();
if(wconf->contains(curWeaponsName))
{
QString ammo = getWeaponsString(curWeaponsName);
@@ -327,10 +351,12 @@
{
//name already used -> look for an appropriate name:
int i=2;
- while(wconf->contains(newName = tr("Copy of %1 (%2)").arg(curWeaponsName, i++)));
+ while(wconf->contains(newName = tr("Copy of %1 (%2)").arg(curWeaponsName).arg(i++)));
}
setWeaponsName(newName);
setWeapons(ammo);
+ wconf->setValue(newName, ammo);
+ emit weaponsAdded(newName, ammo);
}
}
@@ -352,3 +378,13 @@
return sl.join(QString());
}
+
+void SelWeaponWidget::deletionDone()
+{
+ isDeleting = false;
+}
+
+void SelWeaponWidget::init()
+{
+ isDeleting = false;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/selectWeapon.h
--- a/QTfrontend/ui/widget/selectWeapon.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/selectWeapon.h Sun Dec 17 00:09:24 2017 +0100
@@ -52,24 +52,30 @@
SelWeaponWidget(int numItems, QWidget* parent=0);
QString getWeaponsString(const QString& name) const;
QStringList getWeaponNames() const;
+ void deletionDone();
+ void init();
public slots:
void setDefault();
void setWeapons(const QString& ammo);
//sets the name of the current set
void setWeaponsName(const QString& name);
+ void switchWeapons(const QString& name);
void deleteWeaponsName();
void newWeaponsName();
void save();
void copy();
signals:
- void weaponsChanged();
- void weaponsDeleted();
+ void weaponsDeleted(QString weaponsName);
+ void weaponsAdded(QString weaponsName, QString ammo);
+ void weaponsEdited(QString oldWeaponsName, QString newWeaponsName, QString ammo);
private:
//the name of the current weapon set
QString curWeaponsName;
+ //set to true while an entry is deleted. Used to avoid duplicate saving due to combobox change
+ bool isDeleting;
QLineEdit* m_name;
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/teamselect.cpp
--- a/QTfrontend/ui/widget/teamselect.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/teamselect.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -43,6 +43,12 @@
blockSignals(false);
connect(framePlaying->getTeamWidget(team), SIGNAL(teamColorChanged(const HWTeam&)),
this, SLOT(proxyTeamColorChanged(const HWTeam&)));
+
+ // Hide team notice if at least two teams.
+ if (curPlayingTeams.size() >= 2)
+ {
+ numTeamNotice->hide();
+ }
}
else
{
@@ -133,6 +139,11 @@
QObject::disconnect(framePlaying->getTeamWidget(*itPlay), SIGNAL(teamStatusChanged(HWTeam)));
framePlaying->removeTeam(team);
curPlayingTeams.erase(itPlay);
+ // Show team notice if less than two teams.
+ if (curPlayingTeams.size() < 2)
+ {
+ numTeamNotice->show();
+ }
}
else
{
@@ -229,15 +240,17 @@
emit setEnabledGameStart(curPlayingTeams.size()>1);
}
-void TeamSelWidget::addScrArea(FrameTeams* pfteams, QColor color, int fixedHeight)
+void TeamSelWidget::addScrArea(FrameTeams* pfteams, QColor color, int minHeight, int maxHeight, bool setFrame)
{
VertScrArea* area = new VertScrArea(color);
area->setWidget(pfteams);
- mainLayout.addWidget(area, 30);
- if (fixedHeight > 0)
+ mainLayout.addWidget(area);
+ if (minHeight > 0)
+ area->setMinimumHeight(minHeight);
+ if (maxHeight > 0)
+ area->setMaximumHeight(maxHeight);
+ if (setFrame)
{
- area->setMinimumHeight(fixedHeight);
- area->setMaximumHeight(fixedHeight);
area->setStyleSheet(
"FrameTeams{"
"border: solid;"
@@ -263,8 +276,8 @@
QPalette p;
p.setColor(QPalette::Window, QColor(0x00, 0x00, 0x00));
- addScrArea(framePlaying, p.color(QPalette::Window).light(105), 150);
- addScrArea(frameDontPlaying, p.color(QPalette::Window).dark(105), 0);
+ addScrArea(framePlaying, p.color(QPalette::Window).light(105), 161, 325, true);
+ addScrArea(frameDontPlaying, p.color(QPalette::Window).dark(105), 80, 0, false);
this->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
this->setMinimumWidth(200);
@@ -292,6 +305,8 @@
foreach(HWTeam team, teamslist)
addTeam(team);
+ numTeamNotice->show();
+
repaint();
}
@@ -310,6 +325,17 @@
return m_curNotPlayingTeams;
}
+unsigned short TeamSelWidget::getNumHedgehogs() const
+{
+ unsigned short numHogs = 0;
+ QList::const_iterator team;
+ for(team = curPlayingTeams.begin(); team != curPlayingTeams.end(); ++team)
+ {
+ numHogs += (*team).numHedgehogs();
+ }
+ return numHogs;
+}
+
void TeamSelWidget::pre_changeTeamStatus(const HWTeam & team)
{
//team.setColor(framePlaying->getNextColor());
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/ui/widget/teamselect.h
--- a/QTfrontend/ui/widget/teamselect.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/ui/widget/teamselect.h Sun Dec 17 00:09:24 2017 +0100
@@ -47,6 +47,7 @@
bool isPlaying(const HWTeam &team) const;
QList getPlayingTeams() const;
QList getNotPlayingTeams() const;
+ unsigned short getNumHedgehogs() const;
void setInteractivity(bool interactive);
public slots:
@@ -69,7 +70,7 @@
void proxyTeamColorChanged(const HWTeam& team);
private:
- void addScrArea(FrameTeams* pfteams, QColor color, int maxHeight);
+ void addScrArea(FrameTeams* pfteams, QColor color, int minHeight, int maxHeight, bool setFrame);
FrameTeams* frameDontPlaying;
FrameTeams* framePlaying;
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/DataManager.cpp
--- a/QTfrontend/util/DataManager.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/util/DataManager.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -31,6 +31,7 @@
#include "hwconsts.h"
#include "HWApplication.h"
#include "sdlkeys.h"
+#include "physfs.h"
#include "DataManager.h"
@@ -61,7 +62,8 @@
QStringList DataManager::entryList(
const QString & subDirectory,
QDir::Filters filters,
- const QStringList & nameFilters
+ const QStringList & nameFilters,
+ bool withDLC
) const
{
QDir tmpDir(QString("physfs://%1").arg(subDirectory));
@@ -69,9 +71,13 @@
// sort case-insensitive
QMap sortedFileNames;
+ QString absolutePath = datadir->absolutePath().toLocal8Bit().data();
foreach ( QString fn, result)
{
- sortedFileNames.insert(fn.toLower(), fn);
+ // Filter out DLC entries if desired
+ QString realDir = PHYSFS_getRealDir(QString(subDirectory + "/" + fn).toLocal8Bit().data());
+ if(withDLC || realDir == absolutePath)
+ sortedFileNames.insert(fn.toLower(), fn);
}
result = sortedFileNames.values();
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/DataManager.h
--- a/QTfrontend/util/DataManager.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/util/DataManager.h Sun Dec 17 00:09:24 2017 +0100
@@ -37,7 +37,7 @@
/**
* @brief Offers access to the data files of hedgewars.
*
- * @see singleton pattern
+ * @see singleton pattern
*
* @author sheepluva
* @since 0.9.17
@@ -50,7 +50,7 @@
/**
* @brief Returns reference to the singleton instance of this class.
*
- * @see singleton pattern
+ * @see singleton pattern
*
* @return reference to the instance.
*/
@@ -66,7 +66,8 @@
*/
QStringList entryList(const QString & subDirectory,
QDir::Filters filters = QDir::NoFilter,
- const QStringList & nameFilters = QStringList("*")
+ const QStringList & nameFilters = QStringList("*"),
+ bool withDLC = true
) const;
/**
@@ -141,7 +142,7 @@
* Not to be used from outside the class,
* use the static {@link DataManager::instance()} instead.
*
- * @see singleton pattern
+ * @see singleton pattern
*/
DataManager();
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/FileEngine.cpp
--- a/QTfrontend/util/FileEngine.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/util/FileEngine.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -295,7 +295,11 @@
QString FileEngine::errorString() const
{
+#if PHYSFS_VER_MAJOR >= 3
+ return PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode());
+#else
return PHYSFS_getLastError();
+#endif
}
bool FileEngine::supportsExtension(Extension extension) const
@@ -352,7 +356,12 @@
QString FileEngineHandler::errorStr()
{
- QString s = QString::fromUtf8(PHYSFS_getLastError());
+ QString s;
+#if PHYSFS_VER_MAJOR >= 3
+ s = QString::fromUtf8(PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
+#else
+ s = QString::fromUtf8(PHYSFS_getLastError());
+#endif
return s.isEmpty() ? "ok" : s;
}
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/LibavInteraction.cpp
--- a/QTfrontend/util/LibavInteraction.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/util/LibavInteraction.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -18,7 +18,7 @@
#include "LibavInteraction.h"
-#if VIDEOREC
+#ifdef VIDEOREC
extern "C"
{
#include "libavcodec/avcodec.h"
@@ -291,7 +291,8 @@
return "";
int s = float(pContext->duration)/AV_TIME_BASE;
- QString desc = tr("Duration: %1m %2s").arg(s/60).arg(s%60) + "\n";
+ //: Duration in minutes and seconds (SI units)
+ QString desc = tr("Duration: %1min %2s").arg(s/60).arg(s%60) + "\n";
for (int i = 0; i < (int)pContext->nb_streams; i++)
{
AVStream* pStream = pContext->streams[i];
@@ -307,7 +308,7 @@
if (pStream->avg_frame_rate.den)
{
float fps = float(pStream->avg_frame_rate.num)/pStream->avg_frame_rate.den;
- desc += QString(tr("%1 fps")).arg(fps, 0, 'f', 2) + ", ";
+ desc += QString(tr("%1 FPS")).arg(fps, 0, 'f', 2) + ", ";
}
}
else if (pCodec->codec_type == AVMEDIA_TYPE_AUDIO)
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/LibavInteraction.h
--- a/QTfrontend/util/LibavInteraction.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/util/LibavInteraction.h Sun Dec 17 00:09:24 2017 +0100
@@ -24,7 +24,7 @@
/**
* @brief Class for interacting with ffmpeg/libav libraries
*
- * @see singleton pattern
+ * @see singleton pattern
*/
class LibavInteraction : public QObject
{
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/SDLInteraction.h
--- a/QTfrontend/util/SDLInteraction.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/util/SDLInteraction.h Sun Dec 17 00:09:24 2017 +0100
@@ -41,7 +41,7 @@
/**
* @brief Class for interacting with SDL (used for music and keys)
*
- * @see singleton pattern
+ * @see singleton pattern
*/
class SDLInteraction
{
@@ -53,7 +53,7 @@
* Not to be used from outside the class,
* use the static {@link DataManager::instance()} instead.
*
- * @see singleton pattern
+ * @see singleton pattern
*/
SDLInteraction();
@@ -73,7 +73,7 @@
/**
* @brief Returns reference to the singleton instance of this class.
*
- * @see singleton pattern
+ * @see singleton pattern
*
* @return reference to the instance.
*/
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/namegen.cpp
--- a/QTfrontend/util/namegen.cpp Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/util/namegen.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -18,6 +18,7 @@
*/
#include
+#include
#include
#include
#include
@@ -33,8 +34,34 @@
QList HWNamegen::TypesHatnames;
bool HWNamegen::typesAvailable = false;
+void HWNamegen::teamRandomTeamName(HWTeam & team)
+{
+ QString newName = getRandomTeamName(-1);
+ if(!newName.isNull())
+ team.setName(newName);
+}
-void HWNamegen::teamRandomNames(HWTeam & team, const bool changeteamname)
+void HWNamegen::teamRandomFlag(HWTeam & team, bool withDLC)
+{
+ team.setFlag(getRandomFlag(withDLC));
+}
+
+void HWNamegen::teamRandomVoice(HWTeam & team, bool withDLC)
+{
+ team.setVoicepack(getRandomVoice(withDLC));
+}
+
+void HWNamegen::teamRandomGrave(HWTeam & team, bool withDLC)
+{
+ team.setGrave(getRandomGrave(withDLC));
+}
+
+void HWNamegen::teamRandomFort(HWTeam & team, bool withDLC)
+{
+ team.setFort(getRandomFort(withDLC));
+}
+
+void HWNamegen::teamRandomEverything(HWTeam & team)
{
// load types if not already loaded
if (!typesAvailable)
@@ -48,34 +75,53 @@
// the hat will influence which names the hogs get
int kind = (rand()%(TypesHatnames.size()));
- // pick team name based on hat
- if (changeteamname)
- {
- if (TypesTeamnames[kind].size() > 0)
- team.setName(TypesTeamnames[kind][rand()%(TypesTeamnames[kind].size())]);
-
- team.setGrave(getRandomGrave());
- team.setFort(getRandomFort());
- team.setVoicepack("Default");
- }
+ team.setGrave(getRandomGrave());
+ team.setFort(getRandomFort());
+ team.setFlag(getRandomFlag());
+ team.setVoicepack(getRandomVoice());
QStringList dicts;
QStringList dict;
- if ((TypesHatnames[kind].size()) <= 0)
- {
- dicts = dictsForHat(team.hedgehog(0).Hat);
- dict = dictContents(dicts[rand()%(dicts.size())]);
- }
+ // Randomness mode:
+ // 0: Themed hats (from types.ini)
+ // 1: Equal hats for all
+ // 2: Random hat for each hedgehog
+ int r = rand() % 10;
+ int randomMode;
+ if (r <= 4) // 0-4 (50%)
+ randomMode = 0;
+ else if (r <= 8) // 5-8 (40%)
+ randomMode = 1;
+ else // 9 (10%)
+ randomMode = 2;
+ // Generate random hats
for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
{
- if ((TypesHatnames[kind].size()) > 0)
+ HWHog hh = team.hedgehog(i);
+
+ if (randomMode == 0)
+ {
+ hh.Hat = TypesHatnames[kind][rand()%(TypesHatnames[kind].size())];
+ }
+ else if (randomMode == 1)
{
- HWHog hh = team.hedgehog(i);
- hh.Hat = TypesHatnames[kind][rand()%(TypesHatnames[kind].size())];
- team.setHedgehog(i,hh);
+ if (i == 0)
+ {
+ hh.Hat = getRandomHat();
+ }
+ else
+ {
+ hh.Hat = team.hedgehog(i-1).Hat;
+ }
}
+ else if (randomMode == 2)
+ {
+ hh.Hat = getRandomHat();
+ }
+
+ team.setHedgehog(i,hh);
// there is a chance that this hog has the same hat as the previous one
// let's reuse the hat-specific dict in this case
@@ -86,21 +132,83 @@
}
// give each hedgehog a random name
- HWNamegen::teamRandomName(team,i,dict);
+ HWNamegen::teamRandomHogName(team,i,dict);
}
+ // If using themed hats, use themed team name.
+ // Otherwise, only use “generic” team names from the first team
+ // in types.txt.
+ if (randomMode == 0)
+ team.setName(getRandomTeamName(kind));
+ else
+ team.setName(getRandomTeamName(0));
+
}
-void HWNamegen::teamRandomName(HWTeam & team, const int HedgehogNumber)
+// Set random hats for entire team
+void HWNamegen::teamRandomHats(HWTeam & team, bool withDLC)
+{
+ // 50% chance that all hogs are set to the same hat.
+ // 50% chance that each hog gets a random head individually.
+
+ bool sameHogs = (rand()%2) == 0;
+ for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
+ {
+ HWHog hh = team.hedgehog(i);
+ if (sameHogs and i > 0)
+ hh.Hat = team.hedgehog(i-1).Hat;
+ else
+ hh.Hat = getRandomHat(withDLC);
+ team.setHedgehog(i, hh);
+ }
+}
+
+void HWNamegen::teamRandomHat(HWTeam & team, const int HedgehogNumber, bool withDLC)
+{
+ HWHog hh = team.hedgehog(HedgehogNumber);
+
+ hh.Hat = getRandomHat(withDLC);
+
+ team.setHedgehog(HedgehogNumber, hh);
+}
+
+void HWNamegen::teamRandomHat(HWTeam & team, const int HedgehogNumber, const QStringList & dict)
+{
+ HWHog hh = team.hedgehog(HedgehogNumber);
+
+ hh.Name = dict[rand()%(dict.size())];
+
+ team.setHedgehog(HedgehogNumber, hh);
+}
+
+void HWNamegen::teamRandomHogNames(HWTeam & team)
+{
+ QStringList dicts, dict;
+ for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
+ {
+ // there is a chance that this hog has the same hat as the previous one
+ // let's reuse the hat-specific dict in this case
+ if ((i == 0) || (team.hedgehog(i).Hat != team.hedgehog(i-1).Hat))
+ {
+ dicts = dictsForHat(team.hedgehog(i).Hat);
+ dict = dictContents(dicts[rand()%(dicts.size())]);
+ }
+
+ // give each hedgehog a random name
+ HWNamegen::teamRandomHogName(team,i,dict);
+ }
+}
+
+void HWNamegen::teamRandomHogName(HWTeam & team, const int HedgehogNumber)
{
QStringList dicts = dictsForHat(team.hedgehog(HedgehogNumber).Hat);
QStringList dict = dictContents(dicts[rand()%(dicts.size())]);
- teamRandomName(team, HedgehogNumber, dict);
+ teamRandomHogName(team, HedgehogNumber, dict);
}
-void HWNamegen::teamRandomName(HWTeam & team, const int HedgehogNumber, const QStringList & dict)
+void HWNamegen::teamRandomHogName(HWTeam & team, const int HedgehogNumber, const QStringList & dict)
{
QStringList namesDict = dict;
@@ -151,22 +259,32 @@
{
QStringList list;
- // find .cfg to load the dicts from
- QFile file(QString("physfs://Names/%1.cfg").arg(hatname));
+ // Find and check .cfg to load the dicts from
+ QString path = QString("physfs://Names/%1.cfg").arg(hatname);
+ QFileInfo check_file(path);
- if (file.open(QIODevice::ReadOnly | QIODevice::Text))
+ // Note: The .cfg file is optional; a fallback mechanism is in place (see below)
+
+ // Check if file exists to prevent PhysFS from complaining in console so much
+ if (check_file.exists() && check_file.isFile())
{
- QTextStream in(&file);
- QString line;
- do
+ QFile file(path);
+
+ if (file.open(QIODevice::ReadOnly | QIODevice::Text))
{
- line = in.readLine();
+ QTextStream in(&file);
+ QString line;
+ do
+ {
+ line = in.readLine();
- if(!line.isEmpty())
- list.append(line);
- } while (!line.isNull());
+ if(!line.isEmpty())
+ list.append(line);
+ } while (!line.isNull());
+ }
}
+ // Use Data/Names/generic.cfg by default
if (list.size() == 0)
list.append(QString("generic"));
@@ -231,9 +349,54 @@
return typesAvailable;
}
+/* Generates a random team name.
+kind: Use to select a team name out of a group (types.ini).
+Use a negative value if you don't care.
+This function may return a null QString on error(this should never happen). */
+QString HWNamegen::getRandomTeamName(int kind)
+{
+ // load types if not already loaded
+ if (!typesAvailable)
+ if (!loadTypes())
+ return QString(); // abort if loading failed
+ // abort if there are no hat types
+ if (TypesHatnames.size() <= 0)
+ return QString();
+
+ if(kind < 0)
+ kind = (rand()%(TypesHatnames.size()));
+
+ if (TypesTeamnames[kind].size() > 0)
+ return TypesTeamnames[kind][rand()%(TypesTeamnames[kind].size())];
+ else
+ return QString();
+}
-QString HWNamegen::getRandomGrave()
+QString HWNamegen::getRandomHat(bool withDLC)
+{
+ QStringList Hats;
+
+ // list all available hats
+ Hats.append(DataManager::instance().entryList(
+ "Graphics/Hats",
+ QDir::Files,
+ QStringList("*.png"),
+ withDLC
+ ).replaceInStrings(QRegExp("\\.png$"), "")
+ );
+
+ if(Hats.size()==0)
+ {
+ // TODO do some serious error handling
+ return "Error";
+ }
+
+ // pick a random hat
+ return Hats[rand()%(Hats.size())];
+}
+
+QString HWNamegen::getRandomGrave(bool withDLC)
{
QStringList Graves;
@@ -241,7 +404,8 @@
Graves.append(DataManager::instance().entryList(
"Graphics/Graves",
QDir::Files,
- QStringList("*.png")
+ QStringList("*.png"),
+ withDLC
).replaceInStrings(QRegExp("\\.png$"), "")
);
@@ -255,7 +419,33 @@
return Graves[rand()%(Graves.size())];
}
-QString HWNamegen::getRandomFort()
+QString HWNamegen::getRandomFlag(bool withDLC)
+{
+ QStringList Flags;
+
+ //list all available flags
+ Flags.append(DataManager::instance().entryList(
+ "Graphics/Flags",
+ QDir::Files,
+ QStringList("*.png"),
+ withDLC
+ ).replaceInStrings(QRegExp("\\.png$"), "")
+ );
+ //remove internal flags
+ Flags.removeAll("cpu");
+ Flags.removeAll("cpu_plain");
+
+ if(Flags.size()==0)
+ {
+ // TODO do some serious error handling
+ return "Error";
+ }
+
+ //pick a random flag
+ return Flags[rand()%(Flags.size())];
+}
+
+QString HWNamegen::getRandomFort(bool withDLC)
{
QStringList Forts;
@@ -263,7 +453,8 @@
Forts.append(DataManager::instance().entryList(
"Forts",
QDir::Files,
- QStringList("*L.png")
+ QStringList("*L.png"),
+ withDLC
).replaceInStrings(QRegExp("L\\.png$"), "")
);
@@ -276,3 +467,24 @@
//pick a random fort
return Forts[rand()%(Forts.size())];
}
+
+QString HWNamegen::getRandomVoice(bool withDLC)
+{
+ QStringList Voices;
+
+ //list all available voices
+ Voices.append(DataManager::instance().entryList(
+ "Sounds/voices",
+ QDir::Dirs | QDir::NoDotAndDotDot,
+ QStringList("*"),
+ withDLC));
+
+ if(Voices.size()==0)
+ {
+ // TODO do some serious error handling
+ return "Error";
+ }
+
+ //pick a random voice
+ return Voices[rand()%(Voices.size())];
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/namegen.h
--- a/QTfrontend/util/namegen.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/util/namegen.h Sun Dec 17 00:09:24 2017 +0100
@@ -28,13 +28,27 @@
class HWNamegen
{
public:
-
- static void teamRandomName(HWTeam & team, const int HedgehogNumber);
- static void teamRandomNames(HWTeam & team, const bool changeteamname);
+ static void teamRandomTeamName(HWTeam & team);
+ static void teamRandomGrave(HWTeam & team, bool withDLC = true);
+ static void teamRandomFort(HWTeam & team, bool withDLC = true);
+ static void teamRandomFlag(HWTeam & team, bool withDLC = true);
+ static void teamRandomVoice(HWTeam & team, bool withDLC = true);
+ static void teamRandomHats(HWTeam & team, bool withDLC = true);
+ static void teamRandomHat(HWTeam & team, const int HedgehogNumber, bool withDLC = true);
+ static void teamRandomHogNames(HWTeam & team);
+ static void teamRandomHogName(HWTeam & team, const int HedgehogNumber);
+ static void teamRandomEverything(HWTeam & team);
private:
HWNamegen();
+ static QString getRandomTeamName(int kind);
+ static QString getRandomHat(bool withDLC = true);
+ static QString getRandomGrave(bool withDLC = true);
+ static QString getRandomFort(bool withDLC = true);
+ static QString getRandomFlag(bool withDLC = true);
+ static QString getRandomVoice(bool withDLC = true);
+
static QList TypesTeamnames;
static QList TypesHatnames;
static bool typesAvailable;
@@ -43,9 +57,8 @@
static QStringList dictContents(const QString filename);
static QStringList dictsForHat(const QString hatname);
- static QString getRandomGrave();
- static QString getRandomFort();
- static void teamRandomName(HWTeam & team, const int HedgehogNumber, const QStringList & dict);
+ static void teamRandomHat(HWTeam & team, const int HedgehogNumber, const QStringList & dict);
+ static void teamRandomHogName(HWTeam & team, const int HedgehogNumber, const QStringList & dict);
};
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/platform/CocoaInitializer.h
--- a/QTfrontend/util/platform/CocoaInitializer.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/util/platform/CocoaInitializer.h Sun Dec 17 00:09:24 2017 +0100
@@ -16,7 +16,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-// see original example here http://el-tramo.be/blog/mixing-cocoa-and-qt
+// see original example here https://el-tramo.be/blog/mixing-cocoa-and-qt
#ifndef COCOAINITIALIZER_H
#define COCOAINITIALIZER_H
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/platform/CocoaInitializer.mm
--- a/QTfrontend/util/platform/CocoaInitializer.mm Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/util/platform/CocoaInitializer.mm Sun Dec 17 00:09:24 2017 +0100
@@ -16,7 +16,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-// see original example here http://el-tramo.be/blog/mixing-cocoa-and-qt
+// see original example here https://el-tramo.be/blog/mixing-cocoa-and-qt
#include "CocoaInitializer.h"
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/platform/SparkleAutoUpdater.mm
--- a/QTfrontend/util/platform/SparkleAutoUpdater.mm Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/util/platform/SparkleAutoUpdater.mm Sun Dec 17 00:09:24 2017 +0100
@@ -16,7 +16,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-// see original example here http://el-tramo.be/blog/mixing-cocoa-and-qt
+// see original example here https://el-tramo.be/blog/mixing-cocoa-and-qt
#include "SparkleAutoUpdater.h"
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/platform/Xfire Game SDK.url
--- a/QTfrontend/util/platform/Xfire Game SDK.url Thu Aug 11 23:05:14 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-[{000214A0-0000-0000-C000-000000000046}]
-Prop3=19,2
-[InternetShortcut]
-URL=http://www.xfire.com/cms/xf_game_sdk
-IDList=
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/platform/xfire.cpp
--- a/QTfrontend/util/platform/xfire.cpp Thu Aug 11 23:05:14 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2015 Andrey Korotaev
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include
-#include
-#include
-
-#include "xfire.h"
-#include "xfiregameclient.h"
-
-#ifdef USE_XFIRE
-// use_xfire: stores if xfire is loaded and functions should do something at all
-bool use_xfire = false;
-char *keys[XFIRE_KEY_COUNT];
-char *values[XFIRE_KEY_COUNT];
-
-// xfire_init(): used to initialize all variables and set their default values
-void xfire_init(void)
-{
- if(use_xfire)
- return;
- use_xfire = XfireIsLoaded() == 1;
-
- if(!use_xfire)
- return;
-
- for(int i = 0; i < XFIRE_KEY_COUNT; i++)
- {
- keys[i] = new char[256];
- values[i] = new char[256];
- strcpy(keys[i], "");
- strcpy(values[i], "");
- }
-
- strcpy(keys[XFIRE_NICKNAME], "Nickname");
- strcpy(keys[XFIRE_ROOM], "Room");
- strcpy(keys[XFIRE_SERVER], "Server");
- strcpy(keys[XFIRE_STATUS], "Status");
- xfire_update();
-}
-
-// xfire_free(): used to free up ressources used etc.
-void xfire_free(void)
-{
- if(!use_xfire)
- return;
-
- for(int i = 0; i < XFIRE_KEY_COUNT; i++)
- {
- delete [] keys[i];
- delete [] values[i];
- }
-}
-
-// xfire_setvalue(): set a specific value
-void xfire_setvalue(const XFIRE_KEYS status, const char *value)
-{
- if(!use_xfire || strlen(value) > 255)
- return;
- strcpy(values[status], value);
-}
-
-// xfire_update(): submits current values to the xfire app
-void xfire_update(void)
-{
- if(!use_xfire)
- return;
- XfireSetCustomGameDataA(XFIRE_KEY_COUNT, (const char**)keys, (const char**)values);
-}
-#endif // USE_XFIRE
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/platform/xfire.h
--- a/QTfrontend/util/platform/xfire.h Thu Aug 11 23:05:14 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2015 Andrey Korotaev
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef XFIRE_H
-#define XFIRE_H
-
-
-#ifdef USE_XFIRE
-enum XFIRE_KEYS
-{
- XFIRE_STATUS = 0,
- XFIRE_NICKNAME,
- XFIRE_SERVER,
- XFIRE_ROOM,
- XFIRE_KEY_COUNT,
-};
-
-void xfire_init(void);
-void xfire_free(void);
-void xfire_setvalue(const XFIRE_KEYS status, const char *value);
-void xfire_update(void);
-#endif
-
-#endif // XFIRE_H
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/platform/xfire_license.txt
--- a/QTfrontend/util/platform/xfire_license.txt Thu Aug 11 23:05:14 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-Terms and Conditions
-AGREEMENT BETWEEN USER AND XFIRE INC.
-This is a legal agreement between you and Xfire Inc. ("Xfire") with respect to your access and use of the Xfire Service, which may also include Xfire software, content and related documentation and information (collectively, the "Service"). You must accept without modification all of the terms, conditions, and notices contained in these Terms of Use in order to access and/or use the Service (collectively, the "Terms of Use" or "Agreement"). If you do not accept these Terms of Use in their entirety, you may not access or use the Service.
-
-Portions of the Service may be governed by posted guidelines, rules, or other terms and conditions. All such guidelines, rules, terms and conditions are hereby incorporated by reference into these Terms of Use. In the event of a conflict between such other guidelines, rules, terms and conditions and these Terms of Use, the Terms of Use shall control, except that the Xfire Service Privacy Policy, referenced below, supersedes any conflicting language in these Terms of Use and/or any other guidelines, rules, terms and conditions published in connection with the Service with respect to the subject matter covered by such privacy policy.
-
-MODIFICATION OF THESE TERMS OF USE; UPDATES
-Xfire may change the Terms of Use at any time and such changes shall be effective immediately. You are responsible for regularly reviewing the Terms of Use. The most recent version of the Terms of Use can be found at http://www.xfire.com/xf/terms.php. Your continued use of the Service affirms your agreement to the Terms of Use and any changes.
-
-Xfire is not obligated to provide updates or improvements to the Service. However, if Xfire, in its sole discretion, updates or improves the Service, these Terms of Use shall apply to such updates and improvements unless expressly noted otherwise.
-
-CLIENT SOFTWARE USE LIMITATION
-YOU MAY ONLY USE XFIRE CLIENT SOFTWARE OR AUTHORIZED THIRD-PARTY SOFTWARE TO ACCESS AND/OR USE THE SERVICE. You may not use any software or services in conjunction with the Xfire software or authorized third-party software which modifies or reroutes, or attempts to modify or reroute, the Service. You may not authorize any third party to access and/or use the Service on your behalf using any automated process such as a BOT, a spider or periodic caching of information stored by the Xfire Service on your behalf without a separate written agreement with Xfire. You may not use any software or hardware that reduces the number of users directly accessing or using the Service (sometimes called 'multiplexing' or 'pooling' software or hardware).
-
-You may not modify, copy, distribute, transmit, display, perform, reproduce, publish, license, create derivative works from, transfer, or sell any information, software, products or services that are part of the Service except as expressly provided in these Terms of Use.
-
-NO UNLAWFUL OR PROHIBITED USE; RESPONSIBILITY FOR YOUR ACCOUNT
-As a condition of your use of the Service, you will not use the Service for any purpose that is unlawful or prohibited by these Terms of Use. You may not use the Service in any manner that could damage, disable, overburden, or impair the Service or interfere with any other party's use and enjoyment of it. You may not attempt to gain unauthorized access to any account, computer systems or networks associated with the Service or to otherwise interfere with or disrupt any accounts, computer systems or networks connected to the Service. You may not obtain or attempt to obtain any materials or information through any means not intentionally made available or provided for through the Service. You may not use access to the Service to obtain information necessary for you to design, develop or update unauthorized software that you use or provide to others to use to access the Service. You may not charge others to use the Service either directly or indirectly without the express written agreement of Xfire.
-Subject to these Terms of Use, you may use the Service within your commercial organization, but you may not use the Service to advertise or offer to buy or sell any goods or services, or to run a business or commercial entity without the express written agreement of Xfire.
-You agree to use the Service only to send, receive, and transfer appropriate messages and material. By way of example, and not as a limitation, you agree that when using the Service, you will not:
-
-
- Use the Service in connection with surveys, contests, pyramid schemes, chain letters, junk email, spamming or any duplicative, bulk or unsolicited messages (commercial or otherwise).
-
- Defame, abuse, harass, stalk, threaten or otherwise violate the legal rights (such as rights of privacy and publicity) of others.
-
- Create a false identity for the purpose of misleading others.
-
- Publish, transfer, distribute or disseminate any inappropriate, profane, defamatory, obscene, indecent or unlawful topic, name, material or information.
-
- Transfer, stream, or otherwise make available, files or other material that contain images, photographs, software or other material protected by intellectual property laws, including, by way of example, and not as limitation, copyright or trademark laws (or by rights of privacy or publicity) unless you own or control the rights thereto or have received all necessary consents to do the same.
-
- Use any material or information, including images or photographs, which is made available through the Service in any manner that infringes any copyright, trademark, patent, trade secret, or other proprietary right of any party.
-
- Transfer, stream or otherwise make available, files or other material that contain viruses, Trojan horses, worms, time bombs, cancelbots, corrupted files, or any other similar software or programs that may damage the operation of another's computer or property of another.
-
- Download any file or other material transferred by another user of the Service that you know, or reasonably should know, cannot be legally distributed in such manner.
-
- Use, download or otherwise copy, or provide (whether or not for a fee) to a person or entity any directory of users of the Service or other user or usage information or any portion thereof.
-
- Falsify or delete any author attributions, legal or other proper notices or proprietary designations or labels of the origin or source of software or other material contained in a file that is transferred.
-
- Violate any code of conduct or other guidelines which may be applicable to the Service.
-
- Use any portion of the Service to harvest or otherwise collect information about others, including e-mail addresses.
-
-Xfire reserves the right at all times to monitor communications on the Service and disclose any information Xfire deems necessary to (i) ensure your compliance with this Agreement; (ii) satisfy any applicable law, regulation or legal process; or (iii) protect the rights, property, and interests of Xfire, its employees or the public. Xfire also reserves the right to edit, refuse to transfer or to remove any information or materials, in whole or in part, in Xfire's sole discretion.
-
-Always use caution when giving out any personally identifiable information about yourself or your children in the Service. Xfire does not control or endorse the content, messages or information exchanged by means of the Service and, therefore, Xfire specifically disclaims any liability with regard to the Service and any actions resulting from your participation in the Service.
-
-You are responsible for all activities that occur in your Service account. You agree to notify Xfire immediately of any unauthorized use of your account or breach in security known to you related to the Service.
-
-
-PRIVACY
-See the Xfire Service Privacy Statement at http://www.xfire.com/xf/privacy.php for disclosures relating to the collection and use of your information.
-
-
-INTERACTION WITH THIRD PARTY SITES AND SERVICES
-The Service may allow you to interact with third-party Web sites and Web services ("Link(s)"). The Links are not under the control of Xfire and Xfire is not responsible for the contents of any Links, including without limitation any link contained in a Link, or any changes or updates to a Link. Xfire is not responsible for any form of transmission received from any Link, nor is Xfire responsible if the Link is not working appropriately. Xfire is providing these Links to you only as a convenience, and the inclusion of any Link does not imply endorsement by Xfire of the Link or any association with its operators. You are responsible for viewing and abiding by any privacy statements and terms of use posted in connection with the Links.
-
-You are solely responsible for any dealings with third parties (including advertisers) who support the Service, including the delivery of and payment for goods and services.
-
-TERMS OF USE FOR SERVICE-ENABLED PROPERTIES
-For the terms and conditions governing your use of any Xfire or authorized third party Web site or service that enables you to use the Service other than the Service itself ("Service-Enabled Properties"), please refer to the applicable Terms of Use for such Service-Enabled Properties.
-
-SOFTWARE AND CONTENT AVAILABLE ON THE SERVICE
-All Xfire content and software (if any) that is made available to view and/or download in connection with the Service ("Software") is owned by and is the copyrighted work of Xfire and/or its suppliers and is licensed, not sold. Your use of the Software is governed by the terms of the license agreement, if any, which accompanies or is included with the Software ("License Agreement"). You may not install or use any Software that is accompanied by or includes a License Agreement unless you first agree to the License Agreement terms. For any Software not accompanied by a license agreement, Xfire hereby grants to you, the user, a non-exclusive, revocable, personal, non-transferable license to use the Software solely in connection with the Service in accordance with these Terms of Use. You may not lend, lease, rent or sublicense the Software or any aspect of the Service.
-
-You will not disassemble, decompile, or reverse engineer the Software. All Software is protected by copyright laws and international treaty provisions. Any unauthorized reproduction or redistribution of the Software is expressly prohibited by law, and may result in severe civil and criminal penalties. WITHOUT LIMITING THE FOREGOING, COPYING OR REPRODUCTION OF THE SOFTWARE TO ANY OTHER SERVER OR LOCATION FOR FURTHER REPRODUCTION OR REDISTRIBUTION IS EXPRESSLY PROHIBITED. THE SOFTWARE IS WARRANTED, IF AT ALL, ONLY ACCORDING TO THE TERMS OF THE LICENSE AGREEMENT. You acknowledge that the Software, and any accompanying documentation and/or technical information, is subject to applicable export control laws and regulations of the U.S.A. You agree not to export or re-export the Software, directly or indirectly, to any countries that are subject to U.S.A. export restrictions.
-
-Your license to use the Software with the Service terminates when you terminate your use of the Service. Your license to use the Software with the Service may also terminate if Xfire, in its sole discretion, modifies the Service to no longer support such Software.
-
-NO WARRANTIES; LIABILITY DISCLAIMER; EXCLUSIVE REMEDY
-XFIRE PROVIDES THE SERVICE AND THE SOFTWARE "AS IS," "WITH ALL FAULTS" AND "AS AVAILABLE," AND THE ENTIRE RISK AS TO SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH YOU. XFIRE, ITS AFFILIATES, ITS RESELLERS, DISTRIBUTORS, SERVICE PROVIDERS AND/OR SUPPLIERS (COLLECTIVELY, THE "XFIRE PARTIES") MAKE NO WARRANTIES. THE XFIRE PARTIES DISCLAIM ANY AND ALL WARRANTIES, EXPRESS, STATUTORY AND IMPLIED, INCLUDING WITHOUT LIMITATION (1) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, WORKMANLIKE EFFORT, ACCURACY, TITLE, QUIET ENJOYMENT, NO ENCUMBRANCES, NO LIENS AND NON-INFRINGEMENT, (2) WARRANTIES ARISING THROUGH COURSE OF DEALING OR USAGE OF TRADE, AND (3) WARRANTIES THAT ACCESS TO OR USE OF THE SERVICE WILL BE UNINTERRUPTED OR ERROR-FREE. THERE ARE NO WARRANTIES THAT EXTEND BEYOND THE FACE OF THIS AGREEMENT. XFIRE MAY CHANGE THE SERVICE OR THE FEATURES IN ANY WAY, AND AT ANY TIME AND FOR ANY REASON.
-
-IN NO EVENT SHALL ANY OF THE XFIRE PARTIES BE LIABLE FOR ANY DIRECT, INDIRECT, CONSEQUENTIAL, SPECIAL, INCIDENTAL, OR PUNITIVE DAMAGES ARISING OUT OF, BASED ON, OR RESULTING FROM THIS AGREEMENT OR YOUR USE OF THE SERVICE, INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF USE, DATA OR PROFITS, WITH THE DELAY OR INABILITY TO USE THE SERVICE, THE PROVISION OF OR FAILURE TO PROVIDE SUPPORT SERVICES, OR FOR ANY INFORMATION, SOFTWARE, PRODUCTS, OR SERVICES OBTAINED THROUGH THE SERVICE, OR OTHERWISE ARISING OUT OF THE USE OF THE SERVICE, WHETHER BASED ON CONTRACT, TORT, NEGLIGENCE, STRICT LIABILITY OR OTHERWISE, EVEN IF XFIREOR ANY OF ITS SUPPLIERS HAS BEEN ADVISED OF THE POSSIBILITY OF DAMAGES. BECAUSE SOME STATES/JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
-
-IF YOU ARE DISSATISFIED WITH ANY PORTION OF THE SERVICE, OR WITH ANY OF THESE TERMS OF USE, YOUR SOLE AND EXCLUSIVE REMEDY IS TO DISCONTINUE USING THE SERVICE.
-
-INDEMNITY
-You agree to indemnify and hold Xfire, its officers, and employees, harmless from any claim or demand, including reasonable attorneys' fees, made by any third party due to or arising out of your use of the Services, the violation of these Terms of Use by you, or the infringement by you, or other user of the Services using your computer or identity, of any intellectual property or other right of any person or entity.
-
-CUSTOMER SUPPORT
-Xfire may, but is not required to, provide you with customer support ("Support"). Unless you have entered into a separate written support agreement with Xfire with respect to the Service, Xfire may terminate any Support it provides at any time in its sole discretion.
-
-Authorized third-party software that uses the Service is not supported by Xfire and you should contact the provider of such software for support, if any.
-
-TERMINATION/ACCESS RESTRICTION
-Unless you, or a third party on your behalf, have entered into a separate written agreement with Xfire that modifies these Terms of Use, Xfire reserves the right, in its sole discretion, to terminate your access to and use of the Service or any portion thereof at any time, without notice. Also, unless you or a third party on your behalf have entered into a separate agreement with Xfire, Xfire may terminate or suspend your access to the Service for inactivity, which is defined as failing to log onto the Service for an extended period of time, as determined by Xfire.
-ELECTRONIC NOTICES
-You consent to Xfire providing you any information regarding the Service in electronic form. Xfire may provide such information to you via e-mail at the e-mail address you specified when you registered for the Service, by instant message to your account, or by access to a Xfire web site. As long as you access and use the Service, you will have the necessary software and hardware to receive such notices. If you do not consent to receive any notices electronically, you must discontinue your use of the Service.
-
-GENERAL
-If you reside in the United States, claims for enforcement, breach or violation of duties or rights under these Terms of Use are governed by the laws of the State of California, without reference to conflict of laws principles. All other claims, including, without limitation, claims under or for violation of state consumer protection laws, unfair competition laws, and in tort, are governed by the laws of your state of residence in the United States. If you reside outside of the United States, these Terms of Use are governed by the laws of the State of California, without reference to conflict of laws principles. You hereby irrevocably consent to the exclusive jurisdiction and venue of courts in San Mateo County, California, U.S.A. in all disputes arising out of or relating to the use of the Service.
-
-YOU AND XFIRE AGREE THAT ANY CAUSE OF ACTION ARISING OUT OF OR RELATED TO THE SERVICE MUST COMMENCE WITHIN ONE (1) YEAR AFTER THE CAUSE OF ACTION ACCRUES. OTHERWISE, SUCH CAUSE OF ACTION IS PERMANENTLY BARRED.
-
-Xfire may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in any Web pages that are part of the Service. Except as expressly provided in these Terms of Use, the furnishing of such Web pages to you does not give you any license to these patents, trademarks, copyrights, or other intellectual property. Any rights not expressly granted herein are reserved.
-
-June 2004
-
-
-
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/platform/xfiregameclient.cpp
--- a/QTfrontend/util/platform/xfiregameclient.cpp Thu Aug 11 23:05:14 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/* This file is NOT open source. See "license.txt" to read the full license provided with the Xfire SDK. */
-
-#define WIN32_LEAN_AND_MEAN
-#include
-#include
-
-#include "xfiregameclient.h"
-
-static HMODULE g_toucan_dll = NULL;
-static void HelperInit();
-static HMODULE HelperGetToucanDLL();
-
-typedef int (*XfireSetCustomGameDataAFunction)(int , const char **, const char **);
-typedef int (*XfireSetCustomGameDataWFunction)(int , const wchar_t **, const wchar_t **);
-typedef int (*XfireSetCustomGameDataUTF8Function)(int , const char **, const char **);
-
-static XfireSetCustomGameDataAFunction ptr_XfireSetCustomGameDataA = NULL;
-static XfireSetCustomGameDataWFunction ptr_XfireSetCustomGameDataW = NULL;
-static XfireSetCustomGameDataUTF8Function ptr_XfireSetCustomGameDataUTF8 = NULL;
-
-/* make sure we are going to call the ANSI version */
-#ifdef MODULEENTRY32
-#undef MODULEENTRY32
-#endif
-
-#ifdef Module32First
-#undef Module32First
-#endif
-
-#ifdef Module32Next
-#undef Module32Next
-#endif
-
-
-int XfireIsLoaded()
-{
- HelperInit();
- if (ptr_XfireSetCustomGameDataA &&
- ptr_XfireSetCustomGameDataW &&
- ptr_XfireSetCustomGameDataUTF8)
- return 1;
- return 0;
-}
-
-int XfireSetCustomGameDataA(int num_keys, const char **keys, const char **values)
-{
- HelperInit();
- if (ptr_XfireSetCustomGameDataA)
- return ptr_XfireSetCustomGameDataA(num_keys, keys, values);
- return 1;
-}
-
-int XfireSetCustomGameDataW(int num_keys, const wchar_t **keys, const wchar_t **values)
-{
- HelperInit();
- if (ptr_XfireSetCustomGameDataW)
- return ptr_XfireSetCustomGameDataW(num_keys, keys, values);
- return 1;
-}
-
-int XfireSetCustomGameDataUTF8(int num_keys, const char **keys, const char **values)
-{
- HelperInit();
- if (ptr_XfireSetCustomGameDataUTF8)
- return ptr_XfireSetCustomGameDataUTF8(num_keys, keys, values);
- return 1;
-}
-
-/* ------------------------------------------------------------------------- */
-static void HelperInit()
-{
- if (!ptr_XfireSetCustomGameDataA ||
- !ptr_XfireSetCustomGameDataW ||
- !ptr_XfireSetCustomGameDataUTF8)
- {
- HMODULE toucan_dll = HelperGetToucanDLL();
- if (toucan_dll)
- {
- ptr_XfireSetCustomGameDataA = (XfireSetCustomGameDataAFunction)::GetProcAddress(toucan_dll, "ToucanSendGameClientDataA_V1");
- ptr_XfireSetCustomGameDataW = (XfireSetCustomGameDataWFunction)::GetProcAddress(toucan_dll, "ToucanSendGameClientDataW_V1");
- ptr_XfireSetCustomGameDataUTF8 = (XfireSetCustomGameDataUTF8Function)::GetProcAddress(toucan_dll, "ToucanSendGameClientDataUTF8_V1");
- }
- }
-}
-
-
-static HMODULE HelperGetToucanDLL()
-{
- if (g_toucan_dll)
- return g_toucan_dll;
-
- /*
- ** We need to enumerate the DLLs loaded to find toucan dll.
- ** This is done because the toucan dll changes with each update.
- ** The toucan dll has the following format. "xfire_toucan_{BUILD_NUMBER}.dll"
- ** We simply try to find a dll w/ the prefix "xfire_toucan"
- */
- HANDLE snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
- if (snapshot_handle != INVALID_HANDLE_VALUE)
- {
- MODULEENTRY32 module_entry;
- module_entry.dwSize = sizeof(MODULEENTRY32);
-
- BOOL result = Module32First(snapshot_handle, &module_entry);
- char module_name[] = "xfire_toucan";
- DWORD module_name_len = sizeof(module_name)-1;
- while (result)
- {
- if (CompareStringA(LOCALE_USER_DEFAULT, NORM_IGNORECASE, module_entry.szModule, module_name_len, module_name, module_name_len) == CSTR_EQUAL)
- {
- g_toucan_dll = module_entry.hModule;
- break;
- }
- result = Module32Next(snapshot_handle, &module_entry);
- }
-
- CloseHandle(snapshot_handle);
- }
-
- return g_toucan_dll;
-}
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/util/platform/xfiregameclient.h
--- a/QTfrontend/util/platform/xfiregameclient.h Thu Aug 11 23:05:14 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/* This file is NOT open source. See "license.txt" to read the full license provided with the Xfire SDK. */
-
-#ifndef __XFIREGAMECLIENT_H__
-#define __XFIREGAMECLIENT_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-** XfireIsLoaded()
-**
-** returns 1 if application can talk to Xfire, 0 otherwise
-*/
-int XfireIsLoaded();
-
-/*
-** XfireSetCustomGameDataA()
-**
-** ANSI version to tell xfire of custom game data
-*/
-int XfireSetCustomGameDataA(int num_keys, const char **keys, const char **values);
-
-/*
-** XfireSetCustomGameDataA()
-**
-** UNICODE version to tell xfire of custom game data
-*/
-int XfireSetCustomGameDataW(int num_keys, const wchar_t **keys, const wchar_t **values);
-
-/*
-** XfireSetCustomGameDataUTF8()
-**
-** UTF8 version to tell xfire of custom game data
-*/
-int XfireSetCustomGameDataUTF8(int num_keys, const char **keys, const char **values);
-
-#ifdef UNICODE
-#define XfireSetCustomGameData XfireSetCustomGameDataW
-#else
-#define XfireSetCustomGameData XfireSetCustomGameDataA
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __XFIREGAMECLIENT_H__ */
diff -r 01f88c3b7b66 -r 1b2b84315d27 QTfrontend/weapons.h
--- a/QTfrontend/weapons.h Thu Aug 11 23:05:14 2016 +0300
+++ b/QTfrontend/weapons.h Sun Dec 17 00:09:24 2017 +0100
@@ -16,10 +16,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#define AMMOLINE_EMPTY_QT "000000900000000000000000000000000000000000000000000000000"
-#define AMMOLINE_EMPTY_PROB "000000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_EMPTY_DELAY "000000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_EMPTY_CRATE "131111031211111112311411111111111111121111111111111111111"
+#define AMMOLINE_EMPTY_QT "0000009000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_EMPTY_PROB "0000000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_EMPTY_DELAY "0000000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_EMPTY_CRATE "1311110312111111123114111111111111111211111111111111111111"
/*
AmmoType lookup table (use monospace font / cursor movements)
@@ -81,63 +81,64 @@
amKnife-------------------------------------------------------------------------------|
amRubber-------------------------------------------------------------------------------|
amAirMine-------------------------------------------------------------------------------|
+ amDuck-----------------------------------------------------------------------------------|
*/
-#define AMMOLINE_DEFAULT_QT "939192942219912103223511100120000000021110010101111100010"
-#define AMMOLINE_DEFAULT_PROB "040504054160065554655446477657666666615551010111541111111"
-#define AMMOLINE_DEFAULT_DELAY "000000000000020550000004000700400000000022000000060002000"
-#define AMMOLINE_DEFAULT_CRATE "131111031211111112311411111111111111121111110111111111111"
+#define AMMOLINE_DEFAULT_QT "9391929422199121032235111001200000000211100101011111000102"
+#define AMMOLINE_DEFAULT_PROB "0405040541600655546554464776576666666155510101115411111114"
+#define AMMOLINE_DEFAULT_DELAY "0000000000000205500000040007004000000000220000000600020000"
+#define AMMOLINE_DEFAULT_CRATE "1311110312111111123114111111111111111211111111111111111111"
-#define AMMOLINE_CRAZY_QT "999999999999999999299999999999999929999999990999999299919"
-#define AMMOLINE_CRAZY_PROB "111111011111111111111111111111111111111111110111111111111"
-#define AMMOLINE_CRAZY_DELAY "000000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_CRAZY_CRATE "131111031211111112311411111111111111121111010111111111111"
+#define AMMOLINE_CRAZY_QT "9999999999999999992999999999999999299999999999999992999199"
+#define AMMOLINE_CRAZY_PROB "1111110111111111111111111111111111111111111111111111111111"
+#define AMMOLINE_CRAZY_DELAY "0000000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_CRAZY_CRATE "1311110312111111123114111111111111111211111111111111111111"
-#define AMMOLINE_PROMODE_QT "909000900000000000000900000000000000000000000000000000000"
-#define AMMOLINE_PROMODE_PROB "000000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_PROMODE_DELAY "000000000000020550000004000700400000000020000000000002000"
-#define AMMOLINE_PROMODE_CRATE "111111011111111111111111111111111111111110010111111111111"
+#define AMMOLINE_PROMODE_QT "9090009000000000000009000000000000000000000000000000000000"
+#define AMMOLINE_PROMODE_PROB "0000000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_PROMODE_DELAY "0000000000000205500000040007004000000000200000000000020000"
+#define AMMOLINE_PROMODE_CRATE "1111110111111111111111111111111111111111111111111111111111"
-#define AMMOLINE_SHOPPA_QT "000000990000000000000000000000000000000000000000000000000"
-#define AMMOLINE_SHOPPA_PROB "444441004424440221011212122242200000000200040001001100101"
-#define AMMOLINE_SHOPPA_DELAY "000000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_SHOPPA_CRATE "111111011111111111111111111111111111111110110111111111101"
+#define AMMOLINE_SHOPPA_QT "0000009900000000000000000000000000000000000000000000000000"
+#define AMMOLINE_SHOPPA_PROB "4444410044244402210112121222422000000002000400010011001011"
+#define AMMOLINE_SHOPPA_DELAY "0000000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_SHOPPA_CRATE "1111110111111111111111111111111111111111111111111111111111"
-#define AMMOLINE_CLEAN_QT "101000900001000001100000000000000000000000000000100000000"
-#define AMMOLINE_CLEAN_PROB "040504054160065554655446477657666666615551010111541112111"
-#define AMMOLINE_CLEAN_DELAY "000000000000000000000000000000000000000000000000000002000"
-#define AMMOLINE_CLEAN_CRATE "131111031211111112311411111111111111121111110111111111111"
+#define AMMOLINE_CLEAN_QT "1010009000010000011000000000000000000000000000001000000000"
+#define AMMOLINE_CLEAN_PROB "0405040541600655546554464776576666666155510101115411121114"
+#define AMMOLINE_CLEAN_DELAY "0000000000000000000000000000000000000000000000000000020000"
+#define AMMOLINE_CLEAN_CRATE "1311110312111111123114111111111111111211111111111111111111"
-#define AMMOLINE_MINES_QT "000000990009000000030000000000000000000000000000000000000"
-#define AMMOLINE_MINES_PROB "000000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_MINES_DELAY "000000000000020550000004000700400000000020000000060002000"
-#define AMMOLINE_MINES_CRATE "111111011111111111111111111111111111111111110111111111111"
+#define AMMOLINE_MINES_QT "0000009900090000000300000000000000000000000000000000000000"
+#define AMMOLINE_MINES_PROB "0000000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_MINES_DELAY "0000000000000205500000040007004000000000200000000600020000"
+#define AMMOLINE_MINES_CRATE "1111110111111111111111111111111111111111111111111111111111"
-#define AMMOLINE_PORTALS_QT "900000900200000000210000000000000011000009000000000000000"
-#define AMMOLINE_PORTALS_PROB "040504054160065554655446477657666666615551010111541112111"
-#define AMMOLINE_PORTALS_DELAY "000000000000020550000004000700400000000020000000060002000"
-#define AMMOLINE_PORTALS_CRATE "131111031211111112311411111111111111121111110111111111111"
+#define AMMOLINE_PORTALS_QT "9000009002000000002100000000000000110000090000000000000000"
+#define AMMOLINE_PORTALS_PROB "0405040541600655546554464776576666666155510101115411121112"
+#define AMMOLINE_PORTALS_DELAY "0000000000000205500000040007004000000000200000000600020000"
+#define AMMOLINE_PORTALS_CRATE "1311110312111111123114111111111111111211111111111111111111"
-#define AMMOLINE_ONEEVERY_QT "111111911111111111111111111111111111111111111111111111111"
-#define AMMOLINE_ONEEVERY_PROB "111111011111111111111111111111111111111111111111111111111"
-#define AMMOLINE_ONEEVERY_DELAY "000000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_ONEEVERY_CRATE "111111011111111111111111111111111111111111111111111111111"
+#define AMMOLINE_ONEEVERY_QT "1111119111111111111111111111111111111111111111111111111111"
+#define AMMOLINE_ONEEVERY_PROB "1111110111111111111111111111111111111111111111111111111111"
+#define AMMOLINE_ONEEVERY_DELAY "0000000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_ONEEVERY_CRATE "1111110111111111111111111111111111111111111111111111111111"
-#define AMMOLINE_HIGHLANDER_QT "111111911111111111110191111111111001011111011110110011010"
-#define AMMOLINE_HIGHLANDER_PROB "000000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_HIGHLANDER_DELAY "000000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_HIGHLANDER_CRATE "000000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_HIGHLANDER_QT "1111119111111111111101911111111110010111110111100100101111"
+#define AMMOLINE_HIGHLANDER_PROB "0000000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_HIGHLANDER_DELAY "0000000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_HIGHLANDER_CRATE "0000000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_CONSTRUCTION_QT "110001900000001001000000000000000000000000000000000000000"
-#define AMMOLINE_CONSTRUCTION_PROB "111111011111111111111111111111111111111111111111111111110"
-#define AMMOLINE_CONSTRUCTION_DELAY "000000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_CONSTRUCTION_CRATE "111111011111111111111111111111111111111111111111111111110"
+#define AMMOLINE_CONSTRUCTION_QT "1100019000000010010000000000000000000000000000000000000000"
+#define AMMOLINE_CONSTRUCTION_PROB "1111110111111111111111111111111111111111111111111111111111"
+#define AMMOLINE_CONSTRUCTION_DELAY "0000000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_CONSTRUCTION_CRATE "1111110111111111111111111111111111111111111111111111111111"
-#define AMMOLINE_SHOPPAPRO_QT "000000990000000000000000000000000000000000000000000000000"
-#define AMMOLINE_SHOPPAPRO_PROB "444440004404440000000000000040000000000000000000000000000"
-#define AMMOLINE_SHOPPAPRO_DELAY "000000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_SHOPPAPRO_CRATE "111111011111111111111111111111111111111110110111111112110"
+#define AMMOLINE_SHOPPAPRO_QT "0000009900000000000000000000000000000000000000000000000000"
+#define AMMOLINE_SHOPPAPRO_PROB "4444400044044400000000000000400000000000000000000000000000"
+#define AMMOLINE_SHOPPAPRO_DELAY "0000000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_SHOPPAPRO_CRATE "1111110111111111111111111111111111111111111111111111121111"
-
-//When adding new weapons also insert one element in cDefaultAmmos list (hwconsts.cpp.in)
-
-
+#define AMMOLINE_HEDGEEDITOR_QT "0000009000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_HEDGEEDITOR_PROB "0000000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_HEDGEEDITOR_DELAY "0000000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_HEDGEEDITOR_CRATE "1111110111111111111111111111111111111111111111111111111111"
diff -r 01f88c3b7b66 -r 1b2b84315d27 README.md
--- a/README.md Thu Aug 11 23:05:14 2016 +0300
+++ b/README.md Sun Dec 17 00:09:24 2017 +0100
@@ -1,48 +1,125 @@
-Hedgewars - a turn based strategy game.
-=======================================
+Hedgewars - a turn-based strategy game
+======================================
+
+Description
+-----------
+This is the funniest and most addictive game you'll ever play—hilarious fun
+that you can enjoy anywhere, anytime. **Hedgewars** is a **turn-based strategy
+game** but the real buzz is from watching the **devastation caused by those
+pesky hedgehogs** with those fantastic weapons—sneaky little blighters with a
+bad attitude!
+
+Each player controls a **team of up to 8 hedgehogs**. During the course of
+the game, players take turns with one of their hedgehogs. They then use
+whatever tools and weapons are available to **attack and kill the opponents'
+hedgehogs**, thereby winning the game. Hedgehogs may move around the terrain
+in a variety of ways, normally by walking and jumping but also by using
+particular tools such as the rope or parachute, to move to otherwise
+inaccessible areas. Each **turn is time-limited** to ensure that players do
+not hold up the game with excessive thinking or moving.
+
+A large **variety of tools and weapons** are available for players during
+the game. Hedgewars features the standard artillery-genre classics (such as
+grenade, cluster bomb, bazooka, shotgun), but also boasts a host of other
+weapons quite unique to it alone.
+
+Most weapons, when used, cause **explosions that deform the terrain**,
+removing circular chunks. Hedgehogs can die by drowning, being thrown off
+either side of the arena, or when their health is reduced to zero.
+
+Getting started
+---------------
+For complete beginners we recommend to start with the the first 2 or 3
+missions of the campaign “A Classic Fairytale” in the singleplayer menu.
+It explains the basic controls and gameplay.
+
+Note that Hedgewars doesn't have a *complete* tutorial yet, but it is
+planned to create one in future versions.
+
+In-depth information about the game can be found online:
+
+* : Getting Started
+* : Hedgewars Wiki
+
+Default controls (excerpt)
+--------------------------
+The most important default controls are:
+
+* Cursor keys: Walk and aim
+* Mouse: Move camera
+* Right mouse button: Open ammo menu
+* Left mouse button: Select target or weapon
+* Space bar: Shoot
+* Left shift: Precise
+* Left shift + Up/Down: Precise aiming
+* Enter: Jump
+* Backspace: High jump
+* Backspace ×2: Backjump
+* Tab: Switch hedgehog (after activating the utility)
+* 1-5: Set weapon timer
+* F1-F10: Weapon shortcuts
+* P: Pause (also shows mission panel)
+* Esc: Quit with prompt (also shows mission panel)
+* T: Chat
+
+For the full list, go to the Hedgewars settings. Also read the weapon tooltips
+for weapon-specific controls.
+
+### Special controls
+
+These are lesser-known controls of Hedgewars, they are based on your
+configured controls:
+
+* Confirm: Team chat (if not confirming quit)
+* Hold down Precise: Prevent slipping on ice
+* Precise + Left/Right: Turn around
+* Precise + Toggle team bars: Change hedgehog tabs
+* Precise + Toggle team bars + Switch: Toggle HUD
+* Precise + Screenshot: Save current map + mask in Screenshot directory
+
+Installation instructions
+-------------------------
+See the `INSTALL.md` file.
+
+Or see our wiki at .
+
+Source code
+-----------
+Our main repository is located at using
+Mercurial as DVCS. A Git repository is also available (mirrored daily)
+at .
[![Build Status](https://travis-ci.org/hedgewars/hw.svg)](https://travis-ci.org/hedgewars/hw)
-Copyright 2004-2015 Andrey Korotaev and others.
-See QTfrontend/res/html/about.html and CREDITS for a complete list of authors.
-
-Licence:
---------
-Source code is distributed under the terms of the GNU General Public Licence
-version 2; images and sounds are distributed under the terms of the GNU Free
-Documentation Licence version 1.2. See the COPYING file for the full text of
-the licenses.
-
-Instructions:
--------------
-See our wiki at: http://hedgewars.org/kb/BuildingHedgewars
-
-You can find an outline of the necessary dependencies in the INSTALL file.
-
-Source code:
-------------
-Our main repository is located at http://hg.hedgewars.org/hedgewars/ using
-Mercurial as DVCS. A Git repository is also available (mirrored daily)
-at https://github.com/hedgewars/hw
-
-Contribute:
------------
+Contribute
+----------
If you see a bug or have any suggestion please use the official bug tracker at
-http://hedgewars.org/bugs or the integrated feedback
-button.
+ or the integrated feedback button.
If you want to help or get to know the sources better you can do that with some
-easy tasks from http://hedgewars.org/kb/TODO. We also have an
-extended API in LUA to customize your adventures in our wiki at
-http://hedgewars.org/kb/LuaAPI.
+easy tasks from . We also have an extensive API
+in Lua to customize your adventures. See our wiki at
+.
If you know your way through the code feel free to send a patch or open a pull
-request. The best LUA scripts get released in the official DLC page and later
+request. The best Lua scripts get released in the official DLC page and later
integrated in the next version.
-Contact:
---------
+Licence and credits
+-------------------
+This game is free software (“free” as in “freedom”). Source code is
+distributed under the terms of the GNU General Public Licence version 2;
+images and sounds are distributed under the terms of the GNU Free Documentation
+Licence version 1.2. See the `COPYING` file for the full text of the licenses.
+
+Copyright 2004-2015 Andrey Korotaev and others.
+See `QTfrontend/res/html/about.html` and `CREDITS` for a more complete list of
+authors.
+
+Contact
+-------
+* Homepage - https://hedgewars.org/
* IRC channel - irc://irc.freenode.net/hedgewars
-* community forum - http://www.hedgewars.org/forum
-* mailing list - https://mail.gna.org/listinfo/hedgewars-dev
+* Community forum - https://hedgewars.org/forum
+* Mailing list - https://mail.gna.org/listinfo/hedgewars-dev
diff -r 01f88c3b7b66 -r 1b2b84315d27 cmake_modules/CheckHaskellModuleExists.cmake
--- a/cmake_modules/CheckHaskellModuleExists.cmake Thu Aug 11 23:05:14 2016 +0300
+++ b/cmake_modules/CheckHaskellModuleExists.cmake Sun Dec 17 00:09:24 2017 +0100
@@ -22,12 +22,15 @@
endforeach()
endif()
- set(PARAMETERS "")
+ #set(PARAMETERS "")
execute_process(COMMAND ${GHC_EXECUTABLE}
"-DMODULE=${MODULE}"
"-DFUNCTION=${FUNCTION}"
"-DPARAMETERS=${PARAMETERS}"
+ -hide-all-packages
+ -package ${LIBRARY}
+ -package base
-cpp
-c "${CMAKE_MODULE_PATH}/checkModule.hs"
RESULT_VARIABLE COMMAND_RESULT
diff -r 01f88c3b7b66 -r 1b2b84315d27 cmake_modules/FindLua.cmake
--- a/cmake_modules/FindLua.cmake Thu Aug 11 23:05:14 2016 +0300
+++ b/cmake_modules/FindLua.cmake Sun Dec 17 00:09:24 2017 +0100
@@ -18,7 +18,7 @@
find_path(LUA_INCLUDE_DIR lua.h
PATHS /usr/include /usr/local/include /usr/pkg/include
PATH_SUFFIXES lua5.1 lua51 lua-5.1)
-find_library(LUA_LIBRARY NAMES lua51 lua5.1 lua-5.1 lua
+find_library(LUA_LIBRARY NAMES liblua lua51 lua5.1 lua-5.1 lua
PATHS /lib /usr/lib /usr/local/lib /usr/pkg/lib)
find_package_handle_standard_args(Lua DEFAULT_MSG LUA_LIBRARY LUA_INCLUDE_DIR)
diff -r 01f88c3b7b66 -r 1b2b84315d27 cmake_modules/FindSDL2_image.cmake
--- a/cmake_modules/FindSDL2_image.cmake Thu Aug 11 23:05:14 2016 +0300
+++ b/cmake_modules/FindSDL2_image.cmake Sun Dec 17 00:09:24 2017 +0100
@@ -55,13 +55,13 @@
PATH_SUFFIXES lib
)
-if(SDL2_IMAGE_INCLUDE_DIR AND EXISTS "${SDL2_IMAGE_INCLUDE_DIR}/SDL2_image.h")
- file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL2_image.h" SDL2_IMAGE_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL2_IMAGE_MAJOR_VERSION[ \t]+[0-9]+$")
- file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL2_image.h" SDL2_IMAGE_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL2_IMAGE_MINOR_VERSION[ \t]+[0-9]+$")
- file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL2_image.h" SDL2_IMAGE_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL2_IMAGE_PATCHLEVEL[ \t]+[0-9]+$")
- string(REGEX REPLACE "^#define[ \t]+SDL2_IMAGE_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MAJOR "${SDL2_IMAGE_VERSION_MAJOR_LINE}")
- string(REGEX REPLACE "^#define[ \t]+SDL2_IMAGE_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MINOR "${SDL2_IMAGE_VERSION_MINOR_LINE}")
- string(REGEX REPLACE "^#define[ \t]+SDL2_IMAGE_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_PATCH "${SDL2_IMAGE_VERSION_PATCH_LINE}")
+if(SDL2_IMAGE_INCLUDE_DIR AND EXISTS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h")
+ file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_IMAGE_PATCHLEVEL[ \t]+[0-9]+$")
+ string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MAJOR "${SDL2_IMAGE_VERSION_MAJOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MINOR "${SDL2_IMAGE_VERSION_MINOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_PATCH "${SDL2_IMAGE_VERSION_PATCH_LINE}")
set(SDL2_IMAGE_VERSION_STRING ${SDL2_IMAGE_VERSION_MAJOR}.${SDL2_IMAGE_VERSION_MINOR}.${SDL2_IMAGE_VERSION_PATCH})
unset(SDL2_IMAGE_VERSION_MAJOR_LINE)
unset(SDL2_IMAGE_VERSION_MINOR_LINE)
@@ -87,8 +87,8 @@
VERSION_VAR SDL2_IMAGE_VERSION_STRING)
# for backward compatiblity
-set(SDL2IMAGE_LIBRARY ${SDL2_IMAGE_LIBRARIES})
-set(SDL2IMAGE_INCLUDE_DIR ${SDL2_IMAGE_INCLUDE_DIRS})
-set(SDL2IMAGE_FOUND ${SDL2_IMAGE_FOUND})
+set(SDLIMAGE_LIBRARY ${SDL2_IMAGE_LIBRARIES})
+set(SDLIMAGE_INCLUDE_DIR ${SDL2_IMAGE_INCLUDE_DIRS})
+set(SDLIMAGE_FOUND ${SDL2_IMAGE_FOUND})
mark_as_advanced(SDL2_IMAGE_LIBRARY SDL2_IMAGE_INCLUDE_DIR)
diff -r 01f88c3b7b66 -r 1b2b84315d27 cmake_modules/FindSDL2_mixer.cmake
--- a/cmake_modules/FindSDL2_mixer.cmake Thu Aug 11 23:05:14 2016 +0300
+++ b/cmake_modules/FindSDL2_mixer.cmake Sun Dec 17 00:09:24 2017 +0100
@@ -33,8 +33,7 @@
# License text for the above reference.)
if(NOT SDL2_MIXER_INCLUDE_DIR AND SDL2MIXER_INCLUDE_DIR)
- set(SDL2_MIXER_INCLUDE_DIR ${SDL2MIXER_INCLUDE_DIR} CACHE PATH "directory cache
-entry initialized from old variable name")
+ set(SDL2_MIXER_INCLUDE_DIR ${SDL2MIXER_INCLUDE_DIR} CACHE PATH "directory cache entry initialized from old variable name")
endif()
find_path(SDL2_MIXER_INCLUDE_DIR SDL_mixer.h
HINTS
@@ -55,13 +54,13 @@
PATH_SUFFIXES lib
)
-if(SDL2_MIXER_INCLUDE_DIR AND EXISTS "${SDL2_MIXER_INCLUDE_DIR}/SDL2_mixer.h")
- file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL2_mixer.h" SDL2_MIXER_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL2_MIXER_MAJOR_VERSION[ \t]+[0-9]+$")
- file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL2_mixer.h" SDL2_MIXER_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL2_MIXER_MINOR_VERSION[ \t]+[0-9]+$")
- file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL2_mixer.h" SDL2_MIXER_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL2_MIXER_PATCHLEVEL[ \t]+[0-9]+$")
- string(REGEX REPLACE "^#define[ \t]+SDL2_MIXER_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MAJOR "${SDL2_MIXER_VERSION_MAJOR_LINE}")
- string(REGEX REPLACE "^#define[ \t]+SDL2_MIXER_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MINOR "${SDL2_MIXER_VERSION_MINOR_LINE}")
- string(REGEX REPLACE "^#define[ \t]+SDL2_MIXER_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_PATCH "${SDL2_MIXER_VERSION_PATCH_LINE}")
+if(SDL2_MIXER_INCLUDE_DIR AND EXISTS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h")
+ file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MIXER_MAJOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MIXER_MINOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_MIXER_PATCHLEVEL[ \t]+[0-9]+$")
+ string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MAJOR "${SDL2_MIXER_VERSION_MAJOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MINOR "${SDL2_MIXER_VERSION_MINOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_PATCH "${SDL2_MIXER_VERSION_PATCH_LINE}")
set(SDL2_MIXER_VERSION_STRING ${SDL2_MIXER_VERSION_MAJOR}.${SDL2_MIXER_VERSION_MINOR}.${SDL2_MIXER_VERSION_PATCH})
unset(SDL2_MIXER_VERSION_MAJOR_LINE)
unset(SDL2_MIXER_VERSION_MINOR_LINE)
@@ -87,8 +86,8 @@
VERSION_VAR SDL2_MIXER_VERSION_STRING)
# for backward compatiblity
-set(SDL2MIXER_LIBRARY ${SDL2_MIXER_LIBRARIES})
-set(SDL2MIXER_INCLUDE_DIR ${SDL2_MIXER_INCLUDE_DIRS})
-set(SDL2MIXER_FOUND ${SDL2_MIXER_FOUND})
+set(SDLMIXER_LIBRARY ${SDL2_MIXER_LIBRARIES})
+set(SDLMIXER_INCLUDE_DIR ${SDL2_MIXER_INCLUDE_DIRS})
+set(SDLMIXER_FOUND ${SDL2_MIXER_FOUND})
mark_as_advanced(SDL2_MIXER_LIBRARY SDL2_MIXER_INCLUDE_DIR)
diff -r 01f88c3b7b66 -r 1b2b84315d27 cmake_modules/FindSDL2_net.cmake
--- a/cmake_modules/FindSDL2_net.cmake Thu Aug 11 23:05:14 2016 +0300
+++ b/cmake_modules/FindSDL2_net.cmake Sun Dec 17 00:09:24 2017 +0100
@@ -55,13 +55,13 @@
PATH_SUFFIXES lib
)
-if(SDL2_NET_INCLUDE_DIR AND EXISTS "${SDL2_NET_INCLUDE_DIR}/SDL2_net.h")
- file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL2_net.h" SDL2_NET_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL2_NET_MAJOR_VERSION[ \t]+[0-9]+$")
- file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL2_net.h" SDL2_NET_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL2_NET_MINOR_VERSION[ \t]+[0-9]+$")
- file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL2_net.h" SDL2_NET_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL2_NET_PATCHLEVEL[ \t]+[0-9]+$")
- string(REGEX REPLACE "^#define[ \t]+SDL2_NET_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_MAJOR "${SDL2_NET_VERSION_MAJOR_LINE}")
- string(REGEX REPLACE "^#define[ \t]+SDL2_NET_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_MINOR "${SDL2_NET_VERSION_MINOR_LINE}")
- string(REGEX REPLACE "^#define[ \t]+SDL2_NET_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_PATCH "${SDL2_NET_VERSION_PATCH_LINE}")
+if(SDL2_NET_INCLUDE_DIR AND EXISTS "${SDL2_NET_INCLUDE_DIR}/SDL_net.h")
+ file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL_net.h" SDL2_NET_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_NET_MAJOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL_net.h" SDL2_NET_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_NET_MINOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL_net.h" SDL2_NET_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_NET_PATCHLEVEL[ \t]+[0-9]+$")
+ string(REGEX REPLACE "^#define[ \t]+SDL_NET_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_MAJOR "${SDL2_NET_VERSION_MAJOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_NET_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_MINOR "${SDL2_NET_VERSION_MINOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_NET_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_PATCH "${SDL2_NET_VERSION_PATCH_LINE}")
set(SDL2_NET_VERSION_STRING ${SDL2_NET_VERSION_MAJOR}.${SDL2_NET_VERSION_MINOR}.${SDL2_NET_VERSION_PATCH})
unset(SDL2_NET_VERSION_MAJOR_LINE)
unset(SDL2_NET_VERSION_MINOR_LINE)
@@ -87,8 +87,8 @@
VERSION_VAR SDL2_NET_VERSION_STRING)
# for backward compatiblity
-set(SDL2NET_LIBRARY ${SDL2_NET_LIBRARIES})
-set(SDL2NET_INCLUDE_DIR ${SDL2_NET_INCLUDE_DIRS})
-set(SDL2NET_FOUND ${SDL2_NET_FOUND})
+set(SDLNET_LIBRARY ${SDL2_NET_LIBRARIES})
+set(SDLNET_INCLUDE_DIR ${SDL2_NET_INCLUDE_DIRS})
+set(SDLNET_FOUND ${SDL2_NET_FOUND})
mark_as_advanced(SDL2_NET_LIBRARY SDL2_NET_INCLUDE_DIR)
diff -r 01f88c3b7b66 -r 1b2b84315d27 cmake_modules/FindSDL2_ttf.cmake
--- a/cmake_modules/FindSDL2_ttf.cmake Thu Aug 11 23:05:14 2016 +0300
+++ b/cmake_modules/FindSDL2_ttf.cmake Sun Dec 17 00:09:24 2017 +0100
@@ -55,13 +55,13 @@
PATH_SUFFIXES lib
)
-if(SDL2_TTF_INCLUDE_DIR AND EXISTS "${SDL2_TTF_INCLUDE_DIR}/SDL2_ttf.h")
- file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL2_ttf.h" SDL2_TTF_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL2_TTF_MAJOR_VERSION[ \t]+[0-9]+$")
- file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL2_ttf.h" SDL2_TTF_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL2_TTF_MINOR_VERSION[ \t]+[0-9]+$")
- file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL2_ttf.h" SDL2_TTF_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL2_TTF_PATCHLEVEL[ \t]+[0-9]+$")
- string(REGEX REPLACE "^#define[ \t]+SDL2_TTF_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_MAJOR "${SDL2_TTF_VERSION_MAJOR_LINE}")
- string(REGEX REPLACE "^#define[ \t]+SDL2_TTF_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_MINOR "${SDL2_TTF_VERSION_MINOR_LINE}")
- string(REGEX REPLACE "^#define[ \t]+SDL2_TTF_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_PATCH "${SDL2_TTF_VERSION_PATCH_LINE}")
+if(SDL2_TTF_INCLUDE_DIR AND EXISTS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h")
+ file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h" SDL2_TTF_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_TTF_MAJOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h" SDL2_TTF_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_TTF_MINOR_VERSION[ \t]+[0-9]+$")
+ file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h" SDL2_TTF_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_TTF_PATCHLEVEL[ \t]+[0-9]+$")
+ string(REGEX REPLACE "^#define[ \t]+SDL_TTF_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_MAJOR "${SDL2_TTF_VERSION_MAJOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_TTF_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_MINOR "${SDL2_TTF_VERSION_MINOR_LINE}")
+ string(REGEX REPLACE "^#define[ \t]+SDL_TTF_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_PATCH "${SDL2_TTF_VERSION_PATCH_LINE}")
set(SDL2_TTF_VERSION_STRING ${SDL2_TTF_VERSION_MAJOR}.${SDL2_TTF_VERSION_MINOR}.${SDL2_TTF_VERSION_PATCH})
unset(SDL2_TTF_VERSION_MAJOR_LINE)
unset(SDL2_TTF_VERSION_MINOR_LINE)
@@ -87,8 +87,8 @@
VERSION_VAR SDL2_TTF_VERSION_STRING)
# for backward compatiblity
-set(SDL2TTF_LIBRARY ${SDL2_TTF_LIBRARIES})
-set(SDL2TTF_INCLUDE_DIR ${SDL2_TTF_INCLUDE_DIRS})
-set(SDL2TTF_FOUND ${SDL2_TTF_FOUND})
+set(SDLTTF_LIBRARY ${SDL2_TTF_LIBRARIES})
+set(SDLTTF_INCLUDE_DIR ${SDL2_TTF_INCLUDE_DIRS})
+set(SDLTTF_FOUND ${SDL2_TTF_FOUND})
mark_as_advanced(SDL2_TTF_LIBRARY SDL2_TTF_INCLUDE_DIR)
diff -r 01f88c3b7b66 -r 1b2b84315d27 cmake_modules/checkModule.hs
--- a/cmake_modules/checkModule.hs Thu Aug 11 23:05:14 2016 +0300
+++ b/cmake_modules/checkModule.hs Sun Dec 17 00:09:24 2017 +0100
@@ -1,3 +1,4 @@
+{-# LANGUAGE ImpredicativeTypes #-}
module Main where
import qualified MODULE as M
diff -r 01f88c3b7b66 -r 1b2b84315d27 cmake_modules/cpackvars.cmake
--- a/cmake_modules/cpackvars.cmake Thu Aug 11 23:05:14 2016 +0300
+++ b/cmake_modules/cpackvars.cmake Sun Dec 17 00:09:24 2017 +0100
@@ -81,6 +81,8 @@
"[dD]ebug$"
"[rR]elease$"
"CPack"
+ "CTestTestfile.cmake"
+ "gameServer2"
"cmake_install\\\\.cmake$"
"cmake_uninstall\\\\.cmake$"
"CMakeCache\\\\.txt$"
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer/Actions.hs
--- a/gameServer/Actions.hs Thu Aug 11 23:05:14 2016 +0300
+++ b/gameServer/Actions.hs Sun Dec 17 00:09:24 2017 +0100
@@ -40,6 +40,9 @@
import Network.Socket
import System.Random
import qualified Data.Traversable as DT
+import Text.Regex.Base
+import qualified Text.Regex.TDFA as TDFA
+import qualified Text.Regex.TDFA.ByteString as TDFAB
-----------------------------
#if defined(OFFICIAL_SERVER)
import OfficialServer.GameReplayStore
@@ -512,12 +515,12 @@
rnc <- gets roomsClients
clientNick <- client's nick
clProto <- client's clientProto
- isAuthenticated <- liftM (not . B.null) $ client's webPassword
+ isAuthenticated <- client's isRegistered
isAdmin <- client's isAdministrator
isContr <- client's isContributor
loggedInClients <- liftM (Prelude.filter isVisible) $! allClientsS
let (lobbyNicks, clientsChans) = unzip . L.map (nick &&& sendChan) $ loggedInClients
- let authenticatedNicks = L.map nick . L.filter (not . B.null . webPassword) $ loggedInClients
+ let authenticatedNicks = L.map nick . L.filter isRegistered $ loggedInClients
let adminsNicks = L.map nick . L.filter isAdministrator $ loggedInClients
let contrNicks = L.map nick . L.filter isContributor $ loggedInClients
inRoomNicks <- io $
@@ -528,8 +531,8 @@
roomsInfoList <- io $ do
rooms <- roomsM rnc
- mapM (\r -> (if isNothing $ masterID r then return "" else client'sM rnc nick (fromJust $ masterID r))
- >>= \cn -> return $ roomInfo clProto cn r)
+ mapM (\r -> (mapM (client'sM rnc id) $ masterID r)
+ >>= \cn -> return $ roomInfo clProto (maybeNick cn) r)
$ filter (\r -> (roomProto r == clProto)) rooms
mapM_ processAction . concat $ [
@@ -658,9 +661,13 @@
where
checkNotExpired testTime (BanByIP _ _ time) = testTime `diffUTCTime` time <= 0
checkNotExpired testTime (BanByNick _ _ time) = testTime `diffUTCTime` time <= 0
- checkBan True ip _ (BanByIP bip _ _) = bip `B.isPrefixOf` ip
- checkBan False _ n (BanByNick bn _ _) = caseInsensitiveCompare bn n
+ checkBan True ip _ (BanByIP bip _ _) = isMatch bip ip
+ checkBan False _ n (BanByNick bn _ _) = isMatch bn n
checkBan _ _ _ _ = False
+ isMatch :: B.ByteString -> B.ByteString -> Bool
+ isMatch rexp src = (==) (Just True) $ mrexp rexp >>= flip matchM src
+ mrexp :: B.ByteString -> Maybe TDFAB.Regex
+ mrexp = makeRegexOptsM TDFA.defaultCompOpt{TDFA.caseSensitive = False} TDFA.defaultExecOpt
getBanReason (BanByIP _ msg _) = msg
getBanReason (BanByNick _ msg _) = msg
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer/CMakeLists.txt
--- a/gameServer/CMakeLists.txt Thu Aug 11 23:05:14 2016 +0300
+++ b/gameServer/CMakeLists.txt Sun Dec 17 00:09:24 2017 +0100
@@ -12,7 +12,7 @@
check_haskell_module_exists("Network.BSD" getHostName 0 network)
check_haskell_module_exists("Data.Time" getCurrentTime 0 time)
check_haskell_module_exists("Control.Monad.State" fix 1 mtl)
-check_haskell_module_exists("Codec.Binary.Base64" encode 1 dataenc)
+check_haskell_module_exists("Codec.Binary.Base64" encode 1 sandi)
check_haskell_module_exists("System.Log.Logger" warningM 1 hslogger)
check_haskell_module_exists("System.Process" createProcess 3 process)
check_haskell_module_exists("Data.ByteString.Lazy.UTF8" decode 1 utf8-string)
@@ -20,6 +20,7 @@
check_haskell_module_exists("System.Entropy" openHandle 0 entropy)
check_haskell_module_exists("Codec.Compression.Zlib" decompress 1 zlib)
check_haskell_module_exists("System.Random" getStdGen 0 random)
+check_haskell_module_exists("Text.Regex.TDFA.ByteString" execute 2 regex-tdfa)
# this one needs type signatures to work
# check_haskell_module_exists("Control.DeepSeq" deepseq 2 deepseq)
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer/CoreTypes.hs
--- a/gameServer/CoreTypes.hs Thu Aug 11 23:05:14 2016 +0300
+++ b/gameServer/CoreTypes.hs Sun Dec 17 00:09:24 2017 +0100
@@ -311,8 +311,8 @@
True
False
"http://www.hedgewars.org/
"
- "Hedgewars 0.9.22 is out! Please update. Download page here
"
- 51 -- latestReleaseVersion
+ "Hedgewars 0.9.23 is out! Please update. Download page here
"
+ 53 -- latestReleaseVersion
41 -- earliestCompatibleVersion
46631
""
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer/EngineInteraction.hs
--- a/gameServer/EngineInteraction.hs Thu Aug 11 23:05:14 2016 +0300
+++ b/gameServer/EngineInteraction.hs Sun Dec 17 00:09:24 2017 +0100
@@ -44,26 +44,20 @@
import Utils
#if defined(OFFICIAL_SERVER)
-{-
- this is snippet from http://stackoverflow.com/questions/10043102/how-to-catch-the-decompress-ioerror
- because standard 'catch' doesn't seem to catch decompression errors for some reason
--}
import qualified Codec.Compression.Zlib.Internal as ZI
import qualified Codec.Compression.Zlib as Z
-decompressWithoutExceptions :: BL.ByteString -> Either String BL.ByteString
-decompressWithoutExceptions = finalise
- . ZI.foldDecompressStream cons nil err
- . ZI.decompressWithErrors ZI.zlibFormat ZI.defaultDecompressParams
- where err _ msg = Left msg
- nil = Right []
- cons chunk = right (chunk :)
- finalise = right BL.fromChunks
-{- end snippet -}
+decompressWithoutExceptions :: BL.ByteString -> BL.ByteString
+decompressWithoutExceptions = BL.fromChunks . ZI.foldDecompressStreamWithInput chunk end err decomp
+ where
+ decomp = ZI.decompressST ZI.zlibFormat ZI.defaultDecompressParams
+ chunk = (:)
+ end _ = []
+ err = const $ [BW.empty]
#endif
toEngineMsg :: B.ByteString -> B.ByteString
-toEngineMsg msg = B.pack $ Base64.encode (fromIntegral (BW.length msg) : BW.unpack msg)
+toEngineMsg msg = Base64.encode (fromIntegral (BW.length msg) `BW.cons` msg)
{-fromEngineMsg :: B.ByteString -> Maybe B.ByteString
@@ -85,15 +79,15 @@
checkNetCmd :: [Word8] -> B.ByteString -> (B.ByteString, B.ByteString, Maybe (Maybe B.ByteString))
checkNetCmd teamsIndexes msg = check decoded
where
- decoded = liftM (splitMessages . BW.pack) $ Base64.decode $ B.unpack msg
- check Nothing = (B.empty, B.empty, Nothing)
- check (Just msgs) = let (a, b) = (filter isLegal msgs, filter isNonEmpty a) in (encode a, encode b, lft a)
- encode = B.pack . Base64.encode . BW.unpack . B.concat
+ decoded = liftM splitMessages $ Base64.decode msg
+ check (Left _) = (B.empty, B.empty, Nothing)
+ check (Right msgs) = let (a, b) = (filter isLegal msgs, filter isNonEmpty a) in (encode a, encode b, lft a)
+ encode = Base64.encode . B.concat
isLegal m = (B.length m > 1) && (flip Set.member legalMessages . B.head . B.tail $ m) && not (isMalformed (B.head m) (B.tail m))
lft = foldr l Nothing
l m n = let m' = B.head $ B.tail m; tst = flip Set.member in
if not $ tst timedMessages m' then n
- else if '+' /= m' then Just Nothing else Just . Just . B.pack . Base64.encode . BW.unpack $ m
+ else if '+' /= m' then Just Nothing else Just . Just . Base64.encode $ m
isNonEmpty = (/=) '+' . B.head . B.tail
legalMessages = Set.fromList $ "M#+LlRrUuDdZzAaSjJ,NpPwtgfhbc12345" ++ slotMessages
slotMessages = "\128\129\130\131\132\133\134\135\136\137\138"
@@ -187,13 +181,10 @@
by200 m = Just $ L.splitAt 200 m
unpackDrawnMap :: B.ByteString -> BL.ByteString
-unpackDrawnMap = either (const BL.empty) id
- . decompressWithoutExceptions
- . BL.pack
- . L.drop 4
- . fromMaybe []
+unpackDrawnMap = either
+ (const BL.empty)
+ (decompressWithoutExceptions . BL.pack . drop 4 . BW.unpack)
. Base64.decode
- . B.unpack
compressWithLength :: BL.ByteString -> BL.ByteString
compressWithLength b = BL.drop 8 . encode . runPut $ do
@@ -201,9 +192,8 @@
mapM_ putWord8 $ BW.unpack $ BL.toStrict $ Z.compress b
packDrawnMap :: BL.ByteString -> B.ByteString
-packDrawnMap = B.pack
- . Base64.encode
- . BW.unpack
+packDrawnMap =
+ Base64.encode
. BL.toStrict
. compressWithLength
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer/HWProtoCore.hs
--- a/gameServer/HWProtoCore.hs Thu Aug 11 23:05:14 2016 +0300
+++ b/gameServer/HWProtoCore.hs Sun Dec 17 00:09:24 2017 +0100
@@ -40,7 +40,7 @@
handleCmd ("QUIT" : xs) = return [ByeClient msg]
where
- msg = if not $ null xs then head xs else loc "bye"
+ msg = if not $ null xs then "User quit: " `B.append` (head xs) else loc "bye"
handleCmd ["PONG"] = do
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer/HWProtoInRoomState.hs
--- a/gameServer/HWProtoInRoomState.hs Thu Aug 11 23:05:14 2016 +0300
+++ b/gameServer/HWProtoInRoomState.hs Sun Dec 17 00:09:24 2017 +0100
@@ -111,7 +111,6 @@
clChan <- thisClientChans
othChans <- roomOthersChans
roomChans <- roomClientsChans
- let isRegistered = (<) 0 . B.length . webPassword $ cl
teamColor <-
if clientProto cl < 42 then
return color
@@ -123,7 +122,7 @@
minimum [hhnum $ head roomTeams, canAddNumber roomTeams]
else
defaultHedgehogsNumber rm
- let newTeam = clNick `seq` TeamInfo clNick tName teamColor grave fort voicepack flag isRegistered dif hhNum (hhsList hhsInfo)
+ let newTeam = clNick `seq` TeamInfo clNick tName teamColor grave fort voicepack flag (isRegistered cl) dif hhNum (hhsList hhsInfo)
return $
if not . null . drop (teamsNumberLimit rm - 1) $ roomTeams then
[Warning $ loc "too many teams"]
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer/HWProtoLobbyState.hs
--- a/gameServer/HWProtoLobbyState.hs Thu Aug 11 23:05:14 2016 +0300
+++ b/gameServer/HWProtoLobbyState.hs Sun Dec 17 00:09:24 2017 +0100
@@ -83,7 +83,7 @@
let chans = map sendChan (cl : jRoomClients)
let isBanned = host cl `elem` roomBansList jRoom
let clTeams =
- if (clientProto cl >= 48) && (isJust $ gameInfo jRoom) then
+ if (clientProto cl >= 48) && (isJust $ gameInfo jRoom) && isRegistered cl then
filter (\t -> teamowner t == nick cl) . teamsAtStart . fromJust $ gameInfo jRoom
else
[]
@@ -95,7 +95,7 @@
[Warning $ loc "Room version incompatible to your hedgewars version"]
else if isRestrictedJoins jRoom && not (hasSuperPower cl) then
[Warning $ loc "Joining restricted"]
- else if isRegisteredOnly jRoom && (B.null . webPassword $ cl) && not (isAdministrator cl) then
+ else if isRegisteredOnly jRoom && (not $ isRegistered cl) && not (isAdministrator cl) then
[Warning $ loc "Registered users only"]
else if isBanned then
[Warning $ loc "You are banned in this room"]
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer/NetRoutines.hs
--- a/gameServer/NetRoutines.hs Thu Aug 11 23:05:14 2016 +0300
+++ b/gameServer/NetRoutines.hs Sun Dec 17 00:09:24 2017 +0100
@@ -25,11 +25,8 @@
import Control.Monad
import Data.Unique
import qualified Codec.Binary.Base64 as Base64
-import qualified Data.ByteString as BW
-import qualified Data.ByteString.Char8 as B
import qualified Control.Exception as E
import System.Entropy
-import Data.Either
-----------------------------
import CoreTypes
import Utils
@@ -48,7 +45,7 @@
sendChan' <- newChan
uid <- newUnique
- salt <- liftM (B.pack . Base64.encode . BW.unpack) $ hGetEntropy ch 18
+ salt <- liftM Base64.encode $ hGetEntropy ch 18
let newClient =
(ClientInfo
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer/OfficialServer/checker.hs
--- a/gameServer/OfficialServer/checker.hs Thu Aug 11 23:05:14 2016 +0300
+++ b/gameServer/OfficialServer/checker.hs Sun Dec 17 00:09:24 2017 +0100
@@ -37,6 +37,7 @@
import qualified Codec.Binary.Base64 as Base64
import System.Process
import Data.Maybe
+import Data.Either
import qualified Data.List as L
#if !defined(mingw32_HOST_OS)
import System.Posix
@@ -54,7 +55,7 @@
deriving Show
serverAddress = "netserver.hedgewars.org"
-protocolNumber = "51"
+protocolNumber = "53"
getLines :: Handle -> IO [B.ByteString]
getLines h = g
@@ -92,7 +93,7 @@
checkReplay home exe prefix coreChan msgs = do
tempDir <- getTemporaryDirectory
(fileName, h) <- openBinaryTempFile tempDir "checker-demo"
- B.hPut h . BW.pack . concat . map (fromMaybe [] . Base64.decode . B.unpack) $ msgs
+ B.hPut h . B.concat . map (either (const B.empty) id . Base64.decode) $ msgs
hFlush h
hClose h
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer/Utils.hs
--- a/gameServer/Utils.hs Thu Aug 11 23:05:14 2016 +0300
+++ b/gameServer/Utils.hs Sun Dec 17 00:09:24 2017 +0100
@@ -116,6 +116,8 @@
, (50, "0.9.22-dev")
, (51, "0.9.22")
, (52, "0.9.23-dev")
+ , (53, "0.9.23")
+ , (54, "0.9.24-dev")
]
askFromConsole :: B.ByteString -> IO B.ByteString
@@ -245,3 +247,6 @@
where
sc c | isAlphaNum c = c
| otherwise = '_'
+
+isRegistered :: ClientInfo -> Bool
+isRegistered = (<) 0 . B.length . webPassword
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer/hedgewars-server.cabal
--- a/gameServer/hedgewars-server.cabal Thu Aug 11 23:05:14 2016 +0300
+++ b/gameServer/hedgewars-server.cabal Sun Dec 17 00:09:24 2017 +0100
@@ -5,7 +5,7 @@
Homepage: http://www.hedgewars.org/
License: GPL-2
Author: unC0Rr
-Maintainer: unC0Rr@hedgewars.org
+Maintainer: a.korotaev@hedgewars.org
Category: Game
Build-type: Simple
Cabal-version: >=1.10
@@ -16,8 +16,9 @@
default-language: Haskell2010
+-- Don't forget to update INSTALL.md when you change these dependencies!
Build-depends:
- base >= 4.3,
+ base >= 4.8,
containers,
vector,
bytestring,
@@ -25,14 +26,15 @@
random,
time,
mtl >= 2,
- dataenc,
+ sandi,
hslogger,
process,
deepseq,
utf8-string,
SHA,
entropy,
- zlib >= 0.5.3 && < 0.6
+ zlib >= 0.5.3 && < 0.6,
+ regex-tdfa
if !os(windows)
build-depends: unix
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/Cargo.toml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/Cargo.toml Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,13 @@
+[package]
+name = "hedgewars-server"
+version = "0.0.1"
+authors = [ "Andrey Korotaev " ]
+
+[dependencies]
+rand = "0.3"
+mio = "0.6"
+slab = "0.4"
+netbuf = "0.4.0"
+nom = "3.2"
+env_logger = "0.4"
+log = "0.3.8"
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/src/main.rs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/src/main.rs Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,59 @@
+extern crate rand;
+extern crate mio;
+extern crate slab;
+extern crate netbuf;
+#[macro_use]
+extern crate nom;
+#[macro_use]
+extern crate log;
+extern crate env_logger;
+
+//use std::io::*;
+//use rand::Rng;
+//use std::cmp::Ordering;
+use mio::net::*;
+use mio::*;
+
+mod utils;
+mod server;
+mod protocol;
+
+fn main() {
+ env_logger::init().unwrap();
+
+ info!("Hedgewars game server, protocol {}", utils::PROTOCOL_VERSION);
+
+ let address = "0.0.0.0:46631".parse().unwrap();
+ let listener = TcpListener::bind(&address).unwrap();
+ let mut server = server::server::HWServer::new(listener, 1024, 512);
+
+ let poll = Poll::new().unwrap();
+ server.register(&poll).unwrap();
+
+ let mut events = Events::with_capacity(1024);
+
+ loop {
+ poll.poll(&mut events, None).unwrap();
+
+ for event in events.iter() {
+ if event.readiness() & Ready::readable() == Ready::readable() {
+ match event.token() {
+ utils::SERVER => server.accept(&poll).unwrap(),
+ Token(tok) => server.client_readable(&poll, tok).unwrap(),
+ }
+ }
+ if event.readiness() & Ready::writable() == Ready::writable() {
+ match event.token() {
+ utils::SERVER => unreachable!(),
+ Token(tok) => server.client_writable(&poll, tok).unwrap(),
+ }
+ }
+// if event.kind().is_hup() || event.kind().is_error() {
+// match event.token() {
+// utils::SERVER => unreachable!(),
+// Token(tok) => server.client_error(&poll, tok).unwrap(),
+// }
+// }
+ }
+ }
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/src/protocol/messages.rs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/src/protocol/messages.rs Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,138 @@
+use server::coretypes::{ServerVar, GameCfg, TeamInfo, HedgehogInfo};
+use std;
+use std::ops;
+use std::convert::From;
+
+#[derive(PartialEq, Debug)]
+pub enum HWProtocolMessage {
+ // core
+ Ping,
+ Pong,
+ Quit(Option),
+ //Cmd(String, Vec),
+ Global(String),
+ Watch(String),
+ ToggleServerRegisteredOnly,
+ SuperPower,
+ Info(String),
+ // not entered state
+ Nick(String),
+ Proto(u32),
+ Password(String, String),
+ Checker(u32, String, String),
+ // lobby
+ List,
+ Chat(String),
+ CreateRoom(String, Option),
+ Join(String, Option),
+ Follow(String),
+ Rnd(Vec),
+ Kick(String),
+ Ban(String, String, u32),
+ BanIP(String, String, u32),
+ BanNick(String, String, u32),
+ BanList,
+ Unban(String),
+ SetServerVar(ServerVar),
+ GetServerVar,
+ RestartServer,
+ Stats,
+ // in room
+ Part(Option),
+ Cfg(GameCfg),
+ AddTeam(TeamInfo),
+ RemoveTeam(String),
+ SetHedgehogsNumber(String, u8),
+ SetTeamColor(String, u8),
+ ToggleReady,
+ StartGame,
+ EngineMessage(String),
+ RoundFinished,
+ ToggleRestrictJoin,
+ ToggleRestrictTeams,
+ ToggleRegisteredOnly,
+ RoomName(String),
+ Delegate(String),
+ TeamChat(String),
+ MaxTeams(u8),
+ Fix,
+ Unfix,
+ Greeting(String),
+ CallVote(Option<(String, Option)>),
+ Vote(String),
+ ForceVote(String),
+ Save(String, String),
+ Delete(String),
+ SaveRoom(String),
+ LoadRoom(String),
+ Malformed,
+ Empty,
+}
+
+pub enum HWServerMessage<'a> {
+ Ping,
+ Pong,
+ Bye(&'a str),
+ Nick(&'a str),
+ LobbyLeft(&'a str),
+ LobbyJoined(&'a [&'a str]),
+ ChatMsg(&'a str, &'a str),
+ ClientFlags(&'a str, &'a [&'a str]),
+
+ Warning(&'a str),
+ Connected(u32),
+ Unreachable,
+}
+
+fn construct_message(msg: & [&str]) -> String {
+ let mut m = String::with_capacity(64);
+
+ for s in msg {
+ m.push_str(s);
+ m.push('\n');
+ }
+ m.push('\n');
+
+ m
+}
+
+impl<'a> HWServerMessage<'a> {
+ pub fn to_raw_protocol(&self) -> String {
+ match self {
+ &HWServerMessage::Ping
+ => "PING\n\n".to_string(),
+ &HWServerMessage::Pong
+ => "PONG\n\n".to_string(),
+ &HWServerMessage::Connected(protocol_version)
+ => construct_message(&[
+ "CONNECTED",
+ "Hedgewars server http://www.hedgewars.org/",
+ &protocol_version.to_string()
+ ]),
+ &HWServerMessage::Bye(msg)
+ => construct_message(&["BYE", &msg]),
+ &HWServerMessage::Nick(nick)
+ => construct_message(&["NICK", &nick]),
+ &HWServerMessage::LobbyLeft(nick)
+ => construct_message(&["LOBBY_LEFT", &nick]),
+ &HWServerMessage::LobbyJoined(nicks)
+ => {
+ let mut v = vec!["LOBBY:JOINED"];
+ v.extend_from_slice(nicks);
+ construct_message(&v)
+ },
+ &HWServerMessage::ClientFlags(flags, nicks)
+ => {
+ let mut v = vec!["CLIENT_FLAGS"];
+ v.push(flags);
+ v.extend_from_slice(nicks);
+ construct_message(&v)
+ },
+ &HWServerMessage::ChatMsg(nick, msg)
+ => construct_message(&["CHAT", &nick, &msg]),
+ &HWServerMessage::Warning(msg)
+ => construct_message(&["WARNING", &msg]),
+ _ => construct_message(&["ERROR", "UNIMPLEMENTED"]),
+ }
+ }
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/src/protocol/mod.rs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/src/protocol/mod.rs Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,42 @@
+use netbuf;
+use std::io::Read;
+use std::io::Result;
+use nom::IResult;
+
+pub mod messages;
+mod parser;
+
+pub struct ProtocolDecoder {
+ buf: netbuf::Buf,
+ consumed: usize,
+}
+
+impl ProtocolDecoder {
+ pub fn new() -> ProtocolDecoder {
+ ProtocolDecoder {
+ buf: netbuf::Buf::new(),
+ consumed: 0,
+ }
+ }
+
+ pub fn read_from(&mut self, stream: &mut R) -> Result {
+ self.buf.read_from(stream)
+ }
+
+ pub fn extract_messages(&mut self) -> Vec {
+ let parse_result = parser::extract_messages(&self.buf[..]);
+ match parse_result {
+ IResult::Done(tail, msgs) => {
+ self.consumed = self.buf.len() - self.consumed - tail.len();
+ msgs
+ },
+ IResult::Incomplete(_) => unreachable!(),
+ IResult::Error(_) => unreachable!(),
+ }
+ }
+
+ pub fn sweep(&mut self) {
+ self.buf.consume(self.consumed);
+ self.consumed = 0;
+ }
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/src/protocol/parser.rs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/src/protocol/parser.rs Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,141 @@
+use nom::*;
+
+use std::str;
+use std::str::FromStr;
+use super::messages::HWProtocolMessage;
+use super::messages::HWProtocolMessage::*;
+
+named!(end_of_message, tag!("\n\n"));
+named!(str_line<&[u8], &str>, map_res!(not_line_ending, str::from_utf8));
+named!( a_line<&[u8], String>, map!(str_line, String::from));
+named!( u8_line<&[u8], u8>, map_res!(str_line, FromStr::from_str));
+named!(u32_line<&[u8], u32>, map_res!(str_line, FromStr::from_str));
+named!(opt_param<&[u8], Option >, opt!(map!(flat_map!(preceded!(eol, str_line), non_empty), String::from)));
+
+named!(basic_message<&[u8], HWProtocolMessage>, alt!(
+ do_parse!(tag!("PING") >> (Ping))
+ | do_parse!(tag!("PONG") >> (Pong))
+ | do_parse!(tag!("LIST") >> (List))
+ | do_parse!(tag!("BANLIST") >> (BanList))
+ | do_parse!(tag!("GET_SERVER_VAR") >> (GetServerVar))
+ | do_parse!(tag!("TOGGLE_READY") >> (ToggleReady))
+ | do_parse!(tag!("START_GAME") >> (StartGame))
+ | do_parse!(tag!("ROUNDFINISHED") >> (RoundFinished))
+ | do_parse!(tag!("TOGGLE_RESTRICT_JOINS") >> (ToggleRestrictJoin))
+ | do_parse!(tag!("TOGGLE_RESTRICT_TEAMS") >> (ToggleRestrictTeams))
+ | do_parse!(tag!("TOGGLE_REGISTERED_ONLY") >> (ToggleRegisteredOnly))
+));
+
+named!(one_param_message<&[u8], HWProtocolMessage>, alt!(
+ do_parse!(tag!("NICK") >> eol >> n: a_line >> (Nick(n)))
+ | do_parse!(tag!("INFO") >> eol >> n: a_line >> (Info(n)))
+ | do_parse!(tag!("CHAT") >> eol >> m: a_line >> (Chat(m)))
+ | do_parse!(tag!("FOLLOW") >> eol >> n: a_line >> (Follow(n)))
+ | do_parse!(tag!("KICK") >> eol >> n: a_line >> (Kick(n)))
+ | do_parse!(tag!("UNBAN") >> eol >> n: a_line >> (Unban(n)))
+ | do_parse!(tag!("EM") >> eol >> m: a_line >> (EngineMessage(m)))
+ | do_parse!(tag!("TEAMCHAT") >> eol >> m: a_line >> (TeamChat(m)))
+ | do_parse!(tag!("ROOM_NAME") >> eol >> n: a_line >> (RoomName(n)))
+ | do_parse!(tag!("REMOVE_TEAM") >> eol >> n: a_line >> (RemoveTeam(n)))
+
+ | do_parse!(tag!("PROTO") >> eol >> d: u32_line >> (Proto(d)))
+
+ | do_parse!(tag!("QUIT") >> msg: opt_param >> (Quit(msg)))
+));
+
+named!(cmd_message<&[u8], HWProtocolMessage>, preceded!(tag!("CMD\n"), alt!(
+ do_parse!(tag_no_case!("STATS") >> (Stats))
+ | do_parse!(tag_no_case!("FIX") >> (Fix))
+ | do_parse!(tag_no_case!("UNFIX") >> (Unfix))
+ | do_parse!(tag_no_case!("RESTART_SERVER") >> eol >> tag!("YES") >> (RestartServer))
+ | do_parse!(tag_no_case!("REGISTERED_ONLY") >> (ToggleServerRegisteredOnly))
+ | do_parse!(tag_no_case!("SUPER_POWER") >> (SuperPower))
+ | do_parse!(tag_no_case!("PART") >> eol >> m: opt_param >> (Quit(m)))
+ | do_parse!(tag_no_case!("QUIT") >> eol >> m: opt_param >> (Part(m)))
+ | do_parse!(tag_no_case!("DELEGATE") >> eol >> n: a_line >> (Delegate(n)))
+ | do_parse!(tag_no_case!("SAVEROOM") >> eol >> r: a_line >> (SaveRoom(r)))
+ | do_parse!(tag_no_case!("LOADROOM") >> eol >> r: a_line >> (LoadRoom(r)))
+ | do_parse!(tag_no_case!("DELETE") >> eol >> r: a_line >> (Delete(r)))
+ | do_parse!(tag_no_case!("GLOBAL") >> eol >> m: a_line >> (Global(m)))
+ | do_parse!(tag_no_case!("WATCH") >> eol >> i: a_line >> (Watch(i)))
+ | do_parse!(tag_no_case!("GREETING") >> eol >> m: a_line >> (Greeting(m)))
+ | do_parse!(tag_no_case!("VOTE") >> eol >> m: a_line >> (Vote(m)))
+ | do_parse!(tag_no_case!("FORCE") >> eol >> m: a_line >> (ForceVote(m)))
+ | do_parse!(tag_no_case!("INFO") >> eol >> n: a_line >> (Info(n)))
+ | do_parse!(tag_no_case!("MAXTEAMS") >> eol >> n: u8_line >> (MaxTeams(n)))
+)));
+
+named!(complex_message<&[u8], HWProtocolMessage>, alt!(
+ do_parse!(tag!("PASSWORD") >> eol >>
+ p: a_line >> eol >>
+ s: a_line >>
+ (Password(p, s)))
+ | do_parse!(tag!("CHECKER") >> eol >>
+ i: u32_line >> eol >>
+ n: a_line >> eol >>
+ p: a_line >>
+ (Checker(i, n, p)))
+ | do_parse!(tag!("CREATE_ROOM") >> eol >>
+ n: a_line >>
+ p: opt_param >>
+ (CreateRoom(n, p)))
+ | do_parse!(tag!("JOIN") >> eol >>
+ n: a_line >>
+ p: opt_param >>
+ (Join(n, p)))
+ | do_parse!(tag!("BAN") >> eol >>
+ n: a_line >> eol >>
+ r: a_line >> eol >>
+ t: u32_line >>
+ (Ban(n, r, t)))
+ | do_parse!(tag!("BAN_IP") >> eol >>
+ n: a_line >> eol >>
+ r: a_line >> eol >>
+ t: u32_line >>
+ (BanIP(n, r, t)))
+ | do_parse!(tag!("BAN_NICK") >> eol >>
+ n: a_line >> eol >>
+ r: a_line >> eol >>
+ t: u32_line >>
+ (BanNick(n, r, t)))
+));
+
+named!(malformed_message<&[u8], HWProtocolMessage>,
+ do_parse!(separated_list!(eol, a_line) >> (Malformed)));
+
+named!(empty_message<&[u8], HWProtocolMessage>,
+ do_parse!(alt!(end_of_message | eol) >> (Empty)));
+
+named!(message<&[u8], HWProtocolMessage>, alt!(terminated!(
+ alt!(
+ basic_message
+ | one_param_message
+ | cmd_message
+ | complex_message
+ ), end_of_message
+ )
+ | terminated!(malformed_message, end_of_message)
+ | empty_message
+ )
+);
+
+named!(pub extract_messages<&[u8], Vec >, many0!(complete!(message)));
+
+#[test]
+fn parse_test() {
+ assert_eq!(message(b"PING\n\n"), IResult::Done(&b""[..], Ping));
+ assert_eq!(message(b"START_GAME\n\n"), IResult::Done(&b""[..], StartGame));
+ assert_eq!(message(b"NICK\nit's me\n\n"), IResult::Done(&b""[..], Nick("it's me".to_string())));
+ assert_eq!(message(b"PROTO\n51\n\n"), IResult::Done(&b""[..], Proto(51)));
+ assert_eq!(message(b"QUIT\nbye-bye\n\n"), IResult::Done(&b""[..], Quit(Some("bye-bye".to_string()))));
+ assert_eq!(message(b"QUIT\n\n"), IResult::Done(&b""[..], Quit(None)));
+ assert_eq!(message(b"CMD\nwatch\ndemo\n\n"), IResult::Done(&b""[..], Watch("demo".to_string())));
+ assert_eq!(message(b"BAN\nme\nbad\n77\n\n"), IResult::Done(&b""[..], Ban("me".to_string(), "bad".to_string(), 77)));
+
+ assert_eq!(extract_messages(b"QUIT\n1\n2\n\n"), IResult::Done(&b""[..], vec![Malformed]));
+
+ assert_eq!(extract_messages(b"PING\n\nPING\n\nP"), IResult::Done(&b"P"[..], vec![Ping, Ping]));
+ assert_eq!(extract_messages(b"SING\n\nPING\n\n"), IResult::Done(&b""[..], vec![Malformed, Ping]));
+ assert_eq!(extract_messages(b"\n\n\n\nPING\n\n"), IResult::Done(&b""[..], vec![Empty, Empty, Ping]));
+ assert_eq!(extract_messages(b"\n\n\nPING\n\n"), IResult::Done(&b""[..], vec![Empty, Empty, Ping]));
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/src/server/actions.rs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/src/server/actions.rs Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,92 @@
+use mio;
+use std::io::Write;
+use std::io;
+
+use super::server::HWServer;
+use super::server::HWRoom;
+use protocol::messages::HWProtocolMessage;
+use protocol::messages::HWServerMessage::*;
+use super::handlers;
+
+pub enum Action {
+ SendMe(String),
+ SendAllButMe(String),
+ RemoveClient,
+ ByeClient(String),
+ ReactProtocolMessage(HWProtocolMessage),
+ CheckRegistered,
+ JoinLobby,
+ AddRoom(String, Option),
+ Warn(String),
+}
+
+use self::Action::*;
+
+pub fn run_action(server: &mut HWServer, token: usize, poll: &mio::Poll, action: Action) {
+ match action {
+ SendMe(msg) =>
+ server.send(token, &msg),
+ SendAllButMe(msg) => {
+ for (_i, c) in server.clients.iter_mut() {
+ if c.id != token {
+ c.send_string(&msg)
+ }
+ }
+ },
+ ByeClient(msg) => {
+ server.react(token, poll, vec![
+ SendMe(Bye(&msg).to_raw_protocol()),
+ RemoveClient,
+ ]);
+ },
+ RemoveClient => {
+ server.clients[token].deregister(poll);
+ server.clients.remove(token);
+ },
+ ReactProtocolMessage(msg) =>
+ handlers::handle(server, token, poll, msg),
+ CheckRegistered =>
+ if server.clients[token].protocol_number > 0 && server.clients[token].nick != "" {
+ server.react(token, poll, vec![
+ JoinLobby,
+ ]);
+ },
+ JoinLobby => {
+ server.clients[token].room_id = Some(server.lobby_id);
+
+ let joined_msg;
+ {
+ let mut lobby_nicks: Vec<&str> = Vec::new();
+ for (_, c) in server.clients.iter() {
+ if c.room_id.is_some() {
+ lobby_nicks.push(&c.nick);
+ }
+ }
+ joined_msg = LobbyJoined(&lobby_nicks).to_raw_protocol();
+ }
+ let everyone_msg = LobbyJoined(&[&server.clients[token].nick]).to_raw_protocol();
+ server.react(token, poll, vec![
+ SendAllButMe(everyone_msg),
+ SendMe(joined_msg),
+ ]);
+ },
+ AddRoom(name, password) => {
+ let room_id = server.rooms.insert(HWRoom::new());
+ {
+ let r = &mut server.rooms[room_id];
+ let c = &mut server.clients[token];
+ r.name = name;
+ r.password = password;
+ r.id = room_id.clone();
+ r.ready_players_number = 1;
+ r.protocol_number = c.protocol_number;
+ c.room_id = Some(room_id);
+ }
+
+ },
+ Warn(msg) => {
+ run_action(server, token, poll, SendMe(Warning(&msg).to_raw_protocol()));
+ }
+ //_ => unimplemented!(),
+ }
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/src/server/client.rs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/src/server/client.rs Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,97 @@
+use mio::net::TcpStream;
+use mio::*;
+use std::io::Write;
+use std::io;
+use netbuf;
+
+use utils;
+use protocol::ProtocolDecoder;
+use protocol::messages::*;
+use super::actions::Action::*;
+use super::actions::Action;
+
+pub struct HWClient {
+ sock: TcpStream,
+ decoder: ProtocolDecoder,
+ buf_out: netbuf::Buf,
+
+ pub id: usize,
+ pub room_id: Option,
+ pub nick: String,
+ pub protocol_number: u32,
+ pub is_master: bool,
+ pub is_ready: bool,
+ pub is_joined_mid_game: bool,
+}
+
+impl HWClient {
+ pub fn new(sock: TcpStream) -> HWClient {
+ HWClient {
+ sock: sock,
+ decoder: ProtocolDecoder::new(),
+ buf_out: netbuf::Buf::new(),
+ room_id: None,
+ id: 0,
+
+ nick: String::new(),
+ protocol_number: 0,
+ is_master: false,
+ is_ready: false,
+ is_joined_mid_game: false,
+ }
+ }
+
+ pub fn register(&mut self, poll: &Poll, token: Token) {
+ poll.register(&self.sock, token, Ready::readable() | Ready::writable(),
+ PollOpt::edge())
+ .ok().expect("could not register socket with event loop");
+
+ self.send_msg(HWServerMessage::Connected(utils::PROTOCOL_VERSION));
+ }
+
+ pub fn deregister(&mut self, poll: &Poll) {
+ poll.deregister(&self.sock)
+ .ok().expect("could not deregister socket");
+ }
+
+ pub fn send_raw_msg(&mut self, msg: &[u8]) {
+ self.buf_out.write(msg).unwrap();
+ self.flush();
+ }
+
+ pub fn send_string(&mut self, msg: &String) {
+ self.send_raw_msg(&msg.as_bytes());
+ }
+
+ pub fn send_msg(&mut self, msg: HWServerMessage) {
+ self.send_string(&msg.to_raw_protocol());
+ }
+
+ fn flush(&mut self) {
+ self.buf_out.write_to(&mut self.sock).unwrap();
+ self.sock.flush();
+ }
+
+ pub fn readable(&mut self, _poll: &Poll) -> Vec {
+ let v = self.decoder.read_from(&mut self.sock).unwrap();
+ debug!("Read {} bytes", v);
+ let mut response = Vec::new();
+ {
+ for msg in self.decoder.extract_messages() {
+ response.push(ReactProtocolMessage(msg));
+ }
+ }
+ self.decoder.sweep();
+ response
+ }
+
+ pub fn writable(&mut self, _poll: &Poll) -> io::Result<()> {
+ self.buf_out.write_to(&mut self.sock)?;
+
+ Ok(())
+ }
+
+ pub fn error(&mut self, _poll: &Poll) -> Vec {
+ return vec![ByeClient("Connection reset".to_string())]
+ }
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/src/server/coretypes.rs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/src/server/coretypes.rs Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,30 @@
+#[derive(PartialEq, Debug)]
+pub enum ServerVar {
+ MOTDNew(String),
+ MOTDOld(String),
+ LatestProto(u32),
+}
+
+#[derive(PartialEq, Debug)]
+pub enum GameCfg {
+
+}
+
+#[derive(PartialEq, Debug)]
+pub struct TeamInfo {
+ name: String,
+ color: u8,
+ grave: String,
+ fort: String,
+ voice_pack: String,
+ flag: String,
+ difficulty: u8,
+ hedgehogs_number: u8,
+ hedgehogs: [HedgehogInfo; 8],
+}
+
+#[derive(PartialEq, Debug)]
+pub struct HedgehogInfo {
+ name: String,
+ hat: String,
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/src/server/handlers/inroom.rs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/src/server/handlers/inroom.rs Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,13 @@
+use mio;
+
+use server::server::HWServer;
+use server::actions::Action;
+use server::actions::Action::*;
+use protocol::messages::HWProtocolMessage;
+use protocol::messages::HWServerMessage::*;
+
+pub fn handle(server: &mut HWServer, token: usize, _poll: &mio::Poll, message: HWProtocolMessage) {
+ match message {
+ _ => warn!("Unimplemented!"),
+ }
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/src/server/handlers/lobby.rs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/src/server/handlers/lobby.rs Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,39 @@
+use mio;
+
+use server::server::HWServer;
+use server::actions::Action;
+use server::actions::Action::*;
+use protocol::messages::HWProtocolMessage;
+use protocol::messages::HWServerMessage::*;
+
+pub fn handle(server: &mut HWServer, token: usize, poll: &mio::Poll, message: HWProtocolMessage) {
+ match message {
+ HWProtocolMessage::Chat(msg) => {
+ let chat_msg = ChatMsg(&server.clients[token].nick, &msg).to_raw_protocol();
+ server.react(token, poll, vec![SendAllButMe(chat_msg)]);
+ },
+ HWProtocolMessage::CreateRoom(name, password) => {
+ let room_exists = server.rooms.iter().find(|&(_, r)| r.name == name).is_some();
+ if room_exists {
+ server.react(token, poll, vec![Warn("Room exists".to_string())]);
+ } else {
+ let flags_msg = ClientFlags("+hr", &[&server.clients[token].nick]).to_raw_protocol();
+ {
+ let c = &mut server.clients[token];
+ c.is_master = true;
+ c.is_ready = true;
+ c.is_joined_mid_game = false;
+ }
+ server.react(token, poll, vec![
+ AddRoom(name, password)
+ , SendMe(flags_msg)
+ ]);
+ }
+ },
+ HWProtocolMessage::Join(name, password) => {
+
+ },
+ HWProtocolMessage::List => warn!("Deprecated LIST message received"),
+ _ => warn!("Incorrect command in lobby state"),
+ }
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/src/server/handlers/loggingin.rs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/src/server/handlers/loggingin.rs Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,23 @@
+use mio;
+
+use server::server::HWServer;
+use server::actions::Action;
+use server::actions::Action::*;
+use protocol::messages::HWProtocolMessage;
+use protocol::messages::HWServerMessage::*;
+
+pub fn handle(server: &mut HWServer, token: usize, poll: &mio::Poll, message: HWProtocolMessage) {
+ match message {
+ HWProtocolMessage::Nick(nick) =>
+ if server.clients[token].room_id == None {
+ server.react(token, poll, vec![SendMe(Nick(&nick).to_raw_protocol())]);
+ server.clients[token].nick = nick;
+ server.react(token, poll, vec![CheckRegistered]);
+ },
+ HWProtocolMessage::Proto(proto) => {
+ server.clients[token].protocol_number = proto;
+ server.react(token, poll, vec![CheckRegistered]);
+ },
+ _ => warn!("Incorrect command in logging-in state"),
+ }
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/src/server/handlers/mod.rs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/src/server/handlers/mod.rs Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,35 @@
+use mio;
+use std::io::Write;
+use std::io;
+
+use super::server::HWServer;
+use super::actions::Action;
+use super::actions::Action::*;
+use protocol::messages::HWProtocolMessage;
+use protocol::messages::HWServerMessage::*;
+
+mod loggingin;
+mod lobby;
+mod inroom;
+
+pub fn handle(server: &mut HWServer, token: usize, poll: &mio::Poll, message: HWProtocolMessage) {
+ match message {
+ HWProtocolMessage::Ping =>
+ server.react(token, poll, vec![SendMe(Pong.to_raw_protocol())]),
+ HWProtocolMessage::Quit(Some(msg)) =>
+ server.react(token, poll, vec![ByeClient("User quit: ".to_string() + &msg)]),
+ HWProtocolMessage::Quit(None) =>
+ server.react(token, poll, vec![ByeClient("User quit".to_string())]),
+ HWProtocolMessage::Malformed => warn!("Malformed/unknown message"),
+ HWProtocolMessage::Empty => warn!("Empty message"),
+ _ => {
+ if !server.clients[token].room_id.is_some() {
+ loggingin::handle(server, token, poll, message);
+ } else if server.clients[token].room_id == Some(server.lobby_id) {
+ lobby::handle(server, token, poll, message);
+ } else {
+ inroom::handle(server, token, poll, message);
+ }
+ },
+ }
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/src/server/mod.rs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/src/server/mod.rs Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,5 @@
+pub mod server;
+pub mod client;
+pub mod coretypes;
+mod actions;
+mod handlers;
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/src/server/server.rs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/src/server/server.rs Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,110 @@
+use slab;
+use mio::net::*;
+use mio::*;
+use std::io;
+
+use utils;
+use super::client::HWClient;
+use super::actions;
+
+type Slab = slab::Slab;
+
+pub struct HWServer {
+ listener: TcpListener,
+ pub clients: Slab,
+ pub rooms: Slab,
+ pub lobby_id: usize,
+}
+
+impl HWServer {
+ pub fn new(listener: TcpListener, clients_limit: usize, rooms_limit: usize) -> HWServer {
+ let mut rooms = Slab::with_capacity(rooms_limit);
+ let token = rooms.insert(HWRoom::new());
+ HWServer {
+ listener: listener,
+ clients: Slab::with_capacity(clients_limit),
+ rooms: rooms,
+ lobby_id: token,
+ }
+ }
+
+ pub fn register(&self, poll: &Poll) -> io::Result<()> {
+ poll.register(&self.listener, utils::SERVER, Ready::readable(),
+ PollOpt::edge())
+ }
+
+ pub fn accept(&mut self, poll: &Poll) -> io::Result<()> {
+ let (sock, addr) = self.listener.accept()?;
+ info!("Connected: {}", addr);
+
+ let client = HWClient::new(sock);
+ let token = self.clients.insert(client);
+
+ self.clients[token].id = token;
+ self.clients[token].register(poll, Token(token));
+
+ Ok(())
+ }
+
+ pub fn client_readable(&mut self, poll: &Poll,
+ token: usize) -> io::Result<()> {
+ let actions;
+ {
+ actions = self.clients[token].readable(poll);
+ }
+
+ self.react(token, poll, actions);
+
+ Ok(())
+ }
+
+ pub fn client_writable(&mut self, poll: &Poll,
+ token: usize) -> io::Result<()> {
+ self.clients[token].writable(poll)?;
+
+ Ok(())
+ }
+
+ pub fn client_error(&mut self, poll: &Poll,
+ token: usize) -> io::Result<()> {
+ let actions;
+ {
+ actions = self.clients[token].error(poll);
+ }
+
+ self.react(token, poll, actions);
+
+ Ok(())
+ }
+
+ pub fn send(&mut self, token: usize, msg: &String) {
+ self.clients[token].send_string(msg);
+ }
+
+ pub fn react(&mut self, token: usize, poll: &Poll, actions: Vec) {
+ for action in actions {
+ actions::run_action(self, token, poll, action);
+ }
+ }
+}
+
+
+pub struct HWRoom {
+ pub id: usize,
+ pub name: String,
+ pub password: Option,
+ pub protocol_number: u32,
+ pub ready_players_number: u8,
+}
+
+impl HWRoom {
+ pub fn new() -> HWRoom {
+ HWRoom {
+ id: 0,
+ name: String::new(),
+ password: None,
+ protocol_number: 0,
+ ready_players_number: 0,
+ }
+ }
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 gameServer2/src/utils.rs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer2/src/utils.rs Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,4 @@
+use mio;
+
+pub const PROTOCOL_VERSION : u32 = 3;
+pub const SERVER: mio::Token = mio::Token(1000000000 + 0);
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/CMakeLists.txt
--- a/hedgewars/CMakeLists.txt Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/CMakeLists.txt Sun Dec 17 00:09:24 2017 +0100
@@ -1,10 +1,10 @@
enable_language(Pascal)
find_package(SDL2 REQUIRED)
-find_package(SDL2_image REQUIRED)
-find_package(SDL2_net REQUIRED)
-find_package(SDL2_ttf REQUIRED)
-find_package(SDL2_mixer REQUIRED)
+find_package(SDL2_image 2 REQUIRED)
+find_package(SDL2_net 2 REQUIRED)
+find_package(SDL2_ttf 2 REQUIRED)
+find_package(SDL2_mixer 2 REQUIRED)
include(CheckLibraryExists)
include(${CMAKE_MODULE_PATH}/utils.cmake)
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/PNGh.pas
--- a/hedgewars/PNGh.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/PNGh.pas Sun Dec 17 00:09:24 2017 +0100
@@ -79,6 +79,7 @@
procedure PngFlushData(png_ptr: png_structp); cdecl;
begin
+ png_ptr:= png_ptr;
end;
procedure png_init_pascal_io(png_ptr: png_structp; pf : PFile);
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/SDLh.pas
--- a/hedgewars/SDLh.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/SDLh.pas Sun Dec 17 00:09:24 2017 +0100
@@ -27,6 +27,9 @@
{$IFDEF FREEBSD}
{$DEFINE UNIX}
{$ENDIF}
+{$IFDEF OPENBSD}
+ {$DEFINE UNIX}
+{$ENDIF}
{$IFDEF DARWIN}
{$DEFINE UNIX}
{$ENDIF}
@@ -74,6 +77,9 @@
///////////////////// CONSTANT DEFINITIONS /////////////////////
/////////////////////////////////////////////////////////////////
+ SDL_FALSE = 0;
+ SDL_TRUE = 1;
+
// SDL_Init() flags
SDL_INIT_TIMER = $00000001;
SDL_INIT_AUDIO = $00000010;
@@ -94,7 +100,8 @@
AUDIO_S16SYS = {$IFDEF ENDIAN_LITTLE}AUDIO_S16LSB{$ELSE}AUDIO_S16MSB{$ENDIF};
// default audio format from SDL_mixer.h
- MIX_DEFAULT_FORMAT = AUDIO_S16SYS;
+ //MIX_DEFAULT_FORMAT = AUDIO_S16SYS;
+ MIX_DEFAULT_FORMAT = {$IFDEF ENDIAN_LITTLE}AUDIO_S16LSB{$ELSE}AUDIO_S16MSB{$ENDIF};
SDL_BUTTON_LEFT = 1;
SDL_BUTTON_MIDDLE = 2;
@@ -1054,7 +1061,7 @@
procedure SDL_FreeSurface(Surface: PSDL_Surface); cdecl; external SDLLibName;
function SDL_SetColorKey(surface: PSDL_Surface; flag, key: LongWord): LongInt; cdecl; external SDLLibName;
function SDL_SetAlpha(surface: PSDL_Surface; flag, key: LongWord): LongInt; cdecl; external SDLLibName;
-function SDL_ConvertSurface(src: PSDL_Surface; fmt: PSDL_PixelFormat; flags: LongInt): PSDL_Surface; cdecl; external SDLLibName;
+function SDL_ConvertSurface(src: PSDL_Surface; fmt: PSDL_PixelFormat; flags: LongWord): PSDL_Surface; cdecl; external SDLLibName;
function SDL_UpperBlit(src: PSDL_Surface; srcrect: PSDL_Rect; dst: PSDL_Surface; dstrect: PSDL_Rect): LongInt; cdecl; external SDLLibName;
function SDL_FillRect(dst: PSDL_Surface; dstrect: PSDL_Rect; color: LongWord): LongInt; cdecl; external SDLLibName;
@@ -1107,6 +1114,7 @@
function SDL_SetHint(name, value: PChar): Boolean; cdecl; external SDLLibName;
procedure SDL_StartTextInput; cdecl; external SDLLibName;
procedure SDL_StopTextInput; cdecl; external SDLLibName;
+procedure SDL_FlushEvent(eventType: LongWord); cdecl; external SDLLibName;
function SDL_PeepEvents(event: PSDL_Event; numevents: LongInt; action: TSDL_eventaction; minType, maxType: LongWord): LongInt; cdecl; external SDLLibName;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/adler32.pas
--- a/hedgewars/adler32.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/adler32.pas Sun Dec 17 00:09:24 2017 +0100
@@ -65,7 +65,7 @@
Also, the structure was removed to simplify C conversion
*)
-function Adler32Update (var adler : longint; Msg :Pointer; Len :longint ) : longint;
+function Adler32Update (adler : longint; Msg :Pointer; Len :longint ) : longint;
implementation
@@ -123,7 +123,7 @@
end;
*)
-function Adler32Update(var adler:longint; Msg: Pointer; Len :longint) : longint;
+function Adler32Update(adler:longint; Msg: Pointer; Len :longint) : longint;
{-update Adler32 with Msg data}
const
BASE = 65521; {max. prime < 65536 }
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/avwrapper/CMakeLists.txt
--- a/hedgewars/avwrapper/CMakeLists.txt Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/avwrapper/CMakeLists.txt Sun Dec 17 00:09:24 2017 +0100
@@ -3,7 +3,9 @@
include_directories(${LIBAV_INCLUDE_DIR})
add_library(avwrapper avwrapper.c)
-#TODO: find good VERSION and SOVERSION values
+set_target_properties(avwrapper PROPERTIES
+ VERSION 1.0
+ SOVERSION 1.0)
target_link_libraries(avwrapper ${LIBAV_LIBRARIES})
install(TARGETS avwrapper RUNTIME DESTINATION ${target_binary_install_dir}
LIBRARY DESTINATION ${target_library_install_dir}
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/hwengine.pas
--- a/hedgewars/hwengine.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/hwengine.pas Sun Dec 17 00:09:24 2017 +0100
@@ -32,6 +32,7 @@
{$IFDEF USE_VIDEO_RECORDING}, uVideoRec {$ENDIF}
{$IFDEF USE_TOUCH_INTERFACE}, uTouch {$ENDIF}
{$IFDEF ANDROID}, GLUnit{$ENDIF}
+ {$IFDEF WIN32}, dynlibs{$ENDIF}
;
function RunEngine(argc: LongInt; argv: PPChar): Longint; cdecl; export;
@@ -42,6 +43,12 @@
implementation
uses uFLUICallback, uFLTypes;
+{$IFDEF WIN32}
+type TSetProcessDpiAwareness = function(value: Integer): Integer; stdcall;
+var SetProcessDpiAwareness: TSetProcessDpiAwareness;
+var ShcoreLibHandle: TLibHandle;
+{$ENDIF}
+
///////////////////////////////////////////////////////////////////////////////
function DoTimer(Lag: LongInt): boolean;
var s: shortstring;
@@ -57,7 +64,6 @@
SetLandTexture;
UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT, false);
setAILandMarks;
- ParseCommand('sendlanddigest', true);
GameState:= gsStart;
end;
gsStart:
@@ -71,6 +77,7 @@
AddFlakes;
SetRandomSeed(cSeed, false);
StoreLoad(false);
+ ParseCommand('sendlanddigest', true); // extending land digest to all synced pixels (anything that could modify land)
if not allOK then exit;
AssignHHCoords;
AddMiscGears;
@@ -151,6 +158,7 @@
previousGameState: TGameState;
wheelEvent: boolean;
begin
+ previousGameState:= gsStart;
isTerminated:= false;
PrevTime:= SDL_GetTicks;
while (not isTerminated) and allOK do
@@ -188,14 +196,22 @@
cHasFocus:= false;
onFocusStateChanged();
end;
+{$IFDEF MOBILE}
+(* Suspend game if minimized on mobile.
+NOTE: Mobile doesn't support online multiplayer yet, so it's not a problem.
+BUT: This section WILL become a bug when online multiplayer is added to
+Hedgewars and needs to be rethought. This is because it will cause the
+game to freeze if one online player minimizes Hedgewars. *)
SDL_WINDOWEVENT_MINIMIZED:
begin
previousGameState:= GameState;
GameState:= gsSuspend;
end;
+{$ENDIF}
SDL_WINDOWEVENT_RESTORED:
begin
- GameState:= previousGameState;
+ if GameState = gsSuspend then
+ GameState:= previousGameState;
{$IFDEF ANDROID}
//This call is used to reinitialize the glcontext and reload the textures
ParseCommand('fullscr '+intToStr(LongInt(cFullScreen)), true);
@@ -232,7 +248,8 @@
SDL_MOUSEWHEEL:
begin
wheelEvent:= true;
- ProcessMouseWheel(event.wheel.x, event.wheel.y);
+ //ProcessMouseWheel(event.wheel.x, event.wheel.y);
+ ProcessMouseWheel(event.wheel.y);
end;
{$ENDIF}
@@ -362,7 +379,6 @@
ControllerInit(); // has to happen before InitKbdKeyTable to map keys
InitKbdKeyTable();
- AddProgress();
if not allOK then exit;
LoadLocale(cPathz[ptLocale] + '/en.txt'); // Do an initial load with english
@@ -380,6 +396,9 @@
if not allOK then exit;
WriteLnToConsole(msgGettingConfig);
+ LoadFonts();
+ AddProgress();
+
if cTestLua then
begin
ParseCommand('script ' + cScriptName, true);
@@ -416,7 +435,6 @@
if GameType = gmtRecord then
begin
RecorderMainLoop();
- freeEverything(true);
exit;
end;
{$ENDIF}
@@ -514,6 +532,9 @@
{$IFDEF USE_TOUCH_INTERFACE}uTouch.freeModule;{$ENDIF} //stub
{$IFDEF ANDROID}GLUnit.freeModule;{$ENDIF}
uTextures.freeModule;
+ SDL_GL_DeleteContext(SDLGLcontext);
+ SDL_DestroyWindow(SDLwindow);
+ SDL_Quit()
end;
uIO.freeModule;
@@ -577,6 +598,16 @@
operatingsystem_parameter_argc:= argc;
operatingsystem_parameter_argv:= argv;
+{$IFDEF WIN32}
+ ShcoreLibHandle := LoadLibrary('Shcore.dll');
+ if (ShcoreLibHandle <> 0) then
+ begin
+ SetProcessDpiAwareness :=
+ TSetProcessDpiAwareness(GetProcedureAddress(ShcoreLibHandle, 'SetProcessDpiAwareness'));
+ if (SetProcessDpiAwareness <> nil) then
+ SetProcessDpiAwareness(1);
+ end;
+{$ENDIF}
{$IFDEF PAS2C}
// workaround for pascal's ParamStr and ParamCount
init(argc, argv);
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/pas2cRedo.pas
--- a/hedgewars/pas2cRedo.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/pas2cRedo.pas Sun Dec 17 00:09:24 2017 +0100
@@ -8,6 +8,7 @@
LongWord = uinteger;
Cardinal = uinteger;
PtrInt = integer;
+ SizeInt = PtrInt;
Word = uinteger;
Byte = integer;
SmallInt = integer;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/pas2cSystem.pas
--- a/hedgewars/pas2cSystem.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/pas2cSystem.pas Sun Dec 17 00:09:24 2017 +0100
@@ -7,6 +7,7 @@
LongWord = uinteger;
Cardinal = uinteger;
PtrInt = integer;
+ SizeInt = PtrInt;
Word = uinteger;
Byte = integer;
SmallInt = integer;
@@ -133,7 +134,7 @@
PHYSFS_init, PHYSFS_deinit, PHYSFS_mount, PHYSFS_readBytes, PHYSFS_writeBytes, PHYSFS_read : function : LongInt;
PHYSFSRWOPS_openRead, PHYSFSRWOPS_openWrite, PHYSFS_openRead, PHYSFS_openWrite : function : pointer;
- PHYSFS_eof, PHYSFS_close, PHYSFS_exists, PHYSFS_mkdir, PHYSFS_flush, PHYSFS_setWriteDir : function : boolean;
+ PHYSFS_eof, PHYSFS_close, PHYSFS_exists, PHYSFS_mkdir, PHYSFS_flush, PHYSFS_setWriteDir, PHYSFS_setBuffer : function : boolean;
PHYSFS_getLastError : function : PChar;
PHYSFS_enumerateFiles : function : PPChar;
PHYSFS_freeList : procedure;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uAI.pas
--- a/hedgewars/uAI.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uAI.pas Sun Dec 17 00:09:24 2017 +0100
@@ -31,7 +31,8 @@
implementation
uses uConsts, SDLh, uAIMisc, uAIAmmoTests, uAIActions,
uAmmos, uTypes,
- uVariables, uCommands, uUtils, uDebug, uAILandMarks;
+ uVariables, uCommands, uUtils, uDebug, uAILandMarks,
+ uGearsUtils;
var BestActions: TActions;
CanUseAmmo: array [TAmmoType] of boolean;
@@ -150,20 +151,20 @@
// if not between shots, activate invulnerability/vampirism if available
if CurrentHedgehog^.MultiShootAttacks = 0 then
begin
- if HHHasAmmo(Me^.Hedgehog^, amInvulnerable) > 0 then
+ if (HHHasAmmo(Me^.Hedgehog^, amInvulnerable) > 0) and (Me^.Hedgehog^.Effects[heInvulnerable] = 0) then
begin
AddAction(BestActions, aia_Weapon, Longword(amInvulnerable), 80, 0, 0);
AddAction(BestActions, aia_attack, aim_push, 10, 0, 0);
AddAction(BestActions, aia_attack, aim_release, 10, 0, 0);
end;
- if HHHasAmmo(Me^.Hedgehog^, amExtraDamage) > 0 then
+ if (HHHasAmmo(Me^.Hedgehog^, amExtraDamage) > 0) and (cDamageModifier <> _1_5) then
begin
AddAction(BestActions, aia_Weapon, Longword(amExtraDamage), 80, 0, 0);
AddAction(BestActions, aia_attack, aim_push, 10, 0, 0);
AddAction(BestActions, aia_attack, aim_release, 10, 0, 0);
end;
- if HHHasAmmo(Me^.Hedgehog^, amVampiric) > 0 then
+ if (HHHasAmmo(Me^.Hedgehog^, amVampiric) > 0) and (not cVampiric) then
begin
AddAction(BestActions, aia_Weapon, Longword(amVampiric), 80, 0, 0);
AddAction(BestActions, aia_attack, aim_push, 10, 0, 0);
@@ -471,8 +472,17 @@
FillBonuses(false);
+ // Hog has no idea what to do. Use tardis or skip
if not bonuses.activity then
- AddAction(BestActions, aia_Skip, 0, 250, 0, 0);
+ if ((HHHasAmmo(Me^.Hedgehog^, amTardis) > 0)) and (CanUseTardis(Me^.Hedgehog^.Gear)) and (random(4) < 3) then
+ // Tardis brings hog to a random place. Perfect for clueless AI
+ begin
+ AddAction(BestActions, aia_Weapon, Longword(amTardis), 80, 0, 0);
+ AddAction(BestActions, aia_attack, aim_push, 10, 0, 0);
+ AddAction(BestActions, aia_attack, aim_release, 10, 0, 0);
+ end
+ else
+ AddAction(BestActions, aia_Skip, 0, 250, 0, 0);
end;
end else SDL_Delay(100)
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uAIAmmoTests.pas
--- a/hedgewars/uAIAmmoTests.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uAIAmmoTests.pas Sun Dec 17 00:09:24 2017 +0100
@@ -124,7 +124,8 @@
(proc: nil; flags: 0), // amIceGun
(proc: nil; flags: 0), // amKnife
(proc: nil; flags: 0), // amRubber
- (proc: nil; flags: 0) // amAirMine
+ (proc: nil; flags: 0), // amAirMine
+ (proc: nil; flags: 0) // amDuck
);
implementation
@@ -253,7 +254,7 @@
function TestBee(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
var i, j: LongInt;
valueResult, v, a, p: LongInt;
- mX, mY, dX: real;
+ mX, mY: real;
eX, eY: LongInt;
begin
if Level > 1 then
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uAmmos.pas
--- a/hedgewars/uAmmos.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uAmmos.pas Sun Dec 17 00:09:24 2017 +0100
@@ -50,7 +50,7 @@
var StoreCnt: LongInt;
implementation
-uses uVariables, uCommands, uUtils, uCaptions, uDebug;
+uses uVariables, uCommands, uUtils, uCaptions, uDebug, uScript;
type TAmmoCounts = array[TAmmoType] of Longword;
TAmmoArray = array[TAmmoType] of TAmmo;
@@ -210,11 +210,11 @@
cnt:= a^.Count
else
cnt:= 0;
-if (cnt <> AMMO_INFINITE) then
- begin
- inc(cnt, amt);
- SetAmmo(Hedgehog, ammo, cnt)
- end
+if (cnt >= AMMO_INFINITE) or (amt >= AMMO_INFINITE) then
+ cnt:= AMMO_INFINITE
+else
+ cnt:= min(AMMO_FINITE_MAX, cnt + amt);
+SetAmmo(Hedgehog, ammo, cnt);
end;
procedure AddAmmo(var Hedgehog: THedgehog; ammo: TAmmoType);
@@ -287,6 +287,8 @@
CurWeapon:= GetCurAmmoEntry(Hedgehog);
with Hedgehog do
begin
+ if CurAmmoType <> amNothing then
+ ScriptCall('onUsedAmmo', ord(CurAmmoType));
MultiShootAttacks:= 0;
with CurWeapon^ do
@@ -329,11 +331,19 @@
begin
if (AmmoType <> amNothing) then
begin
- CurMinAngle:= Ammoz[AmmoType].minAngle;
- if Ammoz[AmmoType].maxAngle <> 0 then
- CurMaxAngle:= Ammoz[AmmoType].maxAngle
+ if ((CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amRope)) then
+ begin
+ CurMaxAngle:= Ammoz[amRope].maxAngle;
+ CurMinAngle:= Ammoz[amRope].minAngle;
+ end
else
- CurMaxAngle:= cMaxAngle;
+ begin
+ CurMinAngle:= Ammoz[AmmoType].minAngle;
+ if Ammoz[AmmoType].maxAngle <> 0 then
+ CurMaxAngle:= Ammoz[AmmoType].maxAngle
+ else
+ CurMaxAngle:= cMaxAngle;
+ end;
with Hedgehog.Gear^ do
begin
@@ -376,15 +386,14 @@
procedure ApplyAmmoChanges(var Hedgehog: THedgehog);
var s: ansistring;
- CurWeapon: PAmmo;
+ OldWeapon, CurWeapon: PAmmo;
begin
TargetPoint.X:= NoPointX;
with Hedgehog do
begin
- Timer:= 10;
-
CurWeapon:= GetCurAmmoEntry(Hedgehog);
+ OldWeapon:= GetCurAmmoEntry(Hedgehog);
if (CurWeapon^.Count = 0) then
SwitchToFirstLegalAmmo(Hedgehog)
@@ -393,11 +402,18 @@
CurWeapon:= GetCurAmmoEntry(Hedgehog);
+ // Weapon selection animation (if new ammo type)
+ if CurWeapon^.AmmoType <> OldWeapon^.AmmoType then
+ Timer:= 10;
+
ApplyAngleBounds(Hedgehog, CurWeapon^.AmmoType);
with CurWeapon^ do
begin
- s:= trammo[Ammoz[AmmoType].NameId];
+ if length(trluaammo[Ammoz[AmmoType].NameId]) > 0 then
+ s:= trluaammo[Ammoz[AmmoType].NameId]
+ else
+ s:= trammo[Ammoz[AmmoType].NameId];
if (Count <> AMMO_INFINITE) and (not (Hedgehog.Team^.ExtDriven or (Hedgehog.BotLevel > 0))) then
s:= s + ansistring(' (' + IntToStr(Count) + ')');
if (Propz and ammoprop_Timerable) <> 0 then
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uCaptions.pas
--- a/hedgewars/uCaptions.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uCaptions.pas Sun Dec 17 00:09:24 2017 +0100
@@ -47,7 +47,7 @@
if cOnlyStats then exit;
if Length(s) = 0 then
exit;
- if Captions[Group].Text <> s then
+ if (Captions[Group].Text <> s) or (Captions[Group].Color <> Color) then
FreeAndNilTexture(Captions[Group].Tex);
if Captions[Group].Tex = nil then
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uChat.pas
--- a/hedgewars/uChat.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uChat.pas Sun Dec 17 00:09:24 2017 +0100
@@ -47,7 +47,7 @@
s: shortstring;
Color: TSDL_Color;
end;
- TChatCmd = (ccQuit, ccPause, ccFinish, ccShowHistory, ccFullScreen);
+ TChatCmd = (ccQuit, ccPause, ccShowHistory, ccFullScreen);
var Strs: array[0 .. MaxStrIndex] of TChatLine;
MStrs: array[0 .. MaxStrIndex] of shortstring;
@@ -88,7 +88,6 @@
end = (
(ChatCmd: '/quit'; ProcedureCallChatCmd: 'halt'),
(ChatCmd: '/pause'; ProcedureCallChatCmd: 'pause'),
- (ChatCmd: '/finish'; ProcedureCallChatCmd: 'finish'),
(ChatCmd: '/history'; ProcedureCallChatCmd: 'history'),
(ChatCmd: '/fullscreen'; ProcedureCallChatCmd: 'fullscr')
);
@@ -161,7 +160,7 @@
* It will use the color stored in cl and update width
*)
procedure RenderChatLineTex(var cl: TChatLine; var str: shortstring);
-var strSurface,
+var strSurface, tmpSurface,
resSurface: PSDL_Surface;
dstrect : TSDL_Rect; // destination rectangle for blitting
font : THWFont;
@@ -194,10 +193,14 @@
SDL_FillRect(resSurface, @dstrect, shadowint);
// create and blit text
+tmpSurface:= nil;
strSurface:= TTF_RenderUTF8_Blended(Fontz[font].Handle, Str2PChar(str), cl.color);
+// fix format
+if strSurface <> nil then tmpSurface:= SDL_ConvertSurface(strSurface, resSurface^.format, 0);
+SDL_FreeSurface(strSurface);
//SDL_UpperBlit(strSurface, nil, resSurface, @dstrect);
-if strSurface <> nil then copyToXY(strSurface, resSurface, Padding, Padding);
-SDL_FreeSurface(strSurface);
+if tmpSurface <> nil then copyToXY(tmpSurface, resSurface, Padding, Padding);
+SDL_FreeSurface(tmpSurface);
cl.Tex:= Surface2Tex(resSurface, false);
@@ -1095,11 +1098,18 @@
end;
procedure chChat(var s: shortstring);
+var i: Integer;
begin
s:= s; // avoid compiler hint
GameState:= gsChat;
SDL_StopTextInput();
SDL_StartTextInput();
+ //Make REALLY sure unexpected events are flushed (1 time is insufficient as of SDL 2.0.7)
+ for i := 1 to 2 do
+ begin
+ SDL_PumpEvents();
+ SDL_FlushEvent(SDL_TEXTINPUT);
+ end;
//SDL_EnableKeyRepeat(200,45);
if length(s) = 0 then
SetLine(InputStr, '', true)
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uCommandHandlers.pas
--- a/hedgewars/uCommandHandlers.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uCommandHandlers.pas Sun Dec 17 00:09:24 2017 +0100
@@ -27,7 +27,7 @@
implementation
uses uCommands, uTypes, uVariables, uIO, uDebug, uConsts, uScript, uUtils, SDLh, uWorld, uRandom, uCaptions
- , uVisualGearsList
+ , uVisualGearsList, uGearsHedgehog
{$IFDEF USE_VIDEO_RECORDING}, uVideoRec {$ENDIF};
var prevGState: TGameState = gsConfirm;
@@ -37,9 +37,9 @@
procedure chGenCmd(var s: shortstring);
begin
case s[1] of
- 'R': if ReadyTimeLeft > 1 then
+ 'R': if ReadyTimeLeft > 0 then
begin
- ReadyTimeLeft:= 1;
+ ReadyTimeLeft:= 0;
if not isExternalSource then
SendIPC('c'+s);
end
@@ -474,12 +474,7 @@
if not isExternalSource then
SendIPC('t' + s);
-with CurrentHedgehog^.Gear^ do
- begin
- Message:= Message or (gmAnimate and InputMask);
- MsgParam:= byte(s[1]) ;
- ScriptCall('onTaunt', MsgParam);
- end
+PlayTaunt(byte(s[1]))
end;
procedure chPut(var s: shortstring);
@@ -538,7 +533,7 @@
cSeed:= s;
InitStepsFlags:= InitStepsFlags or cifRandomize
end
- end;
+end;
procedure chAmmoMenu(var s: shortstring);
begin
@@ -554,7 +549,7 @@
if bShowAmmoMenu then
bShowAmmoMenu:= false
- else if not(CurrentTeam^.Extdriven) and (((Gear^.State and (gstAttacking or gstAttacked)) <> 0)
+ else if not(CurrentTeam^.Extdriven) and ((Gear = nil) or ((Gear^.State and (gstAttacking or gstAttacked)) <> 0)
or ((Gear^.State and gstHHDriven) = 0)) then
begin
end
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uConsole.pas
--- a/hedgewars/uConsole.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uConsole.pas Sun Dec 17 00:09:24 2017 +0100
@@ -28,7 +28,7 @@
var lastConsoleline : shortstring;
implementation
-uses Types, uUtils {$IFDEF ANDROID}, log in 'log.pas'{$ENDIF};
+uses uUtils {$IFDEF ANDROID}, log in 'log.pas'{$ENDIF};
procedure WriteToConsole(s: shortstring);
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uConsts.pas
--- a/hedgewars/uConsts.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uConsts.pas Sun Dec 17 00:09:24 2017 +0100
@@ -27,17 +27,22 @@
const
HDPIScaleFactor = 1;
+
+ // application return codes
HaltNoError = 0;
- HaltUsageError = 1;
- HaltFatalError = 2;
- HaltStartupError = 3;
- HaltFatalErrorNoIPC = 4;
+
+ // error codes are placed in range 50-99 because that way then don't overlap with run-time errors of pascal
+ // see https://www.freepascal.org/docs-html/user/userap4.html
+ HaltUsageError = 51;
+ HaltFatalError = 52;
+ HaltStartupError = 53;
+ HaltFatalErrorNoIPC = 54;
// for automatic tests
HaltTestSuccess = 0;
- HaltTestFailed = 10;
- HaltTestLuaError = 11;
- HaltTestUnexpected = 12;
+ HaltTestFailed = 60;
+ HaltTestLuaError = 61;
+ HaltTestUnexpected = 62;
sfMax = 1000;
@@ -90,10 +95,11 @@
rqDesyncVBlank= $00000800; // don't sync on vblank
// image flags (for LoadImage())
+ // TODO: discuss whether ifAlpha and ifColorKey are actually needed and if and where we want to support which colorkeys
ifNone = $00000000; // nothing special
ifAlpha = $00000001; // use alpha channel (unused right now?)
ifCritical = $00000002; // image is critical for gameplay (exit game if unable to load)
- ifTransparent = $00000004; // image uses transparent pixels (color keying)
+ ifColorKey = $00000004; // image uses transparent pixels (color keying)
ifIgnoreCaps = $00000008; // ignore hardware capabilities when loading (i.e. image will not be drawn using OpenGL)
// texture priority (allows OpenGL to keep frequently used textures in video memory more easily)
@@ -269,7 +275,8 @@
gmDelete = $00010000;
gmAllStoppable = gmLeft or gmRight or gmUp or gmDown or gmAttack or gmPrecise;
- cMaxSlotIndex = 9;
+ cMaxSlotIndex = 10;
+ cHiddenSlotIndex = cMaxSlotIndex; // slot for hidden ammo types, not visible and has no key
cMaxSlotAmmoIndex = 5;
// ai hints
@@ -299,9 +306,14 @@
ammoprop_Track = $00040000;
ammoprop_DoesntStopTimerInMultiShoot
= $00080000;
+ ammoprop_DoesntStopTimerWhileAttackingInInfAttackMode
+ = $00100000;
+ ammoprop_ForceTurnEnd = $00200000;
+ ammoprop_NoTargetAfter= $00400000;
ammoprop_NoRoundEnd = $10000000;
AMMO_INFINITE = 100;
+ AMMO_FINITE_MAX = 99;
// explosion flags
//EXPLAllDamageInRadius = $00000001; Completely unused for ages
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uCursor.pas
--- a/hedgewars/uCursor.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uCursor.pas Sun Dec 17 00:09:24 2017 +0100
@@ -18,6 +18,13 @@
procedure resetPosition;
begin
+ // Move curser by 1px in case it's already centered.
+ // The game camera in the Alpha for 0.9.23 screwed up if
+ // the game started with the mouse already being centered.
+ // This fixes it, but we might have overlooked a related
+ // bug somewhere else.
+ // No big deal since this function is (so far) only called once.
+ SDL_WarpMouse((cScreenWidth div 2) + 1, cScreenHeight div 2);
SDL_WarpMouse(cScreenWidth div 2, cScreenHeight div 2);
end;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uGears.pas
--- a/hedgewars/uGears.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uGears.pas Sun Dec 17 00:09:24 2017 +0100
@@ -42,16 +42,18 @@
procedure ProcessGears;
procedure EndTurnCleanup;
procedure DrawGears;
+procedure DrawGearsTimers;
procedure FreeGearsList;
procedure AddMiscGears;
procedure AssignHHCoords;
function GearByUID(uid : Longword) : PGear;
+function IsClockRunning() : boolean;
implementation
uses uStore, uSound, uTeams, uRandom, uIO, uLandGraphics,
{$IFDEF USE_TOUCH_INTERFACE}uTouch,{$ENDIF}
uLocale, uAmmos, uStats, uVisualGears, uScript, uVariables,
- uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug,
+ uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions,
uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlersRope
, uVisualGearsList, uGearsHandlersMess, uAI;
@@ -125,7 +127,7 @@
if Gear^.Kind = gtHedgehog then
begin
tmp:= 0;
- if Gear^.Hedgehog^.Effects[hePoisoned] <> 0 then
+ if (Gear^.Hedgehog^.Effects[hePoisoned] <> 0) and (Gear^.Hedgehog^.Effects[heFrozen] = 0) then
begin
inc(tmp, ModifyDamage(Gear^.Hedgehog^.Effects[hePoisoned], Gear));
if (GameFlags and gfResetHealth) <> 0 then
@@ -336,7 +338,7 @@
ChangeToSDClouds;
ChangeToSDFlakes;
- SetSkyColor(SDSkyColor.r * (SDTint/255) / 255, SDSkyColor.g * (SDTint/255) / 255, SDSkyColor.b * (SDTint/255) / 255);
+ SetSkyColor(SDSkyColor.r * (SDTint.r/255) / 255, SDSkyColor.g * (SDTint.r/255) / 255, SDSkyColor.b * (SDTint.b/255) / 255);
Ammoz[amTardis].SkipTurns:= 9999;
Ammoz[amTardis].Probability:= 0;
end;
@@ -437,6 +439,7 @@
step:= stChDmg;
if TagTurnTimeLeft = 0 then
TagTurnTimeLeft:= TurnTimeLeft;
+ GameOver:= true;
TurnTimeLeft:= 0
end
end
@@ -444,27 +447,32 @@
end;
if TurnTimeLeft > 0 then
- if CurrentHedgehog^.Gear <> nil then
- if (((CurrentHedgehog^.Gear^.State and gstAttacking) = 0)
- or (Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_DoesntStopTimerWhileAttacking <> 0))
- and (not(isInMultiShoot and ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_DoesntStopTimerInMultiShoot) <> 0))) then
- //(CurrentHedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle])
- begin
- if (TurnTimeLeft = 5000)
- and (cHedgehogTurnTime >= 10000)
- and (not PlacingHogs)
- and (CurrentHedgehog^.Gear <> nil)
- and ((CurrentHedgehog^.Gear^.State and gstAttacked) = 0) then
- PlaySoundV(sndHurry, CurrentTeam^.voicepack);
- if ReadyTimeLeft > 0 then
- begin
- if (ReadyTimeLeft = 2000) and (LastVoice.snd = sndNone) then
- AddVoice(sndComeonthen, CurrentTeam^.voicepack);
- dec(ReadyTimeLeft)
- end
- else
- dec(TurnTimeLeft)
- end;
+ if IsClockRunning() then
+ //(CurrentHedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle])
+ begin
+ if (cHedgehogTurnTime >= 10000)
+ and (CurrentHedgehog^.Gear <> nil)
+ and ((CurrentHedgehog^.Gear^.State and gstAttacked) = 0)
+ and (not isGetAwayTime) then
+ if TurnTimeLeft = 5000 then
+ PlaySoundV(sndHurry, CurrentTeam^.voicepack)
+ else if TurnTimeLeft = 4000 then
+ PlaySound(sndCountdown4)
+ else if TurnTimeLeft = 3000 then
+ PlaySound(sndCountdown3)
+ else if TurnTimeLeft = 2000 then
+ PlaySound(sndCountdown2)
+ else if TurnTimeLeft = 1000 then
+ PlaySound(sndCountdown1);
+ if ReadyTimeLeft > 0 then
+ begin
+ if (ReadyTimeLeft = 2000) and (LastVoice.snd = sndNone) and (not PlacingHogs) then
+ AddVoice(sndComeonthen, CurrentTeam^.voicepack);
+ dec(ReadyTimeLeft)
+ end
+ else
+ dec(TurnTimeLeft)
+ end;
if skipFlag then
begin
@@ -505,7 +513,8 @@
if (GameFlags and gfLowGravity) = 0 then
begin
cGravity:= cMaxWindSpeed * 2;
- cGravityf:= 0.00025 * 2
+ cGravityf:= 0.00025 * 2;
+ cLowGravity:= false
end;
if (GameFlags and gfVampiric) = 0 then
@@ -514,7 +523,10 @@
cDamageModifier:= _1;
if (GameFlags and gfLaserSight) = 0 then
+ begin
cLaserSighting:= false;
+ cLaserSightingSniper:= false
+ end;
if (GameFlags and gfArtillery) = 0 then
cArtillery:= false;
@@ -578,6 +590,20 @@
DrawHHOrder();
end;
+procedure DrawGearsTimers;
+var Gear: PGear;
+ x, y: LongInt;
+begin
+Gear:= GearsList;
+while Gear <> nil do
+ begin
+ x:= hwRound(Gear^.X) + WorldDx;
+ y:= hwRound(Gear^.Y) + WorldDy;
+ RenderGearTimer(Gear, x, y);
+ Gear:= Gear^.NextGear
+ end;
+end;
+
procedure FreeGearsList;
var t, tt: PGear;
begin
@@ -624,7 +650,10 @@
if Gear = nil then
inc(unplaced)
else
+ begin
unplaced:= 0;
+ AddCI(Gear)
+ end;
inc(i)
end;
@@ -696,7 +725,8 @@
if (GameFlags and gfLowGravity) <> 0 then
begin
cGravity:= cMaxWindSpeed;
- cGravityf:= 0.00025
+ cGravityf:= 0.00025;
+ cLowGravity:= true
end;
if (GameFlags and gfVampiric) <> 0 then
@@ -819,14 +849,24 @@
PlacingHogs:= true;
divide:= ((GameFlags and gfDivideTeams) <> 0);
-sectionDivide:= divide and ((GameFlags and gfForts) <> 0);
+
+(* sectionDivide will determine the mode of hog distribution
+ *
+ * On generated maps or maps not designed with divided mode in mind,
+ * using spawning sections can be problematic, because some sections may
+ * contain too little land surface for sensible spawning.
+ *
+ * if sectionDivide is true, the map will be sliced into equal-width sections
+ * and one team spawned in each
+ * if false, the hogs will be spawned normally and sorted by teams after
+ *
+ *)
// TODO: there might be a smarter way to decide if dividing clans into equal-width map sections makes sense
// e.g. by checking if there is enough spawn area in each section
-if divide and (not sectionDivide) then
- sectionDivide:= (ClansCount = 2);
+sectionDivide:= divide and ((cMapGen = mgForts) or (ClansCount = 2));
-// in section-divide mode, divide the map into equal-width sections and put each clan in one of them
+// divide the map into equal-width sections and put each clan in one of them
if sectionDivide then
begin
t:= leftX;
@@ -845,6 +885,7 @@
FindPlace(Gear, false, t, t + playWidth div ClansCount, true);// could make Gear == nil;
if Gear <> nil then
begin
+ //AddCI(Gear); uncomment if new hogs should be able to spawn on top of old ones.
Gear^.Pos:= GetRandom(49);
// unless the world is wrapping, make outter teams face to map center
if (WorldEdge <> weWrap) and ((p = 0) or (p = ClansCount - 1)) then
@@ -879,6 +920,7 @@
FindPlace(ar[i]^.Gear, false, leftX, rightX, true);
if ar[i]^.Gear <> nil then
begin
+ //AddCI(ar[i]^.Gear); uncomment if new hogs should be able to spawn on top of old ones
ar[i]^.Gear^.dX.isNegative:= hwRound(ar[i]^.Gear^.X) > leftX + playWidth div 2;
ar[i]^.Gear^.Pos:= GetRandom(19)
end;
@@ -906,6 +948,7 @@
hwRound(Gear^.Y) - SpritesData[sprTargetBee].Height div 2,
sprTargetBee, 0, lfBasic, $FFFFFFFF, false, false, false);
Gear^.Y:= int2hwFloat(hwRound(Gear^.Y) - 16 - Gear^.Radius);
+ AddCI(Gear);
Gear^.State:= Gear^.State and (not gsttmpFlag);
AddFileLog('Placed flower for hog at coordinates (' + inttostr(hwRound(Gear^.X)) + ',' + inttostr(hwRound(Gear^.Y)) + ')')
end;
@@ -1038,6 +1081,17 @@
end
end;
+function IsClockRunning() : boolean;
+begin
+ IsClockRunning :=
+ (CurrentHedgehog^.Gear <> nil)
+ and (((CurrentHedgehog^.Gear^.State and gstAttacking) = 0)
+ or (Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_DoesntStopTimerWhileAttacking <> 0)
+ or ((GameFlags and gfInfAttack) <> 0) and (Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_DoesntStopTimerWhileAttackingInInfAttackMode <> 0)
+ or (CurrentHedgehog^.CurAmmoType = amSniperRifle))
+ and (not(isInMultiShoot and ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_DoesntStopTimerInMultiShoot) <> 0)));
+end;
+
procedure chSkip(var s: shortstring);
begin
@@ -1195,7 +1249,8 @@
@doStepIceGun,
@doStepAddAmmo,
@doStepGenericFaller,
- @doStepKnife);
+ @doStepKnife,
+ @doStepDuck);
begin
doStepHandlers:= handlers;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uGearsHandlersMess.pas
--- a/hedgewars/uGearsHandlersMess.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uGearsHandlersMess.pas Sun Dec 17 00:09:24 2017 +0100
@@ -47,7 +47,7 @@
procedure doStepBee(Gear: PGear);
procedure doStepShotIdle(Gear: PGear);
procedure doStepShotgunShot(Gear: PGear);
-procedure spawnBulletTrail(Bullet: PGear);
+procedure spawnBulletTrail(Bullet: PGear; bulletX, bulletY: hwFloat);
procedure doStepBulletWork(Gear: PGear);
procedure doStepDEagleShot(Gear: PGear);
procedure doStepSniperRifleShot(Gear: PGear);
@@ -138,6 +138,7 @@
procedure doStepGenericFaller(Gear: PGear);
//procedure doStepCreeper(Gear: PGear);
procedure doStepKnife(Gear: PGear);
+procedure doStepDuck(Gear: PGear);
var
upd: Longword;
@@ -146,8 +147,8 @@
implementation
uses uConsts, uVariables, uVisualGearsList, uRandom, uCollisions, uGearsList, uUtils, uSound
, SDLh, uScript, uGearsHedgehog, uGearsUtils, uIO, uCaptions, uLandGraphics
- , uGearsHandlers, uTextures, uRenderUtils, uAmmos, uTeams, uLandTexture, uCommands
- , uStore, uAI, uStats;
+ , uGearsHandlers, uTextures, uRenderUtils, uAmmos, uTeams, uLandTexture
+ , uStore, uAI, uStats, uLocale;
procedure doStepPerPixel(Gear: PGear; step: TGearStepProcedure; onlyCheckIfChanged: boolean);
var
@@ -259,7 +260,7 @@
////////////////////////////////////////////////////////////////////////////////
procedure doStepDrowningGear(Gear: PGear);
-var i, d: LongInt;
+var i, d, bubbleX, bubbleY: LongInt;
bubble: PVisualGear;
begin
if Gear^.Timer = 0 then
@@ -291,12 +292,17 @@
Gear^.X := Gear^.X + Gear^.dX * cDrownSpeed;
// Create some bubbles (0.5% might be better but causes too few bubbles sometimes)
+if (Gear^.Kind = gtHedgehog) and (Gear^.dX.isNegative) then
+ bubbleX:= hwRound(Gear^.X) - Gear^.Radius
+else
+ bubbleX:= hwRound(Gear^.X) + Gear^.Radius;
+bubbleY:= hwRound(Gear^.Y) - Gear^.Radius;
if ((not SuddenDeathDmg and (WaterOpacity < $FF))
or (SuddenDeathDmg and (SDWaterOpacity < $FF))) and ((GameTicks and $1F) = 0) then
if (Gear^.Kind = gtHedgehog) and (Random(4) = 0) then
- AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble)
+ AddVisualGear(bubbleX, bubbleY, vgtBubble)
else if Random(12) = 0 then
- AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble);
+ AddVisualGear(bubbleX, bubbleY, vgtBubble);
if (not SuddenDeathDmg and (WaterOpacity > $FE))
or (SuddenDeathDmg and (SDWaterOpacity > $FE))
or (hwRound(Gear^.Y) > Gear^.Radius + cWaterLine + cVisibleWater) then
@@ -467,7 +473,7 @@
if isFalling and (Gear^.State and gstNoGravity = 0) then
begin
Gear^.dY := Gear^.dY + cGravity;
- if (GameFlags and gfMoreWind <> 0) and
+ if (GameFlags and gfMoreWind <> 0) and (TurnTimeLeft > 0) and
((xland or land) = 0) and
((Gear^.dX.QWordValue + Gear^.dY.QWordValue) > _0_02.QWordValue) then
Gear^.dX := Gear^.dX + cWindSpeed / Gear^.Density
@@ -1189,7 +1195,7 @@
end;
////////////////////////////////////////////////////////////////////////////////
-procedure spawnBulletTrail(Bullet: PGear);
+procedure spawnBulletTrail(Bullet: PGear; bulletX, bulletY: hwFloat);
var oX, oY: hwFloat;
VGear: PVisualGear;
begin
@@ -1211,14 +1217,14 @@
begin
VGear^.X:= hwFloat2Float(ox);
VGear^.Y:= hwFloat2Float(oy);
- VGear^.dX:= hwFloat2Float(Bullet^.X);
- VGear^.dY:= hwFloat2Float(Bullet^.Y);
+ VGear^.dX:= hwFloat2Float(bulletX);
+ VGear^.dY:= hwFloat2Float(bulletY);
// reached edge of land. assume infinite beam. Extend it way out past camera
- if (hwRound(Bullet^.X) and LAND_WIDTH_MASK <> 0)
- or (hwRound(Bullet^.Y) and LAND_HEIGHT_MASK <> 0) then
+ if (hwRound(bulletX) and LAND_WIDTH_MASK <> 0)
+ or (hwRound(bulletY) and LAND_HEIGHT_MASK <> 0) then
// only extend if not under water
- if not CheckCoordInWater(hwRound(Bullet^.X), hwRound(Bullet^.Y)) then
+ if not CheckCoordInWater(hwRound(bulletX), hwRound(bulletY)) then
begin
VGear^.dX := VGear^.dX + max(LAND_WIDTH,4096) * (VGear^.dX - VGear^.X);
VGear^.dY := VGear^.dY + max(LAND_WIDTH,4096) * (VGear^.dY - VGear^.Y);
@@ -1230,13 +1236,14 @@
procedure doStepBulletWork(Gear: PGear);
var
- i, x, y: LongWord;
- oX, oY, tX, tY, cX, cY: hwFloat;
+ i, x, y, iInit: LongWord;
+ oX, oY, tX, tY, tDx, tDy: hwFloat;
VGear: PVisualGear;
begin
AllInactive := false;
inc(Gear^.Timer);
- i := 80;
+ iInit := 80;
+ i := iInit;
oX := Gear^.X;
oY := Gear^.Y;
repeat
@@ -1244,19 +1251,19 @@
Gear^.Y := Gear^.Y + Gear^.dY;
tX:= Gear^.X;
tY:= Gear^.Y;
+ tDx:= Gear^.dX;
+ tDy:= Gear^.dY;
if (Gear^.PortalCounter < 30) and WorldWrap(Gear) then
begin
- cX:= Gear^.X;
- cY:= Gear^.Y;
- Gear^.X:= tX;
- Gear^.Y:= tY;
- SpawnBulletTrail(Gear);
- Gear^.X:= cX;
- Gear^.Y:= cY;
+ DrawTunnel(oX, oY, tDx, tDy, iInit + 2 - i, 1);
+ SpawnBulletTrail(Gear, tX, tY);
+ iInit:= i;
+ oX:= Gear^.X;
+ oY:= Gear^.Y;
inc(Gear^.PortalCounter);
Gear^.Elasticity:= Gear^.X;
Gear^.Friction:= Gear^.Y;
- SpawnBulletTrail(Gear);
+ SpawnBulletTrail(Gear, Gear^.X, Gear^.Y);
end;
x := hwRound(Gear^.X);
y := hwRound(Gear^.Y);
@@ -1289,7 +1296,7 @@
if Gear^.Damage > 0 then
begin
- DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 82 - i, 1);
+ DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, iInit + 2 - i, 1);
dec(Gear^.Health, Gear^.Damage);
Gear^.Damage := 0
end;
@@ -1315,8 +1322,8 @@
or (hwRound(Gear^.X) and LAND_WIDTH_MASK <> 0)
or (hwRound(Gear^.Y) and LAND_HEIGHT_MASK <> 0) then
begin
- if (Gear^.Kind = gtSniperRifleShot) and ((GameFlags and gfLaserSight) = 0) then
- cLaserSighting := false;
+ if (Gear^.Kind = gtSniperRifleShot) then
+ cLaserSightingSniper := false;
if (Ammoz[Gear^.AmmoType].Ammo.NumPerTurn <= CurrentHedgehog^.MultiShootAttacks) and ((GameFlags and gfArtillery) = 0) then
cArtillery := false;
@@ -1330,7 +1337,7 @@
end;
end;
- spawnBulletTrail(Gear);
+ spawnBulletTrail(Gear, Gear^.X, Gear^.Y);
Gear^.doStep := @doStepShotIdle
end;
end;
@@ -1369,10 +1376,10 @@
HHGear^.State := HHGear^.State or gstNotKickable;
HedgehogChAngle(HHGear);
- if not cLaserSighting then
- // game does not have default laser sight. turn it on and give them a chance to aim
- begin
- cLaserSighting := true;
+ if cLaserSightingSniper = false then
+ // Turn sniper's laser sight on and give it a chance to aim
+ begin
+ cLaserSightingSniper := true;
HHGear^.Message := 0;
if (HHGear^.Angle >= 32) then
dec(HHGear^.Angle,32)
@@ -1407,9 +1414,7 @@
if (HHGear^.Angle >= 1) then
dec(HHGear^.Angle);
- if (TurnTimeLeft > 0) then
- dec(TurnTimeLeft)
- else
+ if (TurnTimeLeft = 0) then
begin
HHGear^.State := HHGear^.State and (not gstNotKickable);
DeleteGear(Gear);
@@ -1427,7 +1432,7 @@
AllInactive := false;
if Gear^.Timer = 0 then
begin
- AddCaption(trmsg[sidStartFight], cWhiteColor, capgrpGameState);
+ AddCaption(GetEventString(eidRoundStart), cWhiteColor, capgrpGameState);
end
end;
gtATFinishGame:
@@ -1461,8 +1466,6 @@
WorldWrap(Gear);
HHGear := Gear^.Hedgehog^.Gear;
dec(Gear^.Timer);
- if ((GameFlags and gfInfAttack) <> 0) and (TurnTimeLeft > 0) then
- dec(TurnTimeLeft);
if (TurnTimeLeft = 0) or (Gear^.Timer = 0)
or((Gear^.Message and gmDestroy) <> 0)
or((HHGear^.State and gstHHDriven) =0) then
@@ -1589,11 +1592,10 @@
AllInactive := false;
WorldWrap(Gear);
dec(Gear^.Timer);
- if ((GameFlags and gfInfAttack) <> 0) and (TurnTimeLeft > 0) then
- dec(TurnTimeLeft);
if Gear^.Hedgehog^.Gear = nil then
begin
+ StopSoundChan(Gear^.SoundChannel);
DeleteGear(Gear);
AfterAttack;
exit
@@ -1671,6 +1673,7 @@
if (TurnTimeLeft = 0) or (Gear^.Timer = 0)
or ((HHGear^.Message and gmAttack) <> 0) then
begin
+ StopSoundChan(Gear^.SoundChannel);
HHGear^.Message := 0;
HHGear^.State := HHGear^.State and (not gstNotKickable);
DeleteGear(Gear);
@@ -1695,6 +1698,7 @@
cHHStepTicks, cHHRadius * 2 + 7);
HHGear^.Message := 0;
HHGear^.State := HHGear^.State or gstNotKickable;
+ Gear^.SoundChannel := LoopSound(sndBlowTorch);
Gear^.doStep := @doStepBlowTorchWork
end;
@@ -1755,6 +1759,14 @@
else // gstAttacking <> 0
begin
AllInactive := false;
+ // tag of 1 means this mine has a random timer
+ if (Gear^.Tag = 1) and (Gear^.Timer = 0) then
+ begin
+ if (GameTicks mod 2 = 0) then GetRandom(2);
+ if (GameTicks mod 3 = 0) then GetRandom(2);
+ Gear^.Timer:= GetRandom(51) * 100;
+ Gear^.Tag:= 0;
+ end;
if (Gear^.Timer and $FF) = 0 then
PlaySound(sndMineTick);
if Gear^.Timer = 0 then
@@ -1876,9 +1888,15 @@
else
trackSpeed.QWordValue:= Gear^.Power;
if (Gear^.X < targ^.X) and (Gear^.dX < _0_1) then
- Gear^.dX:= Gear^.dX+trackSpeed // please leave as an add. I like the effect
+ if (WorldEdge = weWrap) and ((targ^.X - Gear^.X) > ((Gear^.X - int2hwFloat(LeftX)) + (int2hwFloat(RightX) - targ^.X))) then
+ Gear^.dX:= Gear^.dX-trackSpeed
+ else
+ Gear^.dX:= Gear^.dX+trackSpeed // please leave as an add. I like the effect
else if (Gear^.X > targ^.X) and (Gear^.dX > -_0_1) then
- Gear^.dX:= Gear^.dX-trackSpeed;
+ if (WorldEdge = weWrap) and ((Gear^.X - targ^.X) > ((targ^.X - int2hwFloat(LeftX)) + (int2hwFloat(RightX) - Gear^.X))) then
+ Gear^.dX:= Gear^.dX+trackSpeed
+ else
+ Gear^.dX:= Gear^.dX-trackSpeed;
if (Gear^.Y < targ^.Y) and (Gear^.dY < _0_1) then
Gear^.dY:= Gear^.dY+trackSpeed
else if (Gear^.Y > targ^.Y) and (Gear^.dY > -_0_1) then
@@ -1982,14 +2000,14 @@
if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Health <> 0) then
begin
- if ((Gear^.State and gstAttacking) = 0) then
+ if ((Gear^.State and gstAttacking) = 0) and ((Gear^.State and gstFrozen) = 0) then
begin
if ((GameTicks and $1F) = 0) then
// FIXME - values taken from mine. use a gear val and set both to same
if CheckGearNear(Gear, gtHedgehog, 46, 32) <> nil then
Gear^.State := Gear^.State or gstAttacking
end
- else // gstAttacking <> 0
+ else if (Gear^.State and gstFrozen) = 0 then // gstAttacking <> 0
begin
AllInactive := false;
if Gear^.Timer = 0 then
@@ -2012,7 +2030,6 @@
////////////////////////////////////////////////////////////////////////////////
procedure doStepDynamite(Gear: PGear);
-var VGear: PVisualGear;
begin
doStepFallingGear(Gear);
AllInactive := false;
@@ -2114,7 +2131,6 @@
dX, dY: HWFloat;
hog: PHedgehog;
sparkles: PVisualGear;
- gi: PGear;
begin
k := Gear^.Kind;
@@ -2146,6 +2162,8 @@
for i:= 0 to 63 do
AddGear(x, y, gtFlame, 0, _0, _0, 0);
end
+ else if k = gtTarget then
+ uStats.TargetHit()
else if k = gtExplosives then
begin
doMakeExplosion(x, y, Gear^.Boom, hog, EXPLAutoSound);
@@ -2296,15 +2314,28 @@
var
HHGear: PGear;
begin
- HHGear := Gear^.Hedgehog^.Gear;
- HHGear^.State := HHGear^.State or gstNoDamage;
- DeleteCI(HHGear);
-
- AmmoShove(Gear, Gear^.Boom, 115);
-
- HHGear^.State := (HHGear^.State and (not gstNoDamage)) or gstMoving;
- Gear^.Timer := 250;
- Gear^.doStep := @doStepIdle
+ dec(Gear^.Timer);
+ if Gear^.Timer = 0 then
+ begin
+ inc(Gear^.Tag);
+ Gear^.Timer := 50
+ end;
+
+ if Gear^.Tag = 3 then
+ begin
+ HHGear := Gear^.Hedgehog^.Gear;
+ HHGear^.State := HHGear^.State or gstNoDamage;
+ DeleteCI(HHGear);
+
+ AmmoShove(Gear, Gear^.Boom, 115);
+
+ HHGear^.State := (HHGear^.State and (not gstNoDamage)) or gstMoving;
+ end
+ else if Gear^.Tag = 4 then
+ begin
+ Gear^.Timer := 250;
+ Gear^.doStep := @doStepIdle
+ end
end;
////////////////////////////////////////////////////////////////////////////////
@@ -2599,6 +2630,8 @@
State := State or gstMoving;
end;
DeleteGear(Gear);
+ if (GetAmmoEntry(HHGear^.Hedgehog^, amParachute)^.Count >= 1) and ((Ammoz[HHGear^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
+ HHGear^.Hedgehog^.CurAmmoType:= amParachute;
isCursorVisible := false;
ApplyAmmoChanges(HHGear^.Hedgehog^);
exit
@@ -2848,6 +2881,8 @@
valid:= false;
lx:= Gear^.Target.X - SpritesData[sprHHTelepMask].Width div 2; // left
+ if WorldEdge <> weBounce then
+ lx:= CalcWorldWrap(lx, SpritesData[sprHHTelepMask].Width div 2); // Take world edge into account
ty:= Gear^.Target.Y - SpritesData[sprHHTelepMask].Height div 2; // top
// remember original target location
@@ -2863,6 +2898,9 @@
dec(Gear^.Target.Y);
end;
+ if (WorldEdge = weBounce) and ((Gear^.Target.X < LeftX) or (Gear^.Target.X > RightX)) then
+ valid:= false;
+
if not valid then
begin
HHGear^.Message := HHGear^.Message and (not gmAttack);
@@ -2950,6 +2988,8 @@
CurrentTeam^.CurrHedgehog := (CurrentTeam^.CurrHedgehog + switchDir) mod CurrentTeam^.HedgehogsNumber;
until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil) and
(CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^.Damage = 0) and
+ (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^.Health > 0) and
+ ((CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^.State and gstHHDeath) = 0) and
(CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Effects[heFrozen]=0);
SwitchCurrentHedgehog(@CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog]);
@@ -3025,6 +3065,7 @@
HHGear: PGear;
sparkles: PVisualGear;
hasWishes: boolean;
+ s: ansistring;
begin
AllInactive := false;
hasWishes:= ((Gear^.Message and (gmPrecise or gmSwitch)) = (gmPrecise or gmSwitch));
@@ -3122,10 +3163,13 @@
FrameTicks:= random(400) + 250
end
end;
+ s:= ansistring(Gear^.Hedgehog^.Name);
+ AddCaption(FormatA(GetEventString(eidKamikaze), s), cWhiteColor, capgrpMessage);
+ uStats.HedgehogSacrificed(Gear^.Hedgehog);
AfterAttack;
HHGear^.Message:= HHGear^.Message or gmDestroy;
DeleteGear(Gear);
- end
+ end
else
begin
dec(Gear^.Health, Gear^.Damage);
@@ -3167,6 +3211,7 @@
////////////////////////////////////////////////////////////////////////////////
procedure doStepCakeExpl(Gear: PGear);
+var gi: PGear;
begin
AllInactive := false;
@@ -3175,6 +3220,14 @@
exit;
InCinematicMode:= false;
+ gi := GearsList;
+ while gi <> nil do
+ begin
+ if gi^.Kind = gtHedgehog then
+ gi^.State := gi^.State and (not gstLoser);
+ gi:= gi^.NextGear;
+ end;
+
doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound);
AfterAttack;
DeleteGear(Gear)
@@ -3203,7 +3256,7 @@
//fY.QWordValue:= fY.QWordValue and $FFFFFFFF00000000;
fX:= int2hwFloat(hwRound(Gear^.X));
fY:= int2hwFloat(hwRound(Gear^.Y));
- dmgBase:= cakeDmg shl 1 + cHHRadius div 2;
+ dmgBase:= Gear^.Boom shl 1 + cHHRadius div 2;
partyEpicness:= 0;
gi := GearsList;
while gi <> nil do
@@ -3215,7 +3268,7 @@
tdY:= gi^.Y-fY;
if hwRound(hwAbs(tdX)+hwAbs(tdY)) < dmgBase then
dmg:= dmgBase - max(hwRound(Distance(tdX, tdY)),gi^.Radius);
- if (dmg > 1) then dmg:= ModifyDamage(min(dmg div 2, cakeDmg), gi);
+ if (dmg > 1) then dmg:= ModifyDamage(min(dmg div 2, Gear^.Boom), gi);
if (dmg > 1) then
if (CurrentHedgehog^.Gear = gi) and (gi^.Hedgehog^.Effects[heInvulnerable] = 0) then
begin
@@ -3273,7 +3326,7 @@
if Gear^.Health mod 100 = 0 then
Gear^.PortalCounter:= 0;
// This is not seconds, but at least it is *some* feedback
- if (Gear^.Health = 0) or ((Gear^.Message and gmAttack) <> 0) then
+ if (Gear^.Health <= 0) or ((Gear^.Message and gmAttack) <> 0) then
begin
FollowGear := Gear;
Gear^.RenderTimer := false;
@@ -3308,12 +3361,14 @@
AllInactive := false;
inc(Gear^.Tag);
- if Gear^.Tag < 100 then
+ // Animation delay. Skipped if cake only dropped a very short distance.
+ if (Gear^.Tag < 100) and (Gear^.FlightTime > 1) then
exit;
Gear^.Tag := 0;
- if Gear^.Pos = 6 then
- begin
+ if (Gear^.Pos = 6) or (Gear^.FlightTime <= 1) then
+ begin
+ Gear^.Pos := 6;
cakeData:= PCakeData(Gear^.Data);
with cakeData^ do
begin
@@ -3324,6 +3379,13 @@
end;
CakeI := 0;
end;
+ (* This is called frequently if the cake is completely stuck.
+ With this a stuck cake takes equally long to explode then
+ a normal cake. Removing this code just makes the cake walking
+ for a few seconds longer. *)
+ if (Gear^.FlightTime <= 1) and (Gear^.Health > 2) then
+ dec(Gear^.Health);
+ Gear^.FlightTime := 0;
Gear^.doStep := @doStepCakeWalk
end
else
@@ -3335,6 +3397,8 @@
AllInactive := false;
Gear^.dY := Gear^.dY + cGravity;
+ // FlightTime remembers the drop time
+ inc(Gear^.FlightTime);
if TestCollisionYwithGear(Gear, 1) <> 0 then
Gear^.doStep := @doStepCakeUp
else
@@ -3369,7 +3433,12 @@
with hogs.ar^[i]^ do
if (hogs.ar^[i] <> CurrentHedgehog^.Gear) and (Hedgehog^.Effects[heFrozen] = 0) then
begin
- dX:= _50 * cGravity * (Gear^.X - X) / _25;
+ if (WorldEdge <> weWrap) or (not (hwAbs(Gear^.X - X) > int2hwFloat(Gear^.Radius))) then
+ dX:= _50 * cGravity * (Gear^.X - X) / _25
+ else if (not (hwAbs(Gear^.X + int2hwFloat(RightX-LeftX) - X) > int2hwFloat(Gear^.Radius))) then
+ dX:= _50 * cGravity * ((Gear^.X + int2hwFloat(RightX-LeftX)) - X) / _25
+ else
+ dX:= _50 * cGravity * ((Gear^.X - int2hwFloat(RightX-LeftX)) - X) / _25;
dY:= -_450 * cGravity;
Active:= true;
end
@@ -3416,18 +3485,47 @@
PlaySound(sndYoohoo);
end;
- if (Gear^.Pos = 14) and (RealTicks and $3 = 0) then
+
+ // note: use GameTicks, not RealTicks, otherwise amount can vary greatly
+ if (Gear^.Pos = 14) and (GameTicks and $1 = 0) then
begin
heart:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtStraightShot);
if heart <> nil then
with heart^ do
begin
+ { // old calcs
dx:= 0.001 * (random(200));
dy:= 0.001 * (random(200));
if random(2) = 0 then
dx := -dx;
if random(2) = 0 then
dy := -dy;
+ }
+
+ // randomize speed in both directions
+ dx:= 0.001 * (random(201));
+ dy:= 0.001 * (random(201));
+
+ // half of hearts go down
+ if random(2) = 0 then
+ begin
+ // create a pointy shape
+ if 0.2 < dx + dy then
+ begin
+ dy:= 0.2 - dy;
+ dx:= 0.2 - dx;
+ end;
+ // sin bulge it out a little to avoid corners on the side
+ dx:= dx + (dx/0.2) * ((0.2 * sin(pi * ((0.2 - dy) / 0.4))) - (0.2 - dy));
+ // change sign
+ dy:= -dy;
+ end
+ else // shape hearts on top into 2 arcs
+ dy:= dy * (0.3 + 0.7 * sin(pi * dx / 0.2));
+
+ // half of the hearts go left
+ if random(2) = 0 then
+ dx := -dx;
FrameTicks:= random(750) + 1000;
State:= ord(sprSeduction)
end;
@@ -3799,8 +3897,10 @@
end;
if HHGear <> nil then
+ begin
HHGear^.Message := 0;
- ParseCommand('/taunt ' + #1, true)
+ PlayTaunt(1)
+ end
end
end;
@@ -3859,7 +3959,11 @@
bubble^.dY:= random(20)/10+0.1;
end
end
- else HHGear^.dY := HHGear^.dY - move;
+ else
+ begin
+ PlaySound(sndJetpackBoost);
+ HHGear^.dY := HHGear^.dY - move;
+ end
end;
dec(Gear^.Health, fuel);
Gear^.MsgParam := Gear^.MsgParam or gmUp;
@@ -3885,7 +3989,8 @@
else bubble^.X := bubble^.X - 28;
end;
end
- end;
+ end
+ else PlaySound(sndJetpackBoost);
dec(Gear^.Health, fuel div 5);
Gear^.MsgParam := Gear^.MsgParam or (HHGear^.Message and (gmLeft or gmRight));
Gear^.Timer := GameTicks
@@ -3948,6 +4053,8 @@
State := State or gstMoving
end;
DeleteGear(Gear);
+ if (GetAmmoEntry(HHGear^.Hedgehog^, amJetpack)^.Count >= 1) and ((Ammoz[HHGear^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
+ HHGear^.Hedgehog^.CurAmmoType:= amJetpack;
isCursorVisible := false;
ApplyAmmoChanges(HHGear^.Hedgehog^);
// if Gear^.Tex <> nil then FreeTexture(Gear^.Tex);
@@ -3966,6 +4073,8 @@
Gear^.doStep := @doStepJetpackWork;
HHGear := Gear^.Hedgehog^.Gear;
+
+ PlaySound(sndJetpackLaunch);
FollowGear := HHGear;
AfterAttack;
with HHGear^ do
@@ -4114,8 +4223,9 @@
dec(Gear^.Timer, 1);
HHGear := Gear^.Hedgehog^.Gear;
- if HHGear = nil then
- begin
+ if (HHGear = nil) or ((HHGear^.State and gstHHDriven) = 0) then
+ begin
+ Gear^.Hedgehog := nil;
Gear^.Timer := 0;
Gear^.State := Gear^.State or gstAnimation or gstTmpFlag;
Gear^.Timer := 0;
@@ -4225,6 +4335,7 @@
with CurrentHedgehog^ do
if (CurAmmoType = amPortalGun) then
begin
+ PlaySound(sndPortalSwitch);
CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and (not gmSwitch);
CurWeapon:= GetCurAmmoEntry(CurrentHedgehog^);
@@ -4339,6 +4450,10 @@
if not ((Gear^.dX*ox + Gear^.dY*oy).isNegative) then
continue;
+ if iterator^.Kind = gtDuck then
+ // Make duck go into “falling” mode again
+ iterator^.Pos:= 0;
+
isbullet:= (iterator^.Kind in [gtShotgunShot, gtDEagleShot, gtSniperRifleShot, gtSineGunShot]);
r:= int2hwFloat(iterator^.Radius);
@@ -4369,7 +4484,7 @@
if (iterator^.Kind = gtDEagleShot) or (iterator^.Kind = gtSniperRifleShot) then
begin
// draw bullet trail
- spawnBulletTrail(iterator);
+ spawnBulletTrail(iterator, iterator^.X, iterator^.Y);
// the bullet can now hurt the hog that fired it
iterator^.Data:= nil;
end;
@@ -4636,6 +4751,7 @@
if ((Gear^.LinkedGear = nil)
or (hwRound(Distance(Gear^.X - Gear^.LinkedGear^.X,Gear^.Y-Gear^.LinkedGear^.Y)) >=Gear^.Radius*2)) then
begin
+ PlaySound(sndPortalOpen);
loadNewPortalBall(Gear, false);
inc(Gear^.Tag);
Gear^.doStep := @doStepPortal;
@@ -4678,6 +4794,8 @@
newPortal^.LinkedGear := nil;
+ PlaySound(sndPortalShot);
+
if CurrentHedgehog <> nil then
with CurrentHedgehog^ do
begin
@@ -4720,7 +4838,7 @@
iterator:= GearsList;
while iterator <> nil do
begin
- if not (iterator^.Kind in [gtPortal, gtAirAttack, gtKnife]) and ((iterator^.Hedgehog <> CurrentHedgehog)
+ if not (iterator^.Kind in [gtPortal, gtAirAttack, gtKnife, gtSMine]) and ((iterator^.Hedgehog <> CurrentHedgehog)
or ((iterator^.Message and gmAllStoppable) = 0)) then
begin
iterator^.Active:= true;
@@ -4773,6 +4891,7 @@
begin
Gear^.Y:= Gear^.Y + _50;
OnUsedAmmo(CurrentHedgehog^);
+ uStats.HedgehogSacrificed(CurrentHedgehog);
if CurrentHedgehog^.Gear <> nil then
begin
// Drown the hedgehog. Could also just delete it, but hey, this gets a caption
@@ -4796,6 +4915,7 @@
begin
Gear^.Y:= Gear^.Y + _50;
OnUsedAmmo(CurrentHedgehog^);
+ uStats.HedgehogSacrificed(CurrentHedgehog);
if CurrentHedgehog^.Gear <> nil then
begin
// Drown the hedgehog. Could also just delete it, but hey, this gets a caption
@@ -5242,7 +5362,7 @@
procedure doStepHammer(Gear: PGear);
var HHGear, tmp, tmp2: PGear;
t: PGearArray;
- i, dmg, d: LongInt;
+ i, dmg: LongInt;
begin
HHGear:= Gear^.Hedgehog^.Gear;
HHGear^.State:= HHGear^.State or gstNoDamage;
@@ -5385,6 +5505,7 @@
resgear: PGear;
hh: PHedgehog;
i: LongInt;
+ s: ansistring;
begin
if (TurnTimeLeft > 0) then
dec(TurnTimeLeft);
@@ -5456,6 +5577,8 @@
RenderHealth(resgear^.Hedgehog^);
RecountTeamHealth(resgear^.Hedgehog^.Team);
resgear^.Hedgehog^.Effects[heResurrected]:= 1;
+ s:= ansistring(resgear^.Hedgehog^.Name);
+ AddCaption(FormatA(GetEventString(eidResurrected), s), cWhiteColor, capgrpMessage);
// only make hat-less hedgehogs look like zombies, preserve existing hats
if resgear^.Hedgehog^.Hat = 'NoHat' then
@@ -5659,11 +5782,13 @@
procedure doStepTardisWarp(Gear: PGear);
var HH: PHedgehog;
i,j,cnt: LongWord;
+ s: ansistring;
begin
HH:= Gear^.Hedgehog;
if Gear^.Pos = 2 then
begin
StopSoundChan(Gear^.SoundChannel);
+ Gear^.SoundChannel:= -1;
if (Gear^.Timer = 0) then
begin
if (HH^.Gear <> nil) and (HH^.Gear^.State and gstInvisible = 0) then
@@ -5676,7 +5801,11 @@
end
//else if (HH^.Gear <> nil) and (HH^.Gear^.State and gstInvisible <> 0) then
else if (HH^.GearHidden <> nil) then// and (HH^.Gear^.State and gstInvisible <> 0) then
- RestoreHog(HH)
+ begin
+ RestoreHog(HH);
+ s:= ansistring(HH^.Name);
+ AddCaption(FormatA(GetEventString(eidTimeTravelEnd), s), cWhiteColor, capgrpMessage)
+ end
end;
inc(Gear^.Timer);
@@ -5708,6 +5837,7 @@
if (Gear^.Pos = 3) and (Gear^.Power = 0) then
begin
StopSoundChan(Gear^.SoundChannel);
+ Gear^.SoundChannel:= -1;
if HH^.GearHidden = nil then
begin
DeleteGear(Gear);
@@ -5758,46 +5888,17 @@
end;
procedure doStepTardis(Gear: PGear);
-var i,j,cnt: LongWord;
- HH: PHedgehog;
+var HH: PHedgehog;
begin
-(*
- Conditions for not activating.
- 1. Hog is last of his clan
- 2. Sudden Death is in play
- 3. Hog is a king
-*)
HH:= Gear^.Hedgehog;
- if HH^.Gear <> nil then
- if (HH^.Gear = nil) or (HH^.King) or (SuddenDeathDmg) then
- begin
- if HH^.Gear <> nil then
- begin
- HH^.Gear^.Message := HH^.Gear^.Message and (not gmAttack);
- HH^.Gear^.State:= HH^.Gear^.State and (not gstAttacking);
- end;
+ if (not CanUseTardis(HH^.Gear)) then
+ begin
+ HH^.Gear^.Message := HH^.Gear^.Message and (not gmAttack);
+ HH^.Gear^.State:= HH^.Gear^.State and (not gstAttacking);
PlaySound(sndDenied);
- DeleteGear(gear);
+ DeleteGear(Gear);
exit
- end;
- cnt:= 0;
- for j:= 0 to Pred(HH^.Team^.Clan^.TeamsNumber) do
- for i:= 0 to Pred(HH^.Team^.Clan^.Teams[j]^.HedgehogsNumber) do
- if (HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear <> nil)
- and ((HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.State and gstDrowning) = 0)
- and (HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.Health > HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.Damage) then
- inc(cnt);
- if cnt < 2 then
- begin
- if HH^.Gear <> nil then
- begin
- HH^.Gear^.Message := HH^.Gear^.Message and (not gmAttack);
- HH^.Gear^.State:= HH^.Gear^.State and (not gstAttacking);
- end;
- PlaySound(sndDenied);
- DeleteGear(gear);
- exit
- end;
+ end;
Gear^.SoundChannel := LoopSound(sndTardis);
Gear^.doStep:= @doStepTardisWarp
end;
@@ -5964,7 +6065,7 @@
while iter <> nil do
begin
if (iter^.State and gstFrozen = 0) and
- ((iter^.Kind = gtExplosives) or (iter^.Kind = gtCase) or (iter^.Kind = gtMine)) and
+ ((iter^.Kind = gtExplosives) or (iter^.Kind = gtCase) or (iter^.Kind = gtMine) or (iter^.Kind = gtSMine)) and
(abs(LongInt(iter^.X.Round) - target.x) + abs(LongInt(iter^.Y.Round) - target.y) + 2 < 2 * iceRadius)
and (Distance(iter^.X - int2hwFloat(target.x), iter^.Y - int2hwFloat(target.y)) < int2hwFloat(iceRadius * 2)) then
begin
@@ -5992,6 +6093,16 @@
iter^.Damage := 0;
iter^.State := iter^.State and (not gstAttacking)
end
+ else if iter^.Kind = gtSMine then // disabe sticky mine and drop it into the water
+ begin
+ iter^.State:= iter^.State or gstFrozen;
+ iter^.CollisionMask:= 0;
+ vg:= AddVisualGear(hwRound(iter^.X) - 2 + Random(4), hwRound(iter^.Y) - 2 - Random(2), vgtSmoke);
+ if vg <> nil then
+ vg^.Scale:= 0.4;
+ PlaySound(sndVaporize);
+ iter^.State := iter^.State and (not gstAttacking)
+ end
else if iter^.Kind = gtCase then
begin
DeleteCI(iter);
@@ -6279,6 +6390,180 @@
and (TestCollisionYwithGear(Gear, 1) = 0) then Gear^.State:= Gear^.State and (not gstCollision) or gstMoving;
end
end;
+
+////////////////////////////////////////////////////////////////////////////////
+procedure doStepDuck(Gear: PGear);
+begin
+ // Mirror duck on bounce world edge, even turn around later
+ if WorldWrap(Gear) and (WorldEdge = weBounce) then
+ begin
+ Gear^.Tag:= Gear^.Tag * -1;
+ if Gear^.Pos = 2 then
+ Gear^.Pos:= 1
+ else if Gear^.Pos = 1 then
+ Gear^.Pos:= 2
+ else if Gear^.Pos = 5 then
+ Gear^.Pos:= 6
+ else if Gear^.Pos = 5 then
+ Gear^.Pos:= 5;
+ end;
+
+ AllInactive := false;
+
+ // Duck falls (Pos = 0)
+ if Gear^.Pos = 0 then
+ doStepFallingGear(Gear);
+
+ (* Check if duck is near water surface
+ (Karma is distance from water) *)
+ if (Gear^.Pos <> 1) and (Gear^.Pos <> 2) and (cWaterLine <= hwRound(Gear^.Y) + Gear^.Karma) then
+ begin
+ if cWaterLine = hwRound(Gear^.Y) + Gear^.Karma then
+ begin
+ // Let's make that duck swim!
+ // Does the duck come FROM the Sea edge? (left or right)
+ if (((Gear^.Pos = 3) or (Gear^.Pos = 7)) and (cWindSpeed > _0)) or (((Gear^.Pos = 4) or (Gear^.Pos = 8)) and (cWindSpeed < _0)) then
+ begin
+ PlaySound(sndDuckWater);
+ Gear^.DirAngle:= 0;
+ Gear^.Pos:= 1;
+ Gear^.dY:= _0;
+ end;
+
+ // Duck comes either falling (usual case) or was rising from below
+ if (Gear^.Pos = 0) or (Gear^.Pos = 5) or (Gear^.Pos = 6) then
+ begin
+ PlaySound(sndDroplet2);
+ if Gear^.dY > _0_4 then
+ PlaySound(sndDuckWater);
+ Gear^.Pos:= 1;
+ Gear^.dY:= _0;
+ end;
+ end
+ else if Gear^.Pos = 0 then
+ Gear^.Pos:= 5;
+ end;
+
+ // Manual speed handling when duck is on water
+ if Gear^.Pos <> 0 then
+ begin
+ Gear^.X:= Gear^.X + Gear^.dX;
+ Gear^.Y:= Gear^.Y + Gear^.dY;
+ end;
+
+ // Handle speed
+ // 1-4: On water: Let's swim!
+ if Gear^.Pos = 1 then
+ // On water (normal)
+ Gear^.dX:= cWindSpeed * Gear^.Damage
+ else if Gear^.Pos = 2 then
+ // On water, mirrored (after bounce edge bounce)
+ Gear^.dX:= -cWindSpeed * Gear^.Damage
+ else if Gear^.Pos = 3 then
+ // On left Sea edge
+ Gear^.dY:= cWindSpeed * Gear^.Damage
+ else if Gear^.Pos = 4 then
+ // On right Sea edge
+ Gear^.dY:= -cWindSpeed * Gear^.Damage
+ // 5-8: Underwater: Slowly rise to the surface and slightly follow wind
+ else if Gear^.Pos = 5 then
+ // Underwater (normal)
+ begin
+ Gear^.dX:= (cWindSpeed / 4) * Gear^.Damage;
+ Gear^.dY:= -_0_07;
+ end
+ else if Gear^.Pos = 6 then
+ // Underwater, mirrored duck (after bounce edge bounce)
+ begin
+ Gear^.dX:= -(cWindSpeed / 4) * Gear^.Damage;
+ Gear^.dY:= -_0_07;
+ end
+ else if Gear^.Pos = 7 then
+ // Inside left Sea edge
+ begin
+ Gear^.dX:= _0_07;
+ Gear^.dY:= (cWindSpeed / 4) * Gear^.Damage;
+ end
+ else if Gear^.Pos = 8 then
+ // Inside right Sea edge
+ begin
+ Gear^.dX:= -_0_07;
+ Gear^.dY:= -(cWindSpeed / 4) * Gear^.Damage;
+ end;
+
+
+ // Rotate duck and change direction when reaching Sea world edge (Pos 3 or 4)
+ if (WorldEdge = weSea) and (Gear^.Pos <> 3) and (Gear^.Pos <> 4) then
+ // Swimming TOWARDS left edge
+ if (LeftX >= hwRound(Gear^.X) - Gear^.Karma) and ((cWindSpeed < _0) or ((Gear^.Pos = 0) or (Gear^.Pos = 7))) then
+ begin
+ // Turn duck when reaching edge the first time
+ if (Gear^.Pos <> 3) and (Gear^.Pos <> 7) then
+ begin
+ if Gear^.Tag = 1 then
+ Gear^.DirAngle:= 90
+ else
+ Gear^.DirAngle:= 270;
+ end;
+
+ // Reaching the edge surface
+ if (LeftX = hwRound(Gear^.X) - Gear^.Karma) and (Gear^.Pos <> 3) then
+ // We are coming from the horizontal side
+ begin
+ PlaySound(sndDuckWater);
+ Gear^.dX:= _0;
+ Gear^.Pos:= 3;
+ end
+ else
+ // We are coming from inside the Sea, go into “surfacing” mode
+ Gear^.Pos:= 7;
+
+ end
+
+ // Swimming TOWARDS right edge (similar to left edge)
+ else if (RightX <= hwRound(Gear^.X) + Gear^.Karma) and ((cWindSpeed > _0) or ((Gear^.Pos = 0) or (Gear^.Pos = 8))) then
+ begin
+ if (Gear^.Pos <> 4) and (Gear^.Pos <> 8) then
+ begin
+ if Gear^.Tag = 1 then
+ Gear^.DirAngle:= 270
+ else
+ Gear^.DirAngle:= 90;
+ end;
+
+ if (RightX = hwRound(Gear^.X) + Gear^.Karma) and (Gear^.Pos <> 4) then
+ begin
+ PlaySound(sndDuckWater);
+ Gear^.dX:= _0;
+ Gear^.Pos:= 4;
+ end
+ else
+ Gear^.Pos:= 8;
+
+ end;
+
+
+ if Gear^.Pos <> 0 then
+ // Manual collision check required because we don't use onStepFallingGear in this case
+ CheckCollision(Gear);
+ if (Gear^.Timer = 0) or ((Gear^.State and gstCollision) <> 0) then
+ // Explode duck
+ begin
+ doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound);
+ PlaySound(sndDuckDie);
+ DeleteGear(Gear);
+ exit;
+ end;
+
+ // Update timer stuff
+ if Gear^.Timer < 6000 then
+ Gear^.RenderTimer:= true
+ else
+ Gear^.RenderTimer:= false;
+
+ dec(Gear^.Timer);
+end;
+
(*
This didn't end up getting used, but, who knows, might be reasonable for javellin or something
// Make the knife initial angle based on the hog attack angle, or is that too hard?
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uGearsHandlersRope.pas
--- a/hedgewars/uGearsHandlersRope.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uGearsHandlersRope.pas Sun Dec 17 00:09:24 2017 +0100
@@ -66,6 +66,8 @@
or (TestCollisionYwithGear(HHGear, 1) <> 0) then
begin
DeleteGear(Gear);
+ if (TestCollisionYwithGear(HHGear, 1) <> 0) and (GetAmmoEntry(HHGear^.Hedgehog^, amRope)^.Count >= 1) and ((Ammoz[HHGear^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
+ HHGear^.Hedgehog^.CurAmmoType:= amRope;
isCursorVisible := false;
ApplyAmmoChanges(HHGear^.Hedgehog^);
exit
@@ -441,6 +443,21 @@
end
else if not CurrentTeam^.ExtDriven and (FollowGear <> nil) then FollowGear := HHGear;
+ // Destroy rope if it touched bouncy or world wrap world edge.
+ // TODO: Allow to shoot rope through the world wrap edge and rope normally.
+ if (WorldWrap(Gear) and (WorldEdge = weWrap)) or
+ ((WorldEdge = weBounce) and ((hwRound(Gear^.X) <= LeftX) or (hwRound(Gear^.X) >= RightX))) then
+ begin
+ HHGear^.State := HHGear^.State and (not (gstAttacking or gstHHJumping or gstHHHJump));
+ HHGear^.Message := HHGear^.Message and (not gmAttack);
+ DeleteGear(Gear);
+ if (GetAmmoEntry(HHGear^.Hedgehog^, amRope)^.Count >= 1) and ((Ammoz[HHGear^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
+ HHGear^.Hedgehog^.CurAmmoType:= amRope;
+ isCursorVisible := false;
+ ApplyAmmoChanges(HHGear^.Hedgehog^);
+ exit()
+ end;
+
DeleteCI(HHGear);
if (HHGear^.State and gstMoving) <> 0 then
@@ -530,6 +547,10 @@
Message := Message and (not gmAttack)
end;
DeleteGear(Gear);
+ if (GetAmmoEntry(HHGear^.Hedgehog^, amRope)^.Count >= 1) and ((Ammoz[HHGear^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
+ HHGear^.Hedgehog^.CurAmmoType:= amRope;
+ isCursorVisible := false;
+ ApplyAmmoChanges(HHGear^.Hedgehog^);
exit;
end;
if CheckGearDrowning(HHGear) then DeleteGear(Gear)
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uGearsHedgehog.pas
--- a/hedgewars/uGearsHedgehog.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uGearsHedgehog.pas Sun Dec 17 00:09:24 2017 +0100
@@ -30,6 +30,7 @@
procedure PickUp(HH, Gear: PGear);
procedure AddPickup(HH: THedgehog; ammo: TAmmoType; cnt, X, Y: LongWord);
procedure CheckIce(Gear: PGear); inline;
+procedure PlayTaunt(taunt: Longword);
implementation
uses uConsts, uVariables, uFloat, uAmmos, uSound, uCaptions,
@@ -325,6 +326,19 @@
newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtSniperRifleShot, 0, xx * _0_5, yy * _0_5, 0);
end;
amDynamite: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtDynamite, 0, SignAs(_0_03, dX), _0, 5000);
+ amDuck: begin
+ // Does duck spawn inside water?
+ if (LeftX > hwRound(Gear^.X) - Gear^.Karma) or (RightX < hwRound(Gear^.X) + Gear^.Karma) or (cWaterLine < hwRound(Gear^.Y) + Gear^.Karma) then
+ PlaySound(sndDroplet2)
+ else
+ // Duck spawned in air, normal drop sound
+ PlaySound(sndDuckDrop);
+ newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtDuck, 0, SignAs(_0_03, dX), _0, 0);
+ if not ((not dX.isNegative) xor ((State and gstHHHJump) <> 0)) then
+ newGear^.Tag:= -1
+ else
+ newGear^.Tag:= 1;
+ end;
amFirePunch: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtFirePunch, 0, xx, _0, 0);
amWhip: begin
newGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtWhip, 0, SignAs(_1, dX), - _0_8, 0);
@@ -378,18 +392,25 @@
amLowGravity: begin
PlaySound(sndLowGravity);
cGravity:= cMaxWindSpeed;
- cGravityf:= 0.00025
+ cGravityf:= 0.00025;
+ cLowGravity := true
end;
amExtraDamage: begin
PlaySound(sndHellishImpact4);
cDamageModifier:= _1_5
end;
- amInvulnerable: Effects[heInvulnerable]:= 1;
+ amInvulnerable: begin
+ PlaySound(sndInvulnerable);
+ Effects[heInvulnerable]:= 1
+ end;
amExtraTime: begin
PlaySound(sndExtraTime);
TurnTimeLeft:= TurnTimeLeft + 30000
end;
- amLaserSight: cLaserSighting:= true;
+ amLaserSight: begin
+ PlaySound(sndLaserSight);
+ cLaserSighting:= true
+ end;
amVampiric: begin
PlaySoundV(sndOw1, Team^.voicepack);
cVampiric:= true;
@@ -552,10 +573,12 @@
if (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0) and CheckCoordInWater(hwRound(CurAmmoGear^.X), hwRound(CurAmmoGear^.Y)) then
TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 25
else TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 100;
+ IsGetAwayTime := true;
end;
if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) and (HHGear <> nil) then
HHGear^.State:= HHGear^.State or gstAttacked;
- if (Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) <> 0 then
+ if (a = amNothing) or ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) <> 0) or
+ (((GameFlags and gfInfAttack) <> 0) and ((Ammoz[a].Ammo.Propz and ammoprop_ForceTurnEnd) = 0)) then
ApplyAmmoChanges(CurrentHedgehog^)
end;
end
@@ -655,32 +678,45 @@
procedure AddPickup(HH: THedgehog; ammo: TAmmoType; cnt, X, Y: LongWord);
var s: ansistring;
+ name: ansistring;
vga: PVisualGear;
begin
if cnt <> 0 then AddAmmo(HH, ammo, cnt)
else AddAmmo(HH, ammo);
- if (not (HH.Team^.ExtDriven
- or (HH.BotLevel > 0)))
- or (HH.Team^.Clan^.ClanIndex = LocalClan)
- or (GameType = gmtDemo) then
+ if IsHogLocal(@HH) then
begin
- if cnt <> 0 then
- s:= trammo[Ammoz[ammo].NameId] + ansistring(' (+' + IntToStr(cnt) + ')')
+ if length(trluaammo[Ammoz[ammo].NameId]) > 0 then
+ name:= trluaammo[Ammoz[ammo].NameId]
else
- s:= trammo[Ammoz[ammo].NameId] + ansistring(' (+' + IntToStr(Ammoz[ammo].NumberInCase) + ')');
+ name:= trammo[Ammoz[ammo].NameId];
+
+ if cnt = 0 then
+ cnt:= Ammoz[ammo].NumberInCase;
+
+ if (ammo = amNothing) or (cnt = 0) then
+ s:= trmsg[sidEmptyCrate]
+ else if cnt >= AMMO_INFINITE then
+ s:= name + ansistring(' (+∞)')
+ else
+ s:= name + ansistring(' (+' + IntToStr(cnt) + ')');
+
AddCaption(s, HH.Team^.Clan^.Color, capgrpAmmoinfo);
- // show ammo icon
- vga:= AddVisualGear(X, Y, vgtAmmo);
- if vga <> nil then
- vga^.Frame:= Longword(ammo);
+ // show ammo icon (if not empty)
+ if (ammo <> amNothing) and (cnt <> 0) then
+ begin
+ vga:= AddVisualGear(X, Y, vgtAmmo);
+ if vga <> nil then
+ vga^.Frame:= Longword(ammo);
+ end
+
end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure PickUp(HH, Gear: PGear);
-var s: shortstring;
+var s: ansistring;
i: LongInt;
vga: PVisualGear;
ag, gi: PGear;
@@ -732,13 +768,13 @@
PlaySound(sndShotgunReload);
inc(HH^.Health, Gear^.Health);
HH^.Hedgehog^.Effects[hePoisoned] := 0;
- s:= '+' + IntToStr(Gear^.Health);
- AddCaption(ansistring(s), HH^.Hedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
+ s:= IntToStr(Gear^.Health);
+ AddCaption(FormatA(trmsg[sidHealthGain], s), HH^.Hedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
RenderHealth(HH^.Hedgehog^);
RecountTeamHealth(HH^.Hedgehog^.Team);
i:= 0;
- while i < Gear^.Health do
+ while (i < Gear^.Health) and (i <= 1000) do
begin
vga:= AddVisualGear(hwRound(HH^.X), hwRound(HH^.Y), vgtStraightShot);
if vga <> nil then
@@ -927,6 +963,7 @@
var isFalling, isUnderwater: boolean;
land: Word;
cnt: LongWord;
+ s: ansistring;
begin
if Gear^.Hedgehog^.Unplaced then
begin
@@ -1178,7 +1215,8 @@
if (Gear^.FlightTime > 1500) and ((hwRound(Gear^.X) < LongInt(leftX)-250) or (hwRound(Gear^.X) > LongInt(rightX)+250)) then
begin
Gear^.FlightTime:= 0;
- AddCaption(GetEventString(eidHomerun), cWhiteColor, capgrpMessage);
+ s:= ansistring(CurrentHedgehog^.Name);
+ AddCaption(FormatA(GetEventString(eidHomerun), s), cWhiteColor, capgrpMessage);
PlaySound(sndHomerun)
end;
end
@@ -1194,28 +1232,41 @@
var t: PGear;
wasJumping: boolean;
Hedgehog: PHedgehog;
+ s: ansistring;
begin
Hedgehog:= HHGear^.Hedgehog;
if not isInMultiShoot then
AllInactive:= false
else if Hedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle] then
- HHGear^.Message:= 0;
+ HHGear^.Message:= HHGear^.Message and gmPrecise;
if ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_Utility) <> 0) and isInMultiShoot then
AllInactive:= true
else if not isInMultiShoot then
AllInactive:= false;
-if (TurnTimeLeft = 0) or (HHGear^.Damage > 0) then
+if (TurnTimeLeft = 0) or (HHGear^.Damage > 0) or (LuaEndTurnRequested = true) then
begin
if (Hedgehog^.CurAmmoType = amKnife) then
LoadHedgehogHat(Hedgehog^, Hedgehog^.Hat);
if TagTurnTimeLeft = 0 then
TagTurnTimeLeft:= TurnTimeLeft;
TurnTimeLeft:= 0;
+ if (GameOver = false) and ((GameFlags and gfInfAttack) = 0) and ((HHGear^.State and gstAttacked) = 0) and (HHGear^.Damage = 0) and (LuaNoEndTurnTaunts = false) then
+ begin
+ AddVoice(sndBoring, Hedgehog^.Team^.voicepack);
+ if (GameFlags and gfInfAttack = 0) then
+ begin
+ s:= Hedgehog^.Name;
+ AddCaption(FormatA(GetEventString(eidTimeout), s), cWhiteColor, capgrpMessage);
+ end;
+ end;
isCursorVisible:= false;
HHGear^.State:= HHGear^.State and (not (gstHHDriven or gstAnimation or gstAttacking));
AttackBar:= 0;
+ StopSound(sndThrowPowerUp);
+ LuaEndTurnRequested:= false;
+ LuaNoEndTurnTaunts:= false;
if HHGear^.Damage > 0 then
HHGear^.State:= HHGear^.State and (not (gstHHJumping or gstHHHJump));
exit
@@ -1375,7 +1426,10 @@
Gear^.doStep:= @doStepHedgehogDead;
// Death message
s:= ansistring(Gear^.Hedgehog^.Name);
- AddCaption(FormatA(GetEventString(eidDied), s), cWhiteColor, capgrpMessage);
+ if Gear^.Hedgehog^.King then
+ AddCaption(FormatA(GetEventString(eidKingDied), s), cWhiteColor, capgrpMessage)
+ else
+ AddCaption(FormatA(GetEventString(eidDied), s), cWhiteColor, capgrpMessage);
end;
end
else
@@ -1498,4 +1552,15 @@
end;
end;
+procedure PlayTaunt(taunt: Longword);
+begin
+ if CurrentHedgehog^.Gear <> nil then
+ with CurrentHedgehog^.Gear^ do
+ begin
+ Message:= Message or (gmAnimate and InputMask);
+ MsgParam:= taunt;
+ ScriptCall('onTaunt', MsgParam);
+ end
+end;
+
end.
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uGearsList.pas
--- a/hedgewars/uGearsList.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uGearsList.pas Sun Dec 17 00:09:24 2017 +0100
@@ -105,6 +105,7 @@
(* gtAddAmmo *) , amNothing
(* gtGenericFaller *) , amNothing
(* gtKnife *) , amKnife
+(* gtDuck *) , amDuck
);
@@ -263,6 +264,7 @@
else Gear^.Boom := 3;
gtPoisonCloud: Gear^.Boom := 20;
gtKnife: Gear^.Boom := 40000; // arbitrary scaling factor since impact-based
+ gtDuck: Gear^.Boom := 40;
end;
case Kind of
@@ -507,7 +509,11 @@
gear^.Density:= _1_5;
gear^.RenderTimer:= true
end;
- gtShover: gear^.Radius:= 20;
+ gtShover: begin
+ gear^.Radius:= 20;
+ gear^.Tag:= 0;
+ gear^.Timer:= 50;
+ end;
gtFlame: begin
gear^.Tag:= GetRandom(32);
gear^.Radius:= 1;
@@ -574,6 +580,8 @@
gear^.Z:= cOnHHZ;
gear^.RenderTimer:= false;
gear^.DirAngle:= -90 * hwSign(Gear^.dX);
+ gear^.FlightTime:= 100; // (roughly) ticks spent dropping, used to skip getting up anim when stuck.
+ // Initially set to a high value so cake has at least one getting up anim.
if not dX.isNegative then
gear^.Angle:= 1
else
@@ -631,6 +639,8 @@
gtMolotov: begin
gear^.AdvBounce:= 1;
gear^.Radius:= 6;
+ gear^.Elasticity:= _0_8;
+ gear^.Friction:= _0_8;
gear^.Density:= _2
end;
gtBirdy: begin
@@ -713,6 +723,24 @@
gear^.Health:= 1000;
gear^.Radius:= 8;
end;
+ gtDuck: begin
+ gear^.Pos:= 0; // 0: in air, 1-4: on water, 5-8: underwater
+ // 1: bottom, 2: bottom (mirrored),
+ // 3: left Sea edge, 4: right Sea edge
+ // 6: bottom, 7: bottom (mirrored)
+ // 7: left Sea edge, 8: right Sea edge
+ gear^.Tag:= 1; // 1: facing right, -1: facing left
+ if gear^.Timer = 0 then
+ gear^.Timer:= 15000; // Explosion timer to avoid duck existing forever
+ gear^.Radius:= 9; // Collision radius (with landscape)
+ gear^.Karma:= 24; // Distance from water when swimming
+ gear^.Damage:= 500; // Speed factor when swimming on water (multiplied with wind speed)
+ gear^.State:= gear^.State or gstSubmersible;
+ gear^.Elasticity:= _0_6;
+ gear^.Friction:= _0_8;
+ gear^.Density:= _0_5;
+ gear^.AdvBounce:= 1;
+ end;
gtGenericFaller:begin
gear^.AdvBounce:= 1;
gear^.Radius:= 1;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uGearsRender.pas
--- a/hedgewars/uGearsRender.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uGearsRender.pas Sun Dec 17 00:09:24 2017 +0100
@@ -36,6 +36,7 @@
rounded : array[0..MAXROPEPOINTS + 2] of TVertex2f;
end;
procedure RenderGear(Gear: PGear; x, y: LongInt);
+procedure RenderGearTimer(Gear: PGear; x, y: LongInt);
procedure DrawHHOrder();
var RopePoints: record
@@ -382,7 +383,7 @@
*)
dx:= sign * m * Sin(Gear^.Angle * pi / cMaxAngle);
dy:= -Cos(Gear^.Angle * pi / cMaxAngle);
- if cLaserSighting then
+ if cLaserSighting or cLaserSightingSniper then
begin
lx:= GetLaunchX(HH^.CurAmmoType, sign * m, Gear^.Angle);
ly:= GetLaunchY(HH^.CurAmmoType, Gear^.Angle);
@@ -536,7 +537,6 @@
end;
defaultPos:= false
end;
- gtShover: DrawSpriteRotated(sprHandBaseball, hx, hy, sign, aangle + 180);
gtFirePunch:
begin
DrawHedgehog(sx, sy,
@@ -633,13 +633,18 @@
case CurAmmoGear^.Kind of
gtShotgunShot,
gtDEagleShot,
- gtSniperRifleShot,
- gtShover:
+ gtSniperRifleShot:
begin
DrawHedgehog(sx, sy, sign, 0, 4, 0);
defaultPos:= false;
HatVisible:= true
- end
+ end;
+ gtShover:
+ begin
+ DrawHedgehog(sx, sy, sign, 0, 5, 0);
+ defaultPos:= false;
+ HatVisible:= true
+ end
end
end else
@@ -725,6 +730,7 @@
amSkip: DrawSpriteRotated(sprHandSkip, hx, hy, sign, aangle);
amClusterBomb: DrawSpriteRotated(sprHandCluster, hx, hy, sign, aangle);
amDynamite: DrawSpriteRotated(sprHandDynamite, hx, hy, sign, aangle);
+ amDuck: DrawSpriteRotatedF(sprHandDuck, hx, hy, 0, sign, aangle);
amHellishBomb: DrawSpriteRotated(sprHandHellish, hx, hy, sign, aangle);
amGasBomb: DrawSpriteRotated(sprHandCheese, hx, hy, sign, aangle);
amMine: DrawSpriteRotated(sprHandMine, hx, hy, sign, aangle);
@@ -789,6 +795,7 @@
case amt of
amAirAttack,
+ amNapalm,
amMineStrike,
amDrillStrike: DrawSpriteRotated(sprHandAirAttack, sx, oy, sign, 0);
amPickHammer: DrawHedgehog(sx, sy,
@@ -796,7 +803,8 @@
1,
2,
0);
- amTeleport: DrawSpriteRotatedF(sprTeleport, sx, sy, 0, sign, 0);
+ amTeleport,
+ amPiano: DrawSpriteRotatedF(sprTeleport, sx, sy, 0, sign, 0);
amKamikaze: DrawHedgehog(sx, sy,
sign,
1,
@@ -814,6 +822,15 @@
0,
sign,
0);
+ amBaseballBat:
+ begin
+ HatVisible:= true;
+ DrawHedgehog(sx, sy,
+ sign,
+ 0,
+ 5,
+ 0);
+ end
else
DrawHedgehog(sx, sy,
sign,
@@ -836,9 +853,9 @@
end;
case amt of
- amBaseballBat: DrawSpriteRotated(sprHandBaseball,
- sx - 4 * sign,
- sy + 9, sign, aangle);
+ amBaseballBat: DrawSpritePivotedF(sprHandBaseball,
+ sx + 9 * sign,
+ sy + 2, 0, sign, -8, 1, aangle);
end;
defaultPos:= false
@@ -916,26 +933,66 @@
and (HatVisibility > 0) then
if DefaultPos then
begin
- DrawTextureF(curhat,
- HatVisibility,
- sx,
- sy - 5,
- (RealTicks div 128 + Gear^.Pos) mod 19,
- sign,
- 32,
- 32);
- if curhat^.w > 64 then
+ // Simple hat with automatic offset
+ if (curhat^.h = 32) and ((curhat^.w = 32) or (curhat^.w = 64)) then
begin
- Tint(HH^.Team^.Clan^.Color shl 8 or $FF);
+ // Frame
+ tx := (RealTicks div 128 + Gear^.Pos) mod 19;
+ // Hat offset
+ ty := 0;
+ if (tx = 2) or (tx = 7) or (tx = 12) then
+ ty := 1
+ else if tx = 16 then
+ ty := -1;
+ // First frame: No tint
+ DrawTextureF(curhat,
+ HatVisibility,
+ sx,
+ sy - 5 + ty,
+ 0,
+ sign,
+ 32,
+ 32);
+ // Second frame: Clan tint (if present)
+ if (curhat^.w = 64) then
+ begin
+ Tint(HH^.Team^.Clan^.Color shl 8 or $FF);
+ DrawTextureF(curhat,
+ HatVisibility,
+ sx,
+ sy - 5 + ty,
+ 1,
+ sign,
+ 32,
+ 32);
+ untint
+ end
+ end
+ else
+ // Classic animated hat (all frames drawn manually)
+ begin
DrawTextureF(curhat,
HatVisibility,
sx,
sy - 5,
- (RealTicks div 128 + Gear^.Pos) mod 19 + 32,
+ (RealTicks div 128 + Gear^.Pos) mod 19,
sign,
32,
32);
- untint
+ // Apply clan tint
+ if curhat^.w > 64 then
+ begin
+ Tint(HH^.Team^.Clan^.Color shl 8 or $FF);
+ DrawTextureF(curhat,
+ HatVisibility,
+ sx,
+ sy - 5,
+ (RealTicks div 128 + Gear^.Pos) mod 19 + 32,
+ sign,
+ 32,
+ 32);
+ untint
+ end
end;
if HH^.Team^.hasGone then untint
end
@@ -949,14 +1006,18 @@
sign*m,
32,
32);
- if curhat^.w > 64 then
+ if (curhat^.w > 64) or ((curhat^.w = 64) and (curhat^.h = 32)) then
begin
+ if ((curhat^.w = 64) and (curhat^.h = 32)) then
+ tx := 1
+ else
+ tx := 32;
Tint(HH^.Team^.Clan^.Color shl 8 or $FF);
DrawTextureF(curhat,
HatVisibility,
sx,
sy - 5,
- 32,
+ tx,
sign*m,
32,
32);
@@ -973,8 +1034,21 @@
amJetpack: DrawSprite(sprJetpack, sx-32, sy-32, 0);
end
end; *)
- if CurAmmoGear <> nil then
+ if (CurAmmoGear = nil) then
+ begin
+ if ((Gear^.State and (gstAttacked or gstAnimation or gstHHJumping)) = 0)
+ and (Gear^.Message and (gmLeft or gmRight) = 0) then
begin
+ amt:= CurrentHedgehog^.CurAmmoType;
+ case amt of
+ amBaseballBat: DrawSpritePivotedF(sprHandBaseball,
+ sx + 9 * sign, sy + 2, 0, sign, -8, 1, aangle);
+ end;
+ end;
+ end
+ else
+ begin
+ aangle:= Gear^.Angle * 180 / cMaxAngle - 90;
case CurAmmoGear^.Kind of
gtJetpack: begin
DrawSprite(sprJetpack, sx-32, sy-32, 0);
@@ -991,6 +1065,7 @@
DrawTextureCentered(sx, sy - 40, CurAmmoGear^.Tex);
DrawAltWeapon(Gear, sx, sy)
end;
+ gtShover: DrawSpritePivotedF(sprHandBaseball, sx + 9 * sign, sy + 2, CurAmmoGear^.Tag, sign, -8, 1, aangle);
end;
end
end;
@@ -1168,17 +1243,17 @@
gtShell: DrawSpriteRotated(sprBazookaShell, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
gtGrave: begin
- DrawTextureF(Gear^.Hedgehog^.Team^.GraveTex, 1, x, y, (GameTicks shr 7+Gear^.uid) and 7, 1, 32, 32);
+ DrawTextureF(Gear^.Hedgehog^.Team^.GraveTex, 1, x, y, (RealTicks shr 7+Gear^.uid) and 15, 1, 32, 32);
if Gear^.Health > 0 then
begin
//Tint($33, $33, $FF, max($40, round($FF * abs(1 - (GameTicks mod (6000 div Gear^.Health)) / 750))));
- Tint($f5, $db, $35, max($40, round($FF * abs(1 - (GameTicks mod 1500) / (750 + Gear^.Health)))));
+ Tint($f5, $db, $35, max($40, round($FF * abs(1 - (RealTicks mod 1500) / (750 + Gear^.Health)))));
//Tint($FF, $FF, $FF, max($40, round($FF * abs(1 - (RealTicks mod 1500) / 750))));
DrawSprite(sprVampiric, x - 24, y - 24, 0);
untint
end
end;
- gtBee: DrawSpriteRotatedF(sprBee, x, y, (GameTicks shr 5) mod 2, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+ gtBee: DrawSpriteRotatedF(sprBee, x, y, (RealTicks shr 5) mod 2, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
gtPickHammer: DrawSprite(sprPHammer, x - 16, y - 50 + LongInt(((GameTicks shr 5) and 1) * 2), 0);
gtRope: DrawRope(Gear);
@@ -1218,7 +1293,7 @@
DrawSprite(sprCase, x - 24, y - 28, 0)
else
begin
- i:= (GameTicks shr 6) mod 64;
+ i:= (RealTicks shr 6) mod 64;
if i > 18 then i:= 0;
DrawSprite(sprCase, x - 24, y - 24, i)
end
@@ -1229,7 +1304,7 @@
DrawSprite(sprFAid, x - 24, y - 28, 0)
else
begin
- i:= ((GameTicks shr 6) + 38) mod 64;
+ i:= ((RealTicks shr 6) + 38) mod 64;
if i > 13 then i:= 0;
DrawSprite(sprFAid, x - 24, y - 24, i)
end
@@ -1240,7 +1315,7 @@
DrawSprite(sprUtility, x - 24, y - 28, 0)
else
begin
- i:= (GameTicks shr 6) mod 70;
+ i:= (RealTicks shr 6) mod 70;
if i > 23 then i:= 0;
i:= i mod 12;
DrawSprite(sprUtility, x - 24, y - 24, i)
@@ -1258,7 +1333,7 @@
DrawSprite(sprExplosivesRoll, x - 24, y - 24, 0)
else if Gear^.State and gstAnimation = 0 then
begin
- i:= (GameTicks shr 6 + Gear^.uid*3) mod 64;
+ i:= (RealTicks shr 6 + Gear^.uid*3) mod 64;
if i > 18 then
i:= 0;
DrawSprite(sprExplosives, x - 24, y - 24, i)
@@ -1294,8 +1369,8 @@
gtClusterBomb: DrawSpriteRotated(sprClusterBomb, x, y, 0, Gear^.DirAngle);
gtCluster: DrawSprite(sprClusterParticle, x - 8, y - 8, 0);
gtFlame: if Gear^.Tag and 1 = 0 then
- DrawTextureF(SpritesData[sprFlame].Texture, 2 / (Gear^.Tag mod 3 + 2), x, y, (GameTicks shr 7 + LongWord(Gear^.Tag)) mod 8, 1, 16, 16)
- else DrawTextureF(SpritesData[sprFlame].Texture, 2 / (Gear^.Tag mod 3 + 2), x, y, (GameTicks shr 7 + LongWord(Gear^.Tag)) mod 8, -1, 16, 16);
+ DrawTextureF(SpritesData[sprFlame].Texture, 2 / (Gear^.Tag mod 3 + 2), x, y, (RealTicks shr 7 + LongWord(Gear^.Tag)) mod 8, 1, 16, 16)
+ else DrawTextureF(SpritesData[sprFlame].Texture, 2 / (Gear^.Tag mod 3 + 2), x, y, (RealTicks shr 7 + LongWord(Gear^.Tag)) mod 8, -1, 16, 16);
gtParachute: begin
DrawSprite(sprParachute, x - 24, y - 48, 0);
DrawAltWeapon(Gear, x + 1, y - 3)
@@ -1316,7 +1391,7 @@
DrawSpriteRotatedF(sprTeleport, hwRound(HHGear^.X) + 1 + WorldDx, hwRound(HHGear^.Y) - 3 + WorldDy, 11 - Gear^.Pos, hwSign(HHGear^.dX), 0)
end
end;
- gtSwitcher: DrawSprite(sprSwitch, x - 16, y - 56, (GameTicks shr 6) mod 12);
+ gtSwitcher: DrawSprite(sprSwitch, x - 16, y - 56, (RealTicks shr 6) mod 12);
gtTarget: begin
Tint($FF, $FF, $FF, round($FF * Gear^.Timer / 1000));
DrawSprite(sprTarget, x - 16, y - 16, 0);
@@ -1473,11 +1548,18 @@
end
end
end;
+ gtDuck: DrawSpriteRotatedF(sprDuck, x, y, 1, Gear^.Tag,
+ // replace with something based on dx/dy?
+ Gear^.DirAngle + 10-round(20 * abs(1 - (RealTicks mod round(0.1/max(0.00005,cWindSpeedf))) / round(0.05/max(0.00005,cWindSpeedf))) ));
gtGenericFaller: DrawCircle(x, y, 3, 3, $FF, $00, $00, $FF); // debug
end;
- if Gear^.RenderTimer and (Gear^.Tex <> nil) then
- DrawTextureCentered(x + 8, y + 8, Gear^.Tex);
if Gear^.State and gstFrozen <> 0 then untint
end;
+procedure RenderGearTimer(Gear: PGear; x, y: LongInt);
+begin
+if Gear^.RenderTimer and (Gear^.Tex <> nil) then
+ DrawTextureCentered(x + 8, y + 8, Gear^.Tex);
+end;
+
end.
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uGearsUtils.pas
--- a/hedgewars/uGearsUtils.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uGearsUtils.pas Sun Dec 17 00:09:24 2017 +0100
@@ -47,6 +47,7 @@
function GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): PGearArrayS;
procedure SpawnBoxOfSmth;
procedure ShotgunShot(Gear: PGear);
+function CanUseTardis(HHGear: PGear): boolean;
procedure SetAllToActive;
procedure SetAllHHToActive(Ice: boolean);
@@ -57,6 +58,7 @@
function WorldWrap(var Gear: PGear): boolean;
+function IsHogLocal(HH: PHedgehog): boolean;
function MakeHedgehogsStep(Gear: PGear) : boolean;
@@ -83,6 +85,7 @@
i, cnt: LongInt;
wrap: boolean;
bubble: PVisualGear;
+ s: ansistring;
begin
if Radius > 4 then AddFileLog('Explosion: at (' + inttostr(x) + ',' + inttostr(y) + ')');
if Radius > 25 then KickFlakes(Radius, X, Y);
@@ -174,8 +177,18 @@
Gear^.Active:= true;
if Gear^.Kind <> gtFlame then FollowGear:= Gear
end;
- if ((Mask and EXPLPoisoned) <> 0) and (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heInvulnerable] = 0) and (Gear^.State and gstHHDeath = 0) then
- Gear^.Hedgehog^.Effects[hePoisoned] := 5;
+ if ((Mask and EXPLPoisoned) <> 0) and (Gear^.Kind = gtHedgehog) and
+ (Gear^.Hedgehog^.Effects[heInvulnerable] = 0) and (Gear^.Hedgehog^.Effects[heFrozen] = 0) and
+ (Gear^.State and gstHHDeath = 0) then
+ begin
+ if Gear^.Hedgehog^.Effects[hePoisoned] = 0 then
+ begin
+ s:= ansistring(Gear^.Hedgehog^.Name);
+ AddCaption(FormatA(GetEventString(eidPoisoned), s), cWhiteColor, capgrpMessage);
+ uStats.HedgehogPoisoned(Gear, AttackingHog)
+ end;
+ Gear^.Hedgehog^.Effects[hePoisoned] := 5;
+ end
end;
end;
@@ -249,7 +262,7 @@
end;
procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource);
-var s: shortstring;
+var s: ansistring;
vampDmg, tmpDmg, i: Longword;
vg: PVisualGear;
begin
@@ -274,12 +287,12 @@
// was considering pulsing on attack, Tiy thinks it should be permanent while in play
//CurrentHedgehog^.Gear^.State:= CurrentHedgehog^.Gear^.State or gstVampiric;
inc(CurrentHedgehog^.Gear^.Health,vampDmg);
- s:= '+' + IntToStr(vampDmg);
- AddCaption(ansistring(s), CurrentHedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
+ s:= IntToStr(vampDmg);
+ AddCaption(FormatA(trmsg[sidHealthGain], s), CurrentHedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
RenderHealth(CurrentHedgehog^);
RecountTeamHealth(CurrentHedgehog^.Team);
i:= 0;
- while i < vampDmg do
+ while (i < vampDmg) and (i < 1000) do
begin
vg:= AddVisualGear(hwRound(CurrentHedgehog^.Gear^.X), hwRound(CurrentHedgehog^.Gear^.Y), vgtStraightShot);
if vg <> nil then
@@ -292,15 +305,16 @@
end;
end
end;
- if (GameFlags and gfKarma <> 0) and (GameFlags and gfInvulnerable = 0) and
- (CurrentHedgehog^.Effects[heInvulnerable] = 0) then
- begin // this cannot just use Damage or it interrupts shotgun and gets you called stupid
- inc(CurrentHedgehog^.Gear^.Karma, tmpDmg);
- CurrentHedgehog^.Gear^.LastDamage := CurrentHedgehog;
- spawnHealthTagForHH(CurrentHedgehog^.Gear, tmpDmg);
+ if (GameFlags and gfKarma <> 0) and (GameFlags and gfInvulnerable = 0) and
+ (CurrentHedgehog^.Effects[heInvulnerable] = 0) then
+ begin // this cannot just use Damage or it interrupts shotgun and gets you called stupid
+ inc(CurrentHedgehog^.Gear^.Karma, tmpDmg);
+ CurrentHedgehog^.Gear^.LastDamage := CurrentHedgehog;
+ spawnHealthTagForHH(CurrentHedgehog^.Gear, tmpDmg);
+ end;
end;
+
uStats.HedgehogDamaged(Gear, AttackerHog, Damage, false);
- end;
if AprilOne and (Gear^.Hedgehog^.Hat = 'fr_tomato') and (Damage > 2) then
for i := 0 to random(min(Damage,20))+5 do
@@ -474,7 +488,7 @@
PlaySound(sndSplash)
else if hwTmp > _0_5 then
PlaySound(sndSkip)
- else
+ else if hwTmp > _0_0002 then // arbitrary sanity cutoff. mostly for airmines
PlaySound(sndDroplet2);
end;
@@ -645,6 +659,8 @@
begin
CheckGearDrowning := true;
Gear^.State := gstDrowning;
+ if Gear = CurrentHedgehog^.Gear then
+ TurnTimeLeft := 0;
Gear^.RenderTimer := false;
if (Gear^.Kind <> gtSniperRifleShot) and (Gear^.Kind <> gtShotgunShot)
and (Gear^.Kind <> gtDEagleShot) and (Gear^.Kind <> gtSineGunShot) then
@@ -661,7 +677,10 @@
DrownGear(Gear);
Gear^.State := Gear^.State and (not gstHHDriven);
s:= ansistring(Gear^.Hedgehog^.Name);
- AddCaption(FormatA(GetEventString(eidDrowned), s), cWhiteColor, capgrpMessage);
+ if Gear^.Hedgehog^.King then
+ AddCaption(FormatA(GetEventString(eidKingDied), s), cWhiteColor, capgrpMessage)
+ else
+ AddCaption(FormatA(GetEventString(eidDrowned), s), cWhiteColor, capgrpMessage);
end
end
else
@@ -683,7 +702,7 @@
// check if surface was penetrated
// no penetration if center's water distance not smaller than radius
- if abs(dist2Water + Gear^.Radius) >= Gear^.Radius then
+ if ((dist2Water + Gear^.Radius div 2) < 0) or (abs(dist2Water + Gear^.Radius) >= Gear^.Radius) then
isImpact:= false
else
begin
@@ -691,16 +710,19 @@
if isDirH then
begin
tmp:= hwRound(Gear^.X - Gear^.dX);
- tmp:= abs(min(tmp - leftX, rightX - tmp));
+ if abs(tmp - real(leftX)) < abs(tmp - real(rightX)) then // left edge
+ isImpact:= (abs(tmp-real(leftX)) >= Gear^.Radius) and (Gear^.dX.isNegative)
+ else
+ isImpact:= (abs(tmp-real(rightX)) >= Gear^.Radius) and (not Gear^.dX.isNegative);
end
else
begin
tmp:= hwRound(Gear^.Y - Gear^.dY);
tmp:= abs(cWaterLine - tmp);
+ // there was an impact if distance was >= radius
+ isImpact:= (tmp >= Gear^.Radius) and (not Gear^.dY.isNegative);
end;
- // there was an impact if distance was >= radius
- isImpact:= (tmp >= Gear^.Radius)
end;
end; // end of submersible
end; // end of not skipping
@@ -763,22 +785,22 @@
RecountTeamHealth(tempTeam);
end;
-function CountNonZeroz(x, y, r, c: LongInt; mask: LongWord): LongInt;
+function CountLand(x, y, r, c: LongInt; mask, antimask: LongWord): LongInt;
var i: LongInt;
count: LongInt = 0;
begin
if (y and LAND_HEIGHT_MASK) = 0 then
for i:= max(x - r, 0) to min(x + r, LAND_WIDTH - 1) do
- if Land[y, i] and mask <> 0 then
- begin
+ if (Land[y, i] and mask <> 0) and (Land[y, i] and antimask = 0) then
+ begin
inc(count);
if count = c then
- begin
- CountNonZeroz:= count;
+ begin
+ CountLand:= count;
exit
+ end;
end;
- end;
- CountNonZeroz:= count;
+ CountLand:= count;
end;
function isSteadyPosition(x, y, r, c: LongInt; mask: Longword): boolean;
@@ -860,27 +882,32 @@
repeat
inc(y, 2);
until (y >= cWaterLine) or
- ((not ignoreOverlap) and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FFFF) = 0)) or
- (ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, lfLandMask) = 0));
+ (ignoreOverLap and (CountLand(x, y, Gear^.Radius - 1, 1, $FF00, 0) = 0)) or
+ (not ignoreOverLap and (CountLand(x, y, Gear^.Radius - 1, 1, $FFFF, 0) = 0));
+
sy:= y;
repeat
inc(y);
until (y >= cWaterLine) or
- ((not ignoreOverlap) and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FFFF) <> 0)) or
- (ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, lfLandMask) <> 0));
+ (ignoreOverlap and
+ (CountLand(x, y, Gear^.Radius - 1, 1, $FFFF, 0) <> 0)) or
+ (not ignoreOverlap and
+ (CountLand(x, y, Gear^.Radius - 1, 1, lfLandMask, 0) <> 0));
if (y - sy > Gear^.Radius * 2) and (y < cWaterLine)
and (((Gear^.Kind = gtExplosives)
and (ignoreNearObjects or NoGearsToAvoid(x, y - Gear^.Radius, 60, 60))
and (isSteadyPosition(x, y+1, Gear^.Radius - 1, 3, $FFFF)
- or (CountNonZeroz(x, y+1, Gear^.Radius - 1, Gear^.Radius+1, $FFFF) > Gear^.Radius)
+ or (CountLand(x, y+1, Gear^.Radius - 1, Gear^.Radius+1, $FFFF, 0) > Gear^.Radius)
))
or
((Gear^.Kind <> gtExplosives)
and (ignoreNearObjects or NoGearsToAvoid(x, y - Gear^.Radius, 110, 110))
- )) then
+ and (isSteadyPosition(x, y+1, Gear^.Radius - 1, 3, lfIce)
+ or (CountLand(x, y+1, Gear^.Radius - 1, Gear^.Radius+1, $FFFF, lfIce) <> 0)
+ ))) then
begin
ar[cnt].X:= x;
if withFall then
@@ -975,7 +1002,10 @@
while t <> nil do
begin
if (t <> Gear) and (t^.Kind = Kind) then
- if not((hwSqr(Gear^.X - t^.X) / rX + hwSqr(Gear^.Y - t^.Y) / rY) > _1) then
+ if (not ((hwSqr(Gear^.X - t^.X) / rX + hwSqr(Gear^.Y - t^.Y) / rY) > _1)) or
+ ((WorldEdge = weWrap) and (
+ (not ((hwSqr(Gear^.X - int2hwFloat(RightX-LeftX) - t^.X) / rX + hwSqr(Gear^.Y - t^.Y) / rY) > _1)) or
+ (not ((hwSqr(Gear^.X + int2hwFloat(RightX-LeftX) - t^.X) / rX + hwSqr(Gear^.Y - t^.Y) / rY) > _1)))) then
begin
CheckGearNear:= t;
exit;
@@ -1145,6 +1175,35 @@
DrawExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), cShotgunRadius)
end;
+// Returns true if the given hog gear can use the tardis
+function CanUseTardis(HHGear: PGear): boolean;
+var usable: boolean;
+ i, j, cnt: LongInt;
+ HH: PHedgehog;
+begin
+(*
+ Conditions for not activating.
+ 1. Hog is last of his clan
+ 2. Sudden Death is in play
+ 3. Hog is a king
+*)
+ usable:= true;
+ HH:= HHGear^.Hedgehog;
+ if HHGear <> nil then
+ if (HHGear = nil) or (HH^.King) or (SuddenDeathDmg) then
+ usable:= false;
+ cnt:= 0;
+ for j:= 0 to Pred(HH^.Team^.Clan^.TeamsNumber) do
+ for i:= 0 to Pred(HH^.Team^.Clan^.Teams[j]^.HedgehogsNumber) do
+ if (HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear <> nil)
+ and ((HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.State and gstDrowning) = 0)
+ and (HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.Health > HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.Damage) then
+ inc(cnt);
+ if (cnt < 2) then
+ usable:= false;
+ CanUseTardis:= usable;
+end;
+
procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt);
var t: PGearArray;
Gear: PGear;
@@ -1335,6 +1394,7 @@
var
t: PGear;
s: Longword;
+ xc, xc_left, xc_right, yc: hwFloat;
begin
r:= r*r;
s:= 0;
@@ -1342,15 +1402,22 @@
t := GearsList;
while t <> nil do
begin
- if (t^.Kind = Kind)
- and ((X - t^.X)*(X - t^.X) + (Y - t^.Y)*(Y-t^.Y) < int2hwFloat(r)) then
- begin
- inc(s);
- SetLength(GearsNearArray, s);
- GearsNearArray[s - 1] := t;
- end;
- t := t^.NextGear;
- end;
+ xc:= (X - t^.X)*(X - t^.X);
+ xc_left:= ((X - int2hwFloat(RightX-LeftX)) - t^.X)*((X - int2hwFloat(RightX-LeftX)) - t^.X);
+ xc_right := ((X + int2hwFloat(RightX-LeftX)) - t^.X)*((X + int2hwFloat(RightX-LeftX)) - t^.X);
+ yc:= (Y - t^.Y)*(Y - t^.Y);
+ if (t^.Kind = Kind)
+ and ((xc + yc < int2hwFloat(r))
+ or ((WorldEdge = weWrap) and
+ ((xc_left + yc < int2hwFloat(r)) or
+ (xc_right + yc < int2hwFloat(r))))) then
+ begin
+ inc(s);
+ SetLength(GearsNearArray, s);
+ GearsNearArray[s - 1] := t;
+ end;
+ t := t^.NextGear;
+ end;
GearsNear.size:= s;
GearsNear.ar:= @GearsNearArray
@@ -1586,7 +1653,15 @@
Scale:= hwFloat2Float(Gear^.Density * hwAbs(Gear^.dY) + hwAbs(Gear^.dX)) / 1.5;
State:= ord(sprBoing)
end;
- PlaySound(sndMelonImpact, true)
+ if Gear^.Kind = gtDuck then
+ PlaySound(sndDuckDrop, true)
+ else
+ PlaySound(sndMelonImpact, true)
+end;
+
+function IsHogLocal(HH: PHedgehog): boolean;
+begin
+ IsHogLocal:= (not (HH^.Team^.ExtDriven or (HH^.BotLevel > 0))) or (HH^.Team^.Clan^.ClanIndex = LocalClan) or (GameType = gmtDemo);
end;
end.
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uIO.pas
--- a/hedgewars/uIO.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uIO.pas Sun Dec 17 00:09:24 2017 +0100
@@ -457,7 +457,8 @@
CurrentHedgehog^ do
if (State and gstChooseTarget) <> 0 then
begin
- isCursorVisible:= false;
+ if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoTargetAfter) <> 0 then
+ isCursorVisible:= false;
if not CurrentTeam^.ExtDriven then
begin
if fromAI then
@@ -470,10 +471,13 @@
TargetPoint.X:= CursorPoint.X - WorldDx;
TargetPoint.Y:= cScreenHeight - CursorPoint.Y - WorldDy;
end;
+ if (WorldEdge <> weBounce) then
+ TargetPoint.X:= CalcWorldWrap(TargetPoint.X, 0);
SendIPCXY('p', TargetPoint.X, TargetPoint.Y);
end
else
begin
+ TargetPoint.X:= CalcWorldWrap(TargetPoint.X, 0);
TargetPoint.X:= putX;
TargetPoint.Y:= putY
end;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uInputHandler.pas
--- a/hedgewars/uInputHandler.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uInputHandler.pas Sun Dec 17 00:09:24 2017 +0100
@@ -30,7 +30,8 @@
//procedure MaskModifier(var code: LongInt; modifier: LongWord);
procedure MaskModifier(Modifier: shortstring; var code: LongInt);
procedure ProcessMouse(event: TSDL_MouseButtonEvent; ButtonDown: boolean);
-procedure ProcessMouseWheel(x, y: LongInt);
+//procedure ProcessMouseWheel(x, y: LongInt);
+procedure ProcessMouseWheel(y: LongInt);
procedure ProcessKey(event: TSDL_KeyboardEvent); inline;
procedure ProcessKey(code: LongInt; KeyDown: boolean);
@@ -172,7 +173,7 @@
begin
if (code < cKeyMaxIndex - 2) // means not mouse buttons
and KeyDown
- and (not ((CurrentBinds[code] = 'put')) or (CurrentBinds[code] = 'ammomenu') or (CurrentBinds[code] = '+cur_u') or (CurrentBinds[code] = '+cur_d') or (CurrentBinds[code] = '+cur_l') or (CurrentBinds[code] = '+cur_r'))
+ and (not ((CurrentBinds[code] = 'put') or (CurrentBinds[code] = 'ammomenu') or (CurrentBinds[code] = '+cur_u') or (CurrentBinds[code] = '+cur_d') or (CurrentBinds[code] = '+cur_l') or (CurrentBinds[code] = '+cur_r')))
and (CurrentTeam <> nil)
and (not CurrentTeam^.ExtDriven)
then bShowAmmoMenu:= false;
@@ -232,8 +233,10 @@
var mwheelupCode, mwheeldownCode: Integer;
-procedure ProcessMouseWheel(x, y: LongInt);
+//procedure ProcessMouseWheel(x, y: LongInt);
+procedure ProcessMouseWheel(y: LongInt);
begin
+ // we don't use
//writelntoconsole('[MOUSEWHEEL] '+inttostr(x)+', '+inttostr(y));
if y > 0 then
begin
@@ -321,7 +324,7 @@
for i:= 1 to 10 do DefaultBinds[KeyNameToCode('f'+IntToStr(i))]:= 'slot '+char(48+i);
for i:= 1 to 5 do DefaultBinds[KeyNameToCode(IntToStr(i))]:= 'timer '+IntToStr(i);
- loadBinds('dbind', cPathz[ptData] + '/settings.ini');
+ loadBinds('dbind', cPathz[ptConfig] + '/settings.ini');
end;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uLand.pas
--- a/hedgewars/uLand.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uLand.pas Sun Dec 17 00:09:24 2017 +0100
@@ -53,7 +53,7 @@
x, yd, yu: LongInt;
targetMask: Word;
begin
- tmpsurf:= LoadDataImage(ptCurrTheme, 'Border', ifCritical or ifIgnoreCaps or ifTransparent);
+ tmpsurf:= LoadDataImage(ptCurrTheme, 'Border', ifCritical or ifIgnoreCaps or ifColorKey);
// if mask only, all land gets filled with landtex and therefore needs borders
if maskOnly then
@@ -165,6 +165,96 @@
end
end;
+procedure ColorizeLandFast(mapsurf: PSDL_Surface);
+var ltexsurf: PSDL_Surface;
+ i: LongInt;
+ ltlnp, srcp, dstp, stopp: Pointer;
+ c: SizeInt;
+begin
+ ltexsurf:= LoadDataImage(ptCurrTheme, 'LandTex', ifCritical or ifIgnoreCaps);
+
+ // pointer to current line of ltexsurf pixels. will be moved from line to line
+ ltlnp:= ltexsurf^.pixels;
+ // pointer to mapsurf pixels. will jump forward after every move()
+ dstp:= mapsurf^.pixels;
+
+ // time to get serious
+ SDL_LockSurface(mapsurf);
+ SDL_LockSurface(ltexsurf);
+
+ // for now only fill a row with the height of landtex. do vertical copies within mapsurf after
+
+ // do this loop for each line of ltexsurf (unless we run out of map height first)
+ for i:= 1 to min(ltexsurf^.h, mapsurf^.h) do
+ begin
+ // amount of pixels to write in first move()
+ c:= ltexsurf^.pitch;
+
+ // protect from odd cases where landtex wider than map
+ if c > mapsurf^.pitch then
+ c:= mapsurf^.pitch;
+
+ // write line of landtex to mapsurf
+ move(ltlnp^, dstp^, c);
+
+ // fill the rest of the line by copying left-to-right until full
+
+ // new src is start of line that we've just written to
+ srcp:= dstp;
+ // set stop pointer to start of next pixel line of mapsurf
+ stopp:= dstp + mapsurf^.pitch;
+ // move dst pointer to after what we've just written
+ inc(dstp, c);
+
+ // loop until dstp went past end of line
+ while dstp < stopp do
+ begin
+ // copy all from left of dstp to right of it (or just fill the gap if smaller)
+ c:= min(dstp-srcp, stopp-dstp);
+ move(srcp^, dstp^, c);
+ inc(dstp, c);
+ end;
+
+ // move to next line in ltexsurf
+ inc(ltlnp, ltexsurf^.pitch);
+ end;
+
+ // we don't need ltexsurf itself anymore -> cleanup
+ ltlnp:= nil;
+ SDL_UnlockSurface(ltexsurf);
+ SDL_FreeSurface(ltexsurf);
+ ltexsurf:= nil;
+
+ // from now on only copy pixels within mapsurf
+
+ // copy all the already written lines at once for that get number of written bytes so far
+ // already written pixels are between start and current dstp
+ srcp:= mapsurf^.pixels;
+
+ // first byte after end of pixels
+ stopp:= srcp + (mapsurf^.pitch * mapsurf^.h);
+
+ while dstp < stopp do
+ begin
+ // copy all from before dstp to after (or just fill the gap if smaller)
+ c:= min(dstp-srcp, stopp-dstp);
+ // worried about size of c with humongous maps? don't be:
+ // the OS wouldn't have allowed allocation of object with size > max of SizeInt anyway
+ move(srcp^, dstp^, c);
+ inc(dstp, c);
+ end;
+
+ // cleanup
+ srcp:= nil;
+ dstp:= nil;
+ stopp:= nil;
+ SDL_UnlockSurface(mapsurf);
+
+ // freed in freeModule() below
+ LandBackSurface:= LoadDataImage(ptCurrTheme, 'LandBackTex', ifIgnoreCaps or ifColorKey);
+ if (LandBackSurface <> nil) and GrayScale then Surface2GrayScale(LandBackSurface);
+end;
+
procedure ColorizeLand(Surface: PSDL_Surface);
var tmpsurf: PSDL_Surface;
r: TSDL_Rect;
@@ -188,7 +278,7 @@
SDL_FreeSurface(tmpsurf);
// freed in freeModule() below
- LandBackSurface:= LoadDataImage(ptCurrTheme, 'LandBackTex', ifIgnoreCaps or ifTransparent);
+ LandBackSurface:= LoadDataImage(ptCurrTheme, 'LandBackTex', ifIgnoreCaps or ifColorKey);
if (LandBackSurface <> nil) and GrayScale then Surface2GrayScale(LandBackSurface);
end;
@@ -277,7 +367,7 @@
tmpsurf:= SDL_CreateRGBSurface(SDL_SWSURFACE, LAND_WIDTH, LAND_HEIGHT, 32, RMask, GMask, BMask, AMask);
if checkFails(tmpsurf <> nil, 'Error creating pre-land surface', true) then exit;
- ColorizeLand(tmpsurf);
+ ColorizeLandFast(tmpsurf);
if gameFlags and gfShoppaBorder = 0 then DrawBorderFromImage(tmpsurf);
AddOnLandObjects(tmpsurf);
@@ -454,11 +544,11 @@
if mirror then
begin
// not critical because if no R we can fallback to mirrored L
- tmpsurf:= LoadDataImage(ptForts, SpawnClansArray[i]^.Teams[0]^.FortName + 'R', ifAlpha or ifTransparent or ifIgnoreCaps);
+ tmpsurf:= LoadDataImage(ptForts, SpawnClansArray[i]^.Teams[0]^.FortName + 'R', ifAlpha or ifColorKey or ifIgnoreCaps);
// fallback
if tmpsurf = nil then
begin
- tmpsurf:= LoadDataImage(ptForts, SpawnClansArray[i]^.Teams[0]^.FortName + 'L', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps);
+ tmpsurf:= LoadDataImage(ptForts, SpawnClansArray[i]^.Teams[0]^.FortName + 'L', ifAlpha or ifCritical or ifColorKey or ifIgnoreCaps);
BlitImageAndGenerateCollisionInfo(leftX + sectionWidth * i + ((sectionWidth - tmpsurf^.w) div 2), LAND_HEIGHT - tmpsurf^.h, tmpsurf^.w, tmpsurf, 0, true);
end
else
@@ -467,7 +557,7 @@
end
else
begin
- tmpsurf:= LoadDataImage(ptForts, SpawnClansArray[i]^.Teams[0]^.FortName + 'L', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps);
+ tmpsurf:= LoadDataImage(ptForts, SpawnClansArray[i]^.Teams[0]^.FortName + 'L', ifAlpha or ifCritical or ifColorKey or ifIgnoreCaps);
BlitImageAndGenerateCollisionInfo(leftX + sectionWidth * i + ((sectionWidth - tmpsurf^.w) div 2), LAND_HEIGHT - tmpsurf^.h, tmpsurf^.w, tmpsurf);
SDL_FreeSurface(tmpsurf);
end;
@@ -507,11 +597,11 @@
x, y, cpX, cpY: Longword;
mapName: shortstring;
begin
-tmpsurf:= LoadDataImage(ptMapCurrent, 'mask', ifAlpha or ifTransparent or ifIgnoreCaps);
+tmpsurf:= LoadDataImage(ptMapCurrent, 'mask', ifAlpha or ifColorKey or ifIgnoreCaps);
if tmpsurf = nil then
begin
mapName:= ExtractFileName(cPathz[ptMapCurrent]);
- tmpsurf:= LoadDataImage(ptMissionMaps, mapName + '/mask', ifAlpha or ifTransparent or ifIgnoreCaps);
+ tmpsurf:= LoadDataImage(ptMissionMaps, mapName + '/mask', ifAlpha or ifColorKey or ifIgnoreCaps);
end;
@@ -549,7 +639,7 @@
if not disableLandBack then
begin
// freed in freeModule() below
- LandBackSurface:= LoadDataImage(ptCurrTheme, 'LandBackTex', ifIgnoreCaps or ifTransparent);
+ LandBackSurface:= LoadDataImage(ptCurrTheme, 'LandBackTex', ifIgnoreCaps or ifColorKey);
if (LandBackSurface <> nil) and GrayScale then
Surface2GrayScale(LandBackSurface)
end;
@@ -566,11 +656,11 @@
begin
WriteLnToConsole('Loading land from file...');
AddProgress;
-tmpsurf:= LoadDataImage(ptMapCurrent, 'map', ifAlpha or ifTransparent or ifIgnoreCaps);
+tmpsurf:= LoadDataImage(ptMapCurrent, 'map', ifAlpha or ifColorKey or ifIgnoreCaps);
if tmpsurf = nil then
begin
mapName:= ExtractFileName(cPathz[ptMapCurrent]);
- tmpsurf:= LoadDataImage(ptMissionMaps, mapName + '/map', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps);
+ tmpsurf:= LoadDataImage(ptMissionMaps, mapName + '/map', ifAlpha or ifCritical or ifColorKey or ifIgnoreCaps);
if not allOK then exit;
end;
// (bare) Sanity check. Considering possible LongInt comparisons as well as just how much system memoery it would take
@@ -599,26 +689,27 @@
end;
procedure DrawBottomBorder; // broken out from other borders for doing a floor-only map, or possibly updating bottom during SD
-var x, w, c: Longword;
+var x, w, c, y: Longword;
begin
for w:= 0 to 23 do
for x:= leftX to rightX do
begin
- Land[Longword(cWaterLine) - 1 - w, x]:= lfIndestructible;
- if (x + w) mod 32 < 16 then
+ y:= Longword(cWaterLine) - 1 - w;
+ Land[y, x]:= lfIndestructible;
+ if (x + y) mod 32 < 16 then
c:= AMask
else
c:= AMask or RMask or GMask; // FF00FFFF
if (cReducedQuality and rqBlurryLand) = 0 then
- LandPixels[Longword(cWaterLine) - 1 - w, x]:= c
+ LandPixels[y, x]:= c
else
- LandPixels[(Longword(cWaterLine) - 1 - w) div 2, x div 2]:= c
+ LandPixels[y div 2, x div 2]:= c
end
end;
procedure GenMap;
-var x, y, w, c: Longword;
+var x, y, w, c, c2: Longword;
map, mask: shortstring;
begin
hasBorder:= false;
@@ -630,36 +721,33 @@
//if ((GameFlags and gfForts) <> 0) or (Pathz[ptMapCurrent] <> '') then
// FillChar(Land,SizeOf(TCollisionArray),0);*)
- if (GameFlags and gfForts) = 0 then
- if cPathz[ptMapCurrent] <> '' then
- begin
- map:= cPathz[ptMapCurrent] + '/map.png';
- mask:= cPathz[ptMapCurrent] + '/mask.png';
- if (not(pfsExists(map)) and pfsExists(mask)) then
- begin
- maskOnly:= true;
- LoadMask;
- GenLandSurface
- end
- else LoadMap;
- end
- else
+ if cPathz[ptMapCurrent] <> '' then
+ begin
+ map:= cPathz[ptMapCurrent] + '/map.png';
+ mask:= cPathz[ptMapCurrent] + '/mask.png';
+ if (not(pfsExists(map)) and pfsExists(mask)) then
begin
- WriteLnToConsole('Generating land...');
- case cMapGen of
- mgRandom: GenTemplated(EdgeTemplates[SelectTemplate]);
- mgMaze : begin ResizeLand(4096,2048); GenMaze; end;
- mgPerlin: begin ResizeLand(4096,2048); GenPerlin; end;
- mgDrawn : GenDrawnMap;
- mgForts : begin GameFlags:= (GameFlags or gfForts or gfDivideTeams); MakeFortsMap(); end;
- else
- OutError('Unknown mapgen', true);
- end;
- if cMapGen <> mgForts then
- GenLandSurface
+ maskOnly:= true;
+ LoadMask;
+ GenLandSurface
end
+ else LoadMap;
+ end
else
- MakeFortsMap;
+ begin
+ WriteLnToConsole('Generating land...');
+ case cMapGen of
+ mgRandom: GenTemplated(EdgeTemplates[SelectTemplate]);
+ mgMaze : begin ResizeLand(4096,2048); GenMaze; end;
+ mgPerlin: begin ResizeLand(4096,2048); GenPerlin; end;
+ mgDrawn : GenDrawnMap;
+ mgForts : begin GameFlags:= (GameFlags or gfForts or gfDivideTeams); MakeFortsMap(); end;
+ else
+ OutError('Unknown mapgen', true);
+ end;
+ if cMapGen <> mgForts then
+ GenLandSurface
+ end;
AddProgress;
@@ -704,20 +792,24 @@
begin
Land[y, leftX + w]:= lfIndestructible;
Land[y, rightX - w]:= lfIndestructible;
- if (y + w) mod 32 < 16 then
+ if (y + leftX + w) mod 32 < 16 then
c:= AMask
else
c:= AMask or RMask or GMask; // FF00FFFF
+ if (y + rightX - w) mod 32 < 16 then
+ c2:= AMask
+ else
+ c2:= AMask or RMask or GMask; // FF00FFFF
if (cReducedQuality and rqBlurryLand) = 0 then
begin
LandPixels[y, leftX + w]:= c;
- LandPixels[y, rightX - w]:= c;
+ LandPixels[y, rightX - w]:= c2;
end
else
begin
LandPixels[y div 2, (leftX + w) div 2]:= c;
- LandPixels[y div 2, (rightX - w) div 2]:= c;
+ LandPixels[y div 2, (rightX - w) div 2]:= c2;
end;
end;
@@ -886,16 +978,15 @@
if digest = '' then
digest:= s
else
- checkFails(s = digest, 'Different maps generated, sorry', true);
+ checkFails(s = digest, 'Different map or critical resources loaded, sorry', true);
end;
procedure chSendLandDigest(var s: shortstring);
-var adler, i: LongInt;
+var i: LongInt;
begin
- adler:= 1;
for i:= 0 to LAND_HEIGHT-1 do
- adler:= Adler32Update(adler, @Land[i,0], LAND_WIDTH);
- s:= 'M' + IntToStr(adler) + cScriptName;
+ syncedPixelDigest:= Adler32Update(syncedPixelDigest, @Land[i,0], LAND_WIDTH*2);
+ s:= 'M' + IntToStr(syncedPixelDigest); // + cScriptName; script name is no longer needed. scripts are hashed
ScriptSetString('LandDigest', s);
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uLandObjects.pas
--- a/hedgewars/uLandObjects.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uLandObjects.pas Sun Dec 17 00:09:24 2017 +0100
@@ -35,7 +35,7 @@
implementation
uses uStore, uConsts, uConsole, uRandom, uSound
, uTypes, uVariables, uDebug, uUtils
- , uPhysFSLayer;
+ , uPhysFSLayer, adler32, uRenderUtils;
const MaxRects = 512;
MAXOBJECTRECTS = 16;
@@ -46,9 +46,10 @@
PRectArray = ^TRectsArray;
TThemeObject = record
Surf, Mask: PSDL_Surface;
- inland: TSDL_Rect;
+ inland: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect;
outland: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect;
- rectcnt: Longword;
+ inrectcnt: Longword;
+ outrectcnt: Longword;
Width, Height: Longword;
Maxcnt: Longword;
end;
@@ -258,7 +259,10 @@
bRes: boolean;
begin
if girSurf = nil then
- girSurf:= LoadDataImageAltPath(ptCurrTheme, ptGraphics, 'Girder', ifCritical or ifTransparent or ifIgnoreCaps);
+ girSurf:= LoadDataImageAltPath(ptCurrTheme, ptGraphics, 'Girder', ifCritical or ifColorKey or ifIgnoreCaps);
+
+for y := 0 to girsurf^.h-1 do
+ syncedPixelDigest:= Adler32Update(syncedPixelDigest, @PByteArray(girsurf^.pixels)^[y*girsurf^.pitch], girsurf^.w*4);
girderHeight:= girSurf^.h;
@@ -355,22 +359,27 @@
var i: Longword;
bRes: boolean;
begin
-with Obj do
- if CheckLand(inland, x, y, lfBasic) then
- begin
+ with Obj do begin
bRes:= true;
i:= 1;
- while bRes and (i <= rectcnt) do
+ while bRes and (i <= inrectcnt) do
+ begin
+ bRes:= CheckLand(inland[i], x, y, lfBasic);
+ inc(i)
+ end;
+
+ i:= 1;
+ while bRes and (i <= outrectcnt) do
begin
bRes:= CheckLand(outland[i], x, y, 0);
inc(i)
end;
+
if bRes then
- bRes:= not CheckIntersect(x, y, Width, Height)
- end
- else
- bRes:= false;
-CheckCanPlace:= bRes;
+ bRes:= not CheckIntersect(x, y, Width, Height);
+
+ CheckCanPlace:= bRes;
+ end
end;
function TryPut(var Obj: TThemeObject): boolean;
@@ -390,6 +399,10 @@
repeat
y:= topY+32; // leave room for a hedgie to teleport in
repeat
+
+ if (inland[1].x = 0) and (inland[1].y = 0) and (inland[1].w = 0) and (inland[1].h = 0) then
+ y := LAND_HEIGHT - Height;
+
if CheckCanPlace(x, y, Obj) then
begin
ar[cnt].x:= x;
@@ -459,15 +472,10 @@
inc(x, getrandom(12) + 12)
until x >= LAND_WIDTH - Width;
bRes:= cnt <> 0;
-AddFileLog('CHECKPOINT 004');
if bRes then
begin
i:= getrandom(cnt);
- r.x:= ar[i].X;
- r.y:= ar[i].Y;
- r.w:= Width;
- r.h:= Height;
- SDL_UpperBlit(Obj.Surf, nil, Surface, @r);
+ copyToXY(Obj.Surf, Surface, ar[i].X, ar[i].Y);
AddRect(ar[i].x - 32, ar[i].y - 32, Width + 64, Height + 64);
dec(Maxcnt)
end
@@ -488,7 +496,7 @@
procedure ReadThemeInfo(var ThemeObjects: TThemeObjects; var SprayObjects: TSprayObjects);
var s, key: shortstring;
f: PFSFile;
- i: LongInt;
+ i, y: LongInt;
ii, t: Longword;
c2: TSDL_Color;
begin
@@ -561,6 +569,29 @@
SDSkyColor.g:= SkyColor.g;
SDSkyColor.b:= SkyColor.b;
end
+ else if key = 'sd-tint' then
+ begin
+ i:= Pos(',', s);
+ SDTint.r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+ Delete(s, 1, i);
+ i:= Pos(',', s);
+ SDTint.g:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+ Delete(s, 1, i);
+ i:= Pos(',', s);
+ SDTint.b:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+ Delete(s, 1, i);
+ SDTint.a:= StrToInt(Trim(s));
+ if GrayScale
+ then
+ begin
+ t:= round(SDTint.r * RGB_LUMINANCE_RED + SDTint.g * RGB_LUMINANCE_GREEN + SDTint.b * RGB_LUMINANCE_BLUE);
+ if t > 255 then
+ t:= 255;
+ SDTint.r:= t;
+ SDTint.g:= t;
+ SDTint.b:= t
+ end;
+ end
else if key = 'border' then
begin
i:= Pos(',', s);
@@ -652,36 +683,55 @@
with ThemeObjects.objs[Pred(ThemeObjects.Count)] do
begin
i:= Pos(',', s);
- Surf:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i))), ifTransparent or ifIgnoreCaps or ifCritical);
+ Surf:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i))), ifColorKey or ifIgnoreCaps or ifCritical);
Width:= Surf^.w;
Height:= Surf^.h;
- Mask:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i)))+'_mask', ifTransparent or ifIgnoreCaps);
+ Mask:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i)))+'_mask', ifColorKey or ifIgnoreCaps);
Delete(s, 1, i);
i:= Pos(',', s);
Maxcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
Delete(s, 1, i);
if (Maxcnt < 1) or (Maxcnt > MAXTHEMEOBJECTS) then
OutError('Object''s max count should be between 1 and '+ inttostr(MAXTHEMEOBJECTS) +' (it was '+ inttostr(Maxcnt) +').', true);
- with inland do
- begin
- i:= Pos(',', s);
- x:= StrToInt(Trim(Copy(s, 1, Pred(i))));
- Delete(s, 1, i);
- i:= Pos(',', s);
- y:= StrToInt(Trim(Copy(s, 1, Pred(i))));
- Delete(s, 1, i);
- i:= Pos(',', s);
- w:= StrToInt(Trim(Copy(s, 1, Pred(i))));
- Delete(s, 1, i);
- i:= Pos(',', s);
- h:= StrToInt(Trim(Copy(s, 1, Pred(i))));
- Delete(s, 1, i);
- CheckRect(Width, Height, x, y, w, h)
- end;
+ for y := 0 to Surf^.h-1 do
+ syncedPixelDigest:= Adler32Update(syncedPixelDigest, @PByteArray(Surf^.pixels)^[y*Surf^.pitch], Surf^.w*4);
+
+ inrectcnt := 0;
+
+ for ii := 1 to Length(S) do
+ if S[ii] = ',' then
+ inc(inrectcnt);
+
+ if inrectcnt mod 2 = 0 then
+ inrectcnt := 1
+ else begin
+ i:= Pos(',', s);
+ inrectcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+ Delete(s, 1, i);
+ end;
+
+ for ii:= 1 to inrectcnt do
+ with inland[ii] do
+ begin
+ i:= Pos(',', s);
+ x:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+ Delete(s, 1, i);
+ i:= Pos(',', s);
+ y:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+ Delete(s, 1, i);
+ i:= Pos(',', s);
+ w:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+ Delete(s, 1, i);
+ i:= Pos(',', s);
+ h:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+ Delete(s, 1, i);
+ CheckRect(Width, Height, x, y, w, h)
+ end;
+
i:= Pos(',', s);
- rectcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+ outrectcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
Delete(s, 1, i);
- for ii:= 1 to rectcnt do
+ for ii:= 1 to outrectcnt do
with outland[ii] do
begin
i:= Pos(',', s);
@@ -693,7 +743,7 @@
i:= Pos(',', s);
w:= StrToInt(Trim(Copy(s, 1, Pred(i))));
Delete(s, 1, i);
- if ii = rectcnt then
+ if ii = outrectcnt then
h:= StrToInt(Trim(s))
else
begin
@@ -703,6 +753,7 @@
end;
CheckRect(Width, Height, x, y, w, h)
end;
+
end;
end
else if key = 'spray' then
@@ -711,13 +762,33 @@
with SprayObjects.objs[Pred(SprayObjects.Count)] do
begin
i:= Pos(',', s);
- Surf:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i))), ifTransparent or ifIgnoreCaps);
+ Surf:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i))), ifAlpha or ifIgnoreCaps);
Width:= Surf^.w;
Height:= Surf^.h;
Delete(s, 1, i);
Maxcnt:= StrToInt(Trim(s));
end;
end
+ else if key = 'water-animation' then
+ begin
+ i:= Pos(',', s);
+ watFrames:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+ Delete(s, 1, i);
+ i:= Pos(',', s);
+ watFrameTicks:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+ Delete(s, 1, i);
+ watMove:= StrToInt(Trim(s));
+ end
+ else if key = 'sd-water-animation' then
+ begin
+ i:= Pos(',', s);
+ watSDFrames:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+ Delete(s, 1, i);
+ i:= Pos(',', s);
+ watSDFrameTicks:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+ Delete(s, 1, i);
+ watSDMove:= StrToInt(Trim(s));
+ end
else if key = 'flakes' then
begin
i:= Pos(',', s);
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uLandUtils.pas
--- a/hedgewars/uLandUtils.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uLandUtils.pas Sun Dec 17 00:09:24 2017 +0100
@@ -42,6 +42,7 @@
lx:= LongInt(LAND_WIDTH) - 1;
+// use maximum available map width if there is no special world edge
if WorldEdge = weNone then
begin
playWidth:= LAND_WIDTH;
@@ -50,6 +51,13 @@
EXIT;
end;
+// keep fort distance consistent if we're in wrap mode on fort map
+if (cMapGen = mgForts) and (WorldEdge = weWrap) then
+ begin
+ // edges were adjusted already in MakeFortsMap() in uLand
+ EXIT;
+ end;
+
ly:= LongInt(LAND_HEIGHT) - 1;
// find most left land pixels and set leftX accordingly
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uLocale.pas
--- a/hedgewars/uLocale.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uLocale.pas Sun Dec 17 00:09:24 2017 +0100
@@ -22,7 +22,7 @@
interface
uses uTypes;
-const MAX_EVENT_STRINGS = 100;
+const MAX_EVENT_STRINGS = 255;
procedure LoadLocale(FileName: shortstring);
function Format(fmt: shortstring; var arg: shortstring): shortstring;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uMisc.pas
--- a/hedgewars/uMisc.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uMisc.pas Sun Dec 17 00:09:24 2017 +0100
@@ -164,6 +164,7 @@
Rewrite(f, 1);
if IOResult = 0 then
begin
+ writeResult:= 0; // suppress fpc hint
BlockWrite(f, head, sizeof(head), writeResult);
BlockWrite(f, image^.buffer^, size, writeResult);
Close(f);
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uPhysFSLayer.pas
--- a/hedgewars/uPhysFSLayer.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uPhysFSLayer.pas Sun Dec 17 00:09:24 2017 +0100
@@ -61,6 +61,7 @@
function PHYSFS_seek(f: PFSFile; pos: QWord): LongBool; cdecl; external PhysfsLibName;
function PHYSFS_flush(f: PFSFile): LongBool; cdecl; external PhysfsLibName;
function PHYSFS_close(f: PFSFile): LongBool; cdecl; external PhysfsLibName;
+function PHYSFS_setBuffer(f: PFSFile; pos: QWord): LongBool; cdecl; external PhysfsLibName;
function PHYSFS_exists(fname: PChar): LongBool; cdecl; external PhysfsLibName;
function PHYSFS_mkdir(path: PChar): LongBool; cdecl; external PhysfsLibName;
function PHYSFS_getLastError(): PChar; cdecl; external PhysfsLibName;
@@ -84,8 +85,12 @@
end;
function pfsOpenRead(fname: shortstring): PFSFile;
+var f: PFSFile;
begin
- exit(PHYSFS_openRead(Str2PChar(fname)));
+ f:= PHYSFS_openRead(Str2PChar(fname));
+ if f <> nil then
+ PHYSFS_setBuffer(f, 4096);
+ exit(f);
end;
function pfsOpenWrite(fname: shortstring): PFSFile;
@@ -189,11 +194,13 @@
procedure pfsMount(path: PChar; mountpoint: PChar);
begin
+ system.writeln('Mounting ',path,' at ', mountpoint);
PHYSFS_mount(path, mountpoint, false)
end;
procedure pfsMountAtRoot(path: PChar);
begin
+ system.writeln('Mounting ',path,' at root');
pfsMount(path, PChar(_S'/'));
end;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uRender.pas
--- a/hedgewars/uRender.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uRender.pas Sun Dec 17 00:09:24 2017 +0100
@@ -34,6 +34,7 @@
procedure DrawSpriteClipped (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt);
procedure DrawSpriteRotated (Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
procedure DrawSpriteRotatedF (Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
+procedure DrawSpritePivotedF(Sprite: TSprite; X, Y, Frame, Dir, PivotX, PivotY: LongInt; Angle: real);
procedure DrawTexture (X, Y: LongInt; Texture: PTexture); inline;
procedure DrawTexture (X, Y: LongInt; Texture: PTexture; Scale: GLfloat);
@@ -73,6 +74,7 @@
procedure FinishRender();
function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline;
+function isCircleOffscreen(X, Y, RadiusSquared: LongInt): boolean; inline;
// 0 => not offscreen, <0 => left/top of screen >0 => right/below of screen
function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline;
@@ -103,8 +105,8 @@
implementation
-uses {$IFNDEF PAS2C} StrUtils, {$ENDIF}uVariables, uUtils, uConsts
- {$IFDEF GL2}, uMatrix, uConsole{$ENDIF}, uPhysFSLayer, uDebug;
+uses {$IFNDEF PAS2C} StrUtils, {$ENDIF}uVariables, uUtils
+ {$IFDEF GL2}, uMatrix, uConsole{$ENDIF}, uConsts;
{$IFDEF USE_TOUCH_INTERFACE}
const
@@ -147,6 +149,20 @@
isAreaOffscreen:= (isDxAreaOffscreen(X, Width) <> 0) or (isDyAreaOffscreen(Y, Height) <> 0);
end;
+function isCircleOffscreen(X, Y, RadiusSquared: LongInt): boolean; inline;
+var dRightX, dBottomY, dLeftX, dTopY: LongInt;
+begin
+ dRightX:= (X - ViewRightX);
+ dBottomY:= (Y - ViewBottomY);
+ dLeftX:= (ViewLeftX - X);
+ dTopY:= (ViewTopY - Y);
+ isCircleOffscreen:=
+ ((dRightX > 0) and (sqr(dRightX) > RadiusSquared)) or
+ ((dBottomY > 0) and (sqr(dBottomY) > RadiusSquared)) or
+ ((dLeftX > 0) and (sqr(dLeftX) > RadiusSquared)) or
+ ((dTopY > 0) and (sqr(dTopY) > RadiusSquared))
+end;
+
function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline;
begin
if X > ViewRightX then exit(1);
@@ -1131,11 +1147,8 @@
if Angle <> 0 then
begin
- // sized doubled because the sprite might occupy up to 1.4 * of it's
- // original size in each dimension, because it is rotated
- if isDxAreaOffscreen(X - SpritesData[Sprite].Width, 2 * SpritesData[Sprite].Width) <> 0 then
- exit;
- if isDYAreaOffscreen(Y - SpritesData[Sprite].Height, 2 * SpritesData[Sprite].Height) <> 0 then
+ // Check the bounding circle
+ if isCircleOffscreen(X, Y, sqr(SpritesData[Sprite].Width) + sqr(SpritesData[Sprite].Height)) then
exit;
end
else
@@ -1164,6 +1177,43 @@
end;
+procedure DrawSpritePivotedF(Sprite: TSprite; X, Y, Frame, Dir, PivotX, PivotY: LongInt; Angle: real);
+begin
+if Angle <> 0 then
+ begin
+ // Check the bounding circle
+ // Assuming the pivot point is inside the sprite's rectangle, the farthest possible point is 3/2 of its diagonal away from the center
+ if isCircleOffscreen(X, Y, 9 * (sqr(SpritesData[Sprite].Width) + sqr(SpritesData[Sprite].Height)) div 4) then
+ exit;
+ end
+else
+ begin
+ if isDxAreaOffscreen(X - SpritesData[Sprite].Width div 2, SpritesData[Sprite].Width) <> 0 then
+ exit;
+ if isDYAreaOffscreen(Y - SpritesData[Sprite].Height div 2 , SpritesData[Sprite].Height) <> 0 then
+ exit;
+ end;
+
+openglPushMatrix;
+openglTranslatef(X, Y, 0);
+
+// mirror
+if Dir < 0 then
+ openglScalef(-1.0, 1.0, 1.0);
+
+// apply rotation around the pivot after (conditional) mirroring
+if Angle <> 0 then
+ begin
+ openglTranslatef(PivotX, PivotY, 0);
+ openglRotatef(Angle, 0, 0, 1);
+ openglTranslatef(-PivotX, -PivotY, 0);
+ end;
+
+DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame);
+
+openglPopMatrix;
+end;
+
procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
begin
@@ -1733,19 +1783,31 @@
end;
procedure DrawWaves(Dir, dX, dY, oX: LongInt; tnt: Byte);
-var first, count, topy, lx, rx, spriteHeight, spriteWidth: LongInt;
- lw, nWaves, shift: GLfloat;
+var first, count, topy, lx, rx, spriteHeight, spriteWidth, waterSpeed: LongInt;
+ waterFrames, waterFrameTicks, frame : LongWord;
+ lw, nWaves, shift, realHeight: GLfloat;
sprite: TSprite;
begin
// note: spriteHeight is the Height of the wave sprite while
// cWaveHeight describes how many pixels of it will be above waterline
if SuddenDeathDmg then
- sprite:= sprSDWater
+ begin
+ sprite:= sprSDWater;
+ waterFrames:= watSDFrames;
+ waterFrameTicks:= watSDFrameTicks;
+ waterSpeed:= watSDMove;
+ end
else
+ begin
sprite:= sprWater;
-
+ waterFrames:= watFrames;
+ waterFrameTicks:= watFrameTicks;
+ waterSpeed:= watMove;
+ end;
+
spriteHeight:= SpritesData[sprite].Height;
+realHeight:= SpritesData[sprite].Texture^.ry / waterFrames;
// shift parameters by wave height
// ( ox and dy are used to create different horizontal and vertical offsets
@@ -1806,14 +1868,19 @@
nWaves:= lw / spriteWidth;
shift:= - nWaves / 2;
-TextureBuffer[3].X:= shift + ((LongInt(RealTicks shr 6) * Dir + dX) mod spriteWidth) / (spriteWidth - 1);
-TextureBuffer[3].Y:= 0;
+if waterFrames > 1 then
+ frame:= RealTicks div waterFrameTicks mod waterFrames
+else
+ frame:= 0;
+
+TextureBuffer[3].X:= shift + ((LongInt((RealTicks * waterSpeed div 100) shr 6) * Dir + dX) mod spriteWidth) / (spriteWidth - 1);
+TextureBuffer[3].Y:= frame * realHeight;
TextureBuffer[5].X:= TextureBuffer[3].X + nWaves;
-TextureBuffer[5].Y:= 0;
+TextureBuffer[5].Y:= frame * realHeight;
TextureBuffer[4].X:= TextureBuffer[5].X;
-TextureBuffer[4].Y:= SpritesData[sprite].Texture^.ry;
+TextureBuffer[4].Y:= (frame+1) * realHeight;
TextureBuffer[2].X:= TextureBuffer[3].X;
-TextureBuffer[2].Y:= SpritesData[sprite].Texture^.ry;
+TextureBuffer[2].Y:= (frame+1) * realHeight;
if (WorldEdge = weSea) then
begin
@@ -1821,15 +1888,15 @@
// left side
TextureBuffer[1].X:= TextureBuffer[3].X - nWaves;
- TextureBuffer[1].Y:= 0;
+ TextureBuffer[1].Y:= frame * realHeight;
TextureBuffer[0].X:= TextureBuffer[1].X;
- TextureBuffer[0].Y:= SpritesData[sprite].Texture^.ry;
+ TextureBuffer[0].Y:= (frame+1) * realHeight;
// right side
TextureBuffer[7].X:= TextureBuffer[5].X + nWaves;
- TextureBuffer[7].Y:= 0;
+ TextureBuffer[7].Y:= frame * realHeight;
TextureBuffer[6].X:= TextureBuffer[7].X;
- TextureBuffer[6].Y:= SpritesData[sprite].Texture^.ry;
+ TextureBuffer[6].Y:= (frame+1) * realHeight;
end;
glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.id);
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uRenderUtils.pas
--- a/hedgewars/uRenderUtils.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uRenderUtils.pas Sun Dec 17 00:09:24 2017 +0100
@@ -144,38 +144,74 @@
procedure copyToXY(src, dest: PSDL_Surface; destX, destY: LongInt); inline;
begin
+ // copy from complete src
copyToXYFromRect(src, dest, 0, 0, src^.w, src^.h, destX, destY);
end;
procedure copyToXYFromRect(src, dest: PSDL_Surface; srcX, srcY, srcW, srcH, destX, destY: LongInt);
-var i, j, maxDest, maxSrc, iX, iY: LongInt;
+var spi, dpi, iX, iY, dX, dY, lX, lY, aT: LongInt;
srcPixels, destPixels: PLongWordArray;
- r0, g0, b0, a0, r1, g1, b1, a1: Byte;
+ rD, gD, bD, aD, rT, gT, bT: Byte;
begin
- maxDest:= (dest^.pitch div 4) * dest^.h;
- maxSrc:= (src^.pitch div 4) * src^.h;
-
SDL_LockSurface(src);
SDL_LockSurface(dest);
srcPixels:= src^.pixels;
destPixels:= dest^.pixels;
- for iX:= 0 to srcW - 1 do
- for iY:= 0 to srcH - 1 do
+ // what's the offset between src and dest coords?
+ dX:= destX - srcX;
+ dY:= destY - srcY;
+
+ // let's figure out where the rectangle we can actually copy ends
+ lX:= min(srcX + srcW, src^.w) - 1;
+ if lX + dx >= dest^.w then lX:= dest^.w - dx - 1;
+ lY:= min(srcY + srcH, src^.h) - 1;
+ if lY + dy >= dest^.h then lY:= dest^.h - dy - 1;
+
+ for iX:= srcX to lX do
+ for iY:= srcY to lY do
begin
- i:= (destY + iY) * (dest^.pitch div 4) + (destX + iX);
- j:= (srcY + iY) * (src^.pitch div 4) + (srcX + iX);
- if (i < maxDest) and (j < maxSrc) and (srcPixels^[j] and AMask <> 0) then
+ // src pixel index
+ spi:= iY * src^.w + iX;
+ // dest pixel index
+ dpi:= (iY + dY) * dest^.w + (iX + dX);
+
+ // get src alpha (and set it as target alpha for now)
+ aT:= (srcPixels^[spi] and AMask) shr AShift;
+
+ // src pixel opaque?
+ if aT = 255 then
begin
- SDL_GetRGBA(destPixels^[i], dest^.format, @r0, @g0, @b0, @a0);
- SDL_GetRGBA(srcPixels^[j], src^.format, @r1, @g1, @b1, @a1);
- r0:= (r0 * (255 - LongInt(a1)) + r1 * LongInt(a1)) div 255;
- g0:= (g0 * (255 - LongInt(a1)) + g1 * LongInt(a1)) div 255;
- b0:= (b0 * (255 - LongInt(a1)) + b1 * LongInt(a1)) div 255;
- a0:= a0 + ((255 - LongInt(a0)) * a1 div 255);
- destPixels^[i]:= SDL_MapRGBA(dest^.format, r0, g0, b0, a0);
+ // just copy full pixel
+ destPixels^[dpi]:= srcPixels^[spi];
+ continue;
+ end;
+
+ // get dst alpha (without shift for now)
+ aD:= (destPixels^[dpi] and AMask) shr AShift;
+
+ // dest completely transparent?
+ if aD = 0 then
+ begin
+ // just copy src pixel
+ destPixels^[dpi]:= srcPixels^[spi];
+ continue;
end;
+
+ // looks like some blending is necessary
+
+ // set color of target RGB to src for now
+ SDL_GetRGB(srcPixels^[spi], src^.format, @rT, @gT, @bT);
+ SDL_GetRGB(destPixels^[dpi], dest^.format, @rD, @gD, @bD);
+ // note: this is not how to correctly blend RGB, just sayin' (R,G,B are not linear...)
+ rT:= (rD * (255 - aT) + rT * aT) div 255;
+ gT:= (gD * (255 - aT) + gT * aT) div 255;
+ bT:= (bD * (255 - aT) + bT * aT) div 255;
+ aT:= aD + ((255 - LongInt(aD)) * aT div 255);
+
+ destPixels^[dpi]:= SDL_MapRGBA(dest^.format, rT, gT, bT, Byte(aT));
+
end;
SDL_UnlockSurface(src);
@@ -184,7 +220,7 @@
procedure DrawSprite2Surf(sprite: TSprite; dest: PSDL_Surface; x,y: LongInt); inline;
begin
- DrawSpriteFrame2Surf(sprite, dest, x, y, 0);
+ DrawSpriteFrame2Surf(sprite, dest, x, y, 0);
end;
procedure DrawSpriteFrame2Surf(sprite: TSprite; dest: PSDL_Surface; x,y,frame: LongInt);
@@ -300,7 +336,7 @@
WriteInRoundRect(finalSurface, 0, 0, Color, font, s, maxLength);
- checkFails(SDL_SetColorKey(finalSurface, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, false);
+ checkFails(SDL_SetColorKey(finalSurface, SDL_TRUE, 0) = 0, errmsgTransparentSet, false);
RenderStringTexLim:= Surface2Tex(finalSurface, false);
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uScript.pas
--- a/hedgewars/uScript.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uScript.pas Sun Dec 17 00:09:24 2017 +0100
@@ -23,7 +23,7 @@
* This unit defines, implements and registers functions and
* variables/constants bindings for usage in Lua scripts.
*
- * Please keep http://hedgewars.org/kb/LuaAPI up to date!
+ * Please keep https://hedgewars.org/kb/LuaAPI up to date!
*
* Note: If you add a new function, make sure to test if _all_ parameters
* work as intended! (Especially conversions errors can sneak in
@@ -223,7 +223,7 @@
function LuaToGearTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
begin
if lua_isnoneornil(L, i) then i:= -1
- else i:= lua_tointeger(L, i);
+ else i:= Trunc(lua_tonumber(L, i));
if (i < ord(Low(TGearType))) or (i > ord(High(TGearType))) then
begin
LuaCallError('Invalid gearType!', call, paramsyntax);
@@ -236,7 +236,7 @@
function LuaToVisualGearTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
begin
if lua_isnoneornil(L, i) then i:= -1
- else i:= lua_tointeger(L, i);
+ else i:= Trunc(lua_tonumber(L, i));
if (i < ord(Low(TVisualGearType))) or (i > ord(High(TVisualGearType))) then
begin
LuaCallError('Invalid visualGearType!', call, paramsyntax);
@@ -249,7 +249,7 @@
function LuaToAmmoTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
begin
if lua_isnoneornil(L, i) then i:= -1
- else i:= lua_tointeger(L, i);
+ else i:= Trunc(lua_tonumber(L, i));
if (i < ord(Low(TAmmoType))) or (i > ord(High(TAmmoType))) then
begin
LuaCallError('Invalid ammoType!', call, paramsyntax);
@@ -262,7 +262,7 @@
function LuaToStatInfoTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
begin
if lua_isnoneornil(L, i) then i:= -1
- else i:= lua_tointeger(L, i);
+ else i:= Trunc(lua_tonumber(L, i));
if (i < ord(Low(TStatInfoType))) or (i > ord(High(TStatInfoType))) then
begin
LuaCallError('Invalid statInfoType!', call, paramsyntax);
@@ -275,7 +275,7 @@
function LuaToSoundOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
begin
if lua_isnoneornil(L, i) then i:= -1
- else i:= lua_tointeger(L, i);
+ else i:= Trunc(lua_tonumber(L, i));
if (i < ord(Low(TSound))) or (i > ord(High(TSound))) then
begin
LuaCallError('Invalid soundId!', call, paramsyntax);
@@ -288,10 +288,10 @@
function LuaToHogEffectOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
begin
if lua_isnoneornil(L, i) then i:= -1
- else i:= lua_tointeger(L, i);
+ else i:= Trunc(lua_tonumber(L, i));
if (i < ord(Low(THogEffect))) or (i > ord(High(THogEffect))) then
begin
- LuaCallError('Invalid gear type!', call, paramsyntax);
+ LuaCallError('Invalid effect type!', call, paramsyntax);
LuaToHogEffectOrd:= -1;
end
else
@@ -301,7 +301,7 @@
function LuaToCapGroupOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
begin
if lua_isnoneornil(L, i) then i:= -1
- else i:= lua_tointeger(L, i);
+ else i:= Trunc(lua_tonumber(L, i));
if (i < ord(Low(TCapGroup))) or (i > ord(High(TCapGroup))) then
begin
LuaCallError('Invalid capgroup type!', call, paramsyntax);
@@ -314,7 +314,7 @@
function LuaToSpriteOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
begin
if lua_isnoneornil(L, i) then i:= -1
- else i:= lua_tointeger(L, i);
+ else i:= Trunc(lua_tonumber(L, i));
if (i < ord(Low(TSprite))) or (i > ord(High(TSprite))) then
begin
LuaCallError('Invalid sprite id!', call, paramsyntax);
@@ -327,7 +327,7 @@
function LuaToMapGenOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline;
begin
if lua_isnoneornil(L, i) then i:= -1
- else i:= lua_tointeger(L, i);
+ else i:= Trunc(lua_tonumber(L, i));
if (i < ord(Low(TMapGen))) or (i > ord(High(TMapGen))) then
begin
LuaCallError('Invalid mapgen id!', call, paramsyntax);
@@ -350,7 +350,7 @@
function lc_band(L: PLua_State): LongInt; Cdecl;
begin
if CheckLuaParamCount(L, 2, 'band', 'value1, value2') then
- lua_pushinteger(L, lua_tointeger(L, 2) and lua_tointeger(L, 1))
+ lua_pushnumber(L, Trunc(lua_tonumber(L, 2)) and Trunc(lua_tonumber(L, 1)))
else
lua_pushnil(L);
lc_band := 1;
@@ -359,7 +359,7 @@
function lc_bor(L: PLua_State): LongInt; Cdecl;
begin
if CheckLuaParamCount(L, 2, 'bor', 'value1, value2') then
- lua_pushinteger(L, lua_tointeger(L, 2) or lua_tointeger(L, 1))
+ lua_pushnumber(L, Trunc(lua_tonumber(L, 2)) or Trunc(lua_tonumber(L, 1)))
else
lua_pushnil(L);
lc_bor := 1;
@@ -368,7 +368,7 @@
function lc_bnot(L: PLua_State): LongInt; Cdecl;
begin
if CheckLuaParamCount(L, 1, 'bnot', 'value') then
- lua_pushinteger(L, (not lua_tointeger(L, 1)))
+ lua_pushnumber(L, (not Trunc(lua_tonumber(L, 1))))
else
lua_pushnil(L);
lc_bnot := 1;
@@ -377,7 +377,7 @@
function lc_div(L: PLua_State): LongInt; Cdecl;
begin
if CheckLuaParamCount(L, 2, 'div', 'dividend, divisor') then
- lua_pushinteger(L, lua_tointeger(L, 1) div lua_tointeger(L, 2))
+ lua_pushnumber(L, Trunc(lua_tonumber(L, 1)) div Trunc(lua_tonumber(L, 2)))
else
lua_pushnil(L);
lc_div := 1;
@@ -386,14 +386,14 @@
function lc_getinputmask(L : Plua_State) : LongInt; Cdecl;
begin
if CheckLuaParamCount(L, 0, 'GetInputMask', '') then
- lua_pushinteger(L, InputMask);
+ lua_pushnumber(L, InputMask);
lc_getinputmask:= 1
end;
function lc_setinputmask(L : Plua_State) : LongInt; Cdecl;
begin
if CheckLuaParamCount(L, 1, 'SetInputMask', 'mask') then
- InputMask:= lua_tointeger(L, 1);
+ InputMask:= Trunc(lua_tonumber(L, 1));
lc_setinputmask:= 0
end;
@@ -467,7 +467,7 @@
cBuildMaxDist:= cDefaultBuildMaxDist;
end
else
- CBuildMaxDist:= lua_tointeger(L, 1);
+ CBuildMaxDist:= Trunc(lua_tonumber(L, 1));
end;
lc_setmaxbuilddistance:= 0;
end;
@@ -539,7 +539,7 @@
function lc_showmission(L : Plua_State) : LongInt; Cdecl;
begin
if CheckLuaParamCount(L, 5, 'ShowMission', 'caption, subcaption, text, icon, time') then
- ShowMission(lua_tostringA(L, 1), lua_tostringA(L, 2), lua_tostringA(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5));
+ ShowMission(lua_tostringA(L, 1), lua_tostringA(L, 2), lua_tostringA(L, 3), Trunc(lua_tonumber(L, 4)), Trunc(lua_tonumber(L, 5)));
lc_showmission:= 0;
end;
@@ -550,6 +550,33 @@
lc_hidemission:= 0;
end;
+function lc_setammotexts(L : Plua_State) : LongInt; Cdecl;
+const
+ call = 'SetAmmoTexts';
+ params = 'ammoType, name, caption, description';
+begin
+ if CheckLuaParamCount(L, 4, call, params) then
+ SetAmmoTexts(TAmmoType(LuaToAmmoTypeOrd(L, 1, call, params)), lua_tostringA(L, 2), lua_tostringA(L, 3), lua_tostringA(L, 4));
+ lc_setammotexts:= 0;
+end;
+
+function lc_setammodescriptionappendix(L : Plua_State) : LongInt; Cdecl;
+const
+ call = 'SetAmmoDescriptionAppendix';
+ params = 'ammoType, descAppend';
+var
+ ammoType: TAmmoType;
+ descAppend: ansistring;
+begin
+ if CheckLuaParamCount(L, 2, call, params) then
+ begin
+ ammoType := TAmmoType(LuaToAmmoTypeOrd(L, 1, call, params));
+ descAppend := lua_tostringA(L, 2);
+ trluaammoa[Ammoz[ammoType].NameId] := descAppend;
+ end;
+ lc_setammodescriptionappendix := 0;
+end;
+
function lc_enablegameflags(L : Plua_State) : LongInt; Cdecl;
var i, n : integer;
begin
@@ -557,7 +584,7 @@
if CheckAndFetchLuaParamMinCount(L, 1, 'EnableGameFlags', 'gameFlag, ... ', n) then
begin
for i:= 1 to n do
- GameFlags := GameFlags or LongWord(lua_tointeger(L, i));
+ GameFlags := GameFlags or LongWord(Trunc(lua_tonumber(L, i)));
ScriptSetInteger('GameFlags', GameFlags);
end;
lc_enablegameflags:= 0;
@@ -570,7 +597,7 @@
if CheckAndFetchLuaParamMinCount(L, 1, 'DisableGameFlags', 'gameFlag, ... ', n) then
begin
for i:= 1 to n do
- GameFlags := GameFlags and (not LongWord(lua_tointeger(L, i)));
+ GameFlags := GameFlags and (not LongWord(Trunc(lua_tonumber(L, i))));
ScriptSetInteger('GameFlags', GameFlags);
end;
lc_disablegameflags:= 0;
@@ -589,7 +616,7 @@
function lc_getgameflag(L : Plua_State) : LongInt; Cdecl;
begin
if CheckLuaParamCount(L, 1, 'GetGameFlag', 'gameflag') then
- lua_pushboolean(L, (GameFlags and LongWord(lua_tointeger(L, 1)) <> 0))
+ lua_pushboolean(L, (GameFlags and LongWord(Trunc(lua_tonumber(L, 1))) <> 0))
else
lua_pushnil(L);
lc_getgameflag:= 1;
@@ -609,7 +636,7 @@
begin
cg:= LuaToCapGroupOrd(L, 3, call, params);
if cg >= 0 then
- AddCaption(lua_tostringA(L, 1), lua_tointeger(L, 2) shr 8, TCapGroup(cg));
+ AddCaption(lua_tostringA(L, 1), Trunc(lua_tonumber(L, 2)) shr 8, TCapGroup(cg));
end
end;
lc_addcaption:= 0;
@@ -638,10 +665,10 @@
begin
if CheckLuaParamCount(L, 4,'SpawnFakeHealthCrate', 'x, y, explode, poison') then
begin
- gear := SpawnFakeCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2),
+ gear := SpawnFakeCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)),
HealthCrate, lua_toboolean(L, 3), lua_toboolean(L, 4));
if gear <> nil then
- lua_pushinteger(L, gear^.uid)
+ lua_pushnumber(L, gear^.uid)
else lua_pushnil(L)
end
else
@@ -654,10 +681,10 @@
begin
if CheckLuaParamCount(L, 4,'SpawnFakeAmmoCrate', 'x, y, explode, poison') then
begin
- gear := SpawnFakeCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2),
+ gear := SpawnFakeCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)),
AmmoCrate, lua_toboolean(L, 3), lua_toboolean(L, 4));
if gear <> nil then
- lua_pushinteger(L, gear^.uid)
+ lua_pushnumber(L, gear^.uid)
else lua_pushnil(L)
end
else
@@ -670,10 +697,10 @@
begin
if CheckLuaParamCount(L, 4,'SpawnFakeUtilityCrate', 'x, y, explode, poison') then
begin
- gear := SpawnFakeCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2),
+ gear := SpawnFakeCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)),
UtilityCrate, lua_toboolean(L, 3), lua_toboolean(L, 4));
if gear <> nil then
- lua_pushinteger(L, gear^.uid)
+ lua_pushnumber(L, gear^.uid)
else lua_pushnil(L)
end
else
@@ -688,12 +715,12 @@
if CheckAndFetchParamCount(L, 2, 3, 'SpawnHealthCrate', 'x, y [, health]', n) then
begin
if n = 3 then
- health:= lua_tointeger(L, 3)
+ health:= Trunc(lua_tonumber(L, 3))
else
health:= cHealthCaseAmount;
- gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), HealthCrate, health, 0);
+ gear := SpawnCustomCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)), HealthCrate, health, 0);
if gear <> nil then
- lua_pushinteger(L, gear^.uid)
+ lua_pushnumber(L, gear^.uid)
else lua_pushnil(L);
end
else
@@ -708,10 +735,10 @@
if CheckAndFetchParamCount(L, 3, 4, 'SpawnAmmoCrate', 'x, y, content [, amount]', n) then
begin
if n = 3 then
- gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), AmmoCrate, lua_tointeger(L, 3), 0)
- else gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), AmmoCrate, lua_tointeger(L, 3), lua_tointeger(L, 4));
+ gear := SpawnCustomCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)), AmmoCrate, Trunc(lua_tonumber(L, 3)), 0)
+ else gear := SpawnCustomCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)), AmmoCrate, Trunc(lua_tonumber(L, 3)), Trunc(lua_tonumber(L, 4)));
if gear <> nil then
- lua_pushinteger(L, gear^.uid)
+ lua_pushnumber(L, gear^.uid)
else lua_pushnil(L);
end
else
@@ -726,10 +753,10 @@
if CheckAndFetchParamCount(L, 3, 4, 'SpawnUtilityCrate', 'x, y, content [, amount]', n) then
begin
if n = 3 then
- gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), UtilityCrate, lua_tointeger(L, 3), 0)
- else gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), UtilityCrate, lua_tointeger(L, 3), lua_tointeger(L, 4));
+ gear := SpawnCustomCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)), UtilityCrate, Trunc(lua_tonumber(L, 3)), 0)
+ else gear := SpawnCustomCrateAt(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)), UtilityCrate, Trunc(lua_tonumber(L, 3)), Trunc(lua_tonumber(L, 4)));
if gear <> nil then
- lua_pushinteger(L, gear^.uid)
+ lua_pushnumber(L, gear^.uid)
else lua_pushnil(L);
end
else
@@ -752,16 +779,16 @@
if t >= 0 then
begin
gt:= TGearType(t);
- x:= lua_tointeger(L, 1);
- y:= lua_tointeger(L, 2);
- s:= lua_tointeger(L, 4);
- dx:= int2hwFloat(lua_tointeger(L, 5)) / 1000000;
- dy:= int2hwFloat(lua_tointeger(L, 6)) / 1000000;
- t:= lua_tointeger(L, 7);
+ x:= Trunc(lua_tonumber(L, 1));
+ y:= Trunc(lua_tonumber(L, 2));
+ s:= Trunc(lua_tonumber(L, 4));
+ dx:= int2hwFloat(Trunc(lua_tonumber(L, 5))) / 1000000;
+ dy:= int2hwFloat(Trunc(lua_tonumber(L, 6))) / 1000000;
+ t:= Trunc(lua_tonumber(L, 7));
gear:= AddGear(x, y, gt, s, dx, dy, t);
lastGearByUID:= gear;
- lua_pushinteger(L, gear^.uid)
+ lua_pushnumber(L, gear^.uid)
end
else
lua_pushnil(L);
@@ -776,7 +803,7 @@
begin
if CheckLuaParamCount(L, 1, 'DeleteGear', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
gear^.Message:= gear^.Message or gmDelete;
end;
@@ -800,14 +827,14 @@
if s >= 0 then
begin
vgt:= TVisualGearType(s);
- x:= lua_tointeger(L, 1);
- y:= lua_tointeger(L, 2);
- s:= lua_tointeger(L, 4);
+ x:= Trunc(lua_tonumber(L, 1));
+ y:= Trunc(lua_tonumber(L, 2));
+ s:= Trunc(lua_tonumber(L, 4));
c:= lua_toboolean(L, 5);
if n = 6 then
begin
- layer:= lua_tointeger(L, 6);
+ layer:= Trunc(lua_tonumber(L, 6));
vg:= AddVisualGear(x, y, vgt, s, c, layer);
end
else
@@ -817,7 +844,7 @@
begin
lastVisualGearByUID:= vg;
uid:= vg^.uid;
- lua_pushinteger(L, uid);
+ lua_pushnumber(L, uid);
end;
end
else
@@ -834,7 +861,7 @@
vg:= nil;
if CheckLuaParamCount(L, 1, 'DeleteVisualGear', 'vgUid') then
begin
- vg:= VisualGearByUID(lua_tointeger(L, 1));
+ vg:= VisualGearByUID(Trunc(lua_tonumber(L, 1)));
if vg <> nil then
DeleteVisualGear(vg);
end;
@@ -843,24 +870,41 @@
lc_deletevisualgear:= 1
end;
+function lc_getvisualgeartype(L : Plua_State) : LongInt; Cdecl;
+var vg : PVisualGear;
+begin
+ if CheckLuaParamCount(L, 1, 'GetVisualGearType', 'vgUid') then
+ begin
+ vg := VisualGearByUID(Trunc(lua_tonumber(L, 1)));
+ if vg <> nil then
+ lua_pushnumber(L, ord(vg^.Kind))
+ else
+ lua_pushnil(L);
+ end
+ else
+ lua_pushnil(L); // return value on stack (nil)
+ lc_getvisualgeartype:= 1
+end;
+
+
function lc_getvisualgearvalues(L : Plua_State) : LongInt; Cdecl;
var vg: PVisualGear;
begin
if CheckLuaParamCount(L, 1, 'GetVisualGearValues', 'vgUid') then
begin
- vg:= VisualGearByUID(lua_tointeger(L, 1));
+ vg:= VisualGearByUID(Trunc(lua_tonumber(L, 1)));
if vg <> nil then
begin
- lua_pushinteger(L, round(vg^.X));
- lua_pushinteger(L, round(vg^.Y));
+ lua_pushnumber(L, round(vg^.X));
+ lua_pushnumber(L, round(vg^.Y));
lua_pushnumber(L, vg^.dX);
lua_pushnumber(L, vg^.dY);
lua_pushnumber(L, vg^.Angle);
- lua_pushinteger(L, vg^.Frame);
- lua_pushinteger(L, vg^.FrameTicks);
- lua_pushinteger(L, vg^.State);
- lua_pushinteger(L, vg^.Timer);
- lua_pushinteger(L, vg^.Tint);
+ lua_pushnumber(L, vg^.Frame);
+ lua_pushnumber(L, vg^.FrameTicks);
+ lua_pushnumber(L, vg^.State);
+ lua_pushnumber(L, vg^.Timer);
+ lua_pushnumber(L, vg^.Tint);
end
else
begin
@@ -882,13 +926,13 @@
// Param count can be 1-11 at present
// if CheckLuaParamCount(L, 11, 'SetVisualGearValues', 'vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint') then
// begin
- vg:= VisualGearByUID(lua_tointeger(L, 1));
+ vg:= VisualGearByUID(Trunc(lua_tonumber(L, 1)));
if vg <> nil then
begin
if not lua_isnoneornil(L, 2) then
- vg^.X:= lua_tointeger(L, 2);
+ vg^.X:= Trunc(lua_tonumber(L, 2));
if not lua_isnoneornil(L, 3) then
- vg^.Y:= lua_tointeger(L, 3);
+ vg^.Y:= Trunc(lua_tonumber(L, 3));
if not lua_isnoneornil(L, 4) then
vg^.dX:= lua_tonumber(L, 4);
if not lua_isnoneornil(L, 5) then
@@ -896,15 +940,15 @@
if not lua_isnoneornil(L, 6) then
vg^.Angle:= lua_tonumber(L, 6);
if not lua_isnoneornil(L, 7) then
- vg^.Frame:= lua_tointeger(L, 7);
+ vg^.Frame:= Trunc(lua_tonumber(L, 7));
if not lua_isnoneornil(L, 8) then
- vg^.FrameTicks:= lua_tointeger(L, 8);
+ vg^.FrameTicks:= Trunc(lua_tonumber(L, 8));
if not lua_isnoneornil(L, 9) then
- vg^.State:= lua_tointeger(L, 9);
+ vg^.State:= Trunc(lua_tonumber(L, 9));
if not lua_isnoneornil(L, 10) then
- vg^.Timer:= lua_tointeger(L, 10);
+ vg^.Timer:= Trunc(lua_tonumber(L, 10));
if not lua_isnoneornil(L, 11) then
- vg^.Tint:= lua_tointeger(L, 11)
+ vg^.Tint:= Trunc(lua_tonumber(L, 11))
end;
// end
// else
@@ -919,22 +963,22 @@
begin
if CheckLuaParamCount(L, 1, 'GetGearValues', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
begin
- lua_pushinteger(L, gear^.Angle);
- lua_pushinteger(L, gear^.Power);
- lua_pushinteger(L, gear^.WDTimer);
- lua_pushinteger(L, gear^.Radius);
- lua_pushinteger(L, hwRound(gear^.Density * _10000));
- lua_pushinteger(L, gear^.Karma);
+ lua_pushnumber(L, gear^.Angle);
+ lua_pushnumber(L, gear^.Power);
+ lua_pushnumber(L, gear^.WDTimer);
+ lua_pushnumber(L, gear^.Radius);
+ lua_pushnumber(L, hwRound(gear^.Density * _10000));
+ lua_pushnumber(L, gear^.Karma);
lua_pushnumber(L, gear^.DirAngle);
- lua_pushinteger(L, gear^.AdvBounce);
- lua_pushinteger(L, Integer(gear^.ImpactSound));
- lua_pushinteger(L, gear^.nImpactSounds);
- lua_pushinteger(L, gear^.Tint);
- lua_pushinteger(L, gear^.Damage);
- lua_pushinteger(L, gear^.Boom)
+ lua_pushnumber(L, gear^.AdvBounce);
+ lua_pushnumber(L, Integer(gear^.ImpactSound));
+ lua_pushnumber(L, gear^.nImpactSounds);
+ lua_pushnumber(L, gear^.Tint);
+ lua_pushnumber(L, gear^.Damage);
+ lua_pushnumber(L, gear^.Boom)
end
else
begin
@@ -958,35 +1002,35 @@
// Currently allows 1-14 params
// if CheckLuaParamCount(L, 14, 'SetGearValues', 'gearUid, Angle, Power, WDTimer, Radius, Density, Karma, DirAngle, AdvBounce, ImpactSound, # ImpactSounds, Tint, Damage, Boom') then
// begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
begin
if not lua_isnoneornil(L, 2) then
- gear^.Angle := lua_tointeger(L, 2);
+ gear^.Angle := Trunc(lua_tonumber(L, 2));
if not lua_isnoneornil(L, 3) then
- gear^.Power := lua_tointeger(L, 3);
+ gear^.Power := Trunc(lua_tonumber(L, 3));
if not lua_isnoneornil(L, 4) then
- gear^.WDTimer := lua_tointeger(L, 4);
+ gear^.WDTimer := Trunc(lua_tonumber(L, 4));
if not lua_isnoneornil(L, 5) then
- gear^.Radius := lua_tointeger(L, 5);
+ gear^.Radius := Trunc(lua_tonumber(L, 5));
if not lua_isnoneornil(L, 6) then
- gear^.Density:= int2hwFloat(lua_tointeger(L, 6)) / 10000;
+ gear^.Density:= int2hwFloat(Trunc(lua_tonumber(L, 6))) / 10000;
if not lua_isnoneornil(L, 7) then
- gear^.Karma := lua_tointeger(L, 7);
+ gear^.Karma := Trunc(lua_tonumber(L, 7));
if not lua_isnoneornil(L, 8) then
gear^.DirAngle:= lua_tonumber(L, 8);
if not lua_isnoneornil(L, 9) then
- gear^.AdvBounce := lua_tointeger(L, 9);
+ gear^.AdvBounce := Trunc(lua_tonumber(L, 9));
if not lua_isnoneornil(L, 10) then
- gear^.ImpactSound := TSound(lua_tointeger(L, 10));
+ gear^.ImpactSound := TSound(Trunc(lua_tonumber(L, 10)));
if not lua_isnoneornil(L, 11) then
- gear^.nImpactSounds := lua_tointeger(L, 11);
+ gear^.nImpactSounds := Trunc(lua_tonumber(L, 11));
if not lua_isnoneornil(L, 12) then
- gear^.Tint := lua_tointeger(L, 12);
+ gear^.Tint := Trunc(lua_tonumber(L, 12));
if not lua_isnoneornil(L, 13) then
- gear^.Damage := lua_tointeger(L, 13);
+ gear^.Damage := Trunc(lua_tonumber(L, 13));
if not lua_isnoneornil(L, 14) then
- gear^.Boom := lua_tointeger(L, 14);
+ gear^.Boom := Trunc(lua_tonumber(L, 14));
end;
// end
// else
@@ -1001,7 +1045,7 @@
if FollowGear = nil then
lua_pushnil(L)
else
- lua_pushinteger(L, FollowGear^.uid);
+ lua_pushnumber(L, FollowGear^.uid);
end
else
lua_pushnil(L);
@@ -1013,9 +1057,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetGearType', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- lua_pushinteger(L, ord(gear^.Kind))
+ lua_pushnumber(L, ord(gear^.Kind))
else
lua_pushnil(L);
end
@@ -1029,9 +1073,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetGearMessage', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- lua_pushinteger(L, gear^.message)
+ lua_pushnumber(L, gear^.message)
else
lua_pushnil(L);
end
@@ -1045,9 +1089,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetGearElasticity', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- lua_pushinteger(L, hwRound(gear^.elasticity * _10000))
+ lua_pushnumber(L, hwRound(gear^.elasticity * _10000))
else
lua_pushnil(L);
end
@@ -1061,9 +1105,9 @@
begin
if CheckLuaParamCount(L, 2, 'SetGearElasticity', 'gearUid, Elasticity') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- gear^.Elasticity:= int2hwFloat(lua_tointeger(L, 2)) / 10000
+ gear^.Elasticity:= int2hwFloat(Trunc(lua_tonumber(L, 2))) / 10000
end;
lc_setgearelasticity:= 0
end;
@@ -1073,9 +1117,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetGearFriction', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- lua_pushinteger(L, hwRound(gear^.friction * _10000))
+ lua_pushnumber(L, hwRound(gear^.friction * _10000))
else
lua_pushnil(L);
end
@@ -1089,9 +1133,9 @@
begin
if CheckLuaParamCount(L, 2, 'SetGearFriction', 'gearUid, Friction') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- gear^.Friction:= int2hwFloat(lua_tointeger(L, 2)) / 10000
+ gear^.Friction:= int2hwFloat(Trunc(lua_tonumber(L, 2))) / 10000
end;
lc_setgearfriction:= 0
end;
@@ -1101,9 +1145,9 @@
begin
if CheckLuaParamCount(L, 2, 'SetGearMessage', 'gearUid, message') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- gear^.message:= lua_tointeger(L, 2);
+ gear^.message:= Trunc(lua_tonumber(L, 2));
end;
lc_setgearmessage:= 0
end;
@@ -1113,9 +1157,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetGearPos', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- lua_pushinteger(L, gear^.Pos)
+ lua_pushnumber(L, gear^.Pos)
else
lua_pushnil(L);
end
@@ -1129,9 +1173,9 @@
begin
if CheckLuaParamCount(L, 2, 'SetGearPos', 'gearUid, value') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- gear^.Pos:= lua_tointeger(L, 2);
+ gear^.Pos:= Trunc(lua_tonumber(L, 2));
end;
lc_setgearpos:= 0
end;
@@ -1141,9 +1185,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetGearCollisionMask', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- lua_pushinteger(L, gear^.CollisionMask)
+ lua_pushnumber(L, gear^.CollisionMask)
else
lua_pushnil(L);
end
@@ -1157,9 +1201,9 @@
begin
if CheckLuaParamCount(L, 2, 'SetGearCollisionMask', 'gearUid, mask') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- gear^.CollisionMask:= lua_tointeger(L, 2);
+ gear^.CollisionMask:= Trunc(lua_tonumber(L, 2));
end;
lc_setgearcollisionmask:= 0
end;
@@ -1169,9 +1213,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetHogLevel', 'gearUid') then
begin
- gear := GearByUID(lua_tointeger(L, 1));
+ gear := GearByUID(Trunc(lua_tonumber(L, 1)));
if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
- lua_pushinteger(L, gear^.Hedgehog^.BotLevel)
+ lua_pushnumber(L, gear^.Hedgehog^.BotLevel)
else
lua_pushnil(L);
end;
@@ -1183,9 +1227,9 @@
begin
if CheckLuaParamCount(L, 2, 'SetHogLevel', 'gearUid, level') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
- gear^.Hedgehog^.BotLevel:= lua_tointeger(L, 2);
+ gear^.Hedgehog^.BotLevel:= Trunc(lua_tonumber(L, 2));
end;
lc_sethoglevel:= 0
end;
@@ -1195,10 +1239,10 @@
begin
if CheckLuaParamCount(L, 1, 'GetHogClan', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
begin
- lua_pushinteger(L, gear^.Hedgehog^.Team^.Clan^.ClanIndex)
+ lua_pushnumber(L, gear^.Hedgehog^.Team^.Clan^.ClanIndex)
end
else
lua_pushnil(L);
@@ -1213,7 +1257,7 @@
begin
if CheckLuaParamCount(L, 1, 'GetClanColor', 'clanIdx') then
begin
- idx:= lua_tointeger(L, 1);
+ idx:= Trunc(lua_tonumber(L, 1));
if (not lua_isnumber(L, 1)) then
begin
LuaError('Argument ''clanIdx'' must be a number!');
@@ -1225,7 +1269,7 @@
lua_pushnil(L);
end
else
- lua_pushinteger(L, ClansArray[idx]^.Color shl 8 or $FF);
+ lua_pushnumber(L, ClansArray[idx]^.Color shl 8 or $FF);
end
else
lua_pushnil(L); // return value on stack (nil)
@@ -1240,10 +1284,10 @@
begin
if CheckLuaParamCount(L, 2, 'SetClanColor', 'clan, color') then
begin
- i:= lua_tointeger(L,1);
+ i:= Trunc(lua_tonumber(L,1));
if i >= ClansCount then exit(0);
clan := ClansArray[i];
- clan^.Color:= lua_tointeger(L, 2) shr 8;
+ clan^.Color:= Trunc(lua_tonumber(L, 2)) shr 8;
for i:= 0 to Pred(clan^.TeamsNumber) do
begin
@@ -1274,7 +1318,7 @@
begin
if CheckLuaParamCount(L, 1, 'GetHogVoicepack', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.Voicepack^.name))
else
@@ -1290,7 +1334,7 @@
begin
if CheckLuaParamCount(L, 1, 'GetHogGrave', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.GraveName))
else
@@ -1306,7 +1350,8 @@
begin
if CheckLuaParamCount(L, 1, 'GetHogFlag', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
+ // TODO error messages
if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.Flag))
else
@@ -1317,12 +1362,47 @@
lc_gethogflag:= 1
end;
+function lc_gethogfort(L : Plua_State) : LongInt; Cdecl;
+var gear : PGear;
+begin
+ if CheckLuaParamCount(L, 1, 'GetHogFort', 'gearUid') then
+ begin
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
+ // TODO error messages
+ if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
+ lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.FortName))
+ else
+ lua_pushnil(L);
+ end
+ else
+ lua_pushnil(L); // return value on stack (nil)
+ lc_gethogfort:= 1
+end;
+
+function lc_ishoglocal(L : Plua_State) : LongInt; Cdecl;
+var gear : PGear;
+begin
+ if CheckLuaParamCount(L, 1, 'IsHogLocal', 'gearUid') then
+ begin
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
+ // TODO error messages
+ if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
+ lua_pushboolean(L, IsHogLocal(gear^.Hedgehog))
+ else
+ lua_pushnil(L);
+ end
+ else
+ lua_pushnil(L); // return value on stack (nil)
+ lc_ishoglocal:= 1
+end;
+
function lc_gethogteamname(L : Plua_State) : LongInt; Cdecl;
var gear : PGear;
begin
if CheckLuaParamCount(L, 1, 'GetHogTeamName', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
+ // TODO error messages
if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.TeamName))
else
@@ -1338,7 +1418,7 @@
begin
if CheckLuaParamCount(L, 2, 'SetHogTeamName', 'gearUid, name') then
begin
- gear := GearByUID(lua_tointeger(L, 1));
+ gear := GearByUID(Trunc(lua_tonumber(L, 1)));
if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
begin
gear^.Hedgehog^.Team^.TeamName := lua_tostring(L, 2);
@@ -1359,7 +1439,7 @@
begin
if CheckLuaParamCount(L, 1, 'GetHogName', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
begin
lua_pushstring(L, str2pchar(gear^.Hedgehog^.Name))
@@ -1377,7 +1457,7 @@
begin
if CheckLuaParamCount(L, 2, 'SetHogName', 'gearUid, name') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
begin
gear^.Hedgehog^.Name:= lua_tostring(L, 2);
@@ -1394,9 +1474,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetTimer', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- lua_pushinteger(L, gear^.Timer)
+ lua_pushnumber(L, gear^.Timer)
else
lua_pushnil(L);
end
@@ -1410,9 +1490,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetFlightTime', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- lua_pushinteger(L, gear^.FlightTime)
+ lua_pushnumber(L, gear^.FlightTime)
else
lua_pushnil(L);
end
@@ -1426,9 +1506,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetHealth', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- lua_pushinteger(L, gear^.Health)
+ lua_pushnumber(L, gear^.Health)
else
lua_pushnil(L);
end
@@ -1442,9 +1522,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetX', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- lua_pushinteger(L, hwRound(gear^.X))
+ lua_pushnumber(L, hwRound(gear^.X))
else
lua_pushnil(L);
end
@@ -1458,9 +1538,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetY', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- lua_pushinteger(L, hwRound(gear^.Y))
+ lua_pushnumber(L, hwRound(gear^.Y))
else
lua_pushnil(L);
end
@@ -1474,8 +1554,8 @@
begin
if CheckLuaParamCount(L, 2, 'CopyPV', 'fromGearUid, toGearUid') then
begin
- gears:= GearByUID(lua_tointeger(L, 1));
- geard:= GearByUID(lua_tointeger(L, 2));
+ gears:= GearByUID(Trunc(lua_tonumber(L, 1)));
+ geard:= GearByUID(Trunc(lua_tonumber(L, 2)));
if (gears <> nil) and (geard <> nil) then
begin
geard^.X:= gears^.X;
@@ -1492,7 +1572,7 @@
begin
if CheckLuaParamCount(L, 1, 'FollowGear', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then FollowGear:= gear
end;
lc_followgear:= 0
@@ -1506,12 +1586,12 @@
begin
if CheckAndFetchParamCount(L, 3, 4, 'HogSay', 'gearUid, text, manner [, vgState]', n) then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
begin
// state defaults to 0 if state param is given
if n = 4 then
- s:= lua_tointeger(L, 4)
+ s:= Trunc(lua_tonumber(L, 4))
else
s:= 0;
vgear:= AddVisualGear(0, 0, vgtSpeechBubble, s, true);
@@ -1525,10 +1605,10 @@
end
else vgear^.Frame:= gear^.uid;
- vgear^.FrameTicks:= lua_tointeger(L, 3);
+ vgear^.FrameTicks:= Trunc(lua_tonumber(L, 3));
if (vgear^.FrameTicks < 1) or (vgear^.FrameTicks > 3) then
vgear^.FrameTicks:= 1;
- lua_pushinteger(L, vgear^.Uid);
+ lua_pushnumber(L, vgear^.Uid);
end
end
else
@@ -1544,7 +1624,7 @@
begin
if CheckLuaParamCount(L, 1, 'SwitchHog', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
// should we allow this when there is no current hedgehog? might do some odd(er) things to turn sequence.
if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) and (CurrentHedgehog <> nil) then
begin
@@ -1558,8 +1638,14 @@
end;
SwitchCurrentHedgehog(gear^.Hedgehog);
+ AmmoMenuInvalidated:= true;
CurrentTeam:= CurrentHedgehog^.Team;
+ repeat
+ CurrentTeam^.CurrHedgehog := (CurrentTeam^.CurrHedgehog + 1) mod CurrentTeam^.HedgehogsNumber
+ until
+ CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear = CurrentHedgehog^.Gear;
+
gear^.State:= gear^.State or gstHHDriven;
gear^.Active := true;
gear^.Z := cCurrHHZ;
@@ -1581,12 +1667,12 @@
at:= LuaToAmmoTypeOrd(L, 2, call, params);
if at >= 0 then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if (gear <> nil) and (gear^.Hedgehog <> nil) then
if n = 2 then
AddAmmo(gear^.Hedgehog^, TAmmoType(at))
else
- SetAmmo(gear^.Hedgehog^, TAmmoType(at), lua_tointeger(L, 3))
+ SetAmmo(gear^.Hedgehog^, TAmmoType(at), Trunc(lua_tonumber(L, 3)))
end;
end;
lc_addammo:= 0
@@ -1602,7 +1688,7 @@
begin
if CheckLuaParamCount(L, 2, call, params) then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if (gear <> nil) and (gear^.Hedgehog <> nil) then
begin
at:= LuaToAmmoTypeOrd(L, 2, call, params);
@@ -1610,12 +1696,12 @@
begin
ammo:= GetAmmoEntry(gear^.Hedgehog^, TAmmoType(at));
if ammo^.AmmoType = amNothing then
- lua_pushinteger(L, 0)
+ lua_pushnumber(L, 0)
else
- lua_pushinteger(L, ammo^.Count);
+ lua_pushnumber(L, ammo^.Count);
end;
end
- else lua_pushinteger(L, 0);
+ else lua_pushnumber(L, 0);
end
else
lua_pushnil(L);
@@ -1627,10 +1713,10 @@
begin
if CheckLuaParamCount(L, 2, 'SetHealth', 'gearUid, health') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
begin
- gear^.Health:= lua_tointeger(L, 2);
+ gear^.Health:= Trunc(lua_tonumber(L, 2));
if (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
begin
@@ -1651,8 +1737,8 @@
begin
if CheckLuaParamCount(L, 2, 'SetTimer', 'gearUid, timer') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
- if gear <> nil then gear^.Timer:= lua_tointeger(L, 2)
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
+ if gear <> nil then gear^.Timer:= Trunc(lua_tonumber(L, 2))
end;
lc_settimer:= 0
end;
@@ -1662,8 +1748,8 @@
begin
if CheckLuaParamCount(L, 2, 'SetFlightTime', 'gearUid, flighttime') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
- if gear <> nil then gear^.FlightTime:= lua_tointeger(L, 2)
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
+ if gear <> nil then gear^.FlightTime:= Trunc(lua_tonumber(L, 2))
end;
lc_setflighttime:= 0
end;
@@ -1680,9 +1766,9 @@
t:= LuaToHogEffectOrd(L, 2, call, params);
if t >= 0 then
begin
- gear := GearByUID(lua_tointeger(L, 1));
+ gear := GearByUID(Trunc(lua_tonumber(L, 1)));
if (gear <> nil) and (gear^.Hedgehog <> nil) then
- gear^.Hedgehog^.Effects[THogEffect(t)]:= lua_tointeger(L, 3);
+ gear^.Hedgehog^.Effects[THogEffect(t)]:= Trunc(lua_tonumber(L, 3));
end;
end;
lc_seteffect := 0;
@@ -1700,15 +1786,15 @@
t:= LuaToHogEffectOrd(L, 2, call, params);
if t >= 0 then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if (gear <> nil) and (gear^.Hedgehog <> nil) then
- lua_pushinteger(L, gear^.Hedgehog^.Effects[THogEffect(t)])
+ lua_pushnumber(L, gear^.Hedgehog^.Effects[THogEffect(t)])
else
- lua_pushinteger(L, 0)
+ lua_pushnumber(L, 0)
end;
end
else
- lua_pushinteger(L, 0);
+ lua_pushnumber(L, 0);
lc_geteffect:= 1
end;
@@ -1717,10 +1803,10 @@
begin
if CheckLuaParamCount(L, 2, 'SetState', 'gearUid, state') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
begin
- gear^.State:= lua_tointeger(L, 2);
+ gear^.State:= Trunc(lua_tonumber(L, 2));
SetAllToActive;
end
end;
@@ -1732,9 +1818,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetState', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- lua_pushinteger(L, gear^.State)
+ lua_pushnumber(L, gear^.State)
else
lua_pushnil(L)
end
@@ -1748,9 +1834,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetTag', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- lua_pushinteger(L, gear^.Tag)
+ lua_pushnumber(L, gear^.Tag)
else
lua_pushnil(L);
end
@@ -1764,10 +1850,10 @@
begin
if CheckLuaParamCount(L, 2, 'SetTag', 'gearUid, tag') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
begin
- gear^.Tag:= lua_tointeger(L, 2);
+ gear^.Tag:= Trunc(lua_tonumber(L, 2));
SetAllToActive;
end
end;
@@ -1781,6 +1867,19 @@
lc_endgame:= 0
end;
+function lc_endturn(L : Plua_State) : LongInt; Cdecl;
+var n: LongInt;
+const
+ call = 'EndTurn';
+ params = '[noTaunts]';
+begin
+ if CheckAndFetchParamCount(L, 0, 1, call, params, n) then
+ if n >= 1 then
+ LuaNoEndTurnTaunts:= lua_toboolean(L, 1);
+ LuaEndTurnRequested:= true;
+ lc_endturn:= 0
+end;
+
function lc_sendstat(L : Plua_State) : LongInt; Cdecl;
var statInfo : TStatInfoType;
i, n : LongInt;
@@ -1844,6 +1943,27 @@
lc_sendstat:= 0
end;
+function lc_sendgameresultoff(L : Plua_State) : LongInt; Cdecl;
+begin
+ L:= L; // avoid compiler hint
+ uStats.SendGameResultOn := false;
+ lc_sendgameresultoff:= 0
+end;
+
+function lc_sendrankingstatsoff(L : Plua_State) : LongInt; Cdecl;
+begin
+ L:= L; // avoid compiler hint
+ uStats.SendRankingStatsOn := false;
+ lc_sendrankingstatsoff:= 0
+end;
+
+function lc_sendachievementsstatsoff(L : Plua_State) : LongInt; Cdecl;
+begin
+ L:= L; // avoid compiler hint
+ uStats.SendAchievementsStatsOn := false;
+ lc_sendachievementsstatsoff:= 0
+end;
+
function lc_sendhealthstatsoff(L : Plua_State) : LongInt; Cdecl;
begin
L:= L; // avoid compiler hint
@@ -1859,10 +1979,10 @@
begin
if CheckAndFetchParamCount(L, 4, 5, 'FindPlace', 'gearUid, fall, left, right [, tryHarder]', n) then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
fall:= lua_toboolean(L, 2);
- left:= lua_tointeger(L, 3);
- right:= lua_tointeger(L, 4);
+ left:= Trunc(lua_tonumber(L, 3));
+ right:= Trunc(lua_tonumber(L, 4));
if n = 5 then
tryhard:= lua_toboolean(L, 5)
else
@@ -1870,7 +1990,7 @@
if gear <> nil then
FindPlace(gear, fall, left, right, tryhard);
if gear <> nil then
- lua_pushinteger(L, gear^.uid)
+ lua_pushnumber(L, gear^.uid)
else
lua_pushnil(L);
end
@@ -1896,7 +2016,7 @@
PlaySound(TSound(s))
else
begin
- gear:= GearByUID(lua_tointeger(L, 2));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 2)));
if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
AddVoice(TSound(s),gear^.Hedgehog^.Team^.Voicepack)
end;
@@ -1917,7 +2037,7 @@
if (np = 6) then ParseCommand('flag ' + lua_tostring(L, 6), true, true);
CurrentTeam^.Binds:= DefaultBinds
// fails on x64
- //lua_pushinteger(L, LongInt(CurrentTeam));
+ //lua_pushnumber(L, LongInt(CurrentTeam));
end;
//else
//lua_pushnil(L)
@@ -1967,6 +2087,53 @@
lc_dismissteam:= 0;
end;
+function lc_getteamstats(L : Plua_State) : LongInt; Cdecl;
+var i: LongInt;
+begin
+ if CheckLuaParamCount(L, 1, 'GetTeamStats', 'teamname') then
+ begin
+ if TeamsCount > 0 then
+ for i:= 0 to Pred(TeamsCount) do
+ begin
+ // skip teams that don't have matching name
+ if TeamsArray[i]^.TeamName <> lua_tostring(L, 1) then
+ continue;
+
+ lua_newtable(L);
+
+ lua_pushstring(L, str2pchar('Kills'));
+ lua_pushnumber(L, TeamsArray[i]^.stats.Kills);
+ lua_settable(L, -3);
+
+ lua_pushstring(L, str2pchar('Suicides'));
+ lua_pushnumber(L, TeamsArray[i]^.stats.Suicides);
+ lua_settable(L, -3);
+
+ lua_pushstring(L, str2pchar('AIKills'));
+ lua_pushnumber(L, TeamsArray[i]^.stats.AIKills);
+ lua_settable(L, -3);
+
+ lua_pushstring(L, str2pchar('TeamKills'));
+ lua_pushnumber(L, TeamsArray[i]^.stats.TeamKills);
+ lua_settable(L, -3);
+
+ lua_pushstring(L, str2pchar('TurnSkips'));
+ lua_pushnumber(L, TeamsArray[i]^.stats.TurnSkips);
+ lua_settable(L, -3);
+
+ lua_pushstring(L, str2pchar('TeamDamage'));
+ lua_pushnumber(L, TeamsArray[i]^.stats.TeamDamage);
+ lua_settable(L, -3);
+
+ end;
+ end
+ else
+ lua_pushnil(L);
+ lc_getteamstats:= 1;
+end;
+
+
+
function lc_addhog(L : Plua_State) : LongInt; Cdecl;
var temp: ShortString;
begin
@@ -1975,7 +2142,7 @@
temp:= lua_tostring(L, 4);
ParseCommand('addhh ' + lua_tostring(L, 2) + ' ' + lua_tostring(L, 3) + ' ' + lua_tostring(L, 1), true, true);
ParseCommand('hat ' + temp, true, true);
- lua_pushinteger(L, CurrentHedgehog^.Gear^.uid);
+ lua_pushnumber(L, CurrentHedgehog^.Gear^.uid);
end
else
lua_pushnil(L);
@@ -1987,7 +2154,7 @@
begin
if CheckLuaParamCount(L, 2, 'HogTurnLeft', 'gearUid, boolean') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
gear^.dX.isNegative:= lua_toboolean(L, 2);
end;
@@ -1999,11 +2166,11 @@
begin
if CheckLuaParamCount(L, 1, 'GetGearPosition', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
begin
- lua_pushinteger(L, hwRound(gear^.X));
- lua_pushinteger(L, hwRound(gear^.Y))
+ lua_pushnumber(L, hwRound(gear^.X));
+ lua_pushnumber(L, hwRound(gear^.Y))
end
else
begin
@@ -2026,12 +2193,12 @@
begin
if CheckLuaParamCount(L, 3, 'SetGearPosition', 'gearUid, x, y') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
begin
col:= gear^.CollisionIndex >= 0;
- x:= lua_tointeger(L, 2);
- y:= lua_tointeger(L, 3);
+ x:= Trunc(lua_tonumber(L, 2));
+ y:= Trunc(lua_tonumber(L, 3));
if col then
DeleteCI(gear);
gear^.X:= int2hwfloat(x);
@@ -2049,11 +2216,11 @@
begin
if CheckLuaParamCount(L, 1, 'GetGearTarget', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
begin
- lua_pushinteger(L, gear^.Target.X);
- lua_pushinteger(L, gear^.Target.Y)
+ lua_pushnumber(L, gear^.Target.X);
+ lua_pushnumber(L, gear^.Target.Y)
end
else
begin
@@ -2074,11 +2241,11 @@
begin
if CheckLuaParamCount(L, 3, 'SetGearTarget', 'gearUid, x, y') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
begin
- gear^.Target.X:= lua_tointeger(L, 2);
- gear^.Target.Y:= lua_tointeger(L, 3)
+ gear^.Target.X:= Trunc(lua_tonumber(L, 2));
+ gear^.Target.Y:= Trunc(lua_tonumber(L, 3))
end
end;
lc_setgeartarget:= 0
@@ -2090,14 +2257,14 @@
begin
if CheckLuaParamCount(L, 1, 'GetGearVelocity', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
begin
t:= hwRound(gear^.dX * 1000000);
// gear dX determines hog orientation
if (gear^.dX.isNegative) and (t = 0) then t:= -1;
- lua_pushinteger(L, t);
- lua_pushinteger(L, hwRound(gear^.dY * 1000000))
+ lua_pushnumber(L, t);
+ lua_pushnumber(L, hwRound(gear^.dY * 1000000))
end
end
else
@@ -2113,11 +2280,11 @@
begin
if CheckLuaParamCount(L, 3, 'SetGearVelocity', 'gearUid, dx, dy') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
begin
- gear^.dX:= int2hwFloat(lua_tointeger(L, 2)) / 1000000;
- gear^.dY:= int2hwFloat(lua_tointeger(L, 3)) / 1000000;
+ gear^.dX:= int2hwFloat(Trunc(lua_tonumber(L, 2))) / 1000000;
+ gear^.dY:= int2hwFloat(Trunc(lua_tonumber(L, 3))) / 1000000;
SetAllToActive;
end
end;
@@ -2158,9 +2325,9 @@
if at >= 0 then
begin
if np = 4 then
- ScriptSetAmmo(TAmmoType(at), lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4), 1)
+ ScriptSetAmmo(TAmmoType(at), Trunc(lua_tonumber(L, 2)), Trunc(lua_tonumber(L, 3)), Trunc(lua_tonumber(L, 4)), 1)
else
- ScriptSetAmmo(TAmmoType(at), lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5));
+ ScriptSetAmmo(TAmmoType(at), Trunc(lua_tonumber(L, 2)), Trunc(lua_tonumber(L, 3)), Trunc(lua_tonumber(L, 4)), Trunc(lua_tonumber(L, 5)));
end;
end;
lc_setammo:= 0
@@ -2176,31 +2343,19 @@
begin
at:= LuaToAmmoTypeOrd(L, 1, call, params);
if at >= 0 then
- ScriptSetAmmoDelay(TAmmoType(at), lua_tointeger(L, 2));
+ ScriptSetAmmoDelay(TAmmoType(at), Trunc(lua_tonumber(L, 2)));
end;
lc_setammodelay:= 0
end;
-function lc_setammostore(L : Plua_State) : LongInt; Cdecl;
-begin
- if CheckLuaParamCount(L, 4, 'SetAmmoStore', 'loadouts, probabilities, delays, reinforments') then
- begin
- ScriptAmmoLoadout:= lua_tostring(L, 1);
- ScriptAmmoProbability:= lua_tostring(L, 2);
- ScriptAmmoDelay:= lua_tostring(L, 3);
- ScriptAmmoReinforcement:= lua_tostring(L, 4);
- end;
- lc_setammostore:= 0
-end;
-
function lc_getrandom(L : Plua_State) : LongInt; Cdecl;
var m : LongInt;
begin
if CheckLuaParamCount(L, 1, 'GetRandom', 'number') then
begin
- m:= lua_tointeger(L, 1);
+ m:= Trunc(lua_tonumber(L, 1));
if (m > 0) then
- lua_pushinteger(L, GetRandom(m))
+ lua_pushnumber(L, GetRandom(m))
else
begin
LuaError('Lua: Tried to pass 0 to GetRandom!');
@@ -2216,7 +2371,7 @@
begin
if CheckLuaParamCount(L, 1, 'SetWind', 'windSpeed') then
begin
- cWindSpeed:= int2hwfloat(lua_tointeger(L, 1)) / 100 * cMaxWindSpeed;
+ cWindSpeed:= int2hwfloat(Trunc(lua_tonumber(L, 1))) / 100 * cMaxWindSpeed;
cWindSpeedf:= SignAs(cWindSpeed,cWindSpeed).QWordValue / SignAs(_1,_1).QWordValue;
if cWindSpeed.isNegative then
CWindSpeedf := -cWindSpeedf;
@@ -2239,9 +2394,9 @@
begin
if CheckLuaParamCount(L, 1, 'GetGearRadius', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- lua_pushinteger(L, gear^.Radius)
+ lua_pushnumber(L, gear^.Radius)
else
lua_pushnil(L);
end
@@ -2255,7 +2410,7 @@
begin
if CheckLuaParamCount(L, 1, 'GetHogHat', 'gearUid') then
begin
- gear := GearByUID(lua_tointeger(L, 1));
+ gear := GearByUID(Trunc(lua_tonumber(L, 1)));
if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then
lua_pushstring(L, str2pchar(gear^.Hedgehog^.Hat))
else
@@ -2272,7 +2427,7 @@
begin
if CheckLuaParamCount(L, 2, 'SetHogHat', 'gearUid, hat') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
begin
hat:= lua_tostring(L, 2);
@@ -2301,7 +2456,7 @@
if CheckAndFetchLuaParamMinCount(L, 4, call, params, n) then
begin
if not lua_isnoneornil(L, 5) then
- tint := lua_tointeger(L, 5)
+ tint := Trunc(lua_tonumber(L, 5))
else tint := $FFFFFFFF;
if not lua_isnoneornil(L, 6) then
behind := lua_toboolean(L, 6)
@@ -2316,7 +2471,7 @@
// accept any amount of landflags, loop is never executed if n<9
for i:= 9 to n do
- lf:= lf or lua_tointeger(L, i);
+ lf:= lf or Trunc(lua_tonumber(L, i));
n:= LuaToSpriteOrd(L, 3, call, params);
if n >= 0 then
@@ -2326,9 +2481,9 @@
LuaError(call + ': ' + EnumToStr(spr) + ' cannot be placed! (required information not loaded)' )
else
placed:= ForcePlaceOnLand(
- lua_tointeger(L, 1) - SpritesData[spr].Width div 2,
- lua_tointeger(L, 2) - SpritesData[spr].Height div 2,
- spr, lua_tointeger(L, 4), lf, tint, behind, flipHoriz, flipVert);
+ Trunc(lua_tonumber(L, 1)) - SpritesData[spr].Width div 2,
+ Trunc(lua_tonumber(L, 2)) - SpritesData[spr].Height div 2,
+ spr, Trunc(lua_tonumber(L, 4)), lf, tint, behind, flipHoriz, flipVert);
end;
end;
@@ -2363,7 +2518,7 @@
// accept any amount of landflags, loop is never executed if n<9
for i:= 9 to n do
- lf:= lf or lua_tointeger(L, i);
+ lf:= lf or Trunc(lua_tonumber(L, i));
n:= LuaToSpriteOrd(L, 3, call, params);
if n >= 0 then
@@ -2373,9 +2528,9 @@
LuaError(call + ': ' + EnumToStr(spr) + ' cannot be placed! (required information not loaded)' )
else
EraseLand(
- lua_tointeger(L, 1) - SpritesData[spr].Width div 2,
- lua_tointeger(L, 2) - SpritesData[spr].Height div 2,
- spr, lua_tointeger(L, 4), lf, eraseOnLFMatch, onlyEraseLF, flipHoriz, flipVert);
+ Trunc(lua_tonumber(L, 1)) - SpritesData[spr].Width div 2,
+ Trunc(lua_tonumber(L, 2)) - SpritesData[spr].Height div 2,
+ spr, Trunc(lua_tonumber(L, 4)), lf, eraseOnLFMatch, onlyEraseLF, flipHoriz, flipVert);
end;
end;
lc_erasesprite:= 0
@@ -2387,20 +2542,34 @@
placed:= false;
if CheckLuaParamCount(L, 3, 'PlaceGirder', 'x, y, frameIdx') then
placed:= TryPlaceOnLandSimple(
- lua_tointeger(L, 1) - SpritesData[sprAmGirder].Width div 2,
- lua_tointeger(L, 2) - SpritesData[sprAmGirder].Height div 2,
- sprAmGirder, lua_tointeger(L, 3), true, false);
+ Trunc(lua_tonumber(L, 1)) - SpritesData[sprAmGirder].Width div 2,
+ Trunc(lua_tonumber(L, 2)) - SpritesData[sprAmGirder].Height div 2,
+ sprAmGirder, Trunc(lua_tonumber(L, 3)), true, false);
lua_pushboolean(L, placed);
lc_placegirder:= 1
end;
+function lc_placerubber(L : Plua_State) : LongInt; Cdecl;
+var placed: boolean;
+begin
+ placed:= false;
+ if CheckLuaParamCount(L, 3, 'PlaceRubber', 'x, y, frameIdx') then
+ placed:= TryPlaceOnLand(
+ Trunc(lua_tonumber(L, 1)) - SpritesData[sprAmRubber].Width div 2,
+ Trunc(lua_tonumber(L, 2)) - SpritesData[sprAmRubber].Height div 2,
+ sprAmRubber, Trunc(lua_tonumber(L, 3)), true, lfBouncy);
+
+ lua_pushboolean(L, placed);
+ lc_placerubber:= 1
+end;
+
function lc_getcurammotype(L : Plua_State): LongInt; Cdecl;
begin
if (CurrentHedgehog <> nil) and (CheckLuaParamCount(L, 0, 'GetCurAmmoType', '')) then
- lua_pushinteger(L, ord(CurrentHedgehog^.CurAmmoType))
+ lua_pushnumber(L, ord(CurrentHedgehog^.CurAmmoType))
else
- lua_pushinteger(L, ord(amNothing));
+ lua_pushnumber(L, ord(amNothing));
lc_getcurammotype := 1;
end;
@@ -2424,10 +2593,16 @@
begin
if CheckLuaParamCount(L, 1, 'HideHog', 'gearUid') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
- HideHog(gear^.hedgehog)
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
+ if (gear <> nil) and (gear^.hedgehog <> nil) then
+ begin
+ HideHog(gear^.hedgehog);
+ lua_pushboolean(L, true);
+ end
+ else
+ lua_pushboolean(L, false);
end;
- lc_hidehog := 0;
+ lc_hidehog := 1;
end;
function lc_restorehog(L: Plua_State): LongInt; Cdecl;
@@ -2436,7 +2611,7 @@
begin
if CheckLuaParamCount(L, 1, 'RestoreHog', 'gearUid') then
begin
- uid:= LongWord(lua_tointeger(L, 1));
+ uid:= LongWord(Trunc(lua_tonumber(L, 1)));
if TeamsCount > 0 then
for i:= 0 to Pred(TeamsCount) do
for h:= 0 to cMaxHHIndex do
@@ -2456,10 +2631,10 @@
if CheckLuaParamCount(L, 5, 'TestRectForObstacle', 'x1, y1, x2, y2, landOnly') then
begin
rtn:= TestRectangleForObstacle(
- lua_tointeger(L, 1),
- lua_tointeger(L, 2),
- lua_tointeger(L, 3),
- lua_tointeger(L, 4),
+ Trunc(lua_tonumber(L, 1)),
+ Trunc(lua_tonumber(L, 2)),
+ Trunc(lua_tonumber(L, 3)),
+ Trunc(lua_tonumber(L, 4)),
lua_toboolean(L, 5)
);
lua_pushboolean(L, rtn);
@@ -2473,7 +2648,7 @@
function lc_getgravity(L : Plua_State) : LongInt; Cdecl;
begin
if CheckLuaParamCount(L, 0, 'GetGravity', '') then
- lua_pushinteger(L, hwRound(SignAs(_0_5, cGravity) + (cGravity * 50 / cMaxWindSpeed)));
+ lua_pushnumber(L, hwRound(SignAs(_0_5, cGravity) + (cGravity * 50 / cMaxWindSpeed)));
lc_getgravity:= 1
end;
@@ -2481,8 +2656,8 @@
begin
if CheckLuaParamCount(L, 1, 'SetGravity', 'percent') then
begin
- cGravity:= _0_02 * lua_tointeger(L, 1) * cMaxWindSpeed;
- cGravityf:= 0.00025 * lua_tointeger(L, 1) * 0.02
+ cGravity:= _0_02 * Trunc(lua_tonumber(L, 1)) * cMaxWindSpeed;
+ cGravityf:= 0.00025 * Trunc(lua_tonumber(L, 1)) * 0.02
end;
lc_setgravity:= 0
end;
@@ -2492,7 +2667,7 @@
begin
if CheckLuaParamCount(L, 1, 'SetWaterLine', 'waterline') then
begin
- cWaterLine:= lua_tointeger(L,1);
+ cWaterLine:= Trunc(lua_tonumber(L,1));
AllInactive:= false;
iterator:= GearsList;
while iterator <> nil do
@@ -2515,9 +2690,9 @@
begin
if CheckLuaParamCount(L, 2, 'SetAIHintOnGear', 'gearUid, aiHints') then
begin
- gear:= GearByUID(lua_tointeger(L, 1));
+ gear:= GearByUID(Trunc(lua_tonumber(L, 1)));
if gear <> nil then
- gear^.aihints:= lua_tointeger(L, 2);
+ gear^.aihints:= Trunc(lua_tonumber(L, 2));
end;
lc_setgearaihints:= 0
end;
@@ -2536,21 +2711,44 @@
function lc_declareachievement(L : Plua_State) : LongInt; Cdecl;
begin
if CheckLuaParamCount(L, 4, 'DeclareAchievement', 'achievementId, teamname, location, value') then
- declareAchievement(lua_tostring(L, 1), lua_tostring(L, 2), lua_tostring(L, 3), lua_tointeger(L, 4));
+ declareAchievement(lua_tostring(L, 1), lua_tostring(L, 2), lua_tostring(L, 3), Trunc(lua_tonumber(L, 4)));
lc_declareachievement:= 0
end;
+function lc_getammoname(L : Plua_state) : LongInt; Cdecl;
+var np, at: LongInt;
+ ignoreOverwrite: Boolean;
+const call = 'GetAmmoName';
+ params = 'ammoType [, ignoreOverwrite ]';
+begin
+ if CheckAndFetchParamCountRange(L, 1, 2, call, params, np) then
+ begin
+ at:= LuaToAmmoTypeOrd(L, 1, call, params);
+ ignoreOverwrite := false;
+ if np > 1 then
+ ignoreOverwrite := lua_toboolean(L, 2);
+ if at >= 0 then
+ if (not ignoreOverwrite) and (length(trluaammo[Ammoz[TAmmoType(at)].NameId]) > 0) then
+ lua_pushstring(L, PChar(trluaammo[Ammoz[TAmmoType(at)].NameId]))
+ else
+ lua_pushstring(L, PChar(trammo[Ammoz[TAmmoType(at)].NameId]));
+ end
+ else
+ lua_pushnil(L);
+ lc_getammoname:= 1;
+end;
+
function lc_startghostpoints(L : Plua_State) : LongInt; Cdecl;
begin
if CheckLuaParamCount(L, 1, 'StartGhostPoints', 'count') then
- startGhostPoints(lua_tointeger(L, 1));
+ startGhostPoints(Trunc(lua_tonumber(L, 1)));
lc_startghostpoints:= 0
end;
function lc_dumppoint(L : Plua_State) : LongInt; Cdecl;
begin
if CheckLuaParamCount(L, 2, 'DumpPoint', 'x, y') then
- dumpPoint(lua_tointeger(L, 1), lua_tointeger(L, 2));
+ dumpPoint(Trunc(lua_tonumber(L, 1)), Trunc(lua_tonumber(L, 2)));
lc_dumppoint:= 0
end;
@@ -2568,17 +2766,17 @@
if CheckAndFetchParamCountRange(L, 2, 4, 'AddPoint', 'x, y [, width [, erase] ]', np) then
begin
// x
- param:= LongInt(lua_tointeger(L,1));
+ param:= LongInt(Trunc(lua_tonumber(L,1)));
PointsBuffer:= PointsBuffer + char((param shr 8) and $FF);
PointsBuffer:= PointsBuffer + char((param and $FF));
// y
- param:= LongInt(lua_tointeger(L,2));
+ param:= LongInt(Trunc(lua_tonumber(L,2)));
PointsBuffer:= PointsBuffer + char((param shr 8) and $FF);
PointsBuffer:= PointsBuffer + char((param and $FF));
// width
if np > 2 then
begin
- param:= lua_tointeger(L,3);
+ param:= Trunc(lua_tonumber(L,3));
param:= (param or $80);
// erase
if (np > 3) and lua_toboolean(L, 4) then
@@ -2615,7 +2813,7 @@
if CheckLuaParamCount(L, 1, call, params) then
begin
- case lua_tointeger(L, 1) of
+ case Trunc(lua_tonumber(L, 1)) of
HaltTestSuccess : rstring:= 'Success';
HaltTestFailed: rstring:= 'FAILED';
else
@@ -2628,7 +2826,7 @@
if cTestLua then
begin
WriteLnToConsole('Lua test finished, result: ' + rstring);
- halt(lua_tointeger(L, 1));
+ halt(Trunc(lua_tonumber(L, 1)));
end
else LuaError('Not in lua test mode, engine will keep running. Reported test result: ' + rstring);
@@ -2665,7 +2863,7 @@
procedure ScriptSetInteger(name : shortstring; value : LongInt);
begin
- lua_pushinteger(luaState, value);
+ lua_pushnumber(luaState, value);
lua_setglobal(luaState, Str2PChar(name));
end;
@@ -2678,7 +2876,7 @@
function ScriptGetInteger(name : shortstring) : LongInt;
begin
lua_getglobal(luaState, Str2PChar(name));
- ScriptGetInteger:= lua_tointeger(luaState, -1);
+ ScriptGetInteger:= Trunc(lua_tonumber(luaState, -1));
lua_pop(luaState, 1);
end;
@@ -2689,6 +2887,13 @@
lua_pop(luaState, 1);
end;
+function ScriptGetAnsiString(name : shortstring) : ansistring;
+begin
+ lua_getglobal(luaState, Str2PChar(name));
+ ScriptGetAnsiString:= lua_tostringa(luaState, -1);
+ lua_pop(luaState, 1);
+end;
+
procedure ScriptOnPreviewInit;
begin
// not required if there is no script to run
@@ -2721,8 +2926,8 @@
// push game variables so they may be modified by the script
ScriptSetInteger('CursorX', CursorPoint.X);
ScriptSetInteger('CursorY', CursorPoint.Y);
-ScriptSetInteger('BorderColor', ExplosionBorderColor);
ScriptSetInteger('GameFlags', GameFlags);
+ScriptSetInteger('WorldEdge', ord(WorldEdge));
ScriptSetString('Seed', cSeed);
ScriptSetInteger('TemplateFilter', cTemplateFilter);
ScriptSetInteger('TemplateNumber', LuaTemplateNumber);
@@ -2739,6 +2944,7 @@
ScriptSetInteger('MinesNum', cLandMines);
ScriptSetInteger('MinesTime', cMinesTime);
ScriptSetInteger('MineDudPercent', cMineDudPercent);
+ScriptSetInteger('AirMinesNum', cAirMines);
ScriptSetInteger('Explosives', cExplosives);
ScriptSetInteger('Delay', cInactDelay);
ScriptSetInteger('Ready', cReadyDelay);
@@ -2746,6 +2952,7 @@
ScriptSetInteger('WaterRise', cWaterRise);
ScriptSetInteger('HealthDecrease', cHealthDecrease);
ScriptSetInteger('GetAwayTime', cGetAwayTime);
+ScriptSetInteger('AmmoTypeMax', Ord(High(TAmmoType)));
ScriptSetString('Map', cMapName);
ScriptSetString('Theme', Theme);
ScriptSetString('Goals', '');
@@ -2759,6 +2966,7 @@
cMapGen := TMapGen(ScriptGetInteger('MapGen'));
cFeatureSize := ScriptGetInteger('MapFeatureSize');
GameFlags := ScriptGetInteger('GameFlags');
+WorldEdge := TWorldEdge(ScriptGetInteger('WorldEdge'));
cHedgehogTurnTime:= ScriptGetInteger('TurnTime');
cCaseFactor := ScriptGetInteger('CaseFreq');
cHealthCaseProb := ScriptGetInteger('HealthCaseProb');
@@ -2768,6 +2976,7 @@
cLandMines := ScriptGetInteger('MinesNum');
cMinesTime := ScriptGetInteger('MinesTime');
cMineDudPercent := ScriptGetInteger('MineDudPercent');
+cAirMines := ScriptGetInteger('AirMinesNum');
cExplosives := ScriptGetInteger('Explosives');
cInactDelay := ScriptGetInteger('Delay');
cReadyDelay := ScriptGetInteger('Ready');
@@ -2780,7 +2989,7 @@
ParseCommand('map ' + ScriptGetString('Map'), true, true);
if ScriptGetString('Theme') <> '' then
ParseCommand('theme ' + ScriptGetString('Theme'), true, true);
-LuaGoals:= ScriptGetString('Goals');
+LuaGoals:= ScriptGetAnsiString('Goals');
// Support lua changing the ammo layout - assume all hogs have same ammo, note this might leave a few ammo stores lying around.
k:= 0;
@@ -2839,12 +3048,89 @@
// custom script loader via physfs, passed to lua_load
const BUFSIZE = 1024;
+var inComment: boolean;
+var inQuote: boolean;
+var locSum: LongWord;
+var braceCount: LongWord;
+var wordCount: LongWord;
+var lastChar: char;
+// ⭒⭐⭒✨⭐⭒✨⭐☆✨⭐✨✧✨☆✨✧✨☆⭒✨☆⭐⭒☆✧✨⭒✨⭐✧⭒☆⭒✧☆✨✧⭐☆✨☆✧⭒✨✧⭒☆⭐☆✧
+function ScriptReader(L: Plua_State; f: PFSFile; sz: Psize_t) : PChar; Cdecl;
+var mybuf: PChar;
+ i: LongInt;
+begin
+ SetRandomSeed(cSeed,true);
+ mybuf := physfsReader(L, f, sz);
+ if (mybuf <> nil) and ((sz^) > 0) then
+ begin
+ for i:= 0 to sz^-1 do
+ begin
+ if (lastChar = '-') and (mybuf[i] = '-') then
+ inComment := true
+ // gonna add any non-magic whitespace and skip - just to make comment avoidance easier
+ else if not inComment and (byte(mybuf[i]) > $20) and (byte(mybuf[i]) < $7F) and (mybuf[i]<>'-') then
+ begin
+ AddRandomness(byte(mybuf[i])); // wish I had the seed...
+ CheckSum := CheckSum xor GetRandom($FFFFFFFF);
+ end;
+ lastChar := mybuf[i];
+ if (byte(mybuf[i]) = $0D) or (byte(mybuf[i]) = $0A) then
+ inComment := false
+ end;
+ end;
+ ScriptReader:= mybuf
+end;
+function ScriptLocaleReader(L: Plua_State; f: PFSFile; sz: Psize_t) : PChar; Cdecl;
+var mybuf: PChar;
+ i: LongInt;
+begin
+ mybuf := physfsReader(L, f, sz);
+ if (mybuf <> nil) and ((sz^) > 0) then
+ begin
+ for i:= 0 to sz^-1 do
+ begin
+ if not inComment and (mybuf[i] = '"') and (lastChar <> '\') then
+ inQuote := not inQuote;
+ if not inQuote and (lastChar = '-') and (mybuf[i] = '-') then
+ inComment := true;
+ if not inComment and (not inQuote) then
+ locSum := locSum xor (byte(mybuf[i]) shl (i mod 4));
+ if not inComment and (not inQuote) and
+ ((mybuf[i] = '(') or
+ (mybuf[i] = ')') or
+ (mybuf[i] = '+') or
+ (mybuf[i] = '#') or
+ (braceCount > 2) or
+ (wordCount > 6)) then
+ CheckSum := locSum;
+ if not inComment and (not inQuote) and ((mybuf[i] = '{') or (mybuf[i] = '}')) then
+ inc(braceCount);
+ if not inComment and (not inQuote) and
+ (((byte(mybuf[i]) > $40) and (byte(mybuf[i]) < $5B)) or
+ ((byte(mybuf[i]) > $60) and (byte(mybuf[i]) < $7B)) or
+ ((byte(mybuf[i]) >= $30) and (byte(mybuf[i]) < $3A))) then
+ inc(wordCount);
+ lastChar := mybuf[i];
+ if (byte(mybuf[i]) = $0D) or (byte(mybuf[i]) = $0A) then
+ inComment := false
+ end;
+ end;
+ ScriptLocaleReader:= mybuf
+end;
+// ⭒⭐⭒✨⭐⭒✨⭐☆✨⭐✨✧✨☆✨✧✨☆⭒✨☆⭐⭒☆✧✨⭒✨⭐✧⭒☆⭒✧☆✨✧⭐☆✨☆✧⭒✨✧⭒☆⭐☆✧
+
procedure ScriptLoad(name : shortstring);
var ret : LongInt;
s : shortstring;
f : PFSFile;
buf : array[0..Pred(BUFSIZE)] of byte;
begin
+inComment:= false;
+inQuote:= false;
+lastChar:= 'X';
+braceCount:= 0;
+wordCount:= 0;
+locSum:= 0;
s:= cPathz[ptData] + name;
if not pfsExists(s) then
begin
@@ -2856,8 +3142,12 @@
if f = nil then
exit;
+hedgewarsMountPackage(Str2PChar(copy(s, 1, length(s)-4)+'.hwp'));
+
physfsReaderSetBuffer(@buf);
-ret:= lua_load(luaState, @physfsReader, f, Str2PChar(s));
+if Pos('Locale/',s) <> 0 then
+ ret:= lua_load(luaState, @ScriptLocaleReader, f, Str2PChar(s))
+else ret:= lua_load(luaState, @ScriptReader, f, Str2PChar(s));
pfsClose(f);
if ret <> 0 then
@@ -2872,12 +3162,12 @@
lua_pcall(luaState, 0, 0, 0);
ScriptLoaded:= true
end;
-hedgewarsMountPackage(Str2PChar(copy(s, 1, length(s)-4)+'.hwp'));
end;
procedure SetGlobals;
begin
ScriptSetInteger('TurnTimeLeft', TurnTimeLeft);
+ScriptSetInteger('ReadyTimeLeft', ReadyTimeLeft);
ScriptSetInteger('GameTime', GameTicks);
ScriptSetInteger('TotalRounds', TotalRounds);
ScriptSetInteger('WaterLine', cWaterLine);
@@ -2924,6 +3214,7 @@
// It is inconsistent anyway to have some globals be read-only and others not with no indication whatsoever.
// -- sheepluva
TurnTimeLeft:= ScriptGetInteger('TurnTimeLeft');
+ReadyTimeLeft:= ScriptGetInteger('ReadyTimeLeft');
end;
procedure ScriptCall(fname : shortstring);
@@ -2983,10 +3274,10 @@
exit(0);
SetGlobals;
lua_getglobal(luaState, Str2PChar(fname));
-lua_pushinteger(luaState, par1);
-lua_pushinteger(luaState, par2);
-lua_pushinteger(luaState, par3);
-lua_pushinteger(luaState, par4);
+lua_pushnumber(luaState, par1);
+lua_pushnumber(luaState, par2);
+lua_pushnumber(luaState, par3);
+lua_pushnumber(luaState, par4);
ScriptCall:= 0;
if lua_pcall(luaState, 4, 1, 0) <> 0 then
begin
@@ -2995,7 +3286,7 @@
end
else
begin
- ScriptCall:= lua_tointeger(luaState, -1);
+ ScriptCall:= Trunc(lua_tonumber(luaState, -1));
lua_pop(luaState, 1)
end;
GetGlobals;
@@ -3010,7 +3301,7 @@
end;
lua_getglobal(luaState, Str2PChar(fname));
ScriptExists:= not lua_isnoneornil(luaState, -1);
-lua_pop(luaState, -1)
+lua_pop(luaState, 1)
end;
procedure ScriptPrepareAmmoStore;
@@ -3117,6 +3408,7 @@
cg : TCapGroup;
spr: TSprite;
mg : TMapGen;
+ we : TWorldEdge;
begin
// initialize lua
luaState:= lua_open;
@@ -3212,6 +3504,9 @@
for mg:= Low(TMapGen) to High(TMapGen) do
ScriptSetInteger(EnumToStr(mg), ord(mg));
+for we:= Low(TWorldEdge) to High(TWorldEdge) do
+ ScriptSetInteger(EnumToStr(we), ord(we));
+
ScriptSetInteger('gstDrowning' , gstDrowning);
ScriptSetInteger('gstHHDriven' , gstHHDriven);
ScriptSetInteger('gstMoving' , gstMoving);
@@ -3265,6 +3560,7 @@
lua_register(luaState, _P'DeleteGear', @lc_deletegear);
lua_register(luaState, _P'AddVisualGear', @lc_addvisualgear);
lua_register(luaState, _P'DeleteVisualGear', @lc_deletevisualgear);
+lua_register(luaState, _P'GetVisualGearType', @lc_getvisualgeartype);
lua_register(luaState, _P'GetVisualGearValues', @lc_getvisualgearvalues);
lua_register(luaState, _P'SetVisualGearValues', @lc_setvisualgearvalues);
lua_register(luaState, _P'GetGearValues', @lc_getgearvalues);
@@ -3278,7 +3574,12 @@
lua_register(luaState, _P'WriteLnToConsole', @lc_writelntoconsole);
lua_register(luaState, _P'GetGearType', @lc_getgeartype);
lua_register(luaState, _P'EndGame', @lc_endgame);
+lua_register(luaState, _P'EndTurn', @lc_endturn);
+lua_register(luaState, _P'GetTeamStats', @lc_getteamstats);
lua_register(luaState, _P'SendStat', @lc_sendstat);
+lua_register(luaState, _P'SendGameResultOff', @lc_sendgameresultoff);
+lua_register(luaState, _P'SendRankingStatsOff', @lc_sendrankingstatsoff);
+lua_register(luaState, _P'SendAchievementsStatsOff', @lc_sendachievementsstatsoff);
lua_register(luaState, _P'SendHealthStatsOff', @lc_sendhealthstatsoff);
lua_register(luaState, _P'FindPlace', @lc_findplace);
lua_register(luaState, _P'SetGearPosition', @lc_setgearposition);
@@ -3290,10 +3591,11 @@
lua_register(luaState, _P'ParseCommand', @lc_parsecommand);
lua_register(luaState, _P'ShowMission', @lc_showmission);
lua_register(luaState, _P'HideMission', @lc_hidemission);
+lua_register(luaState, _P'SetAmmoTexts', @lc_setammotexts);
+lua_register(luaState, _P'SetAmmoDescriptionAppendix', @lc_setammodescriptionappendix);
lua_register(luaState, _P'AddCaption', @lc_addcaption);
lua_register(luaState, _P'SetAmmo', @lc_setammo);
lua_register(luaState, _P'SetAmmoDelay', @lc_setammodelay);
-lua_register(luaState, _P'SetAmmoStore', @lc_setammostore);
lua_register(luaState, _P'PlaySound', @lc_playsound);
lua_register(luaState, _P'AddTeam', @lc_addteam);
lua_register(luaState, _P'AddHog', @lc_addhog);
@@ -3308,7 +3610,9 @@
lua_register(luaState, _P'SetClanColor', @lc_setclancolor);
lua_register(luaState, _P'GetHogVoicepack', @lc_gethogvoicepack);
lua_register(luaState, _P'GetHogFlag', @lc_gethogflag);
+lua_register(luaState, _P'GetHogFort', @lc_gethogfort);
lua_register(luaState, _P'GetHogGrave', @lc_gethoggrave);
+lua_register(luaState, _P'IsHogLocal', @lc_ishoglocal);
lua_register(luaState, _P'GetHogTeamName', @lc_gethogteamname);
lua_register(luaState, _P'SetHogTeamName', @lc_sethogteamname);
lua_register(luaState, _P'GetHogName', @lc_gethogname);
@@ -3354,6 +3658,7 @@
lua_register(luaState, _P'EraseSprite', @lc_erasesprite);
lua_register(luaState, _P'PlaceSprite', @lc_placesprite);
lua_register(luaState, _P'PlaceGirder', @lc_placegirder);
+lua_register(luaState, _P'PlaceRubber', @lc_placerubber);
lua_register(luaState, _P'GetCurAmmoType', @lc_getcurammotype);
lua_register(luaState, _P'TestRectForObstacle', @lc_testrectforobstacle);
lua_register(luaState, _P'GetGravity', @lc_getgravity);
@@ -3363,6 +3668,7 @@
lua_register(luaState, _P'SetWeapon', @lc_setweapon);
lua_register(luaState, _P'SetCinematicMode', @lc_setcinematicmode);
lua_register(luaState, _P'SetMaxBuildDistance', @lc_setmaxbuilddistance);
+lua_register(luaState, _P'GetAmmoName', @lc_getammoname);
// drawn map functions
lua_register(luaState, _P'AddPoint', @lc_addPoint);
lua_register(luaState, _P'FlushPoints', @lc_flushPoints);
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uSound.pas
--- a/hedgewars/uSound.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uSound.pas Sun Dec 17 00:09:24 2017 +0100
@@ -110,7 +110,7 @@
var Volume: LongInt;
SoundTimerTicks: Longword;
implementation
-uses uVariables, uConsole, uCommands, uChat, uUtils, uDebug, uPhysFSLayer;
+uses uVariables, uConsole, uCommands, uDebug, uPhysFSLayer;
const chanTPU = 32;
var cInitVolume: LongInt;
@@ -133,133 +133,155 @@
( snd: sndNone; voicepack: nil));
Soundz: array[TSound] of record
FileName: string[31];
- Path : TPathType;
+ Path, AltPath : TPathType;
end = (
- (FileName: ''; Path: ptNone ),// sndNone
- (FileName: 'grenadeimpact.ogg'; Path: ptSounds),// sndGrenadeImpact
- (FileName: 'explosion.ogg'; Path: ptSounds),// sndExplosion
- (FileName: 'throwpowerup.ogg'; Path: ptSounds),// sndThrowPowerUp
- (FileName: 'throwrelease.ogg'; Path: ptSounds),// sndThrowRelease
- (FileName: 'splash.ogg'; Path: ptSounds),// sndSplash
- (FileName: 'shotgunreload.ogg'; Path: ptSounds),// sndShotgunReload
- (FileName: 'shotgunfire.ogg'; Path: ptSounds),// sndShotgunFire
- (FileName: 'graveimpact.ogg'; Path: ptSounds),// sndGraveImpact
- (FileName: 'mineimpact.ogg'; Path: ptSounds),// sndMineImpact
- (FileName: 'minetick.ogg'; Path: ptSounds),// sndMineTicks
- (FileName: 'Droplet1.ogg'; Path: ptSounds),// sndMudballImpact
- (FileName: 'pickhammer.ogg'; Path: ptSounds),// sndPickhammer
- (FileName: 'gun.ogg'; Path: ptSounds),// sndGun
- (FileName: 'bee.ogg'; Path: ptSounds),// sndBee
- (FileName: 'Jump1.ogg'; Path: ptVoices),// sndJump1
- (FileName: 'Jump2.ogg'; Path: ptVoices),// sndJump2
- (FileName: 'Jump3.ogg'; Path: ptVoices),// sndJump3
- (FileName: 'Yessir.ogg'; Path: ptVoices),// sndYesSir
- (FileName: 'Laugh.ogg'; Path: ptVoices),// sndLaugh
- (FileName: 'Illgetyou.ogg'; Path: ptVoices),// sndIllGetYou
- (FileName: 'Justyouwait.ogg'; Path: ptVoices),// sndJustyouwait
- (FileName: 'Incoming.ogg'; Path: ptVoices),// sndIncoming
- (FileName: 'Missed.ogg'; Path: ptVoices),// sndMissed
- (FileName: 'Stupid.ogg'; Path: ptVoices),// sndStupid
- (FileName: 'Firstblood.ogg'; Path: ptVoices),// sndFirstBlood
- (FileName: 'Boring.ogg'; Path: ptVoices),// sndBoring
- (FileName: 'Byebye.ogg'; Path: ptVoices),// sndByeBye
- (FileName: 'Sameteam.ogg'; Path: ptVoices),// sndSameTeam
- (FileName: 'Nutter.ogg'; Path: ptVoices),// sndNutter
- (FileName: 'Reinforcements.ogg'; Path: ptVoices),// sndReinforce
- (FileName: 'Traitor.ogg'; Path: ptVoices),// sndTraitor
- (FileName: 'Youllregretthat.ogg'; Path: ptVoices),// sndRegret
- (FileName: 'Enemydown.ogg'; Path: ptVoices),// sndEnemyDown
- (FileName: 'Coward.ogg'; Path: ptVoices),// sndCoward
- (FileName: 'Hurry.ogg'; Path: ptVoices),// sndHurry
- (FileName: 'Watchit.ogg'; Path: ptVoices),// sndWatchIt
- (FileName: 'Kamikaze.ogg'; Path: ptVoices),// sndKamikaze
- (FileName: 'cake2.ogg'; Path: ptSounds),// sndCake
- (FileName: 'Ow1.ogg'; Path: ptVoices),// sndOw1
- (FileName: 'Ow2.ogg'; Path: ptVoices),// sndOw2
- (FileName: 'Ow3.ogg'; Path: ptVoices),// sndOw3
- (FileName: 'Ow4.ogg'; Path: ptVoices),// sndOw4
- (FileName: 'Firepunch1.ogg'; Path: ptVoices),// sndFirepunch1
- (FileName: 'Firepunch2.ogg'; Path: ptVoices),// sndFirepunch2
- (FileName: 'Firepunch3.ogg'; Path: ptVoices),// sndFirepunch3
- (FileName: 'Firepunch4.ogg'; Path: ptVoices),// sndFirepunch4
- (FileName: 'Firepunch5.ogg'; Path: ptVoices),// sndFirepunch5
- (FileName: 'Firepunch6.ogg'; Path: ptVoices),// sndFirepunch6
- (FileName: 'Melon.ogg'; Path: ptVoices),// sndMelon
- (FileName: 'Hellish.ogg'; Path: ptSounds),// sndHellish
- (FileName: 'Yoohoo.ogg'; Path: ptSounds),// sndYoohoo
- (FileName: 'rcplane.ogg'; Path: ptSounds),// sndRCPlane
- (FileName: 'whipcrack.ogg'; Path: ptSounds),// sndWhipCrack
- (FileName:'ride_of_the_valkyries.ogg'; Path: ptSounds),// sndRideOfTheValkyries
- (FileName: 'denied.ogg'; Path: ptSounds),// sndDenied
- (FileName: 'placed.ogg'; Path: ptSounds),// sndPlaced
- (FileName: 'baseballbat.ogg'; Path: ptSounds),// sndBaseballBat
- (FileName: 'steam.ogg'; Path: ptSounds),// sndVaporize
- (FileName: 'warp.ogg'; Path: ptSounds),// sndWarp
- (FileName: 'suddendeath.ogg'; Path: ptSounds),// sndSuddenDeath
- (FileName: 'mortar.ogg'; Path: ptSounds),// sndMortar
- (FileName: 'shutterclick.ogg'; Path: ptSounds),// sndShutter
- (FileName: 'homerun.ogg'; Path: ptSounds),// sndHomerun
- (FileName: 'molotov.ogg'; Path: ptSounds),// sndMolotov
- (FileName: 'Takecover.ogg'; Path: ptVoices),// sndCover
- (FileName: 'Uh-oh.ogg'; Path: ptVoices),// sndUhOh
- (FileName: 'Oops.ogg'; Path: ptVoices),// sndOops
- (FileName: 'Nooo.ogg'; Path: ptVoices),// sndNooo
- (FileName: 'Hello.ogg'; Path: ptVoices),// sndHello
- (FileName: 'ropeshot.ogg'; Path: ptSounds),// sndRopeShot
- (FileName: 'ropeattach.ogg'; Path: ptSounds),// sndRopeAttach
- (FileName: 'roperelease.ogg'; Path: ptSounds),// sndRopeRelease
- (FileName: 'switchhog.ogg'; Path: ptSounds),// sndSwitchHog
- (FileName: 'Victory.ogg'; Path: ptVoices),// sndVictory
- (FileName: 'Flawless.ogg'; Path: ptVoices),// sndFlawless
- (FileName: 'sniperreload.ogg'; Path: ptSounds),// sndSniperReload
- (FileName: 'steps.ogg'; Path: ptSounds),// sndSteps
- (FileName: 'lowgravity.ogg'; Path: ptSounds),// sndLowGravity
- (FileName: 'hell_growl.ogg'; Path: ptSounds),// sndHellishImpact1
- (FileName: 'hell_ooff.ogg'; Path: ptSounds),// sndHellishImpact2
- (FileName: 'hell_ow.ogg'; Path: ptSounds),// sndHellishImpact3
- (FileName: 'hell_ugh.ogg'; Path: ptSounds),// sndHellishImpact4
- (FileName: 'melonimpact.ogg'; Path: ptSounds),// sndMelonImpact
- (FileName: 'Droplet1.ogg'; Path: ptSounds),// sndDroplet1
- (FileName: 'Droplet2.ogg'; Path: ptSounds),// sndDroplet2
- (FileName: 'Droplet3.ogg'; Path: ptSounds),// sndDroplet3
- (FileName: 'egg.ogg'; Path: ptSounds),// sndEggBreak
- (FileName: 'drillgun.ogg'; Path: ptSounds),// sndDrillRocket
- (FileName: 'PoisonCough.ogg'; Path: ptVoices),// sndPoisonCough
- (FileName: 'PoisonMoan.ogg'; Path: ptVoices),// sndPoisonMoan
- (FileName: 'BirdyLay.ogg'; Path: ptSounds),// sndBirdyLay
- (FileName: 'Whistle.ogg'; Path: ptSounds),// sndWhistle
- (FileName: 'beewater.ogg'; Path: ptSounds),// sndBeeWater
- (FileName: '1C.ogg'; Path: ptSounds),// sndPiano0
- (FileName: '2D.ogg'; Path: ptSounds),// sndPiano1
- (FileName: '3E.ogg'; Path: ptSounds),// sndPiano2
- (FileName: '4F.ogg'; Path: ptSounds),// sndPiano3
- (FileName: '5G.ogg'; Path: ptSounds),// sndPiano4
- (FileName: '6A.ogg'; Path: ptSounds),// sndPiano5
- (FileName: '7B.ogg'; Path: ptSounds),// sndPiano6
- (FileName: '8C.ogg'; Path: ptSounds),// sndPiano7
- (FileName: '9D.ogg'; Path: ptSounds),// sndPiano8
- (FileName: 'skip.ogg'; Path: ptSounds),// sndSkip
- (FileName: 'sinegun.ogg'; Path: ptSounds),// sndSineGun
- (FileName: 'Ooff1.ogg'; Path: ptVoices),// sndOoff1
- (FileName: 'Ooff2.ogg'; Path: ptVoices),// sndOoff2
- (FileName: 'Ooff3.ogg'; Path: ptVoices),// sndOoff3
- (FileName: 'hammer.ogg'; Path: ptSounds),// sndWhack
- (FileName: 'Comeonthen.ogg'; Path: ptVoices),// sndComeonthen
- (FileName: 'parachute.ogg'; Path: ptSounds),// sndParachute
- (FileName: 'bump.ogg'; Path: ptSounds),// sndBump
- (FileName: 'hogchant3.ogg'; Path: ptSounds),// sndResurrector
- (FileName: 'plane.ogg'; Path: ptSounds),// sndPlane
- (FileName: 'TARDIS.ogg'; Path: ptSounds),// sndTardis
- (FileName: 'frozen_hog_impact.ogg'; Path: ptSounds),// sndFrozenHogImpact
- (FileName: 'ice_beam.ogg'; Path: ptSounds),// sndIceBeam
- (FileName: 'hog_freeze.ogg'; Path: ptSounds),// sndHogFreeze
- (FileName: 'airmine_impact.ogg'; Path: ptSounds),// sndAirMineImpact
- (FileName: 'knife_impact.ogg'; Path: ptSounds),// sndKnifeImpact
- (FileName: 'extratime.ogg'; Path: ptSounds) // sndExtraTime
+ (FileName: ''; Path: ptNone; AltPath: ptNone),// sndNone
+ (FileName: 'grenadeimpact.ogg'; Path: ptSounds; AltPath: ptNone),// sndGrenadeImpact
+ (FileName: 'explosion.ogg'; Path: ptSounds; AltPath: ptNone),// sndExplosion
+ (FileName: 'throwpowerup.ogg'; Path: ptSounds; AltPath: ptNone),// sndThrowPowerUp
+ (FileName: 'throwrelease.ogg'; Path: ptSounds; AltPath: ptNone),// sndThrowRelease
+ (FileName: 'splash.ogg'; Path: ptCurrTheme; AltPath: ptSounds),// sndSplash
+ (FileName: 'shotgunreload.ogg'; Path: ptSounds; AltPath: ptNone),// sndShotgunReload
+ (FileName: 'shotgunfire.ogg'; Path: ptSounds; AltPath: ptNone),// sndShotgunFire
+ (FileName: 'graveimpact.ogg'; Path: ptSounds; AltPath: ptNone),// sndGraveImpact
+ (FileName: 'mineimpact.ogg'; Path: ptSounds; AltPath: ptNone),// sndMineImpact
+ (FileName: 'minetick.ogg'; Path: ptSounds; AltPath: ptNone),// sndMineTicks
+ (FileName: 'Droplet1.ogg'; Path: ptSounds; AltPath: ptNone),// sndMudballImpact
+ (FileName: 'pickhammer.ogg'; Path: ptSounds; AltPath: ptNone),// sndPickhammer
+ (FileName: 'gun.ogg'; Path: ptSounds; AltPath: ptNone),// sndGun
+ (FileName: 'bee.ogg'; Path: ptSounds; AltPath: ptNone),// sndBee
+ (FileName: 'Jump1.ogg'; Path: ptVoices; AltPath: ptNone),// sndJump1
+ (FileName: 'Jump2.ogg'; Path: ptVoices; AltPath: ptNone),// sndJump2
+ (FileName: 'Jump3.ogg'; Path: ptVoices; AltPath: ptNone),// sndJump3
+ (FileName: 'Yessir.ogg'; Path: ptVoices; AltPath: ptNone),// sndYesSir
+ (FileName: 'Laugh.ogg'; Path: ptVoices; AltPath: ptNone),// sndLaugh
+ (FileName: 'Illgetyou.ogg'; Path: ptVoices; AltPath: ptNone),// sndIllGetYou
+ (FileName: 'Justyouwait.ogg'; Path: ptVoices; AltPath: ptNone),// sndJustyouwait
+ (FileName: 'Incoming.ogg'; Path: ptVoices; AltPath: ptNone),// sndIncoming
+ (FileName: 'Missed.ogg'; Path: ptVoices; AltPath: ptNone),// sndMissed
+ (FileName: 'Stupid.ogg'; Path: ptVoices; AltPath: ptNone),// sndStupid
+ (FileName: 'Firstblood.ogg'; Path: ptVoices; AltPath: ptNone),// sndFirstBlood
+ (FileName: 'Boring.ogg'; Path: ptVoices; AltPath: ptNone),// sndBoring
+ (FileName: 'Byebye.ogg'; Path: ptVoices; AltPath: ptNone),// sndByeBye
+ (FileName: 'Sameteam.ogg'; Path: ptVoices; AltPath: ptNone),// sndSameTeam
+ (FileName: 'Nutter.ogg'; Path: ptVoices; AltPath: ptNone),// sndNutter
+ (FileName: 'Reinforcements.ogg'; Path: ptVoices; AltPath: ptNone),// sndReinforce
+ (FileName: 'Traitor.ogg'; Path: ptVoices; AltPath: ptNone),// sndTraitor
+ (FileName: 'Youllregretthat.ogg'; Path: ptVoices; AltPath: ptNone),// sndRegret
+ (FileName: 'Enemydown.ogg'; Path: ptVoices; AltPath: ptNone),// sndEnemyDown
+ (FileName: 'Coward.ogg'; Path: ptVoices; AltPath: ptNone),// sndCoward
+ (FileName: 'Hurry.ogg'; Path: ptVoices; AltPath: ptNone),// sndHurry
+ (FileName: 'Watchit.ogg'; Path: ptVoices; AltPath: ptNone),// sndWatchIt
+ (FileName: 'Kamikaze.ogg'; Path: ptVoices; AltPath: ptNone),// sndKamikaze
+ (FileName: 'cake2.ogg'; Path: ptSounds; AltPath: ptNone),// sndCake
+ (FileName: 'Ow1.ogg'; Path: ptVoices; AltPath: ptNone),// sndOw1
+ (FileName: 'Ow2.ogg'; Path: ptVoices; AltPath: ptNone),// sndOw2
+ (FileName: 'Ow3.ogg'; Path: ptVoices; AltPath: ptNone),// sndOw3
+ (FileName: 'Ow4.ogg'; Path: ptVoices; AltPath: ptNone),// sndOw4
+ (FileName: 'Firepunch1.ogg'; Path: ptVoices; AltPath: ptNone),// sndFirepunch1
+ (FileName: 'Firepunch2.ogg'; Path: ptVoices; AltPath: ptNone),// sndFirepunch2
+ (FileName: 'Firepunch3.ogg'; Path: ptVoices; AltPath: ptNone),// sndFirepunch3
+ (FileName: 'Firepunch4.ogg'; Path: ptVoices; AltPath: ptNone),// sndFirepunch4
+ (FileName: 'Firepunch5.ogg'; Path: ptVoices; AltPath: ptNone),// sndFirepunch5
+ (FileName: 'Firepunch6.ogg'; Path: ptVoices; AltPath: ptNone),// sndFirepunch6
+ (FileName: 'Melon.ogg'; Path: ptVoices; AltPath: ptNone),// sndMelon
+ (FileName: 'Hellish.ogg'; Path: ptSounds; AltPath: ptNone),// sndHellish
+ (FileName: 'Yoohoo.ogg'; Path: ptSounds; AltPath: ptNone),// sndYoohoo
+ (FileName: 'rcplane.ogg'; Path: ptSounds; AltPath: ptNone),// sndRCPlane
+ (FileName: 'whipcrack.ogg'; Path: ptSounds; AltPath: ptNone),// sndWhipCrack
+ (FileName:'ride_of_the_valkyries.ogg'; Path: ptSounds; AltPath: ptNone),// sndRideOfTheValkyries
+ (FileName: 'denied.ogg'; Path: ptSounds; AltPath: ptNone),// sndDenied
+ (FileName: 'placed.ogg'; Path: ptSounds; AltPath: ptNone),// sndPlaced
+ (FileName: 'baseballbat.ogg'; Path: ptSounds; AltPath: ptNone),// sndBaseballBat
+ (FileName: 'steam.ogg'; Path: ptSounds; AltPath: ptNone),// sndVaporize
+ (FileName: 'warp.ogg'; Path: ptSounds; AltPath: ptNone),// sndWarp
+ (FileName: 'suddendeath.ogg'; Path: ptSounds; AltPath: ptNone),// sndSuddenDeath
+ (FileName: 'mortar.ogg'; Path: ptSounds; AltPath: ptNone),// sndMortar
+ (FileName: 'shutterclick.ogg'; Path: ptSounds; AltPath: ptNone),// sndShutter
+ (FileName: 'homerun.ogg'; Path: ptSounds; AltPath: ptNone),// sndHomerun
+ (FileName: 'molotov.ogg'; Path: ptSounds; AltPath: ptNone),// sndMolotov
+ (FileName: 'Takecover.ogg'; Path: ptVoices; AltPath: ptNone),// sndCover
+ (FileName: 'Uh-oh.ogg'; Path: ptVoices; AltPath: ptNone),// sndUhOh
+ (FileName: 'Oops.ogg'; Path: ptVoices; AltPath: ptNone),// sndOops
+ (FileName: 'Nooo.ogg'; Path: ptVoices; AltPath: ptNone),// sndNooo
+ (FileName: 'Hello.ogg'; Path: ptVoices; AltPath: ptNone),// sndHello
+ (FileName: 'ropeshot.ogg'; Path: ptSounds; AltPath: ptNone),// sndRopeShot
+ (FileName: 'ropeattach.ogg'; Path: ptSounds; AltPath: ptNone),// sndRopeAttach
+ (FileName: 'roperelease.ogg'; Path: ptSounds; AltPath: ptNone),// sndRopeRelease
+ (FileName: 'switchhog.ogg'; Path: ptSounds; AltPath: ptNone),// sndSwitchHog
+ (FileName: 'Victory.ogg'; Path: ptVoices; AltPath: ptNone),// sndVictory
+ (FileName: 'Flawless.ogg'; Path: ptVoices; AltPath: ptNone),// sndFlawless
+ (FileName: 'sniperreload.ogg'; Path: ptSounds; AltPath: ptNone),// sndSniperReload
+ (FileName: 'steps.ogg'; Path: ptSounds; AltPath: ptNone),// sndSteps
+ (FileName: 'lowgravity.ogg'; Path: ptSounds; AltPath: ptNone),// sndLowGravity
+ (FileName: 'hell_growl.ogg'; Path: ptSounds; AltPath: ptNone),// sndHellishImpact1
+ (FileName: 'hell_ooff.ogg'; Path: ptSounds; AltPath: ptNone),// sndHellishImpact2
+ (FileName: 'hell_ow.ogg'; Path: ptSounds; AltPath: ptNone),// sndHellishImpact3
+ (FileName: 'hell_ugh.ogg'; Path: ptSounds; AltPath: ptNone),// sndHellishImpact4
+ (FileName: 'melonimpact.ogg'; Path: ptSounds; AltPath: ptNone),// sndMelonImpact
+ (FileName: 'Droplet1.ogg'; Path: ptCurrTheme; AltPath: ptSounds),// sndDroplet1
+ (FileName: 'Droplet2.ogg'; Path: ptCurrTheme; AltPath: ptSounds),// sndDroplet2
+ (FileName: 'Droplet3.ogg'; Path: ptCurrTheme; AltPath: ptSounds),// sndDroplet3
+ (FileName: 'egg.ogg'; Path: ptSounds; AltPath: ptNone),// sndEggBreak
+ (FileName: 'drillgun.ogg'; Path: ptSounds; AltPath: ptNone),// sndDrillRocket
+ (FileName: 'PoisonCough.ogg'; Path: ptVoices; AltPath: ptNone),// sndPoisonCough
+ (FileName: 'PoisonMoan.ogg'; Path: ptVoices; AltPath: ptNone),// sndPoisonMoan
+ (FileName: 'BirdyLay.ogg'; Path: ptSounds; AltPath: ptNone),// sndBirdyLay
+ (FileName: 'Whistle.ogg'; Path: ptSounds; AltPath: ptNone),// sndWhistle
+ (FileName: 'beewater.ogg'; Path: ptSounds; AltPath: ptNone),// sndBeeWater
+ (FileName: '1C.ogg'; Path: ptSounds; AltPath: ptNone),// sndPiano0
+ (FileName: '2D.ogg'; Path: ptSounds; AltPath: ptNone),// sndPiano1
+ (FileName: '3E.ogg'; Path: ptSounds; AltPath: ptNone),// sndPiano2
+ (FileName: '4F.ogg'; Path: ptSounds; AltPath: ptNone),// sndPiano3
+ (FileName: '5G.ogg'; Path: ptSounds; AltPath: ptNone),// sndPiano4
+ (FileName: '6A.ogg'; Path: ptSounds; AltPath: ptNone),// sndPiano5
+ (FileName: '7B.ogg'; Path: ptSounds; AltPath: ptNone),// sndPiano6
+ (FileName: '8C.ogg'; Path: ptSounds; AltPath: ptNone),// sndPiano7
+ (FileName: '9D.ogg'; Path: ptSounds; AltPath: ptNone),// sndPiano8
+ (FileName: 'skip.ogg'; Path: ptCurrTheme; AltPath: ptSounds),// sndSkip
+ (FileName: 'sinegun.ogg'; Path: ptSounds; AltPath: ptNone),// sndSineGun
+ (FileName: 'Ooff1.ogg'; Path: ptVoices; AltPath: ptNone),// sndOoff1
+ (FileName: 'Ooff2.ogg'; Path: ptVoices; AltPath: ptNone),// sndOoff2
+ (FileName: 'Ooff3.ogg'; Path: ptVoices; AltPath: ptNone),// sndOoff3
+ (FileName: 'hammer.ogg'; Path: ptSounds; AltPath: ptNone),// sndWhack
+ (FileName: 'Comeonthen.ogg'; Path: ptVoices; AltPath: ptNone),// sndComeonthen
+ (FileName: 'parachute.ogg'; Path: ptSounds; AltPath: ptNone),// sndParachute
+ (FileName: 'bump.ogg'; Path: ptSounds; AltPath: ptNone),// sndBump
+ (FileName: 'hogchant3.ogg'; Path: ptSounds; AltPath: ptNone),// sndResurrector
+ (FileName: 'plane.ogg'; Path: ptSounds; AltPath: ptNone),// sndPlane
+ (FileName: 'TARDIS.ogg'; Path: ptSounds; AltPath: ptNone),// sndTardis
+ (FileName: 'frozen_hog_impact.ogg'; Path: ptSounds; AltPath: ptNone),// sndFrozenHogImpact
+ (FileName: 'ice_beam.ogg'; Path: ptSounds; AltPath: ptNone),// sndIceBeam
+ (FileName: 'hog_freeze.ogg'; Path: ptSounds; AltPath: ptNone), // sndHogFreeze
+ (FileName: 'airmine_impact.ogg'; Path: ptSounds; AltPath: ptNone),// sndAirMineImpact
+ (FileName: 'knife_impact.ogg'; Path: ptSounds; AltPath: ptNone),// sndKnifeImpact
+ (FileName: 'extratime.ogg'; Path: ptSounds; AltPath: ptNone),// sndExtraTime
+ (FileName: 'lasersight.ogg'; Path: ptSounds; AltPath: ptNone),// sndLaserSight
+ (FileName: 'invulnerable.ogg'; Path: ptSounds; AltPath: ptNone),// sndInvulnerable
+ (FileName: 'ufo.ogg'; Path: ptSounds; AltPath: ptNone),// sndJetpackLaunch
+ (FileName: 'jetpackboost.ogg'; Path: ptSounds; AltPath: ptNone),// sndJetpackBoost
+ (FileName: 'portalshot.ogg'; Path: ptSounds; AltPath: ptNone),// sndPortalShot
+ (FileName: 'portalswitch.ogg'; Path: ptSounds; AltPath: ptNone),// sndPortalSwitch
+ (FileName: 'portalopen.ogg'; Path: ptSounds; AltPath: ptNone),// sndPortalOpen
+ (FileName: 'blowtorch.ogg'; Path: ptSounds; AltPath: ptNone),// sndBlowTorch
+ (FileName: 'countdown1.ogg'; Path: ptSounds; AltPath: ptNone),// sndCountdown1
+ (FileName: 'countdown2.ogg'; Path: ptSounds; AltPath: ptNone),// sndCountdown2
+ (FileName: 'countdown3.ogg'; Path: ptSounds; AltPath: ptNone),// sndCountdown3
+ (FileName: 'countdown4.ogg'; Path: ptSounds; AltPath: ptNone),// sndCountdown4
+ (FileName: 'rubberduck_drop.ogg'; Path: ptSounds; AltPath: ptNone),// sndDuckDrop
+ (FileName: 'rubberduck_water.ogg'; Path: ptSounds; AltPath: ptNone),// sndDuckWater
+ (FileName: 'rubberduck_die.ogg'; Path: ptSounds; AltPath: ptNone),// sndDuckDie
+ (FileName: 'custom1.ogg'; Path: ptSounds; AltPath: ptNone),// sndCustom1
+ (FileName: 'custom2.ogg'; Path: ptSounds; AltPath: ptNone),// sndCustom2
+ (FileName: 'custom3.ogg'; Path: ptSounds; AltPath: ptNone),// sndCustom3
+ (FileName: 'custom4.ogg'; Path: ptSounds; AltPath: ptNone),// sndCustom4
+ (FileName: 'custom5.ogg'; Path: ptSounds; AltPath: ptNone),// sndCustom5
+ (FileName: 'custom6.ogg'; Path: ptSounds; AltPath: ptNone),// sndCustom6
+ (FileName: 'custom7.ogg'; Path: ptSounds; AltPath: ptNone),// sndCustom7
+ (FileName: 'custom8.ogg'; Path: ptSounds; AltPath: ptNone) // sndCustom8
);
-
function AskForVoicepack(name: shortstring): Pointer;
var i: Longword;
locName, path: shortstring;
@@ -310,10 +332,14 @@
if not (isSoundEnabled or isMusicEnabled) then
exit;
WriteToConsole('Init sound...');
- success:= SDL_InitSubSystem(SDL_INIT_AUDIO) >= 0;
+ success:= SDL_InitSubSystem(SDL_INIT_AUDIO) = 0;
if success then
+ begin
+ WriteLnToConsole(msgOK);
+ WriteToConsole('Open audio...');
success:= Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, channels, 1024) = 0;
+ end;
if success then
WriteLnToConsole(msgOK)
@@ -398,6 +424,7 @@
procedure PlaySoundV(snd: TSound; voicepack: PVoicepack; keepPlaying: boolean);
var s:shortstring;
+rwops: PSDL_RWops;
begin
if (not isSoundEnabled) or fastUntilLag then
exit;
@@ -413,7 +440,16 @@
if (not pfsExists(s)) and (snd in [sndFirePunch2, sndFirePunch3, sndFirePunch4, sndFirePunch5, sndFirePunch6]) then
s:= cPathz[Soundz[sndFirePunch1].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName;
WriteToConsole(msgLoading + s + ' ');
- voicepack^.chunks[snd]:= Mix_LoadWAV_RW(rwopsOpenRead(s), 1);
+ rwops := rwopsOpenRead(s);
+
+ if rwops = nil then
+ begin
+ s:= cPathz[Soundz[snd].AltPath] + '/' + voicepack^.name + '/' + Soundz[snd].FileName;
+ WriteToConsole(msgLoading + s + ' ... ');
+ rwops := rwopsOpenRead(s);
+ end;
+ voicepack^.chunks[snd]:= Mix_LoadWAV_RW(rwops, 1);
+
if voicepack^.chunks[snd] = nil then
WriteLnToConsole(msgFailed)
else
@@ -427,7 +463,16 @@
begin
s:= cPathz[Soundz[snd].Path] + '/' + Soundz[snd].FileName;
WriteToConsole(msgLoading + s + ' ');
- defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(rwopsOpenRead(s), 1);
+ rwops := rwopsOpenRead(s);
+
+ if rwops = nil then
+ begin
+ s:= cPathz[Soundz[snd].AltPath] + '/' + Soundz[snd].FileName;
+ WriteToConsole(msgLoading + s + ' ... ');
+ rwops := rwopsOpenRead(s);
+ end;
+
+ defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(rwops, 1);
if SDLCheck(defVoicepack^.chunks[snd] <> nil, 'Mix_LoadWAV_RW', true) then exit;
WriteLnToConsole(msgOK);
end;
@@ -499,6 +544,7 @@
function LoopSoundV(snd: TSound; voicepack: PVoicepack; fadems: LongInt): LongInt;
var s: shortstring;
+rwops: PSDL_RWops;
begin
if (not isSoundEnabled) or fastUntilLag then
begin
@@ -512,7 +558,16 @@
begin
s:= cPathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName;
WriteToConsole(msgLoading + s + ' ');
- voicepack^.chunks[snd]:= Mix_LoadWAV_RW(rwopsOpenRead(s), 1);
+ rwops:=rwopsOpenRead(s);
+
+ if rwops = nil then
+ begin
+ s:= cPathz[Soundz[snd].AltPath] + '/' + Soundz[snd].FileName;
+ WriteToConsole(msgLoading + s + ' ... ');
+ rwops:=rwopsOpenRead(s);
+ end;
+
+ voicepack^.chunks[snd]:= Mix_LoadWAV_RW(rwops, 1);
if voicepack^.chunks[snd] = nil then
WriteLnToConsole(msgFailed)
else
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uStats.pas
--- a/hedgewars/uStats.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uStats.pas Sun Dec 17 00:09:24 2017 +0100
@@ -24,13 +24,19 @@
var TotalRounds: LongInt;
FinishedTurnsTotal: LongInt;
+ SendGameResultOn : boolean = true;
+ SendRankingStatsOn : boolean = true;
+ SendAchievementsStatsOn : boolean = true;
SendHealthStatsOn : boolean = true;
procedure initModule;
procedure freeModule;
procedure AmmoUsed(am: TAmmoType);
+procedure HedgehogPoisoned(Gear: PGear; Attacker: PHedgehog);
+procedure HedgehogSacrificed(Hedgehog: PHedgehog);
procedure HedgehogDamaged(Gear: PGear; Attacker: PHedgehog; Damage: Longword; killed: boolean);
+procedure TargetHit;
procedure Skipped;
procedure TurnReaction;
procedure SendStats;
@@ -45,9 +51,13 @@
var DamageClan : Longword = 0;
DamageTotal : Longword = 0;
DamageTurn : Longword = 0;
+ PoisonTurn : Longword = 0; // Poisoned enemies per turn
+ PoisonClan : Longword = 0; // Poisoned own clan members in turn
+ PoisonTotal : Longword = 0; // Poisoned hogs in whole round
KillsClan : LongWord = 0;
Kills : LongWord = 0;
KillsTotal : LongWord = 0;
+ HitTargets : LongWord = 0; // Target (gtTarget) hits per turn
AmmoUsedCount : Longword = 0;
AmmoDamagingUsed : boolean = false;
SkippedTurns: LongWord = 0;
@@ -55,6 +65,27 @@
vpHurtSameClan: PVoicepack = nil;
vpHurtEnemy: PVoicepack = nil;
+procedure HedgehogPoisoned(Gear: PGear; Attacker: PHedgehog);
+begin
+ if Attacker^.Team^.Clan = Gear^.HEdgehog^.Team^.Clan then
+ begin
+ vpHurtSameClan:= CurrentHedgehog^.Team^.voicepack;
+ inc(PoisonClan)
+ end
+ else
+ begin
+ vpHurtEnemy:= Gear^.Hedgehog^.Team^.voicepack;
+ inc(PoisonTurn)
+ end;
+ Gear^.Hedgehog^.stats.StepPoisoned:= true;
+ inc(PoisonTotal)
+end;
+
+procedure HedgehogSacrificed(Hedgehog: PHedgehog);
+begin
+ Hedgehog^.stats.Sacrificed:= true
+end;
+
procedure HedgehogDamaged(Gear: PGear; Attacker: PHedgehog; Damage: Longword; killed: boolean);
begin
if Attacker^.Team^.Clan = Gear^.Hedgehog^.Team^.Clan then
@@ -72,6 +103,7 @@
if killed then
begin
+ Gear^.Hedgehog^.stats.StepDied:= true;
inc(Attacker^.stats.StepKills);
inc(Kills);
inc(KillsTotal);
@@ -91,6 +123,11 @@
inc(DamageTurn, Damage)
end;
+procedure TargetHit();
+begin
+ inc(HitTargets)
+end;
+
procedure Skipped;
begin
inc(SkippedTurns);
@@ -99,6 +136,7 @@
procedure TurnReaction;
var i, t: LongInt;
+ killsCheck: LongInt;
s: ansistring;
begin
//TryDo(not bBetweenTurns, 'Engine bug: TurnReaction between turns', true);
@@ -108,19 +146,28 @@
begin
s:= ansistring(CurrentHedgehog^.Name);
inc(CurrentHedgehog^.stats.FinishedTurns);
+ // If the hog sacrificed (=kamikaze/piano) itself, this needs to be taken into accounts for the reactions later
+ if (CurrentHedgehog^.stats.Sacrificed) then
+ killsCheck:= 1
+ else
+ killsCheck:= 0;
- if (CurrentHedgehog^.stats.DamageGiven = DamageTotal) and (DamageTotal > 0) then
+ // First blood (first damage, poison or kill)
+ if ((DamageTotal > 0) or (KillsTotal > 0) or (PoisonTotal > 0)) and ((CurrentHedgehog^.stats.DamageGiven = DamageTotal) and (CurrentHedgehog^.stats.StepKills = KillsTotal) and (PoisonTotal = PoisonTurn + PoisonClan)) then
AddVoice(sndFirstBlood, CurrentTeam^.voicepack)
- else if CurrentHedgehog^.stats.StepDamageRecv > 0 then
+ // Hog hurts, poisons or kills itself (except sacrifice)
+ else if (CurrentHedgehog^.stats.Sacrificed = false) and ((CurrentHedgehog^.stats.StepDamageRecv > 0) or (CurrentHedgehog^.stats.StepPoisoned) or (CurrentHedgehog^.stats.StepDied)) then
begin
AddVoice(sndStupid, PreviousTeam^.voicepack);
- if CurrentHedgehog^.stats.DamageGiven = CurrentHedgehog^.stats.StepDamageRecv then
+ // Message for hurting itself only (not drowning)
+ if (CurrentHedgehog^.stats.DamageGiven = CurrentHedgehog^.stats.StepDamageRecv) and (CurrentHedgehog^.stats.StepDamageRecv >= 1) then
AddCaption(FormatA(GetEventString(eidHurtSelf), s), cWhiteColor, capgrpMessage);
end
- else if DamageClan <> 0 then
- if DamageTurn > DamageClan then
+ // Hog hurts, poisons or kills own team/clan member. Sacrifice is taken into account
+ else if (DamageClan <> 0) or (KillsClan > killsCheck) or (PoisonClan <> 0) then
+ if (DamageTurn > DamageClan) or (Kills > KillsClan) then
if random(2) = 0 then
AddVoice(sndNutter, CurrentTeam^.voicepack)
else
@@ -131,23 +178,35 @@
else
AddVoice(sndTraitor, vpHurtSameClan)
- else if CurrentHedgehog^.stats.StepDamageGiven <> 0 then
- if Kills > 0 then
+ // Hog hurts, kills or poisons enemy
+ else if (CurrentHedgehog^.stats.StepDamageGiven <> 0) or (CurrentHedgehog^.stats.StepKills > killsCheck) or (PoisonTurn <> 0) then
+ if Kills > killsCheck then
AddVoice(sndEnemyDown, CurrentTeam^.voicepack)
else
AddVoice(sndRegret, vpHurtEnemy)
- else if AmmoDamagingUsed then
- AddVoice(sndMissed, PreviousTeam^.voicepack)
+ // Missed shot
+ // A miss is defined as a shot with a damaging weapon with 0 kills, 0 damage, 0 hogs poisoned and 0 targets hit
+ else if AmmoDamagingUsed and (Kills <= killsCheck) and (PoisonTurn = 0) and (PoisonClan = 0) and (DamageTurn = 0) and (HitTargets = 0) then
+ // Chance to call hedgehog stupid if sacrificed for nothing
+ if CurrentHedgehog^.stats.Sacrificed then
+ if random(2) = 0 then
+ AddVoice(sndMissed, PreviousTeam^.voicepack)
+ else
+ AddVoice(sndStupid, PreviousTeam^.voicepack)
+ else
+ AddVoice(sndMissed, PreviousTeam^.voicepack)
+
+ // Timeout
else if (AmmoUsedCount > 0) and (not isTurnSkipped) then
begin end// nothing ?
- else if isTurnSkipped then
+
+ // Turn skipped
+ else if isTurnSkipped and (not PlacingHogs) then
begin
- AddVoice(sndBoring, PreviousTeam^.voicepack);
+ AddVoice(sndCoward, PreviousTeam^.voicepack);
AddCaption(FormatA(GetEventString(eidTurnSkipped), s), cWhiteColor, capgrpMessage);
end
- else if not PlacingHogs then
- AddVoice(sndCoward, PreviousTeam^.voicepack);
end;
@@ -166,7 +225,9 @@
MaxStepKills:= StepKills;
StepKills:= 0;
StepDamageRecv:= 0;
- StepDamageGiven:= 0
+ StepDamageGiven:= 0;
+ StepPoisoned:= false;
+ StepDied:= false;
end;
if SendHealthStatsOn then
@@ -180,6 +241,9 @@
KillsClan:= 0;
DamageClan:= 0;
DamageTurn:= 0;
+HitTargets:= 0;
+PoisonClan:= 0;
+PoisonTurn:= 0;
AmmoUsedCount:= 0;
AmmoDamagingUsed:= false;
isTurnSkipped:= false
@@ -226,7 +290,7 @@
for t:= 0 to Pred(TeamsCount) do
with TeamsArray[t]^ do
begin
- if not ExtDriven then
+ if (not ExtDriven) and SendRankingStatsOn then
SendStat(siTeamStats, GetTeamStatString(TeamsArray[t]));
for i:= 0 to cMaxHHIndex do
begin
@@ -250,8 +314,9 @@
if Clan^.ClanHealth > 0 then
begin
winnersClan:= Clan;
- SendStat(siPlayerKills, IntToStr(Clan^.Color) + ' ' +
- IntToStr(stats.Kills) + ' ' + TeamName);
+ if SendRankingStatsOn then
+ SendStat(siPlayerKills, IntToStr(Clan^.Color) + ' ' +
+ IntToStr(stats.Kills) + ' ' + TeamName);
end;
{ determine maximum values of TeamKills, TurnSkips, TeamDamage }
@@ -274,32 +339,37 @@
end;
{ now send player stats for loser teams }
- for t:= 0 to Pred(TeamsCount) do
- begin
- with TeamsArray[t]^ do
+ if SendRankingStatsOn then
+ for t:= 0 to Pred(TeamsCount) do
begin
- if Clan^.ClanHealth = 0 then
+ with TeamsArray[t]^ do
begin
- SendStat(siPlayerKills, IntToStr(Clan^.Color) + ' ' +
- IntToStr(stats.Kills) + ' ' + TeamName);
+ if Clan^.ClanHealth = 0 then
+ begin
+ SendStat(siPlayerKills, IntToStr(Clan^.Color) + ' ' +
+ IntToStr(stats.Kills) + ' ' + TeamName);
+ end;
end;
end;
- end;
- if msdhh <> nil then
- SendStat(siMaxStepDamage, IntToStr(msd) + ' ' + msdhh^.Name + ' (' + msdhh^.Team^.TeamName + ')');
- if mskcnt = 1 then
- SendStat(siMaxStepKills, IntToStr(msk) + ' ' + mskhh^.Name + ' (' + mskhh^.Team^.TeamName + ')');
+ // “Achievements” / Details part of stats screen
+ if SendAchievementsStatsOn then
+ begin
+ if msdhh <> nil then
+ SendStat(siMaxStepDamage, IntToStr(msd) + ' ' + msdhh^.Name + ' (' + msdhh^.Team^.TeamName + ')');
+ if mskcnt = 1 then
+ SendStat(siMaxStepKills, IntToStr(msk) + ' ' + mskhh^.Name + ' (' + mskhh^.Team^.TeamName + ')');
- if maxTeamKills > 1 then
- SendStat(siMaxTeamKills, IntToStr(maxTeamKills) + ' ' + maxTeamKillsName);
- if maxTurnSkips > 2 then
- SendStat(siMaxTurnSkips, IntToStr(maxTurnSkips) + ' ' + maxTurnSkipsName);
- if maxTeamDamage > 30 then
- SendStat(siMaxTeamDamage, IntToStr(maxTeamDamage) + ' ' + maxTeamDamageName);
+ if maxTeamKills > 1 then
+ SendStat(siMaxTeamKills, IntToStr(maxTeamKills) + ' ' + maxTeamKillsName);
+ if maxTurnSkips > 2 then
+ SendStat(siMaxTurnSkips, IntToStr(maxTurnSkips) + ' ' + maxTurnSkipsName);
+ if maxTeamDamage > 30 then
+ SendStat(siMaxTeamDamage, IntToStr(maxTeamDamage) + ' ' + maxTeamDamageName);
- if KilledHHs > 0 then
- SendStat(siKilledHHs, IntToStr(KilledHHs));
+ if KilledHHs > 0 then
+ SendStat(siKilledHHs, IntToStr(KilledHHs));
+ end;
// now to console
if winnersClan <> nil then
@@ -342,9 +412,12 @@
DamageClan := 0;
DamageTotal := 0;
DamageTurn := 0;
+ PoisonClan := 0;
+ PoisonTurn := 0;
KillsClan := 0;
Kills := 0;
KillsTotal := 0;
+ HitTargets := 0;
AmmoUsedCount := 0;
AmmoDamagingUsed := false;
SkippedTurns:= 0;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uStore.pas
--- a/hedgewars/uStore.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uStore.pas Sun Dec 17 00:09:24 2017 +0100
@@ -26,6 +26,7 @@
procedure initModule;
procedure freeModule;
+procedure LoadFonts();
procedure StoreLoad(reload: boolean);
procedure StoreRelease(reload: boolean);
procedure RenderHealth(var Hedgehog: THedgehog);
@@ -61,17 +62,16 @@
implementation
uses uMisc, uConsole, uVariables, uUtils, uTextures, uRender, uRenderUtils,
- uCommands, uPhysFSLayer, uDebug
+ uCommands, uPhysFSLayer, uDebug, adler32
{$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF};
//type TGPUVendor = (gvUnknown, gvNVIDIA, gvATI, gvIntel, gvApple);
var
- SDLwindow: PSDL_Window;
- SDLGLcontext: PSDL_GLContext;
squaresize : LongInt;
numsquares : LongInt;
ProgrTex: PTexture;
+ LoadingText: PTexture;
prevHat: shortstring;
tmpHatSurf: PSDL_Surface;
@@ -150,7 +150,7 @@
texsurf:= SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, RMask, GMask, BMask, AMask);
if not checkFails(texsurf <> nil, errmsgCreateSurface, true) then
- checkFails(SDL_SetColorKey(texsurf, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, true);
+ checkFails(SDL_SetColorKey(texsurf, SDL_TRUE, 0) = 0, errmsgTransparentSet, true);
if not allOK then exit(nil);
@@ -199,7 +199,7 @@
r.h:= 32;
texsurf:= SDL_CreateRGBSurface(SDL_SWSURFACE, r.w, r.h, 32, RMask, GMask, BMask, AMask);
if not checkFails(texsurf <> nil, errmsgCreateSurface, true) then
- checkFails(SDL_SetColorKey(texsurf, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, true);
+ checkFails(SDL_SetColorKey(texsurf, SDL_TRUE, 0) = 0, errmsgTransparentSet, true);
if not allOK then exit;
r.w:= 26;
@@ -342,23 +342,19 @@
begin
if GraveName = '' then
GraveName:= 'Statue';
- texsurf:= LoadDataImageAltFile(ptGraves, GraveName, 'Statue', ifCritical or ifTransparent);
+ texsurf:= LoadDataImageAltFile(ptGraves, GraveName, 'Statue', ifCritical or ifColorKey);
GraveTex:= Surface2Tex(texsurf, false);
SDL_FreeSurface(texsurf)
end
end;
-procedure StoreLoad(reload: boolean);
+procedure LoadFonts();
var s: shortstring;
- ii: TSprite;
fi: THWFont;
- ai: TAmmoType;
- tmpsurf: PSDL_Surface;
- i, imflags: LongInt;
begin
-AddFileLog('StoreLoad()');
+AddFileLog('LoadFonts();');
-if (not reload) and (not cOnlyStats) then
+if (not cOnlyStats) then
for fi:= Low(THWFont) to High(THWFont) do
with Fontz[fi] do
begin
@@ -369,6 +365,15 @@
TTF_SetFontStyle(Handle, style);
WriteLnToConsole(msgOK)
end;
+end;
+
+procedure StoreLoad(reload: boolean);
+var ii: TSprite;
+ ai: TAmmoType;
+ tmpsurf, tmpoverlay: PSDL_Surface;
+ i, y, imflags: LongInt;
+begin
+AddFileLog('StoreLoad()');
if not cOnlyStats then
begin
@@ -403,14 +408,17 @@
tmpsurf:= Surface
else
begin
- imflags := (ifAlpha or ifTransparent);
+ imflags := (ifAlpha or ifColorKey);
// these sprites are optional
- if not (ii in [sprHorizont, sprHorizontL, sprHorizontR, sprSky, sprSkyL, sprSkyR, sprChunk]) then // FIXME: hack
+ if critical then
imflags := (imflags or ifCritical);
// load the image
- tmpsurf := LoadDataImageAltPath(Path, AltPath, FileName, imflags)
+ tmpsurf := LoadDataImageAltPath(Path, AltPath, FileName, imflags);
+ if (tmpsurf <> nil) and checkSum then
+ for y := 0 to tmpsurf^.h-1 do
+ syncedPixelDigest:= Adler32Update(syncedPixelDigest, @PByteArray(tmpsurf^.pixels)^[y*tmpsurf^.pitch], tmpsurf^.w*4)
end;
if tmpsurf <> nil then
@@ -421,9 +429,29 @@
imageHeight:= tmpsurf^.h
end;
if getDimensions then
+ if Height = -1 then //BlueWater
+ begin
+ Width:= tmpsurf^.w;
+ Height:= tmpsurf^.h div watFrames;
+ end
+ else if Height = -2 then //SDWater
+ begin
+ Width:= tmpsurf^.w;
+ Height:= tmpsurf^.h div watSDFrames;
+ end
+ else
+ begin
+ Width:= tmpsurf^.w;
+ Height:= tmpsurf^.h
+ end;
+ if (ii in [sprAMAmmos, sprAMAmmosBW]) then
begin
- Width:= tmpsurf^.w;
- Height:= tmpsurf^.h
+ tmpoverlay := LoadDataImage(Path, copy(FileName, 1, length(FileName)-5), (imflags and (not ifCritical)));
+ if tmpoverlay <> nil then
+ begin
+ copyToXY(tmpoverlay, tmpsurf, 0, 0);
+ SDL_FreeSurface(tmpoverlay)
+ end
end;
if (ii in [sprSky, sprSkyL, sprSkyR, sprHorizont, sprHorizontL, sprHorizontR]) then
begin
@@ -462,7 +490,7 @@
if not reload then
AddProgress;
- tmpsurf:= LoadDataImage(ptGraphics, cHHFileName, ifAlpha or ifCritical or ifTransparent);
+ tmpsurf:= LoadDataImage(ptGraphics, cHHFileName, ifAlpha or ifCritical or ifColorKey);
HHTexture:= Surface2Tex(tmpsurf, false);
SDL_FreeSurface(tmpsurf);
@@ -634,8 +662,8 @@
tmpsurf:= doSurfaceConversion(tmpsurf);
- if (imageFlags and ifTransparent) <> 0 then
- if checkFails(SDL_SetColorKey(tmpsurf, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, true) then exit;
+ if (imageFlags and ifColorKey) <> 0 then
+ if checkFails(SDL_SetColorKey(tmpsurf, SDL_TRUE, 0) = 0, errmsgTransparentSet, true) then exit;
WriteLnToConsole(msgOK + ' (' + inttostr(tmpsurf^.w) + 'x' + inttostr(tmpsurf^.h) + ')');
@@ -770,13 +798,16 @@
if Step = 0 then
begin
WriteToConsole(msgLoading + 'progress sprite: ');
- texsurf:= LoadDataImage(ptGraphics, 'Progress', ifCritical or ifTransparent);
+ texsurf:= LoadDataImage(ptGraphics, 'Progress', ifCritical or ifColorKey);
ProgrTex:= Surface2Tex(texsurf, false);
+ LoadingText:= RenderStringTex(trmsg[sidLoading], $FFF39EE8, fntBig);
+
squaresize:= texsurf^.w shr 1;
numsquares:= texsurf^.h div squaresize;
SDL_FreeSurface(texsurf);
+
{$IFNDEF PAS2C}
with mobileRecord do
if GameLoading <> nil then
@@ -797,6 +828,7 @@
r.h:= squaresize;
DrawTextureFromRect( -squaresize div 2, (cScreenHeight - squaresize) shr 1, @r, ProgrTex);
+ DrawTexture( -LoadingText^.w div 2, (cScreenHeight - LoadingText^.h) shr 1 - (squaresize div 2) - (LoadingText^.h div 2) - 8, LoadingText);
SwapBuffers;
@@ -810,8 +842,9 @@
if GameLoaded <> nil then
GameLoaded();
{$ENDIF}
- WriteLnToConsole('Freeing progress surface... ');
+ WriteLnToConsole('Freeing progress textures... ');
FreeAndNilTexture(ProgrTex);
+ FreeAndNilTexture(LoadingText);
Step:= 0
end;
@@ -928,7 +961,7 @@
r.y:= cFontBorder + 4;
r.w:= 32;
r.h:= 32;
-SDL_FillRect(tmpsurf, @r, $ffffffff);
+SDL_FillRect(tmpsurf, @r, $ff000000);
SDL_UpperBlit(iconsurf, iconrect, tmpsurf, @r);
RenderHelpWindow:= Surface2Tex(tmpsurf, true);
@@ -938,6 +971,9 @@
procedure RenderWeaponTooltip(atype: TAmmoType);
var r: TSDL_Rect;
i: LongInt;
+ ammoname: ansistring;
+ ammocap: ansistring;
+ ammodesc: ansistring;
extra: ansistring;
extracolor: LongInt;
begin
@@ -964,7 +1000,10 @@
if (CurrentTeam <> nil) and (Ammoz[atype].SkipTurns >= CurrentTeam^.Clan^.TurnNumber) then // weapon or utility is not yet available
begin
- extra:= trmsg[sidNotYetAvailable];
+ if (atype = amTardis) and (suddenDeathDmg) then
+ extra:= trmsg[sidNotAvailableInSD]
+ else
+ extra:= trmsg[sidNotYetAvailable];
extracolor:= LongInt($ffc77070);
end
else if (Ammoz[atype].Ammo.Propz and ammoprop_NoRoundEnd) <> 0 then // weapon or utility will not end your turn
@@ -978,8 +1017,26 @@
extracolor:= 0;
end;
+if length(trluaammo[Ammoz[atype].NameId]) > 0 then
+ ammoname := trluaammo[Ammoz[atype].NameId]
+else
+ ammoname := trammo[Ammoz[atype].NameId];
+
+if length(trluaammoc[Ammoz[atype].NameId]) > 0 then
+ ammocap := trluaammoc[Ammoz[atype].NameId]
+else
+ ammocap := trammoc[Ammoz[atype].NameId];
+
+if length(trluaammod[Ammoz[atype].NameId]) > 0 then
+ ammodesc := trluaammod[Ammoz[atype].NameId]
+else
+ ammodesc := trammod[Ammoz[atype].NameId];
+
+if length(trluaammoa[Ammoz[atype].NameId]) > 0 then
+ ammodesc := ammodesc + '|' + trluaammoa[Ammoz[atype].NameId];
+
// render window and return the texture
-WeaponTooltipTex:= RenderHelpWindow(trammo[Ammoz[atype].NameId], trammoc[Ammoz[atype].NameId], trammod[Ammoz[atype].NameId], extra, extracolor, SpritesData[sprAMAmmos].Surface, @r)
+WeaponTooltipTex:= RenderHelpWindow(ammoname, ammocap, ammodesc, extra, extracolor, SpritesData[sprAMAmmos].Surface, @r)
end;
procedure ShowWeaponTooltip(x, y: LongInt);
@@ -1131,7 +1188,7 @@
// clean the window from any previous content
RenderClear();
if SuddenDeathDmg then
- SetSkyColor(SDSkyColor.r * (SDTint/255) / 255, SDSkyColor.g * (SDTint/255) / 255, SDSkyColor.b * (SDTint/255) / 255)
+ SetSkyColor(SDSkyColor.r * (SDTint.r/255) / 255, SDSkyColor.g * (SDTint.g/255) / 255, SDSkyColor.b * (SDTint.b/255) / 255)
else if ((cReducedQuality and rqNoBackground) = 0) then
SetSkyColor(SkyColor.r / 255, SkyColor.g / 255, SkyColor.b / 255)
else
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uTeams.pas
--- a/hedgewars/uTeams.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uTeams.pas Sun Dec 17 00:09:24 2017 +0100
@@ -49,12 +49,12 @@
uGearsUtils, uGearsList, uVisualGearsList, uTextures
{$IFDEF USE_TOUCH_INTERFACE}, uTouch{$ENDIF};
-var GameOver: boolean;
+var TeamsGameOver: boolean;
NextClan: boolean;
function CheckForWin: boolean;
var AliveClan: PClan;
- s, ts: ansistring;
+ s, ts, cap: ansistring;
t, AliveCount, i, j: LongInt;
begin
CheckForWin:= false;
@@ -77,22 +77,47 @@
if (not bBetweenTurns) and isInMultiShoot then
TurnReaction();
-if not GameOver then
+if not TeamsGameOver then
begin
if AliveCount = 0 then
begin // draw
- AddCaption(trmsg[sidDraw], cWhiteColor, capgrpGameState);
- SendStat(siGameResult, shortstring(trmsg[sidDraw]));
- AddGear(0, 0, gtATFinishGame, 0, _0, _0, 3000)
+ AddCaption(GetEventString(eidRoundDraw), cWhiteColor, capgrpGameState);
+ if SendGameResultOn then
+ SendStat(siGameResult, shortstring(trmsg[sidDraw]));
+ AddGear(0, 0, gtATFinishGame, 0, _0, _0, 3000);
end
else // win
+ begin
with AliveClan^ do
begin
ts:= ansistring(Teams[0]^.TeamName);
- if TeamsNumber = 1 then
- s:= FormatA(trmsg[sidWinner], ts) // team wins
- else
- s:= FormatA(trmsg[sidWinner], ts); // clan wins
+ if TeamsNumber = 1 then // team wins
+ begin
+ s:= FormatA(trmsg[sidWinner], ts);
+ cap:= FormatA(GetEventString(eidRoundWin), ts);
+ AddCaption(cap, cWhiteColor, capgrpGameState);
+ end
+ else // clan wins
+ begin
+ s:= '';
+ for j:= 0 to Pred(TeamsNumber) do
+ begin
+ (*
+ Currently, the game result string is just the victory
+ string concatenated multiple times. This assumes that
+ sidWinner is a complete sentence.
+ This might not work well for some languages.
+
+ FIXME/TODO: Add event strings for 2, 3, 4 and >4 teams winning.
+ This requires FormatA to work with multiple parameters. *)
+ ts:= Teams[j]^.TeamName;
+ s:= s + ' ' + FormatA(trmsg[sidWinner], ts);
+
+ // FIXME: Show victory captions one-by-one, not all at once
+ cap:= FormatA(GetEventString(eidRoundWin), ts);
+ AddCaption(cap, cWhiteColor, capgrpGameState);
+ end;
+ end;
for j:= 0 to Pred(TeamsNumber) do
with Teams[j]^ do
@@ -104,13 +129,15 @@
AddVoice(sndFlawless, Teams[0]^.voicepack)
else
AddVoice(sndVictory, Teams[0]^.voicepack);
+ end;
- AddCaption(s, cWhiteColor, capgrpGameState);
+ if SendGameResultOn then
SendStat(siGameResult, shortstring(s));
- AddGear(0, 0, gtATFinishGame, 0, _0, _0, 3000)
- end;
+ AddGear(0, 0, gtATFinishGame, 0, _0, _0, 3000)
+ end;
SendStats;
end;
+TeamsGameOver:= true;
GameOver:= true
end;
@@ -320,6 +347,7 @@
TagTurnTimeLeft:= 0;
NextClan:= false;
end;
+IsGetAwayTime:= false;
if (TurnTimeLeft > 0) and (CurrentHedgehog^.BotLevel = 0) then
begin
@@ -732,25 +760,6 @@
end;
-procedure chFinish(var s:shortstring);
-var t: LongInt;
-begin
-// avoid compiler hint
-s:= s;
-
-isPaused:= false;
-
-t:= 0;
-while t < TeamsCount do
- begin
- TeamsArray[t]^.hasGone:= true;
- inc(t)
- end;
-
-AddChatString(#7 + '* Good-bye!');
-RecountAllTeamsHealth();
-end;
-
procedure SwitchCurrentHedgehog(newHog: PHedgehog);
var oldCI, newCI: boolean;
oldHH: PHedgehog;
@@ -832,7 +841,6 @@
RegisterVariable('bind', @chBind, true );
RegisterVariable('teamgone', @chTeamGone, true );
RegisterVariable('teamback', @chTeamBack, true );
-RegisterVariable('finish', @chFinish, true ); // all teams gone
RegisterVariable('fort' , @chFort , false);
RegisterVariable('grave' , @chGrave , false);
RegisterVariable('hat' , @chSetHat , false);
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uTextures.pas
--- a/hedgewars/uTextures.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uTextures.pas Sun Dec 17 00:09:24 2017 +0100
@@ -78,7 +78,6 @@
new(NewTexture);
NewTexture^.PrevTexture:= nil;
NewTexture^.NextTexture:= nil;
-NewTexture^.Scale:= 1;
if TextureList <> nil then
begin
TextureList^.PrevTexture:= NewTexture;
@@ -86,6 +85,8 @@
end;
TextureList:= NewTexture;
+NewTexture^.Scale:= 1;
+NewTexture^.Priority:= 0;
NewTexture^.w:= width;
NewTexture^.h:= height;
NewTexture^.rx:= 1.0;
@@ -224,6 +225,8 @@
end;
TextureList:= Surface2Tex;
+Surface2Tex^.Scale:= 1;
+Surface2Tex^.Priority:= 0;
Surface2Tex^.w:= surf^.w;
Surface2Tex^.h:= surf^.h;
@@ -244,9 +247,11 @@
fromP4:= Surf^.pixels;
+// FIXME move out of surface2tex
if GrayScale then
Surface2GrayScale(Surf);
+// FIXME move out of surface2tex
PrettifySurfaceAlpha(surf, fromP4);
if (not SupportNPOTT) and (not (isPowerOf2(Surf^.w) and isPowerOf2(Surf^.h))) then
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uTypes.pas
--- a/hedgewars/uTypes.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uTypes.pas Sun Dec 17 00:09:24 2017 +0100
@@ -42,14 +42,14 @@
TGameType = (gmtLocal, gmtDemo, gmtNet, gmtSave, gmtLandPreview, gmtSyntax, gmtRecord);
// Different files are stored in different folders, this enumeration is used to tell which folder to use
- TPathType = (ptNone, ptData, ptGraphics, ptThemes, ptCurrTheme, ptTeams, ptMaps,
+ TPathType = (ptNone, ptData, ptGraphics, ptThemes, ptCurrTheme, ptConfig, ptTeams, ptMaps,
ptMapCurrent, ptDemos, ptSounds, ptGraves, ptFonts, ptForts, ptLocale,
ptAmmoMenu, ptHedgehog, ptVoices, ptHats, ptFlags, ptMissionMaps,
- ptSuddenDeath, ptButtons, ptShaders, ptConfig);
+ ptSuddenDeath, ptButtons, ptShaders);
// Available sprites for displaying stuff
- TSprite = (sprWater, sprCloud, sprBomb, sprBigDigit, sprFrame,
- sprLag, sprArrow, sprBazookaShell, sprTargetP, sprBee,
+ TSprite = (sprWater, sprCloud, sprBomb, sprBigDigit, sprBigDigitGray, sprBigDigitGreen,
+ sprBigDigitRed, sprFrame, sprLag, sprArrow, sprBazookaShell, sprTargetP, sprBee,
sprSmokeTrace, sprRopeHook, sprExplosion50, sprMineOff,
sprMineOn, sprMineDead, sprCase, sprFAid, sprDynamite, sprPower,
sprClusterBomb, sprClusterParticle, sprFlame,
@@ -89,7 +89,9 @@
sprBulletHit, sprSnowball, sprHandSnowball, sprSnow,
sprSDFlake, sprSDWater, sprSDCloud, sprSDSplash, sprSDDroplet, sprTardis,
sprSlider, sprBotlevels, sprHandKnife, sprKnife, sprStar, sprIceTexture, sprIceGun,
- sprFrozenHog, sprAmRubber, sprBoing, sprCustom1, sprCustom2, sprAirMine, sprHandAirMine
+ sprFrozenHog, sprAmRubber, sprBoing, sprCustom1, sprCustom2, sprCustom3, sprCustom4,
+ sprCustom5, sprCustom6, sprCustom7, sprCustom8, sprAirMine, sprHandAirMine,
+ sprFlakeL, sprSDFlakeL, sprCloudL, sprSDCloudL, sprDuck, sprHandDuck
);
// Gears that interact with other Gears and/or Land
@@ -107,7 +109,7 @@
gtEgg, gtPortal, gtPiano, gtGasBomb, gtSineGunShot, gtFlamethrower, // 51
gtSMine, gtPoisonCloud, gtHammer, gtHammerHit, gtResurrector, // 56
gtNapalmBomb, gtSnowball, gtFlake, {gtStructure,} gtLandGun, gtTardis, // 61
- gtIceGun, gtAddAmmo, gtGenericFaller, gtKnife); // 65
+ gtIceGun, gtAddAmmo, gtGenericFaller, gtKnife, gtDuck); // 66
// Gears that are _only_ of visual nature (e.g. background stuff, visual effects, speechbubbles, etc.)
TVisualGearType = (vgtFlake, vgtCloud, vgtExplPart, vgtExplPart2, vgtFire,
@@ -145,8 +147,11 @@
sndPiano0, sndPiano1, sndPiano2, sndPiano3, sndPiano4, sndPiano5, sndPiano6, sndPiano7,
sndPiano8, sndSkip, sndSineGun, sndOoff1, sndOoff2, sndOoff3, sndWhack,
sndComeonthen, sndParachute, sndBump, sndResurrector, sndPlane, sndTardis, sndFrozenHogImpact,
- sndIceBeam, sndHogFreeze, sndAirMineImpact, sndKnifeImpact, sndExtraTime
- );
+ sndIceBeam, sndHogFreeze, sndAirMineImpact, sndKnifeImpact, sndExtraTime, sndLaserSight,
+ sndInvulnerable, sndJetpackLaunch, sndJetpackBoost, sndPortalShot, sndPortalSwitch,
+ sndPortalOpen, sndBlowTorch, sndCountdown1, sndCountdown2, sndCountdown3, sndCountdown4,
+ sndDuckDrop, sndDuckWater, sndDuckDie, sndCustom1, sndCustom2, sndCustom3, sndCustom4,
+ sndCustom5, sndCustom6, sndCustom7, sndCustom8);
// Available ammo types to be used by hedgehogs
TAmmoType = (amNothing, amGrenade, amClusterBomb, amBazooka, amBee, amShotgun, amPickHammer, // 6
@@ -158,7 +163,7 @@
amLaserSight, amVampiric, amSniperRifle, amJetpack, amMolotov, amBirdy, amPortalGun, // 42
amPiano, amGasBomb, amSineGun, amFlamethrower, amSMine, amHammer, // 48
amResurrector, amDrillStrike, amSnowball, amTardis, {amStructure,} amLandGun, // 53
- amIceGun, amKnife, amRubber, amAirMine); // 57
+ amIceGun, amKnife, amRubber, amAirMine, amDuck); // 58
// Different kind of crates that e.g. hedgehogs can pick up
TCrateType = (HealthCrate, AmmoCrate, UtilityCrate);
@@ -273,7 +278,7 @@
// DirAngle is a 'real' - if you do not need it for rotation of sprite in uGearsRender, you can use it for any visual-only value
DirAngle: real;
// These are frequently overridden to serve some other purpose
- Boom: Longword; // amount of damage caused by the gear
+ Boom: Longword; // amount of damage caused by the gear
Pos: Longword; // Commonly overridden. Example use is posCase values in uConsts.
Angle, Power : Longword; // Used for hog aiming/firing. Angle is rarely used as an Angle otherwise.
Timer, WDTimer : LongWord; // Typically used for some sort of gear timer. Time to explosion, remaining fuel...
@@ -326,6 +331,9 @@
StepDamageRecv,
StepDamageGiven,
StepKills: Longword;
+ StepPoisoned,
+ StepDied,
+ Sacrificed: boolean;
MaxStepDamageRecv,
MaxStepDamageGiven,
MaxStepKills: Longword;
@@ -451,24 +459,27 @@
sidMolotov, sidBirdy, sidPortalGun, sidPiano, sidGasBomb,
sidSineGun, sidFlamethrower,sidSMine, sidHammer, sidResurrector,
sidDrillStrike, sidSnowball, sidNothing, sidTardis,
- {sidStructure,} sidLandGun, sidIceGun, sidKnife, sidRubber, sidAirMine);
+ {sidStructure,} sidLandGun, sidIceGun, sidKnife, sidRubber, sidAirMine,
+ sidDuck);
- TMsgStrId = (sidStartFight, sidDraw, sidWinner, sidVolume, sidPaused,
+ TMsgStrId = (sidLoading, sidDraw, sidWinner, sidVolume, sidPaused,
sidConfirm, sidSuddenDeath, sidRemaining, sidFuel, sidSync,
sidNoEndTurn, sidNotYetAvailable, sidRoundSD, sidRoundsSD, sidReady,
sidBounce1, sidBounce2, sidBounce3, sidBounce4, sidBounce5, sidBounce,
- sidMute, sidAFK, sidAutoCameraOff, sidAutoCameraOn, sidPressTarget);
+ sidMute, sidAFK, sidAutoCameraOff, sidAutoCameraOn, sidPressTarget,
+ sidNotAvailableInSD, sidHealthGain, sidEmptyCrate);
// Events that are important for the course of the game or at least interesting for other reasons
TEventId = (eidDied, eidDrowned, eidRoundStart, eidRoundWin, eidRoundDraw,
eidNewHealthPack, eidNewAmmoPack, eidNewUtilityPack, eidTurnSkipped,
- eidHurtSelf, eidHomerun, eidGone);
+ eidHurtSelf, eidHomerun, eidGone, eidPoisoned, eidResurrected,
+ eidKamikaze, eidTimeTravelEnd, eidTimeout, eidKingDied);
- TGoalStrId = (gidCaption, gidSubCaption, gidForts, gidLowGravity, gidInvulnerable,
+ TGoalStrId = (gidCaption, gidSubCaption, gidPlaceKing, gidLowGravity, gidInvulnerable,
gidVampiric, gidKarma, gidKing, gidPlaceHog, gidArtillery,
gidSolidLand, gidSharedAmmo, gidMineTimer, gidNoMineTimer,
gidRandomMineTimer, gidDamageModifier, gidResetHealth, gidAISurvival,
- gidInfAttack, gidResetWeps, gidPerHogAmmo, gidTagTeam);
+ gidInfAttack, gidResetWeps, gidPerHogAmmo, gidTagTeam, gidMoreWind);
TLandArray = packed array of array of LongWord;
@@ -515,6 +526,8 @@
Surface: PSDL_Surface;
Width, Height, imageWidth, imageHeight: LongInt;
saveSurf: boolean;
+ critical: boolean;
+ checkSum: boolean; // use for images where if they are missing a desync can occur.
priority: GLfloat;
getDimensions, getImageDimensions: boolean;
end;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uUtils.pas
--- a/hedgewars/uUtils.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uUtils.pas Sun Dec 17 00:09:24 2017 +0100
@@ -42,6 +42,7 @@
function EnumToStr(const en : TCapGroup) : shortstring; overload;
function EnumToStr(const en : TSprite) : shortstring; overload;
function EnumToStr(const en : TMapGen) : shortstring; overload;
+function EnumToStr(const en : TWorldEdge) : shortstring; overload;
function Min(a, b: LongInt): LongInt; inline;
function MinD(a, b: double) : double; inline;
@@ -76,6 +77,8 @@
function GetLaunchX(at: TAmmoType; dir: LongInt; angle: LongInt): LongInt;
function GetLaunchY(at: TAmmoType; angle: LongInt): LongInt;
+function CalcWorldWrap(X, radius: LongInt): LongInt;
+
function read1stLn(filePath: shortstring): shortstring;
function readValueFromINI(key, filePath: shortstring): shortstring;
@@ -296,6 +299,11 @@
EnumToStr := GetEnumName(TypeInfo(TMapGen), ord(en))
end;
+function EnumToStr(const en: TWorldEdge) : shortstring; overload;
+begin
+EnumToStr := GetEnumName(TypeInfo(TWorldEdge), ord(en))
+end;
+
function Min(a, b: LongInt): LongInt;
begin
@@ -530,6 +538,7 @@
function GetLaunchX(at: TAmmoType; dir: LongInt; angle: LongInt): LongInt;
begin
+at:= at; dir:= dir; angle:= angle; // parameter hint suppression because code below is currently disabled
GetLaunchX:= 0
(*
if (Ammoz[at].ejectX <> 0) or (Ammoz[at].ejectY <> 0) then
@@ -540,6 +549,7 @@
function GetLaunchY(at: TAmmoType; angle: LongInt): LongInt;
begin
+at:= at; angle:= angle; // parameter hint suppression because code below is currently disabled
GetLaunchY:= 0
(*
if (Ammoz[at].ejectX <> 0) or (Ammoz[at].ejectY <> 0) then
@@ -548,6 +558,31 @@
GetLaunchY:= 0*)
end;
+// Takes an X coordinate and corrects if according to the world edge rules
+// Wrap-around: X will be wrapped
+// Bouncy: X will be kept inside the legal land (taking radius into account)
+// Other world edges: Just returns X
+// radius is a radius (gear radius) tolerance for an appropriate distance from bouncy world edges.
+// Set radius to 0 if you don't care.
+function CalcWorldWrap(X, radius: LongInt): LongInt;
+begin
+ if WorldEdge = weWrap then
+ begin
+ if X < leftX then
+ X:= X + (rightX - leftX)
+ else if X > rightX then
+ X:= X - (rightX - leftX);
+ end
+ else if WorldEdge = weBounce then
+ begin
+ if (X + radius) < leftX then
+ X:= leftX + radius
+ else if (X - radius) > rightX then
+ X:= rightX - radius;
+ end;
+ CalcWorldWrap:= X;
+end;
+
function CheckNoTeamOrHH: boolean;
begin
CheckNoTeamOrHH:= (CurrentTeam = nil) or (CurrentHedgehog^.Gear = nil);
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uVariables.pas
--- a/hedgewars/uVariables.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uVariables.pas Sun Dec 17 00:09:24 2017 +0100
@@ -66,7 +66,8 @@
cAudioCodec : shortstring;
{$ENDIF}
//////////////////////////
- cMapName : shortstring;
+ cMapName : shortstring;
+ syncedPixelDigest : LongInt;
isCursorVisible : boolean;
isInLag : boolean;
isPaused : boolean;
@@ -93,6 +94,8 @@
TurnClockActive : boolean;
TagTurnTimeLeft : Longword;
ReadyTimeLeft : Longword;
+ IsGetAwayTime : boolean;
+ GameOver : boolean;
cSuddenDTurns : LongInt;
cDamagePercent : LongInt;
cMineDudPercent : LongWord;
@@ -178,9 +181,11 @@
cElastic : hwFloat;
cGravity : hwFloat;
cGravityf : real;
+ cLowGravity : boolean;
cBuildMaxDist : LongInt;
cDamageModifier : hwFloat;
cLaserSighting : boolean;
+ cLaserSightingSniper : boolean;
cVampiric : boolean;
cArtillery : boolean;
WeaponTooltipTex: PTexture;
@@ -202,7 +207,6 @@
WaterColorArray : array[0..7] of HwColor4f;
SDWaterColorArray : array[0..7] of HwColor4f;
- SDTint : LongInt;
TargetCursorPoint : TPoint;
CursorPoint : TPoint;
@@ -237,16 +241,23 @@
hiTicks: Word;
- LuaGoals : shortstring;
+ LuaGoals : ansistring;
LuaTemplateNumber : LongWord;
+ // for EndTurn Lua call
+ LuaEndTurnRequested: boolean;
+ LuaNoEndTurnTaunts: boolean;
+
LastVoice : TVoice;
mobileRecord: TMobileRecord;
MaxTextureSize: LongInt;
+ SDLwindow: PSDL_Window;
+ SDLGLcontext: PSDL_GLContext;
+
/////////////////////////////////////
//Buttons
{$IFDEF USE_TOUCH_INTERFACE}
@@ -269,6 +280,7 @@
'/Graphics', // ptGraphics
'/Themes', // ptThemes
'/Themes/Bamboo', // ptCurrTheme
+ '/Config', // ptConfig
'/Config/Teams', // ptTeams
'/Maps', // ptMaps
'', // ptMapCurrent
@@ -286,8 +298,7 @@
'/Missions/Maps', // ptMissionMaps
'/Graphics/SuddenDeath', // ptSuddenDeath
'/Graphics/Buttons', // ptButton
- '/Shaders', // ptShaders
- '/Config' // ptConfig
+ '/Shaders' // ptShaders
);
var
@@ -329,406 +340,436 @@
const
SpritesDataInit: array[TSprite] of TSpriteData = (
(FileName: 'BlueWater'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: true; getImageDimensions: true),// sprWater
+ Width: 0; Height: -1; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: true; getImageDimensions: true),// sprWater
(FileName: 'Clouds'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 256; Height:128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprCloud
+ Width: 256; Height:128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprCloud
(FileName: 'Bomb'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBomb
+ Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBomb
(FileName: 'BigDigits'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBigDigit
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBigDigit
+ (FileName: 'BigDigitsGray'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBigDigitGray
+ (FileName: 'BigDigitsGreen'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBigDigitGreen
+ (FileName: 'BigDigitsRed'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBigDigitRed
(FileName: 'Frame'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 4; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprFrame
+ Width: 4; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprFrame
(FileName: 'Lag'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 65; Height: 65; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprLag
+ Width: 65; Height: 65; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprLag
(FileName: 'Arrow'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCursor
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCursor
(FileName:'BazookaShell'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBazookaShell
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBazookaShell
(FileName: 'Targetp'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTargetP
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTargetP
(FileName: 'Bee'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBee
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBee
(FileName: 'SmokeTrace'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmokeTrace
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmokeTrace
(FileName: 'RopeHook'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprRopeHook
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprRopeHook
(FileName: 'Expl50'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosion50
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosion50
(FileName: 'MineOff'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineOff
+ Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineOff
(FileName: 'MineOn'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineOn
+ Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineOn
(FileName: 'MineDead'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineDead
+ Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineDead
(FileName: 'Case'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprCase
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprCase
(FileName: 'FirstAid'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprFAid
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprFAid
(FileName: 'dynamite'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDynamite
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDynamite
(FileName: 'Power'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprPower
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprPower
(FileName: 'ClBomb'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprClusterBomb
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprClusterBomb
(FileName: 'ClParticle'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprClusterParticle
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprClusterParticle
(FileName: 'Flame'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFlame
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFlame
(FileName: 'horizont'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizont
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: false; checkSum: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizont
(FileName: 'horizontL'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizontL
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: false; checkSum: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizontL
(FileName: 'horizontR'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizontR
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: false; checkSum: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizontR
(FileName: 'Sky'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: false; checkSum: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky
(FileName: 'SkyL'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSkyL
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: false; checkSum: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSkyL
(FileName: 'SkyR'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSkyR
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: false; checkSum: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSkyR
(FileName: 'Slot'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMSlot
- (FileName: 'Ammos'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMAmmos
- (FileName: 'Ammos_bw'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprAMAmmosBW
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMSlot
+ (FileName: 'Ammos_base'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMAmmos
+ (FileName: 'Ammos_bw_base'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprAMAmmosBW
(FileName: 'SlotKeys'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMSlotKeys
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMSlotKeys
(FileName: 'Corners'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 2; Height: 2; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMCorners
+ Width: 2; Height: 2; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMCorners
(FileName: 'Finger'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprFinger
+ Width: 32; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprFinger
(FileName: 'AirBomb'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAirBomb
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAirBomb
(FileName: 'Airplane'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 256; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAirplane
+ Width: 256; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAirplane
(FileName: 'amAirplane'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmAirplane
+ Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmAirplane
(FileName: 'amGirder'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 160; Height:160; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmGirder
+ Width: 160; Height:160; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmGirder
(FileName: 'hhMask'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHHTelepMask
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHHTelepMask
(FileName: 'Switch'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSwitch
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSwitch
(FileName: 'Parachute'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprParachute
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprParachute
(FileName: 'Target'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTarget
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTarget
(FileName: 'RopeNode'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 6; Height: 6; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprRopeNode
+ Width: 6; Height: 6; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprRopeNode
(FileName: 'thinking'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprQuestion
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprQuestion
(FileName: 'PowerBar'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 256; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPowerBar
+ Width: 256; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPowerBar
(FileName: 'WindBar'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 151; Height: 17; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindBar
+ Width: 151; Height: 17; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindBar
(FileName: 'WindL'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 80; Height: 13; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindL
+ Width: 80; Height: 13; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindL
(FileName: 'WindR'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 80; Height: 13; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindR
+ Width: 80; Height: 13; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindR
{$IFDEF USE_TOUCH_INTERFACE}
(FileName: 'firebutton'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprFireButton
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprFireButton
(FileName: 'arrowup'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowUp
+ Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowUp
(FileName: 'arrowdown'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowDown
+ Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowDown
(FileName: 'arrowleft'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowLeft
+ Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowLeft
(FileName: 'arrowright'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowRight
+ Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowRight
(FileName: 'forwardjump'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprAMWidget
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprAMWidget
(FileName: 'backjump'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprJumpWidget
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprJumpWidget
(FileName: 'pause'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 120; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprPauseButton
+ Width: 120; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprPauseButton
(FileName: 'timerbutton'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprTimerButton
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprTimerButton
(FileName: 'targetbutton'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprTargetButton
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprTargetButton
(FileName: 'switchbutton'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprSwitchButton
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprSwitchButton
{$ENDIF}
(FileName: 'Flake'; Path:ptCurrTheme; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFlake
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFlake
(FileName: 'amRope'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandRope
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandRope
(FileName: 'amBazooka'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBazooka
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBazooka
(FileName: 'amShotgun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandShotgun
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandShotgun
(FileName: 'amDEagle'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDEagle
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDEagle
(FileName:'amAirAttack'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandAirAttack
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandAirAttack
(FileName: 'amBaseball'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBaseball
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBaseball
(FileName: 'Hammer'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPHammer
+ Width: 32; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPHammer
(FileName: 'amBTorch_i'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBlowTorch
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBlowTorch
(FileName: 'amBTorch_w'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBlowTorch
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBlowTorch
(FileName: 'Teleport'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTeleport
+ Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTeleport
(FileName: 'HHDeath'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprHHDeath
+ Width: 32; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprHHDeath
(FileName:'amShotgun_w'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprShotgun
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprShotgun
(FileName: 'amDEagle_w'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDEagle
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDEagle
(FileName: 'Idle'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprHHIdle
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprHHIdle
(FileName: 'Mortar'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMortar
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMortar
(FileName: 'TurnsLeft'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTurnsLeft
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTurnsLeft
(FileName: 'amKamikaze'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprKamikaze
+ Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprKamikaze
(FileName: 'amWhip'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWhip
+ Width: 128; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWhip
(FileName: 'Kowtow'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprKowtow
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprKowtow
(FileName: 'Sad'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSad
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSad
(FileName: 'Wave'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprWave
+ Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprWave
(FileName: 'Hurrah'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprHurrah
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprHurrah
(FileName:'ILoveLemonade';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprLemonade
+ Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprLemonade
(FileName: 'Shrug'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShrug
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShrug
(FileName: 'Juggle'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprJuggle
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprJuggle
(FileName: 'ExplPart'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplPart
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplPart
(FileName: 'ExplPart2'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplPart2
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplPart2
(FileName: 'Cake_walk'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCakeWalk
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCakeWalk
(FileName: 'Cake_down'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCakeDown
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCakeDown
(FileName: 'Watermelon'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWatermelon
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWatermelon
(FileName: 'EvilTrace'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprEvilTrace
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprEvilTrace
(FileName:'HellishBomb'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHellishBomb
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHellishBomb
(FileName: 'Seduction'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSeduction
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSeduction
(FileName: 'HHDress'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprDress
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprDress
(FileName: 'Censored'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprCensored
+ Width: 64; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprCensored
(FileName: 'Drill'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDrill
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDrill
(FileName: 'amDrill'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDrill
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDrill
(FileName: 'amBallgun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBallgun
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBallgun
(FileName: 'Balls'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 20; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprBalls
+ Width: 32; Height: 20; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprBalls
(FileName: 'RCPlane'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPlane
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPlane
(FileName: 'amRCPlane'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandPlane
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandPlane
(FileName: 'Utility'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprUtility
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprUtility
(FileName:'Invulnerable';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprInvulnerable
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprInvulnerable
(FileName: 'Vampiric'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprVampiric
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprVampiric
(FileName: 'amGirder'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 512; Height:512; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprGirder
+ Width: 512; Height:512; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprGirder
(FileName:'SpeechCorner';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 12; Height: 9; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechCorner
+ Width: 12; Height: 9; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechCorner
(FileName: 'SpeechEdge'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 25; Height: 9; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechEdge
+ Width: 25; Height: 9; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechEdge
(FileName: 'SpeechTail'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 25; Height: 26; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechTail
+ Width: 25; Height: 26; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechTail
(FileName:'ThoughtCorner';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 49; Height: 37; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtCorner
+ Width: 49; Height: 37; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtCorner
(FileName:'ThoughtEdge'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 23; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtEdge
+ Width: 23; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtEdge
(FileName:'ThoughtTail'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 45; Height: 65; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtTail
+ Width: 45; Height: 65; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtTail
(FileName:'ShoutCorner'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 34; Height: 23; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutCorner
+ Width: 34; Height: 23; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutCorner
(FileName: 'ShoutEdge'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 30; Height: 20; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutEdge
+ Width: 30; Height: 20; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutEdge
(FileName: 'ShoutTail'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 30; Height: 37; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutTail
+ Width: 30; Height: 37; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutTail
(FileName:'amSniperRifle';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSniperRifle
+ Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSniperRifle
(FileName: 'Bubbles'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprBubbles
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprBubbles
(FileName: 'amJetpack'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprJetpack
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprJetpack
(FileName: 'Health'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprHealth
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprHealth
(FileName: 'amMolotov'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),//sprHandMolotov
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),//sprHandMolotov
(FileName: 'Molotov'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMolotov
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMolotov
(FileName: 'Smoke'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmoke
+ Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmoke
(FileName: 'SmokeWhite'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmokeWhite
+ Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmokeWhite
(FileName: 'Shells'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: true),// sprShell
+ Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpLow; getDimensions: false; getImageDimensions: true),// sprShell
(FileName: 'Dust'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprDust
+ Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprDust
(FileName: 'SnowDust'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSnowDust
+ Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSnowDust
(FileName: 'Explosives'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosives
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosives
(FileName: 'ExplosivesRoll'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosivesRoll
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosivesRoll
(FileName: 'amTeleport'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmTeleport
+ Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmTeleport
(FileName: 'Splash'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 80; Height: 50; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSplash
+ Width: 80; Height: 50; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSplash
(FileName: 'Droplet'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprDroplet
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprDroplet
(FileName: 'Birdy'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 75; Height: 75; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBirdy
+ Width: 75; Height: 75; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBirdy
(FileName: 'amCake'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCake
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCake
(FileName: 'amConstruction'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandConstruction
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandConstruction
(FileName: 'amGrenade'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandGrenade
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandGrenade
(FileName: 'amMelon'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMelon
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMelon
(FileName: 'amMortar'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMortar
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMortar
(FileName: 'amSkip'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSkip
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSkip
(FileName: 'amCluster'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCluster
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCluster
(FileName: 'amDynamite'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDynamite
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDynamite
(FileName: 'amHellish'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandHellish
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandHellish
(FileName: 'amMine'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMine
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMine
(FileName: 'amSeduction'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSeduction
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSeduction
(FileName: 'amVamp'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandVamp
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandVamp
(FileName: 'BigExplosion'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 385; Height: 385; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBigExplosion
+ Width: 385; Height: 385; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBigExplosion
(FileName: 'SmokeRing'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 200; Height: 200; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSmokeRing
+ Width: 200; Height: 200; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSmokeRing
(FileName: 'BeeTrace'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprBeeTrace
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprBeeTrace
(FileName: 'Egg'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprEgg
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprEgg
(FileName: 'TargetBee'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTargetBee
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTargetBee
(FileName: 'amBee'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBee
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBee
(FileName: 'Feather'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 15; Height: 25; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFeather
+ Width: 15; Height: 25; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFeather
(FileName: 'Piano'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPiano
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPiano
(FileName: 'amSineGun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSineGun
+ Width: 128; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSineGun
(FileName: 'amPortalGun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPortalGun
+ Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPortalGun
(FileName: 'Portal'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPortal
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPortal
(FileName: 'cheese'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCheese
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCheese
(FileName: 'amCheese'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCheese
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCheese
(FileName: 'amFlamethrower'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandFlamethrower
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandFlamethrower
(FileName: 'Chunk'; Path: ptCurrTheme; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprChunk
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: false; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprChunk
(FileName: 'Note'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprNote
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprNote
(FileName: 'SMineOff'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSMineOff
+ Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSMineOff
(FileName: 'SMineOn'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSMineOn
+ Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSMineOn
(FileName: 'amSMine'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSMine
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSMine
(FileName: 'amHammer'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true), // sprHammer
+ Width: 128; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true), // sprHammer
(FileName: 'amResurrector'; Path: ptHedgehog; AltPath: ptNone;
Texture: nil; Surface: nil; Width: 32; Height: 32;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
+ imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority:
tpMedium; getDimensions: false; getImageDimensions: true),
//sprHandResurrector
(FileName: 'Cross'; Path: ptGraphics; AltPath: ptNone;
Texture: nil; Surface: nil; Width: 108; Height: 138;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
+ imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority:
tpMedium; getDimensions: false; getImageDimensions: true),
//sprCross
(FileName: 'AirDrill'; Path: ptGraphics; AltPath: ptNone;
Texture: nil; Surface: nil; Width: 16; Height: 16;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
+ imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority:
tpMedium; getDimensions: false; getImageDimensions: true),
// sprAirDrill
(FileName: 'NapalmBomb'; Path: ptGraphics; AltPath: ptNone;
Texture: nil; Surface: nil; Width: 16; Height: 16;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
+ imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority:
tpMedium; getDimensions: false; getImageDimensions: true),
// sprNapalmBomb
(FileName: 'BulletHit'; Path: ptGraphics; AltPath: ptNone;
Texture: nil; Surface: nil; Width: 32; Height: 32;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
+ imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority:
tpMedium; getDimensions: false; getImageDimensions: true),
// sprNapalmBomb
(FileName: 'Snowball'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSnowball
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSnowball
(FileName: 'amSnowball'; Path: ptCurrTheme; AltPath: ptHedgehog; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSnowball
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSnowball
(FileName: 'Snow'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 4; Height: 4; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSnow
+ Width: 4; Height: 4; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSnow
(FileName: 'SDFlake'; Path: ptCurrTheme; AltPath: ptSuddenDeath; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSDFlake
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSDFlake
(FileName: 'SDWater'; Path: ptCurrTheme; AltPath: ptSuddenDeath; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: true; getImageDimensions: true),// sprSDWater
+ Width: 0; Height: -2; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: true; getImageDimensions: true),// sprSDWater
(FileName: 'SDClouds'; Path: ptCurrTheme; AltPath: ptSuddenDeath; Texture: nil; Surface: nil;
- Width: 256; Height:128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprSDCloud
+ Width: 256; Height:128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprSDCloud
(FileName: 'SDSplash'; Path: ptCurrTheme; AltPath: ptSuddenDeath; Texture: nil; Surface: nil;
- Width: 80; Height: 50; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSDSplash
+ Width: 80; Height: 50; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSDSplash
(FileName: 'SDDroplet'; Path: ptCurrTheme; AltPath: ptSuddenDeath; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSDDroplet
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSDDroplet
(FileName: 'Timebox'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 50; Height: 81; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprTardis
+ Width: 50; Height: 81; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprTardis
(FileName: 'slider'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 3; Height: 17; imageWidth: 3; imageHeight: 17; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprSlider
+ Width: 3; Height: 17; imageWidth: 3; imageHeight: 17; saveSurf: false; critical: true; checkSum: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprSlider
(FileName: 'botlevels'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 22; Height: 15; imageWidth: 22; imageHeight: 15; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprBotlevels
+ Width: 22; Height: 15; imageWidth: 22; imageHeight: 15; saveSurf: true; critical: true; checkSum: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprBotlevels
(FileName: 'amCleaver'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 64; imageHeight: 64; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: false),// sprHandKnife
+ Width: 64; Height: 64; imageWidth: 64; imageHeight: 64; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: false),// sprHandKnife
(FileName: 'cleaver'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 64; imageHeight: 128; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprKnife
+ Width: 64; Height: 64; imageWidth: 64; imageHeight: 128; saveSurf: false; critical: true; checkSum: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprKnife
(FileName: 'star'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 12; Height: 12; imageWidth: 12; imageHeight: 12; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprStar
+ Width: 12; Height: 12; imageWidth: 12; imageHeight: 12; saveSurf: false; critical: true; checkSum: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprStar
(FileName: 'icetexture'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 128; imageHeight: 128; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: true), // sprIceTexture
+ Width: 128; Height: 128; imageWidth: 128; imageHeight: 128; saveSurf: true; critical: true; checkSum: false; priority: tpLow; getDimensions: false; getImageDimensions: true), // sprIceTexture
(FileName: 'amIceGun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 32; imageHeight: 32; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprIceGun
+ Width: 32; Height: 32; imageWidth: 32; imageHeight: 32; saveSurf: false; critical: true; checkSum: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprIceGun
(FileName: 'amFrozenHog'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 64; imageHeight: 64; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprFrozenHog
+ Width: 64; Height: 64; imageWidth: 64; imageHeight: 64; saveSurf: false; critical: true; checkSum: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprFrozenHog
(FileName: 'amRubber'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 160; Height:160; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true), // sprAmRubber
+ Width: 160; Height:160; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: true; priority: tpMedium; getDimensions: false; getImageDimensions: true), // sprAmRubber
(FileName: 'boing'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 101; Height: 97; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprBoing
+ Width: 101; Height: 97; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprBoing
(FileName: 'custom1'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLow; getDimensions: true; getImageDimensions: true), // sprCustom1
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: true; priority: tpLow; getDimensions: true; getImageDimensions: true), // sprCustom1
(FileName: 'custom2'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLow; getDimensions: true; getImageDimensions: true), // sprCustom2
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: true; priority: tpLow; getDimensions: true; getImageDimensions: true), // sprCustom2
+ (FileName: 'custom3'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: true; priority: tpLow; getDimensions: true; getImageDimensions: true), // sprCustom3
+ (FileName: 'custom4'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: true; priority: tpLow; getDimensions: true; getImageDimensions: true), // sprCustom4
+ (FileName: 'custom5'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: true; priority: tpLow; getDimensions: true; getImageDimensions: true), // sprCustom5
+ (FileName: 'custom6'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: true; priority: tpLow; getDimensions: true; getImageDimensions: true), // sprCustom6
+ (FileName: 'custom7'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: true; priority: tpLow; getDimensions: true; getImageDimensions: true), // sprCustom7
+ (FileName: 'custom8'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: true; critical: true; checkSum: true; priority: tpLow; getDimensions: true; getImageDimensions: true), // sprCustom8
(FileName: 'AirMine'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true), // sprAirMine
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true), // sprAirMine
(FileName: 'amAirMine'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true) // sprHandAirMine
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true), // sprHandAirMine
+ (FileName: 'FlakeL'; Path:ptCurrTheme; AltPath: ptNone; Texture: nil; Surface: nil;
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: false; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFlakeL
+ (FileName: 'SDFlakeL'; Path: ptCurrTheme; AltPath: ptSuddenDeath; Texture: nil; Surface: nil;
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: false; checkSum: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSDFlakeL
+ (FileName: 'CloudsL'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
+ Width: 256; Height:128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: false; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprCloudL
+ (FileName: 'SDCloudsL'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
+ Width: 256; Height:128; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: false; checkSum: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprSDCloudL
+ (FileName: 'Duck'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDuck
+ (FileName: 'amDuck'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; critical: true; checkSum: false; priority: tpMedium; getDimensions: false; getImageDimensions: true) // sprHandDuck
);
const
@@ -782,7 +823,7 @@
AmmoType: amNothing;
AttackVoice: sndNone;
Bounciness: 1000);
- Slot: 0;
+ Slot: cHiddenSlotIndex;
TimeAfterTurn: 0;
minAngle: 0;
maxAngle: 0;
@@ -882,6 +923,7 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_Power or
ammoprop_NeedTarget or
+ ammoprop_NoTargetAfter or
ammoprop_DontHold or
ammoprop_NeedUpDown;
Count: 2;
@@ -936,7 +978,8 @@
Ammo: (Propz: ammoprop_ForwMsgs or
ammoprop_AttackInMove or
ammoprop_NoCrosshair or
- ammoprop_DontHold;
+ ammoprop_DontHold or
+ ammoprop_DoesntStopTimerWhileAttackingInInfAttackMode;
Count: 2;
NumPerTurn: 0;
Timer: 0;
@@ -962,7 +1005,8 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_NoCrosshair or
ammoprop_AttackInMove or
- ammoprop_DontHold;
+ ammoprop_DontHold or
+ ammoprop_ForceTurnEnd;
Count: AMMO_INFINITE;
NumPerTurn: 0;
Timer: 0;
@@ -1258,7 +1302,8 @@
Probability: 100;
NumberInCase: 2;
Ammo: (Propz: ammoprop_ForwMsgs or
- ammoprop_NeedUpDown;
+ ammoprop_NeedUpDown or
+ ammoprop_DoesntStopTimerWhileAttackingInInfAttackMode;
Count: 1;
NumPerTurn: 0;
Timer: 0;
@@ -1394,7 +1439,8 @@
Ammo: (Propz: ammoprop_ForwMsgs or
ammoprop_DontHold or
ammoprop_NeedUpDown or
- ammoprop_AttackInMove;
+ ammoprop_AttackInMove or
+ ammoprop_ForceTurnEnd;
Count: 1;
NumPerTurn: 0;
Timer: 0;
@@ -1946,9 +1992,11 @@
NumberInCase: 1;
Ammo: (Propz: ammoprop_NoCrosshair or
ammoprop_NeedTarget or
+ ammoprop_NoTargetAfter or
ammoprop_AttackingPut or
ammoprop_DontHold or
- ammoprop_NotBorder;
+ ammoprop_NotBorder or
+ ammoprop_ForceTurnEnd;
Count: 1;
NumPerTurn: 0;
Timer: 0;
@@ -2186,7 +2234,8 @@
Ammo: (Propz: ammoprop_ForwMsgs or
ammoprop_NoCrosshair or
ammoprop_Utility or
- ammoprop_DontHold;
+ ammoprop_DontHold or
+ ammoprop_ForceTurnEnd;
Count: 2;
NumPerTurn: 0;
Timer: 0;
@@ -2360,7 +2409,33 @@
PosCount: 1;
PosSprite: sprWater;
ejectX: 0;
- ejectY: 0)
+ ejectY: 0),
+// Rubber duck
+ (NameId: sidDuck;
+ NameTex: nil;
+ Probability: 100;
+ NumberInCase: 1;
+ Ammo: (Propz: ammoprop_NoCrosshair or
+ ammoprop_AttackInMove or
+ ammoprop_DontHold or
+ ammoprop_AltUse;
+ Count: 2;
+ NumPerTurn: 0;
+ Timer: 15000;
+ Pos: 0;
+ AmmoType: amDuck;
+ AttackVoice: sndNone;
+ Bounciness: 1000);
+ Slot: 0;
+ TimeAfterTurn: 3000;
+ minAngle: 0;
+ maxAngle: 0;
+ isDamaging: true;
+ SkipTurns: 0;
+ PosCount: 1;
+ PosSprite: sprWater;
+ ejectX: 15;
+ ejectY: -7)
);
var
@@ -2404,7 +2479,7 @@
bShowFinger: boolean;
Frames: Longword;
WaterColor, DeepWaterColor: TSDL_Color;
- SkyColor, RQSkyColor, SDSkyColor: TSDL_Color;
+ SDTint, SkyColor, RQSkyColor, SDSkyColor: TSDL_Color;
SkyOffset: LongInt;
{$IFDEF COUNTTICKS}
cntTicks: LongWord;
@@ -2435,6 +2510,10 @@
vobVelocity, vobFallSpeed: LongInt;
vobSDFrameTicks, vobSDFramesCount, vobSDCount: Longword;
vobSDVelocity, vobSDFallSpeed: LongInt;
+ watFrames, watFrameTicks: Longword;
+ watMove: LongInt;
+ watSDFrames, watSDFrameTicks: Longword;
+ watSDMove: LongInt;
DefaultBinds : TBinds;
@@ -2460,6 +2539,10 @@
var trammo: array[TAmmoStrId] of ansistring; // name of the weapon
trammoc: array[TAmmoStrId] of ansistring; // caption of the weapon
trammod: array[TAmmoStrId] of ansistring; // description of the weapon
+ trluaammo: array[TAmmoStrId] of ansistring; // name of the weapon (Lua overwrite)
+ trluaammoc: array[TAmmoStrId] of ansistring; // caption of the weapon (Lua overwrite)
+ trluaammod: array[TAmmoStrId] of ansistring; // description of the weapon (Lua overwrite)
+ trluaammoa: array[TAmmoStrId] of ansistring; // description appendix of the weapon (Lua only)
trmsg: array[TMsgStrId] of ansistring; // message of the event
trgoal: array[TGoalStrId] of ansistring; // message of the goal
cTestLua : Boolean;
@@ -2482,7 +2565,7 @@
cScreenHeight := cWindowedHeight;
cShowFPS := false;
- cAltDamage := true;
+ cAltDamage := false;
cTimerInterval := 8;
cReducedQuality := rqNone;
cLocaleFName := 'en.txt';
@@ -2565,6 +2648,25 @@
LAND_HEIGHT_MASK:= $FFFFF800
end;
+ // default water
+ WaterColorArray[0].r := 52;
+ WaterColorArray[0].g := 60;
+ WaterColorArray[0].b := 125;
+ WaterColorArray[0].a := 255;
+ WaterColorArray[2]:= WaterColorArray[0];
+ WaterColorArray[4]:= WaterColorArray[0];
+ WaterColorArray[6]:= WaterColorArray[0];
+ // water surface
+ WaterColorArray[1].r := 84;
+ WaterColorArray[1].g := 92;
+ WaterColorArray[1].b := 157;
+ WaterColorArray[1].a := 255;
+ WaterColorArray[3]:= WaterColorArray[1];
+ WaterColorArray[5]:= WaterColorArray[1];
+ WaterColorArray[7]:= WaterColorArray[1];
+
+ WaterOpacity:= $80;
+
// default sudden death water
// deep water
@@ -2586,7 +2688,11 @@
SDWaterOpacity:= $80;
- SDTint:= $80;
+ SDTint.r := $80;
+ SDTint.g := $80;
+ SDTint.b := $80;
+ SDTint.a := $FF;
+
ExplosionBorderColorR:= 80;
ExplosionBorderColorG:= 80;
ExplosionBorderColorB:= 80;
@@ -2606,6 +2712,7 @@
cElastic := _0_9;
cGravity := cMaxWindSpeed * 2;
cGravityf := 0.00025 * 2;
+ cLowGravity := false;
cBuildMaxDist := cDefaultBuildMaxDist;
cDamageModifier := _1;
TargetPoint := cTargetPointRef;
@@ -2636,6 +2743,8 @@
LeftImpactTimer := 0;
RightImpactTimer := 0;
TurnTimeLeft := 0;
+ IsGetAwayTime := false;
+ GameOver := false;
TurnClockActive := true;
TagTurnTimeLeft := 0;
cSuddenDTurns := 15;
@@ -2670,6 +2779,7 @@
ZoomValue := cDefaultZoomLevel;
WeaponTooltipTex:= nil;
cLaserSighting := false;
+ cLaserSightingSniper := false;
cVampiric := false;
cArtillery := false;
flagMakeCapture := false;
@@ -2708,12 +2818,18 @@
vobCount:= 0;
vobVelocity:= 10;
vobFallSpeed:= 100;
+ watFrames:= 1;
+ watFrameTicks:= 0;
+ watMove:= 100;
vobSDFrameTicks:= 0;
vobSDFramesCount:= 4;
vobSDCount:= 30 * cScreenSpace div LAND_WIDTH;
vobSDVelocity:= 15;
vobSDFallSpeed:= 250;
+ watSDFrames:= 1;
+ watSDFrameTicks:= 0;
+ watSDMove:= 100;
{$IFDEF MOBILE}
cMinScreenWidth := min(cScreenWidth, 480);
@@ -2737,9 +2853,13 @@
LuaGoals:= '';
cMapName:= '';
+ syncedPixelDigest:= 1;
LuaTemplateNumber:= 0;
+ LuaEndTurnRequested:= false;
+ LuaNoEndTurnTaunts:= false;
+
UIDisplay:= uiAll;
LocalMessage:= 0;
@@ -2768,6 +2888,9 @@
MissionIcons:= nil;
ropeIconTex:= nil;
+ SDLWindow:= nil;
+ SDLGLContext:= nil;
+
for i:= Low(ClansArray) to High(ClansArray) do
begin
ClansArray[i]:= nil;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uVideoRec.pas
--- a/hedgewars/uVideoRec.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uVideoRec.pas Sun Dec 17 00:09:24 2017 +0100
@@ -67,8 +67,7 @@
zoom: single;
end;
-var YCbCr_Planes: array[0..2] of PByte;
- RGB_Buffer: PByte;
+var RGB_Buffer: PByte;
cameraFile: File of TFrame;
audioFile: File;
numPixels: LongWord;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uVisualGears.pas
--- a/hedgewars/uVisualGears.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uVisualGears.pas Sun Dec 17 00:09:24 2017 +0100
@@ -125,6 +125,14 @@
exit(sprite);
end;
+function GetSpriteByWind(sprite, Lsprite: TSprite): TSprite; inline;
+begin
+ if (SpritesData[Lsprite].Texture <> nil) and (cWindSpeedf<0) then
+ exit(Lsprite)
+ else
+ exit(sprite);
+end;
+
function GetSpriteData(sprite, SDsprite: TSprite): PSpriteData; inline;
begin
exit(@SpritesData[GetSprite(sprite, SDsprite)]);
@@ -152,11 +160,11 @@
if Gear^.Tint <> $FFFFFFFF then Tint(Gear^.Tint);
case Gear^.Kind of
vgtCloud: begin
- spriteData:= GetSpriteData(sprCloud, sprSDCloud);
+ spriteData:= GetSpriteData(GetSpriteByWind(sprCloud, sprCloudL), GetSpriteByWind(sprSDCloud, sprSDCloudL));
DrawTextureF(spriteData^.Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, spriteData^.Width, spriteData^.Height)
end;
vgtFlake: begin
- sprite:= GetSprite(sprFlake, sprSDFlake);
+ sprite:= GetSpriteByWind(GetSprite(sprFlake, sprSDFlake), GetSprite(sprFlakeL, sprSDFlakeL));
if cFlattenFlakes then
begin
if speedlessFlakes then
@@ -188,7 +196,7 @@
Tint(Gear^.Tint);
case Gear^.Kind of
vgtFlake: begin
- sprite:= GetSprite(sprFlake, sprSDFlake);
+ sprite:= GetSpriteByWind(GetSprite(sprFlake, sprSDFlake), GetSprite(sprFlakeL, sprSDFlakeL));
if speedlessFlakes then
DrawSprite(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame)
else
@@ -331,7 +339,8 @@
tinted:= true;
Tint($FF, $FF, $FF, round(Gear^.alpha * $FF));
DrawTextureF(ropeIconTex, Gear^.scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 0, 1, 32, 32);
- DrawTextureF(SpritesData[sprAMAmmos].Texture, Gear^.scale * 0.90, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame - 1, 1, 32, 32);
+ if Gear^.Frame <> ord(amNothing) then
+ DrawTextureF(SpritesData[sprAMAmmos].Texture, Gear^.scale * 0.90, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame - 1, 1, 32, 32);
end;
vgtShell: begin
if Gear^.FrameTicks < $FF then
@@ -360,7 +369,7 @@
end;
case Gear^.Kind of
vgtFlake: begin
- spriteData:= GetSpriteData(sprFlake, sprSDFlake);
+ spriteData:= GetSpriteData(GetSpriteByWind(sprFlake, sprFlakeL), GetSpriteByWind(sprSDFlake, sprSDFlakeL));
if speedlessFlakes then
DrawTextureF(spriteData^.Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, spriteData^.Width, spriteData^.Height)
else
@@ -388,11 +397,11 @@
Tint(Gear^.Tint);
case Gear^.Kind of
vgtCloud: begin
- spriteData:= GetSpriteData(sprCloud, sprSDCloud);
+ spriteData:= GetSpriteData(GetSpriteByWind(sprCloud, sprCloudL), GetSpriteByWind(sprSDCloud, sprSDCloudL));
DrawTextureF(spriteData^.Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, spriteData^.Width, spriteData^.Height);
end;
vgtFlake: begin
- spriteData:= GetSpriteData(sprFlake, sprSDFlake);
+ spriteData:= GetSpriteData(GetSpriteByWind(sprFlake, sprFlakeL), GetSpriteByWind(sprSDFlake, sprSDFlakeL));
if speedlessFlakes then
DrawTextureF(spriteData^.Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, spriteData^.Width, spriteData^.Height)
else
@@ -413,11 +422,11 @@
Tint(Gear^.Tint);
case Gear^.Kind of
vgtCloud: begin
- sprite:= GetSprite(sprCloud, sprSDCloud);
+ sprite:= GetSpriteByWind(GetSprite(sprCloud, sprSDCloud), GetSprite(sprCloudL, sprSDCloudL));
DrawSprite(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame);
end;
vgtFlake: begin
- sprite:= GetSprite(sprFlake, sprSDFlake);
+ sprite:= GetSpriteByWind(GetSprite(sprFlake, sprSDFlake), GetSprite(sprFlakeL, sprSDFlakeL));
if speedlessFlakes then
DrawSprite(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame)
else
@@ -438,7 +447,7 @@
Tint(Gear^.Tint);
case Gear^.Kind of
vgtFlake: begin
- sprite:= GetSprite(sprFlake, sprSDFlake);
+ sprite:= GetSpriteByWind(GetSprite(sprFlake, sprSDFlake), GetSprite(sprFlakeL, sprSDFlakeL));
if speedlessFlakes then
DrawSprite(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame)
else
@@ -463,22 +472,25 @@
end;
procedure ChangeToSDClouds;
-var i: LongInt;
+var i, j: LongInt;
vg, tmp: PVisualGear;
begin
if cCloudsNumber = cSDCloudsNumber then
exit;
-vg:= VisualGearLayers[0];
-while vg <> nil do
- if vg^.Kind = vgtCloud then
- begin
- tmp:= vg^.NextGear;
- DeleteVisualGear(vg);
- vg:= tmp
- end
- else vg:= vg^.NextGear;
-for i:= 0 to cSDCloudsNumber - 1 do
- AddVisualGear(cLeftScreenBorder + i * LongInt(cScreenSpace div (cSDCloudsNumber + 1)), LAND_HEIGHT-1184, vgtCloud)
+for i:= 0 to 6 do
+ begin
+ vg:= VisualGearLayers[i];
+ while vg <> nil do
+ if vg^.Kind = vgtCloud then
+ begin
+ tmp:= vg^.NextGear;
+ DeleteVisualGear(vg);
+ vg:= tmp
+ end
+ else vg:= vg^.NextGear;
+ for j:= 0 to cSDCloudsNumber - 1 do
+ AddVisualGear(cLeftScreenBorder + j * LongInt(cScreenSpace div (cSDCloudsNumber + 1)), LAND_HEIGHT-1184, vgtCloud)
+ end;
end;
procedure AddFlakes;
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uVisualGearsHandlers.pas
--- a/hedgewars/uVisualGearsHandlers.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uVisualGearsHandlers.pas Sun Dec 17 00:09:24 2017 +0100
@@ -79,8 +79,11 @@
procedure doStepFlake(Gear: PVisualGear; Steps: Longword);
var sign: real;
- moved: boolean;
+ moved, rising, outside: boolean;
vfc, vft: LongWord;
+ spawnMargin: LongInt;
+const
+ randMargin = 50;
begin
if SuddenDeathDmg then
begin
@@ -162,28 +165,34 @@
X:= X - cScreenSpace;
moved:= true
end;
- // if round(Y) < (LAND_HEIGHT - 1024 - 75) then Y:= Y + 25.0; // For if flag is set for flakes rising upwards?
- if (Gear^.Layer = 2) and (round(Y) - 400 > LAND_HEIGHT) and (cGravityf >= 0) then
- begin
- X:= cLeftScreenBorder + random(cScreenSpace);
- Y:= Y-(1024 + 400 + random(50)); // TODO - configure in theme (jellies for example could use limited range)
- moved:= true
- end
- else if (Gear^.Layer <> 2) and (round(Y) - 150 > LAND_HEIGHT) and (cGravityf >= 0) then
+
+ // it's possible for flakes to move upwards
+ if SuddenDeathDmg then
+ rising:= (cGravityf * vobSDFallSpeed) < 0
+ else
+ rising:= (cGravityf * vobFallSpeed) < 0;
+
+ if gear^.layer = 2 then
+ spawnMargin:= 400
+ else
+ spawnMargin:= 200;
+
+ // flake fell far below map?
+ outside:= (not rising) and (round(Y) - spawnMargin + randMargin > LAND_HEIGHT);
+ // if not, did it rise far above map?
+ outside:= outside or (rising and (round(Y) < LAND_HEIGHT - 1024 - spawnMargin - randMargin));
+
+ // if flake left acceptable vertical area, respawn it opposite side
+ if outside then
begin
X:= cLeftScreenBorder + random(cScreenSpace);
- Y:= Y-(1024 + 200 + random(50));
- moved:= true
- end
- else if (round(Y) < LAND_HEIGHT-1200) and (cGravityf < 0) then // gravity can make flakes move upwards
- begin
- X:= cLeftScreenBorder + random(cScreenSpace);
- if Gear^.Layer = 2 then
- Y:= Y+(1024 + 150 + random(100))
+ if rising then
+ Y:= Y + (1024 + spawnMargin + random(50))
else
- Y:= Y+(1024 + random(50));
- moved:= true
+ Y:= Y - (1024 + spawnMargin + random(50));
+ moved:= true;
end;
+
if moved then
begin
Angle:= random(360);
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uVisualGearsList.pas
--- a/hedgewars/uVisualGearsList.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uVisualGearsList.pas Sun Dec 17 00:09:24 2017 +0100
@@ -36,7 +36,7 @@
VisualGearLayers: array[0..6] of PVisualGear;
implementation
-uses uCollisions, uFloat, uVariables, uConsts, uTextures, uVisualGearsHandlers;
+uses uCollisions, uFloat, uVariables, uConsts, uTextures, uVisualGearsHandlers, uScript;
function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType): PVisualGear; inline;
begin
@@ -230,8 +230,16 @@
end;
vgtDroplet:
begin
- dx:= 0.001 * (random(180) - 90);
- dy:= -0.001 * (random(160) + 40);
+ // old dx & dy calcs
+ // dx:= 0.001 * (random(180) - 90);
+ // dy:= -0.001 * (random(160) + 40);
+ // => min speed ~ 0.098, max speed ~ 0.218, speed range ~ 0.120
+ // => min angle(4096) ~ 129, max angle ~ 1919, angle range ~ 1790
+ dx:= 0.001 * (98 + random(121)); // speed
+ Frame:= 129 + random(1791); // angle
+ dy:= -dx * hwFloat2Float(AngleSin(Frame));
+ // divide by 2 to create an eliptic shape
+ dx:= dx * hwFloat2Float(AngleCos(Frame)) / 2;
FrameTicks:= 250 + random(1751);
Frame:= random(3)
end;
@@ -341,9 +349,8 @@
gear^.State:= State;
case Gear^.Kind of
- vgtFlake: if cFlattenFlakes then
- gear^.Layer:= 0
- else if random(3) = 0 then
+ vgtFlake:
+ if random(3) = 0 then
begin
gear^.Scale:= 0.5;
gear^.Layer:= 0 // 33% - far back
@@ -355,13 +362,17 @@
end
else if random(3) <> 0 then
gear^.Layer:= 5 // 30% - just behind land
- else if random(2) = 0 then
+ else if (not cFlattenFlakes) and (random(2) = 0) then
gear^.Layer:= 6 // 7% - just in front of land
- else
+ else if not cFlattenFlakes then
begin
gear^.Scale:= 1.5;
- gear^.Layer:= 2; // 7% - close up
- end;
+ gear^.Layer:= 2 // 7% - close up
+ end
+ else begin
+ gear^.Layer:= 0;
+ gear^.Scale:= 0.5
+ end;
vgtCloud: if cFlattenClouds then gear^.Layer:= 5
else if random(3) = 0 then
@@ -429,10 +440,12 @@
VisualGearLayers[gear^.Layer]:= gear;
AddVisualGear:= gear;
+ScriptCall('onVisualGearAdd', gear^.uid);
end;
procedure DeleteVisualGear(Gear: PVisualGear);
begin
+ ScriptCall('onVisualGearDelete', Gear^.uid);
FreeAndNilTexture(Gear^.Tex);
if Gear^.NextGear <> nil then
diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uWorld.pas
--- a/hedgewars/uWorld.pas Thu Aug 11 23:05:14 2016 +0300
+++ b/hedgewars/uWorld.pas Sun Dec 17 00:09:24 2017 +0100
@@ -32,6 +32,7 @@
procedure DrawWorldStereo(Lag: LongInt; RM: TRenderMode);
procedure ShowMission(caption, subcaption, text: ansistring; icon, time : LongInt);
procedure HideMission;
+procedure SetAmmoTexts(ammoType: TAmmoType; name: ansistring; caption: ansistring; description: ansistring);
procedure ShakeCamera(amount: LongInt);
procedure InitCameraBorders;
procedure InitTouchInterface;
@@ -60,6 +61,7 @@
, uCursor
, uCommands
, uTeams
+ , uDebug
{$IFDEF USE_VIDEO_RECORDING}
, uVideoRec
{$ENDIF}
@@ -169,28 +171,28 @@
g:= ''; // no text/things to note yet
// add custom goals from lua script if there are any
-if LuaGoals <> '' then
+if LuaGoals <> ansistring('') then
g:= LuaGoals + '|';
-// check different game flags (goals/game modes first for now)
+// check different game flags
+g:= AddGoal(g, gfPlaceHog, gidPlaceHog); // placement?
g:= AddGoal(g, gfKing, gidKing); // king?
+if ((GameFlags and gfKing) <> 0) and ((GameFlags and gfPlaceHog) = 0) then
+ g:= AddGoal(g, gfAny, gidPlaceKing);
g:= AddGoal(g, gfTagTeam, gidTagTeam); // tag team mode?
-
-// other important flags
-g:= AddGoal(g, gfForts, gidForts); // forts?
+g:= AddGoal(g, gfSharedAmmo, gidSharedAmmo); // shared ammo?
+g:= AddGoal(g, gfPerHogAmmo, gidPerHogAmmo);
+g:= AddGoal(g, gfMoreWind, gidMoreWind);
g:= AddGoal(g, gfLowGravity, gidLowGravity); // low gravity?
-g:= AddGoal(g, gfInvulnerable, gidInvulnerable); // invulnerability?
-g:= AddGoal(g, gfVampiric, gidVampiric); // vampirism?
-g:= AddGoal(g, gfKarma, gidKarma); // karma?
-g:= AddGoal(g, gfPlaceHog, gidPlaceHog); // placement?
+g:= AddGoal(g, gfSolidLand, gidSolidLand); // solid land?
g:= AddGoal(g, gfArtillery, gidArtillery); // artillery?
-g:= AddGoal(g, gfSolidLand, gidSolidLand); // solid land?
-g:= AddGoal(g, gfSharedAmmo, gidSharedAmmo); // shared ammo?
-g:= AddGoal(g, gfResetHealth, gidResetHealth);
-g:= AddGoal(g, gfAISurvival, gidAISurvival);
g:= AddGoal(g, gfInfAttack, gidInfAttack);
g:= AddGoal(g, gfResetWeps, gidResetWeps);
-g:= AddGoal(g, gfPerHogAmmo, gidPerHogAmmo);
+g:= AddGoal(g, gfResetHealth, gidResetHealth);
+g:= AddGoal(g, gfKarma, gidKarma); // karma?
+g:= AddGoal(g, gfVampiric, gidVampiric); // vampirism?
+g:= AddGoal(g, gfInvulnerable, gidInvulnerable); // invulnerability?
+g:= AddGoal(g, gfAISurvival, gidAISurvival);
// modified damage modificator?
if cDamagePercent <> 100 then
@@ -422,7 +424,7 @@
SlotsNum:= 0;
for i:= 0 to cMaxSlotIndex do
- if((i = 0) and (Ammo^[i,1].Count > 0)) or ((i <> 0) and (Ammo^[i,0].Count > 0)) then
+ if (i <> cHiddenSlotIndex) and (Ammo^[i, 0].Count > 0) then
inc(SlotsNum);
{$IFDEF USE_LANDSCAPE_AMMOMENU}
SlotsNumX:= SlotsNum;
@@ -453,7 +455,7 @@
x:= AMRect.x;
y:= AMRect.y;
for i:= 0 to cMaxSlotIndex do
- if ((i = 0) and (Ammo^[i, 1].Count > 0)) or ((i <> 0) and (Ammo^[i, 0].Count > 0)) then
+ if (i <> cHiddenSlotIndex) and (Ammo^[i, 0].Count > 0) then
begin
{$IFDEF USE_LANDSCAPE_AMMOMENU}
y:= AMRect.y;
@@ -660,7 +662,7 @@
{$IFDEF USE_LANDSCAPE_AMMOMENU}
c:= -1;
for i:= 0 to cMaxSlotIndex do
- if ((i = 0) and (Ammo^[i, 1].Count > 0)) or ((i <> 0) and (Ammo^[i, 0].Count > 0)) then
+ if (i <> cHiddenSlotIndex) and (Ammo^[i, 0].Count > 0) then
begin
inc(c);
{$IFDEF USE_AM_NUMCOLUMN}
@@ -690,7 +692,7 @@
{$ELSE}
c:= -1;
for i:= 0 to cMaxSlotIndex do
- if ((i = 0) and (Ammo^[i, 1].Count > 0)) or ((i <> 0) and (Ammo^[i, 0].Count > 0)) then
+ if (i <> cHiddenSlotIndex) and (Ammo^[i, 0].Count > 0) then
begin
inc(c);
{$IFDEF USE_AM_NUMCOLUMN}
@@ -718,7 +720,7 @@
end;
end;
{$ENDIF}
- if (Pos >= 0) and (Pos <= cMaxSlotAmmoIndex) and (Slot >= 0) and (Slot <= cMaxSlotIndex)then
+ if (Pos >= 0) and (Pos <= cMaxSlotAmmoIndex) and (Slot >= 0) and (Slot <= cMaxSlotIndex) and (Slot <> cHiddenSlotIndex) then
begin
if (AMShiftX = 0) and (AMShiftY = 0) then
if (Ammo^[Slot, Pos].Count > 0) and (Ammo^[Slot, Pos].AmmoType <> amNothing) then
@@ -1025,7 +1027,7 @@
procedure RenderTeamsHealth;
-var t, i, h, smallScreenOffset, TeamHealthBarWidth : LongInt;
+var t, i, h, smallScreenOffset, TeamHealthBarWidth : LongInt;
r: TSDL_Rect;
highlight: boolean;
htex: PTexture;
@@ -1159,12 +1161,15 @@
procedure DrawWorldStereo(Lag: LongInt; RM: TRenderMode);
var i, t: LongInt;
+ spr: TSprite;
r: TSDL_Rect;
tdx, tdy: Double;
s: shortstring;
offsetX, offsetY, screenBottom: LongInt;
replicateToLeft, replicateToRight, tmp: boolean;
+{$IFDEF USE_VIDEO_RECORDING}
a: Byte;
+{$ENDIF}
begin
if WorldEdge <> weWrap then
begin
@@ -1193,7 +1198,7 @@
// background
ChangeDepth(RM, cStereo_Sky);
if SuddenDeathDmg then
- Tint(SDTint, SDTint, SDTint, $FF);
+ Tint(SDTint.r, SDTint.g, SDTint.b, SDTint.a);
DrawRepeated(sprSky, sprSkyL, sprSkyR, (WorldDx + LAND_WIDTH div 2) * 3 div 8, SkyOffset);
ChangeDepth(RM, -cStereo_Horizon);
DrawRepeated(sprHorizont, sprHorizontL, sprHorizontR, (WorldDx + LAND_WIDTH div 2) * 3 div 5, HorizontOffset);
@@ -1323,6 +1328,8 @@
else
DrawWaves(-1, 50, cWaveHeight div 2, cWaveHeight div 2, 0);
+DrawGearsTimers;
+
// everything after this ChangeDepth will be drawn outside the screen
// note: negative parallax gears should last very little for a smooth stereo effect
ChangeDepth(RM, cStereo_Outside);
@@ -1424,7 +1431,7 @@
offsetX:= 48;
{$ENDIF}
offsetY:= cOffsetY;
- if ((TurnTimeLeft <> 0) and (TurnTimeLeft < 1000000)) or (ReadyTimeLeft <> 0) then
+ if ((TurnTimeLeft <> 0) and (TurnTimeLeft < 999000)) or (ReadyTimeLeft <> 0) then
begin
if ReadyTimeLeft <> 0 then
i:= Succ(Pred(ReadyTimeLeft) div 1000)
@@ -1441,7 +1448,15 @@
while i > 0 do
begin
dec(t, 32);
- DrawSprite(sprBigDigit, -(cScreenWidth shr 1) + t + offsetY, cScreenHeight - offsetX, i mod 10);
+ if isPaused or (not IsClockRunning()) then
+ spr := sprBigDigitGray
+ else if (ReadyTimeLeft <> 0) then
+ spr := sprBigDigitGreen
+ else if IsGetAwayTime then
+ spr := sprBigDigitRed
+ else
+ spr := sprBigDigit;
+ DrawSprite(spr, -(cScreenWidth shr 1) + t + offsetY, cScreenHeight - offsetX, i mod 10);
i:= i div 10
end;
DrawSprite(sprFrame, -(cScreenWidth shr 1) + t - 4 + offsetY, cScreenHeight - offsetX, 0);
@@ -1506,6 +1521,28 @@
end
end;
+{$IFNDEF USE_TOUCH_INTERFACE}
+// Indicators for global effects (extra damage, low gravity)
+// TODO: Add support for touch interface (need to find out correct offset)
+if UIDisplay <> uiNone then
+ begin
+ offsetX:= 45;
+ offsetY:= 51;
+
+ if cDamageModifier = _1_5 then
+ begin
+ DrawTextureF(ropeIconTex, 1, (cScreenWidth shr 1) - offsetX, cScreenHeight - offsetY, 0, 1, 32, 32);
+ DrawTextureF(SpritesData[sprAMAmmos].Texture, 0.90, (cScreenWidth shr 1) - offsetX, cScreenHeight - offsetY, ord(amExtraDamage) - 1, 1, 32, 32);
+ offsetX := offsetX + 33
+ end;
+ if (cLowGravity) or ((GameFlags and gfLowGravity) <> 0) then
+ begin
+ DrawTextureF(ropeIconTex, 1, (cScreenWidth shr 1) - offsetX, cScreenHeight - offsetY, 0, 1, 32, 32);
+ DrawTextureF(SpritesData[sprAMAmmos].Texture, 0.90, (cScreenWidth shr 1) - offsetX, cScreenHeight - offsetY, ord(amLowGravity) - 1, 1, 32, 32);
+ end;
+ end;
+{$ENDIF}
+
// AmmoMenu
if bShowAmmoMenu and ((AMState = AMHidden) or (AMState = AMHiding)) then
begin
@@ -1917,6 +1954,33 @@
missionTimer:= 0;
end;
+procedure SetAmmoTexts(ammoType: TAmmoType; name: ansistring; caption: ansistring; description: ansistring);
+var
+ ammoStrId: TAmmoStrId;
+ ammoStr: ansistring;
+ tmpsurf: PSDL_Surface;
+begin
+ ammoStrId := Ammoz[ammoType].NameId;
+
+ trluaammo[ammoStrId] := name;
+ if length(trluaammo[ammoStrId]) > 0 then
+ ammoStr:= trluaammo[ammoStrId]
+ else
+ ammoStr:= trammo[ammoStrId];
+
+ if checkFails(length(ammoStr) > 0,'No default text/translation found for ammo type #' + intToStr(ord(ammoType)) + '!',true) then exit;
+
+ tmpsurf:= TTF_RenderUTF8_Blended(Fontz[CheckCJKFont(ammoStr,fnt16)].Handle, PChar(ammoStr), cWhiteColorChannels);
+ if checkFails(tmpsurf <> nil,'Name-texture creation for ammo type #' + intToStr(ord(ammoType)) + ' failed!',true) then exit;
+ tmpsurf:= doSurfaceConversion(tmpsurf);
+ FreeAndNilTexture(Ammoz[ammoType].NameTex);
+ Ammoz[ammoType].NameTex:= Surface2Tex(tmpsurf, false);
+ SDL_FreeSurface(tmpsurf);
+
+ trluaammoc[ammoStrId] := caption;
+ trluaammod[ammoStrId] := description;
+end;
+
procedure ShakeCamera(amount: LongInt);
begin
if isCursorVisible then
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/hats_js_anim.xhtml
--- a/misc/hats_js_anim.xhtml Thu Aug 11 23:05:14 2016 +0300
+++ b/misc/hats_js_anim.xhtml Sun Dec 17 00:09:24 2017 +0100
@@ -8,7 +8,7 @@
* {padding: 0; margin: 0; }
body
{
- background: url('http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Themes/Nature/Sky.png') fixed no-repeat bottom left;
+ background: url('//hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Themes/Nature/Sky.png') fixed no-repeat bottom left;
-moz-background-size: 200%;
background-size: 100% 100%;
font-family: sans-serif;
@@ -22,14 +22,14 @@
height: 32px;
width: 32px;
color: transparent;
- background-image: url("http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Graphics/Hedgehog/Idle.png");
+ background-image: url("//hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Graphics/Hedgehog/Idle.png");
}
.girder
{
width: 100%;
height: 30px;
clear: left;
- background-image: url('http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Themes/Nature/Girder.png');
+ background-image: url('//hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Themes/Nature/Girder.png');
background-repeat: repeat-x;
}
.hide { visibility: hidden; }
@@ -82,7 +82,7 @@
window.onload = function()
{
var xml=new XMLHttpRequest();
- xml.open("GET", "/hg/share/hedgewars/Data/Graphics/Hats/", false);
+ xml.open("GET", "/hedgewars/file/tip/share/hedgewars/Data/Graphics/Hats/", false);
xml.send(null);
/*var resp = xml.responseXML; unfortunately not served as XHTML
var a = resp.getElementsByTagName("a");
@@ -126,7 +126,7 @@
for (var i=0;i
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/archiver_dir.c
--- a/misc/libphysfs/archiver_dir.c Thu Aug 11 23:05:14 2016 +0300
+++ b/misc/libphysfs/archiver_dir.c Sun Dec 17 00:09:24 2017 +0100
@@ -43,10 +43,9 @@
char *retval = NULL;
const size_t namelen = strlen(name);
const size_t seplen = 1;
- int exists = 0;
assert(io == NULL); /* shouldn't create an Io for these. */
- BAIL_IF_MACRO(!__PHYSFS_platformStat(name, &exists, &st), ERRPASS, NULL);
+ BAIL_IF_MACRO(!__PHYSFS_platformStat(name, &st), ERRPASS, NULL);
if (st.filetype != PHYSFS_FILETYPE_DIRECTORY)
BAIL_MACRO(PHYSFS_ERR_UNSUPPORTED, NULL);
@@ -66,8 +65,8 @@
} /* DIR_openArchive */
-static void DIR_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
- int omitSymLinks, PHYSFS_EnumFilesCallback cb,
+static void DIR_enumerateFiles(void *opaque, const char *dname,
+ PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
char *d;
@@ -75,38 +74,28 @@
CVT_TO_DEPENDENT(d, opaque, dname);
if (d != NULL)
{
- __PHYSFS_platformEnumerateFiles(d, omitSymLinks, cb,
- origdir, callbackdata);
+ __PHYSFS_platformEnumerateFiles(d, cb, origdir, callbackdata);
__PHYSFS_smallFree(d);
} /* if */
} /* DIR_enumerateFiles */
-static PHYSFS_Io *doOpen(PHYSFS_Dir *opaque, const char *name,
- const int mode, int *fileExists)
+static PHYSFS_Io *doOpen(void *opaque, const char *name, const int mode)
{
- char *f;
PHYSFS_Io *io = NULL;
- int existtmp = 0;
+ char *f = NULL;
CVT_TO_DEPENDENT(f, opaque, name);
BAIL_IF_MACRO(!f, ERRPASS, NULL);
- if (fileExists == NULL)
- fileExists = &existtmp;
-
io = __PHYSFS_createNativeIo(f, mode);
if (io == NULL)
{
const PHYSFS_ErrorCode err = PHYSFS_getLastErrorCode();
PHYSFS_Stat statbuf;
- __PHYSFS_platformStat(f, fileExists, &statbuf);
- __PHYSFS_setError(err);
+ __PHYSFS_platformStat(f, &statbuf);
+ PHYSFS_setErrorCode(err);
} /* if */
- else
- {
- *fileExists = 1;
- } /* else */
__PHYSFS_smallFree(f);
@@ -114,25 +103,25 @@
} /* doOpen */
-static PHYSFS_Io *DIR_openRead(PHYSFS_Dir *opaque, const char *fnm, int *exist)
+static PHYSFS_Io *DIR_openRead(void *opaque, const char *filename)
{
- return doOpen(opaque, fnm, 'r', exist);
+ return doOpen(opaque, filename, 'r');
} /* DIR_openRead */
-static PHYSFS_Io *DIR_openWrite(PHYSFS_Dir *opaque, const char *filename)
+static PHYSFS_Io *DIR_openWrite(void *opaque, const char *filename)
{
- return doOpen(opaque, filename, 'w', NULL);
+ return doOpen(opaque, filename, 'w');
} /* DIR_openWrite */
-static PHYSFS_Io *DIR_openAppend(PHYSFS_Dir *opaque, const char *filename)
+static PHYSFS_Io *DIR_openAppend(void *opaque, const char *filename)
{
- return doOpen(opaque, filename, 'a', NULL);
+ return doOpen(opaque, filename, 'a');
} /* DIR_openAppend */
-static int DIR_remove(PHYSFS_Dir *opaque, const char *name)
+static int DIR_remove(void *opaque, const char *name)
{
int retval;
char *f;
@@ -145,7 +134,7 @@
} /* DIR_remove */
-static int DIR_mkdir(PHYSFS_Dir *opaque, const char *name)
+static int DIR_mkdir(void *opaque, const char *name)
{
int retval;
char *f;
@@ -158,21 +147,20 @@
} /* DIR_mkdir */
-static void DIR_closeArchive(PHYSFS_Dir *opaque)
+static void DIR_closeArchive(void *opaque)
{
allocator.Free(opaque);
} /* DIR_closeArchive */
-static int DIR_stat(PHYSFS_Dir *opaque, const char *name,
- int *exists, PHYSFS_Stat *stat)
+static int DIR_stat(void *opaque, const char *name, PHYSFS_Stat *stat)
{
int retval = 0;
char *d;
CVT_TO_DEPENDENT(d, opaque, name);
BAIL_IF_MACRO(!d, ERRPASS, 0);
- retval = __PHYSFS_platformStat(d, exists, stat);
+ retval = __PHYSFS_platformStat(d, stat);
__PHYSFS_smallFree(d);
return retval;
} /* DIR_stat */
@@ -180,22 +168,24 @@
const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"",
"Non-archive, direct filesystem I/O",
"Ryan C. Gordon ",
- "http://icculus.org/physfs/",
+ "https://icculus.org/physfs/",
+ 1, /* supportsSymlinks */
},
- DIR_openArchive, /* openArchive() method */
- DIR_enumerateFiles, /* enumerateFiles() method */
- DIR_openRead, /* openRead() method */
- DIR_openWrite, /* openWrite() method */
- DIR_openAppend, /* openAppend() method */
- DIR_remove, /* remove() method */
- DIR_mkdir, /* mkdir() method */
- DIR_closeArchive, /* closeArchive() method */
- DIR_stat /* stat() method */
+ DIR_openArchive,
+ DIR_enumerateFiles,
+ DIR_openRead,
+ DIR_openWrite,
+ DIR_openAppend,
+ DIR_remove,
+ DIR_mkdir,
+ DIR_stat,
+ DIR_closeArchive
};
-/* end of dir.c ... */
+/* end of archiver_dir.c ... */
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/archiver_grp.c
--- a/misc/libphysfs/archiver_grp.c Thu Aug 11 23:05:14 2016 +0300
+++ b/misc/libphysfs/archiver_grp.c Sun Dec 17 00:09:24 2017 +0100
@@ -87,24 +87,26 @@
const PHYSFS_Archiver __PHYSFS_Archiver_GRP =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"GRP",
"Build engine Groupfile format",
"Ryan C. Gordon ",
- "http://icculus.org/physfs/",
+ "https://icculus.org/physfs/",
+ 0, /* supportsSymlinks */
},
- GRP_openArchive, /* openArchive() method */
- UNPK_enumerateFiles, /* enumerateFiles() method */
- UNPK_openRead, /* openRead() method */
- UNPK_openWrite, /* openWrite() method */
- UNPK_openAppend, /* openAppend() method */
- UNPK_remove, /* remove() method */
- UNPK_mkdir, /* mkdir() method */
- UNPK_closeArchive, /* closeArchive() method */
- UNPK_stat /* stat() method */
+ GRP_openArchive,
+ UNPK_enumerateFiles,
+ UNPK_openRead,
+ UNPK_openWrite,
+ UNPK_openAppend,
+ UNPK_remove,
+ UNPK_mkdir,
+ UNPK_stat,
+ UNPK_closeArchive
};
#endif /* defined PHYSFS_SUPPORTS_GRP */
-/* end of grp.c ... */
+/* end of archiver_grp.c ... */
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/archiver_hog.c
--- a/misc/libphysfs/archiver_hog.c Thu Aug 11 23:05:14 2016 +0300
+++ b/misc/libphysfs/archiver_hog.c Sun Dec 17 00:09:24 2017 +0100
@@ -93,24 +93,26 @@
const PHYSFS_Archiver __PHYSFS_Archiver_HOG =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"HOG",
"Descent I/II HOG file format",
"Bradley Bell ",
- "http://icculus.org/physfs/",
+ "https://icculus.org/physfs/",
+ 0, /* supportsSymlinks */
},
- HOG_openArchive, /* openArchive() method */
- UNPK_enumerateFiles, /* enumerateFiles() method */
- UNPK_openRead, /* openRead() method */
- UNPK_openWrite, /* openWrite() method */
- UNPK_openAppend, /* openAppend() method */
- UNPK_remove, /* remove() method */
- UNPK_mkdir, /* mkdir() method */
- UNPK_closeArchive, /* closeArchive() method */
- UNPK_stat /* stat() method */
+ HOG_openArchive,
+ UNPK_enumerateFiles,
+ UNPK_openRead,
+ UNPK_openWrite,
+ UNPK_openAppend,
+ UNPK_remove,
+ UNPK_mkdir,
+ UNPK_stat,
+ UNPK_closeArchive
};
#endif /* defined PHYSFS_SUPPORTS_HOG */
-/* end of hog.c ... */
+/* end of archiver_hog.c ... */
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/archiver_iso9660.c
--- a/misc/libphysfs/archiver_iso9660.c Thu Aug 11 23:05:14 2016 +0300
+++ b/misc/libphysfs/archiver_iso9660.c Sun Dec 17 00:09:24 2017 +0100
@@ -291,8 +291,8 @@
for(;pos < descriptor->filenamelen; pos++)
if (descriptor->filename[pos] == ';')
lastfound = pos;
- BAIL_IF_MACRO(lastfound < 1, PHYSFS_ERR_NO_SUCH_PATH /* !!! FIXME: PHYSFS_ERR_BAD_FILENAME */, -1);
- BAIL_IF_MACRO(lastfound == (descriptor->filenamelen -1), PHYSFS_ERR_NO_SUCH_PATH /* !!! PHYSFS_ERR_BAD_FILENAME */, -1);
+ BAIL_IF_MACRO(lastfound < 1, PHYSFS_ERR_NOT_FOUND /* !!! FIXME: PHYSFS_ERR_BAD_FILENAME */, -1);
+ BAIL_IF_MACRO(lastfound == (descriptor->filenamelen -1), PHYSFS_ERR_NOT_FOUND /* !!! PHYSFS_ERR_BAD_FILENAME */, -1);
strncpy(filename, descriptor->filename, lastfound);
if (filename[lastfound - 1] == '.')
filename[lastfound - 1] = '\0'; /* consume trailing ., as done in all implementations */
@@ -398,7 +398,7 @@
* a file needs to branch to the directory extent sooner or later.
*/
static int iso_find_dir_entry(ISO9660Handle *handle,const char *path,
- ISO9660FileDescriptor *descriptor, int *exists)
+ ISO9660FileDescriptor *descriptor)
{
char *subpath = 0;
PHYSFS_uint64 readpos, end_of_dir;
@@ -409,7 +409,6 @@
strcpy(pathcopy, path);
mypath = pathcopy;
- *exists = 0;
readpos = handle->rootdirstart;
end_of_dir = handle->rootdirstart + handle->rootdirsize;
@@ -442,10 +441,7 @@
if (strcmp(filename, mypath) == 0)
{
if ( (subpath == 0) || (subpath[0] == 0) )
- {
- *exists = 1;
return 0; /* no subpaths left and we found the entry */
- } /* if */
if (descriptor->flags.directory)
{
@@ -458,12 +454,14 @@
} /* if */
else
{
+ /* !!! FIXME: set PHYSFS_ERR_NOT_FOUND? */
/* we're at a file but have a remaining subpath -> no match */
return 0;
} /* else */
} /* if */
} /* while */
+ /* !!! FIXME: set PHYSFS_ERR_NOT_FOUND? */
return 0;
} /* iso_find_dir_entry */
@@ -555,7 +553,7 @@
/* Skip system area to magic number in Volume descriptor */
BAIL_IF_MACRO(!io->seek(io, 32769), ERRPASS, NULL);
- BAIL_IF_MACRO(!io->read(io, magicnumber, 5) != 5, ERRPASS, NULL);
+ BAIL_IF_MACRO(io->read(io, magicnumber, 5) != 5, ERRPASS, NULL);
if (memcmp(magicnumber, "CD001", 6) != 0)
BAIL_MACRO(PHYSFS_ERR_UNSUPPORTED, NULL);
@@ -638,7 +636,7 @@
} /* ISO9660_openArchive */
-static void ISO9660_closeArchive(PHYSFS_Dir *opaque)
+static void ISO9660_closeArchive(void *opaque)
{
ISO9660Handle *handle = (ISO9660Handle*) opaque;
handle->io->destroy(handle->io);
@@ -766,8 +764,7 @@
} /* iso_file_open_foreign */
-static PHYSFS_Io *ISO9660_openRead(PHYSFS_Dir *opaque, const char *filename,
- int *exists)
+static PHYSFS_Io *ISO9660_openRead(void *opaque, const char *filename)
{
PHYSFS_Io *retval = NULL;
ISO9660Handle *handle = (ISO9660Handle*) opaque;
@@ -783,9 +780,8 @@
GOTO_IF_MACRO(retval == 0, PHYSFS_ERR_OUT_OF_MEMORY, errorhandling);
/* find file descriptor */
- rc = iso_find_dir_entry(handle, filename, &descriptor, exists);
+ rc = iso_find_dir_entry(handle, filename, &descriptor);
GOTO_IF_MACRO(rc, ERRPASS, errorhandling);
- GOTO_IF_MACRO(!*exists, PHYSFS_ERR_NO_SUCH_PATH, errorhandling);
fhandle->startblock = descriptor.extentpos + descriptor.extattributelen;
fhandle->filesize = descriptor.datalen;
@@ -816,8 +812,7 @@
* Information gathering functions
******************************************************************************/
-static void ISO9660_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
- int omitSymLinks,
+static void ISO9660_enumerateFiles(void *opaque, const char *dname,
PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
@@ -836,9 +831,7 @@
else
{
printf("pfad %s\n",dname);
- int exists = 0;
- BAIL_IF_MACRO(iso_find_dir_entry(handle,dname, &descriptor, &exists), ERRPASS,);
- BAIL_IF_MACRO(!exists, ERRPASS, );
+ BAIL_IF_MACRO(iso_find_dir_entry(handle,dname, &descriptor), ERRPASS,);
BAIL_IF_MACRO(!descriptor.flags.directory, ERRPASS,);
readpos = descriptor.extentpos * 2048;
@@ -873,15 +866,12 @@
} /* ISO9660_enumerateFiles */
-static int ISO9660_stat(PHYSFS_Dir *opaque, const char *name, int *exists,
- PHYSFS_Stat *stat)
+static int ISO9660_stat(void *opaque, const char *name, PHYSFS_Stat *stat)
{
ISO9660Handle *handle = (ISO9660Handle*) opaque;
ISO9660FileDescriptor descriptor;
ISO9660ExtAttributeRec extattr;
- BAIL_IF_MACRO(iso_find_dir_entry(handle, name, &descriptor, exists), ERRPASS, -1);
- if (!*exists)
- return 0;
+ BAIL_IF_MACRO(iso_find_dir_entry(handle, name, &descriptor), ERRPASS, -1);
stat->readonly = 1;
@@ -920,25 +910,25 @@
* Not supported functions
******************************************************************************/
-static PHYSFS_Io *ISO9660_openWrite(PHYSFS_Dir *opaque, const char *name)
+static PHYSFS_Io *ISO9660_openWrite(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* ISO9660_openWrite */
-static PHYSFS_Io *ISO9660_openAppend(PHYSFS_Dir *opaque, const char *name)
+static PHYSFS_Io *ISO9660_openAppend(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* ISO9660_openAppend */
-static int ISO9660_remove(PHYSFS_Dir *opaque, const char *name)
+static int ISO9660_remove(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* ISO9660_remove */
-static int ISO9660_mkdir(PHYSFS_Dir *opaque, const char *name)
+static int ISO9660_mkdir(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* ISO9660_mkdir */
@@ -946,21 +936,23 @@
const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660 =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"ISO",
"ISO9660 image file",
"Christoph Nelles ",
- "http://www.evilazrael.de/",
+ "https://www.evilazrael.de/",
+ 0, /* supportsSymlinks */
},
- ISO9660_openArchive, /* openArchive() method */
- ISO9660_enumerateFiles, /* enumerateFiles() method */
- ISO9660_openRead, /* openRead() method */
- ISO9660_openWrite, /* openWrite() method */
- ISO9660_openAppend, /* openAppend() method */
- ISO9660_remove, /* remove() method */
- ISO9660_mkdir, /* mkdir() method */
- ISO9660_closeArchive, /* closeArchive() method */
- ISO9660_stat /* stat() method */
+ ISO9660_openArchive,
+ ISO9660_enumerateFiles,
+ ISO9660_openRead,
+ ISO9660_openWrite,
+ ISO9660_openAppend,
+ ISO9660_remove,
+ ISO9660_mkdir,
+ ISO9660_stat,
+ ISO9660_closeArchive
};
#endif /* defined PHYSFS_SUPPORTS_ISO9660 */
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/archiver_lzma.c
--- a/misc/libphysfs/archiver_lzma.c Thu Aug 11 23:05:14 2016 +0300
+++ b/misc/libphysfs/archiver_lzma.c Sun Dec 17 00:09:24 2017 +0100
@@ -124,7 +124,7 @@
SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size,
size_t *processedSize)
{
- FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); /* HACK! */
+ FileInputStream *s = (FileInputStream *)((size_t)object - offsetof(FileInputStream, inStream)); /* HACK! */
const size_t processedSizeLoc = s->io->read(s->io, buffer, size);
if (processedSize != NULL)
*processedSize = processedSizeLoc;
@@ -139,7 +139,7 @@
*/
SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
{
- FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); /* HACK! */
+ FileInputStream *s = (FileInputStream *)((size_t)object - offsetof(FileInputStream, inStream)); /* HACK! */
if (s->io->seek(s->io, (PHYSFS_uint64) pos))
return SZ_OK;
return SZE_FAIL;
@@ -205,7 +205,7 @@
{
LZMAfile *file = bsearch(name, archive->files, archive->db.Database.NumFiles, sizeof(*archive->files), lzma_file_cmp_stdlib); /* FIXME: Should become __PHYSFS_search!!! */
- BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NO_SUCH_PATH, NULL);
+ BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NOT_FOUND, NULL);
return file;
} /* lzma_find_file */
@@ -291,25 +291,25 @@
case SZ_OK: /* Same as LZMA_RESULT_OK */
break;
case SZE_DATA_ERROR: /* Same as LZMA_RESULT_DATA_ERROR */
- __PHYSFS_setError(PHYSFS_ERR_CORRUPT); /*!!!FIXME: was "PHYSFS_ERR_DATA_ERROR" */
+ PHYSFS_setErrorCode(PHYSFS_ERR_CORRUPT); /*!!!FIXME: was "PHYSFS_ERR_DATA_ERROR" */
break;
case SZE_OUTOFMEMORY:
- __PHYSFS_setError(PHYSFS_ERR_OUT_OF_MEMORY);
+ PHYSFS_setErrorCode(PHYSFS_ERR_OUT_OF_MEMORY);
break;
case SZE_CRC_ERROR:
- __PHYSFS_setError(PHYSFS_ERR_CORRUPT);
+ PHYSFS_setErrorCode(PHYSFS_ERR_CORRUPT);
break;
case SZE_NOTIMPL:
- __PHYSFS_setError(PHYSFS_ERR_UNSUPPORTED);
+ PHYSFS_setErrorCode(PHYSFS_ERR_UNSUPPORTED);
break;
case SZE_FAIL:
- __PHYSFS_setError(PHYSFS_ERR_OTHER_ERROR); /* !!! FIXME: right? */
+ PHYSFS_setErrorCode(PHYSFS_ERR_OTHER_ERROR); /* !!! FIXME: right? */
break;
case SZE_ARCHIVE_ERROR:
- __PHYSFS_setError(PHYSFS_ERR_CORRUPT); /* !!! FIXME: right? */
+ PHYSFS_setErrorCode(PHYSFS_ERR_CORRUPT); /* !!! FIXME: right? */
break;
default:
- __PHYSFS_setError(PHYSFS_ERR_OTHER_ERROR);
+ PHYSFS_setErrorCode(PHYSFS_ERR_OTHER_ERROR);
} /* switch */
return rc;
@@ -531,8 +531,8 @@
} /* doEnumCallback */
-static void LZMA_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
- int omitSymLinks, PHYSFS_EnumFilesCallback cb,
+static void LZMA_enumerateFiles(void *opaque, const char *dname,
+ PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
size_t dlen = strlen(dname),
@@ -551,7 +551,7 @@
file = archive->files;
}
- BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NO_SUCH_PATH, );
+ BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NOT_FOUND, );
while (file < lastFile)
{
@@ -575,15 +575,13 @@
} /* LZMA_enumerateFiles */
-static PHYSFS_Io *LZMA_openRead(PHYSFS_Dir *opaque, const char *name,
- int *fileExists)
+static PHYSFS_Io *LZMA_openRead(void *opaque, const char *name)
{
LZMAarchive *archive = (LZMAarchive *) opaque;
LZMAfile *file = lzma_find_file(archive, name);
PHYSFS_Io *io = NULL;
- *fileExists = (file != NULL);
- BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NO_SUCH_PATH, NULL);
+ BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NOT_FOUND, NULL);
BAIL_IF_MACRO(file->folder == NULL, PHYSFS_ERR_NOT_A_FILE, NULL);
file->position = 0;
@@ -598,19 +596,19 @@
} /* LZMA_openRead */
-static PHYSFS_Io *LZMA_openWrite(PHYSFS_Dir *opaque, const char *filename)
+static PHYSFS_Io *LZMA_openWrite(void *opaque, const char *filename)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* LZMA_openWrite */
-static PHYSFS_Io *LZMA_openAppend(PHYSFS_Dir *opaque, const char *filename)
+static PHYSFS_Io *LZMA_openAppend(void *opaque, const char *filename)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* LZMA_openAppend */
-static void LZMA_closeArchive(PHYSFS_Dir *opaque)
+static void LZMA_closeArchive(void *opaque)
{
LZMAarchive *archive = (LZMAarchive *) opaque;
@@ -628,24 +626,22 @@
} /* LZMA_closeArchive */
-static int LZMA_remove(PHYSFS_Dir *opaque, const char *name)
+static int LZMA_remove(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* LZMA_remove */
-static int LZMA_mkdir(PHYSFS_Dir *opaque, const char *name)
+static int LZMA_mkdir(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* LZMA_mkdir */
-static int LZMA_stat(PHYSFS_Dir *opaque, const char *filename,
- int *exists, PHYSFS_Stat *stat)
+static int LZMA_stat(void *opaque, const char *filename, PHYSFS_Stat *stat)
{
const LZMAarchive *archive = (const LZMAarchive *) opaque;
const LZMAfile *file = lzma_find_file(archive, filename);
- *exists = (file != 0);
if (!file)
return 0;
@@ -678,24 +674,26 @@
const PHYSFS_Archiver __PHYSFS_Archiver_LZMA =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"7Z",
"LZMA (7zip) format",
"Dennis Schridde ",
- "http://icculus.org/physfs/",
+ "https://icculus.org/physfs/",
+ 0, /* supportsSymlinks */
},
- LZMA_openArchive, /* openArchive() method */
- LZMA_enumerateFiles, /* enumerateFiles() method */
- LZMA_openRead, /* openRead() method */
- LZMA_openWrite, /* openWrite() method */
- LZMA_openAppend, /* openAppend() method */
- LZMA_remove, /* remove() method */
- LZMA_mkdir, /* mkdir() method */
- LZMA_closeArchive, /* closeArchive() method */
- LZMA_stat /* stat() method */
+ LZMA_openArchive,
+ LZMA_enumerateFiles,
+ LZMA_openRead,
+ LZMA_openWrite,
+ LZMA_openAppend,
+ LZMA_remove,
+ LZMA_mkdir,
+ LZMA_stat,
+ LZMA_closeArchive
};
#endif /* defined PHYSFS_SUPPORTS_7Z */
-/* end of lzma.c ... */
+/* end of archiver_lzma.c ... */
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/archiver_mvl.c
--- a/misc/libphysfs/archiver_mvl.c Thu Aug 11 23:05:14 2016 +0300
+++ b/misc/libphysfs/archiver_mvl.c Sun Dec 17 00:09:24 2017 +0100
@@ -80,24 +80,26 @@
const PHYSFS_Archiver __PHYSFS_Archiver_MVL =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"MVL",
"Descent II Movielib format",
"Bradley Bell ",
- "http://icculus.org/physfs/",
+ "https://icculus.org/physfs/",
+ 0, /* supportsSymlinks */
},
- MVL_openArchive, /* openArchive() method */
- UNPK_enumerateFiles, /* enumerateFiles() method */
- UNPK_openRead, /* openRead() method */
- UNPK_openWrite, /* openWrite() method */
- UNPK_openAppend, /* openAppend() method */
- UNPK_remove, /* remove() method */
- UNPK_mkdir, /* mkdir() method */
- UNPK_closeArchive, /* closeArchive() method */
- UNPK_stat /* stat() method */
+ MVL_openArchive,
+ UNPK_enumerateFiles,
+ UNPK_openRead,
+ UNPK_openWrite,
+ UNPK_openAppend,
+ UNPK_remove,
+ UNPK_mkdir,
+ UNPK_stat,
+ UNPK_closeArchive
};
#endif /* defined PHYSFS_SUPPORTS_MVL */
-/* end of mvl.c ... */
+/* end of archiver_mvl.c ... */
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/archiver_qpak.c
--- a/misc/libphysfs/archiver_qpak.c Thu Aug 11 23:05:14 2016 +0300
+++ b/misc/libphysfs/archiver_qpak.c Sun Dec 17 00:09:24 2017 +0100
@@ -96,24 +96,26 @@
const PHYSFS_Archiver __PHYSFS_Archiver_QPAK =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"PAK",
"Quake I/II format",
"Ryan C. Gordon ",
- "http://icculus.org/physfs/",
+ "https://icculus.org/physfs/",
+ 0, /* supportsSymlinks */
},
- QPAK_openArchive, /* openArchive() method */
- UNPK_enumerateFiles, /* enumerateFiles() method */
- UNPK_openRead, /* openRead() method */
- UNPK_openWrite, /* openWrite() method */
- UNPK_openAppend, /* openAppend() method */
- UNPK_remove, /* remove() method */
- UNPK_mkdir, /* mkdir() method */
- UNPK_closeArchive, /* closeArchive() method */
- UNPK_stat /* stat() method */
+ QPAK_openArchive,
+ UNPK_enumerateFiles,
+ UNPK_openRead,
+ UNPK_openWrite,
+ UNPK_openAppend,
+ UNPK_remove,
+ UNPK_mkdir,
+ UNPK_stat,
+ UNPK_closeArchive
};
#endif /* defined PHYSFS_SUPPORTS_QPAK */
-/* end of qpak.c ... */
+/* end of archiver_qpak.c ... */
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/archiver_slb.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/archiver_slb.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,126 @@
+/*
+ * SLB support routines for PhysicsFS.
+ *
+ * This driver handles SLB archives ("slab files"). This uncompressed format
+ * is used in I-War / Independence War and Independence War: Defiance.
+ *
+ * The format begins with four zero bytes (version?), the file count and the
+ * location of the table of contents. Each ToC entry contains a 64-byte buffer
+ * containing a zero-terminated filename, the offset of the data, and its size.
+ * All the filenames begin with the separator character '\'.
+ *
+ * Please see the file LICENSE.txt in the source's root directory.
+ *
+ * This file written by Aleksi Nurmi, based on the GRP archiver by
+ * Ryan C. Gordon.
+ */
+
+#define __PHYSICSFS_INTERNAL__
+#include "physfs_internal.h"
+
+#if PHYSFS_SUPPORTS_SLB
+
+static UNPKentry *slbLoadEntries(PHYSFS_Io *io, PHYSFS_uint32 fileCount)
+{
+ UNPKentry *entries = NULL;
+ UNPKentry *entry = NULL;
+
+ entries = (UNPKentry *) allocator.Malloc(sizeof (UNPKentry) * fileCount);
+ BAIL_IF_MACRO(entries == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
+
+ for (entry = entries; fileCount > 0; fileCount--, entry++)
+ {
+ char *ptr;
+
+ /* don't include the '\' in the beginning */
+ char backslash;
+ GOTO_IF_MACRO(!__PHYSFS_readAll(io, &backslash, 1), ERRPASS, failed);
+ GOTO_IF_MACRO(backslash != '\\', ERRPASS, failed);
+
+ /* read the rest of the buffer, 63 bytes */
+ GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->name, 63), ERRPASS, failed);
+ entry->name[63] = '\0'; /* in case the name lacks the null terminator */
+
+ /* convert backslashes */
+ for (ptr = entry->name; *ptr; ptr++)
+ {
+ if (*ptr == '\\')
+ *ptr = '/';
+ } /* for */
+
+ GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->startPos, 4),
+ ERRPASS, failed);
+ entry->startPos = PHYSFS_swapULE32(entry->startPos);
+
+ GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->size, 4), ERRPASS, failed);
+ entry->size = PHYSFS_swapULE32(entry->size);
+ } /* for */
+
+ return entries;
+
+failed:
+ allocator.Free(entries);
+ return NULL;
+
+} /* slbLoadEntries */
+
+
+static void *SLB_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
+{
+ PHYSFS_uint32 version;
+ PHYSFS_uint32 count = 0;
+ PHYSFS_uint32 tocPos = 0;
+ UNPKentry *entries = NULL;
+
+ assert(io != NULL); /* shouldn't ever happen. */
+
+ BAIL_IF_MACRO(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
+
+ BAIL_IF_MACRO(!__PHYSFS_readAll(io, &version, sizeof(version)),
+ ERRPASS, NULL);
+ version = PHYSFS_swapULE32(version);
+ BAIL_IF_MACRO(version != 0, ERRPASS, NULL);
+
+ BAIL_IF_MACRO(!__PHYSFS_readAll(io, &count, sizeof(count)), ERRPASS, NULL);
+ count = PHYSFS_swapULE32(count);
+
+ /* offset of the table of contents */
+ BAIL_IF_MACRO(!__PHYSFS_readAll(io, &tocPos, sizeof(tocPos)),
+ ERRPASS, NULL);
+ tocPos = PHYSFS_swapULE32(tocPos);
+
+ /* seek to the table of contents */
+ BAIL_IF_MACRO(!io->seek(io, tocPos), ERRPASS, NULL);
+
+ entries = slbLoadEntries(io, count);
+ BAIL_IF_MACRO(!entries, ERRPASS, NULL);
+
+ return UNPK_openArchive(io, entries, count);
+} /* SLB_openArchive */
+
+
+const PHYSFS_Archiver __PHYSFS_Archiver_SLB =
+{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
+ {
+ "SLB",
+ "I-War / Independence War Slab file",
+ "Aleksi Nurmi ",
+ "https://bitbucket.org/ahnurmi/",
+ 0, /* supportsSymlinks */
+ },
+ SLB_openArchive,
+ UNPK_enumerateFiles,
+ UNPK_openRead,
+ UNPK_openWrite,
+ UNPK_openAppend,
+ UNPK_remove,
+ UNPK_mkdir,
+ UNPK_stat,
+ UNPK_closeArchive
+};
+
+#endif /* defined PHYSFS_SUPPORTS_SLB */
+
+/* end of archiver_slb.c ... */
+
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/archiver_unpacked.c
--- a/misc/libphysfs/archiver_unpacked.c Thu Aug 11 23:05:14 2016 +0300
+++ b/misc/libphysfs/archiver_unpacked.c Sun Dec 17 00:09:24 2017 +0100
@@ -7,7 +7,7 @@
*
* RULES: Archive entries must be uncompressed, must not have separate subdir
* entries (but can have subdirs), must be case insensitive LOW ASCII
- * filenames <= 56 bytes. No symlinks, etc. We can relax some of these rules
+ * filenames <= 64 bytes. No symlinks, etc. We can relax some of these rules
* as necessary.
*
* Please see the file LICENSE.txt in the source's root directory.
@@ -34,7 +34,7 @@
} UNPKfileinfo;
-void UNPK_closeArchive(PHYSFS_Dir *opaque)
+void UNPK_closeArchive(void *opaque)
{
UNPKinfo *info = ((UNPKinfo *) opaque);
info->io->destroy(info->io);
@@ -200,7 +200,7 @@
rc = -1;
else if (ch > '/')
rc = 1;
- else
+ else
{
if (stop_on_first_find) /* Just checking dir's existance? */
return middle;
@@ -242,8 +242,8 @@
} /* doEnumCallback */
-void UNPK_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
- int omitSymLinks, PHYSFS_EnumFilesCallback cb,
+void UNPK_enumerateFiles(void *opaque, const char *dname,
+ PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
UNPKinfo *info = ((UNPKinfo *) opaque);
@@ -293,7 +293,7 @@
/*
* This will find the UNPKentry associated with a path in platform-independent
- * notation. Directories don't have UNPKentries associated with them, but
+ * notation. Directories don't have UNPKentries associated with them, but
* (*isDir) will be set to non-zero if a dir was hit.
*/
static UNPKentry *findEntry(const UNPKinfo *info, const char *path, int *isDir)
@@ -340,19 +340,18 @@
if (isDir != NULL)
*isDir = 0;
- BAIL_MACRO(PHYSFS_ERR_NO_SUCH_PATH, NULL);
+ BAIL_MACRO(PHYSFS_ERR_NOT_FOUND, NULL);
} /* findEntry */
-PHYSFS_Io *UNPK_openRead(PHYSFS_Dir *opaque, const char *fnm, int *fileExists)
+PHYSFS_Io *UNPK_openRead(void *opaque, const char *name)
{
PHYSFS_Io *retval = NULL;
UNPKinfo *info = (UNPKinfo *) opaque;
UNPKfileinfo *finfo = NULL;
int isdir = 0;
- UNPKentry *entry = findEntry(info, fnm, &isdir);
+ UNPKentry *entry = findEntry(info, name, &isdir);
- *fileExists = (entry != NULL);
GOTO_IF_MACRO(isdir, PHYSFS_ERR_NOT_A_FILE, UNPK_openRead_failed);
GOTO_IF_MACRO(!entry, ERRPASS, UNPK_openRead_failed);
@@ -390,32 +389,31 @@
} /* UNPK_openRead */
-PHYSFS_Io *UNPK_openWrite(PHYSFS_Dir *opaque, const char *name)
+PHYSFS_Io *UNPK_openWrite(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* UNPK_openWrite */
-PHYSFS_Io *UNPK_openAppend(PHYSFS_Dir *opaque, const char *name)
+PHYSFS_Io *UNPK_openAppend(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* UNPK_openAppend */
-int UNPK_remove(PHYSFS_Dir *opaque, const char *name)
+int UNPK_remove(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* UNPK_remove */
-int UNPK_mkdir(PHYSFS_Dir *opaque, const char *name)
+int UNPK_mkdir(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* UNPK_mkdir */
-int UNPK_stat(PHYSFS_Dir *opaque, const char *filename,
- int *exists, PHYSFS_Stat *stat)
+int UNPK_stat(void *opaque, const char *filename, PHYSFS_Stat *stat)
{
int isDir = 0;
const UNPKinfo *info = (const UNPKinfo *) opaque;
@@ -423,19 +421,16 @@
if (isDir)
{
- *exists = 1;
stat->filetype = PHYSFS_FILETYPE_DIRECTORY;
stat->filesize = 0;
} /* if */
else if (entry != NULL)
{
- *exists = 1;
stat->filetype = PHYSFS_FILETYPE_REGULAR;
stat->filesize = entry->size;
} /* else if */
else
{
- *exists = 0;
return 0;
} /* else */
@@ -448,8 +443,7 @@
} /* UNPK_stat */
-PHYSFS_Dir *UNPK_openArchive(PHYSFS_Io *io, UNPKentry *e,
- const PHYSFS_uint32 num)
+void *UNPK_openArchive(PHYSFS_Io *io, UNPKentry *e, const PHYSFS_uint32 num)
{
UNPKinfo *info = (UNPKinfo *) allocator.Malloc(sizeof (UNPKinfo));
if (info == NULL)
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/archiver_wad.c
--- a/misc/libphysfs/archiver_wad.c Thu Aug 11 23:05:14 2016 +0300
+++ b/misc/libphysfs/archiver_wad.c Sun Dec 17 00:09:24 2017 +0100
@@ -1,7 +1,7 @@
/*
* WAD support routines for PhysicsFS.
*
- * This driver handles DOOM engine archives ("wads").
+ * This driver handles DOOM engine archives ("wads").
* This format (but not this driver) was designed by id Software for use
* with the DOOM engine.
* The specs of the format are from the unofficial doom specs v1.666
@@ -28,7 +28,7 @@
* (c) an 8-byte ASCII string, the name of the lump, padded with zeros.
* For example, the "DEMO1" entry in hexadecimal would be
* (44 45 4D 4F 31 00 00 00)
- *
+ *
* Note that there is no way to tell if an opened WAD archive is a
* IWAD or PWAD with this archiver.
* I couldn't think of a way to provide that information, without being too
@@ -104,24 +104,26 @@
const PHYSFS_Archiver __PHYSFS_Archiver_WAD =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"WAD",
"DOOM engine format",
"Travis Wells ",
"http://www.3dmm2.com/doom/",
+ 0, /* supportsSymlinks */
},
- WAD_openArchive, /* openArchive() method */
- UNPK_enumerateFiles, /* enumerateFiles() method */
- UNPK_openRead, /* openRead() method */
- UNPK_openWrite, /* openWrite() method */
- UNPK_openAppend, /* openAppend() method */
- UNPK_remove, /* remove() method */
- UNPK_mkdir, /* mkdir() method */
- UNPK_closeArchive, /* closeArchive() method */
- UNPK_stat /* stat() method */
+ WAD_openArchive,
+ UNPK_enumerateFiles,
+ UNPK_openRead,
+ UNPK_openWrite,
+ UNPK_openAppend,
+ UNPK_remove,
+ UNPK_mkdir,
+ UNPK_stat,
+ UNPK_closeArchive
};
#endif /* defined PHYSFS_SUPPORTS_WAD */
-/* end of wad.c ... */
+/* end of archiver_wad.c ... */
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/archiver_zip.c
--- a/misc/libphysfs/archiver_zip.c Thu Aug 11 23:05:14 2016 +0300
+++ b/misc/libphysfs/archiver_zip.c Sun Dec 17 00:09:24 2017 +0100
@@ -15,12 +15,7 @@
#include
#include
-#define USE_MINIZ 1
-#if USE_MINIZ
#include "physfs_miniz.h"
-#else
-#include
-#endif
/*
* A buffer of ZIP_READBUFSIZE is allocated for each compressed file opened,
@@ -51,6 +46,7 @@
ZIP_UNRESOLVED_SYMLINK,
ZIP_RESOLVING,
ZIP_RESOLVED,
+ ZIP_DIRECTORY,
ZIP_BROKEN_FILE,
ZIP_BROKEN_SYMLINK
} ZipResolveType;
@@ -67,11 +63,16 @@
PHYSFS_uint64 offset; /* offset of data in archive */
PHYSFS_uint16 version; /* version made by */
PHYSFS_uint16 version_needed; /* version needed to extract */
+ PHYSFS_uint16 general_bits; /* general purpose bits */
PHYSFS_uint16 compression_method; /* compression method */
PHYSFS_uint32 crc; /* crc-32 */
PHYSFS_uint64 compressed_size; /* compressed size */
PHYSFS_uint64 uncompressed_size; /* uncompressed size */
PHYSFS_sint64 last_mod_time; /* last file mod time */
+ PHYSFS_uint32 dos_mod_time; /* original MS-DOS style mod time */
+ struct _ZIPentry *hashnext; /* next item in this hash bucket */
+ struct _ZIPentry *children; /* linked list of kids, if dir */
+ struct _ZIPentry *sibling; /* next item in same dir */
} ZIPentry;
/*
@@ -79,10 +80,12 @@
*/
typedef struct
{
- PHYSFS_Io *io;
- int zip64; /* non-zero if this is a Zip64 archive. */
- PHYSFS_uint64 entryCount; /* Number of files in ZIP. */
- ZIPentry *entries; /* info on all files in ZIP. */
+ PHYSFS_Io *io; /* the i/o interface for this archive. */
+ ZIPentry root; /* root of directory tree. */
+ ZIPentry **hash; /* all entries hashed for fast lookup. */
+ size_t hashBuckets; /* number of buckets in hash. */
+ int zip64; /* non-zero if this is a Zip64 archive. */
+ int has_crypto; /* non-zero if any entry uses encryption. */
} ZIPinfo;
/*
@@ -95,6 +98,8 @@
PHYSFS_uint32 compressed_position; /* offset in compressed data. */
PHYSFS_uint32 uncompressed_position; /* tell() position. */
PHYSFS_uint8 *buffer; /* decompression buffer. */
+ PHYSFS_uint32 crypto_keys[3]; /* for "traditional" crypto. */
+ PHYSFS_uint32 initial_crypto_keys[3]; /* for "traditional" crypto. */
z_stream stream; /* zlib stream state. */
} ZIPfileinfo;
@@ -115,6 +120,103 @@
#define UNIX_FILETYPE_MASK 0170000
#define UNIX_FILETYPE_SYMLINK 0120000
+#define ZIP_GENERAL_BITS_TRADITIONAL_CRYPTO (1 << 0)
+#define ZIP_GENERAL_BITS_IGNORE_LOCAL_HEADER (1 << 3)
+
+/* support for "traditional" PKWARE encryption. */
+static int zip_entry_is_tradional_crypto(const ZIPentry *entry)
+{
+ return (entry->general_bits & ZIP_GENERAL_BITS_TRADITIONAL_CRYPTO) != 0;
+} /* zip_entry_is_traditional_crypto */
+
+static int zip_entry_ignore_local_header(const ZIPentry *entry)
+{
+ return (entry->general_bits & ZIP_GENERAL_BITS_IGNORE_LOCAL_HEADER) != 0;
+} /* zip_entry_is_traditional_crypto */
+
+static PHYSFS_uint32 zip_crypto_crc32(const PHYSFS_uint32 crc, const PHYSFS_uint8 val)
+{
+ int i;
+ PHYSFS_uint32 xorval = (crc ^ ((PHYSFS_uint32) val)) & 0xFF;
+ for (i = 0; i < 8; i++)
+ xorval = ((xorval & 1) ? (0xEDB88320 ^ (xorval >> 1)) : (xorval >> 1));
+ return xorval ^ (crc >> 8);
+} /* zip_crc32 */
+
+static void zip_update_crypto_keys(PHYSFS_uint32 *keys, const PHYSFS_uint8 val)
+{
+ keys[0] = zip_crypto_crc32(keys[0], val);
+ keys[1] = keys[1] + (keys[0] & 0x000000FF);
+ keys[1] = (keys[1] * 134775813) + 1;
+ keys[2] = zip_crypto_crc32(keys[2], (PHYSFS_uint8) ((keys[1] >> 24) & 0xFF));
+} /* zip_update_crypto_keys */
+
+static PHYSFS_uint8 zip_decrypt_byte(const PHYSFS_uint32 *keys)
+{
+ const PHYSFS_uint16 tmp = keys[2] | 2;
+ return (PHYSFS_uint8) ((tmp * (tmp ^ 1)) >> 8);
+} /* zip_decrypt_byte */
+
+static PHYSFS_sint64 zip_read_decrypt(ZIPfileinfo *finfo, void *buf, PHYSFS_uint64 len)
+{
+ PHYSFS_Io *io = finfo->io;
+ const PHYSFS_sint64 br = io->read(io, buf, len);
+
+ /* Decompression the new data if necessary. */
+ if (zip_entry_is_tradional_crypto(finfo->entry) && (br > 0))
+ {
+ PHYSFS_uint32 *keys = finfo->crypto_keys;
+ PHYSFS_uint8 *ptr = (PHYSFS_uint8 *) buf;
+ PHYSFS_sint64 i;
+ for (i = 0; i < br; i++, ptr++)
+ {
+ const PHYSFS_uint8 ch = *ptr ^ zip_decrypt_byte(keys);
+ zip_update_crypto_keys(keys, ch);
+ *ptr = ch;
+ } /* for */
+ } /* if */
+
+ return br;
+} /* zip_read_decrypt */
+
+static int zip_prep_crypto_keys(ZIPfileinfo *finfo, const PHYSFS_uint8 *crypto_header, const PHYSFS_uint8 *password)
+{
+ /* It doesn't appear to be documented in PKWare's APPNOTE.TXT, but you
+ need to use a different byte in the header to verify the password
+ if general purpose bit 3 is set. Discovered this from Info-Zip.
+ That's what the (verifier) value is doing, below. */
+
+ PHYSFS_uint32 *keys = finfo->crypto_keys;
+ const ZIPentry *entry = finfo->entry;
+ const int usedate = zip_entry_ignore_local_header(entry);
+ const PHYSFS_uint8 verifier = (PHYSFS_uint8) ((usedate ? (entry->dos_mod_time >> 8) : (entry->crc >> 24)) & 0xFF);
+ PHYSFS_uint8 finalbyte = 0;
+ int i = 0;
+
+ /* initialize vector with defaults, then password, then header. */
+ keys[0] = 305419896;
+ keys[1] = 591751049;
+ keys[2] = 878082192;
+
+ while (*password)
+ zip_update_crypto_keys(keys, *(password++));
+
+ for (i = 0; i < 12; i++)
+ {
+ const PHYSFS_uint8 c = crypto_header[i] ^ zip_decrypt_byte(keys);
+ zip_update_crypto_keys(keys, c);
+ finalbyte = c;
+ } /* for */
+
+ /* you have a 1/256 chance of passing this test incorrectly. :/ */
+ if (finalbyte != verifier)
+ BAIL_MACRO(PHYSFS_ERR_BAD_PASSWORD, 0);
+
+ /* save the initial vector for seeking purposes. Not secure!! */
+ memcpy(finfo->initial_crypto_keys, finfo->crypto_keys, 12);
+ return 1;
+} /* zip_prep_crypto_keys */
+
/*
* Bridge physfs allocation functions to zlib's format...
@@ -163,10 +265,17 @@
*/
static int zlib_err(const int rc)
{
- __PHYSFS_setError(zlib_error_code(rc));
+ PHYSFS_setErrorCode(zlib_error_code(rc));
return rc;
} /* zlib_err */
+/*
+ * Hash a string for lookup an a ZIPinfo hashtable.
+ */
+static inline PHYSFS_uint32 zip_hash_string(const ZIPinfo *info, const char *s)
+{
+ return __PHYSFS_hashString(s, strlen(s)) % info->hashBuckets;
+} /* zip_hash_string */
/*
* Read an unsigned 64-bit int and swap to native byte order.
@@ -206,7 +315,6 @@
static PHYSFS_sint64 ZIP_read(PHYSFS_Io *_io, void *buf, PHYSFS_uint64 len)
{
ZIPfileinfo *finfo = (ZIPfileinfo *) _io->opaque;
- PHYSFS_Io *io = finfo->io;
ZIPentry *entry = finfo->entry;
PHYSFS_sint64 retval = 0;
PHYSFS_sint64 maxread = (PHYSFS_sint64) len;
@@ -219,7 +327,7 @@
BAIL_IF_MACRO(maxread == 0, ERRPASS, 0); /* quick rejection. */
if (entry->compression_method == COMPMETH_NONE)
- retval = io->read(io, buf, maxread);
+ retval = zip_read_decrypt(finfo, buf, maxread);
else
{
finfo->stream.next_out = buf;
@@ -240,7 +348,7 @@
if (br > ZIP_READBUFSIZE)
br = ZIP_READBUFSIZE;
- br = io->read(io, finfo->buffer, (PHYSFS_uint64) br);
+ br = zip_read_decrypt(finfo, finfo->buffer, (PHYSFS_uint64) br);
if (br <= 0)
break;
@@ -282,12 +390,13 @@
ZIPfileinfo *finfo = (ZIPfileinfo *) _io->opaque;
ZIPentry *entry = finfo->entry;
PHYSFS_Io *io = finfo->io;
+ const int encrypted = zip_entry_is_tradional_crypto(entry);
BAIL_IF_MACRO(offset > entry->uncompressed_size, PHYSFS_ERR_PAST_EOF, 0);
- if (entry->compression_method == COMPMETH_NONE)
+ if (!encrypted && (entry->compression_method == COMPMETH_NONE))
{
- const PHYSFS_sint64 newpos = offset + entry->offset;
+ PHYSFS_sint64 newpos = offset + entry->offset;
BAIL_IF_MACRO(!io->seek(io, newpos), ERRPASS, 0);
finfo->uncompressed_position = (PHYSFS_uint32) offset;
} /* if */
@@ -308,12 +417,15 @@
if (zlib_err(inflateInit2(&str, -MAX_WBITS)) != Z_OK)
return 0;
- if (!io->seek(io, entry->offset))
+ if (!io->seek(io, entry->offset + (encrypted ? 12 : 0)))
return 0;
inflateEnd(&finfo->stream);
memcpy(&finfo->stream, &str, sizeof (z_stream));
finfo->uncompressed_position = finfo->compressed_position = 0;
+
+ if (encrypted)
+ memcpy(finfo->crypto_keys, finfo->initial_crypto_keys, 12);
} /* if */
while (finfo->uncompressed_position != offset)
@@ -434,7 +546,7 @@
int found = 0;
filelen = io->length(io);
- BAIL_IF_MACRO(filelen == -1, ERRPASS, 0);
+ BAIL_IF_MACRO(filelen == -1, ERRPASS, -1);
/*
* Jump to the end of the file and start reading backwards.
@@ -488,7 +600,7 @@
(buf[i + 3] == 0x06) )
{
found = 1; /* that's the signature! */
- break;
+ break;
} /* if */
} /* for */
@@ -536,71 +648,35 @@
} /* isZip */
-static void zip_free_entries(ZIPentry *entries, PHYSFS_uint64 max)
+/* Find the ZIPentry for a path in platform-independent notation. */
+static ZIPentry *zip_find_entry(ZIPinfo *info, const char *path)
{
- PHYSFS_uint64 i;
- for (i = 0; i < max; i++)
+ PHYSFS_uint32 hashval;
+ ZIPentry *prev = NULL;
+ ZIPentry *retval;
+
+ if (*path == '\0')
+ return &info->root;
+
+ hashval = zip_hash_string(info, path);
+ for (retval = info->hash[hashval]; retval; retval = retval->hashnext)
{
- ZIPentry *entry = &entries[i];
- if (entry->name != NULL)
- allocator.Free(entry->name);
+ if (strcmp(retval->name, path) == 0)
+ {
+ if (prev != NULL) /* move this to the front of the list */
+ {
+ prev->hashnext = retval->hashnext;
+ retval->hashnext = info->hash[hashval];
+ info->hash[hashval] = retval;
+ } /* if */
+
+ return retval;
+ } /* if */
+
+ prev = retval;
} /* for */
- allocator.Free(entries);
-} /* zip_free_entries */
-
-
-/*
- * This will find the ZIPentry associated with a path in platform-independent
- * notation. Directories don't have ZIPentries associated with them, but
- * (*isDir) will be set to non-zero if a dir was hit.
- */
-static ZIPentry *zip_find_entry(const ZIPinfo *info, const char *path,
- int *isDir)
-{
- ZIPentry *a = info->entries;
- PHYSFS_sint32 pathlen = (PHYSFS_sint32) strlen(path);
- PHYSFS_sint64 lo = 0;
- PHYSFS_sint64 hi = (PHYSFS_sint64) (info->entryCount - 1);
- PHYSFS_sint64 middle;
- const char *thispath = NULL;
- int rc;
-
- while (lo <= hi)
- {
- middle = lo + ((hi - lo) / 2);
- thispath = a[middle].name;
- rc = strncmp(path, thispath, pathlen);
-
- if (rc > 0)
- lo = middle + 1;
-
- else if (rc < 0)
- hi = middle - 1;
-
- else /* substring match...might be dir or entry or nothing. */
- {
- if (isDir != NULL)
- {
- *isDir = (thispath[pathlen] == '/');
- if (*isDir)
- return NULL;
- } /* if */
-
- if (thispath[pathlen] == '\0') /* found entry? */
- return &a[middle];
- /* adjust search params, try again. */
- else if (thispath[pathlen] > '/')
- hi = middle - 1;
- else
- lo = middle + 1;
- } /* if */
- } /* while */
-
- if (isDir != NULL)
- *isDir = 0;
-
- BAIL_MACRO(PHYSFS_ERR_NO_SUCH_PATH, NULL);
+ BAIL_MACRO(PHYSFS_ERR_NOT_FOUND, NULL);
} /* zip_find_entry */
@@ -692,7 +768,7 @@
ZIPentry *entry;
zip_expand_symlink_path(path);
- entry = zip_find_entry(info, path, NULL);
+ entry = zip_find_entry(info, path);
if (entry != NULL)
{
if (!zip_resolve(io, info, entry)) /* recursive! */
@@ -724,7 +800,7 @@
path = (char *) __PHYSFS_smallAlloc(size + 1);
BAIL_IF_MACRO(!path, PHYSFS_ERR_OUT_OF_MEMORY, 0);
-
+
if (entry->compression_method == COMPMETH_NONE)
rc = __PHYSFS_readAll(io, path, size);
@@ -787,6 +863,10 @@
* possible that's a Zip64 thing.
*/
+ /* !!! FIXME: apparently these are zero if general purpose bit 3 is set,
+ !!! FIXME: which is probably true for Jar files, fwiw, but we don't
+ !!! FIXME: care about these values anyhow. */
+
BAIL_IF_MACRO(!io->seek(io, entry->offset), ERRPASS, 0);
BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
BAIL_IF_MACRO(ui32 != ZIP_LOCAL_FILE_SIG, PHYSFS_ERR_CORRUPT, 0);
@@ -818,7 +898,10 @@
static int zip_resolve(PHYSFS_Io *io, ZIPinfo *info, ZIPentry *entry)
{
int retval = 1;
- ZipResolveType resolve_type = entry->resolved;
+ const ZipResolveType resolve_type = entry->resolved;
+
+ if (resolve_type == ZIP_DIRECTORY)
+ return 1; /* we're good. */
/* Don't bother if we've failed to resolve this entry before. */
BAIL_IF_MACRO(resolve_type == ZIP_BROKEN_FILE, PHYSFS_ERR_CORRUPT, 0);
@@ -860,6 +943,77 @@
} /* zip_resolve */
+static int zip_hash_entry(ZIPinfo *info, ZIPentry *entry);
+
+/* Fill in missing parent directories. */
+static ZIPentry *zip_hash_ancestors(ZIPinfo *info, char *name)
+{
+ ZIPentry *retval = &info->root;
+ char *sep = strrchr(name, '/');
+
+ if (sep)
+ {
+ const size_t namelen = (sep - name) + 1;
+
+ *sep = '\0'; /* chop off last piece. */
+ retval = zip_find_entry(info, name);
+ *sep = '/';
+
+ if (retval != NULL)
+ {
+ if (retval->resolved != ZIP_DIRECTORY)
+ BAIL_MACRO(PHYSFS_ERR_CORRUPT, NULL);
+ return retval; /* already hashed. */
+ } /* if */
+
+ /* okay, this is a new dir. Build and hash us. */
+ retval = (ZIPentry *) allocator.Malloc(sizeof (ZIPentry) + namelen);
+ BAIL_IF_MACRO(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
+ memset(retval, '\0', sizeof (*retval));
+ retval->name = ((char *) retval) + sizeof (ZIPentry);
+ memcpy(retval->name, name, namelen - 1);
+ retval->name[namelen - 1] = '\0';
+ retval->resolved = ZIP_DIRECTORY;
+ if (!zip_hash_entry(info, retval))
+ {
+ allocator.Free(retval);
+ return NULL;
+ } /* if */
+ } /* else */
+
+ return retval;
+} /* zip_hash_ancestors */
+
+
+static int zip_hash_entry(ZIPinfo *info, ZIPentry *entry)
+{
+ PHYSFS_uint32 hashval;
+ ZIPentry *parent;
+
+ assert(!zip_find_entry(info, entry->name)); /* checked elsewhere */
+
+ parent = zip_hash_ancestors(info, entry->name);
+ if (!parent)
+ return 0;
+
+ hashval = zip_hash_string(info, entry->name);
+ entry->hashnext = info->hash[hashval];
+ info->hash[hashval] = entry;
+
+ entry->sibling = parent->children;
+ parent->children = entry;
+ return 1;
+} /* zip_hash_entry */
+
+
+static int zip_entry_is_symlink(const ZIPentry *entry)
+{
+ return ((entry->resolved == ZIP_UNRESOLVED_SYMLINK) ||
+ (entry->resolved == ZIP_BROKEN_SYMLINK) ||
+ (entry->symlink));
+} /* zip_entry_is_symlink */
+
+
static int zip_version_does_symlinks(PHYSFS_uint32 version)
{
int retval = 0;
@@ -892,14 +1046,6 @@
} /* zip_version_does_symlinks */
-static int zip_entry_is_symlink(const ZIPentry *entry)
-{
- return ((entry->resolved == ZIP_UNRESOLVED_SYMLINK) ||
- (entry->resolved == ZIP_BROKEN_SYMLINK) ||
- (entry->symlink));
-} /* zip_entry_is_symlink */
-
-
static int zip_has_symlink_attr(ZIPentry *entry, PHYSFS_uint32 extern_attr)
{
PHYSFS_uint16 xattr = ((extern_attr >> 16) & 0xFFFF);
@@ -935,9 +1081,11 @@
} /* zip_dos_time_to_physfs_time */
-static int zip_load_entry(PHYSFS_Io *io, const int zip64, ZIPentry *entry,
- PHYSFS_uint64 ofs_fixup)
+static ZIPentry *zip_load_entry(PHYSFS_Io *io, const int zip64,
+ const PHYSFS_uint64 ofs_fixup)
{
+ ZIPentry entry;
+ ZIPentry *retval = NULL;
PHYSFS_uint16 fnamelen, extralen, commentlen;
PHYSFS_uint32 external_attr;
PHYSFS_uint32 starting_disk;
@@ -946,43 +1094,57 @@
PHYSFS_uint32 ui32;
PHYSFS_sint64 si64;
+ memset(&entry, '\0', sizeof (entry));
+
/* sanity check with central directory signature... */
- BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
- BAIL_IF_MACRO(ui32 != ZIP_CENTRAL_DIR_SIG, PHYSFS_ERR_CORRUPT, 0);
+ if (!readui32(io, &ui32)) return NULL;
+ BAIL_IF_MACRO(ui32 != ZIP_CENTRAL_DIR_SIG, PHYSFS_ERR_CORRUPT, NULL);
/* Get the pertinent parts of the record... */
- BAIL_IF_MACRO(!readui16(io, &entry->version), ERRPASS, 0);
- BAIL_IF_MACRO(!readui16(io, &entry->version_needed), ERRPASS, 0);
- BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0); /* general bits */
- BAIL_IF_MACRO(!readui16(io, &entry->compression_method), ERRPASS, 0);
- BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
- entry->last_mod_time = zip_dos_time_to_physfs_time(ui32);
- BAIL_IF_MACRO(!readui32(io, &entry->crc), ERRPASS, 0);
- BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
- entry->compressed_size = (PHYSFS_uint64) ui32;
- BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
- entry->uncompressed_size = (PHYSFS_uint64) ui32;
- BAIL_IF_MACRO(!readui16(io, &fnamelen), ERRPASS, 0);
- BAIL_IF_MACRO(!readui16(io, &extralen), ERRPASS, 0);
- BAIL_IF_MACRO(!readui16(io, &commentlen), ERRPASS, 0);
- BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0);
+ if (!readui16(io, &entry.version)) return NULL;
+ if (!readui16(io, &entry.version_needed)) return NULL;
+ if (!readui16(io, &entry.general_bits)) return NULL; /* general bits */
+ if (!readui16(io, &entry.compression_method)) return NULL;
+ if (!readui32(io, &entry.dos_mod_time)) return NULL;
+ entry.last_mod_time = zip_dos_time_to_physfs_time(entry.dos_mod_time);
+ if (!readui32(io, &entry.crc)) return NULL;
+ if (!readui32(io, &ui32)) return NULL;
+ entry.compressed_size = (PHYSFS_uint64) ui32;
+ if (!readui32(io, &ui32)) return NULL;
+ entry.uncompressed_size = (PHYSFS_uint64) ui32;
+ if (!readui16(io, &fnamelen)) return NULL;
+ if (!readui16(io, &extralen)) return NULL;
+ if (!readui16(io, &commentlen)) return NULL;
+ if (!readui16(io, &ui16)) return NULL;
starting_disk = (PHYSFS_uint32) ui16;
- BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0); /* internal file attribs */
- BAIL_IF_MACRO(!readui32(io, &external_attr), ERRPASS, 0);
- BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
+ if (!readui16(io, &ui16)) return NULL; /* internal file attribs */
+ if (!readui32(io, &external_attr)) return NULL;
+ if (!readui32(io, &ui32)) return NULL;
offset = (PHYSFS_uint64) ui32;
- entry->symlink = NULL; /* will be resolved later, if necessary. */
- entry->resolved = (zip_has_symlink_attr(entry, external_attr)) ?
- ZIP_UNRESOLVED_SYMLINK : ZIP_UNRESOLVED_FILE;
+ retval = (ZIPentry *) allocator.Malloc(sizeof (ZIPentry) + fnamelen + 1);
+ BAIL_IF_MACRO(retval == NULL, PHYSFS_ERR_OUT_OF_MEMORY, 0);
+ memcpy(retval, &entry, sizeof (*retval));
+ retval->name = ((char *) retval) + sizeof (ZIPentry);
- entry->name = (char *) allocator.Malloc(fnamelen + 1);
- BAIL_IF_MACRO(entry->name == NULL, PHYSFS_ERR_OUT_OF_MEMORY, 0);
- if (!__PHYSFS_readAll(io, entry->name, fnamelen))
+ if (!__PHYSFS_readAll(io, retval->name, fnamelen))
goto zip_load_entry_puked;
- entry->name[fnamelen] = '\0'; /* null-terminate the filename. */
- zip_convert_dos_path(entry, entry->name);
+ retval->name[fnamelen] = '\0'; /* null-terminate the filename. */
+ zip_convert_dos_path(retval, retval->name);
+
+ retval->symlink = NULL; /* will be resolved later, if necessary. */
+
+ if (retval->name[fnamelen - 1] == '/')
+ {
+ retval->name[fnamelen - 1] = '\0';
+ retval->resolved = ZIP_DIRECTORY;
+ } /* if */
+ else
+ {
+ retval->resolved = (zip_has_symlink_attr(&entry, external_attr)) ?
+ ZIP_UNRESOLVED_SYMLINK : ZIP_UNRESOLVED_FILE;
+ } /* else */
si64 = io->tell(io);
if (si64 == -1)
@@ -995,8 +1157,8 @@
if ( (zip64) &&
((offset == 0xFFFFFFFF) ||
(starting_disk == 0xFFFFFFFF) ||
- (entry->compressed_size == 0xFFFFFFFF) ||
- (entry->uncompressed_size == 0xFFFFFFFF)) )
+ (retval->compressed_size == 0xFFFFFFFF) ||
+ (retval->uncompressed_size == 0xFFFFFFFF)) )
{
int found = 0;
PHYSFS_uint16 sig, len;
@@ -1022,18 +1184,18 @@
GOTO_IF_MACRO(!found, PHYSFS_ERR_CORRUPT, zip_load_entry_puked);
- if (entry->uncompressed_size == 0xFFFFFFFF)
+ if (retval->uncompressed_size == 0xFFFFFFFF)
{
GOTO_IF_MACRO(len < 8, PHYSFS_ERR_CORRUPT, zip_load_entry_puked);
- if (!readui64(io, &entry->uncompressed_size))
+ if (!readui64(io, &retval->uncompressed_size))
goto zip_load_entry_puked;
len -= 8;
} /* if */
- if (entry->compressed_size == 0xFFFFFFFF)
+ if (retval->compressed_size == 0xFFFFFFFF)
{
GOTO_IF_MACRO(len < 8, PHYSFS_ERR_CORRUPT, zip_load_entry_puked);
- if (!readui64(io, &entry->compressed_size))
+ if (!readui64(io, &retval->compressed_size))
goto zip_load_entry_puked;
len -= 8;
} /* if */
@@ -1059,69 +1221,74 @@
GOTO_IF_MACRO(starting_disk != 0, PHYSFS_ERR_CORRUPT, zip_load_entry_puked);
- entry->offset = offset + ofs_fixup;
+ retval->offset = offset + ofs_fixup;
/* seek to the start of the next entry in the central directory... */
if (!io->seek(io, si64 + extralen + commentlen))
goto zip_load_entry_puked;
- return 1; /* success. */
+ return retval; /* success. */
zip_load_entry_puked:
- allocator.Free(entry->name);
- return 0; /* failure. */
+ allocator.Free(retval);
+ return NULL; /* failure. */
} /* zip_load_entry */
-static int zip_entry_cmp(void *_a, size_t one, size_t two)
-{
- if (one != two)
- {
- const ZIPentry *a = (const ZIPentry *) _a;
- return strcmp(a[one].name, a[two].name);
- } /* if */
-
- return 0;
-} /* zip_entry_cmp */
-
-
-static void zip_entry_swap(void *_a, size_t one, size_t two)
+/* This leaves things allocated on error; the caller will clean up the mess. */
+static int zip_load_entries(ZIPinfo *info,
+ const PHYSFS_uint64 data_ofs,
+ const PHYSFS_uint64 central_ofs,
+ const PHYSFS_uint64 entry_count)
{
- if (one != two)
- {
- ZIPentry tmp;
- ZIPentry *first = &(((ZIPentry *) _a)[one]);
- ZIPentry *second = &(((ZIPentry *) _a)[two]);
- memcpy(&tmp, first, sizeof (ZIPentry));
- memcpy(first, second, sizeof (ZIPentry));
- memcpy(second, &tmp, sizeof (ZIPentry));
- } /* if */
-} /* zip_entry_swap */
-
-
-static int zip_load_entries(PHYSFS_Io *io, ZIPinfo *info,
- const PHYSFS_uint64 data_ofs,
- const PHYSFS_uint64 central_ofs)
-{
- const PHYSFS_uint64 max = info->entryCount;
+ PHYSFS_Io *io = info->io;
const int zip64 = info->zip64;
PHYSFS_uint64 i;
- BAIL_IF_MACRO(!io->seek(io, central_ofs), ERRPASS, 0);
+ if (!io->seek(io, central_ofs))
+ return 0;
- info->entries = (ZIPentry *) allocator.Malloc(sizeof (ZIPentry) * max);
- BAIL_IF_MACRO(!info->entries, PHYSFS_ERR_OUT_OF_MEMORY, 0);
+ for (i = 0; i < entry_count; i++)
+ {
+ ZIPentry *entry = zip_load_entry(io, zip64, data_ofs);
+ ZIPentry *find;
+
+ if (!entry)
+ return 0;
- for (i = 0; i < max; i++)
- {
- if (!zip_load_entry(io, zip64, &info->entries[i], data_ofs))
+ find = zip_find_entry(info, entry->name);
+ if (find != NULL) /* duplicate? */
{
- zip_free_entries(info->entries, i);
+ if (find->last_mod_time != 0) /* duplicate? */
+ {
+ allocator.Free(entry);
+ BAIL_MACRO(PHYSFS_ERR_CORRUPT, 0);
+ } /* if */
+ else /* we filled this in as a placeholder. Update it. */
+ {
+ find->offset = entry->offset;
+ find->version = entry->version;
+ find->version_needed = entry->version_needed;
+ find->compression_method = entry->compression_method;
+ find->crc = entry->crc;
+ find->compressed_size = entry->compressed_size;
+ find->uncompressed_size = entry->uncompressed_size;
+ find->last_mod_time = entry->last_mod_time;
+ allocator.Free(entry);
+ continue;
+ } /* else */
+ } /* if */
+
+ if (!zip_hash_entry(info, entry))
+ {
+ allocator.Free(entry);
return 0;
} /* if */
+
+ if (zip_entry_is_tradional_crypto(entry))
+ info->has_crypto = 1;
} /* for */
- __PHYSFS_sort(info->entries, (size_t) max, zip_entry_cmp, zip_entry_swap);
return 1;
} /* zip_load_entries */
@@ -1181,36 +1348,47 @@
/* Just try moving back at most 256k. Oh well. */
if ((offset < pos) && (pos > 4))
{
- /* we assume you can eat this stack if you handle Zip64 files. */
- PHYSFS_uint8 buf[256 * 1024];
+ const PHYSFS_uint64 maxbuflen = 256 * 1024;
PHYSFS_uint64 len = pos - offset;
+ PHYSFS_uint8 *buf = NULL;
PHYSFS_sint32 i;
- if (len > sizeof (buf))
- len = sizeof (buf);
+ if (len > maxbuflen)
+ len = maxbuflen;
+
+ buf = (PHYSFS_uint8 *) __PHYSFS_smallAlloc(len);
+ BAIL_IF_MACRO(!buf, PHYSFS_ERR_OUT_OF_MEMORY, -1);
- BAIL_IF_MACRO(!io->seek(io, pos - len), ERRPASS, -1);
- BAIL_IF_MACRO(!__PHYSFS_readAll(io, buf, len), ERRPASS, -1);
+ if (!io->seek(io, pos - len) || !__PHYSFS_readAll(io, buf, len))
+ {
+ __PHYSFS_smallFree(buf);
+ return -1; /* error was set elsewhere. */
+ } /* if */
+
for (i = (PHYSFS_sint32) (len - 4); i >= 0; i--)
{
- if (buf[i] != 0x50)
- continue;
- if ( (buf[i+1] == 0x4b) &&
- (buf[i+2] == 0x06) &&
- (buf[i+3] == 0x06) )
+ if ( (buf[i] == 0x50) && (buf[i+1] == 0x4b) &&
+ (buf[i+2] == 0x06) && (buf[i+3] == 0x06) )
+ {
+ __PHYSFS_smallFree(buf);
return pos - (len - i);
+ } /* if */
} /* for */
+
+ __PHYSFS_smallFree(buf);
} /* if */
BAIL_MACRO(PHYSFS_ERR_CORRUPT, -1); /* didn't find it. */
} /* zip64_find_end_of_central_dir */
-static int zip64_parse_end_of_central_dir(PHYSFS_Io *io, ZIPinfo *info,
+static int zip64_parse_end_of_central_dir(ZIPinfo *info,
PHYSFS_uint64 *data_start,
PHYSFS_uint64 *dir_ofs,
+ PHYSFS_uint64 *entry_count,
PHYSFS_sint64 pos)
{
+ PHYSFS_Io *io = info->io;
PHYSFS_uint64 ui64;
PHYSFS_uint32 ui32;
PHYSFS_uint16 ui16;
@@ -1278,8 +1456,8 @@
BAIL_IF_MACRO(!readui64(io, &ui64), ERRPASS, 0);
/* total number of entries in the central dir */
- BAIL_IF_MACRO(!readui64(io, &info->entryCount), ERRPASS, 0);
- BAIL_IF_MACRO(ui64 != info->entryCount, PHYSFS_ERR_CORRUPT, 0);
+ BAIL_IF_MACRO(!readui64(io, entry_count), ERRPASS, 0);
+ BAIL_IF_MACRO(ui64 != *entry_count, PHYSFS_ERR_CORRUPT, 0);
/* size of the central directory */
BAIL_IF_MACRO(!readui64(io, &ui64), ERRPASS, 0);
@@ -1299,10 +1477,12 @@
} /* zip64_parse_end_of_central_dir */
-static int zip_parse_end_of_central_dir(PHYSFS_Io *io, ZIPinfo *info,
+static int zip_parse_end_of_central_dir(ZIPinfo *info,
PHYSFS_uint64 *data_start,
- PHYSFS_uint64 *dir_ofs)
+ PHYSFS_uint64 *dir_ofs,
+ PHYSFS_uint64 *entry_count)
{
+ PHYSFS_Io *io = info->io;
PHYSFS_uint16 entryCount16;
PHYSFS_uint32 offset32;
PHYSFS_uint32 ui32;
@@ -1322,10 +1502,12 @@
/* Seek back to see if "Zip64 end of central directory locator" exists. */
/* this record is 20 bytes before end-of-central-dir */
- rc = zip64_parse_end_of_central_dir(io, info, data_start, dir_ofs, pos-20);
- BAIL_IF_MACRO(rc == 0, ERRPASS, 0);
- if (rc == 1)
- return 1; /* we're done here. */
+ rc = zip64_parse_end_of_central_dir(info, data_start, dir_ofs,
+ entry_count, pos - 20);
+
+ /* Error or success? Bounce out of here. Keep going if not zip64. */
+ if ((rc == 0) || (rc == 1))
+ return rc;
assert(rc == -1); /* no error, just not a Zip64 archive. */
@@ -1347,7 +1529,7 @@
BAIL_IF_MACRO(!readui16(io, &entryCount16), ERRPASS, 0);
BAIL_IF_MACRO(ui16 != entryCount16, PHYSFS_ERR_CORRUPT, 0);
- info->entryCount = entryCount16;
+ *entry_count = entryCount16;
/* size of the central directory */
BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
@@ -1384,11 +1566,30 @@
} /* zip_parse_end_of_central_dir */
+static int zip_alloc_hashtable(ZIPinfo *info, const PHYSFS_uint64 entry_count)
+{
+ size_t alloclen;
+
+ info->hashBuckets = (size_t) (entry_count / 5);
+ if (!info->hashBuckets)
+ info->hashBuckets = 1;
+
+ alloclen = info->hashBuckets * sizeof (ZIPentry *);
+ info->hash = (ZIPentry **) allocator.Malloc(alloclen);
+ BAIL_IF_MACRO(!info->hash, PHYSFS_ERR_OUT_OF_MEMORY, 0);
+ memset(info->hash, '\0', alloclen);
+
+ return 1;
+} /* zip_alloc_hashtable */
+
+static void ZIP_closeArchive(void *opaque);
+
static void *ZIP_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
{
ZIPinfo *info = NULL;
- PHYSFS_uint64 data_start;
- PHYSFS_uint64 cent_dir_ofs;
+ PHYSFS_uint64 dstart; /* data start */
+ PHYSFS_uint64 cdir_ofs; /* central dir offset */
+ PHYSFS_uint64 entry_count;
assert(io != NULL); /* shouldn't ever happen. */
@@ -1398,138 +1599,40 @@
info = (ZIPinfo *) allocator.Malloc(sizeof (ZIPinfo));
BAIL_IF_MACRO(!info, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
memset(info, '\0', sizeof (ZIPinfo));
+ info->root.resolved = ZIP_DIRECTORY;
info->io = io;
- if (!zip_parse_end_of_central_dir(io, info, &data_start, ¢_dir_ofs))
+ if (!zip_parse_end_of_central_dir(info, &dstart, &cdir_ofs, &entry_count))
+ goto ZIP_openarchive_failed;
+ else if (!zip_alloc_hashtable(info, entry_count))
+ goto ZIP_openarchive_failed;
+ else if (!zip_load_entries(info, dstart, cdir_ofs, entry_count))
goto ZIP_openarchive_failed;
- if (!zip_load_entries(io, info, data_start, cent_dir_ofs))
- goto ZIP_openarchive_failed;
-
+ assert(info->root.sibling == NULL);
return info;
ZIP_openarchive_failed:
- if (info != NULL)
- allocator.Free(info);
-
+ info->io = NULL; /* don't let ZIP_closeArchive destroy (io). */
+ ZIP_closeArchive(info);
return NULL;
} /* ZIP_openArchive */
-static PHYSFS_sint64 zip_find_start_of_dir(ZIPinfo *info, const char *path,
- int stop_on_first_find)
-{
- PHYSFS_sint64 lo = 0;
- PHYSFS_sint64 hi = (PHYSFS_sint64) (info->entryCount - 1);
- PHYSFS_sint64 middle;
- PHYSFS_uint32 dlen = (PHYSFS_uint32) strlen(path);
- PHYSFS_sint64 retval = -1;
- const char *name;
- int rc;
-
- if (*path == '\0') /* root dir? */
- return 0;
-
- if ((dlen > 0) && (path[dlen - 1] == '/')) /* ignore trailing slash. */
- dlen--;
-
- while (lo <= hi)
- {
- middle = lo + ((hi - lo) / 2);
- name = info->entries[middle].name;
- rc = strncmp(path, name, dlen);
- if (rc == 0)
- {
- char ch = name[dlen];
- if ('/' < ch) /* make sure this isn't just a substr match. */
- rc = -1;
- else if ('/' > ch)
- rc = 1;
- else
- {
- if (stop_on_first_find) /* Just checking dir's existance? */
- return middle;
-
- if (name[dlen + 1] == '\0') /* Skip initial dir entry. */
- return (middle + 1);
-
- /* there might be more entries earlier in the list. */
- retval = middle;
- hi = middle - 1;
- } /* else */
- } /* if */
-
- if (rc > 0)
- lo = middle + 1;
- else
- hi = middle - 1;
- } /* while */
-
- return retval;
-} /* zip_find_start_of_dir */
-
-
-/*
- * Moved to seperate function so we can use alloca then immediately throw
- * away the allocated stack space...
- */
-static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
- const char *odir, const char *str, PHYSFS_sint32 ln)
-{
- char *newstr = __PHYSFS_smallAlloc(ln + 1);
- if (newstr == NULL)
- return;
-
- memcpy(newstr, str, ln);
- newstr[ln] = '\0';
- cb(callbackdata, odir, newstr);
- __PHYSFS_smallFree(newstr);
-} /* doEnumCallback */
-
-
-static void ZIP_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
- int omitSymLinks, PHYSFS_EnumFilesCallback cb,
+static void ZIP_enumerateFiles(void *opaque, const char *dname,
+ PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
ZIPinfo *info = ((ZIPinfo *) opaque);
- PHYSFS_sint32 dlen, dlen_inc;
- PHYSFS_sint64 i, max;
-
- i = zip_find_start_of_dir(info, dname, 0);
- if (i == -1) /* no such directory. */
- return;
-
- dlen = (PHYSFS_sint32) strlen(dname);
- if ((dlen > 0) && (dname[dlen - 1] == '/')) /* ignore trailing slash. */
- dlen--;
-
- dlen_inc = ((dlen > 0) ? 1 : 0) + dlen;
- max = (PHYSFS_sint64) info->entryCount;
- while (i < max)
+ const ZIPentry *entry = zip_find_entry(info, dname);
+ if (entry && (entry->resolved == ZIP_DIRECTORY))
{
- char *e = info->entries[i].name;
- if ((dlen) && ((strncmp(e, dname, dlen) != 0) || (e[dlen] != '/')))
- break; /* past end of this dir; we're done. */
-
- if ((omitSymLinks) && (zip_entry_is_symlink(&info->entries[i])))
- i++;
- else
+ for (entry = entry->children; entry; entry = entry->sibling)
{
- char *add = e + dlen_inc;
- char *ptr = strchr(add, '/');
- PHYSFS_sint32 ln = (PHYSFS_sint32) ((ptr) ? ptr-add : strlen(add));
- doEnumCallback(cb, callbackdata, origdir, add, ln);
- ln += dlen_inc; /* point past entry to children... */
-
- /* increment counter and skip children of subdirs... */
- while ((++i < max) && (ptr != NULL))
- {
- char *e_new = info->entries[i].name;
- if ((strncmp(e, e_new, ln) != 0) || (e_new[ln] != '/'))
- break;
- } /* while */
- } /* else */
- } /* while */
+ const char *ptr = strrchr(entry->name, '/');
+ cb(callbackdata, origdir, ptr ? ptr + 1 : entry->name);
+ } /* for */
+ } /* if */
} /* ZIP_enumerateFiles */
@@ -1560,15 +1663,33 @@
} /* zip_get_io */
-static PHYSFS_Io *ZIP_openRead(PHYSFS_Dir *opaque, const char *fnm,
- int *fileExists)
+static PHYSFS_Io *ZIP_openRead(void *opaque, const char *filename)
{
PHYSFS_Io *retval = NULL;
ZIPinfo *info = (ZIPinfo *) opaque;
- ZIPentry *entry = zip_find_entry(info, fnm, NULL);
+ ZIPentry *entry = zip_find_entry(info, filename);
ZIPfileinfo *finfo = NULL;
+ PHYSFS_Io *io = NULL;
+ PHYSFS_uint8 *password = NULL;
+ int i;
- *fileExists = (entry != NULL);
+ /* if not found, see if maybe "$PASSWORD" is appended. */
+ if ((!entry) && (info->has_crypto))
+ {
+ const char *ptr = strrchr(filename, '$');
+ if (ptr != NULL)
+ {
+ const PHYSFS_uint64 len = (PHYSFS_uint64) (ptr - filename);
+ char *str = (char *) __PHYSFS_smallAlloc(len + 1);
+ BAIL_IF_MACRO(!str, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
+ memcpy(str, filename, len);
+ str[len] = '\0';
+ entry = zip_find_entry(info, str);
+ __PHYSFS_smallFree(str);
+ password = (PHYSFS_uint8 *) (ptr + 1);
+ } /* if */
+ } /* if */
+
BAIL_IF_MACRO(!entry, ERRPASS, NULL);
retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io));
@@ -1578,8 +1699,9 @@
GOTO_IF_MACRO(!finfo, PHYSFS_ERR_OUT_OF_MEMORY, ZIP_openRead_failed);
memset(finfo, '\0', sizeof (ZIPfileinfo));
- finfo->io = zip_get_io(info->io, info, entry);
- GOTO_IF_MACRO(!finfo->io, ERRPASS, ZIP_openRead_failed);
+ io = zip_get_io(info->io, info, entry);
+ GOTO_IF_MACRO(!io, ERRPASS, ZIP_openRead_failed);
+ finfo->io = io;
finfo->entry = ((entry->symlink != NULL) ? entry->symlink : entry);
initializeZStream(&finfo->stream);
@@ -1592,6 +1714,18 @@
goto ZIP_openRead_failed;
} /* if */
+ if (!zip_entry_is_tradional_crypto(entry))
+ GOTO_IF_MACRO(password != NULL, PHYSFS_ERR_BAD_PASSWORD, ZIP_openRead_failed);
+ else
+ {
+ PHYSFS_uint8 crypto_header[12];
+ GOTO_IF_MACRO(password == NULL, PHYSFS_ERR_BAD_PASSWORD, ZIP_openRead_failed);
+ if (io->read(io, crypto_header, 12) != 12)
+ goto ZIP_openRead_failed;
+ else if (!zip_prep_crypto_keys(finfo, crypto_header, password))
+ goto ZIP_openRead_failed;
+ } /* if */
+
memcpy(retval, &ZIP_Io, sizeof (PHYSFS_Io));
retval->opaque = finfo;
@@ -1619,53 +1753,74 @@
} /* ZIP_openRead */
-static PHYSFS_Io *ZIP_openWrite(PHYSFS_Dir *opaque, const char *filename)
+static PHYSFS_Io *ZIP_openWrite(void *opaque, const char *filename)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* ZIP_openWrite */
-static PHYSFS_Io *ZIP_openAppend(PHYSFS_Dir *opaque, const char *filename)
+static PHYSFS_Io *ZIP_openAppend(void *opaque, const char *filename)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* ZIP_openAppend */
-static void ZIP_closeArchive(PHYSFS_Dir *opaque)
+static void ZIP_closeArchive(void *opaque)
{
- ZIPinfo *zi = (ZIPinfo *) (opaque);
- zi->io->destroy(zi->io);
- zip_free_entries(zi->entries, zi->entryCount);
- allocator.Free(zi);
+ ZIPinfo *info = (ZIPinfo *) (opaque);
+
+ if (!info)
+ return;
+
+ if (info->io)
+ info->io->destroy(info->io);
+
+ assert(info->root.sibling == NULL);
+ assert(info->hash || (info->root.children == NULL));
+
+ if (info->hash)
+ {
+ size_t i;
+ for (i = 0; i < info->hashBuckets; i++)
+ {
+ ZIPentry *entry;
+ ZIPentry *next;
+ for (entry = info->hash[i]; entry; entry = next)
+ {
+ next = entry->hashnext;
+ allocator.Free(entry);
+ } /* for */
+ } /* for */
+ allocator.Free(info->hash);
+ } /* if */
+
+ allocator.Free(info);
} /* ZIP_closeArchive */
-static int ZIP_remove(PHYSFS_Dir *opaque, const char *name)
+static int ZIP_remove(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* ZIP_remove */
-static int ZIP_mkdir(PHYSFS_Dir *opaque, const char *name)
+static int ZIP_mkdir(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* ZIP_mkdir */
-static int ZIP_stat(PHYSFS_Dir *opaque, const char *filename, int *exists,
- PHYSFS_Stat *stat)
+static int ZIP_stat(void *opaque, const char *filename, PHYSFS_Stat *stat)
{
- int isDir = 0;
- const ZIPinfo *info = (const ZIPinfo *) opaque;
- const ZIPentry *entry = zip_find_entry(info, filename, &isDir);
+ ZIPinfo *info = (ZIPinfo *) opaque;
+ const ZIPentry *entry = zip_find_entry(info, filename);
/* !!! FIXME: does this need to resolve entries here? */
- *exists = isDir || (entry != 0);
- if (!*exists)
+ if (entry == NULL)
return 0;
- if (isDir)
+ else if (entry->resolved == ZIP_DIRECTORY)
{
stat->filesize = 0;
stat->filetype = PHYSFS_FILETYPE_DIRECTORY;
@@ -1694,24 +1849,26 @@
const PHYSFS_Archiver __PHYSFS_Archiver_ZIP =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"ZIP",
"PkZip/WinZip/Info-Zip compatible",
"Ryan C. Gordon ",
- "http://icculus.org/physfs/",
+ "https://icculus.org/physfs/",
+ 1, /* supportsSymlinks */
},
- ZIP_openArchive, /* openArchive() method */
- ZIP_enumerateFiles, /* enumerateFiles() method */
- ZIP_openRead, /* openRead() method */
- ZIP_openWrite, /* openWrite() method */
- ZIP_openAppend, /* openAppend() method */
- ZIP_remove, /* remove() method */
- ZIP_mkdir, /* mkdir() method */
- ZIP_closeArchive, /* closeArchive() method */
- ZIP_stat /* stat() method */
+ ZIP_openArchive,
+ ZIP_enumerateFiles,
+ ZIP_openRead,
+ ZIP_openWrite,
+ ZIP_openAppend,
+ ZIP_remove,
+ ZIP_mkdir,
+ ZIP_stat,
+ ZIP_closeArchive
};
#endif /* defined PHYSFS_SUPPORTS_ZIP */
-/* end of zip.c ... */
+/* end of archiver_zip.c ... */
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/7zC.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/7zC.txt Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,237 @@
+7z ANSI-C Decoder 4.48
+----------------------
+
+7z ANSI-C Decoder 4.48 Copyright (C) 1999-2006 Igor Pavlov
+
+7z ANSI-C provides 7z/LZMA decoding.
+7z ANSI-C version is simplified version ported from C++ code.
+
+LZMA is default and general compression method of 7z format
+in 7-Zip compression program (www.7-zip.org). LZMA provides high
+compression ratio and very fast decompression.
+
+
+LICENSE
+-------
+
+Read lzma.txt for information about license.
+
+
+Files
+---------------------
+
+7zAlloc.* - Allocate and Free
+7zBuffer.* - Buffer structure
+7zCrc.* - CRC32 code
+7zDecode.* - Low level memory->memory decoding
+7zExtract.* - High level stream->memory decoding
+7zHeader.* - .7z format constants
+7zIn.* - .7z archive opening
+7zItem.* - .7z structures
+7zMain.c - Test application
+7zMethodID.* - MethodID structure
+7zTypes.h - Base types and constants
+
+
+How To Use
+----------
+
+You must download 7-Zip program from www.7-zip.org.
+
+You can create .7z archive with 7z.exe or 7za.exe:
+
+ 7za.exe a archive.7z *.htm -r -mx -m0fb=255
+
+If you have big number of files in archive, and you need fast extracting,
+you can use partly-solid archives:
+
+ 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K
+
+In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only
+512KB for extracting one file from such archive.
+
+
+Limitations of current version of 7z ANSI-C Decoder
+---------------------------------------------------
+
+ - It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive.
+ - It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters.
+ - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names.
+
+These limitations will be fixed in future versions.
+
+
+Using 7z ANSI-C Decoder Test application:
+-----------------------------------------
+
+Usage: 7zDec
+
+:
+ e: Extract files from archive
+ l: List contents of archive
+ t: Test integrity of archive
+
+Example:
+
+ 7zDec l archive.7z
+
+lists contents of archive.7z
+
+ 7zDec e archive.7z
+
+extracts files from archive.7z to current folder.
+
+
+How to use .7z Decoder
+----------------------
+
+.7z Decoder can be compiled in one of two modes:
+
+1) Default mode. In that mode 7z Decoder will read full compressed
+ block to RAM before decompressing.
+
+2) Mode with defined _LZMA_IN_CB. In that mode 7z Decoder can read
+ compressed block by parts. And you can specify desired buffer size.
+ So memory requirements can be reduced. But decompressing speed will
+ be 5-10% lower and code size is slightly larger.
+
+
+Memory allocation
+~~~~~~~~~~~~~~~~~
+
+7z Decoder uses two memory pools:
+1) Temporary pool
+2) Main pool
+Such scheme can allow you to avoid fragmentation of allocated blocks.
+
+Steps for using 7z decoder
+--------------------------
+
+Use code at 7zMain.c as example.
+
+1) Declare variables:
+ inStream /* implements ISzInStream interface */
+ CArchiveDatabaseEx db; /* 7z archive database structure */
+ ISzAlloc allocImp; /* memory functions for main pool */
+ ISzAlloc allocTempImp; /* memory functions for temporary pool */
+
+2) call InitCrcTable(); function to initialize CRC structures.
+
+3) call SzArDbExInit(&db); function to initialize db structures.
+
+4) call SzArchiveOpen(inStream, &db, &allocMain, &allocTemp) to open archive
+
+This function opens archive "inStream" and reads headers to "db".
+All items in "db" will be allocated with "allocMain" functions.
+SzArchiveOpen function allocates and frees temporary structures by "allocTemp" functions.
+
+5) List items or Extract items
+
+ Listing code:
+ ~~~~~~~~~~~~~
+ {
+ UInt32 i;
+ for (i = 0; i < db.Database.NumFiles; i++)
+ {
+ CFileItem *f = db.Database.Files + i;
+ printf("%10d %s\n", (int)f->Size, f->Name);
+ }
+ }
+
+ Extracting code:
+ ~~~~~~~~~~~~~~~~
+
+ SZ_RESULT SzExtract(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ UInt32 fileIndex, /* index of file */
+ UInt32 *blockIndex, /* index of solid block */
+ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
+ size_t *outBufferSize, /* buffer size for output buffer */
+ size_t *offset, /* offset of stream for required file in *outBuffer */
+ size_t *outSizeProcessed, /* size of file in *outBuffer */
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp);
+
+ If you need to decompress more than one file, you can send these values from previous call:
+ blockIndex,
+ outBuffer,
+ outBufferSize,
+ You can consider "outBuffer" as cache of solid block. If your archive is solid,
+ it will increase decompression speed.
+
+ After decompressing you must free "outBuffer":
+ allocImp.Free(outBuffer);
+
+6) call SzArDbExFree(&db, allocImp.Free) to free allocated items in "db".
+
+
+
+
+Memory requirements for .7z decoding
+------------------------------------
+
+Memory usage for Archive opening:
+ - Temporary pool:
+ - Memory for compressed .7z headers (if _LZMA_IN_CB is not defined)
+ - Memory for uncompressed .7z headers
+ - some other temporary blocks
+ - Main pool:
+ - Memory for database:
+ Estimated size of one file structures in solid archive:
+ - Size (4 or 8 Bytes)
+ - CRC32 (4 bytes)
+ - LastWriteTime (8 bytes)
+ - Some file information (4 bytes)
+ - File Name (variable length) + pointer + allocation structures
+
+Memory usage for archive Decompressing:
+ - Temporary pool:
+ - Memory for compressed solid block (if _LZMA_IN_CB is not defined)
+ - Memory for LZMA decompressing structures
+ - Main pool:
+ - Memory for decompressed solid block
+ - Memory for temprorary buffers, if BCJ2 fileter is used. Usually these
+ temprorary buffers can be about 15% of solid block size.
+
+
+If _LZMA_IN_CB is defined, 7z Decoder will not allocate memory for
+compressed blocks. Instead of this, you must allocate buffer with desired
+size before calling 7z Decoder. Use 7zMain.c as example.
+
+
+
+EXIT codes
+-----------
+
+7z Decoder functions can return one of the following codes:
+
+#define SZ_OK (0)
+#define SZE_DATA_ERROR (1)
+#define SZE_OUTOFMEMORY (2)
+#define SZE_CRC_ERROR (3)
+
+#define SZE_NOTIMPL (4)
+#define SZE_FAIL (5)
+
+#define SZE_ARCHIVE_ERROR (6)
+
+
+
+LZMA Defines
+------------
+
+_LZMA_IN_CB - Use special callback mode for input stream to reduce memory requirements
+
+_SZ_FILE_SIZE_32 - define it if you need only support for files smaller than 4 GB
+_SZ_NO_INT_64 - define it if your compiler doesn't support long long int or __int64.
+
+_LZMA_PROB32 - it can increase LZMA decompressing speed on some 32-bit CPUs.
+
+_SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr.
+
+
+---
+
+http://www.7-zip.org
+http://www.7-zip.org/support.html
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/7zFormat.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/7zFormat.txt Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,471 @@
+7z Format description (2.30 Beta 25)
+-----------------------------------
+
+This file contains description of 7z archive format.
+7z archive can contain files compressed with any method.
+See "Methods.txt" for description for defined compressing methods.
+
+
+Format structure Overview
+-------------------------
+
+Some fields can be optional.
+
+Archive structure
+~~~~~~~~~~~~~~~~~
+SignatureHeader
+[PackedStreams]
+[PackedStreamsForHeaders]
+[
+ Header
+ or
+ {
+ Packed Header
+ HeaderInfo
+ }
+]
+
+
+
+Header structure
+~~~~~~~~~~~~~~~~
+{
+ ArchiveProperties
+ AdditionalStreams
+ {
+ PackInfo
+ {
+ PackPos
+ NumPackStreams
+ Sizes[NumPackStreams]
+ CRCs[NumPackStreams]
+ }
+ CodersInfo
+ {
+ NumFolders
+ Folders[NumFolders]
+ {
+ NumCoders
+ CodersInfo[NumCoders]
+ {
+ ID
+ NumInStreams;
+ NumOutStreams;
+ PropertiesSize
+ Properties[PropertiesSize]
+ }
+ NumBindPairs
+ BindPairsInfo[NumBindPairs]
+ {
+ InIndex;
+ OutIndex;
+ }
+ PackedIndices
+ }
+ UnPackSize[Folders][Folders.NumOutstreams]
+ CRCs[NumFolders]
+ }
+ SubStreamsInfo
+ {
+ NumUnPackStreamsInFolders[NumFolders];
+ UnPackSizes[]
+ CRCs[]
+ }
+ }
+ MainStreamsInfo
+ {
+ (Same as in AdditionalStreams)
+ }
+ FilesInfo
+ {
+ NumFiles
+ Properties[]
+ {
+ ID
+ Size
+ Data
+ }
+ }
+}
+
+HeaderInfo structure
+~~~~~~~~~~~~~~~~~~~~
+{
+ (Same as in AdditionalStreams)
+}
+
+
+
+Notes about Notation and encoding
+---------------------------------
+
+7z uses little endian encoding.
+
+7z archive format has optional headers that are marked as
+[]
+Header
+[]
+
+REAL_UINT64 means real UINT64.
+
+UINT64 means real UINT64 encoded with the following scheme:
+
+ Size of encoding sequence depends from first byte:
+ First_Byte Extra_Bytes Value
+ (binary)
+ 0xxxxxxx : ( xxxxxxx )
+ 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y
+ 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y
+ ...
+ 1111110x BYTE y[6] : ( x << (8 * 6)) + y
+ 11111110 BYTE y[7] : y
+ 11111111 BYTE y[8] : y
+
+
+
+Property IDs
+------------
+
+0x00 = kEnd,
+
+0x01 = kHeader,
+
+0x02 = kArchiveProperties,
+
+0x03 = kAdditionalStreamsInfo,
+0x04 = kMainStreamsInfo,
+0x05 = kFilesInfo,
+
+0x06 = kPackInfo,
+0x07 = kUnPackInfo,
+0x08 = kSubStreamsInfo,
+
+0x09 = kSize,
+0x0A = kCRC,
+
+0x0B = kFolder,
+
+0x0C = kCodersUnPackSize,
+0x0D = kNumUnPackStream,
+
+0x0E = kEmptyStream,
+0x0F = kEmptyFile,
+0x10 = kAnti,
+
+0x11 = kName,
+0x12 = kCreationTime,
+0x13 = kLastAccessTime,
+0x14 = kLastWriteTime,
+0x15 = kWinAttributes,
+0x16 = kComment,
+
+0x17 = kEncodedHeader,
+
+
+7z format headers
+-----------------
+
+SignatureHeader
+~~~~~~~~~~~~~~~
+ BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
+
+ ArchiveVersion
+ {
+ BYTE Major; // now = 0
+ BYTE Minor; // now = 2
+ };
+
+ UINT32 StartHeaderCRC;
+
+ StartHeader
+ {
+ REAL_UINT64 NextHeaderOffset
+ REAL_UINT64 NextHeaderSize
+ UINT32 NextHeaderCRC
+ }
+
+
+...........................
+
+
+ArchiveProperties
+~~~~~~~~~~~~~~~~~
+BYTE NID::kArchiveProperties (0x02)
+for (;;)
+{
+ BYTE PropertyType;
+ if (aType == 0)
+ break;
+ UINT64 PropertySize;
+ BYTE PropertyData[PropertySize];
+}
+
+
+Digests (NumStreams)
+~~~~~~~~~~~~~~~~~~~~~
+ BYTE AllAreDefined
+ if (AllAreDefined == 0)
+ {
+ for(NumStreams)
+ BIT Defined
+ }
+ UINT32 CRCs[NumDefined]
+
+
+PackInfo
+~~~~~~~~~~~~
+ BYTE NID::kPackInfo (0x06)
+ UINT64 PackPos
+ UINT64 NumPackStreams
+
+ []
+ BYTE NID::kSize (0x09)
+ UINT64 PackSizes[NumPackStreams]
+ []
+
+ []
+ BYTE NID::kCRC (0x0A)
+ PackStreamDigests[NumPackStreams]
+ []
+
+ BYTE NID::kEnd
+
+
+Folder
+~~~~~~
+ UINT64 NumCoders;
+ for (NumCoders)
+ {
+ BYTE
+ {
+ 0:3 DecompressionMethod.IDSize
+ 4:
+ 0 - IsSimple
+ 1 - Is not simple
+ 5:
+ 0 - No Attributes
+ 1 - There Are Attributes
+ 7:
+ 0 - Last Method in Alternative_Method_List
+ 1 - There are more alternative methods
+ }
+ BYTE DecompressionMethod.ID[DecompressionMethod.IDSize]
+ if (!IsSimple)
+ {
+ UINT64 NumInStreams;
+ UINT64 NumOutStreams;
+ }
+ if (DecompressionMethod[0] != 0)
+ {
+ UINT64 PropertiesSize
+ BYTE Properties[PropertiesSize]
+ }
+ }
+
+ NumBindPairs = NumOutStreamsTotal - 1;
+
+ for (NumBindPairs)
+ {
+ UINT64 InIndex;
+ UINT64 OutIndex;
+ }
+
+ NumPackedStreams = NumInStreamsTotal - NumBindPairs;
+ if (NumPackedStreams > 1)
+ for(NumPackedStreams)
+ {
+ UINT64 Index;
+ };
+
+
+
+
+Coders Info
+~~~~~~~~~~~
+
+ BYTE NID::kUnPackInfo (0x07)
+
+
+ BYTE NID::kFolder (0x0B)
+ UINT64 NumFolders
+ BYTE External
+ switch(External)
+ {
+ case 0:
+ Folders[NumFolders]
+ case 1:
+ UINT64 DataStreamIndex
+ }
+
+
+ BYTE ID::kCodersUnPackSize (0x0C)
+ for(Folders)
+ for(Folder.NumOutStreams)
+ UINT64 UnPackSize;
+
+
+ []
+ BYTE NID::kCRC (0x0A)
+ UnPackDigests[NumFolders]
+ []
+
+
+
+ BYTE NID::kEnd
+
+
+
+SubStreams Info
+~~~~~~~~~~~~~~
+ BYTE NID::kSubStreamsInfo; (0x08)
+
+ []
+ BYTE NID::kNumUnPackStream; (0x0D)
+ UINT64 NumUnPackStreamsInFolders[NumFolders];
+ []
+
+
+ []
+ BYTE NID::kSize (0x09)
+ UINT64 UnPackSizes[]
+ []
+
+
+ []
+ BYTE NID::kCRC (0x0A)
+ Digests[Number of streams with unknown CRC]
+ []
+
+
+ BYTE NID::kEnd
+
+
+Streams Info
+~~~~~~~~~~~~
+
+ []
+ PackInfo
+ []
+
+
+ []
+ CodersInfo
+ []
+
+
+ []
+ SubStreamsInfo
+ []
+
+ BYTE NID::kEnd
+
+
+FilesInfo
+~~~~~~~~~
+ BYTE NID::kFilesInfo; (0x05)
+ UINT64 NumFiles
+
+ for (;;)
+ {
+ BYTE PropertyType;
+ if (aType == 0)
+ break;
+
+ UINT64 Size;
+
+ switch(PropertyType)
+ {
+ kEmptyStream: (0x0E)
+ for(NumFiles)
+ BIT IsEmptyStream
+
+ kEmptyFile: (0x0F)
+ for(EmptyStreams)
+ BIT IsEmptyFile
+
+ kAnti: (0x10)
+ for(EmptyStreams)
+ BIT IsAntiFile
+
+ case kCreationTime: (0x12)
+ case kLastAccessTime: (0x13)
+ case kLastWriteTime: (0x14)
+ BYTE AllAreDefined
+ if (AllAreDefined == 0)
+ {
+ for(NumFiles)
+ BIT TimeDefined
+ }
+ BYTE External;
+ if(External != 0)
+ UINT64 DataIndex
+ []
+ for(Definded Items)
+ UINT32 Time
+ []
+
+ kNames: (0x11)
+ BYTE External;
+ if(External != 0)
+ UINT64 DataIndex
+ []
+ for(Files)
+ {
+ wchar_t Names[NameSize];
+ wchar_t 0;
+ }
+ []
+
+ kAttributes: (0x15)
+ BYTE AllAreDefined
+ if (AllAreDefined == 0)
+ {
+ for(NumFiles)
+ BIT AttributesAreDefined
+ }
+ BYTE External;
+ if(External != 0)
+ UINT64 DataIndex
+ []
+ for(Definded Attributes)
+ UINT32 Attributes
+ []
+ }
+ }
+
+
+Header
+~~~~~~
+ BYTE NID::kHeader (0x01)
+
+ []
+ ArchiveProperties
+ []
+
+ []
+ BYTE NID::kAdditionalStreamsInfo; (0x03)
+ StreamsInfo
+ []
+
+ []
+ BYTE NID::kMainStreamsInfo; (0x04)
+ StreamsInfo
+ []
+
+ []
+ FilesInfo
+ []
+
+ BYTE NID::kEnd
+
+
+HeaderInfo
+~~~~~~~~~~
+ []
+ BYTE NID::kEncodedHeader; (0x17)
+ StreamsInfo for Encoded Header
+ []
+
+
+---
+End of document
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/7zCrc.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/7zCrc.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,32 @@
+/* 7zCrc.c */
+
+#include "7zCrc.h"
+
+#define kCrcPoly 0xEDB88320
+UInt32 g_CrcTable[256];
+
+void MY_FAST_CALL CrcGenerateTable(void)
+{
+ UInt32 i;
+ for (i = 0; i < 256; i++)
+ {
+ UInt32 r = i;
+ int j;
+ for (j = 0; j < 8; j++)
+ r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
+ g_CrcTable[i] = r;
+ }
+}
+
+UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
+{
+ const Byte *p = (const Byte *)data;
+ for (; size > 0 ; size--, p++)
+ v = CRC_UPDATE_BYTE(v, *p);
+ return v;
+}
+
+UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
+{
+ return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/7zCrc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/7zCrc.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,21 @@
+/* 7zCrc.h */
+
+#ifndef __7Z_CRC_H
+#define __7Z_CRC_H
+
+#include
+
+#include "Types.h"
+
+extern UInt32 g_CrcTable[];
+
+void MY_FAST_CALL CrcGenerateTable(void);
+
+#define CRC_INIT_VAL 0xFFFFFFFF
+#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF)
+#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
+
+UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
+UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/7zCrcT8.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/7zCrcT8.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,40 @@
+/* 7zCrcT8.c */
+
+#include "7zCrc.h"
+
+#define kCrcPoly 0xEDB88320
+#define CRC_NUM_TABLES 8
+
+UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
+
+void MY_FAST_CALL CrcGenerateTable()
+{
+ UInt32 i;
+ for (i = 0; i < 256; i++)
+ {
+ UInt32 r = i;
+ int j;
+ for (j = 0; j < 8; j++)
+ r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
+ g_CrcTable[i] = r;
+ }
+ #if CRC_NUM_TABLES > 1
+ for (; i < 256 * CRC_NUM_TABLES; i++)
+ {
+ UInt32 r = g_CrcTable[i - 256];
+ g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
+ }
+ #endif
+}
+
+UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
+
+UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
+{
+ return CrcUpdateT8(v, data, size, g_CrcTable);
+}
+
+UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
+{
+ return CrcUpdateT8(CRC_INIT_VAL, data, size, g_CrcTable) ^ 0xFFFFFFFF;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Alloc.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Alloc.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,119 @@
+/* Alloc.c */
+
+#ifdef _WIN32
+#include
+#endif
+#include
+
+#include "Alloc.h"
+
+/* #define _SZ_ALLOC_DEBUG */
+
+/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
+#ifdef _SZ_ALLOC_DEBUG
+#include
+int g_allocCount = 0;
+int g_allocCountMid = 0;
+int g_allocCountBig = 0;
+#endif
+
+void *MyAlloc(size_t size)
+{
+ if (size == 0)
+ return 0;
+ #ifdef _SZ_ALLOC_DEBUG
+ fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++);
+ #endif
+ return malloc(size);
+}
+
+void MyFree(void *address)
+{
+ #ifdef _SZ_ALLOC_DEBUG
+ if (address != 0)
+ fprintf(stderr, "\nFree; count = %10d", --g_allocCount);
+ #endif
+ free(address);
+}
+
+#ifdef _WIN32
+
+void *MidAlloc(size_t size)
+{
+ if (size == 0)
+ return 0;
+ #ifdef _SZ_ALLOC_DEBUG
+ fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++);
+ #endif
+ return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
+}
+
+void MidFree(void *address)
+{
+ #ifdef _SZ_ALLOC_DEBUG
+ if (address != 0)
+ fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);
+ #endif
+ if (address == 0)
+ return;
+ VirtualFree(address, 0, MEM_RELEASE);
+}
+
+#ifndef MEM_LARGE_PAGES
+#undef _7ZIP_LARGE_PAGES
+#endif
+
+#ifdef _7ZIP_LARGE_PAGES
+SIZE_T g_LargePageSize = 0;
+typedef SIZE_T (WINAPI *GetLargePageMinimumP)();
+#endif
+
+void SetLargePageSize()
+{
+ #ifdef _7ZIP_LARGE_PAGES
+ SIZE_T size = 0;
+ GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)
+ GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
+ if (largePageMinimum == 0)
+ return;
+ size = largePageMinimum();
+ if (size == 0 || (size & (size - 1)) != 0)
+ return;
+ g_LargePageSize = size;
+ #endif
+}
+
+
+void *BigAlloc(size_t size)
+{
+ if (size == 0)
+ return 0;
+ #ifdef _SZ_ALLOC_DEBUG
+ fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++);
+ #endif
+
+ #ifdef _7ZIP_LARGE_PAGES
+ if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18))
+ {
+ void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),
+ MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
+ if (res != 0)
+ return res;
+ }
+ #endif
+ return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
+}
+
+void BigFree(void *address)
+{
+ #ifdef _SZ_ALLOC_DEBUG
+ if (address != 0)
+ fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);
+ #endif
+
+ if (address == 0)
+ return;
+ VirtualFree(address, 0, MEM_RELEASE);
+}
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Alloc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Alloc.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,29 @@
+/* Alloc.h */
+
+#ifndef __COMMON_ALLOC_H
+#define __COMMON_ALLOC_H
+
+#include
+
+void *MyAlloc(size_t size);
+void MyFree(void *address);
+
+#ifdef _WIN32
+
+void SetLargePageSize();
+
+void *MidAlloc(size_t size);
+void MidFree(void *address);
+void *BigAlloc(size_t size);
+void BigFree(void *address);
+
+#else
+
+#define MidAlloc(size) MyAlloc(size)
+#define MidFree(address) MyFree(address)
+#define BigAlloc(size) MyAlloc(size)
+#define BigFree(address) MyFree(address)
+
+#endif
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zAlloc.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zAlloc.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,70 @@
+/* 7zAlloc.c */
+
+#include
+#include "7zAlloc.h"
+
+/* #define _SZ_ALLOC_DEBUG */
+/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
+
+#ifdef _SZ_ALLOC_DEBUG
+
+#ifdef _WIN32
+#include
+#endif
+#include
+int g_allocCount = 0;
+int g_allocCountTemp = 0;
+#endif
+
+void *SzAlloc(size_t size)
+{
+ if (size == 0)
+ return 0;
+ #ifdef _SZ_ALLOC_DEBUG
+ fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);
+ g_allocCount++;
+ #endif
+ return malloc(size);
+}
+
+void SzFree(void *address)
+{
+ #ifdef _SZ_ALLOC_DEBUG
+ if (address != 0)
+ {
+ g_allocCount--;
+ fprintf(stderr, "\nFree; count = %10d", g_allocCount);
+ }
+ #endif
+ free(address);
+}
+
+void *SzAllocTemp(size_t size)
+{
+ if (size == 0)
+ return 0;
+ #ifdef _SZ_ALLOC_DEBUG
+ fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp);
+ g_allocCountTemp++;
+ #ifdef _WIN32
+ return HeapAlloc(GetProcessHeap(), 0, size);
+ #endif
+ #endif
+ return malloc(size);
+}
+
+void SzFreeTemp(void *address)
+{
+ #ifdef _SZ_ALLOC_DEBUG
+ if (address != 0)
+ {
+ g_allocCountTemp--;
+ fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);
+ }
+ #ifdef _WIN32
+ HeapFree(GetProcessHeap(), 0, address);
+ return;
+ #endif
+ #endif
+ free(address);
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zAlloc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zAlloc.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,20 @@
+/* 7zAlloc.h */
+
+#ifndef __7Z_ALLOC_H
+#define __7Z_ALLOC_H
+
+#include
+
+typedef struct _ISzAlloc
+{
+ void *(*Alloc)(size_t size);
+ void (*Free)(void *address); /* address can be 0 */
+} ISzAlloc;
+
+void *SzAlloc(size_t size);
+void SzFree(void *address);
+
+void *SzAllocTemp(size_t size);
+void SzFreeTemp(void *address);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zBuffer.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zBuffer.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,29 @@
+/* 7zBuffer.c */
+
+#include "7zBuffer.h"
+#include "7zAlloc.h"
+
+void SzByteBufferInit(CSzByteBuffer *buffer)
+{
+ buffer->Capacity = 0;
+ buffer->Items = 0;
+}
+
+int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size))
+{
+ buffer->Capacity = newCapacity;
+ if (newCapacity == 0)
+ {
+ buffer->Items = 0;
+ return 1;
+ }
+ buffer->Items = (Byte *)allocFunc(newCapacity);
+ return (buffer->Items != 0);
+}
+
+void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *))
+{
+ freeFunc(buffer->Items);
+ buffer->Items = 0;
+ buffer->Capacity = 0;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zBuffer.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zBuffer.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,19 @@
+/* 7zBuffer.h */
+
+#ifndef __7Z_BUFFER_H
+#define __7Z_BUFFER_H
+
+#include
+#include "../../Types.h"
+
+typedef struct _CSzByteBuffer
+{
+ size_t Capacity;
+ Byte *Items;
+}CSzByteBuffer;
+
+void SzByteBufferInit(CSzByteBuffer *buffer);
+int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size));
+void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *));
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zDecode.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zDecode.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,345 @@
+/* 7zDecode.c */
+
+#include
+
+/* BEGIN PHYSFS CHANGE */
+#include
+/* END PHYSFS CHANGE */
+
+#include "7zDecode.h"
+#ifdef _SZ_ONE_DIRECTORY
+#include "LzmaDecode.h"
+#else
+#include "../../Compress/Lzma/LzmaDecode.h"
+#include "../../Compress/Branch/BranchX86.h"
+#include "../../Compress/Branch/BranchX86_2.h"
+#endif
+
+#define k_Copy 0
+#define k_LZMA 0x30101
+#define k_BCJ 0x03030103
+#define k_BCJ2 0x0303011B
+
+#ifdef _LZMA_IN_CB
+
+typedef struct _CLzmaInCallbackImp
+{
+ ILzmaInCallback InCallback;
+ ISzInStream *InStream;
+ CFileSize Size;
+} CLzmaInCallbackImp;
+
+int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size)
+{
+ CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object;
+ size_t processedSize;
+ SZ_RESULT res;
+ size_t curSize = (1 << 20);
+ if (curSize > cb->Size)
+ curSize = (size_t)cb->Size;
+ *size = 0;
+ res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, curSize, &processedSize);
+ *size = (SizeT)processedSize;
+ if (processedSize > curSize)
+ return (int)SZE_FAIL;
+ cb->Size -= processedSize;
+ if (res == SZ_OK)
+ return 0;
+ return (int)res;
+}
+
+#endif
+
+SZ_RESULT SzDecodeLzma(CCoderInfo *coder, CFileSize inSize,
+ #ifdef _LZMA_IN_CB
+ ISzInStream *inStream,
+ #else
+ const Byte *inBuffer,
+ #endif
+ Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
+{
+ #ifdef _LZMA_IN_CB
+ CLzmaInCallbackImp lzmaCallback;
+ #else
+ SizeT inProcessed;
+ #endif
+
+ CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
+ int result;
+ SizeT outSizeProcessedLoc;
+
+ #ifdef _LZMA_IN_CB
+ lzmaCallback.Size = inSize;
+ lzmaCallback.InStream = inStream;
+ lzmaCallback.InCallback.Read = LzmaReadImp;
+ #endif
+
+ if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items,
+ (unsigned)coder->Properties.Capacity) != LZMA_RESULT_OK)
+ return SZE_FAIL;
+
+ state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+ if (state.Probs == 0)
+ return SZE_OUTOFMEMORY;
+
+ #ifdef _LZMA_OUT_READ
+ if (state.Properties.DictionarySize == 0)
+ state.Dictionary = 0;
+ else
+ {
+ state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize);
+ if (state.Dictionary == 0)
+ {
+ allocMain->Free(state.Probs);
+ return SZE_OUTOFMEMORY;
+ }
+ }
+ LzmaDecoderInit(&state);
+ #endif
+
+ result = LzmaDecode(&state,
+ #ifdef _LZMA_IN_CB
+ &lzmaCallback.InCallback,
+ #else
+ inBuffer, (SizeT)inSize, &inProcessed,
+ #endif
+ outBuffer, (SizeT)outSize, &outSizeProcessedLoc);
+ allocMain->Free(state.Probs);
+ #ifdef _LZMA_OUT_READ
+ allocMain->Free(state.Dictionary);
+ #endif
+ if (result == LZMA_RESULT_DATA_ERROR)
+ return SZE_DATA_ERROR;
+ if (result != LZMA_RESULT_OK)
+ return SZE_FAIL;
+ return (outSizeProcessedLoc == outSize) ? SZ_OK : SZE_DATA_ERROR;
+}
+
+#ifdef _LZMA_IN_CB
+SZ_RESULT SzDecodeCopy(CFileSize inSize, ISzInStream *inStream, Byte *outBuffer)
+{
+ while (inSize > 0)
+ {
+ void *inBuffer;
+ size_t processedSize, curSize = (1 << 18);
+ if (curSize > inSize)
+ curSize = (size_t)(inSize);
+ RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, curSize, &processedSize));
+ if (processedSize == 0)
+ return SZE_DATA_ERROR;
+ if (processedSize > curSize)
+ return SZE_FAIL;
+ memcpy(outBuffer, inBuffer, processedSize);
+ outBuffer += processedSize;
+ inSize -= processedSize;
+ }
+ return SZ_OK;
+}
+#endif
+
+#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA)
+#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1)
+#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
+#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
+
+SZ_RESULT CheckSupportedFolder(const CFolder *f)
+{
+ if (f->NumCoders < 1 || f->NumCoders > 4)
+ return SZE_NOTIMPL;
+ if (IS_UNSUPPORTED_CODER(f->Coders[0]))
+ return SZE_NOTIMPL;
+ if (f->NumCoders == 1)
+ {
+ if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
+ return SZE_NOTIMPL;
+ return SZ_OK;
+ }
+ if (f->NumCoders == 2)
+ {
+ if (IS_NO_BCJ(f->Coders[1]) ||
+ f->NumPackStreams != 1 || f->PackStreams[0] != 0 ||
+ f->NumBindPairs != 1 ||
+ f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0)
+ return SZE_NOTIMPL;
+ return SZ_OK;
+ }
+ if (f->NumCoders == 4)
+ {
+ if (IS_UNSUPPORTED_CODER(f->Coders[1]) ||
+ IS_UNSUPPORTED_CODER(f->Coders[2]) ||
+ IS_NO_BCJ2(f->Coders[3]))
+ return SZE_NOTIMPL;
+ if (f->NumPackStreams != 4 ||
+ f->PackStreams[0] != 2 ||
+ f->PackStreams[1] != 6 ||
+ f->PackStreams[2] != 1 ||
+ f->PackStreams[3] != 0 ||
+ f->NumBindPairs != 3 ||
+ f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
+ f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
+ f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
+ return SZE_NOTIMPL;
+ return SZ_OK;
+ }
+ return SZE_NOTIMPL;
+}
+
+CFileSize GetSum(const CFileSize *values, UInt32 index)
+{
+ CFileSize sum = 0;
+ UInt32 i;
+ for (i = 0; i < index; i++)
+ sum += values[i];
+ return sum;
+}
+
+SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder,
+ #ifdef _LZMA_IN_CB
+ ISzInStream *inStream, CFileSize startPos,
+ #else
+ const Byte *inBuffer,
+ #endif
+ Byte *outBuffer, size_t outSize, ISzAlloc *allocMain,
+ Byte *tempBuf[])
+{
+ UInt32 ci;
+ size_t tempSizes[3] = { 0, 0, 0};
+ size_t tempSize3 = 0;
+ Byte *tempBuf3 = 0;
+
+ RINOK(CheckSupportedFolder(folder));
+
+ for (ci = 0; ci < folder->NumCoders; ci++)
+ {
+ CCoderInfo *coder = &folder->Coders[ci];
+
+ if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA)
+ {
+ UInt32 si = 0;
+ CFileSize offset;
+ CFileSize inSize;
+ Byte *outBufCur = outBuffer;
+ size_t outSizeCur = outSize;
+ if (folder->NumCoders == 4)
+ {
+ UInt32 indices[] = { 3, 2, 0 };
+ CFileSize unpackSize = folder->UnPackSizes[ci];
+ si = indices[ci];
+ if (ci < 2)
+ {
+ Byte *temp;
+ outSizeCur = (size_t)unpackSize;
+ if (outSizeCur != unpackSize)
+ return SZE_OUTOFMEMORY;
+ temp = (Byte *)allocMain->Alloc(outSizeCur);
+ if (temp == 0 && outSizeCur != 0)
+ return SZE_OUTOFMEMORY;
+ outBufCur = tempBuf[1 - ci] = temp;
+ tempSizes[1 - ci] = outSizeCur;
+ }
+ else if (ci == 2)
+ {
+ if (unpackSize > outSize)
+ return SZE_OUTOFMEMORY;
+ tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
+ tempSize3 = outSizeCur = (size_t)unpackSize;
+ }
+ else
+ return SZE_NOTIMPL;
+ }
+ offset = GetSum(packSizes, si);
+ inSize = packSizes[si];
+ #ifdef _LZMA_IN_CB
+ RINOK(inStream->Seek(inStream, startPos + offset));
+ #endif
+
+ if (coder->MethodID == k_Copy)
+ {
+ if (inSize != outSizeCur)
+ return SZE_DATA_ERROR;
+
+ #ifdef _LZMA_IN_CB
+ RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
+ #else
+ memcpy(outBufCur, inBuffer + (size_t)offset, (size_t)inSize);
+ #endif
+ }
+ else
+ {
+ SZ_RESULT res = SzDecodeLzma(coder, inSize,
+ #ifdef _LZMA_IN_CB
+ inStream,
+ #else
+ inBuffer + (size_t)offset,
+ #endif
+ outBufCur, outSizeCur, allocMain);
+ RINOK(res)
+ }
+ }
+ else if (coder->MethodID == k_BCJ)
+ {
+ UInt32 state;
+ if (ci != 1)
+ return SZE_NOTIMPL;
+ x86_Convert_Init(state);
+ x86_Convert(outBuffer, outSize, 0, &state, 0);
+ }
+ else if (coder->MethodID == k_BCJ2)
+ {
+ CFileSize offset = GetSum(packSizes, 1);
+ CFileSize s3Size = packSizes[1];
+ SZ_RESULT res;
+ if (ci != 3)
+ return SZE_NOTIMPL;
+
+ #ifdef _LZMA_IN_CB
+ RINOK(inStream->Seek(inStream, startPos + offset));
+ tempSizes[2] = (size_t)s3Size;
+ if (tempSizes[2] != s3Size)
+ return SZE_OUTOFMEMORY;
+ tempBuf[2] = (Byte *)allocMain->Alloc(tempSizes[2]);
+ if (tempBuf[2] == 0 && tempSizes[2] != 0)
+ return SZE_OUTOFMEMORY;
+ res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
+ RINOK(res)
+ #endif
+
+ res = x86_2_Decode(
+ tempBuf3, tempSize3,
+ tempBuf[0], tempSizes[0],
+ tempBuf[1], tempSizes[1],
+ #ifdef _LZMA_IN_CB
+ tempBuf[2], tempSizes[2],
+ #else
+ inBuffer + (size_t)offset, (size_t)s3Size,
+ #endif
+ outBuffer, outSize);
+ RINOK(res)
+ }
+ else
+ return SZE_NOTIMPL;
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
+ #ifdef _LZMA_IN_CB
+ ISzInStream *inStream, CFileSize startPos,
+ #else
+ const Byte *inBuffer,
+ #endif
+ Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
+{
+ Byte *tempBuf[3] = { 0, 0, 0};
+ int i;
+ SZ_RESULT res = SzDecode2(packSizes, folder,
+ #ifdef _LZMA_IN_CB
+ inStream, startPos,
+ #else
+ inBuffer,
+ #endif
+ outBuffer, outSize, allocMain, tempBuf);
+ for (i = 0; i < 3; i++)
+ allocMain->Free(tempBuf[i]);
+ return res;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zDecode.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zDecode.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,20 @@
+/* 7zDecode.h */
+
+#ifndef __7Z_DECODE_H
+#define __7Z_DECODE_H
+
+#include "7zItem.h"
+#include "7zAlloc.h"
+#ifdef _LZMA_IN_CB
+#include "7zIn.h"
+#endif
+
+SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
+ #ifdef _LZMA_IN_CB
+ ISzInStream *stream, CFileSize startPos,
+ #else
+ const Byte *inBuffer,
+ #endif
+ Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zExtract.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zExtract.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,119 @@
+/* 7zExtract.c */
+
+#include "7zExtract.h"
+#include "7zDecode.h"
+#include "../../7zCrc.h"
+
+SZ_RESULT SzExtract(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ UInt32 fileIndex,
+ UInt32 *blockIndex,
+ Byte **outBuffer,
+ size_t *outBufferSize,
+ size_t *offset,
+ size_t *outSizeProcessed,
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex];
+ SZ_RESULT res = SZ_OK;
+ *offset = 0;
+ *outSizeProcessed = 0;
+ if (folderIndex == (UInt32)-1)
+ {
+ allocMain->Free(*outBuffer);
+ *blockIndex = folderIndex;
+ *outBuffer = 0;
+ *outBufferSize = 0;
+ return SZ_OK;
+ }
+
+ if (*outBuffer == 0 || *blockIndex != folderIndex)
+ {
+ CFolder *folder = db->Database.Folders + folderIndex;
+ CFileSize unPackSizeSpec = SzFolderGetUnPackSize(folder);
+ size_t unPackSize = (size_t)unPackSizeSpec;
+ CFileSize startOffset = SzArDbGetFolderStreamPos(db, folderIndex, 0);
+ #ifndef _LZMA_IN_CB
+ Byte *inBuffer = 0;
+ size_t processedSize;
+ CFileSize packSizeSpec;
+ size_t packSize;
+ RINOK(SzArDbGetFolderFullPackSize(db, folderIndex, &packSizeSpec));
+ packSize = (size_t)packSizeSpec;
+ if (packSize != packSizeSpec)
+ return SZE_OUTOFMEMORY;
+ #endif
+ if (unPackSize != unPackSizeSpec)
+ return SZE_OUTOFMEMORY;
+ *blockIndex = folderIndex;
+ allocMain->Free(*outBuffer);
+ *outBuffer = 0;
+
+ RINOK(inStream->Seek(inStream, startOffset));
+
+ #ifndef _LZMA_IN_CB
+ if (packSize != 0)
+ {
+ inBuffer = (Byte *)allocTemp->Alloc(packSize);
+ if (inBuffer == 0)
+ return SZE_OUTOFMEMORY;
+ }
+ res = inStream->Read(inStream, inBuffer, packSize, &processedSize);
+ if (res == SZ_OK && processedSize != packSize)
+ res = SZE_FAIL;
+ #endif
+ if (res == SZ_OK)
+ {
+ *outBufferSize = unPackSize;
+ if (unPackSize != 0)
+ {
+ *outBuffer = (Byte *)allocMain->Alloc(unPackSize);
+ if (*outBuffer == 0)
+ res = SZE_OUTOFMEMORY;
+ }
+ if (res == SZ_OK)
+ {
+ res = SzDecode(db->Database.PackSizes +
+ db->FolderStartPackStreamIndex[folderIndex], folder,
+ #ifdef _LZMA_IN_CB
+ inStream, startOffset,
+ #else
+ inBuffer,
+ #endif
+ *outBuffer, unPackSize, allocTemp);
+ if (res == SZ_OK)
+ {
+ if (folder->UnPackCRCDefined)
+ {
+ if (CrcCalc(*outBuffer, unPackSize) != folder->UnPackCRC)
+ res = SZE_CRC_ERROR;
+ }
+ }
+ }
+ }
+ #ifndef _LZMA_IN_CB
+ allocTemp->Free(inBuffer);
+ #endif
+ }
+ if (res == SZ_OK)
+ {
+ UInt32 i;
+ CFileItem *fileItem = db->Database.Files + fileIndex;
+ *offset = 0;
+ for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
+ *offset += (UInt32)db->Database.Files[i].Size;
+ *outSizeProcessed = (size_t)fileItem->Size;
+ if (*offset + *outSizeProcessed > *outBufferSize)
+ return SZE_FAIL;
+ {
+ if (fileItem->IsFileCRCDefined)
+ {
+ if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
+ res = SZE_CRC_ERROR;
+ }
+ }
+ }
+ return res;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zExtract.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zExtract.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,40 @@
+/* 7zExtract.h */
+
+#ifndef __7Z_EXTRACT_H
+#define __7Z_EXTRACT_H
+
+#include "7zIn.h"
+
+/*
+ SzExtract extracts file from archive
+
+ *outBuffer must be 0 before first call for each new archive.
+
+ Extracting cache:
+ If you need to decompress more than one file, you can send
+ these values from previous call:
+ *blockIndex,
+ *outBuffer,
+ *outBufferSize
+ You can consider "*outBuffer" as cache of solid block. If your archive is solid,
+ it will increase decompression speed.
+
+ If you use external function, you can declare these 3 cache variables
+ (blockIndex, outBuffer, outBufferSize) as static in that external function.
+
+ Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
+*/
+
+SZ_RESULT SzExtract(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ UInt32 fileIndex, /* index of file */
+ UInt32 *blockIndex, /* index of solid block */
+ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
+ size_t *outBufferSize, /* buffer size for output buffer */
+ size_t *offset, /* offset of stream for required file in *outBuffer */
+ size_t *outSizeProcessed, /* size of file in *outBuffer */
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zHeader.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zHeader.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,5 @@
+/* 7zHeader.c */
+
+#include "7zHeader.h"
+
+Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zHeader.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zHeader.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,55 @@
+/* 7zHeader.h */
+
+#ifndef __7Z_HEADER_H
+#define __7Z_HEADER_H
+
+#include "../../Types.h"
+
+#define k7zSignatureSize 6
+extern Byte k7zSignature[k7zSignatureSize];
+
+#define k7zMajorVersion 0
+
+#define k7zStartHeaderSize 0x20
+
+enum EIdEnum
+{
+ k7zIdEnd,
+
+ k7zIdHeader,
+
+ k7zIdArchiveProperties,
+
+ k7zIdAdditionalStreamsInfo,
+ k7zIdMainStreamsInfo,
+ k7zIdFilesInfo,
+
+ k7zIdPackInfo,
+ k7zIdUnPackInfo,
+ k7zIdSubStreamsInfo,
+
+ k7zIdSize,
+ k7zIdCRC,
+
+ k7zIdFolder,
+
+ k7zIdCodersUnPackSize,
+ k7zIdNumUnPackStream,
+
+ k7zIdEmptyStream,
+ k7zIdEmptyFile,
+ k7zIdAnti,
+
+ k7zIdName,
+ k7zIdCreationTime,
+ k7zIdLastAccessTime,
+ k7zIdLastWriteTime,
+ k7zIdWinAttributes,
+ k7zIdComment,
+
+ k7zIdEncodedHeader,
+
+ k7zIdStartPos
+};
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zIn.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zIn.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,1314 @@
+/* 7zIn.c */
+
+#include "7zIn.h"
+#include "7zDecode.h"
+#include "../../7zCrc.h"
+
+#define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; }
+
+void SzArDbExInit(CArchiveDatabaseEx *db)
+{
+ SzArchiveDatabaseInit(&db->Database);
+ db->FolderStartPackStreamIndex = 0;
+ db->PackStreamStartPositions = 0;
+ db->FolderStartFileIndex = 0;
+ db->FileIndexToFolderIndexMap = 0;
+}
+
+void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *))
+{
+ freeFunc(db->FolderStartPackStreamIndex);
+ freeFunc(db->PackStreamStartPositions);
+ freeFunc(db->FolderStartFileIndex);
+ freeFunc(db->FileIndexToFolderIndexMap);
+ SzArchiveDatabaseFree(&db->Database, freeFunc);
+ SzArDbExInit(db);
+}
+
+/*
+CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const
+{
+ return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
+}
+
+CFileSize GetFilePackSize(int fileIndex) const
+{
+ int folderIndex = FileIndexToFolderIndexMap[fileIndex];
+ if (folderIndex >= 0)
+ {
+ const CFolder &folderInfo = Folders[folderIndex];
+ if (FolderStartFileIndex[folderIndex] == fileIndex)
+ return GetFolderFullPackSize(folderIndex);
+ }
+ return 0;
+}
+*/
+
+#define MY_ALLOC(T, p, size, allocFunc) { if ((size) == 0) p = 0; else \
+ if ((p = (T *)allocFunc((size) * sizeof(T))) == 0) return SZE_OUTOFMEMORY; }
+
+SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size))
+{
+ UInt32 startPos = 0;
+ CFileSize startPosSize = 0;
+ UInt32 i;
+ UInt32 folderIndex = 0;
+ UInt32 indexInFolder = 0;
+ MY_ALLOC(UInt32, db->FolderStartPackStreamIndex, db->Database.NumFolders, allocFunc);
+ for(i = 0; i < db->Database.NumFolders; i++)
+ {
+ db->FolderStartPackStreamIndex[i] = startPos;
+ startPos += db->Database.Folders[i].NumPackStreams;
+ }
+
+ MY_ALLOC(CFileSize, db->PackStreamStartPositions, db->Database.NumPackStreams, allocFunc);
+
+ for(i = 0; i < db->Database.NumPackStreams; i++)
+ {
+ db->PackStreamStartPositions[i] = startPosSize;
+ startPosSize += db->Database.PackSizes[i];
+ }
+
+ MY_ALLOC(UInt32, db->FolderStartFileIndex, db->Database.NumFolders, allocFunc);
+ MY_ALLOC(UInt32, db->FileIndexToFolderIndexMap, db->Database.NumFiles, allocFunc);
+
+ for (i = 0; i < db->Database.NumFiles; i++)
+ {
+ CFileItem *file = db->Database.Files + i;
+ int emptyStream = !file->HasStream;
+ if (emptyStream && indexInFolder == 0)
+ {
+ db->FileIndexToFolderIndexMap[i] = (UInt32)-1;
+ continue;
+ }
+ if (indexInFolder == 0)
+ {
+ /*
+ v3.13 incorrectly worked with empty folders
+ v4.07: Loop for skipping empty folders
+ */
+ for (;;)
+ {
+ if (folderIndex >= db->Database.NumFolders)
+ return SZE_ARCHIVE_ERROR;
+ db->FolderStartFileIndex[folderIndex] = i;
+ if (db->Database.Folders[folderIndex].NumUnPackStreams != 0)
+ break;
+ folderIndex++;
+ }
+ }
+ db->FileIndexToFolderIndexMap[i] = folderIndex;
+ if (emptyStream)
+ continue;
+ indexInFolder++;
+ if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams)
+ {
+ folderIndex++;
+ indexInFolder = 0;
+ }
+ }
+ return SZ_OK;
+}
+
+
+CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder)
+{
+ return db->ArchiveInfo.DataStartPosition +
+ db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder];
+}
+
+int SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex, CFileSize *resSize)
+{
+ UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex];
+ CFolder *folder = db->Database.Folders + folderIndex;
+ CFileSize size = 0;
+ UInt32 i;
+ for (i = 0; i < folder->NumPackStreams; i++)
+ {
+ CFileSize t = size + db->Database.PackSizes[packStreamIndex + i];
+ if (t < size)
+ return SZE_FAIL;
+ size = t;
+ }
+ *resSize = size;
+ return SZ_OK;
+}
+
+
+/*
+SZ_RESULT SzReadTime(const CObjectVector &dataVector,
+ CObjectVector &files, UInt64 type)
+{
+ CBoolVector boolVector;
+ RINOK(ReadBoolVector2(files.Size(), boolVector))
+
+ CStreamSwitch streamSwitch;
+ RINOK(streamSwitch.Set(this, &dataVector));
+
+ for(int i = 0; i < files.Size(); i++)
+ {
+ CFileItem &file = files[i];
+ CArchiveFileTime fileTime;
+ bool defined = boolVector[i];
+ if (defined)
+ {
+ UInt32 low, high;
+ RINOK(SzReadUInt32(low));
+ RINOK(SzReadUInt32(high));
+ fileTime.dwLowDateTime = low;
+ fileTime.dwHighDateTime = high;
+ }
+ switch(type)
+ {
+ case k7zIdCreationTime:
+ file.IsCreationTimeDefined = defined;
+ if (defined)
+ file.CreationTime = fileTime;
+ break;
+ case k7zIdLastWriteTime:
+ file.IsLastWriteTimeDefined = defined;
+ if (defined)
+ file.LastWriteTime = fileTime;
+ break;
+ case k7zIdLastAccessTime:
+ file.IsLastAccessTimeDefined = defined;
+ if (defined)
+ file.LastAccessTime = fileTime;
+ break;
+ }
+ }
+ return SZ_OK;
+}
+*/
+
+SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size)
+{
+ #ifdef _LZMA_IN_CB
+ while (size > 0)
+ {
+ void *inBufferSpec;
+ size_t processedSize;
+ const Byte *inBuffer;
+ RINOK(inStream->Read(inStream, (void **)&inBufferSpec, size, &processedSize));
+ inBuffer = (const Byte *)inBufferSpec;
+ if (processedSize == 0 || processedSize > size)
+ return SZE_FAIL;
+ size -= processedSize;
+ do
+ {
+ *data++ = *inBuffer++;
+ }
+ while (--processedSize != 0);
+ }
+ #else
+ size_t processedSize;
+ RINOK(inStream->Read(inStream, data, size, &processedSize));
+ if (processedSize != size)
+ return SZE_FAIL;
+ #endif
+ return SZ_OK;
+}
+
+SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data)
+{
+ return SafeReadDirect(inStream, data, 1);
+}
+
+SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value, UInt32 *crc)
+{
+ int i;
+ *value = 0;
+ for (i = 0; i < 4; i++)
+ {
+ Byte b;
+ RINOK(SafeReadDirectByte(inStream, &b));
+ *value |= ((UInt32)b << (8 * i));
+ *crc = CRC_UPDATE_BYTE(*crc, b);
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value, UInt32 *crc)
+{
+ int i;
+ *value = 0;
+ for (i = 0; i < 8; i++)
+ {
+ Byte b;
+ RINOK(SafeReadDirectByte(inStream, &b));
+ *value |= ((UInt64)b << (8 * i));
+ *crc = CRC_UPDATE_BYTE(*crc, b);
+ }
+ return SZ_OK;
+}
+
+int TestSignatureCandidate(Byte *testBytes)
+{
+ size_t i;
+ for (i = 0; i < k7zSignatureSize; i++)
+ if (testBytes[i] != k7zSignature[i])
+ return 0;
+ return 1;
+}
+
+typedef struct _CSzState
+{
+ Byte *Data;
+ size_t Size;
+}CSzData;
+
+SZ_RESULT SzReadByte(CSzData *sd, Byte *b)
+{
+ if (sd->Size == 0)
+ return SZE_ARCHIVE_ERROR;
+ sd->Size--;
+ *b = *sd->Data++;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size)
+{
+ size_t i;
+ for (i = 0; i < size; i++)
+ {
+ RINOK(SzReadByte(sd, data + i));
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value)
+{
+ int i;
+ *value = 0;
+ for (i = 0; i < 4; i++)
+ {
+ Byte b;
+ RINOK(SzReadByte(sd, &b));
+ *value |= ((UInt32)(b) << (8 * i));
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value)
+{
+ Byte firstByte;
+ Byte mask = 0x80;
+ int i;
+ RINOK(SzReadByte(sd, &firstByte));
+ *value = 0;
+ for (i = 0; i < 8; i++)
+ {
+ Byte b;
+ if ((firstByte & mask) == 0)
+ {
+ UInt64 highPart = firstByte & (mask - 1);
+ *value += (highPart << (8 * i));
+ return SZ_OK;
+ }
+ RINOK(SzReadByte(sd, &b));
+ *value |= ((UInt64)b << (8 * i));
+ mask >>= 1;
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value)
+{
+ UInt64 value64;
+ RINOK(SzReadNumber(sd, &value64));
+ *value = (CFileSize)value64;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value)
+{
+ UInt64 value64;
+ RINOK(SzReadNumber(sd, &value64));
+ if (value64 >= 0x80000000)
+ return SZE_NOTIMPL;
+ if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2)))
+ return SZE_NOTIMPL;
+ *value = (UInt32)value64;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadID(CSzData *sd, UInt64 *value)
+{
+ return SzReadNumber(sd, value);
+}
+
+SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size)
+{
+ if (size > sd->Size)
+ return SZE_ARCHIVE_ERROR;
+ sd->Size -= (size_t)size;
+ sd->Data += (size_t)size;
+ return SZ_OK;
+}
+
+SZ_RESULT SzSkeepData(CSzData *sd)
+{
+ UInt64 size;
+ RINOK(SzReadNumber(sd, &size));
+ return SzSkeepDataSize(sd, size);
+}
+
+SZ_RESULT SzReadArchiveProperties(CSzData *sd)
+{
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdEnd)
+ break;
+ SzSkeepData(sd);
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute)
+{
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if (type == attribute)
+ return SZ_OK;
+ if (type == k7zIdEnd)
+ return SZE_ARCHIVE_ERROR;
+ RINOK(SzSkeepData(sd));
+ }
+}
+
+SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size))
+{
+ Byte b = 0;
+ Byte mask = 0;
+ size_t i;
+ MY_ALLOC(Byte, *v, numItems, allocFunc);
+ for (i = 0; i < numItems; i++)
+ {
+ if (mask == 0)
+ {
+ RINOK(SzReadByte(sd, &b));
+ mask = 0x80;
+ }
+ (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0);
+ mask >>= 1;
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size))
+{
+ Byte allAreDefined;
+ size_t i;
+ RINOK(SzReadByte(sd, &allAreDefined));
+ if (allAreDefined == 0)
+ return SzReadBoolVector(sd, numItems, v, allocFunc);
+ MY_ALLOC(Byte, *v, numItems, allocFunc);
+ for(i = 0; i < numItems; i++)
+ (*v)[i] = 1;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadHashDigests(
+ CSzData *sd,
+ size_t numItems,
+ Byte **digestsDefined,
+ UInt32 **digests,
+ void * (*allocFunc)(size_t size))
+{
+ size_t i;
+ RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc));
+ MY_ALLOC(UInt32, *digests, numItems, allocFunc);
+ for(i = 0; i < numItems; i++)
+ if ((*digestsDefined)[i])
+ {
+ RINOK(SzReadUInt32(sd, (*digests) + i));
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadPackInfo(
+ CSzData *sd,
+ CFileSize *dataOffset,
+ UInt32 *numPackStreams,
+ CFileSize **packSizes,
+ Byte **packCRCsDefined,
+ UInt32 **packCRCs,
+ void * (*allocFunc)(size_t size))
+{
+ UInt32 i;
+ RINOK(SzReadSize(sd, dataOffset));
+ RINOK(SzReadNumber32(sd, numPackStreams));
+
+ RINOK(SzWaitAttribute(sd, k7zIdSize));
+
+ MY_ALLOC(CFileSize, *packSizes, (size_t)*numPackStreams, allocFunc);
+
+ for(i = 0; i < *numPackStreams; i++)
+ {
+ RINOK(SzReadSize(sd, (*packSizes) + i));
+ }
+
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdEnd)
+ break;
+ if (type == k7zIdCRC)
+ {
+ RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc));
+ continue;
+ }
+ RINOK(SzSkeepData(sd));
+ }
+ if (*packCRCsDefined == 0)
+ {
+ MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, allocFunc);
+ MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, allocFunc);
+ for(i = 0; i < *numPackStreams; i++)
+ {
+ (*packCRCsDefined)[i] = 0;
+ (*packCRCs)[i] = 0;
+ }
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadSwitch(CSzData *sd)
+{
+ Byte external;
+ RINOK(SzReadByte(sd, &external));
+ return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR;
+}
+
+SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size))
+{
+ UInt32 numCoders;
+ UInt32 numBindPairs;
+ UInt32 numPackedStreams;
+ UInt32 i;
+ UInt32 numInStreams = 0;
+ UInt32 numOutStreams = 0;
+ RINOK(SzReadNumber32(sd, &numCoders));
+ folder->NumCoders = numCoders;
+
+ MY_ALLOC(CCoderInfo, folder->Coders, (size_t)numCoders, allocFunc);
+
+ for (i = 0; i < numCoders; i++)
+ SzCoderInfoInit(folder->Coders + i);
+
+ for (i = 0; i < numCoders; i++)
+ {
+ Byte mainByte;
+ CCoderInfo *coder = folder->Coders + i;
+ {
+ unsigned idSize, j;
+ Byte longID[15];
+ RINOK(SzReadByte(sd, &mainByte));
+ idSize = (unsigned)(mainByte & 0xF);
+ RINOK(SzReadBytes(sd, longID, idSize));
+ if (idSize > sizeof(coder->MethodID))
+ return SZE_NOTIMPL;
+ coder->MethodID = 0;
+ for (j = 0; j < idSize; j++)
+ coder->MethodID |= (CMethodID)longID[idSize - 1 - j] << (8 * j);
+
+ if ((mainByte & 0x10) != 0)
+ {
+ RINOK(SzReadNumber32(sd, &coder->NumInStreams));
+ RINOK(SzReadNumber32(sd, &coder->NumOutStreams));
+ }
+ else
+ {
+ coder->NumInStreams = 1;
+ coder->NumOutStreams = 1;
+ }
+ if ((mainByte & 0x20) != 0)
+ {
+ UInt64 propertiesSize = 0;
+ RINOK(SzReadNumber(sd, &propertiesSize));
+ if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc))
+ return SZE_OUTOFMEMORY;
+ RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize));
+ }
+ }
+ while ((mainByte & 0x80) != 0)
+ {
+ RINOK(SzReadByte(sd, &mainByte));
+ RINOK(SzSkeepDataSize(sd, (mainByte & 0xF)));
+ if ((mainByte & 0x10) != 0)
+ {
+ UInt32 n;
+ RINOK(SzReadNumber32(sd, &n));
+ RINOK(SzReadNumber32(sd, &n));
+ }
+ if ((mainByte & 0x20) != 0)
+ {
+ UInt64 propertiesSize = 0;
+ RINOK(SzReadNumber(sd, &propertiesSize));
+ RINOK(SzSkeepDataSize(sd, propertiesSize));
+ }
+ }
+ numInStreams += (UInt32)coder->NumInStreams;
+ numOutStreams += (UInt32)coder->NumOutStreams;
+ }
+
+ numBindPairs = numOutStreams - 1;
+ folder->NumBindPairs = numBindPairs;
+
+
+ MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, allocFunc);
+
+ for (i = 0; i < numBindPairs; i++)
+ {
+ CBindPair *bindPair = folder->BindPairs + i;;
+ RINOK(SzReadNumber32(sd, &bindPair->InIndex));
+ RINOK(SzReadNumber32(sd, &bindPair->OutIndex));
+ }
+
+ numPackedStreams = numInStreams - (UInt32)numBindPairs;
+
+ folder->NumPackStreams = numPackedStreams;
+ MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackedStreams, allocFunc);
+
+ if (numPackedStreams == 1)
+ {
+ UInt32 j;
+ UInt32 pi = 0;
+ for (j = 0; j < numInStreams; j++)
+ if (SzFolderFindBindPairForInStream(folder, j) < 0)
+ {
+ folder->PackStreams[pi++] = j;
+ break;
+ }
+ }
+ else
+ for(i = 0; i < numPackedStreams; i++)
+ {
+ RINOK(SzReadNumber32(sd, folder->PackStreams + i));
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadUnPackInfo(
+ CSzData *sd,
+ UInt32 *numFolders,
+ CFolder **folders, /* for allocFunc */
+ void * (*allocFunc)(size_t size),
+ ISzAlloc *allocTemp)
+{
+ UInt32 i;
+ RINOK(SzWaitAttribute(sd, k7zIdFolder));
+ RINOK(SzReadNumber32(sd, numFolders));
+ {
+ RINOK(SzReadSwitch(sd));
+
+ MY_ALLOC(CFolder, *folders, (size_t)*numFolders, allocFunc);
+
+ for(i = 0; i < *numFolders; i++)
+ SzFolderInit((*folders) + i);
+
+ for(i = 0; i < *numFolders; i++)
+ {
+ RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc));
+ }
+ }
+
+ RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize));
+
+ for(i = 0; i < *numFolders; i++)
+ {
+ UInt32 j;
+ CFolder *folder = (*folders) + i;
+ UInt32 numOutStreams = SzFolderGetNumOutStreams(folder);
+
+ MY_ALLOC(CFileSize, folder->UnPackSizes, (size_t)numOutStreams, allocFunc);
+
+ for(j = 0; j < numOutStreams; j++)
+ {
+ RINOK(SzReadSize(sd, folder->UnPackSizes + j));
+ }
+ }
+
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdEnd)
+ return SZ_OK;
+ if (type == k7zIdCRC)
+ {
+ SZ_RESULT res;
+ Byte *crcsDefined = 0;
+ UInt32 *crcs = 0;
+ res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc);
+ if (res == SZ_OK)
+ {
+ for(i = 0; i < *numFolders; i++)
+ {
+ CFolder *folder = (*folders) + i;
+ folder->UnPackCRCDefined = crcsDefined[i];
+ folder->UnPackCRC = crcs[i];
+ }
+ }
+ allocTemp->Free(crcs);
+ allocTemp->Free(crcsDefined);
+ RINOK(res);
+ continue;
+ }
+ RINOK(SzSkeepData(sd));
+ }
+}
+
+SZ_RESULT SzReadSubStreamsInfo(
+ CSzData *sd,
+ UInt32 numFolders,
+ CFolder *folders,
+ UInt32 *numUnPackStreams,
+ CFileSize **unPackSizes,
+ Byte **digestsDefined,
+ UInt32 **digests,
+ ISzAlloc *allocTemp)
+{
+ UInt64 type = 0;
+ UInt32 i;
+ UInt32 si = 0;
+ UInt32 numDigests = 0;
+
+ for(i = 0; i < numFolders; i++)
+ folders[i].NumUnPackStreams = 1;
+ *numUnPackStreams = numFolders;
+
+ for (;;)
+ {
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdNumUnPackStream)
+ {
+ *numUnPackStreams = 0;
+ for(i = 0; i < numFolders; i++)
+ {
+ UInt32 numStreams;
+ RINOK(SzReadNumber32(sd, &numStreams));
+ folders[i].NumUnPackStreams = numStreams;
+ *numUnPackStreams += numStreams;
+ }
+ continue;
+ }
+ if (type == k7zIdCRC || type == k7zIdSize)
+ break;
+ if (type == k7zIdEnd)
+ break;
+ RINOK(SzSkeepData(sd));
+ }
+
+ if (*numUnPackStreams == 0)
+ {
+ *unPackSizes = 0;
+ *digestsDefined = 0;
+ *digests = 0;
+ }
+ else
+ {
+ *unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize));
+ RINOM(*unPackSizes);
+ *digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte));
+ RINOM(*digestsDefined);
+ *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32));
+ RINOM(*digests);
+ }
+
+ for(i = 0; i < numFolders; i++)
+ {
+ /*
+ v3.13 incorrectly worked with empty folders
+ v4.07: we check that folder is empty
+ */
+ CFileSize sum = 0;
+ UInt32 j;
+ UInt32 numSubstreams = folders[i].NumUnPackStreams;
+ if (numSubstreams == 0)
+ continue;
+ if (type == k7zIdSize)
+ for (j = 1; j < numSubstreams; j++)
+ {
+ CFileSize size;
+ RINOK(SzReadSize(sd, &size));
+ (*unPackSizes)[si++] = size;
+ sum += size;
+ }
+ (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum;
+ }
+ if (type == k7zIdSize)
+ {
+ RINOK(SzReadID(sd, &type));
+ }
+
+ for(i = 0; i < *numUnPackStreams; i++)
+ {
+ (*digestsDefined)[i] = 0;
+ (*digests)[i] = 0;
+ }
+
+
+ for(i = 0; i < numFolders; i++)
+ {
+ UInt32 numSubstreams = folders[i].NumUnPackStreams;
+ if (numSubstreams != 1 || !folders[i].UnPackCRCDefined)
+ numDigests += numSubstreams;
+ }
+
+
+ si = 0;
+ for (;;)
+ {
+ if (type == k7zIdCRC)
+ {
+ int digestIndex = 0;
+ Byte *digestsDefined2 = 0;
+ UInt32 *digests2 = 0;
+ SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc);
+ if (res == SZ_OK)
+ {
+ for (i = 0; i < numFolders; i++)
+ {
+ CFolder *folder = folders + i;
+ UInt32 numSubstreams = folder->NumUnPackStreams;
+ if (numSubstreams == 1 && folder->UnPackCRCDefined)
+ {
+ (*digestsDefined)[si] = 1;
+ (*digests)[si] = folder->UnPackCRC;
+ si++;
+ }
+ else
+ {
+ UInt32 j;
+ for (j = 0; j < numSubstreams; j++, digestIndex++)
+ {
+ (*digestsDefined)[si] = digestsDefined2[digestIndex];
+ (*digests)[si] = digests2[digestIndex];
+ si++;
+ }
+ }
+ }
+ }
+ allocTemp->Free(digestsDefined2);
+ allocTemp->Free(digests2);
+ RINOK(res);
+ }
+ else if (type == k7zIdEnd)
+ return SZ_OK;
+ else
+ {
+ RINOK(SzSkeepData(sd));
+ }
+ RINOK(SzReadID(sd, &type));
+ }
+}
+
+
+SZ_RESULT SzReadStreamsInfo(
+ CSzData *sd,
+ CFileSize *dataOffset,
+ CArchiveDatabase *db,
+ UInt32 *numUnPackStreams,
+ CFileSize **unPackSizes, /* allocTemp */
+ Byte **digestsDefined, /* allocTemp */
+ UInt32 **digests, /* allocTemp */
+ void * (*allocFunc)(size_t size),
+ ISzAlloc *allocTemp)
+{
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if ((UInt64)(int)type != type)
+ return SZE_FAIL;
+ switch((int)type)
+ {
+ case k7zIdEnd:
+ return SZ_OK;
+ case k7zIdPackInfo:
+ {
+ RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams,
+ &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc));
+ break;
+ }
+ case k7zIdUnPackInfo:
+ {
+ RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp));
+ break;
+ }
+ case k7zIdSubStreamsInfo:
+ {
+ RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders,
+ numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp));
+ break;
+ }
+ default:
+ return SZE_FAIL;
+ }
+ }
+}
+
+Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files,
+ void * (*allocFunc)(size_t size))
+{
+ UInt32 i;
+ for(i = 0; i < numFiles; i++)
+ {
+ UInt32 len = 0;
+ UInt32 pos = 0;
+ CFileItem *file = files + i;
+ while(pos + 2 <= sd->Size)
+ {
+ int numAdds;
+ UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
+ pos += 2;
+ len++;
+ if (value == 0)
+ break;
+ if (value < 0x80)
+ continue;
+ if (value >= 0xD800 && value < 0xE000)
+ {
+ UInt32 c2;
+ if (value >= 0xDC00)
+ return SZE_ARCHIVE_ERROR;
+ if (pos + 2 > sd->Size)
+ return SZE_ARCHIVE_ERROR;
+ c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
+ pos += 2;
+ if (c2 < 0xDC00 || c2 >= 0xE000)
+ return SZE_ARCHIVE_ERROR;
+ value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
+ }
+ for (numAdds = 1; numAdds < 5; numAdds++)
+ if (value < (((UInt32)1) << (numAdds * 5 + 6)))
+ break;
+ len += numAdds;
+ }
+
+ MY_ALLOC(char, file->Name, (size_t)len, allocFunc);
+
+ len = 0;
+ while(2 <= sd->Size)
+ {
+ int numAdds;
+ UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
+ SzSkeepDataSize(sd, 2);
+ if (value < 0x80)
+ {
+ file->Name[len++] = (char)value;
+ if (value == 0)
+ break;
+ continue;
+ }
+ if (value >= 0xD800 && value < 0xE000)
+ {
+ UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
+ SzSkeepDataSize(sd, 2);
+ value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
+ }
+ for (numAdds = 1; numAdds < 5; numAdds++)
+ if (value < (((UInt32)1) << (numAdds * 5 + 6)))
+ break;
+ file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
+ do
+ {
+ numAdds--;
+ file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
+ }
+ while(numAdds > 0);
+
+ len += numAdds;
+ }
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadHeader2(
+ CSzData *sd,
+ CArchiveDatabaseEx *db, /* allocMain */
+ CFileSize **unPackSizes, /* allocTemp */
+ Byte **digestsDefined, /* allocTemp */
+ UInt32 **digests, /* allocTemp */
+ Byte **emptyStreamVector, /* allocTemp */
+ Byte **emptyFileVector, /* allocTemp */
+ Byte **lwtVector, /* allocTemp */
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ UInt64 type;
+ UInt32 numUnPackStreams = 0;
+ UInt32 numFiles = 0;
+ CFileItem *files = 0;
+ UInt32 numEmptyStreams = 0;
+ UInt32 i;
+
+ RINOK(SzReadID(sd, &type));
+
+ if (type == k7zIdArchiveProperties)
+ {
+ RINOK(SzReadArchiveProperties(sd));
+ RINOK(SzReadID(sd, &type));
+ }
+
+
+ if (type == k7zIdMainStreamsInfo)
+ {
+ RINOK(SzReadStreamsInfo(sd,
+ &db->ArchiveInfo.DataStartPosition,
+ &db->Database,
+ &numUnPackStreams,
+ unPackSizes,
+ digestsDefined,
+ digests, allocMain->Alloc, allocTemp));
+ db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader;
+ RINOK(SzReadID(sd, &type));
+ }
+
+ if (type == k7zIdEnd)
+ return SZ_OK;
+ if (type != k7zIdFilesInfo)
+ return SZE_ARCHIVE_ERROR;
+
+ RINOK(SzReadNumber32(sd, &numFiles));
+ db->Database.NumFiles = numFiles;
+
+ MY_ALLOC(CFileItem, files, (size_t)numFiles, allocMain->Alloc);
+
+ db->Database.Files = files;
+ for(i = 0; i < numFiles; i++)
+ SzFileInit(files + i);
+
+ for (;;)
+ {
+ UInt64 type;
+ UInt64 size;
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdEnd)
+ break;
+ RINOK(SzReadNumber(sd, &size));
+
+ if ((UInt64)(int)type != type)
+ {
+ RINOK(SzSkeepDataSize(sd, size));
+ }
+ else
+ switch((int)type)
+ {
+ case k7zIdName:
+ {
+ RINOK(SzReadSwitch(sd));
+ RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc))
+ break;
+ }
+ case k7zIdEmptyStream:
+ {
+ RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc));
+ numEmptyStreams = 0;
+ for (i = 0; i < numFiles; i++)
+ if ((*emptyStreamVector)[i])
+ numEmptyStreams++;
+ break;
+ }
+ case k7zIdEmptyFile:
+ {
+ RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc));
+ break;
+ }
+ case k7zIdLastWriteTime:
+ {
+ RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp->Alloc));
+ RINOK(SzReadSwitch(sd));
+ for (i = 0; i < numFiles; i++)
+ {
+ CFileItem *f = &files[i];
+ Byte defined = (*lwtVector)[i];
+ f->IsLastWriteTimeDefined = defined;
+ f->LastWriteTime.Low = f->LastWriteTime.High = 0;
+ if (defined)
+ {
+ RINOK(SzReadUInt32(sd, &f->LastWriteTime.Low));
+ RINOK(SzReadUInt32(sd, &f->LastWriteTime.High));
+ }
+ }
+ break;
+ }
+ default:
+ {
+ RINOK(SzSkeepDataSize(sd, size));
+ }
+ }
+ }
+
+ {
+ UInt32 emptyFileIndex = 0;
+ UInt32 sizeIndex = 0;
+ for(i = 0; i < numFiles; i++)
+ {
+ CFileItem *file = files + i;
+ file->IsAnti = 0;
+ if (*emptyStreamVector == 0)
+ file->HasStream = 1;
+ else
+ file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1);
+ if(file->HasStream)
+ {
+ file->IsDirectory = 0;
+ file->Size = (*unPackSizes)[sizeIndex];
+ file->FileCRC = (*digests)[sizeIndex];
+ file->IsFileCRCDefined = (Byte)(*digestsDefined)[sizeIndex];
+ sizeIndex++;
+ }
+ else
+ {
+ if (*emptyFileVector == 0)
+ file->IsDirectory = 1;
+ else
+ file->IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);
+ emptyFileIndex++;
+ file->Size = 0;
+ file->IsFileCRCDefined = 0;
+ }
+ }
+ }
+ return SzArDbExFill(db, allocMain->Alloc);
+}
+
+SZ_RESULT SzReadHeader(
+ CSzData *sd,
+ CArchiveDatabaseEx *db,
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ CFileSize *unPackSizes = 0;
+ Byte *digestsDefined = 0;
+ UInt32 *digests = 0;
+ Byte *emptyStreamVector = 0;
+ Byte *emptyFileVector = 0;
+ Byte *lwtVector = 0;
+ SZ_RESULT res = SzReadHeader2(sd, db,
+ &unPackSizes, &digestsDefined, &digests,
+ &emptyStreamVector, &emptyFileVector, &lwtVector,
+ allocMain, allocTemp);
+ allocTemp->Free(unPackSizes);
+ allocTemp->Free(digestsDefined);
+ allocTemp->Free(digests);
+ allocTemp->Free(emptyStreamVector);
+ allocTemp->Free(emptyFileVector);
+ allocTemp->Free(lwtVector);
+ return res;
+}
+
+SZ_RESULT SzReadAndDecodePackedStreams2(
+ ISzInStream *inStream,
+ CSzData *sd,
+ CSzByteBuffer *outBuffer,
+ CFileSize baseOffset,
+ CArchiveDatabase *db,
+ CFileSize **unPackSizes,
+ Byte **digestsDefined,
+ UInt32 **digests,
+ #ifndef _LZMA_IN_CB
+ Byte **inBuffer,
+ #endif
+ ISzAlloc *allocTemp)
+{
+
+ UInt32 numUnPackStreams = 0;
+ CFileSize dataStartPos;
+ CFolder *folder;
+ #ifndef _LZMA_IN_CB
+ CFileSize packSize = 0;
+ UInt32 i = 0;
+ #endif
+ CFileSize unPackSize;
+ SZ_RESULT res;
+
+ RINOK(SzReadStreamsInfo(sd, &dataStartPos, db,
+ &numUnPackStreams, unPackSizes, digestsDefined, digests,
+ allocTemp->Alloc, allocTemp));
+
+ dataStartPos += baseOffset;
+ if (db->NumFolders != 1)
+ return SZE_ARCHIVE_ERROR;
+
+ folder = db->Folders;
+ unPackSize = SzFolderGetUnPackSize(folder);
+
+ RINOK(inStream->Seek(inStream, dataStartPos));
+
+ #ifndef _LZMA_IN_CB
+ for (i = 0; i < db->NumPackStreams; i++)
+ packSize += db->PackSizes[i];
+
+ MY_ALLOC(Byte, *inBuffer, (size_t)packSize, allocTemp->Alloc);
+
+ RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize));
+ #endif
+
+ if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc))
+ return SZE_OUTOFMEMORY;
+
+ res = SzDecode(db->PackSizes, folder,
+ #ifdef _LZMA_IN_CB
+ inStream, dataStartPos,
+ #else
+ *inBuffer,
+ #endif
+ outBuffer->Items, (size_t)unPackSize, allocTemp);
+ RINOK(res)
+ if (folder->UnPackCRCDefined)
+ if (CrcCalc(outBuffer->Items, (size_t)unPackSize) != folder->UnPackCRC)
+ return SZE_FAIL;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadAndDecodePackedStreams(
+ ISzInStream *inStream,
+ CSzData *sd,
+ CSzByteBuffer *outBuffer,
+ CFileSize baseOffset,
+ ISzAlloc *allocTemp)
+{
+ CArchiveDatabase db;
+ CFileSize *unPackSizes = 0;
+ Byte *digestsDefined = 0;
+ UInt32 *digests = 0;
+ #ifndef _LZMA_IN_CB
+ Byte *inBuffer = 0;
+ #endif
+ SZ_RESULT res;
+ SzArchiveDatabaseInit(&db);
+ res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset,
+ &db, &unPackSizes, &digestsDefined, &digests,
+ #ifndef _LZMA_IN_CB
+ &inBuffer,
+ #endif
+ allocTemp);
+ SzArchiveDatabaseFree(&db, allocTemp->Free);
+ allocTemp->Free(unPackSizes);
+ allocTemp->Free(digestsDefined);
+ allocTemp->Free(digests);
+ #ifndef _LZMA_IN_CB
+ allocTemp->Free(inBuffer);
+ #endif
+ return res;
+}
+
+SZ_RESULT SzArchiveOpen2(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ Byte signature[k7zSignatureSize];
+ Byte version;
+ UInt32 crcFromArchive;
+ UInt64 nextHeaderOffset;
+ UInt64 nextHeaderSize;
+ UInt32 nextHeaderCRC;
+ UInt32 crc = 0;
+ CFileSize pos = 0;
+ CSzByteBuffer buffer;
+ CSzData sd;
+ SZ_RESULT res;
+
+ RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize));
+
+ if (!TestSignatureCandidate(signature))
+ return SZE_ARCHIVE_ERROR;
+
+ /*
+ db.Clear();
+ db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;
+ */
+ RINOK(SafeReadDirectByte(inStream, &version));
+ if (version != k7zMajorVersion)
+ return SZE_ARCHIVE_ERROR;
+ RINOK(SafeReadDirectByte(inStream, &version));
+
+ RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive, &crc));
+
+ crc = CRC_INIT_VAL;
+ RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset, &crc));
+ RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize, &crc));
+ RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC, &crc));
+
+ pos = k7zStartHeaderSize;
+ db->ArchiveInfo.StartPositionAfterHeader = pos;
+
+ if (CRC_GET_DIGEST(crc) != crcFromArchive)
+ return SZE_ARCHIVE_ERROR;
+
+ if (nextHeaderSize == 0)
+ return SZ_OK;
+
+ RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset)));
+
+ if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc))
+ return SZE_OUTOFMEMORY;
+
+ res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize);
+ if (res == SZ_OK)
+ {
+ res = SZE_ARCHIVE_ERROR;
+ if (CrcCalc(buffer.Items, (UInt32)nextHeaderSize) == nextHeaderCRC)
+ {
+ for (;;)
+ {
+ UInt64 type;
+ sd.Data = buffer.Items;
+ sd.Size = buffer.Capacity;
+ res = SzReadID(&sd, &type);
+ if (res != SZ_OK)
+ break;
+ if (type == k7zIdHeader)
+ {
+ res = SzReadHeader(&sd, db, allocMain, allocTemp);
+ break;
+ }
+ if (type != k7zIdEncodedHeader)
+ {
+ res = SZE_ARCHIVE_ERROR;
+ break;
+ }
+ {
+ CSzByteBuffer outBuffer;
+ res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer,
+ db->ArchiveInfo.StartPositionAfterHeader,
+ allocTemp);
+ if (res != SZ_OK)
+ {
+ SzByteBufferFree(&outBuffer, allocTemp->Free);
+ break;
+ }
+ SzByteBufferFree(&buffer, allocTemp->Free);
+ buffer.Items = outBuffer.Items;
+ buffer.Capacity = outBuffer.Capacity;
+ }
+ }
+ }
+ }
+ SzByteBufferFree(&buffer, allocTemp->Free);
+ return res;
+}
+
+SZ_RESULT SzArchiveOpen(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp);
+ if (res != SZ_OK)
+ SzArDbExFree(db, allocMain->Free);
+ return res;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zIn.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zIn.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,55 @@
+/* 7zIn.h */
+
+#ifndef __7Z_IN_H
+#define __7Z_IN_H
+
+#include "7zHeader.h"
+#include "7zItem.h"
+#include "7zAlloc.h"
+
+typedef struct _CInArchiveInfo
+{
+ CFileSize StartPositionAfterHeader;
+ CFileSize DataStartPosition;
+}CInArchiveInfo;
+
+typedef struct _CArchiveDatabaseEx
+{
+ CArchiveDatabase Database;
+ CInArchiveInfo ArchiveInfo;
+ UInt32 *FolderStartPackStreamIndex;
+ CFileSize *PackStreamStartPositions;
+ UInt32 *FolderStartFileIndex;
+ UInt32 *FileIndexToFolderIndexMap;
+}CArchiveDatabaseEx;
+
+void SzArDbExInit(CArchiveDatabaseEx *db);
+void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *));
+CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder);
+int SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex, CFileSize *resSize);
+
+typedef struct _ISzInStream
+{
+ #ifdef _LZMA_IN_CB
+ SZ_RESULT (*Read)(
+ void *object, /* pointer to ISzInStream itself */
+ void **buffer, /* out: pointer to buffer with data */
+ size_t maxRequiredSize, /* max required size to read */
+ size_t *processedSize); /* real processed size.
+ processedSize can be less than maxRequiredSize.
+ If processedSize == 0, then there are no more
+ bytes in stream. */
+ #else
+ SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize);
+ #endif
+ SZ_RESULT (*Seek)(void *object, CFileSize pos);
+} ISzInStream;
+
+
+int SzArchiveOpen(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zItem.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zItem.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,134 @@
+/* 7zItem.c */
+
+#include "7zItem.h"
+#include "7zAlloc.h"
+
+void SzCoderInfoInit(CCoderInfo *coder)
+{
+ SzByteBufferInit(&coder->Properties);
+}
+
+void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p))
+{
+ SzByteBufferFree(&coder->Properties, freeFunc);
+ SzCoderInfoInit(coder);
+}
+
+void SzFolderInit(CFolder *folder)
+{
+ folder->NumCoders = 0;
+ folder->Coders = 0;
+ folder->NumBindPairs = 0;
+ folder->BindPairs = 0;
+ folder->NumPackStreams = 0;
+ folder->PackStreams = 0;
+ folder->UnPackSizes = 0;
+ folder->UnPackCRCDefined = 0;
+ folder->UnPackCRC = 0;
+ folder->NumUnPackStreams = 0;
+}
+
+void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p))
+{
+ UInt32 i;
+ for (i = 0; i < folder->NumCoders; i++)
+ SzCoderInfoFree(&folder->Coders[i], freeFunc);
+ freeFunc(folder->Coders);
+ freeFunc(folder->BindPairs);
+ freeFunc(folder->PackStreams);
+ freeFunc(folder->UnPackSizes);
+ SzFolderInit(folder);
+}
+
+UInt32 SzFolderGetNumOutStreams(CFolder *folder)
+{
+ UInt32 result = 0;
+ UInt32 i;
+ for (i = 0; i < folder->NumCoders; i++)
+ result += folder->Coders[i].NumOutStreams;
+ return result;
+}
+
+int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex)
+{
+ UInt32 i;
+ for(i = 0; i < folder->NumBindPairs; i++)
+ if (folder->BindPairs[i].InIndex == inStreamIndex)
+ return i;
+ return -1;
+}
+
+
+int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex)
+{
+ UInt32 i;
+ for(i = 0; i < folder->NumBindPairs; i++)
+ if (folder->BindPairs[i].OutIndex == outStreamIndex)
+ return i;
+ return -1;
+}
+
+CFileSize SzFolderGetUnPackSize(CFolder *folder)
+{
+ int i = (int)SzFolderGetNumOutStreams(folder);
+ if (i == 0)
+ return 0;
+ for (i--; i >= 0; i--)
+ if (SzFolderFindBindPairForOutStream(folder, i) < 0)
+ return folder->UnPackSizes[i];
+ /* throw 1; */
+ return 0;
+}
+
+/*
+int FindPackStreamArrayIndex(int inStreamIndex) const
+{
+ for(int i = 0; i < PackStreams.Size(); i++)
+ if (PackStreams[i] == inStreamIndex)
+ return i;
+ return -1;
+}
+*/
+
+void SzFileInit(CFileItem *fileItem)
+{
+ fileItem->IsFileCRCDefined = 0;
+ fileItem->HasStream = 1;
+ fileItem->IsDirectory = 0;
+ fileItem->IsAnti = 0;
+ fileItem->IsLastWriteTimeDefined = 0;
+ fileItem->Name = 0;
+}
+
+void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p))
+{
+ freeFunc(fileItem->Name);
+ SzFileInit(fileItem);
+}
+
+void SzArchiveDatabaseInit(CArchiveDatabase *db)
+{
+ db->NumPackStreams = 0;
+ db->PackSizes = 0;
+ db->PackCRCsDefined = 0;
+ db->PackCRCs = 0;
+ db->NumFolders = 0;
+ db->Folders = 0;
+ db->NumFiles = 0;
+ db->Files = 0;
+}
+
+void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *))
+{
+ UInt32 i;
+ for (i = 0; i < db->NumFolders; i++)
+ SzFolderFree(&db->Folders[i], freeFunc);
+ for (i = 0; i < db->NumFiles; i++)
+ SzFileFree(&db->Files[i], freeFunc);
+ freeFunc(db->PackSizes);
+ freeFunc(db->PackCRCsDefined);
+ freeFunc(db->PackCRCs);
+ freeFunc(db->Folders);
+ freeFunc(db->Files);
+ SzArchiveDatabaseInit(db);
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zItem.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zItem.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,95 @@
+/* 7zItem.h */
+
+#ifndef __7Z_ITEM_H
+#define __7Z_ITEM_H
+
+#include "7zMethodID.h"
+#include "7zHeader.h"
+#include "7zBuffer.h"
+
+typedef struct _CCoderInfo
+{
+ UInt32 NumInStreams;
+ UInt32 NumOutStreams;
+ CMethodID MethodID;
+ CSzByteBuffer Properties;
+}CCoderInfo;
+
+void SzCoderInfoInit(CCoderInfo *coder);
+void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p));
+
+typedef struct _CBindPair
+{
+ UInt32 InIndex;
+ UInt32 OutIndex;
+}CBindPair;
+
+typedef struct _CFolder
+{
+ UInt32 NumCoders;
+ CCoderInfo *Coders;
+ UInt32 NumBindPairs;
+ CBindPair *BindPairs;
+ UInt32 NumPackStreams;
+ UInt32 *PackStreams;
+ CFileSize *UnPackSizes;
+ int UnPackCRCDefined;
+ UInt32 UnPackCRC;
+
+ UInt32 NumUnPackStreams;
+}CFolder;
+
+void SzFolderInit(CFolder *folder);
+CFileSize SzFolderGetUnPackSize(CFolder *folder);
+int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex);
+UInt32 SzFolderGetNumOutStreams(CFolder *folder);
+CFileSize SzFolderGetUnPackSize(CFolder *folder);
+
+typedef struct _CArchiveFileTime
+{
+ UInt32 Low;
+ UInt32 High;
+} CArchiveFileTime;
+
+typedef struct _CFileItem
+{
+ CArchiveFileTime LastWriteTime;
+ /*
+ CFileSize StartPos;
+ UInt32 Attributes;
+ */
+ CFileSize Size;
+ UInt32 FileCRC;
+ char *Name;
+
+ Byte IsFileCRCDefined;
+ Byte HasStream;
+ Byte IsDirectory;
+ Byte IsAnti;
+ Byte IsLastWriteTimeDefined;
+ /*
+ int AreAttributesDefined;
+ int IsLastWriteTimeDefined;
+ int IsStartPosDefined;
+ */
+}CFileItem;
+
+void SzFileInit(CFileItem *fileItem);
+
+typedef struct _CArchiveDatabase
+{
+ UInt32 NumPackStreams;
+ CFileSize *PackSizes;
+ Byte *PackCRCsDefined;
+ UInt32 *PackCRCs;
+ UInt32 NumFolders;
+ CFolder *Folders;
+ UInt32 NumFiles;
+ CFileItem *Files;
+}CArchiveDatabase;
+
+void SzArchiveDatabaseInit(CArchiveDatabase *db);
+void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *));
+
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zMain.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zMain.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,428 @@
+/*
+7zMain.c
+Test application for 7z Decoder
+LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-06-04)
+*/
+
+#include
+#include
+#include
+
+#ifdef _WIN32
+#define USE_WINDOWS_FUNCTIONS
+#endif
+
+#ifdef USE_WINDOWS_FUNCTIONS
+#include
+#endif
+
+#include "7zIn.h"
+#include "7zExtract.h"
+
+#include "../../7zCrc.h"
+
+
+#ifdef USE_WINDOWS_FUNCTIONS
+typedef HANDLE MY_FILE_HANDLE;
+#else
+typedef FILE *MY_FILE_HANDLE;
+#endif
+
+void ConvertNumberToString(CFileSize value, char *s)
+{
+ char temp[32];
+ int pos = 0;
+ do
+ {
+ temp[pos++] = (char)('0' + (int)(value % 10));
+ value /= 10;
+ }
+ while (value != 0);
+ do
+ *s++ = temp[--pos];
+ while(pos > 0);
+ *s = '\0';
+}
+
+#define PERIOD_4 (4 * 365 + 1)
+#define PERIOD_100 (PERIOD_4 * 25 - 1)
+#define PERIOD_400 (PERIOD_100 * 4 + 1)
+
+void ConvertFileTimeToString(CArchiveFileTime *ft, char *s)
+{
+ unsigned year, mon, day, hour, min, sec;
+ UInt64 v64 = ft->Low | ((UInt64)ft->High << 32);
+ Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ unsigned temp;
+ UInt32 v;
+ v64 /= 10000000;
+ sec = (unsigned)(v64 % 60);
+ v64 /= 60;
+ min = (unsigned)(v64 % 60);
+ v64 /= 60;
+ hour = (unsigned)(v64 % 24);
+ v64 /= 24;
+
+ v = (UInt32)v64;
+
+ year = (unsigned)(1601 + v / PERIOD_400 * 400);
+ v %= PERIOD_400;
+
+ temp = (unsigned)(v / PERIOD_100);
+ if (temp == 4)
+ temp = 3;
+ year += temp * 100;
+ v -= temp * PERIOD_100;
+
+ temp = v / PERIOD_4;
+ if (temp == 25)
+ temp = 24;
+ year += temp * 4;
+ v -= temp * PERIOD_4;
+
+ temp = v / 365;
+ if (temp == 4)
+ temp = 3;
+ year += temp;
+ v -= temp * 365;
+
+ if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
+ ms[1] = 29;
+ for (mon = 1; mon <= 12; mon++)
+ {
+ unsigned s = ms[mon - 1];
+ if (v < s)
+ break;
+ v -= s;
+ }
+ day = (unsigned)v + 1;
+ sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec);
+}
+
+
+#ifdef USE_WINDOWS_FUNCTIONS
+/*
+ ReadFile and WriteFile functions in Windows have BUG:
+ If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
+ from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
+ (Insufficient system resources exist to complete the requested service).
+*/
+#define kChunkSizeMax (1 << 24)
+#endif
+
+size_t MyReadFile(MY_FILE_HANDLE file, void *data, size_t size)
+{
+ if (size == 0)
+ return 0;
+ #ifdef USE_WINDOWS_FUNCTIONS
+ {
+ size_t processedSize = 0;
+ do
+ {
+ DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size;
+ DWORD processedLoc = 0;
+ BOOL res = ReadFile(file, data, curSize, &processedLoc, NULL);
+ data = (void *)((unsigned char *)data + processedLoc);
+ size -= processedLoc;
+ processedSize += processedLoc;
+ if (!res || processedLoc == 0)
+ break;
+ }
+ while (size > 0);
+ return processedSize;
+ }
+ #else
+ return fread(data, 1, size, file);
+ #endif
+}
+
+size_t MyWriteFile(MY_FILE_HANDLE file, void *data, size_t size)
+{
+ if (size == 0)
+ return 0;
+ #ifdef USE_WINDOWS_FUNCTIONS
+ {
+ size_t processedSize = 0;
+ do
+ {
+ DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size;
+ DWORD processedLoc = 0;
+ BOOL res = WriteFile(file, data, curSize, &processedLoc, NULL);
+ data = (void *)((unsigned char *)data + processedLoc);
+ size -= processedLoc;
+ processedSize += processedLoc;
+ if (!res)
+ break;
+ }
+ while (size > 0);
+ return processedSize;
+ }
+ #else
+ return fwrite(data, 1, size, file);
+ #endif
+}
+
+int MyCloseFile(MY_FILE_HANDLE file)
+{
+ #ifdef USE_WINDOWS_FUNCTIONS
+ return (CloseHandle(file) != FALSE) ? 0 : 1;
+ #else
+ return fclose(file);
+ #endif
+}
+
+typedef struct _CFileInStream
+{
+ ISzInStream InStream;
+ MY_FILE_HANDLE File;
+} CFileInStream;
+
+#ifdef _LZMA_IN_CB
+
+#define kBufferSize (1 << 12)
+Byte g_Buffer[kBufferSize];
+
+SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize)
+{
+ CFileInStream *s = (CFileInStream *)object;
+ size_t processedSizeLoc;
+ if (maxRequiredSize > kBufferSize)
+ maxRequiredSize = kBufferSize;
+ processedSizeLoc = MyReadFile(s->File, g_Buffer, maxRequiredSize);
+ *buffer = g_Buffer;
+ if (processedSize != 0)
+ *processedSize = processedSizeLoc;
+ return SZ_OK;
+}
+
+#else
+
+SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize)
+{
+ CFileInStream *s = (CFileInStream *)object;
+ size_t processedSizeLoc = MyReadFile(s->File, buffer, size);
+ if (processedSize != 0)
+ *processedSize = processedSizeLoc;
+ return SZ_OK;
+}
+
+#endif
+
+SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
+{
+ CFileInStream *s = (CFileInStream *)object;
+
+ #ifdef USE_WINDOWS_FUNCTIONS
+ {
+ LARGE_INTEGER value;
+ value.LowPart = (DWORD)pos;
+ value.HighPart = (LONG)((UInt64)pos >> 32);
+ #ifdef _SZ_FILE_SIZE_32
+ /* VC 6.0 has bug with >> 32 shifts. */
+ value.HighPart = 0;
+ #endif
+ value.LowPart = SetFilePointer(s->File, value.LowPart, &value.HighPart, FILE_BEGIN);
+ if (value.LowPart == 0xFFFFFFFF)
+ if(GetLastError() != NO_ERROR)
+ return SZE_FAIL;
+ return SZ_OK;
+ }
+ #else
+ int res = fseek(s->File, (long)pos, SEEK_SET);
+ if (res == 0)
+ return SZ_OK;
+ return SZE_FAIL;
+ #endif
+}
+
+void PrintError(char *sz)
+{
+ printf("\nERROR: %s\n", sz);
+}
+
+int main(int numargs, char *args[])
+{
+ CFileInStream archiveStream;
+ CArchiveDatabaseEx db;
+ SZ_RESULT res;
+ ISzAlloc allocImp;
+ ISzAlloc allocTempImp;
+
+ printf("\n7z ANSI-C Decoder 4.48 Copyright (c) 1999-2007 Igor Pavlov 2007-06-21\n");
+ if (numargs == 1)
+ {
+ printf(
+ "\nUsage: 7zDec \n\n"
+ "\n"
+ " e: Extract files from archive\n"
+ " l: List contents of archive\n"
+ " t: Test integrity of archive\n");
+ return 0;
+ }
+ if (numargs < 3)
+ {
+ PrintError("incorrect command");
+ return 1;
+ }
+
+ archiveStream.File =
+ #ifdef USE_WINDOWS_FUNCTIONS
+ CreateFile(args[2], GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (archiveStream.File == INVALID_HANDLE_VALUE)
+ #else
+ archiveStream.File = fopen(args[2], "rb");
+ if (archiveStream.File == 0)
+ #endif
+ {
+ PrintError("can not open input file");
+ return 1;
+ }
+
+ archiveStream.InStream.Read = SzFileReadImp;
+ archiveStream.InStream.Seek = SzFileSeekImp;
+
+ allocImp.Alloc = SzAlloc;
+ allocImp.Free = SzFree;
+
+ allocTempImp.Alloc = SzAllocTemp;
+ allocTempImp.Free = SzFreeTemp;
+
+ CrcGenerateTable();
+
+ SzArDbExInit(&db);
+ res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp);
+ if (res == SZ_OK)
+ {
+ char *command = args[1];
+ int listCommand = 0;
+ int testCommand = 0;
+ int extractCommand = 0;
+ if (strcmp(command, "l") == 0)
+ listCommand = 1;
+ if (strcmp(command, "t") == 0)
+ testCommand = 1;
+ else if (strcmp(command, "e") == 0)
+ extractCommand = 1;
+
+ if (listCommand)
+ {
+ UInt32 i;
+ for (i = 0; i < db.Database.NumFiles; i++)
+ {
+ CFileItem *f = db.Database.Files + i;
+ char s[32], t[32];
+ ConvertNumberToString(f->Size, s);
+ if (f->IsLastWriteTimeDefined)
+ ConvertFileTimeToString(&f->LastWriteTime, t);
+ else
+ strcpy(t, " ");
+
+ printf("%10s %s %s\n", s, t, f->Name);
+ }
+ }
+ else if (testCommand || extractCommand)
+ {
+ UInt32 i;
+
+ /*
+ if you need cache, use these 3 variables.
+ if you use external function, you can make these variable as static.
+ */
+ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
+ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
+ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
+
+ printf("\n");
+ for (i = 0; i < db.Database.NumFiles; i++)
+ {
+ size_t offset;
+ size_t outSizeProcessed;
+ CFileItem *f = db.Database.Files + i;
+ if (f->IsDirectory)
+ printf("Directory ");
+ else
+ printf(testCommand ?
+ "Testing ":
+ "Extracting");
+ printf(" %s", f->Name);
+ if (f->IsDirectory)
+ {
+ printf("\n");
+ continue;
+ }
+ res = SzExtract(&archiveStream.InStream, &db, i,
+ &blockIndex, &outBuffer, &outBufferSize,
+ &offset, &outSizeProcessed,
+ &allocImp, &allocTempImp);
+ if (res != SZ_OK)
+ break;
+ if (!testCommand)
+ {
+ MY_FILE_HANDLE outputHandle;
+ size_t processedSize;
+ char *fileName = f->Name;
+ size_t nameLen = strlen(f->Name);
+ for (; nameLen > 0; nameLen--)
+ if (f->Name[nameLen - 1] == '/')
+ {
+ fileName = f->Name + nameLen;
+ break;
+ }
+
+ outputHandle =
+ #ifdef USE_WINDOWS_FUNCTIONS
+ CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ,
+ NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (outputHandle == INVALID_HANDLE_VALUE)
+ #else
+ fopen(fileName, "wb+");
+ if (outputHandle == 0)
+ #endif
+ {
+ PrintError("can not open output file");
+ res = SZE_FAIL;
+ break;
+ }
+ processedSize = MyWriteFile(outputHandle, outBuffer + offset, outSizeProcessed);
+ if (processedSize != outSizeProcessed)
+ {
+ PrintError("can not write output file");
+ res = SZE_FAIL;
+ break;
+ }
+ if (MyCloseFile(outputHandle))
+ {
+ PrintError("can not close output file");
+ res = SZE_FAIL;
+ break;
+ }
+ }
+ printf("\n");
+ }
+ allocImp.Free(outBuffer);
+ }
+ else
+ {
+ PrintError("incorrect command");
+ res = SZE_FAIL;
+ }
+ }
+ SzArDbExFree(&db, allocImp.Free);
+
+ MyCloseFile(archiveStream.File);
+ if (res == SZ_OK)
+ {
+ printf("\nEverything is Ok\n");
+ return 0;
+ }
+ if (res == (SZ_RESULT)SZE_NOTIMPL)
+ PrintError("decoder doesn't support this archive");
+ else if (res == (SZ_RESULT)SZE_OUTOFMEMORY)
+ PrintError("can not allocate memory");
+ else if (res == (SZ_RESULT)SZE_CRC_ERROR)
+ PrintError("CRC error");
+ else
+ printf("\nERROR #%d\n", res);
+ return 1;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zMethodID.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zMethodID.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,10 @@
+/* 7zMethodID.c */
+
+#include "7zMethodID.h"
+
+/*
+int AreMethodsEqual(CMethodID *a1, CMethodID *a2)
+{
+ return (*a1 == *a2) ? 1 : 0;
+}
+*/
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7zMethodID.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7zMethodID.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,10 @@
+/* 7zMethodID.h */
+
+#ifndef __7Z_METHOD_ID_H
+#define __7Z_METHOD_ID_H
+
+#include "../../Types.h"
+
+typedef UInt64 CMethodID;
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7z_C.dsp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7z_C.dsp Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,211 @@
+# Microsoft Developer Studio Project File - Name="7z_C" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=7z_C - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "7z_C.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "7z_C.mak" CFG="7z_C - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "7z_C - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "7z_C - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "7z_C - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "7z_C - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "7z_C - Win32 Release"
+# Name "7z_C - Win32 Debug"
+# Begin Group "LZMA"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzma\LzmaDecode.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzma\LzmaDecode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzma\LzmaTypes.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\7zCrc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zCrc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Types.h
+# End Source File
+# End Group
+# Begin Group "Branch"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\BranchTypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\BranchX86.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\BranchX86.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\BranchX86_2.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\BranchX86_2.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\7zAlloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zAlloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zBuffer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zDecode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zDecode.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zExtract.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zExtract.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zHeader.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zIn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zItem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMain.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMethodID.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMethodID.h
+# End Source File
+# End Target
+# End Project
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/7z_C.dsw
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/7z_C.dsw Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "7z_C"=.\7z_C.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/makefile Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,74 @@
+PROG = 7zDec.exe
+
+!IFDEF CPU
+LIBS = $(LIBS) bufferoverflowU.lib
+CFLAGS = $(CFLAGS) -GS- -Zc:forScope -WX -GS- -Gy -W4
+!ENDIF
+
+!IFNDEF O
+!IFDEF CPU
+O=$(CPU)
+!ELSE
+O=O
+!ENDIF
+!ENDIF
+
+CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -D_LZMA_IN_CB
+CFLAGS_O1 = $(CFLAGS) -O1
+CFLAGS_O2 = $(CFLAGS) -O2
+
+LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF
+
+PROGPATH = $O\$(PROG)
+
+COMPL_O1 = $(CPP) $(CFLAGS_O1) $**
+COMPL_O2 = $(CPP) $(CFLAGS_O2) $**
+COMPL = $(CPP) $(CFLAGS_O1) $**
+
+C_OBJS = \
+ $O\7zCrc.obj \
+
+
+7Z_OBJS = \
+ $O\7zAlloc.obj \
+ $O\7zBuffer.obj \
+ $O\7zDecode.obj \
+ $O\7zExtract.obj \
+ $O\7zHeader.obj \
+ $O\7zIn.obj \
+ $O\7zItem.obj \
+ $O\7zMain.obj \
+ $O\7zMethodID.obj \
+
+OBJS = \
+ $(7Z_OBJS) \
+ $O\LzmaDecode.obj \
+ $O\BranchX86.obj \
+ $O\BranchX86_2.obj \
+ $(C_OBJS) \
+
+all: $(PROGPATH)
+
+clean:
+ -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch
+
+$O:
+ if not exist "$O" mkdir "$O"
+
+$(PROGPATH): $O $(OBJS)
+ link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS)
+
+
+$(7Z_OBJS): $(*B).c
+ $(COMPL)
+$O\LzmaDecode.obj: ../../Compress/Lzma/$(*B).c
+ $(COMPL_O2)
+
+$O\BranchX86.obj: ../../Compress/Branch/$(*B).c
+ $(COMPL_O2)
+
+$O\BranchX86_2.obj: ../../Compress/Branch/$(*B).c
+ $(COMPL_O2)
+
+$(C_OBJS): ../../$(*B).c
+ $(COMPL_O2)
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Archive/7z/makefile.gcc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Archive/7z/makefile.gcc Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,55 @@
+PROG = 7zDec
+CXX = g++
+LIB =
+RM = rm -f
+CFLAGS = -c -O2 -Wall -D_LZMA_IN_CB
+
+OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o BranchX86.o BranchX86_2.o
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)
+
+7zAlloc.o: 7zAlloc.c
+ $(CXX) $(CFLAGS) 7zAlloc.c
+
+7zBuffer.o: 7zBuffer.c
+ $(CXX) $(CFLAGS) 7zBuffer.c
+
+7zCrc.o: ../../7zCrc.c
+ $(CXX) $(CFLAGS) ../../7zCrc.c
+
+7zDecode.o: 7zDecode.c
+ $(CXX) $(CFLAGS) 7zDecode.c
+
+7zExtract.o: 7zExtract.c
+ $(CXX) $(CFLAGS) 7zExtract.c
+
+7zHeader.o: 7zHeader.c
+ $(CXX) $(CFLAGS) 7zHeader.c
+
+7zIn.o: 7zIn.c
+ $(CXX) $(CFLAGS) 7zIn.c
+
+7zItem.o: 7zItem.c
+ $(CXX) $(CFLAGS) 7zItem.c
+
+7zMain.o: 7zMain.c
+ $(CXX) $(CFLAGS) 7zMain.c
+
+7zMethodID.o: 7zMethodID.c
+ $(CXX) $(CFLAGS) 7zMethodID.c
+
+LzmaDecode.o: ../../Compress/Lzma/LzmaDecode.c
+ $(CXX) $(CFLAGS) ../../Compress/Lzma/LzmaDecode.c
+
+BranchX86.o: ../../Compress/Branch/BranchX86.c
+ $(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86.c
+
+BranchX86_2.o: ../../Compress/Branch/BranchX86_2.c
+ $(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86_2.c
+
+clean:
+ -$(RM) $(PROG) $(OBJS)
+
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchARM.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchARM.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,26 @@
+/* BranchARM.c */
+
+#include "BranchARM.h"
+
+UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 4 <= size; i += 4)
+ {
+ if (data[i + 3] == 0xEB)
+ {
+ UInt32 dest;
+ UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]);
+ src <<= 2;
+ if (encoding)
+ dest = nowPos + i + 8 + src;
+ else
+ dest = src - (nowPos + i + 8);
+ dest >>= 2;
+ data[i + 2] = (Byte)(dest >> 16);
+ data[i + 1] = (Byte)(dest >> 8);
+ data[i + 0] = (Byte)dest;
+ }
+ }
+ return i;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchARM.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchARM.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,10 @@
+/* BranchARM.h */
+
+#ifndef __BRANCH_ARM_H
+#define __BRANCH_ARM_H
+
+#include "BranchTypes.h"
+
+UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchARMThumb.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchARMThumb.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,35 @@
+/* BranchARMThumb.c */
+
+#include "BranchARMThumb.h"
+
+UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 4 <= size; i += 2)
+ {
+ if ((data[i + 1] & 0xF8) == 0xF0 &&
+ (data[i + 3] & 0xF8) == 0xF8)
+ {
+ UInt32 dest;
+ UInt32 src =
+ ((data[i + 1] & 0x7) << 19) |
+ (data[i + 0] << 11) |
+ ((data[i + 3] & 0x7) << 8) |
+ (data[i + 2]);
+
+ src <<= 1;
+ if (encoding)
+ dest = nowPos + i + 4 + src;
+ else
+ dest = src - (nowPos + i + 4);
+ dest >>= 1;
+
+ data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));
+ data[i + 0] = (Byte)(dest >> 11);
+ data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));
+ data[i + 2] = (Byte)dest;
+ i += 2;
+ }
+ }
+ return i;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchARMThumb.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchARMThumb.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,10 @@
+/* BranchARMThumb.h */
+
+#ifndef __BRANCH_ARM_THUMB_H
+#define __BRANCH_ARM_THUMB_H
+
+#include "BranchTypes.h"
+
+UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchIA64.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchIA64.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,66 @@
+/* BranchIA64.c */
+
+#include "BranchIA64.h"
+
+const Byte kBranchTable[32] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 6, 6, 0, 0, 7, 7,
+ 4, 4, 0, 0, 4, 4, 0, 0
+};
+
+UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 16 <= size; i += 16)
+ {
+ UInt32 instrTemplate = data[i] & 0x1F;
+ UInt32 mask = kBranchTable[instrTemplate];
+ UInt32 bitPos = 5;
+ int slot;
+ for (slot = 0; slot < 3; slot++, bitPos += 41)
+ {
+ UInt32 bytePos, bitRes;
+ UInt64 instruction, instNorm;
+ int j;
+ if (((mask >> slot) & 1) == 0)
+ continue;
+ bytePos = (bitPos >> 3);
+ bitRes = bitPos & 0x7;
+ instruction = 0;
+ for (j = 0; j < 6; j++)
+ instruction += (UInt64)(data[i + j + bytePos]) << (8 * j);
+
+ instNorm = instruction >> bitRes;
+ if (((instNorm >> 37) & 0xF) == 0x5
+ && ((instNorm >> 9) & 0x7) == 0
+ /* && (instNorm & 0x3F)== 0 */
+ )
+ {
+ UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF);
+ UInt32 dest;
+ src |= ((UInt32)(instNorm >> 36) & 1) << 20;
+
+ src <<= 4;
+
+ if (encoding)
+ dest = nowPos + i + src;
+ else
+ dest = src - (nowPos + i);
+
+ dest >>= 4;
+
+ instNorm &= ~((UInt64)(0x8FFFFF) << 13);
+ instNorm |= ((UInt64)(dest & 0xFFFFF) << 13);
+ instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20));
+
+ instruction &= (1 << bitRes) - 1;
+ instruction |= (instNorm << bitRes);
+ for (j = 0; j < 6; j++)
+ data[i + j + bytePos] = (Byte)(instruction >> (8 * j));
+ }
+ }
+ }
+ return i;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchIA64.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchIA64.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,10 @@
+/* BranchIA64.h */
+
+#ifndef __BRANCH_IA64_H
+#define __BRANCH_IA64_H
+
+#include "BranchTypes.h"
+
+UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchPPC.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchPPC.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,36 @@
+/* BranchPPC.c */
+
+#include "BranchPPC.h"
+
+UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 4 <= size; i += 4)
+ {
+ /* PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) */
+ if ((data[i] >> 2) == 0x12 &&
+ (
+ (data[i + 3] & 3) == 1
+ /* || (data[i+3] & 3) == 3 */
+ )
+ )
+ {
+ UInt32 src = ((data[i + 0] & 3) << 24) |
+ (data[i + 1] << 16) |
+ (data[i + 2] << 8) |
+ (data[i + 3] & (~3));
+
+ UInt32 dest;
+ if (encoding)
+ dest = nowPos + i + src;
+ else
+ dest = src - (nowPos + i);
+ data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3));
+ data[i + 1] = (Byte)(dest >> 16);
+ data[i + 2] = (Byte)(dest >> 8);
+ data[i + 3] &= 0x3;
+ data[i + 3] |= dest;
+ }
+ }
+ return i;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchPPC.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchPPC.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,10 @@
+/* BranchPPC.h */
+
+#ifndef __BRANCH_PPC_H
+#define __BRANCH_PPC_H
+
+#include "BranchTypes.h"
+
+UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchSPARC.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchSPARC.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,36 @@
+/* BranchSPARC.c */
+
+#include "BranchSPARC.h"
+
+UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 4 <= size; i += 4)
+ {
+ if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 ||
+ data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0)
+ {
+ UInt32 src =
+ ((UInt32)data[i + 0] << 24) |
+ ((UInt32)data[i + 1] << 16) |
+ ((UInt32)data[i + 2] << 8) |
+ ((UInt32)data[i + 3]);
+ UInt32 dest;
+
+ src <<= 2;
+ if (encoding)
+ dest = nowPos + i + src;
+ else
+ dest = src - (nowPos + i);
+ dest >>= 2;
+
+ dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
+
+ data[i + 0] = (Byte)(dest >> 24);
+ data[i + 1] = (Byte)(dest >> 16);
+ data[i + 2] = (Byte)(dest >> 8);
+ data[i + 3] = (Byte)dest;
+ }
+ }
+ return i;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchSPARC.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchSPARC.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,10 @@
+/* BranchSPARC.h */
+
+#ifndef __BRANCH_SPARC_H
+#define __BRANCH_SPARC_H
+
+#include "BranchTypes.h"
+
+UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchTypes.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchTypes.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,51 @@
+/* BranchTypes.h */
+
+#ifndef __BRANCHTYPES_H
+#define __BRANCHTYPES_H
+
+#ifndef _7ZIP_BYTE_DEFINED
+#define _7ZIP_BYTE_DEFINED
+typedef unsigned char Byte;
+#endif
+
+#ifndef _7ZIP_UINT16_DEFINED
+#define _7ZIP_UINT16_DEFINED
+typedef unsigned short UInt16;
+#endif
+
+#ifndef _7ZIP_UINT32_DEFINED
+#define _7ZIP_UINT32_DEFINED
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef unsigned long UInt32;
+#else
+typedef unsigned int UInt32;
+#endif
+#endif
+
+#ifndef _7ZIP_UINT64_DEFINED
+#define _7ZIP_UINT64_DEFINED
+#ifdef _SZ_NO_INT_64
+typedef unsigned long UInt64;
+#else
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef unsigned __int64 UInt64;
+#else
+typedef unsigned long long int UInt64;
+#endif
+#endif
+#endif
+
+/* #define _LZMA_NO_SYSTEM_SIZE_T */
+/* You can use it, if you don't want */
+
+#ifndef _7ZIP_SIZET_DEFINED
+#define _7ZIP_SIZET_DEFINED
+#ifdef _LZMA_NO_SYSTEM_SIZE_T
+typedef UInt32 SizeT;
+#else
+#include
+typedef size_t SizeT;
+#endif
+#endif
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchX86.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchX86.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,84 @@
+/* BranchX86.c */
+
+#include "BranchX86.h"
+
+#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
+
+const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
+const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
+
+SizeT x86_Convert(Byte *buffer, SizeT endPos, UInt32 nowPos, UInt32 *prevMaskMix, int encoding)
+{
+ SizeT bufferPos = 0, prevPosT;
+ UInt32 prevMask = *prevMaskMix & 0x7;
+ if (endPos < 5)
+ return 0;
+ nowPos += 5;
+ prevPosT = (SizeT)0 - 1;
+
+ for(;;)
+ {
+ Byte *p = buffer + bufferPos;
+ Byte *limit = buffer + endPos - 4;
+ for (; p < limit; p++)
+ if ((*p & 0xFE) == 0xE8)
+ break;
+ bufferPos = (SizeT)(p - buffer);
+ if (p >= limit)
+ break;
+ prevPosT = bufferPos - prevPosT;
+ if (prevPosT > 3)
+ prevMask = 0;
+ else
+ {
+ prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
+ if (prevMask != 0)
+ {
+ Byte b = p[4 - kMaskToBitNumber[prevMask]];
+ if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
+ {
+ prevPosT = bufferPos;
+ prevMask = ((prevMask << 1) & 0x7) | 1;
+ bufferPos++;
+ continue;
+ }
+ }
+ }
+ prevPosT = bufferPos;
+
+ if (Test86MSByte(p[4]))
+ {
+ UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
+ UInt32 dest;
+ for (;;)
+ {
+ Byte b;
+ int index;
+ if (encoding)
+ dest = (nowPos + (UInt32)bufferPos) + src;
+ else
+ dest = src - (nowPos + (UInt32)bufferPos);
+ if (prevMask == 0)
+ break;
+ index = kMaskToBitNumber[prevMask] * 8;
+ b = (Byte)(dest >> (24 - index));
+ if (!Test86MSByte(b))
+ break;
+ src = dest ^ ((1 << (32 - index)) - 1);
+ }
+ p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
+ p[3] = (Byte)(dest >> 16);
+ p[2] = (Byte)(dest >> 8);
+ p[1] = (Byte)dest;
+ bufferPos += 5;
+ }
+ else
+ {
+ prevMask = ((prevMask << 1) & 0x7) | 1;
+ bufferPos++;
+ }
+ }
+ prevPosT = bufferPos - prevPosT;
+ *prevMaskMix = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
+ return bufferPos;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchX86.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchX86.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,12 @@
+/* BranchX86.h */
+
+#ifndef __BRANCHX86_H
+#define __BRANCHX86_H
+
+#include "BranchTypes.h"
+
+#define x86_Convert_Init(state) { state = 0; }
+
+SizeT x86_Convert(Byte *buffer, SizeT endPos, UInt32 nowPos, UInt32 *state, int encoding);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchX86_2.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchX86_2.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,135 @@
+// BranchX86_2.c
+
+#include "BranchX86_2.h"
+
+#include "../../Alloc.h"
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb UInt16
+#endif
+
+#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
+#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
+ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
+
+#define RC_TEST { if (Buffer == BufferLim) return BCJ2_RESULT_DATA_ERROR; }
+
+#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
+
+#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+// #define UpdateBit0(p) Range = bound; *(p) = (CProb)(*(p) + ((kBitModelTotal - *(p)) >> kNumMoveBits));
+// #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) = (CProb)(*(p) - (*(p) >> kNumMoveBits));
+
+int x86_2_Decode(
+ const Byte *buf0, SizeT size0,
+ const Byte *buf1, SizeT size1,
+ const Byte *buf2, SizeT size2,
+ const Byte *buf3, SizeT size3,
+ Byte *outBuf, SizeT outSize)
+{
+ CProb p[256 + 2];
+ SizeT inPos = 0, outPos = 0;
+
+ const Byte *Buffer, *BufferLim;
+ UInt32 Range, Code;
+ Byte prevByte = 0;
+
+ unsigned int i;
+ for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
+ p[i] = kBitModelTotal >> 1;
+ RC_INIT(buf3, size3);
+
+ if (outSize == 0)
+ return BCJ2_RESULT_OK;
+
+ for (;;)
+ {
+ Byte b;
+ CProb *prob;
+ UInt32 bound;
+
+ SizeT limit = size0 - inPos;
+ if (outSize - outPos < limit)
+ limit = outSize - outPos;
+ while (limit != 0)
+ {
+ Byte b = buf0[inPos];
+ outBuf[outPos++] = b;
+ if (IsJ(prevByte, b))
+ break;
+ inPos++;
+ prevByte = b;
+ limit--;
+ }
+
+ if (limit == 0 || outPos == outSize)
+ break;
+
+ b = buf0[inPos++];
+
+ if (b == 0xE8)
+ prob = p + prevByte;
+ else if (b == 0xE9)
+ prob = p + 256;
+ else
+ prob = p + 257;
+
+ IfBit0(prob)
+ {
+ UpdateBit0(prob)
+ prevByte = b;
+ }
+ else
+ {
+ UInt32 dest;
+ const Byte *v;
+ UpdateBit1(prob)
+ if (b == 0xE8)
+ {
+ v = buf1;
+ if (size1 < 4)
+ return BCJ2_RESULT_DATA_ERROR;
+ buf1 += 4;
+ size1 -= 4;
+ }
+ else
+ {
+ v = buf2;
+ if (size2 < 4)
+ return BCJ2_RESULT_DATA_ERROR;
+ buf2 += 4;
+ size2 -= 4;
+ }
+ dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
+ ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
+ outBuf[outPos++] = (Byte)dest;
+ if (outPos == outSize)
+ break;
+ outBuf[outPos++] = (Byte)(dest >> 8);
+ if (outPos == outSize)
+ break;
+ outBuf[outPos++] = (Byte)(dest >> 16);
+ if (outPos == outSize)
+ break;
+ outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
+ }
+ }
+ return (outPos == outSize) ? BCJ2_RESULT_OK : BCJ2_RESULT_DATA_ERROR;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Branch/BranchX86_2.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Branch/BranchX86_2.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,28 @@
+// BranchX86_2.h
+
+#ifndef __BRANCHX86_2_H
+#define __BRANCHX86_2_H
+
+#include "BranchTypes.h"
+
+#define BCJ2_RESULT_OK 0
+#define BCJ2_RESULT_DATA_ERROR 1
+
+/*
+Conditions:
+ outSize <= FullOutputSize,
+ where FullOutputSize is full size of output stream of x86_2 filter.
+
+If buf0 overlaps outBuf, there are two required conditions:
+ 1) (buf0 >= outBuf)
+ 2) (buf0 + size0 >= outBuf + FullOutputSize).
+*/
+
+int x86_2_Decode(
+ const Byte *buf0, SizeT size0,
+ const Byte *buf1, SizeT size1,
+ const Byte *buf2, SizeT size2,
+ const Byte *buf3, SizeT size3,
+ Byte *outBuf, SizeT outSize);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Huffman/HuffmanEncode.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Huffman/HuffmanEncode.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,146 @@
+/* Compress/HuffmanEncode.c */
+
+#include "HuffmanEncode.h"
+#include "../../Sort.h"
+
+#define kMaxLen 16
+#define NUM_BITS 10
+#define MASK ((1 << NUM_BITS) - 1)
+
+#define NUM_COUNTERS 64
+
+/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize > 1M */
+#define HUFFMAN_SPEED_OPT
+
+void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen)
+{
+ UInt32 num = 0;
+ /* if (maxLen > 10) maxLen = 10; */
+ {
+ UInt32 i;
+
+ #ifdef HUFFMAN_SPEED_OPT
+
+ UInt32 counters[NUM_COUNTERS];
+ for (i = 0; i < NUM_COUNTERS; i++)
+ counters[i] = 0;
+ for (i = 0; i < numSymbols; i++)
+ {
+ UInt32 freq = freqs[i];
+ counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++;
+ }
+
+ for (i = 1; i < NUM_COUNTERS; i++)
+ {
+ UInt32 temp = counters[i];
+ counters[i] = num;
+ num += temp;
+ }
+
+ for (i = 0; i < numSymbols; i++)
+ {
+ UInt32 freq = freqs[i];
+ if (freq == 0)
+ lens[i] = 0;
+ else
+ p[counters[((freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1)]++] = i | (freq << NUM_BITS);
+ }
+ counters[0] = 0;
+ HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]);
+
+ #else
+
+ for (i = 0; i < numSymbols; i++)
+ {
+ UInt32 freq = freqs[i];
+ if (freq == 0)
+ lens[i] = 0;
+ else
+ p[num++] = i | (freq << NUM_BITS);
+ }
+ HeapSort(p, num);
+
+ #endif
+ }
+
+ if (num < 2)
+ {
+ int minCode = 0;
+ int maxCode = 1;
+ if (num == 1)
+ {
+ maxCode = p[0] & MASK;
+ if (maxCode == 0)
+ maxCode++;
+ }
+ p[minCode] = 0;
+ p[maxCode] = 1;
+ lens[minCode] = lens[maxCode] = 1;
+ return;
+ }
+
+ {
+ UInt32 b, e, i;
+
+ i = b = e = 0;
+ do
+ {
+ UInt32 n, m, freq;
+ n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
+ freq = (p[n] & ~MASK);
+ p[n] = (p[n] & MASK) | (e << NUM_BITS);
+ m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
+ freq += (p[m] & ~MASK);
+ p[m] = (p[m] & MASK) | (e << NUM_BITS);
+ p[e] = (p[e] & MASK) | freq;
+ e++;
+ }
+ while (num - e > 1);
+
+ {
+ UInt32 lenCounters[kMaxLen + 1];
+ for (i = 0; i <= kMaxLen; i++)
+ lenCounters[i] = 0;
+
+ p[--e] &= MASK;
+ lenCounters[1] = 2;
+ while (e > 0)
+ {
+ UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1;
+ p[e] = (p[e] & MASK) | (len << NUM_BITS);
+ if (len >= maxLen)
+ for (len = maxLen - 1; lenCounters[len] == 0; len--);
+ lenCounters[len]--;
+ lenCounters[len + 1] += 2;
+ }
+
+ {
+ UInt32 len;
+ i = 0;
+ for (len = maxLen; len != 0; len--)
+ {
+ UInt32 num;
+ for (num = lenCounters[len]; num != 0; num--)
+ lens[p[i++] & MASK] = (Byte)len;
+ }
+ }
+
+ {
+ UInt32 nextCodes[kMaxLen + 1];
+ {
+ UInt32 code = 0;
+ UInt32 len;
+ for (len = 1; len <= kMaxLen; len++)
+ nextCodes[len] = code = (code + lenCounters[len - 1]) << 1;
+ }
+ /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */
+
+ {
+ UInt32 i;
+ for (i = 0; i < numSymbols; i++)
+ p[i] = nextCodes[lens[i]]++;
+ }
+ }
+ }
+ }
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Huffman/HuffmanEncode.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Huffman/HuffmanEncode.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,18 @@
+/* Compress/HuffmanEncode.h */
+
+#ifndef __COMPRESS_HUFFMANENCODE_H
+#define __COMPRESS_HUFFMANENCODE_H
+
+#include "../../Types.h"
+
+/*
+Conditions:
+ num <= 1024 = 2 ^ NUM_BITS
+ Sum(freqs) < 4M = 2 ^ (32 - NUM_BITS)
+ maxLen <= 16 = kMaxLen
+ Num_Items(p) >= HUFFMAN_TEMP_SIZE(num)
+*/
+
+void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Lz/LzHash.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Lz/LzHash.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,53 @@
+/* LzHash.h */
+
+#ifndef __C_LZHASH_H
+#define __C_LZHASH_H
+
+#define kHash2Size (1 << 10)
+#define kHash3Size (1 << 16)
+#define kHash4Size (1 << 20)
+
+#define kFix3HashSize (kHash2Size)
+#define kFix4HashSize (kHash2Size + kHash3Size)
+#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
+
+#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
+
+#define HASH3_CALC { \
+ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
+
+#define HASH4_CALC { \
+ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & p->hashMask; }
+
+#define HASH5_CALC { \
+ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)); \
+ hashValue = (hash4Value ^ (g_CrcTable[cur[4]] << 3)) & p->hashMask; \
+ hash4Value &= (kHash4Size - 1); }
+
+/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ g_CrcTable[cur[2]]) & 0xFFFF; */
+#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ g_CrcTable[cur[1]]) & 0xFFFF;
+
+
+#define MT_HASH2_CALC \
+ hash2Value = (g_CrcTable[cur[0]] ^ cur[1]) & (kHash2Size - 1);
+
+#define MT_HASH3_CALC { \
+ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
+
+#define MT_HASH4_CALC { \
+ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & (kHash4Size - 1); }
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Lz/MatchFinder.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Lz/MatchFinder.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,742 @@
+/* MatchFinder.c */
+/* Please call InitCrcTable before */
+
+#include
+
+#include "MatchFinder.h"
+#include "LzHash.h"
+
+#include "../../7zCrc.h"
+
+#define kEmptyHashValue 0
+#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
+#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
+#define kNormalizeMask (~(kNormalizeStepMin - 1))
+#define kMaxHistorySize ((UInt32)3 << 30)
+
+#define kStartMaxLen 3
+
+void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+ if (!p->directInput)
+ {
+ alloc->Free(p->bufferBase);
+ p->bufferBase = 0;
+ }
+}
+
+/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
+
+int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
+{
+ UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
+ if (p->directInput)
+ {
+ p->blockSize = blockSize;
+ return 1;
+ }
+ if (p->bufferBase == 0 || p->blockSize != blockSize)
+ {
+ LzInWindow_Free(p, alloc);
+ p->blockSize = blockSize;
+ p->bufferBase = (Byte *)alloc->Alloc(blockSize);
+ }
+ return (p->bufferBase != 0);
+}
+
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
+Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
+
+UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
+
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
+{
+ p->posLimit -= subValue;
+ p->pos -= subValue;
+ p->streamPos -= subValue;
+}
+
+void MatchFinder_ReadBlock(CMatchFinder *p)
+{
+ if (p->streamEndWasReached || p->result != SZ_OK)
+ return;
+ for (;;)
+ {
+ Byte *dest = p->buffer + (p->streamPos - p->pos);
+ UInt32 numReadBytes;
+ UInt32 size = (UInt32)(p->bufferBase + p->blockSize - dest);
+ if (size == 0)
+ return;
+ p->result = p->stream->Read(p->stream, dest, size, &numReadBytes);
+ if (p->result != SZ_OK)
+ return;
+ if (numReadBytes == 0)
+ {
+ p->streamEndWasReached = 1;
+ return;
+ }
+ p->streamPos += numReadBytes;
+ if (p->streamPos - p->pos > p->keepSizeAfter)
+ return;
+ }
+}
+
+void MatchFinder_MoveBlock(CMatchFinder *p)
+{
+ memmove(p->bufferBase,
+ p->buffer - p->keepSizeBefore,
+ p->streamPos - p->pos + p->keepSizeBefore);
+ p->buffer = p->bufferBase + p->keepSizeBefore;
+}
+
+int MatchFinder_NeedMove(CMatchFinder *p)
+{
+ /* if (p->streamEndWasReached) return 0; */
+ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
+}
+
+void MatchFinder_ReadIfRequired(CMatchFinder *p)
+{
+ if (p->streamEndWasReached)
+ return;
+ if (p->keepSizeAfter >= p->streamPos - p->pos)
+ MatchFinder_ReadBlock(p);
+}
+
+void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
+{
+ if (MatchFinder_NeedMove(p))
+ MatchFinder_MoveBlock(p);
+ MatchFinder_ReadBlock(p);
+}
+
+void MatchFinder_SetDefaultSettings(CMatchFinder *p)
+{
+ p->cutValue = 32;
+ p->btMode = 1;
+ p->numHashBytes = 4;
+ /* p->skipModeBits = 0; */
+ p->directInput = 0;
+ p->bigHash = 0;
+}
+
+void MatchFinder_Construct(CMatchFinder *p)
+{
+ p->bufferBase = 0;
+ p->directInput = 0;
+ p->hash = 0;
+ MatchFinder_SetDefaultSettings(p);
+}
+
+void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
+{
+ alloc->Free(p->hash);
+ p->hash = 0;
+}
+
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+ MatchFinder_FreeThisClassMemory(p, alloc);
+ LzInWindow_Free(p, alloc);
+}
+
+CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
+{
+ size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
+ if (sizeInBytes / sizeof(CLzRef) != num)
+ return 0;
+ return (CLzRef *)alloc->Alloc(sizeInBytes);
+}
+
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
+ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+ ISzAlloc *alloc)
+{
+ UInt32 sizeReserv;
+ if (historySize > kMaxHistorySize)
+ {
+ MatchFinder_Free(p, alloc);
+ return 0;
+ }
+ sizeReserv = historySize >> 1;
+ if (historySize > ((UInt32)2 << 30))
+ sizeReserv = historySize >> 2;
+ sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
+
+ p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
+ p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
+ /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
+ if (LzInWindow_Create(p, sizeReserv, alloc))
+ {
+ UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1;
+ UInt32 hs;
+ p->matchMaxLen = matchMaxLen;
+ {
+ p->fixedHashSize = 0;
+ if (p->numHashBytes == 2)
+ hs = (1 << 16) - 1;
+ else
+ {
+ hs = historySize - 1;
+ hs |= (hs >> 1);
+ hs |= (hs >> 2);
+ hs |= (hs >> 4);
+ hs |= (hs >> 8);
+ hs >>= 1;
+ /* hs >>= p->skipModeBits; */
+ hs |= 0xFFFF; /* don't change it! It's required for Deflate */
+ if (hs > (1 << 24))
+ {
+ if (p->numHashBytes == 3)
+ hs = (1 << 24) - 1;
+ else
+ hs >>= 1;
+ }
+ }
+ p->hashMask = hs;
+ hs++;
+ if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
+ if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
+ if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
+ hs += p->fixedHashSize;
+ }
+
+ {
+ UInt32 prevSize = p->hashSizeSum + p->numSons;
+ UInt32 newSize;
+ p->historySize = historySize;
+ p->hashSizeSum = hs;
+ p->cyclicBufferSize = newCyclicBufferSize;
+ p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
+ newSize = p->hashSizeSum + p->numSons;
+ if (p->hash != 0 && prevSize == newSize)
+ return 1;
+ MatchFinder_FreeThisClassMemory(p, alloc);
+ p->hash = AllocRefs(newSize, alloc);
+ if (p->hash != 0)
+ {
+ p->son = p->hash + p->hashSizeSum;
+ return 1;
+ }
+ }
+ }
+ MatchFinder_Free(p, alloc);
+ return 0;
+}
+
+void MatchFinder_SetLimits(CMatchFinder *p)
+{
+ UInt32 limit = kMaxValForNormalize - p->pos;
+ UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
+ if (limit2 < limit)
+ limit = limit2;
+ limit2 = p->streamPos - p->pos;
+ if (limit2 <= p->keepSizeAfter)
+ {
+ if (limit2 > 0)
+ limit2 = 1;
+ }
+ else
+ limit2 -= p->keepSizeAfter;
+ if (limit2 < limit)
+ limit = limit2;
+ {
+ UInt32 lenLimit = p->streamPos - p->pos;
+ if (lenLimit > p->matchMaxLen)
+ lenLimit = p->matchMaxLen;
+ p->lenLimit = lenLimit;
+ }
+ p->posLimit = p->pos + limit;
+}
+
+void MatchFinder_Init(CMatchFinder *p)
+{
+ UInt32 i;
+ for(i = 0; i < p->hashSizeSum; i++)
+ p->hash[i] = kEmptyHashValue;
+ p->cyclicBufferPos = 0;
+ p->buffer = p->bufferBase;
+ p->pos = p->streamPos = p->cyclicBufferSize;
+ p->result = SZ_OK;
+ p->streamEndWasReached = 0;
+ MatchFinder_ReadBlock(p);
+ MatchFinder_SetLimits(p);
+}
+
+UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
+{
+ return (p->pos - p->historySize - 1) & kNormalizeMask;
+}
+
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
+{
+ UInt32 i;
+ for (i = 0; i < numItems; i++)
+ {
+ UInt32 value = items[i];
+ if (value <= subValue)
+ value = kEmptyHashValue;
+ else
+ value -= subValue;
+ items[i] = value;
+ }
+}
+
+void MatchFinder_Normalize(CMatchFinder *p)
+{
+ UInt32 subValue = MatchFinder_GetSubValue(p);
+ MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
+ MatchFinder_ReduceOffsets(p, subValue);
+}
+
+void MatchFinder_CheckLimits(CMatchFinder *p)
+{
+ if (p->pos == kMaxValForNormalize)
+ MatchFinder_Normalize(p);
+ if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
+ MatchFinder_CheckAndMoveAndRead(p);
+ if (p->cyclicBufferPos == p->cyclicBufferSize)
+ p->cyclicBufferPos = 0;
+ MatchFinder_SetLimits(p);
+}
+
+UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
+ UInt32 *distances, UInt32 maxLen)
+{
+ son[_cyclicBufferPos] = curMatch;
+ for (;;)
+ {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+ return distances;
+ {
+ const Byte *pb = cur - delta;
+ curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
+ if (pb[maxLen] == cur[maxLen] && *pb == *cur)
+ {
+ UInt32 len = 0;
+ while(++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ if (maxLen < len)
+ {
+ *distances++ = maxLen = len;
+ *distances++ = delta - 1;
+ if (len == lenLimit)
+ return distances;
+ }
+ }
+ }
+ }
+}
+
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
+ UInt32 *distances, UInt32 maxLen)
+{
+ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+ UInt32 len0 = 0, len1 = 0;
+ for (;;)
+ {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+ {
+ *ptr0 = *ptr1 = kEmptyHashValue;
+ return distances;
+ }
+ {
+ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ const Byte *pb = cur - delta;
+ UInt32 len = (len0 < len1 ? len0 : len1);
+ if (pb[len] == cur[len])
+ {
+ if (++len != lenLimit && pb[len] == cur[len])
+ while(++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ if (maxLen < len)
+ {
+ *distances++ = maxLen = len;
+ *distances++ = delta - 1;
+ if (len == lenLimit)
+ {
+ *ptr1 = pair[0];
+ *ptr0 = pair[1];
+ return distances;
+ }
+ }
+ }
+ if (pb[len] < cur[len])
+ {
+ *ptr1 = curMatch;
+ ptr1 = pair + 1;
+ curMatch = *ptr1;
+ len1 = len;
+ }
+ else
+ {
+ *ptr0 = curMatch;
+ ptr0 = pair;
+ curMatch = *ptr0;
+ len0 = len;
+ }
+ }
+ }
+}
+
+void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
+{
+ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+ UInt32 len0 = 0, len1 = 0;
+ for (;;)
+ {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+ {
+ *ptr0 = *ptr1 = kEmptyHashValue;
+ return;
+ }
+ {
+ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ const Byte *pb = cur - delta;
+ UInt32 len = (len0 < len1 ? len0 : len1);
+ if (pb[len] == cur[len])
+ {
+ while(++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ {
+ if (len == lenLimit)
+ {
+ *ptr1 = pair[0];
+ *ptr0 = pair[1];
+ return;
+ }
+ }
+ }
+ if (pb[len] < cur[len])
+ {
+ *ptr1 = curMatch;
+ ptr1 = pair + 1;
+ curMatch = *ptr1;
+ len1 = len;
+ }
+ else
+ {
+ *ptr0 = curMatch;
+ ptr0 = pair;
+ curMatch = *ptr0;
+ len0 = len;
+ }
+ }
+ }
+}
+
+#define MOVE_POS \
+ ++p->cyclicBufferPos; \
+ p->buffer++; \
+ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
+
+#define MOVE_POS_RET MOVE_POS return offset;
+
+void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
+
+#define GET_MATCHES_HEADER2(minLen, ret_op) \
+ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
+ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
+ cur = p->buffer;
+
+#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
+#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
+
+#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
+
+#define GET_MATCHES_FOOTER(offset, maxLen) \
+ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
+ distances + offset, maxLen) - distances); MOVE_POS_RET;
+
+#define SKIP_FOOTER \
+ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
+
+UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 offset;
+ GET_MATCHES_HEADER(2)
+ HASH2_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ offset = 0;
+ GET_MATCHES_FOOTER(offset, 1)
+}
+
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 offset;
+ GET_MATCHES_HEADER(3)
+ HASH_ZIP_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ offset = 0;
+ GET_MATCHES_FOOTER(offset, 2)
+}
+
+UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 hash2Value, delta2, maxLen, offset;
+ GET_MATCHES_HEADER(3)
+
+ HASH3_CALC;
+
+ delta2 = p->pos - p->hash[hash2Value];
+ curMatch = p->hash[kFix3HashSize + hashValue];
+
+ p->hash[hash2Value] =
+ p->hash[kFix3HashSize + hashValue] = p->pos;
+
+
+ maxLen = 2;
+ offset = 0;
+ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+ {
+ for (; maxLen != lenLimit; maxLen++)
+ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+ break;
+ distances[0] = maxLen;
+ distances[1] = delta2 - 1;
+ offset = 2;
+ if (maxLen == lenLimit)
+ {
+ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+ MOVE_POS_RET;
+ }
+ }
+ GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
+ GET_MATCHES_HEADER(4)
+
+ HASH4_CALC;
+
+ delta2 = p->pos - p->hash[ hash2Value];
+ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
+ curMatch = p->hash[kFix4HashSize + hashValue];
+
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] =
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+
+ maxLen = 1;
+ offset = 0;
+ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+ {
+ distances[0] = maxLen = 2;
+ distances[1] = delta2 - 1;
+ offset = 2;
+ }
+ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
+ {
+ maxLen = 3;
+ distances[offset + 1] = delta3 - 1;
+ offset += 2;
+ delta2 = delta3;
+ }
+ if (offset != 0)
+ {
+ for (; maxLen != lenLimit; maxLen++)
+ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+ break;
+ distances[offset - 2] = maxLen;
+ if (maxLen == lenLimit)
+ {
+ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+ MOVE_POS_RET;
+ }
+ }
+ if (maxLen < 3)
+ maxLen = 3;
+ GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
+ GET_MATCHES_HEADER(4)
+
+ HASH4_CALC;
+
+ delta2 = p->pos - p->hash[ hash2Value];
+ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
+ curMatch = p->hash[kFix4HashSize + hashValue];
+
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] =
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+
+ maxLen = 1;
+ offset = 0;
+ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+ {
+ distances[0] = maxLen = 2;
+ distances[1] = delta2 - 1;
+ offset = 2;
+ }
+ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
+ {
+ maxLen = 3;
+ distances[offset + 1] = delta3 - 1;
+ offset += 2;
+ delta2 = delta3;
+ }
+ if (offset != 0)
+ {
+ for (; maxLen != lenLimit; maxLen++)
+ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+ break;
+ distances[offset - 2] = maxLen;
+ if (maxLen == lenLimit)
+ {
+ p->son[p->cyclicBufferPos] = curMatch;
+ MOVE_POS_RET;
+ }
+ }
+ if (maxLen < 3)
+ maxLen = 3;
+ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+ distances + offset, maxLen) - (distances));
+ MOVE_POS_RET
+}
+
+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 offset;
+ GET_MATCHES_HEADER(3)
+ HASH_ZIP_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+ distances, 2) - (distances));
+ MOVE_POS_RET
+}
+
+void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ SKIP_HEADER(2)
+ HASH2_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ SKIP_FOOTER
+ }
+ while (--num != 0);
+}
+
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ SKIP_HEADER(3)
+ HASH_ZIP_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ SKIP_FOOTER
+ }
+ while (--num != 0);
+}
+
+void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ UInt32 hash2Value;
+ SKIP_HEADER(3)
+ HASH3_CALC;
+ curMatch = p->hash[kFix3HashSize + hashValue];
+ p->hash[hash2Value] =
+ p->hash[kFix3HashSize + hashValue] = p->pos;
+ SKIP_FOOTER
+ }
+ while (--num != 0);
+}
+
+void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ UInt32 hash2Value, hash3Value;
+ SKIP_HEADER(4)
+ HASH4_CALC;
+ curMatch = p->hash[kFix4HashSize + hashValue];
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] = p->pos;
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+ SKIP_FOOTER
+ }
+ while (--num != 0);
+}
+
+void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ UInt32 hash2Value, hash3Value;
+ SKIP_HEADER(4)
+ HASH4_CALC;
+ curMatch = p->hash[kFix4HashSize + hashValue];
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] =
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+ p->son[p->cyclicBufferPos] = curMatch;
+ MOVE_POS
+ }
+ while (--num != 0);
+}
+
+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ SKIP_HEADER(3)
+ HASH_ZIP_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ p->son[p->cyclicBufferPos] = curMatch;
+ MOVE_POS
+ }
+ while (--num != 0);
+}
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
+{
+ vTable->Init = (Mf_Init_Func)MatchFinder_Init;
+ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
+ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
+ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
+ if (!p->btMode)
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
+ }
+ else if (p->numHashBytes == 2)
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
+ }
+ else if (p->numHashBytes == 3)
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
+ }
+ else
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
+ }
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Lz/MatchFinder.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Lz/MatchFinder.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,106 @@
+/* MatchFinder.h */
+
+#ifndef __MATCHFINDER_H
+#define __MATCHFINDER_H
+
+#include "../../IStream.h"
+
+typedef UInt32 CLzRef;
+
+typedef struct _CMatchFinder
+{
+ Byte *buffer;
+ UInt32 pos;
+ UInt32 posLimit;
+ UInt32 streamPos;
+ UInt32 lenLimit;
+
+ UInt32 cyclicBufferPos;
+ UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
+
+ UInt32 matchMaxLen;
+ CLzRef *hash;
+ CLzRef *son;
+ UInt32 hashMask;
+ UInt32 cutValue;
+
+ Byte *bufferBase;
+ ISeqInStream *stream;
+ int streamEndWasReached;
+
+ UInt32 blockSize;
+ UInt32 keepSizeBefore;
+ UInt32 keepSizeAfter;
+
+ UInt32 numHashBytes;
+ int directInput;
+ int btMode;
+ /* int skipModeBits; */
+ int bigHash;
+ UInt32 historySize;
+ UInt32 fixedHashSize;
+ UInt32 hashSizeSum;
+ UInt32 numSons;
+
+ HRes result;
+} CMatchFinder;
+
+#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
+#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
+
+#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
+
+int MatchFinder_NeedMove(CMatchFinder *p);
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
+void MatchFinder_MoveBlock(CMatchFinder *p);
+void MatchFinder_ReadIfRequired(CMatchFinder *p);
+
+void MatchFinder_Construct(CMatchFinder *p);
+
+/* Conditions:
+ historySize <= 3 GB
+ keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
+*/
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
+ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+ ISzAlloc *alloc);
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
+
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
+ UInt32 *distances, UInt32 maxLen);
+
+/*
+Conditions:
+ Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
+ Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
+*/
+
+typedef void (*Mf_Init_Func)(void *object);
+typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
+typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
+typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
+typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
+typedef void (*Mf_Skip_Func)(void *object, UInt32);
+
+typedef struct _IMatchFinder
+{
+ Mf_Init_Func Init;
+ Mf_GetIndexByte_Func GetIndexByte;
+ Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
+ Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
+ Mf_GetMatches_Func GetMatches;
+ Mf_Skip_Func Skip;
+} IMatchFinder;
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
+
+void MatchFinder_Init(CMatchFinder *p);
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Lz/MatchFinderMt.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Lz/MatchFinderMt.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,806 @@
+/* MatchFinderMt.c */
+
+#ifdef _WIN32
+#define USE_ALLOCA
+#endif
+
+#ifdef USE_ALLOCA
+#ifdef _WIN32
+#include
+#else
+#include
+#endif
+#endif
+
+#include "../../7zCrc.h"
+#include "LzHash.h"
+
+#include "MatchFinderMt.h"
+
+void MtSync_Construct(CMtSync *p)
+{
+ p->wasCreated = False;
+ p->csWasInitialized = False;
+ p->csWasEntered = False;
+ Thread_Construct(&p->thread);
+ Event_Construct(&p->canStart);
+ Event_Construct(&p->wasStarted);
+ Event_Construct(&p->wasStopped);
+ Semaphore_Construct(&p->freeSemaphore);
+ Semaphore_Construct(&p->filledSemaphore);
+}
+
+void MtSync_GetNextBlock(CMtSync *p)
+{
+ if (p->needStart)
+ {
+ p->numProcessedBlocks = 1;
+ p->needStart = False;
+ p->stopWriting = False;
+ p->exit = False;
+ Event_Reset(&p->wasStarted);
+ Event_Reset(&p->wasStopped);
+
+ Event_Set(&p->canStart);
+ Event_Wait(&p->wasStarted);
+ }
+ else
+ {
+ CriticalSection_Leave(&p->cs);
+ p->csWasEntered = False;
+ p->numProcessedBlocks++;
+ Semaphore_Release1(&p->freeSemaphore);
+ }
+ Semaphore_Wait(&p->filledSemaphore);
+ CriticalSection_Enter(&p->cs);
+ p->csWasEntered = True;
+}
+
+/* MtSync_StopWriting must be called if Writing was started */
+
+void MtSync_StopWriting(CMtSync *p)
+{
+ UInt32 myNumBlocks = p->numProcessedBlocks;
+ if (!Thread_WasCreated(&p->thread) || p->needStart)
+ return;
+ p->stopWriting = True;
+ if (p->csWasEntered)
+ {
+ CriticalSection_Leave(&p->cs);
+ p->csWasEntered = False;
+ }
+ Semaphore_Release1(&p->freeSemaphore);
+
+ Event_Wait(&p->wasStopped);
+
+ while (myNumBlocks++ != p->numProcessedBlocks)
+ {
+ Semaphore_Wait(&p->filledSemaphore);
+ Semaphore_Release1(&p->freeSemaphore);
+ }
+ p->needStart = True;
+}
+
+void MtSync_Destruct(CMtSync *p)
+{
+ if (Thread_WasCreated(&p->thread))
+ {
+ MtSync_StopWriting(p);
+ p->exit = True;
+ if (p->needStart)
+ Event_Set(&p->canStart);
+ Thread_Wait(&p->thread);
+ Thread_Close(&p->thread);
+ }
+ if (p->csWasInitialized)
+ {
+ CriticalSection_Delete(&p->cs);
+ p->csWasInitialized = False;
+ }
+
+ Event_Close(&p->canStart);
+ Event_Close(&p->wasStarted);
+ Event_Close(&p->wasStopped);
+ Semaphore_Close(&p->freeSemaphore);
+ Semaphore_Close(&p->filledSemaphore);
+
+ p->wasCreated = False;
+}
+
+HRes MtSync_Create2(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks)
+{
+ if (p->wasCreated)
+ return SZ_OK;
+
+ RINOK(CriticalSection_Init(&p->cs));
+ p->csWasInitialized = True;
+
+ RINOK(AutoResetEvent_CreateNotSignaled(&p->canStart));
+ RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStarted));
+ RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStopped));
+
+ RINOK(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks));
+ RINOK(Semaphore_Create(&p->filledSemaphore, 0, numBlocks));
+
+ p->needStart = True;
+
+ RINOK(Thread_Create(&p->thread, startAddress, obj));
+ p->wasCreated = True;
+ return SZ_OK;
+}
+
+HRes MtSync_Create(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks)
+{
+ HRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
+ if (res != SZ_OK)
+ MtSync_Destruct(p);
+ return res;
+}
+
+
+void MtSync_Init(CMtSync *p) { p->needStart = True; }
+
+#define kMtMaxValForNormalize 0xFFFFFFFF
+
+#define DEF_GetHeads(name, v) \
+static void GetHeads ## name(const Byte *p, UInt32 pos, \
+UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads) { \
+for (; numHeads != 0; numHeads--) { \
+const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
+
+DEF_GetHeads(2, (p[0] | ((UInt32)p[1] << 8)) & hashMask)
+DEF_GetHeads(3, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
+DEF_GetHeads(4, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5)) & hashMask)
+DEF_GetHeads(4b, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
+DEF_GetHeads(5, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5) ^ (g_CrcTable[p[4]] << 3)) & hashMask)
+
+void HashThreadFunc(CMatchFinderMt *mt)
+{
+ CMtSync *p = &mt->hashSync;
+ for (;;)
+ {
+ UInt32 numProcessedBlocks = 0;
+ Event_Wait(&p->canStart);
+ Event_Set(&p->wasStarted);
+ for (;;)
+ {
+ if (p->exit)
+ return;
+ if (p->stopWriting)
+ {
+ p->numProcessedBlocks = numProcessedBlocks;
+ Event_Set(&p->wasStopped);
+ break;
+ }
+
+ {
+ CMatchFinder *mf = mt->MatchFinder;
+ if (MatchFinder_NeedMove(mf))
+ {
+ CriticalSection_Enter(&mt->btSync.cs);
+ CriticalSection_Enter(&mt->hashSync.cs);
+ {
+ const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);
+ const Byte *afterPtr;
+ MatchFinder_MoveBlock(mf);
+ afterPtr = MatchFinder_GetPointerToCurrentPos(mf);
+ mt->pointerToCurPos -= beforePtr - afterPtr;
+ mt->buffer -= beforePtr - afterPtr;
+ }
+ CriticalSection_Leave(&mt->btSync.cs);
+ CriticalSection_Leave(&mt->hashSync.cs);
+ continue;
+ }
+
+ Semaphore_Wait(&p->freeSemaphore);
+
+ MatchFinder_ReadIfRequired(mf);
+ if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize))
+ {
+ UInt32 subValue = (mf->pos - mf->historySize - 1);
+ MatchFinder_ReduceOffsets(mf, subValue);
+ MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1);
+ }
+ {
+ UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;
+ UInt32 num = mf->streamPos - mf->pos;
+ heads[0] = 2;
+ heads[1] = num;
+ if (num >= mf->numHashBytes)
+ {
+ num = num - mf->numHashBytes + 1;
+ if (num > kMtHashBlockSize - 2)
+ num = kMtHashBlockSize - 2;
+ mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num);
+ heads[0] += num;
+ }
+ mf->pos += num;
+ mf->buffer += num;
+ }
+ }
+
+ Semaphore_Release1(&p->filledSemaphore);
+ }
+ }
+}
+
+void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
+{
+ MtSync_GetNextBlock(&p->hashSync);
+ p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;
+ p->hashBufPosLimit += p->hashBuf[p->hashBufPos++];
+ p->hashNumAvail = p->hashBuf[p->hashBufPos++];
+}
+
+#define kEmptyHashValue 0
+
+/* #define MFMT_GM_INLINE */
+
+#ifdef MFMT_GM_INLINE
+
+#if _MSC_VER >= 1300
+#define NO_INLINE __declspec(noinline) __fastcall
+#else
+#ifdef _MSC_VER
+#define NO_INLINE __fastcall
+#endif
+#endif
+
+Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
+ UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
+{
+ do
+ {
+ UInt32 *distances = _distances + 1;
+ UInt32 curMatch = pos - *hash++;
+
+ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+ UInt32 len0 = 0, len1 = 0;
+ UInt32 cutValue = _cutValue;
+ UInt32 maxLen = _maxLen;
+ for (;;)
+ {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+ {
+ *ptr0 = *ptr1 = kEmptyHashValue;
+ break;
+ }
+ {
+ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ const Byte *pb = cur - delta;
+ UInt32 len = (len0 < len1 ? len0 : len1);
+ if (pb[len] == cur[len])
+ {
+ if (++len != lenLimit && pb[len] == cur[len])
+ while(++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ if (maxLen < len)
+ {
+ *distances++ = maxLen = len;
+ *distances++ = delta - 1;
+ if (len == lenLimit)
+ {
+ *ptr1 = pair[0];
+ *ptr0 = pair[1];
+ break;
+ }
+ }
+ }
+ if (pb[len] < cur[len])
+ {
+ *ptr1 = curMatch;
+ ptr1 = pair + 1;
+ curMatch = *ptr1;
+ len1 = len;
+ }
+ else
+ {
+ *ptr0 = curMatch;
+ ptr0 = pair;
+ curMatch = *ptr0;
+ len0 = len;
+ }
+ }
+ }
+ pos++;
+ _cyclicBufferPos++;
+ cur++;
+ {
+ UInt32 num = (UInt32)(distances - _distances);
+ *_distances = num - 1;
+ _distances += num;
+ limit -= num;
+ }
+ }
+ while (limit > 0 && --size != 0);
+ *posRes = pos;
+ return limit;
+}
+
+#endif
+
+void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
+{
+ UInt32 numProcessed = 0;
+ UInt32 curPos = 2;
+ UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
+ distances[1] = p->hashNumAvail;
+ while (curPos < limit)
+ {
+ if (p->hashBufPos == p->hashBufPosLimit)
+ {
+ MatchFinderMt_GetNextBlock_Hash(p);
+ distances[1] = numProcessed + p->hashNumAvail;
+ if (p->hashNumAvail >= p->numHashBytes)
+ continue;
+ for (; p->hashNumAvail != 0; p->hashNumAvail--)
+ distances[curPos++] = 0;
+ break;
+ }
+ {
+ UInt32 size = p->hashBufPosLimit - p->hashBufPos;
+ UInt32 lenLimit = p->matchMaxLen;
+ UInt32 pos = p->pos;
+ UInt32 cyclicBufferPos = p->cyclicBufferPos;
+ if (lenLimit >= p->hashNumAvail)
+ lenLimit = p->hashNumAvail;
+ {
+ UInt32 size2 = p->hashNumAvail - lenLimit + 1;
+ if (size2 < size)
+ size = size2;
+ size2 = p->cyclicBufferSize - cyclicBufferPos;
+ if (size2 < size)
+ size = size2;
+ }
+ #ifndef MFMT_GM_INLINE
+ while (curPos < limit && size-- != 0)
+ {
+ UInt32 *startDistances = distances + curPos;
+ UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],
+ pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
+ startDistances + 1, p->numHashBytes - 1) - startDistances);
+ *startDistances = num - 1;
+ curPos += num;
+ cyclicBufferPos++;
+ pos++;
+ p->buffer++;
+ }
+ #else
+ {
+ UInt32 posRes;
+ curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
+ distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);
+ p->hashBufPos += posRes - pos;
+ cyclicBufferPos += posRes - pos;
+ p->buffer += posRes - pos;
+ pos = posRes;
+ }
+ #endif
+
+ numProcessed += pos - p->pos;
+ p->hashNumAvail -= pos - p->pos;
+ p->pos = pos;
+ if (cyclicBufferPos == p->cyclicBufferSize)
+ cyclicBufferPos = 0;
+ p->cyclicBufferPos = cyclicBufferPos;
+ }
+ }
+ distances[0] = curPos;
+}
+
+void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
+{
+ CMtSync *sync = &p->hashSync;
+ if (!sync->needStart)
+ {
+ CriticalSection_Enter(&sync->cs);
+ sync->csWasEntered = True;
+ }
+
+ BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize);
+
+ if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)
+ {
+ UInt32 subValue = p->pos - p->cyclicBufferSize;
+ MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);
+ p->pos -= subValue;
+ }
+
+ if (!sync->needStart)
+ {
+ CriticalSection_Leave(&sync->cs);
+ sync->csWasEntered = False;
+ }
+}
+
+void BtThreadFunc(CMatchFinderMt *mt)
+{
+ CMtSync *p = &mt->btSync;
+ for (;;)
+ {
+ UInt32 blockIndex = 0;
+ Event_Wait(&p->canStart);
+ Event_Set(&p->wasStarted);
+ for (;;)
+ {
+ if (p->exit)
+ return;
+ if (p->stopWriting)
+ {
+ p->numProcessedBlocks = blockIndex;
+ MtSync_StopWriting(&mt->hashSync);
+ Event_Set(&p->wasStopped);
+ break;
+ }
+ Semaphore_Wait(&p->freeSemaphore);
+ BtFillBlock(mt, blockIndex++);
+ Semaphore_Release1(&p->filledSemaphore);
+ }
+ }
+}
+
+void MatchFinderMt_Construct(CMatchFinderMt *p)
+{
+ p->hashBuf = 0;
+ MtSync_Construct(&p->hashSync);
+ MtSync_Construct(&p->btSync);
+}
+
+void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
+{
+ alloc->Free(p->hashBuf);
+ p->hashBuf = 0;
+}
+
+void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
+{
+ MtSync_Destruct(&p->hashSync);
+ MtSync_Destruct(&p->btSync);
+ MatchFinderMt_FreeMem(p, alloc);
+}
+
+#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
+#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
+
+static unsigned StdCall HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
+static unsigned StdCall BtThreadFunc2(void *p)
+{
+ #ifdef USE_ALLOCA
+ alloca(0x180);
+ #endif
+ BtThreadFunc((CMatchFinderMt *)p);
+ return 0;
+}
+
+HRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc)
+{
+ CMatchFinder *mf = p->MatchFinder;
+ p->historySize = historySize;
+ if (kMtBtBlockSize <= matchMaxLen * 4)
+ return E_INVALIDARG;
+ if (p->hashBuf == 0)
+ {
+ p->hashBuf = (UInt32 *)alloc->Alloc((kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
+ if (p->hashBuf == 0)
+ return SZE_OUTOFMEMORY;
+ p->btBuf = p->hashBuf + kHashBufferSize;
+ }
+ keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);
+ keepAddBufferAfter += kMtHashBlockSize;
+ if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))
+ return SZE_OUTOFMEMORY;
+
+ RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks));
+ RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks));
+ return SZ_OK;
+}
+
+/* Call it after ReleaseStream / SetStream */
+void MatchFinderMt_Init(CMatchFinderMt *p)
+{
+ CMatchFinder *mf = p->MatchFinder;
+ p->btBufPos = p->btBufPosLimit = 0;
+ p->hashBufPos = p->hashBufPosLimit = 0;
+ MatchFinder_Init(mf);
+ p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);
+ p->btNumAvailBytes = 0;
+ p->lzPos = p->historySize + 1;
+
+ p->hash = mf->hash;
+ p->fixedHashSize = mf->fixedHashSize;
+
+ p->son = mf->son;
+ p->matchMaxLen = mf->matchMaxLen;
+ p->numHashBytes = mf->numHashBytes;
+ p->pos = mf->pos;
+ p->buffer = mf->buffer;
+ p->cyclicBufferPos = mf->cyclicBufferPos;
+ p->cyclicBufferSize = mf->cyclicBufferSize;
+ p->cutValue = mf->cutValue;
+}
+
+/* ReleaseStream is required to finish multithreading */
+void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
+{
+ MtSync_StopWriting(&p->btSync);
+ /* p->MatchFinder->ReleaseStream(); */
+}
+
+void MatchFinderMt_Normalize(CMatchFinderMt *p)
+{
+ MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);
+ p->lzPos = p->historySize + 1;
+}
+
+void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
+{
+ UInt32 blockIndex;
+ MtSync_GetNextBlock(&p->btSync);
+ blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask);
+ p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize;
+ p->btBufPosLimit += p->btBuf[p->btBufPos++];
+ p->btNumAvailBytes = p->btBuf[p->btBufPos++];
+ if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize)
+ MatchFinderMt_Normalize(p);
+}
+
+const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
+{
+ return p->pointerToCurPos;
+}
+
+#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
+
+UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
+{
+ GET_NEXT_BLOCK_IF_REQUIRED;
+ return p->btNumAvailBytes;
+}
+
+Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index)
+{
+ return p->pointerToCurPos[index];
+}
+
+UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
+{
+ UInt32 hash2Value, curMatch2;
+ UInt32 *hash = p->hash;
+ const Byte *cur = p->pointerToCurPos;
+ UInt32 lzPos = p->lzPos;
+ MT_HASH2_CALC
+
+ curMatch2 = hash[hash2Value];
+ hash[hash2Value] = lzPos;
+
+ if (curMatch2 >= matchMinPos)
+ if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
+ {
+ *distances++ = 2;
+ *distances++ = lzPos - curMatch2 - 1;
+ }
+ return distances;
+}
+
+UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
+{
+ UInt32 hash2Value, hash3Value, curMatch2, curMatch3;
+ UInt32 *hash = p->hash;
+ const Byte *cur = p->pointerToCurPos;
+ UInt32 lzPos = p->lzPos;
+ MT_HASH3_CALC
+
+ curMatch2 = hash[ hash2Value];
+ curMatch3 = hash[kFix3HashSize + hash3Value];
+
+ hash[ hash2Value] =
+ hash[kFix3HashSize + hash3Value] =
+ lzPos;
+
+ if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
+ {
+ distances[1] = lzPos - curMatch2 - 1;
+ if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
+ {
+ distances[0] = 3;
+ return distances + 2;
+ }
+ distances[0] = 2;
+ distances += 2;
+ }
+ if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
+ {
+ *distances++ = 3;
+ *distances++ = lzPos - curMatch3 - 1;
+ }
+ return distances;
+}
+
+/*
+UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
+{
+ UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;
+ UInt32 *hash = p->hash;
+ const Byte *cur = p->pointerToCurPos;
+ UInt32 lzPos = p->lzPos;
+ MT_HASH4_CALC
+
+ curMatch2 = hash[ hash2Value];
+ curMatch3 = hash[kFix3HashSize + hash3Value];
+ curMatch4 = hash[kFix4HashSize + hash4Value];
+
+ hash[ hash2Value] =
+ hash[kFix3HashSize + hash3Value] =
+ hash[kFix4HashSize + hash4Value] =
+ lzPos;
+
+ if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
+ {
+ distances[1] = lzPos - curMatch2 - 1;
+ if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
+ {
+ distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
+ return distances + 2;
+ }
+ distances[0] = 2;
+ distances += 2;
+ }
+ if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
+ {
+ distances[1] = lzPos - curMatch3 - 1;
+ if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3])
+ {
+ distances[0] = 4;
+ return distances + 2;
+ }
+ distances[0] = 3;
+ distances += 2;
+ }
+
+ if (curMatch4 >= matchMinPos)
+ if (
+ cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] &&
+ cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3]
+ )
+ {
+ *distances++ = 4;
+ *distances++ = lzPos - curMatch4 - 1;
+ }
+ return distances;
+}
+*/
+
+#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
+
+UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
+{
+ const UInt32 *btBuf = p->btBuf + p->btBufPos;
+ UInt32 len = *btBuf++;
+ p->btBufPos += 1 + len;
+ p->btNumAvailBytes--;
+ {
+ UInt32 i;
+ for (i = 0; i < len; i += 2)
+ {
+ *distances++ = *btBuf++;
+ *distances++ = *btBuf++;
+ }
+ }
+ INCREASE_LZ_POS
+ return len;
+}
+
+UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
+{
+ const UInt32 *btBuf = p->btBuf + p->btBufPos;
+ UInt32 len = *btBuf++;
+ p->btBufPos += 1 + len;
+
+ if (len == 0)
+ {
+ if (p->btNumAvailBytes-- >= 4)
+ len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));
+ }
+ else
+ {
+ /* Condition: there are matches in btBuf with length < p->numHashBytes */
+ UInt32 *distances2;
+ p->btNumAvailBytes--;
+ distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);
+ do
+ {
+ *distances2++ = *btBuf++;
+ *distances2++ = *btBuf++;
+ }
+ while ((len -= 2) != 0);
+ len = (UInt32)(distances2 - (distances));
+ }
+ INCREASE_LZ_POS
+ return len;
+}
+
+#define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED
+#define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
+#define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while(--num != 0);
+
+void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
+{
+ SKIP_HEADER2 { p->btNumAvailBytes--;
+ SKIP_FOOTER
+}
+
+void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
+{
+ SKIP_HEADER(2)
+ UInt32 hash2Value;
+ MT_HASH2_CALC
+ hash[hash2Value] = p->lzPos;
+ SKIP_FOOTER
+}
+
+void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
+{
+ SKIP_HEADER(3)
+ UInt32 hash2Value, hash3Value;
+ MT_HASH3_CALC
+ hash[kFix3HashSize + hash3Value] =
+ hash[ hash2Value] =
+ p->lzPos;
+ SKIP_FOOTER
+}
+
+/*
+void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
+{
+ SKIP_HEADER(4)
+ UInt32 hash2Value, hash3Value, hash4Value;
+ MT_HASH4_CALC
+ hash[kFix4HashSize + hash4Value] =
+ hash[kFix3HashSize + hash3Value] =
+ hash[ hash2Value] =
+ p->lzPos;
+ SKIP_FOOTER
+}
+*/
+
+void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
+{
+ vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;
+ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;
+ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;
+ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;
+ vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;
+ switch(p->MatchFinder->numHashBytes)
+ {
+ case 2:
+ p->GetHeadsFunc = GetHeads2;
+ p->MixMatchesFunc = (Mf_Mix_Matches)0;
+ vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip;
+ vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches;
+ break;
+ case 3:
+ p->GetHeadsFunc = GetHeads3;
+ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2;
+ vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip;
+ break;
+ default:
+ /* case 4: */
+ p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;
+ /* p->GetHeadsFunc = GetHeads4; */
+ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;
+ vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;
+ break;
+ /*
+ default:
+ p->GetHeadsFunc = GetHeads5;
+ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4;
+ vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip;
+ break;
+ */
+ }
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Lz/MatchFinderMt.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Lz/MatchFinderMt.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,95 @@
+/* MatchFinderMt.h */
+
+#ifndef __MATCHFINDERMT_H
+#define __MATCHFINDERMT_H
+
+#include "../../Threads.h"
+#include "MatchFinder.h"
+
+#define kMtHashBlockSize (1 << 13)
+#define kMtHashNumBlocks (1 << 3)
+#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1)
+
+#define kMtBtBlockSize (1 << 14)
+#define kMtBtNumBlocks (1 << 6)
+#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1)
+
+typedef struct _CMtSync
+{
+ Bool wasCreated;
+ Bool needStart;
+ Bool exit;
+ Bool stopWriting;
+
+ CThread thread;
+ CAutoResetEvent canStart;
+ CAutoResetEvent wasStarted;
+ CAutoResetEvent wasStopped;
+ CSemaphore freeSemaphore;
+ CSemaphore filledSemaphore;
+ Bool csWasInitialized;
+ Bool csWasEntered;
+ CCriticalSection cs;
+ UInt32 numProcessedBlocks;
+} CMtSync;
+
+typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances);
+
+/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */
+#define kMtCacheLineDummy 128
+
+typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,
+ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads);
+
+typedef struct _CMatchFinderMt
+{
+ /* LZ */
+ const Byte *pointerToCurPos;
+ UInt32 *btBuf;
+ UInt32 btBufPos;
+ UInt32 btBufPosLimit;
+ UInt32 lzPos;
+ UInt32 btNumAvailBytes;
+
+ UInt32 *hash;
+ UInt32 fixedHashSize;
+ UInt32 historySize;
+
+ Mf_Mix_Matches MixMatchesFunc;
+
+ /* LZ + BT */
+ CMtSync btSync;
+ Byte btDummy[kMtCacheLineDummy];
+
+ /* BT */
+ UInt32 *hashBuf;
+ UInt32 hashBufPos;
+ UInt32 hashBufPosLimit;
+ UInt32 hashNumAvail;
+
+ CLzRef *son;
+ UInt32 matchMaxLen;
+ UInt32 numHashBytes;
+ UInt32 pos;
+ Byte *buffer;
+ UInt32 cyclicBufferPos;
+ UInt32 cyclicBufferSize; /* it must be historySize + 1 */
+ UInt32 cutValue;
+
+ /* BT + Hash */
+ CMtSync hashSync;
+ /* Byte hashDummy[kMtCacheLineDummy]; */
+
+ /* Hash */
+ Mf_GetHeads GetHeadsFunc;
+ CMatchFinder *MatchFinder;
+} CMatchFinderMt;
+
+void MatchFinderMt_Construct(CMatchFinderMt *p);
+void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc);
+HRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc);
+void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
+void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Lzma/LzmaDecode.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Lzma/LzmaDecode.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,584 @@
+/*
+ LzmaDecode.c
+ LZMA Decoder (optimized for Speed version)
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this Code, expressly permits you to
+ statically or dynamically link your Code (or bind by name) to the
+ interfaces of this file without subjecting your linked Code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
+ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
+
+#ifdef _LZMA_IN_CB
+
+#define RC_TEST { if (Buffer == BufferLim) \
+ { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
+ BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
+
+#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
+
+#else
+
+#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
+
+#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
+
+#endif
+
+#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+ { UpdateBit0(p); mi <<= 1; A0; } else \
+ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
+
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+ { int i = numLevels; res = 1; \
+ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+ res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ #ifdef _LZMA_OUT_READ
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ }
+ #endif
+ return LZMA_RESULT_OK;
+}
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+ CProb *p = vs->Probs;
+ SizeT nowPos = 0;
+ Byte previousByte = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+
+ #ifdef _LZMA_OUT_READ
+
+ UInt32 Range = vs->Range;
+ UInt32 Code = vs->Code;
+ #ifdef _LZMA_IN_CB
+ const Byte *Buffer = vs->Buffer;
+ const Byte *BufferLim = vs->BufferLim;
+ #else
+ const Byte *Buffer = inStream;
+ const Byte *BufferLim = inStream + inSize;
+ #endif
+ int state = vs->State;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ Byte tempDictionary[4];
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ #else /* if !_LZMA_OUT_READ */
+
+ int state = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ int len = 0;
+ const Byte *Buffer;
+ const Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+
+ {
+ UInt32 i;
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ }
+
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+
+ #endif /* _LZMA_OUT_READ */
+
+ while(nowPos < outSize)
+ {
+ CProb *prob;
+ UInt32 bound;
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+
+ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ int symbol = 1;
+ UpdateBit0(prob)
+ prob = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ int matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ do
+ {
+ int bit;
+ CProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & 0x100);
+ probLit = prob + 0x100 + bit + symbol;
+ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+ }
+ while (symbol < 0x100);
+ }
+ while (symbol < 0x100)
+ {
+ CProb *probLit = prob + symbol;
+ RC_GET_BIT(probLit, symbol)
+ }
+ previousByte = (Byte)symbol;
+
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRep + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < kNumLitStates ? 0 : 3;
+ prob = p + LenCoder;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG0 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+ UpdateBit0(prob);
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit == 0)
+ #else
+ if (nowPos == 0)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ state = state < kNumLitStates ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ #endif
+
+ continue;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ UpdateBit1(prob);
+ prob = p + IsRepG1 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG2 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = p + RepLenCoder;
+ }
+ {
+ int numBits, offset;
+ CProb *probLen = prob + LenChoice;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ numBits = kLenNumLowBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenChoice2;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ numBits = kLenNumMidBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ numBits = kLenNumHighBits;
+ }
+ }
+ RangeDecoderBitTreeDecode(probLen, numBits, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ int posSlot;
+ state += kNumLitStates;
+ prob = p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = (2 | ((UInt32)posSlot & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 <<= numDirectBits;
+ prob = p + SpecPos + rep0 - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ RC_NORMALIZE
+ Range >>= 1;
+ rep0 <<= 1;
+ if (Code >= Range)
+ {
+ Code -= Range;
+ rep0 |= 1;
+ }
+ }
+ while (--numDirectBits != 0);
+ prob = p + Align;
+ rep0 <<= kNumAlignBits;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ int i = 1;
+ int mi = 1;
+ do
+ {
+ CProb *prob3 = prob + mi;
+ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+ i <<= 1;
+ }
+ while(--numDirectBits != 0);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ #ifdef _LZMA_OUT_READ
+ if (rep0 > distanceLimit)
+ #else
+ if (rep0 > nowPos)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ #ifdef _LZMA_OUT_READ
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+ #endif
+
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+ RC_NORMALIZE;
+
+ #ifdef _LZMA_OUT_READ
+ vs->Range = Range;
+ vs->Code = Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + (UInt32)nowPos;
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+ #endif
+
+ #ifdef _LZMA_IN_CB
+ vs->Buffer = Buffer;
+ vs->BufferLim = BufferLim;
+ #else
+ *inSizeProcessed = (SizeT)(Buffer - inStream);
+ #endif
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Lzma/LzmaDecode.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Lzma/LzmaDecode.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,113 @@
+/*
+ LzmaDecode.h
+ LZMA Decoder interface
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+#include "LzmaTypes.h"
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+/* #define _LZMA_OUT_READ */
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb UInt16
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+ int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+ int lc;
+ int lp;
+ int pb;
+ #ifdef _LZMA_OUT_READ
+ UInt32 DictionarySize;
+ #endif
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+ CLzmaProperties Properties;
+ CProb *Probs;
+
+ #ifdef _LZMA_IN_CB
+ const unsigned char *Buffer;
+ const unsigned char *BufferLim;
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ unsigned char *Dictionary;
+ UInt32 Range;
+ UInt32 Code;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 DistanceLimit;
+ UInt32 Reps[4];
+ int State;
+ int RemainLen;
+ unsigned char TempDictionary[4];
+ #endif
+} CLzmaDecoderState;
+
+#ifdef _LZMA_OUT_READ
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
+#endif
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Lzma/LzmaDecodeSize.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Lzma/LzmaDecodeSize.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,712 @@
+/*
+ LzmaDecodeSize.c
+ LZMA Decoder (optimized for Size version)
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+typedef struct _CRangeDecoder
+{
+ const Byte *Buffer;
+ const Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback;
+ int Result;
+ #endif
+ int ExtraBytes;
+} CRangeDecoder;
+
+Byte RangeDecoderReadByte(CRangeDecoder *rd)
+{
+ if (rd->Buffer == rd->BufferLim)
+ {
+ #ifdef _LZMA_IN_CB
+ SizeT size;
+ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
+ rd->BufferLim = rd->Buffer + size;
+ if (size == 0)
+ #endif
+ {
+ rd->ExtraBytes = 1;
+ return 0xFF;
+ }
+ }
+ return (*rd->Buffer++);
+}
+
+/* #define ReadByte (*rd->Buffer++) */
+#define ReadByte (RangeDecoderReadByte(rd))
+
+void RangeDecoderInit(CRangeDecoder *rd
+ #ifndef _LZMA_IN_CB
+ , const Byte *stream, SizeT bufferSize
+ #endif
+ )
+{
+ int i;
+ #ifdef _LZMA_IN_CB
+ rd->Buffer = rd->BufferLim = 0;
+ #else
+ rd->Buffer = stream;
+ rd->BufferLim = stream + bufferSize;
+ #endif
+ rd->ExtraBytes = 0;
+ rd->Code = 0;
+ rd->Range = (0xFFFFFFFF);
+ for(i = 0; i < 5; i++)
+ rd->Code = (rd->Code << 8) | ReadByte;
+}
+
+#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
+#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
+#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
+
+UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
+{
+ RC_INIT_VAR
+ UInt32 result = 0;
+ int i;
+ for (i = numTotalBits; i != 0; i--)
+ {
+ /* UInt32 t; */
+ range >>= 1;
+
+ result <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ result |= 1;
+ }
+ /*
+ t = (code - range) >> 31;
+ t &= 1;
+ code -= range & (t - 1);
+ result = (result + result) | (1 - t);
+ */
+ RC_NORMALIZE
+ }
+ RC_FLUSH_VAR
+ return result;
+}
+
+int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
+{
+ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
+ if (rd->Code < bound)
+ {
+ rd->Range = bound;
+ *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 0;
+ }
+ else
+ {
+ rd->Range -= bound;
+ rd->Code -= bound;
+ *prob -= (*prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 1;
+ }
+}
+
+#define RC_GET_BIT2(prob, mi, A0, A1) \
+ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
+ if (code < bound) \
+ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
+ else \
+ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
+ RC_NORMALIZE
+
+#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
+
+int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = numLevels; i != 0; i--)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT(prob, mi)
+ #else
+ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return mi - (1 << numLevels);
+}
+
+int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ int symbol = 0;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = 0; i < numLevels; i++)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
+ #else
+ int bit = RangeDecoderBitDecode(probs + mi, rd);
+ mi = mi + mi + bit;
+ symbol |= (bit << i);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ int bit;
+ int matchBit = (matchByte >> 7) & 1;
+ matchByte <<= 1;
+ #ifdef _LZMA_LOC_OPT
+ {
+ CProb *prob = probs + 0x100 + (matchBit << 8) + symbol;
+ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
+ }
+ #else
+ bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd);
+ symbol = (symbol << 1) | bit;
+ #endif
+ if (matchBit != bit)
+ {
+ while (symbol < 0x100)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ break;
+ }
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
+{
+ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
+ return RangeDecoderBitTreeDecode(p + LenLow +
+ (posState << kLenNumLowBits), kLenNumLowBits, rd);
+ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
+ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
+ (posState << kLenNumMidBits), kLenNumMidBits, rd);
+ return kLenNumLowSymbols + kLenNumMidSymbols +
+ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
+}
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ #ifdef _LZMA_OUT_READ
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ }
+ #endif
+ return LZMA_RESULT_OK;
+}
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+ CProb *p = vs->Probs;
+ SizeT nowPos = 0;
+ Byte previousByte = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+ CRangeDecoder rd;
+
+ #ifdef _LZMA_OUT_READ
+
+ int state = vs->State;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ Byte tempDictionary[4];
+
+ rd.Range = vs->Range;
+ rd.Code = vs->Code;
+ #ifdef _LZMA_IN_CB
+ rd.InCallback = InCallback;
+ rd.Buffer = vs->Buffer;
+ rd.BufferLim = vs->BufferLim;
+ #else
+ rd.Buffer = inStream;
+ rd.BufferLim = inStream + inSize;
+ #endif
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ RangeDecoderInit(&rd
+ #ifndef _LZMA_IN_CB
+ , inStream, inSize
+ #endif
+ );
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ #ifdef _LZMA_IN_CB
+ rd.Result = LZMA_RESULT_OK;
+ #endif
+ rd.ExtraBytes = 0;
+
+ #else /* if !_LZMA_OUT_READ */
+
+ int state = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ int len = 0;
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+
+ {
+ UInt32 i;
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ }
+
+ #ifdef _LZMA_IN_CB
+ rd.InCallback = InCallback;
+ #endif
+ RangeDecoderInit(&rd
+ #ifndef _LZMA_IN_CB
+ , inStream, inSize
+ #endif
+ );
+
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+
+ #endif /* _LZMA_OUT_READ */
+
+
+ while(nowPos < outSize)
+ {
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ CProb *probs = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ Byte matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
+ }
+ else
+ previousByte = LzmaLiteralDecode(probs, &rd);
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
+ {
+ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
+ {
+ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit == 0)
+ #else
+ if (nowPos == 0)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ state = state < 7 ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ #endif
+ continue;
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
+ distance = rep1;
+ else
+ {
+ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
+ distance = rep2;
+ else
+ {
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
+ state = state < 7 ? 8 : 11;
+ }
+ else
+ {
+ int posSlot;
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < 7 ? 7 : 10;
+ len = LzmaLenDecode(p + LenCoder, &rd, posState);
+ posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits), kNumPosSlotBits, &rd);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 += RangeDecoderReverseBitTreeDecode(
+ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
+ }
+ else
+ {
+ rep0 += RangeDecoderDecodeDirectBits(&rd,
+ numDirectBits - kNumAlignBits) << kNumAlignBits;
+ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ #ifdef _LZMA_OUT_READ
+ if (rep0 > distanceLimit)
+ #else
+ if (rep0 > nowPos)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ #ifdef _LZMA_OUT_READ
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+ #endif
+
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+
+
+ #ifdef _LZMA_OUT_READ
+ vs->Range = rd.Range;
+ vs->Code = rd.Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + (UInt32)nowPos;
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+ #endif
+
+ #ifdef _LZMA_IN_CB
+ vs->Buffer = rd.Buffer;
+ vs->BufferLim = rd.BufferLim;
+ #else
+ *inSizeProcessed = (SizeT)(rd.Buffer - inStream);
+ #endif
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Lzma/LzmaStateDecode.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Lzma/LzmaStateDecode.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,521 @@
+/*
+ LzmaStateDecode.c
+ LZMA Decoder (State version)
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this Code, expressly permits you to
+ statically or dynamically link your Code (or bind by name) to the
+ interfaces of this file without subjecting your linked Code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaStateDecode.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT Code = 0; Range = 0xFFFFFFFF; \
+ { int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }}
+
+#define RC_NORMALIZE if (Range < kTopValue) { Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+ { UpdateBit0(p); mi <<= 1; A0; } else \
+ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
+
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+ { int i = numLevels; res = 1; \
+ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+ res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+/* kRequiredInBufferSize = number of required input bytes for worst case:
+ longest match with longest distance.
+ kLzmaInBufferSize must be larger than kRequiredInBufferSize
+ 23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE)
+*/
+
+#define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8)
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ return LZMA_RESULT_OK;
+ }
+}
+
+int LzmaDecode(
+ CLzmaDecoderState *vs,
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed,
+ int finishDecoding)
+{
+ UInt32 Range = vs->Range;
+ UInt32 Code = vs->Code;
+
+ unsigned char *Buffer = vs->Buffer;
+ int BufferSize = vs->BufferSize; /* don't change it to unsigned int */
+ CProb *p = vs->Probs;
+
+ int state = vs->State;
+ unsigned char previousByte;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ SizeT nowPos = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ unsigned char *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ unsigned char tempDictionary[4];
+
+ (*inSizeProcessed) = 0;
+ (*outSizeProcessed) = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ while (inSize > 0 && BufferSize < kLzmaInBufferSize)
+ {
+ Buffer[BufferSize++] = *inStream++;
+ (*inSizeProcessed)++;
+ inSize--;
+ }
+ if (BufferSize < 5)
+ {
+ vs->BufferSize = BufferSize;
+ return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK;
+ }
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ RC_INIT;
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ for (;;)
+ {
+ int bufferPos = (int)(Buffer - vs->Buffer);
+ if (BufferSize - bufferPos < kRequiredInBufferSize)
+ {
+ int i;
+ BufferSize -= bufferPos;
+ if (BufferSize < 0)
+ return LZMA_RESULT_DATA_ERROR;
+ for (i = 0; i < BufferSize; i++)
+ vs->Buffer[i] = Buffer[i];
+ Buffer = vs->Buffer;
+ while (inSize > 0 && BufferSize < kLzmaInBufferSize)
+ {
+ Buffer[BufferSize++] = *inStream++;
+ (*inSizeProcessed)++;
+ inSize--;
+ }
+ if (BufferSize < kRequiredInBufferSize && !finishDecoding)
+ break;
+ }
+ if (nowPos >= outSize)
+ break;
+ {
+ CProb *prob;
+ UInt32 bound;
+ int posState = (int)((nowPos + globalPos) & posStateMask);
+
+ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ int symbol = 1;
+ UpdateBit0(prob)
+ prob = p + Literal + (LZMA_LIT_SIZE *
+ ((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ int matchByte;
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ do
+ {
+ int bit;
+ CProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & 0x100);
+ probLit = prob + 0x100 + bit + symbol;
+ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+ }
+ while (symbol < 0x100);
+ }
+ while (symbol < 0x100)
+ {
+ CProb *probLit = prob + symbol;
+ RC_GET_BIT(probLit, symbol)
+ }
+ previousByte = (unsigned char)symbol;
+
+ outStream[nowPos++] = previousByte;
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRep + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < kNumLitStates ? 0 : 3;
+ prob = p + LenCoder;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG0 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ UInt32 pos;
+ UpdateBit0(prob);
+ if (distanceLimit == 0)
+ return LZMA_RESULT_DATA_ERROR;
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ state = state < kNumLitStates ? 9 : 11;
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ outStream[nowPos++] = previousByte;
+ continue;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ UpdateBit1(prob);
+ prob = p + IsRepG1 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG2 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = p + RepLenCoder;
+ }
+ {
+ int numBits, offset;
+ CProb *probLen = prob + LenChoice;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ numBits = kLenNumLowBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenChoice2;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ numBits = kLenNumMidBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ numBits = kLenNumHighBits;
+ }
+ }
+ RangeDecoderBitTreeDecode(probLen, numBits, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ int posSlot;
+ state += kNumLitStates;
+ prob = p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = (2 | ((UInt32)posSlot & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 <<= numDirectBits;
+ prob = p + SpecPos + rep0 - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ RC_NORMALIZE
+ Range >>= 1;
+ rep0 <<= 1;
+ if (Code >= Range)
+ {
+ Code -= Range;
+ rep0 |= 1;
+ }
+ }
+ while (--numDirectBits != 0);
+ prob = p + Align;
+ rep0 <<= kNumAlignBits;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ int i = 1;
+ int mi = 1;
+ do
+ {
+ CProb *prob3 = prob + mi;
+ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+ i <<= 1;
+ }
+ while(--numDirectBits != 0);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ if (rep0 > distanceLimit)
+ return LZMA_RESULT_DATA_ERROR;
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+
+ do
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+ }
+ RC_NORMALIZE;
+
+ BufferSize -= (int)(Buffer - vs->Buffer);
+ if (BufferSize < 0)
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ int i;
+ for (i = 0; i < BufferSize; i++)
+ vs->Buffer[i] = Buffer[i];
+ }
+ vs->BufferSize = BufferSize;
+ vs->Range = Range;
+ vs->Code = Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = (UInt32)(globalPos + nowPos);
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+
+ (*outSizeProcessed) = nowPos;
+ return LZMA_RESULT_OK;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Lzma/LzmaStateDecode.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Lzma/LzmaStateDecode.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,96 @@
+/*
+ LzmaStateDecode.h
+ LZMA Decoder interface (State version)
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMASTATEDECODE_H
+#define __LZMASTATEDECODE_H
+
+#include "LzmaTypes.h"
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb UInt16
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+ int lc;
+ int lp;
+ int pb;
+ UInt32 DictionarySize;
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp)))
+
+#define kLzmaInBufferSize 64 /* don't change it. it must be larger than kRequiredInBufferSize */
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+ CLzmaProperties Properties;
+ CProb *Probs;
+ unsigned char *Dictionary;
+
+ unsigned char Buffer[kLzmaInBufferSize];
+ int BufferSize;
+
+ UInt32 Range;
+ UInt32 Code;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 DistanceLimit;
+ UInt32 Reps[4];
+ int State;
+ int RemainLen; /* -2: decoder needs internal initialization
+ -1: stream was finished,
+ 0: ok
+ > 0: need to write RemainLen bytes as match Reps[0],
+ */
+ unsigned char TempDictionary[4]; /* it's required when DictionarySize = 0 */
+} CLzmaDecoderState;
+
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; }
+
+/* LzmaDecode: decoding from input stream to output stream.
+ If finishDecoding != 0, then there are no more bytes in input stream
+ after inStream[inSize - 1]. */
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed,
+ int finishDecoding);
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Lzma/LzmaStateTest.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Lzma/LzmaStateTest.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,195 @@
+/*
+LzmaStateTest.c
+Test application for LZMA Decoder (State version)
+
+This file written and distributed to public domain by Igor Pavlov.
+This file is part of LZMA SDK 4.26 (2005-08-02)
+*/
+
+#include
+#include
+#include
+
+#include "LzmaStateDecode.h"
+
+const char *kCantReadMessage = "Can not read input file";
+const char *kCantWriteMessage = "Can not write output file";
+const char *kCantAllocateMessage = "Can not allocate memory";
+
+#define kInBufferSize (1 << 15)
+#define kOutBufferSize (1 << 15)
+
+unsigned char g_InBuffer[kInBufferSize];
+unsigned char g_OutBuffer[kOutBufferSize];
+
+size_t MyReadFile(FILE *file, void *data, size_t size)
+ { return fread(data, 1, size, file); }
+
+int MyReadFileAndCheck(FILE *file, void *data, size_t size)
+ { return (MyReadFile(file, data, size) == size); }
+
+int PrintError(char *buffer, const char *message)
+{
+ sprintf(buffer + strlen(buffer), "\nError: ");
+ sprintf(buffer + strlen(buffer), message);
+ return 1;
+}
+
+int main3(FILE *inFile, FILE *outFile, char *rs)
+{
+ /* We use two 32-bit integers to construct 64-bit integer for file size.
+ You can remove outSizeHigh, if you don't need >= 4GB supporting,
+ or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
+ UInt32 outSize = 0;
+ UInt32 outSizeHigh = 0;
+
+ int waitEOS = 1;
+ /* waitEOS = 1, if there is no uncompressed size in headers,
+ so decoder will wait EOS (End of Stream Marker) in compressed stream */
+
+ int i;
+ int res = 0;
+ CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */
+ unsigned char properties[LZMA_PROPERTIES_SIZE];
+ SizeT inAvail = 0;
+ unsigned char *inBuffer = 0;
+
+ if (sizeof(UInt32) < 4)
+ return PrintError(rs, "LZMA decoder needs correct UInt32");
+
+ /* Read LZMA properties for compressed stream */
+
+ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
+ return PrintError(rs, kCantReadMessage);
+
+ /* Read uncompressed size */
+
+ for (i = 0; i < 8; i++)
+ {
+ unsigned char b;
+ if (!MyReadFileAndCheck(inFile, &b, 1))
+ return PrintError(rs, kCantReadMessage);
+ if (b != 0xFF)
+ waitEOS = 0;
+ if (i < 4)
+ outSize += (UInt32)(b) << (i * 8);
+ else
+ outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
+ }
+
+ /* Decode LZMA properties and allocate memory */
+
+ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
+ return PrintError(rs, "Incorrect stream properties");
+ state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+ if (state.Probs == 0)
+ return PrintError(rs, kCantAllocateMessage);
+
+ if (state.Properties.DictionarySize == 0)
+ state.Dictionary = 0;
+ else
+ {
+ state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+ if (state.Dictionary == 0)
+ {
+ free(state.Probs);
+ return PrintError(rs, kCantAllocateMessage);
+ }
+ }
+
+ /* Decompress */
+
+ LzmaDecoderInit(&state);
+
+ do
+ {
+ SizeT inProcessed, outProcessed;
+ int finishDecoding;
+ UInt32 outAvail = kOutBufferSize;
+ if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
+ outAvail = outSize;
+ if (inAvail == 0)
+ {
+ inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize);
+ inBuffer = g_InBuffer;
+ }
+ finishDecoding = (inAvail == 0);
+ res = LzmaDecode(&state,
+ inBuffer, inAvail, &inProcessed,
+ g_OutBuffer, outAvail, &outProcessed,
+ finishDecoding);
+ if (res != 0)
+ {
+ sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+ res = 1;
+ break;
+ }
+ inAvail -= inProcessed;
+ inBuffer += inProcessed;
+
+ if (outFile != 0)
+ if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed)
+ {
+ PrintError(rs, kCantWriteMessage);
+ res = 1;
+ break;
+ }
+
+ if (outSize < outProcessed)
+ outSizeHigh--;
+ outSize -= (UInt32)outProcessed;
+ outSize &= 0xFFFFFFFF;
+
+ if (outProcessed == 0 && finishDecoding)
+ {
+ if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
+ res = 1;
+ break;
+ }
+ }
+ while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS);
+
+ free(state.Dictionary);
+ free(state.Probs);
+ return res;
+}
+
+int main2(int numArgs, const char *args[], char *rs)
+{
+ FILE *inFile = 0;
+ FILE *outFile = 0;
+ int res;
+
+ sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n");
+ if (numArgs < 2 || numArgs > 3)
+ {
+ sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n");
+ return 1;
+ }
+
+ inFile = fopen(args[1], "rb");
+ if (inFile == 0)
+ return PrintError(rs, "Can not open input file");
+
+ if (numArgs > 2)
+ {
+ outFile = fopen(args[2], "wb+");
+ if (outFile == 0)
+ return PrintError(rs, "Can not open output file");
+ }
+
+ res = main3(inFile, outFile, rs);
+
+ if (outFile != 0)
+ fclose(outFile);
+ fclose(inFile);
+ return res;
+}
+
+int main(int numArgs, const char *args[])
+{
+ char rs[800] = { 0 };
+ int res = main2(numArgs, args, rs);
+ printf(rs);
+ return res;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Lzma/LzmaTest.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Lzma/LzmaTest.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,342 @@
+/*
+LzmaTest.c
+Test application for LZMA Decoder
+
+This file written and distributed to public domain by Igor Pavlov.
+This file is part of LZMA SDK 4.26 (2005-08-05)
+*/
+
+#include
+#include
+#include
+
+#include "LzmaDecode.h"
+
+const char *kCantReadMessage = "Can not read input file";
+const char *kCantWriteMessage = "Can not write output file";
+const char *kCantAllocateMessage = "Can not allocate memory";
+
+size_t MyReadFile(FILE *file, void *data, size_t size)
+{
+ if (size == 0)
+ return 0;
+ return fread(data, 1, size, file);
+}
+
+int MyReadFileAndCheck(FILE *file, void *data, size_t size)
+ { return (MyReadFile(file, data, size) == size);}
+
+size_t MyWriteFile(FILE *file, const void *data, size_t size)
+{
+ if (size == 0)
+ return 0;
+ return fwrite(data, 1, size, file);
+}
+
+int MyWriteFileAndCheck(FILE *file, const void *data, size_t size)
+ { return (MyWriteFile(file, data, size) == size); }
+
+#ifdef _LZMA_IN_CB
+#define kInBufferSize (1 << 15)
+typedef struct _CBuffer
+{
+ ILzmaInCallback InCallback;
+ FILE *File;
+ unsigned char Buffer[kInBufferSize];
+} CBuffer;
+
+int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size)
+{
+ CBuffer *b = (CBuffer *)object;
+ *buffer = b->Buffer;
+ *size = (SizeT)MyReadFile(b->File, b->Buffer, kInBufferSize);
+ return LZMA_RESULT_OK;
+}
+CBuffer g_InBuffer;
+
+#endif
+
+#ifdef _LZMA_OUT_READ
+#define kOutBufferSize (1 << 15)
+unsigned char g_OutBuffer[kOutBufferSize];
+#endif
+
+int PrintError(char *buffer, const char *message)
+{
+ sprintf(buffer + strlen(buffer), "\nError: ");
+ sprintf(buffer + strlen(buffer), message);
+ return 1;
+}
+
+int main3(FILE *inFile, FILE *outFile, char *rs)
+{
+ /* We use two 32-bit integers to construct 64-bit integer for file size.
+ You can remove outSizeHigh, if you don't need >= 4GB supporting,
+ or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
+ UInt32 outSize = 0;
+ UInt32 outSizeHigh = 0;
+ #ifndef _LZMA_OUT_READ
+ SizeT outSizeFull;
+ unsigned char *outStream;
+ #endif
+
+ int waitEOS = 1;
+ /* waitEOS = 1, if there is no uncompressed size in headers,
+ so decoder will wait EOS (End of Stream Marker) in compressed stream */
+
+ #ifndef _LZMA_IN_CB
+ SizeT compressedSize;
+ unsigned char *inStream;
+ #endif
+
+ CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
+ unsigned char properties[LZMA_PROPERTIES_SIZE];
+
+ int res;
+
+ #ifdef _LZMA_IN_CB
+ g_InBuffer.File = inFile;
+ #endif
+
+ if (sizeof(UInt32) < 4)
+ return PrintError(rs, "LZMA decoder needs correct UInt32");
+
+ #ifndef _LZMA_IN_CB
+ {
+ long length;
+ fseek(inFile, 0, SEEK_END);
+ length = ftell(inFile);
+ fseek(inFile, 0, SEEK_SET);
+ if ((long)(SizeT)length != length)
+ return PrintError(rs, "Too big compressed stream");
+ compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8));
+ }
+ #endif
+
+ /* Read LZMA properties for compressed stream */
+
+ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
+ return PrintError(rs, kCantReadMessage);
+
+ /* Read uncompressed size */
+
+ {
+ int i;
+ for (i = 0; i < 8; i++)
+ {
+ unsigned char b;
+ if (!MyReadFileAndCheck(inFile, &b, 1))
+ return PrintError(rs, kCantReadMessage);
+ if (b != 0xFF)
+ waitEOS = 0;
+ if (i < 4)
+ outSize += (UInt32)(b) << (i * 8);
+ else
+ outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
+ }
+
+ #ifndef _LZMA_OUT_READ
+ if (waitEOS)
+ return PrintError(rs, "Stream with EOS marker is not supported");
+ outSizeFull = (SizeT)outSize;
+ if (sizeof(SizeT) >= 8)
+ outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
+ else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize)
+ return PrintError(rs, "Too big uncompressed stream");
+ #endif
+ }
+
+ /* Decode LZMA properties and allocate memory */
+
+ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
+ return PrintError(rs, "Incorrect stream properties");
+ state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+
+ #ifdef _LZMA_OUT_READ
+ if (state.Properties.DictionarySize == 0)
+ state.Dictionary = 0;
+ else
+ state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+ #else
+ if (outSizeFull == 0)
+ outStream = 0;
+ else
+ outStream = (unsigned char *)malloc(outSizeFull);
+ #endif
+
+ #ifndef _LZMA_IN_CB
+ if (compressedSize == 0)
+ inStream = 0;
+ else
+ inStream = (unsigned char *)malloc(compressedSize);
+ #endif
+
+ if (state.Probs == 0
+ #ifdef _LZMA_OUT_READ
+ || (state.Dictionary == 0 && state.Properties.DictionarySize != 0)
+ #else
+ || (outStream == 0 && outSizeFull != 0)
+ #endif
+ #ifndef _LZMA_IN_CB
+ || (inStream == 0 && compressedSize != 0)
+ #endif
+ )
+ {
+ free(state.Probs);
+ #ifdef _LZMA_OUT_READ
+ free(state.Dictionary);
+ #else
+ free(outStream);
+ #endif
+ #ifndef _LZMA_IN_CB
+ free(inStream);
+ #endif
+ return PrintError(rs, kCantAllocateMessage);
+ }
+
+ /* Decompress */
+
+ #ifdef _LZMA_IN_CB
+ g_InBuffer.InCallback.Read = LzmaReadCompressed;
+ #else
+ if (!MyReadFileAndCheck(inFile, inStream, compressedSize))
+ return PrintError(rs, kCantReadMessage);
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ {
+ #ifndef _LZMA_IN_CB
+ SizeT inAvail = compressedSize;
+ const unsigned char *inBuffer = inStream;
+ #endif
+ LzmaDecoderInit(&state);
+ do
+ {
+ #ifndef _LZMA_IN_CB
+ SizeT inProcessed;
+ #endif
+ SizeT outProcessed;
+ SizeT outAvail = kOutBufferSize;
+ if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
+ outAvail = (SizeT)outSize;
+ res = LzmaDecode(&state,
+ #ifdef _LZMA_IN_CB
+ &g_InBuffer.InCallback,
+ #else
+ inBuffer, inAvail, &inProcessed,
+ #endif
+ g_OutBuffer, outAvail, &outProcessed);
+ if (res != 0)
+ {
+ sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+ res = 1;
+ break;
+ }
+ #ifndef _LZMA_IN_CB
+ inAvail -= inProcessed;
+ inBuffer += inProcessed;
+ #endif
+
+ if (outFile != 0)
+ if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed))
+ {
+ PrintError(rs, kCantWriteMessage);
+ res = 1;
+ break;
+ }
+
+ if (outSize < outProcessed)
+ outSizeHigh--;
+ outSize -= (UInt32)outProcessed;
+ outSize &= 0xFFFFFFFF;
+
+ if (outProcessed == 0)
+ {
+ if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
+ res = 1;
+ break;
+ }
+ }
+ while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS);
+ }
+
+ #else
+ {
+ #ifndef _LZMA_IN_CB
+ SizeT inProcessed;
+ #endif
+ SizeT outProcessed;
+ res = LzmaDecode(&state,
+ #ifdef _LZMA_IN_CB
+ &g_InBuffer.InCallback,
+ #else
+ inStream, compressedSize, &inProcessed,
+ #endif
+ outStream, outSizeFull, &outProcessed);
+ if (res != 0)
+ {
+ sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+ res = 1;
+ }
+ else if (outFile != 0)
+ {
+ if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed))
+ {
+ PrintError(rs, kCantWriteMessage);
+ res = 1;
+ }
+ }
+ }
+ #endif
+
+ free(state.Probs);
+ #ifdef _LZMA_OUT_READ
+ free(state.Dictionary);
+ #else
+ free(outStream);
+ #endif
+ #ifndef _LZMA_IN_CB
+ free(inStream);
+ #endif
+ return res;
+}
+
+int main2(int numArgs, const char *args[], char *rs)
+{
+ FILE *inFile = 0;
+ FILE *outFile = 0;
+ int res;
+
+ sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n");
+ if (numArgs < 2 || numArgs > 3)
+ {
+ sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n");
+ return 1;
+ }
+
+ inFile = fopen(args[1], "rb");
+ if (inFile == 0)
+ return PrintError(rs, "Can not open input file");
+
+ if (numArgs > 2)
+ {
+ outFile = fopen(args[2], "wb+");
+ if (outFile == 0)
+ return PrintError(rs, "Can not open output file");
+ }
+
+ res = main3(inFile, outFile, rs);
+
+ if (outFile != 0)
+ fclose(outFile);
+ fclose(inFile);
+ return res;
+}
+
+int main(int numArgs, const char *args[])
+{
+ char rs[800] = { 0 };
+ int res = main2(numArgs, args, rs);
+ printf(rs);
+ return res;
+}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Compress/Lzma/LzmaTypes.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Compress/Lzma/LzmaTypes.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,45 @@
+/*
+LzmaTypes.h
+
+Types for LZMA Decoder
+
+This file written and distributed to public domain by Igor Pavlov.
+This file is part of LZMA SDK 4.40 (2006-05-01)
+*/
+
+#ifndef __LZMATYPES_H
+#define __LZMATYPES_H
+
+#ifndef _7ZIP_BYTE_DEFINED
+#define _7ZIP_BYTE_DEFINED
+typedef unsigned char Byte;
+#endif
+
+#ifndef _7ZIP_UINT16_DEFINED
+#define _7ZIP_UINT16_DEFINED
+typedef unsigned short UInt16;
+#endif
+
+#ifndef _7ZIP_UINT32_DEFINED
+#define _7ZIP_UINT32_DEFINED
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef unsigned long UInt32;
+#else
+typedef unsigned int UInt32;
+#endif
+#endif
+
+/* #define _LZMA_NO_SYSTEM_SIZE_T */
+/* You can use it, if you don't want */
+
+#ifndef _7ZIP_SIZET_DEFINED
+#define _7ZIP_SIZET_DEFINED
+#ifdef _LZMA_NO_SYSTEM_SIZE_T
+typedef UInt32 SizeT;
+#else
+#include
+typedef size_t SizeT;
+#endif
+#endif
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/CpuArch.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/CpuArch.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,18 @@
+/* CpuArch.h */
+
+#ifndef __CPUARCH_H
+#define __CPUARCH_H
+
+/*
+LITTLE_ENDIAN_UNALIGN means:
+ 1) CPU is LITTLE_ENDIAN
+ 2) it's allowed to make unaligned memory accesses
+if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know
+about these properties of platform.
+*/
+
+#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__)
+#define LITTLE_ENDIAN_UNALIGN
+#endif
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/IStream.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/IStream.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,19 @@
+/* IStream.h */
+
+#ifndef __C_ISTREAM_H
+#define __C_ISTREAM_H
+
+#include "Types.h"
+
+typedef struct _ISeqInStream
+{
+ HRes (*Read)(void *object, void *data, UInt32 size, UInt32 *processedSize);
+} ISeqInStream;
+
+typedef struct _ISzAlloc
+{
+ void *(*Alloc)(size_t size);
+ void (*Free)(void *address); /* address can be 0 */
+} ISzAlloc;
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Sort.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Sort.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,92 @@
+/* Sort.c */
+
+#include "Sort.h"
+
+#define HeapSortDown(p, k, size, temp) \
+ { for (;;) { \
+ UInt32 s = (k << 1); \
+ if (s > size) break; \
+ if (s < size && p[s + 1] > p[s]) s++; \
+ if (temp >= p[s]) break; \
+ p[k] = p[s]; k = s; \
+ } p[k] = temp; }
+
+void HeapSort(UInt32 *p, UInt32 size)
+{
+ if (size <= 1)
+ return;
+ p--;
+ {
+ UInt32 i = size / 2;
+ do
+ {
+ UInt32 temp = p[i];
+ UInt32 k = i;
+ HeapSortDown(p, k, size, temp)
+ }
+ while(--i != 0);
+ }
+ /*
+ do
+ {
+ UInt32 k = 1;
+ UInt32 temp = p[size];
+ p[size--] = p[1];
+ HeapSortDown(p, k, size, temp)
+ }
+ while (size > 1);
+ */
+ while (size > 3)
+ {
+ UInt32 temp = p[size];
+ UInt32 k = (p[3] > p[2]) ? 3 : 2;
+ p[size--] = p[1];
+ p[1] = p[k];
+ HeapSortDown(p, k, size, temp)
+ }
+ {
+ UInt32 temp = p[size];
+ p[size] = p[1];
+ if (size > 2 && p[2] < temp)
+ {
+ p[1] = p[2];
+ p[2] = temp;
+ }
+ else
+ p[1] = temp;
+ }
+}
+
+/*
+#define HeapSortRefDown(p, vals, n, size, temp) \
+ { UInt32 k = n; UInt32 val = vals[temp]; for (;;) { \
+ UInt32 s = (k << 1); \
+ if (s > size) break; \
+ if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \
+ if (val >= vals[p[s]]) break; \
+ p[k] = p[s]; k = s; \
+ } p[k] = temp; }
+
+void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size)
+{
+ if (size <= 1)
+ return;
+ p--;
+ {
+ UInt32 i = size / 2;
+ do
+ {
+ UInt32 temp = p[i];
+ HeapSortRefDown(p, vals, i, size, temp);
+ }
+ while(--i != 0);
+ }
+ do
+ {
+ UInt32 temp = p[size];
+ p[size--] = p[1];
+ HeapSortRefDown(p, vals, 1, size, temp);
+ }
+ while (size > 1);
+}
+*/
\ No newline at end of file
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Sort.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Sort.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,11 @@
+/* Sort.h */
+
+#ifndef __7Z_Sort_H
+#define __7Z_Sort_H
+
+#include "Types.h"
+
+void HeapSort(UInt32 *p, UInt32 size);
+/* void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size); */
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Threads.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Threads.c Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,106 @@
+/* Threads.c */
+
+#include "Threads.h"
+#include
+
+HRes GetError()
+{
+ DWORD res = GetLastError();
+ return (res) ? (HRes)(res) : SZE_FAIL;
+}
+
+HRes BoolToHRes(int v) { return v ? SZ_OK : GetError(); }
+HRes BOOLToHRes(BOOL v) { return v ? SZ_OK : GetError(); }
+
+HRes MyCloseHandle(HANDLE *h)
+{
+ if (*h != NULL)
+ if (!CloseHandle(*h))
+ return GetError();
+ *h = NULL;
+ return SZ_OK;
+}
+
+HRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter)
+{
+ unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
+ thread->handle =
+ /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */
+ (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId);
+ /* maybe we must use errno here, but probably GetLastError() is also OK. */
+ return BoolToHRes(thread->handle != 0);
+}
+
+HRes WaitObject(HANDLE h)
+{
+ return (HRes)WaitForSingleObject(h, INFINITE);
+}
+
+HRes Thread_Wait(CThread *thread)
+{
+ if (thread->handle == NULL)
+ return 1;
+ return WaitObject(thread->handle);
+}
+
+HRes Thread_Close(CThread *thread)
+{
+ return MyCloseHandle(&thread->handle);
+}
+
+HRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled)
+{
+ p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL);
+ return BoolToHRes(p->handle != 0);
+}
+
+HRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled)
+ { return Event_Create(p, TRUE, initialSignaled); }
+HRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p)
+ { return ManualResetEvent_Create(p, 0); }
+
+HRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled)
+ { return Event_Create(p, FALSE, initialSignaled); }
+HRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p)
+ { return AutoResetEvent_Create(p, 0); }
+
+HRes Event_Set(CEvent *p) { return BOOLToHRes(SetEvent(p->handle)); }
+HRes Event_Reset(CEvent *p) { return BOOLToHRes(ResetEvent(p->handle)); }
+HRes Event_Wait(CEvent *p) { return WaitObject(p->handle); }
+HRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); }
+
+
+HRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount)
+{
+ p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL);
+ return BoolToHRes(p->handle != 0);
+}
+
+HRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
+{
+ return BOOLToHRes(ReleaseSemaphore(p->handle, releaseCount, previousCount));
+}
+HRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount)
+{
+ return Semaphore_Release(p, (LONG)releaseCount, NULL);
+}
+HRes Semaphore_Release1(CSemaphore *p)
+{
+ return Semaphore_ReleaseN(p, 1);
+}
+
+HRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); }
+HRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); }
+
+HRes CriticalSection_Init(CCriticalSection *p)
+{
+ /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */
+ __try
+ {
+ InitializeCriticalSection(p);
+ /* InitializeCriticalSectionAndSpinCount(p, 0); */
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER) { return SZE_OUTOFMEMORY; }
+ return SZ_OK;
+}
+
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Threads.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Threads.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,69 @@
+/* Threads.h */
+
+#ifndef __7Z_THRESDS_H
+#define __7Z_THRESDS_H
+
+#include
+
+#include "Types.h"
+
+typedef struct _CThread
+{
+ HANDLE handle;
+} CThread;
+
+#define Thread_Construct(thread) (thread)->handle = NULL
+#define Thread_WasCreated(thread) ((thread)->handle != NULL)
+
+typedef unsigned THREAD_FUNC_RET_TYPE;
+#define THREAD_FUNC_CALL_TYPE StdCall
+#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
+
+HRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter);
+HRes Thread_Wait(CThread *thread);
+HRes Thread_Close(CThread *thread);
+
+typedef struct _CEvent
+{
+ HANDLE handle;
+} CEvent;
+
+typedef CEvent CAutoResetEvent;
+typedef CEvent CManualResetEvent;
+
+#define Event_Construct(event) (event)->handle = NULL
+#define Event_IsCreated(event) ((event)->handle != NULL)
+
+HRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled);
+HRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event);
+HRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled);
+HRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event);
+HRes Event_Set(CEvent *event);
+HRes Event_Reset(CEvent *event);
+HRes Event_Wait(CEvent *event);
+HRes Event_Close(CEvent *event);
+
+
+typedef struct _CSemaphore
+{
+ HANDLE handle;
+} CSemaphore;
+
+#define Semaphore_Construct(p) (p)->handle = NULL
+
+HRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount);
+HRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
+HRes Semaphore_Release1(CSemaphore *p);
+HRes Semaphore_Wait(CSemaphore *p);
+HRes Semaphore_Close(CSemaphore *p);
+
+
+typedef CRITICAL_SECTION CCriticalSection;
+
+HRes CriticalSection_Init(CCriticalSection *p);
+#define CriticalSection_Delete(p) DeleteCriticalSection(p)
+#define CriticalSection_Enter(p) EnterCriticalSection(p)
+#define CriticalSection_Leave(p) LeaveCriticalSection(p)
+
+#endif
+
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/C/Types.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/C/Types.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,100 @@
+/* 7zTypes.h */
+
+#ifndef __C_TYPES_H
+#define __C_TYPES_H
+
+#ifndef _7ZIP_BYTE_DEFINED
+#define _7ZIP_BYTE_DEFINED
+typedef unsigned char Byte;
+#endif
+
+#ifndef _7ZIP_UINT16_DEFINED
+#define _7ZIP_UINT16_DEFINED
+typedef unsigned short UInt16;
+#endif
+
+#ifndef _7ZIP_UINT32_DEFINED
+#define _7ZIP_UINT32_DEFINED
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef unsigned long UInt32;
+#else
+typedef unsigned int UInt32;
+#endif
+#endif
+
+#ifndef _7ZIP_INT32_DEFINED
+#define _7ZIP_INT32_DEFINED
+#ifdef _LZMA_INT32_IS_ULONG
+typedef long Int32;
+#else
+typedef int Int32;
+#endif
+#endif
+
+/* #define _SZ_NO_INT_64 */
+/* define it your compiler doesn't support long long int */
+
+#ifndef _7ZIP_UINT64_DEFINED
+#define _7ZIP_UINT64_DEFINED
+#ifdef _SZ_NO_INT_64
+typedef unsigned long UInt64;
+#else
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef unsigned __int64 UInt64;
+#else
+typedef unsigned long long int UInt64;
+#endif
+#endif
+#endif
+
+
+/* #define _SZ_FILE_SIZE_32 */
+/* You can define _SZ_FILE_SIZE_32, if you don't need support for files larger than 4 GB*/
+
+#ifndef CFileSize
+#ifdef _SZ_FILE_SIZE_32
+typedef UInt32 CFileSize;
+#else
+typedef UInt64 CFileSize;
+#endif
+#endif
+
+#define SZ_RESULT int
+
+typedef int HRes;
+#define RES_OK (0)
+
+#define SZ_OK (0)
+#define SZE_DATA_ERROR (1)
+#define SZE_CRC_ERROR (3)
+#define SZE_ARCHIVE_ERROR (6)
+
+#define SZE_OUTOFMEMORY (0x8007000EL)
+#define SZE_NOTIMPL (0x80004001L)
+#define SZE_FAIL (0x80004005L)
+#define SZE_INVALIDARG (0x80070057L)
+
+
+#ifndef RINOK
+#define RINOK(x) { HRes __result_ = (x); if(__result_ != 0) return __result_; }
+#endif
+
+typedef int Bool;
+#define True 1
+#define False 0
+
+#ifdef _MSC_VER
+#define StdCall __stdcall
+#else
+#define StdCall
+#endif
+
+#if _MSC_VER >= 1300
+#define MY_FAST_CALL __declspec(noinline) __fastcall
+#elif defined( _MSC_VER)
+#define MY_FAST_CALL __fastcall
+#else
+#define MY_FAST_CALL
+#endif
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7z.ico
Binary file misc/libphysfs/lzma/CPP/7zip/Archive/7z/7z.ico has changed
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zCompressionMode.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zCompressionMode.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,3 @@
+// CompressionMethod.cpp
+
+#include "StdAfx.h"
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zCompressionMode.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zCompressionMode.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,50 @@
+// 7zCompressionMode.h
+
+#ifndef __7Z_COMPRESSION_MODE_H
+#define __7Z_COMPRESSION_MODE_H
+
+#include "../../../Common/MyString.h"
+
+#include "../../../Windows/PropVariant.h"
+
+#include "../../Common/MethodProps.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CMethodFull: public CMethod
+{
+ UInt32 NumInStreams;
+ UInt32 NumOutStreams;
+ bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
+};
+
+struct CBind
+{
+ UInt32 InCoder;
+ UInt32 InStream;
+ UInt32 OutCoder;
+ UInt32 OutStream;
+};
+
+struct CCompressionMethodMode
+{
+ CObjectVector Methods;
+ CRecordVector Binds;
+ #ifdef COMPRESS_MT
+ UInt32 NumThreads;
+ #endif
+ bool PasswordIsDefined;
+ UString Password;
+
+ bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
+ CCompressionMethodMode(): PasswordIsDefined(false)
+ #ifdef COMPRESS_MT
+ , NumThreads(1)
+ #endif
+ {}
+};
+
+}}
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zDecode.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zDecode.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,330 @@
+// 7zDecode.cpp
+
+#include "StdAfx.h"
+
+#include "7zDecode.h"
+
+#include "../../IPassword.h"
+#include "../../Common/LockedStream.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/CreateCoder.h"
+#include "../../Common/FilterCoder.h"
+
+namespace NArchive {
+namespace N7z {
+
+static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
+ CBindInfoEx &bindInfo)
+{
+ bindInfo.Clear();
+ int i;
+ for (i = 0; i < folder.BindPairs.Size(); i++)
+ {
+ NCoderMixer::CBindPair bindPair;
+ bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
+ bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
+ bindInfo.BindPairs.Add(bindPair);
+ }
+ UInt32 outStreamIndex = 0;
+ for (i = 0; i < folder.Coders.Size(); i++)
+ {
+ NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
+ const CCoderInfo &coderInfo = folder.Coders[i];
+ coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
+ coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
+ bindInfo.Coders.Add(coderStreamsInfo);
+ bindInfo.CoderMethodIDs.Add(coderInfo.MethodID);
+ for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
+ if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
+ bindInfo.OutStreams.Add(outStreamIndex);
+ }
+ for (i = 0; i < folder.PackStreams.Size(); i++)
+ bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);
+}
+
+static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,
+ const NCoderMixer::CCoderStreamsInfo &a2)
+{
+ return (a1.NumInStreams == a2.NumInStreams) &&
+ (a1.NumOutStreams == a2.NumOutStreams);
+}
+
+static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)
+{
+ return (a1.InIndex == a2.InIndex) &&
+ (a1.OutIndex == a2.OutIndex);
+}
+
+static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
+{
+ if (a1.Coders.Size() != a2.Coders.Size())
+ return false;
+ int i;
+ for (i = 0; i < a1.Coders.Size(); i++)
+ if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
+ return false;
+ if (a1.BindPairs.Size() != a2.BindPairs.Size())
+ return false;
+ for (i = 0; i < a1.BindPairs.Size(); i++)
+ if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
+ return false;
+ for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
+ if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
+ return false;
+ if (a1.InStreams.Size() != a2.InStreams.Size())
+ return false;
+ if (a1.OutStreams.Size() != a2.OutStreams.Size())
+ return false;
+ return true;
+}
+
+CDecoder::CDecoder(bool multiThread)
+{
+ #ifndef _ST_MODE
+ multiThread = true;
+ #endif
+ _multiThread = multiThread;
+ _bindInfoExPrevIsDefined = false;
+}
+
+HRESULT CDecoder::Decode(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ IInStream *inStream,
+ UInt64 startPos,
+ const UInt64 *packSizes,
+ const CFolder &folderInfo,
+ ISequentialOutStream *outStream,
+ ICompressProgressInfo *compressProgress
+ #ifndef _NO_CRYPTO
+ , ICryptoGetTextPassword *getTextPassword
+ #endif
+ #ifdef COMPRESS_MT
+ , bool mtMode, UInt32 numThreads
+ #endif
+ )
+{
+ CObjectVector< CMyComPtr > inStreams;
+
+ CLockedInStream lockedInStream;
+ lockedInStream.Init(inStream);
+
+ for (int j = 0; j < folderInfo.PackStreams.Size(); j++)
+ {
+ CLockedSequentialInStreamImp *lockedStreamImpSpec = new
+ CLockedSequentialInStreamImp;
+ CMyComPtr lockedStreamImp = lockedStreamImpSpec;
+ lockedStreamImpSpec->Init(&lockedInStream, startPos);
+ startPos += packSizes[j];
+
+ CLimitedSequentialInStream *streamSpec = new
+ CLimitedSequentialInStream;
+ CMyComPtr inStream = streamSpec;
+ streamSpec->SetStream(lockedStreamImp);
+ streamSpec->Init(packSizes[j]);
+ inStreams.Add(inStream);
+ }
+
+ int numCoders = folderInfo.Coders.Size();
+
+ CBindInfoEx bindInfo;
+ ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
+ bool createNewCoders;
+ if (!_bindInfoExPrevIsDefined)
+ createNewCoders = true;
+ else
+ createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
+ if (createNewCoders)
+ {
+ int i;
+ _decoders.Clear();
+ // _decoders2.Clear();
+
+ _mixerCoder.Release();
+
+ if (_multiThread)
+ {
+ _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;
+ _mixerCoder = _mixerCoderMTSpec;
+ _mixerCoderCommon = _mixerCoderMTSpec;
+ }
+ else
+ {
+ #ifdef _ST_MODE
+ _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;
+ _mixerCoder = _mixerCoderSTSpec;
+ _mixerCoderCommon = _mixerCoderSTSpec;
+ #endif
+ }
+ RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));
+
+ for (i = 0; i < numCoders; i++)
+ {
+ const CCoderInfo &coderInfo = folderInfo.Coders[i];
+
+
+ CMyComPtr decoder;
+ CMyComPtr decoder2;
+ RINOK(CreateCoder(
+ EXTERNAL_CODECS_LOC_VARS
+ coderInfo.MethodID, decoder, decoder2, false));
+ CMyComPtr decoderUnknown;
+ if (coderInfo.IsSimpleCoder())
+ {
+ if (decoder == 0)
+ return E_NOTIMPL;
+
+ decoderUnknown = (IUnknown *)decoder;
+
+ if (_multiThread)
+ _mixerCoderMTSpec->AddCoder(decoder);
+ #ifdef _ST_MODE
+ else
+ _mixerCoderSTSpec->AddCoder(decoder, false);
+ #endif
+ }
+ else
+ {
+ if (decoder2 == 0)
+ return E_NOTIMPL;
+ decoderUnknown = (IUnknown *)decoder2;
+ if (_multiThread)
+ _mixerCoderMTSpec->AddCoder2(decoder2);
+ #ifdef _ST_MODE
+ else
+ _mixerCoderSTSpec->AddCoder2(decoder2, false);
+ #endif
+ }
+ _decoders.Add(decoderUnknown);
+ #ifdef EXTERNAL_CODECS
+ CMyComPtr setCompressCodecsInfo;
+ decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
+ if (setCompressCodecsInfo)
+ {
+ RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));
+ }
+ #endif
+ }
+ _bindInfoExPrev = bindInfo;
+ _bindInfoExPrevIsDefined = true;
+ }
+ int i;
+ _mixerCoderCommon->ReInit();
+
+ UInt32 packStreamIndex = 0, unPackStreamIndex = 0;
+ UInt32 coderIndex = 0;
+ // UInt32 coder2Index = 0;
+
+ for (i = 0; i < numCoders; i++)
+ {
+ const CCoderInfo &coderInfo = folderInfo.Coders[i];
+ CMyComPtr &decoder = _decoders[coderIndex];
+
+ {
+ CMyComPtr setDecoderProperties;
+ decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
+ if (setDecoderProperties)
+ {
+ const CByteBuffer &properties = coderInfo.Properties;
+ size_t size = properties.GetCapacity();
+ if (size > 0xFFFFFFFF)
+ return E_NOTIMPL;
+ if (size > 0)
+ {
+ RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, (UInt32)size));
+ }
+ }
+ }
+
+ #ifdef COMPRESS_MT
+ if (mtMode)
+ {
+ CMyComPtr setCoderMt;
+ decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
+ if (setCoderMt)
+ {
+ RINOK(setCoderMt->SetNumberOfThreads(numThreads));
+ }
+ }
+ #endif
+
+ #ifndef _NO_CRYPTO
+ {
+ CMyComPtr cryptoSetPassword;
+ decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
+ if (cryptoSetPassword)
+ {
+ if (getTextPassword == 0)
+ return E_FAIL;
+ CMyComBSTR password;
+ RINOK(getTextPassword->CryptoGetTextPassword(&password));
+ CByteBuffer buffer;
+ UString unicodePassword(password);
+ const UInt32 sizeInBytes = unicodePassword.Length() * 2;
+ buffer.SetCapacity(sizeInBytes);
+ for (int i = 0; i < unicodePassword.Length(); i++)
+ {
+ wchar_t c = unicodePassword[i];
+ ((Byte *)buffer)[i * 2] = (Byte)c;
+ ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
+ }
+ RINOK(cryptoSetPassword->CryptoSetPassword(
+ (const Byte *)buffer, sizeInBytes));
+ }
+ }
+ #endif
+
+ coderIndex++;
+
+ UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
+ UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
+ CRecordVector packSizesPointers;
+ CRecordVector unPackSizesPointers;
+ packSizesPointers.Reserve(numInStreams);
+ unPackSizesPointers.Reserve(numOutStreams);
+ UInt32 j;
+ for (j = 0; j < numOutStreams; j++, unPackStreamIndex++)
+ unPackSizesPointers.Add(&folderInfo.UnPackSizes[unPackStreamIndex]);
+
+ for (j = 0; j < numInStreams; j++, packStreamIndex++)
+ {
+ int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
+ if (bindPairIndex >= 0)
+ packSizesPointers.Add(
+ &folderInfo.UnPackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);
+ else
+ {
+ int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
+ if (index < 0)
+ return E_FAIL;
+ packSizesPointers.Add(&packSizes[index]);
+ }
+ }
+
+ _mixerCoderCommon->SetCoderInfo(i,
+ &packSizesPointers.Front(),
+ &unPackSizesPointers.Front());
+ }
+ UInt32 mainCoder, temp;
+ bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
+
+ if (_multiThread)
+ _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
+ /*
+ else
+ _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
+ */
+
+ if (numCoders == 0)
+ return 0;
+ CRecordVector inStreamPointers;
+ inStreamPointers.Reserve(inStreams.Size());
+ for (i = 0; i < inStreams.Size(); i++)
+ inStreamPointers.Add(inStreams[i]);
+ ISequentialOutStream *outStreamPointer = outStream;
+ return _mixerCoder->Code(&inStreamPointers.Front(), NULL,
+ inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);
+}
+
+}}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zDecode.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zDecode.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,68 @@
+// 7zDecode.h
+
+#ifndef __7Z_DECODE_H
+#define __7Z_DECODE_H
+
+#include "../../IStream.h"
+#include "../../IPassword.h"
+
+#include "../Common/CoderMixer2.h"
+#include "../Common/CoderMixer2MT.h"
+#ifdef _ST_MODE
+#include "../Common/CoderMixer2ST.h"
+#endif
+
+#include "../../Common/CreateCoder.h"
+
+#include "7zItem.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CBindInfoEx: public NCoderMixer::CBindInfo
+{
+ CRecordVector CoderMethodIDs;
+ void Clear()
+ {
+ CBindInfo::Clear();
+ CoderMethodIDs.Clear();
+ }
+};
+
+class CDecoder
+{
+ bool _bindInfoExPrevIsDefined;
+ CBindInfoEx _bindInfoExPrev;
+
+ bool _multiThread;
+ #ifdef _ST_MODE
+ NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec;
+ #endif
+ NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec;
+ NCoderMixer::CCoderMixer2 *_mixerCoderCommon;
+
+ CMyComPtr _mixerCoder;
+ CObjectVector > _decoders;
+ // CObjectVector > _decoders2;
+public:
+ CDecoder(bool multiThread);
+ HRESULT Decode(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ IInStream *inStream,
+ UInt64 startPos,
+ const UInt64 *packSizes,
+ const CFolder &folder,
+ ISequentialOutStream *outStream,
+ ICompressProgressInfo *compressProgress
+ #ifndef _NO_CRYPTO
+ , ICryptoGetTextPassword *getTextPasswordSpec
+ #endif
+ #ifdef COMPRESS_MT
+ , bool mtMode, UInt32 numThreads
+ #endif
+ );
+};
+
+}}
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zEncode.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zEncode.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,453 @@
+// Encode.cpp
+
+#include "StdAfx.h"
+
+#include "7zEncode.h"
+#include "7zSpecStream.h"
+
+#include "../../IPassword.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/InOutTempBuffer.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/CreateCoder.h"
+#include "../../Common/FilterCoder.h"
+
+static const UInt64 k_AES = 0x06F10701;
+static const UInt64 k_BCJ = 0x03030103;
+static const UInt64 k_BCJ2 = 0x0303011B;
+
+namespace NArchive {
+namespace N7z {
+
+static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo,
+ const CRecordVector decompressionMethods,
+ CFolder &folder)
+{
+ folder.Coders.Clear();
+ // bindInfo.CoderMethodIDs.Clear();
+ // folder.OutStreams.Clear();
+ folder.PackStreams.Clear();
+ folder.BindPairs.Clear();
+ int i;
+ for (i = 0; i < bindInfo.BindPairs.Size(); i++)
+ {
+ CBindPair bindPair;
+ bindPair.InIndex = bindInfo.BindPairs[i].InIndex;
+ bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex;
+ folder.BindPairs.Add(bindPair);
+ }
+ for (i = 0; i < bindInfo.Coders.Size(); i++)
+ {
+ CCoderInfo coderInfo;
+ const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
+ coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;
+ coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;
+ coderInfo.MethodID = decompressionMethods[i];
+ folder.Coders.Add(coderInfo);
+ }
+ for (i = 0; i < bindInfo.InStreams.Size(); i++)
+ folder.PackStreams.Add(bindInfo.InStreams[i]);
+}
+
+HRESULT CEncoder::CreateMixerCoder(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const UInt64 *inSizeForReduce)
+{
+ _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT;
+ _mixerCoder = _mixerCoderSpec;
+ RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo));
+ for (int i = 0; i < _options.Methods.Size(); i++)
+ {
+ const CMethodFull &methodFull = _options.Methods[i];
+ _codersInfo.Add(CCoderInfo());
+ CCoderInfo &encodingInfo = _codersInfo.Back();
+ encodingInfo.MethodID = methodFull.Id;
+ CMyComPtr encoder;
+ CMyComPtr encoder2;
+
+
+ RINOK(CreateCoder(
+ EXTERNAL_CODECS_LOC_VARS
+ methodFull.Id, encoder, encoder2, true));
+
+ if (!encoder && !encoder2)
+ return E_FAIL;
+
+ CMyComPtr encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2;
+
+ #ifdef COMPRESS_MT
+ {
+ CMyComPtr setCoderMt;
+ encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
+ if (setCoderMt)
+ {
+ RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads));
+ }
+ }
+ #endif
+
+
+ RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon));
+
+ /*
+ CMyComPtr resetSalt;
+ encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);
+ if (resetSalt != NULL)
+ {
+ resetSalt->ResetSalt();
+ }
+ */
+
+ #ifdef EXTERNAL_CODECS
+ CMyComPtr setCompressCodecsInfo;
+ encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
+ if (setCompressCodecsInfo)
+ {
+ RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));
+ }
+ #endif
+
+ CMyComPtr cryptoSetPassword;
+ encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
+
+ if (cryptoSetPassword)
+ {
+ CByteBuffer buffer;
+ const UInt32 sizeInBytes = _options.Password.Length() * 2;
+ buffer.SetCapacity(sizeInBytes);
+ for (int i = 0; i < _options.Password.Length(); i++)
+ {
+ wchar_t c = _options.Password[i];
+ ((Byte *)buffer)[i * 2] = (Byte)c;
+ ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
+ }
+ RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
+ }
+
+ if (encoder)
+ _mixerCoderSpec->AddCoder(encoder);
+ else
+ _mixerCoderSpec->AddCoder2(encoder2);
+ }
+ return S_OK;
+}
+
+HRESULT CEncoder::Encode(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ ISequentialInStream *inStream,
+ const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
+ CFolder &folderItem,
+ ISequentialOutStream *outStream,
+ CRecordVector &packSizes,
+ ICompressProgressInfo *compressProgress)
+{
+ RINOK(EncoderConstr());
+
+ if (_mixerCoderSpec == NULL)
+ {
+ RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
+ }
+ _mixerCoderSpec->ReInit();
+ // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);
+
+ CObjectVector inOutTempBuffers;
+ CObjectVector tempBufferSpecs;
+ CObjectVector > tempBuffers;
+ int numMethods = _bindInfo.Coders.Size();
+ int i;
+ for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+ {
+ inOutTempBuffers.Add(CInOutTempBuffer());
+ inOutTempBuffers.Back().Create();
+ inOutTempBuffers.Back().InitWriting();
+ }
+ for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+ {
+ CSequentialOutTempBufferImp *tempBufferSpec =
+ new CSequentialOutTempBufferImp;
+ CMyComPtr tempBuffer = tempBufferSpec;
+ tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
+ tempBuffers.Add(tempBuffer);
+ tempBufferSpecs.Add(tempBufferSpec);
+ }
+
+ for (i = 0; i < numMethods; i++)
+ _mixerCoderSpec->SetCoderInfo(i, NULL, NULL);
+
+ if (_bindInfo.InStreams.IsEmpty())
+ return E_FAIL;
+ UInt32 mainCoderIndex, mainStreamIndex;
+ _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);
+
+ if (inStreamSize != NULL)
+ {
+ CRecordVector sizePointers;
+ for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)
+ if (i == mainStreamIndex)
+ sizePointers.Add(inStreamSize);
+ else
+ sizePointers.Add(NULL);
+ _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);
+ }
+
+
+ // UInt64 outStreamStartPos;
+ // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
+
+ CSequentialInStreamSizeCount2 *inStreamSizeCountSpec =
+ new CSequentialInStreamSizeCount2;
+ CMyComPtr inStreamSizeCount = inStreamSizeCountSpec;
+ CSequentialOutStreamSizeCount *outStreamSizeCountSpec =
+ new CSequentialOutStreamSizeCount;
+ CMyComPtr outStreamSizeCount = outStreamSizeCountSpec;
+
+ inStreamSizeCountSpec->Init(inStream);
+ outStreamSizeCountSpec->SetStream(outStream);
+ outStreamSizeCountSpec->Init();
+
+ CRecordVector inStreamPointers;
+ CRecordVector outStreamPointers;
+ inStreamPointers.Add(inStreamSizeCount);
+ outStreamPointers.Add(outStreamSizeCount);
+ for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+ outStreamPointers.Add(tempBuffers[i - 1]);
+
+ for (i = 0; i < _codersInfo.Size(); i++)
+ {
+ CCoderInfo &encodingInfo = _codersInfo[i];
+
+ CMyComPtr resetInitVector;
+ _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
+ if (resetInitVector != NULL)
+ {
+ resetInitVector->ResetInitVector();
+ }
+
+ CMyComPtr writeCoderProperties;
+ _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
+ if (writeCoderProperties != NULL)
+ {
+ CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;
+ CMyComPtr outStream(outStreamSpec);
+ outStreamSpec->Init();
+ writeCoderProperties->WriteCoderProperties(outStream);
+ size_t size = outStreamSpec->GetSize();
+ encodingInfo.Properties.SetCapacity(size);
+ memmove(encodingInfo.Properties, outStreamSpec->GetBuffer(), size);
+ }
+ }
+
+ UInt32 progressIndex = mainCoderIndex;
+
+ for (i = 0; i < _codersInfo.Size(); i++)
+ {
+ const CCoderInfo &e = _codersInfo[i];
+ if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size())
+ progressIndex = i + 1;
+ }
+
+ _mixerCoderSpec->SetProgressCoderIndex(progressIndex);
+
+ RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
+ &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
+
+ ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods,
+ folderItem);
+
+ packSizes.Add(outStreamSizeCountSpec->GetSize());
+
+ for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+ {
+ CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
+ inOutTempBuffer.FlushWrite();
+ inOutTempBuffer.InitReading();
+ inOutTempBuffer.WriteToStream(outStream);
+ packSizes.Add(inOutTempBuffer.GetDataSize());
+ }
+
+ for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)
+ {
+ int binder = _bindInfo.FindBinderForInStream(
+ _bindReverseConverter->DestOutToSrcInMap[i]);
+ UInt64 streamSize;
+ if (binder < 0)
+ streamSize = inStreamSizeCountSpec->GetSize();
+ else
+ streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);
+ folderItem.UnPackSizes.Add(streamSize);
+ }
+ for (i = numMethods - 1; i >= 0; i--)
+ folderItem.Coders[numMethods - 1 - i].Properties = _codersInfo[i].Properties;
+ return S_OK;
+}
+
+
+CEncoder::CEncoder(const CCompressionMethodMode &options):
+ _bindReverseConverter(0),
+ _constructed(false)
+{
+ if (options.IsEmpty())
+ throw 1;
+
+ _options = options;
+ _mixerCoderSpec = NULL;
+}
+
+HRESULT CEncoder::EncoderConstr()
+{
+ if (_constructed)
+ return S_OK;
+ if (_options.Methods.IsEmpty())
+ {
+ // it has only password method;
+ if (!_options.PasswordIsDefined)
+ throw 1;
+ if (!_options.Binds.IsEmpty())
+ throw 1;
+ NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
+ CMethodFull method;
+
+ method.NumInStreams = 1;
+ method.NumOutStreams = 1;
+ coderStreamsInfo.NumInStreams = 1;
+ coderStreamsInfo.NumOutStreams = 1;
+ method.Id = k_AES;
+
+ _options.Methods.Add(method);
+ _bindInfo.Coders.Add(coderStreamsInfo);
+
+ _bindInfo.InStreams.Add(0);
+ _bindInfo.OutStreams.Add(0);
+ }
+ else
+ {
+
+ UInt32 numInStreams = 0, numOutStreams = 0;
+ int i;
+ for (i = 0; i < _options.Methods.Size(); i++)
+ {
+ const CMethodFull &methodFull = _options.Methods[i];
+ NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
+ coderStreamsInfo.NumInStreams = methodFull.NumOutStreams;
+ coderStreamsInfo.NumOutStreams = methodFull.NumInStreams;
+ if (_options.Binds.IsEmpty())
+ {
+ if (i < _options.Methods.Size() - 1)
+ {
+ NCoderMixer::CBindPair bindPair;
+ bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams;
+ bindPair.OutIndex = numOutStreams;
+ _bindInfo.BindPairs.Add(bindPair);
+ }
+ else
+ _bindInfo.OutStreams.Insert(0, numOutStreams);
+ for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)
+ _bindInfo.OutStreams.Add(numOutStreams + j);
+ }
+
+ numInStreams += coderStreamsInfo.NumInStreams;
+ numOutStreams += coderStreamsInfo.NumOutStreams;
+
+ _bindInfo.Coders.Add(coderStreamsInfo);
+ }
+
+ if (!_options.Binds.IsEmpty())
+ {
+ for (i = 0; i < _options.Binds.Size(); i++)
+ {
+ NCoderMixer::CBindPair bindPair;
+ const CBind &bind = _options.Binds[i];
+ bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream;
+ bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream;
+ _bindInfo.BindPairs.Add(bindPair);
+ }
+ for (i = 0; i < (int)numOutStreams; i++)
+ if (_bindInfo.FindBinderForOutStream(i) == -1)
+ _bindInfo.OutStreams.Add(i);
+ }
+
+ for (i = 0; i < (int)numInStreams; i++)
+ if (_bindInfo.FindBinderForInStream(i) == -1)
+ _bindInfo.InStreams.Add(i);
+
+ if (_bindInfo.InStreams.IsEmpty())
+ throw 1; // this is error
+
+ // Make main stream first in list
+ int inIndex = _bindInfo.InStreams[0];
+ for (;;)
+ {
+ UInt32 coderIndex, coderStreamIndex;
+ _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);
+ UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
+ int binder = _bindInfo.FindBinderForOutStream(outIndex);
+ if (binder >= 0)
+ {
+ inIndex = _bindInfo.BindPairs[binder].InIndex;
+ continue;
+ }
+ for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
+ if (_bindInfo.OutStreams[i] == outIndex)
+ {
+ _bindInfo.OutStreams.Delete(i);
+ _bindInfo.OutStreams.Insert(0, outIndex);
+ break;
+ }
+ break;
+ }
+
+ if (_options.PasswordIsDefined)
+ {
+ int numCryptoStreams = _bindInfo.OutStreams.Size();
+
+ for (i = 0; i < numCryptoStreams; i++)
+ {
+ NCoderMixer::CBindPair bindPair;
+ bindPair.InIndex = numInStreams + i;
+ bindPair.OutIndex = _bindInfo.OutStreams[i];
+ _bindInfo.BindPairs.Add(bindPair);
+ }
+ _bindInfo.OutStreams.Clear();
+
+ /*
+ if (numCryptoStreams == 0)
+ numCryptoStreams = 1;
+ */
+
+ for (i = 0; i < numCryptoStreams; i++)
+ {
+ NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
+ CMethodFull method;
+ method.NumInStreams = 1;
+ method.NumOutStreams = 1;
+ coderStreamsInfo.NumInStreams = method.NumOutStreams;
+ coderStreamsInfo.NumOutStreams = method.NumInStreams;
+ method.Id = k_AES;
+
+ _options.Methods.Add(method);
+ _bindInfo.Coders.Add(coderStreamsInfo);
+ _bindInfo.OutStreams.Add(numOutStreams + i);
+ }
+ }
+
+ }
+
+ for (int i = _options.Methods.Size() - 1; i >= 0; i--)
+ {
+ const CMethodFull &methodFull = _options.Methods[i];
+ _decompressionMethods.Add(methodFull.Id);
+ }
+
+ _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo);
+ _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo);
+ _constructed = true;
+ return S_OK;
+}
+
+CEncoder::~CEncoder()
+{
+ delete _bindReverseConverter;
+}
+
+}}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zEncode.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zEncode.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,55 @@
+// 7zEncode.h
+
+#ifndef __7Z_ENCODE_H
+#define __7Z_ENCODE_H
+
+// #include "../../Common/StreamObjects.h"
+
+#include "7zCompressionMode.h"
+
+#include "../Common/CoderMixer2.h"
+#include "../Common/CoderMixer2MT.h"
+#ifdef _ST_MODE
+#include "../Common/CoderMixer2ST.h"
+#endif
+#include "7zItem.h"
+
+#include "../../Common/CreateCoder.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CEncoder
+{
+ NCoderMixer::CCoderMixer2MT *_mixerCoderSpec;
+ CMyComPtr _mixerCoder;
+
+ CObjectVector _codersInfo;
+
+ CCompressionMethodMode _options;
+ NCoderMixer::CBindInfo _bindInfo;
+ NCoderMixer::CBindInfo _decompressBindInfo;
+ NCoderMixer::CBindReverseConverter *_bindReverseConverter;
+ CRecordVector _decompressionMethods;
+
+ HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS
+ const UInt64 *inSizeForReduce);
+
+ bool _constructed;
+public:
+ CEncoder(const CCompressionMethodMode &options);
+ ~CEncoder();
+ HRESULT EncoderConstr();
+ HRESULT Encode(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ ISequentialInStream *inStream,
+ const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
+ CFolder &folderItem,
+ ISequentialOutStream *outStream,
+ CRecordVector &packSizes,
+ ICompressProgressInfo *compressProgress);
+};
+
+}}
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zExtract.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zExtract.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,269 @@
+// 7zExtract.cpp
+
+#include "StdAfx.h"
+
+#include "7zHandler.h"
+#include "7zFolderOutStream.h"
+#include "7zDecode.h"
+// #include "7z1Decode.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CExtractFolderInfo
+{
+ #ifdef _7Z_VOL
+ int VolumeIndex;
+ #endif
+ CNum FileIndex;
+ CNum FolderIndex;
+ CBoolVector ExtractStatuses;
+ UInt64 UnPackSize;
+ CExtractFolderInfo(
+ #ifdef _7Z_VOL
+ int volumeIndex,
+ #endif
+ CNum fileIndex, CNum folderIndex):
+ #ifdef _7Z_VOL
+ VolumeIndex(volumeIndex),
+ #endif
+ FileIndex(fileIndex),
+ FolderIndex(folderIndex),
+ UnPackSize(0)
+ {
+ if (fileIndex != kNumNoIndex)
+ {
+ ExtractStatuses.Reserve(1);
+ ExtractStatuses.Add(true);
+ }
+ };
+};
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)
+{
+ COM_TRY_BEGIN
+ bool testMode = (testModeSpec != 0);
+ CMyComPtr extractCallback = extractCallbackSpec;
+ UInt64 importantTotalUnPacked = 0;
+
+ bool allFilesMode = (numItems == UInt32(-1));
+ if (allFilesMode)
+ numItems =
+ #ifdef _7Z_VOL
+ _refs.Size();
+ #else
+ _database.Files.Size();
+ #endif
+
+ if(numItems == 0)
+ return S_OK;
+
+ /*
+ if(_volumes.Size() != 1)
+ return E_FAIL;
+ const CVolume &volume = _volumes.Front();
+ const CArchiveDatabaseEx &_database = volume.Database;
+ IInStream *_inStream = volume.Stream;
+ */
+
+ CObjectVector extractFolderInfoVector;
+ for(UInt32 ii = 0; ii < numItems; ii++)
+ {
+ // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex];
+ UInt32 ref2Index = allFilesMode ? ii : indices[ii];
+ // const CRef2 &ref2 = _refs[ref2Index];
+
+ // for(UInt32 ri = 0; ri < ref2.Refs.Size(); ri++)
+ {
+ #ifdef _7Z_VOL
+ // const CRef &ref = ref2.Refs[ri];
+ const CRef &ref = _refs[ref2Index];
+
+ int volumeIndex = ref.VolumeIndex;
+ const CVolume &volume = _volumes[volumeIndex];
+ const CArchiveDatabaseEx &database = volume.Database;
+ UInt32 fileIndex = ref.ItemIndex;
+ #else
+ const CArchiveDatabaseEx &database = _database;
+ UInt32 fileIndex = ref2Index;
+ #endif
+
+ CNum folderIndex = database.FileIndexToFolderIndexMap[fileIndex];
+ if (folderIndex == kNumNoIndex)
+ {
+ extractFolderInfoVector.Add(CExtractFolderInfo(
+ #ifdef _7Z_VOL
+ volumeIndex,
+ #endif
+ fileIndex, kNumNoIndex));
+ continue;
+ }
+ if (extractFolderInfoVector.IsEmpty() ||
+ folderIndex != extractFolderInfoVector.Back().FolderIndex
+ #ifdef _7Z_VOL
+ || volumeIndex != extractFolderInfoVector.Back().VolumeIndex
+ #endif
+ )
+ {
+ extractFolderInfoVector.Add(CExtractFolderInfo(
+ #ifdef _7Z_VOL
+ volumeIndex,
+ #endif
+ kNumNoIndex, folderIndex));
+ const CFolder &folderInfo = database.Folders[folderIndex];
+ UInt64 unPackSize = folderInfo.GetUnPackSize();
+ importantTotalUnPacked += unPackSize;
+ extractFolderInfoVector.Back().UnPackSize = unPackSize;
+ }
+
+ CExtractFolderInfo &efi = extractFolderInfoVector.Back();
+
+ // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex];
+ CNum startIndex = database.FolderStartFileIndex[folderIndex];
+ for (CNum index = efi.ExtractStatuses.Size();
+ index <= fileIndex - startIndex; index++)
+ {
+ // UInt64 unPackSize = _database.Files[startIndex + index].UnPackSize;
+ // Count partial_folder_size
+ // efi.UnPackSize += unPackSize;
+ // importantTotalUnPacked += unPackSize;
+ efi.ExtractStatuses.Add(index == fileIndex - startIndex);
+ }
+ }
+ }
+
+ extractCallback->SetTotal(importantTotalUnPacked);
+
+ CDecoder decoder(
+ #ifdef _ST_MODE
+ false
+ #else
+ true
+ #endif
+ );
+ // CDecoder1 decoder;
+
+ UInt64 currentTotalPacked = 0;
+ UInt64 currentTotalUnPacked = 0;
+ UInt64 totalFolderUnPacked;
+ UInt64 totalFolderPacked;
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr progress = lps;
+ lps->Init(extractCallback, false);
+
+ for(int i = 0; i < extractFolderInfoVector.Size(); i++,
+ currentTotalUnPacked += totalFolderUnPacked,
+ currentTotalPacked += totalFolderPacked)
+ {
+ lps->OutSize = currentTotalUnPacked;
+ lps->InSize = currentTotalPacked;
+ RINOK(lps->SetCur());
+
+ const CExtractFolderInfo &efi = extractFolderInfoVector[i];
+ totalFolderUnPacked = efi.UnPackSize;
+
+ totalFolderPacked = 0;
+
+ CFolderOutStream *folderOutStream = new CFolderOutStream;
+ CMyComPtr outStream(folderOutStream);
+
+ #ifdef _7Z_VOL
+ const CVolume &volume = _volumes[efi.VolumeIndex];
+ const CArchiveDatabaseEx &database = volume.Database;
+ #else
+ const CArchiveDatabaseEx &database = _database;
+ #endif
+
+ CNum startIndex;
+ if (efi.FileIndex != kNumNoIndex)
+ startIndex = efi.FileIndex;
+ else
+ startIndex = database.FolderStartFileIndex[efi.FolderIndex];
+
+
+ HRESULT result = folderOutStream->Init(&database,
+ #ifdef _7Z_VOL
+ volume.StartRef2Index,
+ #else
+ 0,
+ #endif
+ startIndex,
+ &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0);
+
+ RINOK(result);
+
+ if (efi.FileIndex != kNumNoIndex)
+ continue;
+
+ CNum folderIndex = efi.FolderIndex;
+ const CFolder &folderInfo = database.Folders[folderIndex];
+
+ totalFolderPacked = _database.GetFolderFullPackSize(folderIndex);
+
+ CNum packStreamIndex = database.FolderStartPackStreamIndex[folderIndex];
+ UInt64 folderStartPackPos = database.GetFolderStreamPos(folderIndex, 0);
+
+ #ifndef _NO_CRYPTO
+ CMyComPtr getTextPassword;
+ if (extractCallback)
+ extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
+ #endif
+
+ try
+ {
+ HRESULT result = decoder.Decode(
+ EXTERNAL_CODECS_VARS
+ #ifdef _7Z_VOL
+ volume.Stream,
+ #else
+ _inStream,
+ #endif
+ folderStartPackPos,
+ &database.PackSizes[packStreamIndex],
+ folderInfo,
+ outStream,
+ progress
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ #ifdef COMPRESS_MT
+ , true, _numThreads
+ #endif
+ );
+
+ if (result == S_FALSE)
+ {
+ RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError));
+ continue;
+ }
+ if (result == E_NOTIMPL)
+ {
+ RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ continue;
+ }
+ if (result != S_OK)
+ return result;
+ if (folderOutStream->WasWritingFinished() != S_OK)
+ {
+ RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError));
+ continue;
+ }
+ }
+ catch(...)
+ {
+ RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError));
+ continue;
+ }
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+}}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zFolderInStream.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zFolderInStream.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,130 @@
+// 7zFolderInStream.cpp
+
+#include "StdAfx.h"
+
+#include "7zFolderInStream.h"
+
+namespace NArchive {
+namespace N7z {
+
+CFolderInStream::CFolderInStream()
+{
+ _inStreamWithHashSpec = new CSequentialInStreamWithCRC;
+ _inStreamWithHash = _inStreamWithHashSpec;
+}
+
+void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
+ const UInt32 *fileIndices, UInt32 numFiles)
+{
+ _updateCallback = updateCallback;
+ _numFiles = numFiles;
+ _fileIndex = 0;
+ _fileIndices = fileIndices;
+ Processed.Clear();
+ CRCs.Clear();
+ Sizes.Clear();
+ _fileIsOpen = false;
+ _currentSizeIsDefined = false;
+}
+
+HRESULT CFolderInStream::OpenStream()
+{
+ _filePos = 0;
+ while (_fileIndex < _numFiles)
+ {
+ _currentSizeIsDefined = false;
+ CMyComPtr stream;
+ HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream);
+ if (result != S_OK && result != S_FALSE)
+ return result;
+ _fileIndex++;
+ _inStreamWithHashSpec->SetStream(stream);
+ _inStreamWithHashSpec->Init();
+ if (!stream)
+ {
+ RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+ Sizes.Add(0);
+ Processed.Add(result == S_OK);
+ AddDigest();
+ continue;
+ }
+ CMyComPtr streamGetSize;
+ if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK)
+ {
+ if(streamGetSize)
+ {
+ _currentSizeIsDefined = true;
+ RINOK(streamGetSize->GetSize(&_currentSize));
+ }
+ }
+
+ _fileIsOpen = true;
+ return S_OK;
+ }
+ return S_OK;
+}
+
+void CFolderInStream::AddDigest()
+{
+ CRCs.Add(_inStreamWithHashSpec->GetCRC());
+}
+
+HRESULT CFolderInStream::CloseStream()
+{
+ RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+ _inStreamWithHashSpec->ReleaseStream();
+ _fileIsOpen = false;
+ Processed.Add(true);
+ Sizes.Add(_filePos);
+ AddDigest();
+ return S_OK;
+}
+
+STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize = 0;
+ while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0)
+ {
+ if (_fileIsOpen)
+ {
+ UInt32 localProcessedSize;
+ RINOK(_inStreamWithHash->Read(
+ ((Byte *)data) + realProcessedSize, size, &localProcessedSize));
+ if (localProcessedSize == 0)
+ {
+ RINOK(CloseStream());
+ continue;
+ }
+ realProcessedSize += localProcessedSize;
+ _filePos += localProcessedSize;
+ size -= localProcessedSize;
+ break;
+ }
+ else
+ {
+ RINOK(OpenStream());
+ }
+ }
+ if (processedSize != 0)
+ *processedSize = realProcessedSize;
+ return S_OK;
+}
+
+STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
+{
+ *value = 0;
+ int subStreamIndex = (int)subStream;
+ if (subStreamIndex < 0 || subStream > Sizes.Size())
+ return E_FAIL;
+ if (subStreamIndex < Sizes.Size())
+ {
+ *value= Sizes[subStreamIndex];
+ return S_OK;
+ }
+ if (!_currentSizeIsDefined)
+ return S_FALSE;
+ *value = _currentSize;
+ return S_OK;
+}
+
+}}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zFolderInStream.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zFolderInStream.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,66 @@
+// 7z/FolderInStream.h
+
+#ifndef __7Z_FOLDERINSTREAM_H
+#define __7Z_FOLDERINSTREAM_H
+
+#include "7zItem.h"
+#include "7zHeader.h"
+
+#include "../IArchive.h"
+#include "../Common/InStreamWithCRC.h"
+#include "../../IStream.h"
+#include "../../ICoder.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CFolderInStream:
+ public ISequentialInStream,
+ public ICompressGetSubStreamSize,
+ public CMyUnknownImp
+{
+public:
+
+ MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
+
+ CFolderInStream();
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+ STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
+private:
+ CSequentialInStreamWithCRC *_inStreamWithHashSpec;
+ CMyComPtr _inStreamWithHash;
+ CMyComPtr _updateCallback;
+
+ bool _currentSizeIsDefined;
+ UInt64 _currentSize;
+
+ bool _fileIsOpen;
+ UInt64 _filePos;
+
+ const UInt32 *_fileIndices;
+ UInt32 _numFiles;
+ UInt32 _fileIndex;
+
+ HRESULT OpenStream();
+ HRESULT CloseStream();
+ void AddDigest();
+public:
+ void Init(IArchiveUpdateCallback *updateCallback,
+ const UInt32 *fileIndices, UInt32 numFiles);
+ CRecordVector Processed;
+ CRecordVector CRCs;
+ CRecordVector Sizes;
+ UInt64 GetFullSize() const
+ {
+ UInt64 size = 0;
+ for (int i = 0; i < Sizes.Size(); i++)
+ size += Sizes[i];
+ return size;
+ }
+};
+
+}}
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,165 @@
+// 7zFolderOutStream.cpp
+
+#include "StdAfx.h"
+
+#include "7zFolderOutStream.h"
+
+namespace NArchive {
+namespace N7z {
+
+CFolderOutStream::CFolderOutStream()
+{
+ _outStreamWithHashSpec = new COutStreamWithCRC;
+ _outStreamWithHash = _outStreamWithHashSpec;
+}
+
+HRESULT CFolderOutStream::Init(
+ const CArchiveDatabaseEx *archiveDatabase,
+ UInt32 ref2Offset,
+ UInt32 startIndex,
+ const CBoolVector *extractStatuses,
+ IArchiveExtractCallback *extractCallback,
+ bool testMode,
+ bool checkCrc)
+{
+ _archiveDatabase = archiveDatabase;
+ _ref2Offset = ref2Offset;
+ _startIndex = startIndex;
+
+ _extractStatuses = extractStatuses;
+ _extractCallback = extractCallback;
+ _testMode = testMode;
+
+ _checkCrc = checkCrc;
+
+ _currentIndex = 0;
+ _fileIsOpen = false;
+ return WriteEmptyFiles();
+}
+
+HRESULT CFolderOutStream::OpenFile()
+{
+ Int32 askMode;
+ if((*_extractStatuses)[_currentIndex])
+ askMode = _testMode ?
+ NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+ else
+ askMode = NArchive::NExtract::NAskMode::kSkip;
+ CMyComPtr realOutStream;
+
+ UInt32 index = _startIndex + _currentIndex;
+ RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
+
+ _outStreamWithHashSpec->SetStream(realOutStream);
+ _outStreamWithHashSpec->Init(_checkCrc);
+ if (askMode == NArchive::NExtract::NAskMode::kExtract &&
+ (!realOutStream))
+ {
+ const CFileItem &fileInfo = _archiveDatabase->Files[index];
+ if (!fileInfo.IsAnti && !fileInfo.IsDirectory)
+ askMode = NArchive::NExtract::NAskMode::kSkip;
+ }
+ return _extractCallback->PrepareOperation(askMode);
+}
+
+HRESULT CFolderOutStream::WriteEmptyFiles()
+{
+ for(;_currentIndex < _extractStatuses->Size(); _currentIndex++)
+ {
+ UInt32 index = _startIndex + _currentIndex;
+ const CFileItem &fileInfo = _archiveDatabase->Files[index];
+ if (!fileInfo.IsAnti && !fileInfo.IsDirectory && fileInfo.UnPackSize != 0)
+ return S_OK;
+ RINOK(OpenFile());
+ RINOK(_extractCallback->SetOperationResult(
+ NArchive::NExtract::NOperationResult::kOK));
+ _outStreamWithHashSpec->ReleaseStream();
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CFolderOutStream::Write(const void *data,
+ UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize = 0;
+ while(_currentIndex < _extractStatuses->Size())
+ {
+ if (_fileIsOpen)
+ {
+ UInt32 index = _startIndex + _currentIndex;
+ const CFileItem &fileInfo = _archiveDatabase->Files[index];
+ UInt64 fileSize = fileInfo.UnPackSize;
+
+ UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos,
+ UInt64(size - realProcessedSize));
+
+ UInt32 processedSizeLocal;
+ RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize,
+ numBytesToWrite, &processedSizeLocal));
+
+ _filePos += processedSizeLocal;
+ realProcessedSize += processedSizeLocal;
+ if (_filePos == fileSize)
+ {
+ bool digestsAreEqual;
+ if (fileInfo.IsFileCRCDefined && _checkCrc)
+ digestsAreEqual = fileInfo.FileCRC == _outStreamWithHashSpec->GetCRC();
+ else
+ digestsAreEqual = true;
+
+ RINOK(_extractCallback->SetOperationResult(
+ digestsAreEqual ?
+ NArchive::NExtract::NOperationResult::kOK :
+ NArchive::NExtract::NOperationResult::kCRCError));
+ _outStreamWithHashSpec->ReleaseStream();
+ _fileIsOpen = false;
+ _currentIndex++;
+ }
+ if (realProcessedSize == size)
+ {
+ if (processedSize != NULL)
+ *processedSize = realProcessedSize;
+ return WriteEmptyFiles();
+ }
+ }
+ else
+ {
+ RINOK(OpenFile());
+ _fileIsOpen = true;
+ _filePos = 0;
+ }
+ }
+ if (processedSize != NULL)
+ *processedSize = size;
+ return S_OK;
+}
+
+HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
+{
+ while(_currentIndex < _extractStatuses->Size())
+ {
+ if (_fileIsOpen)
+ {
+ RINOK(_extractCallback->SetOperationResult(resultEOperationResult));
+ _outStreamWithHashSpec->ReleaseStream();
+ _fileIsOpen = false;
+ _currentIndex++;
+ }
+ else
+ {
+ RINOK(OpenFile());
+ _fileIsOpen = true;
+ }
+ }
+ return S_OK;
+}
+
+HRESULT CFolderOutStream::WasWritingFinished()
+{
+ if (_currentIndex == _extractStatuses->Size())
+ return S_OK;
+ return E_FAIL;
+}
+
+}}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,60 @@
+// 7zFolderOutStream.h
+
+#ifndef __7Z_FOLDEROUTSTREAM_H
+#define __7Z_FOLDEROUTSTREAM_H
+
+#include "7zIn.h"
+
+#include "../../IStream.h"
+#include "../IArchive.h"
+#include "../Common/OutStreamWithCRC.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CFolderOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ CFolderOutStream();
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+private:
+
+ COutStreamWithCRC *_outStreamWithHashSpec;
+ CMyComPtr _outStreamWithHash;
+ const CArchiveDatabaseEx *_archiveDatabase;
+ const CBoolVector *_extractStatuses;
+ UInt32 _startIndex;
+ UInt32 _ref2Offset;
+ int _currentIndex;
+ // UInt64 _currentDataPos;
+ CMyComPtr _extractCallback;
+ bool _testMode;
+
+ bool _fileIsOpen;
+
+ bool _checkCrc;
+ UInt64 _filePos;
+
+ HRESULT OpenFile();
+ HRESULT WriteEmptyFiles();
+public:
+ HRESULT Init(
+ const CArchiveDatabaseEx *archiveDatabase,
+ UInt32 ref2Offset,
+ UInt32 startIndex,
+ const CBoolVector *extractStatuses,
+ IArchiveExtractCallback *extractCallback,
+ bool testMode,
+ bool checkCrc);
+ HRESULT FlushCorrupted(Int32 resultEOperationResult);
+ HRESULT WasWritingFinished();
+};
+
+}}
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zHandler.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zHandler.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,793 @@
+// 7zHandler.cpp
+
+#include "StdAfx.h"
+
+#include "7zHandler.h"
+#include "7zProperties.h"
+
+#include "../../../Common/IntToString.h"
+#include "../../../Common/ComTry.h"
+#include "../../../Windows/Defs.h"
+
+#include "../Common/ItemNameUtils.h"
+#ifdef _7Z_VOL
+#include "../Common/MultiStream.h"
+#endif
+
+#ifdef __7Z_SET_PROPERTIES
+#ifdef EXTRACT_ONLY
+#include "../Common/ParseProperties.h"
+#endif
+#endif
+
+#ifdef COMPRESS_MT
+#include "../../../Windows/System.h"
+#endif
+
+using namespace NWindows;
+
+extern UString ConvertMethodIdToString(UInt64 id);
+
+namespace NArchive {
+namespace N7z {
+
+CHandler::CHandler()
+{
+ _crcSize = 4;
+
+ #ifdef EXTRACT_ONLY
+ #ifdef COMPRESS_MT
+ _numThreads = NWindows::NSystem::GetNumberOfProcessors();
+ #endif
+ #else
+ Init();
+ #endif
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems =
+ #ifdef _7Z_VOL
+ _refs.Size();
+ #else
+ *numItems = _database.Files.Size();
+ #endif
+ return S_OK;
+}
+
+#ifdef _SFX
+
+IMP_IInArchive_ArcProps_NO
+
+STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)
+{
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
+ BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
+{
+ return E_NOTIMPL;
+}
+
+
+#else
+
+STATPROPSTG kArcProps[] =
+{
+ { NULL, kpidMethod, VT_BSTR},
+ { NULL, kpidSolid, VT_BOOL},
+ { NULL, kpidNumBlocks, VT_UI4}
+};
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant prop;
+ switch(propID)
+ {
+ case kpidMethod:
+ {
+ UString resString;
+ CRecordVector ids;
+ int i;
+ for (i = 0; i < _database.Folders.Size(); i++)
+ {
+ const CFolder &f = _database.Folders[i];
+ for (int j = f.Coders.Size() - 1; j >= 0; j--)
+ ids.AddToUniqueSorted(f.Coders[j].MethodID);
+ }
+
+ for (i = 0; i < ids.Size(); i++)
+ {
+ UInt64 id = ids[i];
+ UString methodName;
+ /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName);
+ if (methodName.IsEmpty())
+ methodName = ConvertMethodIdToString(id);
+ if (!resString.IsEmpty())
+ resString += L' ';
+ resString += methodName;
+ }
+ prop = resString;
+ break;
+ }
+ case kpidSolid: prop = _database.IsSolid(); break;
+ case kpidNumBlocks: prop = (UInt32)_database.Folders.Size(); break;
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+IMP_IInArchive_ArcProps
+
+#endif
+
+static void MySetFileTime(bool timeDefined, FILETIME unixTime, NWindows::NCOM::CPropVariant &prop)
+{
+ if (timeDefined)
+ prop = unixTime;
+}
+
+#ifndef _SFX
+
+static UString ConvertUInt32ToString(UInt32 value)
+{
+ wchar_t buffer[32];
+ ConvertUInt64ToString(value, buffer);
+ return buffer;
+}
+
+static UString GetStringForSizeValue(UInt32 value)
+{
+ for (int i = 31; i >= 0; i--)
+ if ((UInt32(1) << i) == value)
+ return ConvertUInt32ToString(i);
+ UString result;
+ if (value % (1 << 20) == 0)
+ {
+ result += ConvertUInt32ToString(value >> 20);
+ result += L"m";
+ }
+ else if (value % (1 << 10) == 0)
+ {
+ result += ConvertUInt32ToString(value >> 10);
+ result += L"k";
+ }
+ else
+ {
+ result += ConvertUInt32ToString(value);
+ result += L"b";
+ }
+ return result;
+}
+
+static const UInt64 k_Copy = 0x0;
+static const UInt64 k_LZMA = 0x030101;
+static const UInt64 k_PPMD = 0x030401;
+
+static wchar_t GetHex(Byte value)
+{
+ return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
+}
+static inline UString GetHex2(Byte value)
+{
+ UString result;
+ result += GetHex((Byte)(value >> 4));
+ result += GetHex((Byte)(value & 0xF));
+ return result;
+}
+
+#endif
+
+static const UInt64 k_AES = 0x06F10701;
+
+#ifndef _SFX
+static inline UInt32 GetUInt32FromMemLE(const Byte *p)
+{
+ return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24);
+}
+#endif
+
+bool CHandler::IsEncrypted(UInt32 index2) const
+{
+ CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ {
+ const CFolder &folderInfo = _database.Folders[folderIndex];
+ for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
+ if (folderInfo.Coders[i].MethodID == k_AES)
+ return true;
+ }
+ return false;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant prop;
+
+ /*
+ const CRef2 &ref2 = _refs[index];
+ if (ref2.Refs.IsEmpty())
+ return E_FAIL;
+ const CRef &ref = ref2.Refs.Front();
+ */
+
+ #ifdef _7Z_VOL
+ const CRef &ref = _refs[index];
+ const CVolume &volume = _volumes[ref.VolumeIndex];
+ const CArchiveDatabaseEx &_database = volume.Database;
+ UInt32 index2 = ref.ItemIndex;
+ const CFileItem &item = _database.Files[index2];
+ #else
+ const CFileItem &item = _database.Files[index];
+ UInt32 index2 = index;
+ #endif
+
+ switch(propID)
+ {
+ case kpidPath:
+ {
+ if (!item.Name.IsEmpty())
+ prop = NItemName::GetOSName(item.Name);
+ break;
+ }
+ case kpidIsFolder:
+ prop = item.IsDirectory;
+ break;
+ case kpidSize:
+ {
+ prop = item.UnPackSize;
+ // prop = ref2.UnPackSize;
+ break;
+ }
+ case kpidPosition:
+ {
+ /*
+ if (ref2.Refs.Size() > 1)
+ prop = ref2.StartPos;
+ else
+ */
+ if (item.IsStartPosDefined)
+ prop = item.StartPos;
+ break;
+ }
+ case kpidPackedSize:
+ {
+ // prop = ref2.PackSize;
+ {
+ CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ {
+ if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2)
+ prop = _database.GetFolderFullPackSize(folderIndex);
+ /*
+ else
+ prop = (UInt64)0;
+ */
+ }
+ else
+ prop = (UInt64)0;
+ }
+ break;
+ }
+ case kpidLastAccessTime:
+ MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, prop);
+ break;
+ case kpidCreationTime:
+ MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, prop);
+ break;
+ case kpidLastWriteTime:
+ MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, prop);
+ break;
+ case kpidAttributes:
+ if (item.AreAttributesDefined)
+ prop = item.Attributes;
+ break;
+ case kpidCRC:
+ if (item.IsFileCRCDefined)
+ prop = item.FileCRC;
+ break;
+ case kpidEncrypted:
+ {
+ prop = IsEncrypted(index2);
+ break;
+ }
+ #ifndef _SFX
+ case kpidMethod:
+ {
+ CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ {
+ const CFolder &folderInfo = _database.Folders[folderIndex];
+ UString methodsString;
+ for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
+ {
+ const CCoderInfo &coderInfo = folderInfo.Coders[i];
+ if (!methodsString.IsEmpty())
+ methodsString += L' ';
+
+ {
+ UString methodName;
+ bool methodIsKnown = FindMethod(
+ EXTERNAL_CODECS_VARS
+ coderInfo.MethodID, methodName);
+
+ if (methodIsKnown)
+ {
+ methodsString += methodName;
+ if (coderInfo.MethodID == k_LZMA)
+ {
+ if (coderInfo.Properties.GetCapacity() >= 5)
+ {
+ methodsString += L":";
+ UInt32 dicSize = GetUInt32FromMemLE(
+ ((const Byte *)coderInfo.Properties + 1));
+ methodsString += GetStringForSizeValue(dicSize);
+ }
+ }
+ else if (coderInfo.MethodID == k_PPMD)
+ {
+ if (coderInfo.Properties.GetCapacity() >= 5)
+ {
+ Byte order = *(const Byte *)coderInfo.Properties;
+ methodsString += L":o";
+ methodsString += ConvertUInt32ToString(order);
+ methodsString += L":mem";
+ UInt32 dicSize = GetUInt32FromMemLE(
+ ((const Byte *)coderInfo.Properties + 1));
+ methodsString += GetStringForSizeValue(dicSize);
+ }
+ }
+ else if (coderInfo.MethodID == k_AES)
+ {
+ if (coderInfo.Properties.GetCapacity() >= 1)
+ {
+ methodsString += L":";
+ const Byte *data = (const Byte *)coderInfo.Properties;
+ Byte firstByte = *data++;
+ UInt32 numCyclesPower = firstByte & 0x3F;
+ methodsString += ConvertUInt32ToString(numCyclesPower);
+ /*
+ if ((firstByte & 0xC0) != 0)
+ {
+ methodsString += L":";
+ return S_OK;
+ UInt32 saltSize = (firstByte >> 7) & 1;
+ UInt32 ivSize = (firstByte >> 6) & 1;
+ if (coderInfo.Properties.GetCapacity() >= 2)
+ {
+ Byte secondByte = *data++;
+ saltSize += (secondByte >> 4);
+ ivSize += (secondByte & 0x0F);
+ }
+ }
+ */
+ }
+ }
+ else
+ {
+ if (coderInfo.Properties.GetCapacity() > 0)
+ {
+ methodsString += L":[";
+ for (size_t bi = 0; bi < coderInfo.Properties.GetCapacity(); bi++)
+ {
+ if (bi > 5 && bi + 1 < coderInfo.Properties.GetCapacity())
+ {
+ methodsString += L"..";
+ break;
+ }
+ else
+ methodsString += GetHex2(coderInfo.Properties[bi]);
+ }
+ methodsString += L"]";
+ }
+ }
+ }
+ else
+ {
+ methodsString += ConvertMethodIdToString(coderInfo.MethodID);
+ }
+ }
+ }
+ prop = methodsString;
+ }
+ }
+ break;
+ case kpidBlock:
+ {
+ CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ prop = (UInt32)folderIndex;
+ }
+ break;
+ case kpidPackedSize0:
+ case kpidPackedSize1:
+ case kpidPackedSize2:
+ case kpidPackedSize3:
+ case kpidPackedSize4:
+ {
+ CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ {
+ const CFolder &folderInfo = _database.Folders[folderIndex];
+ if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
+ folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))
+ {
+ prop = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
+ }
+ else
+ prop = (UInt64)0;
+ }
+ else
+ prop = (UInt64)0;
+ }
+ break;
+ #endif
+ case kpidIsAnti:
+ prop = item.IsAnti;
+ break;
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+#ifdef _7Z_VOL
+
+static const wchar_t *kExt = L"7z";
+static const wchar_t *kAfterPart = L".7z";
+
+class CVolumeName
+{
+ bool _first;
+ UString _unchangedPart;
+ UString _changedPart;
+ UString _afterPart;
+public:
+ bool InitName(const UString &name)
+ {
+ _first = true;
+ int dotPos = name.ReverseFind('.');
+ UString basePart = name;
+ if (dotPos >= 0)
+ {
+ UString ext = name.Mid(dotPos + 1);
+ if (ext.CompareNoCase(kExt)==0 ||
+ ext.CompareNoCase(L"EXE") == 0)
+ {
+ _afterPart = kAfterPart;
+ basePart = name.Left(dotPos);
+ }
+ }
+
+ int numLetters = 1;
+ bool splitStyle = false;
+ if (basePart.Right(numLetters) == L"1")
+ {
+ while (numLetters < basePart.Length())
+ {
+ if (basePart[basePart.Length() - numLetters - 1] != '0')
+ break;
+ numLetters++;
+ }
+ }
+ else
+ return false;
+ _unchangedPart = basePart.Left(basePart.Length() - numLetters);
+ _changedPart = basePart.Right(numLetters);
+ return true;
+ }
+
+ UString GetNextName()
+ {
+ UString newName;
+ // if (_newStyle || !_first)
+ {
+ int i;
+ int numLetters = _changedPart.Length();
+ for (i = numLetters - 1; i >= 0; i--)
+ {
+ wchar_t c = _changedPart[i];
+ if (c == L'9')
+ {
+ c = L'0';
+ newName = c + newName;
+ if (i == 0)
+ newName = UString(L'1') + newName;
+ continue;
+ }
+ c++;
+ newName = UString(c) + newName;
+ i--;
+ for (; i >= 0; i--)
+ newName = _changedPart[i] + newName;
+ break;
+ }
+ _changedPart = newName;
+ }
+ _first = false;
+ return _unchangedPart + _changedPart + _afterPart;
+ }
+};
+
+#endif
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ COM_TRY_BEGIN
+ Close();
+ #ifndef _SFX
+ _fileInfoPopIDs.Clear();
+ #endif
+ try
+ {
+ CMyComPtr openArchiveCallbackTemp = openArchiveCallback;
+ #ifdef _7Z_VOL
+ CVolumeName seqName;
+
+ CMyComPtr openVolumeCallback;
+ #endif
+
+ #ifndef _NO_CRYPTO
+ CMyComPtr getTextPassword;
+ if (openArchiveCallback)
+ {
+ openArchiveCallbackTemp.QueryInterface(
+ IID_ICryptoGetTextPassword, &getTextPassword);
+ }
+ #endif
+ #ifdef _7Z_VOL
+ if (openArchiveCallback)
+ {
+ openArchiveCallbackTemp.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
+ }
+ for (;;)
+ {
+ CMyComPtr inStream;
+ if (!_volumes.IsEmpty())
+ {
+ if (!openVolumeCallback)
+ break;
+ if(_volumes.Size() == 1)
+ {
+ UString baseName;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
+ if (prop.vt != VT_BSTR)
+ break;
+ baseName = prop.bstrVal;
+ }
+ seqName.InitName(baseName);
+ }
+
+ UString fullName = seqName.GetNextName();
+ HRESULT result = openVolumeCallback->GetStream(fullName, &inStream);
+ if (result == S_FALSE)
+ break;
+ if (result != S_OK)
+ return result;
+ if (!stream)
+ break;
+ }
+ else
+ inStream = stream;
+
+ CInArchive archive;
+ RINOK(archive.Open(inStream, maxCheckStartPosition));
+
+ _volumes.Add(CVolume());
+ CVolume &volume = _volumes.Back();
+ CArchiveDatabaseEx &database = volume.Database;
+ volume.Stream = inStream;
+ volume.StartRef2Index = _refs.Size();
+
+ HRESULT result = archive.ReadDatabase(database
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ );
+ if (result != S_OK)
+ {
+ _volumes.Clear();
+ return result;
+ }
+ database.Fill();
+ for(int i = 0; i < database.Files.Size(); i++)
+ {
+ CRef refNew;
+ refNew.VolumeIndex = _volumes.Size() - 1;
+ refNew.ItemIndex = i;
+ _refs.Add(refNew);
+ /*
+ const CFileItem &file = database.Files[i];
+ int j;
+ */
+ /*
+ for (j = _refs.Size() - 1; j >= 0; j--)
+ {
+ CRef2 &ref2 = _refs[j];
+ const CRef &ref = ref2.Refs.Back();
+ const CVolume &volume2 = _volumes[ref.VolumeIndex];
+ const CArchiveDatabaseEx &database2 = volume2.Database;
+ const CFileItem &file2 = database2.Files[ref.ItemIndex];
+ if (file2.Name.CompareNoCase(file.Name) == 0)
+ {
+ if (!file.IsStartPosDefined)
+ continue;
+ if (file.StartPos != ref2.StartPos + ref2.UnPackSize)
+ continue;
+ ref2.Refs.Add(refNew);
+ break;
+ }
+ }
+ */
+ /*
+ j = -1;
+ if (j < 0)
+ {
+ CRef2 ref2New;
+ ref2New.Refs.Add(refNew);
+ j = _refs.Add(ref2New);
+ }
+ CRef2 &ref2 = _refs[j];
+ ref2.UnPackSize += file.UnPackSize;
+ ref2.PackSize += database.GetFilePackSize(i);
+ if (ref2.Refs.Size() == 1 && file.IsStartPosDefined)
+ ref2.StartPos = file.StartPos;
+ */
+ }
+ if (database.Files.Size() != 1)
+ break;
+ const CFileItem &file = database.Files.Front();
+ if (!file.IsStartPosDefined)
+ break;
+ }
+ #else
+ CInArchive archive;
+ RINOK(archive.Open(stream, maxCheckStartPosition));
+ HRESULT result = archive.ReadDatabase(
+ EXTERNAL_CODECS_VARS
+ _database
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ );
+ RINOK(result);
+ _database.Fill();
+ _inStream = stream;
+ #endif
+ }
+ catch(...)
+ {
+ Close();
+ return S_FALSE;
+ }
+ // _inStream = stream;
+ #ifndef _SFX
+ FillPopIDs();
+ #endif
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ COM_TRY_BEGIN
+ #ifdef _7Z_VOL
+ _volumes.Clear();
+ _refs.Clear();
+ #else
+ _inStream.Release();
+ _database.Clear();
+ #endif
+ return S_OK;
+ COM_TRY_END
+}
+
+#ifdef _7Z_VOL
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+ if (index != 0)
+ return E_INVALIDARG;
+ *stream = 0;
+ CMultiStream *streamSpec = new CMultiStream;
+ CMyComPtr streamTemp = streamSpec;
+
+ UInt64 pos = 0;
+ const UString *fileName;
+ for (int i = 0; i < _refs.Size(); i++)
+ {
+ const CRef &ref = _refs[i];
+ const CVolume &volume = _volumes[ref.VolumeIndex];
+ const CArchiveDatabaseEx &database = volume.Database;
+ const CFileItem &file = database.Files[ref.ItemIndex];
+ if (i == 0)
+ fileName = &file.Name;
+ else
+ if (fileName->Compare(file.Name) != 0)
+ return S_FALSE;
+ if (!file.IsStartPosDefined)
+ return S_FALSE;
+ if (file.StartPos != pos)
+ return S_FALSE;
+ CNum folderIndex = database.FileIndexToFolderIndexMap[ref.ItemIndex];
+ if (folderIndex == kNumNoIndex)
+ {
+ if (file.UnPackSize != 0)
+ return E_FAIL;
+ continue;
+ }
+ if (database.NumUnPackStreamsVector[folderIndex] != 1)
+ return S_FALSE;
+ const CFolder &folder = database.Folders[folderIndex];
+ if (folder.Coders.Size() != 1)
+ return S_FALSE;
+ const CCoderInfo &coder = folder.Coders.Front();
+ if (coder.NumInStreams != 1 || coder.NumOutStreams != 1)
+ return S_FALSE;
+ if (coder.MethodID != k_Copy)
+ return S_FALSE;
+
+ pos += file.UnPackSize;
+ CMultiStream::CSubStreamInfo subStreamInfo;
+ subStreamInfo.Stream = volume.Stream;
+ subStreamInfo.Pos = database.GetFolderStreamPos(folderIndex, 0);
+ subStreamInfo.Size = file.UnPackSize;
+ streamSpec->Streams.Add(subStreamInfo);
+ }
+ streamSpec->Init();
+ *stream = streamTemp.Detach();
+ return S_OK;
+}
+#endif
+
+
+#ifdef __7Z_SET_PROPERTIES
+#ifdef EXTRACT_ONLY
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
+{
+ COM_TRY_BEGIN
+ #ifdef COMPRESS_MT
+ const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
+ _numThreads = numProcessors;
+ #endif
+
+ for (int i = 0; i < numProperties; i++)
+ {
+ UString name = names[i];
+ name.MakeUpper();
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+ const PROPVARIANT &value = values[i];
+ UInt32 number;
+ int index = ParseStringToUInt32(name, number);
+ if (index == 0)
+ {
+ if(name.Left(2).CompareNoCase(L"MT") == 0)
+ {
+ #ifdef COMPRESS_MT
+ RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
+ #endif
+ continue;
+ }
+ else
+ return E_INVALIDARG;
+ }
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+#endif
+#endif
+
+IMPL_ISetCompressCodecsInfo
+
+}}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zHandler.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zHandler.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,146 @@
+// 7z/Handler.h
+
+#ifndef __7Z_HANDLER_H
+#define __7Z_HANDLER_H
+
+#include "../../ICoder.h"
+#include "../IArchive.h"
+#include "7zIn.h"
+
+#include "7zCompressionMode.h"
+
+#include "../../Common/CreateCoder.h"
+
+#ifndef EXTRACT_ONLY
+#include "../Common/HandlerOut.h"
+#endif
+
+namespace NArchive {
+namespace N7z {
+
+#ifdef _7Z_VOL
+struct CRef
+{
+ int VolumeIndex;
+ int ItemIndex;
+};
+
+struct CVolume
+{
+ int StartRef2Index;
+ CMyComPtr Stream;
+ CArchiveDatabaseEx Database;
+};
+#endif
+
+#ifndef __7Z_SET_PROPERTIES
+
+#ifdef EXTRACT_ONLY
+#ifdef COMPRESS_MT
+#define __7Z_SET_PROPERTIES
+#endif
+#else
+#define __7Z_SET_PROPERTIES
+#endif
+
+#endif
+
+
+class CHandler:
+ #ifndef EXTRACT_ONLY
+ public NArchive::COutHandler,
+ #endif
+ public IInArchive,
+ #ifdef _7Z_VOL
+ public IInArchiveGetStream,
+ #endif
+ #ifdef __7Z_SET_PROPERTIES
+ public ISetProperties,
+ #endif
+ #ifndef EXTRACT_ONLY
+ public IOutArchive,
+ #endif
+ PUBLIC_ISetCompressCodecsInfo
+ public CMyUnknownImp
+{
+public:
+ MY_QUERYINTERFACE_BEGIN2(IInArchive)
+ #ifdef _7Z_VOL
+ MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream)
+ #endif
+ #ifdef __7Z_SET_PROPERTIES
+ MY_QUERYINTERFACE_ENTRY(ISetProperties)
+ #endif
+ #ifndef EXTRACT_ONLY
+ MY_QUERYINTERFACE_ENTRY(IOutArchive)
+ #endif
+ QUERY_ENTRY_ISetCompressCodecsInfo
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ INTERFACE_IInArchive(;)
+
+ #ifdef _7Z_VOL
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+ #endif
+
+ #ifdef __7Z_SET_PROPERTIES
+ STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);
+ #endif
+
+ #ifndef EXTRACT_ONLY
+ INTERFACE_IOutArchive(;)
+ #endif
+
+ DECL_ISetCompressCodecsInfo
+
+ CHandler();
+
+private:
+ #ifdef _7Z_VOL
+ CObjectVector _volumes;
+ CObjectVector _refs;
+ #else
+ CMyComPtr _inStream;
+ NArchive::N7z::CArchiveDatabaseEx _database;
+ #endif
+
+ #ifdef EXTRACT_ONLY
+
+ #ifdef COMPRESS_MT
+ UInt32 _numThreads;
+ #endif
+
+ UInt32 _crcSize;
+
+ #else
+
+ CRecordVector _binds;
+
+ HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback);
+
+ HRESULT SetCompressionMethod(CCompressionMethodMode &method,
+ CObjectVector &methodsInfo
+ #ifdef COMPRESS_MT
+ , UInt32 numThreads
+ #endif
+ );
+
+ HRESULT SetCompressionMethod(
+ CCompressionMethodMode &method,
+ CCompressionMethodMode &headerMethod);
+
+ #endif
+
+ bool IsEncrypted(UInt32 index2) const;
+ #ifndef _SFX
+
+ CRecordVector _fileInfoPopIDs;
+ void FillPopIDs();
+
+ #endif
+};
+
+}}
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zHandlerOut.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zHandlerOut.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,464 @@
+// 7zHandlerOut.cpp
+
+#include "StdAfx.h"
+
+#include "7zHandler.h"
+#include "7zOut.h"
+#include "7zUpdate.h"
+
+#include "../../../Windows/PropVariant.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/StringToInt.h"
+#include "../../IPassword.h"
+#include "../../ICoder.h"
+
+#include "../Common/ItemNameUtils.h"
+#include "../Common/ParseProperties.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace N7z {
+
+static const wchar_t *kLZMAMethodName = L"LZMA";
+static const wchar_t *kCopyMethod = L"Copy";
+static const wchar_t *kDefaultMethodName = kLZMAMethodName;
+
+static const UInt32 kLzmaAlgorithmX5 = 1;
+static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";
+static const UInt32 kDictionaryForHeaders = 1 << 20;
+static const UInt32 kNumFastBytesForHeaders = 273;
+static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5;
+
+static inline bool IsCopyMethod(const UString &methodName)
+ { return (methodName.CompareNoCase(kCopyMethod) == 0); }
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
+{
+ *type = NFileTimeType::kWindows;
+ return S_OK;
+}
+
+HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode,
+ IArchiveUpdateCallback *updateCallback)
+{
+ CMyComPtr getTextPassword;
+ if (!getTextPassword)
+ {
+ CMyComPtr udateCallback2(updateCallback);
+ udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);
+ }
+
+ if (getTextPassword)
+ {
+ CMyComBSTR password;
+ Int32 passwordIsDefined;
+ RINOK(getTextPassword->CryptoGetTextPassword2(
+ &passwordIsDefined, &password));
+ methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
+ if (methodMode.PasswordIsDefined)
+ methodMode.Password = password;
+ }
+ else
+ methodMode.PasswordIsDefined = false;
+ return S_OK;
+}
+
+HRESULT CHandler::SetCompressionMethod(
+ CCompressionMethodMode &methodMode,
+ CCompressionMethodMode &headerMethod)
+{
+ HRESULT res = SetCompressionMethod(methodMode, _methods
+ #ifdef COMPRESS_MT
+ , _numThreads
+ #endif
+ );
+ RINOK(res);
+ methodMode.Binds = _binds;
+
+ if (_compressHeaders)
+ {
+ // headerMethod.Methods.Add(methodMode.Methods.Back());
+
+ CObjectVector headerMethodInfoVector;
+ COneMethodInfo oneMethodInfo;
+ oneMethodInfo.MethodName = kLZMAMethodName;
+ {
+ CProp property;
+ property.Id = NCoderPropID::kMatchFinder;
+ property.Value = kLzmaMatchFinderForHeaders;
+ oneMethodInfo.Properties.Add(property);
+ }
+ {
+ CProp property;
+ property.Id = NCoderPropID::kAlgorithm;
+ property.Value = kAlgorithmForHeaders;
+ oneMethodInfo.Properties.Add(property);
+ }
+ {
+ CProp property;
+ property.Id = NCoderPropID::kNumFastBytes;
+ property.Value = UInt32(kNumFastBytesForHeaders);
+ oneMethodInfo.Properties.Add(property);
+ }
+ {
+ CProp property;
+ property.Id = NCoderPropID::kDictionarySize;
+ property.Value = UInt32(kDictionaryForHeaders);
+ oneMethodInfo.Properties.Add(property);
+ }
+ headerMethodInfoVector.Add(oneMethodInfo);
+ HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector
+ #ifdef COMPRESS_MT
+ ,1
+ #endif
+ );
+ RINOK(res);
+ }
+ return S_OK;
+}
+
+HRESULT CHandler::SetCompressionMethod(
+ CCompressionMethodMode &methodMode,
+ CObjectVector &methodsInfo
+ #ifdef COMPRESS_MT
+ , UInt32 numThreads
+ #endif
+ )
+{
+ UInt32 level = _level;
+
+ if (methodsInfo.IsEmpty())
+ {
+ COneMethodInfo oneMethodInfo;
+ oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName);
+ methodsInfo.Add(oneMethodInfo);
+ }
+
+ bool needSolid = false;
+ for(int i = 0; i < methodsInfo.Size(); i++)
+ {
+ COneMethodInfo &oneMethodInfo = methodsInfo[i];
+ SetCompressionMethod2(oneMethodInfo
+ #ifdef COMPRESS_MT
+ , numThreads
+ #endif
+ );
+
+ if (!IsCopyMethod(oneMethodInfo.MethodName))
+ needSolid = true;
+
+ CMethodFull methodFull;
+
+ if (!FindMethod(
+ EXTERNAL_CODECS_VARS
+ oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams))
+ return E_INVALIDARG;
+ methodFull.Properties = oneMethodInfo.Properties;
+ methodMode.Methods.Add(methodFull);
+
+ if (!_numSolidBytesDefined)
+ {
+ for (int j = 0; j < methodFull.Properties.Size(); j++)
+ {
+ const CProp &prop = methodFull.Properties[j];
+ if ((prop.Id == NCoderPropID::kDictionarySize ||
+ prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4)
+ {
+ _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7;
+ const UInt64 kMinSize = (1 << 24);
+ if (_numSolidBytes < kMinSize)
+ _numSolidBytes = kMinSize;
+ _numSolidBytesDefined = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!needSolid && !_numSolidBytesDefined)
+ {
+ _numSolidBytesDefined = true;
+ _numSolidBytes = 0;
+ }
+ return S_OK;
+}
+
+static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, CArchiveFileTime &filetime, bool &filetimeIsDefined)
+{
+ filetimeIsDefined = false;
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(index, propID, &propVariant));
+ if (propVariant.vt == VT_FILETIME)
+ {
+ filetime = propVariant.filetime;
+ filetimeIsDefined = true;
+ }
+ else if (propVariant.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *updateCallback)
+{
+ COM_TRY_BEGIN
+
+ const CArchiveDatabaseEx *database = 0;
+ #ifdef _7Z_VOL
+ if(_volumes.Size() > 1)
+ return E_FAIL;
+ const CVolume *volume = 0;
+ if (_volumes.Size() == 1)
+ {
+ volume = &_volumes.Front();
+ database = &volume->Database;
+ }
+ #else
+ if (_inStream != 0)
+ database = &_database;
+ #endif
+
+ // CRecordVector compressStatuses;
+ CObjectVector updateItems;
+ // CRecordVector copyIndices;
+
+ // CMyComPtr updateCallback2;
+ // updateCallback->QueryInterface(&updateCallback2);
+
+ for(UInt32 i = 0; i < numItems; i++)
+ {
+ Int32 newData;
+ Int32 newProperties;
+ UInt32 indexInArchive;
+ if (!updateCallback)
+ return E_FAIL;
+ RINOK(updateCallback->GetUpdateItemInfo(i,
+ &newData, &newProperties, &indexInArchive));
+ CUpdateItem updateItem;
+ updateItem.NewProperties = IntToBool(newProperties);
+ updateItem.NewData = IntToBool(newData);
+ updateItem.IndexInArchive = indexInArchive;
+ updateItem.IndexInClient = i;
+ updateItem.IsAnti = false;
+ updateItem.Size = 0;
+
+ if (updateItem.IndexInArchive != -1)
+ {
+ const CFileItem &fileItem = database->Files[updateItem.IndexInArchive];
+ updateItem.Name = fileItem.Name;
+ updateItem.IsDirectory = fileItem.IsDirectory;
+ updateItem.Size = fileItem.UnPackSize;
+ updateItem.IsAnti = fileItem.IsAnti;
+
+ updateItem.CreationTime = fileItem.CreationTime;
+ updateItem.IsCreationTimeDefined = fileItem.IsCreationTimeDefined;
+ updateItem.LastWriteTime = fileItem.LastWriteTime;
+ updateItem.IsLastWriteTimeDefined = fileItem.IsLastWriteTimeDefined;
+ updateItem.LastAccessTime = fileItem.LastAccessTime;
+ updateItem.IsLastAccessTimeDefined = fileItem.IsLastAccessTimeDefined;
+ }
+
+ if (updateItem.NewProperties)
+ {
+ bool nameIsDefined;
+ bool folderStatusIsDefined;
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidAttributes, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ updateItem.AttributesAreDefined = false;
+ else if (propVariant.vt != VT_UI4)
+ return E_INVALIDARG;
+ else
+ {
+ updateItem.Attributes = propVariant.ulVal;
+ updateItem.AttributesAreDefined = true;
+ }
+ }
+
+ RINOK(GetTime(updateCallback, i, kpidCreationTime, updateItem.CreationTime, updateItem.IsCreationTimeDefined));
+ RINOK(GetTime(updateCallback, i, kpidLastWriteTime, updateItem.LastWriteTime , updateItem.IsLastWriteTimeDefined));
+ RINOK(GetTime(updateCallback, i, kpidLastAccessTime, updateItem.LastAccessTime, updateItem.IsLastAccessTimeDefined));
+
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidPath, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ nameIsDefined = false;
+ else if (propVariant.vt != VT_BSTR)
+ return E_INVALIDARG;
+ else
+ {
+ updateItem.Name = NItemName::MakeLegalName(propVariant.bstrVal);
+ nameIsDefined = true;
+ }
+ }
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidIsFolder, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ folderStatusIsDefined = false;
+ else if (propVariant.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ {
+ updateItem.IsDirectory = (propVariant.boolVal != VARIANT_FALSE);
+ folderStatusIsDefined = true;
+ }
+ }
+
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidIsAnti, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ updateItem.IsAnti = false;
+ else if (propVariant.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ updateItem.IsAnti = (propVariant.boolVal != VARIANT_FALSE);
+ }
+
+ if (updateItem.IsAnti)
+ {
+ updateItem.AttributesAreDefined = false;
+
+ updateItem.IsCreationTimeDefined = false;
+ updateItem.IsLastWriteTimeDefined = false;
+ updateItem.IsLastAccessTimeDefined = false;
+
+ updateItem.Size = 0;
+ }
+
+ if (!folderStatusIsDefined && updateItem.AttributesAreDefined)
+ updateItem.SetDirectoryStatusFromAttributes();
+ }
+
+ if (updateItem.NewData)
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidSize, &propVariant));
+ if (propVariant.vt != VT_UI8)
+ return E_INVALIDARG;
+ updateItem.Size = (UInt64)propVariant.uhVal.QuadPart;
+ if (updateItem.Size != 0 && updateItem.IsAnti)
+ return E_INVALIDARG;
+ }
+ updateItems.Add(updateItem);
+ }
+
+ CCompressionMethodMode methodMode, headerMethod;
+ RINOK(SetCompressionMethod(methodMode, headerMethod));
+ #ifdef COMPRESS_MT
+ methodMode.NumThreads = _numThreads;
+ headerMethod.NumThreads = 1;
+ #endif
+
+ RINOK(SetPassword(methodMode, updateCallback));
+
+ bool compressMainHeader = _compressHeaders; // check it
+
+ if (methodMode.PasswordIsDefined)
+ {
+ compressMainHeader = true;
+ if(_encryptHeaders)
+ RINOK(SetPassword(headerMethod, updateCallback));
+ }
+
+ if (numItems < 2)
+ compressMainHeader = false;
+
+ CUpdateOptions options;
+ options.Method = &methodMode;
+ options.HeaderMethod = (_compressHeaders ||
+ (methodMode.PasswordIsDefined && _encryptHeaders)) ?
+ &headerMethod : 0;
+ options.UseFilters = _level != 0 && _autoFilter;
+ options.MaxFilter = _level >= 8;
+
+ options.HeaderOptions.CompressMainHeader = compressMainHeader;
+ options.HeaderOptions.WriteModified = WriteModified;
+ options.HeaderOptions.WriteCreated = WriteCreated;
+ options.HeaderOptions.WriteAccessed = WriteAccessed;
+
+ options.NumSolidFiles = _numSolidFiles;
+ options.NumSolidBytes = _numSolidBytes;
+ options.SolidExtension = _solidExtension;
+ options.RemoveSfxBlock = _removeSfxBlock;
+ options.VolumeMode = _volumeMode;
+ return Update(
+ EXTERNAL_CODECS_VARS
+ #ifdef _7Z_VOL
+ volume ? volume->Stream: 0,
+ volume ? database: 0,
+ #else
+ _inStream,
+ database,
+ #endif
+ updateItems, outStream, updateCallback, options);
+ COM_TRY_END
+}
+
+static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream)
+{
+ stream = 0;
+ int index = ParseStringToUInt32(srcString, coder);
+ if (index == 0)
+ return E_INVALIDARG;
+ srcString.Delete(0, index);
+ if (srcString[0] == 'S')
+ {
+ srcString.Delete(0);
+ int index = ParseStringToUInt32(srcString, stream);
+ if (index == 0)
+ return E_INVALIDARG;
+ srcString.Delete(0, index);
+ }
+ return S_OK;
+}
+
+static HRESULT GetBindInfo(UString &srcString, CBind &bind)
+{
+ RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream));
+ if (srcString[0] != ':')
+ return E_INVALIDARG;
+ srcString.Delete(0);
+ RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream));
+ if (!srcString.IsEmpty())
+ return E_INVALIDARG;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
+{
+ COM_TRY_BEGIN
+ _binds.Clear();
+ BeforeSetProperty();
+
+ for (int i = 0; i < numProperties; i++)
+ {
+ UString name = names[i];
+ name.MakeUpper();
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+
+ const PROPVARIANT &value = values[i];
+
+ if (name[0] == 'B')
+ {
+ name.Delete(0);
+ CBind bind;
+ RINOK(GetBindInfo(name, bind));
+ _binds.Add(bind);
+ continue;
+ }
+
+ RINOK(SetProperty(name, value));
+ }
+
+ return S_OK;
+ COM_TRY_END
+}
+
+}}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zHeader.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zHeader.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,27 @@
+// 7z/Header.cpp
+
+#include "StdAfx.h"
+#include "7zHeader.h"
+
+namespace NArchive {
+namespace N7z {
+
+Byte kSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C};
+#ifdef _7Z_VOL
+Byte kFinishSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C + 1};
+#endif
+
+class SignatureInitializer
+{
+public:
+ SignatureInitializer()
+ {
+ kSignature[0]--;
+ #ifdef _7Z_VOL
+ kFinishSignature[0]--;
+ #endif
+ };
+} g_SignatureInitializer;
+
+}}
+
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zHeader.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zHeader.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,96 @@
+// 7z/7zHeader.h
+
+#ifndef __7Z_HEADER_H
+#define __7Z_HEADER_H
+
+#include "../../../Common/Types.h"
+
+namespace NArchive {
+namespace N7z {
+
+const int kSignatureSize = 6;
+extern Byte kSignature[kSignatureSize];
+
+// #define _7Z_VOL
+// 7z-MultiVolume is not finished yet.
+// It can work already, but I still do not like some
+// things of that new multivolume format.
+// So please keep it commented.
+
+#ifdef _7Z_VOL
+extern Byte kFinishSignature[kSignatureSize];
+#endif
+
+struct CArchiveVersion
+{
+ Byte Major;
+ Byte Minor;
+};
+
+const Byte kMajorVersion = 0;
+
+struct CStartHeader
+{
+ UInt64 NextHeaderOffset;
+ UInt64 NextHeaderSize;
+ UInt32 NextHeaderCRC;
+};
+
+const UInt32 kStartHeaderSize = 20;
+
+#ifdef _7Z_VOL
+struct CFinishHeader: public CStartHeader
+{
+ UInt64 ArchiveStartOffset; // data offset from end if that struct
+ UInt64 AdditionalStartBlockSize; // start signature & start header size
+};
+
+const UInt32 kFinishHeaderSize = kStartHeaderSize + 16;
+#endif
+
+namespace NID
+{
+ enum EEnum
+ {
+ kEnd,
+
+ kHeader,
+
+ kArchiveProperties,
+
+ kAdditionalStreamsInfo,
+ kMainStreamsInfo,
+ kFilesInfo,
+
+ kPackInfo,
+ kUnPackInfo,
+ kSubStreamsInfo,
+
+ kSize,
+ kCRC,
+
+ kFolder,
+
+ kCodersUnPackSize,
+ kNumUnPackStream,
+
+ kEmptyStream,
+ kEmptyFile,
+ kAnti,
+
+ kName,
+ kCreationTime,
+ kLastAccessTime,
+ kLastWriteTime,
+ kWinAttributes,
+ kComment,
+
+ kEncodedHeader,
+
+ kStartPos
+ };
+}
+
+}}
+
+#endif
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zIn.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zIn.cpp Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,1206 @@
+// 7zIn.cpp
+
+#include "StdAfx.h"
+
+#include "7zIn.h"
+#include "7zDecode.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/StreamUtils.h"
+extern "C"
+{
+#include "../../../../C/7zCrc.h"
+}
+
+// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader
+#ifndef _SFX
+#define FORMAT_7Z_RECOVERY
+#endif
+
+namespace NArchive {
+namespace N7z {
+
+class CInArchiveException {};
+
+static void ThrowException() { throw CInArchiveException(); }
+static inline void ThrowEndOfData() { ThrowException(); }
+static inline void ThrowUnsupported() { ThrowException(); }
+static inline void ThrowIncorrect() { ThrowException(); }
+static inline void ThrowUnsupportedVersion() { ThrowException(); }
+
+/*
+class CInArchiveException
+{
+public:
+ enum CCauseType
+ {
+ kUnsupportedVersion = 0,
+ kUnsupported,
+ kIncorrect,
+ kEndOfData,
+ } Cause;
+ CInArchiveException(CCauseType cause): Cause(cause) {};
+};
+
+static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); }
+static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); }
+static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); }
+static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); }
+static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); }
+*/
+
+class CStreamSwitch
+{
+ CInArchive *_archive;
+ bool _needRemove;
+public:
+ CStreamSwitch(): _needRemove(false) {}
+ ~CStreamSwitch() { Remove(); }
+ void Remove();
+ void Set(CInArchive *archive, const Byte *data, size_t size);
+ void Set(CInArchive *archive, const CByteBuffer &byteBuffer);
+ void Set(CInArchive *archive, const CObjectVector *dataVector);
+};
+
+void CStreamSwitch::Remove()
+{
+ if (_needRemove)
+ {
+ _archive->DeleteByteStream();
+ _needRemove = false;
+ }
+}
+
+void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size)
+{
+ Remove();
+ _archive = archive;
+ _archive->AddByteStream(data, size);
+ _needRemove = true;
+}
+
+void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer)
+{
+ Set(archive, byteBuffer, byteBuffer.GetCapacity());
+}
+
+void CStreamSwitch::Set(CInArchive *archive, const CObjectVector *dataVector)
+{
+ Remove();
+ Byte external = archive->ReadByte();
+ if (external != 0)
+ {
+ int dataIndex = (int)archive->ReadNum();
+ if (dataIndex < 0 || dataIndex >= dataVector->Size())
+ ThrowIncorrect();
+ Set(archive, (*dataVector)[dataIndex]);
+ }
+}
+
+#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__)
+#define SZ_LITTLE_ENDIAN_UNALIGN
+#endif
+
+#ifdef SZ_LITTLE_ENDIAN_UNALIGN
+static inline UInt16 GetUInt16FromMem(const Byte *p) { return *(const UInt16 *)p; }
+static inline UInt32 GetUInt32FromMem(const Byte *p) { return *(const UInt32 *)p; }
+static inline UInt64 GetUInt64FromMem(const Byte *p) { return *(const UInt64 *)p; }
+#else
+static inline UInt16 GetUInt16FromMem(const Byte *p) { return p[0] | ((UInt16)p[1] << 8); }
+static inline UInt32 GetUInt32FromMem(const Byte *p) { return p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24); }
+static inline UInt64 GetUInt64FromMem(const Byte *p) { return GetUInt32FromMem(p) | ((UInt64)GetUInt32FromMem(p + 4) << 32); }
+#endif
+
+Byte CInByte2::ReadByte()
+{
+ if (_pos >= _size)
+ ThrowEndOfData();
+ return _buffer[_pos++];
+}
+
+void CInByte2::ReadBytes(Byte *data, size_t size)
+{
+ if (size > _size - _pos)
+ ThrowEndOfData();
+ for (size_t i = 0; i < size; i++)
+ data[i] = _buffer[_pos++];
+}
+
+void CInByte2::SkeepData(UInt64 size)
+{
+ if (size > _size - _pos)
+ ThrowEndOfData();
+}
+
+void CInByte2::SkeepData()
+{
+ SkeepData(ReadNumber());
+}
+
+UInt64 CInByte2::ReadNumber()
+{
+ if (_pos >= _size)
+ ThrowEndOfData();
+ Byte firstByte = _buffer[_pos++];
+ Byte mask = 0x80;
+ UInt64 value = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ if ((firstByte & mask) == 0)
+ {
+ UInt64 highPart = firstByte & (mask - 1);
+ value += (highPart << (i * 8));
+ return value;
+ }
+ if (_pos >= _size)
+ ThrowEndOfData();
+ value |= ((UInt64)_buffer[_pos++] << (8 * i));
+ mask >>= 1;
+ }
+ return value;
+}
+
+CNum CInByte2::ReadNum()
+{
+ UInt64 value = ReadNumber();
+ if (value > kNumMax)
+ ThrowUnsupported();
+ return (CNum)value;
+}
+
+UInt32 CInByte2::ReadUInt32()
+{
+ if (_pos + 4 > _size)
+ ThrowEndOfData();
+ UInt32 res = GetUInt32FromMem(_buffer + _pos);
+ _pos += 4;
+ return res;
+}
+
+UInt64 CInByte2::ReadUInt64()
+{
+ if (_pos + 8 > _size)
+ ThrowEndOfData();
+ UInt64 res = GetUInt64FromMem(_buffer + _pos);
+ _pos += 8;
+ return res;
+}
+
+void CInByte2::ReadString(UString &s)
+{
+ const Byte *buf = _buffer + _pos;
+ size_t rem = (_size - _pos) / 2 * 2;
+ {
+ size_t i;
+ for (i = 0; i < rem; i += 2)
+ if (buf[i] == 0 && buf[i + 1] == 0)
+ break;
+ if (i == rem)
+ ThrowEndOfData();
+ rem = i;
+ }
+ int len = (int)(rem / 2);
+ if (len < 0 || (size_t)len * 2 != rem)
+ ThrowUnsupported();
+ wchar_t *p = s.GetBuffer(len);
+ int i;
+ for (i = 0; i < len; i++, buf += 2)
+ p[i] = (wchar_t)GetUInt16FromMem(buf);
+ p[i] = 0;
+ s.ReleaseBuffer(len);
+ _pos += rem + 2;
+}
+
+static inline bool TestSignatureCandidate(const Byte *p)
+{
+ for (int i = 0; i < kSignatureSize; i++)
+ if (p[i] != kSignature[i])
+ return false;
+ return (p[0x1A] == 0 && p[0x1B] == 0);
+}
+
+HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
+{
+ UInt32 processedSize;
+ RINOK(ReadStream(stream, _header, kHeaderSize, &processedSize));
+ if (processedSize != kHeaderSize)
+ return S_FALSE;
+ if (TestSignatureCandidate(_header))
+ return S_OK;
+
+ CByteBuffer byteBuffer;
+ const UInt32 kBufferSize = (1 << 16);
+ byteBuffer.SetCapacity(kBufferSize);
+ Byte *buffer = byteBuffer;
+ UInt32 numPrevBytes = kHeaderSize - 1;
+ memcpy(buffer, _header + 1, numPrevBytes);
+ UInt64 curTestPos = _arhiveBeginStreamPosition + 1;
+ for (;;)
+ {
+ if (searchHeaderSizeLimit != NULL)
+ if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit)
+ break;
+ UInt32 numReadBytes = kBufferSize - numPrevBytes;
+ RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize));
+ UInt32 numBytesInBuffer = numPrevBytes + processedSize;
+ if (numBytesInBuffer < kHeaderSize)
+ break;
+ UInt32 numTests = numBytesInBuffer - kHeaderSize + 1;
+ for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++)
+ {
+ if (TestSignatureCandidate(buffer + pos))
+ {
+ memcpy(_header, buffer + pos, kHeaderSize);
+ _arhiveBeginStreamPosition = curTestPos;
+ return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL);
+ }
+ }
+ numPrevBytes = numBytesInBuffer - numTests;
+ memmove(buffer, buffer + numTests, numPrevBytes);
+ }
+ return S_FALSE;
+}
+
+// S_FALSE means that file is not archive
+HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
+{
+ Close();
+ RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition))
+ RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit));
+ _stream = stream;
+ return S_OK;
+}
+
+void CInArchive::Close()
+{
+ _stream.Release();
+}
+
+void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
+{
+ for (;;)
+ {
+ if (ReadID() == NID::kEnd)
+ break;
+ SkeepData();
+ }
+}
+
+void CInArchive::GetNextFolderItem(CFolder &folder)
+{
+ CNum numCoders = ReadNum();
+
+ folder.Coders.Clear();
+ folder.Coders.Reserve((int)numCoders);
+ CNum numInStreams = 0;
+ CNum numOutStreams = 0;
+ CNum i;
+ for (i = 0; i < numCoders; i++)
+ {
+ folder.Coders.Add(CCoderInfo());
+ CCoderInfo &coder = folder.Coders.Back();
+
+ {
+ Byte mainByte = ReadByte();
+ int idSize = (mainByte & 0xF);
+ Byte longID[15];
+ ReadBytes(longID, idSize);
+ if (idSize > 8)
+ ThrowUnsupported();
+ UInt64 id = 0;
+ for (int j = 0; j < idSize; j++)
+ id |= (UInt64)longID[idSize - 1 - j] << (8 * j);
+ coder.MethodID = id;
+
+ if ((mainByte & 0x10) != 0)
+ {
+ coder.NumInStreams = ReadNum();
+ coder.NumOutStreams = ReadNum();
+ }
+ else
+ {
+ coder.NumInStreams = 1;
+ coder.NumOutStreams = 1;
+ }
+ if ((mainByte & 0x20) != 0)
+ {
+ CNum propertiesSize = ReadNum();
+ coder.Properties.SetCapacity((size_t)propertiesSize);
+ ReadBytes((Byte *)coder.Properties, (size_t)propertiesSize);
+ }
+ if ((mainByte & 0x80) != 0)
+ ThrowUnsupported();
+ }
+ numInStreams += coder.NumInStreams;
+ numOutStreams += coder.NumOutStreams;
+ }
+
+ CNum numBindPairs;
+ numBindPairs = numOutStreams - 1;
+ folder.BindPairs.Clear();
+ folder.BindPairs.Reserve(numBindPairs);
+ for (i = 0; i < numBindPairs; i++)
+ {
+ CBindPair bindPair;
+ bindPair.InIndex = ReadNum();
+ bindPair.OutIndex = ReadNum();
+ folder.BindPairs.Add(bindPair);
+ }
+
+ CNum numPackedStreams = numInStreams - numBindPairs;
+ folder.PackStreams.Reserve(numPackedStreams);
+ if (numPackedStreams == 1)
+ {
+ for (CNum j = 0; j < numInStreams; j++)
+ if (folder.FindBindPairForInStream(j) < 0)
+ {
+ folder.PackStreams.Add(j);
+ break;
+ }
+ }
+ else
+ for(i = 0; i < numPackedStreams; i++)
+ folder.PackStreams.Add(ReadNum());
+}
+
+void CInArchive::WaitAttribute(UInt64 attribute)
+{
+ for (;;)
+ {
+ UInt64 type = ReadID();
+ if (type == attribute)
+ return;
+ if (type == NID::kEnd)
+ ThrowIncorrect();
+ SkeepData();
+ }
+}
+
+void CInArchive::ReadHashDigests(int numItems,
+ CRecordVector &digestsDefined,
+ CRecordVector &digests)
+{
+ ReadBoolVector2(numItems, digestsDefined);
+ digests.Clear();
+ digests.Reserve(numItems);
+ for(int i = 0; i < numItems; i++)
+ {
+ UInt32 crc = 0;
+ if (digestsDefined[i])
+ crc = ReadUInt32();
+ digests.Add(crc);
+ }
+}
+
+void CInArchive::ReadPackInfo(
+ UInt64 &dataOffset,
+ CRecordVector &packSizes,
+ CRecordVector &packCRCsDefined,
+ CRecordVector &packCRCs)
+{
+ dataOffset = ReadNumber();
+ CNum numPackStreams = ReadNum();
+
+ WaitAttribute(NID::kSize);
+ packSizes.Clear();
+ packSizes.Reserve(numPackStreams);
+ for (CNum i = 0; i < numPackStreams; i++)
+ packSizes.Add(ReadNumber());
+
+ UInt64 type;
+ for (;;)
+ {
+ type = ReadID();
+ if (type == NID::kEnd)
+ break;
+ if (type == NID::kCRC)
+ {
+ ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs);
+ continue;
+ }
+ SkeepData();
+ }
+ if (packCRCsDefined.IsEmpty())
+ {
+ packCRCsDefined.Reserve(numPackStreams);
+ packCRCsDefined.Clear();
+ packCRCs.Reserve(numPackStreams);
+ packCRCs.Clear();
+ for(CNum i = 0; i < numPackStreams; i++)
+ {
+ packCRCsDefined.Add(false);
+ packCRCs.Add(0);
+ }
+ }
+}
+
+void CInArchive::ReadUnPackInfo(
+ const CObjectVector *dataVector,
+ CObjectVector &folders)
+{
+ WaitAttribute(NID::kFolder);
+ CNum numFolders = ReadNum();
+
+ {
+ CStreamSwitch streamSwitch;
+ streamSwitch.Set(this, dataVector);
+ folders.Clear();
+ folders.Reserve(numFolders);
+ for(CNum i = 0; i < numFolders; i++)
+ {
+ folders.Add(CFolder());
+ GetNextFolderItem(folders.Back());
+ }
+ }
+
+ WaitAttribute(NID::kCodersUnPackSize);
+
+ CNum i;
+ for (i = 0; i < numFolders; i++)
+ {
+ CFolder &folder = folders[i];
+ CNum numOutStreams = folder.GetNumOutStreams();
+ folder.UnPackSizes.Reserve(numOutStreams);
+ for (CNum j = 0; j < numOutStreams; j++)
+ folder.UnPackSizes.Add(ReadNumber());
+ }
+
+ for (;;)
+ {
+ UInt64 type = ReadID();
+ if (type == NID::kEnd)
+ return;
+ if (type == NID::kCRC)
+ {
+ CRecordVector crcsDefined;
+ CRecordVector crcs;
+ ReadHashDigests(numFolders, crcsDefined, crcs);
+ for(i = 0; i < numFolders; i++)
+ {
+ CFolder &folder = folders[i];
+ folder.UnPackCRCDefined = crcsDefined[i];
+ folder.UnPackCRC = crcs[i];
+ }
+ continue;
+ }
+ SkeepData();
+ }
+}
+
+void CInArchive::ReadSubStreamsInfo(
+ const CObjectVector &folders,
+ CRecordVector &numUnPackStreamsInFolders,
+ CRecordVector &unPackSizes,
+ CRecordVector &digestsDefined,
+ CRecordVector &digests)
+{
+ numUnPackStreamsInFolders.Clear();
+ numUnPackStreamsInFolders.Reserve(folders.Size());
+ UInt64 type;
+ for (;;)
+ {
+ type = ReadID();
+ if (type == NID::kNumUnPackStream)
+ {
+ for(int i = 0; i < folders.Size(); i++)
+ numUnPackStreamsInFolders.Add(ReadNum());
+ continue;
+ }
+ if (type == NID::kCRC || type == NID::kSize)
+ break;
+ if (type == NID::kEnd)
+ break;
+ SkeepData();
+ }
+
+ if (numUnPackStreamsInFolders.IsEmpty())
+ for(int i = 0; i < folders.Size(); i++)
+ numUnPackStreamsInFolders.Add(1);
+
+ int i;
+ for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
+ {
+ // v3.13 incorrectly worked with empty folders
+ // v4.07: we check that folder is empty
+ CNum numSubstreams = numUnPackStreamsInFolders[i];
+ if (numSubstreams == 0)
+ continue;
+ UInt64 sum = 0;
+ for (CNum j = 1; j < numSubstreams; j++)
+ if (type == NID::kSize)
+ {
+ UInt64 size = ReadNumber();
+ unPackSizes.Add(size);
+ sum += size;
+ }
+ unPackSizes.Add(folders[i].GetUnPackSize() - sum);
+ }
+ if (type == NID::kSize)
+ type = ReadID();
+
+ int numDigests = 0;
+ int numDigestsTotal = 0;
+ for(i = 0; i < folders.Size(); i++)
+ {
+ CNum numSubstreams = numUnPackStreamsInFolders[i];
+ if (numSubstreams != 1 || !folders[i].UnPackCRCDefined)
+ numDigests += numSubstreams;
+ numDigestsTotal += numSubstreams;
+ }
+
+ for (;;)
+ {
+ if (type == NID::kCRC)
+ {
+ CRecordVector digestsDefined2;
+ CRecordVector digests2;
+ ReadHashDigests(numDigests, digestsDefined2, digests2);
+ int digestIndex = 0;
+ for (i = 0; i < folders.Size(); i++)
+ {
+ CNum numSubstreams = numUnPackStreamsInFolders[i];
+ const CFolder &folder = folders[i];
+ if (numSubstreams == 1 && folder.UnPackCRCDefined)
+ {
+ digestsDefined.Add(true);
+ digests.Add(folder.UnPackCRC);
+ }
+ else
+ for (CNum j = 0; j < numSubstreams; j++, digestIndex++)
+ {
+ digestsDefined.Add(digestsDefined2[digestIndex]);
+ digests.Add(digests2[digestIndex]);
+ }
+ }
+ }
+ else if (type == NID::kEnd)
+ {
+ if (digestsDefined.IsEmpty())
+ {
+ digestsDefined.Clear();
+ digests.Clear();
+ for (int i = 0; i < numDigestsTotal; i++)
+ {
+ digestsDefined.Add(false);
+ digests.Add(0);
+ }
+ }
+ return;
+ }
+ else
+ SkeepData();
+ type = ReadID();
+ }
+}
+
+void CInArchive::ReadStreamsInfo(
+ const CObjectVector *dataVector,
+ UInt64 &dataOffset,
+ CRecordVector &packSizes,
+ CRecordVector &packCRCsDefined,
+ CRecordVector &packCRCs,
+ CObjectVector &folders,
+ CRecordVector &numUnPackStreamsInFolders,
+ CRecordVector &unPackSizes,
+ CRecordVector &digestsDefined,
+ CRecordVector &digests)
+{
+ for (;;)
+ {
+ UInt64 type = ReadID();
+ if (type > ((UInt32)1 << 30))
+ ThrowIncorrect();
+ switch((UInt32)type)
+ {
+ case NID::kEnd:
+ return;
+ case NID::kPackInfo:
+ {
+ ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs);
+ break;
+ }
+ case NID::kUnPackInfo:
+ {
+ ReadUnPackInfo(dataVector, folders);
+ break;
+ }
+ case NID::kSubStreamsInfo:
+ {
+ ReadSubStreamsInfo(folders, numUnPackStreamsInFolders,
+ unPackSizes, digestsDefined, digests);
+ break;
+ }
+ default:
+ ThrowIncorrect();
+ }
+ }
+}
+
+void CInArchive::ReadBoolVector(int numItems, CBoolVector &v)
+{
+ v.Clear();
+ v.Reserve(numItems);
+ Byte b = 0;
+ Byte mask = 0;
+ for(int i = 0; i < numItems; i++)
+ {
+ if (mask == 0)
+ {
+ b = ReadByte();
+ mask = 0x80;
+ }
+ v.Add((b & mask) != 0);
+ mask >>= 1;
+ }
+}
+
+void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v)
+{
+ Byte allAreDefined = ReadByte();
+ if (allAreDefined == 0)
+ {
+ ReadBoolVector(numItems, v);
+ return;
+ }
+ v.Clear();
+ v.Reserve(numItems);
+ for (int i = 0; i < numItems; i++)
+ v.Add(true);
+}
+
+void CInArchive::ReadTime(const CObjectVector &dataVector,
+ CObjectVector &files, UInt32 type)
+{
+ CBoolVector boolVector;
+ ReadBoolVector2(files.Size(), boolVector);
+
+ CStreamSwitch streamSwitch;
+ streamSwitch.Set(this, &dataVector);
+
+ for(int i = 0; i < files.Size(); i++)
+ {
+ CFileItem &file = files[i];
+ CArchiveFileTime fileTime;
+ fileTime.dwLowDateTime = 0;
+ fileTime.dwHighDateTime = 0;
+ bool defined = boolVector[i];
+ if (defined)
+ {
+ fileTime.dwLowDateTime = ReadUInt32();
+ fileTime.dwHighDateTime = ReadUInt32();
+ }
+ switch(type)
+ {
+ case NID::kCreationTime:
+ file.IsCreationTimeDefined = defined;
+ if (defined)
+ file.CreationTime = fileTime;
+ break;
+ case NID::kLastWriteTime:
+ file.IsLastWriteTimeDefined = defined;
+ if (defined)
+ file.LastWriteTime = fileTime;
+ break;
+ case NID::kLastAccessTime:
+ file.IsLastAccessTimeDefined = defined;
+ if (defined)
+ file.LastAccessTime = fileTime;
+ break;
+ }
+ }
+}
+
+HRESULT CInArchive::ReadAndDecodePackedStreams(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ UInt64 baseOffset,
+ UInt64 &dataOffset, CObjectVector &dataVector
+ #ifndef _NO_CRYPTO
+ , ICryptoGetTextPassword *getTextPassword
+ #endif
+ )
+{
+ CRecordVector packSizes;
+ CRecordVector packCRCsDefined;
+ CRecordVector packCRCs;
+ CObjectVector folders;
+
+ CRecordVector numUnPackStreamsInFolders;
+ CRecordVector unPackSizes;
+ CRecordVector digestsDefined;
+ CRecordVector digests;
+
+ ReadStreamsInfo(NULL,
+ dataOffset,
+ packSizes,
+ packCRCsDefined,
+ packCRCs,
+ folders,
+ numUnPackStreamsInFolders,
+ unPackSizes,
+ digestsDefined,
+ digests);
+
+ // database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader;
+
+ CNum packIndex = 0;
+ CDecoder decoder(
+ #ifdef _ST_MODE
+ false
+ #else
+ true
+ #endif
+ );
+ UInt64 dataStartPos = baseOffset + dataOffset;
+ for(int i = 0; i < folders.Size(); i++)
+ {
+ const CFolder &folder = folders[i];
+ dataVector.Add(CByteBuffer());
+ CByteBuffer &data = dataVector.Back();
+ UInt64 unPackSize64 = folder.GetUnPackSize();
+ size_t unPackSize = (size_t)unPackSize64;
+ if (unPackSize != unPackSize64)
+ ThrowUnsupported();
+ data.SetCapacity(unPackSize);
+
+ CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2;
+ CMyComPtr outStream = outStreamSpec;
+ outStreamSpec->Init(data, unPackSize);
+
+ HRESULT result = decoder.Decode(
+ EXTERNAL_CODECS_LOC_VARS
+ _stream, dataStartPos,
+ &packSizes[packIndex], folder, outStream, NULL
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ #ifdef COMPRESS_MT
+ , false, 1
+ #endif
+ );
+ RINOK(result);
+
+ if (folder.UnPackCRCDefined)
+ if (CrcCalc(data, unPackSize) != folder.UnPackCRC)
+ ThrowIncorrect();
+ for (int j = 0; j < folder.PackStreams.Size(); j++)
+ dataStartPos += packSizes[packIndex++];
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadHeader(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CArchiveDatabaseEx &database
+ #ifndef _NO_CRYPTO
+ , ICryptoGetTextPassword *getTextPassword
+ #endif
+ )
+{
+ UInt64 type = ReadID();
+
+ if (type == NID::kArchiveProperties)
+ {
+ ReadArchiveProperties(database.ArchiveInfo);
+ type = ReadID();
+ }
+
+ CObjectVector dataVector;
+
+ if (type == NID::kAdditionalStreamsInfo)
+ {
+ HRESULT result = ReadAndDecodePackedStreams(
+ EXTERNAL_CODECS_LOC_VARS
+ database.ArchiveInfo.StartPositionAfterHeader,
+ database.ArchiveInfo.DataStartPosition2,
+ dataVector
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ );
+ RINOK(result);
+ database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader;
+ type = ReadID();
+ }
+
+ CRecordVector unPackSizes;
+ CRecordVector digestsDefined;
+ CRecordVector digests;
+
+ if (type == NID::kMainStreamsInfo)
+ {
+ ReadStreamsInfo(&dataVector,
+ database.ArchiveInfo.DataStartPosition,
+ database.PackSizes,
+ database.PackCRCsDefined,
+ database.PackCRCs,
+ database.Folders,
+ database.NumUnPackStreamsVector,
+ unPackSizes,
+ digestsDefined,
+ digests);
+ database.ArchiveInfo.DataStartPosition += database.ArchiveInfo.StartPositionAfterHeader;
+ type = ReadID();
+ }
+ else
+ {
+ for(int i = 0; i < database.Folders.Size(); i++)
+ {
+ database.NumUnPackStreamsVector.Add(1);
+ CFolder &folder = database.Folders[i];
+ unPackSizes.Add(folder.GetUnPackSize());
+ digestsDefined.Add(folder.UnPackCRCDefined);
+ digests.Add(folder.UnPackCRC);
+ }
+ }
+
+ database.Files.Clear();
+
+ if (type == NID::kEnd)
+ return S_OK;
+ if (type != NID::kFilesInfo)
+ ThrowIncorrect();
+
+ CNum numFiles = ReadNum();
+ database.Files.Reserve(numFiles);
+ CNum i;
+ for(i = 0; i < numFiles; i++)
+ database.Files.Add(CFileItem());
+
+ database.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize);
+ if (!database.PackSizes.IsEmpty())
+ database.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo);
+ if (numFiles > 0 && !digests.IsEmpty())
+ database.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC);
+
+ CBoolVector emptyStreamVector;
+ emptyStreamVector.Reserve((int)numFiles);
+ for(i = 0; i < numFiles; i++)
+ emptyStreamVector.Add(false);
+ CBoolVector emptyFileVector;
+ CBoolVector antiFileVector;
+ CNum numEmptyStreams = 0;
+
+ for (;;)
+ {
+ UInt64 type = ReadID();
+ if (type == NID::kEnd)
+ break;
+ UInt64 size = ReadNumber();
+ bool isKnownType = true;
+ if (type > ((UInt32)1 << 30))
+ isKnownType = false;
+ else switch((UInt32)type)
+ {
+ case NID::kName:
+ {
+ CStreamSwitch streamSwitch;
+ streamSwitch.Set(this, &dataVector);
+ for(int i = 0; i < database.Files.Size(); i++)
+ _inByteBack->ReadString(database.Files[i].Name);
+ break;
+ }
+ case NID::kWinAttributes:
+ {
+ CBoolVector boolVector;
+ ReadBoolVector2(database.Files.Size(), boolVector);
+ CStreamSwitch streamSwitch;
+ streamSwitch.Set(this, &dataVector);
+ for(i = 0; i < numFiles; i++)
+ {
+ CFileItem &file = database.Files[i];
+ file.AreAttributesDefined = boolVector[i];
+ if (file.AreAttributesDefined)
+ file.Attributes = ReadUInt32();
+ }
+ break;
+ }
+ case NID::kStartPos:
+ {
+ CBoolVector boolVector;
+ ReadBoolVector2(database.Files.Size(), boolVector);
+ CStreamSwitch streamSwitch;
+ streamSwitch.Set(this, &dataVector);
+ for(i = 0; i < numFiles; i++)
+ {
+ CFileItem &file = database.Files[i];
+ file.IsStartPosDefined = boolVector[i];
+ if (file.IsStartPosDefined)
+ file.StartPos = ReadUInt64();
+ }
+ break;
+ }
+ case NID::kEmptyStream:
+ {
+ ReadBoolVector(numFiles, emptyStreamVector);
+ for (i = 0; i < (CNum)emptyStreamVector.Size(); i++)
+ if (emptyStreamVector[i])
+ numEmptyStreams++;
+ emptyFileVector.Reserve(numEmptyStreams);
+ antiFileVector.Reserve(numEmptyStreams);
+ for (i = 0; i < numEmptyStreams; i++)
+ {
+ emptyFileVector.Add(false);
+ antiFileVector.Add(false);
+ }
+ break;
+ }
+ case NID::kEmptyFile:
+ {
+ ReadBoolVector(numEmptyStreams, emptyFileVector);
+ break;
+ }
+ case NID::kAnti:
+ {
+ ReadBoolVector(numEmptyStreams, antiFileVector);
+ break;
+ }
+ case NID::kCreationTime:
+ case NID::kLastWriteTime:
+ case NID::kLastAccessTime:
+ {
+ ReadTime(dataVector, database.Files, (UInt32)type);
+ break;
+ }
+ default:
+ isKnownType = false;
+ }
+ if (isKnownType)
+ database.ArchiveInfo.FileInfoPopIDs.Add(type);
+ else
+ SkeepData(size);
+ }
+
+ CNum emptyFileIndex = 0;
+ CNum sizeIndex = 0;
+ for(i = 0; i < numFiles; i++)
+ {
+ CFileItem &file = database.Files[i];
+ file.HasStream = !emptyStreamVector[i];
+ if(file.HasStream)
+ {
+ file.IsDirectory = false;
+ file.IsAnti = false;
+ file.UnPackSize = unPackSizes[sizeIndex];
+ file.FileCRC = digests[sizeIndex];
+ file.IsFileCRCDefined = digestsDefined[sizeIndex];
+ sizeIndex++;
+ }
+ else
+ {
+ file.IsDirectory = !emptyFileVector[emptyFileIndex];
+ file.IsAnti = antiFileVector[emptyFileIndex];
+ emptyFileIndex++;
+ file.UnPackSize = 0;
+ file.IsFileCRCDefined = false;
+ }
+ }
+ return S_OK;
+}
+
+
+void CArchiveDatabaseEx::FillFolderStartPackStream()
+{
+ FolderStartPackStreamIndex.Clear();
+ FolderStartPackStreamIndex.Reserve(Folders.Size());
+ CNum startPos = 0;
+ for(int i = 0; i < Folders.Size(); i++)
+ {
+ FolderStartPackStreamIndex.Add(startPos);
+ startPos += (CNum)Folders[i].PackStreams.Size();
+ }
+}
+
+void CArchiveDatabaseEx::FillStartPos()
+{
+ PackStreamStartPositions.Clear();
+ PackStreamStartPositions.Reserve(PackSizes.Size());
+ UInt64 startPos = 0;
+ for(int i = 0; i < PackSizes.Size(); i++)
+ {
+ PackStreamStartPositions.Add(startPos);
+ startPos += PackSizes[i];
+ }
+}
+
+void CArchiveDatabaseEx::FillFolderStartFileIndex()
+{
+ FolderStartFileIndex.Clear();
+ FolderStartFileIndex.Reserve(Folders.Size());
+ FileIndexToFolderIndexMap.Clear();
+ FileIndexToFolderIndexMap.Reserve(Files.Size());
+
+ int folderIndex = 0;
+ CNum indexInFolder = 0;
+ for (int i = 0; i < Files.Size(); i++)
+ {
+ const CFileItem &file = Files[i];
+ bool emptyStream = !file.HasStream;
+ if (emptyStream && indexInFolder == 0)
+ {
+ FileIndexToFolderIndexMap.Add(kNumNoIndex);
+ continue;
+ }
+ if (indexInFolder == 0)
+ {
+ // v3.13 incorrectly worked with empty folders
+ // v4.07: Loop for skipping empty folders
+ for (;;)
+ {
+ if (folderIndex >= Folders.Size())
+ ThrowIncorrect();
+ FolderStartFileIndex.Add(i); // check it
+ if (NumUnPackStreamsVector[folderIndex] != 0)
+ break;
+ folderIndex++;
+ }
+ }
+ FileIndexToFolderIndexMap.Add(folderIndex);
+ if (emptyStream)
+ continue;
+ indexInFolder++;
+ if (indexInFolder >= NumUnPackStreamsVector[folderIndex])
+ {
+ folderIndex++;
+ indexInFolder = 0;
+ }
+ }
+}
+
+HRESULT CInArchive::ReadDatabase2(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CArchiveDatabaseEx &database
+ #ifndef _NO_CRYPTO
+ , ICryptoGetTextPassword *getTextPassword
+ #endif
+ )
+{
+ database.Clear();
+ database.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;
+
+ database.ArchiveInfo.Version.Major = _header[6];
+ database.ArchiveInfo.Version.Minor = _header[7];
+
+ if (database.ArchiveInfo.Version.Major != kMajorVersion)
+ ThrowUnsupportedVersion();
+
+ UInt32 crcFromArchive = GetUInt32FromMem(_header + 8);
+ UInt64 nextHeaderOffset = GetUInt64FromMem(_header + 0xC);
+ UInt64 nextHeaderSize = GetUInt64FromMem(_header + 0x14);
+ UInt32 nextHeaderCRC = GetUInt32FromMem(_header + 0x1C);
+ UInt32 crc = CrcCalc(_header + 0xC, 20);
+
+ #ifdef FORMAT_7Z_RECOVERY
+ if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)
+ {
+ UInt64 cur, cur2;
+ RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur));
+ const int kCheckSize = 500;
+ Byte buf[kCheckSize];
+ RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2));
+ int checkSize = kCheckSize;
+ if (cur2 - cur < kCheckSize)
+ checkSize = (int)(cur2 - cur);
+ RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2));
+
+ UInt32 realProcessedSize;
+ RINOK(_stream->Read(buf, (UInt32)kCheckSize, &realProcessedSize));
+
+ int i;
+ for (i = (int)realProcessedSize - 2; i >= 0; i--)
+ if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04)
+ break;
+ if (i < 0)
+ return S_FALSE;
+ nextHeaderSize = realProcessedSize - i;
+ nextHeaderOffset = cur2 - cur + i;
+ nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);
+ RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL));
+ }
+ #endif
+
+ #ifdef FORMAT_7Z_RECOVERY
+ crcFromArchive = crc;
+ #endif
+
+ database.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;
+
+ if (crc != crcFromArchive)
+ ThrowIncorrect();
+
+ if (nextHeaderSize == 0)
+ return S_OK;
+
+ if (nextHeaderSize > (UInt64)0xFFFFFFFF)
+ return S_FALSE;
+
+ RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL));
+
+ CByteBuffer buffer2;
+ buffer2.SetCapacity((size_t)nextHeaderSize);
+
+ UInt32 realProcessedSize;
+ RINOK(_stream->Read(buffer2, (UInt32)nextHeaderSize, &realProcessedSize));
+ if (realProcessedSize != (UInt32)nextHeaderSize)
+ return S_FALSE;
+ if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC)
+ ThrowIncorrect();
+
+ CStreamSwitch streamSwitch;
+ streamSwitch.Set(this, buffer2);
+
+ CObjectVector dataVector;
+
+ for (;;)
+ {
+ UInt64 type = ReadID();
+ if (type == NID::kHeader)
+ break;
+ if (type != NID::kEncodedHeader)
+ ThrowIncorrect();
+ HRESULT result = ReadAndDecodePackedStreams(
+ EXTERNAL_CODECS_LOC_VARS
+ database.ArchiveInfo.StartPositionAfterHeader,
+ database.ArchiveInfo.DataStartPosition2,
+ dataVector
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ );
+ RINOK(result);
+ if (dataVector.Size() == 0)
+ return S_OK;
+ if (dataVector.Size() > 1)
+ ThrowIncorrect();
+ streamSwitch.Remove();
+ streamSwitch.Set(this, dataVector.Front());
+ }
+
+ return ReadHeader(
+ EXTERNAL_CODECS_LOC_VARS
+ database
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ );
+}
+
+HRESULT CInArchive::ReadDatabase(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CArchiveDatabaseEx &database
+ #ifndef _NO_CRYPTO
+ , ICryptoGetTextPassword *getTextPassword
+ #endif
+ )
+{
+ try
+ {
+ return ReadDatabase2(
+ EXTERNAL_CODECS_LOC_VARS database
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ );
+ }
+ catch(CInArchiveException &) { return S_FALSE; }
+}
+
+}}
diff -r 01f88c3b7b66 -r 1b2b84315d27 misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zIn.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Archive/7z/7zIn.h Sun Dec 17 00:09:24 2017 +0100
@@ -0,0 +1,235 @@
+// 7zIn.h
+
+#ifndef __7Z_IN_H
+#define __7Z_IN_H
+
+#include "../../../Common/MyCom.h"
+#include "../../IStream.h"
+#include "../../IPassword.h"
+#include "../../Common/CreateCoder.h"
+#include "../../Common/InBuffer.h"
+
+#include "7zItem.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CInArchiveInfo
+{
+ CArchiveVersion Version;
+ UInt64 StartPosition;
+ UInt64 StartPositionAfterHeader;
+ UInt64 DataStartPosition;
+ UInt64 DataStartPosition2;
+ CRecordVector FileInfoPopIDs;
+ void Clear()
+ {
+ FileInfoPopIDs.Clear();
+ }
+};
+
+struct CArchiveDatabaseEx: public CArchiveDatabase
+{
+ CInArchiveInfo ArchiveInfo;
+ CRecordVector PackStreamStartPositions;
+ CRecordVector FolderStartPackStreamIndex;
+ CRecordVector FolderStartFileIndex;
+ CRecordVector FileIndexToFolderIndexMap;
+
+ void Clear()
+ {
+ CArchiveDatabase::Clear();
+ ArchiveInfo.Clear();
+ PackStreamStartPositions.Clear();
+ FolderStartPackStreamIndex.Clear();
+ FolderStartFileIndex.Clear();
+ FileIndexToFolderIndexMap.Clear();
+ }
+
+ void FillFolderStartPackStream();
+ void FillStartPos();
+ void FillFolderStartFileIndex();
+
+ void Fill()
+ {
+ FillFolderStartPackStream();
+ FillStartPos();
+ FillFolderStartFileIndex();
+ }
+
+ UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const
+ {
+ return ArchiveInfo.DataStartPosition +
+ PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder];
+ }
+
+ UInt64 GetFolderFullPackSize(int folderIndex) const
+ {
+ CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex];
+ const CFolder &folder = Folders[folderIndex];
+ UInt64 size = 0;
+ for (int i = 0; i < folder.PackStreams.Size(); i++)
+ size += PackSizes[packStreamIndex + i];
+ return size;
+ }
+
+ UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const
+ {
+ return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
+ }
+
+ UInt64 GetFilePackSize(CNum fileIndex) const
+ {
+ CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
+ if (folderIndex != kNumNoIndex)
+ if (FolderStartFileIndex[folderIndex] == fileIndex)
+ return GetFolderFullPackSize(folderIndex);
+ return 0;
+ }
+};
+
+class CInByte2
+{
+ const Byte *_buffer;
+ size_t _size;
+ size_t _pos;
+public:
+ void Init(const Byte *buffer, size_t size)
+ {
+ _buffer = buffer;
+ _size = size;
+ _pos = 0;
+ }
+ Byte ReadByte();
+ void ReadBytes(Byte *data, size_t size);
+ void SkeepData(UInt64 size);
+ void SkeepData();
+ UInt64 ReadNumber();
+ CNum ReadNum();
+ UInt32 ReadUInt32();
+ UInt64 ReadUInt64();
+ void ReadString(UString &s);
+};
+
+class CStreamSwitch;
+
+const UInt32 kHeaderSize = 32;
+
+class CInArchive
+{
+ friend class CStreamSwitch;
+
+ CMyComPtr _stream;
+
+ CObjectVector _inByteVector;
+ CInByte2 *_inByteBack;
+
+ UInt64 _arhiveBeginStreamPosition;
+
+ Byte _header[kHeaderSize];
+
+ void AddByteStream(const Byte *buffer, size_t size)
+ {
+ _inByteVector.Add(CInByte2());
+ _inByteBack = &_inByteVector.Back();
+ _inByteBack->Init(buffer, size);
+ }
+
+ void DeleteByteStream()
+ {
+ _inByteVector.DeleteBack();
+ if (!_inByteVector.IsEmpty())
+ _inByteBack = &_inByteVector.Back();
+ }
+
+private:
+ HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
+
+ void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
+ Byte ReadByte() { return _inByteBack->ReadByte(); }
+ UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
+ CNum ReadNum() { return _inByteBack->ReadNum(); }
+ UInt64 ReadID() { return _inByteBack->ReadNumber(); }
+ UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
+ UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
+ void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); }
+ void SkeepData() { _inByteBack->SkeepData(); }
+ void WaitAttribute(UInt64 attribute);
+
+ void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
+ void GetNextFolderItem(CFolder &itemInfo);
+ void ReadHashDigests(int numItems,
+ CRecordVector &digestsDefined, CRecordVector &digests);
+
+ void ReadPackInfo(
+ UInt64 &dataOffset,
+ CRecordVector &packSizes,
+ CRecordVector &packCRCsDefined,
+ CRecordVector &packCRCs);
+
+ void ReadUnPackInfo(
+ const CObjectVector *dataVector,
+ CObjectVector &folders);
+
+ void ReadSubStreamsInfo(
+ const CObjectVector