diff options
-rw-r--r-- | .vscode/c_cpp_properties.json | 32 | ||||
-rw-r--r-- | .vscode/launch.json | 89 | ||||
-rw-r--r-- | .vscode/settings.json | 30 | ||||
-rw-r--r-- | .vscode/tasks.json | 95 | ||||
-rw-r--r-- | CODING_STYLE.md | 107 | ||||
-rw-r--r-- | README.md | 111 | ||||
-rw-r--r-- | premake5.lua | 2 | ||||
-rw-r--r-- | src/audio/DMAudio.cpp | 1 | ||||
-rw-r--r-- | src/control/CarCtrl.cpp | 2 | ||||
-rw-r--r-- | src/control/Darkel.cpp | 20 | ||||
-rw-r--r-- | src/core/config.h | 5 | ||||
-rw-r--r-- | src/extras/ini_parser.hpp | 314 | ||||
-rw-r--r-- | src/render/Font.cpp | 40 | ||||
-rw-r--r-- | src/render/Font.h | 6 | ||||
-rw-r--r-- | src/save/GenericGameStorage.cpp | 1 | ||||
-rw-r--r-- | src/save/PCSave.cpp | 1 | ||||
-rw-r--r-- | src/skel/crossplatform.cpp | 10 | ||||
-rw-r--r-- | src/skel/crossplatform.h | 4 | ||||
-rw-r--r-- | src/skel/glfw/glfw.cpp | 89 | ||||
-rw-r--r-- | src/skel/win/win.cpp | 2 | ||||
-rw-r--r-- | src/text/Text.cpp | 125 | ||||
-rw-r--r-- | src/text/Text.h | 5 | ||||
-rw-r--r-- | src/vehicles/Vehicle.cpp | 2 |
23 files changed, 871 insertions, 222 deletions
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..327d8cc7 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,32 @@ +{ + "configurations": [ + { + "name": "Mac", + "includePath": ["${default}"], + "defines": [], + "macFrameworkPath": [ + "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks" + ], + "compilerPath": "/opt/local/bin/clang", + "compilerArgs": ["-g"], + "cStandard": "gnu11", + "cppStandard": "gnu++14", + "browse": { + "path": [ + "/opt/local/include", + "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include" + ] + } + }, + { + "name": "Linux", + "includePath": ["${default}"], + "defines": ["XDG_ROOT"], + "compilerPath": "/usr/bin/gcc", + "compilerArgs": ["-ggdb"], + "cStandard": "gnu11", + "cppStandard": "gnu++14" + } + ], + "version": 4 +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..82ce041f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,89 @@ +{ + "configurations": [ + { + "MIMode": "gdb", + "args": [], + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "name": "(gdb) Launch (Linux Debug)", + "preLaunchTask": "Compile (Debug Linux x64)", + "program": "${workspaceFolder}/bin/linux-amd64-librw_gl3_glfw-oal/Debug/re3", + "request": "launch", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "ignoreFailures": true, + "text": "-enable-pretty-printing" + } + ], + "stopAtEntry": false, + "targetArchitecture": "x64", + "type": "cppdbg" + }, + { + "MIMode": "gdb", + "args": [], + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "name": "(gdb) Launch (Linux Release)", + "preLaunchTask": "Compile (Release Linux x64)", + "program": "${workspaceFolder}/bin/linux-amd64-librw_gl3_glfw-oal/Release/re3", + "request": "launch", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "ignoreFailures": true, + "text": "-enable-pretty-printing" + } + ], + "stopAtEntry": false, + "targetArchitecture": "x64", + "type": "cppdbg" + }, + { + "MIMode": "lldb", + "args": [], + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "name": "(lldb) Launch (macOS Debug)", + "preLaunchTask": "Compile (Debug macOS x64)", + "program": "${workspaceFolder}/bin/macosx-amd64-librw_gl3_glfw-oal/Debug/re3.app", + "request": "launch", + "setupCommands": [ + { + "description": "Enable pretty-printing for lldb", + "ignoreFailures": true, + "text": "-enable-pretty-printing" + } + ], + "stopAtEntry": false, + "targetArchitecture": "x64", + "type": "cppdbg" + }, + { + "MIMode": "lldb", + "args": [], + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "name": "(lldb) Launch (macOS Release)", + "preLaunchTask": "Compile (Release macOS x64)", + "program": "${workspaceFolder}/bin/macosx-amd64-librw_gl3_glfw-oal/Release/re3.app", + "request": "launch", + "setupCommands": [ + { + "description": "Enable pretty-printing for lldb", + "ignoreFailures": true, + "text": "-enable-pretty-printing" + } + ], + "stopAtEntry": false, + "targetArchitecture": "x64", + "type": "cppdbg" + } + ], + "version": "0.2.0" +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..10cb5627 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,30 @@ +{ + "C_Cpp.default.cStandard": "gnu11", + "C_Cpp.default.cppStandard": "gnu++14", + "C_Cpp.default.includePath": [ + "src/animation", + "src/audio", + "src/control", + "src/core", + "src/entities", + "src/extras", + "src/fakerw", + "src/math", + "src/modelinfo", + "src/objects", + "src/peds", + "src/render", + "src/rw", + "src/save", + "src/skel", + "src/text", + "src/vehicles", + "src/weapons", + "vendor/librw" + ], + "C_Cpp.vcFormat.indent.gotoLabels": "leftmostColumn", + "C_Cpp.vcFormat.space.pointerReferenceAlignment": "right", + "cSpell.enabled": false, + "files.trimFinalNewlines": false, + "files.trimTrailingWhitespace": false +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..0f610d5f --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,95 @@ +{ + "tasks": [ + { + "args": ["--with-librw", "gmake2"], + "command": "./premake5Linux", + "label": "Premake (Linux)", + "problemMatcher": "$gcc", + "type": "shell" + }, + { + "args": ["--with-librw", "gmake2"], + "command": "premake5", + "label": "Premake (macOS)", + "problemMatcher": "$gcc", + "type": "shell" + }, + { + "args": [ + "-j5", + "config=debug_linux-amd64-librw_gl3_glfw-oal", + "verbose=1" + ], + "command": "make", + "dependsOn": "Premake (Linux)", + "group": { + "isDefault": true, + "kind": "build" + }, + "label": "Compile (Debug Linux x64)", + "options": { + "cwd": "${workspaceFolder}/build" + }, + "problemMatcher": "$gcc", + "type": "shell" + }, + { + "args": [ + "-j5", + "config=release_linux-amd64-librw_gl3_glfw-oal", + "verbose=1" + ], + "command": "make", + "dependsOn": "Premake (Linux)", + "group": { + "isDefault": true, + "kind": "build" + }, + "label": "Compile (Release Linux x64)", + "options": { + "cwd": "${workspaceFolder}/build" + }, + "problemMatcher": "$gcc", + "type": "shell" + }, + { + "args": [ + "-j5", + "config=debug_macosx-amd64-librw_gl3_glfw-oal", + "verbose=1" + ], + "command": "make", + "dependsOn": "Premake (macOS)", + "group": { + "isDefault": true, + "kind": "build" + }, + "label": "Compile (Debug macOS x64)", + "options": { + "cwd": "${workspaceFolder}/build" + }, + "problemMatcher": "$gcc", + "type": "shell" + }, + { + "args": [ + "-j5", + "config=release_macosx-amd64-librw_gl3_glfw-oal", + "verbose=1" + ], + "command": "make", + "dependsOn": "Premake (macOS)", + "group": { + "isDefault": true, + "kind": "build" + }, + "label": "Compile (Release macOS x64)", + "options": { + "cwd": "${workspaceFolder}/build" + }, + "problemMatcher": "$gcc", + "type": "shell" + } + ], + "version": "2.0.0" +} diff --git a/CODING_STYLE.md b/CODING_STYLE.md new file mode 100644 index 00000000..b8be02bc --- /dev/null +++ b/CODING_STYLE.md @@ -0,0 +1,107 @@ +# Coding style + +I started writing in [Plan 9 style](http://man.cat-v.org/plan_9/6/style), +but realize that this is not the most popular style, so I'm willing to compromise. +Try not to deviate too much so the code will look similar across the whole project. + +To give examples, these two styles (or anything in between) are fine: + +``` +type +functionname(args) +{ + if(a == b){ + s1; + s2; + }else{ + s3; + s4; + } + if(x != y) + s5; +} + +type functionname(args) +{ + if (a == b) { + s1; + s2; + } else { + s3; + s4; + } + if (x != y) + s5; +} +``` + +This one (or anything more extreme) is heavily discouraged: + +``` +type functionname ( args ) +{ + if ( a == b ) + { + s1; + s2; + } + else + { + s3; + s4; + } + if ( x != y ) + { + s5; + } +} +``` + +i.e. + +* Put the brace on the same line as control statements + +* Put the brace on the next line after function definitions and structs/classes + +* Put an `else` on the same line with the braces + +* Don't put braces around single statements + +* Put the function return type on a separate line + +* Indent with TABS + +As for the less cosmetic choices, here are some guidelines how the code should look: + +* Don't use magic numbers where the original source code would have had an enum or similar. +Even if you don't know the exact meaning it's better to call something `FOOBAR_TYPE_4` than just `4`, +since `4` will be used in other places and you can't easily see where else the enum value is used. + +* Don't just copy paste code from IDA, make it look nice + +* Use the right types. In particular: + + * don't use types like `__int16`, we have `int16` for that + + * don't use `unsigned`, we have typedefs for that + + * don't use `char` for anything but actual characters, use `int8`, `uint8` or `bool` + + * don't even think about using win32 types (`BYTE`, `WORD`, &c.) unless you're writing win32 specific code + + * declare pointers like `int *ptr;`, not `int* ptr;` + +* As for variable names, the original gta source code was not written in a uniform style, +but here are some observations: + + * many variables employ a form of hungarian notation, i.e.: + + * `m_` may be used for class member variables (mostly those that are considered private) + + * `ms_` for (mostly private) static members + + * `f` is a float, `i` or `n` is an integer, `b` is a boolean, `a` is an array + + * do *not* use `dw` for `DWORD` or so, we're not programming win32 + +* Generally, try to make the code look as if R* could have written it @@ -21,8 +21,7 @@ such that we have a working game at all times. ## Preparing the environment for building -- Clone the repo. -- Run `git submodule init` and `git submodule update`. +- Clone the repo using the argument `--recursive`. - Point GTA_III_RE_DIR environment variable to GTA3 root folder. - Run premake - On Windows: one of the `premake-vsXXXX.cmd` variants on root folder @@ -36,6 +35,7 @@ such that we have a working game at all times. > :information_source: **Did you notice librw?** re3 uses completely homebrew RenderWare-replacement rendering engine; [librw](https://github.com/aap/librw/). librw comes as submodule of re3, but you also can use LIBRW enviorenment variable to specify path to your own librw. ## Contributing +Please read the [Coding Style](https://github.com/GTAmodding/re3/blob/master/CODING_STYLE.md) Document ### Unreversed / incomplete classes (at least the ones we know) The following classes have only unused or practically unused code left: @@ -44,110 +44,3 @@ CCullZone - only mobile stuff CCullZones - only mobile stuff ``` -### Coding style - -I started writing in [Plan 9 style](http://man.cat-v.org/plan_9/6/style), -but realize that this is not the most popular style, so I'm willing to compromise. -Try not to deviate too much so the code will look similar across the whole project. - -To give examples, these two styles (or anything in between) are fine: - -``` -type -functionname(args) -{ - if(a == b){ - s1; - s2; - }else{ - s3; - s4; - } - if(x != y) - s5; -} - -type functionname(args) -{ - if (a == b) { - s1; - s2; - } else { - s3; - s4; - } - if (x != y) - s5; -} -``` - -This one (or anything more extreme) is heavily discouraged: - -``` -type functionname ( args ) -{ - if ( a == b ) - { - s1; - s2; - } - else - { - s3; - s4; - } - if ( x != y ) - { - s5; - } -} -``` - -i.e. - -* Put the brace on the same line as control statements - -* Put the brace on the next line after function definitions and structs/classes - -* Put an `else` on the same line with the braces - -* Don't put braces around single statements - -* Put the function return type on a separate line - -* Indent with TABS - -As for the less cosmetic choices, here are some guidelines how the code should look: - -* Don't use magic numbers where the original source code would have had an enum or similar. -Even if you don't know the exact meaning it's better to call something `FOOBAR_TYPE_4` than just `4`, -since `4` will be used in other places and you can't easily see where else the enum value is used. - -* Don't just copy paste code from IDA, make it look nice - -* Use the right types. In particular: - - * don't use types like `__int16`, we have `int16` for that - - * don't use `unsigned`, we have typedefs for that - - * don't use `char` for anything but actual characters, use `int8`, `uint8` or `bool` - - * don't even think about using win32 types (`BYTE`, `WORD`, &c.) unless you're writing win32 specific code - - * declare pointers like `int *ptr;`, not `int* ptr;` - -* As for variable names, the original gta source code was not written in a uniform style, -but here are some observations: - - * many variables employ a form of hungarian notation, i.e.: - - * `m_` may be used for class member variables (mostly those that are considered private) - - * `ms_` for (mostly private) static members - - * `f` is a float, `i` or `n` is an integer, `b` is a boolean, `a` is an array - - * do *not* use `dw` for `DWORD` or so, we're not programming win32 - -* Generally, try to make the code look as if R* could have written it diff --git a/premake5.lua b/premake5.lua index fb408fe0..334c9c53 100644 --- a/premake5.lua +++ b/premake5.lua @@ -185,7 +185,7 @@ project "librw" includedirs {"/usr/local/include" } libdirs { "/opt/local/lib" } libdirs { "/usr/local/lib" } - + filter "platforms:*RW34*" flags { "ExcludeFromBuild" } filter {} diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index 486daebf..a4db2862 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -5,6 +5,7 @@ #include "AudioManager.h" #include "AudioScriptObject.h" #include "sampman.h" +#include "Font.h" #include "Text.h" #include "crossplatform.h" diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 7d2abce4..db7d7b66 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -3075,7 +3075,7 @@ void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle* pVehicle) void CCarCtrl::JoinCarWithRoadSystem(CVehicle* pVehicle) { pVehicle->AutoPilot.m_nPrevRouteNode = pVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_nNextRouteNode = 0; - pVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_nPreviousPathNodeInfo = pVehicle->AutoPilot.m_nNextPathNodeInfo = 0; + pVehicle->AutoPilot.m_nCurrentPathNodeInfo = pVehicle->AutoPilot.m_nPreviousPathNodeInfo = pVehicle->AutoPilot.m_nNextPathNodeInfo = 0; int nodeId = ThePaths.FindNodeClosestToCoorsFavourDirection(pVehicle->GetPosition(), 0, pVehicle->GetForward().x, pVehicle->GetForward().y); CPathNode* pNode = &ThePaths.m_pathNodes[nodeId]; int prevNodeId = -1; diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp index ea9fe160..84da59da 100644 --- a/src/control/Darkel.cpp +++ b/src/control/Darkel.cpp @@ -15,6 +15,9 @@ #include "Text.h" #include "Vehicle.h" #include "GameLogic.h" +#ifdef FIX_BUGS +#include "Replay.h" +#endif //--MIAMI: file done except TODO @@ -173,6 +176,10 @@ CDarkel::ReadStatus() void CDarkel::RegisterCarBlownUpByPlayer(CVehicle *vehicle) { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return; +#endif if (FrenzyOnGoing()) { int32 model = vehicle->GetModelIndex(); if (ModelToKill == FRENZY_ANY_CAR || ModelToKill == model || ModelToKill2 == model || ModelToKill3 == model || ModelToKill4 == model) { @@ -200,6 +207,10 @@ CDarkel::RegisterCarBlownUpByPlayer(CVehicle *vehicle) void CDarkel::RegisterKillByPlayer(CPed *victim, eWeaponType weapon, bool headshot) { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return; +#endif if (FrenzyOnGoing() && (weapon == WeaponType || weapon == WEAPONTYPE_EXPLOSION || weapon == WEAPONTYPE_UZI_DRIVEBY && WeaponType == WEAPONTYPE_UZI @@ -225,6 +236,10 @@ CDarkel::RegisterKillByPlayer(CPed *victim, eWeaponType weapon, bool headshot) void CDarkel::RegisterKillNotByPlayer(CPed* victim, eWeaponType weapontype) { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return; +#endif CStats::PeopleKilledByOthers++; } @@ -305,6 +320,11 @@ CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 mode void CDarkel::Update() { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return; +#endif + if (Status != KILLFRENZY_ONGOING) return; diff --git a/src/core/config.h b/src/core/config.h index 83834e20..3b9ae400 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -249,6 +249,9 @@ enum Config { #if !defined(RW_GL3) && defined(_WIN32) #define XINPUT #endif +#if !defined(_WIN32) && !defined(__SWITCH__) +#define DONT_TRUST_RECOGNIZED_JOYSTICKS // Then we'll only rely on GLFW gamepad DB, and expect user to enter Controller->Detect joysticks if his joystick isn't on that list. +#endif #define DETECT_PAD_INPUT_SWITCH // Adds automatic switch of pad related stuff between controller and kb/m #define KANGAROO_CHEAT #define RESTORE_ALLCARSHELI_CHEAT @@ -324,4 +327,4 @@ enum Config { #undef NO_ISLAND_LOADING #define PC_PARTICLE #define VC_PED_PORTS // To not process collisions always. But should be tested if that's really beneficial -#endif
\ No newline at end of file +#endif diff --git a/src/extras/ini_parser.hpp b/src/extras/ini_parser.hpp new file mode 100644 index 00000000..99acf1ee --- /dev/null +++ b/src/extras/ini_parser.hpp @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2013-2015 Denilson das Mercês Amorim <dma_2012@hotmail.com> + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ +#ifndef LINB_INI_PARSER_HPP +#define LINB_INI_PARSER_HPP + +/* + * STL-like INI Container + */ + +#include <string> // for std::string +#include <map> // for std::map +#include <cstdio> // for std::FILE +#include <algorithm> // for std::find_if +#include <functional> // for std::function + +namespace linb +{ + template< + class CharT = char, /* Not compatible with other type here, since we're using C streams */ + class StringType = std::basic_string<CharT>, + class KeyContainer = std::map<StringType, StringType>, + class SectionContainer = std::map<StringType, KeyContainer> + > class basic_ini + { + public: + typedef CharT char_type; + typedef StringType string_type; + typedef KeyContainer key_container; + typedef SectionContainer section_container; + + // Typedef container values types + typedef typename section_container::value_type value_type; + typedef typename section_container::key_type key_type; + typedef typename section_container::mapped_type mapped_type; + + // Typedef common types + typedef typename section_container::size_type size_type; + typedef typename section_container::difference_type difference_type; + + // Typedef iterators + typedef typename section_container::iterator iterator; + typedef typename section_container::const_iterator const_iterator; + typedef typename section_container::reverse_iterator reverse_iterator; + typedef typename section_container::const_reverse_iterator const_reverse_iterator; + + // typedef References and pointers + typedef typename section_container::reference reference; + typedef typename section_container::const_reference const_reference; + typedef typename section_container::pointer pointer; + typedef typename section_container::const_pointer const_pointer; + + private: + section_container data; + + public: + + basic_ini() + { } + + basic_ini(const char_type* filename) + { this->read_file(filename); } + + /* Iterator methods */ + iterator begin() + { return data.begin(); } + const_iterator begin() const + { return data.begin(); } + iterator end() + { return data.end(); } + const_iterator end() const + { return data.end(); } + const_iterator cbegin() const + { return data.cbegin(); } + const_iterator cend() const + { return data.cend(); } + + /* Reverse iterator methods */ + reverse_iterator rbegin() + { return data.rbegin(); } + const_reverse_iterator rbegin() const + { return data.rbegin(); } + reverse_iterator rend() + { return data.rend(); } + const_reverse_iterator rend() const + { return data.rend(); } + const_reverse_iterator crbegin() const + { return data.crbegin(); } + const_reverse_iterator crend() const + { return data.crend(); } + + /* Acessing index methods */ + mapped_type& operator[](const string_type& sect) + { return data[sect]; } + mapped_type& operator[](string_type&& sect) + { return data[std::forward<string_type>(sect)]; } + mapped_type& at( const string_type& sect) + { return data.at(sect); } + const mapped_type& at(const string_type& sect) const + { return data.at(sect); } + + /* Capacity information */ + bool empty() const + { return data.empty(); } + size_type size() const + { return data.size(); } + size_type max_size() const + { return data.max_size(); } + + /* Modifiers */ + void clear() + { return data.clear(); } + + /* Lookup */ + size_type count(const string_type& sect) + { return data.count(sect); } + iterator find(const string_type& sect) + { return data.find(sect); } + + /* Gets a value from the specified section & key, default_value is returned if the sect & key doesn't exist */ + string_type get(const string_type& sect, const key_type& key, const string_type& default_value) + { + auto it = this->find(sect); + if(it != this->end()) + { + auto itv = it->second.find(key); + if(itv != it->second.end()) + return itv->second; + } + return default_value; + } + + /* Sets the value of a value in the ini */ + void set(const string_type& sect, const key_type& key, const string_type& value) + { + (*this)[sect][key] = value; // no emplace since overwrite! + } + + /* Too lazy to continue this container... If you need more methods, just add it */ + + +#if 1 + bool read_file(const char_type* filename) + { + /* Using C stream in a STL-like container, funny? + */ + if(FILE* f = fopen(filename, "r")) + { + key_container* keys = nullptr; + char_type buf[2048]; + string_type line; + string_type key; + string_type value; + string_type null_string; + size_type pos; + + // Trims an string + auto trim = [](string_type& s, bool trimLeft, bool trimRight) -> string_type& + { + if(s.size()) + { + // Ignore UTF-8 BOM + while(s.size() >= 3 && s[0] == (char)(0xEF) && s[1] == (char)(0xBB) && s[2] == (char)(0xBF)) + s.erase(s.begin(), s.begin() + 3); + + if(trimLeft) + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::function<int(int)>(::isspace)))); + if(trimRight) + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::function<int(int)>(::isspace))).base(), s.end()); + } + return s; + }; + + // Start parsing + while(fgets(buf, sizeof(buf), f)) + { + // What a thing, reading into a char buffer and then putting in the string... + line = buf; + + // Find comment and remove anything after it from the line + if((pos = line.find_first_of(';')) != line.npos) + line.erase(pos); + + // Trim the string, and if it gets empty, skip this line + if(trim(line, true, true).empty()) + continue; + + // Find section name + if(line.front() == '[' && line.back() == ']') + { + pos = line.length() - 1; //line.find_first_of(']'); + if(pos != line.npos) + { + trim(key.assign(line, 1, pos-1), true, true); + keys = &data[std::move(key)]; // Create section + } + else + keys = nullptr; + } + else + { + // Find key and value positions + pos = line.find_first_of('='); + if(pos == line.npos) + { + // There's only the key + key = line; // No need for trim, line is already trimmed + value.clear(); + } + else + { + // There's the key and the value + trim(key.assign(line, 0, pos), false, true); // trim the right + trim(value.assign(line, pos + 1, line.npos), true, false); // trim the left + } + + // Put the key/value into the current keys object, or into the section "" if no section has been found + #if __cplusplus >= 201103L || _MSC_VER >= 1800 + (keys ? *keys : data[null_string]).emplace(std::move(key), std::move(value)); + #else + (keys ? *keys : data[null_string])[key] = value; + key.clear(); value.clear(); + #endif + } + } + + fclose(f); + return true; + } + return false; + } + + /* + * Dumps the content of this container into an ini file + */ + bool write_file(const char_type* filename) + { + if(FILE* f = fopen(filename, "w")) + { + bool first = true; + for(auto& sec : this->data) + { + fprintf(f, first? "[%s]\n" : "\n[%s]\n", sec.first.c_str()); + first = false; + for(auto& kv : sec.second) + { + if(kv.second.empty()) + fprintf(f, "%s\n", kv.first.c_str()); + else + fprintf(f, "%s = %s\n", kv.first.c_str(), kv.second.c_str()); + } + } + fclose(f); + return true; + } + return false; + } + + + /* + */ + bool load_file(const char_type* filename) + { + return read_file(filename); + } + + bool load_file(const StringType& filename) + { + return load_file(filename.c_str()); + } + + bool write_file(const StringType& filename) + { + return write_file(filename.c_str()); + } +#endif + + + + }; + + + /* Use default basic_ini + * + * Limitations: + * * Not unicode aware + * * Case sensitive + * * Sections must have unique keys + */ + typedef basic_ini<> ini; +} + +#endif + diff --git a/src/render/Font.cpp b/src/render/Font.cpp index c0cc333a..8deac7bf 100644 --- a/src/render/Font.cpp +++ b/src/render/Font.cpp @@ -5,6 +5,46 @@ #include "Font.h" #include "Timer.h" +void +AsciiToUnicode(const char *src, wchar *dst) +{ + while((*dst++ = (unsigned char)*src++) != '\0'); +} + +void +UnicodeStrcat(wchar *dst, wchar *append) +{ + UnicodeStrcpy(&dst[UnicodeStrlen(dst)], append); +} + +void +UnicodeStrcpy(wchar *dst, const wchar *src) +{ + while((*dst++ = *src++) != '\0'); +} + +int +UnicodeStrlen(const wchar *str) +{ + int len; + for(len = 0; *str != '\0'; len++, str++); + return len; +} + +void +UnicodeMakeUpperCase(wchar *dst, const wchar *src) //idk what to do with it, seems to be incorrect implementation by R* +{ + while (*src != '\0') { + if (*src < 'a' || *src > 'z') + *dst = *src; + else + *dst = *src - 32; + dst++; + src++; + } + *dst = '\0'; +} + CFontDetails CFont::Details; int16 CFont::NewLine; CSprite2d CFont::Sprite[MAX_FONTS]; diff --git a/src/render/Font.h b/src/render/Font.h index ca0ed7d0..47a39f73 100644 --- a/src/render/Font.h +++ b/src/render/Font.h @@ -1,5 +1,11 @@ #pragma once +void AsciiToUnicode(const char *src, wchar *dst); +void UnicodeStrcpy(wchar *dst, const wchar *src); +void UnicodeStrcat(wchar *dst, wchar *append); +int UnicodeStrlen(const wchar *str); +void UnicodeMakeUpperCase(wchar *dst, const wchar *src); + struct CFontDetails { CRGBA color; diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index b98b8243..18eecd95 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -11,6 +11,7 @@ #include "Clock.h" #include "Date.h" #include "FileMgr.h" +#include "Font.h" #include "Frontend.h" #include "GameLogic.h" #include "Gangs.h" diff --git a/src/save/PCSave.cpp b/src/save/PCSave.cpp index 6449d586..dd0926cf 100644 --- a/src/save/PCSave.cpp +++ b/src/save/PCSave.cpp @@ -3,6 +3,7 @@ #include "crossplatform.h" #include "FileMgr.h" +#include "Font.h" #ifdef MORE_LANGUAGES #include "Game.h" #endif diff --git a/src/skel/crossplatform.cpp b/src/skel/crossplatform.cpp index 6188992d..452ad9fa 100644 --- a/src/skel/crossplatform.cpp +++ b/src/skel/crossplatform.cpp @@ -84,6 +84,16 @@ void FileTimeToSystemTime(time_t* writeTime, SYSTEMTIME* out) { } #endif +// Because wchar length differs between platforms. +wchar* +AllocUnicode(const char* src) +{ + wchar *dst = (wchar*)malloc(strlen(src)*2 + 2); + wchar *i = dst; + while((*i++ = (unsigned char)*src++) != '\0'); + return dst; +} + // Funcs/features from Windows that we need on other platforms #ifndef _WIN32 char *strupr(char *s) { diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h index 69600385..1635781b 100644 --- a/src/skel/crossplatform.h +++ b/src/skel/crossplatform.h @@ -67,6 +67,10 @@ void CapturePad(RwInt32 padID); void joysChangeCB(int jid, int event); #endif +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS +extern char gSelectedJoystickName[128]; +#endif + enum eGameState { GS_START_UP = 0, diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 0f520cad..08e5c021 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -41,7 +41,6 @@ #include "AnimViewer.h" #include "Font.h" - #define MAX_SUBSYSTEMS (16) @@ -92,6 +91,11 @@ long _dwOperatingSystemVersion; #include <signal.h> #include <errno.h> #endif + +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS +char gSelectedJoystickName[128] = ""; +#endif + /* ***************************************************************************** */ @@ -429,6 +433,10 @@ psInitialize(void) _dwOperatingSystemVersion = OS_WIN95; } } +#else + _dwOperatingSystemVersion = OS_WINXP; // To fool other classes +#endif + #ifndef PS2_MENU @@ -438,6 +446,8 @@ psInitialize(void) #endif + +#ifdef _WIN32 MEMORYSTATUS memstats; GlobalMemoryStatus(&memstats); @@ -445,17 +455,22 @@ psInitialize(void) debug("Physical memory size %u\n", memstats.dwTotalPhys); debug("Available physical memory %u\n", memstats.dwAvailPhys); +#elif defined (__APPLE__) + uint64_t size = 0; + uint64_t page_size = 0; + size_t uint64_len = sizeof(uint64_t); + size_t ull_len = sizeof(unsigned long long); + sysctl((int[]){CTL_HW, HW_PAGESIZE}, 2, &page_size, &ull_len, NULL, 0); + sysctl((int[]){CTL_HW, HW_MEMSIZE}, 2, &size, &uint64_len, NULL, 0); + vm_statistics_data_t vm_stat; + mach_msg_type_number_t count = HOST_VM_INFO_COUNT; + host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stat, &count); + _dwMemAvailPhys = (uint64_t)(vm_stat.free_count * page_size); + debug("Physical memory size %llu\n", _dwMemAvailPhys); + debug("Available physical memory %llu\n", size); #else - -#ifndef PS2_MENU - -#ifdef GTA3_1_1_PATCH - FrontEndMenuManager.LoadSettings(); -#endif - -#endif #ifndef __APPLE__ - struct sysinfo systemInfo; + struct sysinfo systemInfo; sysinfo(&systemInfo); _dwMemAvailPhys = systemInfo.freeram; debug("Physical memory size %u\n", systemInfo.totalram); @@ -476,7 +491,8 @@ psInitialize(void) #endif _dwOperatingSystemVersion = OS_WINXP; // To fool other classes #endif - TheText.Unload(); + + TheText.Unload(); return TRUE; } @@ -843,35 +859,26 @@ void joysChangeCB(int jid, int event); bool IsThisJoystickBlacklisted(int i) { +#ifndef DONT_TRUST_RECOGNIZED_JOYSTICKS + return false; +#else if (glfwJoystickIsGamepad(i)) return false; const char* joyname = glfwGetJoystickName(i); - // this is just a keyboard and mouse - // Microsoft Microsoft® 2.4GHz Transceiver v8.0 Consumer Control - // Microsoft Microsoft® 2.4GHz Transceiver v8.0 System Control - if (strstr(joyname, "2.4GHz Transceiver")) - return true; - // COMPANY USB Device System Control - // COMPANY USB Device Consumer Control - if (strstr(joyname, "COMPANY USB")) - return true; - // i.e. Synaptics TM2438-005 - if (strstr(joyname, "Synaptics ")) - return true; - // i.e. ELAN Touchscreen - if (strstr(joyname, "ELAN ")) - return true; - // i.e. Primax Electronics, Ltd HP Wireless Keyboard Mouse Kit Consumer Control - if (strstr(joyname, "Keyboard")) - return true; + if (strncmp(joyname, gSelectedJoystickName, strlen(gSelectedJoystickName)) == 0) + return false; - return false; + return true; +#endif } void _InputInitialiseJoys() { + PSGLOBAL(joy1id) = -1; + PSGLOBAL(joy2id) = -1; + for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) { if (glfwJoystickPresent(i) && !IsThisJoystickBlacklisted(i)) { if (PSGLOBAL(joy1id) == -1) @@ -886,6 +893,9 @@ void _InputInitialiseJoys() if (PSGLOBAL(joy1id) != -1) { int count; glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS + strcpy(gSelectedJoystickName, glfwGetJoystickName(PSGLOBAL(joy1id))); +#endif ControlsManager.InitDefaultControlConfigJoyPad(count); } } @@ -2104,18 +2114,19 @@ void CapturePad(RwInt32 padID) void joysChangeCB(int jid, int event) { - if (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) - { - if (PSGLOBAL(joy1id) == -1) + if (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) { + if (PSGLOBAL(joy1id) == -1) { PSGLOBAL(joy1id) = jid; - else if (PSGLOBAL(joy2id) == -1) +#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS + strcpy(gSelectedJoystickName, glfwGetJoystickName(jid)); +#endif + } else if (PSGLOBAL(joy2id) == -1) PSGLOBAL(joy2id) = jid; - } - else if (event == GLFW_DISCONNECTED) - { - if (PSGLOBAL(joy1id) == jid) + + } else if (event == GLFW_DISCONNECTED) { + if (PSGLOBAL(joy1id) == jid) { PSGLOBAL(joy1id) = -1; - else if (PSGLOBAL(joy2id) == jid) + } else if (PSGLOBAL(joy2id) == jid) PSGLOBAL(joy2id) = -1; } } diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index b98d5710..1d1037af 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -3414,4 +3414,4 @@ int strncasecmp(const char *str1, const char *str2, size_t len) return _strnicmp(str1, str2, len); } #endif -#endif
\ No newline at end of file +#endif diff --git a/src/text/Text.cpp b/src/text/Text.cpp index 64f303eb..5adc576a 100644 --- a/src/text/Text.cpp +++ b/src/text/Text.cpp @@ -9,11 +9,12 @@ #include "Text.h" #include "Timer.h" +//--MIAMI: file done + static wchar WideErrorString[25]; CText TheText; -//--MIAMI: DONE CText::CText(void) { encoding = 'e'; @@ -23,7 +24,6 @@ CText::CText(void) memset(WideErrorString, 0, sizeof(WideErrorString)); } -//--MIAMI: DONE void CText::Load(void) { @@ -95,7 +95,6 @@ CText::Load(void) CFileMgr::SetDir(""); } -//--MIAMI: DONE void CText::Unload(void) { @@ -108,7 +107,6 @@ CText::Unload(void) memset(szMissionTableName, 0, sizeof(szMissionTableName)); } -//--MIAMI: DONE wchar* CText::Get(const char *key) { @@ -158,7 +156,6 @@ wchar FrenchUpperCaseTable[128] = { 253, 254, 255 }; -//--MIAMI: TODO (check tables) wchar CText::GetUpperCase(wchar c) { @@ -190,7 +187,6 @@ CText::GetUpperCase(wchar c) return c; } -//--MIAMI: DONE void CText::UpperCase(wchar *s) { @@ -200,27 +196,33 @@ CText::UpperCase(wchar *s) } } -//--MIAMI: DONE void CText::GetNameOfLoadedMissionText(char *outName) { strcpy(outName, szMissionTableName); } -//--MIAMI: DONE void CText::ReadChunkHeader(ChunkHeader *buf, int32 file, size_t *offset) { +#if DUMB + char *_buf = (char*)buf; + for (int i = 0; i < sizeof(ChunkHeader); i++) { + CFileMgr::Read(file, &_buf[i], 1); + (*offset)++; + } +#else // original code loops 8 times to read 1 byte with CFileMgr::Read, that's retarded CFileMgr::Read(file, (char*)buf, sizeof(ChunkHeader)); *offset += sizeof(ChunkHeader); +#endif } -//--MIAMI: DONE void CText::LoadMissionText(char *MissionTableName) { char filename[32]; + CMessages::ClearAllMessagesDisplayedByGame(); mission_keyArray.Unload(); mission_data.Unload(); @@ -306,7 +308,6 @@ CText::LoadMissionText(char *MissionTableName) } -//--MIAMI: DONE void CKeyArray::Load(size_t length, int file, size_t* offset) { @@ -318,14 +319,16 @@ CKeyArray::Load(size_t length, int file, size_t* offset) rawbytes = (char*)entries; #if DUMB - for (uint32 i = 0; i < length; i++) + for (uint32 i = 0; i < length; i++) { CFileMgr::Read(file, &rawbytes[i], 1); + (*offset)++; + } #else CFileMgr::Read(file, rawbytes, length); + *offset += length; #endif } -//--MIAMI: DONE void CKeyArray::Unload(void) { @@ -334,7 +337,6 @@ CKeyArray::Unload(void) numEntries = 0; } -//--MIAMI: DONE void CKeyArray::Update(wchar *chars) { @@ -345,7 +347,6 @@ CKeyArray::Update(wchar *chars) #endif } -//--MIAMI: DONE CKeyEntry* CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high) { @@ -366,7 +367,6 @@ CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 hi return nil; } -//--MIAMI: DONE wchar* #ifdef FIX_BUGS CKeyArray::Search(const char *key, wchar *data, uint8 *result) @@ -402,7 +402,6 @@ CKeyArray::Search(const char *key, uint8 *result) return WideErrorString; } -//--MIAMI: DONE void CData::Load(size_t length, int file, size_t * offset) { @@ -414,14 +413,16 @@ CData::Load(size_t length, int file, size_t * offset) rawbytes = (char*)chars; #if DUMB - for(uint32 i = 0; i < length; i++) + for(uint32 i = 0; i < length; i++){ CFileMgr::Read(file, &rawbytes[i], 1); + (*offset)++; + } #else CFileMgr::Read(file, rawbytes, length); + *offset += length; #endif } -//--MIAMI: DONE void CData::Unload(void) { @@ -430,22 +431,31 @@ CData::Unload(void) numChars = 0; } -//--MIAMI: DONE void CMissionTextOffsets::Load(size_t table_size, int file, size_t *offset, int) { +#if DUMB + size_t num_of_entries = table_size / sizeof(CMissionTextOffsets::Entry); + for (size_t mi = 0; mi < num_of_entries; mi++) { + for (uint32 i = 0; i < sizeof(data[mi].szMissionName); i++) { + CFileMgr::Read(file, &data[i].szMissionName[i], 1); + (*offset)++; + } + char* _buf = (char*)&data[mi].offset; + for (uint32 i = 0; i < sizeof(data[mi].offset); i++) { + CFileMgr::Read(file, &_buf[i], 1); + (*offset)++; + } + } + size = (uint16)num_of_entries; +#else // not exact VC code but smaller and better :P // You can make this size_t if you want to exceed 32-bit boundaries, everything else should be ready. size = (uint16) (table_size / sizeof(CMissionTextOffsets::Entry)); CFileMgr::Read(file, (char*)data, sizeof(CMissionTextOffsets::Entry) * size); *offset += sizeof(CMissionTextOffsets::Entry) * size; -} - -void -AsciiToUnicode(const char *src, wchar *dst) -{ - while((*dst++ = (unsigned char)*src++) != '\0'); +#endif } char* @@ -460,8 +470,29 @@ UnicodeToAscii(wchar *src) if(*src < 128) #endif aStr[len] = *src; - else - aStr[len] = '#'; + // convert to CP1252 + else if(*src <= 131) + aStr[len] = *src + 64; + else if (*src <= 141) + aStr[len] = *src + 66; + else if (*src <= 145) + aStr[len] = *src + 68; + else if (*src <= 149) + aStr[len] = *src + 71; + else if (*src <= 154) + aStr[len] = *src + 73; + else if (*src <= 164) + aStr[len] = *src + 75; + else if (*src <= 168) + aStr[len] = *src + 77; + else if (*src <= 204) + aStr[len] = *src + 80; + else switch (*src) { + case 205: aStr[len] = 209; break; + case 206: aStr[len] = 241; break; + case 207: aStr[len] = 191; break; + default: aStr[len] = '#'; break; + } aStr[len] = '\0'; return aStr; } @@ -471,7 +502,7 @@ UnicodeToAsciiForSaveLoad(wchar *src) { static char aStr[256]; int len; - for(len = 0; *src != '\0' && len < 256-1; len++, src++) + for(len = 0; *src != '\0' && len < 256; len++, src++) if(*src < 256) aStr[len] = *src; else @@ -485,7 +516,7 @@ UnicodeToAsciiForMemoryCard(wchar *src) { static char aStr[256]; int len; - for(len = 0; *src != '\0' && len < 256-1; len++, src++) + for(len = 0; *src != '\0' && len < 256; len++, src++) if(*src < 256) aStr[len] = *src; else @@ -495,41 +526,7 @@ UnicodeToAsciiForMemoryCard(wchar *src) } void -UnicodeMakeUpperCase(wchar *dst, wchar *src) //idk what to do with it, seems to be incorrect implementation by R* -{ - while (*src != '\0') { - if (*src < 'a' || *src > 'z') - *dst = *src; - else - *dst = *src - 32; - dst++; - src++; - } - *dst = '\0'; -} - -void -UnicodeStrcpy(wchar *dst, const wchar *src) -{ - while((*dst++ = *src++) != '\0'); -} - -void -UnicodeStrcat(wchar *dst, wchar *append) -{ - UnicodeStrcpy(&dst[UnicodeStrlen(dst)], append); -} - -int -UnicodeStrlen(const wchar *str) -{ - int len; - for(len = 0; *str != '\0'; len++, str++); - return len; -} - -void TextCopy(wchar *dst, const wchar *src) { while((*dst++ = *src++) != '\0'); -}
\ No newline at end of file +} diff --git a/src/text/Text.h b/src/text/Text.h index 0bad9a83..33dc313e 100644 --- a/src/text/Text.h +++ b/src/text/Text.h @@ -1,14 +1,9 @@ #pragma once -void AsciiToUnicode(const char *src, wchar *dst); char *UnicodeToAscii(wchar *src); char *UnicodeToAsciiForSaveLoad(wchar *src); char *UnicodeToAsciiForMemoryCard(wchar *src); -void UnicodeStrcpy(wchar *dst, const wchar *src); -void UnicodeStrcat(wchar *dst, wchar *append); -int UnicodeStrlen(const wchar *str); void TextCopy(wchar *dst, const wchar *src); -void UnicodeMakeUpperCase(wchar *dst, wchar *src); struct CKeyEntry { diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 6e86dbe4..994f3c99 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -1303,7 +1303,7 @@ CVehicle::InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage } } #ifdef FIX_BUGS // removing dumb case when shooting police car in player's own garage gives wanted level - if (GetModelIndex() == MI_POLICE && damagedBy == FindPlayerPed() && !bHasBeenOwnedByPlayer) + if (GetModelIndex() == MI_POLICE && damagedBy == FindPlayerPed() && damagedBy != nil && !bHasBeenOwnedByPlayer) #else if (GetModelIndex() == MI_POLICE && damagedBy == FindPlayerPed()) #endif |