summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorerorcun <erayorcunus@gmail.com>2020-10-08 15:15:55 +0200
committerGitHub <noreply@github.com>2020-10-08 15:15:55 +0200
commitbf98dcbc3a19bd80fefe0c4cd2a1cb975e678242 (patch)
tree1f5e271c7f3447686fb8b9e5715e9fba14bc19c2
parentlittle renamings & librw update (diff)
parentFix some sanitizer errors, improve POSIX streamer (diff)
downloadre3-bf98dcbc3a19bd80fefe0c4cd2a1cb975e678242.tar
re3-bf98dcbc3a19bd80fefe0c4cd2a1cb975e678242.tar.gz
re3-bf98dcbc3a19bd80fefe0c4cd2a1cb975e678242.tar.bz2
re3-bf98dcbc3a19bd80fefe0c4cd2a1cb975e678242.tar.lz
re3-bf98dcbc3a19bd80fefe0c4cd2a1cb975e678242.tar.xz
re3-bf98dcbc3a19bd80fefe0c4cd2a1cb975e678242.tar.zst
re3-bf98dcbc3a19bd80fefe0c4cd2a1cb975e678242.zip
-rw-r--r--src/control/Garages.cpp2
-rw-r--r--src/core/CdStreamPosix.cpp288
-rw-r--r--src/core/FileLoader.cpp4
-rw-r--r--src/core/FileMgr.cpp10
-rw-r--r--src/core/Streaming.cpp120
-rw-r--r--src/core/common.h2
-rw-r--r--src/extras/frontendoption.cpp2
-rw-r--r--src/vehicles/CarGen.cpp9
-rw-r--r--src/vehicles/Vehicle.h2
-rw-r--r--src/weapons/WeaponInfo.cpp22
10 files changed, 302 insertions, 159 deletions
diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp
index e1f06c97..61c1a850 100644
--- a/src/control/Garages.cpp
+++ b/src/control/Garages.cpp
@@ -1509,7 +1509,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 40000f03..04a5de4b 100644
--- a/src/core/CdStreamPosix.cpp
+++ b/src/core/CdStreamPosix.cpp
@@ -34,9 +34,9 @@ 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
int32 hFile;
@@ -52,7 +52,7 @@ 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
+int8 gCdStreamThreadStatus; // 0: created 1:priority set up 2:abort now
Queue gChannelRequestQ;
bool _gbCdStreamOverlapped;
#endif
@@ -69,15 +69,14 @@ 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 );
- gCdStreamSema = sem_open("/semaphore_cd_stream", O_CREAT, 0644, 1);
-#endif
+ gCdStreamSema = sem_open("/semaphore_cd_stream", O_CREAT, 0644, 1);
if (gCdStreamSema == SEM_FAILED) {
@@ -85,33 +84,35 @@ CdStreamInitThread(void)
ASSERT(0);
return;
}
-
+#endif
if ( gNumChannels > 0 )
{
for ( int32 i = 0; i < gNumChannels; i++ )
{
- gpReadInfo[i].pDoneSemaphore = sem_open("/semaphore_done", O_CREAT, 0644, 1);
+ sprintf(semName,"/semaphore_done%d",i);
+ gpReadInfo[i].pDoneSemaphore = sem_open(semName, O_CREAT, 0644, 1);
- if (gpReadInfo[i].pDoneSemaphore == SEM_FAILED)
+ if (gpReadInfo[i].pDoneSemaphore == SEM_FAILED)
{
CDTRACE("failed to create sync semaphore");
ASSERT(0);
return;
}
#ifdef ONE_THREAD_PER_CHANNEL
- gpReadInfo[i].pStartSemaphore = sem_open("/semaphore_start", O_CREAT, 0644, 1);
+ sprintf(semName,"/semaphore_start%d",i);
+ gpReadInfo[i].pStartSemaphore = sem_open(semName, O_CREAT, 0644, 1);
- if (gpReadInfo[i].pStartSemaphore == SEM_FAILED)
+ 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 separate 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
@@ -185,26 +186,26 @@ 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:
+ CDTRACE("can't get size of gta3.img");
+ ASSERT(0);
+ return 0;
+ }
+ ok:
return (uint32)statbuf.st_size;
}
@@ -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) {
+ while (gCdStreamThreadStatus != 2) {
sem_wait(gCdStreamSema);
- int32 channel = GetFirstInQueue(&gChannelRequestQ);
+ 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,26 +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_close(gpReadInfo[i].pDoneSemaphore);
- sem_unlink("/semaphore_done");
- }
- sem_close(gCdStreamSema);
- sem_unlink("/semaphore_cd_stream");
- free(gChannelRequestQ.items);
+ 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_close(gpReadInfo[channel].pStartSemaphore);
- sem_unlink("/semaphore_start");
- sem_close(gpReadInfo[channel].pDoneSemaphore);
- sem_unlink("/semaphore_done");
+ 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);
}
@@ -473,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);
}
}
@@ -506,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 b4da1a5e..ff50575f 100644
--- a/src/core/FileLoader.cpp
+++ b/src/core/FileLoader.cpp
@@ -980,7 +980,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;
}
diff --git a/src/core/FileMgr.cpp b/src/core/FileMgr.cpp
index ac51f8de..6e6a8efc 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 4e12ab6d..3c5689fd 100644
--- a/src/core/Streaming.cpp
+++ b/src/core/Streaming.cpp
@@ -45,7 +45,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;
@@ -198,6 +202,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
@@ -1831,6 +1839,109 @@ 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;
+
+ 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)
{
@@ -1883,6 +1994,7 @@ CStreaming::LoadAllRequestedModels(bool priority)
ms_channel[1].state = CHANNELSTATE_IDLE;
bInsideLoadAll = false;
}
+#endif
void
CStreaming::FlushChannels(void)
@@ -1914,6 +2026,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();
}
diff --git a/src/core/common.h b/src/core/common.h
index ef3da265..48b20884 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/extras/frontendoption.cpp b/src/extras/frontendoption.cpp
index ed8aa2a9..88a930a9 100644
--- a/src/extras/frontendoption.cpp
+++ b/src/extras/frontendoption.cpp
@@ -56,7 +56,7 @@ GetNumberOfMenuOptions(int screen)
uint8
GetLastMenuScreen()
{
- uint8 page = -1;
+ int8 page = -1;
for (int i = 0; i < MENUPAGES; i++) {
if (strcmp(aScreens[i].m_ScreenName, "") == 0 && aScreens[i].unk == 0)
break;
diff --git a/src/vehicles/CarGen.cpp b/src/vehicles/CarGen.cpp
index 338eaba4..9bab9640 100644
--- a/src/vehicles/CarGen.cpp
+++ b/src/vehicles/CarGen.cpp
@@ -22,8 +22,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 48546e68..999ee002 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -111,7 +111,7 @@ public:
CAutoPilot AutoPilot;
uint8 m_currentColour1;
uint8 m_currentColour2;
- uint8 m_aExtras[2];
+ int8 m_aExtras[2];
int16 m_nAlarmState;
int16 m_nMissionValue;
CPed *pDriver;
diff --git a/src/weapons/WeaponInfo.cpp b/src/weapons/WeaponInfo.cpp
index 93370a18..284a0c20 100644
--- a/src/weapons/WeaponInfo.cpp
+++ b/src/weapons/WeaponInfo.cpp
@@ -160,17 +160,17 @@ CWeaponInfo::LoadWeaponData(void)
ms_apWeaponInfos[weaponType].m_fAnimFrameFire = delayBetweenAnimAndFire / 30.0f;
ms_apWeaponInfos[weaponType].m_fAnim2FrameFire = delayBetweenAnim2AndFire / 30.0f;
ms_apWeaponInfos[weaponType].m_nModelId = modelId;
- 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_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;
}
}