diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 000000000..e8b177725 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,39 @@ +version: 0.50.9.{build} + +branches: + only: + - master + +environment: + COMPILER: msys2 + BUILDTOOL: cmake + MSYS2_DIR: msys64 + MSYSTEM: MINGW32 + +init: + - cmd: set PATH=C:\%MSYS2_DIR%\%MSYSTEM%\bin;C:\%MSYS2_DIR%\usr\bin;%PATH% + +build_script: + - ps: | + mkdir msys2 + + cd C:/msys64 + + C:\msys64\usr\bin\bash -lc ("for i in {1..3}; do pacman --noconfirm -Syu --force coreutils && break || sleep 15; done"); + C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Su" + C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S git" + C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-gcc" + + C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S make" + + C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-cmake" + C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-libpng" + C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-SDL2" + C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-pkg-config" + + cd C:/projects/ivan + + cmake -G "MSYS Makefiles" -DCMAKE_CXX_FLAGS=-DWIZARD -DCMAKE_INSTALL_PREFIX=C:/projects/ivan/build + cmake . + make -j4 install + diff --git a/.devsPrefs/AquariusPower/.cproject b/.devsPrefs/AquariusPower/.cproject new file mode 100644 index 000000000..1a5e13926 --- /dev/null +++ b/.devsPrefs/AquariusPower/.cproject @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.devsPrefs/AquariusPower/.gitignore.AquariusPower b/.devsPrefs/AquariusPower/.gitignore.AquariusPower new file mode 100644 index 000000000..04bc83fd9 --- /dev/null +++ b/.devsPrefs/AquariusPower/.gitignore.AquariusPower @@ -0,0 +1,84 @@ +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +ivan +igor/igor +mihail/mihail + +# Editor backup/swap files +*~ +*.swp +*.swap + +# CMake generated files +CMakeCache.txt +CMakeFiles +CMakeScripts +cmake_install.cmake +install_manifest.txt +Makefile + +# Folders and misc stuff like f. ex. save folders :) +Bones +/ivan.cfg +/HScore.dat +Save +/Debug/ +/Linux/ + +# OS / IDE files +.DS_Store + +###### +## Eclipse developers preferences over different operational systems +## and personalized configurations. +###### + +# link to some user folder at /.devsPrefs +/.devsPrefs/Current + +# direct links to preferences at /.devsPrefs/Current +/.cproject +/.project +/.settings + +# Git ignore files are special. They are relative to their current path! +# If the one at '/.devsPrefs/SomeUserName/.gitignore' remains named like that, +# git will recognize and ignore files as that sub folder is a root folder! +# Therefore ONLY that file must be named like: '/.devsPrefs/SomeUserName/.gitignore.SomeUserName' +# And after creating the link to it, the link itself must be renamed to '.gitignore' to be again recognized by git. +/.gitignore + + +######################### my preferences ############################ +dbgmsg.h +dbgmsg.cpp +/Linux/ +/SDL2-2.0.4/ +build +build.* diff --git a/.devsPrefs/AquariusPower/.project b/.devsPrefs/AquariusPower/.project new file mode 100644 index 000000000..678a6a2db --- /dev/null +++ b/.devsPrefs/AquariusPower/.project @@ -0,0 +1,27 @@ + + + Ivan + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/.devsPrefs/AquariusPower/.settings/language.settings.xml b/.devsPrefs/AquariusPower/.settings/language.settings.xml new file mode 100644 index 000000000..beff3fb72 --- /dev/null +++ b/.devsPrefs/AquariusPower/.settings/language.settings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.devsPrefs/AquariusPower/.settings/org.eclipse.cdt.codan.core.prefs b/.devsPrefs/AquariusPower/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100755 index 000000000..067d6fd2b --- /dev/null +++ b/.devsPrefs/AquariusPower/.settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,73 @@ +eclipse.preferences.version=1 +org.eclipse.cdt.codan.checkers.errnoreturn=Warning +org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false} +org.eclipse.cdt.codan.checkers.errreturnvalue=Error +org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"} +org.eclipse.cdt.codan.checkers.nocommentinside=-Error +org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"} +org.eclipse.cdt.codan.checkers.nolinecomment=-Error +org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"} +org.eclipse.cdt.codan.checkers.noreturn=Error +org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false} +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"} +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"} +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"} +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"} +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false} +org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning +org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"} +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true} +org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem=Error +org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"} +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error +org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"} +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"} +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"} +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"} +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"} +org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error +org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"} +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"} +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"} +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"} +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"} +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false} +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false} +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")} +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"} diff --git a/.devsPrefs/Attnam/.cproject b/.devsPrefs/Attnam/.cproject new file mode 100644 index 000000000..8a90643bc --- /dev/null +++ b/.devsPrefs/Attnam/.cproject @@ -0,0 +1,262 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.devsPrefs/Attnam/.gitignore.Attnam similarity index 100% rename from .gitignore rename to .devsPrefs/Attnam/.gitignore.Attnam diff --git a/.devsPrefs/Attnam/.project b/.devsPrefs/Attnam/.project new file mode 100644 index 000000000..678a6a2db --- /dev/null +++ b/.devsPrefs/Attnam/.project @@ -0,0 +1,27 @@ + + + Ivan + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/.devsPrefs/prepareUser.sh b/.devsPrefs/prepareUser.sh new file mode 100755 index 000000000..65b2c6c81 --- /dev/null +++ b/.devsPrefs/prepareUser.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +if [[ ! -L Current ]];then echo "must be run at .devsPrefs folder where is the relative link to the curren usesr: 'Current'!";exit 1;fi + +ls -l Current&&: +echo + +strUser="`readlink Current`" +strUser="`basename "$strUser"`" #grant is is relativised +declare -p strUser +echo + +cd .. +pwd +echo + +echo "--------------" +ls -l .gitignore .cproject .project&&: +echo + +echo ">>>>>>>>>>>>>>> .cproject" +trash -v .cproject&&: +ln -vsf .devsPrefs/Current/.cproject .cproject +echo + +echo ">>>>>>>>>>>>>>> .project" +trash -v .project&&: +ln -vsf .devsPrefs/Current/.project .project +echo + +echo ">>>>>>>>>>>>>>> .gitignore" +trash -v .gitignore&&: +ln -vsf ".devsPrefs/Current/.gitignore.$strUser" .gitignore +echo + +echo "--------------" +ls -l .gitignore .cproject .project&&: diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..244a643d2 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false + +[*.mak] +indent_style = tab diff --git a/.travis.yml b/.travis.yml index ec01a98e4..53fd46643 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,32 +1,92 @@ +# If you want to set up another Travis CI service for your fork (not branch), +# you can alter it to disable tests and notification for the official repo. +if: repo = Attnam/ivan + sudo: required dist: trusty language: cpp -compiler: - - clang - - gcc +matrix: + + include: + + - env: CXXFLAGS= IVAN_PLATFORM= + os: linux + compiler: clang + + - env: CXXFLAGS=-DWIZARD IVAN_PLATFORM= + os: linux + compiler: clang + + - env: CXXFLAGS= IVAN_PLATFORM= + os: osx + compiler: clang + + - env: CXXFLAGS=-DWIZARD IVAN_PLATFORM= + os: osx + compiler: clang + + - env: CXXFLAGS= IVAN_PLATFORM= + os: linux + compiler: gcc + + - env: CXXFLAGS=-DWIZARD IVAN_PLATFORM= + os: linux + compiler: gcc + + - env: CXXFLAGS= IVAN_PLATFORM= + os: osx + compiler: gcc + + - env: CXXFLAGS=-DWIZARD IVAN_PLATFORM= + os: osx + compiler: gcc + + - env: CXXFLAGS=-DWIZARD IVAN_PLATFORM=win + os: linux + compiler: gcc + + - env: CXXFLAGS=-DWIZARD IVAN_PLATFORM=osx SDL2DIR=$HOME/Thirdparty/Frameworks + os: osx + compiler: clang + +cache: + directories: + - $HOME/Thirdparty/Frameworks -os: - - linux - - osx +addons: + apt: + packages: + - libsdl2-dev + - libsdl2-mixer-dev before_install: - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -qq; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y libsdl2-dev; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install sdl2; fi + - export IVAN_BUILD_DIR=${TRAVIS_BUILD_DIR}/build + - export IVAN_FILE_VERSION=${TRAVIS_TAG#v} + - if [[ "$TRAVIS_OS_NAME" = osx ]]; then ./ci/osx/requirements.sh; fi + - if [[ "$IVAN_PLATFORM" = win ]]; then ./ci/win/requirements.sh; fi script: - mkdir build - cd build - - cmake -G "Unix Makefiles" -DCMAKE_CXX_FLAGS=$CXXFLAGS .. + - if [[ -z "$IVAN_PLATFORM" ]]; then cmake .. -G "Unix Makefiles" -DCMAKE_CXX_FLAGS="-Werror -Wno-format-security -Wno-undefined-var-template -Wno-unknown-warning-option ${CXXFLAGS}"; fi + - if [[ -n "$IVAN_PLATFORM" ]]; then "../ci/$IVAN_PLATFORM/build.sh"; fi - make - make igor - make mihail - - sudo make install + - if [[ -z "$IVAN_PLATFORM" ]]; then sudo make install; fi + - if [[ -n "$IVAN_PLATFORM" ]]; then make install; fi + - if [[ -n "$IVAN_PLATFORM" ]]; then "../ci/$IVAN_PLATFORM/package.sh"; fi -env: - matrix: - - CXXFLAGS="" - - CXXFLAGS="-DWIZARD" +deploy: + provider: releases + api_key: $GH_API_KEY + skip_cleanup: true + file_glob: true + file: $IVAN_BUILD_DIR/$IVAN_PLATFORM/*.zip + on: + condition: '"$IVAN_PLATFORM" =~ ^(win|osx)$' + repo: Attnam/ivan + tags: true + branch: master diff --git a/CMakeLists.txt b/CMakeLists.txt index 91d61154c..13e143edc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,29 +1,52 @@ cmake_minimum_required(VERSION 2.8.12.2) - project(ivan CXX C) -set(PROJECT_VERSION 0.50.7) + +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") + +set(VERSION_MAJOR 0) +set(VERSION_MINOR 54) +set(PROJECT_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}") +#set(VERSION_PATCH 0) +#set(PROJECT_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") add_definitions(-DIVAN_VERSION="${PROJECT_VERSION}" -DUSE_SDL) +option(BUILD_MAC_APP "Build standalone application for MacOS" OFF) + if(UNIX) add_definitions(-DUNIX) include(GNUInstallDirs) - install(DIRECTORY Graphics Script Music DESTINATION "${CMAKE_INSTALL_DATADIR}/ivan") - add_definitions(-DDATADIR="${CMAKE_INSTALL_FULL_DATADIR}" - -DLOCAL_STATE_DIR="${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/ivan") + + if(BUILD_MAC_APP) + install(DIRECTORY Graphics Script Music Sound DESTINATION "ivan") + install(FILES AUTHORS COPYING INSTALL LICENSING NEWS README README.md DESTINATION "docs") + add_definitions(-DMAC_APP) + else() + install(DIRECTORY Graphics Script Music Sound DESTINATION "${CMAKE_INSTALL_DATADIR}/ivan") + add_definitions(-DDATADIR="${CMAKE_INSTALL_FULL_DATADIR}" + -DLOCAL_STATE_DIR="${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/ivan") + endif() + elseif(WIN32) - install(DIRECTORY Graphics Script Music DESTINATION "ivan") + install(DIRECTORY Graphics Script Music Sound DESTINATION "ivan") + install(FILES AUTHORS COPYING INSTALL LICENSING NEWS README README.md DESTINATION "ivan") add_definitions(-DWIN32) + if(MINGW) + set(CMAKE_EXE_LINKER_FLAGS -mwindows) + endif(MINGW) + # This is bad. To remove below defines, FeLib should switch to std::chrono and serialize time since common epoch. # 32 bit TIME_T has year 2038 problem. Moreover, serialized value is not portable for time_t in general. # Switching to std::chrono should not be hard, but it's not a topic for this pull request. add_definitions(-D_USE_32BIT_TIME_T) -endif() +endif(UNIX) add_subdirectory(FeLib) add_subdirectory(audio) add_subdirectory(Main) add_subdirectory(igor) add_subdirectory(mihail) +add_subdirectory(xbrzscale) +add_subdirectory(fantasyname) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..a23e18c8f --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at capristo@attnam.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + diff --git a/Doc/HelperScripts/prepareCmdsDescrCode.sh b/Doc/HelperScripts/prepareCmdsDescrCode.sh new file mode 100755 index 000000000..2ceebf30b --- /dev/null +++ b/Doc/HelperScripts/prepareCmdsDescrCode.sh @@ -0,0 +1,13 @@ +#!/bin/bash +echo "//this script will prepare the full code to determine what commands will enable stretched/scaledup blitting regions" +echo "//just paste the output in the proper source file!" + +cd ../../Main/Source + +sedCollectDescription='s@[^"]*"([^"]*)".*@\1@' +sedPrepareCode='s@.*@if(strcmp(str,"&")==0)return true;@' + +egrep "new command" command.cpp \ + |sed -r \ + -e "$sedCollectDescription" \ + -e "$sedPrepareCode" # already in alphabetic order for user cmds diff --git a/Doc/Misc/DefinesValidator.txt b/Doc/Misc/DefinesValidator.txt new file mode 100644 index 000000000..0aa1731e3 --- /dev/null +++ b/Doc/Misc/DefinesValidator.txt @@ -0,0 +1,18 @@ +To see how it works, modify the define.dat file like + +1) change ex. TORSO value to 2 (so that it will differ from TORSO value at ivandef.h, could be other .h file tho), +actually the problem will happen when someone create a new value at define.dat and use another value at c++ .h files with the same `#define` identifier, +or when someone changes a value only at `define.dat` or at some c++ .h file, so they we be out of sync. + +2) compile and install the game. + +3) go to that option and toggle it to yes. + +4) the file `definesvalidator.h` will be created at the same path where the `ivan.conf` is located. + +5) move `definesvalidator.h` to the project development path at `Main/Include/definesvalidator.h` overwriting it + +6) compile and install again so that the validator will know what value the c++ `#define` should have, based on the define.dat file. +in case c++ has no such define, it will be ignored ex.: the check will be performed only `#ifdef EMISSARY` (currently not used in c++ .h files) + +7) run and activate that option to `yes`, it will abort complaining about TORSO value with this message: "Defined TORSO with value 2 from .dat file mismatches hardcoded c++ define value of 1!" diff --git a/Doc/Misc/MirrorFlipRotateToDegrees.jpg b/Doc/Misc/MirrorFlipRotateToDegrees.jpg new file mode 100644 index 000000000..e6c6d4b1a Binary files /dev/null and b/Doc/Misc/MirrorFlipRotateToDegrees.jpg differ diff --git a/Doc/Misc/SaveGameImportingOldVersion.txt b/Doc/Misc/SaveGameImportingOldVersion.txt new file mode 100644 index 000000000..e32cec314 --- /dev/null +++ b/Doc/Misc/SaveGameImportingOldVersion.txt @@ -0,0 +1,47 @@ +(changed from: https://github.com/Attnam/ivan/issues/346) + +Based on the version collected on the savegame binary file, a simple code can implemented like this: + +if(loadedSavegameFileVersion >= 132){ +// load new stuff from 132 +} + +if(loadedSavegameFileVersion >= 133){ +// load new stuff from 133 +} + +Only to load the savegame of course, and at all related classes that may have new stuff. + +ex.: +v132 [ some old data ] [ some old dataaaaaaa ] [ some old dataaaaaaaaaaaaaa ] +v133 [ some old data ] [ some old dataaaaaaa ] [ some NEW v133 data ] [ some old dataaaaaaaaaaaaaa ] + +The importer at v133 to load v132, if it just skip loading "some NEW v133 data" from v132, even if it is not in the end of the file, may work well, just test it! + +===================================== + +Being simple means no compatibilization should be coded, ex. if gameplay was too easy, when importing an old save, the result shall not be modified to make it adequate to the new way things work. + +So, after the import ends, the things that were not imported (from the end of the savegame binary file), that were missing, "will probably/expectedly" receive default values equivalent to when starting a new game. +That's why an import "may" work. The user may try the importer, or just continue playing using the old game version til char's death. + +Anyway, if in some special case, something severe changes breaking the game to an unplayable point, the import will fail, may be from save version 131 to 141 too many critical things changed and it could fail, but if the user upgrade the save, thru all "game versions" "importer" one by one, then instead of importing directly to save version 141, going every step (132, 133, 134 etc) could probably make it work better, may be... + + + + + + + + + + + +/////////////////////////////// TODO one day may be ////////////////////////////////////// + +Another thing I thought would be to create savegames structure based on tokens/IDs for each data sector. + +Not necessarily a xml file, neither a non binary save (user readable/editable would not be good), +so it could be some kind of binary with tokens delimiting sectors. + +That way these gaps, or saved data position changing, created by new savegame versions could (probably) not be a problem at all, and there would (probably) not have compatibility problems. diff --git a/ChangeLog b/Doc/Obsolete/ChangeLog similarity index 100% rename from ChangeLog rename to Doc/Obsolete/ChangeLog diff --git a/Doc/Obsolete/convertSoundEffectsFileToNewCfgFormat.sh b/Doc/Obsolete/convertSoundEffectsFileToNewCfgFormat.sh new file mode 100755 index 000000000..24236dd22 --- /dev/null +++ b/Doc/Obsolete/convertSoundEffectsFileToNewCfgFormat.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +############## +#### sed commands also restores CR for windows users +############## +sedB4EndCR='s@.*@&\r@' +sedGet1stFileName='s"([^.]*)[.]wav.*"\1"' + +IFS=$'\n' read -d '' -r -a astrList < <(cat config.txt |tr -d '\r'); #removes CR too +for((i=0;i<${#astrList[@]};i++));do + strLine="${astrList[i]}"; + + if((i%2==0));then + strRegex="$strLine"; + else + strFiles="`echo "$strLine" |tr ' ' ',' |sed 's",", "g'`" + strDesc="`echo "$strFiles" |sed -r "$sedGet1stFileName"`" + echo "$strDesc; $strFiles;$strRegex"; # the sound files is the 2nd line + fi; +done \ + |sort \ + |sed -r "$sedB4EndCR" \ + >SoundEffects.cfg + +if((`cat config.txt |wc -l` != (`cat SoundEffects.cfg |wc -l`*2) ));then + echo "SOME PROBLEM HAPPENED!" +fi + +# prettyfiing readability +sedGetDesc='s"([^;]*);.*"\1"' +IFS=$'\n' read -d '' -r -a astrList < <(cat SoundEffects.cfg |tr -d '\r'); #removes CR too +for((i=0;i<${#astrList[@]};i++));do + strLine="${astrList[i]}"; + strDesc="`echo "$strLine" |sed -r "$sedGetDesc"`" + + if [[ "$strDescPrev" != "$strDesc" ]];then + strFullDesc="### $strDesc ###" + strDescOutline="`printf "%0${#strFullDesc}d\n" 0 |tr '0' '#'`" + + echo "$strDescOutline" + echo "$strFullDesc" + echo "$strDescOutline" + fi + + echo "$strLine" + echo + + strDescPrev="$strDesc" +done >SoundEffects.cfg diff --git a/Doc/Obsolete/sortSoundEffectsFile.sh b/Doc/Obsolete/sortSoundEffectsFile.sh new file mode 100755 index 000000000..783e8dde2 --- /dev/null +++ b/Doc/Obsolete/sortSoundEffectsFile.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +#~ ls -l config.txt +#~ echo "newline, word, character, byte, maximum line length" +#~ wc -cmlwL config.txt +#~ echo + +#~ cat config.txt |tr -d '\r' >config.NoCR.txt +#~ ls -l config.NoCR.txt +#~ wc -cmlwL config.NoCR.txt +#~ echo + +############## +#### sed commands also restores CR for windows users +############## +sedMiddleCRNL='s@[\]n@\r\n@' +sedB4EndCR='s@.*@&\r@' + +IFS=$'\n' read -d '' -r -a astrList < <(cat config.txt |tr -d '\r'); #removes CR too +#IFS=$'\n' read -d '' -r -a astrList < <(cat config.NoCR.txt); #removes CR too +str2=""; +for((i=0;i<${#astrList[@]};i++));do + strLine="${astrList[i]}"; + + str2+="$strLine"; + if((i%2==0));then + str2+="\n"; # add NL readable marker + else + echo "$str2"; + str2=""; + fi; +done \ + |sort \ + |sed -r \ + -e "$sedB4EndCR" \ + -e "$sedMiddleCRNL" \ + >config.SORTED.txt + +#~ ls -l config.SORTED.txt +#~ echo "newline, word, character, byte, maximum line length" +#~ wc -cmlwL config.SORTED.txt +#~ echo + +#~ if read -p "all seems ok? (hit ctrl+c to stop)" -n 1;then + #~ mv -v config.SORTED.txt config.txt + #~ ls -l config* + #~ echo "newline, word, character, byte, maximum line length" + #~ wc -cmlwL config.txt +#~ fi + +if((`cat config.txt |wc -l`==`cat config.SORTED.txt |wc -l`));then + mv -v config.SORTED.txt config.txt +fi diff --git a/Doc/OutlinedGraphicsHowTo/Char.xcf b/Doc/OutlinedGraphicsHowTo/Char.xcf new file mode 100644 index 000000000..a881b24f6 Binary files /dev/null and b/Doc/OutlinedGraphicsHowTo/Char.xcf differ diff --git a/Doc/OutlinedGraphicsHowTo/CharExample-HowToConvert.txt b/Doc/OutlinedGraphicsHowTo/CharExample-HowToConvert.txt new file mode 100644 index 000000000..38ae41b7f --- /dev/null +++ b/Doc/OutlinedGraphicsHowTo/CharExample-HowToConvert.txt @@ -0,0 +1,29 @@ +Outline pixel quality for new additions, using gimp (see Char.xcf for details) + +- use the wand [fuzzy select tool] on the background of "LatestWork" +- invert selection (so pictures are now the content of the OutlineSelection) +- ctrl+c to copy the OutlineSelection and just paste what will create a floating layer and make it become a real new layer "LatestPictures" + +- grow OutlineSelection by 1 +- create a new layer OutlineSimpleAfterGrow1 (below "LatestPictures") and paint the inside of the selections with black (0,0,0) +- zoom in and take care of the outline corners to avoid getting too bold. just look on the already done work as reference. + +- open Char.png on gimp, and temporarily merge all visible layers on Char.xcf (and undo just after) to copy the final result inside Char.png, to keep the correct file format after you select "overwrite" to save it. + + +TIP: fast click on one layer eye to see the differences of old and new pictures + + +TIP: convert from pcx to png (there may have a better way but...) + + in this order: + - open the pcx file on gimp + - copy the png file to a new one (I will call it new.png) + - open new.png on gimp + - copy the contents of pcx file into new.png + - save overwriting + + this will keep the correct file format. + + +TIP: these stuff can be done in many ways, these are just the way I found, if you find a better way we would like to know :) diff --git a/Doc/OutlinedGraphicsHowTo/Humanoid.xcf b/Doc/OutlinedGraphicsHowTo/Humanoid.xcf new file mode 100644 index 000000000..985d760ae Binary files /dev/null and b/Doc/OutlinedGraphicsHowTo/Humanoid.xcf differ diff --git a/Doc/OutlinedGraphicsHowTo/Item.xcf b/Doc/OutlinedGraphicsHowTo/Item.xcf new file mode 100644 index 000000000..2a02060e4 Binary files /dev/null and b/Doc/OutlinedGraphicsHowTo/Item.xcf differ diff --git a/Doc/OutlinedGraphicsHowTo/char.pcx b/Doc/OutlinedGraphicsHowTo/char.pcx new file mode 100644 index 000000000..f346b9e6b Binary files /dev/null and b/Doc/OutlinedGraphicsHowTo/char.pcx differ diff --git a/Doc/OutlinedGraphicsHowTo/humanoid.pcx b/Doc/OutlinedGraphicsHowTo/humanoid.pcx new file mode 100644 index 000000000..0bf54f273 Binary files /dev/null and b/Doc/OutlinedGraphicsHowTo/humanoid.pcx differ diff --git a/Doc/OutlinedGraphicsHowTo/item.pcx b/Doc/OutlinedGraphicsHowTo/item.pcx new file mode 100644 index 000000000..f0f5b9064 Binary files /dev/null and b/Doc/OutlinedGraphicsHowTo/item.pcx differ diff --git a/FeLib/CMakeLists.txt b/FeLib/CMakeLists.txt index 80362a4be..c28c44753 100644 --- a/FeLib/CMakeLists.txt +++ b/FeLib/CMakeLists.txt @@ -1,21 +1,19 @@ file(GLOB FELIB_SOURCES Include/*.h Source/*.cpp) -if(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") add_definitions(-DGCC) # TODO: Use __GNUC__ in the code instead. endif() -add_library(FeLib ${FELIB_SOURCES}) +option(IGNORE_EXTRA_WHITESPACES "Sets CMP0004 to OLD" OFF) -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) -find_package(SDL2) -if(SDL2_FOUND) - message(STATUS "Using SDL2") -else() - message(WARNING "SDL2 not found") - find_package(SDL 1.2.0 REQUIRED) - message(STATUS "Using SDL1") +if(IGNORE_EXTRA_WHITESPACES) + cmake_policy(SET CMP0004 OLD) endif() +add_library(FeLib ${FELIB_SOURCES}) + +find_package(SDL2 REQUIRED) + if(MSVC) # Not very pretty solution. This finds SDL2.dll from SDL2.lib path, so that it can be installed where ivan.exe will end up. message("SDL2_LIBRARY ${SDL2_LIBRARY}") @@ -33,11 +31,36 @@ if(MINGW) message("sdl_lib_dir ${sdl_lib_dir}") get_filename_component(sdl_lib_dir "${sdl_lib_dir}" DIRECTORY) message("sdl_lib_dir ${sdl_lib_dir}") - install(FILES "${sdl_lib_dir}/../bin/SDL2.dll" DESTINATION "ivan") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++") + if((NOT BUILD_SHARED_LIBS) AND BUILD_STATIC_LIBS) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") + set(SDL2_LIBRARIES ${SDL2_LIBRARY} ${SDL2_LDFLAGS}) + else() + install(FILES "${sdl_lib_dir}/../bin/SDL2.dll" DESTINATION "ivan") + endif() +endif() + +# Try finding libpng using pkg-config first, because find_package(PNG) finds a +# mismatching header + library combination for me. +include(FindPkgConfig) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PNG libpng) + set(PNG_LIBRARIES ${PNG_LDFLAGS}) +endif() +if(NOT PNG_FOUND) + find_package(PNG REQUIRED) + add_definitions(${PNG_DEFINITIONS}) endif() target_include_directories(FeLib PUBLIC Include) -target_include_directories(FeLib SYSTEM PUBLIC ${SDL2_INCLUDE_DIR}) -target_link_libraries(FeLib ${SDL2_LIBRARY}) +target_include_directories(FeLib SYSTEM PUBLIC ${SDL2_INCLUDE_DIR} PRIVATE ${PNG_INCLUDE_DIRS}) +target_include_directories(FeLib PUBLIC ../xbrzscale ../xbrzscale/xbrz) + +if((NOT BUILD_SHARED_LIBS) AND BUILD_STATIC_LIBS) + target_link_libraries(FeLib ${PNG_LIBRARIES} ${SDL2_LIBRARIES} -static-libgcc -static-libstdc++) +else() + target_link_libraries(FeLib ${SDL2_LIBRARY} ${PNG_LIBRARIES}) +endif() + +target_compile_options(FeLib PUBLIC ${SDL2_CFLAGS} ${SDL2_CFLAGS_OTHER}) + diff --git a/FeLib/Include/bitmap.h b/FeLib/Include/bitmap.h index 5534e3600..bbeb3e287 100644 --- a/FeLib/Include/bitmap.h +++ b/FeLib/Include/bitmap.h @@ -14,6 +14,7 @@ #define __BITMAP_H__ #include "v2.h" +#include "SDL.h" class bitmap; class rawbitmap; @@ -37,6 +38,7 @@ struct blitdata col16 MaskColor; ulong CustomData; }; +#define DEFAULT_BLITDATA {NULL,{0,0},{0,0},{0,0}, {0}, TRANSPARENT_COLOR,0} //easy initializer TODO should be TRANSPARENT_COLOR? TODO update everywere with this default and just apply there differences to shrink the code? class bitmap { @@ -83,6 +85,11 @@ class bitmap void DrawHorizontalLine(int, int, int, col16, truth = false); void StretchBlit(cblitdata&) const; + void StretchBlitXbrz(cblitdata&,bool) const; + SDL_Surface* CopyToSurface(v2 v2TopLeft, v2 v2Size, col16 MaskColor = TRANSPARENT_COLOR, SDL_Surface* srf = NULL) const; + + static void ResetBlitdataRotation(blitdata& B); + static void ConfigureBlitdataRotation(blitdata& B,int i); void DrawRectangle(int, int, int, int, col16, truth = false); void DrawRectangle(v2, int, int, col16, truth = false); @@ -132,6 +139,10 @@ class bitmap void MoveLineVertically(int, int); void MoveLineHorizontally(int, int); void InterLace(); + + truth HasColor(col16 findColor); + void ReplaceColor(col16 findColor,col16 replaceWith); + void CopyLineFrom(int iYDest, bitmap* bmpFrom, int iYFrom, int iSize, bool bFailSafe=false); protected: v2 Size; ulong XSizeTimesYSize : 31; @@ -140,6 +151,8 @@ class bitmap packalpha** AlphaMap; packpriority** PriorityMap; truth* RandMap; + SDL_Surface* img; + SDL_Surface* imgStretched; }; inline void bitmap::SafeUpdateRandMap(v2 Pos, truth What) diff --git a/FeLib/Include/config.h b/FeLib/Include/config.h index 265e458b4..74dbf632d 100644 --- a/FeLib/Include/config.h +++ b/FeLib/Include/config.h @@ -31,7 +31,7 @@ class configsystem static truth Save(); static truth Load(); static void Show(void (*)() = 0, void (*)(felist&) = 0, truth = false); - static void AddOption(configoption*); + static void AddOption(festring fsCategory, configoption*); static void NormalStringDisplayer(const stringoption*, festring&); static void NormalNumberDisplayer(const numberoption*, festring&); static void NormalTruthDisplayer(const truthoption*, festring&); @@ -62,9 +62,10 @@ struct configoption virtual void SaveValue(std::ofstream&) const = 0; virtual void LoadValue(inputfile&) = 0; virtual truth ActivateChangeInterface() = 0; - virtual void DisplayeValue(festring&) const = 0; + virtual void DisplayValue(festring&) const = 0; cchar* Name; cchar* Description; + festring fsCategory; }; struct stringoption : public configoption @@ -78,7 +79,7 @@ struct stringoption : public configoption = &configsystem::NormalStringChanger); virtual void SaveValue(std::ofstream&) const; virtual void LoadValue(inputfile&); - virtual void DisplayeValue(festring& Entry) const + virtual void DisplayValue(festring& Entry) const { ValueDisplayer(this, Entry); } virtual truth ActivateChangeInterface() { return ChangeInterface(this); } void ChangeValue(cfestring& What) { ValueChanger(this, What); } @@ -99,7 +100,7 @@ struct numberoption : public configoption = &configsystem::NormalNumberChanger); virtual void SaveValue(std::ofstream&) const; virtual void LoadValue(inputfile&); - virtual void DisplayeValue(festring& Entry) const + virtual void DisplayValue(festring& Entry) const { ValueDisplayer(this, Entry); } virtual truth ActivateChangeInterface() { return ChangeInterface(this); } void ChangeValue(long What) { ValueChanger(this, What); } @@ -131,7 +132,7 @@ struct truthoption : public configoption = &configsystem::NormalTruthChanger); virtual void SaveValue(std::ofstream&) const; virtual void LoadValue(inputfile&); - virtual void DisplayeValue(festring& Entry) const + virtual void DisplayValue(festring& Entry) const { ValueDisplayer(this, Entry); } virtual truth ActivateChangeInterface() { return ChangeInterface(this); } void ChangeValue(truth What) { ValueChanger(this, What); } @@ -152,7 +153,7 @@ struct cycleoption : public configoption = &configsystem::NormalCycleChanger); virtual void SaveValue(std::ofstream&) const; virtual void LoadValue(inputfile&); - virtual void DisplayeValue(festring& Entry) const + virtual void DisplayValue(festring& Entry) const { ValueDisplayer(this, Entry); } virtual truth ActivateChangeInterface() { return ChangeInterface(this); } void ChangeValue(long What) { ValueChanger(this, What); } diff --git a/FeLib/Include/dbgmsgproj.h b/FeLib/Include/dbgmsgproj.h new file mode 100644 index 000000000..8b1264a42 --- /dev/null +++ b/FeLib/Include/dbgmsgproj.h @@ -0,0 +1,109 @@ +#ifndef INCLUDE_DBGMSGPROJ_H_ +#define INCLUDE_DBGMSGPROJ_H_ + +// just copy this file freely anywhere or it's contents +#ifdef DBGMSG + #include "dbgmsg.h" + + /************************************************************ + * CUSTOM / PROJECT SPECIFIC, modify at will + ************************************************************/ + #ifndef DBGMSG_OBJ //do NOT define this in your project cpp files! + #include + + #define DBGCHAR(ch,info) DBG8(info, ch->CHAR_NAME(DEFINITE), ch->GetAssignedName().CStr(), ch, ch->GetID(), ch->IsPlayer(), ch->GetStack()->GetItems(), ch->GetEquipments() ) //, std::bitset<16>(ch->GetFlags()) ) + #define DBGITEM(it,info) DBG3(info,it,(it==NULL?0:it->GetID())) + #define DBGABORT(x...) ABORT(x) //will only abort in development mode + + class dbgmsgprj{ + public: + + #ifdef DBGMSG_STRETCHREGION + #define DBGMSG_BLITDATA // alows the dependency + #define DBGSRI(info) DBG1( dbgmsgprj::dbgSRI(rSR,info).str()) + #define DBGSR DBGSRI("") + static std::stringstream dbgSRI(stretchRegion& SR,const char* strInfo){ + blitdata& rB=SR.B; + std::stringstream ss; + ss<GetSize() + if(rB.Bitmap!=NULL)ss<<"BitmapSize="<GetSize().X<<","<GetSize().Y<<"/"; + return ss; + } + #endif //DBGMSG_BLITDATA + + #ifdef DBGMSG_V2 + #define DBGAV2(v2) dbgmsgprj::dbgV2(v2,DBGTOSTR(v2)).str() + #define DBGSV2(v2) DBGSS(DBGAV2(v2)) + static std::stringstream dbgV2(v2 v2Val,const char* c){ + std::stringstream ss; + ss< Entry; @@ -79,6 +86,11 @@ class felist uint UpKey; uint DownKey; entrydrawer EntryDrawer; + v2 v2FinalPageSize; + static v2 v2SelectedPos; + static col16 colSelectedBkg; + v2 v2OriginalPos; + static v2 v2DefaultEntryImageSize; }; #endif diff --git a/FeLib/Include/graphics.h b/FeLib/Include/graphics.h index 5f8862547..ade274034 100644 --- a/FeLib/Include/graphics.h +++ b/FeLib/Include/graphics.h @@ -13,6 +13,8 @@ #ifndef __GRAPHICS_H__ #define __GRAPHICS_H__ +#include + #ifdef USE_SDL #include "SDL.h" #endif @@ -27,38 +29,78 @@ class bitmap; class rawbitmap; class festring; +typedef void (*drawabove)(bitmap*); + class graphics { public: friend class bitmap; static void Init(); static void DeInit(); + #ifdef USE_SDL + static void SetScale(int); static void SwitchMode(); + static void SetMode(cchar*, cchar*, v2, int, int, truth); #endif + #ifdef __DJGPP__ static void SwitchMode() { } -#endif static void SetMode(cchar*, cchar*, v2, truth); +#endif + + static void Stretch(bool, bitmap*, blitdata&, bool); + static void DrawRectangleOutlineAround(bitmap* bmpAt, v2 v2TopLeft, v2 v2Border, col16 color, bool wide); static void BlitDBToScreen(); + + static void DrawAboveAll(bitmap* bmpDest); + static void AddDrawAboveAll(drawabove da, int iPriority, const char* desc); + static v2 GetRes() { return Res; } static bitmap* GetDoubleBuffer() { return DoubleBuffer; } static void LoadDefaultFont(cfestring&); static rawbitmap* GetDefaultFont() { return DefaultFont; } - static void SetSwitchModeHandler(void (*What)()) - { SwitchModeHandler = What; } + static void SetSwitchModeHandler(void (*What)()){ SwitchModeHandler = What; } + + static int AddStretchRegion(blitdata B,const char* strId); + static int GetTotSRegions(); + static void SetSpecialListItemAltPos(bool b){bSpecialListItemAltPos=b;} + static void SetAllowStretchedBlit(){bAllowStretchedRegionsBlit=true;} //as the dungeon shows most of the time, + static void SetDenyStretchedBlit(){bAllowStretchedRegionsBlit=false;} //it should be denied only during a few moments. + static bool isStretchedRegionsAllowed(); + static void PrepareBeforeDrawingFelist(); + static void DrawAtDoubleBufferBeforeFelistPage(); + static bitmap* PrepareBuffer(); + + //TODO utility class for sregion? + static bool IsSRegionEnabled(int iIndex); + static void SetSRegionEnabled(int iIndex, bool b); + static void SetSRegionUseXBRZ(int iIndex, bool b); + static void SetSRegionDrawAfterFelist(int iIndex, bool b); + static void SetSRegionDrawAlways(int iIndex, bool b); + static void SetSRegionDrawBeforeFelistPage(int iIndex, bool, bool); + static void SetSRegionDrawRectangleOutline(int iIndex, bool b); + static void SetSRegionSrcBitmapOverride(int iIndex, bitmap* bmp, int iStretch, v2 v2Dest); + static void SetSRegionListItem(int iIndex); + static int SetSRegionBlitdata(int iIndex, blitdata B); + static void SetSRegionClearSquaresAt(int iIndex, v2 v2Size, std::vector vv2); + #ifdef USE_SDL -#if SDL_MAJOR_VERSION == 1 - static SDL_Surface* Screen; -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - static SDL_Surface* TempSurface; -#endif -#else - static SDL_Window* Window; - static SDL_Renderer *Renderer; - static SDL_Texture *Texture; -#endif + #if SDL_MAJOR_VERSION == 1 + static SDL_Surface* Screen; + #if SDL_BYTEORDER == SDL_BIG_ENDIAN + static SDL_Surface* TempSurface; + #endif + #else + public: + static SDL_Window* GetWindow(){return Window;}; + private: + static SDL_Window* Window; + static SDL_Renderer *Renderer; + static SDL_Texture *Texture; + #endif #endif + private: static void (*SwitchModeHandler)(); #ifdef __DJGPP__ @@ -114,7 +156,11 @@ class graphics } ModeInfo; #endif static bitmap* DoubleBuffer; + static bitmap* StretchedBuffer; + static truth bAllowStretchedRegionsBlit; + static truth bSpecialListItemAltPos; static v2 Res; + static int Scale; static int ColorDepth; static rawbitmap* DefaultFont; }; diff --git a/FeLib/Include/hscore.h b/FeLib/Include/hscore.h index 4caf3ff3d..f3857a334 100644 --- a/FeLib/Include/hscore.h +++ b/FeLib/Include/hscore.h @@ -19,11 +19,11 @@ #include "festring.h" #ifdef UNIX -#define HIGH_SCORE_FILENAME LOCAL_STATE_DIR "/ivan-highscore.scores" +#define HIGH_SCORE_FILENAME "ivan-highscore.scores" #endif #if defined(WIN32) || defined(__DJGPP__) -#define HIGH_SCORE_FILENAME CONST_S("HScore.dat") +#define HIGH_SCORE_FILENAME "HScore.dat" #endif class festring; @@ -31,11 +31,11 @@ class festring; class highscore { public: - highscore(cfestring& = HIGH_SCORE_FILENAME); + highscore(cfestring&); truth Add(long, cfestring&); void Draw() const; - void Save(cfestring& = HIGH_SCORE_FILENAME) const; - void Load(cfestring& = HIGH_SCORE_FILENAME); + void Save(cfestring& = "") const; + void Load(cfestring& = ""); truth LastAddFailed() const; void AddToFile(highscore*) const; truth MergeToFile(highscore*) const; @@ -54,6 +54,7 @@ class highscore std::vector RandomID; int LastAdd; ushort Version; + cfestring DefaultFile; }; #endif diff --git a/FeLib/Include/rawbit.h b/FeLib/Include/rawbit.h index a234cbbf8..5d1df428b 100644 --- a/FeLib/Include/rawbit.h +++ b/FeLib/Include/rawbit.h @@ -29,6 +29,7 @@ typedef std::map> fontcache; class rawbitmap { public: + friend class bitmap; rawbitmap(cfestring&); rawbitmap(v2); ~rawbitmap(); diff --git a/FeLib/Include/save.h b/FeLib/Include/save.h index 014caccb8..e639a6f36 100644 --- a/FeLib/Include/save.h +++ b/FeLib/Include/save.h @@ -14,7 +14,7 @@ #define __SAVE_H__ #include -#include +#include #include #include #include @@ -40,30 +40,28 @@ inline inputfile& operator>>(inputfile& SaveFile, type& Value)\ typedef std::map valuemap; -/* fstream seems to bug with DJGPP, so we use FILE* here */ - class outputfile { public: outputfile(cfestring&, truth = true); - ~outputfile(); - void Put(char What) { fputc(What, Buffer); } - void Write(cchar* Offset, long Size) - { fwrite(Offset, 1, Size, Buffer); } - truth IsOpen() { return Buffer != 0; } - void Close() { fclose(Buffer); Buffer = 0; } - void Flush() { fflush(Buffer); } - void ReOpen(); + void Put(char What) { File.put(What); } + void Write(cchar* Data, long Size) { File.write(Data, Size); } + truth IsOpen() { return File.is_open(); } + void Close(); + ~outputfile(){Close();} + static void SetSafeSaving(truth b); private: - FILE* Buffer; + static truth bakcupBeforeSaving; + static truth saveOnNewFileAlways; + std::ofstream File; festring FileName; + festring FileNameNewTmp; }; class inputfile { public: inputfile(cfestring&, const valuemap* = 0, truth = true); - ~inputfile(); festring ReadWord(truth = true); void ReadWord(festring&, truth = true); char ReadLetter(truth = true); @@ -71,23 +69,22 @@ class inputfile festring ReadStringOrNumber (long *num, truth *isString, truth PreserveTerminator=false); v2 ReadVector2d(); rect ReadRect(); - int Get() { return fgetc(Buffer); } - void Read(char* Offset, long Size) { fread(Offset, 1, Size, Buffer); } - truth IsOpen() { return Buffer != 0; } - truth Eof() { return feof(Buffer); } - void ClearFlags() { clearerr(Buffer); } - void SeekPosBegin(long Offset) { fseek(Buffer, Offset, SEEK_SET); } - void SeekPosCurrent(long Offset) { fseek(Buffer, Offset, SEEK_CUR); } - void SeekPosEnd(long Offset) { fseek(Buffer, Offset, SEEK_END); } - long TellPos() { return ftell(Buffer); } + int Get() { return File.get(); } + void Read(char* Data, long Size) { File.read(Data, Size); } + truth IsOpen() { return File.is_open(); } + truth Eof() { return File.eof(); } + void SeekPosBegin(long Offset) { File.seekg(Offset, std::ios::beg); } + void SeekPosCurrent(long Offset) { File.seekg(Offset, std::ios::cur); } + void SeekPosEnd(long Offset) { File.seekg(Offset, std::ios::end); } + long TellPos() { return File.tellg(); } ulong TellLine() { return TellLineOfPos(TellPos()); } ulong TellLineOfPos(long); cfestring& GetFileName() const { return FileName; } - void Close() { fclose(Buffer); Buffer = 0; } + void Close() { File.close(); } private: festring ReadNumberIntr (int CallLevel, long *num, truth *isString, truth allowStr, truth PreserveTerminator); int HandlePunct(festring&, int, int); - FILE* Buffer; + std::ifstream File; festring FileName; const valuemap* ValueMap; truth lastWordWasString; diff --git a/FeLib/Include/whandler.h b/FeLib/Include/whandler.h index 7fab8afb2..c5fb6a500 100644 --- a/FeLib/Include/whandler.h +++ b/FeLib/Include/whandler.h @@ -28,12 +28,24 @@ #define GET_KEY globalwindowhandler::GetKey #define READ_KEY globalwindowhandler::ReadKey #define GET_TICK globalwindowhandler::GetTick +#define WAIT_FOR_KEY_DOWN globalwindowhandler::WaitForKeyDown +#define WAIT_FOR_KEY_UP globalwindowhandler::WaitForKeyUp class globalwindowhandler { public: + static void CheckKeyTimeout(); + static truth IsKeyTimeoutEnabled(); + static void SetKeyTimeout(int iTimeoutMillis,int iDefaultReturnedKey); + static void SetPlayInBackground(truth b){playInBackground=b;} + static float GetFPS(bool bInsta); + static truth HasKeysOnBuffer(); static int GetKey(truth = true); static int ReadKey(); + static truth WaitForKeyEvent(uint Key); + static truth WaitForKeyDown(){return WaitForKeyEvent(SDL_KEYDOWN);} + static truth WaitForKeyUp (){return WaitForKeyEvent(SDL_KEYUP );} + static truth IsLastSDLkeyEventWasKeyUp(); static void InstallControlLoop(truth (*)()); static void DeInstallControlLoop(truth (*)()); static ulong GetTick() { return Tick; } @@ -41,13 +53,12 @@ class globalwindowhandler static void EnableControlLoops() { ControlLoopsEnabled = true; } static void DisableControlLoops() { ControlLoopsEnabled = false; } static truth ShiftIsDown(); - static void SetScrshotDirectory(cfestring& DirectoryName) - { ScrshotDirectoryName = DirectoryName; } + static void SetScrshotDirectory(cfestring& DirectoryName){ ScrshotDirectoryName = DirectoryName; } static festring ScrshotNameHandler(); // Number successive screenshots based on existing filenames + static void SetAddFrameSkip(int i); #ifdef USE_SDL static void Init(); - static void SetQuitMessageHandler(truth (*What)()) - { QuitMessageHandler = What; } + static void SetQuitMessageHandler(truth (*What)()){ QuitMessageHandler = What; } static ulong UpdateTick() { return Tick = SDL_GetTicks() / 40; } #endif #ifdef __DJGPP__ @@ -65,6 +76,7 @@ class globalwindowhandler static int Controls; static ulong Tick; static truth ControlLoopsEnabled; + static truth playInBackground; static festring ScrshotDirectoryName; }; diff --git a/FeLib/Source/bitmap.cpp b/FeLib/Source/bitmap.cpp index c5265679a..01953b945 100644 --- a/FeLib/Source/bitmap.cpp +++ b/FeLib/Source/bitmap.cpp @@ -12,6 +12,8 @@ #include #include +#include +#include #include "bitmap.h" #include "graphics.h" @@ -19,6 +21,10 @@ #include "allocate.h" #include "femath.h" #include "rawbit.h" +#include "libxbrzscale.h" + +#define DBGMSG_V2 +#include "dbgmsgproj.h" /* * Blitting must be as fast as possible, even if no optimizations are used; @@ -109,56 +115,21 @@ int Blue;\ bitmap::bitmap(cfestring& FileName) : FastFlag(0), AlphaMap(0), PriorityMap(0), RandMap(0) { - inputfile File(FileName.CStr(), 0, false); - - if(!File.IsOpen()) - ABORT("Bitmap %s not found!", FileName.CStr()); - - uchar Palette[768]; - File.SeekPosEnd(-768); - File.Read(reinterpret_cast(Palette), 768); - File.SeekPosBegin(8); - Size.X = File.Get(); - Size.X += (File.Get() << 8) + 1; - Size.Y = File.Get(); - Size.Y += (File.Get() << 8) + 1; + rawbitmap Temp(FileName); + Size = Temp.Size; XSizeTimesYSize = Size.X * Size.Y; - File.SeekPosBegin(128); Alloc2D(Image, Size.Y, Size.X); packcol16* Buffer = Image[0]; + paletteindex* TempBuffer = Temp.PaletteBuffer[0]; for(int y = 0; y < Size.Y; ++y) for(int x = 0; x < Size.X; ++x) { - int Char1 = File.Get(); - - if(Char1 > 192) - { - --x; - int Char2 = File.Get(); - int Char3 = Char2 + (Char2 << 1); - int Color = int(Palette[Char3] >> 3) << 11 - | int(Palette[Char3 + 1] >> 2) << 5 - | int(Palette[Char3 + 2] >> 3); - - for(; Char1 > 192; --Char1) - { - *Buffer++ = Color; - - if(++x == Size.X) - { - x = 0; - ++y; - } - } - } - else - { - int Char3 = Char1 + (Char1 << 1); - *Buffer++ = int(Palette[Char3] >> 3) << 11 - | int(Palette[Char3 + 1] >> 2) << 5 - | int(Palette[Char3 + 2] >> 3); - } + int Char1 = *TempBuffer++; + int Char3 = Char1 + (Char1 << 1); + *Buffer++ = int(Temp.Palette[Char3] >> 3) << 11 + | int(Temp.Palette[Char3 + 1] >> 2) << 5 + | int(Temp.Palette[Char3 + 2] >> 3); } } @@ -331,6 +302,30 @@ void bitmap::ClearToColor(col16 Color) } } +truth bitmap::HasColor(col16 findColor) +{ + for(int iY=0;iY=Size.Y)return; + memcpy(&Image[iYDest][0], &bmpFrom->Image[iYFrom][0], iSize); +} + void bitmap::NormalBlit(cblitdata& BlitData) const { blitdata B = BlitData; @@ -1192,6 +1187,191 @@ void bitmap::FadeToScreen(bitmapeditor BitmapEditor) graphics::BlitDBToScreen(); } +std::vector vSurfaceCache; +SDL_Surface* SurfaceCache(blitdata B,bool bUseScale){ // good to prevent memory hungryness + int iW=B.Border.X; + if(bUseScale)iW*=B.Stretch; + + int iH=B.Border.Y; + if(bUseScale)iH*=B.Stretch; + + for(int i=0;iw==iW && vSurfaceCache[i]->h==iH){ + return vSurfaceCache[i]; + } + } + + DBG4("Cache not found for surface w=",iW," h=",iH); + SDL_Surface* srf = libxbrzscale::createARGBSurface(iW, iH); //src img for look zoom at least is always 16x16 tho + + vSurfaceCache.push_back(srf);DBG3(srf,DBGI(srf->w),DBGI(srf->h)); + DBGSI(vSurfaceCache.size()); + + return srf; +} + +void bitmap::ResetBlitdataRotation(blitdata& B) +{ + B.Flags &= ~MIRROR; + B.Flags &= ~FLIP; + B.Flags &= ~ROTATE; +} + +void bitmap::ConfigureBlitdataRotation(blitdata& B,int iR){ + ResetBlitdataRotation(B); + + // set + iR %= 4; + /**** + * 1 1 + * 2 2 + * 3 3 + * 4 0->4 + * 5 1 + * 6 2 + * 7 3 + * 8 0->4 + */ + if(iR==0)iR = 4 * (iR>0 ? 1 : -1); + /*** the blade side is inverted, so invert the rotation + * -1 -> -4 + * -2 -> -3 + * -3 -> -2 + * -4 -> -1 + */ + switch(iR){ + case -1:iR=-4;break; + case -2:iR=-3;break; + case -3:iR=-2;break; + case -4:iR=-1;break; + } + + switch(iR){ + case 1: // 1st step always rotate once + B.Flags |= ROTATE; //90 degrees + break; + case 2: + B.Flags |= FLIP|MIRROR; //180 degrees + break; + case 3: + B.Flags |= ROTATE|FLIP|MIRROR; //270 degrees + break; + case 4: + // initial/default rotation + break; + case -1: // 1st step always rotate once + B.Flags |= MIRROR; //-90 degrees + break; + case -2: + B.Flags |= FLIP|ROTATE; //-180 degrees + break; + case -3: + B.Flags |= FLIP; //-270 degrees + break; + case -4: + B.Flags |= MIRROR|ROTATE; //-0 degrees (like a mirrored image :)) + break; + } +} + +SDL_PixelFormat* fmt = SDL_AllocFormat(SDL_PIXELFORMAT_RGBA8888); //format based on xbrzscale code + +SDL_Surface* bitmap::CopyToSurface(v2 v2TopLeft, v2 v2Size, col16 MaskColor, SDL_Surface* srf) const +{ + if(srf==NULL) srf = libxbrzscale::createARGBSurface(this->Size.X,this->Size.Y); + + // copy pixels to surface + Uint32 color32bit; + packcol16 PixelFrom; + unsigned char ca=0xff; + for(int x1 = 0; x1 < v2Size.X; x1++) + { + for(int y1 = 0; y1 < v2Size.Y; y1++) + { + PixelFrom = Image[v2TopLeft.Y + y1][v2TopLeft.X + x1]; + + if(PixelFrom == MaskColor){ //0 invisible, 0xff opaque + ca = 0; +// static packcol16 DarkestNotBlack = MakeRGB16(1,1,1); +// PixelFrom = DarkestNotBlack; //didnt work :( + PixelFrom = WHITE; //xBRZ blends countours perfectly this way + }else{ + ca = 0xff; + } + + color32bit = SDL_MapRGBA( + fmt, + (unsigned char)GetRed16(PixelFrom), + (unsigned char)GetGreen16(PixelFrom), + (unsigned char)GetBlue16(PixelFrom), + ca + ); + libxbrzscale::SDL_PutPixel(srf, x1, y1, color32bit); + } + } + + return srf; +} + +/** + * stretch from 2 to 6 only! + */ +void bitmap::StretchBlitXbrz(cblitdata& BlitDataTo, bool bAllowTransparency) const +{ + if( + (BlitDataTo.Src.X+BlitDataTo.Border.X) > Size.X + || + (BlitDataTo.Src.Y+BlitDataTo.Border.Y) > Size.Y + ){ + ABORT("requested copy from rectangle pos=%d,%d size=%d,%d outside of limits=%d,%d",BlitDataTo.Src.X,BlitDataTo.Src.Y,BlitDataTo.Border.X,BlitDataTo.Border.Y,Size.X,Size.Y); + } + + blitdata Bto = BlitDataTo;DBGLN; //to easy coding + if(Bto.Dest.X>=Bto.Bitmap->GetSize().X || Bto.Dest.Y>=Bto.Bitmap->GetSize().Y){ + ABORT("invalid stretch destination %d,%d on target bitmap size %d,%d",Bto.Dest.X,Bto.Dest.Y,Bto.Bitmap->GetSize().X,Bto.Bitmap->GetSize().Y); + } + + static bool bXbrzLibCfgInitialized=false; + if(!bXbrzLibCfgInitialized){ //TODO this config should be placed more globally? + libxbrzscale::setUseCache(true);DBGLN; +#ifdef DBGMSG + libxbrzscale::setDebugMsg(true);DBGLN; +#endif + libxbrzscale::setFreeSurfaceAfterScale(false,false);DBGLN; + bXbrzLibCfgInitialized=true;DBGLN; + } + + bool bFreeImg=false;DBGLN; + + DBG2(Bto.Bitmap,DBGAV2(Bto.Bitmap->GetSize())); + SDL_Surface* imgCopy = CopyToSurface(Bto.Src, Bto.Border, Bto.MaskColor, SurfaceCache(Bto,false));DBGLN; + + Uint32 color32bit;DBGLN; + unsigned char cr,cg,cb,ca;DBGLN; + SDL_Surface* imgStretchedCopy=NULL;DBGLN; + imgStretchedCopy=libxbrzscale::scale(SurfaceCache(Bto,true), imgCopy, Bto.Stretch);DBG3(imgStretchedCopy,DBGI(imgStretchedCopy->w),DBGI(imgStretchedCopy->h)); +// if( ((Bto.Dest.X+imgStretchedCopy->w) >= Bto.Bitmap->GetSize().X) || +// ((Bto.Dest.Y+imgStretchedCopy->h) >= Bto.Bitmap->GetSize().Y) )ABORT("blit %d,%d + %d,%d outside dest bitmap %d,%d",Bto.Dest.X,Bto.Dest.Y,imgStretchedCopy->w,imgStretchedCopy->h,Bto.Bitmap->GetSize().X,Bto.Bitmap->GetSize().Y); + // copy from surface the scaled image back to where it is expected TODO comment a more precise info... + for(int x1 = 0; x1 < imgStretchedCopy->w; ++x1) + { + for(int y1 = 0; y1 < imgStretchedCopy->h; ++y1) + { + color32bit = libxbrzscale::SDL_GetPixel(imgStretchedCopy,x1,y1);//DBGLN; + SDL_GetRGBA(color32bit,fmt,&cr,&cg,&cb,&ca);//DBGLN; + if(!bAllowTransparency || ca==0xff){ //TODO ca==0xff may work better than ca!=0 the day xBRZScale blends from opaque to transparent with a half-transparent alpha value as result!? + if((Bto.Dest.X+x1)GetSize().X && (Bto.Dest.Y+y1)GetSize().Y){ + Bto.Bitmap->Image[Bto.Dest.Y+y1][Bto.Dest.X+x1] = MakeRGB16(cr,cg,cb);//DBGLN; //TODO does alpha make any sense here anyway? + } + } + } + } + DBGLN; + +// SDL_FreeSurface(imgCopy); +// SDL_FreeSurface(imgStretchedCopy); +} + void bitmap::StretchBlit(cblitdata& BlitData) const { blitdata B = BlitData; diff --git a/FeLib/Source/config.cpp b/FeLib/Source/config.cpp index 81f936f95..e2e99d8e2 100644 --- a/FeLib/Source/config.cpp +++ b/FeLib/Source/config.cpp @@ -19,7 +19,12 @@ configoption* configsystem::Option[MAX_CONFIG_OPTIONS]; festring configsystem::ConfigFileName; int configsystem::Options; -void configsystem::AddOption(configoption* O) { Option[Options++] = O; } +void configsystem::AddOption(festring fsCategory, configoption* O) { + for(int i=0;iName, O->Description); //help developers to prevent duplicated entries + + O->fsCategory=fsCategory; + Option[Options++] = O; +} void configsystem::NormalStringChanger(stringoption* O, cfestring& What) { O->Value = What; } void configsystem::NormalNumberChanger(numberoption* O, long What) @@ -134,7 +139,7 @@ void configsystem::Show(void (*BackGroundDrawer)(), int Chosen; truth TruthChange = false; - felist List(CONST_S("Which setting do you wish to configure?")); + felist List(CONST_S("Which setting do you wish to configure? (* - req. restart)")); List.AddDescription(CONST_S("")); List.AddDescription(CONST_S("Setting Value")); @@ -145,12 +150,19 @@ void configsystem::Show(void (*BackGroundDrawer)(), List.Empty(); + festring fsLastCategory; for(int c = 0; c < Options; ++c) { festring Entry = Option[c]->Description; Entry.Capitalize(); Entry.Resize(60); - Option[c]->DisplayeValue(Entry); + Option[c]->DisplayValue(Entry); + + if(fsLastCategory!=Option[c]->fsCategory){ + List.AddEntry(Option[c]->fsCategory, WHITE, 0, NO_IMAGE, false); + fsLastCategory=Option[c]->fsCategory; + } + List.AddEntry(Entry, LIGHT_GRAY); } diff --git a/FeLib/Source/error.cpp b/FeLib/Source/error.cpp index af78c334f..b5c9d4894 100644 --- a/FeLib/Source/error.cpp +++ b/FeLib/Source/error.cpp @@ -26,6 +26,11 @@ #include #else #include +#include +#include +#include +#include +#include #endif #ifdef VC @@ -36,6 +41,8 @@ #define set_new_handler std::set_new_handler #endif +#include "dbgmsgproj.h" + #include "error.h" /* Shouldn't be initialized here! */ @@ -58,6 +65,16 @@ int globalerrorhandler::Signal[SIGNALS] = { SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM, SIGINT, SIGKILL, SIGQUIT }; #endif +#ifndef WIN32 +void globalerrorhandler::DumpStackTraceToStdErr(int Signal){ + // Prints stack trace to stderr. + void* CallStack[128]; + size_t Frames = backtrace(CallStack, 128); + if(Signal>-1)std::cerr << strsignal(Signal) << std::endl; + backtrace_symbols_fd(CallStack, Frames, STDERR_FILENO); +} +#endif + void globalerrorhandler::Install() { static truth AlreadyInstalled = false; @@ -88,6 +105,10 @@ void globalerrorhandler::DeInstall() void globalerrorhandler::Abort(cchar* Format, ...) { +#ifndef WIN32 + DumpStackTraceToStdErr(); +#endif + char Buffer[512]; va_list AP; @@ -110,6 +131,7 @@ void globalerrorhandler::Abort(cchar* Format, ...) std::cout << Buffer << std::endl; #endif + DBGSTK;DBG2("ABORT:",Buffer); exit(4); } diff --git a/FeLib/Source/feio.cpp b/FeLib/Source/feio.cpp index 1500025ac..f5f1adec0 100644 --- a/FeLib/Source/feio.cpp +++ b/FeLib/Source/feio.cpp @@ -13,7 +13,16 @@ #include #include +#include +#include +#include + +#include +#include +#include + #ifdef WIN32 +#define stat _stat #include #endif @@ -21,21 +30,27 @@ #include #include #include -#include -#include +#include +#include +#include +#include #endif #ifdef __DJGPP__ #include #endif -#include "graphics.h" +#include "bitmap.h" +#include "error.h" #include "feio.h" -#include "whandler.h" #include "felist.h" -#include "rawbit.h" #include "festring.h" -#include "bitmap.h" +#include "graphics.h" +#include "rawbit.h" +#include "save.h" +#include "whandler.h" + +#include "dbgmsgproj.h" #define PENT_WIDTH 70 @@ -110,6 +125,12 @@ int CountChars(char cSF, cfestring& sSH) return iReturnCounter; } +truth bMenuIsActive=false; + +truth iosystem::IsOnMenu(){ + return bMenuIsActive; +} + /* Draws a menu on bitmap BackGround to position Pos. festring Topic is the text that is shown before the choices '\r' is a line-ending character. Topic must end with a '\r'. sMS is a list of choices @@ -132,6 +153,7 @@ int iosystem::Menu(cbitmap* BackGround, v2 Pos, if(CountChars('\r', sMS) < 1) return (-1); + bMenuIsActive=true; truth bReady = false; int iSelected = 0; bitmap Backup(DOUBLE_BUFFER); @@ -140,9 +162,18 @@ int iosystem::Menu(cbitmap* BackGround, v2 Pos, Buffer.ActivateFastFlag(); int c = 0; - if(BackGround) - BackGround->FastBlit(&Buffer); - else + if(BackGround){ + //vanilla was 800x600 as the background menu image. TODO provide calculations for lower than 800x600 one day? + if(RES.X < BackGround->GetSize().X)ABORT("invalid window width %d",RES.X); + if(RES.Y < BackGround->GetSize().Y)ABORT("invalid window height %d",RES.Y); + + if( (RES.X!=BackGround->GetSize().X) || (RES.Y!=BackGround->GetSize().Y) ){ + Buffer.ClearToColor(0); + BackGround->FastBlit(&Buffer,{(RES.X-BackGround->GetSize().X)/2, (RES.Y-BackGround->GetSize().Y)/2}); + }else{ + BackGround->FastBlit(&Buffer); + } + }else Buffer.ClearToColor(0); festring sCopyOfMS; @@ -185,7 +216,7 @@ int iosystem::Menu(cbitmap* BackGround, v2 Pos, FONT->Printf(&Buffer, v2(XPos, YPos), Color, "%d. %s", i + 1, VeryUnGuruPrintf.CStr()); - } + } sCopyOfMS = SmallText1; @@ -260,11 +291,14 @@ int iosystem::Menu(cbitmap* BackGround, v2 Pos, break; default: - if(k > 0x30 && k < 0x31 + CountChars('\r', sMS)) + if(k > 0x30 && k < 0x31 + CountChars('\r', sMS)){ + bMenuIsActive=false; return k - 0x31; + } } } + bMenuIsActive=false; return iSelected; } @@ -356,7 +390,7 @@ int iosystem::StringQuestion(festring& Input, if(LastKey == KEY_BACK_SPACE) { - if(CursorPos) + if(CursorPos > 0) Input.Erase(static_cast(--CursorPos), 1); continue; @@ -373,25 +407,23 @@ int iosystem::StringQuestion(festring& Input, } } - if(LastKey == KEY_LEFT) + if(LastKey == KEY_HOME) { - if(CursorPos) - --CursorPos; + CursorPos = 0; continue; } - if(LastKey == KEY_RIGHT) + if(LastKey == KEY_END) { - if(CursorPos < static_cast(Input.GetSize())) - ++CursorPos; + CursorPos = static_cast(Input.GetSize()); continue; } if(LastKey == KEY_LEFT) { - if(CursorPos) + if(CursorPos > 0) --CursorPos; continue; @@ -405,9 +437,9 @@ int iosystem::StringQuestion(festring& Input, continue; } - if(LastKey >= 0x20 && Input.GetSize() < MaxLetters + if(LastKey >= 0x20 && LastKey < 0x7F && (LastKey != ' ' || !Input.IsEmpty()) - && LastKey != KEY_UP && LastKey != KEY_DOWN) + && Input.GetSize() < MaxLetters) Input.Insert(static_cast(CursorPos++), static_cast(LastKey)); } @@ -472,13 +504,14 @@ long iosystem::NumberQuestion(cfestring& Topic, v2 Pos, col16 Color, while(!isdigit(LastKey) && LastKey != KEY_BACK_SPACE && LastKey != KEY_ENTER && LastKey != KEY_ESC + && LastKey != KEY_HOME && LastKey != KEY_END && LastKey != KEY_LEFT && LastKey != KEY_RIGHT && (LastKey != '-' || !Input.IsEmpty())) LastKey = GET_KEY(false); if(LastKey == KEY_BACK_SPACE) { - if(CursorPos) + if(CursorPos > 0) Input.Erase(static_cast(--CursorPos), 1); continue; @@ -495,9 +528,23 @@ long iosystem::NumberQuestion(cfestring& Topic, v2 Pos, col16 Color, break; } + if(LastKey == KEY_HOME) + { + CursorPos = 0; + + continue; + } + + if(LastKey == KEY_END) + { + CursorPos = static_cast(Input.GetSize()); + + continue; + } + if(LastKey == KEY_LEFT) { - if(CursorPos) + if(CursorPos > 0) --CursorPos; continue; @@ -644,6 +691,7 @@ long iosystem::ScrollBarQuestion(cfestring& Topic, v2 Pos, while(!isdigit(LastKey) && LastKey != KEY_ESC && LastKey != KEY_BACK_SPACE && LastKey != KEY_ENTER && LastKey != KEY_SPACE && LastKey != '<' && LastKey != '>' + && LastKey != KEY_HOME && LastKey != KEY_END && LastKey != RightKey && LastKey != LeftKey && LastKey != KEY_RIGHT && LastKey != KEY_LEFT) LastKey = GET_KEY(false); @@ -665,6 +713,24 @@ long iosystem::ScrollBarQuestion(cfestring& Topic, v2 Pos, if(LastKey == KEY_ENTER || LastKey == KEY_SPACE) break; + if(LastKey == KEY_HOME) + { + BarValue = Min; + + Input.Empty(); + Input << BarValue; + continue; + } + + if(LastKey == KEY_END) + { + BarValue = Max; + + Input.Empty(); + Input << BarValue; + continue; + } + if(LastKey == '<' || LastKey == LeftKey || LastKey == KEY_LEFT) { BarValue -= Step; @@ -696,133 +762,538 @@ long iosystem::ScrollBarQuestion(cfestring& Topic, v2 Pos, return BarValue; } -/* DirectoryName is the directory where the savefiles are located. Returns - the selected file or "" if an error occures or if no files are found. */ +//TODO dropped in favor of non crashing (for old saves) new code protection, clean this commented code later +///** +// * this will surely work if savegame sorting is disabled +// */ +//festring ContinueMenuOldAndSafe(col16 TopicColor, col16 ListColor, +// cfestring& DirectoryName) +//{ +//#ifdef WIN32 +// struct _finddata_t Found; +// long hFile; +// int Check = 0; +// festring Buffer; +// felist List(CONST_S("Choose a file and be sorry:"), TopicColor); +// hFile = _findfirst(festring(DirectoryName + "*.sav").CStr(), &Found); +// +// /* No file found */ +// if(hFile == -1L) +// { +// iosystem::TextScreen(CONST_S("You don't have any previous saves."), ZERO_V2, TopicColor); +// return ""; +// } +// +// while(!Check) +// { +// /* Copy all the filenames to Buffer */ +// /* Buffer = Found.name; Doesn't work because of a festring bug */ +// +// Buffer.Empty(); +// Buffer << Found.name; +// List.AddEntry(Buffer, ListColor); +// Check = _findnext(hFile, &Found); +// } +// +// Check = List.Draw(); +// +// /* an error has occured in felist */ +// +// if(Check & FELIST_ERROR_BIT) +// return ""; +// +// return List.GetEntry(Check); +//#endif +// +//#ifdef UNIX +// DIR* dp; +// struct dirent* ep; +// festring Buffer; +// felist List(CONST_S("Choose a file and be sorry:"), TopicColor); +// dp = opendir(DirectoryName.CStr()); +// +// if(dp) +// { +// while((ep = readdir(dp))) +// { +// /* Buffer = ep->d_name; Doesn't work because of a festring bug */ +// Buffer.Empty(); +// Buffer << ep->d_name; +// /* Add to List all save files */ +// if(Buffer.Find(".sav") != Buffer.NPos) +// List.AddEntry(Buffer, ListColor); +// } +// +// closedir(dp); +// +// if(List.IsEmpty()) +// { +// iosystem::TextScreen(CONST_S("You don't have any previous saves."), ZERO_V2, TopicColor); +// return ""; +// } +// else +// { +// int Check = List.Draw(); +// +// if(Check & FELIST_ERROR_BIT) +// return ""; +// +// return List.GetEntry(Check); +// } +// +// } +// +// return ""; +//#endif +// +//#ifdef __DJGPP__ +// struct ffblk Found; +// int Check = 0; +// festring Buffer; +// felist List(CONST_S("Choose a file and be sorry:"), TopicColor); +// +// /* get all filenames ending with .sav. Accepts all files even if they +// FA_HIDDEN or FA_ARCH flags are set (ie. they are hidden or archives */ +// +// Check = findfirst(festring(DirectoryName + "*.sav").CStr(), +// &Found, FA_HIDDEN | FA_ARCH); +// +// if(Check) +// { +// iosystem::TextScreen(CONST_S("You don't have any previous saves."), ZERO_V2, TopicColor); +// return ""; +// } +// +// while(!Check) +// { +// /* Buffer = Found.ff_name; Doesn't work because of a festring bug */ +// Buffer.Empty(); +// Buffer << Found.ff_name; +// List.AddEntry(Buffer, ListColor); +// Check = findnext(&Found); +// } +// +// Check = List.Draw(); +// +// if(Check & FELIST_ERROR_BIT) +// return ""; +// +// return List.GetEntry(Check); +//#endif +//} + +bool AlertConfirmMsg(const char* cMsg, bool bAbortIfNot=true) //TODO this method could be more global +{ + v2 v2Border(700,100); + v2 v2TL(RES.X/2-v2Border.X/2,RES.Y/2-v2Border.Y/2); + + DOUBLE_BUFFER->Fill(v2TL,v2Border,RED); + graphics::DrawRectangleOutlineAround(DOUBLE_BUFFER, v2TL, v2Border, YELLOW, true); + + v2TL+=v2(16,16); + FONT->Printf(DOUBLE_BUFFER, v2(v2TL.X,v2TL.Y ), WHITE, "%s", cMsg); + FONT->Printf(DOUBLE_BUFFER, v2(v2TL.X,v2TL.Y+32), WHITE, "%s", "(y)es, any other key to ignore this message."); + + graphics::BlitDBToScreen(); //as the final blit may be from StretchedBuffer + if(GET_KEY() == 'y')return true; + + return false; +} + +static bool bSaveGameSortModeByDtTm; +static bool bSaveGameSortModeProgress; +static bool bSaveGameSortModeReversed; +void iosystem::SetSaveGameSortMode(int i){ + bSaveGameSortModeByDtTm=false; + bSaveGameSortModeProgress=false; + bSaveGameSortModeReversed=false; + + switch(i){ + case 0: + bSaveGameSortModeReversed=true; + bSaveGameSortModeByDtTm=true; + break; + case 1: + bSaveGameSortModeReversed=true; + bSaveGameSortModeByDtTm=true; + bSaveGameSortModeProgress=true; + break; + case 2: //alphanum is essential + break; + case 3: + bSaveGameSortModeProgress=true; + break; + default: + ABORT("unsupported savegame sort option %d",i); + } +} +struct fileInfo{ + int Version = -1; + char* GameScript = 0; //dummy + int CurrentDungeonIndex = -1; + int CurrentLevelIndex = -1; + v2 Camera; //dummy + truth WizardMode; + festring fileName=festring(); //TODO this init helps with festring? is it buggy? + festring absFileName=festring(); //contains the full path + festring time=festring(); + festring idOnList=festring(); + festring dungeonID=festring(); + festring fileNameAutoSave=festring(); + std::vector vBackups; + bool bIsBkp = false; +}; +std::vector vFiles; +bool addFileInfo(const char* c){ + // skippers + if(strcmp(c,".")==0)return false; + if(strcmp(c,"..")==0)return false; + + // do add + fileInfo fi; + fi.fileName<