diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/CdStreamPosix.cpp | 302 | ||||
-rw-r--r-- | src/core/FileLoader.cpp | 4 | ||||
-rw-r--r-- | src/core/FileMgr.cpp | 10 | ||||
-rw-r--r-- | src/core/Fire.cpp | 118 | ||||
-rw-r--r-- | src/core/Fire.h | 12 | ||||
-rw-r--r-- | src/core/Game.cpp | 6 | ||||
-rw-r--r-- | src/core/General.h | 2 | ||||
-rw-r--r-- | src/core/Pad.cpp | 6 | ||||
-rw-r--r-- | src/core/Streaming.cpp | 134 | ||||
-rw-r--r-- | src/core/User.cpp | 2 | ||||
-rw-r--r-- | src/core/Zones.cpp | 191 | ||||
-rw-r--r-- | src/core/Zones.h | 2 | ||||
-rw-r--r-- | src/core/common.h | 42 | ||||
-rw-r--r-- | src/core/config.h | 10 |
14 files changed, 551 insertions, 290 deletions
diff --git a/src/core/CdStreamPosix.cpp b/src/core/CdStreamPosix.cpp index e114a29a..a6ab62bc 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 } @@ -241,27 +240,33 @@ CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size) CdReadInfo *pChannel = &gpReadInfo[channel]; ASSERT( pChannel != nil ); - pChannel->hFile = hImage - 1; - if ( pChannel->nSectorsToRead != 0 || pChannel->bReading ) - return STREAM_NONE; + if ( pChannel->nSectorsToRead != 0 || pChannel->bReading ) { + if (pChannel->nSectorOffset == _GET_OFFSET(offset) && pChannel->nSectorsToRead >= size) + return STREAM_SUCCESS; + + 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->hFile = hImage - 1; + 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 +277,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 +319,35 @@ CdStreamSync(int32 channel) if (flushStream[channel]) { #ifdef ONE_THREAD_PER_CHANNEL pChannel->nSectorsToRead = 0; - pthread_kill(gpReadInfo[channel].pChannelThread, SIGINT); + pthread_kill(pChannel->pChannelThread, SIGUSR1); + if (pChannel->bReading) { + pChannel->bLocked = true; + sem_wait(pChannel->pDoneSemaphore); + } #else + pChannel->nSectorsToRead = 0; if (pChannel->bReading) { - pChannel->nSectorsToRead = 0; - pthread_kill(_gCdStreamThread, SIGINT); - } else { - pChannel->nSectorsToRead = 0; + pChannel->bLocked = true; + pthread_kill(_gCdStreamThread, SIGUSR1); + 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 +392,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 +446,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 +489,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 +522,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/Fire.cpp b/src/core/Fire.cpp index a6928def..5b57cb73 100644 --- a/src/core/Fire.cpp +++ b/src/core/Fire.cpp @@ -16,6 +16,9 @@ #include "Ped.h" #include "Fire.h" #include "GameLogic.h" +#include "CarAI.h" + +// --MIAMI: file done CFireManager gFireManager; @@ -26,14 +29,13 @@ CFire::CFire() m_bPropagationFlag = true; m_bAudioSet = true; m_vecPos = CVector(0.0f, 0.0f, 0.0f); - m_pEntity = nil; - m_pSource = nil; - m_nFiremenPuttingOut = 0; m_nExtinguishTime = 0; m_nStartTime = 0; - field_20 = 1; - m_nNextTimeToAddFlames = 0; + m_pEntity = nil; + m_pSource = nil; m_fStrength = 0.8f; + m_fWaterExtinguishCountdown = 1.0f; + m_bExtinguishedWithWater = false; } CFire::~CFire() {} @@ -52,6 +54,8 @@ CFire::ProcessFire(void) CPed *ped = (CPed *)m_pEntity; CVehicle *veh = (CVehicle*)m_pEntity; + m_fWaterExtinguishCountdown = Min(1.0f, 0.002f * CTimer::GetTimeStep() + m_fWaterExtinguishCountdown); + if (m_pEntity) { m_vecPos = m_pEntity->GetPosition(); @@ -109,7 +113,7 @@ CFire::ProcessFire(void) gFireManager.StartFire(FindPlayerPed(), m_pSource, 0.8f, 1); } if (CTimer::GetTimeInMilliseconds() > m_nNextTimeToAddFlames) { - m_nNextTimeToAddFlames = CTimer::GetTimeInMilliseconds() + 80; + m_nNextTimeToAddFlames = CTimer::GetTimeInMilliseconds() + (m_fWaterExtinguishCountdown < 0.3f ? 400 : (m_fWaterExtinguishCountdown < 0.7f ? 200 : 80)); firePos = m_vecPos; if (veh && veh->IsVehicle() && veh->IsCar()) { @@ -170,11 +174,23 @@ CFire::Extinguish(void) m_nExtinguishTime = 0; m_bIsOngoing = false; + m_bExtinguishedWithWater = false; if (m_pEntity) { if (m_pEntity->IsPed()) { - ((CPed *)m_pEntity)->RestorePreviousState(); - ((CPed *)m_pEntity)->m_pFire = nil; + CPed *ped = (CPed*)m_pEntity; + if (ped->CanSetPedState()) { + if (ped->m_nPedState != PED_DRIVING && ped->m_nPedState != PED_FALL) { + if (ped->IsPlayer()) { + ped->SetIdle(); + } else { + ped->m_nLastPedState = PED_NONE; + ped->SetWanderPath(0); + ped->SetWaitState(WAITSTATE_FINISH_FLEE, 0); + } + } + } + ped->m_pFire = nil; } else if (m_pEntity->IsVehicle()) { ((CVehicle *)m_pEntity)->m_pCarFire = nil; } @@ -184,7 +200,7 @@ CFire::Extinguish(void) } void -CFireManager::StartFire(CVector pos, float size, bool propagation) +CFireManager::StartFire(CVector pos, float size, uint8 propagation) { CFire *fire = GetNextFreeFire(); @@ -201,11 +217,12 @@ CFireManager::StartFire(CVector pos, float size, bool propagation) fire->m_nNextTimeToAddFlames = 0; fire->ReportThisFire(); fire->m_fStrength = size; + fire->m_bExtinguishedWithWater = false; } } CFire * -CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, bool propagation) +CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, uint8 propagation) { CPed *ped = (CPed *)entityOnFire; CVehicle *veh = (CVehicle *)entityOnFire; @@ -234,10 +251,11 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength ped->SetFlee(pos, 10000); ped->m_fleeFrom = nil; } + ped->m_fleeTimer = CTimer::GetTimeInMilliseconds() + 10000; ped->bDrawLast = false; ped->SetMoveState(PEDMOVE_SPRINT); ped->SetMoveAnim(); - ped->m_nPedState = PED_ON_FIRE; + ped->SetPedState(PED_ON_FIRE); } if (fleeFrom) { if (ped->m_nPedType == PEDTYPE_COP) { @@ -251,6 +269,9 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength } else { if (entityOnFire->IsVehicle()) { veh->m_pCarFire = fire; + if (CModelInfo::IsBikeModel(veh->GetModelIndex()) || CModelInfo::IsCarModel(veh->GetModelIndex())) + CCarAI::TellOccupantsToFleeCar(veh); + if (fleeFrom) { CEventList::RegisterEvent(EVENT_CAR_SET_ON_FIRE, EVENT_ENTITY_VEHICLE, entityOnFire, (CPed *)fleeFrom, 10000); @@ -259,6 +280,7 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength } fire->m_bIsOngoing = true; + fire->m_bExtinguishedWithWater = false; fire->m_bIsScriptFire = false; fire->m_vecPos = entityOnFire->GetPosition(); @@ -297,26 +319,23 @@ CFireManager::Update(void) CFire* CFireManager::FindNearestFire(CVector vecPos, float *pDistance) { - for (int i = 0; i < MAX_FIREMEN_ATTENDING; i++) { - int fireId = -1; - float minDistance = 999999; - for (int j = 0; j < NUM_FIRES; j++) { - if (!m_aFires[j].m_bIsOngoing) - continue; - if (m_aFires[j].m_bIsScriptFire) - continue; - if (m_aFires[j].m_nFiremenPuttingOut != i) - continue; - float distance = (m_aFires[j].m_vecPos - vecPos).Magnitude2D(); - if (distance < minDistance) { - minDistance = distance; - fireId = j; - } + int fireId = -1; + float minDistance = 999999; + for (int j = 0; j < NUM_FIRES; j++) { + if (!m_aFires[j].m_bIsOngoing) + continue; + if (m_aFires[j].m_bIsScriptFire) + continue; + float distance = (m_aFires[j].m_vecPos - vecPos).Magnitude2D(); + if (distance < minDistance) { + minDistance = distance; + fireId = j; } - *pDistance = minDistance; - if (fireId != -1) - return &m_aFires[fireId]; } + *pDistance = minDistance; + if (fireId != -1) + return &m_aFires[fireId]; + return nil; } @@ -369,8 +388,39 @@ CFireManager::ExtinguishPoint(CVector point, float range) } } +bool +CFireManager::ExtinguishPointWithWater(CVector point, float range) +{ + int fireI = 0; + for (int i = 0; i < NUM_FIRES; i++) { + if (m_aFires[i].m_bIsOngoing) { + if ((point - m_aFires[i].m_vecPos).MagnitudeSqr() < sq(range)) { + fireI = i; + break; + } + } + } + if (fireI == NUM_FIRES) + return false; + + CFire *fireToExtinguish = &m_aFires[fireI]; + fireToExtinguish->m_fWaterExtinguishCountdown -= 0.012f * CTimer::GetTimeStep(); + CVector steamPos = fireToExtinguish->m_vecPos + + CVector((CGeneral::GetRandomNumber() - 128) * 31.f / 200.f, + (CGeneral::GetRandomNumber() - 128) * 31.f / 200.f, + CGeneral::GetRandomNumber() / 200.f); + + CParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, steamPos, CVector(0.f, 0.f, 0.2f), nil, 0.5f); + CParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, steamPos, CVector(0.f, 0.f, 0.1f), nil, 0.8f); + fireToExtinguish->m_bExtinguishedWithWater = true; + if (fireToExtinguish->m_fWaterExtinguishCountdown < 0.0f ) + fireToExtinguish->Extinguish(); + + return true; +} + int32 -CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strength, bool propagation) +CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strength, uint8 propagation) { CFire *fire; CPed *ped = (CPed *)target; @@ -397,12 +447,15 @@ CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strengt fire->m_vecPos = pos; fire->m_nStartTime = CTimer::GetTimeInMilliseconds() + 400; fire->m_pEntity = target; + fire->m_bExtinguishedWithWater = false; if (target) target->RegisterReference(&fire->m_pEntity); fire->m_pSource = nil; fire->m_nNextTimeToAddFlames = 0; fire->m_fStrength = strength; + fire->m_fWaterExtinguishCountdown = 1.0f; + if (target) { if (target->IsPed()) { ped->m_pFire = fire; @@ -410,7 +463,7 @@ CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strengt CVector2D pos = target->GetPosition(); ped->SetFlee(pos, 10000); ped->SetMoveAnim(); - ped->m_nPedState = PED_ON_FIRE; + ped->SetPedState(PED_ON_FIRE); } } else if (target->IsVehicle()) { veh->m_pCarFire = fire; @@ -430,8 +483,7 @@ CFireManager::RemoveAllScriptFires(void) { for (int i = 0; i < NUM_FIRES; i++) { if (m_aFires[i].m_bIsScriptFire) { - m_aFires[i].Extinguish(); - m_aFires[i].m_bIsScriptFire = false; + RemoveScriptFire(i); } } } diff --git a/src/core/Fire.h b/src/core/Fire.h index 85e53f61..8126f830 100644 --- a/src/core/Fire.h +++ b/src/core/Fire.h @@ -14,10 +14,10 @@ public: CEntity *m_pSource; uint32 m_nExtinguishTime; uint32 m_nStartTime; - int32 field_20; uint32 m_nNextTimeToAddFlames; - uint32 m_nFiremenPuttingOut; float m_fStrength; + float m_fWaterExtinguishCountdown; + bool m_bExtinguishedWithWater; CFire(); ~CFire(); @@ -34,15 +34,17 @@ class CFireManager public: uint32 m_nTotalFires; CFire m_aFires[NUM_FIRES]; - void StartFire(CVector pos, float size, bool propagation); - CFire *StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, bool propagation); + + void StartFire(CVector pos, float size, uint8 propagation); + CFire *StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, uint8 propagation); void Update(void); CFire *FindFurthestFire_NeverMindFireMen(CVector coords, float minRange, float maxRange); CFire *FindNearestFire(CVector vecPos, float *pDistance); CFire *GetNextFreeFire(void); uint32 GetTotalActiveFires() const; void ExtinguishPoint(CVector point, float range); - int32 StartScriptFire(const CVector &pos, CEntity *target, float strength, bool propagation); + bool ExtinguishPointWithWater(CVector point, float range); + int32 StartScriptFire(const CVector &pos, CEntity *target, float strength, uint8 propagation); bool IsScriptFireExtinguish(int16 index); void RemoveAllScriptFires(void); void RemoveScriptFire(int16 index); diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 6ba6b191..a8637980 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -90,6 +90,7 @@ #include "debugmenu.h" #include "Ropes.h" #include "WindModifiers.h" +#include "WaterCreatures.h" #include "postfx.h" #include "custompipes.h" @@ -478,8 +479,7 @@ bool CGame::ShutDown(void) CPlane::Shutdown(); CTrain::Shutdown(); CScriptPaths::Shutdown(); - // TODO(Miami) - // CWaterCreatures::RemoveAll(); + CWaterCreatures::RemoveAll(); CSpecialFX::Shutdown(); #ifndef PS2 CGarages::Shutdown(); @@ -650,7 +650,7 @@ void CGame::ShutDownForRestart(void) CRadar::RemoveRadarSections(); FrontEndMenuManager.UnloadTextures(); CParticleObject::RemoveAllExpireableParticleObjects(); - //CWaterCreatures::RemoveAll(); //TODO(Miami) + CWaterCreatures::RemoveAll(); CSetPieces::Init(); CPedType::Shutdown(); CSpecialFX::Shutdown(); diff --git a/src/core/General.h b/src/core/General.h index 7ab444a4..7e06b96e 100644 --- a/src/core/General.h +++ b/src/core/General.h @@ -2,6 +2,8 @@ #include <ctype.h> +// --MIAMI: file done + class CGeneral { public: diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index aa6e5cc8..b723eb1d 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -3209,7 +3209,7 @@ int16 CPad::SniperModeLookLeftRight(void) if ( Abs(axis) > Abs(dpad) ) { if ( Abs(axis) > 35.0f ) { - return (axis > 0.f ? axis - 35.f : axis + 35.f) * 1.3763441f; + return (axis > 0.f ? axis - 35.f : axis + 35.f) * (128.f / (128 - 35)); } else { return 0; } @@ -3231,7 +3231,7 @@ int16 CPad::SniperModeLookUpDown(void) if ( Abs(axis) > Abs(dpad) ) { if ( Abs(axis) > 35.0f ) { - return (axis > 0.f ? axis - 35.f : axis + 35.f) * 1.3763441f; + return (axis > 0.f ? axis - 35.f : axis + 35.f) * (128.f / (128 - 35)); } else { return 0; } @@ -3573,4 +3573,4 @@ void CPad::FixPadsAfterSave(void) bObsoleteControllerMessage = false; GetPad(0)->Phase = 0; } -}
\ No newline at end of file +} 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/User.cpp b/src/core/User.cpp index 53196d03..8d584b74 100644 --- a/src/core/User.cpp +++ b/src/core/User.cpp @@ -10,6 +10,8 @@ #include "World.h" #include "Zones.h" +// --MIAMI: file done + CPlaceName CUserDisplay::PlaceName; COnscreenTimer CUserDisplay::OnscnTimer; CPager CUserDisplay::Pager; diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp index 1eb1513e..288b975e 100644 --- a/src/core/Zones.cpp +++ b/src/core/Zones.cpp @@ -9,7 +9,7 @@ #include "World.h" #include "Timer.h" -//--MIAMI: file almost done (loading/saving will perhaps stay different) +//--MIAMI: file done eLevelName CTheZones::m_CurrLevel; int16 CTheZones::FindIndex; @@ -638,127 +638,132 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size) + sizeof(int16) // padding + sizeof(NavigationZoneArray) + sizeof(InfoZoneArray) + sizeof(ZoneInfoArray) + sizeof(TotalNumberOfNavigationZones) + sizeof(TotalNumberOfInfoZones) + sizeof(TotalNumberOfZoneInfos) + + sizeof(int16) // padding + sizeof(MapZoneArray) + sizeof(AudioZoneArray) + sizeof(TotalNumberOfMapZones) + sizeof(NumberOfAudioZones); - WriteSaveHeader(buffer, 'Z', 'N', 'S', '\0', *size - SAVE_HEADER_SIZE); + uint32 length = 0; + WriteSaveHeaderWithLength(buffer, length, 'Z', 'N', 'S', '\0', *size - SAVE_HEADER_SIZE); - WriteSaveBuf(buffer, m_CurrLevel); - WriteSaveBuf(buffer, FindIndex); - WriteSaveBuf(buffer, (int16)0); // padding + WriteSaveBuf(buffer, length, m_CurrLevel); + WriteSaveBuf(buffer, length, FindIndex); + WriteSaveBuf(buffer, length, (int16)0); // padding -// TODO(MIAMI) ? implement SaveOneZone - for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++){ - CZone *zone = WriteSaveBuf(buffer, NavigationZoneArray[i]); - zone->child = (CZone*)GetIndexForZonePointer(NavigationZoneArray[i].child); - zone->parent = (CZone*)GetIndexForZonePointer(NavigationZoneArray[i].parent); - zone->next = (CZone*)GetIndexForZonePointer(NavigationZoneArray[i].next); - } + for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++) + SaveOneZone(&NavigationZoneArray[i], &buffer, &length, ZONE_NAVIG); - for(i = 0; i < ARRAY_SIZE(InfoZoneArray); i++){ - CZone *zone = WriteSaveBuf(buffer, InfoZoneArray[i]); - /* - The call of GetIndexForZonePointer is wrong, as it is - meant for a different array, but the game doesn't brake - if those fields are nil. Let's make sure they are. - */ - assert(InfoZoneArray[i].child == nil); - assert(InfoZoneArray[i].parent == nil); - assert(InfoZoneArray[i].next == nil); - zone->child = (CZone*)GetIndexForZonePointer(InfoZoneArray[i].child); - zone->parent = (CZone*)GetIndexForZonePointer(InfoZoneArray[i].parent); - zone->next = (CZone*)GetIndexForZonePointer(InfoZoneArray[i].next); - } + for(i = 0; i < ARRAY_SIZE(InfoZoneArray); i++) + SaveOneZone(&InfoZoneArray[i], &buffer, &length, ZONE_INFO); for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) - WriteSaveBuf(buffer, ZoneInfoArray[i]); - - WriteSaveBuf(buffer, TotalNumberOfNavigationZones); - WriteSaveBuf(buffer, TotalNumberOfInfoZones); - WriteSaveBuf(buffer, TotalNumberOfZoneInfos); - - for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) { - CZone* zone = WriteSaveBuf(buffer, MapZoneArray[i]); - - // see above - assert(MapZoneArray[i].child == nil); - assert(MapZoneArray[i].parent == nil); - assert(MapZoneArray[i].next == nil); - zone->child = (CZone*)GetIndexForZonePointer(MapZoneArray[i].child); - zone->parent = (CZone*)GetIndexForZonePointer(MapZoneArray[i].parent); - zone->next = (CZone*)GetIndexForZonePointer(MapZoneArray[i].next); - } + WriteSaveBuf(buffer, length, ZoneInfoArray[i]); + + WriteSaveBuf(buffer, length, TotalNumberOfNavigationZones); + WriteSaveBuf(buffer, length, TotalNumberOfInfoZones); + WriteSaveBuf(buffer, length, TotalNumberOfZoneInfos); + WriteSaveBuf(buffer, length, (int16)0); // padding + + for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) + SaveOneZone(&MapZoneArray[i], &buffer, &length, ZONE_MAPZONE); for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++) - WriteSaveBuf(buffer, AudioZoneArray[i]); + WriteSaveBuf(buffer, length, AudioZoneArray[i]); - WriteSaveBuf(buffer, TotalNumberOfMapZones); - WriteSaveBuf(buffer, NumberOfAudioZones); + WriteSaveBuf(buffer, length, TotalNumberOfMapZones); + WriteSaveBuf(buffer, length, NumberOfAudioZones); VALIDATESAVEBUF(*size) } void +CTheZones::SaveOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType) +{ + WriteSaveBuf(*buffer, *length, *(uint32*)&zone->name[0]); + WriteSaveBuf(*buffer, *length, *(uint32*)&zone->name[4]); + + WriteSaveBuf(*buffer, *length, zone->minx); + WriteSaveBuf(*buffer, *length, zone->miny); + WriteSaveBuf(*buffer, *length, zone->minz); + WriteSaveBuf(*buffer, *length, zone->maxx); + WriteSaveBuf(*buffer, *length, zone->maxy); + WriteSaveBuf(*buffer, *length, zone->maxz); + + WriteSaveBuf(*buffer, *length, zone->type); + WriteSaveBuf(*buffer, *length, zone->level); + WriteSaveBuf(*buffer, *length, zone->zoneinfoDay); + WriteSaveBuf(*buffer, *length, zone->zoneinfoNight); + + int32 zoneId; + zoneId = GetIndexForZonePointer(zone->child); + WriteSaveBuf(*buffer, *length, zoneId); + zoneId = GetIndexForZonePointer(zone->parent); + WriteSaveBuf(*buffer, *length, zoneId); + zoneId = GetIndexForZonePointer(zone->next); + WriteSaveBuf(*buffer, *length, zoneId); +} + +void CTheZones::LoadAllZones(uint8 *buffer, uint32 size) { INITSAVEBUF int i; - CheckSaveHeader(buffer, 'Z', 'N', 'S', '\0', size - SAVE_HEADER_SIZE); + uint32 length = 0; + CheckSaveHeaderWithLength(buffer, length, 'Z', 'N', 'S', '\0', size - SAVE_HEADER_SIZE); - m_CurrLevel = ReadSaveBuf<eLevelName>(buffer); - FindIndex = ReadSaveBuf<int16>(buffer); - ReadSaveBuf<int16>(buffer); + m_CurrLevel = ReadSaveBuf<eLevelName>(buffer, length); + FindIndex = ReadSaveBuf<int16>(buffer, length); + ReadSaveBuf<int16>(buffer, length); -// TODO(MIAMI) ? implement LoadOneZone - for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++){ - NavigationZoneArray[i] = ReadSaveBuf<CZone>(buffer); + for(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++) + LoadOneZone(&NavigationZoneArray[i], &buffer, &length, ZONE_NAVIG); - NavigationZoneArray[i].child = GetPointerForZoneIndex((uintptr)NavigationZoneArray[i].child); - NavigationZoneArray[i].parent = GetPointerForZoneIndex((uintptr)NavigationZoneArray[i].parent); - NavigationZoneArray[i].next = GetPointerForZoneIndex((uintptr)NavigationZoneArray[i].next); - } - - for(i = 0; i < ARRAY_SIZE(InfoZoneArray); i++){ - InfoZoneArray[i] = ReadSaveBuf<CZone>(buffer); - - /* - The call of GetPointerForZoneIndex is wrong, as it is - meant for a different array, but the game doesn't brake - if save data stored is -1. - */ - InfoZoneArray[i].child = GetPointerForZoneIndex((uintptr)InfoZoneArray[i].child); - InfoZoneArray[i].parent = GetPointerForZoneIndex((uintptr)InfoZoneArray[i].parent); - InfoZoneArray[i].next = GetPointerForZoneIndex((uintptr)InfoZoneArray[i].next); - assert(InfoZoneArray[i].child == nil); - assert(InfoZoneArray[i].parent == nil); - assert(InfoZoneArray[i].next == nil); - } + for (i = 0; i < ARRAY_SIZE(InfoZoneArray); i++) + LoadOneZone(&InfoZoneArray[i], &buffer, &length, ZONE_INFO); for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) - ZoneInfoArray[i] = ReadSaveBuf<CZoneInfo>(buffer); - - TotalNumberOfNavigationZones = ReadSaveBuf<int16>(buffer); - TotalNumberOfInfoZones = ReadSaveBuf<int16>(buffer); - TotalNumberOfZoneInfos = ReadSaveBuf<int16>(buffer); - - for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++){ - MapZoneArray[i] = ReadSaveBuf<CZone>(buffer); - - // see above - MapZoneArray[i].child = GetPointerForZoneIndex((uintptr)MapZoneArray[i].child); - MapZoneArray[i].parent = GetPointerForZoneIndex((uintptr)MapZoneArray[i].parent); - MapZoneArray[i].next = GetPointerForZoneIndex((uintptr)MapZoneArray[i].next); - assert(MapZoneArray[i].child == nil); - assert(MapZoneArray[i].parent == nil); - assert(MapZoneArray[i].next == nil); - } + ZoneInfoArray[i] = ReadSaveBuf<CZoneInfo>(buffer, length); + + TotalNumberOfNavigationZones = ReadSaveBuf<int16>(buffer, length); + TotalNumberOfInfoZones = ReadSaveBuf<int16>(buffer, length); + TotalNumberOfZoneInfos = ReadSaveBuf<int16>(buffer, length); + ReadSaveBuf<int16>(buffer, length); + + for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) + LoadOneZone(&MapZoneArray[i], &buffer, &length, ZONE_MAPZONE); for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++) - AudioZoneArray[i] = ReadSaveBuf<int16>(buffer); + AudioZoneArray[i] = ReadSaveBuf<int16>(buffer, length); - TotalNumberOfMapZones = ReadSaveBuf<uint16>(buffer); - NumberOfAudioZones = ReadSaveBuf<uint16>(buffer); + TotalNumberOfMapZones = ReadSaveBuf<uint16>(buffer, length); + NumberOfAudioZones = ReadSaveBuf<uint16>(buffer, length); VALIDATESAVEBUF(size) } + +void +CTheZones::LoadOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType) +{ + *(uint32*)&zone->name[0] = ReadSaveBuf<uint32>(*buffer, *length); + *(uint32*)&zone->name[4] = ReadSaveBuf<uint32>(*buffer, *length); + + zone->minx = ReadSaveBuf<float>(*buffer, *length); + zone->miny = ReadSaveBuf<float>(*buffer, *length); + zone->minz = ReadSaveBuf<float>(*buffer, *length); + zone->maxx = ReadSaveBuf<float>(*buffer, *length); + zone->maxy = ReadSaveBuf<float>(*buffer, *length); + zone->maxz = ReadSaveBuf<float>(*buffer, *length); + + zone->type = ReadSaveBuf<eZoneType>(*buffer, *length); + zone->level = ReadSaveBuf<eLevelName>(*buffer, *length); + zone->zoneinfoDay = ReadSaveBuf<int16>(*buffer, *length); + zone->zoneinfoNight = ReadSaveBuf<int16>(*buffer, *length); + + int32 zoneId; + zoneId = ReadSaveBuf<int32>(*buffer, *length); + zone->child = GetPointerForZoneIndex(zoneId); + zoneId = ReadSaveBuf<int32>(*buffer, *length); + zone->parent = GetPointerForZoneIndex(zoneId); + zoneId = ReadSaveBuf<int32>(*buffer, *length); + zone->next = GetPointerForZoneIndex(zoneId); +}
\ No newline at end of file diff --git a/src/core/Zones.h b/src/core/Zones.h index 92e292b8..3a74427d 100644 --- a/src/core/Zones.h +++ b/src/core/Zones.h @@ -108,5 +108,7 @@ public: static void AddZoneToAudioZoneArray(CZone *zone); static void InitialiseAudioZoneArray(void); static void SaveAllZones(uint8 *buffer, uint32 *length); + static void SaveOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType); static void LoadAllZones(uint8 *buffer, uint32 length); + static void LoadOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType); }; diff --git a/src/core/common.h b/src/core/common.h index 16d32b32..0e6bd60f 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) { @@ -412,6 +412,15 @@ inline void SkipSaveBuf(uint8 *&buf, int32 skip) #endif } +inline void SkipSaveBuf(uint8*& buf, uint32 &length, int32 skip) +{ + buf += skip; + length += skip; +#ifdef VALIDATE_SAVE_SIZE + _saveBufCount += skip; +#endif +} + template<typename T> inline const T ReadSaveBuf(uint8 *&buf) { @@ -421,6 +430,14 @@ inline const T ReadSaveBuf(uint8 *&buf) } template<typename T> +inline const T ReadSaveBuf(uint8 *&buf, uint32 &length) +{ + T &value = *(T*)buf; + SkipSaveBuf(buf, length, sizeof(T)); + return value; +} + +template<typename T> inline T *WriteSaveBuf(uint8 *&buf, const T &value) { T *p = (T*)buf; @@ -429,6 +446,15 @@ inline T *WriteSaveBuf(uint8 *&buf, const T &value) return p; } +template<typename T> +inline T *WriteSaveBuf(uint8 *&buf, uint32 &length, const T &value) +{ + T *p = (T*)buf; + *p = value; + SkipSaveBuf(buf, length, sizeof(T)); + return p; +} + #define SAVE_HEADER_SIZE (4*sizeof(char)+sizeof(uint32)) @@ -439,6 +465,13 @@ inline T *WriteSaveBuf(uint8 *&buf, const T &value) WriteSaveBuf(buf, d);\ WriteSaveBuf<uint32>(buf, size); +#define WriteSaveHeaderWithLength(buf,len,a,b,c,d,size) \ + WriteSaveBuf(buf, len, a);\ + WriteSaveBuf(buf, len, b);\ + WriteSaveBuf(buf, len, c);\ + WriteSaveBuf(buf, len, d);\ + WriteSaveBuf<uint32>(buf, len, size); + #define CheckSaveHeader(buf,a,b,c,d,size)\ assert(ReadSaveBuf<char>(buf) == a);\ assert(ReadSaveBuf<char>(buf) == b);\ @@ -446,5 +479,12 @@ inline T *WriteSaveBuf(uint8 *&buf, const T &value) assert(ReadSaveBuf<char>(buf) == d);\ assert(ReadSaveBuf<uint32>(buf) == size); +#define CheckSaveHeaderWithLength(buf,len,a,b,c,d,size)\ + assert(ReadSaveBuf<char>(buf,len) == a);\ + assert(ReadSaveBuf<char>(buf,len) == b);\ + assert(ReadSaveBuf<char>(buf,len) == c);\ + assert(ReadSaveBuf<char>(buf,len) == d);\ + assert(ReadSaveBuf<uint32>(buf,len) == size); + void cprintf(char*, ...);
\ No newline at end of file diff --git a/src/core/config.h b/src/core/config.h index 475a63f8..3f077f4c 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -87,7 +87,8 @@ enum Config { NUMMBLURSTREAKS = 4, NUMSKIDMARKS = 32, - NUMONSCREENTIMERENTRIES = 1, + NUMONSCREENCLOCKS = 1, + NUMONSCREENCOUNTERS = 3, NUMRADARBLIPS = 75, NUMGENERALPICKUPS = 320, NUMSCRIPTEDPICKUPS = 16, @@ -137,6 +138,7 @@ enum Config { NUM_CRANES = 8, NUM_ESCALATORS = 22, + NUM_WATER_CREATURES = 8, NUM_EXPLOSIONS = 48, @@ -248,6 +250,9 @@ enum Config { #if !defined(RW_GL3) && defined(_WIN32) #define XINPUT #endif +#if !defined(_WIN32) && !defined(__SWITCH__) +#define DONT_TRUST_RECOGNIZED_JOYSTICKS // Then we'll only rely on GLFW gamepad DB, and expect user to enter Controller->Detect joysticks if his joystick isn't on that list. +#endif #define DETECT_PAD_INPUT_SWITCH // Adds automatic switch of pad related stuff between controller and kb/m #define KANGAROO_CHEAT #define RESTORE_ALLCARSHELI_CHEAT @@ -257,7 +262,6 @@ enum Config { //#define BIND_VEHICLE_FIREWEAPON // Adds ability to rebind fire key for 'in vehicle' controls // Hud, frontend and radar -#define HUD_ENHANCEMENTS // Adjusts some aspects to make the HUD look/behave a little bit better. //#define BETA_SLIDING_TEXT #define TRIANGULAR_BLIPS // height indicating triangular radar blips, as in VC #define PC_MENU @@ -323,4 +327,4 @@ enum Config { #undef NO_ISLAND_LOADING #define PC_PARTICLE #define VC_PED_PORTS // To not process collisions always. But should be tested if that's really beneficial -#endif
\ No newline at end of file +#endif |