diff options
-rw-r--r-- | .travis.yml | 43 | ||||
-rw-r--r-- | premake5.lua | 38 | ||||
-rw-r--r-- | src/control/Garages.cpp | 2 | ||||
-rw-r--r-- | src/core/CdStreamPosix.cpp | 294 | ||||
-rw-r--r-- | src/core/FileLoader.cpp | 4 | ||||
-rw-r--r-- | src/core/FileMgr.cpp | 10 | ||||
-rw-r--r-- | src/core/Streaming.cpp | 134 | ||||
-rw-r--r-- | src/core/common.h | 2 | ||||
-rw-r--r-- | src/skel/glfw/glfw.cpp | 25 | ||||
-rw-r--r-- | src/vehicles/CarGen.cpp | 9 | ||||
-rw-r--r-- | src/vehicles/Vehicle.h | 2 | ||||
-rw-r--r-- | src/weapons/WeaponInfo.cpp | 44 | ||||
m--------- | vendor/librw | 0 |
13 files changed, 421 insertions, 186 deletions
diff --git a/.travis.yml b/.travis.yml index 51ef58eb..c124a9f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,44 @@ language: cpp -os: linux dist: focal -matrix: +os: linux +jobs: include: - env: TARGET=release_linux-amd64-librw_gl3_glfw-oal + os: linux - 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: - - 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" - cd "$TRAVIS_BUILD_DIR" - - ./premake5Linux --with-librw gmake2 - - cd build - - CC=gcc-8 CXX=g++-8 make config=$TARGET -j4 verbose=1 + - 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 + - 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 diff --git a/premake5.lua b/premake5.lua index b61a9c4c..fb408fe0 100644 --- a/premake5.lua +++ b/premake5.lua @@ -84,6 +84,12 @@ workspace "reVC" platforms { "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" defines { "DEBUG" } @@ -100,6 +106,9 @@ workspace "reVC" filter { "platforms:bsd*" } system "bsd" + + filter { "platforms:macosx*" } + system "macosx" filter { "platforms:*x86*" } architecture "x86" @@ -109,6 +118,13 @@ workspace "reVC" filter { "platforms:*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*" } defines { "RW_D3D9" } @@ -162,7 +178,14 @@ project "librw" filter "platforms:bsd*" includedirs { "/usr/local/include" } 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:*RW34*" flags { "ExcludeFromBuild" } filter {} @@ -277,6 +300,11 @@ project "reVC" filter "platforms:bsd*oal" 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 filter {} @@ -330,3 +358,11 @@ project "reVC" links { "GL", "GLEW", "glfw", "sysinfo" } includedirs { "/usr/local/include" } 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" } diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 290bacad..dc07d142 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1462,7 +1462,7 @@ void CGarage::UpdateCrusherShake(float X, float Y) } // This is dumb but there is no way to avoid goto. What was there originally even? -static bool DoINeedToRefreshPointer(CEntity * pDoor, bool bIsDummy, int8 nIndex) +static bool DoINeedToRefreshPointer(CEntity * pDoor, bool bIsDummy, uint8 nIndex) { bool bNeedToFindDoorEntities = false; if (pDoor) { diff --git a/src/core/CdStreamPosix.cpp b/src/core/CdStreamPosix.cpp index e114a29a..04a5de4b 100644 --- a/src/core/CdStreamPosix.cpp +++ b/src/core/CdStreamPosix.cpp @@ -34,11 +34,11 @@ struct CdReadInfo bool bReading; int32 nStatus; #ifdef ONE_THREAD_PER_CHANNEL - int8 nThreadStatus; // 0: created 1:initalized 2:abort now - pthread_t pChannelThread; - sem_t pStartSemaphore; + int8 nThreadStatus; // 0: created 1:priority set up 2:abort now + pthread_t pChannelThread; + sem_t *pStartSemaphore; #endif - sem_t pDoneSemaphore; // used for CdStreamSync + sem_t *pDoneSemaphore; // used for CdStreamSync int32 hFile; }; @@ -51,8 +51,8 @@ char *gImgNames[MAX_CDIMAGES]; #ifndef ONE_THREAD_PER_CHANNEL pthread_t _gCdStreamThread; -sem_t gCdStreamSema; // released when we have new thing to read(so channel is set) -int8 gCdStreamThreadStatus; // 0: created 1:initalized 2:abort now +sem_t *gCdStreamSema; // released when we have new thing to read(so channel is set) +int8 gCdStreamThreadStatus; // 0: created 1:priority set up 2:abort now Queue gChannelRequestQ; bool _gbCdStreamOverlapped; #endif @@ -69,49 +69,50 @@ void CdStreamInitThread(void) { int status; - + char semName[20]; #ifndef ONE_THREAD_PER_CHANNEL gChannelRequestQ.items = (int32 *)calloc(gNumChannels + 1, sizeof(int32)); gChannelRequestQ.head = 0; gChannelRequestQ.tail = 0; gChannelRequestQ.size = gNumChannels + 1; ASSERT(gChannelRequestQ.items != nil ); - status = sem_init(&gCdStreamSema, 0, 0); -#endif + gCdStreamSema = sem_open("/semaphore_cd_stream", O_CREAT, 0644, 1); - if (status == -1) { + if (gCdStreamSema == SEM_FAILED) { CDTRACE("failed to create stream semaphore"); ASSERT(0); return; } - +#endif if ( gNumChannels > 0 ) { for ( int32 i = 0; i < gNumChannels; i++ ) { - status = sem_init(&gpReadInfo[i].pDoneSemaphore, 0, 0); + sprintf(semName,"/semaphore_done%d",i); + gpReadInfo[i].pDoneSemaphore = sem_open(semName, O_CREAT, 0644, 1); - if (status == -1) + if (gpReadInfo[i].pDoneSemaphore == SEM_FAILED) { CDTRACE("failed to create sync semaphore"); ASSERT(0); return; } #ifdef ONE_THREAD_PER_CHANNEL - status = sem_init(&gpReadInfo[i].pStartSemaphore, 0, 0); + sprintf(semName,"/semaphore_start%d",i); + gpReadInfo[i].pStartSemaphore = sem_open(semName, O_CREAT, 0644, 1); - if (status == -1) + if (gpReadInfo[i].pStartSemaphore == SEM_FAILED) { CDTRACE("failed to create start semaphore"); ASSERT(0); return; } - gpReadInfo[i].nThreadStatus = 0; + gpReadInfo[i].nThreadStatus = 0; int *channelI = (int*)malloc(sizeof(int)); *channelI = i; - status = pthread_create(&gpReadInfo[i].pChannelThread, NULL, CdStreamThread, (void*)channelI); + status = pthread_create(&gpReadInfo[i].pChannelThread, NULL, CdStreamThread, (void*)channelI); if (status == -1) { @@ -124,32 +125,32 @@ CdStreamInitThread(void) } #ifndef ONE_THREAD_PER_CHANNEL - debug("Using one streaming thread for all channels\n"); - status = pthread_create(&_gCdStreamThread, NULL, CdStreamThread, nil); - gCdStreamThreadStatus = 0; - - if (status == -1) - { - CDTRACE("failed to create sync thread"); - ASSERT(0); - return; - } + debug("Using one streaming thread for all channels\n"); + gCdStreamThreadStatus = 0; + status = pthread_create(&_gCdStreamThread, NULL, CdStreamThread, nil); + + if (status == -1) + { + CDTRACE("failed to create sync thread"); + ASSERT(0); + return; + } #else - debug("Using seperate streaming threads for each channel\n"); + debug("Using separate streaming threads for each channel\n"); #endif } void CdStreamInit(int32 numChannels) { - struct statvfs fsInfo; - - if((statvfs("models/gta3.img", &fsInfo)) < 0) - { - CDTRACE("can't get filesystem info"); - ASSERT(0); - return; - } + struct statvfs fsInfo; + + if((statvfs("models/gta3.img", &fsInfo)) < 0) + { + CDTRACE("can't get filesystem info"); + ASSERT(0); + return; + } #ifdef __linux__ _gdwCdStreamFlags = O_RDONLY | O_NOATIME; #else @@ -163,7 +164,7 @@ CdStreamInit(int32 numChannels) 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 ); gNumImages = 0; @@ -185,27 +186,27 @@ uint32 GetGTA3ImgSize(void) { ASSERT( gImgFiles[0] > 0 ); - struct stat statbuf; + struct stat statbuf; - char path[PATH_MAX]; - realpath(gImgNames[0], path); - if (stat(path, &statbuf) == -1) { + char path[PATH_MAX]; + realpath(gImgNames[0], path); + if (stat(path, &statbuf) == -1) { // Try case-insensitivity char* real = casepath(gImgNames[0], false); if (real) { realpath(real, path); free(real); - if (stat(path, &statbuf) != -1) + if (stat(path, &statbuf) != -1) goto ok; } - CDTRACE("can't get size of gta3.img"); - ASSERT(0); - return 0; - } -ok: - return statbuf.st_size; + CDTRACE("can't get size of gta3.img"); + ASSERT(0); + return 0; + } + ok: + return (uint32)statbuf.st_size; } void @@ -213,15 +214,13 @@ CdStreamShutdown(void) { // Destroying semaphores and free(gpReadInfo) will be done at threads #ifndef ONE_THREAD_PER_CHANNEL - gCdStreamThreadStatus = 2; - sem_post(&gCdStreamSema); -#endif - -#ifdef ONE_THREAD_PER_CHANNEL - for ( int32 i = 0; i < gNumChannels; i++ ) { - gpReadInfo[i].nThreadStatus = 2; - sem_post(&gpReadInfo[i].pStartSemaphore); - } + gCdStreamThreadStatus = 2; + sem_post(gCdStreamSema); +#else + for ( int32 i = 0; i < gNumChannels; i++ ) { + gpReadInfo[i].nThreadStatus = 2; + sem_post(gpReadInfo[i].pStartSemaphore); + } #endif } @@ -243,25 +242,28 @@ CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size) pChannel->hFile = hImage - 1; - if ( pChannel->nSectorsToRead != 0 || pChannel->bReading ) - return STREAM_NONE; + if ( pChannel->nSectorsToRead != 0 || pChannel->bReading ) { + flushStream[channel] = 1; + CdStreamSync(channel); + //return STREAM_NONE; + } - pChannel->nStatus = STREAM_NONE; - pChannel->nSectorOffset = _GET_OFFSET(offset); - pChannel->nSectorsToRead = size; - pChannel->pBuffer = buffer; - pChannel->bLocked = 0; + pChannel->nStatus = STREAM_NONE; + pChannel->nSectorOffset = _GET_OFFSET(offset); + pChannel->nSectorsToRead = size; + pChannel->pBuffer = buffer; + pChannel->bLocked = 0; #ifndef ONE_THREAD_PER_CHANNEL - AddToQueue(&gChannelRequestQ, channel); - if ( sem_post(&gCdStreamSema) != 0 ) - printf("Signal Sema Error\n"); + AddToQueue(&gChannelRequestQ, channel); + if ( sem_post(gCdStreamSema) != 0 ) + printf("Signal Sema Error\n"); #else - if ( sem_post(&gpReadInfo[channel].pStartSemaphore) != 0 ) - printf("Signal Sema Error\n"); + if ( sem_post(pChannel->pStartSemaphore) != 0 ) + printf("Signal Sema Error\n"); #endif - return STREAM_SUCCESS; + return STREAM_SUCCESS; } int32 @@ -272,29 +274,29 @@ CdStreamGetStatus(int32 channel) ASSERT( pChannel != nil ); #ifdef ONE_THREAD_PER_CHANNEL - if (pChannel->nThreadStatus == 2) - return STREAM_NONE; + if (pChannel->nThreadStatus == 2) + return STREAM_NONE; #else - if (gCdStreamThreadStatus == 2) - return STREAM_NONE; + if (gCdStreamThreadStatus == 2) + return STREAM_NONE; #endif - if ( pChannel->bReading ) - return STREAM_READING; + if ( pChannel->bReading ) + return STREAM_READING; - if ( pChannel->nSectorsToRead != 0 ) - return STREAM_WAITING; + if ( pChannel->nSectorsToRead != 0 ) + return STREAM_WAITING; - if ( pChannel->nStatus != STREAM_NONE ) - { - int32 status = pChannel->nStatus; + if ( pChannel->nStatus != STREAM_NONE ) + { + int32 status = pChannel->nStatus; - pChannel->nStatus = STREAM_NONE; + pChannel->nStatus = STREAM_NONE; - return status; - } + return status; + } - return STREAM_NONE; + return STREAM_NONE; } int32 @@ -314,30 +316,34 @@ CdStreamSync(int32 channel) if (flushStream[channel]) { #ifdef ONE_THREAD_PER_CHANNEL pChannel->nSectorsToRead = 0; - pthread_kill(gpReadInfo[channel].pChannelThread, SIGINT); + pthread_kill(pChannel->pChannelThread, SIGINT); + if (pChannel->bReading) { + pChannel->bLocked = true; + sem_wait(pChannel->pDoneSemaphore); + } #else + pChannel->nSectorsToRead = 0; if (pChannel->bReading) { - pChannel->nSectorsToRead = 0; + pChannel->bLocked = true; pthread_kill(_gCdStreamThread, SIGINT); - } else { - pChannel->nSectorsToRead = 0; + sem_wait(pChannel->pDoneSemaphore); } #endif pChannel->bReading = false; flushStream[channel] = false; - return STREAM_NONE; + return STREAM_NONE; } - if ( pChannel->nSectorsToRead != 0 ) - { - pChannel->bLocked = true; + if ( pChannel->nSectorsToRead != 0 ) + { + pChannel->bLocked = true; - sem_wait(&pChannel->pDoneSemaphore); - } + sem_wait(pChannel->pDoneSemaphore); + } - pChannel->bReading = false; + pChannel->bReading = false; - return pChannel->nStatus; + return pChannel->nStatus; } void @@ -382,53 +388,52 @@ void *CdStreamThread(void *param) debug("Created cdstream thread\n"); #ifndef ONE_THREAD_PER_CHANNEL - while (gCdStreamThreadStatus != 2) { - sem_wait(&gCdStreamSema); - int32 channel = GetFirstInQueue(&gChannelRequestQ); + while (gCdStreamThreadStatus != 2) { + sem_wait(gCdStreamSema); + int32 channel = GetFirstInQueue(&gChannelRequestQ); #else - int channel = *((int*)param); - while (gpReadInfo[channel].nThreadStatus != 2){ - sem_wait(&gpReadInfo[channel].pStartSemaphore); + int channel = *((int*)param); + while (gpReadInfo[channel].nThreadStatus != 2){ + sem_wait(gpReadInfo[channel].pStartSemaphore); #endif - ASSERT( channel < gNumChannels ); CdReadInfo *pChannel = &gpReadInfo[channel]; ASSERT( pChannel != nil ); -#ifdef ONE_THREAD_PER_CHANNEL - if (gpReadInfo[channel].nThreadStatus == 0){ - gpReadInfo[channel].nThreadStatus = 1; -#else - if (gCdStreamThreadStatus == 0){ - gCdStreamThreadStatus = 1; -#endif - -#ifdef __linux__ - pid_t tid = syscall(SYS_gettid); - int ret = setpriority(PRIO_PROCESS, tid, getpriority(PRIO_PROCESS, getpid()) + 1); -#endif - } - // spurious wakeup or we sent interrupt signal for flushing if(pChannel->nSectorsToRead == 0) - continue; + continue; pChannel->bReading = true; + // Not standard POSIX :shrug: +#ifdef __linux__ +#ifdef ONE_THREAD_PER_CHANNEL + if (gpReadInfo[channel].nThreadStatus == 0){ + gpReadInfo[channel].nThreadStatus = 1; +#else + if (gCdStreamThreadStatus == 0){ + gCdStreamThreadStatus = 1; +#endif + pid_t tid = syscall(SYS_gettid); + int ret = setpriority(PRIO_PROCESS, tid, getpriority(PRIO_PROCESS, getpid()) + 1); + } +#endif if ( pChannel->nStatus == STREAM_NONE ) { - ASSERT(pChannel->hFile >= 0); - ASSERT(pChannel->pBuffer != nil ); + ASSERT(pChannel->hFile >= 0); + ASSERT(pChannel->pBuffer != nil ); lseek(pChannel->hFile, pChannel->nSectorOffset * CDSTREAM_SECTOR_SIZE, SEEK_SET); - if (read(pChannel->hFile, pChannel->pBuffer, pChannel->nSectorsToRead * CDSTREAM_SECTOR_SIZE) == -1) { + if (read(pChannel->hFile, pChannel->pBuffer, pChannel->nSectorsToRead * CDSTREAM_SECTOR_SIZE) == -1) { // pChannel->nSectorsToRead == 0 at this point means we wanted to flush channel - pChannel->nStatus = pChannel->nSectorsToRead == 0 ? STREAM_NONE : STREAM_ERROR; - } else { - pChannel->nStatus = STREAM_NONE; - } + // STREAM_WAITING is a little hack to make CStreaming not process this data + pChannel->nStatus = pChannel->nSectorsToRead == 0 ? STREAM_WAITING : STREAM_ERROR; + } else { + pChannel->nStatus = STREAM_NONE; + } } - + #ifndef ONE_THREAD_PER_CHANNEL RemoveFirstInQueue(&gChannelRequestQ); #endif @@ -437,22 +442,33 @@ void *CdStreamThread(void *param) if ( pChannel->bLocked ) { - sem_post(&pChannel->pDoneSemaphore); + sem_post(pChannel->pDoneSemaphore); } pChannel->bReading = false; } + char semName[20]; #ifndef ONE_THREAD_PER_CHANNEL - for ( int32 i = 0; i < gNumChannels; i++ ) - { - sem_destroy(&gpReadInfo[i].pDoneSemaphore); - } - sem_destroy(&gCdStreamSema); + for ( int32 i = 0; i < gNumChannels; i++ ) + { + sem_close(gpReadInfo[i].pDoneSemaphore); + sprintf(semName,"/semaphore_done%d",i); + sem_unlink(semName); + } + sem_close(gCdStreamSema); + sem_unlink("/semaphore_cd_stream"); free(gChannelRequestQ.items); #else - sem_destroy(&gpReadInfo[channel].pStartSemaphore); - sem_destroy(&gpReadInfo[channel].pDoneSemaphore); + sem_close(gpReadInfo[channel].pStartSemaphore); + sprintf(semName,"/semaphore_start%d",channel); + sem_unlink(semName); + + sem_close(gpReadInfo[channel].pDoneSemaphore); + sprintf(semName,"/semaphore_done%d",channel); + sem_unlink(semName); #endif - free(gpReadInfo); + if (gpReadInfo) + free(gpReadInfo); + gpReadInfo = nil; pthread_exit(nil); } @@ -469,7 +485,7 @@ CdStreamAddImage(char const *path) char* real = casepath(path, false); if (real) { - gImgFiles[gNumImages] = open(real, _gdwCdStreamFlags); + gImgFiles[gNumImages] = open(real, _gdwCdStreamFlags); free(real); } } @@ -502,8 +518,10 @@ CdStreamGetImageName(int32 cd) void CdStreamRemoveImages(void) { - for ( int32 i = 0; i < gNumChannels; i++ ) + for ( int32 i = 0; i < gNumChannels; i++ ) { + flushStream[i] = 1; CdStreamSync(i); + } for ( int32 i = 0; i < gNumImages; i++ ) { diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index 635192ea..da678fd3 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -1052,7 +1052,11 @@ CFileLoader::Load2dEffect(const char *line) &effect->attractor.dir.z, &probability); effect->attractor.type = flags; +#ifdef FIX_BUGS + effect->attractor.probability = clamp(probability, 0, 255); +#else effect->attractor.probability = probability; +#endif break; case EFFECT_PED_ATTRACTOR: sscanf(line, "%d %f %f %f %d %d %d %d %d %d %f %f %f %f %f %f", diff --git a/src/core/FileMgr.cpp b/src/core/FileMgr.cpp index 4477a190..d3695cb4 100644 --- a/src/core/FileMgr.cpp +++ b/src/core/FileMgr.cpp @@ -142,17 +142,17 @@ static size_t myfread(void *buf, size_t elt, size_t n, int fd) { if(myfiles[fd].isText){ - char *p; + unsigned char *p; size_t i; int c; n *= elt; - p = (char*)buf; + p = (unsigned char*)buf; for(i = 0; i < n; i++){ c = myfgetc(fd); if(c == EOF) break; - *p++ = c; + *p++ = (unsigned char)c; } return i / elt; } @@ -163,12 +163,12 @@ static size_t myfwrite(void *buf, size_t elt, size_t n, int fd) { if(myfiles[fd].isText){ - char *p; + unsigned char *p; size_t i; int c; n *= elt; - p = (char*)buf; + p = (unsigned char*)buf; for(i = 0; i < n; i++){ c = *p++; myfputc(c, fd); diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index d296496e..ddde4664 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -46,7 +46,11 @@ CStreamingInfo CStreaming::ms_endRequestedList; int32 CStreaming::ms_oldSectorX; int32 CStreaming::ms_oldSectorY; int32 CStreaming::ms_streamingBufferSize; +#ifndef ONE_THREAD_PER_CHANNEL int8 *CStreaming::ms_pStreamingBuffer[2]; +#else +int8 *CStreaming::ms_pStreamingBuffer[4]; +#endif size_t CStreaming::ms_memoryUsed; CStreamingChannel CStreaming::ms_channel[2]; int32 CStreaming::ms_channelError; @@ -197,6 +201,10 @@ CStreaming::Init2(void) ms_pStreamingBuffer[0] = (int8*)RwMallocAlign(ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE); ms_streamingBufferSize /= 2; ms_pStreamingBuffer[1] = ms_pStreamingBuffer[0] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE; +#ifdef ONE_THREAD_PER_CHANNEL + ms_pStreamingBuffer[2] = (int8*)RwMallocAlign(ms_streamingBufferSize*2*CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE); + ms_pStreamingBuffer[3] = ms_pStreamingBuffer[2] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE; +#endif debug("Streaming buffer size is %d sectors", ms_streamingBufferSize); // PC only, figure out how much memory we got @@ -2196,6 +2204,110 @@ CStreaming::LoadRequestedModels(void) } } + +// Let's load models first, then process it. Unfortunately processing models are still single-threaded. +// Currently only supported on POSIX streamer. +#ifdef ONE_THREAD_PER_CHANNEL +void +CStreaming::LoadAllRequestedModels(bool priority) +{ + static bool bInsideLoadAll = false; + int imgOffset, streamId, status; + int i; + uint32 posn, size; + + if(bInsideLoadAll) + return; + bInsideLoadAll = true; + + FlushChannels(); + imgOffset = GetCdImageOffset(CdStreamGetLastPosn()); + + int streamIds[ARRAY_SIZE(ms_pStreamingBuffer)]; + int streamSizes[ARRAY_SIZE(ms_pStreamingBuffer)]; + int streamPoses[ARRAY_SIZE(ms_pStreamingBuffer)]; + bool first = true; + int processI = 0; + + while (true) { + // Enumerate files and start reading + for (int i=0; i<ARRAY_SIZE(ms_pStreamingBuffer); i++) { + if (!first && streamIds[i] != -1) { + processI = i; + continue; + } + + if(ms_endRequestedList.m_prev != &ms_startRequestedList){ + streamId = GetNextFileOnCd(0, priority); + if(streamId == -1){ + streamIds[i] = -1; + break; + } + + if (ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size)) { + streamIds[i] = -1; + if (size > (uint32)ms_streamingBufferSize) { + if (i + 1 == ARRAY_SIZE(ms_pStreamingBuffer)) + continue; + else if (!first && streamIds[i+1] != -1) + continue; + } else { + if (i != 0 && streamIds[i-1] != -1 && streamSizes[i-1] > (uint32)ms_streamingBufferSize) + continue; + } + ms_aInfoForModel[streamId].RemoveFromList(); + DecrementRef(streamId); + + streamIds[i] = streamId; + streamSizes[i] = size; + streamPoses[i] = posn; + CdStreamRead(i, ms_pStreamingBuffer[i], imgOffset+posn, size); + processI = i; + } else { + ms_aInfoForModel[streamId].RemoveFromList(); + DecrementRef(streamId); + + ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED; + streamIds[i] = -1; + } + } else + streamIds[i] = -1; + } + + first = false; + + // Now process + if (streamIds[processI] == -1) + break; + + // Try again on error + while (CdStreamSync(processI) != STREAM_NONE) { + CdStreamRead(processI, ms_pStreamingBuffer[processI], imgOffset+streamPoses[processI], streamSizes[processI]); + } + ms_aInfoForModel[streamIds[processI]].m_loadState = STREAMSTATE_READING; + + MakeSpaceFor(streamSizes[processI] * CDSTREAM_SECTOR_SIZE); + ConvertBufferToObject(ms_pStreamingBuffer[processI], streamIds[processI]); + if(ms_aInfoForModel[streamIds[processI]].m_loadState == STREAMSTATE_STARTED) + FinishLoadingLargeFile(ms_pStreamingBuffer[processI], streamIds[processI]); + + if(streamIds[processI] < STREAM_OFFSET_TXD){ + CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(streamIds[processI]); + if(mi->IsSimple()) + mi->m_alpha = 255; + } + streamIds[processI] = -1; + } + + ms_bLoadingBigModel = false; + for(i = 0; i < 4; i++){ + ms_channel[1].streamIds[i] = -1; + ms_channel[1].offsets[i] = -1; + } + ms_channel[1].state = CHANNELSTATE_IDLE; + bInsideLoadAll = false; +} +#else void CStreaming::LoadAllRequestedModels(bool priority) { @@ -2256,6 +2368,7 @@ CStreaming::LoadAllRequestedModels(bool priority) ms_channel[1].state = CHANNELSTATE_IDLE; bInsideLoadAll = false; } +#endif void CStreaming::FlushChannels(void) @@ -2287,6 +2400,14 @@ CStreaming::FlushRequestList(void) next = si->m_next; RemoveModel(si - ms_aInfoForModel); } +#ifndef _WIN32 + if(ms_channel[0].state == CHANNELSTATE_READING) { + flushStream[0] = 1; + } + if(ms_channel[1].state == CHANNELSTATE_READING) { + flushStream[1] = 1; + } +#endif FlushChannels(); } @@ -2815,10 +2936,15 @@ CStreaming::DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, size_t mem) void CStreaming::MakeSpaceFor(int32 size) { - // BUG: ms_memoryAvailable can be uninitialized - // the code still happens to work in that case because ms_memoryAvailable is unsigned - // but it's not nice.... - +#ifdef FIX_BUGS +#define MB (1024 * 1024) + if(ms_memoryAvailable == 0) { + extern size_t _dwMemAvailPhys; + ms_memoryAvailable = (_dwMemAvailPhys - 10 * MB) / 2; + if(ms_memoryAvailable < 65 * MB) ms_memoryAvailable = 65 * MB; + } +#undef MB +#endif while(ms_memoryUsed >= ms_memoryAvailable - size) if(!RemoveLeastUsedModel(STREAMFLAGS_20)){ DeleteRwObjectsBehindCamera(ms_memoryAvailable - size); diff --git a/src/core/common.h b/src/core/common.h index 16d32b32..c4c133fa 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -106,7 +106,7 @@ typedef uint16_t wchar; inline uint32 dpb(uint32 b, uint32 p, uint32 s, uint32 w) { uint32 m = MASK(p,s); - return w & ~m | b<<p & m; + return (w & ~m) | ((b<<p) & m); } inline uint32 ldb(uint32 p, uint32 s, uint32 w) { diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index b40130c4..74330141 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -81,7 +81,12 @@ DWORD _dwOperatingSystemVersion; #include "resource.h" #else long _dwOperatingSystemVersion; +#ifndef __APPLE__ #include <sys/sysinfo.h> +#else +#include <mach/mach_host.h> +#include <sys/sysctl.h> +#endif #include <stddef.h> #include <locale.h> #include <signal.h> @@ -449,15 +454,27 @@ psInitialize(void) #endif #endif +#ifndef __APPLE__ struct sysinfo systemInfo; sysinfo(&systemInfo); - _dwMemAvailPhys = systemInfo.freeram; - _dwOperatingSystemVersion = OS_WINXP; // To fool other classes - debug("Physical memory size %u\n", systemInfo.totalram); debug("Available physical memory %u\n", systemInfo.freeram); - +#else + 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); +#endif + _dwOperatingSystemVersion = OS_WINXP; // To fool other classes #endif TheText.Unload(); diff --git a/src/vehicles/CarGen.cpp b/src/vehicles/CarGen.cpp index b0fa91a4..598b8342 100644 --- a/src/vehicles/CarGen.cpp +++ b/src/vehicles/CarGen.cpp @@ -28,8 +28,13 @@ uint32 CTheCarGenerators::CurrentActiveCount; void CCarGenerator::SwitchOff() { - m_nUsesRemaining = 0; - --CTheCarGenerators::CurrentActiveCount; +#ifdef FIX_BUGS + if (m_nUsesRemaining != 0) +#endif + { + m_nUsesRemaining = 0; + --CTheCarGenerators::CurrentActiveCount; + } } void CCarGenerator::SwitchOn() diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 705fca3a..004f1fd9 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -187,7 +187,7 @@ public: CAutoPilot AutoPilot; uint8 m_currentColour1; uint8 m_currentColour2; - uint8 m_aExtras[2]; + int8 m_aExtras[2]; int16 m_nAlarmState; int16 m_nRouteSeed; CPed *pDriver; diff --git a/src/weapons/WeaponInfo.cpp b/src/weapons/WeaponInfo.cpp index 6debf725..b911805d 100644 --- a/src/weapons/WeaponInfo.cpp +++ b/src/weapons/WeaponInfo.cpp @@ -249,28 +249,28 @@ CWeaponInfo::LoadWeaponData(void) ms_apWeaponInfos[weaponType].m_nModelId = modelId; ms_apWeaponInfos[weaponType].m_nModel2Id = modelId2; - ms_apWeaponInfos[weaponType].m_bUseGravity = flags; - ms_apWeaponInfos[weaponType].m_bSlowsDown = flags >> 1; - ms_apWeaponInfos[weaponType].m_bDissipates = flags >> 2; - ms_apWeaponInfos[weaponType].m_bRandSpeed = flags >> 3; - ms_apWeaponInfos[weaponType].m_bExpands = flags >> 4; - ms_apWeaponInfos[weaponType].m_bExplodes = flags >> 5; - ms_apWeaponInfos[weaponType].m_bCanAim = flags >> 6; - ms_apWeaponInfos[weaponType].m_bCanAimWithArm = flags >> 7; - ms_apWeaponInfos[weaponType].m_b1stPerson = flags >> 8; - ms_apWeaponInfos[weaponType].m_bHeavy = flags >> 9; - ms_apWeaponInfos[weaponType].m_bThrow = flags >> 10; - ms_apWeaponInfos[weaponType].m_bReloadLoop2Start = flags >> 11; - ms_apWeaponInfos[weaponType].m_bUse2nd = flags >> 12; - ms_apWeaponInfos[weaponType].m_bGround2nd = flags >> 13; - ms_apWeaponInfos[weaponType].m_bFinish3rd = flags >> 14; - ms_apWeaponInfos[weaponType].m_bReload = flags >> 15; - ms_apWeaponInfos[weaponType].m_bFightMode = flags >> 16; - ms_apWeaponInfos[weaponType].m_bCrouchFire = flags >> 17; - ms_apWeaponInfos[weaponType].m_bCop3rd = flags >> 18; - ms_apWeaponInfos[weaponType].m_bGround3rd = flags >> 19; - ms_apWeaponInfos[weaponType].m_bPartialAttack = flags >> 20; - ms_apWeaponInfos[weaponType].m_bAnimDetonate = flags >> 21; + ms_apWeaponInfos[weaponType].m_bUseGravity = flags & 1; + ms_apWeaponInfos[weaponType].m_bSlowsDown = (flags >> 1) & 1; + ms_apWeaponInfos[weaponType].m_bDissipates = (flags >> 2) & 1; + ms_apWeaponInfos[weaponType].m_bRandSpeed = (flags >> 3) & 1; + ms_apWeaponInfos[weaponType].m_bExpands = (flags >> 4) & 1; + ms_apWeaponInfos[weaponType].m_bExplodes = (flags >> 5) & 1; + ms_apWeaponInfos[weaponType].m_bCanAim = (flags >> 6) & 1; + ms_apWeaponInfos[weaponType].m_bCanAimWithArm = (flags >> 7) & 1; + ms_apWeaponInfos[weaponType].m_b1stPerson = (flags >> 8) & 1; + ms_apWeaponInfos[weaponType].m_bHeavy = (flags >> 9) & 1; + ms_apWeaponInfos[weaponType].m_bThrow = (flags >> 10) & 1; + ms_apWeaponInfos[weaponType].m_bReloadLoop2Start = (flags >> 11) & 1; + ms_apWeaponInfos[weaponType].m_bUse2nd = (flags >> 12) & 1; + ms_apWeaponInfos[weaponType].m_bGround2nd = (flags >> 13) & 1; + ms_apWeaponInfos[weaponType].m_bFinish3rd = (flags >> 14) & 1; + ms_apWeaponInfos[weaponType].m_bReload = (flags >> 15) & 1; + ms_apWeaponInfos[weaponType].m_bFightMode = (flags >> 16) & 1; + ms_apWeaponInfos[weaponType].m_bCrouchFire = (flags >> 17) & 1; + ms_apWeaponInfos[weaponType].m_bCop3rd = (flags >> 18) & 1; + ms_apWeaponInfos[weaponType].m_bGround3rd = (flags >> 19) & 1; + ms_apWeaponInfos[weaponType].m_bPartialAttack = (flags >> 20) & 1; + ms_apWeaponInfos[weaponType].m_bAnimDetonate = (flags >> 21) & 1; ms_apWeaponInfos[weaponType].m_nWeaponSlot = weaponSlot; diff --git a/vendor/librw b/vendor/librw -Subproject 30b77b0b32b4113b5dce2b67813ce9b85d1e1e5 +Subproject edc77742c512b85ad35544b2cfbe3f359dc7580 |