summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CdStreamPosix.cpp294
-rw-r--r--src/core/FileLoader.cpp4
-rw-r--r--src/core/FileMgr.cpp10
-rw-r--r--src/core/Streaming.cpp134
-rw-r--r--src/core/common.h2
5 files changed, 296 insertions, 148 deletions
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)
{