summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
authorSergeanur <s.anureev@yandex.ua>2020-05-12 23:19:21 +0200
committerSergeanur <s.anureev@yandex.ua>2020-05-12 23:27:15 +0200
commit33dfaf7da11675fdad2909e39b6d15e49fc6cc68 (patch)
treeff2b3fe079b51b521cb26ceb2da0a5717b0601ff /src/core
parentMerge remote-tracking branch 'upstream/miami' into miami (diff)
parentfix shotgun (diff)
downloadre3-33dfaf7da11675fdad2909e39b6d15e49fc6cc68.tar
re3-33dfaf7da11675fdad2909e39b6d15e49fc6cc68.tar.gz
re3-33dfaf7da11675fdad2909e39b6d15e49fc6cc68.tar.bz2
re3-33dfaf7da11675fdad2909e39b6d15e49fc6cc68.tar.lz
re3-33dfaf7da11675fdad2909e39b6d15e49fc6cc68.tar.xz
re3-33dfaf7da11675fdad2909e39b6d15e49fc6cc68.tar.zst
re3-33dfaf7da11675fdad2909e39b6d15e49fc6cc68.zip
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CdStream.cpp10
-rw-r--r--src/core/CdStream.h6
-rw-r--r--src/core/CdStreamPosix.cpp516
-rw-r--r--src/core/ControllerConfig.cpp29
-rw-r--r--src/core/FileMgr.cpp59
-rw-r--r--src/core/Fire.cpp8
-rw-r--r--src/core/Frontend.cpp41
-rw-r--r--src/core/Frontend.h1
-rw-r--r--src/core/Game.cpp2
-rw-r--r--src/core/Streaming.cpp8
-rw-r--r--src/core/Timer.cpp31
-rw-r--r--src/core/Zones.cpp6
-rw-r--r--src/core/config.h11
-rw-r--r--src/core/main.cpp3
-rw-r--r--src/core/patcher.cpp20
-rw-r--r--src/core/re3.cpp51
16 files changed, 734 insertions, 68 deletions
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 <pthread.h>
+#include <signal.h>
+#include <semaphore.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/statvfs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+
+#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 <fcntl.h>
+#ifdef _WIN32
#include <direct.h>
+#endif
#include "common.h"
#include "FileMgr.h"
@@ -24,6 +26,31 @@ struct myFILE
#define NUMFILES 20
static myFILE myfiles[NUMFILES];
+
+#if !defined(_WIN32)
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#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 5663b9ab..e313bee8 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 99597a15..5c713f53 100644
--- a/src/core/Frontend.h
+++ b/src/core/Frontend.h
@@ -664,4 +664,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 6a6b31e7..9aea817e 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 c1f0be5d..d2c4c9b0 100644
--- a/src/core/Streaming.cpp
+++ b/src/core/Streaming.cpp
@@ -1618,7 +1618,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
@@ -1667,8 +1667,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;
@@ -2005,7 +2005,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/Zones.cpp b/src/core/Zones.cpp
index c0fa7cbe..8e73a07b 100644
--- a/src/core/Zones.cpp
+++ b/src/core/Zones.cpp
@@ -752,9 +752,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 17cea982..30f6b898 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -195,19 +195,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
@@ -225,7 +228,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 00ae3774..14c854bd 100644
--- a/src/core/main.cpp
+++ b/src/core/main.cpp
@@ -1776,6 +1776,8 @@ void GameInit()
}
}
+// Not used anyway. PS2 main() port
+#ifdef _WIN32
int
main(int argc, char *argv[])
{
@@ -1847,3 +1849,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<uint32> 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 bbac265f..0e62f3a5 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -1,7 +1,7 @@
-#include <direct.h>
#include <csignal>
#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 <stdarg.h>
+#endif
+
#include <list>
#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
@@ -207,13 +212,22 @@ static const char *carnames[] = {
"bloodra", "bloodrb", "vicechee"
};
-static std::list<CTweakVar *> 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);
@@ -223,8 +237,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;
}
@@ -395,6 +409,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!" );
@@ -439,13 +454,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);
@@ -457,18 +481,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);
@@ -477,6 +509,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