Merge branch 'master' into master

This commit is contained in:
erorcun 2020-10-04 22:12:57 +03:00 committed by GitHub
commit fae97f29c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 248 additions and 143 deletions

View File

@ -1,15 +1,44 @@
language: cpp language: cpp
os: linux
dist: focal dist: focal
matrix: os: linux
jobs:
include: include:
- env: TARGET=release_linux-amd64-librw_gl3_glfw-oal - env: TARGET=release_linux-amd64-librw_gl3_glfw-oal
os: linux
- env: TARGET=debug_linux-amd64-librw_gl3_glfw-oal - env: TARGET=debug_linux-amd64-librw_gl3_glfw-oal
os: linux
- env: TARGET=release_macosx-amd64-librw_gl3_glfw-oal PREMAKE5=premake-5.0.0-alpha15
compiler: clang
os: osx
osx_image: xcode12u
- env: TARGET=debug_macosx-amd64-librw_gl3_glfw-oal PREMAKE5=premake-5.0.0-alpha15
compiler: clang
os: osx
osx_image: xcode12u
addons:
apt:
update: true
packages:
- linux-libc-dev
- libopenal-dev
- libglew-dev
- libglfw3-dev
- libsndfile1-dev
- libmpg123-dev
- gcc-8-multilib
- g++-8-multilib
homebrew:
packages:
- libsndfile
- mpg123
- glew
- glfw
- openal-soft
script: script:
- sudo apt-get update
- sudo apt-get -y install linux-libc-dev libopenal-dev libglew-dev libglfw3-dev libsndfile1-dev libmpg123-dev gcc-8-multilib g++-8-multilib
- mkdir -p "$TRAVIS_BUILD_DIR/build" - mkdir -p "$TRAVIS_BUILD_DIR/build"
- cd "$TRAVIS_BUILD_DIR" - cd "$TRAVIS_BUILD_DIR"
- ./premake5Linux --with-librw gmake2 - if [ "$TRAVIS_OS_NAME" = linux ]; then ./premake5Linux --with-librw gmake2; fi
- if [ "$TRAVIS_OS_NAME" = osx ]; then curl -L -o "${PREMAKE5}.zip" "https://github.com/premake/premake-core/releases/download/v5.0.0-alpha15/${PREMAKE5}-src.zip" && unzip -q "${PREMAKE5}.zip" && cd "$PREMAKE5" && make -f Bootstrap.mak osx && cd .. && "./${PREMAKE5}/bin/release/premake5" --with-librw gmake2; fi
- cd build - cd build
- CC=gcc-8 CXX=g++-8 make config=$TARGET -j4 verbose=1 - if [ "$TRAVIS_OS_NAME" = linux ]; then env CC=gcc-8 CXX=g++-8 make config=$TARGET -j4 verbose=1; fi
- if [ "$TRAVIS_OS_NAME" = osx ]; then make config=$TARGET -j4 verbose=1; fi

107
CODING_STYLE.md Normal file
View File

@ -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

111
README.md
View File

@ -21,8 +21,7 @@ such that we have a working game at all times.
## Preparing the environment for building ## Preparing the environment for building
- Clone the repo. - Clone the repo using the argument `--recursive`.
- Run `git submodule init` and `git submodule update`.
- Point GTA_III_RE_DIR environment variable to GTA3 root folder. - Point GTA_III_RE_DIR environment variable to GTA3 root folder.
- Run premake - Run premake
- On Windows: one of the `premake-vsXXXX.cmd` variants on root folder - 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. > :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 ## 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) ### Unreversed / incomplete classes (at least the ones we know)
The following classes have only unused or practically unused code left: The following classes have only unused or practically unused code left:
@ -44,110 +44,3 @@ CCullZone - only mobile stuff
CCullZones - 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

Binary file not shown.

View File

@ -85,6 +85,12 @@ workspace "re3"
"bsd-amd64-librw_gl3_glfw-oal" "bsd-amd64-librw_gl3_glfw-oal"
} }
filter { "system:macosx" }
platforms {
"macosx-arm64-librw_gl3_glfw-oal",
"macosx-amd64-librw_gl3_glfw-oal",
}
filter "configurations:Debug" filter "configurations:Debug"
defines { "DEBUG" } defines { "DEBUG" }
@ -101,6 +107,9 @@ workspace "re3"
filter { "platforms:bsd*" } filter { "platforms:bsd*" }
system "bsd" system "bsd"
filter { "platforms:macosx*" }
system "macosx"
filter { "platforms:*x86*" } filter { "platforms:*x86*" }
architecture "x86" architecture "x86"
@ -110,6 +119,12 @@ workspace "re3"
filter { "platforms:*arm*" } filter { "platforms:*arm*" }
architecture "ARM" architecture "ARM"
filter { "platforms:macosx-arm64-*" }
buildoptions { "-target", "arm64-apple-macos11", "-std=gnu++14" }
filter { "platforms:macosx-amd64-*" }
buildoptions { "-target", "x86_64-apple-macos10.12", "-std=gnu++14" }
filter { "platforms:*librw_d3d9*" } filter { "platforms:*librw_d3d9*" }
defines { "RW_D3D9" } defines { "RW_D3D9" }
if(not _OPTIONS["with-librw"]) then if(not _OPTIONS["with-librw"]) then
@ -163,6 +178,13 @@ project "librw"
includedirs { "/usr/local/include" } includedirs { "/usr/local/include" }
libdirs { "/usr/local/lib" } libdirs { "/usr/local/lib" }
filter "platforms:macosx*"
-- Support MacPorts and Homebrew
includedirs { "/opt/local/include" }
includedirs {"/usr/local/include" }
libdirs { "/opt/local/lib" }
libdirs { "/usr/local/lib" }
filter "platforms:*RW33*" filter "platforms:*RW33*"
flags { "ExcludeFromBuild" } flags { "ExcludeFromBuild" }
filter {} filter {}
@ -277,6 +299,11 @@ project "re3"
filter "platforms:bsd*oal" filter "platforms:bsd*oal"
links { "openal", "mpg123", "sndfile", "pthread" } links { "openal", "mpg123", "sndfile", "pthread" }
filter "platforms:macosx*oal"
links { "openal", "mpg123", "sndfile", "pthread" }
includedirs { "/usr/local/opt/openal-soft/include" }
libdirs { "/usr/local/opt/openal-soft/lib" }
if _OPTIONS["with-opus"] then if _OPTIONS["with-opus"] then
filter {} filter {}
links { "libogg" } links { "libogg" }
@ -329,3 +356,11 @@ project "re3"
links { "GL", "GLEW", "glfw", "sysinfo" } links { "GL", "GLEW", "glfw", "sysinfo" }
includedirs { "/usr/local/include" } includedirs { "/usr/local/include" }
libdirs { "/usr/local/lib" } libdirs { "/usr/local/lib" }
filter "platforms:macosx*gl3_glfw*"
links { "GLEW", "glfw" }
linkoptions { "-framework OpenGL" }
includedirs { "/opt/local/include" }
includedirs { "/usr/local/include" }
libdirs { "/opt/local/lib" }
libdirs { "/usr/local/lib" }

View File

@ -2578,7 +2578,7 @@ void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle* pVehicle)
void CCarCtrl::JoinCarWithRoadSystem(CVehicle* pVehicle) void CCarCtrl::JoinCarWithRoadSystem(CVehicle* pVehicle)
{ {
pVehicle->AutoPilot.m_nPrevRouteNode = pVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_nNextRouteNode = 0; 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); int nodeId = ThePaths.FindNodeClosestToCoorsFavourDirection(pVehicle->GetPosition(), 0, pVehicle->GetForward().x, pVehicle->GetForward().y);
CPathNode* pNode = &ThePaths.m_pathNodes[nodeId]; CPathNode* pNode = &ThePaths.m_pathNodes[nodeId];
int prevNodeId = -1; int prevNodeId = -1;

View File

@ -36,9 +36,9 @@ struct CdReadInfo
#ifdef ONE_THREAD_PER_CHANNEL #ifdef ONE_THREAD_PER_CHANNEL
int8 nThreadStatus; // 0: created 1:initalized 2:abort now int8 nThreadStatus; // 0: created 1:initalized 2:abort now
pthread_t pChannelThread; pthread_t pChannelThread;
sem_t pStartSemaphore; sem_t *pStartSemaphore;
#endif #endif
sem_t pDoneSemaphore; // used for CdStreamSync sem_t *pDoneSemaphore; // used for CdStreamSync
int32 hFile; int32 hFile;
}; };
@ -51,7 +51,7 @@ char *gImgNames[MAX_CDIMAGES];
#ifndef ONE_THREAD_PER_CHANNEL #ifndef ONE_THREAD_PER_CHANNEL
pthread_t _gCdStreamThread; pthread_t _gCdStreamThread;
sem_t gCdStreamSema; // released when we have new thing to read(so channel is set) sem_t *gCdStreamSema; // released when we have new thing to read(so channel is set)
int8 gCdStreamThreadStatus; // 0: created 1:initalized 2:abort now int8 gCdStreamThreadStatus; // 0: created 1:initalized 2:abort now
Queue gChannelRequestQ; Queue gChannelRequestQ;
bool _gbCdStreamOverlapped; bool _gbCdStreamOverlapped;
@ -76,11 +76,11 @@ CdStreamInitThread(void)
gChannelRequestQ.tail = 0; gChannelRequestQ.tail = 0;
gChannelRequestQ.size = gNumChannels + 1; gChannelRequestQ.size = gNumChannels + 1;
ASSERT(gChannelRequestQ.items != nil ); ASSERT(gChannelRequestQ.items != nil );
status = sem_init(&gCdStreamSema, 0, 0); gCdStreamSema = sem_open("/semaphore_cd_stream", O_CREAT, 0644, 1);
#endif #endif
if (status == -1) { if (gCdStreamSema == SEM_FAILED) {
CDTRACE("failed to create stream semaphore"); CDTRACE("failed to create stream semaphore");
ASSERT(0); ASSERT(0);
return; return;
@ -91,18 +91,18 @@ CdStreamInitThread(void)
{ {
for ( int32 i = 0; i < gNumChannels; i++ ) for ( int32 i = 0; i < gNumChannels; i++ )
{ {
status = sem_init(&gpReadInfo[i].pDoneSemaphore, 0, 0); gpReadInfo[i].pDoneSemaphore = sem_open("/semaphore_done", O_CREAT, 0644, 1);
if (status == -1) if (gpReadInfo[i].pDoneSemaphore == SEM_FAILED)
{ {
CDTRACE("failed to create sync semaphore"); CDTRACE("failed to create sync semaphore");
ASSERT(0); ASSERT(0);
return; return;
} }
#ifdef ONE_THREAD_PER_CHANNEL #ifdef ONE_THREAD_PER_CHANNEL
status = sem_init(&gpReadInfo[i].pStartSemaphore, 0, 0); gpReadInfo[i].pStartSemaphore = sem_open("/semaphore_start", O_CREAT, 0644, 1);
if (status == -1) if (gpReadInfo[i].pStartSemaphore == SEM_FAILED)
{ {
CDTRACE("failed to create start semaphore"); CDTRACE("failed to create start semaphore");
ASSERT(0); ASSERT(0);
@ -135,7 +135,7 @@ CdStreamInitThread(void)
return; return;
} }
#else #else
debug("Using seperate streaming threads for each channel\n"); debug("Using separate streaming threads for each channel\n");
#endif #endif
} }
@ -163,7 +163,7 @@ CdStreamInit(int32 numChannels)
debug("Using no buffered loading for streaming\n"); debug("Using no buffered loading for streaming\n");
} }
*/ */
void *pBuffer = (void *)RwMallocAlign(CDSTREAM_SECTOR_SIZE, fsInfo.f_bsize); void *pBuffer = (void *)RwMallocAlign(CDSTREAM_SECTOR_SIZE, (RwUInt32)fsInfo.f_bsize);
ASSERT( pBuffer != nil ); ASSERT( pBuffer != nil );
gNumImages = 0; gNumImages = 0;
@ -205,7 +205,7 @@ GetGTA3ImgSize(void)
return 0; return 0;
} }
ok: ok:
return statbuf.st_size; return (uint32)statbuf.st_size;
} }
void void
@ -214,7 +214,7 @@ CdStreamShutdown(void)
// Destroying semaphores and free(gpReadInfo) will be done at threads // Destroying semaphores and free(gpReadInfo) will be done at threads
#ifndef ONE_THREAD_PER_CHANNEL #ifndef ONE_THREAD_PER_CHANNEL
gCdStreamThreadStatus = 2; gCdStreamThreadStatus = 2;
sem_post(&gCdStreamSema); sem_post(gCdStreamSema);
#endif #endif
#ifdef ONE_THREAD_PER_CHANNEL #ifdef ONE_THREAD_PER_CHANNEL
@ -254,7 +254,7 @@ CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size)
#ifndef ONE_THREAD_PER_CHANNEL #ifndef ONE_THREAD_PER_CHANNEL
AddToQueue(&gChannelRequestQ, channel); AddToQueue(&gChannelRequestQ, channel);
if ( sem_post(&gCdStreamSema) != 0 ) if ( sem_post(gCdStreamSema) != 0 )
printf("Signal Sema Error\n"); printf("Signal Sema Error\n");
#else #else
if ( sem_post(&gpReadInfo[channel].pStartSemaphore) != 0 ) if ( sem_post(&gpReadInfo[channel].pStartSemaphore) != 0 )
@ -332,7 +332,7 @@ CdStreamSync(int32 channel)
{ {
pChannel->bLocked = true; pChannel->bLocked = true;
sem_wait(&pChannel->pDoneSemaphore); sem_wait(pChannel->pDoneSemaphore);
} }
pChannel->bReading = false; pChannel->bReading = false;
@ -383,7 +383,7 @@ void *CdStreamThread(void *param)
#ifndef ONE_THREAD_PER_CHANNEL #ifndef ONE_THREAD_PER_CHANNEL
while (gCdStreamThreadStatus != 2) { while (gCdStreamThreadStatus != 2) {
sem_wait(&gCdStreamSema); sem_wait(gCdStreamSema);
int32 channel = GetFirstInQueue(&gChannelRequestQ); int32 channel = GetFirstInQueue(&gChannelRequestQ);
#else #else
int channel = *((int*)param); int channel = *((int*)param);
@ -437,20 +437,24 @@ void *CdStreamThread(void *param)
if ( pChannel->bLocked ) if ( pChannel->bLocked )
{ {
sem_post(&pChannel->pDoneSemaphore); sem_post(pChannel->pDoneSemaphore);
} }
pChannel->bReading = false; pChannel->bReading = false;
} }
#ifndef ONE_THREAD_PER_CHANNEL #ifndef ONE_THREAD_PER_CHANNEL
for ( int32 i = 0; i < gNumChannels; i++ ) for ( int32 i = 0; i < gNumChannels; i++ )
{ {
sem_destroy(&gpReadInfo[i].pDoneSemaphore); sem_close(gpReadInfo[i].pDoneSemaphore);
sem_unlink("/semaphore_done");
} }
sem_destroy(&gCdStreamSema); sem_close(gCdStreamSema);
sem_unlink("/semaphore_cd_stream");
free(gChannelRequestQ.items); free(gChannelRequestQ.items);
#else #else
sem_destroy(&gpReadInfo[channel].pStartSemaphore); sem_close(gpReadInfo[channel].pStartSemaphore);
sem_destroy(&gpReadInfo[channel].pDoneSemaphore); sem_unlink("/semaphore_start");
sem_close(gpReadInfo[channel].pDoneSemaphore);
sem_unlink("/semaphore_done");
#endif #endif
free(gpReadInfo); free(gpReadInfo);
pthread_exit(nil); pthread_exit(nil);

View File

@ -80,7 +80,12 @@ DWORD _dwOperatingSystemVersion;
#include "resource.h" #include "resource.h"
#else #else
long _dwOperatingSystemVersion; long _dwOperatingSystemVersion;
#ifndef __APPLE__
#include <sys/sysinfo.h> #include <sys/sysinfo.h>
#else
#include <mach/mach_host.h>
#include <sys/sysctl.h>
#endif
#include <stddef.h> #include <stddef.h>
#include <locale.h> #include <locale.h>
#include <signal.h> #include <signal.h>
@ -446,15 +451,27 @@ psInitialize(void)
debug("Physical memory size %u\n", memstats.dwTotalPhys); debug("Physical memory size %u\n", memstats.dwTotalPhys);
debug("Available physical memory %u\n", memstats.dwAvailPhys); 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 #else
struct sysinfo systemInfo; struct sysinfo systemInfo;
sysinfo(&systemInfo); sysinfo(&systemInfo);
_dwMemAvailPhys = systemInfo.freeram; _dwMemAvailPhys = systemInfo.freeram;
debug("Physical memory size %u\n", systemInfo.totalram); debug("Physical memory size %u\n", systemInfo.totalram);
debug("Available physical memory %u\n", systemInfo.freeram); debug("Available physical memory %u\n", systemInfo.freeram);
#endif #endif
TheText.Unload(); TheText.Unload();
return TRUE; return TRUE;

View File

@ -8002,6 +8002,26 @@ HIGH
[FEM_2PR] [FEM_2PR]
PS2 ALPHA TEST PS2 ALPHA TEST
[FEC_FRC]
FREE CAM
{ Linux joy detection }
[FEC_JOD]
DETECT JOYSTICK
[FEC_JPR]
Press any key on the joystick of your choice that you want to use on the game, and it will be selected.
[FEC_JDE]
Detected joystick
{ mission restart }
[FET_RMS]
REPLAY MISSION
[FESZ_RM]
RETRY?
{ end of file } { end of file }
[DUMMY] [DUMMY]