2012-05-11 16:25:53 +02:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2012-06-22 14:10:08 +02:00
|
|
|
|
2012-05-11 16:25:53 +02:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2012-06-22 14:10:08 +02:00
|
|
|
|
2012-05-11 16:25:53 +02:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
*/
|
2012-03-06 05:43:20 +01:00
|
|
|
|
2012-05-11 16:25:53 +02:00
|
|
|
/*
|
|
|
|
* This file is based on WME Lite.
|
|
|
|
* http://dead-code.org/redir.php?target=wmelite
|
|
|
|
* Copyright (c) 2011 Jan Nedoma
|
|
|
|
*/
|
2012-03-06 05:43:20 +01:00
|
|
|
|
2012-06-08 18:24:41 +02:00
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_fclose
|
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_fopen
|
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_fwrite
|
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_ftell
|
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_fseek
|
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_fprintf
|
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_FILE
|
|
|
|
|
2012-06-02 02:21:01 +02:00
|
|
|
#include "engines/wintermute/Sys/SysClassRegistry.h"
|
|
|
|
#include "engines/wintermute/Sys/SysClass.h"
|
2012-06-02 02:05:11 +02:00
|
|
|
#include "engines/wintermute/Base/scriptables/ScStack.h"
|
|
|
|
#include "engines/wintermute/Base/scriptables/ScValue.h"
|
|
|
|
#include "engines/wintermute/Base/scriptables/ScScript.h"
|
2012-06-02 02:31:59 +02:00
|
|
|
#include "engines/wintermute/utils/utils.h"
|
2012-06-02 02:05:11 +02:00
|
|
|
#include "engines/wintermute/Base/BGame.h"
|
2012-06-02 02:41:18 +02:00
|
|
|
#include "engines/wintermute/Base/file/BFile.h"
|
2012-06-02 02:05:11 +02:00
|
|
|
#include "engines/wintermute/Base/BFileManager.h"
|
2012-03-13 16:28:08 +01:00
|
|
|
#include "engines/wintermute/PlatformSDL.h"
|
2012-06-02 02:05:11 +02:00
|
|
|
#include "engines/wintermute/Base/scriptables/SXFile.h"
|
2012-03-06 05:43:20 +01:00
|
|
|
|
|
|
|
namespace WinterMute {
|
|
|
|
|
|
|
|
IMPLEMENT_PERSISTENT(CSXFile, false)
|
|
|
|
|
2012-06-15 01:54:26 +02:00
|
|
|
CBScriptable *makeSXFile(CBGame *inGame, CScStack *stack) {
|
|
|
|
return new CSXFile(inGame, stack);
|
|
|
|
}
|
|
|
|
|
2012-03-06 05:43:20 +01:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
CSXFile::CSXFile(CBGame *inGame, CScStack *Stack): CBScriptable(inGame) {
|
|
|
|
Stack->CorrectParams(1);
|
|
|
|
CScValue *Val = Stack->Pop();
|
|
|
|
|
2012-04-28 01:00:14 +03:00
|
|
|
_filename = NULL;
|
|
|
|
if (!Val->IsNULL()) CBUtils::SetString(&_filename, Val->GetString());
|
2012-03-06 05:43:20 +01:00
|
|
|
|
2012-04-28 01:00:14 +03:00
|
|
|
_readFile = NULL;
|
|
|
|
_writeFile = NULL;
|
2012-03-06 05:43:20 +01:00
|
|
|
|
2012-04-28 01:00:14 +03:00
|
|
|
_mode = 0;
|
|
|
|
_textMode = false;
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
CSXFile::~CSXFile() {
|
2012-06-26 00:41:05 +02:00
|
|
|
cleanup();
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2012-06-26 00:41:05 +02:00
|
|
|
void CSXFile::cleanup() {
|
2012-04-28 01:00:14 +03:00
|
|
|
delete[] _filename;
|
|
|
|
_filename = NULL;
|
2012-03-06 05:43:20 +01:00
|
|
|
Close();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void CSXFile::Close() {
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_readFile) {
|
2012-06-26 02:07:12 +02:00
|
|
|
Game->_fileManager->closeFile(_readFile);
|
2012-04-28 01:00:14 +03:00
|
|
|
_readFile = NULL;
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
2012-06-22 14:10:08 +02:00
|
|
|
if ((FILE *)_writeFile) {
|
|
|
|
fclose((FILE *)_writeFile);
|
2012-04-28 01:00:14 +03:00
|
|
|
_writeFile = NULL;
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
2012-04-28 01:00:14 +03:00
|
|
|
_mode = 0;
|
|
|
|
_textMode = false;
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2012-06-25 16:44:44 +02:00
|
|
|
const char *CSXFile::scToString() {
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_filename) return _filename;
|
2012-03-06 05:43:20 +01:00
|
|
|
else return "[file object]";
|
|
|
|
}
|
|
|
|
|
|
|
|
#define FILE_BUFFER_SIZE 32768
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2012-06-25 16:44:44 +02:00
|
|
|
HRESULT CSXFile::scCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, const char *Name) {
|
2012-03-06 05:43:20 +01:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// SetFilename
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
if (strcmp(Name, "SetFilename") == 0) {
|
|
|
|
Stack->CorrectParams(1);
|
2012-05-11 14:16:50 +02:00
|
|
|
const char *Filename = Stack->Pop()->GetString();
|
2012-06-26 00:41:05 +02:00
|
|
|
cleanup();
|
2012-04-28 01:00:14 +03:00
|
|
|
CBUtils::SetString(&_filename, Filename);
|
2012-03-06 05:43:20 +01:00
|
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// OpenAsText / OpenAsBinary
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "OpenAsText") == 0 || strcmp(Name, "OpenAsBinary") == 0) {
|
|
|
|
Stack->CorrectParams(1);
|
|
|
|
Close();
|
2012-04-28 01:00:14 +03:00
|
|
|
_mode = Stack->Pop()->GetInt(1);
|
|
|
|
if (_mode < 1 || _mode > 3) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: invalid access mode. Setting read mode.", Name);
|
2012-04-28 01:00:14 +03:00
|
|
|
_mode = 1;
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_mode == 1) {
|
2012-06-26 02:07:12 +02:00
|
|
|
_readFile = Game->_fileManager->openFile(_filename);
|
2012-04-28 01:00:14 +03:00
|
|
|
if (!_readFile) {
|
|
|
|
//Script->RuntimeError("File.%s: Error opening file '%s' for reading.", Name, _filename);
|
2012-03-06 05:43:20 +01:00
|
|
|
Close();
|
2012-04-28 01:00:14 +03:00
|
|
|
} else _textMode = strcmp(Name, "OpenAsText") == 0;
|
2012-03-06 05:43:20 +01:00
|
|
|
} else {
|
|
|
|
if (strcmp(Name, "OpenAsText") == 0) {
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_mode == 2) _writeFile = fopen(_filename, "w+");
|
|
|
|
else _writeFile = fopen(_filename, "a+");
|
2012-03-06 05:43:20 +01:00
|
|
|
} else {
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_mode == 2) _writeFile = fopen(_filename, "wb+");
|
|
|
|
else _writeFile = fopen(_filename, "ab+");
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
|
2012-04-28 01:00:14 +03:00
|
|
|
if (!_writeFile) {
|
|
|
|
//Script->RuntimeError("File.%s: Error opening file '%s' for writing.", Name, _filename);
|
2012-03-06 05:43:20 +01:00
|
|
|
Close();
|
2012-04-28 01:00:14 +03:00
|
|
|
} else _textMode = strcmp(Name, "OpenAsText") == 0;
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_readFile || _writeFile) Stack->PushBool(true);
|
2012-03-06 05:43:20 +01:00
|
|
|
else Stack->PushBool(false);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Close
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "Close") == 0) {
|
|
|
|
Stack->CorrectParams(0);
|
|
|
|
Close();
|
|
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// SetPosition
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "SetPosition") == 0) {
|
|
|
|
Stack->CorrectParams(1);
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_mode == 0) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File is not open", Name);
|
|
|
|
Stack->PushBool(false);
|
|
|
|
} else {
|
|
|
|
int Pos = Stack->Pop()->GetInt();
|
|
|
|
Stack->PushBool(SetPos(Pos));
|
|
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Delete
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "Delete") == 0) {
|
|
|
|
Stack->CorrectParams(0);
|
|
|
|
Close();
|
2012-05-11 18:17:49 +02:00
|
|
|
Stack->PushBool(CBPlatform::DeleteFile(_filename) != false);
|
2012-03-06 05:43:20 +01:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Copy
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "Copy") == 0) {
|
|
|
|
Stack->CorrectParams(2);
|
2012-05-11 14:16:50 +02:00
|
|
|
const char *Dest = Stack->Pop()->GetString();
|
2012-03-06 05:43:20 +01:00
|
|
|
bool Overwrite = Stack->Pop()->GetBool(true);
|
|
|
|
|
|
|
|
Close();
|
2012-05-11 18:17:49 +02:00
|
|
|
Stack->PushBool(CBPlatform::CopyFile(_filename, Dest, !Overwrite) != false);
|
2012-03-06 05:43:20 +01:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// ReadLine
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "ReadLine") == 0) {
|
|
|
|
Stack->CorrectParams(0);
|
2012-04-28 01:00:14 +03:00
|
|
|
if (!_textMode || !_readFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open in text mode.", Name);
|
|
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
uint32 BufSize = FILE_BUFFER_SIZE;
|
2012-05-11 16:03:59 +02:00
|
|
|
byte *Buf = (byte *)malloc(BufSize);
|
2012-03-06 05:43:20 +01:00
|
|
|
uint32 Counter = 0;
|
|
|
|
byte b;
|
|
|
|
bool FoundNewLine = false;
|
|
|
|
HRESULT Ret = E_FAIL;
|
|
|
|
do {
|
2012-06-02 11:09:22 +02:00
|
|
|
Ret = _readFile->read(&b, 1);
|
|
|
|
if (Ret != 1) break;
|
2012-03-06 05:43:20 +01:00
|
|
|
|
|
|
|
if (Counter > BufSize) {
|
2012-05-11 16:03:59 +02:00
|
|
|
Buf = (byte *)realloc(Buf, BufSize + FILE_BUFFER_SIZE);
|
2012-03-06 05:43:20 +01:00
|
|
|
BufSize += FILE_BUFFER_SIZE;
|
|
|
|
}
|
|
|
|
if (b == '\n') {
|
|
|
|
Buf[Counter] = '\0';
|
|
|
|
FoundNewLine = true;
|
|
|
|
break;
|
|
|
|
} else if (b == 0x0D) continue;
|
|
|
|
else {
|
|
|
|
Buf[Counter] = b;
|
|
|
|
Counter++;
|
|
|
|
}
|
|
|
|
} while (SUCCEEDED(Ret));
|
|
|
|
|
|
|
|
if (Counter > BufSize) {
|
2012-05-11 16:03:59 +02:00
|
|
|
Buf = (byte *)realloc(Buf, BufSize + FILE_BUFFER_SIZE);
|
2012-03-06 05:43:20 +01:00
|
|
|
BufSize += FILE_BUFFER_SIZE;
|
|
|
|
}
|
|
|
|
Buf[Counter] = '\0';
|
|
|
|
|
|
|
|
if (!FoundNewLine && Counter == 0) Stack->PushNULL();
|
|
|
|
else Stack->PushString((char *)Buf);
|
|
|
|
|
|
|
|
free(Buf);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// ReadText
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "ReadText") == 0) {
|
|
|
|
Stack->CorrectParams(1);
|
|
|
|
int TextLen = Stack->Pop()->GetInt();
|
|
|
|
|
2012-04-28 01:00:14 +03:00
|
|
|
if (!_textMode || !_readFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open in text mode.", Name);
|
|
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
uint32 BufSize = FILE_BUFFER_SIZE;
|
2012-05-11 16:03:59 +02:00
|
|
|
byte *Buf = (byte *)malloc(BufSize);
|
2012-03-06 05:43:20 +01:00
|
|
|
uint32 Counter = 0;
|
|
|
|
byte b;
|
|
|
|
|
|
|
|
HRESULT Ret = E_FAIL;
|
|
|
|
while (Counter < TextLen) {
|
2012-06-02 11:09:22 +02:00
|
|
|
Ret = _readFile->read(&b, 1);
|
|
|
|
if (Ret != 1) break;
|
2012-03-06 05:43:20 +01:00
|
|
|
|
|
|
|
if (Counter > BufSize) {
|
2012-05-11 16:03:59 +02:00
|
|
|
Buf = (byte *)realloc(Buf, BufSize + FILE_BUFFER_SIZE);
|
2012-03-06 05:43:20 +01:00
|
|
|
BufSize += FILE_BUFFER_SIZE;
|
|
|
|
}
|
|
|
|
if (b == 0x0D) continue;
|
|
|
|
else {
|
|
|
|
Buf[Counter] = b;
|
|
|
|
Counter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Counter > BufSize) {
|
2012-05-11 16:03:59 +02:00
|
|
|
Buf = (byte *)realloc(Buf, BufSize + FILE_BUFFER_SIZE);
|
2012-03-06 05:43:20 +01:00
|
|
|
BufSize += FILE_BUFFER_SIZE;
|
|
|
|
}
|
|
|
|
Buf[Counter] = '\0';
|
|
|
|
|
|
|
|
if (TextLen > 0 && Counter == 0) Stack->PushNULL();
|
|
|
|
else Stack->PushString((char *)Buf);
|
|
|
|
|
|
|
|
free(Buf);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// WriteLine / WriteText
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "WriteLine") == 0 || strcmp(Name, "WriteText") == 0) {
|
|
|
|
Stack->CorrectParams(1);
|
2012-05-11 14:16:50 +02:00
|
|
|
const char *Line = Stack->Pop()->GetString();
|
2012-04-28 01:00:14 +03:00
|
|
|
if (!_textMode || !_writeFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for writing in text mode.", Name);
|
|
|
|
Stack->PushBool(false);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
if (strcmp(Name, "WriteLine") == 0)
|
2012-06-22 14:10:08 +02:00
|
|
|
fprintf((FILE *)_writeFile, "%s\n", Line);
|
2012-03-06 05:43:20 +01:00
|
|
|
else
|
2012-06-22 14:10:08 +02:00
|
|
|
fprintf((FILE *)_writeFile, "%s", Line);
|
2012-03-06 05:43:20 +01:00
|
|
|
|
|
|
|
Stack->PushBool(true);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// ReadBool
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "ReadBool") == 0) {
|
|
|
|
Stack->CorrectParams(0);
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode || !_readFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for reading in binary mode.", Name);
|
|
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
bool Val;
|
2012-06-02 11:09:22 +02:00
|
|
|
if (_readFile->read(&Val, sizeof(bool)) == sizeof(bool)) Stack->PushBool(Val);
|
2012-03-06 05:43:20 +01:00
|
|
|
else Stack->PushNULL();
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// ReadByte
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "ReadByte") == 0) {
|
|
|
|
Stack->CorrectParams(0);
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode || !_readFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for reading in binary mode.", Name);
|
|
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
byte Val;
|
2012-06-02 11:09:22 +02:00
|
|
|
if (_readFile->read(&Val, sizeof(byte)) == sizeof(byte)) Stack->PushInt(Val);
|
2012-03-06 05:43:20 +01:00
|
|
|
else Stack->PushNULL();
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// ReadShort
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "ReadShort") == 0) {
|
|
|
|
Stack->CorrectParams(0);
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode || !_readFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for reading in binary mode.", Name);
|
|
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
short Val;
|
2012-06-02 11:09:22 +02:00
|
|
|
if (_readFile->read(&Val, sizeof(short)) == sizeof(short)) Stack->PushInt(65536 + Val);
|
2012-03-06 05:43:20 +01:00
|
|
|
else Stack->PushNULL();
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// ReadInt / ReadLong
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "ReadInt") == 0 || strcmp(Name, "ReadLong") == 0) {
|
|
|
|
Stack->CorrectParams(0);
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode || !_readFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for reading in binary mode.", Name);
|
|
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
int Val;
|
2012-06-02 11:09:22 +02:00
|
|
|
if (_readFile->read(&Val, sizeof(int)) == sizeof(int)) Stack->PushInt(Val);
|
2012-03-06 05:43:20 +01:00
|
|
|
else Stack->PushNULL();
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// ReadFloat
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "ReadFloat") == 0) {
|
|
|
|
Stack->CorrectParams(0);
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode || !_readFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for reading in binary mode.", Name);
|
|
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
float Val;
|
2012-06-02 11:09:22 +02:00
|
|
|
if (_readFile->read(&Val, sizeof(float)) == sizeof(float)) Stack->PushFloat(Val);
|
2012-03-06 05:43:20 +01:00
|
|
|
else Stack->PushNULL();
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// ReadDouble
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "ReadDouble") == 0) {
|
|
|
|
Stack->CorrectParams(0);
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode || !_readFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for reading in binary mode.", Name);
|
|
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
double Val;
|
2012-06-02 11:09:22 +02:00
|
|
|
if (_readFile->read(&Val, sizeof(double)) == sizeof(double)) Stack->PushFloat(Val);
|
2012-03-06 05:43:20 +01:00
|
|
|
else Stack->PushNULL();
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// ReadString
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "ReadString") == 0) {
|
|
|
|
Stack->CorrectParams(0);
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode || !_readFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for reading in binary mode.", Name);
|
|
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
uint32 Size;
|
2012-06-02 11:09:22 +02:00
|
|
|
if (_readFile->read(&Size, sizeof(uint32)) == sizeof(uint32)) {
|
2012-03-06 05:43:20 +01:00
|
|
|
byte *Str = new byte[Size + 1];
|
|
|
|
if (Str) {
|
2012-06-02 11:09:22 +02:00
|
|
|
if (_readFile->read(Str, Size) == Size) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Str[Size] = '\0';
|
|
|
|
Stack->PushString((char *)Str);
|
|
|
|
}
|
|
|
|
delete [] Str;
|
|
|
|
} else Stack->PushNULL();
|
|
|
|
} else Stack->PushNULL();
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// WriteBool
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "WriteBool") == 0) {
|
|
|
|
Stack->CorrectParams(1);
|
|
|
|
bool Val = Stack->Pop()->GetBool();
|
|
|
|
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode || !_writeFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for writing in binary mode.", Name);
|
|
|
|
Stack->PushBool(false);
|
|
|
|
return S_OK;
|
|
|
|
}
|
2012-06-22 14:10:08 +02:00
|
|
|
fwrite(&Val, sizeof(Val), 1, (FILE *)_writeFile);
|
2012-03-06 05:43:20 +01:00
|
|
|
Stack->PushBool(true);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// WriteByte
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "WriteByte") == 0) {
|
|
|
|
Stack->CorrectParams(1);
|
|
|
|
byte Val = Stack->Pop()->GetInt();
|
|
|
|
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode || !_writeFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for writing in binary mode.", Name);
|
|
|
|
Stack->PushBool(false);
|
|
|
|
return S_OK;
|
|
|
|
}
|
2012-06-22 14:10:08 +02:00
|
|
|
fwrite(&Val, sizeof(Val), 1, (FILE *)_writeFile);
|
2012-03-06 05:43:20 +01:00
|
|
|
Stack->PushBool(true);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// WriteShort
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "WriteShort") == 0) {
|
|
|
|
Stack->CorrectParams(1);
|
|
|
|
short Val = Stack->Pop()->GetInt();
|
|
|
|
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode || !_writeFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for writing in binary mode.", Name);
|
|
|
|
Stack->PushBool(false);
|
|
|
|
return S_OK;
|
|
|
|
}
|
2012-06-22 14:10:08 +02:00
|
|
|
fwrite(&Val, sizeof(Val), 1, (FILE *)_writeFile);
|
2012-03-06 05:43:20 +01:00
|
|
|
Stack->PushBool(true);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// WriteInt / WriteLong
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "WriteInt") == 0 || strcmp(Name, "WriteLong") == 0) {
|
|
|
|
Stack->CorrectParams(1);
|
|
|
|
int Val = Stack->Pop()->GetInt();
|
|
|
|
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode || !_writeFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for writing in binary mode.", Name);
|
|
|
|
Stack->PushBool(false);
|
|
|
|
return S_OK;
|
|
|
|
}
|
2012-06-22 14:10:08 +02:00
|
|
|
fwrite(&Val, sizeof(Val), 1, (FILE *)_writeFile);
|
2012-03-06 05:43:20 +01:00
|
|
|
Stack->PushBool(true);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// WriteFloat
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "WriteFloat") == 0) {
|
|
|
|
Stack->CorrectParams(1);
|
|
|
|
float Val = Stack->Pop()->GetFloat();
|
|
|
|
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode || !_writeFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for writing in binary mode.", Name);
|
|
|
|
Stack->PushBool(false);
|
|
|
|
return S_OK;
|
|
|
|
}
|
2012-06-22 14:10:08 +02:00
|
|
|
fwrite(&Val, sizeof(Val), 1, (FILE *)_writeFile);
|
2012-03-06 05:43:20 +01:00
|
|
|
Stack->PushBool(true);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// WriteDouble
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "WriteDouble") == 0) {
|
|
|
|
Stack->CorrectParams(1);
|
|
|
|
double Val = Stack->Pop()->GetFloat();
|
|
|
|
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode || !_writeFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for writing in binary mode.", Name);
|
|
|
|
Stack->PushBool(false);
|
|
|
|
return S_OK;
|
|
|
|
}
|
2012-06-22 14:10:08 +02:00
|
|
|
fwrite(&Val, sizeof(Val), 1, (FILE *)_writeFile);
|
2012-03-06 05:43:20 +01:00
|
|
|
Stack->PushBool(true);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// WriteString
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "WriteString") == 0) {
|
|
|
|
Stack->CorrectParams(1);
|
2012-05-11 14:16:50 +02:00
|
|
|
const char *Val = Stack->Pop()->GetString();
|
2012-03-06 05:43:20 +01:00
|
|
|
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode || !_writeFile) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Script->RuntimeError("File.%s: File must be open for writing in binary mode.", Name);
|
|
|
|
Stack->PushBool(false);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 Size = strlen(Val);
|
2012-06-22 14:10:08 +02:00
|
|
|
fwrite(&Size, sizeof(Size), 1, (FILE *)_writeFile);
|
|
|
|
fwrite(Val, Size, 1, (FILE *)_writeFile);
|
2012-03-06 05:43:20 +01:00
|
|
|
|
|
|
|
Stack->PushBool(true);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-25 16:44:44 +02:00
|
|
|
else return CBScriptable::scCallMethod(Script, Stack, ThisStack, Name);
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2012-06-25 16:44:44 +02:00
|
|
|
CScValue *CSXFile::scGetProperty(const char *Name) {
|
2012-04-28 01:00:14 +03:00
|
|
|
_scValue->SetNULL();
|
2012-03-06 05:43:20 +01:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Type (RO)
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
if (strcmp(Name, "Type") == 0) {
|
2012-04-28 01:00:14 +03:00
|
|
|
_scValue->SetString("file");
|
|
|
|
return _scValue;
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Filename (RO)
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
if (strcmp(Name, "Filename") == 0) {
|
2012-04-28 01:00:14 +03:00
|
|
|
_scValue->SetString(_filename);
|
|
|
|
return _scValue;
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Position (RO)
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "Position") == 0) {
|
2012-04-28 01:00:14 +03:00
|
|
|
_scValue->SetInt(GetPos());
|
|
|
|
return _scValue;
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Length (RO)
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "Length") == 0) {
|
2012-04-28 01:00:14 +03:00
|
|
|
_scValue->SetInt(GetLength());
|
|
|
|
return _scValue;
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// TextMode (RO)
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "TextMode") == 0) {
|
2012-04-28 01:00:14 +03:00
|
|
|
_scValue->SetBool(_textMode);
|
|
|
|
return _scValue;
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// AccessMode (RO)
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
else if (strcmp(Name, "AccessMode") == 0) {
|
2012-04-28 01:00:14 +03:00
|
|
|
_scValue->SetInt(_mode);
|
|
|
|
return _scValue;
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
|
2012-06-25 16:44:44 +02:00
|
|
|
else return CBScriptable::scGetProperty(Name);
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2012-06-25 16:44:44 +02:00
|
|
|
HRESULT CSXFile::scSetProperty(const char *Name, CScValue *Value) {
|
2012-03-06 05:43:20 +01:00
|
|
|
/*
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Length
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
if(strcmp(Name, "Length")==0){
|
2012-04-28 01:00:14 +03:00
|
|
|
int OrigLength = _length;
|
|
|
|
_length = max(Value->GetInt(0), 0);
|
2012-03-06 05:43:20 +01:00
|
|
|
|
|
|
|
char PropName[20];
|
2012-04-28 01:00:14 +03:00
|
|
|
if(_length < OrigLength){
|
|
|
|
for(int i=_length; i<OrigLength; i++){
|
2012-03-06 05:43:20 +01:00
|
|
|
sprintf(PropName, "%d", i);
|
2012-04-28 01:00:14 +03:00
|
|
|
_values->DeleteProp(PropName);
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
}
|
2012-06-25 16:44:44 +02:00
|
|
|
else*/ return CBScriptable::scSetProperty(Name, Value);
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
uint32 CSXFile::GetPos() {
|
2012-06-02 11:09:22 +02:00
|
|
|
if (_mode == 1 && _readFile) return _readFile->pos();
|
2012-06-22 14:10:08 +02:00
|
|
|
else if ((_mode == 2 || _mode == 3) && _writeFile) return ftell((FILE *)_writeFile);
|
2012-03-06 05:43:20 +01:00
|
|
|
else return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2012-06-02 11:09:22 +02:00
|
|
|
bool CSXFile::SetPos(uint32 pos, TSeek origin) {
|
|
|
|
if (_mode == 1 && _readFile) return _readFile->seek(pos, origin);
|
2012-06-22 14:10:08 +02:00
|
|
|
else if ((_mode == 2 || _mode == 3) && _writeFile) return fseek((FILE *)_writeFile, pos, (int)origin) == 0;
|
2012-03-06 05:43:20 +01:00
|
|
|
else return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
uint32 CSXFile::GetLength() {
|
2012-06-02 11:09:22 +02:00
|
|
|
if (_mode == 1 && _readFile) return _readFile->size();
|
2012-04-28 01:00:14 +03:00
|
|
|
else if ((_mode == 2 || _mode == 3) && _writeFile) {
|
2012-06-22 14:10:08 +02:00
|
|
|
uint32 CurrentPos = ftell((FILE *)_writeFile);
|
|
|
|
fseek((FILE *)_writeFile, 0, SEEK_END);
|
|
|
|
int Ret = ftell((FILE *)_writeFile);
|
|
|
|
fseek((FILE *)_writeFile, CurrentPos, SEEK_SET);
|
2012-03-06 05:43:20 +01:00
|
|
|
return Ret;
|
|
|
|
} else return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2012-06-22 20:06:12 +02:00
|
|
|
HRESULT CSXFile::persist(CBPersistMgr *persistMgr) {
|
2012-03-06 05:43:20 +01:00
|
|
|
|
2012-06-22 20:06:12 +02:00
|
|
|
CBScriptable::persist(persistMgr);
|
2012-03-06 05:43:20 +01:00
|
|
|
|
2012-06-22 13:56:51 +02:00
|
|
|
persistMgr->transfer(TMEMBER(_filename));
|
|
|
|
persistMgr->transfer(TMEMBER(_mode));
|
|
|
|
persistMgr->transfer(TMEMBER(_textMode));
|
2012-03-06 05:43:20 +01:00
|
|
|
|
|
|
|
uint32 Pos = 0;
|
2012-06-22 13:56:51 +02:00
|
|
|
if (persistMgr->_saving) {
|
2012-03-06 05:43:20 +01:00
|
|
|
Pos = GetPos();
|
2012-06-22 13:56:51 +02:00
|
|
|
persistMgr->transfer(TMEMBER(Pos));
|
2012-03-06 05:43:20 +01:00
|
|
|
} else {
|
2012-06-22 13:56:51 +02:00
|
|
|
persistMgr->transfer(TMEMBER(Pos));
|
2012-03-06 05:43:20 +01:00
|
|
|
|
|
|
|
// try to re-open file if needed
|
2012-04-28 01:00:14 +03:00
|
|
|
_writeFile = NULL;
|
|
|
|
_readFile = NULL;
|
2012-03-06 05:43:20 +01:00
|
|
|
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_mode != 0) {
|
2012-03-06 05:43:20 +01:00
|
|
|
// open for reading
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_mode == 1) {
|
2012-06-26 02:07:12 +02:00
|
|
|
_readFile = Game->_fileManager->openFile(_filename);
|
2012-04-28 01:00:14 +03:00
|
|
|
if (!_readFile) Close();
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
// open for writing / appending
|
|
|
|
else {
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_textMode) {
|
|
|
|
if (_mode == 2) _writeFile = fopen(_filename, "w+");
|
|
|
|
else _writeFile = fopen(_filename, "a+");
|
2012-03-06 05:43:20 +01:00
|
|
|
} else {
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_mode == 2) _writeFile = fopen(_filename, "wb+");
|
|
|
|
else _writeFile = fopen(_filename, "ab+");
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
2012-04-28 01:00:14 +03:00
|
|
|
if (_writeFile) Close();
|
2012-03-06 05:43:20 +01:00
|
|
|
}
|
|
|
|
SetPos(Pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // end of namespace WinterMute
|