implemented CFileMgr (barf)
This commit is contained in:
parent
8384815dad
commit
886633293d
294
src/FileMgr.cpp
Normal file
294
src/FileMgr.cpp
Normal file
@ -0,0 +1,294 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <fcntl.h>
|
||||
#include <direct.h>
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "FileMgr.h"
|
||||
|
||||
/*
|
||||
* Windows FILE is BROKEN for GTA.
|
||||
*
|
||||
* We need to support mapping between LF and CRLF for text files
|
||||
* but we do NOT want to end the file at the first sight of a SUB character.
|
||||
* So here is a simple implementation of a FILE interface that works like GTA expects.
|
||||
*/
|
||||
|
||||
struct myFILE
|
||||
{
|
||||
bool isText;
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
#define NUMFILES 20
|
||||
static myFILE myfiles[NUMFILES];
|
||||
|
||||
/* Force file to open as binary but remember if it was text mode */
|
||||
static int
|
||||
myfopen(const char *filename, const char *mode)
|
||||
{
|
||||
int fd;
|
||||
char realmode[10], *p;
|
||||
|
||||
for(fd = 1; fd < NUMFILES; fd++)
|
||||
if(myfiles[fd].file == nil)
|
||||
goto found;
|
||||
return 0; // no free fd
|
||||
found:
|
||||
myfiles[fd].isText = strchr(mode, 'b') == nil;
|
||||
p = realmode;
|
||||
while(*mode)
|
||||
if(*mode != 't' && *mode != 'b')
|
||||
*p++ = *mode++;
|
||||
else
|
||||
mode++;
|
||||
*p++ = 'b';
|
||||
*p = '\0';
|
||||
myfiles[fd].file = fopen(filename, realmode);
|
||||
if(myfiles[fd].file == nil)
|
||||
return 0;
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void
|
||||
myfclose(int fd)
|
||||
{
|
||||
assert(fd < NUMFILES);
|
||||
if(myfiles[fd].file){
|
||||
fclose(myfiles[fd].file);
|
||||
myfiles[fd].file = nil;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
myfgetc(int fd)
|
||||
{
|
||||
int c;
|
||||
c = fgetc(myfiles[fd].file);
|
||||
if(myfiles[fd].isText && c == 015){
|
||||
/* translate CRLF to LF */
|
||||
c = fgetc(myfiles[fd].file);
|
||||
if(c == 012)
|
||||
return c;
|
||||
ungetc(c, myfiles[fd].file);
|
||||
return 015;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static int
|
||||
myfputc(int c, int fd)
|
||||
{
|
||||
/* translate LF to CRLF */
|
||||
if(myfiles[fd].isText && c == 012)
|
||||
fputc(015, myfiles[fd].file);
|
||||
return fputc(c, myfiles[fd].file);
|
||||
}
|
||||
|
||||
static char*
|
||||
myfgets(char *buf, int len, int fd)
|
||||
{
|
||||
int c;
|
||||
char *p;
|
||||
|
||||
p = buf;
|
||||
len--; // NUL byte
|
||||
while(len--){
|
||||
c = myfgetc(fd);
|
||||
if(c == EOF){
|
||||
if(p == buf)
|
||||
return nil;
|
||||
break;
|
||||
}
|
||||
*p++ = c;
|
||||
if(c == '\n')
|
||||
break;
|
||||
}
|
||||
*p = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int
|
||||
myfread(void *buf, size_t elt, size_t n, int fd)
|
||||
{
|
||||
if(myfiles[fd].isText){
|
||||
char *p;
|
||||
size_t i;
|
||||
int c;
|
||||
|
||||
n *= elt;
|
||||
p = (char*)buf;
|
||||
for(i = 0; i < n; i++){
|
||||
c = myfgetc(fd);
|
||||
if(c == EOF)
|
||||
break;
|
||||
*p++ = c;
|
||||
}
|
||||
return i / elt;
|
||||
}
|
||||
return fread(buf, elt, n, myfiles[fd].file);
|
||||
}
|
||||
|
||||
static int
|
||||
myfwrite(void *buf, size_t elt, size_t n, int fd)
|
||||
{
|
||||
if(myfiles[fd].isText){
|
||||
char *p;
|
||||
size_t i;
|
||||
int c;
|
||||
|
||||
n *= elt;
|
||||
p = (char*)buf;
|
||||
for(i = 0; i < n; i++){
|
||||
c = *p++;
|
||||
myfputc(c, fd);
|
||||
if(feof(myfiles[fd].file)) // is this right?
|
||||
break;
|
||||
}
|
||||
return i / elt;
|
||||
}
|
||||
return fwrite(buf, elt, n, myfiles[fd].file);
|
||||
}
|
||||
|
||||
static int
|
||||
myfseek(int fd, long offset, int whence)
|
||||
{
|
||||
return fseek(myfiles[fd].file, offset, whence);
|
||||
}
|
||||
|
||||
static int
|
||||
myfeof(int fd)
|
||||
{
|
||||
return feof(myfiles[fd].file);
|
||||
}
|
||||
|
||||
|
||||
char *CFileMgr::ms_rootDirName = (char*)0x5F18F8;
|
||||
char *CFileMgr::ms_dirName = (char*)0x713CA8;
|
||||
|
||||
void
|
||||
CFileMgr::Initialise(void)
|
||||
{
|
||||
_getcwd(ms_rootDirName, 128);
|
||||
strcat(ms_rootDirName, "\\");
|
||||
}
|
||||
|
||||
void
|
||||
CFileMgr::ChangeDir(const char *dir)
|
||||
{
|
||||
if(*dir == '\\'){
|
||||
strcpy(ms_dirName, ms_rootDirName);
|
||||
dir++;
|
||||
}
|
||||
if(*dir != '\0'){
|
||||
strcat(ms_dirName, dir);
|
||||
// BUG in the game it seems, it's off by one
|
||||
if(dir[strlen(dir)-1] != '\\')
|
||||
strcat(ms_dirName, "\\");
|
||||
}
|
||||
chdir(ms_dirName);
|
||||
}
|
||||
|
||||
void
|
||||
CFileMgr::SetDir(const char *dir)
|
||||
{
|
||||
strcpy(ms_dirName, ms_rootDirName);
|
||||
if(*dir != '\0'){
|
||||
strcat(ms_dirName, dir);
|
||||
// BUG in the game it seems, it's off by one
|
||||
if(dir[strlen(dir)-1] != '\\')
|
||||
strcat(ms_dirName, "\\");
|
||||
}
|
||||
chdir(ms_dirName);
|
||||
}
|
||||
|
||||
void
|
||||
CFileMgr::SetDirMyDocuments(void)
|
||||
{
|
||||
SetDir(""); // better start at the root if user directory is relative
|
||||
chdir(GetUserDirectory());
|
||||
}
|
||||
|
||||
int
|
||||
CFileMgr::LoadFile(const char *file, uint8 *buf, int unused, const char *mode)
|
||||
{
|
||||
int fd;
|
||||
int n, len;
|
||||
|
||||
fd = myfopen(file, mode);
|
||||
if(fd == 0)
|
||||
return 0;
|
||||
len = 0;
|
||||
do{
|
||||
n = myfread(buf + len, 1, 0x4000, fd);
|
||||
if(n < 0)
|
||||
return -1;
|
||||
len += n;
|
||||
}while(n == 0x4000);
|
||||
buf[len] = 0;
|
||||
myfclose(fd);
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
CFileMgr::OpenFile(const char *file, const char *mode)
|
||||
{
|
||||
return myfopen(file, mode);
|
||||
}
|
||||
|
||||
int
|
||||
CFileMgr::OpenFileForWriting(const char *file)
|
||||
{
|
||||
return OpenFile(file, "wb");
|
||||
}
|
||||
|
||||
int
|
||||
CFileMgr::Read(int fd, char *buf, int len)
|
||||
{
|
||||
return myfread(buf, 1, len, fd);
|
||||
}
|
||||
|
||||
int
|
||||
CFileMgr::Write(int fd, char *buf, int len)
|
||||
{
|
||||
return myfwrite(buf, 1, len, fd);
|
||||
}
|
||||
|
||||
bool
|
||||
CFileMgr::Seek(int fd, int offset, int whence)
|
||||
{
|
||||
return !!myfseek(fd, offset, whence);
|
||||
}
|
||||
|
||||
char*
|
||||
CFileMgr::ReadLine(int fd, char *buf, int len)
|
||||
{
|
||||
return myfgets(buf, len, fd);
|
||||
}
|
||||
|
||||
void
|
||||
CFileMgr::CloseFile(int fd)
|
||||
{
|
||||
myfclose(fd);
|
||||
}
|
||||
|
||||
int
|
||||
CFileMgr::GetErrorReadWrite(int fd)
|
||||
{
|
||||
return myfeof(fd);
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x478F80, CFileMgr::Initialise, PATCH_JUMP);
|
||||
InjectHook(0x478FB0, CFileMgr::ChangeDir, PATCH_JUMP);
|
||||
InjectHook(0x479020, CFileMgr::SetDir, PATCH_JUMP);
|
||||
InjectHook(0x479080, CFileMgr::SetDirMyDocuments, PATCH_JUMP);
|
||||
InjectHook(0x479090, CFileMgr::LoadFile, PATCH_JUMP);
|
||||
InjectHook(0x479100, CFileMgr::OpenFile, PATCH_JUMP);
|
||||
InjectHook(0x479120, CFileMgr::OpenFileForWriting, PATCH_JUMP);
|
||||
InjectHook(0x479140, CFileMgr::Read, PATCH_JUMP);
|
||||
InjectHook(0x479160, CFileMgr::Write, PATCH_JUMP);
|
||||
InjectHook(0x479180, CFileMgr::Seek, PATCH_JUMP);
|
||||
InjectHook(0x4791D0, CFileMgr::ReadLine, PATCH_JUMP);
|
||||
InjectHook(0x479200, CFileMgr::CloseFile, PATCH_JUMP);
|
||||
InjectHook(0x479210, CFileMgr::GetErrorReadWrite, PATCH_JUMP);
|
||||
ENDPATCHES
|
21
src/FileMgr.h
Normal file
21
src/FileMgr.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
class CFileMgr
|
||||
{
|
||||
static char *ms_rootDirName; //[128];
|
||||
static char *ms_dirName; //[128];
|
||||
public:
|
||||
static void Initialise(void);
|
||||
static void ChangeDir(const char *dir);
|
||||
static void SetDir(const char *dir);
|
||||
static void SetDirMyDocuments(void);
|
||||
static int LoadFile(const char *file, uint8 *buf, int unused, const char *mode);
|
||||
static int OpenFile(const char *file, const char *mode);
|
||||
static int OpenFileForWriting(const char *file);
|
||||
static int Read(int fd, char *buf, int len);
|
||||
static int Write(int fd, char *buf, int len);
|
||||
static bool Seek(int fd, int offset, int whence);
|
||||
static char *ReadLine(int fd, char *buf, int len);
|
||||
static void CloseFile(int fd);
|
||||
static int GetErrorReadWrite(int fd);
|
||||
};
|
@ -5,6 +5,7 @@
|
||||
#pragma warning(disable: 4244) // int to float
|
||||
#pragma warning(disable: 4800) // int to bool
|
||||
#pragma warning(disable: 4838) // narrowing conversion
|
||||
#pragma warning(disable: 4996) // POSIX names
|
||||
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
@ -61,6 +62,8 @@ extern RsGlobalType &RsGlobal;
|
||||
#define SCREENW (RsGlobal.maximumWidth)
|
||||
#define SCREENH (RsGlobal.maximumHeight)
|
||||
|
||||
char *GetUserDirectory(void);
|
||||
|
||||
struct GlobalScene
|
||||
{
|
||||
RpWorld *world;
|
||||
|
13
src/main.cpp
13
src/main.cpp
@ -1,5 +1,6 @@
|
||||
#include "common.h"
|
||||
#include <direct.h>
|
||||
#include <Windows.h>
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Renderer.h"
|
||||
#include "debugmenu_public.h"
|
||||
@ -36,6 +37,16 @@ mysrand(unsigned int seed)
|
||||
myrand_seed = seed;
|
||||
}
|
||||
|
||||
// platform stuff
|
||||
char*
|
||||
GetUserDirectory(void)
|
||||
{
|
||||
static char path[MAX_PATH];
|
||||
strcpy(path, "userfiles");
|
||||
mkdir(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
int (*open_script_orig)(const char *path, const char *mode);
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user