Fix some sanitizer errors, improve POSIX streamer
This commit is contained in:
parent
ea4007a13c
commit
8c170a62ee
@ -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?
|
// 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;
|
bool bNeedToFindDoorEntities = false;
|
||||||
if (pDoor) {
|
if (pDoor) {
|
||||||
|
@ -34,9 +34,9 @@ struct CdReadInfo
|
|||||||
bool bReading;
|
bool bReading;
|
||||||
int32 nStatus;
|
int32 nStatus;
|
||||||
#ifdef ONE_THREAD_PER_CHANNEL
|
#ifdef ONE_THREAD_PER_CHANNEL
|
||||||
int8 nThreadStatus; // 0: created 1:initalized 2:abort now
|
int8 nThreadStatus; // 0: created 1:priority set up 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;
|
||||||
@ -52,7 +52,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:priority set up 2:abort now
|
||||||
Queue gChannelRequestQ;
|
Queue gChannelRequestQ;
|
||||||
bool _gbCdStreamOverlapped;
|
bool _gbCdStreamOverlapped;
|
||||||
#endif
|
#endif
|
||||||
@ -69,15 +69,14 @@ void
|
|||||||
CdStreamInitThread(void)
|
CdStreamInitThread(void)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
char semName[20];
|
||||||
#ifndef ONE_THREAD_PER_CHANNEL
|
#ifndef ONE_THREAD_PER_CHANNEL
|
||||||
gChannelRequestQ.items = (int32 *)calloc(gNumChannels + 1, sizeof(int32));
|
gChannelRequestQ.items = (int32 *)calloc(gNumChannels + 1, sizeof(int32));
|
||||||
gChannelRequestQ.head = 0;
|
gChannelRequestQ.head = 0;
|
||||||
gChannelRequestQ.tail = 0;
|
gChannelRequestQ.tail = 0;
|
||||||
gChannelRequestQ.size = gNumChannels + 1;
|
gChannelRequestQ.size = gNumChannels + 1;
|
||||||
ASSERT(gChannelRequestQ.items != nil );
|
ASSERT(gChannelRequestQ.items != nil );
|
||||||
gCdStreamSema = sem_open("/semaphore_cd_stream", O_CREAT, 0644, 1);
|
gCdStreamSema = sem_open("/semaphore_cd_stream", O_CREAT, 0644, 1);
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
if (gCdStreamSema == SEM_FAILED) {
|
if (gCdStreamSema == SEM_FAILED) {
|
||||||
@ -85,33 +84,35 @@ CdStreamInitThread(void)
|
|||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( gNumChannels > 0 )
|
if ( gNumChannels > 0 )
|
||||||
{
|
{
|
||||||
for ( int32 i = 0; i < gNumChannels; i++ )
|
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");
|
CDTRACE("failed to create sync semaphore");
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef ONE_THREAD_PER_CHANNEL
|
#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");
|
CDTRACE("failed to create start semaphore");
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gpReadInfo[i].nThreadStatus = 0;
|
gpReadInfo[i].nThreadStatus = 0;
|
||||||
int *channelI = (int*)malloc(sizeof(int));
|
int *channelI = (int*)malloc(sizeof(int));
|
||||||
*channelI = i;
|
*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)
|
if (status == -1)
|
||||||
{
|
{
|
||||||
@ -124,32 +125,32 @@ CdStreamInitThread(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ONE_THREAD_PER_CHANNEL
|
#ifndef ONE_THREAD_PER_CHANNEL
|
||||||
debug("Using one streaming thread for all channels\n");
|
debug("Using one streaming thread for all channels\n");
|
||||||
status = pthread_create(&_gCdStreamThread, NULL, CdStreamThread, nil);
|
gCdStreamThreadStatus = 0;
|
||||||
gCdStreamThreadStatus = 0;
|
status = pthread_create(&_gCdStreamThread, NULL, CdStreamThread, nil);
|
||||||
|
|
||||||
if (status == -1)
|
if (status == -1)
|
||||||
{
|
{
|
||||||
CDTRACE("failed to create sync thread");
|
CDTRACE("failed to create sync thread");
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
debug("Using separate streaming threads for each channel\n");
|
debug("Using separate streaming threads for each channel\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CdStreamInit(int32 numChannels)
|
CdStreamInit(int32 numChannels)
|
||||||
{
|
{
|
||||||
struct statvfs fsInfo;
|
struct statvfs fsInfo;
|
||||||
|
|
||||||
if((statvfs("models/gta3.img", &fsInfo)) < 0)
|
if((statvfs("models/gta3.img", &fsInfo)) < 0)
|
||||||
{
|
{
|
||||||
CDTRACE("can't get filesystem info");
|
CDTRACE("can't get filesystem info");
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
_gdwCdStreamFlags = O_RDONLY | O_NOATIME;
|
_gdwCdStreamFlags = O_RDONLY | O_NOATIME;
|
||||||
#else
|
#else
|
||||||
@ -185,26 +186,26 @@ uint32
|
|||||||
GetGTA3ImgSize(void)
|
GetGTA3ImgSize(void)
|
||||||
{
|
{
|
||||||
ASSERT( gImgFiles[0] > 0 );
|
ASSERT( gImgFiles[0] > 0 );
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
realpath(gImgNames[0], path);
|
realpath(gImgNames[0], path);
|
||||||
if (stat(path, &statbuf) == -1) {
|
if (stat(path, &statbuf) == -1) {
|
||||||
// Try case-insensitivity
|
// Try case-insensitivity
|
||||||
char* real = casepath(gImgNames[0], false);
|
char* real = casepath(gImgNames[0], false);
|
||||||
if (real)
|
if (real)
|
||||||
{
|
{
|
||||||
realpath(real, path);
|
realpath(real, path);
|
||||||
free(real);
|
free(real);
|
||||||
if (stat(path, &statbuf) != -1)
|
if (stat(path, &statbuf) != -1)
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
CDTRACE("can't get size of gta3.img");
|
CDTRACE("can't get size of gta3.img");
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ok:
|
ok:
|
||||||
return (uint32)statbuf.st_size;
|
return (uint32)statbuf.st_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,15 +214,13 @@ 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
|
#else
|
||||||
|
for ( int32 i = 0; i < gNumChannels; i++ ) {
|
||||||
#ifdef ONE_THREAD_PER_CHANNEL
|
gpReadInfo[i].nThreadStatus = 2;
|
||||||
for ( int32 i = 0; i < gNumChannels; i++ ) {
|
sem_post(gpReadInfo[i].pStartSemaphore);
|
||||||
gpReadInfo[i].nThreadStatus = 2;
|
}
|
||||||
sem_post(&gpReadInfo[i].pStartSemaphore);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,25 +242,28 @@ CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size)
|
|||||||
|
|
||||||
pChannel->hFile = hImage - 1;
|
pChannel->hFile = hImage - 1;
|
||||||
|
|
||||||
if ( pChannel->nSectorsToRead != 0 || pChannel->bReading )
|
if ( pChannel->nSectorsToRead != 0 || pChannel->bReading ) {
|
||||||
return STREAM_NONE;
|
flushStream[channel] = 1;
|
||||||
|
CdStreamSync(channel);
|
||||||
|
//return STREAM_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
pChannel->nStatus = STREAM_NONE;
|
pChannel->nStatus = STREAM_NONE;
|
||||||
pChannel->nSectorOffset = _GET_OFFSET(offset);
|
pChannel->nSectorOffset = _GET_OFFSET(offset);
|
||||||
pChannel->nSectorsToRead = size;
|
pChannel->nSectorsToRead = size;
|
||||||
pChannel->pBuffer = buffer;
|
pChannel->pBuffer = buffer;
|
||||||
pChannel->bLocked = 0;
|
pChannel->bLocked = 0;
|
||||||
|
|
||||||
#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(pChannel->pStartSemaphore) != 0 )
|
||||||
printf("Signal Sema Error\n");
|
printf("Signal Sema Error\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return STREAM_SUCCESS;
|
return STREAM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32
|
int32
|
||||||
@ -272,29 +274,29 @@ CdStreamGetStatus(int32 channel)
|
|||||||
ASSERT( pChannel != nil );
|
ASSERT( pChannel != nil );
|
||||||
|
|
||||||
#ifdef ONE_THREAD_PER_CHANNEL
|
#ifdef ONE_THREAD_PER_CHANNEL
|
||||||
if (pChannel->nThreadStatus == 2)
|
if (pChannel->nThreadStatus == 2)
|
||||||
return STREAM_NONE;
|
return STREAM_NONE;
|
||||||
#else
|
#else
|
||||||
if (gCdStreamThreadStatus == 2)
|
if (gCdStreamThreadStatus == 2)
|
||||||
return STREAM_NONE;
|
return STREAM_NONE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( pChannel->bReading )
|
if ( pChannel->bReading )
|
||||||
return STREAM_READING;
|
return STREAM_READING;
|
||||||
|
|
||||||
if ( pChannel->nSectorsToRead != 0 )
|
if ( pChannel->nSectorsToRead != 0 )
|
||||||
return STREAM_WAITING;
|
return STREAM_WAITING;
|
||||||
|
|
||||||
if ( pChannel->nStatus != STREAM_NONE )
|
if ( pChannel->nStatus != STREAM_NONE )
|
||||||
{
|
{
|
||||||
int32 status = pChannel->nStatus;
|
int32 status = pChannel->nStatus;
|
||||||
|
|
||||||
pChannel->nStatus = STREAM_NONE;
|
pChannel->nStatus = STREAM_NONE;
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
return STREAM_NONE;
|
return STREAM_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32
|
int32
|
||||||
@ -314,30 +316,34 @@ CdStreamSync(int32 channel)
|
|||||||
if (flushStream[channel]) {
|
if (flushStream[channel]) {
|
||||||
#ifdef ONE_THREAD_PER_CHANNEL
|
#ifdef ONE_THREAD_PER_CHANNEL
|
||||||
pChannel->nSectorsToRead = 0;
|
pChannel->nSectorsToRead = 0;
|
||||||
pthread_kill(gpReadInfo[channel].pChannelThread, SIGINT);
|
pthread_kill(pChannel->pChannelThread, SIGINT);
|
||||||
#else
|
|
||||||
if (pChannel->bReading) {
|
if (pChannel->bReading) {
|
||||||
pChannel->nSectorsToRead = 0;
|
pChannel->bLocked = true;
|
||||||
|
sem_wait(pChannel->pDoneSemaphore);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
pChannel->nSectorsToRead = 0;
|
||||||
|
if (pChannel->bReading) {
|
||||||
|
pChannel->bLocked = true;
|
||||||
pthread_kill(_gCdStreamThread, SIGINT);
|
pthread_kill(_gCdStreamThread, SIGINT);
|
||||||
} else {
|
sem_wait(pChannel->pDoneSemaphore);
|
||||||
pChannel->nSectorsToRead = 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
pChannel->bReading = false;
|
pChannel->bReading = false;
|
||||||
flushStream[channel] = false;
|
flushStream[channel] = false;
|
||||||
return STREAM_NONE;
|
return STREAM_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pChannel->nSectorsToRead != 0 )
|
if ( pChannel->nSectorsToRead != 0 )
|
||||||
{
|
{
|
||||||
pChannel->bLocked = true;
|
pChannel->bLocked = true;
|
||||||
|
|
||||||
sem_wait(pChannel->pDoneSemaphore);
|
sem_wait(pChannel->pDoneSemaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
pChannel->bReading = false;
|
pChannel->bReading = false;
|
||||||
|
|
||||||
return pChannel->nStatus;
|
return pChannel->nStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -382,51 +388,50 @@ void *CdStreamThread(void *param)
|
|||||||
debug("Created cdstream thread\n");
|
debug("Created cdstream thread\n");
|
||||||
|
|
||||||
#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);
|
||||||
while (gpReadInfo[channel].nThreadStatus != 2){
|
while (gpReadInfo[channel].nThreadStatus != 2){
|
||||||
sem_wait(&gpReadInfo[channel].pStartSemaphore);
|
sem_wait(gpReadInfo[channel].pStartSemaphore);
|
||||||
#endif
|
#endif
|
||||||
ASSERT( channel < gNumChannels );
|
|
||||||
|
|
||||||
CdReadInfo *pChannel = &gpReadInfo[channel];
|
CdReadInfo *pChannel = &gpReadInfo[channel];
|
||||||
ASSERT( pChannel != nil );
|
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
|
// spurious wakeup or we sent interrupt signal for flushing
|
||||||
if(pChannel->nSectorsToRead == 0)
|
if(pChannel->nSectorsToRead == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pChannel->bReading = true;
|
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 )
|
if ( pChannel->nStatus == STREAM_NONE )
|
||||||
{
|
{
|
||||||
ASSERT(pChannel->hFile >= 0);
|
ASSERT(pChannel->hFile >= 0);
|
||||||
ASSERT(pChannel->pBuffer != nil );
|
ASSERT(pChannel->pBuffer != nil );
|
||||||
|
|
||||||
lseek(pChannel->hFile, pChannel->nSectorOffset * CDSTREAM_SECTOR_SIZE, SEEK_SET);
|
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->nSectorsToRead == 0 at this point means we wanted to flush channel
|
||||||
pChannel->nStatus = pChannel->nSectorsToRead == 0 ? STREAM_NONE : STREAM_ERROR;
|
// STREAM_WAITING is a little hack to make CStreaming not process this data
|
||||||
} else {
|
pChannel->nStatus = pChannel->nSectorsToRead == 0 ? STREAM_WAITING : STREAM_ERROR;
|
||||||
pChannel->nStatus = STREAM_NONE;
|
} else {
|
||||||
}
|
pChannel->nStatus = STREAM_NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ONE_THREAD_PER_CHANNEL
|
#ifndef ONE_THREAD_PER_CHANNEL
|
||||||
@ -441,22 +446,29 @@ void *CdStreamThread(void *param)
|
|||||||
}
|
}
|
||||||
pChannel->bReading = false;
|
pChannel->bReading = false;
|
||||||
}
|
}
|
||||||
|
char semName[20];
|
||||||
#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_close(gpReadInfo[i].pDoneSemaphore);
|
sem_close(gpReadInfo[i].pDoneSemaphore);
|
||||||
sem_unlink("/semaphore_done");
|
sprintf(semName,"/semaphore_done%d",i);
|
||||||
}
|
sem_unlink(semName);
|
||||||
sem_close(gCdStreamSema);
|
}
|
||||||
sem_unlink("/semaphore_cd_stream");
|
sem_close(gCdStreamSema);
|
||||||
free(gChannelRequestQ.items);
|
sem_unlink("/semaphore_cd_stream");
|
||||||
|
free(gChannelRequestQ.items);
|
||||||
#else
|
#else
|
||||||
sem_close(gpReadInfo[channel].pStartSemaphore);
|
sem_close(gpReadInfo[channel].pStartSemaphore);
|
||||||
sem_unlink("/semaphore_start");
|
sprintf(semName,"/semaphore_start%d",channel);
|
||||||
sem_close(gpReadInfo[channel].pDoneSemaphore);
|
sem_unlink(semName);
|
||||||
sem_unlink("/semaphore_done");
|
|
||||||
|
sem_close(gpReadInfo[channel].pDoneSemaphore);
|
||||||
|
sprintf(semName,"/semaphore_done%d",channel);
|
||||||
|
sem_unlink(semName);
|
||||||
#endif
|
#endif
|
||||||
free(gpReadInfo);
|
if (gpReadInfo)
|
||||||
|
free(gpReadInfo);
|
||||||
|
gpReadInfo = nil;
|
||||||
pthread_exit(nil);
|
pthread_exit(nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,7 +485,7 @@ CdStreamAddImage(char const *path)
|
|||||||
char* real = casepath(path, false);
|
char* real = casepath(path, false);
|
||||||
if (real)
|
if (real)
|
||||||
{
|
{
|
||||||
gImgFiles[gNumImages] = open(real, _gdwCdStreamFlags);
|
gImgFiles[gNumImages] = open(real, _gdwCdStreamFlags);
|
||||||
free(real);
|
free(real);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -506,8 +518,10 @@ CdStreamGetImageName(int32 cd)
|
|||||||
void
|
void
|
||||||
CdStreamRemoveImages(void)
|
CdStreamRemoveImages(void)
|
||||||
{
|
{
|
||||||
for ( int32 i = 0; i < gNumChannels; i++ )
|
for ( int32 i = 0; i < gNumChannels; i++ ) {
|
||||||
|
flushStream[i] = 1;
|
||||||
CdStreamSync(i);
|
CdStreamSync(i);
|
||||||
|
}
|
||||||
|
|
||||||
for ( int32 i = 0; i < gNumImages; i++ )
|
for ( int32 i = 0; i < gNumImages; i++ )
|
||||||
{
|
{
|
||||||
|
@ -980,7 +980,11 @@ CFileLoader::Load2dEffect(const char *line)
|
|||||||
&effect->attractor.dir.z,
|
&effect->attractor.dir.z,
|
||||||
&probability);
|
&probability);
|
||||||
effect->attractor.type = flags;
|
effect->attractor.type = flags;
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
effect->attractor.probability = clamp(probability, 0, 255);
|
||||||
|
#else
|
||||||
effect->attractor.probability = probability;
|
effect->attractor.probability = probability;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,17 +142,17 @@ static size_t
|
|||||||
myfread(void *buf, size_t elt, size_t n, int fd)
|
myfread(void *buf, size_t elt, size_t n, int fd)
|
||||||
{
|
{
|
||||||
if(myfiles[fd].isText){
|
if(myfiles[fd].isText){
|
||||||
char *p;
|
unsigned char *p;
|
||||||
size_t i;
|
size_t i;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
n *= elt;
|
n *= elt;
|
||||||
p = (char*)buf;
|
p = (unsigned char*)buf;
|
||||||
for(i = 0; i < n; i++){
|
for(i = 0; i < n; i++){
|
||||||
c = myfgetc(fd);
|
c = myfgetc(fd);
|
||||||
if(c == EOF)
|
if(c == EOF)
|
||||||
break;
|
break;
|
||||||
*p++ = c;
|
*p++ = (unsigned char)c;
|
||||||
}
|
}
|
||||||
return i / elt;
|
return i / elt;
|
||||||
}
|
}
|
||||||
@ -163,12 +163,12 @@ static size_t
|
|||||||
myfwrite(void *buf, size_t elt, size_t n, int fd)
|
myfwrite(void *buf, size_t elt, size_t n, int fd)
|
||||||
{
|
{
|
||||||
if(myfiles[fd].isText){
|
if(myfiles[fd].isText){
|
||||||
char *p;
|
unsigned char *p;
|
||||||
size_t i;
|
size_t i;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
n *= elt;
|
n *= elt;
|
||||||
p = (char*)buf;
|
p = (unsigned char*)buf;
|
||||||
for(i = 0; i < n; i++){
|
for(i = 0; i < n; i++){
|
||||||
c = *p++;
|
c = *p++;
|
||||||
myfputc(c, fd);
|
myfputc(c, fd);
|
||||||
|
@ -45,7 +45,11 @@ CStreamingInfo CStreaming::ms_endRequestedList;
|
|||||||
int32 CStreaming::ms_oldSectorX;
|
int32 CStreaming::ms_oldSectorX;
|
||||||
int32 CStreaming::ms_oldSectorY;
|
int32 CStreaming::ms_oldSectorY;
|
||||||
int32 CStreaming::ms_streamingBufferSize;
|
int32 CStreaming::ms_streamingBufferSize;
|
||||||
|
#ifndef ONE_THREAD_PER_CHANNEL
|
||||||
int8 *CStreaming::ms_pStreamingBuffer[2];
|
int8 *CStreaming::ms_pStreamingBuffer[2];
|
||||||
|
#else
|
||||||
|
int8 *CStreaming::ms_pStreamingBuffer[4];
|
||||||
|
#endif
|
||||||
size_t CStreaming::ms_memoryUsed;
|
size_t CStreaming::ms_memoryUsed;
|
||||||
CStreamingChannel CStreaming::ms_channel[2];
|
CStreamingChannel CStreaming::ms_channel[2];
|
||||||
int32 CStreaming::ms_channelError;
|
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_pStreamingBuffer[0] = (int8*)RwMallocAlign(ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE);
|
||||||
ms_streamingBufferSize /= 2;
|
ms_streamingBufferSize /= 2;
|
||||||
ms_pStreamingBuffer[1] = ms_pStreamingBuffer[0] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE;
|
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);
|
debug("Streaming buffer size is %d sectors", ms_streamingBufferSize);
|
||||||
|
|
||||||
// PC only, figure out how much memory we got
|
// 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
|
void
|
||||||
CStreaming::LoadAllRequestedModels(bool priority)
|
CStreaming::LoadAllRequestedModels(bool priority)
|
||||||
{
|
{
|
||||||
@ -1883,6 +1994,7 @@ CStreaming::LoadAllRequestedModels(bool priority)
|
|||||||
ms_channel[1].state = CHANNELSTATE_IDLE;
|
ms_channel[1].state = CHANNELSTATE_IDLE;
|
||||||
bInsideLoadAll = false;
|
bInsideLoadAll = false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
CStreaming::FlushChannels(void)
|
CStreaming::FlushChannels(void)
|
||||||
@ -1914,6 +2026,14 @@ CStreaming::FlushRequestList(void)
|
|||||||
next = si->m_next;
|
next = si->m_next;
|
||||||
RemoveModel(si - ms_aInfoForModel);
|
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();
|
FlushChannels();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ typedef uint16_t wchar;
|
|||||||
inline uint32 dpb(uint32 b, uint32 p, uint32 s, uint32 w)
|
inline uint32 dpb(uint32 b, uint32 p, uint32 s, uint32 w)
|
||||||
{
|
{
|
||||||
uint32 m = MASK(p,s);
|
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)
|
inline uint32 ldb(uint32 p, uint32 s, uint32 w)
|
||||||
{
|
{
|
||||||
|
@ -56,7 +56,7 @@ GetNumberOfMenuOptions(int screen)
|
|||||||
uint8
|
uint8
|
||||||
GetLastMenuScreen()
|
GetLastMenuScreen()
|
||||||
{
|
{
|
||||||
uint8 page = -1;
|
int8 page = -1;
|
||||||
for (int i = 0; i < MENUPAGES; i++) {
|
for (int i = 0; i < MENUPAGES; i++) {
|
||||||
if (strcmp(aScreens[i].m_ScreenName, "") == 0 && aScreens[i].unk == 0)
|
if (strcmp(aScreens[i].m_ScreenName, "") == 0 && aScreens[i].unk == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -22,8 +22,13 @@ uint32 CTheCarGenerators::CurrentActiveCount;
|
|||||||
|
|
||||||
void CCarGenerator::SwitchOff()
|
void CCarGenerator::SwitchOff()
|
||||||
{
|
{
|
||||||
m_nUsesRemaining = 0;
|
#ifdef FIX_BUGS
|
||||||
--CTheCarGenerators::CurrentActiveCount;
|
if (m_nUsesRemaining != 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
m_nUsesRemaining = 0;
|
||||||
|
--CTheCarGenerators::CurrentActiveCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCarGenerator::SwitchOn()
|
void CCarGenerator::SwitchOn()
|
||||||
|
@ -111,7 +111,7 @@ public:
|
|||||||
CAutoPilot AutoPilot;
|
CAutoPilot AutoPilot;
|
||||||
uint8 m_currentColour1;
|
uint8 m_currentColour1;
|
||||||
uint8 m_currentColour2;
|
uint8 m_currentColour2;
|
||||||
uint8 m_aExtras[2];
|
int8 m_aExtras[2];
|
||||||
int16 m_nAlarmState;
|
int16 m_nAlarmState;
|
||||||
int16 m_nMissionValue;
|
int16 m_nMissionValue;
|
||||||
CPed *pDriver;
|
CPed *pDriver;
|
||||||
|
@ -160,17 +160,17 @@ CWeaponInfo::LoadWeaponData(void)
|
|||||||
ms_apWeaponInfos[weaponType].m_fAnimFrameFire = delayBetweenAnimAndFire / 30.0f;
|
ms_apWeaponInfos[weaponType].m_fAnimFrameFire = delayBetweenAnimAndFire / 30.0f;
|
||||||
ms_apWeaponInfos[weaponType].m_fAnim2FrameFire = delayBetweenAnim2AndFire / 30.0f;
|
ms_apWeaponInfos[weaponType].m_fAnim2FrameFire = delayBetweenAnim2AndFire / 30.0f;
|
||||||
ms_apWeaponInfos[weaponType].m_nModelId = modelId;
|
ms_apWeaponInfos[weaponType].m_nModelId = modelId;
|
||||||
ms_apWeaponInfos[weaponType].m_bUseGravity = flags;
|
ms_apWeaponInfos[weaponType].m_bUseGravity = flags & 1;
|
||||||
ms_apWeaponInfos[weaponType].m_bSlowsDown = flags >> 1;
|
ms_apWeaponInfos[weaponType].m_bSlowsDown = (flags >> 1) & 1;
|
||||||
ms_apWeaponInfos[weaponType].m_bDissipates = flags >> 2;
|
ms_apWeaponInfos[weaponType].m_bDissipates = (flags >> 2) & 1;
|
||||||
ms_apWeaponInfos[weaponType].m_bRandSpeed = flags >> 3;
|
ms_apWeaponInfos[weaponType].m_bRandSpeed = (flags >> 3) & 1;
|
||||||
ms_apWeaponInfos[weaponType].m_bExpands = flags >> 4;
|
ms_apWeaponInfos[weaponType].m_bExpands = (flags >> 4) & 1;
|
||||||
ms_apWeaponInfos[weaponType].m_bExplodes = flags >> 5;
|
ms_apWeaponInfos[weaponType].m_bExplodes = (flags >> 5) & 1;
|
||||||
ms_apWeaponInfos[weaponType].m_bCanAim = flags >> 6;
|
ms_apWeaponInfos[weaponType].m_bCanAim = (flags >> 6) & 1;
|
||||||
ms_apWeaponInfos[weaponType].m_bCanAimWithArm = flags >> 7;
|
ms_apWeaponInfos[weaponType].m_bCanAimWithArm = (flags >> 7) & 1;
|
||||||
ms_apWeaponInfos[weaponType].m_b1stPerson = flags >> 8;
|
ms_apWeaponInfos[weaponType].m_b1stPerson = (flags >> 8) & 1;
|
||||||
ms_apWeaponInfos[weaponType].m_bHeavy = flags >> 9;
|
ms_apWeaponInfos[weaponType].m_bHeavy = (flags >> 9) & 1;
|
||||||
ms_apWeaponInfos[weaponType].m_bThrow = flags >> 10;
|
ms_apWeaponInfos[weaponType].m_bThrow = (flags >> 10) & 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user