From 8a4fa58cd42b7cca4a86fe2d9913b839b554bf10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Mon, 11 May 2020 05:55:57 +0300 Subject: Linux build support --- src/core/CdStream.cpp | 10 +- src/core/CdStream.h | 6 +- src/core/CdStreamPosix.cpp | 516 ++++++++++++++++++++++++++++++++++++++++++ src/core/ControllerConfig.cpp | 29 +-- src/core/FileMgr.cpp | 59 ++++- src/core/Fire.cpp | 8 +- src/core/Frontend.cpp | 41 ++-- src/core/Frontend.h | 1 - src/core/Game.cpp | 2 +- src/core/Streaming.cpp | 8 +- src/core/Timer.cpp | 31 ++- src/core/ZoneCull.cpp | 5 +- src/core/Zones.cpp | 12 +- src/core/config.h | 11 +- src/core/main.cpp | 3 + src/core/patcher.cpp | 20 +- src/core/re3.cpp | 51 ++++- 17 files changed, 740 insertions(+), 73 deletions(-) create mode 100644 src/core/CdStreamPosix.cpp (limited to 'src/core') diff --git a/src/core/CdStream.cpp b/src/core/CdStream.cpp index 666041e1..d9978040 100644 --- a/src/core/CdStream.cpp +++ b/src/core/CdStream.cpp @@ -1,3 +1,4 @@ +#ifdef _WIN32 #define WITHWINDOWS #include "common.h" @@ -16,9 +17,8 @@ struct CdReadInfo char field_C; bool bLocked; bool bInUse; - char _pad0; int32 nStatus; - HANDLE hSemaphore; + HANDLE hSemaphore; // used for CdStreamSync HANDLE hFile; OVERLAPPED Overlapped; }; @@ -32,7 +32,7 @@ int32 gNumChannels; HANDLE gImgFiles[MAX_CDIMAGES]; HANDLE _gCdStreamThread; -HANDLE gCdStreamSema; +HANDLE gCdStreamSema; // released when we have new thing to read(so channel is set) DWORD _gCdStreamThreadId; CdReadInfo *gpReadInfo; @@ -296,6 +296,7 @@ CdStreamGetLastPosn(void) return lastPosnRead; } +// wait for channel to finish reading int32 CdStreamSync(int32 channel) { @@ -324,6 +325,7 @@ CdStreamSync(int32 channel) if ( _gbCdStreamOverlapped && pChannel->hFile ) { ASSERT(pChannel->hFile != nil ); + // Beware: This is blocking call (because of last parameter) if ( GetOverlappedResult(pChannel->hFile, &pChannel->Overlapped, &NumberOfBytesTransferred, TRUE) ) return STREAM_NONE; else @@ -406,6 +408,7 @@ WINAPI CdStreamThread(LPVOID lpThreadParameter) { pChannel->nStatus = STREAM_NONE; } + // Beware: This is blocking call (because of last parameter) else if ( GetLastError() == ERROR_IO_PENDING && GetOverlappedResult(pChannel->hFile, &pChannel->Overlapped, &NumberOfBytesTransferred, TRUE) ) { @@ -508,3 +511,4 @@ CdStreamGetNumImages(void) { return gNumImages; } +#endif diff --git a/src/core/CdStream.h b/src/core/CdStream.h index ba6c63a3..d0f9a855 100644 --- a/src/core/CdStream.h +++ b/src/core/CdStream.h @@ -41,4 +41,8 @@ void RemoveFirstInQueue(Queue *queue); bool CdStreamAddImage(char const *path); char *CdStreamGetImageName(int32 cd); void CdStreamRemoveImages(void); -int32 CdStreamGetNumImages(void); \ No newline at end of file +int32 CdStreamGetNumImages(void); + +#ifndef _WIN32 +extern bool flushStream[MAX_CDCHANNELS]; +#endif diff --git a/src/core/CdStreamPosix.cpp b/src/core/CdStreamPosix.cpp new file mode 100644 index 00000000..7c49f5f1 --- /dev/null +++ b/src/core/CdStreamPosix.cpp @@ -0,0 +1,516 @@ +#ifndef _WIN32 +#include "common.h" +#include "crossplatform.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CdStream.h" +#include "rwcore.h" +#include "RwHelper.h" + +#define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__) +#define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__) + +// #define ONE_THREAD_PER_CHANNEL // Don't use if you're not on SSD/Flash. (Also you may want to benefit from this via using all channels in Streaming.cpp) + +bool flushStream[MAX_CDCHANNELS]; + +struct CdReadInfo +{ + uint32 nSectorOffset; + uint32 nSectorsToRead; + void *pBuffer; + bool bLocked; + bool bReading; + int32 nStatus; +#ifdef ONE_THREAD_PER_CHANNEL + int8 nThreadStatus; // 0: created 1:initalized 2:abort now + pthread_t pChannelThread; + sem_t pStartSemaphore; +#endif + sem_t pDoneSemaphore; // used for CdStreamSync + int32 hFile; +}; + +char gCdImageNames[MAX_CDIMAGES+1][64]; +int32 gNumImages; +int32 gNumChannels; + +int32 gImgFiles[MAX_CDIMAGES]; // -1: error 0:unused otherwise: fd +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 +Queue gChannelRequestQ; +bool _gbCdStreamOverlapped; +#endif + +CdReadInfo *gpReadInfo; + +int32 lastPosnRead; + +int _gdwCdStreamFlags; + +void *CdStreamThread(void* channelId); + +void +CdStreamInitThread(void) +{ + int status; + +#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 + + + if (status == -1) { + CDTRACE("failed to create stream semaphore"); + ASSERT(0); + return; + } + + + if ( gNumChannels > 0 ) + { + for ( int32 i = 0; i < gNumChannels; i++ ) + { + status = sem_init(&gpReadInfo[i].pDoneSemaphore, 0, 0); + + if (status == -1) + { + CDTRACE("failed to create sync semaphore"); + ASSERT(0); + return; + } +#ifdef ONE_THREAD_PER_CHANNEL + status = sem_init(&gpReadInfo[i].pStartSemaphore, 0, 0); + + if (status == -1) + { + CDTRACE("failed to create start semaphore"); + ASSERT(0); + return; + } + gpReadInfo[i].nThreadStatus = 0; + int *channelI = (int*)malloc(sizeof(int)); + *channelI = i; + status = pthread_create(&gpReadInfo[i].pChannelThread, NULL, CdStreamThread, (void*)channelI); + + if (status == -1) + { + CDTRACE("failed to create sync thread"); + ASSERT(0); + return; + } +#endif + } + } + +#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; + } +#else + debug("Using seperate 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; + } + + _gdwCdStreamFlags = O_RDONLY | O_NOATIME; + + // People say it's slower +/* + if ( fsInfo.f_bsize <= CDSTREAM_SECTOR_SIZE ) + { + _gdwCdStreamFlags |= O_DIRECT; + debug("Using no buffered loading for streaming\n"); + } +*/ + void *pBuffer = (void *)RwMallocAlign(CDSTREAM_SECTOR_SIZE, fsInfo.f_bsize); + ASSERT( pBuffer != nil ); + + gNumImages = 0; + + gNumChannels = numChannels; + + gpReadInfo = (CdReadInfo *)calloc(sizeof(CdReadInfo), numChannels); + ASSERT( gpReadInfo != nil ); + + CDDEBUG("read info %p", gpReadInfo); + + CdStreamInitThread(); + + ASSERT( pBuffer != nil ); + RwFreeAlign(pBuffer); +} + +uint32 +GetGTA3ImgSize(void) +{ + ASSERT( gImgFiles[0] > 0 ); + struct stat statbuf; + + char path[PATH_MAX]; + realpath(gImgNames[0], path); + if (stat(path, &statbuf) == -1) { + // Try case-insensitivity + char *r = (char*)alloca(strlen(gImgNames[0]) + 2); + if (casepath(gImgNames[0], r)) + { + realpath(r, path); + if (stat(path, &statbuf) != -1) + goto ok; + } + + CDTRACE("can't get size of gta3.img"); + ASSERT(0); + return 0; + } +ok: + return statbuf.st_size; +} + +void +CdStreamShutdown(void) +{ + // Destroying semaphores and free(gpReadInfo) will be done at threads +#ifndef ONE_THREAD_PER_CHANNEL + free(gChannelRequestQ.items); + 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); + } +#endif +} + + +int32 +CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size) +{ + ASSERT( channel < gNumChannels ); + ASSERT( buffer != nil ); + + lastPosnRead = size + offset; + + ASSERT( _GET_INDEX(offset) < MAX_CDIMAGES ); + int32 hImage = gImgFiles[_GET_INDEX(offset)]; + ASSERT( hImage > 0 ); + + CdReadInfo *pChannel = &gpReadInfo[channel]; + ASSERT( pChannel != nil ); + + pChannel->hFile = hImage - 1; + + if ( pChannel->nSectorsToRead != 0 || pChannel->bReading ) + return STREAM_NONE; + + 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"); +#else + if ( sem_post(&gpReadInfo[channel].pStartSemaphore) != 0 ) + printf("Signal Sema Error\n"); +#endif + + return STREAM_SUCCESS; +} + +int32 +CdStreamGetStatus(int32 channel) +{ + ASSERT( channel < gNumChannels ); + CdReadInfo *pChannel = &gpReadInfo[channel]; + ASSERT( pChannel != nil ); + +#ifdef ONE_THREAD_PER_CHANNEL + if (pChannel->nThreadStatus == 2) + return STREAM_NONE; +#else + if (gCdStreamThreadStatus == 2) + return STREAM_NONE; +#endif + + if ( pChannel->bReading ) + return STREAM_READING; + + if ( pChannel->nSectorsToRead != 0 ) + return STREAM_WAITING; + + if ( pChannel->nStatus != STREAM_NONE ) + { + int32 status = pChannel->nStatus; + + pChannel->nStatus = STREAM_NONE; + + return status; + } + + return STREAM_NONE; +} + +int32 +CdStreamGetLastPosn(void) +{ + return lastPosnRead; +} + +// wait for channel to finish reading +int32 +CdStreamSync(int32 channel) +{ + ASSERT( channel < gNumChannels ); + CdReadInfo *pChannel = &gpReadInfo[channel]; + ASSERT( pChannel != nil ); + + if (flushStream[channel]) { +#ifdef ONE_THREAD_PER_CHANNEL + pChannel->nSectorsToRead = 0; + pthread_kill(gpReadInfo[channel].pChannelThread, SIGINT); +#else + if (pChannel->bReading) { + pChannel->nSectorsToRead = 0; + pthread_kill(_gCdStreamThread, SIGINT); + } else { + pChannel->nSectorsToRead = 0; + } +#endif + pChannel->bReading = false; + flushStream[channel] = false; + return STREAM_NONE; + } + + if ( pChannel->nSectorsToRead != 0 ) + { + pChannel->bLocked = true; + + sem_wait(&pChannel->pDoneSemaphore); + } + + pChannel->bReading = false; + + return pChannel->nStatus; +} + +void +AddToQueue(Queue *queue, int32 item) +{ + ASSERT( queue != nil ); + ASSERT( queue->items != nil ); + queue->items[queue->tail] = item; + + queue->tail = (queue->tail + 1) % queue->size; + + if ( queue->head == queue->tail ) + debug("Queue is full\n"); +} + +int32 +GetFirstInQueue(Queue *queue) +{ + ASSERT( queue != nil ); + if ( queue->head == queue->tail ) + return -1; + + ASSERT( queue->items != nil ); + return queue->items[queue->head]; +} + +void +RemoveFirstInQueue(Queue *queue) +{ + ASSERT( queue != nil ); + if ( queue->head == queue->tail ) + { + debug("Queue is empty\n"); + return; + } + + queue->head = (queue->head + 1) % queue->size; +} + +void *CdStreamThread(void *param) +{ + debug("Created cdstream thread\n"); + +#ifndef ONE_THREAD_PER_CHANNEL + 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); +#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 + pid_t tid = syscall(SYS_gettid); + int ret = setpriority(PRIO_PROCESS, tid, getpriority(PRIO_PROCESS, getpid()) + 1); + } + + // spurious wakeup or we sent interrupt signal for flushing + if(pChannel->nSectorsToRead == 0) + continue; + + pChannel->bReading = true; + + if ( pChannel->nStatus == STREAM_NONE ) + { + 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) { + // 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; + } + } + +#ifndef ONE_THREAD_PER_CHANNEL + RemoveFirstInQueue(&gChannelRequestQ); +#endif + + pChannel->nSectorsToRead = 0; + + if ( pChannel->bLocked ) + { + sem_post(&pChannel->pDoneSemaphore); + } + pChannel->bReading = false; + } +#ifndef ONE_THREAD_PER_CHANNEL + for ( int32 i = 0; i < gNumChannels; i++ ) + { + sem_destroy(&gpReadInfo[i].pDoneSemaphore); + } + sem_destroy(&gCdStreamSema); +#else + sem_destroy(&gpReadInfo[channel].pStartSemaphore); + sem_destroy(&gpReadInfo[channel].pDoneSemaphore); +#endif + free(gpReadInfo); + pthread_exit(nil); +} + +bool +CdStreamAddImage(char const *path) +{ + ASSERT(path != nil); + ASSERT(gNumImages < MAX_CDIMAGES); + + gImgFiles[gNumImages] = open(path, _gdwCdStreamFlags); + + // Fix case sensitivity and backslashes. + if (gImgFiles[gNumImages] == -1) { + char *r = (char*)alloca(strlen(path) + 2); + if (casepath(path, r)) + { + gImgFiles[gNumImages] = open(r, _gdwCdStreamFlags); + } + } + + if ( gImgFiles[gNumImages] == -1 ) { + assert(false); + return false; + } + + gImgNames[gNumImages] = strdup(path); + gImgFiles[gNumImages]++; // because -1: error 0: not used + + strcpy(gCdImageNames[gNumImages], path); + + gNumImages++; + + return true; +} + +char * +CdStreamGetImageName(int32 cd) +{ + ASSERT(cd < MAX_CDIMAGES); + if ( gImgFiles[cd] > 0) + return gCdImageNames[cd]; + + return nil; +} + +void +CdStreamRemoveImages(void) +{ + for ( int32 i = 0; i < gNumChannels; i++ ) + CdStreamSync(i); + + for ( int32 i = 0; i < gNumImages; i++ ) + { + close(gImgFiles[i] - 1); + free(gImgNames[i]); + gImgFiles[i] = 0; + } + + gNumImages = 0; +} + +int32 +CdStreamGetNumImages(void) +{ + return gNumImages; +} +#endif diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index cba8186f..dcd9f125 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -4,7 +4,8 @@ #endif #include "common.h" -#include "crossplatform.h" +#include "platform.h" +#include "crossplatform.h" // for Windows version #include "ControllerConfig.h" #include "Pad.h" #include "FileMgr.h" @@ -163,14 +164,14 @@ void CControllerConfigManager::InitDefaultControlConfiguration() SetControllerKeyAssociatedWithAction (VEHICLE_LOOKRIGHT, rsPADDOWN, KEYBOARD); SetControllerKeyAssociatedWithAction (VEHICLE_LOOKRIGHT, 'E', OPTIONAL_EXTRA); - - if ( _dwOperatingSystemVersion != OS_WIN98 ) - { + + if ( _dwOperatingSystemVersion == OS_WIN98 ) + SetControllerKeyAssociatedWithAction(VEHICLE_HORN, rsSHIFT, OPTIONAL_EXTRA); // BUG: must be KEYBOARD ? + else + { SetControllerKeyAssociatedWithAction(VEHICLE_HORN, rsLSHIFT, OPTIONAL_EXTRA); SetControllerKeyAssociatedWithAction(VEHICLE_HORN, rsRSHIFT, KEYBOARD); - } - else - SetControllerKeyAssociatedWithAction(VEHICLE_HORN, rsSHIFT, OPTIONAL_EXTRA); // BUG: must be KEYBOARD ? + } SetControllerKeyAssociatedWithAction (VEHICLE_HANDBRAKE, rsRCTRL, KEYBOARD); SetControllerKeyAssociatedWithAction (VEHICLE_HANDBRAKE, ' ', OPTIONAL_EXTRA); @@ -216,19 +217,19 @@ void CControllerConfigManager::InitDefaultControlConfiguration() SetControllerKeyAssociatedWithAction (PED_JUMPING, rsRCTRL, KEYBOARD); SetControllerKeyAssociatedWithAction (PED_JUMPING, ' ', OPTIONAL_EXTRA); - - if ( _dwOperatingSystemVersion != OS_WIN98 ) - { + + if ( _dwOperatingSystemVersion == OS_WIN98 ) + SetControllerKeyAssociatedWithAction(PED_SPRINT, rsSHIFT, OPTIONAL_EXTRA); // BUG: must be KEYBOARD ? + else + { SetControllerKeyAssociatedWithAction(PED_SPRINT, rsLSHIFT, OPTIONAL_EXTRA); #ifndef FIX_BUGS SetControllerKeyAssociatedWithAction(PED_SPRINT, rsRSHIFT, OPTIONAL_EXTRA); // BUG: must be KEYBOARD #else SetControllerKeyAssociatedWithAction(PED_SPRINT, rsRSHIFT, KEYBOARD); #endif - } - else - SetControllerKeyAssociatedWithAction(PED_SPRINT, rsSHIFT, OPTIONAL_EXTRA); // BUG: must be KEYBOARD ? - + } + SetControllerKeyAssociatedWithAction (PED_CYCLE_TARGET_LEFT, '[', KEYBOARD); SetControllerKeyAssociatedWithAction (PED_CYCLE_TARGET_RIGHT, ']', OPTIONAL_EXTRA); // BUG: must be KEYBOARD ? diff --git a/src/core/FileMgr.cpp b/src/core/FileMgr.cpp index 46d725cd..1939c861 100644 --- a/src/core/FileMgr.cpp +++ b/src/core/FileMgr.cpp @@ -1,6 +1,8 @@ #define _CRT_SECURE_NO_WARNINGS #include +#ifdef _WIN32 #include +#endif #include "common.h" #include "FileMgr.h" @@ -24,6 +26,31 @@ struct myFILE #define NUMFILES 20 static myFILE myfiles[NUMFILES]; + +#if !defined(_WIN32) +#include +#include +#include +#include "crossplatform.h" +#define _getcwd getcwd + +// Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen) +void mychdir(char const *path) +{ + char *r = (char*)alloca(strlen(path) + 2); + if (casepath(path, r)) + { + chdir(r); + } + else + { + errno = ENOENT; + } +} +#else +#define mychdir chdir +#endif + /* Force file to open as binary but remember if it was text mode */ static int myfopen(const char *filename, const char *mode) @@ -45,7 +72,31 @@ found: mode++; *p++ = 'b'; *p = '\0'; - myfiles[fd].file = fopen(filename, realmode); + +#if !defined(_WIN32) + char *newPath = strdup(filename); + // Normally casepath() fixes backslashes, but if the mode is sth other than r/rb it will create new file with backslashes on linux, so fix backslashes here + char *nextBs; + while(nextBs = strstr(newPath, "\\")){ + *nextBs = '/'; + } +#else + const char *newPath = filename; +#endif + + myfiles[fd].file = fopen(newPath, realmode); +// Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/) +#if !defined(_WIN32) + if (!myfiles[fd].file) { + char *r = (char*)alloca(strlen(newPath) + 2); + if (casepath(newPath, r)) + { + myfiles[fd].file = fopen(r, realmode); + } + } + + free(newPath); +#endif if(myfiles[fd].file == nil) return 0; return fd; @@ -191,7 +242,7 @@ CFileMgr::ChangeDir(const char *dir) if(dir[strlen(dir)-1] != '\\') strcat(ms_dirName, "\\"); } - chdir(ms_dirName); + mychdir(ms_dirName); } void @@ -204,14 +255,14 @@ CFileMgr::SetDir(const char *dir) if(dir[strlen(dir)-1] != '\\') strcat(ms_dirName, "\\"); } - chdir(ms_dirName); + mychdir(ms_dirName); } void CFileMgr::SetDirMyDocuments(void) { SetDir(""); // better start at the root if user directory is relative - chdir(_psGetUserFilesFolder()); + mychdir(_psGetUserFilesFolder()); } int diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp index 65b6deb2..933c73da 100644 --- a/src/core/Fire.cpp +++ b/src/core/Fire.cpp @@ -128,7 +128,7 @@ CFire::ProcessFire(void) lightpos.z = m_vecPos.z + 5.0f; if (!m_pEntity) { - CShadows::StoreStaticShadow((uint32)this, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &lightpos, + CShadows::StoreStaticShadow((uintptr)this, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &lightpos, 7.0f, 0.0f, 0.0f, -7.0f, 255, // this is 0 on PC which results in no shadow nRandNumber / 2, nRandNumber / 2, 0, @@ -199,7 +199,7 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength { CPed *ped = (CPed *)entityOnFire; CVehicle *veh = (CVehicle *)entityOnFire; - + if (entityOnFire->IsPed()) { if (ped->m_pFire) return nil; @@ -212,7 +212,7 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength return nil; } CFire *fire = GetNextFreeFire(); - + if (fire) { if (entityOnFire->IsPed()) { ped->m_pFire = fire; @@ -243,7 +243,7 @@ CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength veh->m_pCarFire = fire; if (fleeFrom) { CEventList::RegisterEvent(EVENT_CAR_SET_ON_FIRE, EVENT_ENTITY_VEHICLE, - entityOnFire, (CPed *)fleeFrom, 10000); + entityOnFire, (CPed *)fleeFrom, 10000); } } } diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 827e2ca7..f0d75d12 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -6,6 +6,7 @@ #define WITHWINDOWS #include "common.h" #include "crossplatform.h" +#include "platform.h" #include "Frontend.h" #include "Font.h" #include "Pad.h" @@ -900,6 +901,7 @@ CMenuManager::Draw() float smallestSliderBar = lineHeight * 0.1f; bool foundTheHoveringItem = false; wchar unicodeTemp[64]; + char asciiTemp[32]; #ifdef MENU_MAP if (m_nCurrScreen == MENUPAGE_MAP) { @@ -1054,15 +1056,18 @@ CMenuManager::Draw() #else switch (m_PrefsUseWideScreen) { case AR_AUTO: - rightText = (wchar*)L"AUTO"; + sprintf(asciiTemp, "AUTO"); break; case AR_4_3: - rightText = (wchar*)L"4:3"; + sprintf(asciiTemp, "4:3"); break; case AR_16_9: - rightText = (wchar*)L"16:9"; + sprintf(asciiTemp, "16:9"); break; } + + AsciiToUnicode(asciiTemp, unicodeTemp); + rightText = unicodeTemp; #endif break; case MENUACTION_RADIO: @@ -1102,13 +1107,12 @@ CMenuManager::Draw() break; #ifdef IMPROVED_VIDEOMODE case MENUACTION_SCREENMODE: - char mode[32]; if (m_nSelectedScreenMode == 0) - sprintf(mode, "FULLSCREEN"); + sprintf(asciiTemp, "FULLSCREEN"); else - sprintf(mode, "WINDOWED"); + sprintf(asciiTemp, "WINDOWED"); - AsciiToUnicode(mode, unicodeTemp); + AsciiToUnicode(asciiTemp, unicodeTemp); rightText = unicodeTemp; break; #endif @@ -4794,6 +4798,21 @@ CMenuManager::ProcessButtonPresses(void) DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1); OutputDebugString("FRONTEND RADIO STATION CHANGED"); break; +#ifdef ASPECT_RATIO_SCALE + case MENUACTION_WIDESCREEN: + if (changeValueBy > 0) { + m_PrefsUseWideScreen++; + if (m_PrefsUseWideScreen > 2) + m_PrefsUseWideScreen = 2; + } else { + m_PrefsUseWideScreen--; + if (m_PrefsUseWideScreen < 0) + m_PrefsUseWideScreen = 0; + } + DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); + SaveSettings(); + break; +#endif case MENUACTION_SCREENRES: if (m_bGameNotLoaded) { RwChar** videoMods = _psGetVideoModeList(); @@ -4903,17 +4922,13 @@ CMenuManager::ProcessOnOffMenuOptions() DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); SaveSettings(); break; - case MENUACTION_WIDESCREEN: #ifndef ASPECT_RATIO_SCALE + case MENUACTION_WIDESCREEN: m_PrefsUseWideScreen = !m_PrefsUseWideScreen; -#else - m_PrefsUseWideScreen++; - if (m_PrefsUseWideScreen > 2) - m_PrefsUseWideScreen = 0; -#endif DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); SaveSettings(); break; +#endif case MENUACTION_SETDBGFLAG: CTheScripts::InvertDebugFlag(); DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SUCCESS, 0); diff --git a/src/core/Frontend.h b/src/core/Frontend.h index e496f9c0..65c4e178 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -662,4 +662,3 @@ VALIDATE_SIZE(CMenuManager, 0x564); #endif extern CMenuManager FrontEndMenuManager; -extern unsigned long _dwOperatingSystemVersion; \ No newline at end of file diff --git a/src/core/Game.cpp b/src/core/Game.cpp index c50471f1..33afc956 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -2,7 +2,7 @@ #pragma warning( disable : 4005) #pragma warning( pop ) #include "common.h" -#include "crossplatform.h" +#include "platform.h" #include "Game.h" #include "main.h" diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index f24192ef..ed3892a6 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -1465,7 +1465,7 @@ CStreaming::GetCdImageOffset(int32 lastPosn) int dist, mindist; img = -1; - mindist = INT_MAX; + mindist = INT32_MAX; offset = ms_imageOffsets[ms_lastImageRead]; if(lastPosn <= offset || lastPosn > offset + ms_imageSize){ // last read position is not in last image @@ -1513,8 +1513,8 @@ CStreaming::GetNextFileOnCd(int32 lastPosn, bool priority) streamIdFirst = -1; streamIdNext = -1; - posnFirst = UINT_MAX; - posnNext = UINT_MAX; + posnFirst = UINT32_MAX; + posnNext = UINT32_MAX; for(si = ms_startRequestedList.m_next; si != &ms_endRequestedList; si = next){ next = si->m_next; @@ -1834,7 +1834,7 @@ CStreaming::LoadAllRequestedModels(bool priority) status = CdStreamRead(0, ms_pStreamingBuffer[0], imgOffset+posn, size); while(CdStreamSync(0) || status == STREAM_NONE); ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_READING; - + MakeSpaceFor(size * CDSTREAM_SECTOR_SIZE); ConvertBufferToObject(ms_pStreamingBuffer[0], streamId); if(ms_aInfoForModel[streamId].m_loadState == STREAMSTATE_STARTED) diff --git a/src/core/Timer.cpp b/src/core/Timer.cpp index aca7c1dc..ed5580fd 100644 --- a/src/core/Timer.cpp +++ b/src/core/Timer.cpp @@ -1,5 +1,6 @@ #define WITHWINDOWS #include "common.h" +#include "crossplatform.h" #include "DMAudio.h" #include "Record.h" @@ -16,15 +17,19 @@ float CTimer::ms_fTimeStepNonClipped; bool CTimer::m_UserPause; bool CTimer::m_CodePause; -uint32 oldPcTimer; - -uint32 suspendPcTimer; - uint32 _nCyclesPerMS = 1; +#ifdef _WIN32 LARGE_INTEGER _oldPerfCounter; - LARGE_INTEGER perfSuspendCounter; +#define RsTimerType uint32 +#else +#define RsTimerType double +#endif + +RsTimerType oldPcTimer; + +RsTimerType suspendPcTimer; uint32 suspendDepth; @@ -45,6 +50,7 @@ void CTimer::Initialise(void) m_snPreviousTimeInMilliseconds = 0; m_snTimeInMilliseconds = 1; +#ifdef _WIN32 LARGE_INTEGER perfFreq; if ( QueryPerformanceFrequency(&perfFreq) ) { @@ -53,6 +59,7 @@ void CTimer::Initialise(void) QueryPerformanceCounter(&_oldPerfCounter); } else +#endif { OutputDebugString("Performance counter not available, using millesecond timer\n"); _nCyclesPerMS = 0; @@ -77,6 +84,7 @@ void CTimer::Update(void) { m_snPreviousTimeInMilliseconds = m_snTimeInMilliseconds; +#ifdef _WIN32 if ( (double)_nCyclesPerMS != 0.0 ) { LARGE_INTEGER pc; @@ -106,10 +114,11 @@ void CTimer::Update(void) } } else +#endif { - uint32 timer = RsTimer(); + RsTimerType timer = RsTimer(); - uint32 updInMs = timer - oldPcTimer; + RsTimerType updInMs = timer - oldPcTimer; // We need that real frame time to fix transparent menu bug. #ifndef FIX_BUGS @@ -158,9 +167,11 @@ void CTimer::Suspend(void) if ( ++suspendDepth > 1 ) return; +#ifdef _WIN32 if ( (double)_nCyclesPerMS != 0.0 ) QueryPerformanceCounter(&perfSuspendCounter); else +#endif suspendPcTimer = RsTimer(); } @@ -169,6 +180,7 @@ void CTimer::Resume(void) if ( --suspendDepth != 0 ) return; +#ifdef _WIN32 if ( (double)_nCyclesPerMS != 0.0 ) { LARGE_INTEGER pc; @@ -177,19 +189,23 @@ void CTimer::Resume(void) _oldPerfCounter.LowPart += pc.LowPart - perfSuspendCounter.LowPart; } else +#endif oldPcTimer += RsTimer() - suspendPcTimer; } uint32 CTimer::GetCyclesPerMillisecond(void) { +#ifdef _WIN32 if (_nCyclesPerMS != 0) return _nCyclesPerMS; else +#endif return 1; } uint32 CTimer::GetCurrentTimeInCycles(void) { +#ifdef _WIN32 if ( _nCyclesPerMS != 0 ) { LARGE_INTEGER pc; @@ -197,6 +213,7 @@ uint32 CTimer::GetCurrentTimeInCycles(void) return (pc.LowPart - _oldPerfCounter.LowPart); // & 0x7FFFFFFF; pointless } else +#endif return RsTimer() - oldPcTimer; } diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp index 6dcd0f18..c376e11f 100644 --- a/src/core/ZoneCull.cpp +++ b/src/core/ZoneCull.cpp @@ -533,7 +533,8 @@ CCullZone::IsEntityCloseEnoughToZone(CEntity *entity, bool checkLevel) if (lodDist > distToZone) return true; if (!checkLevel) return false; - return CTheZones::GetLevelFromPosition(&pos) == CTheZones::GetLevelFromPosition(&CVector(minx, miny, minz)); + CVector tempPos(minx, miny, minz); + return CTheZones::GetLevelFromPosition(&pos) == CTheZones::GetLevelFromPosition(&tempPos); } bool @@ -560,4 +561,4 @@ CCullZones::DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set) } } return false; -} \ No newline at end of file +} diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp index 22c0735a..5b7519dc 100644 --- a/src/core/Zones.cpp +++ b/src/core/Zones.cpp @@ -703,9 +703,9 @@ CTheZones::LoadAllZones(uint8 *buffer, uint32 size) for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){ ZoneArray[i] = ReadSaveBuf(buffer); - ZoneArray[i].child = GetPointerForZoneIndex((int32)ZoneArray[i].child); - ZoneArray[i].parent = GetPointerForZoneIndex((int32)ZoneArray[i].parent); - ZoneArray[i].next = GetPointerForZoneIndex((int32)ZoneArray[i].next); + ZoneArray[i].child = GetPointerForZoneIndex((uintptr)ZoneArray[i].child); + ZoneArray[i].parent = GetPointerForZoneIndex((uintptr)ZoneArray[i].parent); + ZoneArray[i].next = GetPointerForZoneIndex((uintptr)ZoneArray[i].next); } for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) @@ -722,9 +722,9 @@ CTheZones::LoadAllZones(uint8 *buffer, uint32 size) meant for a different array, but the game doesn't brake if save data stored is -1. */ - MapZoneArray[i].child = GetPointerForZoneIndex((int32)MapZoneArray[i].child); - MapZoneArray[i].parent = GetPointerForZoneIndex((int32)MapZoneArray[i].parent); - MapZoneArray[i].next = GetPointerForZoneIndex((int32)MapZoneArray[i].next); + 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); diff --git a/src/core/config.h b/src/core/config.h index ae30b539..d9f892a6 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -194,19 +194,22 @@ enum Config { #define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more #define TOGGLEABLE_BETA_FEATURES // toggleable from debug menu. not too many things #define MORE_LANGUAGES // Add more translations to the game -#define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) +#define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) #define USE_TXD_CDIMAGE // generate and load textures from txd.img #define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number //#define USE_TEXTURE_POOL -//#define AUDIO_OAL +#ifdef _WIN32 #define AUDIO_MSS +#else +#define AUDIO_OAL +#endif // Particle //#define PC_PARTICLE //#define PS2_ALTERNATIVE_CARSPLASH // unused on PS2 // Pad -#ifndef RW_GL3 +#if !defined(RW_GL3) && defined(_WIN32) #define XINPUT #endif #define DETECT_PAD_INPUT_SWITCH // Adds automatic switch of pad related stuff between controller and kb/m @@ -224,7 +227,7 @@ enum Config { #define SCROLLABLE_STATS_PAGE // only draggable by mouse atm #define TRIANGLE_BACK_BUTTON // #define CIRCLE_BACK_BUTTON -#define HUD_ENHANCEMENTS // Adjusts some aspects to make the HUD look/behave a little bit better. +#define HUD_ENHANCEMENTS // Adjusts some aspects to make the HUD look/behave a little bit better. #define BETA_SLIDING_TEXT // Script diff --git a/src/core/main.cpp b/src/core/main.cpp index 37a5673f..d6af0b2a 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -1773,6 +1773,8 @@ void GameInit() } } +// Not used anyway. PS2 main() port +#ifdef _WIN32 int main(int argc, char *argv[]) { @@ -1844,3 +1846,4 @@ main(int argc, char *argv[]) return 0; } +#endif diff --git a/src/core/patcher.cpp b/src/core/patcher.cpp index e5242e9d..83e06886 100644 --- a/src/core/patcher.cpp +++ b/src/core/patcher.cpp @@ -24,7 +24,7 @@ StaticPatcher::Apply() } ms_head = nil; } - +#ifdef _WIN32 std::vector usedAddresses; static DWORD protect[2]; @@ -75,4 +75,20 @@ InjectHook_internal(uint32 address, uint32 hook, int type) VirtualProtect((void*)(address + 1), 4, protect[0], &protect[1]); else VirtualProtect((void*)address, 5, protect[0], &protect[1]); -} \ No newline at end of file +} +#else +void +Protect_internal(uint32 address, uint32 size) +{ +} + +void +Unprotect_internal(void) +{ +} + +void +InjectHook_internal(uint32 address, uint32 hook, int type) +{ +} +#endif diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 0ab32999..9bc6400c 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -1,7 +1,7 @@ -#include #include #define WITHWINDOWS #include "common.h" +#include "crossplatform.h" #include "patcher.h" #include "Renderer.h" #include "Credits.h" @@ -28,6 +28,11 @@ #include "debugmenu.h" #include "Frontend.h" +#ifndef _WIN32 +#include "assert.h" +#include +#endif + #include #ifdef RWLIBS @@ -36,7 +41,7 @@ extern "C" int vsprintf(char* const _Buffer, char const* const _Format, va_list #ifdef USE_PS2_RAND -unsigned __int64 myrand_seed = 1; +unsigned long long myrand_seed = 1; #else unsigned long int myrand_seed = 1; #endif @@ -201,13 +206,22 @@ static const char *carnames[] = { "yankee", "escape", "borgnine", "toyz", "ghost", }; -static std::list TweakVarsList; +static CTweakVar** TweakVarsList; +static int TweakVarsListSize = -1; static bool bAddTweakVarsNow = false; static const char *pTweakVarsDefaultPath = NULL; void CTweakVars::Add(CTweakVar *var) { - TweakVarsList.push_back(var); + if(TweakVarsListSize == -1) { + TweakVarsList = (CTweakVar**)malloc(64 * sizeof(CTweakVar*)); + TweakVarsListSize = 0; + } + if(TweakVarsListSize > 63) + TweakVarsList = (CTweakVar**) realloc(TweakVarsList, (TweakVarsListSize + 1) * sizeof(var)); + + TweakVarsList[TweakVarsListSize++] = var; +// TweakVarsList.push_back(var); if ( bAddTweakVarsNow ) var->AddDBG(pTweakVarsDefaultPath); @@ -217,8 +231,8 @@ void CTweakVars::AddDBG(const char *path) { pTweakVarsDefaultPath = path; - for(auto i = TweakVarsList.begin(); i != TweakVarsList.end(); ++i) - (*i)->AddDBG(pTweakVarsDefaultPath); + for(int i = 0; i < TweakVarsListSize; ++i) + TweakVarsList[i]->AddDBG(pTweakVarsDefaultPath); bAddTweakVarsNow = true; } @@ -392,6 +406,7 @@ static char re3_buff[re3_buffsize]; void re3_assert(const char *expr, const char *filename, unsigned int lineno, const char *func) { +#ifdef _WIN32 int nCode; strcpy_s(re3_buff, re3_buffsize, "Assertion failed!" ); @@ -436,13 +451,22 @@ void re3_assert(const char *expr, const char *filename, unsigned int lineno, con return; abort(); +#else + // TODO + printf("\nRE3 ASSERT FAILED\n\tFile: %s\n\tLine: %d\n\tFunction: %s\n\tExpression: %s\n",filename,lineno,func,expr); + assert(false); +#endif } void re3_debug(const char *format, ...) { va_list va; va_start(va, format); +#ifdef _WIN32 vsprintf_s(re3_buff, re3_buffsize, format, va); +#else + vsprintf(re3_buff, format, va); +#endif va_end(va); printf("%s", re3_buff); @@ -454,18 +478,26 @@ void re3_trace(const char *filename, unsigned int lineno, const char *func, cons char buff[re3_buffsize *2]; va_list va; va_start(va, format); +#ifdef _WIN32 vsprintf_s(re3_buff, re3_buffsize, format, va); va_end(va); sprintf_s(buff, re3_buffsize * 2, "[%s.%s:%d]: %s", filename, func, lineno, re3_buff); +#else + vsprintf(re3_buff, format, va); + va_end(va); - OutputDebugStringA(buff); + sprintf(buff, "[%s.%s:%d]: %s", filename, func, lineno, re3_buff); +#endif + + OutputDebugString(buff); } void re3_usererror(const char *format, ...) { va_list va; va_start(va, format); +#ifdef _WIN32 vsprintf_s(re3_buff, re3_buffsize, format, va); va_end(va); @@ -474,6 +506,11 @@ void re3_usererror(const char *format, ...) raise(SIGABRT); _exit(3); +#else + vsprintf(re3_buff, format, va); + printf("\nRE3 Error!\n\t%s\n",re3_buff); + assert(false); +#endif } #ifdef VALIDATE_SAVE_SIZE -- cgit v1.2.3